sandbox/yixian/Sandglass3D.c
Flow in a Sandglass / Hourglass with an orifice at the bottom in 3D case
We propose an implementation of the Jop Pouliquen Forterre µ(I) rheology for the flow in a hourglass.
Code
Includes and definitions
// #include "grid/multigrid.h"
#include "grid/octree.h"
#include "navier-stokes/centered.h"
#include "vof.h"
// Domain extent
#define LDOMAIN 1.
// heap definition
double H0,R0,D,W,tmax,Q,Wmin,DW;
//film size
double Lz;
passive fluid small density to preserve 0 pressure and small viscocity
#define RHOF 1e-4
#define mug 1e-5
// Maximum refinement
#define LEVEL 5 //7
char s[80];
FILE * fpf,*fwq;
scalar f[];
scalar * interfaces = {f};
face vector alphav[];
face vector muv[];
scalar rhov[];
Boundary conditions for granular flow, pressure must be zero at the surface. The pressure is zero in the hole x=1 and 4\deltax < y< W+4\deltax, but the lithostatic gradient is given elswhere on the right wall. No slip boundary conditions on the other walls.
[top] = dirichlet(0);
p.n[top] = neumann(0);
u.t[bottom] = (x-LDOMAIN/2)*(x-LDOMAIN/2)+ (z-LDOMAIN/2)*(z-LDOMAIN/2) <= W/2.*W/2. ? neumann(0): dirichlet(0);
u.n[bottom] = (x-LDOMAIN/2)*(x-LDOMAIN/2)+ (z-LDOMAIN/2)*(z-LDOMAIN/2) <= W/2.*W/2. ? neumann(0): dirichlet(0);
u//u.n[bottom] = dirichlet(0);
[bottom] = (x-LDOMAIN/2)*(x-LDOMAIN/2)+ (z-LDOMAIN/2)*(z-LDOMAIN/2) <= W/2.*W/2. ? dirichlet(0): neumann(0);
p.n[right] = dirichlet(0);
u.n[left] = dirichlet(0);
u.t[right] = dirichlet(0);
u.t[left] = dirichlet(0);
u.n[front] = dirichlet(0);
u.t[front] = dirichlet(0);
u.n[back] = dirichlet(0);
u.t[back] = dirichlet(0);
u[left]= neumann(0); f
the three cases in the main
int main(int argc, char ** argv) {
= LDOMAIN;
L0 // number of grid points
= 1 << LEVEL;
N // maximum timestep
= 0.001;
DT
= 1e-3;
TOLERANCE // Initial conditions a=.5
=0.96;
H0=20.000;
R0// Grain size
=1./90.;
D// size of the hole
= 0.25;
W //Wmin = 0.15625;
= LDOMAIN/N;
DW = fopen ("outWQ", "w");
fwq fclose(fwq);
= LDOMAIN;
Lz const face vector g[] = {0.,-1.,0};
= g;
a = alphav;
alpha = muv;
mu = rhov;
rho
= 0;
Q = 3;
tmax = fopen ("interface.txt", "w");
fpf run();
fclose (fpf);
fprintf (stdout,"\n");
= fopen ("outWQ", "a");
fwq fprintf(fwq," %lf %lf \n", W, Q);
fclose (fwq);
}
initial heap, a paralepipede
// note the v
event init (t = 0) {
// mask (x < 3.*L0/4. ? left : none);
scalar phi[];
foreach_vertex()
[] = min(H0 - y, R0 - x);
phifractions (phi, f);
lithostatic pressure, with a zero pressure near the hole to help
foreach()
[] = ((x-LDOMAIN/2)*(x-LDOMAIN/2)+ (z-LDOMAIN/2)*(z-LDOMAIN/2) <= W/2.*W/2. && fabs(y)<= .1) ? 0 : max(H0 - y,0) ;
pboundary ({p});
}
total density
#define rho(f) ((f) + RHOF*(1. - (f)))
Viscosity computing D_2=D_{ij}D_{ji};
In the pure shear flow D_{11}=D_{22}=0 et D_{12}=D_{21}=(1/2)(\partial u/\partial y),
so that
D_2=\sqrt{D_{ij}D_{ij}} =\sqrt{ 2 D_{12}^2} =
\frac{\partial u}{ \sqrt{2}\partial y}. In a pure shear flow,
\partial u/\partial y= \sqrt{2} D_2.
The inertial number I is D \sqrt{2} D_2/\sqrt(p) and \mu = \mu_s+ \frac{\Delta \mu}{1+I/I_0} the
viscosity is \eta = \mu(I)p/D_2:
note that if \eta is too small an artificial small viscosity \rho D \sqrt{gD} is taken see Lagrée et al. 11 § 2.3.1
event properties (i++) {
({alphav});
trash scalar eta[];
foreach_dimension() { double dxx = u.x[1,0] - u.x[-1,0]; double dxy = (u.x[0,1] - u.x[0,-1] + u.y[1,0] - u.y[-1,0])/2.; D2 += sq(dxx) + sq(dxy); }
foreach() {
[] = mug;
etaif (p[] > 0.) {
double D2 = 0.;
double dxx = u.x[1,0,0] - u.x[-1,0,0];
double dyy = u.y[0,1,0] - u.y[0,-1,0];
double dzz = u.z[0,0,1] - u.z[0,0,-1];
double dxy = (u.x[0,1,0] - u.x[0,-1,0] + u.y[1,0,0] - u.y[-1,0,0])/2.;
double dxz = (u.x[0,0,1] - u.x[0,0,-1] + u.z[1,0,0] - u.z[-1,0,0])/2.;
double dyz = (u.y[0,0,1] - u.y[0,0,-1] + u.z[0,1,0] - u.z[0,-1,0])/2.;
= sq(dxx) + sq(dyy) +sq(dzz) +2.*sq(dxy) +2.*sq(dxz) +2.*sq(dyz);
D2 if (D2 > 0.) {
= sqrt(2.*D2)/(2.*Delta);
D2 double In = D2*D/sqrt(p[]);
double muI = .32 + .28*In/(.4 + In);
double etamin = sqrt(D*D*D);
[] = max((muI*p[])/D2, etamin);
eta[] = min(eta[],100);
eta}
}
}
boundary ({eta});
scalar fa[];
foreach()
[] = (8.*f[] +
fa4.*(f[-1,0,0] + f[1,0,0] + f[0,-1,0] + f[0,1,0]+ f[0,0,1]+ f[0,0,-1]) +
2*(f[1,1,0] + f[-1,1,0] + f[1,-1,0] + f[-1,-1,0]+f[0,1,1] + f[0,-1,1] +
[0,1,-1] + f[0,-1,-1]+f[1,0,1] + f[-1,0,1] + f[1,0,-1] + f[-1,0,-1])+
f[1,1,1]+ f[1,1,-1]+f[-1,1,-1]+f[-1,1,1]+f[1,-1,1]+ f[1,-1,-1]+f[-1,-1,-1]+f[-1,-1,1])/64.;
fboundary ({fa});
foreach_face() {
double fm = (fa[] + fa[-1])/2.;
.x[] = (fm*(eta[] + eta[-1])/2. + (1. - fm)*mug);
muv// mu.x[] = 1./(2.*fm/(eta[] + eta[-1,0]) + (1. - fm)/mug);
.x[] = 1./rho(fm);
alphav}
foreach()
[] = rho(fa[]);
rhovboundary ({muv,alphav,rhov});
//boundary ((scalar *){muv,alphav});
}
convergence outputs
void mg_print (mgstats mg)
{
if (mg.i > 0 && mg.resa > 0.)
fprintf (stderr, "# %d %g %g %g\n", mg.i, mg.resb, mg.resa,
(log (mg.resb/mg.resa)/mg.i));
exp }
convergence stats
event logfile (i += 1) {
stats s = statsf (f);
fprintf (stderr, "%g %d %g %g %g %g\n", t, i, dt, s.sum, s.min, s.max - 1.);
mg_print (mgp);
mg_print (mgpf);
mg_print (mgu);
fflush (stderr);
}
Rate of flowing materials across the hole
event debit (t = 0 ;t += 0.1 ; t<= tmax ) {
static double V=1;
=0;
Vforeach()
= V + f[]* Delta * Delta* Delta;
V if(t>=0.) fprintf (stdout,"%lf %lf \n",t,V);
fflush (stdout);
}
film output for 2D
#if 0
event movie (t += 0.05) {
static FILE * fp1 = popen ("ppm2mpeg > level.mpg", "w");
scalar l[];
foreach()
[] = level;
loutput_ppm (l, fp1, min = 0, max = LEVEL,
= 256, box = {{0,0},{Lz,Lz}});
n
foreach()
[] = f[]*(1+sqrt(sq(u.x[]) + sq(u.y[])));
lboundary ({l});
static FILE * fp2 = popen ("ppm2mpeg > velo.mpg", "w");
output_ppm (l, fp2, min = 0, max = 2., linear = true,
= 256, box = {{0,0},{Lz,Lz}});
n
static FILE * fp3 = popen ("ppm2mpeg > f.mpg", "w");
foreach()
[] = f[]*p[];
loutput_ppm (l, fp3, min = 0, linear = true,
= 256, box = {{0,0},{Lz,Lz}});
n }
event pictures (t==3) {
output_ppm (f, file = "f.png", min=0, max = 2, spread = 2, n = 256, linear = true,
box = {{0,0},{2,2}});
}
#endif
gfsview…
#if 0
event gfsview (i += 1) {
static FILE * fp = popen (dimension == 2 ?
"gfsview2D gfsview.gfv" :
"gfsview3D gfsview3D.gfv",
"w");
output_gfs (fp, t = t);
}
#endif
if “grid/multigrid.h” is not included, then this is the quadtree with possibility of adaptation
#if 0 // QUADTREE
event adapt (i++) {
({f,u.x,u.y}, (double[]){5e-3,0.001,0.001}, LEVEL, LEVEL-2,
adapt_wavelet = {p,u,pf,uf,g,f});
list }
#endif
# Run
to run
qcc -g -O2 -Wall -o Sandglass3D Sandglass3D.c -lm
./Sandglass3D > out
Result
We plot the volume as function of time. it is linear after a transition, this is Beverloo law:p'out' w l
#Bibliography
L. Staron, P.-Y. Lagrée, & S. Popinet (2014) “Continuum simulation of the discharge of the granular silo, A validation test for the μ(I) visco-plastic flow law” Eur. Phys. J. E (2014) 37: 5 DOI 10.1140/epje/i2014-14005-6
L. Staron, P.-Y. Lagrée & S. Popinet (2012) “The granular silo as a continuum plastic flow: the hour-glass vs the clepsydra” Phys. Fluids 24, 103301 (2012); doi: 10.1063/1.4757390
Y. Zhou PhD