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