Cantera  4.0.0a1
Loading...
Searching...
No Matches
Falloff.cpp
Go to the documentation of this file.
1/**
2 * @file Falloff.cpp Definitions for member functions of classes derived from
3 * Falloff
4 */
5
6// This file is part of Cantera. See License.txt in the top-level directory or
7// at https://cantera.org/license.txt for license and copyright information.
8
11#include "cantera/base/global.h"
12#include "cantera/base/AnyMap.h"
13#include "cantera/kinetics/Falloff.h"
16
17namespace Cantera
18{
19
20FalloffData::FalloffData()
21{
22 conc_3b.resize(1, NAN);
23 m_conc_3b_buf.resize(1, NAN);
24}
25
26void FalloffData::update(double T)
27{
28 throw CanteraError("FalloffData::update",
29 "Missing state information: 'FalloffData' requires third-body concentration.");
30}
31
32void FalloffData::update(double T, double M)
33{
35 conc_3b[0] = M;
36}
37
38bool FalloffData::update(const ThermoPhase& phase, const Kinetics& kin)
39{
40 double rho_m = phase.molarDensity();
41 int mf = phase.stateMFNumber();
42 double T = phase.temperature();
43 bool changed = false;
44 if (T != temperature) {
46 changed = true;
47 }
48 if (rho_m != molar_density || mf != m_state_mf_number) {
49 molar_density = rho_m;
51 auto concm = kin.thirdBodyConcentrations();
52 conc_3b.assign(concm.begin(), concm.end());
53 changed = true;
54 }
55 return changed;
56}
57
59{
60 if (m_perturbed) {
61 throw CanteraError("FalloffData::perturbThirdBodies",
62 "Cannot apply another perturbation as state is already perturbed.");
63 }
65 for (auto& c3b : conc_3b) {
66 c3b *= 1. + deltaM;
67 }
68 m_perturbed = true;
69}
70
72{
74 // only restore if there is a valid buffered value
75 if (!m_perturbed) {
76 return;
77 }
79 m_perturbed = false;
80}
81
83 conc_3b.resize(kin.nReactions(), NAN);
84 m_conc_3b_buf.resize(kin.nReactions(), NAN);
85 ready = true;
86}
87
88FalloffRate::FalloffRate(const AnyMap& node, const UnitStack& rate_units)
89 : FalloffRate()
90{
91 setParameters(node, rate_units);
92}
93
95{
96 ArrheniusRate _low = low;
98 _low.check(m_input.getString("equation", ""));
100 throw CanteraError("FalloffRate::setLowRate",
101 "Detected inconsistent rate definitions;\nhigh and low "
102 "rate pre-exponential factors must have the same sign.");
103 }
104 m_lowRate = std::move(_low);
105}
106
108{
109 ArrheniusRate _high = high;
111 _high.check(m_input.getString("equation", ""));
113 throw CanteraError("FalloffRate::setHighRate",
114 "Detected inconsistent rate definitions;\nhigh and low "
115 "rate pre-exponential factors must have the same sign.");
116 }
117 m_highRate = std::move(_high);
118}
119
120void FalloffRate::setFalloffCoeffs(span<const double> c)
121{
122 if (c.size() != 0) {
123 throw InputFileError("FalloffRate::setFalloffCoeffs", m_input,
124 "Incorrect number of parameters. 0 required. Received {}.",
125 c.size());
126 }
127 m_valid = true;
128}
129
130void FalloffRate::setParameters(const AnyMap& node, const UnitStack& rate_units)
131{
132 ReactionRate::setParameters(node, rate_units);
133 if (node.empty()) {
134 return;
135 }
136
137 m_negativeA_ok = node.getBool("negative-A", false);
138 if (node["type"] == "chemically-activated") {
140 }
141
142 UnitStack low_rate_units = rate_units;
143 UnitStack high_rate_units = rate_units;
144 if (rate_units.size()) {
146 high_rate_units.join(1);
147 } else {
148 low_rate_units.join(-1);
149 }
150 }
151 if (node.hasKey("low-P-rate-constant")) {
153 node["low-P-rate-constant"], node.units(), low_rate_units);
155 }
156 if (node.hasKey("high-P-rate-constant")) {
158 node["high-P-rate-constant"], node.units(), high_rate_units);
160 }
161}
162
164{
165 if (m_negativeA_ok) {
166 node["negative-A"] = true;
167 }
168 AnyMap rNode;
170 if (!rNode.empty()) {
171 node["low-P-rate-constant"] = std::move(rNode);
172 }
173 rNode.clear();
175 if (!rNode.empty()) {
176 node["high-P-rate-constant"] = std::move(rNode);
177 }
178}
179
180void FalloffRate::check(const string& equation)
181{
182 m_lowRate.check(equation);
183 m_highRate.check(equation);
184 if (!m_lowRate.valid() || !m_highRate.valid()) {
185 // arrhenius rates are not initialized
186 return;
187 }
189 throw InputFileError("FalloffRate::check", m_input,
190 "Inconsistent rate definitions found in reaction '{}';\nhigh and low "
191 "rate pre-exponential factors must have the same sign.", equation);
192 }
193}
194
195void FalloffRate::validate(const string& equation, const Kinetics& kin)
196{
197 try {
198 m_lowRate.validate(equation, kin);
199 m_highRate.validate(equation, kin);
200 } catch (CanteraError& err) {
201 throw InputFileError("FalloffRate::validate", m_input, err.getMessage());
202 }
203}
204
205LindemannRate::LindemannRate(const AnyMap& node, const UnitStack& rate_units)
206 : LindemannRate()
207{
208 setParameters(node, rate_units);
209}
210
211LindemannRate::LindemannRate(const ArrheniusRate& low, const ArrheniusRate& high,
212 span<const double> c)
213 : LindemannRate()
214{
215 m_lowRate = low;
216 m_highRate = high;
218}
219
220TroeRate::TroeRate(const AnyMap& node, const UnitStack& rate_units)
221 : TroeRate()
222{
223 setParameters(node, rate_units);
224}
225
226TroeRate::TroeRate(const ArrheniusRate& low, const ArrheniusRate& high,
227 span<const double> c)
228 : TroeRate()
229{
230 m_lowRate = low;
231 m_highRate = high;
233}
234
235void TroeRate::setFalloffCoeffs(span<const double> c)
236{
237 if (c.size() != 3 && c.size() != 4) {
238 throw InputFileError("TroeRate::setFalloffCoeffs", m_input,
239 "Incorrect number of coefficients. 3 or 4 required. Received {}.",
240 c.size());
241 }
242 m_a = c[0];
243 if (std::abs(c[1]) < SmallNumber) {
244 m_rt3 = std::numeric_limits<double>::infinity();
245 } else {
246 m_rt3 = 1.0 / c[1];
247 }
248
249 if (std::abs(c[2]) < SmallNumber) {
250 m_rt1 = std::numeric_limits<double>::infinity();
251 } else {
252 m_rt1 = 1.0 / c[2];
253 }
254
255 if (c.size() == 4) {
256 if (std::abs(c[3]) < SmallNumber) {
257 warn_user("TroeRate::setFalloffCoeffs",
258 "Unexpected parameter value T2=0. Omitting exp(T2/T) term from "
259 "falloff expression. To suppress this warning, remove value "
260 "for T2 from the input file. In the unlikely case that the "
261 "exp(T2/T) term should be included with T2 effectively equal "
262 "to 0, set T2 to a sufficiently small value "
263 "(for example, T2 < 1e-16).");
264 }
265 m_t2 = c[3];
266 } else {
267 m_t2 = 0.;
268 }
269 m_valid = true;
270}
271
272void TroeRate::getFalloffCoeffs(span<double> c) const
273{
274 checkArraySize("TroeRate::getFalloffCoeffs", c.size(), nParameters());
275 c[0] = m_a;
276 c[1] = 1.0 / m_rt3;
277 c[2] = 1.0 / m_rt1;
278 c[3] = m_t2;
279}
280
281void TroeRate::updateTemp(double T, span<double> work) const
282{
283 double Fcent = (1.0 - m_a) * exp(-T*m_rt3) + m_a * exp(-T*m_rt1);
284 if (m_t2) {
285 Fcent += exp(- m_t2 / T);
286 }
287 work[0] = log10(std::max(Fcent, SmallNumber));
288}
289
290double TroeRate::F(double pr, span<const double> work) const
291{
292 double lpr = log10(std::max(pr,SmallNumber));
293 double cc = -0.4 - 0.67 * work[0];
294 double nn = 0.75 - 1.27 * work[0];
295 double f1 = (lpr + cc)/ (nn - 0.14 * (lpr + cc));
296 double lgf = work[0] / (1.0 + f1 * f1);
297 return pow(10.0, lgf);
298}
299
300void TroeRate::setParameters(const AnyMap& node, const UnitStack& rate_units)
301{
302 if (node.empty()) {
303 return;
304 }
305
306 FalloffRate::setParameters(node, rate_units);
307 auto& f = node["Troe"].as<AnyMap>();
308 if (f.empty()) {
309 return;
310 }
311 vector<double> params{
312 f["A"].asDouble(),
313 f["T3"].asDouble(),
314 f["T1"].asDouble()
315 };
316 if (f.hasKey("T2")) {
317 params.push_back(f["T2"].asDouble());
318 }
319 setFalloffCoeffs(params);
320}
321
323{
325
326 AnyMap params;
327 if (valid()) {
328 params["A"] = m_a;
329 params["T3"].setQuantity(1.0 / m_rt3, "K");
330 params["T1"].setQuantity(1.0 / m_rt1, "K");
331 if (std::abs(m_t2) > SmallNumber) {
332 params["T2"].setQuantity(m_t2, "K");
333 }
334 }
335 params.setFlowStyle();
336 node["Troe"] = std::move(params);
337}
338
339SriRate::SriRate(const AnyMap& node, const UnitStack& rate_units)
340 : SriRate()
341{
342 setParameters(node, rate_units);
343}
344
345void SriRate::setFalloffCoeffs(span<const double> c)
346{
347 if (c.size() != 3 && c.size() != 5) {
348 throw InputFileError("SriRate::setFalloffCoeffs", m_input,
349 "Incorrect number of coefficients. 3 or 5 required. Received {}.",
350 c.size());
351 }
352
353 if (c[2] < 0.0) {
354 throw InputFileError("SriRate::setFalloffCoeffs()", m_input,
355 "m_c parameter is less than zero: {}", c[2]);
356 }
357 m_a = c[0];
358 m_b = c[1];
359 m_c = c[2];
360
361 if (c.size() == 5) {
362 if (c[3] < 0.0) {
363 throw InputFileError("SriRate::setFalloffCoeffs()", m_input,
364 "m_d parameter is less than zero: {}", c[3]);
365 }
366 m_d = c[3];
367 m_e = c[4];
368 } else {
369 m_d = 1.0;
370 m_e = 0.0;
371 }
372 m_valid = true;
373}
374
375void SriRate::getFalloffCoeffs(span<double> c) const
376{
377 checkArraySize("SriRate::getFalloffCoeffs", c.size(), nParameters());
378 c[0] = m_a;
379 c[1] = m_b;
380 c[2] = m_c;
381 c[3] = m_d;
382 c[4] = m_e;
383}
384
385void SriRate::updateTemp(double T, span<double> work) const
386{
387 work[0] = m_a * exp(- m_b / T);
388 if (m_c != 0.0) {
389 work[0] += exp(- T/m_c);
390 }
391 work[1] = m_d * pow(T,m_e);
392}
393
394double SriRate::F(double pr, span<const double> work) const
395{
396 double lpr = log10(std::max(pr,SmallNumber));
397 double xx = 1.0/(1.0 + lpr*lpr);
398 return pow(work[0], xx) * work[1];
399}
400
401void SriRate::setParameters(const AnyMap& node, const UnitStack& rate_units)
402{
403 if (node.empty()) {
404 return;
405 }
406
407 FalloffRate::setParameters(node, rate_units);
408 auto& f = node["SRI"].as<AnyMap>();
409 if (f.empty()) {
410 return;
411 }
412 vector<double> params{
413 f["A"].asDouble(),
414 f["B"].asDouble(),
415 f["C"].asDouble()
416 };
417 if (f.hasKey("D")) {
418 params.push_back(f["D"].asDouble());
419 }
420 if (f.hasKey("E")) {
421 params.push_back(f["E"].asDouble());
422 }
423 setFalloffCoeffs(params);
424}
425
427{
429
430 AnyMap params;
431 if (valid()) {
432 params["A"] = m_a;
433 params["B"].setQuantity(m_b, "K");
434 params["C"].setQuantity(m_c, "K");
435 if (m_d != 1.0 || m_e != 0.0) {
436 params["D"] = m_d;
437 params["E"] = m_e;
438 }
439 }
440 params.setFlowStyle();
441 node["SRI"] = std::move(params);
442}
443
444TsangRate::TsangRate(const AnyMap& node, const UnitStack& rate_units)
445 : TsangRate()
446{
447 setParameters(node, rate_units);
448}
449
450void TsangRate::setFalloffCoeffs(span<const double> c)
451{
452 if (c.size() != 1 && c.size() != 2) {
453 throw InputFileError("TsangRate::init", m_input,
454 "Incorrect number of coefficients. 1 or 2 required. Received {}.",
455 c.size());
456 }
457 m_a = c[0];
458
459 if (c.size() == 2) {
460 m_b = c[1];
461 }
462 else {
463 m_b = 0.0;
464 }
465 m_valid = true;
466}
467
468void TsangRate::getFalloffCoeffs(span<double> c) const
469{
470 checkArraySize("TsangRate::getFalloffCoeffs", c.size(), nParameters());
471 c[0] = m_a;
472 c[1] = m_b;
473}
474
475void TsangRate::updateTemp(double T, span<double> work) const
476{
477 double Fcent = m_a + (m_b * T);
478 work[0] = log10(std::max(Fcent, SmallNumber));
479}
480
481double TsangRate::F(double pr, span<const double> work) const
482{ //identical to TroeRate::F
483 double lpr = log10(std::max(pr,SmallNumber));
484 double cc = -0.4 - 0.67 * work[0];
485 double nn = 0.75 - 1.27 * work[0];
486 double f1 = (lpr + cc)/ (nn - 0.14 * (lpr + cc));
487 double lgf = work[0] / (1.0 + f1 * f1);
488 return pow(10.0, lgf);
489}
490
491void TsangRate::setParameters(const AnyMap& node, const UnitStack& rate_units)
492{
493 if (node.empty()) {
494 return;
495 }
496
497 FalloffRate::setParameters(node, rate_units);
498 auto& f = node["Tsang"].as<AnyMap>();
499 if (f.empty()) {
500 return;
501 }
502 vector<double> params{
503 f["A"].asDouble(),
504 f["B"].asDouble()
505 };
506 setFalloffCoeffs(params);
507}
508
510{
512
513 AnyMap params;
514 if (!valid()) {
515 // pass
516 } else {
517 // Parameters do not have unit system (yet)
518 params["A"] = m_a;
519 params["B"] = m_b;
520 }
521 params.setFlowStyle();
522 node["Tsang"] = std::move(params);
523}
524
525}
Base class for kinetics managers and also contains the kineticsmgr module documentation (see Kinetics...
Header file for class ThermoPhase, the base class for phases with thermodynamic properties,...
A map of string keys to values whose type can vary at runtime.
Definition AnyMap.h:431
size_t size() const
Returns the number of elements in this map.
Definition AnyMap.cpp:1728
bool hasKey(const string &key) const
Returns true if the map contains an item named key.
Definition AnyMap.cpp:1477
const UnitSystem & units() const
Return the default units that should be used to convert stored values.
Definition AnyMap.h:640
bool empty() const
Return boolean indicating whether AnyMap is empty.
Definition AnyMap.cpp:1468
void setFlowStyle(bool flow=true)
Use "flow" style when outputting this AnyMap to YAML.
Definition AnyMap.cpp:1794
bool getBool(const string &key, bool default_) const
If key exists, return it as a bool, otherwise return default_.
Definition AnyMap.cpp:1575
void clear()
Erase all items in the mapping.
Definition AnyMap.cpp:1488
const string & getString(const string &key, const string &default_) const
If key exists, return it as a string, otherwise return default_.
Definition AnyMap.cpp:1590
void setAllowNegativePreExponentialFactor(bool value)
Set flag indicating whether negative A values are permitted.
Definition Arrhenius.h:141
void getRateParameters(AnyMap &node) const
Get Arrhenius parameters used to populate the rate-coefficient or equivalent field.
Definition Arrhenius.cpp:76
void validate(const string &equation, const Kinetics &kin) override
Validate the reaction rate expression.
virtual double preExponentialFactor() const
Return the pre-exponential factor A (in m, kmol, s to powers depending on the reaction order)
Definition Arrhenius.h:97
void check(const string &equation) override
Check rate expression.
Arrhenius reaction rate type depends only on temperature.
Definition Arrhenius.h:170
Base class for exceptions thrown by Cantera classes.
virtual string getMessage() const
Method overridden by derived classes to format the error message.
Base class for falloff rate calculators.
Definition Falloff.h:78
void setParameters(const AnyMap &node, const UnitStack &rate_units) override
Set parameters.
Definition Falloff.cpp:130
void setHighRate(const ArrheniusRate &high)
Set reaction rate in the high-pressure limit.
Definition Falloff.cpp:107
ArrheniusRate m_highRate
The reaction rate in the high-pressure limit.
Definition Falloff.h:229
void validate(const string &equation, const Kinetics &kin) override
Validate the reaction rate expression.
Definition Falloff.cpp:195
ArrheniusRate m_lowRate
The reaction rate in the low-pressure limit.
Definition Falloff.h:228
bool m_chemicallyActivated
Flag labeling reaction as chemically activated.
Definition Falloff.h:232
void getParameters(AnyMap &node) const override
Get parameters.
Definition Falloff.cpp:163
bool m_negativeA_ok
Flag indicating whether negative A values are permitted.
Definition Falloff.h:234
void check(const string &equation) override
Check basic syntax and settings of reaction rate expression.
Definition Falloff.cpp:180
void setLowRate(const ArrheniusRate &low)
Set reaction rate in the low-pressure limit.
Definition Falloff.cpp:94
virtual void setFalloffCoeffs(span< const double > c)
Set coefficients of the falloff parameterization.
Definition Falloff.cpp:120
Error thrown for problems processing information contained in an AnyMap or AnyValue.
Definition AnyMap.h:749
Public interface for kinetics managers.
Definition Kinetics.h:126
virtual span< const double > thirdBodyConcentrations() const
Provide direct access to current third-body concentration values.
Definition Kinetics.h:532
size_t nReactions() const
Number of reactions in the reaction mechanism.
Definition Kinetics.h:161
The Lindemann falloff parameterization.
Definition Falloff.h:249
virtual double molarDensity() const
Molar density (kmol/m^3).
Definition Phase.cpp:587
double temperature() const
Temperature (K).
Definition Phase.h:585
int stateMFNumber() const
Return the State Mole Fraction Number.
Definition Phase.h:794
virtual void setParameters(const AnyMap &node, const UnitStack &units)
Set parameters.
bool valid() const
Get flag indicating whether reaction rate is set up correctly.
bool m_valid
Flag indicating whether reaction rate is set up correctly.
AnyMap m_input
Input data used for specific models.
The SRI falloff function.
Definition Falloff.h:405
void setParameters(const AnyMap &node, const UnitStack &rate_units) override
Set parameters.
Definition Falloff.cpp:401
double F(double pr, span< const double > work) const override
The falloff function.
Definition Falloff.cpp:394
double m_d
parameter d in the 5-parameter SRI falloff function. Dimensionless.
Definition Falloff.h:468
void getParameters(AnyMap &node) const override
Get parameters.
Definition Falloff.cpp:426
void getFalloffCoeffs(span< double > c) const override
Retrieve coefficients of the falloff parameterization.
Definition Falloff.cpp:375
double m_a
parameter a in the 5-parameter SRI falloff function. Dimensionless.
Definition Falloff.h:459
void setFalloffCoeffs(span< const double > c) override
Set coefficients used by parameterization.
Definition Falloff.cpp:345
void updateTemp(double T, span< double > work) const override
Update the temperature parameters in the representation.
Definition Falloff.cpp:385
double m_c
parameter c in the 5-parameter SRI falloff function. [K]
Definition Falloff.h:465
double m_b
parameter b in the 5-parameter SRI falloff function. [K]
Definition Falloff.h:462
SriRate()
Constructor.
Definition Falloff.h:408
double m_e
parameter d in the 5-parameter SRI falloff function. Dimensionless.
Definition Falloff.h:471
size_t nParameters() const override
Returns the number of parameters used by this parameterization.
Definition Falloff.h:450
Base class for a phase with thermodynamic properties.
void setParameters(const AnyMap &node, const UnitStack &rate_units) override
Set parameters.
Definition Falloff.cpp:300
double m_t2
parameter T_2 in the 4-parameter Troe falloff function. [K]
Definition Falloff.h:368
double F(double pr, span< const double > work) const override
The falloff function.
Definition Falloff.cpp:290
void getParameters(AnyMap &node) const override
Get parameters.
Definition Falloff.cpp:322
double m_rt1
parameter 1/T_1 in the 4-parameter Troe falloff function. [K^-1]
Definition Falloff.h:365
void getFalloffCoeffs(span< double > c) const override
Retrieve coefficients of the falloff parameterization.
Definition Falloff.cpp:272
double m_a
parameter a in the 4-parameter Troe falloff function. Dimensionless
Definition Falloff.h:359
void setFalloffCoeffs(span< const double > c) override
Set coefficients used by parameterization.
Definition Falloff.cpp:235
TroeRate()
Constructor.
Definition Falloff.h:314
void updateTemp(double T, span< double > work) const override
Update the temperature parameters in the representation.
Definition Falloff.cpp:281
double m_rt3
parameter 1/T_3 in the 4-parameter Troe falloff function. [K^-1]
Definition Falloff.h:362
size_t nParameters() const override
Returns the number of parameters used by this parameterization.
Definition Falloff.h:349
The 1- or 2-parameter Tsang falloff parameterization.
Definition Falloff.h:499
void setParameters(const AnyMap &node, const UnitStack &rate_units) override
Set parameters.
Definition Falloff.cpp:491
double F(double pr, span< const double > work) const override
The falloff function.
Definition Falloff.cpp:481
TsangRate()
Constructor.
Definition Falloff.h:502
void getParameters(AnyMap &node) const override
Get parameters.
Definition Falloff.cpp:509
void getFalloffCoeffs(span< double > c) const override
Retrieve coefficients of the falloff parameterization.
Definition Falloff.cpp:468
double m_a
parameter a in the Tsang F_cent formulation. Dimensionless
Definition Falloff.h:553
void setFalloffCoeffs(span< const double > c) override
Set coefficients used by parameterization.
Definition Falloff.cpp:450
void updateTemp(double T, span< double > work) const override
Update the temperature parameters in the representation.
Definition Falloff.cpp:475
double m_b
parameter b in the Tsang F_cent formulation. [K^-1]
Definition Falloff.h:556
size_t nParameters() const override
Returns the number of parameters used by this parameterization.
Definition Falloff.h:543
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
This file contains definitions for utility functions and text for modules, inputfiles and logging,...
void warn_user(const string &method, const string &msg, const Args &... args)
Print a user warning raised from method as CanteraWarning.
Definition global.h:263
Namespace for the Cantera kernel.
Definition AnyMap.cpp:595
const double SmallNumber
smallest number to compare to zero.
Definition ct_defs.h:161
void checkArraySize(const char *procedure, size_t available, size_t required)
Wrapper for throwing ArraySizeError.
Contains declarations for string manipulation functions within Cantera.
int m_state_mf_number
integer that is incremented when composition changes
Definition Falloff.h:53
vector< double > m_conc_3b_buf
buffered third-body concentrations
Definition Falloff.h:56
void perturbThirdBodies(double deltaM)
Perturb third-body concentration vector of data container.
Definition Falloff.cpp:58
bool update(const ThermoPhase &phase, const Kinetics &kin) override
Update data container based on thermodynamic phase state.
Definition Falloff.cpp:38
bool ready
boolean indicating whether vectors are accessible
Definition Falloff.h:47
vector< double > conc_3b
vector of effective third-body concentrations
Definition Falloff.h:49
double molar_density
used to determine if updates are needed
Definition Falloff.h:48
void restore() override
Restore data container after a perturbation.
Definition Falloff.cpp:71
void resize(Kinetics &kin) override
Update array sizes that depend on number of species, reactions and phases.
Definition Falloff.cpp:82
bool m_perturbed
boolean indicating whether 3-rd body values are perturbed
Definition Falloff.h:55
virtual void update(double T)
Update data container based on temperature T
double temperature
temperature
virtual void restore()
Restore data container after a perturbation.
Unit aggregation utility.
Definition Units.h:105
size_t size() const
Size of UnitStack.
Definition Units.h:118
void join(double exponent)
Join (update) exponent of standard units, where the updated exponent is the sum of the pre-existing e...
Definition Units.cpp:353