Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option for mass gradient-based fluxes #1668

Merged
merged 1 commit into from
Mar 10, 2024

Conversation

g3bk47
Copy link
Contributor

@g3bk47 g3bk47 commented Feb 16, 2024

Changes proposed in this pull request

Add a new option to compute species diffusive fluxes with respect to their mass fraction gradients for 1D flames. See Cantera/enhancements#195 for extended discussion. All changes are fully backward compatible.

After some brainstoming, I settled on flux_gradient_basis as the new property's name, i.e. using mole or mass fraction gradients for computing species fluxes. If you have a better idea, feel free to let me know.
I also changed the API to use the established basis enum. Performance-wise, this should not have an impact, since the comparison m_fluxGradientBasis == ThermoBasis::molar is a simple hard-coded comparison against zero.

Checklist

  • The pull request includes a clear description of this code change
  • Commit messages have short titles and reference relevant issues
  • Build passes (scons build & scons test) and unit tests address code coverage
  • Style & formatting of contributed code follows contributing guidelines
  • The pull request is ready for review

@g3bk47 g3bk47 force-pushed the flame_mix_diff_mass branch 2 times, most recently from 87248d7 to 19a4da1 Compare February 23, 2024 17:45
Comment on lines 109 to 125
//! Compute species diffusive fluxes with respect to
//! their mass fraction gradients (fluxGradientBasis = ThermoBasis::mass)
//! or mole fraction gradients (fluxGradientBasis = ThermoBasis::molar, default)
//! when using the mixture-averaged transport model
void fluxGradientBasis(ThermoBasis fluxGradientBasis);
ThermoBasis fluxGradientBasis() const {
return m_fluxGradientBasis;
}
Copy link
Member

Choose a reason for hiding this comment

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

Each of these functions needs a docstring so it will be handled correctly by Doxygen. You can use @copydoc or @see to avoid having to repeat the content.

For consistency, the setter should be setFluxGradientBasis rather than overloading the same name as the getter.

Get/Set whether or not species diffusive fluxes are computed with
respect to their mass fraction gradients ('mass')
or mole fraction gradients ('molar', default) when
using the mixture-avaraged transport model.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
using the mixture-avaraged transport model.
using the mixture-averaged transport model.

Get/Set whether or not species diffusive fluxes are computed with
respect to their mass fraction gradients ('mass')
or mole fraction gradients ('molar', default) when
using the mixture-avaraged transport model.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
using the mixture-avaraged transport model.
using the mixture-averaged transport model.

Comment on lines 229 to 234
def flux_gradient_basis(self, basis):
if basis == 'molar' or basis == 'mass':
self.flame.flux_gradient_basis = basis
else:
raise ValueError("Valid choices are 'mass' or 'molar'."
" Got {!r}.".format(basis))
Copy link
Member

Choose a reason for hiding this comment

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

Checking the value of the flag here isn't really necessary -- the _FlowBase.flux_gradient_basis method can handle the error.

Comment on lines 224 to 225
writelog("Warning: setting fluxGradientBasis only affects"
" the mixture-averaged diffusion model.");
Copy link
Member

Choose a reason for hiding this comment

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

I'd suggest using warn_user here, rather than the less-specific writelog.

Comment on lines 651 to 660
for (size_t k=0; k < m_nsp; k++) {
m_diff[k+j*m_nsp] *= m_wt[k] * rho / wtm;
if (m_fluxGradientBasis == ThermoBasis::molar) {
m_diff[k+j*m_nsp] *= m_wt[k] * rho / wtm;
} else {
m_diff[k+j*m_nsp] *= rho;
}
}
Copy link
Member

Choose a reason for hiding this comment

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

At least for this inner loop, I think it's worth inverting the structure to check the m_fluxGradientBasis before the loop.

Comment on lines 699 to 709
if (m_fluxGradientBasis == ThermoBasis::molar) {
m_flux(k,j) *= (X(x,k,j) - X(x,k,j+1))/dz;
} else {
m_flux(k,j) *= (Y(x,k,j) - Y(x,k,j+1))/dz;
}
Copy link
Member

Choose a reason for hiding this comment

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

Likewise in this case.

@@ -780,6 +804,8 @@ AnyMap StFlow::getMeta() const

state["Soret-enabled"] = m_do_soret;

state["Flux-Gradient-Basis"] = static_cast<long int>(m_fluxGradientBasis);
Copy link
Member

Choose a reason for hiding this comment

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

Our naming convention for YAML fields is lower case except for proper names, so this should be flux-gradient-basis.

Comment on lines 483 to 498
def test_flux_gradient_mass(self):
self.create_sim(ct.one_atm, 300, 'H2:1.1, O2:1, AR:5.3')
self.sim.transport_model = 'mixture-averaged'
self.sim.set_refine_criteria(ratio=3.0, slope=0.08, curve=0.12)
self.assertTrue(self.sim.flux_gradient_basis == 'molar')
self.sim.solve(loglevel=0, auto=True)
sl_mole = self.sim.velocity[0]

self.sim.flux_gradient_basis = 'mass'
self.assertTrue(self.sim.flux_gradient_basis == 'mass')
self.sim.solve(loglevel=0)
sl_mass = self.sim.velocity[0]
# flame speeds should not be exactly equal
self.assertNotEqual(sl_mole, sl_mass)
# but they should be close
self.assertTrue(np.abs(sl_mole-sl_mass)/sl_mole < 0.1)

Copy link
Member

Choose a reason for hiding this comment

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

We're (slowly) transitioning to pytest style asserts, so this should be written as:

Suggested change
def test_flux_gradient_mass(self):
self.create_sim(ct.one_atm, 300, 'H2:1.1, O2:1, AR:5.3')
self.sim.transport_model = 'mixture-averaged'
self.sim.set_refine_criteria(ratio=3.0, slope=0.08, curve=0.12)
self.assertTrue(self.sim.flux_gradient_basis == 'molar')
self.sim.solve(loglevel=0, auto=True)
sl_mole = self.sim.velocity[0]
self.sim.flux_gradient_basis = 'mass'
self.assertTrue(self.sim.flux_gradient_basis == 'mass')
self.sim.solve(loglevel=0)
sl_mass = self.sim.velocity[0]
# flame speeds should not be exactly equal
self.assertNotEqual(sl_mole, sl_mass)
# but they should be close
self.assertTrue(np.abs(sl_mole-sl_mass)/sl_mole < 0.1)
def test_flux_gradient_mass(self):
self.create_sim(ct.one_atm, 300, 'H2:1.1, O2:1, AR:5.3')
self.sim.transport_model = 'mixture-averaged'
self.sim.set_refine_criteria(ratio=3.0, slope=0.08, curve=0.12)
assert self.sim.flux_gradient_basis == 'molar'
self.sim.solve(loglevel=0, auto=True)
sl_mole = self.sim.velocity[0]
self.sim.flux_gradient_basis = 'mass'
assert self.sim.flux_gradient_basis == 'mass'
self.sim.solve(loglevel=0)
sl_mass = self.sim.velocity[0]
# flame speeds should not be exactly equal
assert sl_mole != sl_mass
# but they should be close
assert sl_mole == approx(sl_mass, rel=0.1)

Copy link
Member

@speth speth left a comment

Choose a reason for hiding this comment

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

Thanks, @g3bk47, I think this ended up being a pretty clean API. I just had a few small changes to recommend.

If you can rebase onto the current main branch, it will fix the CI errors.

@g3bk47
Copy link
Contributor Author

g3bk47 commented Mar 9, 2024

Thanks, @speth! I rebased and incorporated all requested changes.

Copy link

codecov bot commented Mar 10, 2024

Codecov Report

Attention: Patch coverage is 86.04651% with 6 lines in your changes are missing coverage. Please review.

Project coverage is 72.78%. Comparing base (64ed2b7) to head (c2a9322).

Files Patch % Lines
interfaces/cython/cantera/_onedim.pyx 66.66% 3 Missing ⚠️
src/oneD/StFlow.cpp 88.46% 1 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1668      +/-   ##
==========================================
+ Coverage   72.77%   72.78%   +0.01%     
==========================================
  Files         375      375              
  Lines       56632    56667      +35     
  Branches    20590    20603      +13     
==========================================
+ Hits        41212    41244      +32     
- Misses      12398    12399       +1     
- Partials     3022     3024       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@speth speth left a comment

Choose a reason for hiding this comment

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

Thanks! Looks good to me.

@speth speth merged commit 66835e2 into Cantera:main Mar 10, 2024
49 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants