Skip to content

Commit 04f0681

Browse files
committed
eps change
1 parent 9d37562 commit 04f0681

File tree

4 files changed

+448
-6
lines changed

4 files changed

+448
-6
lines changed

Common/src/linear_algebra/CSysMatrix.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -505,15 +505,17 @@ void CSysMatrix<ScalarType>::Gauss_Elimination(ScalarType* matrix, ScalarType* v
505505
#define A(I, J) matrix[(I)*nVar + (J)]
506506

507507
/*--- Regularization epsilon to prevent divide-by-zero ---*/
508-
constexpr passivedouble eps = 1e-12;
508+
//constexpr passivedouble eps = 1e-12;
509+
const su2double eps = 1e-12;
509510

510511
/*--- Transform system in Upper Matrix ---*/
511512

512513
for (auto iVar = 1ul; iVar < nVar; iVar++) {
513514
for (auto jVar = 0ul; jVar < iVar; jVar++) {
514515
/*--- Regularize pivot if too small to prevent divide-by-zero ---*/
515516
if (std::abs(A(jVar, jVar)) < eps) {
516-
A(jVar, jVar) = (A(jVar, jVar) >= ScalarType(0)) ? ScalarType(eps) : ScalarType(-eps);
517+
//A(jVar, jVar) = (A(jVar, jVar) >= ScalarType(0)) ? ScalarType(eps) : ScalarType(-eps);
518+
A(jVar, jVar) = (A(jVar, jVar) >= 0.0 ? eps : -eps);
517519
std::cout << "DEBUG Gauss_Elimination: Regularized small pivot A(" << jVar << "," << jVar << ") to "
518520
<< A(jVar, jVar) << std::endl;
519521
}
@@ -532,7 +534,8 @@ void CSysMatrix<ScalarType>::Gauss_Elimination(ScalarType* matrix, ScalarType* v
532534

533535
/*--- Regularize diagonal if too small ---*/
534536
if (std::abs(A(iVar, iVar)) < eps) {
535-
A(iVar, iVar) = (A(iVar, iVar) >= ScalarType(0)) ? ScalarType(eps) : ScalarType(-eps);
537+
//A(iVar, iVar) = (A(iVar, iVar) >= ScalarType(0)) ? ScalarType(eps) : ScalarType(-eps);
538+
A(iVar, iVar) = (A(iVar, iVar) >= 0.0 ? eps : -eps);
536539
std::cout << "DEBUG Gauss_Elimination backsubst: Regularized small diagonal A(" << iVar << "," << iVar << ") to "
537540
<< A(iVar, iVar) << std::endl;
538541
}
@@ -568,14 +571,14 @@ void CSysMatrix<ScalarType>::MatrixInverse(ScalarType* matrix, ScalarType* inver
568571
#define A(I, J) matrix[(I)*nVar + (J)]
569572

570573
/*--- Regularization epsilon to prevent divide-by-zero ---*/
571-
constexpr passivedouble eps = 1e-12;
574+
const su2double eps = 1e-12;
572575

573576
/*--- Transform system in Upper Matrix ---*/
574577
for (auto iVar = 1ul; iVar < nVar; iVar++) {
575578
for (auto jVar = 0ul; jVar < iVar; jVar++) {
576579
/*--- Regularize pivot if too small to prevent divide-by-zero ---*/
577580
if (std::abs(A(jVar, jVar)) < eps) {
578-
A(jVar, jVar) = (A(jVar, jVar) >= ScalarType(0)) ? ScalarType(eps) : ScalarType(-eps);
581+
A(jVar, jVar) = (A(jVar, jVar) >= 0.0 ? eps : -eps);
579582
std::cout << "DEBUG MatrixInverse: Regularized small pivot A(" << jVar << "," << jVar << ") to "
580583
<< A(jVar, jVar) << " at iVar=" << iVar << std::endl;
581584
}
@@ -596,7 +599,7 @@ void CSysMatrix<ScalarType>::MatrixInverse(ScalarType* matrix, ScalarType* inver
596599

597600
/*--- Regularize diagonal if too small ---*/
598601
if (std::abs(A(iVar, iVar)) < eps) {
599-
A(iVar, iVar) = (A(iVar, iVar) >= ScalarType(0)) ? ScalarType(eps) : ScalarType(-eps);
602+
A(iVar, iVar) = (A(iVar, iVar) >= 0.0 ? eps : -eps);
600603
std::cout << "DEBUG MatrixInverse backsubst: Regularized small diagonal A(" << iVar << "," << iVar << ") to "
601604
<< A(iVar, iVar) << std::endl;
602605
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Quick Fix Summary: Residual Stagnation Solution
2+
3+
## The Problem
4+
```
5+
Species equation → converges ✓
6+
Update T from species → T = (1-c)*Tu + c*Tf
7+
Flow equations → STAGNATE ✗
8+
```
9+
10+
**Why?** Density wasn't updated when temperature changed!
11+
12+
## The Fix
13+
14+
### BEFORE (Broken):
15+
```python
16+
def update_temperature(SU2Driver, iPoint):
17+
C = SU2Driver.Solution(iSPECIESSOLVER)(iPoint,0)
18+
T = Tu*(1-C) + Tf*C
19+
Cp = SU2Driver.Primitives()(iPoint,iCp)
20+
SU2Driver.Solution(iFLOWSOLVER).Set(iPoint,iTEMP,Cp*T)
21+
# ⚠️ Density not updated! ρ still has old value
22+
```
23+
24+
### AFTER (Fixed):
25+
```python
26+
def update_temperature(SU2Driver, iPoint):
27+
C = SU2Driver.Solution(iSPECIESSOLVER)(iPoint,0)
28+
T_target = Tu*(1-C) + Tf*C
29+
T_old = SU2Driver.Primitives()(iPoint,iTEMPERATURE)
30+
31+
# ✓ Under-relaxation for stability
32+
T_new = RELAX_FACTOR * T_target + (1.0 - RELAX_FACTOR) * T_old
33+
34+
# ✓ Compute gas constant from old state
35+
R_gas = P / (rho_old * T_old)
36+
37+
# ✓ Update density consistently: ρ = P/(RT)
38+
rho_new = P / (R_gas * T_new)
39+
40+
# ✓ Update both temperature and density
41+
SU2Driver.Solution(iFLOWSOLVER).Set(iPoint, iTEMP, T_new)
42+
SU2Driver.Primitives().Set(iPoint, iDENSITY, rho_new)
43+
```
44+
45+
## Main Loop Sequence
46+
47+
### BEFORE:
48+
```python
49+
driver.Preprocess()
50+
driver.Run()
51+
# Set source terms (WRONG: after Run!)
52+
for i in nodes: Source.Set(i, zimont(i))
53+
# Update temperature (no density update)
54+
for i in nodes: update_temperature(i)
55+
driver.Postprocess()
56+
```
57+
58+
### AFTER:
59+
```python
60+
driver.Preprocess()
61+
# ✓ Set source terms BEFORE Run
62+
for i in nodes: Source.Set(i, zimont(i))
63+
# ✓ Run solvers
64+
driver.Run()
65+
# ✓ Update temperature AND density AFTER Run
66+
for i in nodes: update_temperature(i)
67+
# ✓ Monitor coupling
68+
print(f"Max ΔT: {max_delta_T}, Max Δρ/ρ: {max_delta_rho}")
69+
driver.Postprocess()
70+
```
71+
72+
## Key Parameters
73+
74+
```python
75+
# Add at top of file:
76+
RELAX_FACTOR = 0.7 # Adjust 0.5-0.8 for stability vs speed
77+
```
78+
79+
## Expected Behavior
80+
81+
| Before Fix | After Fix |
82+
|------------|-----------|
83+
| Species: ✓ converging | Species: ✓ converging |
84+
| Pressure: ✗ stagnating | Pressure: ✓ converging |
85+
| Velocity: ✗ stagnating | Velocity: ✓ converging |
86+
| ρ inconsistent with T | ρ = P/(RT) ✓ |
87+
88+
## Physics
89+
90+
**In combustion:**
91+
- c: 0 → 1 (progress)
92+
- T: 673K → 1777K ↑
93+
- ρ: 2.52 → ~0.95 ↓ (MUST decrease!)
94+
95+
**If ρ not updated:**
96+
- Continuity: wrong mass fluxes
97+
- Momentum: wrong inertia
98+
- → Residuals can't converge!
99+
100+
## Monitoring
101+
102+
Look for in output:
103+
```
104+
Source term - Max: 1.23e+02, Min: 0.00e+00, Avg: 3.45e+01
105+
Max temperature change: 5.23e+01 K
106+
Max relative density change: 2.15e-02
107+
```
108+
109+
## Troubleshooting
110+
111+
**Still not converging?**
112+
1. Reduce `RELAX_FACTOR` to 0.5
113+
2. Reduce CFL number in config
114+
3. Check source term isn't too strong
115+
4. Verify mass conservation: Σ(source terms) ≈ 0
116+
117+
**Oscillations?**
118+
1. Reduce `RELAX_FACTOR`
119+
2. Check grid quality in flame region
120+
3. Ensure boundary conditions are correct
121+
122+
## One-Line Summary
123+
124+
**Always update density when temperature changes: `ρ_new = P/(R*T_new)`**
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
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

Comments
 (0)