1 /**
2 * @file PDSS_IonsFromNeutral.cpp
3 * Implementation of a pressure dependent standard state
4 * virtual function.
5 */
6
7 // This file is part of Cantera. See License.txt in the top-level directory or
8 // at https://cantera.org/license.txt for license and copyright information.
9
10 #include "cantera/thermo/PDSS_IonsFromNeutral.h"
11 #include "cantera/thermo/IonsFromNeutralVPSSTP.h"
12 #include "cantera/base/stringUtils.h"
13 #include "cantera/base/ctml.h"
14
15 using namespace std;
16
17 namespace Cantera
18 {
19
PDSS_IonsFromNeutral()20 PDSS_IonsFromNeutral::PDSS_IonsFromNeutral()
21 : neutralMoleculePhase_(0)
22 , numMult_(0)
23 , add2RTln2_(true)
24 {
25 }
26
setParent(VPStandardStateTP * phase,size_t k)27 void PDSS_IonsFromNeutral::setParent(VPStandardStateTP* phase, size_t k)
28 {
29 neutralMoleculePhase_ = dynamic_cast<IonsFromNeutralVPSSTP&>(*phase).getNeutralMoleculePhase();
30 }
31
setNeutralSpeciesMultiplier(const std::string & species,double mult)32 void PDSS_IonsFromNeutral::setNeutralSpeciesMultiplier(const std::string& species, double mult)
33 {
34 neutralSpeciesMultipliers_[species] = mult;
35 numMult_++;
36 }
37
setSpecialSpecies(bool special)38 void PDSS_IonsFromNeutral::setSpecialSpecies(bool special) {
39 add2RTln2_ = !special;
40 }
41
setParametersFromXML(const XML_Node & speciesNode)42 void PDSS_IonsFromNeutral::setParametersFromXML(const XML_Node& speciesNode)
43 {
44 PDSS::setParametersFromXML(speciesNode);
45 const XML_Node* tn = speciesNode.findByName("thermo");
46 if (!tn) {
47 throw CanteraError("PDSS_IonsFromNeutral::setParametersFromXML",
48 "no 'thermo' Node for species '{}'", speciesNode.name());
49 }
50 if (!caseInsensitiveEquals(tn->attrib("model"), "ionfromneutral")) {
51 throw CanteraError("PDSS_IonsFromNeutral::setParametersFromXML",
52 "thermo model for species '{}' isn't 'IonsFromNeutral'",
53 speciesNode.name());
54 }
55 const XML_Node* nsm = tn->findByName("neutralSpeciesMultipliers");
56 if (!nsm) {
57 throw CanteraError("PDSS_IonsFromNeutral::setParametersFromXML",
58 "no 'Thermo::neutralSpeciesMultipliers' Node for species '{}'",
59 speciesNode.name());
60 }
61
62 for (auto& species_mult : parseCompString(nsm->value())) {
63 setNeutralSpeciesMultiplier(species_mult.first, species_mult.second);
64 }
65
66 if (tn->findByName("specialSpecies")) {
67 setSpecialSpecies();
68 }
69 }
70
getParameters(AnyMap & eosNode) const71 void PDSS_IonsFromNeutral::getParameters(AnyMap& eosNode) const
72 {
73 PDSS::getParameters(eosNode);
74 eosNode["model"] = "ions-from-neutral-molecule";
75 if (!add2RTln2_) {
76 eosNode["special-species"] = true;
77 }
78 if (!neutralSpeciesMultipliers_.empty()) {
79 eosNode["multipliers"] = neutralSpeciesMultipliers_;
80 }
81 }
82
initThermo()83 void PDSS_IonsFromNeutral::initThermo()
84 {
85 PDSS::initThermo();
86 if (m_input.getBool("special-species", false)) {
87 setSpecialSpecies();
88 }
89 if (m_input.hasKey("multipliers")) {
90 for (const auto& item : m_input["multipliers"].asMap<double>()) {
91 setNeutralSpeciesMultiplier(item.first, item.second);
92 }
93 }
94
95 m_p0 = neutralMoleculePhase_->refPressure();
96 m_minTemp = neutralMoleculePhase_->minTemp();
97 m_maxTemp = neutralMoleculePhase_->maxTemp();
98 tmpNM.resize(neutralMoleculePhase_->nSpecies());
99 for (auto multiplier : neutralSpeciesMultipliers_) {
100 idNeutralMoleculeVec.push_back( neutralMoleculePhase_->speciesIndex(multiplier.first));
101 factorVec.push_back(multiplier.second);
102 }
103 }
104
enthalpy_RT() const105 doublereal PDSS_IonsFromNeutral::enthalpy_RT() const
106 {
107 neutralMoleculePhase_->getEnthalpy_RT(tmpNM.data());
108 doublereal val = 0.0;
109 for (size_t i = 0; i < numMult_; i++) {
110 size_t jNeut = idNeutralMoleculeVec[i];
111 val += factorVec[i] * tmpNM[jNeut];
112 }
113 return val;
114 }
115
intEnergy_mole() const116 doublereal PDSS_IonsFromNeutral::intEnergy_mole() const
117 {
118 return (m_h0_RT - 1.0) * GasConstant * m_temp;
119 }
120
entropy_R() const121 doublereal PDSS_IonsFromNeutral::entropy_R() const
122 {
123 neutralMoleculePhase_->getEntropy_R(tmpNM.data());
124 doublereal val = 0.0;
125 for (size_t i = 0; i < numMult_; i++) {
126 size_t jNeut = idNeutralMoleculeVec[i];
127 val += factorVec[i] * tmpNM[jNeut];
128 }
129 if (add2RTln2_) {
130 val -= 2.0 * log(2.0);
131 }
132 return val;
133 }
134
gibbs_RT() const135 doublereal PDSS_IonsFromNeutral::gibbs_RT() const
136 {
137 neutralMoleculePhase_->getGibbs_RT(tmpNM.data());
138 doublereal val = 0.0;
139 for (size_t i = 0; i < numMult_; i++) {
140 size_t jNeut = idNeutralMoleculeVec[i];
141 val += factorVec[i] * tmpNM[jNeut];
142 }
143 if (add2RTln2_) {
144 val += 2.0 * log(2.0);
145 }
146 return val;
147 }
148
cp_R() const149 doublereal PDSS_IonsFromNeutral::cp_R() const
150 {
151 neutralMoleculePhase_->getCp_R(tmpNM.data());
152 doublereal val = 0.0;
153 for (size_t i = 0; i < numMult_; i++) {
154 size_t jNeut = idNeutralMoleculeVec[i];
155 val += factorVec[i] * tmpNM[jNeut];
156 }
157 return val;
158 }
159
molarVolume() const160 doublereal PDSS_IonsFromNeutral::molarVolume() const
161 {
162 neutralMoleculePhase_->getStandardVolumes(tmpNM.data());
163 doublereal val = 0.0;
164 for (size_t i = 0; i < numMult_; i++) {
165 size_t jNeut = idNeutralMoleculeVec[i];
166 val += factorVec[i] * tmpNM[jNeut];
167 }
168 return val;
169 }
170
density() const171 doublereal PDSS_IonsFromNeutral::density() const
172 {
173 return (m_pres * m_mw / (GasConstant * m_temp));
174 }
175
gibbs_RT_ref() const176 doublereal PDSS_IonsFromNeutral::gibbs_RT_ref() const
177 {
178 neutralMoleculePhase_->getGibbs_RT_ref(tmpNM.data());
179 doublereal val = 0.0;
180 for (size_t i = 0; i < numMult_; i++) {
181 size_t jNeut = idNeutralMoleculeVec[i];
182 val += factorVec[i] * tmpNM[jNeut];
183 }
184 if (add2RTln2_) {
185 val += 2.0 * log(2.0);
186 }
187 return val;
188 }
189
enthalpy_RT_ref() const190 doublereal PDSS_IonsFromNeutral::enthalpy_RT_ref() const
191 {
192 neutralMoleculePhase_->getEnthalpy_RT_ref(tmpNM.data());
193 doublereal val = 0.0;
194 for (size_t i = 0; i < numMult_; i++) {
195 size_t jNeut = idNeutralMoleculeVec[i];
196 val += factorVec[i] * tmpNM[jNeut];
197 }
198 return val;
199 }
200
entropy_R_ref() const201 doublereal PDSS_IonsFromNeutral::entropy_R_ref() const
202 {
203 neutralMoleculePhase_->getEntropy_R_ref(tmpNM.data());
204 doublereal val = 0.0;
205 for (size_t i = 0; i < numMult_; i++) {
206 size_t jNeut = idNeutralMoleculeVec[i];
207 val += factorVec[i] * tmpNM[jNeut];
208 }
209 if (add2RTln2_) {
210 val -= 2.0 * log(2.0);
211 }
212 return val;
213 }
214
cp_R_ref() const215 doublereal PDSS_IonsFromNeutral::cp_R_ref() const
216 {
217 neutralMoleculePhase_->getCp_R_ref(tmpNM.data());
218 doublereal val = 0.0;
219 for (size_t i = 0; i < numMult_; i++) {
220 size_t jNeut = idNeutralMoleculeVec[i];
221 val += factorVec[i] * tmpNM[jNeut];
222 }
223 return val;
224 }
225
molarVolume_ref() const226 doublereal PDSS_IonsFromNeutral::molarVolume_ref() const
227 {
228 neutralMoleculePhase_->getStandardVolumes_ref(tmpNM.data());
229 doublereal val = 0.0;
230 for (size_t i = 0; i < numMult_; i++) {
231 size_t jNeut = idNeutralMoleculeVec[i];
232 val += factorVec[i] * tmpNM[jNeut];
233 }
234 return val;
235 }
236
setState_TP(doublereal temp,doublereal pres)237 void PDSS_IonsFromNeutral::setState_TP(doublereal temp, doublereal pres)
238 {
239 neutralMoleculePhase_->setState_TP(temp, pres);
240 m_pres = pres;
241 m_temp = temp;
242 }
243
244 }
245