|
| 1 | +# Solution for Residual Stagnation in Turbulent Premixed Combustion |
| 2 | + |
| 3 | +## Problem Description |
| 4 | + |
| 5 | +When using the Python wrapper to add species transport with strong source terms and algebraically updating temperature/enthalpy from species composition, the pressure and velocity residuals stagnate in regions with high source terms while the species residuals converge properly. |
| 6 | + |
| 7 | +## Root Cause |
| 8 | + |
| 9 | +The issue occurs because: |
| 10 | + |
| 11 | +1. **Species solver** converges and updates the progress variable `c` |
| 12 | +2. **Temperature is updated algebraically**: `T = (1-c)*Tu + c*Tf` |
| 13 | +3. **Density is NOT updated** to match the new temperature |
| 14 | +4. **Thermodynamic inconsistency**: The ideal gas law `ρ = P/(RT)` is violated |
| 15 | +5. **Flow equations see inconsistent state**: Continuity and momentum equations operate with outdated density |
| 16 | + |
| 17 | +This breaks the coupling between species, energy, and momentum equations, causing residual stagnation. |
| 18 | + |
| 19 | +## Solution Implemented (Solution #1) |
| 20 | + |
| 21 | +### Key Changes in `run.py`: |
| 22 | + |
| 23 | +#### 1. **Updated `update_temperature()` function** (Lines ~90-130) |
| 24 | + - Now computes new density when temperature changes: `ρ_new = P/(R*T_new)` |
| 25 | + - Updates both temperature AND density in the primitive variables |
| 26 | + - Added under-relaxation factor for stability: `T_new = ω*T_target + (1-ω)*T_old` |
| 27 | + - Maintains thermodynamic consistency with ideal gas law |
| 28 | + |
| 29 | +#### 2. **Improved iteration sequence** (Lines ~250-290) |
| 30 | + - **STEP 1**: Set species source terms |
| 31 | + - **STEP 2**: Run all solvers (species equation solved) |
| 32 | + - **STEP 3**: Update temperature AND density from new species field |
| 33 | + - **STEP 4**: Postprocess and update |
| 34 | + - Ensures proper coupling between species and flow equations |
| 35 | + |
| 36 | +#### 3. **Added under-relaxation** (Line ~58) |
| 37 | + - `RELAX_FACTOR = 0.7` prevents oscillations |
| 38 | + - Can be tuned between 0.5-0.8 depending on source term strength |
| 39 | + - Lower values = more stable but slower convergence |
| 40 | + |
| 41 | +#### 4. **Added coupling diagnostics** (Lines ~270-280) |
| 42 | + - Monitors `max_delta_T` and `max_delta_rho` |
| 43 | + - Helps identify coupling issues |
| 44 | + - Shows when thermodynamic updates are stabilizing |
| 45 | + |
| 46 | +#### 5. **Added source term monitoring** (Lines ~185-215, ~260-265) |
| 47 | + - Tracks max/min/avg source term values |
| 48 | + - Helps diagnose convergence problems |
| 49 | + - Important for checking mass conservation |
| 50 | + |
| 51 | +## Physical Interpretation |
| 52 | + |
| 53 | +For a premixed flame: |
| 54 | +- Progress variable goes from `c=0` (unburnt) to `c=1` (burnt) |
| 55 | +- Temperature increases: `T: 673K → 1777K` |
| 56 | +- Density MUST decrease (isobaric): `ρ ∝ 1/T` |
| 57 | +- Without density update: continuity equation sees wrong mass fluxes |
| 58 | +- Result: momentum residuals can't converge |
| 59 | + |
| 60 | +## Expected Results |
| 61 | + |
| 62 | +After this fix: |
| 63 | +- ✅ Species residuals converge (as before) |
| 64 | +- ✅ Temperature correctly updates from species |
| 65 | +- ✅ **Density correctly updates from temperature** |
| 66 | +- ✅ **Pressure residuals converge** (no longer stagnate) |
| 67 | +- ✅ **Velocity residuals converge** (no longer stagnate) |
| 68 | +- ✅ Thermodynamic consistency maintained |
| 69 | + |
| 70 | +## Tuning Parameters |
| 71 | + |
| 72 | +If convergence is still slow, adjust: |
| 73 | + |
| 74 | +### 1. **Under-relaxation factor** (Line 58) |
| 75 | +```python |
| 76 | +RELAX_FACTOR = 0.5-0.8 # Lower = more stable, slower |
| 77 | +``` |
| 78 | + |
| 79 | +### 2. **CFL number in config file** |
| 80 | +``` |
| 81 | +CFL_NUMBER= 10.0 # Reduce if needed |
| 82 | +CFL_ADAPT= YES |
| 83 | +CFL_ADAPT_PARAM= ( 0.3, 0.5, 10.0, 100.0, 1e-6 ) |
| 84 | +``` |
| 85 | + |
| 86 | +### 3. **Number of inner iterations** |
| 87 | +```python |
| 88 | +for inner_iter in range(10): # Increase for more coupling iterations |
| 89 | +``` |
| 90 | + |
| 91 | +## Additional Recommendations |
| 92 | + |
| 93 | +1. **Monitor residual ratios**: Watch for regions where flow residuals are high relative to species residuals |
| 94 | + |
| 95 | +2. **Check mass conservation**: The source term should not create/destroy mass: |
| 96 | + ``` |
| 97 | + ∂(ρc)/∂t + ∇·(ρcv) = S_c |
| 98 | + ``` |
| 99 | + where `S_c` is per unit volume |
| 100 | + |
| 101 | +3. **Verify ideal gas law**: At any point, check if `P = ρRT` holds after updates |
| 102 | + |
| 103 | +4. **Use implicit time stepping**: Helps with stiff source terms (already in config) |
| 104 | + |
| 105 | +5. **Consider local time stepping**: Can help in regions with varying source terms |
| 106 | + |
| 107 | +## Technical Details |
| 108 | + |
| 109 | +### Incompressible Flow Considerations |
| 110 | +This case uses `INC.FLOW` (incompressible solver), which: |
| 111 | +- Solves for pressure directly (not density-based) |
| 112 | +- Assumes low Mach number |
| 113 | +- Still requires density updates for variable density flows (like combustion!) |
| 114 | +- Energy equation is decoupled but affects momentum through density |
| 115 | + |
| 116 | +### Variable Density Incompressible Flow |
| 117 | +Even though it's "incompressible", combustion creates variable density: |
| 118 | +- ∇·(ρv) = 0 (mass conservation, not ∇·v = 0) |
| 119 | +- ρ varies due to temperature, not pressure waves |
| 120 | +- Density MUST be updated when temperature changes |
| 121 | + |
| 122 | +## References |
| 123 | +- See main SU2 documentation for species transport |
| 124 | +- Zimont turbulent flame speed closure: Zimont, V.L., 2000. "Gas premixed combustion at high turbulence." |
| 125 | +- Variable density incompressible flow formulation |
| 126 | + |
| 127 | +## Contact |
| 128 | +For issues or questions about this fix, refer to the SU2 forums or GitHub issues. |
0 commit comments