X Tutup
Skip to content

Add Herschel-Bulkley non-Newtonian viscosity model#1298

Draft
jasontruong2707 wants to merge 5 commits intoMFlowCode:masterfrom
jasontruong2707:feature/non-newtonian-viscosity
Draft

Add Herschel-Bulkley non-Newtonian viscosity model#1298
jasontruong2707 wants to merge 5 commits intoMFlowCode:masterfrom
jasontruong2707:feature/non-newtonian-viscosity

Conversation

@jasontruong2707
Copy link

Summary

  • Implements Herschel-Bulkley (HB) viscosity model with Papanastasiou regularization
  • Supports power-law, Bingham, and HB fluids via per-fluid parameters
  • Replaces static Res_viscous array with dynamic s_compute_re_visc for both Newtonian and non-Newtonian flows
  • Validated against Li et al. (2015) lid-driven cavity benchmarks (Re=500, n=0.5 and n=1.5)

New files

  • src/simulation/m_hb_function.fpp — Core HB viscosity computation
  • src/simulation/m_re_visc.fpp — Dynamic Reynolds number module
  • examples/2D_lid_driven_cavity_nn/ — Validation case
  • examples/2D_poiseuille_nn/ — Validation case

Test plan

  • Builds with gfortran (CPU)
  • 2D lid-driven cavity non-Newtonian cases run without errors
  • Results match Li et al. (2015) benchmarks
  • Existing viscous test cases unaffected (non_newtonian=F by default)

@qodo-code-review
Copy link
Contributor

Review Summary by Qodo

Add Herschel-Bulkley non-Newtonian viscosity model with dynamic Reynolds number computation

✨ Enhancement 🧪 Tests

Grey Divider

Walkthroughs

Description
• Implements Herschel-Bulkley non-Newtonian viscosity model with Papanastasiou regularization for
  power-law, Bingham, and HB fluids
• Replaces static viscous Reynolds arrays (Res_viscous, Res_gs, Res_pr) with dynamic
  computation via new m_re_visc module
• Adds per-fluid non-Newtonian parameters: yield stress (tau0), consistency index (K), flow
  behavior index (nn), viscosity bounds (mu_max, mu_min, mu_bulk), and regularization
  parameter (hb_m)
• Integrates non-Newtonian viscosity computation into time-stepping CFL calculations, Riemann
  solvers, and data output stability criteria
• Adds validation for non-Newtonian fluid parameters in input checker
• Extends MPI communication across pre-processing, simulation, and post-processing modules to
  broadcast non-Newtonian properties
• Supports non-Newtonian viscosity in immersed boundary method calculations
• Includes two validation cases: 2D Poiseuille flow and 2D lid-driven cavity with non-Newtonian
  fluids
• Adds non-Newtonian parameter definitions to toolchain configuration
• Maintains backward compatibility with Newtonian flows (non-Newtonian disabled by default)
Diagram
flowchart LR
  A["Input Parameters<br/>non_newtonian, tau0, K, nn"] --> B["m_hb_function<br/>Herschel-Bulkley<br/>Viscosity Model"]
  B --> C["m_re_visc<br/>Dynamic Re Computation"]
  C --> D["Time Stepping<br/>CFL Calculation"]
  C --> E["Riemann Solvers<br/>Viscous Fluxes"]
  C --> F["Data Output<br/>Stability Criteria"]
  G["Velocity Gradients"] --> C
  H["Strain Rate Tensor"] --> B
Loading

Grey Divider

File Changes

1. src/simulation/m_time_steppers.fpp ✨ Enhancement +1075/-1061

Integrate non-Newtonian viscosity into time-stepping CFL calculations

• Added use m_re_visc module import for non-Newtonian viscosity computations
• Modified s_compute_dt() subroutine to compute per-phase Reynolds numbers for non-Newtonian
 fluids using s_compute_re_visc() and s_compute_mixture_re()
• Added local variables Re_visc_per_phase to track per-phase viscous Reynolds numbers in the CFL
 computation

src/simulation/m_time_steppers.fpp


2. src/simulation/m_viscous.fpp ✨ Enhancement +1578/-1622

Replace static viscous Reynolds array with dynamic computation

• Removed static Res_viscous array allocation and initialization from
 s_initialize_viscous_module()
• Replaced four instances of inline Reynolds number computation with calls to s_compute_re_visc()
 and s_compute_mixture_re() functions
• Added local variable Re_visc_nn to store per-phase viscous Reynolds numbers
• Added comment explaining that dynamic viscosity computation now handles both Newtonian and
 non-Newtonian cases

src/simulation/m_viscous.fpp


3. src/simulation/m_global_parameters.fpp ✨ Enhancement +20/-2

Add non-Newtonian fluid parameters and detection logic

• Added any_non_newtonian logical flag to track if any fluid is non-Newtonian
• Initialized non-Newtonian fluid parameters (non_newtonian, tau0, K, nn, mu_max,
 mu_min, mu_bulk, hb_m) in fluid_pp structure
• Added detection logic to set any_non_newtonian flag based on fluid properties
• Updated GPU declarations to include any_non_newtonian flag

src/simulation/m_global_parameters.fpp


View more (20)
4. src/simulation/m_data_output.fpp ✨ Enhancement +1984/-1974

Integrate non-Newtonian viscosity into data output stability criteria

• Added use m_re_visc module import for non-Newtonian viscosity computations
• Added Re_visc_per_phase local variable to compute per-phase Reynolds numbers
• Integrated non-Newtonian Reynolds number computation in stability criteria calculation using
 s_compute_re_visc() and s_compute_mixture_re()

src/simulation/m_data_output.fpp


5. src/common/m_derived_types.fpp ✨ Enhancement +8/-0

Extend physical parameters type with non-Newtonian fluid properties

• Extended physical_parameters derived type with eight new fields for non-Newtonian fluid modeling
• Added Herschel-Bulkley model parameters: tau0 (yield stress), K (consistency index), nn
 (flow behavior index)
• Added viscosity bounds: mu_max, mu_min, and mu_bulk for non-Newtonian fluids
• Added hb_m parameter for Papanastasiou regularization

src/common/m_derived_types.fpp


6. .github/workflows/frontier_amd/bench.sh ⚙️ Configuration changes +0/-1

Add Frontier AMD benchmark script symlink

• Created symbolic link pointing to parent directory benchmark script

.github/workflows/frontier_amd/bench.sh


7. src/simulation/m_riemann_solvers.fpp ✨ Enhancement +5272/-5257

Replace static viscosity array with dynamic non-Newtonian computation

• Removed static Res_gs array and replaced with dynamic s_compute_re_visc function calls
• Added per-phase Reynolds number arrays Re_visc_per_phase_L and Re_visc_per_phase_R for
 non-Newtonian support
• Updated GPU parallel loop declarations to include new per-phase Re arrays
• Replaced inline Re computation loops with calls to s_compute_mixture_re for both Newtonian and
 non-Newtonian cases

src/simulation/m_riemann_solvers.fpp


8. src/simulation/m_pressure_relaxation.fpp ✨ Enhancement +279/-308

Remove static viscosity array from pressure relaxation module

• Removed static Res_pr array allocation and initialization
• Simplified s_initialize_pressure_relaxation_module and s_finalize_pressure_relaxation_module
 to no-ops
• Removed viscosity computation from s_correct_internal_energies (now handled dynamically via
 m_re_visc)

src/simulation/m_pressure_relaxation.fpp


9. src/simulation/m_re_visc.fpp ✨ Enhancement +346/-0

New dynamic viscosity module for Newtonian and non-Newtonian fluids

• New module implementing dynamic viscosity computation for both Newtonian and non-Newtonian fluids
• s_compute_velocity_gradients_at_cell computes strain rate tensor components using finite
 differences
• s_compute_re_visc returns per-phase Re_visc = 1/mu using Herschel-Bulkley model for
 non-Newtonian fluids
• s_compute_mixture_re combines per-phase values with volume fractions to compute mixture Reynolds
 number

src/simulation/m_re_visc.fpp


10. src/simulation/m_hb_function.fpp ✨ Enhancement +77/-0

New Herschel-Bulkley non-Newtonian viscosity model implementation

• New module implementing Herschel-Bulkley viscosity model with Papanastasiou regularization
• f_compute_hb_viscosity computes viscosity from yield stress, consistency index, and flow
 behavior index
• f_compute_shear_rate_from_components calculates shear rate magnitude from strain rate tensor
 components

src/simulation/m_hb_function.fpp


11. src/simulation/m_checker.fpp Error handling +27/-0

Add validation for non-Newtonian fluid parameters

• Added s_check_inputs_non_newtonian subroutine to validate non-Newtonian fluid parameters
• Validates that viscosity is enabled, consistency index K > 0, flow behavior index nn > 0, yield
 stress tau0 >= 0
• Validates viscosity bounds and Papanastasiou regularization parameter hb_m > 0

src/simulation/m_checker.fpp


12. src/post_process/m_mpi_proxy.fpp ✨ Enhancement +4/-0

Broadcast non-Newtonian fluid parameters in post-processing MPI proxy

• Added MPI broadcast calls for non-Newtonian fluid properties: non_newtonian, tau0, K, nn,
 mu_max, mu_min, mu_bulk, hb_m

src/post_process/m_mpi_proxy.fpp


13. src/pre_process/m_mpi_proxy.fpp ✨ Enhancement +5/-0

Broadcast non-Newtonian fluid parameters in pre-processing MPI proxy

• Added MPI broadcast calls for non-Newtonian fluid properties: non_newtonian, tau0, K, nn,
 mu_max, mu_min, mu_bulk, hb_m

src/pre_process/m_mpi_proxy.fpp


14. src/simulation/m_mpi_proxy.fpp ✨ Enhancement +4/-0

Broadcast non-Newtonian fluid parameters in simulation MPI proxy

• Added MPI broadcast calls for non-Newtonian fluid properties: non_newtonian, tau0, K, nn,
 mu_max, mu_min, mu_bulk, hb_m

src/simulation/m_mpi_proxy.fpp


15. src/simulation/m_ibm.fpp ✨ Enhancement +9/-1

Support non-Newtonian viscosity in immersed boundary method

• Added conditional logic to use mu_max or K as reference viscosity for non-Newtonian fluids in
 IBM calculations
• Falls back to consistency index K if mu_max is not set

src/simulation/m_ibm.fpp


16. src/post_process/m_global_parameters.fpp ✨ Enhancement +8/-0

Initialize non-Newtonian fluid parameters in post-processing

• Initialize non-Newtonian fluid properties: non_newtonian, tau0, K, nn, mu_max, mu_min,
 mu_bulk, hb_m
• Default values: non_newtonian=.false., nn=1.0, hb_m=1000.0, others zero or default

src/post_process/m_global_parameters.fpp


17. src/pre_process/m_global_parameters.fpp ✨ Enhancement +8/-0

Initialize non-Newtonian fluid parameters in pre-processing

• Initialize non-Newtonian fluid properties: non_newtonian, tau0, K, nn, mu_max, mu_min,
 mu_bulk, hb_m
• Default values: non_newtonian=.false., nn=1.0, hb_m=1000.0, others zero or default

src/pre_process/m_global_parameters.fpp


18. examples/2D_poiseuille_nn/case.py 🧪 Tests +158/-0

Add 2D Poiseuille non-Newtonian validation case

• New validation case for 2D Poiseuille flow with Herschel-Bulkley non-Newtonian fluid
• Pressure-driven channel flow with periodic BCs in streamwise direction and no-slip walls
• Configurable HB parameters: yield stress, consistency index, flow behavior index, regularization
 parameter

examples/2D_poiseuille_nn/case.py


19. examples/2D_lid_driven_cavity_nn/case.py 🧪 Tests +116/-0

Add 2D lid-driven cavity non-Newtonian validation case

• New validation case for 2D lid-driven cavity with Herschel-Bulkley non-Newtonian fluid
• Re=5000, shear-thickening fluid (nn=1.5) with mesh stretching near walls
• Demonstrates non-Newtonian behavior in complex flow with recirculation zones

examples/2D_lid_driven_cavity_nn/case.py


20. toolchain/mfc/params/definitions.py ⚙️ Configuration changes +3/-0

Add non-Newtonian fluid parameter definitions to toolchain

• Added parameter definitions for non-Newtonian fluid properties: non_newtonian (logical), tau0,
 K, nn, mu_max, mu_min, mu_bulk, hb_m (real)
• All parameters registered under viscosity category

toolchain/mfc/params/definitions.py


21. .github/workflows/frontier_amd/submit.sh ⚙️ Configuration changes +0/-1

Add AMD frontier workflow submit script link

• Symbolic link to parent frontier submit script

.github/workflows/frontier_amd/submit.sh


22. .github/workflows/frontier_amd/build.sh ⚙️ Configuration changes +0/-1

Add AMD frontier workflow build script link

• Symbolic link to parent frontier build script

.github/workflows/frontier_amd/build.sh


23. .github/workflows/frontier_amd/test.sh ⚙️ Configuration changes +0/-1

Add AMD frontier workflow test script link

• Symbolic link to parent frontier test script

.github/workflows/frontier_amd/test.sh


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Mar 9, 2026

Code Review by Qodo

🐞 Bugs (4) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Action required

1. non_newtonian lacks case validation 📘 Rule violation ⛯ Reliability
Description
New HB parameters (fluid_pp(*)%non_newtonian, tau0, K, nn, mu_*, hb_m) are defined but
not validated in toolchain/mfc/case_validator.py, allowing invalid configurations to pass
toolchain checks. This should be validated in the toolchain since physics constraints are explicitly
enforced in the Fortran input checker.
Code

toolchain/mfc/params/definitions.py[R1061-1063]

+        _r(f"{px}non_newtonian", LOG, {"viscosity"})
+        for a in ["tau0", "K", "nn", "mu_max", "mu_min", "mu_bulk", "hb_m"]:
+            _r(f"{px}{a}", REAL, {"viscosity"})
Evidence
PR Compliance ID 6 requires new parameters to be added to toolchain definitions and also to
case_validator.py when constraints apply. The PR adds the non-Newtonian parameters to
definitions.py and enforces constraints in src/simulation/m_checker.fpp, but
case_validator.py's viscosity validation only checks Re(*) and contains no validation for
non_newtonian or HB parameters.

CLAUDE.md
toolchain/mfc/params/definitions.py[1061-1063]
src/simulation/m_checker.fpp[95-116]
toolchain/mfc/case_validator.py[993-1024]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The PR introduces new non-Newtonian viscosity inputs (`fluid_pp(*)%non_newtonian`, `tau0`, `K`, `nn`, `mu_min`, `mu_max`, `mu_bulk`, `hb_m`) but the toolchain validator does not validate them, so invalid cases can pass toolchain checks and only fail later at runtime.

## Issue Context
Fortran-side validation was added in `src/simulation/m_checker.fpp`, indicating physics constraints apply and should also be enforced in `toolchain/mfc/case_validator.py` per the compliance checklist.

## Fix Focus Areas
- toolchain/mfc/case_validator.py[993-1024]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. IGR uses conservative gradients 🐞 Bug ✓ Correctness
Description
In s_compute_dt, the IGR branch calls s_compute_re_visc with q_cons_ts(1)%vf, but s_compute_re_visc
differentiates q_prim_vf(momxb:), so it treats momenta as velocities and computes an incorrect shear
rate and viscosity. This can yield an incorrect (potentially unstable) time step whenever
any_non_newtonian and igr are enabled.
Code

src/simulation/m_time_steppers.fpp[R748-754]

+                    if (any_non_newtonian) then
+                        if (igr) then
+                            call s_compute_re_visc(q_cons_ts(1)%vf, alpha, j, k, l, Re_visc_per_phase)
+                        else
+                            call s_compute_re_visc(q_prim_vf, alpha, j, k, l, Re_visc_per_phase)
+                        end if
+                        call s_compute_mixture_re(alpha, Re_visc_per_phase, Re)
Evidence
The new dt logic calls s_compute_re_visc with conservative variables when igr is true, but the
viscosity routine explicitly expects primitive variables and computes du/dx etc. from
q_prim_vf(momxb) and q_prim_vf(momxb+1/2), which are velocities in the primitive layout (not
momenta).

src/simulation/m_time_steppers.fpp[729-755]
src/simulation/m_re_visc.fpp[26-32]
src/simulation/m_re_visc.fpp[64-72]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
When `igr` is enabled, `s_compute_dt` calls `s_compute_re_visc` with `q_cons_ts(1)%vf` (conservative state). `s_compute_re_visc` assumes its first argument is primitive variables and differentiates `q_prim_vf(momxb:...)` as velocities, so the IGR path computes wrong shear rate/viscosity and thus wrong dt.

### Issue Context
`m_re_visc` computes velocity gradients directly from the provided field, without converting momenta to velocities.

### Fix Focus Areas
- src/simulation/m_time_steppers.fpp[748-754]
- src/simulation/m_re_visc.fpp[26-90]

### Suggested fix
- Option A (simplest): In `s_compute_dt`, ensure `q_prim_vf` is valid even when `igr` is true (perform conservative→primitive conversion when `any_non_newtonian` is true, or always for dt computation).
- Option B: Add a conservative-aware path in `s_compute_re_visc` (or a new routine) that computes velocities `u=mom/rho` at neighbor cells before differencing, and use that path from the IGR branch.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Frontier AMD scripts mispath 🐞 Bug ⛯ Reliability
Description
The newly added .github/workflows/frontier_amd/*.sh files contain only a relative path like
"../frontier/build.sh", but the workflows execute them via "bash
.github/workflows/frontier_amd/build.sh" from the checkout directory, so the relative path resolves
outside the repo and fails. This breaks Frontier AMD build/test/bench workflow steps.
Code

.github/workflows/frontier_amd/build.sh[1]

+../frontier/build.sh
Evidence
The workflow invokes the Frontier AMD scripts using a repo-root relative path (or after cd pr),
meaning the scripts’ current working directory is not .github/workflows/frontier_amd/. Because the
scripts use ../frontier/... without anchoring to the script directory, the target path is resolved
relative to the current working directory and points outside the repo.

.github/workflows/frontier_amd/build.sh[1-1]
.github/workflows/test.yml[243-266]
.github/workflows/bench.yml[113-117]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The new `frontier_amd/*.sh` wrappers are one-line scripts like `../frontier/build.sh`. Workflows run them from the checkout directory (repo root or `cd pr`), so `../frontier/...` resolves outside the repo and the job fails.

### Issue Context
GitHub Actions `run:` commands and `bash &lt;path&gt;` do not change CWD to the script’s directory; relative paths inside the script are resolved from the caller’s CWD.

### Fix Focus Areas
- .github/workflows/frontier_amd/build.sh[1-1]
- .github/workflows/frontier_amd/submit.sh[1-1]
- .github/workflows/frontier_amd/test.sh[1-1]
- .github/workflows/frontier_amd/bench.sh[1-1]

### Suggested fix
Replace each one-liner with a small bash wrapper:
```bash
#!/usr/bin/env bash
set -euo pipefail
DIR=&quot;$(cd -- &quot;$(dirname -- &quot;${BASH_SOURCE[0]}&quot;)&quot; &amp;&amp; pwd)&quot;
exec bash &quot;$DIR/../frontier/build.sh&quot; &quot;$@&quot;
```
(and similarly for submit/test/bench), or adjust paths to `.github/workflows/frontier/...` if you prefer not to compute `DIR`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. IBM non-Newtonian mu wrong 🐞 Bug ✓ Correctness
Description
In m_ibm, for non-Newtonian fluids the “reference viscosity” used in immersed-boundary viscous
forces falls back to fluid_pp%K when mu_max is not explicitly set, but K is not the dynamic
viscosity for HB fluids except for the special case tau0=0 and nn=1. This makes IBM viscous
forces/torques inconsistent with the HB viscosity model for yield-stress and general power-law
cases.
Code

src/simulation/m_ibm.fpp[R1016-1023]

+                if (fluid_pp(fluid_idx)%non_newtonian) then
+                    ! Non-Newtonian: use mu_max as reference viscosity for IBM
+                    if (fluid_pp(fluid_idx)%mu_max < dflt_real .and. &
+                        fluid_pp(fluid_idx)%mu_max > sgm_eps) then
+                        dynamic_viscosities(fluid_idx) = fluid_pp(fluid_idx)%mu_max
+                    else
+                        dynamic_viscosities(fluid_idx) = fluid_pp(fluid_idx)%K
+                    end if
Evidence
IBM computes a scalar dynamic_viscosity by volume-averaging dynamic_viscosities(fluid_idx) and
then uses it in viscous stress computation. For non-Newtonian fluids, dynamic_viscosities is set
to mu_max (if set) else to K, but the HB model defines viscosity as a function of shear rate
involving tau0, K, and nn, so using K alone does not represent viscosity in general.

src/simulation/m_ibm.fpp[1014-1027]
src/simulation/m_ibm.fpp[1067-1072]
src/simulation/m_hb_function.fpp[7-45]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`m_ibm` needs a scalar “dynamic viscosity” per fluid for immersed boundary viscous forces. For non-Newtonian fluids it uses `mu_max` if set, else falls back to `K`, which is not equal to HB viscosity for general (`tau0`, `nn`) settings.

### Issue Context
HB viscosity is shear-rate dependent: `mu(gdot) = tau0*(1-exp(-m*gdot))/gdot + K*gdot^(nn-1)`.

### Fix Focus Areas
- src/simulation/m_ibm.fpp[1014-1027]
- src/simulation/m_hb_function.fpp[23-49]

### Suggested fix
- Prefer computing a reference viscosity via `f_compute_hb_viscosity(...)` at a documented representative shear rate (e.g., `gdot_ref = 1._wp` or a user-provided parameter), then clamp by `mu_min/mu_max`.
- Alternatively, if IBM must use a bound, require `mu_max` to be explicitly set for non-Newtonian fluids when IBM+viscous is enabled (checker-level validation) and remove the `K` fallback.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Hardcoded shear-rate floor 🐞 Bug ✓ Correctness
Description
The shear-rate magnitude used by the HB model is hard-clamped to be at least 1e-2, so all true shear
rates below 1e-2 produce identical viscosity inputs. This makes viscosity insensitive in low-shear
regions and can override user intent for hb_m/mu_max tuning below that threshold.
Code

src/simulation/m_hb_function.fpp[R68-74]

+        ! 2*D_ij*D_ij = 2*(D_xx^2+D_yy^2+D_zz^2+2*(D_xy^2+D_xz^2+D_yz^2))
+        shear_rate = sqrt(2._wp*(D_xx*D_xx + D_yy*D_yy + D_zz*D_zz + &
+                                 2._wp*(D_xy*D_xy + D_xz*D_xz + D_yz*D_yz)))
+
+        ! Clamp for numerical safety
+        shear_rate = min(max(shear_rate, 1.0e-2_wp), 1.0e5_wp)
+
Evidence
HB viscosity depends directly on shear_rate (including division by shear_rate in the yield term),
but the implementation clamps shear_rate to a minimum of 1e-2 before viscosity is computed,
collapsing all lower-shear behavior to a single effective value.

src/simulation/m_hb_function.fpp[42-45]
src/simulation/m_hb_function.fpp[68-74]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`f_compute_shear_rate_from_components` clamps `shear_rate &gt;= 1e-2`, which forces a constant effective shear rate in all regions below that threshold. Since HB viscosity is a function of shear rate, this can materially change viscosity in low-shear regions.

### Issue Context
The yield term is well-behaved as `gdot -&gt; 0` in the Papanastasiou model, but computing `(1-exp(-m*gdot))/gdot` can suffer cancellation; that should be handled numerically rather than by a large floor.

### Fix Focus Areas
- src/simulation/m_hb_function.fpp[42-45]
- src/simulation/m_hb_function.fpp[68-74]

### Suggested fix
- Reduce the floor to a true numerical epsilon (e.g., `sgm_eps`-scaled) or make it configurable.
- In `f_compute_hb_viscosity`, compute the yield term with a stable formulation near zero shear, e.g. using `expm1`:
 `yield_term = tau0 * (-expm1(-hb_m_val*shear_rate)) / max(shear_rate, eps)`
 (or use the analytic limit `tau0*hb_m_val` when `shear_rate` is very small).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +1061 to +1063
_r(f"{px}non_newtonian", LOG, {"viscosity"})
for a in ["tau0", "K", "nn", "mu_max", "mu_min", "mu_bulk", "hb_m"]:
_r(f"{px}{a}", REAL, {"viscosity"})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. non_newtonian lacks case validation 📘 Rule violation ⛯ Reliability

New HB parameters (fluid_pp(*)%non_newtonian, tau0, K, nn, mu_*, hb_m) are defined but
not validated in toolchain/mfc/case_validator.py, allowing invalid configurations to pass
toolchain checks. This should be validated in the toolchain since physics constraints are explicitly
enforced in the Fortran input checker.
Agent Prompt
## Issue description
The PR introduces new non-Newtonian viscosity inputs (`fluid_pp(*)%non_newtonian`, `tau0`, `K`, `nn`, `mu_min`, `mu_max`, `mu_bulk`, `hb_m`) but the toolchain validator does not validate them, so invalid cases can pass toolchain checks and only fail later at runtime.

## Issue Context
Fortran-side validation was added in `src/simulation/m_checker.fpp`, indicating physics constraints apply and should also be enforced in `toolchain/mfc/case_validator.py` per the compliance checklist.

## Fix Focus Areas
- toolchain/mfc/case_validator.py[993-1024]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +748 to +754
if (any_non_newtonian) then
if (igr) then
call s_compute_re_visc(q_cons_ts(1)%vf, alpha, j, k, l, Re_visc_per_phase)
else
call s_compute_re_visc(q_prim_vf, alpha, j, k, l, Re_visc_per_phase)
end if
call s_compute_mixture_re(alpha, Re_visc_per_phase, Re)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Igr uses conservative gradients 🐞 Bug ✓ Correctness

In s_compute_dt, the IGR branch calls s_compute_re_visc with q_cons_ts(1)%vf, but s_compute_re_visc
differentiates q_prim_vf(momxb:), so it treats momenta as velocities and computes an incorrect shear
rate and viscosity. This can yield an incorrect (potentially unstable) time step whenever
any_non_newtonian and igr are enabled.
Agent Prompt
### Issue description
When `igr` is enabled, `s_compute_dt` calls `s_compute_re_visc` with `q_cons_ts(1)%vf` (conservative state). `s_compute_re_visc` assumes its first argument is primitive variables and differentiates `q_prim_vf(momxb:...)` as velocities, so the IGR path computes wrong shear rate/viscosity and thus wrong dt.

### Issue Context
`m_re_visc` computes velocity gradients directly from the provided field, without converting momenta to velocities.

### Fix Focus Areas
- src/simulation/m_time_steppers.fpp[748-754]
- src/simulation/m_re_visc.fpp[26-90]

### Suggested fix
- Option A (simplest): In `s_compute_dt`, ensure `q_prim_vf` is valid even when `igr` is true (perform conservative→primitive conversion when `any_non_newtonian` is true, or always for dt computation).
- Option B: Add a conservative-aware path in `s_compute_re_visc` (or a new routine) that computes velocities `u=mom/rho` at neighbor cells before differencing, and use that path from the IGR branch.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 9, 2026

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

Adds Herschel–Bulkley non‑Newtonian support: eight new fields to the derived type physical_parameters (non_newtonian, tau0, K, nn, mu_min, mu_max, mu_bulk, hb_m); new modules m_hb_function and m_re_visc for HB viscosity and viscous/Re computations; input validation via s_check_inputs_non_newtonian; MPI broadcasts and GPU updates extended to the new fields; time‑stepper dt computation updated to use per‑phase viscous terms; pressure‑relaxation internals simplified; two example case scripts added; and CI workflow scripts reference shared frontier scripts.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change—adding a Herschel-Bulkley non-Newtonian viscosity model—which is the primary objective of the PR.
Description check ✅ Passed The PR description includes most required sections: Summary explains the implementation and validation approach; New files and Test plan are detailed. However, Type of change and Testing details are missing, and the Checklist items are not explicitly addressed.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sbryngelson sbryngelson marked this pull request as draft March 9, 2026 19:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

X Tutup