sandbox/ecipriano/src/navier-stokes/velocity-jump.h
#define VELOCITY_JUMP 1
#include "common.h"
#include "utils.h"
#include "aslam.h"
scalar jump[];
face vector jumpf[];
vector n[], ur[];
face vector nf[];
scalar pg[], ps[];
bool _boiling = false;
vector u1g[], u2g[];
face vector uf1g[], uf2g[];
extern scalar f;Projection Function
We define the function that performs the projection step with the volume expansion term due to the phase change or due to density changes.
#include "poisson.h"
extern scalar * drhodtlist, * plist;
extern face vector * uflist;
mgstats mgpl, mgpe;
trace
mgstats project_jump (face vector * uflist, scalar * plist,
(const) face vector alpha = unityf,
double dt = 1.,
int nrelax = 4)
{
scalar p1 = plist[1], p2 = plist[0];
face vector uf1 = uflist[1], uf2 = uflist[0];We allocate a local scalar field and compute the divergence of \mathbf{u}_f. The divergence is scaled by dt so that the pressure has the correct dimension.
scalar div[];
scalar drhodt1 = drhodtlist[1], drhodt2 = drhodtlist[0];
foreach() {
double div1 = 0., div2 = 0.;
foreach_dimension() {
div1 += uf1.x[1] - uf1.x[];
div2 += uf2.x[1] - uf2.x[];
}
div1 /= dt*Delta;
div2 /= dt*Delta;
div1 += drhodt1[]/dt;
div2 += drhodt2[]/dt;
div[] = (f[] > 0.5) ? div1 : div2;
}We solve the Poisson problem. The tolerance (set with TOLERANCE) is the maximum relative change in volume of a cell (due to the divergence of the flow) during one timestep i.e. the non-dimensional quantity |\nabla\cdot\mathbf{u}_f|\Delta t Given the scaling of the divergence above, this gives
mgstats mgp = poisson (p1, div, alpha,
tolerance = TOLERANCE/sq(dt), nrelax = nrelax);
foreach()
p2[] = p1[];And compute \mathbf{u}_f^{n+1} using \mathbf{u}_f and p.
foreach_face() {
uf1.x[] -= dt*alpha.x[]*face_gradient_x (p1, 0);
uf2.x[] -= dt*alpha.x[]*face_gradient_x (p2, 0);
}
return mgp;
}
trace
mgstats project_ghost (face vector uf, face vector ufg, scalar p,
(const) face vector alpha = unityf,
double dt = 1.,
int nrelax = 4)
{We allocate a local scalar field and compute the divergence of \mathbf{u}_f. The divergence is scaled by dt so that the pressure has the correct dimension.
scalar div[], drhodt = drhodtlist[1];
foreach() {
div[] = 0.;
foreach_dimension()
div[] += uf.x[1] - uf.x[];
div[] /= dt*Delta;
div[] += drhodt[]/dt;
}We solve the Poisson problem. The tolerance (set with TOLERANCE) is the maximum relative change in volume of a cell (due to the divergence of the flow) during one timestep i.e. the non-dimensional quantity |\nabla\cdot\mathbf{u}_f|\Delta t Given the scaling of the divergence above, this gives
And compute \mathbf{u}_f^{n+1} using \mathbf{u}_f and p.
foreach_face()
ufg.x[] = uf.x[] - dt*alpha.x[]*face_gradient_x (p, 0);
return mgp;
}
trace
mgstats project_liquid (face vector uf, face vector ufg, scalar p,
(const) face vector alpha = unityf,
double dt = 1.,
int nrelax = 4)
{We allocate a local scalar field and compute the divergence of \mathbf{u}_f. The divergence is scaled by dt so that the pressure has the correct dimension.
scalar div[], drhodt = drhodtlist[1];
foreach() {
div[] = 0.;
foreach_dimension()
div[] += ufg.x[1] - ufg.x[];
div[] /= dt*Delta;
div[] += drhodt[]/dt;
}We solve the Poisson problem. The tolerance (set with TOLERANCE) is the maximum relative change in volume of a cell (due to the divergence of the flow) during one timestep i.e. the non-dimensional quantity |\nabla\cdot\mathbf{u}_f|\Delta t Given the scaling of the divergence above, this gives
And compute \mathbf{u}_f^{n+1} using \mathbf{u}_f and p.
foreach_face()
uf.x[] = ufg.x[] - dt*alpha.x[]*face_gradient_x (p, 0);
return mgp;
}
#define project(...) project_jump(__VA_ARGS__)
#include "navier-stokes/low-mach.h"
#undef project
event defaults (i = 0) {
for (int d = 0; d < nboundary; d++) {
pg.boundary[d] = p.boundary[d];
pg.boundary_homogeneous[d] = p.boundary_homogeneous[d];
ps.boundary[d] = p.boundary[d];
ps.boundary_homogeneous[d] = p.boundary_homogeneous[d];
}
}
scalar ls[];
event advection_term (i++,last) {
assert (nv == 2);
vector u1 = ulist[1], u2 = ulist[0];
vector uf1 = uflist[1], uf2 = uflist[0];
gradients ({ls}, {n});
foreach() {
double mag = 0.;
foreach_dimension()
mag += sq (n.x[]);
mag = sqrt (mag);
foreach_dimension()
n.x[] /= (mag + 1e-10);
}
foreach_face()
nf.x[] = face_value (n.x, 0);We compute the value of the centered ghost velocities.
foreach() {
foreach_dimension() {
if (_boiling) {
//u2g.x[] = 0.;
u1g.x[] = u2.x[] + jump[]*n.x[];
}
else {
//u1g.x[] = 0.;
u2g.x[] = u1.x[] - jump[]*n.x[];
}
}
}We compute the value of the face ghost velocities. The interface normal on the face is computed using the level set.
foreach_face() {
if (_boiling) {
uf2g.x[] = 0.;
uf1g.x[] = uf2.x[] + jumpf.x[]*nf.x[]*fm.x[];
}
else {
uf1g.x[] = 0.;
uf2g.x[] = uf1.x[] - jumpf.x[]*nf.x[]*fm.x[];
}
}
foreach() {
foreach_dimension() {
u1.x[] = (f[] > 0.5) ? u1.x[] : u1g.x[];
u2.x[] = (f[] < 0.5) ? u2.x[] : u2g.x[];
}
}
foreach_face() {
double ff = face_value (f, 0);
uf1.x[] = (ff > 0.5) ? uf1.x[] : uf1g.x[];
uf2.x[] = (ff < 0.5) ? uf2.x[] : uf2g.x[];
}
}
event viscous_term (i++,last) {
//setjump (f, ulist[1], ulist[0], jump, n);
//setjumpf (f, uflist[1], uflist[0], jumpf, nf);
}
event acceleration (i++,last) {
//setjump (f, ulist[1], ulist[0], jump, n);
//setjumpf (f, uflist[1], uflist[0], jumpf, nf);
}
event projection (i++,last) {
if (_boiling) {
vector uf2 = uflist[0];
project_ghost (uf2, uf2g, pg, alpha, dt, mgpl.nrelax);
vector gpg[], u2 = ulist[0];
centered_gradient (pg, gpg);
foreach()
foreach_dimension()
u2g.x[] = u2.x[] + dt*gpg.x[];
}
else {
vector uf1 = uflist[1];
project_ghost (uf1, uf1g, pg, alpha, dt, mgpl.nrelax);
vector gpg[], u1 = ulist[1];
centered_gradient (pg, gpg);
foreach()
foreach_dimension()
u1g.x[] = u1.x[] + dt*gpg.x[];
}
}
event end_timestep (i++,last) {
vector u1 = ulist[1], u2 = ulist[0];
if (!_boiling) {
face vector uf1 = uflist[1], uf2 = uflist[0];
foreach() {
foreach_dimension() {
u1g.x[] = u1g.x[];
u2g.x[] = u1.x[] - jump[]*n.x[];
}
}
foreach_face() {
uf1g.x[] = uf1g.x[];
uf2g.x[] = uf1.x[] - jumpf.x[]*nf.x[]*fm.x[];
}
face vector ufs[];
foreach_face() {
double ff = face_value (f, 0);
ufs.x[] = (ff > 0.5) ? uf1.x[] : uf1g.x[];
}
project_liquid (uf1, ufs, ps, alpha, dt, mgpe.nrelax);
foreach_face()
uf1g.x[] = uf1.x[];
foreach() {
foreach_dimension() {
u1.x[] = (f[] > 0.5) ? u1.x[] : u1g.x[];
u2.x[] = (f[] < 0.5) ? u2.x[] : u2g.x[];
}
}
foreach_face() {
double ff = face_value (f, 0);
uf1.x[] = (ff > 0.5) ? uf1.x[] : uf1g.x[];
uf2.x[] = (ff < 0.5) ? uf2.x[] : uf2g.x[];
}
}
// Reconstruction
foreach()
foreach_dimension()
ur.x[] = u1.x[]*f[] + u2.x[]*(1. - f[]);
}
