Skip to content

Schur preconditioner scaling omits the solvent and DEVSS viscosities, and the pressure solve runs away at high Wi #755

Description

@lmoresi

Symptom

Creeping Oldroyd-B flow past a confined cylinder stops making progress above about Wi 0.2. The step cost is flat and then cliffs, and the solution degrades on the same step:

step wall time drag (reference 120.59)
13 70.8 s 114.37
14 77.2 s 113.48
15 1435.7 s 86.07

No iteration cap is hit. Newton converges in one iteration on the absolute residual and the outer Krylov solve converges on relative tolerance in one to four iterations, every step, including the bad one.

Where the time goes

-log_view, 15 steps, 2118 s total:

event time calls per call
KSPSolve_FS_Schu (pressure) 1990.7 s 26 76.6 s
KSPSolve_FS_0 (velocity, FMG) 10.1 s 26 0.39 s
SNESJacobianEval 67.3 s 164 0.41 s
DEVSS projection 66.8 s 32 2.09 s
PCSetUp 0.8 s 164 0.005 s

94% in the Schur (pressure) solve; the velocity multigrid is 0.5% and is not the problem. Underneath: 202,871 MatMult and 709,321 KSPGMRESOrthog calls, so the pressure Krylov solve is running to enormous iteration counts.

Tolerances are as designed (outer 1e-6, pressure 1e-7, velocity 3.3e-8), one order apart, so this is not a tolerance problem.

Likely cause

The pressure block's Schur preconditioner is the viscosity-scaled pressure mass, _pp_G0 = 1 / constitutive_model.K (petsc_generic_snes_solvers.pyx:8044). For the viscoelastic model,

K = dt * eta_p * mu / (dt * mu + eta_p * c0)   ==   eta_p * dt / (lambda + dt)

which is the polymer effective viscosity only. The momentum operator it is meant to precondition actually carries

eta_operator = eta_p * dt / (lambda + dt)  +  eta_s  +  eta_a(DEVSS)

Neither the solvent viscosity nor the DEVSS artificial viscosity appears in K. The mismatch is the ratio eta_operator / K, which grows with Wi and shrinks with dt. For the confined-cylinder benchmark (beta = 0.59, so eta_p = 0.41, eta_s = 0.59):

Wi dt K (what the pc uses) true operator viscosity ratio
0.2 0.4 0.273 0.863 3.2
0.4 0.4 0.205 0.795 3.9
5 0.0125 0.00102 0.591 578

An Oldroyd-B fluid with a significant solvent fraction is exactly the case where this bites, and the cylinder and contraction benchmarks are both in it. DEVSS adds a further eta_a the preconditioner also does not see.

Suggested direction

  1. Include the solvent and DEVSS viscosities in the Schur scaling, so _pp_G0 uses the viscosity the momentum operator actually carries rather than the polymer part alone. Cheap to try: set stokes.saddle_preconditioner = 1/(K + eta_s + eta_a) on a failing case and see whether the pressure iteration count collapses.
  2. Grad-div augmentation (stokes.penalty) as the other standard lever on Schur conditioning.
  3. If neither is enough, the Schur approximation itself may need revisiting for the viscoelastic operator.

Reproducer

~/+Simulations/stress_transport/cylinder_ob/ob_cylinder.py (session scripts, not in the repo):

UW_OB_DEBUG=1 python ob_cylinder.py -uw_wi 0.4 -uw_dt 0.4 -uw_t_end 8 -uw_out run

Half domain, blockage 0.5, beta 0.59, Re 0, 11744 cells, three multigrid levels. Fails at step 15. -uw_penalty and -uw_p_rtol are already wired for experiments. The Newtonian case of the same rig reproduces the benchmark drag to 0.04%, so the rig itself is sound.

Related: #754 (DEVSS not subtracting its own viscosity on a plain Stokes solve).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions