flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
vof_wetting_dynamic Namespace Reference

Functions

 meniscus (w, theta_deg, dg, sigma=1.0, n=600)
 
 meniscus_mean (w, theta_deg, dg, sigma=1.0, xlo=None, xhi=None)
 
 jurin (w, theta_deg, dg, sigma=1.0)
 
 max_u (s, zlo=None)
 
 relax (s, steps, cfl=0.15, dt_cap=None, probe=0, cb=None, ramp=0.02)
 
 capsule_sdf (nx, ny, nz, xm, r, z0, z1)
 
 jurin_scene (nx=96, ny=4, nz=112, w=16.0, plate=8.0, zp=(12.0, 100.0))
 
 jurin_colour (nx, ny, nz, subsdf, zi_of_x, sub=4)
 
 set_zero_mean_buoyancy (s, dg, ratio, wos=False)
 
 _channel_columns (sdf, nz)
 
 level_of (cc, eps, xs)
 
 g3_static (theta=30.0, steps=500, nx=96, ny=4, nz=112, w=16.0, plate=8.0, dg=3.0e-3, sigma=1.0, mu=0.2, ratio=10.0, datum=28.0, zp=(12.0, 100.0), flat_start=False, wos=False)
 
 cap_sphere (volume, theta_deg)
 
 cap_colour (nx, ny, nz, cx, cy, zw, R, theta_deg=90.0)
 
 g2_spread (theta_e=30.0, slip=0.1, steps=1500, probe=50, nx=64, nz=40, R=12.0, zw=4.25, sigma=1.0, oh=0.1, dynamic=True, wall_slip=False)
 
 g3_rise (theta_e=30.0, slips=(0.05, 0.3), steps=1500, nx=96, ny=4, nz=112, w=16.0, plate=8.0, dg=3.0e-3, sigma=1.0, mu=0.2, ratio=10.0, datum=28.0, zp=(12.0, 100.0), static_control=True, wall_slip=False, probe=None, lw=False)
 
 g4_incline (theta_a=70.0, theta_r=50.0, bo_fracs=(0.5, 0.7, 1.5, 2.5), steps=1200, nx=48, nz=32, R=8.0, zw=4.25, sigma=1.0, oh=0.2, slip=0.1)
 

Variables

int PRESS_MAXIT = 300
 
float DEG = math.pi / 180.0
 
dict _MEN_CACHE = {}
 
list args = [a for a in sys.argv[1:] if not a.startswith("--")]
 
str quick = "--quick" in sys.argv
 
list which = args or ["jurin"]
 
 theta
 
 steps
 
 flat_start
 
 wos
 
 probe
 
list res = []
 
 sp
 
 wt
 
 am
 
 slip
 
 sl
 
list d_meas = res[i][1] - res[i - 1][1]
 
float d_pred = 9.0 * math.log(res[i - 1][0] / res[i][0])
 
 wall_slip
 
 slips
 
 lw
 
 False
 
 static_control
 
 True
 

Detailed Description

WO-V6 (rung V6) — the DYNAMIC contact angle and hysteresis: the gate battery, in Python.

Every gate prints its numbers; nothing is summarised into an adjective. The MODEL (state it with
every result, VOF_PLAN section 6):

    theta_Delta^3 = theta_e^3 + 9 Ca_cl ln(Delta/lambda),   Ca_cl = mu_l U_cl / sigma

Afkhami, Zaleski & Bussmann, JCP 228:5370 (2009). `lambda` is an EXPLICIT slip length in cells and
is never omitted from a reported number: a VoF contact line's numerical slip is proportional to the
cell size, so without it the imposed angle is silently grid-dependent.

  jurin   G3-static. CAPILLARY RISE, STATIC. Two 8-cell plates with ROUNDED ends (a capsule SDF, so
          there is no sharp 90-degree corner where |grad sdf| != 1) at QUARTER-integer placement,
          bounding a gap `w`; the periodic outer channel is a second capillary of width `w_out`.
          Both menisci rise, so the reference is the LEVEL DIFFERENCE. Jurin's
          `2 sigma cos(theta)/(drho g) (1/w - 1/w_out)` is the Bond -> 0 asymptote and is NOT the
          right reference at the Bond numbers a finite box affords; the exact reference is the
          static meniscus ODE `sigma z''/(1+z'^2)^{3/2} = drho g (z - z_ref)` with `z'(w/2) =
          cot(theta)`, solved here by shooting. Both are printed.

  spread  G2. SPREADING DROP vs Cox-Voinov. A drop released as a hemisphere on a wall with
          `theta_e = 30`: the contact radius a(t) and the apparent angle theta_app(t) are measured
          from the shape, `Ca_cl = mu (da/dt)/sigma` from the contact line's own motion, and
          `theta_app^3 - theta_e^3` is fitted against `Ca_cl`. The composition property of
          Cox-Voinov says the slope is `9 ln(a/lambda)`: the fill supplies `9 ln(Delta/lambda)` and
          the resolved hydrodynamics supply `9 ln(a/Delta)`. Tanner's `a ~ t^(1/10)` at late times
          is reported alongside.

  rise    G3-dynamics. The same plate scene from a FLAT interface, with the dynamic angle, over a
          slip sweep: the rise curve h(t), the final height against the static equilibrium, and the
          damping class (asymptotic vs oscillatory) — the two regimes Gruending et al. (AMM 86:142,
          2020) separate.

  incline G4. HYSTERESIS: a drop on a tilted wall (the wall is kept axis-aligned and GRAVITY is
          tilted, which is the same problem and keeps the SDF exact). Below the critical Bond
          number `Bo_c = cos(theta_r) - cos(theta_a)` the contact line must stay PINNED; above it
          the drop slides with the front near theta_a and the rear near theta_r.

Usage:
    PYTHONPATH=$PWD/build_cuda python tests/study/vof_wetting_dynamic.py [jurin spread rise incline]
    ... --quick        shorter runs

Function Documentation

◆ meniscus()

vof_wetting_dynamic.meniscus (   w,
  theta_deg,
  dg,
  sigma = 1.0,
  n = 600 
)
The exact 2-D static meniscus in a slot of width `w` with contact angle `theta` on both
walls, in gravity `dg = drho*g`:

    sigma z''/(1 + z'^2)^{3/2} = dg (z - z_ref),    z'(0) = 0,   z'(w/2) = cot(theta)

measured from the flat far-field datum `z_ref = 0`. Shooting on z(0) (monotone: a higher
meniscus has a steeper wall slope). Returns (x, z) on [0, w/2] — the profile is symmetric.
Reduces to Jurin `z = 2 sigma cos(theta)/(dg w)` as Bond -> 0.

Definition at line 59 of file vof_wetting_dynamic.py.

References jurin().

Referenced by g3_static(), and meniscus_mean().

◆ meniscus_mean()

vof_wetting_dynamic.meniscus_mean (   w,
  theta_deg,
  dg,
  sigma = 1.0,
  xlo = None,
  xhi = None 
)
The MEAN interface height over x in [xlo, xhi] (default the whole slot, x measured from the
LEFT wall) — the quantity the colour-integral level read-out measures.

Definition at line 112 of file vof_wetting_dynamic.py.

References meniscus().

Referenced by g3_static().

◆ jurin()

vof_wetting_dynamic.jurin (   w,
  theta_deg,
  dg,
  sigma = 1.0 
)

Definition at line 126 of file vof_wetting_dynamic.py.

Referenced by g3_rise(), g3_static(), and meniscus().

◆ max_u()

vof_wetting_dynamic.max_u (   s,
  zlo = None 
)

Definition at line 131 of file vof_wetting_dynamic.py.

Referenced by relax().

◆ relax()

vof_wetting_dynamic.relax (   s,
  steps,
  cfl = 0.15,
  dt_cap = None,
  probe = 0,
  cb = None,
  ramp = 0.02 
)
`ramp`: the first step is taken at `ramp * dt_cap`, because the interface-local Courant
number is read BEFORE the step and is 0 at rest — a full first step on a scene with a strong
initial capillary imbalance overshoots the Weymouth-Yue cap and the advector (correctly) throws.

Definition at line 139 of file vof_wetting_dynamic.py.

References max_u().

Referenced by g3_rise(), g3_static(), and g4_incline().

◆ capsule_sdf()

vof_wetting_dynamic.capsule_sdf (   nx,
  ny,
  nz,
  xm,
  r,
  z0,
  z1 
)
A plate of thickness 2r centred on x = xm, spanning z in [z0, z1] with SEMICIRCULAR ends:
the distance to the segment (xm, z0+r) -> (xm, z1-r) minus r. Flat vertical faces at xm +/- r,
no sharp corner anywhere (|grad sdf| = 1 everywhere outside the axis).

Definition at line 170 of file vof_wetting_dynamic.py.

Referenced by jurin_scene().

◆ jurin_scene()

vof_wetting_dynamic.jurin_scene (   nx = 96,
  ny = 4,
  nz = 112,
  w = 16.0,
  plate = 8.0,
  zp = (12.0, 100.0) 
)
The two rounded plates. Returns (sdf, xm_gap, xm_outer, w_out, subsdf); the plate FACES sit
at quarter-integer x (WO-S finding 5: at a half-integer the wall cell's tangential MAC faces sit
on the SDF zero level and close, and the contact line cannot move). `subsdf(x, z)` is the same
SDF as a callable, for sub-cell sampling of the initial colour.

Definition at line 182 of file vof_wetting_dynamic.py.

References capsule_sdf().

Referenced by g3_rise(), and g3_static().

◆ jurin_colour()

vof_wetting_dynamic.jurin_colour (   nx,
  ny,
  nz,
  subsdf,
  zi_of_x,
  sub = 4 
)
C = liquid fraction of the FLUID volume of each cell (VOF_PLAN rule 2), for an interface
z = zi(x). The FLUID restriction is not cosmetic: a sub-cell of a cut wall column that is
sampled as if it were fluid drops that column's C to `eps`, and a C of 0.75 in the middle of
the liquid is a FAKE INTERFACE that the V3 cascade turns into |kappa| ~ 3e6 (measured).

Definition at line 203 of file vof_wetting_dynamic.py.

Referenced by g3_rise(), and g3_static().

◆ set_zero_mean_buoyancy()

vof_wetting_dynamic.set_zero_mean_buoyancy (   s,
  dg,
  ratio,
  wos = False 
)
`force_z = g (rho_bar - rho)` with `g = dg/(rho_l - rho_g)`: the buoyancy that produces the
prescribed `drho g` AND has zero volume mean.

THIS IS THE FIX THAT MAKES THE JURIN SCENE WORK, and the defect it removes is what WO-S's G4
measured. The obvious "zero in the gas, -dg in the liquid" form (`[dg/(ratio-1), -dg/(1-1/ratio)]`,
which is what WO-S used) has a NON-ZERO volume mean, and in a fully periodic box a non-zero-mean
body force accelerates the whole fluid without bound (WO-Q finding 9). Worse than a drift: the
accelerating frame contributes its own `-rho a` body force, i.e. it CANCELS PART OF GRAVITY, so
the menisci relax towards a smaller level difference the longer the run goes — exactly the -83 %
WO-S recorded, with the accompanying non-decaying `max|u|`.

Definition at line 218 of file vof_wetting_dynamic.py.

Referenced by g3_rise(), and g3_static().

◆ _channel_columns()

vof_wetting_dynamic._channel_columns (   sdf,
  nz 
)
protected
The fluid columns of the gap and of the periodic outer channel, as index arrays. EVERY fluid
column is included, cut ones too: the level read-out is eps-weighted, so the full-width mean is
what the exact identity below refers to.

Definition at line 244 of file vof_wetting_dynamic.py.

Referenced by g3_rise(), and g3_static().

◆ level_of()

vof_wetting_dynamic.level_of (   cc,
  eps,
  xs 
)

Definition at line 259 of file vof_wetting_dynamic.py.

Referenced by g3_rise(), and g3_static().

◆ g3_static()

vof_wetting_dynamic.g3_static (   theta = 30.0,
  steps = 500,
  nx = 96,
  ny = 4,
  nz = 112,
  w = 16.0,
  plate = 8.0,
  dg = 3.0e-3,
  sigma = 1.0,
  mu = 0.2,
  ratio = 10.0,
  datum = 28.0,
  zp = (12.0, 100.0),
  flat_start = False,
  wos = False 
)

◆ cap_sphere()

vof_wetting_dynamic.cap_sphere (   volume,
  theta_deg 
)

Definition at line 333 of file vof_wetting_dynamic.py.

Referenced by cap_colour().

◆ cap_colour()

vof_wetting_dynamic.cap_colour (   nx,
  ny,
  nz,
  cx,
  cy,
  zw,
  R,
  theta_deg = 90.0 
)

Definition at line 339 of file vof_wetting_dynamic.py.

References cap_sphere().

Referenced by g2_spread(), and g4_incline().

◆ g2_spread()

vof_wetting_dynamic.g2_spread (   theta_e = 30.0,
  slip = 0.1,
  steps = 1500,
  probe = 50,
  nx = 64,
  nz = 40,
  R = 12.0,
  zw = 4.25,
  sigma = 1.0,
  oh = 0.1,
  dynamic = True,
  wall_slip = False 
)

Definition at line 352 of file vof_wetting_dynamic.py.

References cap_colour().

◆ g3_rise()

vof_wetting_dynamic.g3_rise (   theta_e = 30.0,
  slips = (0.05, 0.3),
  steps = 1500,
  nx = 96,
  ny = 4,
  nz = 112,
  w = 16.0,
  plate = 8.0,
  dg = 3.0e-3,
  sigma = 1.0,
  mu = 0.2,
  ratio = 10.0,
  datum = 28.0,
  zp = (12.0, 100.0),
  static_control = True,
  wall_slip = False,
  probe = None,
  lw = False 
)
G3-dynamics: the same plate scene from a FLAT interface, so the contact line has to travel.
The static equilibrium level difference is Jurin's, EXACTLY (see g3_static), so the gate is the
final height against it; the damping class (asymptotic vs oscillatory) is the second half of
the Gruending et al. (AMM 86:142, 2020) comparison.

Definition at line 448 of file vof_wetting_dynamic.py.

References _channel_columns(), jurin(), jurin_colour(), jurin_scene(), level_of(), relax(), and set_zero_mean_buoyancy().

◆ g4_incline()

vof_wetting_dynamic.g4_incline (   theta_a = 70.0,
  theta_r = 50.0,
  bo_fracs = (0.5, 0.7, 1.5, 2.5),
  steps = 1200,
  nx = 48,
  nz = 32,
  R = 8.0,
  zw = 4.25,
  sigma = 1.0,
  oh = 0.2,
  slip = 0.1 
)
The wall is kept axis-aligned and GRAVITY is tilted — the same problem, an exact SDF.
Bo = drho g V^(2/3) sin(alpha) / sigma against Bo_c = cos(theta_r) - cos(theta_a)
(ElSherbini & Jacobi 2006's retention relation in its simplest form).

Definition at line 527 of file vof_wetting_dynamic.py.

References cap_colour(), and relax().

Variable Documentation

◆ PRESS_MAXIT

int vof_wetting_dynamic.PRESS_MAXIT = 300

Definition at line 51 of file vof_wetting_dynamic.py.

◆ DEG

float vof_wetting_dynamic.DEG = math.pi / 180.0

Definition at line 52 of file vof_wetting_dynamic.py.

◆ _MEN_CACHE

dict vof_wetting_dynamic._MEN_CACHE = {}
protected

Definition at line 56 of file vof_wetting_dynamic.py.

◆ args

list vof_wetting_dynamic.args = [a for a in sys.argv[1:] if not a.startswith("--")]

Definition at line 584 of file vof_wetting_dynamic.py.

◆ quick

str vof_wetting_dynamic.quick = "--quick" in sys.argv

Definition at line 585 of file vof_wetting_dynamic.py.

◆ which

list vof_wetting_dynamic.which = args or ["jurin"]

Definition at line 586 of file vof_wetting_dynamic.py.

◆ theta

vof_wetting_dynamic.theta

Definition at line 588 of file vof_wetting_dynamic.py.

◆ steps

vof_wetting_dynamic.steps

Definition at line 588 of file vof_wetting_dynamic.py.

◆ flat_start

vof_wetting_dynamic.flat_start

Definition at line 591 of file vof_wetting_dynamic.py.

◆ wos

vof_wetting_dynamic.wos

Definition at line 593 of file vof_wetting_dynamic.py.

◆ probe

vof_wetting_dynamic.probe

Definition at line 595 of file vof_wetting_dynamic.py.

◆ res

list vof_wetting_dynamic.res = []

Definition at line 601 of file vof_wetting_dynamic.py.

◆ sp

vof_wetting_dynamic.sp

Definition at line 603 of file vof_wetting_dynamic.py.

◆ wt

vof_wetting_dynamic.wt

Definition at line 603 of file vof_wetting_dynamic.py.

◆ am

vof_wetting_dynamic.am

Definition at line 603 of file vof_wetting_dynamic.py.

◆ slip

vof_wetting_dynamic.slip

Definition at line 603 of file vof_wetting_dynamic.py.

◆ sl

vof_wetting_dynamic.sl

Definition at line 603 of file vof_wetting_dynamic.py.

◆ d_meas

list vof_wetting_dynamic.d_meas = res[i][1] - res[i - 1][1]

Definition at line 609 of file vof_wetting_dynamic.py.

◆ d_pred

float vof_wetting_dynamic.d_pred = 9.0 * math.log(res[i - 1][0] / res[i][0])

Definition at line 610 of file vof_wetting_dynamic.py.

◆ wall_slip

vof_wetting_dynamic.wall_slip

Definition at line 621 of file vof_wetting_dynamic.py.

◆ slips

vof_wetting_dynamic.slips

Definition at line 634 of file vof_wetting_dynamic.py.

◆ lw

vof_wetting_dynamic.lw

Definition at line 634 of file vof_wetting_dynamic.py.

◆ False

vof_wetting_dynamic.False

Definition at line 635 of file vof_wetting_dynamic.py.

◆ static_control

vof_wetting_dynamic.static_control

Definition at line 635 of file vof_wetting_dynamic.py.

◆ True

vof_wetting_dynamic.True

Definition at line 637 of file vof_wetting_dynamic.py.