sandbox/ecipriano/test/low-mach.c
VOF advection with non-solenoidal velocity
We test the convergence of the VOF method in combination with a prescribed non divergence-free velocity field.
#include "navier-stokes/low-mach.h"
#include "two-phase.h"
#include "tension.h"
#include "view.h"
#define DIVERGENCE 0
scalar divu[];
u.n[top] = neumann (0.);
u.t[top] = neumann (0.);
p[top] = dirichlet (0.);
u.n[right] = neumann (0.);
u.t[right] = neumann (0.);
p[right] = dirichlet (0.);
int maxlevel;
double R0 = 0.05;
int main (void) {
rho1 = rho2 = 1;
mu1 = mu2 = 1;
f.sigma = 0.03;
for (maxlevel = 4; maxlevel <= 9; maxlevel++) {
init_grid (1 << maxlevel);
run();
}
}
#define circle(x,y,R) (sq(R) - sq(x) - sq(y))
event init (i = 0) {
fraction (f, circle (x, y, R0));
}
double exact (double t) {
return R0 + t;
}
event output (t += 0.01) {
double R = sqrt (4./pi*statsf (f).sum);
double err = fabs (R - exact (t)) / exact (t);
fprintf (stderr, "maxres %d %g %g %g %g\n",
maxlevel, t, R, exact (t), err);
}
void exact_velocity (vector u, face vector uf, scalar divu) {
foreach_face() {
coord o = {x,y,z};
double mag = sqrt (sq(x) + sq(y));
uf.x[] = o.x / (mag + 1e-10);
}
foreach() {
coord o = {x,y,z};
double mag = sqrt (sq(x) + sq(y));
foreach_dimension()
u.x[] = o.x / (mag + 1e-10);
}
foreach() {
divu[] = 0.;
foreach_dimension()
divu[] += (uf.x[1] - uf.x[]);
divu[] /= -Delta;
}
}
void reset_velocity (vector u, face vector uf) {
foreach()
foreach_dimension()
u.x[] = 0.;
foreach_face()
uf.x[] = 0.;
}
#if DIVERGENCE
event tracer_diffusion (i++) {
exact_velocity (u, uf, drhodt);
reset_velocity (u, uf);
}
event end_timestep (t = end) {
vector ue[];
face vector ufe[];
exact_velocity (ue, ufe, drhodt);
scalar e[];
foreach()
e[] = norm (u) - norm (ue);
norm n = normf (e);
fprintf (stderr, "error %d %g %g %g\n", maxlevel, n.avg, n.rms, n.max);
}
#else
event end_timestep (i++) {
exact_velocity (u, uf, drhodt);
}
#endif
#if TREE
event adapt (i++) {
scalar ff[];
foreach()
ff[] = f[];
adapt_wavelet ({f}, (double[]){1e-3}, maxlevel);
}
#endif
event stop (t += 0.1; t <= 0.7) {
scalar magu[];
foreach()
magu[] = norm (u);
#if TREE
restriction ((scalar *){u});
#endif
clear();
view (tx = -0.5, ty = -0.5);
draw_vof ("f", lw = 1.5);
squares ("magu", spread = -1);
vectors ("u", scale = 0.001, level = 5);
save ("movie.mp4");
}Results
set xlabel "time"
set ylabel "Droplet Radius"
set size square
set grid
set key top left
plot "<grep 'maxres 5' log" u 3:4 w l dt 1 lc 2 t "LEVEL 5", \
"<grep 'maxres 6' log" u 3:4 w l dt 1 lc 3 t "LEVEL 6", \
"<grep 'maxres 7' log" u 3:4 w l dt 1 lc 4 t "LEVEL 7", \
"<grep 'maxres 8' log" u 3:4 w l dt 1 lc 5 t "LEVEL 8", \
"<grep 'maxres 8' log" u 3:4 w l dt 2 lc -1 t "Exact"stats "<grep 'maxres 4' log | tail -n 1" u 6 nooutput name "LEVEL4"
stats "<grep 'maxres 5' log | tail -n 1" u 6 nooutput name "LEVEL5"
stats "<grep 'maxres 6' log | tail -n 1" u 6 nooutput name "LEVEL6"
stats "<grep 'maxres 7' log | tail -n 1" u 6 nooutput name "LEVEL7"
stats "<grep 'maxres 8' log | tail -n 1" u 6 nooutput name "LEVEL8"
stats "<grep 'maxres 9' log | tail -n 1" u 6 nooutput name "LEVEL9"
set print "errors"
print sprintf ("%d %.12f", 2**4, LEVEL4_mean)
print sprintf ("%d %.12f", 2**5, LEVEL5_mean)
print sprintf ("%d %.12f", 2**6, LEVEL6_mean)
print sprintf ("%d %.12f", 2**7, LEVEL7_mean)
print sprintf ("%d %.12f", 2**8, LEVEL8_mean)
print sprintf ("%d %.12f", 2**9, LEVEL9_mean)
unset print
reset
set xlabel "N"
set ylabel "Relative Error"
set xr[2**3:2**10]
set size square
set grid
set logscale x 2
set logscale y
f(x) = a*x**-b
fit f(x) "errors" u ($1 > 2**5 ? $1 : $1/0):2 via a,b
ftitle(a,b) = sprintf("%.3f/x^{%4.2f}", exp(a), -b)
plot "errors" w p pt 8 title "Results", \
f(x) w l t ftitle(a,b)