sandbox/bugs/marginal_embed_2.c
This code demonstrates a bug where the no-slip condition is violated at the embedded boundary in pressure-driven viscous microchannel flow. It is similar to Antoon van Hooft’s code for scalar mixing in a tube flow where the key difference is here I numerically compute the flow field instead of prescribing the exact solution.




#include "embed.h"
#include "navier-stokes/centered.h"
#include "diffusion.h"
#include "run.h"
#define tfinal 1
#define time_step 0.1
#define length 5
#define aspect_ratio 10
scalar c[], * tracers = {c};
int main() {
The goal is to simulate viscous Stokes flow, although the convective term of the Navier-Stokes equations can be turned on (leaving the default stokes = false) for debugging purposes.
# if 1
= true;
stokes //TOLERANCE = HUGE;
= 2;
NITERMIN = time_step;
DT # endif
The suggested workaround for this already-documented bug to adjust the domain size or origin did not do the trick.
You can define microchannel geometry here. As suggested in a previous post, moving the boundary (try adjusting the multiplying factor in yoffset) did not help.
double width = L0/aspect_ratio; double yoffset = length*0.5;
solid (cs, fs, -(width/2 - y + yoffset)*(-width/2 - y + yoffset));
refine (cs[] && level < 10);
fractions_cleanup(cs, fs);
// boundary conditions
[left] = dirichlet(0); c[right] = dirichlet(0); c[embed] = neumann(0); c
Both BC’s #1 and #2 led to some instabilities near the channel inlet on the left, and have very different flow fields despite similar pressure fields.
// BC #1: assign a pressure gradient
//p[left] = dirichlet(1)*cs[]; p[right] = dirichlet(0);
// BC #2: uniform inflow and outflow
//u.n[left] = dirichlet(1)*cs[]; u.n[right] = dirichlet(1)*cs[];
The no-slip condition is implemented here but seems to be ignored by the solver.
Alternatively to either BC #1 or #2, you can drive flow through this acceleration term (making sure to select BC #1). In this case, the no-slip condition is observed, however if the advective term of the solute is turned on, the concentration c goes to zero everywhere.
# if 1
// using acceleration term to assign dpdx
const face vector g[] = {-1.,0.};
= g;
a = fm;
mu # endif
Initialize the solute as a thin plug.
// intialize solute cloud
double startpoint = length/4;
foreach()
[] = (startpoint < x)*(x < startpoint*1.1)*cs[];
c}
The advection and diffusion of the scalar are enforced here, although while debugging the flow field I comment out the advection call.
// simple advection diffusion of passive scalar c
event advection_and_diffusion (i++) {
face vector kappa[];
foreach_face()
.x[] = fs.x[]*0.01;
kappa(c, dt, kappa);
diffusion //advection({c}, u, DT);
}
// Generate images at the final timestep.
event stop (t = tfinal) {
output_ppm (c, file = "c.png", n=400);
output_ppm (u.x, file = "ux.png", n=400);
output_ppm (u.y, file = "uy.png", n=400);
output_ppm (p, file = "p.png", n=400);
}