VLB Model Equation Verification¶
Date: 2026-03-30 Sources: Vernerey, Long & Brighenti (2017) JMPS 107:1-20; Vernerey (2018) JMPS 115:217-247 (PMC6824477); Vernerey et al. (2018) Polymers 10(8):848 (PMC6403683); Bell (1978) Science 200:618-627.
1. Distribution Tensor Evolution Equation¶
Paper (Eq. 3b in Polymers 2018; Eq. 17 in JMPS 2018)¶
The full evolution equation from Vernerey (2018 JMPS, Eq. 17) is:
D(c·μ)/Dt = k_a·(C - c)·I - k_d·(c·μ) + c·(L·μ) + c·(L·μ)^T
where c = attached chain concentration, C = total concentration, k_a = association rate, k_d = dissociation rate, L = velocity gradient tensor.
For incompressible material with constant concentration (c = const, C = const), and using the steady-state relation c = C·k_a/(k_a + k_d), this simplifies. In the simplest case where k_a = k_d (equal rates) and c = C/2, or more generally absorbing concentration into the effective rates:
dμ/dt = k_a·((C-c)/c)·I - k_d·μ + L·μ + μ·L^T
At dynamic equilibrium of concentrations, k_a·(C - c)/c = k_d, giving:
dμ/dt = k_d·(I - μ) + L·μ + μ·L^T
RheoJAX Implementation¶
dmu/dt = k_d*(I - mu) + L·mu + mu·L^T
VERDICT: CORRECT. The implementation uses the full velocity gradient L (not just symmetric D), matching the paper. The docstring at the top of _kernels.py incorrectly states D·mu + mu·D but the actual code uses L·mu + mu·L^T which is correct.
Note: The docstring header says
D·mu + mu·D(symmetric part only) but the derivation in the comments and the actual code at lines 127-131 correctly use the full velocity gradient. The docstring should be corrected to sayL·mu + mu·L^T.
2. Cauchy Stress¶
Paper (Eq. 28 in JMPS 2018, Gaussian limit N→∞)¶
For Gaussian chains (N → ∞), the stress from Eq. 28 reduces to:
σ = c·k_B·T·(μ - I) + p·I
where G₀ = c·k_B·T is the network modulus.
RheoJAX Implementation¶
sigma_xy = G0 * mu_xy # (since I_xy = 0)
N1 = G0 * (mu_xx - mu_yy) # = sigma_xx - sigma_yy
VERDICT: CORRECT. The shear stress σ_xy = G₀·μ_xy and N1 = G₀·(μ_xx - μ_yy) are correct for the Gaussian limit.
3. Free Energy¶
Paper (Eq. 5 in Polymers 2018; Eq. 26/27 in JMPS 2018)¶
For Gaussian chains, the stored elastic energy (from the leading term of Eq. 5 in Polymers 2018):
ΔΨ_e = (1/2)·c·k_B·T·[tr(μ) - 3 - ln det(μ)]
= (1/2)·G₀·[tr(μ) - 3 - ln det(μ)]
This is the Neo-Hookean form. The quantity [tr(μ) - 3 - ln det(μ)] ≥ 0 with equality only at μ = I.
RheoJAX Implementation¶
NOT IMPLEMENTED. No vlb_free_energy function exists in _kernels.py.
VERDICT: MISSING (not a bug — the free energy is not needed for stress/strain predictions, only for thermodynamic consistency checks).
4. Dissipation¶
Paper (from Eqs. 19-21 in JMPS 2018)¶
For Gaussian chains, the dissipation is:
D = G₀·k_d·[tr(μ) - 3 - ln det(μ)] ≥ 0
This is 2·k_d·ΔΨ_e, confirming non-negative dissipation.
RheoJAX Implementation¶
NOT IMPLEMENTED. No vlb_dissipation function exists.
VERDICT: MISSING (same rationale as free energy — not needed for predictions).
5. Simple Shear Flow Components¶
Paper derivation¶
With L = [[0, γ̇, 0], [0, 0, 0], [0, 0, 0]] and L^T = [[0, 0, 0], [γ̇, 0, 0], [0, 0, 0]]:
(L·μ)_xx = γ̇·μ_xy, (μ·L^T)_xx = μ_xy·γ̇ → 2γ̇·μ_xy
(L·μ)_yy = 0, (μ·L^T)_yy = 0 → 0
(L·μ)_zz = 0, (μ·L^T)_zz = 0 → 0
(L·μ)_xy = γ̇·μ_yy, (μ·L^T)_xy = 0 → γ̇·μ_yy
Therefore:
dμ_xx/dt = k_d·(1 - μ_xx) + 2·γ̇·μ_xy
dμ_yy/dt = k_d·(1 - μ_yy)
dμ_zz/dt = k_d·(1 - μ_zz)
dμ_xy/dt = -k_d·μ_xy + γ̇·μ_yy
RheoJAX Implementation (lines 127-131)¶
dmu_xx = k_d * (1.0 - mu_xx) + 2.0 * gamma_dot * mu_xy
dmu_yy = k_d * (1.0 - mu_yy)
dmu_zz = k_d * (1.0 - mu_zz)
dmu_xy = -k_d * mu_xy + gamma_dot * mu_yy
VERDICT: CORRECT. Matches exactly. This is equivalent to the upper-convected Maxwell model.
6. Shear Stress and N1¶
Paper (Gaussian limit)¶
σ_xy = G₀·(μ_xy - I_xy) = G₀·μ_xy (since I_xy = 0)
N1 = G₀·(μ_xx - μ_yy)
RheoJAX Implementation¶
def vlb_shear_stress(mu_xy, G0):
return G0 * mu_xy
def vlb_normal_stress_1(mu_xx, mu_yy, G0):
return G0 * (mu_xx - mu_yy)
VERDICT: CORRECT.
7. Steady-State Shear¶
Paper derivation¶
At steady state (dμ/dt = 0):
μ_yy = 1(fromk_d·(1-μ_yy) = 0)μ_xy = γ̇·μ_yy/k_d = γ̇/k_dσ = G₀·γ̇/k_d = η₀·γ̇whereη₀ = G₀/k_d
This is Newtonian with zero-shear viscosity η₀ = G₀/k_d.
RheoJAX Implementation¶
def vlb_steady_shear(gamma_dot, G0, k_d):
return G0 * gamma_dot / k_d
VERDICT: CORRECT. Newtonian response for constant k_d.
8. SAOS (Small Amplitude Oscillatory Shear)¶
Paper derivation¶
The VLB model in the Gaussian limit reduces to the Maxwell model. For a Maxwell element with modulus G₀ and relaxation time τ = 1/k_d:
G'(ω) = G₀·ω²τ²/(1 + ω²τ²) = G₀·ω²/(ω² + k_d²)
G''(ω) = G₀·ωτ/(1 + ω²τ²) = G₀·ω·k_d/(ω² + k_d²)
RheoJAX Implementation¶
t_R = 1.0 / k_d
wt = omega * t_R
wt2 = wt * wt
denom = 1.0 + wt2
G_prime = G0 * wt2 / denom # = G0·ω²/(ω² + k_d²)
G_double_prime = G0 * wt / denom # = G0·ω·k_d/(ω² + k_d²) [since wt/denom = ωτ/(1+ω²τ²)]
Wait — let me verify: wt/denom = (ω/k_d)/(1 + ω²/k_d²) = ω·k_d/(k_d² + ω²).
So G'' = G₀·ω·k_d/(ω² + k_d²). But we can also write this as G₀·ω/(k_d + ω²/k_d).
The formula G''(ω) = G₀·ω·k_d/(ω² + k_d²) matches the standard Maxwell form.
VERDICT: CORRECT.
9. Stress Relaxation¶
Paper¶
Single exponential decay (Maxwell element):
G(t) = G₀·exp(-k_d·t) = G₀·exp(-t/τ)
where τ = 1/k_d.
RheoJAX Implementation¶
def vlb_relaxation_modulus(t, G0, k_d):
return G0 * jnp.exp(-k_d * t)
VERDICT: CORRECT.
10. Creep Compliance¶
Analysis¶
For a Maxwell element (spring G₀ in series with dashpot η = G₀/k_d), the creep compliance under constant stress σ₀ is:
J(t) = 1/G₀ + t/η = 1/G₀ + k_d·t/G₀ = (1 + k_d·t)/G₀
This is not J(t) = (1/G₀)(1 - exp(-k_d·t)) + t·k_d/G₀ — that would be the Kelvin-Voigt or SLS form.
The Maxwell creep: instantaneous elastic strain 1/G₀ followed by linear viscous flow t/η.
RheoJAX Implementation¶
def vlb_creep_compliance_single(t, G0, k_d):
return (1.0 + k_d * t) / G0
VERDICT: CORRECT. This is the standard Maxwell creep compliance. The question mark in the user’s query is resolved: J(t) = (1 + k_d·t)/G₀ is correct for Maxwell. The exponential form would apply to a Kelvin-Voigt element or Standard Linear Solid, which is implemented separately as vlb_creep_compliance_dual for the case with a permanent elastic network (G_e > 0).
11. Bell Model Force-Dependent Dissociation¶
Paper (Bell 1978, applied in Vernerey framework)¶
Bell (1978) proposed for bond dissociation under force:
k_off(f) = k_off_0 · exp(f·γ / k_B·T)
In the Vernerey VLB context, this is adapted using chain stretch rather than force directly. The mean chain stretch is λ̄ = sqrt(tr(μ)/3), and the Bell-type relation becomes:
k_d(μ) = k_d_0 · exp(ν · (λ̄ - 1))
where ν absorbs the force sensitivity. At equilibrium (tr(μ) = 3, λ̄ = 1), k_d = k_d_0.
RheoJAX Implementation¶
def vlb_breakage_bell(mu_xx, mu_yy, mu_zz, k_d_0, nu):
tr_mu = mu_xx + mu_yy + mu_zz
stretch = jnp.sqrt(jnp.maximum(tr_mu / 3.0, 1e-30))
return k_d_0 * jnp.exp(nu * (stretch - 1.0))
VERDICT: CORRECT. The stretch definition √(tr(μ)/3) and the Bell-type exponential are consistent with the VLB framework. The 1e-30 floor prevents sqrt(0) gradient issues.
12. FENE-P Finite Extensibility¶
Paper context¶
The FENE-P (Peterlin) closure introduces a nonlinear spring factor that diverges as chain extension approaches its limit. For a distribution tensor with equilibrium tr(μ) = 3:
f(μ) = L²/(L² - (tr(μ) - 3)) = L²/(L² - tr(μ) + 3)
The stress becomes: σ = G₀·f(μ)·(μ - I) + p·I
At equilibrium: f(tr=3) = L²/L² = 1 (recovers linear stress).
As tr(μ) → L² + 3: f → ∞ (chains reach maximum extensibility).
RheoJAX Implementation¶
def vlb_fene_factor(mu_xx, mu_yy, mu_zz, L_max):
tr_mu = mu_xx + mu_yy + mu_zz
L2 = L_max * L_max
return L2 / jnp.maximum(L2 - tr_mu + 3.0, 1e-10)
def vlb_stress_fene_xy(mu_xx, mu_yy, mu_zz, mu_xy, G0, L_max):
f = vlb_fene_factor(mu_xx, mu_yy, mu_zz, L_max)
return G0 * f * mu_xy
VERDICT: CORRECT. The offset of +3 in the denominator correctly accounts for tr(I) = 3.
Summary Table¶
# |
Equation |
Paper Reference |
RheoJAX |
Status |
|---|---|---|---|---|
1 |
Distribution tensor evolution |
JMPS 2018 Eq.17, Polymers 2018 Eq.3b |
|
CORRECT |
2 |
Cauchy stress |
JMPS 2018 Eq.28 (N→∞) |
|
CORRECT |
3 |
Free energy |
Polymers 2018 Eq.5 |
— |
NOT IMPLEMENTED |
4 |
Dissipation |
JMPS 2018 Eqs.19-21 |
— |
NOT IMPLEMENTED |
5 |
Simple shear components |
Derived from Eq.17 |
|
CORRECT |
6 |
σ_xy and N1 |
Gaussian limit of Eq.28 |
|
CORRECT |
7 |
Steady-state shear |
Polymers 2018 §3.2 |
|
CORRECT |
8 |
SAOS G’(ω), G’’(ω) |
Maxwell limit |
|
CORRECT |
9 |
Stress relaxation G(t) |
Maxwell limit |
|
CORRECT |
10 |
Creep compliance J(t) |
Maxwell element |
|
CORRECT |
11 |
Bell breakage |
Bell (1978) + VLB |
|
CORRECT |
12 |
FENE-P factor |
FENE-P closure |
|
CORRECT |
Issues Found¶
Docstring inconsistency (minor): Line 17 of
_kernels.pystatesdmu/dt = k_d*(I - mu) + D·mu + mu·Dusing the symmetric partD, but the actual model uses the full velocity gradientL·mu + mu·L^T. The code is correct; only the docstring needs updating.Free energy and dissipation not implemented: These are thermodynamic quantities useful for consistency checks but not required for mechanical predictions. Consider adding for completeness.
Key Clarification: L vs D in the Evolution Equation¶
The VLB paper uses the full velocity gradient L = ∇v, not just its symmetric part D = (L + L^T)/2. This is critical because:
With
L·μ + μ·L^T: the model is equivalent to the upper-convected Maxwell modelWith
D·μ + μ·D: the model would be the corotational form
The implementation correctly uses L·μ + μ·L^T (verified by the simple shear components where dμ_yy/dt has NO deformation contribution, which is only true with the full L).