diff --git a/include/cantera/base/ExtensionManager.h b/include/cantera/base/ExtensionManager.h index 6a03ba1e95..00ce4c7890 100644 --- a/include/cantera/base/ExtensionManager.h +++ b/include/cantera/base/ExtensionManager.h @@ -92,6 +92,8 @@ class ExtensionManager //! @param rateName The name of the reaction rate type //! @param wrapperName The name used for Solution wrappers to be used with this //! object, corresponding to a type registered with registerSolutionLinker(). + //! @param link Function that creates ReactionData wrapper and links it to the + //! provided C++ object static void registerReactionDataLinker(const string& rateName, const string& wrapperName, function link); diff --git a/include/cantera/base/SolutionArray.h b/include/cantera/base/SolutionArray.h index afb51e93bd..6a55d0ede8 100644 --- a/include/cantera/base/SolutionArray.h +++ b/include/cantera/base/SolutionArray.h @@ -285,6 +285,7 @@ class SolutionArray * * @param fname Name of container file (YAML or HDF) * @param id Identifier of SolutionArray within the container file + * @param sub Name of the subgroup holding actual data */ AnyMap restore(const string& fname, const string& id, const string& sub); diff --git a/include/cantera/clib/ct.h b/include/cantera/clib/ct.h index b4cb152ab8..066ce03ca2 100644 --- a/include/cantera/clib/ct.h +++ b/include/cantera/clib/ct.h @@ -122,6 +122,7 @@ extern "C" { CANTERA_CAPI int thermo_setState_Psat(int n, double p, double x); CANTERA_CAPI int thermo_setState_Tsat(int n, double t, double x); + //! @since Starting in Cantera 3.0, the "phasename" argument should be blank CANTERA_CAPI int kin_newFromFile(const char* filename, const char* phasename, int reactingPhase, int neighbor1, int neighbor2, int neighbor3, int neighbor4); diff --git a/include/cantera/kinetics/Arrhenius.h b/include/cantera/kinetics/Arrhenius.h index 92db739eb4..d598045a39 100644 --- a/include/cantera/kinetics/Arrhenius.h +++ b/include/cantera/kinetics/Arrhenius.h @@ -71,7 +71,11 @@ class ArrheniusBase : public ReactionRate //! Perform object setup based on AnyValue node information /*! - * @param rate AnyValue containing rate information + * Used to set parameters from a child of the reaction node, which may have + * different names for different rate parameterizations, such as falloff rates. + * + * @param rate Child of the reaction node containing Arrhenius rate parameters. + * For example, the `rate-coefficient` node for a standard Arrhenius reaction. * @param units Unit system * @param rate_units Unit definitions specific to rate information */ @@ -79,7 +83,8 @@ class ArrheniusBase : public ReactionRate const UnitSystem& units, const UnitStack& rate_units); - //! Return parameters + //! Get Arrhenius parameters used to populate the `rate-coefficient` or + //! equivalent field void getRateParameters(AnyMap& node) const; virtual void setParameters( diff --git a/include/cantera/kinetics/BulkKinetics.h b/include/cantera/kinetics/BulkKinetics.h index b7e0c1d63a..cb0e7656ae 100644 --- a/include/cantera/kinetics/BulkKinetics.h +++ b/include/cantera/kinetics/BulkKinetics.h @@ -16,47 +16,148 @@ namespace Cantera { -//! Partial specialization of Kinetics for chemistry in a single bulk phase +//! Specialization of Kinetics for chemistry in a single bulk phase +//! @ingroup kinetics class BulkKinetics : public Kinetics { public: - BulkKinetics() = default; + //! @name Constructors and General Information + //! @{ + BulkKinetics(); //! @deprecated To be removed after Cantera 3.0; code base only uses default. BulkKinetics(ThermoPhase* thermo); - virtual void resizeReactions(); + string kineticsType() const override { + return "bulk"; + } - virtual bool isReversible(size_t i); - - virtual void getDeltaGibbs(doublereal* deltaG); - virtual void getDeltaEnthalpy(doublereal* deltaH); - virtual void getDeltaEntropy(doublereal* deltaS); - - virtual void getDeltaSSGibbs(doublereal* deltaG); - virtual void getDeltaSSEnthalpy(doublereal* deltaH); - virtual void getDeltaSSEntropy(doublereal* deltaS); - - virtual void getRevRateConstants(double* krev, - bool doIrreversible = false); - - virtual bool addReaction(shared_ptr r, bool resize=true); - virtual void modifyReaction(size_t i, shared_ptr rNew); - - virtual void resizeSpecies(); - - virtual void setMultiplier(size_t i, double f); - virtual void invalidateCache(); + bool isReversible(size_t i) override; + //! @} + //! @name Reaction Mechanism Setup Routines + //! @{ + bool addReaction(shared_ptr r, bool resize=true) override; void addThirdBody(shared_ptr r); + void modifyReaction(size_t i, shared_ptr rNew) override; + void resizeSpecies() override; + void resizeReactions() override; + void setMultiplier(size_t i, double f) override; + void invalidateCache() override; + //! @} + + //! @name Reaction rate constants, rates of progress, and thermodynamic properties + //! @{ + void getFwdRateConstants(double* kfwd) override; + void getEquilibriumConstants(double* kc) override; + void getRevRateConstants(double* krev, bool doIrreversible=false) override; + + void getDeltaGibbs(double* deltaG) override; + void getDeltaEnthalpy(double* deltaH) override; + void getDeltaEntropy(double* deltaS) override; + + void getDeltaSSGibbs(double* deltaG) override; + void getDeltaSSEnthalpy(double* deltaH) override; + void getDeltaSSEntropy(double* deltaS) override; + //! @} + + //! @name Derivatives of rate constants and rates of progress + //! @{ + void getDerivativeSettings(AnyMap& settings) const override; + void setDerivativeSettings(const AnyMap& settings) override; + void getFwdRateConstants_ddT(double* dkfwd) override; + void getFwdRatesOfProgress_ddT(double* drop) override; + void getRevRatesOfProgress_ddT(double* drop) override; + void getNetRatesOfProgress_ddT(double* drop) override; + void getFwdRateConstants_ddP(double* dkfwd) override; + void getFwdRatesOfProgress_ddP(double* drop) override; + void getRevRatesOfProgress_ddP(double* drop) override; + void getNetRatesOfProgress_ddP(double* drop) override; + void getFwdRateConstants_ddC(double* dkfwd) override; + void getFwdRatesOfProgress_ddC(double* drop) override; + void getRevRatesOfProgress_ddC(double* drop) override; + void getNetRatesOfProgress_ddC(double* drop) override; + Eigen::SparseMatrix fwdRatesOfProgress_ddX() override; + Eigen::SparseMatrix revRatesOfProgress_ddX() override; + Eigen::SparseMatrix netRatesOfProgress_ddX() override; + Eigen::SparseMatrix fwdRatesOfProgress_ddCi() override; + Eigen::SparseMatrix revRatesOfProgress_ddCi() override; + Eigen::SparseMatrix netRatesOfProgress_ddCi() override; + //! @} + + //! @name Rate calculation intermediate methods + //! @{ + + void updateROP() override; + + void getThirdBodyConcentrations(double* concm) override; + const vector_fp& thirdBodyConcentrations() const override { + return m_concm; + } + + //! @} protected: + //! @name Internal service methods + //! + //! @note These methods are for internal use, and seek to avoid code duplication + //! while evaluating terms used for rate constants, rates of progress, and + //! their derivatives. + //! @{ + + //! Multiply rate with third-body collider concentrations + void processThirdBodies(double* rop); + + //! Multiply rate with inverse equilibrium constant + void applyEquilibriumConstants(double* rop); + + //! Multiply rate with scaled temperature derivatives of the inverse + //! equilibrium constant + /*! + * This (scaled) derivative is handled by a finite difference. + */ + void applyEquilibriumConstants_ddT(double* drkcn); + + //! Process temperature derivative + //! @param in rate expression used for the derivative calculation + //! @param drop pointer to output buffer + void process_ddT(const vector_fp& in, double* drop); + + //! Process pressure derivative + //! @param in rate expression used for the derivative calculation + //! @param drop pointer to output buffer + void process_ddP(const vector_fp& in, double* drop); + + //! Process concentration (molar density) derivative + //! @param stoich stoichiometry manager + //! @param in rate expression used for the derivative calculation + //! @param drop pointer to output buffer + //! @param mass_action boolean indicating whether law of mass action applies + void process_ddC(StoichManagerN& stoich, const vector_fp& in, + double* drop, bool mass_action=true); + + //! Process derivatives + //! @param stoich stoichiometry manager + //! @param in rate expression used for the derivative calculation + //! @param ddX true: w.r.t mole fractions false: w.r.t species concentrations + //! @return a sparse matrix of derivative contributions for each reaction of + //! dimensions nTotalReactions by nTotalSpecies + Eigen::SparseMatrix calculateCompositionDerivatives( + StoichManagerN& stoich, const vector_fp& in, bool ddX=true); + + //! Helper function ensuring that all rate derivatives can be calculated + //! @param name method name used for error output + //! @throw CanteraError if ideal gas assumption does not hold + void assertDerivativesValid(const string& name); + + //! @} + //! Vector of rate handlers - std::vector> m_bulk_rates; - std::map m_bulk_types; //!< Mapping of rate handlers + vector> m_bulk_rates; + map m_bulk_types; //!< Mapping of rate handlers - std::vector m_revindex; //!< Indices of reversible reactions - std::vector m_irrev; //!< Indices of irreversible reactions + vector m_revindex; //!< Indices of reversible reactions + vector m_irrev; //!< Indices of irreversible reactions //! Difference between the global reactants order and the global products //! order. Of type "double" to account for the fact that we can have real- @@ -74,10 +175,21 @@ class BulkKinetics : public Kinetics //! Physical concentrations, as calculated by ThermoPhase::getConcentrations vector_fp m_phys_conc; - vector_fp m_grt; + //! Derivative settings + bool m_jac_skip_third_bodies; + bool m_jac_skip_falloff; + double m_jac_rtol_delta; bool m_ROP_ok = false; - double m_temp = 0.0; + + //! Buffers for partial rop results with length nReactions() + vector_fp m_rbuf0; + vector_fp m_rbuf1; + vector_fp m_rbuf2; + vector_fp m_kf0; //!< Forward rate constants without perturbation + vector_fp m_sbuf0; + vector_fp m_state; + vector_fp m_grt; //!< Standard chemical potentials for each species }; } diff --git a/include/cantera/kinetics/GasKinetics.h b/include/cantera/kinetics/GasKinetics.h index cf58e13871..463955aae9 100644 --- a/include/cantera/kinetics/GasKinetics.h +++ b/include/cantera/kinetics/GasKinetics.h @@ -12,6 +12,11 @@ #include "BulkKinetics.h" #include "Reaction.h" +#ifndef CT_SKIP_DEPRECATION_WARNINGS +#pragma message("warning: GasKinetics.h and class GasKinetics are deprecated and will " \ + "be removed after Cantera 3.0. Replace with class BulkKinetics.") +#endif + namespace Cantera { @@ -20,158 +25,48 @@ namespace Cantera * implements standard mass-action reaction rate expressions for low-density * gases. * @ingroup kinetics + * @deprecated Replace with BulkKinetics. To be removed after Cantera 3.0. */ class GasKinetics : public BulkKinetics { public: - //! @name Constructors and General Information - //! @{ //! Constructor. - GasKinetics(); + GasKinetics() {} //! @deprecated To be removed after Cantera 3.0; code base only uses default. - GasKinetics(ThermoPhase* thermo); + GasKinetics(ThermoPhase* thermo) : GasKinetics() { + warn_deprecated("GasKinetics::GasKinetics(ThermoPhase*)", + "To be removed after Cantera 3.0. Use default constructor instead."); + addPhase(*thermo); + } virtual std::string kineticsType() const { return "gas"; } - virtual void getThirdBodyConcentrations(double* concm); - virtual const vector_fp& thirdBodyConcentrations() const { - return m_concm; - } - - //! @} - //! @name Reaction Rates Of Progress - //! @{ - - virtual void getEquilibriumConstants(doublereal* kc); - virtual void getFwdRateConstants(double* kfwd); - - //! @} - //! @name Reaction Mechanism Setup Routines - //! @{ - virtual bool addReaction(shared_ptr r, bool resize=true); - virtual void modifyReaction(size_t i, shared_ptr rNew); - virtual void invalidateCache(); - //! @} - - virtual void resizeReactions(); - void updateROP(); - - virtual void getDerivativeSettings(AnyMap& settings) const; - virtual void setDerivativeSettings(const AnyMap& settings); - virtual void getFwdRateConstants_ddT(double* dkfwd); - virtual void getFwdRatesOfProgress_ddT(double* drop); - virtual void getRevRatesOfProgress_ddT(double* drop); - virtual void getNetRatesOfProgress_ddT(double* drop); - virtual void getFwdRateConstants_ddP(double* dkfwd); - virtual void getFwdRatesOfProgress_ddP(double* drop); - virtual void getRevRatesOfProgress_ddP(double* drop); - virtual void getNetRatesOfProgress_ddP(double* drop); - virtual void getFwdRateConstants_ddC(double* dkfwd); - virtual void getFwdRatesOfProgress_ddC(double* drop); - virtual void getRevRatesOfProgress_ddC(double* drop); - virtual void getNetRatesOfProgress_ddC(double* drop); - virtual Eigen::SparseMatrix fwdRatesOfProgress_ddX(); - virtual Eigen::SparseMatrix revRatesOfProgress_ddX(); - virtual Eigen::SparseMatrix netRatesOfProgress_ddX(); - virtual Eigen::SparseMatrix fwdRatesOfProgress_ddCi(); - virtual Eigen::SparseMatrix revRatesOfProgress_ddCi(); - virtual Eigen::SparseMatrix netRatesOfProgress_ddCi(); - //! Update temperature-dependent portions of reaction rates and falloff //! functions. - virtual void update_rates_T(); + virtual void update_rates_T() { + warn_deprecated("GasKinetics::update_rates_T", + "Class GasKinetics has been merged into class BulkKinetics, and the " + "update_rates_T() method is now part of updateROP(). Class GasKinetics " + "will be removed after Cantera 3.0."); + updateROP(); + } //! Update properties that depend on concentrations. //! Currently the enhanced collision partner concentrations are updated //! here, as well as the pressure-dependent portion of P-log and Chebyshev //! reactions. - virtual void update_rates_C(); - -protected: - //! @name Internal service methods - //! - //! @note These methods are for internal use, and seek to avoid code duplication - //! while evaluating terms used for rate constants, rates of progress, and - //! their derivatives. - //! @{ - - //! Calculate rate coefficients - void processFwdRateCoefficients(double* ropf); - - //! Multiply rate with third-body collider concentrations - void processThirdBodies(double* rop); - - //! Multiply rate with inverse equilibrium constant - void applyEquilibriumConstants(double* rop); - - //! Multiply rate with scaled temperature derivatives of the inverse - //! equilibrium constant - /*! - * This (scaled) derivative is handled by a finite difference. - */ - void applyEquilibriumConstants_ddT(double* drkcn); - - //! Process temperature derivative - //! @param in rate expression used for the derivative calculation - //! @param drop pointer to output buffer - void process_ddT(const vector_fp& in, double* drop); - - //! Process pressure derivative - //! @param in rate expression used for the derivative calculation - //! @param drop pointer to output buffer - void process_ddP(const vector_fp& in, double* drop); - - //! Process concentration (molar density) derivative - //! @param stoich stoichiometry manager - //! @param in rate expression used for the derivative calculation - //! @param drop pointer to output buffer - //! @param mass_action boolean indicating whether law of mass action applies - void process_ddC(StoichManagerN& stoich, const vector_fp& in, - double* drop, bool mass_action=true); - - //! Process derivatives - //! @param stoich stoichiometry manager - //! @param in rate expression used for the derivative calculation - //! @param ddX true: w.r.t mole fractions false: w.r.t species concentrations - //! @return a sparse matrix of derivative contributions for each reaction of - //! dimensions nTotalReactions by nTotalSpecies - Eigen::SparseMatrix calculateCompositionDerivatives(StoichManagerN& stoich, - const vector_fp& in, bool ddX=true); - - //! Helper function ensuring that all rate derivatives can be calculated - //! @param name method name used for error output - //! @throw CanteraError if ideal gas assumption does not hold - void assertDerivativesValid(const std::string& name); - - //! @} - - //! @name Reaction rate data - //! @{ - - double m_logStandConc = 0.0; - - double m_pres = 0.0; //!< Last pressure at which rates were evaluated - - //! @} - - //! Buffers for partial rop results with length nReactions() - vector_fp m_rbuf0; - vector_fp m_rbuf1; - vector_fp m_rbuf2; - vector_fp m_sbuf0; - vector_fp m_state; - - //! Derivative settings - bool m_jac_skip_third_bodies; - bool m_jac_skip_falloff; - double m_jac_rtol_delta; + virtual void update_rates_C() { + warn_deprecated("GasKinetics::update_rates_C", + "Class GasKinetics has been merged into class BulkKinetics, and the " + "update_rates_T() method is now part of updateROP(). Class GasKinetics " + "will be removed after Cantera 3.0."); + updateROP(); + } - //! Update the equilibrium constants in molar units. - void updateKc(); }; } diff --git a/include/cantera/kinetics/InterfaceKinetics.h b/include/cantera/kinetics/InterfaceKinetics.h index 8f27cdbb11..50f1fd31e0 100644 --- a/include/cantera/kinetics/InterfaceKinetics.h +++ b/include/cantera/kinetics/InterfaceKinetics.h @@ -133,7 +133,8 @@ class InterfaceKinetics : public Kinetics //! Add a thermo phase to the kinetics manager object. /*! * This must be done before the function init() is called or - * before any reactions are input. + * before any reactions are input. The lowest dimensional phase, where reactions + * occur, must be added first. * * This function calls Kinetics::addPhase(). It also sets the following * fields: diff --git a/include/cantera/kinetics/Kinetics.h b/include/cantera/kinetics/Kinetics.h index 20dee5a479..43fe32acdc 100644 --- a/include/cantera/kinetics/Kinetics.h +++ b/include/cantera/kinetics/Kinetics.h @@ -216,6 +216,9 @@ class Kinetics * phase with the smallest spatial dimension (1, 2, or 3) among the list * of phases. If there is more than one, the index of the first one is * returned. For homogeneous mechanisms, the value 0 is returned. + * + * @deprecated Starting in Cantera 3.0, the reacting phase will always be the + * first phase in the InterfaceKinetics object. To be removed after Cantera 3.1. */ size_t reactionPhaseIndex() const { return m_rxnphase; @@ -594,7 +597,7 @@ class Kinetics //! Settings for derivative evaluation are set by keyword/value pairs using //! the methods getDerivativeSettings() and setDerivativeSettings(). //! - //! For GasKinetics, the following keyword/value pairs are supported: + //! For BulkKinetics, the following keyword/value pairs are supported: //! - `skip-third-bodies` (boolean) ... if `false` (default), third body //! concentrations are considered for the evaluation of jacobians //! - `skip-falloff` (boolean) ... if `false` (default), third-body effects @@ -604,14 +607,13 @@ class Kinetics //! //! For InterfaceKinetics, the following keyword/value pairs are supported: //! - `skip-coverage-dependence` (boolean) ... if `false` (default), rate constant - //! coverage dependence is not considered when evaluating derivatives. - //! - `skip-electrochemistry` (boolean) ... if `false` (default), electrical charge - //! is not considered in evaluating the derivatives and these reactions are - //! treated as normal surface reactions. + //! coverage dependence is not considered when evaluating derivatives. + //! - `skip-electrochemistry` (boolean) ... if `false` (default), electrical charge + //! is not considered in evaluating the derivatives and these reactions are + //! treated as normal surface reactions. //! - `rtol-delta` (double) ... relative tolerance used to perturb properties //! when calculating numerical derivatives. The default value is 1e-8. //! - //! //! @warning The calculation of derivatives is an experimental part of the //! %Cantera API and may be changed or removed without notice. //! @{ @@ -1345,7 +1347,9 @@ class Kinetics m_perturb[i] = f; } - virtual void invalidateCache() {}; + virtual void invalidateCache() { + m_cache.clear(); + }; //! @} //! Check for unmarked duplicate reactions and unmatched marked duplicates diff --git a/include/cantera/kinetics/KineticsFactory.h b/include/cantera/kinetics/KineticsFactory.h index 703b6d8ea2..e57366327d 100644 --- a/include/cantera/kinetics/KineticsFactory.h +++ b/include/cantera/kinetics/KineticsFactory.h @@ -65,7 +65,7 @@ shared_ptr newKinetics(const vector>& phases, const AnyMap& rootNode=AnyMap(), shared_ptr soln={}); -//! @copydoc newKinetics(const vector>&, const AnyMap&, const AnyMap&) +//! @see newKinetics(const vector>&, const AnyMap&, const AnyMap&, shared_ptr) //! @deprecated To be removed after Cantera 3.0; //! superseded by newKinetics() returning shared_ptr unique_ptr newKinetics(const std::vector& phases, @@ -82,10 +82,15 @@ unique_ptr newKinetics(const std::vector& phases, * the reactions occur. Searches the Cantera data for this file. * @param phase_name The name of the reacting phase in the input file (that is, the * name of the first phase in the `phases` vector) + * @deprecated The 'phase_name' argument is deprecated and will be removed after + * Cantera 3.0. + * @since Starting with Cantera 3.0, if the reacting phase is not the first item in the + * `phases` vector, a deprecation warning will be issued. In Cantera 3.1, this + * warning will become an error. */ shared_ptr newKinetics(const vector>& phases, const string& filename, - const string& phase_name); + const string& phase_name=""); //! @copydoc newKinetics(const vector>&, const string&, const string&) //! @deprecated To be removed after Cantera 3.0; diff --git a/include/cantera/transport/GasTransport.h b/include/cantera/transport/GasTransport.h index 324fc7cc1b..dafe00e4c4 100644 --- a/include/cantera/transport/GasTransport.h +++ b/include/cantera/transport/GasTransport.h @@ -362,10 +362,6 @@ class GasTransport : public Transport //! Current value of Boltzmann constant times the temperature (Joules) double m_kbt = 0.0; - //! current value of Boltzmann constant times the temperature. - //! (Joules) to 1/2 power - double m_sqrt_kbt = 0.0; - //! current value of temperature to 1/2 power double m_sqrt_t = 0.0; @@ -375,9 +371,6 @@ class GasTransport : public Transport //! Current value of temperature to 1/4 power double m_t14 = 0.0; - //! Current value of temperature to the 3/2 power - double m_t32 = 0.0; - //! Polynomial fits to the binary diffusivity of each species /*! * m_diffcoeff[ic] is vector of polynomial coefficients for species i diff --git a/include/cantera/transport/MultiTransport.h b/include/cantera/transport/MultiTransport.h index f6c7b97744..bb2bed0dfc 100644 --- a/include/cantera/transport/MultiTransport.h +++ b/include/cantera/transport/MultiTransport.h @@ -157,7 +157,6 @@ class MultiTransport : public GasTransport void correctBinDiffCoeffs(); //! Boolean indicating viscosity is up to date - bool m_abc_ok; bool m_l0000_ok; bool m_lmatrix_soln_ok; @@ -188,7 +187,6 @@ class MultiTransport : public GasTransport double pressure_ig(); virtual void solveLMatrixEquation(); - DenseMatrix incl; bool m_debug; }; } diff --git a/interfaces/cython/cantera/kinetics.pyx b/interfaces/cython/cantera/kinetics.pyx index fb1afe1c24..bb0f49b47b 100644 --- a/interfaces/cython/cantera/kinetics.pyx +++ b/interfaces/cython/cantera/kinetics.pyx @@ -111,7 +111,14 @@ cdef class Kinetics(_SolutionBase): return self.kinetics.nPhases() property reaction_phase_index: - """The index of the phase where the reactions occur.""" + """ + The index of the phase where the reactions occur. + + .. deprecated:: 3.0 + + After Cantera 3.0, the reacting phase is always the first phase associated + with the Kinetics object. This method will be removed after Cantera 3.1. + """ def __get__(self): return self.kinetics.reactionPhaseIndex() diff --git a/interfaces/cython/cantera/reaction.pyx b/interfaces/cython/cantera/reaction.pyx index e925a470cf..dc930ab70e 100644 --- a/interfaces/cython/cantera/reaction.pyx +++ b/interfaces/cython/cantera/reaction.pyx @@ -1776,12 +1776,6 @@ cdef class Arrhenius: return self.base.evalRate(np.log(T), 1/T) -cdef wrapArrhenius(CxxArrheniusRate* rate, Reaction reaction): - r = Arrhenius(init=False) - r.base = rate - r.reaction = reaction - return r - cdef copyArrhenius(CxxArrheniusRate* rate): r = Arrhenius(rate.preExponentialFactor(), rate.temperatureExponent(), rate.activationEnergy()) diff --git a/samples/cxx/flamespeed/flamespeed.cpp b/samples/cxx/flamespeed/flamespeed.cpp index 44a403d6ed..0b2b0b26bd 100644 --- a/samples/cxx/flamespeed/flamespeed.cpp +++ b/samples/cxx/flamespeed/flamespeed.cpp @@ -17,6 +17,7 @@ #include "cantera/onedim.h" #include "cantera/oneD/DomainFactory.h" #include "cantera/base/stringUtils.h" +#include using namespace Cantera; using fmt::print; diff --git a/samples/f77/demo_ftnlib.cpp b/samples/f77/demo_ftnlib.cpp index 0f4a2531cb..c3cbc91cf0 100644 --- a/samples/f77/demo_ftnlib.cpp +++ b/samples/f77/demo_ftnlib.cpp @@ -28,10 +28,8 @@ // at https://cantera.org/license.txt for license and copyright information. // add any other Cantera header files you need here -#include "cantera/thermo/IdealGasPhase.h" -#include "cantera/kinetics/GasKinetics.h" -#include "cantera/base/Solution.h" -#include "cantera/transport.h" +#include "cantera/core.h" +#include "cantera/kinetics/Reaction.h" #include diff --git a/src/fortran/cantera_funcs.f90 b/src/fortran/cantera_funcs.f90 index 9496e3fadc..5b0d1b897e 100644 --- a/src/fortran/cantera_funcs.f90 +++ b/src/fortran/cantera_funcs.f90 @@ -24,7 +24,7 @@ type(phase_t) function ctfunc_importPhase(src, id, loglevel) self = ctthermo_newFromFile(src) end if - call ctkin_newFromFile(self, src, id) + call ctkin_newFromFile(self, src, '') if (present(loglevel)) then self%tran_id = trans_newdefault(self%thermo_id, loglevel) @@ -52,7 +52,7 @@ type(interface_t) function ctfunc_importInterface(src, id, gas, bulk, loglevel) self%bulk = bulk end if self%gas = gas - call ctkin_newFromFile(self%surf, src, id, gas, bulk) + call ctkin_newFromFile(self%surf, src, '', gas, bulk) ctfunc_importInterface = self return diff --git a/src/kinetics/BulkKinetics.cpp b/src/kinetics/BulkKinetics.cpp index d56ebaefa5..5d5cab74ef 100644 --- a/src/kinetics/BulkKinetics.cpp +++ b/src/kinetics/BulkKinetics.cpp @@ -8,6 +8,10 @@ namespace Cantera { +BulkKinetics::BulkKinetics() { + setDerivativeSettings(AnyMap()); // use default settings +} + BulkKinetics::BulkKinetics(ThermoPhase* thermo) : BulkKinetics() { warn_deprecated("BulkKinetics::BulkKinetics(ThermoPhase*)", @@ -15,101 +19,10 @@ BulkKinetics::BulkKinetics(ThermoPhase* thermo) : BulkKinetics() addPhase(*thermo); } -void BulkKinetics::resizeReactions() -{ - Kinetics::resizeReactions(); - - m_multi_concm.resizeCoeffs(nTotalSpecies(), nReactions()); - for (auto& rates : m_bulk_rates) { - rates->resize(nTotalSpecies(), nReactions(), nPhases()); - // @todo ensure that ReactionData are updated; calling rates->update - // blocks correct behavior in GasKinetics::update_rates_T - // and running updateROP() is premature - } -} - bool BulkKinetics::isReversible(size_t i) { return std::find(m_revindex.begin(), m_revindex.end(), i) < m_revindex.end(); } -void BulkKinetics::getDeltaGibbs(doublereal* deltaG) -{ - // Get the chemical potentials of the species in the ideal gas solution. - thermo().getChemPotentials(m_grt.data()); - // Use the stoichiometric manager to find deltaG for each reaction. - getReactionDelta(m_grt.data(), deltaG); -} - -void BulkKinetics::getDeltaEnthalpy(doublereal* deltaH) -{ - // Get the partial molar enthalpy of all species in the ideal gas. - thermo().getPartialMolarEnthalpies(m_grt.data()); - // Use the stoichiometric manager to find deltaH for each reaction. - getReactionDelta(m_grt.data(), deltaH); -} - -void BulkKinetics::getDeltaEntropy(doublereal* deltaS) -{ - // Get the partial molar entropy of all species in the solid solution. - thermo().getPartialMolarEntropies(m_grt.data()); - // Use the stoichiometric manager to find deltaS for each reaction. - getReactionDelta(m_grt.data(), deltaS); -} - -void BulkKinetics::getDeltaSSGibbs(doublereal* deltaG) -{ - // Get the standard state chemical potentials of the species. This is the - // array of chemical potentials at unit activity. We define these here as - // the chemical potentials of the pure species at the temperature and - // pressure of the solution. - thermo().getStandardChemPotentials(m_grt.data()); - // Use the stoichiometric manager to find deltaG for each reaction. - getReactionDelta(m_grt.data(), deltaG); -} - -void BulkKinetics::getDeltaSSEnthalpy(doublereal* deltaH) -{ - // Get the standard state enthalpies of the species. - thermo().getEnthalpy_RT(m_grt.data()); - for (size_t k = 0; k < m_kk; k++) { - m_grt[k] *= thermo().RT(); - } - // Use the stoichiometric manager to find deltaH for each reaction. - getReactionDelta(m_grt.data(), deltaH); -} - -void BulkKinetics::getDeltaSSEntropy(doublereal* deltaS) -{ - // Get the standard state entropy of the species. We define these here as - // the entropies of the pure species at the temperature and pressure of the - // solution. - thermo().getEntropy_R(m_grt.data()); - for (size_t k = 0; k < m_kk; k++) { - m_grt[k] *= GasConstant; - } - // Use the stoichiometric manager to find deltaS for each reaction. - getReactionDelta(m_grt.data(), deltaS); -} - -void BulkKinetics::getRevRateConstants(double* krev, bool doIrreversible) -{ - // go get the forward rate constants. -> note, we don't really care about - // speed or redundancy in these informational routines. - getFwdRateConstants(krev); - - if (doIrreversible) { - getEquilibriumConstants(m_ropnet.data()); - for (size_t i = 0; i < nReactions(); i++) { - krev[i] /= m_ropnet[i]; - } - } else { - // m_rkcn[] is zero for irreversible reactions - for (size_t i = 0; i < nReactions(); i++) { - krev[i] *= m_rkcn[i]; - } - } -} - bool BulkKinetics::addReaction(shared_ptr r, bool resize) { bool added = Kinetics::addReaction(r, resize); @@ -134,7 +47,7 @@ bool BulkKinetics::addReaction(shared_ptr r, bool resize) } shared_ptr rate = r->rate(); - std::string rtype = rate->subType(); + string rtype = rate->subType(); if (rtype == "") { rtype = rate->type(); } @@ -160,14 +73,13 @@ bool BulkKinetics::addReaction(shared_ptr r, bool resize) } m_concm.push_back(NAN); - m_ready = resize; - + m_ready = resize; return true; } void BulkKinetics::addThirdBody(shared_ptr r) { - std::map efficiencies; + map efficiencies; for (const auto& [name, efficiency] : r->thirdBody()->efficiencies) { size_t k = kineticsSpeciesIndex(name); if (k != npos) { @@ -189,7 +101,7 @@ void BulkKinetics::modifyReaction(size_t i, shared_ptr rNew) Kinetics::modifyReaction(i, rNew); shared_ptr rate = rNew->rate(); - std::string rtype = rate->subType(); + string rtype = rate->subType(); if (rtype == "") { rtype = rate->type(); } @@ -204,9 +116,7 @@ void BulkKinetics::modifyReaction(size_t i, shared_ptr rNew) size_t index = m_bulk_types[rtype]; rate->setRateIndex(i); rate->setContext(*rNew, *this); - m_bulk_rates[index]->replace(i, *rate); - invalidateCache(); } @@ -221,7 +131,26 @@ void BulkKinetics::resizeSpecies() } } -void BulkKinetics::setMultiplier(size_t i, double f) { +void BulkKinetics::resizeReactions() +{ + Kinetics::resizeReactions(); + m_rbuf0.resize(nReactions()); + m_rbuf1.resize(nReactions()); + m_rbuf2.resize(nReactions()); + m_kf0.resize(nReactions()); + m_sbuf0.resize(nTotalSpecies()); + m_state.resize(thermo().stateSize()); + m_multi_concm.resizeCoeffs(nTotalSpecies(), nReactions()); + for (auto& rates : m_bulk_rates) { + rates->resize(nTotalSpecies(), nReactions(), nPhases()); + // @todo ensure that ReactionData are updated; calling rates->update + // blocks correct behavior in update_rates_T + // and running updateROP() is premature + } +} + +void BulkKinetics::setMultiplier(size_t i, double f) +{ Kinetics::setMultiplier(i, f); m_ROP_ok = false; } @@ -230,7 +159,549 @@ void BulkKinetics::invalidateCache() { Kinetics::invalidateCache(); m_ROP_ok = false; - m_temp += 0.13579; +} + +void BulkKinetics::getFwdRateConstants(double* kfwd) +{ + updateROP(); + copy(m_rfn.begin(), m_rfn.end(), kfwd); + if (legacy_rate_constants_used()) { + processThirdBodies(kfwd); + } +} + +void BulkKinetics::getEquilibriumConstants(double* kc) +{ + updateROP(); + + vector_fp& delta_gibbs0 = m_rbuf0; + fill(delta_gibbs0.begin(), delta_gibbs0.end(), 0.0); + + // compute Delta G^0 for all reactions + getReactionDelta(m_grt.data(), delta_gibbs0.data()); + + double rrt = 1.0 / thermo().RT(); + double logStandConc = log(thermo().standardConcentration()); + for (size_t i = 0; i < nReactions(); i++) { + kc[i] = exp(-delta_gibbs0[i] * rrt + m_dn[i] * logStandConc); + } +} + +void BulkKinetics::getRevRateConstants(double* krev, bool doIrreversible) +{ + // go get the forward rate constants. -> note, we don't really care about + // speed or redundancy in these informational routines. + getFwdRateConstants(krev); + + if (doIrreversible) { + getEquilibriumConstants(m_rbuf0.data()); + for (size_t i = 0; i < nReactions(); i++) { + krev[i] /= m_rbuf0[i]; + } + } else { + // m_rkcn[] is zero for irreversible reactions + for (size_t i = 0; i < nReactions(); i++) { + krev[i] *= m_rkcn[i]; + } + } +} + +void BulkKinetics::getDeltaGibbs(double* deltaG) +{ + // Get the chemical potentials for each species + thermo().getChemPotentials(m_sbuf0.data()); + // Use the stoichiometric manager to find deltaG for each reaction. + getReactionDelta(m_sbuf0.data(), deltaG); +} + +void BulkKinetics::getDeltaEnthalpy(double* deltaH) +{ + // Get the partial molar enthalpy for each species + thermo().getPartialMolarEnthalpies(m_sbuf0.data()); + // Use the stoichiometric manager to find deltaH for each reaction. + getReactionDelta(m_sbuf0.data(), deltaH); +} + +void BulkKinetics::getDeltaEntropy(double* deltaS) +{ + // Get the partial molar entropy for each species + thermo().getPartialMolarEntropies(m_sbuf0.data()); + // Use the stoichiometric manager to find deltaS for each reaction. + getReactionDelta(m_sbuf0.data(), deltaS); +} + +void BulkKinetics::getDeltaSSGibbs(double* deltaG) +{ + // Get the standard state chemical potentials of the species. This is the + // array of chemical potentials at unit activity. We define these here as + // the chemical potentials of the pure species at the temperature and + // pressure of the solution. + thermo().getStandardChemPotentials(m_sbuf0.data()); + // Use the stoichiometric manager to find deltaG for each reaction. + getReactionDelta(m_sbuf0.data(), deltaG); +} + +void BulkKinetics::getDeltaSSEnthalpy(double* deltaH) +{ + // Get the standard state enthalpies of the species. + thermo().getEnthalpy_RT(m_sbuf0.data()); + for (size_t k = 0; k < m_kk; k++) { + m_sbuf0[k] *= thermo().RT(); + } + // Use the stoichiometric manager to find deltaH for each reaction. + getReactionDelta(m_sbuf0.data(), deltaH); +} + +void BulkKinetics::getDeltaSSEntropy(double* deltaS) +{ + // Get the standard state entropy of the species. We define these here as + // the entropies of the pure species at the temperature and pressure of the + // solution. + thermo().getEntropy_R(m_sbuf0.data()); + for (size_t k = 0; k < m_kk; k++) { + m_sbuf0[k] *= GasConstant; + } + // Use the stoichiometric manager to find deltaS for each reaction. + getReactionDelta(m_sbuf0.data(), deltaS); +} + +void BulkKinetics::getDerivativeSettings(AnyMap& settings) const +{ + settings["skip-third-bodies"] = m_jac_skip_third_bodies; + settings["skip-falloff"] = m_jac_skip_falloff; + settings["rtol-delta"] = m_jac_rtol_delta; +} + +void BulkKinetics::setDerivativeSettings(const AnyMap& settings) +{ + bool force = settings.empty(); + if (force || settings.hasKey("skip-third-bodies")) { + m_jac_skip_third_bodies = settings.getBool("skip-third-bodies", false); + } + if (force || settings.hasKey("skip-falloff")) { + m_jac_skip_falloff = settings.getBool("skip-falloff", false); + } + if (force || settings.hasKey("rtol-delta")) { + m_jac_rtol_delta = settings.getDouble("rtol-delta", 1e-8); + } +} + +void BulkKinetics::getFwdRateConstants_ddT(double* dkfwd) +{ + assertDerivativesValid("BulkKinetics::getFwdRateConstants_ddT"); + updateROP(); + process_ddT(m_rfn, dkfwd); +} + +void BulkKinetics::getFwdRatesOfProgress_ddT(double* drop) +{ + assertDerivativesValid("BulkKinetics::getFwdRatesOfProgress_ddT"); + updateROP(); + process_ddT(m_ropf, drop); +} + +void BulkKinetics::getRevRatesOfProgress_ddT(double* drop) +{ + assertDerivativesValid("BulkKinetics::getRevRatesOfProgress_ddT"); + updateROP(); + process_ddT(m_ropr, drop); + Eigen::Map dRevRop(drop, nReactions()); + + // reverse rop times scaled inverse equilibrium constant derivatives + Eigen::Map dRevRop2(m_rbuf2.data(), nReactions()); + copy(m_ropr.begin(), m_ropr.end(), m_rbuf2.begin()); + applyEquilibriumConstants_ddT(dRevRop2.data()); + dRevRop += dRevRop2; +} + +void BulkKinetics::getNetRatesOfProgress_ddT(double* drop) +{ + assertDerivativesValid("BulkKinetics::getNetRatesOfProgress_ddT"); + updateROP(); + process_ddT(m_ropnet, drop); + Eigen::Map dNetRop(drop, nReactions()); + + // reverse rop times scaled inverse equilibrium constant derivatives + Eigen::Map dNetRop2(m_rbuf2.data(), nReactions()); + copy(m_ropr.begin(), m_ropr.end(), m_rbuf2.begin()); + applyEquilibriumConstants_ddT(dNetRop2.data()); + dNetRop -= dNetRop2; +} + +void BulkKinetics::getFwdRateConstants_ddP(double* dkfwd) +{ + assertDerivativesValid("BulkKinetics::getFwdRateConstants_ddP"); + updateROP(); + process_ddP(m_rfn, dkfwd); +} + +void BulkKinetics::getFwdRatesOfProgress_ddP(double* drop) +{ + assertDerivativesValid("BulkKinetics::getFwdRatesOfProgress_ddP"); + updateROP(); + process_ddP(m_ropf, drop); +} + +void BulkKinetics::getRevRatesOfProgress_ddP(double* drop) +{ + assertDerivativesValid("BulkKinetics::getRevRatesOfProgress_ddP"); + updateROP(); + process_ddP(m_ropr, drop); +} + +void BulkKinetics::getNetRatesOfProgress_ddP(double* drop) +{ + assertDerivativesValid("BulkKinetics::getNetRatesOfProgress_ddP"); + updateROP(); + process_ddP(m_ropnet, drop); +} + +void BulkKinetics::getFwdRateConstants_ddC(double* dkfwd) +{ + assertDerivativesValid("BulkKinetics::getFwdRateConstants_ddC"); + updateROP(); + process_ddC(m_reactantStoich, m_rfn, dkfwd, false); +} + +void BulkKinetics::getFwdRatesOfProgress_ddC(double* drop) +{ + assertDerivativesValid("BulkKinetics::getFwdRatesOfProgress_ddC"); + updateROP(); + process_ddC(m_reactantStoich, m_ropf, drop); +} + +void BulkKinetics::getRevRatesOfProgress_ddC(double* drop) +{ + assertDerivativesValid("BulkKinetics::getRevRatesOfProgress_ddC"); + updateROP(); + return process_ddC(m_revProductStoich, m_ropr, drop); +} + +void BulkKinetics::getNetRatesOfProgress_ddC(double* drop) +{ + assertDerivativesValid("BulkKinetics::getNetRatesOfProgress_ddC"); + updateROP(); + process_ddC(m_reactantStoich, m_ropf, drop); + Eigen::Map dNetRop(drop, nReactions()); + + process_ddC(m_revProductStoich, m_ropr, m_rbuf2.data()); + Eigen::Map dNetRop2(m_rbuf2.data(), nReactions()); + dNetRop -= dNetRop2; +} + +Eigen::SparseMatrix BulkKinetics::fwdRatesOfProgress_ddX() +{ + assertDerivativesValid("BulkKinetics::fwdRatesOfProgress_ddX"); + + // forward reaction rate coefficients + vector_fp& rop_rates = m_rbuf0; + getFwdRateConstants(rop_rates.data()); + return calculateCompositionDerivatives(m_reactantStoich, rop_rates); +} + +Eigen::SparseMatrix BulkKinetics::revRatesOfProgress_ddX() +{ + assertDerivativesValid("BulkKinetics::revRatesOfProgress_ddX"); + + // reverse reaction rate coefficients + vector_fp& rop_rates = m_rbuf0; + getFwdRateConstants(rop_rates.data()); + applyEquilibriumConstants(rop_rates.data()); + return calculateCompositionDerivatives(m_revProductStoich, rop_rates); +} + +Eigen::SparseMatrix BulkKinetics::netRatesOfProgress_ddX() +{ + assertDerivativesValid("BulkKinetics::netRatesOfProgress_ddX"); + + // forward reaction rate coefficients + vector_fp& rop_rates = m_rbuf0; + getFwdRateConstants(rop_rates.data()); + auto jac = calculateCompositionDerivatives(m_reactantStoich, rop_rates); + + // reverse reaction rate coefficients + applyEquilibriumConstants(rop_rates.data()); + return jac - calculateCompositionDerivatives(m_revProductStoich, rop_rates); +} + +Eigen::SparseMatrix BulkKinetics::fwdRatesOfProgress_ddCi() +{ + assertDerivativesValid("BulkKinetics::fwdRatesOfProgress_ddCi"); + + // forward reaction rate coefficients + vector_fp& rop_rates = m_rbuf0; + getFwdRateConstants(rop_rates.data()); + return calculateCompositionDerivatives(m_reactantStoich, rop_rates, false); +} + +Eigen::SparseMatrix BulkKinetics::revRatesOfProgress_ddCi() +{ + assertDerivativesValid("BulkKinetics::revRatesOfProgress_ddCi"); + + // reverse reaction rate coefficients + vector_fp& rop_rates = m_rbuf0; + getFwdRateConstants(rop_rates.data()); + applyEquilibriumConstants(rop_rates.data()); + return calculateCompositionDerivatives(m_revProductStoich, rop_rates, false); +} + +Eigen::SparseMatrix BulkKinetics::netRatesOfProgress_ddCi() +{ + assertDerivativesValid("BulkKinetics::netRatesOfProgress_ddCi"); + + // forward reaction rate coefficients + vector_fp& rop_rates = m_rbuf0; + getFwdRateConstants(rop_rates.data()); + auto jac = calculateCompositionDerivatives(m_reactantStoich, rop_rates, false); + + // reverse reaction rate coefficients + applyEquilibriumConstants(rop_rates.data()); + return jac - calculateCompositionDerivatives(m_revProductStoich, rop_rates, false); +} + +void BulkKinetics::updateROP() +{ + static const int cacheId = m_cache.getId(); + CachedScalar last = m_cache.getScalar(cacheId); + double T = thermo().temperature(); + double rho = thermo().density(); + int statenum = thermo().stateMFNumber(); + + if (last.state1 != T || last.state2 != rho) { + // Update properties that are independent of the composition + thermo().getStandardChemPotentials(m_grt.data()); + fill(m_delta_gibbs0.begin(), m_delta_gibbs0.end(), 0.0); + double logStandConc = log(thermo().standardConcentration()); + + // compute Delta G^0 for all reversible reactions + getRevReactionDelta(m_grt.data(), m_delta_gibbs0.data()); + + double rrt = 1.0 / thermo().RT(); + for (size_t i = 0; i < m_revindex.size(); i++) { + size_t irxn = m_revindex[i]; + m_rkcn[irxn] = std::min( + exp(m_delta_gibbs0[irxn] * rrt - m_dn[irxn] * logStandConc), BigNumber); + } + + for (size_t i = 0; i != m_irrev.size(); ++i) { + m_rkcn[ m_irrev[i] ] = 0.0; + } + } + + if (!last.validate(T, rho, statenum)) { + // Update terms dependent on species concentrations and temperature + thermo().getActivityConcentrations(m_act_conc.data()); + thermo().getConcentrations(m_phys_conc.data()); + double ctot = thermo().molarDensity(); + + // Third-body objects interacting with MultiRate evaluator + m_multi_concm.update(m_phys_conc, ctot, m_concm.data()); + + // loop over MultiRate evaluators for each reaction type + for (auto& rates : m_bulk_rates) { + bool changed = rates->update(thermo(), *this); + if (changed) { + rates->getRateConstants(m_kf0.data()); + } + } + m_ROP_ok = false; + } + + if (m_ROP_ok) { + // rates of progress are up-to-date only if both the thermodynamic state + // and m_perturb are unchanged + return; + } + + // Scale the forward rate coefficient by the perturbation factor + for (size_t i = 0; i < nReactions(); ++i) { + m_rfn[i] = m_kf0[i] * m_perturb[i]; + } + + copy(m_rfn.begin(), m_rfn.end(), m_ropf.data()); + processThirdBodies(m_ropf.data()); + copy(m_ropf.begin(), m_ropf.end(), m_ropr.begin()); + + // multiply ropf by concentration products + m_reactantStoich.multiply(m_act_conc.data(), m_ropf.data()); + + // for reversible reactions, multiply ropr by concentration products + applyEquilibriumConstants(m_ropr.data()); + m_revProductStoich.multiply(m_act_conc.data(), m_ropr.data()); + for (size_t j = 0; j != nReactions(); ++j) { + m_ropnet[j] = m_ropf[j] - m_ropr[j]; + } + + for (size_t i = 0; i < m_rfn.size(); i++) { + AssertFinite(m_rfn[i], "BulkKinetics::updateROP", + "m_rfn[{}] is not finite.", i); + AssertFinite(m_ropf[i], "BulkKinetics::updateROP", + "m_ropf[{}] is not finite.", i); + AssertFinite(m_ropr[i], "BulkKinetics::updateROP", + "m_ropr[{}] is not finite.", i); + } + m_ROP_ok = true; +} + +void BulkKinetics::getThirdBodyConcentrations(double* concm) +{ + updateROP(); + std::copy(m_concm.begin(), m_concm.end(), concm); +} + +void BulkKinetics::processThirdBodies(double* rop) +{ + // reactions involving third body + if (!m_concm.empty()) { + m_multi_concm.multiply(rop, m_concm.data()); + } +} + +void BulkKinetics::applyEquilibriumConstants(double* rop) +{ + // For reverse rates computed from thermochemistry, multiply the forward + // rate coefficients by the reciprocals of the equilibrium constants + for (size_t i = 0; i < nReactions(); ++i) { + rop[i] *= m_rkcn[i]; + } +} + +void BulkKinetics::applyEquilibriumConstants_ddT(double* drkcn) +{ + double T = thermo().temperature(); + double P = thermo().pressure(); + double rrt = 1. / thermo().RT(); + + vector_fp& grt = m_sbuf0; + vector_fp& delta_gibbs0 = m_rbuf1; + fill(delta_gibbs0.begin(), delta_gibbs0.end(), 0.0); + + // compute perturbed Delta G^0 for all reversible reactions + thermo().saveState(m_state); + thermo().setState_TP(T * (1. + m_jac_rtol_delta), P); + thermo().getStandardChemPotentials(grt.data()); + getRevReactionDelta(grt.data(), delta_gibbs0.data()); + + // apply scaling for derivative of inverse equilibrium constant + double Tinv = 1. / T; + double rrt_dTinv = rrt * Tinv / m_jac_rtol_delta; + double rrtt = rrt * Tinv; + for (size_t i = 0; i < m_revindex.size(); i++) { + size_t irxn = m_revindex[i]; + double factor = delta_gibbs0[irxn] - m_delta_gibbs0[irxn]; + factor *= rrt_dTinv; + factor += m_dn[irxn] * Tinv - m_delta_gibbs0[irxn] * rrtt; + drkcn[irxn] *= factor; + } + + for (size_t i = 0; i < m_irrev.size(); ++i) { + drkcn[m_irrev[i]] = 0.0; + } + + thermo().restoreState(m_state); +} + +void BulkKinetics::process_ddT(const vector_fp& in, double* drop) +{ + // apply temperature derivative + copy(in.begin(), in.end(), drop); + for (auto& rates : m_bulk_rates) { + rates->processRateConstants_ddT(drop, m_rfn.data(), m_jac_rtol_delta); + } +} + +void BulkKinetics::process_ddP(const vector_fp& in, double* drop) +{ + // apply pressure derivative + copy(in.begin(), in.end(), drop); + for (auto& rates : m_bulk_rates) { + rates->processRateConstants_ddP(drop, m_rfn.data(), m_jac_rtol_delta); + } +} + +void BulkKinetics::process_ddC(StoichManagerN& stoich, const vector_fp& in, + double* drop, bool mass_action) +{ + Eigen::Map out(drop, nReactions()); + out.setZero(); + double ctot_inv = 1. / thermo().molarDensity(); + + // derivatives due to concentrations in law of mass action + if (mass_action) { + stoich.scale(in.data(), out.data(), ctot_inv); + } + if (m_jac_skip_third_bodies || m_multi_concm.empty()) { + return; + } + + // derivatives due to third-body colliders in law of mass action + Eigen::Map outM(m_rbuf1.data(), nReactions()); + if (mass_action) { + outM.fill(0.); + m_multi_concm.scale(in.data(), outM.data(), ctot_inv); + out += outM; + } + + // derivatives due to reaction rates depending on third-body colliders + if (!m_jac_skip_falloff) { + m_multi_concm.scaleM(in.data(), outM.data(), m_concm.data(), ctot_inv); + for (auto& rates : m_bulk_rates) { + // processing step assigns zeros to entries not dependent on M + rates->processRateConstants_ddM( + outM.data(), m_rfn.data(), m_jac_rtol_delta); + } + out += outM; + } +} + +Eigen::SparseMatrix BulkKinetics::calculateCompositionDerivatives( + StoichManagerN& stoich, const vector_fp& in, bool ddX) +{ + Eigen::SparseMatrix out; + vector_fp& scaled = m_rbuf1; + vector_fp& outV = m_rbuf2; + + // convert from concentration to mole fraction output + copy(in.begin(), in.end(), scaled.begin()); + if (ddX) { + double ctot = thermo().molarDensity(); + for (size_t i = 0; i < nReactions(); ++i) { + scaled[i] *= ctot; + } + } + + // derivatives handled by StoichManagerN + copy(scaled.begin(), scaled.end(), outV.begin()); + processThirdBodies(outV.data()); + out = stoich.derivatives(m_act_conc.data(), outV.data()); + if (m_jac_skip_third_bodies || m_multi_concm.empty()) { + return out; + } + + // derivatives due to law of mass action + copy(scaled.begin(), scaled.end(), outV.begin()); + stoich.multiply(m_act_conc.data(), outV.data()); + + // derivatives due to reaction rates depending on third-body colliders + if (!m_jac_skip_falloff) { + for (auto& rates : m_bulk_rates) { + // processing step does not modify entries not dependent on M + rates->processRateConstants_ddM( + outV.data(), m_rfn.data(), m_jac_rtol_delta, false); + } + } + + // derivatives handled by ThirdBodyCalc + out += m_multi_concm.derivatives(outV.data()); + return out; +} + +void BulkKinetics::assertDerivativesValid(const string& name) +{ + if (!thermo().isIdeal()) { + throw NotImplementedError(name, + "Not supported for non-ideal ThermoPhase models."); + } } } diff --git a/src/kinetics/GasKinetics.cpp b/src/kinetics/GasKinetics.cpp deleted file mode 100644 index 3a278e92df..0000000000 --- a/src/kinetics/GasKinetics.cpp +++ /dev/null @@ -1,546 +0,0 @@ -/** - * @file GasKinetics.cpp Homogeneous kinetics in ideal gases - */ - -// This file is part of Cantera. See License.txt in the top-level directory or -// at https://cantera.org/license.txt for license and copyright information. - -#include "cantera/kinetics/GasKinetics.h" -#include "cantera/thermo/ThermoPhase.h" - -namespace Cantera -{ - -GasKinetics::GasKinetics() -{ - setDerivativeSettings(AnyMap()); // use default settings -} - -GasKinetics::GasKinetics(ThermoPhase* thermo) - : GasKinetics() -{ - warn_deprecated("GasKinetics::GasKinetics(ThermoPhase*)", - "To be removed after Cantera 3.0. Use default constructor instead."); - addPhase(*thermo); -} - -void GasKinetics::resizeReactions() -{ - m_rbuf0.resize(nReactions()); - m_rbuf1.resize(nReactions()); - m_rbuf2.resize(nReactions()); - m_sbuf0.resize(nTotalSpecies()); - m_state.resize(thermo().stateSize()); - - BulkKinetics::resizeReactions(); -} - -void GasKinetics::getThirdBodyConcentrations(double* concm) -{ - updateROP(); - std::copy(m_concm.begin(), m_concm.end(), concm); -} - -void GasKinetics::update_rates_T() -{ - double T = thermo().temperature(); - double P = thermo().pressure(); - m_logStandConc = log(thermo().standardConcentration()); - - if (T != m_temp) { - updateKc(); - m_ROP_ok = false; - } - - // loop over MultiRate evaluators for each reaction type - for (auto& rates : m_bulk_rates) { - bool changed = rates->update(thermo(), *this); - if (changed) { - rates->getRateConstants(m_rfn.data()); - m_ROP_ok = false; - } - } - m_pres = P; - m_temp = T; -} - -void GasKinetics::update_rates_C() -{ - thermo().getActivityConcentrations(m_act_conc.data()); - thermo().getConcentrations(m_phys_conc.data()); - doublereal ctot = thermo().molarDensity(); - - // Third-body objects interacting with MultiRate evaluator - m_multi_concm.update(m_phys_conc, ctot, m_concm.data()); - m_ROP_ok = false; -} - -void GasKinetics::updateKc() -{ - thermo().getStandardChemPotentials(m_grt.data()); - fill(m_delta_gibbs0.begin(), m_delta_gibbs0.end(), 0.0); - - // compute Delta G^0 for all reversible reactions - getRevReactionDelta(m_grt.data(), m_delta_gibbs0.data()); - - double rrt = 1.0 / thermo().RT(); - for (size_t i = 0; i < m_revindex.size(); i++) { - size_t irxn = m_revindex[i]; - m_rkcn[irxn] = std::min( - exp(m_delta_gibbs0[irxn] * rrt - m_dn[irxn] * m_logStandConc), - BigNumber); - } - - for (size_t i = 0; i != m_irrev.size(); ++i) { - m_rkcn[ m_irrev[i] ] = 0.0; - } -} - -void GasKinetics::processFwdRateCoefficients(double* ropf) -{ - update_rates_C(); - update_rates_T(); - - // copy rate coefficients into ropf - copy(m_rfn.begin(), m_rfn.end(), ropf); - - // Scale the forward rate coefficient by the perturbation factor - for (size_t i = 0; i < nReactions(); ++i) { - ropf[i] *= m_perturb[i]; - } -} - -void GasKinetics::processThirdBodies(double* rop) -{ - // reactions involving third body - if (!m_concm.empty()) { - m_multi_concm.multiply(rop, m_concm.data()); - } -} - -void GasKinetics::applyEquilibriumConstants(double* rop) -{ - // For reverse rates computed from thermochemistry, multiply the forward - // rate coefficients by the reciprocals of the equilibrium constants - for (size_t i = 0; i < nReactions(); ++i) { - rop[i] *= m_rkcn[i]; - } -} - -void GasKinetics::getEquilibriumConstants(doublereal* kc) -{ - update_rates_T(); // this step ensures that m_grt is updated - - vector_fp& delta_gibbs0 = m_rbuf0; - fill(delta_gibbs0.begin(), delta_gibbs0.end(), 0.0); - - // compute Delta G^0 for all reactions - getReactionDelta(m_grt.data(), delta_gibbs0.data()); - - double rrt = 1.0 / thermo().RT(); - for (size_t i = 0; i < nReactions(); i++) { - kc[i] = exp(-delta_gibbs0[i] * rrt + m_dn[i] * m_logStandConc); - } -} - -void GasKinetics::updateROP() -{ - processFwdRateCoefficients(m_ropf.data()); - processThirdBodies(m_ropf.data()); - copy(m_ropf.begin(), m_ropf.end(), m_ropr.begin()); - - // multiply ropf by concentration products - m_reactantStoich.multiply(m_act_conc.data(), m_ropf.data()); - - // for reversible reactions, multiply ropr by concentration products - applyEquilibriumConstants(m_ropr.data()); - m_revProductStoich.multiply(m_act_conc.data(), m_ropr.data()); - for (size_t j = 0; j != nReactions(); ++j) { - m_ropnet[j] = m_ropf[j] - m_ropr[j]; - } - - for (size_t i = 0; i < m_rfn.size(); i++) { - AssertFinite(m_rfn[i], "GasKinetics::updateROP", - "m_rfn[{}] is not finite.", i); - AssertFinite(m_ropf[i], "GasKinetics::updateROP", - "m_ropf[{}] is not finite.", i); - AssertFinite(m_ropr[i], "GasKinetics::updateROP", - "m_ropr[{}] is not finite.", i); - } - m_ROP_ok = true; -} - -void GasKinetics::getFwdRateConstants(double* kfwd) -{ - processFwdRateCoefficients(m_ropf.data()); - - if (legacy_rate_constants_used()) { - processThirdBodies(m_ropf.data()); - } - - // copy result - copy(m_ropf.begin(), m_ropf.end(), kfwd); -} - -void GasKinetics::getDerivativeSettings(AnyMap& settings) const -{ - settings["skip-third-bodies"] = m_jac_skip_third_bodies; - settings["skip-falloff"] = m_jac_skip_falloff; - settings["rtol-delta"] = m_jac_rtol_delta; -} - -void GasKinetics::setDerivativeSettings(const AnyMap& settings) -{ - bool force = settings.empty(); - if (force || settings.hasKey("skip-third-bodies")) { - m_jac_skip_third_bodies = settings.getBool("skip-third-bodies", false); - } - if (force || settings.hasKey("skip-falloff")) { - m_jac_skip_falloff = settings.getBool("skip-falloff", false); - } - if (force || settings.hasKey("rtol-delta")) { - m_jac_rtol_delta = settings.getDouble("rtol-delta", 1e-8); - } -} - -void GasKinetics::assertDerivativesValid(const std::string& name) -{ - if (!thermo().isIdeal()) { - throw NotImplementedError(name, - "Not supported for non-ideal ThermoPhase models."); - } -} - -void GasKinetics::applyEquilibriumConstants_ddT(double* drkcn) -{ - double T = thermo().temperature(); - double P = thermo().pressure(); - double rrt = 1. / thermo().RT(); - - vector_fp& grt = m_sbuf0; - vector_fp& delta_gibbs0 = m_rbuf1; - fill(delta_gibbs0.begin(), delta_gibbs0.end(), 0.0); - - // compute perturbed Delta G^0 for all reversible reactions - thermo().saveState(m_state); - thermo().setState_TP(T * (1. + m_jac_rtol_delta), P); - thermo().getStandardChemPotentials(grt.data()); - getRevReactionDelta(grt.data(), delta_gibbs0.data()); - - // apply scaling for derivative of inverse equilibrium constant - double Tinv = 1. / T; - double rrt_dTinv = rrt * Tinv / m_jac_rtol_delta; - double rrtt = rrt * Tinv; - for (size_t i = 0; i < m_revindex.size(); i++) { - size_t irxn = m_revindex[i]; - double factor = delta_gibbs0[irxn] - m_delta_gibbs0[irxn]; - factor *= rrt_dTinv; - factor += m_dn[irxn] * Tinv - m_delta_gibbs0[irxn] * rrtt; - drkcn[irxn] *= factor; - } - - for (size_t i = 0; i < m_irrev.size(); ++i) { - drkcn[m_irrev[i]] = 0.0; - } - - thermo().restoreState(m_state); -} - -void GasKinetics::process_ddT(const vector_fp& in, double* drop) -{ - // apply temperature derivative - copy(in.begin(), in.end(), drop); - for (auto& rates : m_bulk_rates) { - rates->processRateConstants_ddT(drop, m_rfn.data(), m_jac_rtol_delta); - } -} - -void GasKinetics::getFwdRateConstants_ddT(double* dkfwd) -{ - assertDerivativesValid("GasKinetics::getFwdRateConstants_ddT"); - updateROP(); - process_ddT(m_rfn, dkfwd); -} - -void GasKinetics::getFwdRatesOfProgress_ddT(double* drop) -{ - assertDerivativesValid("GasKinetics::getFwdRatesOfProgress_ddT"); - updateROP(); - process_ddT(m_ropf, drop); -} - -void GasKinetics::getRevRatesOfProgress_ddT(double* drop) -{ - assertDerivativesValid("GasKinetics::getRevRatesOfProgress_ddT"); - updateROP(); - process_ddT(m_ropr, drop); - Eigen::Map dRevRop(drop, nReactions()); - - // reverse rop times scaled inverse equilibrium constant derivatives - Eigen::Map dRevRop2(m_rbuf2.data(), nReactions()); - copy(m_ropr.begin(), m_ropr.end(), m_rbuf2.begin()); - applyEquilibriumConstants_ddT(dRevRop2.data()); - dRevRop += dRevRop2; -} - -void GasKinetics::getNetRatesOfProgress_ddT(double* drop) -{ - assertDerivativesValid("GasKinetics::getNetRatesOfProgress_ddT"); - updateROP(); - process_ddT(m_ropnet, drop); - Eigen::Map dNetRop(drop, nReactions()); - - // reverse rop times scaled inverse equilibrium constant derivatives - Eigen::Map dNetRop2(m_rbuf2.data(), nReactions()); - copy(m_ropr.begin(), m_ropr.end(), m_rbuf2.begin()); - applyEquilibriumConstants_ddT(dNetRop2.data()); - dNetRop -= dNetRop2; -} - -void GasKinetics::process_ddP(const vector_fp& in, double* drop) -{ - // apply pressure derivative - copy(in.begin(), in.end(), drop); - for (auto& rates : m_bulk_rates) { - rates->processRateConstants_ddP(drop, m_rfn.data(), m_jac_rtol_delta); - } -} - -void GasKinetics::getFwdRateConstants_ddP(double* dkfwd) -{ - assertDerivativesValid("GasKinetics::getFwdRateConstants_ddP"); - updateROP(); - process_ddP(m_rfn, dkfwd); -} - -void GasKinetics::getFwdRatesOfProgress_ddP(double* drop) -{ - assertDerivativesValid("GasKinetics::getFwdRatesOfProgress_ddP"); - updateROP(); - process_ddP(m_ropf, drop); -} - -void GasKinetics::getRevRatesOfProgress_ddP(double* drop) -{ - assertDerivativesValid("GasKinetics::getRevRatesOfProgress_ddP"); - updateROP(); - process_ddP(m_ropr, drop); -} - -void GasKinetics::getNetRatesOfProgress_ddP(double* drop) -{ - assertDerivativesValid("GasKinetics::getNetRatesOfProgress_ddP"); - updateROP(); - process_ddP(m_ropnet, drop); -} - -void GasKinetics::process_ddC( - StoichManagerN& stoich, const vector_fp& in, - double* drop, bool mass_action) -{ - Eigen::Map out(drop, nReactions()); - out.setZero(); - double ctot_inv = 1. / thermo().molarDensity(); - - // derivatives due to concentrations in law of mass action - if (mass_action) { - stoich.scale(in.data(), out.data(), ctot_inv); - } - if (m_jac_skip_third_bodies || m_multi_concm.empty()) { - return; - } - - // derivatives due to third-body colliders in law of mass action - Eigen::Map outM(m_rbuf1.data(), nReactions()); - if (mass_action) { - outM.fill(0.); - m_multi_concm.scale(in.data(), outM.data(), ctot_inv); - out += outM; - } - - // derivatives due to reaction rates depending on third-body colliders - if (!m_jac_skip_falloff) { - m_multi_concm.scaleM(in.data(), outM.data(), m_concm.data(), ctot_inv); - for (auto& rates : m_bulk_rates) { - // processing step assigns zeros to entries not dependent on M - rates->processRateConstants_ddM( - outM.data(), m_rfn.data(), m_jac_rtol_delta); - } - out += outM; - } -} - -void GasKinetics::getFwdRateConstants_ddC(double* dkfwd) -{ - assertDerivativesValid("GasKinetics::getFwdRateConstants_ddC"); - updateROP(); - process_ddC(m_reactantStoich, m_rfn, dkfwd, false); -} - -void GasKinetics::getFwdRatesOfProgress_ddC(double* drop) -{ - assertDerivativesValid("GasKinetics::getFwdRatesOfProgress_ddC"); - updateROP(); - process_ddC(m_reactantStoich, m_ropf, drop); -} - -void GasKinetics::getRevRatesOfProgress_ddC(double* drop) -{ - assertDerivativesValid("GasKinetics::getRevRatesOfProgress_ddC"); - updateROP(); - return process_ddC(m_revProductStoich, m_ropr, drop); -} - -void GasKinetics::getNetRatesOfProgress_ddC(double* drop) -{ - assertDerivativesValid("GasKinetics::getNetRatesOfProgress_ddC"); - updateROP(); - process_ddC(m_reactantStoich, m_ropf, drop); - Eigen::Map dNetRop(drop, nReactions()); - - process_ddC(m_revProductStoich, m_ropr, m_rbuf2.data()); - Eigen::Map dNetRop2(m_rbuf2.data(), nReactions()); - dNetRop -= dNetRop2; -} - -Eigen::SparseMatrix GasKinetics::calculateCompositionDerivatives( - StoichManagerN& stoich, const vector_fp& in, bool ddX) -{ - Eigen::SparseMatrix out; - vector_fp& scaled = m_rbuf1; - vector_fp& outV = m_rbuf2; - - // convert from concentration to mole fraction output - copy(in.begin(), in.end(), scaled.begin()); - if (ddX) { - double ctot = thermo().molarDensity(); - for (size_t i = 0; i < nReactions(); ++i) { - scaled[i] *= ctot; - } - } - - // derivatives handled by StoichManagerN - copy(scaled.begin(), scaled.end(), outV.begin()); - processThirdBodies(outV.data()); - out = stoich.derivatives(m_act_conc.data(), outV.data()); - if (m_jac_skip_third_bodies || m_multi_concm.empty()) { - return out; - } - - // derivatives due to law of mass action - copy(scaled.begin(), scaled.end(), outV.begin()); - stoich.multiply(m_act_conc.data(), outV.data()); - - // derivatives due to reaction rates depending on third-body colliders - if (!m_jac_skip_falloff) { - for (auto& rates : m_bulk_rates) { - // processing step does not modify entries not dependent on M - rates->processRateConstants_ddM( - outV.data(), m_rfn.data(), m_jac_rtol_delta, false); - } - } - - // derivatives handled by ThirdBodyCalc - out += m_multi_concm.derivatives(outV.data()); - - return out; -} - -Eigen::SparseMatrix GasKinetics::fwdRatesOfProgress_ddX() -{ - assertDerivativesValid("GasKinetics::fwdRatesOfProgress_ddX"); - - // forward reaction rate coefficients - vector_fp& rop_rates = m_rbuf0; - processFwdRateCoefficients(rop_rates.data()); - return calculateCompositionDerivatives(m_reactantStoich, rop_rates); -} - -Eigen::SparseMatrix GasKinetics::revRatesOfProgress_ddX() -{ - assertDerivativesValid("GasKinetics::revRatesOfProgress_ddX"); - - // reverse reaction rate coefficients - vector_fp& rop_rates = m_rbuf0; - processFwdRateCoefficients(rop_rates.data()); - applyEquilibriumConstants(rop_rates.data()); - return calculateCompositionDerivatives(m_revProductStoich, rop_rates); -} - -Eigen::SparseMatrix GasKinetics::netRatesOfProgress_ddX() -{ - assertDerivativesValid("GasKinetics::netRatesOfProgress_ddX"); - - // forward reaction rate coefficients - vector_fp& rop_rates = m_rbuf0; - processFwdRateCoefficients(rop_rates.data()); - Eigen::SparseMatrix jac = calculateCompositionDerivatives(m_reactantStoich, - rop_rates); - - // reverse reaction rate coefficients - applyEquilibriumConstants(rop_rates.data()); - return jac - calculateCompositionDerivatives(m_revProductStoich, rop_rates); -} - -Eigen::SparseMatrix GasKinetics::fwdRatesOfProgress_ddCi() -{ - assertDerivativesValid("GasKinetics::fwdRatesOfProgress_ddCi"); - - // forward reaction rate coefficients - vector_fp& rop_rates = m_rbuf0; - processFwdRateCoefficients(rop_rates.data()); - return calculateCompositionDerivatives(m_reactantStoich, rop_rates, false); -} - -Eigen::SparseMatrix GasKinetics::revRatesOfProgress_ddCi() -{ - assertDerivativesValid("GasKinetics::revRatesOfProgress_ddCi"); - - // reverse reaction rate coefficients - vector_fp& rop_rates = m_rbuf0; - processFwdRateCoefficients(rop_rates.data()); - applyEquilibriumConstants(rop_rates.data()); - return calculateCompositionDerivatives(m_revProductStoich, rop_rates, false); -} - -Eigen::SparseMatrix GasKinetics::netRatesOfProgress_ddCi() -{ - assertDerivativesValid("GasKinetics::netRatesOfProgress_ddCi"); - - // forward reaction rate coefficients - vector_fp& rop_rates = m_rbuf0; - processFwdRateCoefficients(rop_rates.data()); - Eigen::SparseMatrix jac = calculateCompositionDerivatives(m_reactantStoich, - rop_rates, false); - - // reverse reaction rate coefficients - applyEquilibriumConstants(rop_rates.data()); - return jac - calculateCompositionDerivatives(m_revProductStoich, rop_rates, false); -} - -bool GasKinetics::addReaction(shared_ptr r, bool resize) -{ - // operations common to all reaction types - bool added = BulkKinetics::addReaction(r, resize); - if (!added) { - return false; - } - return true; -} - -void GasKinetics::modifyReaction(size_t i, shared_ptr rNew) -{ - // operations common to all bulk reaction types - BulkKinetics::modifyReaction(i, rNew); - - // invalidate all cached data - invalidateCache(); -} - -void GasKinetics::invalidateCache() -{ - BulkKinetics::invalidateCache(); - m_pres += 0.13579; -} - -} diff --git a/src/kinetics/Kinetics.cpp b/src/kinetics/Kinetics.cpp index 9d4e9ddd96..abe2aea208 100644 --- a/src/kinetics/Kinetics.cpp +++ b/src/kinetics/Kinetics.cpp @@ -596,6 +596,11 @@ void Kinetics::addThermo(shared_ptr thermo) // the phase with lowest dimensionality is assumed to be the // phase/interface at which reactions take place if (thermo->nDim() <= m_mindim) { + if (!m_thermo.empty()) { + warn_deprecated("Kinetics::addThermo", "The reacting (lowest dimensional) " + "phase should be added first. This warning will become an error after " + "Cantera 3.0."); + } m_mindim = thermo->nDim(); m_rxnphase = nPhases(); } diff --git a/src/kinetics/KineticsFactory.cpp b/src/kinetics/KineticsFactory.cpp index 99aab763c1..9671b65220 100644 --- a/src/kinetics/KineticsFactory.cpp +++ b/src/kinetics/KineticsFactory.cpp @@ -6,7 +6,11 @@ // at https://cantera.org/license.txt for license and copyright information. #include "cantera/kinetics/KineticsFactory.h" -#include "cantera/kinetics/GasKinetics.h" +#include "cantera/kinetics/BulkKinetics.h" + +#define CT_SKIP_DEPRECATION_WARNINGS +#include "cantera/kinetics/GasKinetics.h" // @todo Remove after Cantera 3.0 + #include "cantera/kinetics/InterfaceKinetics.h" #include "cantera/kinetics/EdgeKinetics.h" #include "cantera/thermo/ThermoPhase.h" @@ -25,6 +29,8 @@ KineticsFactory::KineticsFactory() { reg("none", []() { return new Kinetics(); }); addDeprecatedAlias("none", "Kinetics"); addDeprecatedAlias("none", "None"); + reg("bulk", []() { return new BulkKinetics(); }); + // @todo After Cantera 3.0, "gas" should be an alias for "bulk" reg("gas", []() { return new GasKinetics(); }); addDeprecatedAlias("gas", "gaskinetics"); addDeprecatedAlias("gas", "Gas"); @@ -137,8 +143,14 @@ shared_ptr newKinetics(const vector>& phases, const string& filename, const string& phase_name) { + if (phase_name != "") { + warn_deprecated("newKinetics", "After Cantera 3.0, the 'phase_name' argument " + "will be removed and an exception will be thrown if the reacting phase is " + "not the first phase in the 'phases' vector."); + } + string reaction_phase = (phase_name.empty()) ? phases.at(0)->name() : phase_name; AnyMap root = AnyMap::fromYamlFile(filename); - AnyMap& phaseNode = root["phases"].getMapWhere("name", phase_name); + AnyMap& phaseNode = root["phases"].getMapWhere("name", reaction_phase); return newKinetics(phases, phaseNode, root); } diff --git a/src/transport/GasTransport.cpp b/src/transport/GasTransport.cpp index e9265a6031..f3d1a12279 100644 --- a/src/transport/GasTransport.cpp +++ b/src/transport/GasTransport.cpp @@ -40,11 +40,9 @@ void GasTransport::update_T() m_temp = T; m_kbt = Boltzmann * m_temp; - m_sqrt_kbt = sqrt(Boltzmann*m_temp); m_logt = log(m_temp); m_sqrt_t = sqrt(m_temp); m_t14 = sqrt(m_sqrt_t); - m_t32 = m_temp * m_sqrt_t; // compute powers of log(T) m_polytempvec[0] = 1.0; diff --git a/src/transport/MultiTransport.cpp b/src/transport/MultiTransport.cpp index b91d951714..f9e2584026 100644 --- a/src/transport/MultiTransport.cpp +++ b/src/transport/MultiTransport.cpp @@ -57,7 +57,6 @@ void MultiTransport::init(ThermoPhase* thermo, int mode, int log_level) m_cstar.resize(m_nsp, m_nsp); // set flags all false - m_abc_ok = false; m_l0000_ok = false; m_lmatrix_soln_ok = false; m_thermal_tlast = 0.0; @@ -399,7 +398,6 @@ void MultiTransport::update_T() GasTransport::update_T(); // temperature has changed, so polynomial fits will need to be // redone, and the L matrix reevaluated. - m_abc_ok = false; m_lmatrix_soln_ok = false; m_l0000_ok = false; } @@ -449,7 +447,6 @@ void MultiTransport::updateThermal_T() m_cstar(j,i) = m_cstar(i,j); } } - m_abc_ok = true; // evaluate the temperature-dependent rotational relaxation rate for (size_t k = 0; k < m_nsp; k++) { diff --git a/test/clib/test_clib.cpp b/test/clib/test_clib.cpp index ea7a4ceeee..a8382db1c5 100644 --- a/test/clib/test_clib.cpp +++ b/test/clib/test_clib.cpp @@ -175,7 +175,7 @@ TEST(ct, thermo) TEST(ct, kinetics) { int thermo = thermo_newFromFile("gri30.yaml", "gri30"); - int kin = kin_newFromFile("gri30.yaml", "gri30", thermo, -1, -1, -1, -1); + int kin = kin_newFromFile("gri30.yaml", "", thermo, -1, -1, -1, -1); ASSERT_GE(kin, 0); size_t nr = kin_nReactions(kin); diff --git a/test/clib/test_ctonedim.cpp b/test/clib/test_ctonedim.cpp index 4518a4b2be..124d2b2451 100644 --- a/test/clib/test_ctonedim.cpp +++ b/test/clib/test_ctonedim.cpp @@ -102,7 +102,7 @@ TEST(ctonedim, reacting_surface_from_parts) int gas = thermo_newFromFile("ptcombust.yaml", "gas"); int surf = thermo_newFromFile("ptcombust.yaml", "Pt_surf"); - int kin = kin_newFromFile("ptcombust.yaml", "Pt_surf", surf, gas, -1, -1, -1); + int kin = kin_newFromFile("ptcombust.yaml", "", surf, gas, -1, -1, -1); ASSERT_GE(kin, 0); int ret = reactingsurf_setkineticsmgr(index, kin); @@ -117,7 +117,7 @@ TEST(ctonedim, catcomb_stack) int trans = soln_transport(sol); int surf = thermo_newFromFile("ptcombust.yaml", "Pt_surf"); - int surf_kin = kin_newFromFile("ptcombust.yaml", "Pt_surf", surf, gas, -1, -1, -1); + int surf_kin = kin_newFromFile("ptcombust.yaml", "", surf, gas, -1, -1, -1); // inlet int inlet = inlet_new(); diff --git a/test/clib/test_ctreactor.cpp b/test/clib/test_ctreactor.cpp index 3b6688986e..3188c39e14 100644 --- a/test/clib/test_ctreactor.cpp +++ b/test/clib/test_ctreactor.cpp @@ -11,7 +11,7 @@ using namespace Cantera; TEST(ctreactor, reactor_objects) { int thermo = thermo_newFromFile("gri30.yaml", "gri30"); - int kin = kin_newFromFile("gri30.yaml", "gri30", thermo, -1, -1, -1, -1); + int kin = kin_newFromFile("gri30.yaml", "", thermo, -1, -1, -1, -1); int reactor = reactor_new("IdealGasReactor"); ASSERT_GT(reactor, 0); @@ -64,7 +64,7 @@ TEST(ctreactor, reactor_from_parts) string X = "CH4:1.0, O2:2.0, N2:7.52"; int thermo = thermo_newFromFile("gri30.yaml", "gri30"); - int kin = kin_newFromFile("gri30.yaml", "gri30", thermo, -1, -1, -1, -1); + int kin = kin_newFromFile("gri30.yaml", "", thermo, -1, -1, -1, -1); thermo_setMoleFractionsByName(thermo, X.c_str()); thermo_setTemperature(thermo, T); thermo_setPressure(thermo, P); diff --git a/test/general/test_serialization.cpp b/test/general/test_serialization.cpp index 32b91d2dd4..dd4a16fadb 100644 --- a/test/general/test_serialization.cpp +++ b/test/general/test_serialization.cpp @@ -281,7 +281,7 @@ TEST(YamlWriter, Interface) shared_ptr gas1(newThermo("ptcombust.yaml", "gas")); shared_ptr surf1(newThermo("ptcombust.yaml", "Pt_surf")); vector> phases1{surf1, gas1}; - shared_ptr kin1 = newKinetics(phases1, "ptcombust.yaml", "Pt_surf"); + shared_ptr kin1 = newKinetics(phases1, "ptcombust.yaml"); double T = 900; double P = OneAtm; @@ -301,7 +301,7 @@ TEST(YamlWriter, Interface) shared_ptr gas2(newThermo("generated-ptcombust.yaml", "gas")); shared_ptr surf2(newThermo("generated-ptcombust.yaml", "Pt_surf")); vector> phases2{surf2, gas2}; - shared_ptr kin2 = newKinetics(phases2, "generated-ptcombust.yaml", "Pt_surf"); + shared_ptr kin2 = newKinetics(phases2, "generated-ptcombust.yaml"); auto iface1 = std::dynamic_pointer_cast(surf1); auto iface2 = std::dynamic_pointer_cast(surf2); diff --git a/test/kinetics/kineticsFromScratch.cpp b/test/kinetics/kineticsFromScratch.cpp index 54d1eb9c89..c51d24c40e 100644 --- a/test/kinetics/kineticsFromScratch.cpp +++ b/test/kinetics/kineticsFromScratch.cpp @@ -4,7 +4,8 @@ #include "cantera/thermo/SurfPhase.h" #include "cantera/thermo/Species.h" #include "cantera/kinetics/KineticsFactory.h" -#include "cantera/kinetics/GasKinetics.h" +#include "cantera/kinetics/BulkKinetics.h" +#include "cantera/kinetics/Reaction.h" #include "cantera/kinetics/InterfaceKinetics.h" #include "cantera/kinetics/Arrhenius.h" #include "cantera/kinetics/ChebyshevRate.h" @@ -27,7 +28,7 @@ class KineticsFromScratch : public testing::Test { vector> th; th.push_back(pp_ref); - kin_ref = newKinetics(th, "../data/kineticsfromscratch.yaml", "ohmech"); + kin_ref = newKinetics(th, "../data/kineticsfromscratch.yaml"); kin.addThermo(pp); kin.init(); @@ -35,7 +36,7 @@ class KineticsFromScratch : public testing::Test shared_ptr pp; shared_ptr pp_ref; - GasKinetics kin; + BulkKinetics kin; shared_ptr kin_ref; //! iRef is the index of the corresponding reaction in the reference mech @@ -519,7 +520,7 @@ class InterfaceKineticsFromScratch : public testing::Test , surf(newThermo("sofc.yaml", "metal_surface")) , surf_ref(newThermo("sofc.yaml", "metal_surface")) { - kin_ref = newKinetics({surf_ref, gas_ref}, "sofc.yaml", "metal_surface"); + kin_ref = newKinetics({surf_ref, gas_ref}, "sofc.yaml"); kin.addThermo(surf); kin.addThermo(gas); } @@ -602,7 +603,7 @@ class KineticsAddSpecies : public testing::Test p = make_shared(); vector> th; th.push_back(pp_ref); - kin_ref = newKinetics(th, "../data/kineticsfromscratch.yaml", "ohmech"); + kin_ref = newKinetics(th, "../data/kineticsfromscratch.yaml"); kin.addThermo(p); std::vector> S = getSpecies( @@ -617,7 +618,7 @@ class KineticsAddSpecies : public testing::Test shared_ptr p; shared_ptr pp_ref; - GasKinetics kin; + BulkKinetics kin; shared_ptr kin_ref; std::vector> reactions; std::map> species; diff --git a/test/kinetics/kineticsFromYaml.cpp b/test/kinetics/kineticsFromYaml.cpp index 77ddad0d82..2e9a2bb874 100644 --- a/test/kinetics/kineticsFromYaml.cpp +++ b/test/kinetics/kineticsFromYaml.cpp @@ -4,7 +4,7 @@ #include "cantera/base/Interface.h" #include "cantera/kinetics/KineticsFactory.h" #include "cantera/kinetics/ReactionRateFactory.h" -#include "cantera/kinetics/GasKinetics.h" +#include "cantera/kinetics/Reaction.h" #include "cantera/kinetics/Arrhenius.h" #include "cantera/kinetics/ChebyshevRate.h" #include "cantera/kinetics/Custom.h" diff --git a/test/kinetics/rates.cpp b/test/kinetics/rates.cpp index f9e37ae6ae..1d88453ac2 100644 --- a/test/kinetics/rates.cpp +++ b/test/kinetics/rates.cpp @@ -3,7 +3,6 @@ #include "cantera/kinetics.h" #include "cantera/thermo/ThermoFactory.h" #include "cantera/thermo/IdealGasPhase.h" -#include "cantera/kinetics/GasKinetics.h" #include "cantera/base/Solution.h" #include "cantera/base/Interface.h" @@ -16,7 +15,7 @@ class FracCoeffTest : public testing::Test FracCoeffTest() : therm(newThermo("frac.yaml", "gas")) { - kin = newKinetics({therm}, "frac.yaml", "gas"); + kin = newKinetics({therm}, "frac.yaml"); therm->setState_TPX(2000, 4*OneAtm, "H2O:0.5, OH:.05, H:0.1, O2:0.15, H2:0.2"); kH2O = therm->speciesIndex("H2O"); diff --git a/test_problems/diamondSurf/runDiamond.cpp b/test_problems/diamondSurf/runDiamond.cpp index 0cf2a077d4..9b1c8fe430 100644 --- a/test_problems/diamondSurf/runDiamond.cpp +++ b/test_problems/diamondSurf/runDiamond.cpp @@ -28,8 +28,7 @@ int main(int argc, char** argv) size_t nsp_d100 = diamond100->nSpecies(); cout << "Number of species in diamond_100 = " << nsp_d100 << endl; - auto kin = newKinetics({gas, diamond, diamond100}, - "diamond.yaml", "diamond_100"); + auto kin = newKinetics({diamond100, gas, diamond}, "diamond.yaml"); InterfaceKinetics& ikin = dynamic_cast(*kin); size_t nr = kin->nReactions(); cout << "Number of reactions = " << nr << endl; diff --git a/test_problems/surfSolverTest/results2_blessed.txt b/test_problems/surfSolverTest/results2_blessed.txt index 0d95a2810a..40306c47c4 100644 --- a/test_problems/surfSolverTest/results2_blessed.txt +++ b/test_problems/surfSolverTest/results2_blessed.txt @@ -1,6 +1,6 @@ Gas Temperature = 1.4e+03 Gas Pressure = 1.01e+05 -Gas Phase: gas (0) +Gas Phase: gas (2) Name Conc MoleF SrcRate (kmol/m^3) (kmol/m^2/s) 0 H 8.69602e-05 0.00999001 -2.365619e-03 @@ -15,7 +15,7 @@ Gas Phase: gas (0) 9 O2 8.69602e-06 0.000999001 -9.060640e-07 Sum of gas mole fractions= 1 -Bulk Phase: soot (10) +Bulk Phase: soot (11) Bulk Temperature = 1.4e+03 Bulk Pressure = 1.01e+05 Name Conc MoleF SrcRate @@ -28,14 +28,14 @@ Density of bulk phase = 3.52e+03 kg / m^3 = 3.52 gm / cm^3 Sum of bulk mole fractions= 1 -Surface Phase: soot_interface (11) +Surface Phase: soot_interface (0) Surface Temperature = 1.4e+03 Surface Pressure = 1.01e+05 Name Coverage SrcRate 0 Csoot-* 0.0184677 0.000000e+00 1 Csoot-H 0.981532 0.000000e+00 Sum of coverages = 1 -Surface Phase: soot_interface (11) +Surface Phase: soot_interface (0) Surface Temperature = 1.4e+03 Surface Pressure = 1.01e+05 Name Coverage SrcRate diff --git a/test_problems/surfSolverTest/surfaceSolver2.cpp b/test_problems/surfSolverTest/surfaceSolver2.cpp index c7b47424e1..7c681324ac 100644 --- a/test_problems/surfSolverTest/surfaceSolver2.cpp +++ b/test_problems/surfSolverTest/surfaceSolver2.cpp @@ -26,14 +26,15 @@ void printGas(ostream& oooo, shared_ptr gasTP, double x[MSSIZE]; double C[MSSIZE]; oooo.precision(3); - string gasPhaseName = "gas"; + string gasPhaseName = "gas"; gasTP->getMoleFractions(x); gasTP->getConcentrations(C); double Temp = gasTP->temperature(); double p = gasTP->pressure(); oooo << "Gas Temperature = " << Temp << endl; oooo << "Gas Pressure = " << p << endl; - size_t kstart = iKin_ptr->kineticsSpeciesIndex(0, 0); + size_t nGas = iKin_ptr->phaseIndex(gasPhaseName); + size_t kstart = iKin_ptr->kineticsSpeciesIndex(0, nGas); oooo << "Gas Phase: " << gasPhaseName << " " << "(" << kstart << ")" << endl; oooo << " Name " @@ -43,7 +44,7 @@ void printGas(ostream& oooo, shared_ptr gasTP, double sum = 0.0; size_t nspGas = gasTP->nSpecies(); for (size_t k = 0; k < nspGas; k++) { - kstart = iKin_ptr->kineticsSpeciesIndex(k, 0); + kstart = iKin_ptr->kineticsSpeciesIndex(k, nGas); fmt::print(oooo, "{:4d} {:>24s} {:14g} {:14g} {:14e}\n", k, gasTP->speciesName(k), C[k], x[k], src[kstart]); sum += x[k]; @@ -63,7 +64,8 @@ void printBulk(ostream& oooo, shared_ptr bulkPhaseTP, string bulkParticlePhaseName = bulkPhaseTP->name(); bulkPhaseTP->getMoleFractions(x); bulkPhaseTP->getConcentrations(C); - size_t kstart = iKin_ptr->kineticsSpeciesIndex(0, 1); + size_t nBulk = iKin_ptr->phaseIndex(bulkParticlePhaseName); + size_t kstart = iKin_ptr->kineticsSpeciesIndex(0, nBulk); double dens = bulkPhaseTP->density(); oooo << "Bulk Phase: " << bulkParticlePhaseName << " " << "(" << kstart << ")" << endl; @@ -80,7 +82,7 @@ void printBulk(ostream& oooo, shared_ptr bulkPhaseTP, const vector_fp& molecW = bulkPhaseTP->molecularWeights(); size_t nspBulk = bulkPhaseTP->nSpecies(); for (size_t k = 0; k < nspBulk; k++) { - kstart = iKin_ptr->kineticsSpeciesIndex(k, 1); + kstart = iKin_ptr->kineticsSpeciesIndex(k, nBulk); fmt::print(oooo, "{:4d} {:>24s} {:14g} {:14g} {:14e}\n", k, bulkPhaseTP->speciesName(k), C[k], x[k], src[kstart]); sum += x[k]; @@ -105,7 +107,8 @@ void printSurf(ostream& oooo, shared_ptr surfPhaseTP, oooo.precision(3); string surfParticlePhaseName = surfPhaseTP->name(); surfPhaseTP->getMoleFractions(x); - size_t kstart = iKin_ptr->kineticsSpeciesIndex(0, 2); + size_t nSurf = iKin_ptr->phaseIndex(surfParticlePhaseName); + size_t kstart = iKin_ptr->kineticsSpeciesIndex(0, nSurf); oooo << "Surface Phase: " << surfParticlePhaseName << " (" << kstart << ")" << endl; double Temp = surfPhaseTP->temperature(); @@ -117,7 +120,7 @@ void printSurf(ostream& oooo, shared_ptr surfPhaseTP, double sum = 0.0; size_t nspSurf = surfPhaseTP->nSpecies(); for (size_t k = 0; k < nspSurf; k++) { - kstart = iKin_ptr->kineticsSpeciesIndex(0, 2); + kstart = iKin_ptr->kineticsSpeciesIndex(k, nSurf); double srcK = src[kstart]; if (fabs(srcK) < 1.0E-8) { srcK = 0.0; @@ -152,8 +155,7 @@ int main(int argc, char** argv) cout << "Number of species in surface phase, " << surfParticlePhaseName << " = " << nsp_d100 << endl; - auto kin = newKinetics({gasTP, bulkPhaseTP, surfPhaseTP}, - infile, surfParticlePhaseName); + auto kin = newKinetics({surfPhaseTP, gasTP, bulkPhaseTP}, infile); auto iKin_ptr = dynamic_pointer_cast(kin); size_t nr = iKin_ptr->nReactions(); cout << "Number of reactions = " << nr << endl; @@ -170,8 +172,7 @@ int main(int argc, char** argv) // create the second InterfaceKinetics object based on the // second surface phase. - auto kin2 = newKinetics({gasTP, bulkPhaseTP, surfPhaseTP2}, - infile, surfParticlePhaseName); + auto kin2 = newKinetics({surfPhaseTP2, gasTP, bulkPhaseTP}, infile); auto iKin2_ptr = dynamic_pointer_cast(kin2); nr = iKin_ptr->nReactions(); cout << "Number of reactions = " << nr << endl;