Skip to content

Commit

Permalink
[Kinetics] Implement conditional updates for reactions using MultiRate
Browse files Browse the repository at this point in the history
Updating the "shared data" for a rate type returns flags indicating
whether the "update" or "eval" methods for each reaction of that type
need to be called to get new values of the rate constant.
  • Loading branch information
speth authored and ischoegl committed Dec 4, 2021
1 parent d5e075a commit d386d85
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 32 deletions.
12 changes: 9 additions & 3 deletions include/cantera/kinetics/MultiRate.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class MultiBulkRate final : public MultiRateBase
virtual void add(const size_t rxn_index, ReactionRate& rate) override {
m_indices[rxn_index] = m_rxn_rates.size();
m_rxn_rates.emplace_back(rxn_index, dynamic_cast<RateType&>(rate));
m_shared.invalidateCache();
}

virtual bool replace(const size_t rxn_index, ReactionRate& rate) override {
Expand All @@ -48,6 +49,7 @@ class MultiBulkRate final : public MultiRateBase
"Invalid operation: cannot replace rate object of type '{}' "
"with a new rate of type '{}'.", type(), rate.type());
}
m_shared.invalidateCache();
if (m_indices.find(rxn_index) != m_indices.end()) {
size_t j = m_indices[rxn_index];
m_rxn_rates.at(j).second = dynamic_cast<RateType&>(rate);
Expand All @@ -58,6 +60,7 @@ class MultiBulkRate final : public MultiRateBase

virtual void resize(size_t n_species, size_t n_reactions) override {
m_shared.resize(n_species, n_reactions);
m_shared.invalidateCache();
}

virtual void getRateConstants(double* kf) override {
Expand All @@ -78,10 +81,13 @@ class MultiBulkRate final : public MultiRateBase
_updateRates();
}

virtual void update(const ThermoPhase& bulk, const Kinetics& kin) override {
virtual bool update(const ThermoPhase& bulk, const Kinetics& kin) override {
// update common data once for each reaction type
m_shared.update(bulk, kin);
_updateRates();
std::pair<bool, bool> changed = m_shared.update(bulk, kin);
if (changed.first) {
_updateRates();
}
return changed.second;
}

virtual double evalSingle(ReactionRate& rate) override
Expand Down
3 changes: 2 additions & 1 deletion include/cantera/kinetics/MultiRateBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ class MultiRateBase
//! Update data common to reaction rates of a specific type
//! @param bulk object representing bulk phase
//! @param kin object representing kinetics
virtual void update(const ThermoPhase& bulk, const Kinetics& kin) = 0;
//! @returns flag indicating reaction rates need to be re-evaluated
virtual bool update(const ThermoPhase& bulk, const Kinetics& kin) = 0;

//! Get the rate for a single reaction. Used to implement ReactionRate::eval.
virtual double evalSingle(ReactionRate& rate) = 0;
Expand Down
65 changes: 54 additions & 11 deletions include/cantera/kinetics/ReactionData.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,23 @@ struct ArrheniusData
void update(double T, double P) { update(T); }

//! Update data container based on *bulk* phase state
void update(const ThermoPhase& bulk, const Kinetics& kin);
//! @returns A pair where the first element indicates whether the `updateFromStruct`
//! function for individual reactions needs to be called, and the second
//! element indicates whether the `evalFromStruct` method needs to be called
//! (assuming previously-calculated values were cached)
std::pair<bool, bool> update(const ThermoPhase& bulk, const Kinetics& kin);

//! Update number of species and reactions; unused
void resize(size_t n_species, size_t n_reactions) {}

//! Force shared data and reaction rates to be updated next time. This is called by
//! functions that change quantities affecting rate calculations that are normally
//! assumed to be constant, like the reaction rate parameters or the number of
//! reactions.
void invalidateCache() {
temperature = NAN;
}

double temperature; //!< temperature
double logT; //!< logarithm of temperature
double recipT; //!< inverse of temperature
Expand All @@ -55,8 +67,7 @@ struct ArrheniusData
*/
struct BlowersMaselData
{
BlowersMaselData()
: temperature(1.), logT(0.), recipT(1.), finalized(false) {}
BlowersMaselData();

//! Update data container based on temperature *T*
void update(double T);
Expand All @@ -67,7 +78,7 @@ struct BlowersMaselData
}

//! Update data container based on *bulk* phase state and *kin* kinetics
void update(const ThermoPhase& bulk, const Kinetics& kin);
std::pair<bool, bool> update(const ThermoPhase& bulk, const Kinetics& kin);

//! Finalize setup
void resize(size_t n_species, size_t n_reactions) {
Expand All @@ -76,9 +87,16 @@ struct BlowersMaselData
finalized = true;
}

void invalidateCache() {
temperature = NAN;
}

double temperature; //!< temperature
double logT; //!< logarithm of temperature
double recipT; //!< inverse of temperature
double density; //!< used to determine if updates are needed
int state_mf_number; //!< integer that is incremented when composition changes


bool finalized; //!< boolean indicating whether vectors are accessible
vector_fp dH; //!< enthalpy change for each reaction
Expand All @@ -95,10 +113,10 @@ struct BlowersMaselData
*/
struct FalloffData : public ArrheniusData
{
FalloffData() : finalized(false) {}
FalloffData() : finalized(false), molar_density(NAN), state_mf_number(-1) {}

//! Update data container based on *bulk* phase state and *kin* kinetics
void update(const ThermoPhase& bulk, const Kinetics& kin);
std::pair<bool, bool> update(const ThermoPhase& bulk, const Kinetics& kin);
using ArrheniusData::update;

//! Finalize setup
Expand All @@ -107,8 +125,15 @@ struct FalloffData : public ArrheniusData
finalized = true;
}

void invalidateCache() {
ArrheniusData::invalidateCache();
molar_density = NAN;
}

bool finalized; //!< boolean indicating whether vectors are accessible
vector_fp conc_3b; //!< vector of effective third-body concentrations
double molar_density; //!< used to determine if updates are needed
int state_mf_number; //!< integer that is incremented when composition changes
};


Expand All @@ -119,7 +144,7 @@ struct FalloffData : public ArrheniusData
*/
struct PlogData
{
PlogData() : temperature(1.), logT(0.), recipT(1.), logP(0.) {}
PlogData() : temperature(1.), logT(0.), recipT(1.), pressure(NAN), logP(0.) {}

//! Update data container based on temperature *T* (raises exception)
void update(double T);
Expand All @@ -129,18 +154,25 @@ struct PlogData
temperature = T;
logT = std::log(T);
recipT = 1./T;
pressure = P;
logP = std::log(P);
}

//! Update data container based on *bulk* phase state
void update(const ThermoPhase& bulk, const Kinetics& kin);
std::pair<bool, bool> update(const ThermoPhase& bulk, const Kinetics& kin);

//! Update number of species and reactions; unused
void resize(size_t n_species, size_t n_reactions) {}

void invalidateCache() {
temperature = NAN;
pressure = NAN;
}

double temperature; //!< temperature
double logT; //!< logarithm of temperature
double recipT; //!< inverse of temperature
double pressure; //!< Pressure [Pa]
double logP; //!< logarithm of pressure
};

Expand All @@ -152,7 +184,7 @@ struct PlogData
*/
struct ChebyshevData
{
ChebyshevData() : temperature(1.), recipT(1.), log10P(0.) {}
ChebyshevData() : temperature(1.), recipT(1.), pressure(NAN), log10P(0.) {}

//! Update data container based on temperature *T* (raises exception)
void update(double T);
Expand All @@ -162,17 +194,24 @@ struct ChebyshevData
{
temperature = T;
recipT = 1./T;
pressure = P;
log10P = std::log10(P);
}

//! Update data container based on *bulk* phase state
void update(const ThermoPhase& bulk, const Kinetics& kin);
std::pair<bool, bool> update(const ThermoPhase& bulk, const Kinetics& kin);

//! Update number of species and reactions; unused
void resize(size_t n_species, size_t n_reactions) {}

void invalidateCache() {
temperature = NAN;
pressure = NAN;
}

double temperature; //!< temperature
double recipT; //!< inverse of temperature
double pressure; //!< Pressure [Pa]
double log10P; //!< base 10 logarithm of pressure
};

Expand All @@ -189,11 +228,15 @@ struct CustomFunc1Data
void update(double T, double P) { update(T); }

//! Update data container based on *bulk* phase state
void update(const ThermoPhase& bulk, const Kinetics& kin);
std::pair<bool, bool> update(const ThermoPhase& bulk, const Kinetics& kin);

//! Update number of species and reactions; unused
void resize(size_t n_species, size_t n_reactions) {}

void invalidateCache() {
temperature = NAN;
}

double temperature; //!< temperature
};

Expand Down
6 changes: 4 additions & 2 deletions src/kinetics/GasKinetics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ void GasKinetics::update_rates_T()
// KineticsAddSpecies - add_species_sequential)
// a work-around is to call GasKinetics::invalidateCache()
for (auto& rates : m_bulk_rates) {
rates->update(thermo(), *this);
rates->getRateConstants(m_rfn.data());
bool changed = rates->update(thermo(), *this);
if (changed) {
rates->getRateConstants(m_rfn.data());
}
}

// P-log reactions (legacy)
Expand Down
76 changes: 61 additions & 15 deletions src/kinetics/ReactionData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@
namespace Cantera
{

void ArrheniusData::update(const ThermoPhase& bulk, const Kinetics& kin)
std::pair<bool, bool> ArrheniusData::update(const ThermoPhase& bulk,
const Kinetics& kin)
{
update(bulk.temperature());
double T = bulk.temperature();
std::pair<bool, bool> changed{ false, T != temperature };
update(T);
return changed;
}

void BlowersMaselData::update(double T)
Expand All @@ -23,17 +27,48 @@ void BlowersMaselData::update(double T)
recipT = 1./T;
}

void BlowersMaselData::update(const ThermoPhase& bulk, const Kinetics& kin)
BlowersMaselData::BlowersMaselData()
: temperature(1.)
, logT(0.)
, recipT(1.)
, density(NAN)
, state_mf_number(-1)
, finalized(false)
{
update(bulk.temperature());
bulk.getPartialMolarEnthalpies(m_grt.data());
kin.getReactionDelta(m_grt.data(), dH.data());
}

void FalloffData::update(const ThermoPhase& bulk, const Kinetics& kin)
std::pair<bool, bool> BlowersMaselData::update(const ThermoPhase& bulk,
const Kinetics& kin)
{
update(bulk.temperature());
kin.getThirdBodyConcentrations(conc_3b.data());
double rho = bulk.density();
int mf = bulk.stateMFNumber();
double T = bulk.temperature();
std::pair<bool, bool> changed { false, T != temperature };
if (T != temperature || rho != density || mf != state_mf_number) {
density = rho;
state_mf_number = mf;
bulk.getPartialMolarEnthalpies(m_grt.data());
kin.getReactionDelta(m_grt.data(), dH.data());
changed.first = changed.second = true;
}
update(T);
return changed;
}

std::pair<bool, bool> FalloffData::update(const ThermoPhase& bulk, const Kinetics& kin)
{
double rho_m = bulk.molarDensity();
int mf = bulk.stateMFNumber();
double T = bulk.temperature();
std::pair<bool, bool> changed { false, T != temperature };
if (rho_m != molar_density || mf != state_mf_number) {
molar_density = rho_m;
state_mf_number = mf;
kin.getThirdBodyConcentrations(conc_3b.data());
changed.first = changed.second = true;
}
update(T);
return changed;
}

void PlogData::update(double T)
Expand All @@ -42,9 +77,13 @@ void PlogData::update(double T)
"Missing state information: reaction type requires pressure.");
}

void PlogData::update(const ThermoPhase& bulk, const Kinetics& kin)
std::pair<bool, bool> PlogData::update(const ThermoPhase& bulk, const Kinetics& kin)
{
update(bulk.temperature(), bulk.pressure());
double T = bulk.temperature();
double P = bulk.pressure();
std::pair<bool, bool> changed{ P != pressure, P != pressure || T != temperature };
update(T, P);
return changed;
}

void ChebyshevData::update(double T)
Expand All @@ -53,14 +92,21 @@ void ChebyshevData::update(double T)
"Missing state information: reaction type requires pressure.");
}

void ChebyshevData::update(const ThermoPhase& bulk, const Kinetics& kin)
std::pair<bool, bool> ChebyshevData::update(const ThermoPhase& bulk, const Kinetics& kin)
{
update(bulk.temperature(), bulk.pressure());
double T = bulk.temperature();
double P = bulk.pressure();
std::pair<bool, bool> changed{ P != pressure, P != pressure || T != temperature };
update(T, P);
return changed;
}

void CustomFunc1Data::update(const ThermoPhase& bulk, const Kinetics& kin)
std::pair<bool, bool> CustomFunc1Data::update(const ThermoPhase& bulk, const Kinetics& kin)
{
temperature = bulk.temperature();
double T = bulk.temperature();
std::pair<bool, bool> changed { false, T != temperature };
temperature = T;
return changed;
}

}
1 change: 1 addition & 0 deletions src/thermo/Phase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,7 @@ bool Phase::ready() const
}

void Phase::invalidateCache() {
m_stateNum++;
m_cache.clear();
}

Expand Down

0 comments on commit d386d85

Please sign in to comment.