Skip to content

Source term method for preferential diffusion - #2970

Open
joshkellyjak wants to merge 6 commits into
developfrom
feature_new_pref_diffusion
Open

joshkellyjak wants to merge 6 commits into
developfrom
feature_new_pref_diffusion

Conversation

@joshkellyjak

@joshkellyjak joshkellyjak commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Proposed Changes

Adds the resolved Eq. (14) preferential diffusion flux formulation (model B2 of
Schepers & van Oijen, C&F 280 (2025) 114332) to the flamelet scalar transport,
alongside the existing beta correction, and fixes two defects that leave the
current preferential diffusion model not merely inert but actively wrong.

Two fixes that affect develop today. CSpeciesFlameletVariable sizes
AuxVar and Grad_AuxVar to the four beta terms but never sets nAuxVar, so
SetAuxVar_Gradient_GG/LS loop zero times and every beta gradient stays zero.
The FGM model drives the diffusive flux of the controlling variables by
grad(beta) rather than by their own gradient (Bunschoten, Eqs. 2.8-2.10); the
solver reaches that from the generic scalar base class by adding
div(D grad(beta - phi)) to the ordinary div(D grad phi), which sums to
div(D grad beta). With the beta gradients zero that sum is zero, so the
controlling variables are left with no diffusion at all. Separately,
LEAST_SQUARES falls through the auxiliary gradient switch, with the same
consequence for anyone not on Green-Gauss.

New model. PREFERENTIAL_DIFFUSION_METHOD selects BETA_CORRECTION
(default, unchanged) or SOURCE_TERM. PREFERENTIAL_DIFFUSION_MAJOR_SPECIES
names the species carrying the resolved flux; the manifold variables
(Res_<cv>, Y-<sp>, D_<cv>_<sp>, DT_<cv>) are composed from the
configured controlling variable and species names rather than hard-coded, so one
set of strings describes the table on both sides. The Eq. (14) fluxes are a new
branch of CScalarFlux_Flamelet, driven by the CFD-resolved gradients of the
major species and of temperature — the point of tabulating a coefficient per
species instead of pre-contracting them against the one-dimensional flamelet
gradients. They are applied explicitly, with a stabilising self-diffusion added
to the Jacobian alone so the converged solution is untouched. The Eq. (16)
closure sources are gated on manifold validity only.

Also fixed. Soret coefficients are zeroed on viscous walls, where the
manifold carries no quench-layer data. A collective in the volume output ran
behind an iPoint == 0 test inside the per-point loop, so a rank owning no
points would have hung every other rank; it moves to a new per-write
COutput::PrepareVolumeData hook, where an empty partition contributes the
MIN/MAX identity elements instead of not participating. The cached preferential
diffusion source is cleared at off-manifold nodes, and the Newton
non-convergence message is rank-guarded.

Diagnostics. FLAME_QUALITY volume group (C+, chi_C, Da), hull-miss
deviations, FLAMELET_VERBOSE_MISSES, and per-location probe history files.

Validation

Laminar premixed H2 burner against an OpenFOAM FGM reference, on a manifold
whose progress variable is defined on the major species only.

  • Reproduces the reference: converged residuals agree to ~3 decimals across all
    four equations; Temperature and Density agree with the reference
    implementation to 5-6 significant figures.
  • Manifold misses drop from 592 to 1-2.
  • Stabiliser: converged answer unchanged (residuals agree to 5-7 significant
    figures at CFL 1); CFL ceiling moves from (1, 2) without it to (2, 3) with it;
    misses hold at 1-2 across that range, against 1 -> 7 -> 49 without.

A chemical-activity gate on the closure sources was removed:
fmax(0, .) clipping meant it only closed where the tabulated source was
negative, so it closed at 320 preheat-zone nodes (304-567 K) while staying open
across 21k gradient-free bulk nodes — the inverse of its stated purpose.

Caveats

  • The nAuxVar fix changes results for every existing BETA_CORRECTION
    user
    , including regression case 07, which runs the default method.
    Baselines will move. The fix is correct, but the new behaviour still needs
    validating on a manifold built for the beta formulation — on the
    SOURCE_TERM-oriented manifold used here, BETA_CORRECTION diverges.
  • Wall Soret zeroing is a modelling choice, not a bug fix. It changes wall
    heat flux by up to 1.2% and wall temperature by 0.4 K, decaying to nothing
    within 0.5 mm. Justified by manifold support, not impermeability: the wall
    face carries no Eq. (14) flux in any case, since only interior edges are
    visited. What it changes is the near-wall interior edges, through the
    coefficient averaging.
  • The CFL figures are case-specific — 100 iterations from a converged
    restart on this burner, with a coarse ladder (1, 2, 3). Treat ~1.5x as
    indicative, not a precise factor.
  • The three manifold-miss gates were inert in every test (<= 1e-5 K on two
    different manifolds and two different flux discretizations). Retained as
    insurance against a poorly matched table, but unexercised.

Related Work

This work was developed on a branch that predates the rewrite of the flamelet
scalar transport into CScalarFlux_Flamelet / EdgeFluxResidual, and the flux
assembly was ported onto that framework rather than carried over. The port is
validated by reproducing the pre-port implementation's residuals to the digit
with the stabiliser disabled.

PR Checklist

  • I am submitting my contribution to the develop branch.
  • My contribution generates no new compiler warnings (try with --warnlevel=3 when using meson).
  • My contribution is commented and consistent with SU2 style (https://su2code.github.io/docs_v7/Style-Guide/).
  • I used the pre-commit hook to prevent dirty commits and used pre-commit run --all to format old commits.
  • I have added a test case that demonstrates my contribution, if necessary.
  • I have updated appropriate documentation (Tutorials, Docs Page, config_template.cpp), if necessary.

joshkellyjak and others added 2 commits October 9, 2026 23:46
…te fixes

Adds the resolved Eq. (14) preferential diffusion flux formulation (model B2 of
Schepers & van Oijen, C&F 280 (2025) 114332) to the flamelet scalar transport,
alongside the existing beta correction, and fixes two defects that left the
existing model inert or wrong.

Model
- PREFERENTIAL_DIFFUSION_METHOD selects BETA_CORRECTION (default, unchanged) or
  SOURCE_TERM.
- PREFERENTIAL_DIFFUSION_MAJOR_SPECIES names the species carrying the resolved
  flux. The manifold variables (Res_<cv>, Y-<sp>, D_<cv>_<sp>, DT_<cv>) are
  composed from the configured controlling variable and species names.
- The Eq. (14) fluxes are a new branch of CScalarFlux_Flamelet, driven by the
  CFD-resolved gradients of the major species and of temperature. Explicit, with
  a stabilising self-diffusion added to the Jacobian alone so the converged
  solution is unchanged.
- The Eq. (16) closure sources are gated on manifold validity only.

Fixes
- nAuxVar was never set, so SetAuxVar_Gradient_* looped zero times and every beta
  gradient stayed zero. The beta term then evaluated grad(beta) - grad(phi) as
  -grad(phi), cancelling the ordinary diffusion of the controlling variables
  rather than correcting it.
- LEAST_SQUARES fell through the auxiliary gradient switch, with the same effect.
- Soret coefficients are zeroed on viscous walls, where the manifold carries no
  quench layer data.
- A collective in the volume output ran behind an "iPoint == 0" test inside the
  per point loop; a rank owning no points would have hung the others. Moved to a
  new per write COutput::PrepareVolumeData hook.
- The cached preferential diffusion source is cleared at off manifold nodes, and
  the Newton non convergence message is rank guarded.

Diagnostics
- FLAME_QUALITY volume group, hull miss deviations, FLAMELET_VERBOSE_MISSES, and
  per location probe history files.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…le gradient

The stabilising diffusivity is a bound on the Eq. (14) flux recast as a self
diffusion, |J| <= D_stab |grad phi|, so it has to be divided by the controlling
variable's own gradient. Without that division D_stab sits at the raw coefficient
magnitude everywhere, which damps the update far more than the explicit flux
warrants: on the burner case every stabilised run plateaued near rms[h] = -2.45
whatever the CFL, so the higher ceiling bought no convergence. With the division
restored, CFL 2 reaches -2.530 against -2.528 at CFL 1, and the ceiling moves
from (1, 2) without the term to (2, 3) with it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@joshkellyjak joshkellyjak self-assigned this Oct 9, 2026
coefficient D^T_{phi_k}. ---*/
if (source_term_active) {
pd_terms_per_cv = FlameletPDTermsPerCV(flamelet_config_options.n_pd_major_species);
pd_flux_coeff.resize(nPoint, flamelet_config_options.n_control_vars * pd_terms_per_cv) = su2double(0.0);
…spaces) (#2935)

## Proposed Changes

`SU2_PY/SU2/run/interface.py` builds the command as
`os.path.join(SU2_RUN, "SU2_CFD") + " config_CFD.cfg"` and runs it with
`shell=True`. The executable path is quoted only on Windows (`quote =
'"' if sys.platform == "win32" else ""`), so on Linux/macOS any SU2_PY
script (shape_optimization.py, parallel_computation.py, ...) fails if
`SU2_RUN` contains a space.

This PR moves the quoting into `build_command`: the first word of the
command is joined with `SU2_RUN` and quoted (`shlex.quote` on POSIX,
double quotes on Windows as before), the callers pass plain `"SU2_CFD
config_CFD.cfg"` strings. The quoted path is then inserted into the MPI
template as before (`mpirun -n %i %s`, `srun`, `SU2_MPI_COMMAND`). The
module-level `quote` variable is removed; it was not used outside
`interface.py`.

Reproduction on macOS, `SU2_RUN=".../su2 bin"`, `shape_opt_euler_py`
from serial_regression.py:

```
before:
Command = /.../su2 bin/SU2_CFD config_CFD.cfg
SU2 process returned error '127'
/bin/sh: /.../su2: No such file or directory

after:
Command = '/.../su2 bin/SU2_CFD' config_CFD.cfg
optimization runs to the end
```

With the change and `SU2_RUN` containing a space, `history_project.csv`
and the optimizer output of `shape_opt_euler_py` are identical to
develop with a `SU2_RUN` without spaces. The MPI path was checked with
`NUMBER_PART=2`: `mpirun -n 2 '/.../su2 bin/SU2_CFD' config_CFD.cfg`
runs with 2 ranks. The Windows branch produces the same string as
before.

## Related Work

None found. Separate from #2934 (also SU2_PY).

## PR Checklist

- [X] I am submitting my contribution to the develop branch.
- [X] My contribution generates no new compiler warnings (try with
--warnlevel=3 when using meson).
- [X] My contribution is commented and consistent with SU2 style
(https://su2code.github.io/docs_v7/Style-Guide/).
- [X] I used the pre-commit hook to prevent dirty commits and used
`pre-commit run --all` to format old commits.
- [X] I have added a test case that demonstrates my contribution, if
necessary. — Not necessary: the change only affects how the executable
path is quoted; `shape_opt_euler_py` passes unchanged, and the
reproduction above (SU2_RUN with a space) fails before and passes after.
- [X] I have updated appropriate documentation (Tutorials, Docs Page,
config_template.cpp), if necessary. — Not necessary: no user-facing
option changed.

Co-authored-by: Nijso <bigfootedrockmidget@hotmail.com>
@bigfooted

Copy link
Copy Markdown
Contributor

CScalarFlux_Flamelet::extraDiffusionTerms then evaluates grad(beta) - grad(phi) as -grad(phi), and res.flux_i -= D * projGrad adds back
+D*grad(phi) — cancelling the ordinary diffusion of the controlling variables
rather than correcting it

This is the correct behavior as described in Everts thesis, the ordinary diffusion should be cancelled, leaving only the beta correction term.
You could choose not to add the diffusion term in the first place.

@joshkellyjak

Copy link
Copy Markdown
Contributor Author

CScalarFlux_Flamelet::extraDiffusionTerms then evaluates grad(beta) - grad(phi) as -grad(phi), and res.flux_i -= D * projGrad adds back
+D*grad(phi) — cancelling the ordinary diffusion of the controlling variables
rather than correcting it

This is the correct behavior as described in Everts thesis, the ordinary diffusion should be cancelled, leaving only the beta correction term. You could choose not to add the diffusion term in the first place.

This description is wrong the beta correction side is unchanged from develop other than the nAuxVar fix

@bigfooted

bigfooted commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

OK, I checked what was really going on with the nAuxvar fix. This bug actually puts the cross-diffusion term of the gradient of beta to zero. On orthogonal meshes this nAuxvar contribution is zero.
So the preferential diffusion results on the testcases that we have in the regression tests are correct. I was a bit worried there... In any case it's a good fix.

@bigfooted

Copy link
Copy Markdown
Contributor

OK, so I checked the paper of Stijn. So it's an extension of Nithin's paper for mixture averaged diffusion (instead of constant Lewis per species) and he adds Soret diffusion. And Stijn uses only major species and then has some truncation source term.
Can you also make Soret optional, it is usually neglected - and negligible.

@joshkellyjak

Copy link
Copy Markdown
Contributor Author

OK, so I checked the paper of Stijn. So it's an extension of Nithin's paper for mixture averaged diffusion (instead of constant Lewis per species) and he adds Soret diffusion. And Stijn uses only major species and then has some truncation source term. Can you also make Soret optional, it is usually neglected - and negligible.

Yes, as the forthcoming PR to DataMiner will show, when you have a PV definition with non-major species you end up with some additional conservation term, relatively small to all other contributions but necessary for conservation

@bigfooted

bigfooted commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

@EvertBunschoten EvertBunschoten left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I like the extensive commentary on the functionality of the new model and the addition of table diagnostics. I think however that effort should be made to reduce the number of accessors to table diagnostics.

* Returns 0 for 2D tables or when only one Z level exists.
*/
inline su2double GetDistanceToNearestZLevel(su2double val_CV3) const {
if (table_dim < 3 || n_table_levels < 2) return 0.0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

checking for fewer than two table levels is redundant.

inline su2double GetDistanceToNearestZLevel(su2double val_CV3) const {
if (table_dim < 3 || n_table_levels < 2) return 0.0;
auto it = std::lower_bound(z_values_levels.begin(), z_values_levels.end(), val_CV3);
su2double d_hi = (it != z_values_levels.end()) ? abs(*it - val_CV3) : su2double(1e30);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

mind the spacing

*/
inline su2double GetDistanceToNearestZLevel(su2double val_CV3) const {
if (table_dim < 3 || n_table_levels < 2) return 0.0;
auto it = std::lower_bound(z_values_levels.begin(), z_values_levels.end(), val_CV3);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The z-levels are ordered, you can just calculate the distances from the first and last table level.

* themselves are configured at run time with PREFERENTIAL_DIFFUSION_MAJOR_SPECIES, so their
* count is not a compile-time constant.
*/
static inline unsigned short FlameletPDThermalTerm(unsigned short n_major_species) { return n_major_species; }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So this function just returns its own input? Can be removed?

unsigned short n_pd_major_species = 0; /*!< \brief Number of preferential diffusion major species (SOURCE_TERM method). */
std::string* pd_major_species_names; /*!< \brief Names of the preferential diffusion major species; the manifold
variables "D_<cv>_<species>" are composed from these. */
bool verbose_misses = false; /*!< \brief Print per-CV breakdown of manifold miss counts. */

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This option should have a more general scope, as it applies to the LUT class, not just the flamelet solver settings.

Comment on lines +170 to +263
FORCEINLINE void sourceTermFluxes(const FlowIndices& idx, const ScalarFluxOptions& opt, Int iPoint,
const EdgeSide<VariableType>& side_i, Int jPoint,
const EdgeSide<VariableType>& side_j, const CPair<Double>& rho,
const Vector<Double, nDim>& normal, const Vector<Double, nDim>& vector_ij,
EdgeResidual<Double, nVar>& res) const {
const Double dist2_ij = fmax(squaredNorm(vector_ij), EPS);
const Double proj_vector_ij = dot(vector_ij, normal) / dist2_ij;

const Double T_i = gatherVariables(iPoint, side_i.flowNodes->GetPrimitive(), idx.Temperature());
const Double T_j = gatherVariables(jPoint, side_j.flowNodes->GetPrimitive(), idx.Temperature());
const auto gradT_i = gatherVariables<nDim>(iPoint, side_i.flowNodes->GetGradient_Primitive(), idx.Temperature());
const auto gradT_j = gatherVariables<nDim>(jPoint, side_j.flowNodes->GetGradient_Primitive(), idx.Temperature());

/*--- The scalar solvers are templated on CSpeciesVariable, which does not carry the Eq. (14)
coefficients. Only the flamelet solver instantiates this flux, and only on its own interior
edges, so its container is what these sides hold. ---*/
const auto& pdCoeff_i = static_cast<const CSpeciesFlameletVariable&>(side_i.scalarNodes).GetPDFluxCoeffs();
const auto& pdCoeff_j = static_cast<const CSpeciesFlameletVariable&>(side_j.scalarNodes).GetPDFluxCoeffs();

for (auto iScalar = 0u; iScalar < nControlVars; ++iScalar) {
/*--- Magnitude of the Eq. (14) flux on each side, accumulated as the terms are applied, for
the stabilising diffusivity below. ---*/
Double fluxMag_i = 0.0, fluxMag_j = 0.0;

/*--- Molecular terms, one per major species. ---*/
for (auto iSp = 0u; iSp < nMajorSpecies; ++iSp) {
const auto col = iScalar * pdTermsPerCV + iSp;

const Double Y_i = gatherVariables(iPoint, side_i.scalarNodes.GetAuxVar(), iSp);
const Double Y_j = gatherVariables(jPoint, side_j.scalarNodes.GetAuxVar(), iSp);
const auto gradY_i = gatherVariables<nDim>(iPoint, side_i.scalarNodes.GetAuxVarGradient(), iSp);
const auto gradY_j = gatherVariables<nDim>(jPoint, side_j.scalarNodes.GetAuxVarGradient(), iSp);

const Double c_i = gatherVariables(iPoint, pdCoeff_i, col);
const Double c_j = gatherVariables(jPoint, pdCoeff_j, col);
const Double D = 0.5 * (c_i + c_j);

const Double projGrad = projectedGradient(opt, gradY_i, gradY_j, Y_i, Y_j, normal, vector_ij, dist2_ij);

res.flux_i(iScalar) -= D * projGrad;
if (!opt.oneSided) res.flux_j(iScalar) += D * projGrad;

if (opt.implicit) {
fluxMag_i += fabs(c_i) * sqrt(fmax(squaredNorm(gradY_i), EPS));
fluxMag_j += fabs(c_j) * sqrt(fmax(squaredNorm(gradY_j), EPS));
}
}

/*--- Thermal (Soret) term. ---*/
const auto colT = iScalar * pdTermsPerCV + FlameletPDThermalTerm(nMajorSpecies);
const Double Dth = 0.5 * (gatherVariables(iPoint, pdCoeff_i, colT) / T_i +
gatherVariables(jPoint, pdCoeff_j, colT) / T_j);

const Double projGradT = projectedGradient(opt, gradT_i, gradT_j, T_i, T_j, normal, vector_ij, dist2_ij);

res.flux_i(iScalar) -= Dth * projGradT;
if (!opt.oneSided) res.flux_j(iScalar) += Dth * projGradT;

/*--- Stabilisation. The fluxes above are explicit, and explicit diffusion carries a limit on
the pseudo time step that the flame front cells reach first. A self-diffusion of the
controlling variable is added to the Jacobian ALONE: the residual still holds exactly the
Eq. (14) fluxes, so the converged solution is untouched, while the positive definite
operator lifts that limit the way an implicit treatment of a real self-diffusion would.
D_stab is the baseline diffusivity scaled by how much larger the Eq. (14) coefficients are,
capped so a vanishing baseline cannot make it unbounded. ---*/
if (opt.implicit) {
const Double Dbase_i = rho.i * gatherVariables(iPoint, side_i.scalarNodes.GetDiffusivity(), iScalar);
const Double Dbase_j = rho.j * gatherVariables(jPoint, side_j.scalarNodes.GetDiffusivity(), iScalar);

/*--- Recast the flux bound as a self diffusivity, |J| <= D_stab |grad phi|, so the implicit
operator dominates the explicit flux without damping more than the flux itself warrants.
Scaling by the control variable's own gradient is what keeps it that tight: dropping it
leaves D_stab at the raw coefficient magnitude, which over damps and cancels the very CFL
gain the term exists to provide. Where grad(phi) vanishes while the cross gradients do not
the bound degenerates, so it is capped against the baseline diffusion. ---*/
fluxMag_i += fabs(gatherVariables(iPoint, pdCoeff_i, colT) / T_i) * sqrt(fmax(squaredNorm(gradT_i), EPS));
fluxMag_j += fabs(gatherVariables(jPoint, pdCoeff_j, colT) / T_j) * sqrt(fmax(squaredNorm(gradT_j), EPS));

const auto gradPhi_i = gatherVariables<nDim>(iPoint, side_i.scalarNodes.GetGradient(), iScalar);
const auto gradPhi_j = gatherVariables<nDim>(jPoint, side_j.scalarNodes.GetGradient(), iScalar);

const Double Dstab_i = fmin(fluxMag_i / sqrt(fmax(squaredNorm(gradPhi_i), EPS)), C_STAB_MAX * Dbase_i);
const Double Dstab_j = fmin(fluxMag_j / sqrt(fmax(squaredNorm(gradPhi_j), EPS)), C_STAB_MAX * Dbase_j);
const Double Dstab = 0.5 * (Dstab_i + Dstab_j);

res.jac_ii(iScalar, iScalar) += Dstab * proj_vector_ij / rho.i;
if (!opt.oneSided) {
res.jac_ij(iScalar, iScalar) -= Dstab * proj_vector_ij / rho.j;
res.jac_ji(iScalar, iScalar) -= Dstab * proj_vector_ij / rho.i;
res.jac_jj(iScalar, iScalar) += Dstab * proj_vector_ij / rho.j;
}
}
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This function has a lot of scopes and is quite long. Try to refactor it into smaller functions.

* of a boundary do not carry. They are an interior edge term: boundaries instantiate
* CScalarFlux_Species, as they did before this model existed.
*/
template <class Double, class FlowIndices, int nDim, size_t nVar = Dynamic>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What is the reason for using the Double in the template? Why can't we just use su2double throughout?

Comment on lines +146 to +152
inline void SetHullMissDevCV1(unsigned long iPoint, su2double val) override { hull_miss_dcv1_(iPoint) = val; }
inline su2double GetHullMissDevCV1(unsigned long iPoint) const override { return hull_miss_dcv1_(iPoint); }
inline void SetHullMissDevCV2(unsigned long iPoint, su2double val) override { hull_miss_dcv2_(iPoint) = val; }
inline su2double GetHullMissDevCV2(unsigned long iPoint) const override { return hull_miss_dcv2_(iPoint); }
inline void SetZLevelDist(unsigned long iPoint, su2double val) override { z_level_dist_(iPoint) = val; }
inline su2double GetZLevelDist(unsigned long iPoint) const override { return z_level_dist_(iPoint); }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Instead of adding accessors for each individual table diagnostic, it would be more clean to create an array of size nPoint containing structs with table diagnostics. That way, you'll only have to use a single pair of accessors for table diagnostics and it will be easier to add more table diagnostics in the future.

Comment on lines +851 to +859
if (varIdx >= 24) {
return solver[SPECIES_SOL]->GetNodes()->GetAuxVar(iPoint, varIdx - 24);
}
if (varIdx >= 16) {
const auto* src_pd = solver[SPECIES_SOL]->GetNodes()->GetScalarSourcesPD(iPoint);
return src_pd ? src_pd[varIdx - 16] : su2double(0.0);
}
const auto* src = solver[SPECIES_SOL]->GetNodes()->GetScalarSources(iPoint);
return src ? src[varIdx - 8] : su2double(0.0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Magic numbers?

Comment on lines +259 to 275
flamelet_config_options.pd_method == FLAMELET_PD_METHOD::SOURCE_TERM) {
auto* wall_nodes = static_cast<CSpeciesFlameletVariable*>(nodes);
const auto n_CV_wall = flamelet_config_options.n_control_vars;
const auto i_thermal = FlameletPDThermalTerm(flamelet_config_options.n_pd_major_species);

for (auto iMarker = 0u; iMarker < config->GetnMarker_All(); iMarker++) {
/*--- Viscous walls only. GetSolid_Wall would also match EULER_WALL, a slip boundary with no
quench layer and so nothing to suppress. ---*/
if (!config->GetViscous_Wall(iMarker)) continue;
SU2_OMP_FOR_STAT(OMP_MIN_SIZE)
for (auto iVertex = 0ul; iVertex < geometry->nVertex[iMarker]; iVertex++) {
const auto iPoint_wall = geometry->vertex[iMarker][iVertex]->GetNode();
for (auto iCV = 0u; iCV < n_CV_wall; iCV++)
wall_nodes->SetPDFluxCoeff(iPoint_wall, iCV, i_thermal, 0.0);
}
END_SU2_OMP_FOR
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This would be better placed in the BC function for viscous walls.

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants