sandbox/ecipriano/run/fixedbubblevelocity.c
Fixed Flux Bubble Expansion
Expansion of a bubble with a fixed vaporization rate. This test case was proposed by Tanguy et al., 2014 and it is interesting because it can be used to test the velocity profile with the Stefan flow, and how the velocity changes when the volume expansion term in the continuity equation is shifted and/or distributed.
We perform this test case using the Velocity Potential approach, and we compare the results both with the theoretical velocity profile and with the numerical results obtained by Tanguy et al., 2014. The same test is repeated using the Velocity Extrapolation approach, providing a better and smoother velocity profile for the advection of the volume fraction, at the cost of a higher computational time.
The animation shows the growth of the bubble in time.Phase Change Setup
If the Velocity Potential approach is used, we divide the mass balance by the density of the gas phase, and we avoid the Stefan flow shifting procedure. If Velocity Extrapolation is used, we divide the mass balance by the liquid phase density, and we shift the expansion term toward the gas phase.
#if EXTRAPOLATION
# define INT_USE_UF
# define CONSISTENTPHASE2
# define SHIFT_TO_GAS
#else
# define NOSHIFTING
# define BYRHOGAS
#endif
Simulation Setup
We use the centered Navier-Stokes equations solver with the evaporation source term in the projection step. The evporation model is combined with the fixed flux mechanism, that imposes a constant vaporization flowrate.
#include "grid/multigrid.h"
#include "navier-stokes/centered-evaporation.h"
#if EXTRAPOLATION
# include "navier-stokes/velocity-extrapolation.h"
# define ufext ufext1
#else
# include "navier-stokes/velocity-potential.h"
#endif
#include "two-phase.h"
#include "tension.h"
#include "evaporation.h"
#include "fixedflux.h"
#include "view.h"
Boundary Conditions
Outflow boundary conditions are imposed on every domain boundary since the bubble is initially placed at the center of the domain. We set the BCs also for the velocity potential ps.
u.n[top] = neumann (0.);
u.t[top] = neumann (0.);
p[top] = dirichlet (0.);
#if EXTRAPOLATION
ps1[top] = dirichlet (0.);
ps2[top] = dirichlet (0.);
#else
ps[top] = dirichlet (0.);
#endif
u.n[right] = neumann (0.);
u.t[right] = neumann (0.);
p[right] = dirichlet (0.);
#if EXTRAPOLATION
ps1[right] = dirichlet (0.);
ps2[right] = dirichlet (0.);
#else
ps[right] = dirichlet (0.);
#endif
u.n[left] = neumann (0.);
u.t[left] = neumann (0.);
p[left] = dirichlet (0.);
#if EXTRAPOLATION
ps1[left] = dirichlet (0.);
ps2[left] = dirichlet (0.);
#else
ps[left] = dirichlet (0.);
#endif
u.n[bottom] = neumann (0.);
u.t[bottom] = neumann (0.);
p[bottom] = dirichlet (0.);
#if EXTRAPOLATION
ps1[bottom] = dirichlet (0.);
ps2[bottom] = dirichlet (0.);
#else
ps[bottom] = dirichlet (0.);
#endif
Model Data
We set the initial radius of the bubble, the value of the vaporization rate, and the maximum level of refinement.
int maxlevel = 7;
double D0 = 0.002, mEvapVal = -0.1;
double effective_radius0;
int main (void) {
We set the density and viscosity values.
rho1 = 1000., rho2 = 1.;
mu1 = 0.001, mu2 = 1.78e-5;
We set the surface tension coefficient.
f.sigma = 0.07;
We change the dimension of the domain and we shift the origin.
L0 = 0.008;
origin (-0.5*L0, -0.5*L0);
We modify the number of layers used in velocity-extrapolation.h in order to extrapolate the gas phase velocity from the second layer of cells close to the interface. This is necessary if the expansion term is shifted toward the gas phase.
#if EXTRAPOLATION
nl1 = 2;
#endif
We setup the grid and run the simulation.
We initialize the volume fraction field, and from that field we compute the numerical initial radius.
event init (i = 0) {
fraction (f, -circle(x,y,0.5*D0));
double gasvol = 0.;
foreach(reduction(+:gasvol))
gasvol += (1. - f[])*dv();
effective_radius0 = sqrt (gasvol/pi);
}
We adapt the grid according to the velocity and the volume fraction fields.
#if TREE
event adapt (i++) {
adapt_wavelet_leave_interface ({u.x,u.y}, {f},
(double[]){1.e-3,1.e-3}, maxlevel, 1);
}
#endif
Post-Processing
The following lines of code are for post-processing purposes.
Exact Solution
We write a function that computes the analytic solution for the bubble radius.
double exact (double t) {
return effective_radius0 - mEvapVal/rho2*t;
}
Output Files
We write the bubble radius from the numerical simulation, the exact radius and the relative error.
event output_data (i++) {
char name[80];
sprintf (name, "OutputData-%d", maxlevel);
static FILE * fp = fopen (name, "w");
double gasvol = 0.;
foreach(reduction(+:gasvol))
gasvol += (1. - f[])*dv();
double effective_radius = sqrt (gasvol/pi);
double relerr = fabs (exact(t) - effective_radius) / exact(t);
fprintf (fp, "%g %g %g %g\n", t, effective_radius, exact(t), relerr);
fflush (fp);
}
Velocity Profile
We write on a file the velocity profile at a specific time step.
event profiles (t = 0.005,last) {
char name[80];
sprintf (name, "Profiles-%d", maxlevel);
FILE * fp = fopen (name, "w");
We create an array with the mass fraction profiles for each processor.
Array * arruf = array_new();
Array * arrus = array_new();
for (double x = 0.; x < 0.5*L0; x += 0.05*L0/(1 << maxlevel)) {
double val_uf = interpolate (uf.x, x, 0.);
#if EXTRAPOLATION
double val_us = 0.;
#else
double val_us = interpolate (ufs.x, x, 0.);
#endif
val_uf = (val_uf == nodata) ? 0. : val_uf;
val_us = (val_us == nodata) ? 0. : val_us;
array_append (arruf, &val_uf, sizeof(double));
array_append (arrus, &val_us, sizeof(double));
}
double * val_ufp = (double *)arruf->p;
double * val_usp = (double *)arrus->p;
We sum each element of the arrays in every processor.
@if _MPI
int size = arruf->len/sizeof(double);
MPI_Allreduce (MPI_IN_PLACE, val_ufp, size, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
MPI_Allreduce (MPI_IN_PLACE, val_usp, size, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
@endif
The master node writes the profiles on a file.
if (pid() == 0) {
int count = 0;
for (double x = 0.; x < 0.5*L0; x += 0.05*L0/(1 << maxlevel)) {
fprintf (fp, "%g %g %g\n", x, val_ufp[count], val_usp[count]);
count++;
}
fprintf (fp, "\n\n");
fflush (fp);
}
fclose (fp);
array_free (arruf);
array_free (arrus);
}
Movie
We write the animation with the evolution of the volume fraction field and the gas-liquid interface.
event movie (t += 0.0001; t <= 0.01) {
clear();
draw_vof ("f", lw = 1.5);
squares ("f", min = 0., max = 1., linear = true);
save ("movie.mp4");
#if EXTRAPOLATION
clear();
draw_vof ("f", lw = 1.5);
squares ("uext1.x", spread = -1, linear = true);
vectors ("uext1.x", scale = 1.e-3, lc = {1.,1.,1.});
save ("movie-uext1.mp4");
clear();
draw_vof ("f", lw = 1.5);
squares ("uext2.x", spread = -1, linear = true);
save ("movie-uext2.mp4");
#endif
}
Results
We compare the velocity profile with the theretical solution and with the results obtained by Tanguy et al., 2014 (Fig. 5 (b), (c)).
reset
set xlabel "radius [m]"
set ylabel "Velocity [m/s]"
set key top right
set size square
set grid
plot "../data/tanguy-fixedbubblevelocity-theoretical.csv" u 1:2 w p pt 6 t "Theoretical", \
"../data/tanguy-fixedbubblevelocity-b.csv" u 1:2 w p pt 6 t "Tanguy et al., 2014 b", \
"../data/tanguy-fixedbubblevelocity-c.csv" u 1:2 w p pt 6 t "Tanguy et al., 2014 c", \
"Profiles-7" u 1:2 w l lw 1.2 t "Field Velocity (potential)", \
"../fixedbubblevelocity-extrapolation/Profiles-7" u 1:2 w l lw 1.2 t "Field Velocity (extrapolation)"
reset
set xlabel "t [s]"
set ylabel "Bubble Radius [m]"
set key top left
set size square
set grid
plot "OutputData-7" u 1:2 w l lw 2 t "LEVEL 7 potential", \
"../fixedbubblevelocity-extrapolation/OutputData-7" u 1:2 w l lw 2 t "LEVEL 7 extrapolation", \
"OutputData-7" every 20 u 1:3 w p pt 8 ps 1.5 t "Analytical"
Extrapolated Velocity Fields
The following animations show the evolution of the extrapolated velocities ufext1.x
and ufext2.x
. The liquid phase velocity is used for the transport of the volume fraction. We notice that the extrapolation procedure leads to a velocity field which is smooth and continuous across the interface. The extrapolation procedure is expensive, and for this reason it is performed just for a few steps, without the need to extrapolate the velocity field over the whole domain. We just need a few cells across the interface.
References
[tanguy2014benchmarks] |
Sébastien Tanguy, Michaël Sagan, Benjamin Lalanne, Frédéric Couderc, and Catherine Colin. Benchmarks and numerical methods for the simulation of boiling flows. Journal of Computational Physics, 264:1–22, 2014. |