1 /** 2 * @file ReactionRate.h 3 * 4 * @warning This file is an experimental part of the %Cantera API and 5 * may be changed or removed without notice. 6 */ 7 8 // This file is part of Cantera. See License.txt in the top-level directory or 9 // at https://cantera.org/license.txt for license and copyright information. 10 11 #ifndef CT_REACTIONRATE_H 12 #define CT_REACTIONRATE_H 13 14 #include "cantera/base/AnyMap.h" 15 #include "cantera/base/Units.h" 16 #include "cantera/kinetics/RxnRates.h" 17 #include "cantera/kinetics/ReactionData.h" 18 #include "cantera/base/ctexceptions.h" 19 20 namespace Cantera 21 { 22 23 class Func1; 24 class MultiRateBase; 25 26 //! Abstract base class for reaction rate definitions 27 /** 28 * Because this class has no template parameters, derived objects can be 29 * accessed via `shared_ptr<ReactionRateBase>`. For performance reasons 30 * it is essential that derived classes use the keyword `final` to 31 * de-virtualize `virtual` methods. 32 * 33 * Methods defined for the abstract base class are not aware of specialized 34 * data handlers defined by the template class `ReactionRate<DataType>` 35 * and thus can be exposed to the API. 36 */ 37 class ReactionRateBase 38 { 39 public: ReactionRateBase()40 ReactionRateBase() : units(0.) {} ~ReactionRateBase()41 virtual ~ReactionRateBase() {} 42 43 public: 44 //! Identifier of reaction type 45 virtual std::string type() const = 0; 46 47 //! Create multi-rate evaluator 48 virtual unique_ptr<MultiRateBase> newMultiRate() const = 0; 49 50 //! Update reaction rate data based on temperature 51 //! @param T temperature [K] 52 virtual void update(double T) = 0; 53 54 //! Update reaction rate data based on temperature and pressure 55 //! @param T temperature [K] 56 //! @param P pressure [Pa] 57 //! @param concm third-body concentration (if applicable) 58 virtual void update(double T, double P, double concm=0.) = 0; 59 60 //! Update reaction rate data based on bulk phase 61 //! @param bulk object representing bulk phase 62 //! @param concm third-body concentration (if applicable) 63 virtual void update(const ThermoPhase& bulk, double concm=0.) = 0; 64 65 //! Evaluate reaction rate based on temperature 66 //! @param T temperature [K] 67 virtual double eval(double T) const = 0; 68 69 //! Evaluate reaction rate based on temperature and pressure 70 //! @param T temperature [K] 71 //! @param P pressure [Pa] 72 //! @param concm third-body concentration (if applicable) 73 virtual double eval(double T, double P, double concm=0.) const = 0; 74 75 //! Evaluate reaction rate based on bulk phase 76 //! @param bulk object representing bulk phase 77 //! @param concm third-body concentration (if applicable) 78 virtual double eval(const ThermoPhase& bulk, double concm=0.) const = 0; 79 80 //! Evaluate reaction rate derivative based on temperature 81 //! @param T temperature [K] 82 virtual double ddT(double T) const = 0; 83 84 //! Evaluate reaction rate derivative based on temperature and pressure 85 //! @param T temperature [K] 86 //! @param P pressure [Pa] 87 virtual double ddT(double T, double P) const = 0; 88 89 //! Evaluate reaction rate derivative based on bulk phase 90 //! @param bulk object representing bulk phase 91 //! @param concm third-body concentration (if applicable) 92 virtual double ddT(const ThermoPhase& bulk, double concm=0.) const = 0; 93 94 //! Validate the reaction rate expression 95 virtual void validate(const std::string& equation) = 0; 96 97 //! Return the parameters such that an identical Reaction could be reconstructed 98 //! using the newReaction() function. Behavior specific to derived classes is 99 //! handled by the getParameters() method. 100 //! @param rate_units units used for rate parameters 101 AnyMap parameters(const Units& rate_units) const; 102 103 //! Return parameters using original unit system 104 AnyMap parameters() const; 105 106 //! Set parameters 107 //! @param node AnyMap object containing reaction rate specification 108 //! @param rate_units Description of units used for rate parameters 109 virtual void setParameters(const AnyMap& node, const Units& rate_units); 110 111 //! Set rate units 112 //! @param rate_units Description of units used for rate parameters 113 virtual void setUnits(const Units& rate_units); 114 115 protected: 116 //! Get parameters 117 //! Store the parameters of a ReactionRate needed to reconstruct an identical 118 //! object. Does not include user-defined fields available in the #input map. getParameters(AnyMap & rateNode,const Units & rate_units)119 virtual void getParameters(AnyMap& rateNode, const Units& rate_units) const { 120 throw CanteraError("ReactionRate::getParameters", 121 "Not implemented by derived ReactionRate object."); 122 } 123 124 //! Input data used for specific models 125 AnyMap input; 126 127 //! The units of the rate constant. These are determined by the units of the 128 //! standard concentration of the reactant species' phases of the phase 129 //! where the reaction occurs. 130 Units units; 131 }; 132 133 134 //! Class template for reaction rate definitions with specialized DataType 135 /** 136 * This class template ensures that derived objects are aware of specialized 137 * data types, which are passed by MultiRateBase evaluators. 138 */ 139 template <class DataType> 140 class ReactionRate : public ReactionRateBase 141 { 142 public: 143 ReactionRate() = default; 144 145 //! Update information specific to reaction 146 //! @param shared_data data shared by all reactions of a given type 147 virtual void update(const DataType& shared_data, 148 double concm=0.) {} 149 update(double T)150 virtual void update(double T) override { 151 DataType data; 152 data.update(T); 153 update(data); 154 } 155 156 virtual void update(double T, double P, double concm=0.) override { 157 DataType data; 158 data.update(T, P); 159 update(data, concm); 160 } 161 162 virtual void update(const ThermoPhase& bulk, double concm=0.) override { 163 DataType data; 164 data.update(bulk); 165 update(data); 166 } 167 168 //! Evaluate reaction rate 169 //! @param shared_data data shared by all reactions of a given type 170 //! @param concm third-body concentration (if applicable) 171 virtual double eval(const DataType& shared_data, double concm=0.) const = 0; 172 eval(double T)173 virtual double eval(double T) const override { 174 DataType data; 175 data.update(T); 176 return eval(data); 177 } 178 179 virtual double eval(double T, double P, double concm=0.) const override { 180 DataType data; 181 data.update(T, P); 182 return eval(data, concm); 183 } 184 185 virtual double eval(const ThermoPhase& bulk, double concm=0.) const override { 186 DataType data; 187 data.update(bulk); 188 return eval(data, concm); 189 } 190 191 //! Evaluate derivative of reaction rate with respect to temperature 192 //! @param shared_data data shared by all reactions of a given type 193 virtual double ddT(const DataType& shared_data, double concm=0.) const { 194 throw CanteraError("ReactionRate::ddT", 195 "Not implemented by derived ReactionRate object."); 196 } 197 ddT(double T)198 virtual double ddT(double T) const override { 199 DataType data; 200 data.update(T); 201 return ddT(data); 202 } 203 ddT(double T,double P)204 virtual double ddT(double T, double P) const override { 205 DataType data; 206 data.update(T, P); 207 return ddT(data); 208 } 209 210 virtual double ddT(const ThermoPhase& bulk, double concm=0.) const override { 211 DataType data; 212 data.update(bulk); 213 return ddT(data, concm); 214 } 215 }; 216 217 218 //! The ArrheniusRate reaction rate type depends only on temperature 219 /** 220 * A reaction rate coefficient of the following form. 221 * 222 * \f[ 223 * k_f = A T^b \exp (-E/RT) 224 * \f] 225 * 226 * Note: ArrheniusRate acts as a wrapper for the Arrhenius class. 227 */ 228 class ArrheniusRate final : public ReactionRate<ArrheniusData>, public Arrhenius 229 { 230 public: 231 //! Default constructor. 232 ArrheniusRate(); 233 234 //! Constructor. 235 //! @param A pre-exponential. The unit system is 236 //! (kmol, m, s). The actual units depend on the reaction 237 //! order and the dimensionality (surface or bulk). 238 //! @param b Temperature exponent. Non-dimensional. 239 //! @param E Activation energy. J/kmol. 240 ArrheniusRate(double A, double b, double E); 241 242 //! Constructor using AnyMap content 243 //! @param node AnyMap containing rate information 244 //! @param rate_units unit definitions used for rate information 245 ArrheniusRate(const AnyMap& node, const Units& rate_units); 246 247 //! Constructor using AnyMap content 248 //! @param node AnyMap containing rate information 249 ArrheniusRate(const AnyMap& node); 250 251 //! Constructor based on Arrhenius object 252 //! @param arr Arrhenius object 253 //! @param allow_negative_A allow negative pre-exponential factor 254 //! (optional, default is false) 255 ArrheniusRate(const Arrhenius& arr, bool allow_negative_A=false); 256 257 virtual void setParameters(const AnyMap& node, const Units& rate_units) override; 258 virtual void getParameters(AnyMap& rateNode, 259 const Units& rate_units) const override; 260 type()261 virtual std::string type() const override { return "Arrhenius"; } 262 263 virtual unique_ptr<MultiRateBase> newMultiRate() const override; 264 265 //! Update information specific to reaction usesUpdate()266 static bool usesUpdate() { return false; } 267 268 virtual double eval(const ArrheniusData& shared_data, 269 double concm=0.) const override { 270 return updateRC(shared_data.m_logT, shared_data.m_recipT); 271 } 272 273 virtual double ddT(const ArrheniusData& shared_data, 274 double concm=0.) const override { 275 return updateRC(shared_data.m_logT, shared_data.m_recipT) * 276 (m_b + m_E * shared_data.m_recipT) * shared_data.m_recipT; 277 } 278 279 //! Return the activation energy [J/kmol] activationEnergy()280 double activationEnergy() const { 281 return m_E * GasConstant; 282 } 283 284 virtual void validate(const std::string& equation) override; 285 286 bool allow_negative_pre_exponential_factor; 287 }; 288 289 290 //! Pressure-dependent reaction rate expressed by logarithmically interpolating 291 //! between Arrhenius rate expressions at various pressures. 292 /*! 293 * Given two rate expressions at two specific pressures: 294 * 295 * * \f$ P_1: k_1(T) = A_1 T^{b_1} e^{-E_1 / RT} \f$ 296 * * \f$ P_2: k_2(T) = A_2 T^{b_2} e^{-E_2 / RT} \f$ 297 * 298 * The rate at an intermediate pressure \f$ P_1 < P < P_2 \f$ is computed as 299 * \f[ 300 * \log k(T,P) = \log k_1(T) + \bigl(\log k_2(T) - \log k_1(T)\bigr) 301 * \frac{\log P - \log P_1}{\log P_2 - \log P_1} 302 * \f] 303 * Multiple rate expressions may be given at the same pressure, in which case 304 * the rate used in the interpolation formula is the sum of all the rates given 305 * at that pressure. For pressures outside the given range, the rate expression 306 * at the nearest pressure is used. 307 */ 308 class PlogRate final : public ReactionRate<PlogData>, public Plog 309 { 310 public: PlogRate()311 PlogRate() {} 312 313 //! Constructor from Arrhenius rate expressions at a set of pressures 314 explicit PlogRate(const std::multimap<double, Arrhenius>& rates); 315 316 //! Constructor using AnyMap content 317 //! @param node AnyMap containing rate information 318 //! @param rate_units unit definitions used for rate information 319 PlogRate(const AnyMap& node, const Units& rate_units); 320 321 //! Constructor using AnyMap content 322 //! @param node AnyMap containing rate information 323 PlogRate(const AnyMap& node); 324 type()325 virtual std::string type() const override 326 { 327 return "pressure-dependent-Arrhenius"; 328 } 329 330 virtual unique_ptr<MultiRateBase> newMultiRate() const override; 331 332 virtual void setParameters(const AnyMap& node, const Units& rate_units) override; 333 virtual void getParameters(AnyMap& rateNode, 334 const Units& rate_units) const override; 335 336 //! Update information specific to reaction usesUpdate()337 static bool usesUpdate() { return true; } 338 339 virtual void update(const PlogData& shared_data, double concm=0.) override { 340 update_C(&shared_data.m_logP); 341 } 342 343 virtual double eval(const PlogData& shared_data, 344 double concm=0.) const override { 345 return updateRC(shared_data.m_logT, shared_data.m_recipT); 346 } 347 validate(const std::string & equation)348 virtual void validate(const std::string& equation) override { 349 Plog::validate(equation); 350 } 351 }; 352 353 354 //! Pressure-dependent rate expression where the rate coefficient is expressed 355 //! as a bivariate Chebyshev polynomial in temperature and pressure. 356 /*! 357 * The rate constant can be written as: 358 * \f[ 359 * \log k(T,P) = \sum_{t=1}^{N_T} \sum_{p=1}^{N_P} \alpha_{tp} 360 * \phi_t(\tilde{T}) \phi_p(\tilde{P}) 361 * \f] 362 * where \f$\alpha_{tp}\f$ are the constants defining the rate, \f$\phi_n(x)\f$ 363 * is the Chebyshev polynomial of the first kind of degree *n* evaluated at 364 * *x*, and 365 * \f[ 366 * \tilde{T} \equiv \frac{2T^{-1} - T_\mathrm{min}^{-1} - T_\mathrm{max}^{-1}} 367 * {T_\mathrm{max}^{-1} - T_\mathrm{min}^{-1}} 368 * \f] 369 * \f[ 370 * \tilde{P} \equiv \frac{2 \log P - \log P_\mathrm{min} - \log P_\mathrm{max}} 371 * {\log P_\mathrm{max} - \log P_\mathrm{min}} 372 * \f] 373 * are reduced temperature and reduced pressures which map the ranges 374 * \f$ (T_\mathrm{min}, T_\mathrm{max}) \f$ and 375 * \f$ (P_\mathrm{min}, P_\mathrm{max}) \f$ to (-1, 1). 376 * 377 * A Chebyshev rate expression is specified in terms of the coefficient matrix 378 * \f$ \alpha \f$ and the temperature and pressure ranges. Note that the 379 * Chebyshev polynomials are not defined outside the interval (-1,1), and 380 * therefore extrapolation of rates outside the range of temperatures and 381 * pressures for which they are defined is strongly discouraged. 382 * 383 * @TODO rename to ChebyshevRate when the legacy ChebyshevRate class is removed 384 * from RxnRates.h after Cantera 2.6. 385 */ 386 class ChebyshevRate3 final : public ReactionRate<ChebyshevData>, public Chebyshev 387 { 388 public: 389 //! Default constructor. ChebyshevRate3()390 ChebyshevRate3() {} 391 392 //! Constructor using coefficient array 393 /* 394 * @param Tmin Minimum temperature [K] 395 * @param Tmax Maximum temperature [K] 396 * @param Pmin Minimum pressure [Pa] 397 * @param Pmax Maximum pressure [Pa] 398 * @param coeffs Coefficient array dimensioned `nT` by `nP` where `nT` and 399 * `nP` are the number of temperatures and pressures used in the fit, 400 * respectively. 401 */ 402 ChebyshevRate3(double Tmin, double Tmax, double Pmin, double Pmax, 403 const Array2D& coeffs); 404 405 //! Constructor using AnyMap content 406 //! @param node AnyMap containing rate information 407 //! @param rate_units unit definitions used for rate information 408 ChebyshevRate3(const AnyMap& node, const Units& rate_units); 409 410 //! Constructor using AnyMap content 411 //! @param node AnyMap containing rate information 412 ChebyshevRate3(const AnyMap& node); 413 type()414 virtual std::string type() const override { return "Chebyshev"; } 415 416 virtual unique_ptr<MultiRateBase> newMultiRate() const override; 417 418 virtual void setParameters(const AnyMap& node, const Units& rate_units) override; 419 virtual void getParameters(AnyMap& rateNode, 420 const Units& rate_units) const override; 421 422 //! Update information specific to reaction usesUpdate()423 static bool usesUpdate() { return true; } 424 425 virtual void update(const ChebyshevData& shared_data, double concm=0.) override { 426 update_C(&shared_data.m_log10P); 427 } 428 429 virtual double eval(const ChebyshevData& shared_data, 430 double concm=0.) const override { 431 return updateRC(0., shared_data.m_recipT); 432 } 433 434 virtual void validate(const std::string& equation) override; 435 }; 436 437 438 //! Custom reaction rate depending only on temperature 439 /** 440 * The rate expression is provided by a `Func1` object taking a single 441 * argument (temperature) and does not use a formalized parameterization. 442 * 443 * @warning This class is an experimental part of the %Cantera API and 444 * may be changed or removed without notice. 445 */ 446 class CustomFunc1Rate final : public ReactionRate<CustomFunc1Data> 447 { 448 public: 449 CustomFunc1Rate(); 450 451 //! Constructor does nothing, as there is no formalized parameterization 452 //! @param node AnyMap object containing reaction rate specification 453 //! @param rate_units Description of units used for rate parameters CustomFunc1Rate(const AnyMap & rate,const Units & rate_units)454 CustomFunc1Rate(const AnyMap& rate, const Units& rate_units) {} 455 type()456 virtual std::string type() const override { return "custom-rate-function"; } 457 458 virtual unique_ptr<MultiRateBase> newMultiRate() const override; 459 setParameters(const AnyMap & node,const Units & rate_units)460 virtual void setParameters(const AnyMap& node, const Units& rate_units) override { 461 units = rate_units; 462 } 463 464 //! Update information specific to reaction usesUpdate()465 static bool usesUpdate() { return false; } 466 467 //! Set custom rate 468 /** 469 * The call to the Func1 object takes a single argument (temperature) and 470 * does not depend on parameters handled in C++. 471 */ 472 void setRateFunction(shared_ptr<Func1> f); 473 474 virtual double eval(const CustomFunc1Data& shared_data, 475 double concm=0.) const override; 476 validate(const std::string & equation)477 virtual void validate(const std::string& equation) override {} 478 479 protected: 480 shared_ptr<Func1> m_ratefunc; 481 }; 482 483 } 484 485 #endif 486