sandbox/tianlong/test/stefanproblem.c
The Stefan problem setup. This file is copied from Edorado’s sandbox and modified with EBIT.
#define SEMUPC 1
#define IS_1D 1
#define INTGRAD_3rd 1
#define USE_DOUBLE_VEL 1
#define ADV_SCHEME 2
#define TEST "data/"
#if USE_DOUBLE_VEL
#include "double-evaporation.h"
#else
#include "centered-evaporation.h"
#endif //USE_DOUBLE_VEL
#include "semushin_two-phase.h"
#include "semushin-phase-change.h"
#include "mytension.h"
#if USE_MY_SOLID
#include "mysolid.h"
#endif
int maxlevel = 6, minlevel = 3;
double Twall;
double lambdaval = 0.06779249298045148;
double delta0 = 322.5e-6;
double t_stop = 10.0;
double tshift, teff;
const double femax = 1e-6;
const int num_refine = 2;
//out flow for the right
u.n[right] = neumann (0);
p[right] = dirichlet (0);
pf[right] = dirichlet (0);
//wall for the left
u.t[left] = dirichlet (0);
uf.n[left] = 0.0;
TG[left] = dirichlet (Twall);
TL[left] = dirichlet (Twall);
T[left] = dirichlet (Twall);
double tempsol (double time, double x) {
return Twall + ((Tsat - Twall)/erf(lambdaval))*
erf(x/2./sqrt(lambda2/rho2/cp2*time));
}
//use symmetry for the top and bottom (imposed in the solid setup)
#if USE_MY_SOLID
void solidSetup()
{
double delta = L0 / (double)(1 << maxlevel);
SOLID_LEN_y = ((1 << maxlevel) - 1) * delta;
}
#endif
int main (int argc, char * argv[]) {
if (pid() == 0)
{
if (argc == 2)
{
maxlevel = atoi(argv[1]);
}
}
#if _MPI
MPI_Bcast(&maxlevel, 1, MPI_INT, 0, MPI_COMM_WORLD);
#endif
rho1 = 958., rho2 = 0.6;
mu1 = 2.82e-4, mu2 = 1.23e-5;
lambda1 = 0.68, lambda2 = 0.025;
cp1 = 4216., cp2 = 2080.;
dhev = 2.256e6,The initial temperature and the interface temperature are set to the same value.
Tsat = 373.15, Twall = 383.15;We change the dimension of the domain and the surface tension coefficient.
L0 = 10e-3;We define a list with the maximum time steps and the maximum levels of refinement.
double dtlist[] = {0.01, 0.005, 0.001};
DT = dtlist[maxlevel - 4];
TOLERANCE = 1.0e-6;
NITERMAX = 300;
init_grid (1 << maxlevel);
#if USE_MY_SOLID
solidSetup();
origin(-SOLID_LEN_x, -SOLID_LEN_y);
#endif
run();
}
event defaults(i = 0)
{
#if USE_MY_SOLID
for (int ib = 0; ib < nboundary; ib++)
{
pf.boundary[ib] = p.boundary[ib];
}
setSolidFlag();
foreach_dimension()
{
if(IS_SOLID_x)
{
f.boundarySolid_x = boundarySolidNeumman_x;
uf.x.boundarySolid_x = boundarySolidVelF_x;
#if USE_DOUBLE_VEL
uf2.x.boundarySolid_x = boundarySolidVelF_x;
#endif
color_pha_cen.boundarySolid_x = boundarySolidNeumman_x;
s.x.boundarySolid_x = boundarySolidVectorZero_x;
s_tmp.x.boundarySolid_x = boundarySolidVectorZero_x;
with_marker.x.boundarySolid_x = boundarySolidVectorZero_x;
ss_tmp.x.boundarySolid_x = boundarySolidVectorZero_x;
color_cc.boundarySolid_x = boundarySolidNeumman_x;
mdot.boundarySolid_x = boundarySolidNeumman_x;
phi_dis.boundarySolid_x = boundarySolidNeumman_x;
T.boundarySolid_x = boundarySolidNeumman_x;
TL.boundarySolid_x = boundarySolidNeumman_x;
TG.boundarySolid_x = boundarySolidNeumman_x;
dTdnL.boundarySolid_x = boundarySolidNeumman_x;
dTdnG.boundarySolid_x = boundarySolidNeumman_x;
}
}
#endif
}We initialize the volume fraction field and the temperature in the gas and in liquid phase.
event init (i = 0) {
vertex scalar phi[];
foreach_vertex(){
phi[] = x - delta0;
}
init_markers(phi);
double effective_height = 0.0;
foreach(reduction(+:effective_height))
{
if(is_solid[] == 0)
{
effective_height += (1.0 - f[]) * Delta;
}
}
tshift = sq(effective_height/2./lambdaval)*rho2*cp2/lambda2;
foreach() {
TL[] = Tsat;
TG[] = x < delta0 ? tempsol(t + tshift, x) : Tsat;
T[] = f[] > 0.5 ? TL[] : TG[];
foreach_dimension()
{
u.x[] = 0.0;
}
}
boundary({T, TL, TG});
getColorExact(color_cc);
getMdot(color_cc, mdot);
}
void mg_print (mgstats mg)
{
if (mg.i > 0 && mg.resa > 0.)
printf ("%d %g %g %g %d ", mg.i, mg.resb, mg.resa,
mg.resb > 0 ? exp (log (mg.resb/mg.resa)/mg.i) : 0.,
mg.nrelax);
}
event outLog(i++)
{
if(pid() == 0 && i % 100 == 0)
{
printf("i = %d t = %g dt = %g\n", i, t, dt);
}
}We refine the interface and the region where the temperature field changes.
#if TREE
event adapt (i++) {
//correct the strange change of vertex color
foreach_vertex()
{
double vofs = f[] + f[0, -1] + f[-1] + f[-1, -1];
if(vofs == 0.0)
color_pha[] = 0.0;
else if(vofs == 4.0)
color_pha[] = 1.0;
#if USE_MY_SOLID
color_pha[] *= (1.0 - is_solid_vertex[]);
#endif
}
}
#endif
double exact (double time) {
return 2.*lambdaval*sqrt(lambda2/rho2/cp2*time);
}Output Files
We write the thickness of the vapor layer and the analytic solution on a file.
event movie (t += 0.1) {
double effective_height = 0.;
foreach(reduction(+:effective_height))
{
if(is_solid[] == 0)
{
effective_height += (1.0 - f[]) * Delta;
}
}
double relerr = fabs (exact(t+tshift) - effective_height) / exact(t+tshift);
char name[80];
sprintf (name, "data/OutputData-%d", maxlevel);
static FILE * fp = fopen (name, "w");
fprintf (fp, "%g %g %g %g\n", t+tshift, effective_height, exact (t+tshift), relerr);
fflush (fp);
}
event finalEvent(t = t_stop)
{
double effective_height = 0.;
foreach(reduction(+:effective_height))
{
if(is_solid[] == 0)
{
effective_height += (1.0 - f[]) * Delta;
}
}
char name[80];
sprintf(name, "data/Temperature-%d", maxlevel);
Array *arrtemp = array_new();
for (double x = 0.; x < L0; x += 0.5 * L0 / (1 << maxlevel))
{
double val = x > effective_height ? interpolate(TL, x, 0.) : interpolate(TG, x, 0.);
val = (val == nodata) ? 0. : val;
array_append(arrtemp, &val, sizeof(double));
}
double *temps = (double *)arrtemp->p;
#if _MPI
int size = arrtemp->len / sizeof(double);
MPI_Allreduce(MPI_IN_PLACE, temps, size, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
#endif
if(pid() == 0)
{
FILE *fpp = fopen(name, "w");
int count = 0;
for (double x = 0.; x < L0; x += 0.5 * L0 / (1 << maxlevel))
{
double R = exact(t + tshift);
double tempexact = x < R ? tempsol(t + tshift, x) : Tsat;
fprintf(fpp, "%g %g %g\n", x, temps[count], tempexact);
count++;
}
fflush(fpp);
fclose(fpp);
}
array_free(arrtemp);
int Ncell = 1 << grid->maxdepth;
//the last facial velocity will be omitted
double *ucx = (double *)calloc(Ncell, sizeof(double));
double *ufx = (double *)calloc(Ncell, sizeof(double));
for(int ii = 0; ii < Ncell; ++ii)
{
ucx[ii] = 0.0;
ufx[ii] = 0.0;
}
foreach_boundary(top, reduction(+ : ucx[:Ncell]) reduction(+ : ufx[:Ncell]))
{
#if !USE_DOUBLE_VEL
ucx[point.i - 2] = u.x[];
ufx[point.i - 2] = uf.x[];
#else
ucx[point.i - 2] = x > effective_height ? u.x[] : u2.x[];
ufx[point.i - 2] = (x - 0.5 * Delta) > effective_height ? uf.x[] : uf2.x[];
#endif
}
char name_uc[60];
char name_uf[60];
sprintf(name_uc, "data/uc-%d", maxlevel);
sprintf(name_uf, "data/uf-%d", maxlevel);
if (pid() == 0)
{
FILE *fpc = fopen(name_uc, "w");
FILE *fpf = fopen(name_uf, "w");
double delta = L0 / Ncell;
int count = 0;
for (double x = 0.5 * delta; x < L0; x += delta)
{
fprintf(fpc, "%g %g\n", x, ucx[count]);
fprintf(fpf, "%g %g\n", x - 0.5 * delta, ufx[count]);
++count;
}
fflush(fpc);
fclose(fpc);
fflush(fpf);
fclose(fpf);
// exact velocity
double alpha_g = lambda2 / rho2 / cp2;
double ugamma = lambdaval * sqrt(alpha_g / (t + tshift));
double uliq = ugamma - rho2 * ugamma / rho1;
sprintf(name, "data/uexact");
FILE *fpp = fopen(name, "w");
fprintf(fpp, "%g %g\n", exact(t + tshift), uliq);
fclose(fpp);
}
free(ucx);
free(ufx);
sprintf(name, "data/dump-%d", maxlevel);
dump(name);
// do nothing
}