Cantera  4.0.0a1
Loading...
Searching...
No Matches
MolalityVPSSTP.cpp
Go to the documentation of this file.
1/**
2 * @file MolalityVPSSTP.cpp
3 * Definitions for intermediate ThermoPhase object for phases which
4 * employ molality based activity coefficient formulations
5 * (see @ref thermoprops
6 * and class @link Cantera::MolalityVPSSTP MolalityVPSSTP@endlink).
7 */
8
9// This file is part of Cantera. See License.txt in the top-level directory or
10// at https://cantera.org/license.txt for license and copyright information.
11
15
16#include <fstream>
17
18namespace Cantera
19{
20
22{
23 // Change the default to be that charge neutrality in the phase is necessary
24 // condition for the proper specification of thermodynamic functions within
25 // the phase
27}
28
29// -------------- Utilities -------------------------------
30
31void MolalityVPSSTP::setpHScale(const int pHscaleType)
32{
33 m_pHScalingType = pHscaleType;
34 if (pHscaleType != PHSCALE_PITZER && pHscaleType != PHSCALE_NBS) {
35 throw CanteraError("MolalityVPSSTP::setpHScale",
36 "Unknown scale type: {}", pHscaleType);
37 }
38}
39
41{
42 return m_pHScalingType;
43}
44
45void MolalityVPSSTP::setMoleFSolventMin(double xmolSolventMIN)
46{
47 if (xmolSolventMIN <= 0.0) {
48 throw CanteraError("MolalityVPSSTP::setMoleFSolventMin ", "trouble");
49 } else if (xmolSolventMIN > 0.9) {
50 throw CanteraError("MolalityVPSSTP::setMoleFSolventMin ", "trouble");
51 }
52 m_xmolSolventMIN = xmolSolventMIN;
53}
54
56{
57 return m_xmolSolventMIN;
58}
59
61{
63 double xmolSolvent = std::max(m_molalities[0], m_xmolSolventMIN);
64 double denomInv = 1.0/ (m_Mnaught * xmolSolvent);
65 for (size_t k = 0; k < m_kk; k++) {
66 m_molalities[k] *= denomInv;
67 }
68}
69
70void MolalityVPSSTP::getMolalities(span<double> molal) const
71{
72 checkArraySize("MolalityVPSSTP::getMolalities", molal.size(), m_kk);
74 for (size_t k = 0; k < m_kk; k++) {
75 molal[k] = m_molalities[k];
76 }
77}
78
79void MolalityVPSSTP::setMolalities(span<const double> molal)
80{
81 checkArraySize("MolalityVPSSTP::setMolalities", molal.size(), m_kk);
82 double Lsum = 1.0 / m_Mnaught;
83 for (size_t k = 1; k < m_kk; k++) {
84 m_molalities[k] = molal[k];
85 Lsum += molal[k];
86 }
87 double tmp = 1.0 / Lsum;
88 m_molalities[0] = tmp / m_Mnaught;
89 double sum = m_molalities[0];
90 for (size_t k = 1; k < m_kk; k++) {
91 m_molalities[k] = tmp * molal[k];
92 sum += m_molalities[k];
93 }
94 if (sum != 1.0) {
95 tmp = 1.0 / sum;
96 for (size_t k = 0; k < m_kk; k++) {
97 m_molalities[k] *= tmp;
98 }
99 }
101
102 // Essentially we don't trust the input: We calculate the molalities from
103 // the mole fractions that we just obtained.
105}
106
108{
109 // HKM -> Might need to be more complicated here, setting neutrals so that
110 // the existing mole fractions are preserved.
111
112 // Get a vector of mole fractions
113 vector<double> mf(m_kk, 0.0);
115 double xmolSmin = std::max(mf[0], m_xmolSolventMIN);
116 for (size_t k = 0; k < m_kk; k++) {
117 double mol_k = getValue(mMap, speciesName(k), 0.0);
118 if (mol_k > 0) {
119 mf[k] = mol_k * m_Mnaught * xmolSmin;
120 }
121 }
122
123 // check charge neutrality
124 size_t largePos = npos;
125 double cPos = 0.0;
126 size_t largeNeg = npos;
127 double cNeg = 0.0;
128 double sum = 0.0;
129 for (size_t k = 0; k < m_kk; k++) {
130 double ch = charge(k);
131 if (mf[k] > 0.0) {
132 if (ch > 0.0 && ch * mf[k] > cPos) {
133 largePos = k;
134 cPos = ch * mf[k];
135 }
136 if (ch < 0.0 && fabs(ch) * mf[k] > cNeg) {
137 largeNeg = k;
138 cNeg = fabs(ch) * mf[k];
139 }
140 }
141 sum += mf[k] * ch;
142 }
143 if (sum != 0.0) {
144 if (sum > 0.0) {
145 if (cPos > sum) {
146 mf[largePos] -= sum / charge(largePos);
147 } else {
148 throw CanteraError("MolalityVPSSTP:setMolalitiesbyName",
149 "unbalanced charges");
150 }
151 } else {
152 if (cNeg > (-sum)) {
153 mf[largeNeg] -= (-sum) / fabs(charge(largeNeg));
154 } else {
155 throw CanteraError("MolalityVPSSTP:setMolalitiesbyName",
156 "unbalanced charges");
157 }
158 }
159 }
160 sum = 0.0;
161 for (size_t k = 0; k < m_kk; k++) {
162 sum += mf[k];
163 }
164 sum = 1.0/sum;
165 for (size_t k = 0; k < m_kk; k++) {
166 mf[k] *= sum;
167 }
169
170 // After we formally set the mole fractions, we calculate the molalities
171 // again and store it in this object.
173}
174
176{
179}
180
181// - Activities, Standard States, Activity Concentrations -----------
182
184{
186}
187
189{
190 throw NotImplementedError("MolalityVPSSTP::getActivityConcentrations");
191}
192
194{
195 throw NotImplementedError("MolalityVPSSTP::standardConcentration");
196}
197
198void MolalityVPSSTP::getActivities(span<double> ac) const
199{
200 throw NotImplementedError("MolalityVPSSTP::getActivities");
201}
202
204{
206 double xmolSolvent = std::max(moleFraction(0), m_xmolSolventMIN);
207 for (size_t k = 1; k < m_kk; k++) {
208 ac[k] /= xmolSolvent;
209 }
210}
211
212void MolalityVPSSTP::getMolalityActivityCoefficients(span<double> acMolality) const
213{
215 applyphScale(acMolality);
216}
217
219{
220 // First, we calculate the activities all over again
221 vector<double> act(m_kk);
222 getActivities(act);
223
224 // Then, we calculate the sum of the solvent molalities
225 double sum = 0;
226 for (size_t k = 1; k < m_kk; k++) {
227 sum += std::max(m_molalities[k], 0.0);
228 }
229 double oc = 1.0;
230 if (sum > 1.0E-200) {
231 oc = - log(act[0]) / (m_Mnaught * sum);
232 }
233 return oc;
234}
235
236void MolalityVPSSTP::setState_TPM(double t, double p, span<const double> molalities)
237{
238 setMolalities(molalities);
239 setState_TP(t, p);
240}
241
242void MolalityVPSSTP::setState_TPM(double t, double p, const Composition& m)
243{
245 setState_TP(t, p);
246}
247
248void MolalityVPSSTP::setState_TPM(double t, double p, const string& m)
249{
251 setState_TP(t, p);
252}
253
255 AnyValue molalities;
256 if (state.hasKey("molalities")) {
257 molalities = state["molalities"];
258 } else if (state.hasKey("M")) {
259 molalities = state["M"];
260 }
261
262 if (molalities.is<string>()) {
263 setMolalitiesByName(molalities.asString());
264 } else if (molalities.is<AnyMap>()) {
265 setMolalitiesByName(molalities.asMap<double>());
266 }
267
269}
270
272{
274
275 // Find the Cl- species
277}
278
280{
281 throw NotImplementedError("MolalityVPSSTP::getUnscaledMolalityActivityCoefficients");
282}
283
284void MolalityVPSSTP::applyphScale(span<double> acMolality) const
285{
286 throw NotImplementedError("MolalityVPSSTP::applyphScale");
287}
288
290{
291 size_t indexCLM = npos;
292 size_t eCl = npos;
293 size_t eE = npos;
294 size_t ne = nElements();
295 for (size_t e = 0; e < ne; e++) {
296 string sn = elementName(e);
297 if (sn == "Cl" || sn == "CL") {
298 eCl = e;
299 break;
300 }
301 }
302 // We have failed if we can't find the Cl element index
303 if (eCl == npos) {
304 return npos;
305 }
306 for (size_t e = 0; e < ne; e++) {
307 string sn = elementName(e);
308 if (sn == "E" || sn == "e") {
309 eE = e;
310 break;
311 }
312 }
313 // We have failed if we can't find the E element index
314 if (eE == npos) {
315 return npos;
316 }
317 for (size_t k = 1; k < m_kk; k++) {
318 double nCl = nAtoms(k, eCl);
319 if (nCl != 1.0) {
320 continue;
321 }
322 double nE = nAtoms(k, eE);
323 if (nE != 1.0) {
324 continue;
325 }
326 for (size_t e = 0; e < ne; e++) {
327 if (e != eE && e != eCl) {
328 double nA = nAtoms(k, e);
329 if (nA != 0.0) {
330 continue;
331 }
332 }
333 }
334 string sn = speciesName(k);
335 if (sn != "Cl-" && sn != "CL-") {
336 continue;
337 }
338
339 indexCLM = k;
340 break;
341 }
342 return indexCLM;
343}
344
345bool MolalityVPSSTP::addSpecies(shared_ptr<Species> spec)
346{
347 bool added = VPStandardStateTP::addSpecies(spec);
348 if (added) {
349 if (m_kk == 1) {
350 // The solvent defaults to species 0
352 m_Mnaught = m_weightSolvent / 1000.;
353 }
354 m_molalities.push_back(0.0);
355 }
356 return added;
357}
358
359string MolalityVPSSTP::report(bool show_thermo, double threshold) const
360{
361 fmt::memory_buffer b;
362 try {
363 if (name() != "") {
364 fmt_append(b, "\n {}:\n", name());
365 }
366 fmt_append(b, "\n");
367 fmt_append(b, " temperature {:12.6g} K\n", temperature());
368 fmt_append(b, " pressure {:12.6g} Pa\n", pressure());
369 fmt_append(b, " density {:12.6g} kg/m^3\n", density());
370 fmt_append(b, " mean mol. weight {:12.6g} amu\n", meanMolecularWeight());
371
372 double phi = electricPotential();
373 fmt_append(b, " potential {:12.6g} V\n", phi);
374
375 vector<double> x(m_kk);
376 vector<double> molal(m_kk);
377 vector<double> mu(m_kk);
378 vector<double> muss(m_kk);
379 vector<double> acMolal(m_kk);
380 vector<double> actMolal(m_kk);
382 getMolalities(molal);
386 getActivities(actMolal);
387
388 size_t iHp = speciesIndex("H+", false);
389 if (iHp != npos) {
390 double pH = -log(actMolal[iHp]) / log(10.0);
391 fmt_append(b,
392 " pH {:12.4g}\n", pH);
393 }
394
395 if (show_thermo) {
396 fmt_append(b, "\n");
397 fmt_append(b, " 1 kg 1 kmol\n");
398 fmt_append(b, " ----------- ------------\n");
399 fmt_append(b, " enthalpy {:12.6g} {:12.4g} J\n",
401 fmt_append(b, " internal energy {:12.6g} {:12.4g} J\n",
403 fmt_append(b, " entropy {:12.6g} {:12.4g} J/K\n",
405 fmt_append(b, " Gibbs function {:12.6g} {:12.4g} J\n",
407 fmt_append(b, " heat capacity c_p {:12.6g} {:12.4g} J/K\n",
408 cp_mass(), cp_mole());
409 try {
410 fmt_append(b, " heat capacity c_v {:12.6g} {:12.4g} J/K\n",
411 cv_mass(), cv_mole());
412 } catch (NotImplementedError&) {
413 fmt_append(b, " heat capacity c_v <not implemented>\n");
414 }
415 }
416
417 fmt_append(b, "\n");
418 int nMinor = 0;
419 double xMinor = 0.0;
420 if (show_thermo) {
421 fmt_append(b, " X "
422 " Molalities Chem.Pot. ChemPotSS ActCoeffMolal\n");
423 fmt_append(b, " "
424 " (J/kmol) (J/kmol)\n");
425 fmt_append(b, " ------------- "
426 " ------------ ------------ ------------ ------------\n");
427 for (size_t k = 0; k < m_kk; k++) {
428 if (x[k] > threshold) {
429 if (x[k] > SmallNumber) {
430 fmt_append(b,
431 "{:>18s} {:12.6g} {:12.6g} {:12.6g} "
432 "{:12.6g} {:12.6g}\n", speciesName(k),
433 x[k], molal[k], mu[k], muss[k], acMolal[k]);
434 } else {
435 fmt_append(b,
436 "{:>18s} {:12.6g} {:12.6g} N/A "
437 "{:12.6g} {:12.6g}\n", speciesName(k),
438 x[k], molal[k], muss[k], acMolal[k]);
439 }
440 } else {
441 nMinor++;
442 xMinor += x[k];
443 }
444 }
445 } else {
446 fmt_append(b, " X Molalities\n");
447 fmt_append(b, " ------------- ------------\n");
448 for (size_t k = 0; k < m_kk; k++) {
449 if (x[k] > threshold) {
450 fmt_append(b, "{:>18s} {:12.6g} {:12.6g}\n",
451 speciesName(k), x[k], molal[k]);
452 } else {
453 nMinor++;
454 xMinor += x[k];
455 }
456 }
457 }
458 if (nMinor) {
459 fmt_append(b, " [{:+5d} minor] {:12.6g}\n", nMinor, xMinor);
460 }
461 } catch (CanteraError& err) {
462 return to_string(b) + err.what();
463 }
464 return to_string(b);
465}
466
467}
Header for intermediate ThermoPhase object for phases which employ molality based activity coefficien...
A map of string keys to values whose type can vary at runtime.
Definition AnyMap.h:431
bool hasKey(const string &key) const
Returns true if the map contains an item named key.
Definition AnyMap.cpp:1477
A wrapper for a variable whose type is determined at runtime.
Definition AnyMap.h:88
const string & asString() const
Return the held value, if it is a string.
Definition AnyMap.cpp:782
map< string, T > asMap() const
Return the held AnyMap as a map where all of the values have the specified type.
Definition AnyMap.inl.h:162
bool is() const
Returns true if the held value is of the specified type.
Definition AnyMap.inl.h:68
Base class for exceptions thrown by Cantera classes.
const char * what() const override
Get a description of the error.
void getMolalities(span< double > molal) const
This function will return the molalities of the species.
int activityConvention() const override
We set the convention to molality here.
void setState(const AnyMap &state) override
Set the state using an AnyMap containing any combination of properties supported by the thermodynamic...
void setMolalitiesByName(const Composition &xMap)
Set the molalities of a phase.
double m_Mnaught
This is the multiplication factor that goes inside log expressions involving the molalities of specie...
virtual void applyphScale(span< double > acMolality) const
Apply the current phScale to a set of activity Coefficients or activities.
size_t m_indexCLM
Index of the phScale species.
void getActivityCoefficients(span< double > ac) const override
Get the array of non-dimensional activity coefficients at the current solution temperature,...
size_t findCLMIndex() const
Returns the index of the Cl- species.
void setState_TPM(double t, double p, span< const double > molalities)
Set the temperature (K), pressure (Pa), and molalities (gmol kg-1) of the solutes.
void initThermo() override
Initialize the ThermoPhase object after all species have been set up.
int pHScale() const
Reports the pH scale, which determines the scale for single-ion activity coefficients.
void setpHScale(const int pHscaleType)
Set the pH scale, which determines the scale for single-ion activity coefficients.
double m_xmolSolventMIN
In any molality implementation, it makes sense to have a minimum solvent mole fraction requirement,...
void getActivities(span< double > ac) const override
Get the array of non-dimensional activities (molality based for this class and classes that derive fr...
vector< double > m_molalities
Current value of the molalities of the species in the phase.
int m_pHScalingType
Scaling to be used for output of single-ion species activity coefficients.
void setMoleFSolventMin(double xmolSolventMIN)
Sets the minimum mole fraction in the molality formulation.
virtual double osmoticCoefficient() const
Calculate the osmotic coefficient.
MolalityVPSSTP()
Default Constructor.
double moleFSolventMin() const
Returns the minimum mole fraction in the molality formulation.
virtual void getMolalityActivityCoefficients(span< double > acMolality) const
Get the array of non-dimensional molality based activity coefficients at the current solution tempera...
void setMolalities(span< const double > molal)
Set the molalities of the solutes in a phase.
void calcMolalities() const
Calculates the molality of all species and stores the result internally.
double standardConcentration(size_t k=0) const override
Return the standard concentration for the kth species.
double m_weightSolvent
Molecular weight of the Solvent.
bool addSpecies(shared_ptr< Species > spec) override
Add a Species to this Phase.
void getActivityConcentrations(span< double > c) const override
This method returns an array of generalized concentrations.
virtual void getUnscaledMolalityActivityCoefficients(span< double > acMolality) const
Get the array of unscaled non-dimensional molality based activity coefficients at the current solutio...
string report(bool show_thermo=true, double threshold=1e-14) const override
returns a summary of the state of the phase as a string
An error indicating that an unimplemented function has been called.
void getMoleFractions(span< double > x) const
Get the species mole fraction vector.
Definition Phase.cpp:441
size_t m_kk
Number of species in the phase.
Definition Phase.h:875
size_t speciesIndex(const string &name, bool raise=true) const
Returns the index of a species named 'name' within the Phase object.
Definition Phase.cpp:127
double temperature() const
Temperature (K).
Definition Phase.h:585
double meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition Phase.h:676
string speciesName(size_t k) const
Name of the species with index k.
Definition Phase.cpp:143
double moleFraction(size_t k) const
Return the mole fraction of a single species.
Definition Phase.cpp:447
virtual double density() const
Density (kg/m^3).
Definition Phase.h:610
double nAtoms(size_t k, size_t m) const
Number of atoms of element m in species k.
Definition Phase.cpp:101
size_t nElements() const
Number of elements.
Definition Phase.cpp:30
virtual void setMoleFractions(span< const double > x)
Set the mole fractions to the specified values.
Definition Phase.cpp:283
const vector< string > & speciesNames() const
Return a const reference to the vector of species names.
Definition Phase.cpp:151
double molecularWeight(size_t k) const
Molecular weight of species k.
Definition Phase.cpp:388
string elementName(size_t m) const
Name of the element with index m.
Definition Phase.cpp:43
double charge(size_t k) const
Dimensionless electrical charge of a single molecule of species k The charge is normalized by the the...
Definition Phase.h:561
string name() const
Return the name of the phase.
Definition Phase.cpp:20
double electricPotential() const
Returns the electric potential of this phase (V).
virtual double cp_mole() const
Molar heat capacity at constant pressure and composition [J/kmol/K].
virtual double enthalpy_mole() const
Molar enthalpy. Units: J/kmol.
virtual void setState(const AnyMap &state)
Set the state using an AnyMap containing any combination of properties supported by the thermodynamic...
double gibbs_mass() const
Specific Gibbs function. Units: J/kg.
bool m_chargeNeutralityNecessary
Boolean indicating whether a charge neutrality condition is a necessity.
virtual double entropy_mole() const
Molar entropy. Units: J/kmol/K.
double cv_mass() const
Specific heat at constant volume and composition [J/kg/K].
double entropy_mass() const
Specific entropy. Units: J/kg/K.
double cp_mass() const
Specific heat at constant pressure and composition [J/kg/K].
double intEnergy_mass() const
Specific internal energy. Units: J/kg.
virtual double cv_mole() const
Molar heat capacity at constant volume and composition [J/kmol/K].
virtual void getChemPotentials(span< double > mu) const
Get the species chemical potentials. Units: J/kmol.
virtual double intEnergy_mole() const
Molar internal energy. Units: J/kmol.
virtual double gibbs_mole() const
Molar Gibbs function. Units: J/kmol.
double enthalpy_mass() const
Specific enthalpy. Units: J/kg.
double pressure() const override
Returns the current pressure of the phase.
void getStandardChemPotentials(span< double > mu) const override
Get the array of chemical potentials at unit activity for the species at their standard states at the...
void initThermo() override
Initialize the ThermoPhase object after all species have been set up.
void setState_TP(double T, double pres) override
Set the temperature and pressure at the same time.
bool addSpecies(shared_ptr< Species > spec) override
Add a Species to this Phase.
Composition parseCompString(const string &ss, const vector< string > &names)
Parse a composition string into a map consisting of individual key:composition pairs.
Namespace for the Cantera kernel.
Definition AnyMap.cpp:595
const size_t npos
index returned by functions to indicate "no position"
Definition ct_defs.h:183
const int PHSCALE_PITZER
Scale to be used for the output of single-ion activity coefficients is that used by Pitzer.
const double SmallNumber
smallest number to compare to zero.
Definition ct_defs.h:161
const int PHSCALE_NBS
Scale to be used for evaluation of single-ion activity coefficients is that used by the NBS standard ...
const U & getValue(const map< T, U > &m, const T &key, const U &default_val)
Const accessor for a value in a map.
Definition utilities.h:223
map< string, double > Composition
Map from string names to doubles.
Definition ct_defs.h:180
const int cAC_CONVENTION_MOLALITY
Standard state uses the molality convention.
void checkArraySize(const char *procedure, size_t available, size_t required)
Wrapper for throwing ArraySizeError.
Contains declarations for string manipulation functions within Cantera.
Various templated functions that carry out common vector and polynomial operations (see Templated Arr...