Cantera
Loading...
Searching...
No Matches
vcs_VolPhase.cpp
Go to the documentation of this file.
1/**
2 * @file vcs_VolPhase.cpp
3 */
4
5// This file is part of Cantera. See License.txt in the top-level directory or
6// at https://cantera.org/license.txt for license and copyright information.
7
10
13
14#include <cstdio>
15
16namespace Cantera
17{
18
19vcs_VolPhase::vcs_VolPhase(VCS_SOLVE* owningSolverObject,
20 ThermoPhase* thermoPhase, size_t phaseNum)
21 : m_owningSolverObject(owningSolverObject)
22{
23 if (!m_owningSolverObject) {
24 throw CanteraError("vcs_VolPhase::vcs_VolPhase",
25 "owningSolverObject must not be null");
26 }
27 if (!thermoPhase) {
28 throw CanteraError("vcs_VolPhase::vcs_VolPhase",
29 "thermoPhase must not be null");
30 }
31
32 VP_ID_ = phaseNum;
33 PhaseName = thermoPhase->name().empty() ?
34 fmt::format("Phase_{}", VP_ID_) : thermoPhase->name();
35
36 m_numSpecies = thermoPhase->nSpecies();
37 AssertThrowMsg(m_numSpecies > 0, "vcs_VolPhase::vcs_VolPhase",
38 "nspecies Error");
39 m_singleSpecies = (m_numSpecies == 1);
40 m_phiVarIndex = npos;
41
42 p_activityConvention = thermoPhase->activityConvention();
43
44 IndSpecies.assign(m_numSpecies, npos);
45 Xmol_.assign(m_numSpecies, 0.0);
46 creationMoleNumbers_.assign(m_numSpecies, 0.0);
47 creationGlobalRxnNumbers_.assign(m_numSpecies, npos);
48 for (size_t k = 0; k < m_numSpecies; k++) {
49 double defaultFrac = 1.0 / m_numSpecies;
50 Xmol_[k] = defaultFrac;
51 creationMoleNumbers_[k] = defaultFrac;
52 }
53
54 SS0ChemicalPotential.assign(m_numSpecies, -1.0);
55 StarChemicalPotential.assign(m_numSpecies, -1.0);
56 StarMolarVol.assign(m_numSpecies, -1.0);
57 PartialMolarVol.assign(m_numSpecies, -1.0);
58 ActCoeff.assign(m_numSpecies, 1.0);
59 np_dLnActCoeffdMolNumber.resize(m_numSpecies, m_numSpecies, 0.0);
60
61 m_speciesUnknownType.assign(m_numSpecies, VCS_SPECIES_TYPE_MOLNUM);
62 m_UpToDate = false;
63 m_vcsStateStatus = VCS_STATECALC_OLD;
64 m_UpToDate_AC = false;
65 m_UpToDate_VolStar = false;
66 m_UpToDate_VolPM = false;
67 m_UpToDate_GStar = false;
68 m_UpToDate_G0 = false;
69
70 TP_ptr = thermoPhase;
71 Temp_ = TP_ptr->temperature();
72 Pres_ = TP_ptr->pressure();
73 m_phi = TP_ptr->electricPotential();
74
75 transferElementsFM(TP_ptr);
76 setTotalMoles(0.0);
77
78 // Determine the global index for each of the elements in the phase
79 size_t neVP = nElemConstraints();
80 for (size_t eVP = 0; eVP < neVP; eVP++) {
81 string enVP = elementName(eVP);
82 size_t foundPos = m_owningSolverObject->elementIndex(enVP);
83 if (foundPos == npos) {
84 int elType = elementType(eVP);
85 int elactive = elementActive(eVP);
86 foundPos = m_owningSolverObject->addElement(enVP.c_str(), elType, elactive);
87 }
88 setElemGlobalIndex(eVP, foundPos);
89 }
90
91 setState_TP(Temp_, Pres_);
92 TP_ptr->getMoleFractions(Xmol_);
93 creationMoleNumbers_ = Xmol_;
94 _updateMoleFractionDependencies();
95
96 m_isIdealSoln = m_singleSpecies ? true : TP_ptr->isIdeal();
97}
98
99void vcs_VolPhase::elemResize(const size_t numElemConstraints)
100{
101 m_elementNames.resize(numElemConstraints);
102 m_elementActive.resize(numElemConstraints+1, 1);
103 m_elementType.resize(numElemConstraints, VCS_ELEM_TYPE_ABSPOS);
104 m_formulaMatrix.resize(m_numSpecies, numElemConstraints, 0.0);
105 m_elementNames.resize(numElemConstraints, "");
106 m_elemGlobalIndex.resize(numElemConstraints, npos);
107 m_numElemConstraints = numElemConstraints;
108}
109
111{
112 if (m_isIdealSoln) {
113 m_UpToDate_AC = true;
114 return;
115 }
116 TP_ptr->getActivityCoefficients(ActCoeff);
117 m_UpToDate_AC = true;
118}
119
121{
122 TP_ptr->getGibbs_ref(SS0ChemicalPotential);
123 m_UpToDate_G0 = true;
124}
125
126double vcs_VolPhase::G0_calc_one(size_t kspec) const
127{
128 if (!m_UpToDate_G0) {
129 _updateG0();
130 }
131 return SS0ChemicalPotential[kspec];
132}
133
135{
136 TP_ptr->getStandardChemPotentials(StarChemicalPotential);
137 m_UpToDate_GStar = true;
138}
139
140double vcs_VolPhase::GStar_calc_one(size_t kspec) const
141{
142 if (!m_UpToDate_GStar) {
143 _updateGStar();
144 }
145 return StarChemicalPotential[kspec];
146}
147
148void vcs_VolPhase::setMoleFractions(span<const double> xmol)
149{
150 checkArraySize("vcs_VolPhase::setMoleFractions", xmol.size(), m_numSpecies);
151 double sum = -1.0;
152 for (size_t k = 0; k < m_numSpecies; k++) {
153 Xmol_[k] = xmol[k];
154 sum+= xmol[k];
155 }
156 if (std::fabs(sum) > 1.0E-13) {
157 for (size_t k = 0; k < m_numSpecies; k++) {
158 Xmol_[k] /= sum;
159 }
160 }
162 m_UpToDate = false;
164}
165
167{
168 if (TP_ptr) {
169 TP_ptr->setMoleFractions(span<const double>(
171 TP_ptr->setPressure(Pres_);
172 }
173 if (!m_isIdealSoln) {
174 m_UpToDate_AC = false;
175 m_UpToDate_VolPM = false;
176 }
177}
178
179span<const double> vcs_VolPhase::moleFractions() const
180{
181 return Xmol_;
182}
183
184double vcs_VolPhase::moleFraction(size_t k) const
185{
186 return Xmol_[k];
187}
188
190 span<const double> moleFractions, const int vcsStateStatus)
191{
192 checkArraySize("vcs_VolPhase::setMoleFractionsState", moleFractions.size(),
194 if (totalMoles != 0.0) {
195 // There are other ways to set the mole fractions when VCS_STATECALC
196 // is set to a normal settting.
197 if (vcsStateStatus != VCS_STATECALC_TMP) {
198 throw CanteraError("vcs_VolPhase::setMolesFractionsState",
199 "inappropriate usage");
200 }
201 m_UpToDate = false;
204 throw CanteraError("vcs_VolPhase::setMolesFractionsState",
205 "inappropriate usage");
206 }
208 } else {
209 m_UpToDate = true;
210 m_vcsStateStatus = vcsStateStatus;
212 }
213 double fractotal = 1.0;
215 double sum = 0.0;
216 for (size_t k = 0; k < m_numSpecies; k++) {
217 Xmol_[k] = moleFractions[k];
218 sum += moleFractions[k];
219 }
220 if (sum == 0.0) {
221 throw CanteraError("vcs_VolPhase::setMolesFractionsState",
222 "inappropriate usage");
223 }
224 if (sum != fractotal) {
225 for (size_t k = 0; k < m_numSpecies; k++) {
226 Xmol_[k] *= (fractotal /sum);
227 }
228 }
230}
231
232void vcs_VolPhase::setMolesFromVCS(const int stateCalc,
233 span<const double> molesSpeciesVCS)
234{
235 v_totalMoles = 0.0;
236
237 if (molesSpeciesVCS.empty()) {
238 if (stateCalc == VCS_STATECALC_OLD) {
239 molesSpeciesVCS = span<const double>(m_owningSolverObject->m_molNumSpecies_old);
240 } else if (stateCalc == VCS_STATECALC_NEW) {
241 molesSpeciesVCS = span<const double>(m_owningSolverObject->m_molNumSpecies_new);
242 } else {
243 throw CanteraError("vcs_VolPhase::setMolesFromVCS", "shouldn't be here");
244 }
245 }
246
247 for (size_t k = 0; k < m_numSpecies; k++) {
249 size_t kglob = IndSpecies[k];
250 v_totalMoles += std::max(0.0, molesSpeciesVCS[kglob]);
251 }
252 }
253 if (v_totalMoles > 0.0) {
254 for (size_t k = 0; k < m_numSpecies; k++) {
256 size_t kglob = IndSpecies[k];
257 double tmp = std::max(0.0, molesSpeciesVCS[kglob]);
258 Xmol_[k] = tmp / v_totalMoles;
259 }
260 }
262 } else {
263 // This is where we will start to store a better approximation
264 // for the mole fractions, when the phase doesn't exist.
265 // This is currently unimplemented.
267 }
268
269 // Update the electric potential if it is a solution variable in the
270 // equation system
271 if (m_phiVarIndex != npos) {
272 size_t kglob = IndSpecies[m_phiVarIndex];
273 if (m_numSpecies == 1) {
274 Xmol_[m_phiVarIndex] = 1.0;
275 } else {
276 Xmol_[m_phiVarIndex] = 0.0;
277 }
278 double phi = molesSpeciesVCS[kglob];
280 if (m_numSpecies == 1) {
282 }
283 }
285
286 // If stateCalc is old and the total moles is positive, then we have a valid
287 // state. If the phase went away, it would be a valid starting point for
288 // F_k's. So, save the state.
289 if (stateCalc == VCS_STATECALC_OLD && v_totalMoles > 0.0) {
291 }
292
293 // Set flags indicating we are up to date with the VCS state vector.
294 m_UpToDate = true;
295 m_vcsStateStatus = stateCalc;
296}
297
298void vcs_VolPhase::setMolesFromVCSCheck(const int vcsStateStatus,
299 span<const double> molesSpeciesVCS,
300 span<const double> TPhMoles)
301{
302 setMolesFromVCS(vcsStateStatus, molesSpeciesVCS);
303
304 // Check for consistency with TPhMoles[]
305 double Tcheck = TPhMoles[VP_ID_];
306 if (Tcheck != v_totalMoles) {
307 if (vcs_doubleEqual(Tcheck, v_totalMoles)) {
308 Tcheck = v_totalMoles;
309 } else {
310 throw CanteraError("vcs_VolPhase::setMolesFromVCSCheck",
311 "We have a consistency problem: {} {}", Tcheck, v_totalMoles);
312 }
313 }
314}
315
316void vcs_VolPhase::updateFromVCS_MoleNumbers(const int vcsStateStatus)
317{
318 if ((!m_UpToDate || vcsStateStatus != m_vcsStateStatus) &&
319 (vcsStateStatus == VCS_STATECALC_OLD || vcsStateStatus == VCS_STATECALC_NEW)) {
320 setMolesFromVCS(vcsStateStatus);
321 }
322}
323
324void vcs_VolPhase::sendToVCS_ActCoeff(const int vcsStateStatus, span<double> AC)
325{
326 updateFromVCS_MoleNumbers(vcsStateStatus);
327 if (!m_UpToDate_AC) {
329 }
330 for (size_t k = 0; k < m_numSpecies; k++) {
331 size_t kglob = IndSpecies[k];
332 AC[kglob] = ActCoeff[k];
333 }
334}
335
336double vcs_VolPhase::sendToVCS_VolPM(span<double> VolPM) const
337{
338 if (!m_UpToDate_VolPM) {
339 _updateVolPM();
340 }
341 for (size_t k = 0; k < m_numSpecies; k++) {
342 size_t kglob = IndSpecies[k];
343 VolPM[kglob] = PartialMolarVol[k];
344 }
345 return m_totalVol;
346}
347
348void vcs_VolPhase::sendToVCS_GStar(span<double> gstar) const
349{
350 if (!m_UpToDate_GStar) {
351 _updateGStar();
352 }
353 for (size_t k = 0; k < m_numSpecies; k++) {
354 size_t kglob = IndSpecies[k];
355 gstar[kglob] = StarChemicalPotential[k];
356 }
357}
358
360{
361 m_phi = phi;
362 TP_ptr->setElectricPotential(m_phi);
363 // We have changed the state variable. Set uptodate flags to false
364 m_UpToDate_AC = false;
365 m_UpToDate_VolStar = false;
366 m_UpToDate_VolPM = false;
367 m_UpToDate_GStar = false;
368}
369
371{
372 return m_phi;
373}
374
375void vcs_VolPhase::setState_TP(const double temp, const double pres)
376{
377 if (Temp_ == temp && Pres_ == pres) {
378 return;
379 }
380 TP_ptr->setElectricPotential(m_phi);
381 TP_ptr->setState_TP(temp, pres);
382 Temp_ = temp;
383 Pres_ = pres;
384 m_UpToDate_AC = false;
385 m_UpToDate_VolStar = false;
386 m_UpToDate_VolPM = false;
387 m_UpToDate_GStar = false;
388 m_UpToDate_G0 = false;
389}
390
392{
393 TP_ptr->getStandardVolumes(StarMolarVol);
394 m_UpToDate_VolStar = true;
395}
396
398{
399 TP_ptr->getPartialMolarVolumes(PartialMolarVol);
400 m_totalVol = 0.0;
401 for (size_t k = 0; k < m_numSpecies; k++) {
403 }
405 m_UpToDate_VolPM = true;
406 return m_totalVol;
407}
408
410{
411 double phaseTotalMoles = v_totalMoles;
412 if (phaseTotalMoles < 1.0E-14) {
413 phaseTotalMoles = 1.0;
414 }
415
416 // Evaluate the current base activity coefficients if necessary
417 if (!m_UpToDate_AC) {
419 }
420 if (!TP_ptr) {
421 return;
422 }
423 TP_ptr->getdlnActCoeffdlnN(m_numSpecies,
424 span<double>(&np_dLnActCoeffdMolNumber(0, 0), m_numSpecies * m_numSpecies));
425 for (size_t j = 0; j < m_numSpecies; j++) {
426 double moles_j_base = phaseTotalMoles * Xmol_[j];
427 auto np_lnActCoeffCol = np_dLnActCoeffdMolNumber.col(j);
428 if (moles_j_base < 1.0E-200) {
429 moles_j_base = 1.0E-7 * moles_j_base + 1.0E-13 * phaseTotalMoles + 1.0E-150;
430 }
431 for (size_t k = 0; k < m_numSpecies; k++) {
432 np_lnActCoeffCol[k] = np_lnActCoeffCol[k] * phaseTotalMoles / moles_j_base;
433 }
434 }
435
436 double deltaMoles_j = 0.0;
437 // Make copies of ActCoeff and Xmol_ for use in taking differences
438 vector<double> ActCoeff_Base(ActCoeff);
439 vector<double> Xmol_Base(Xmol_);
440 double TMoles_base = phaseTotalMoles;
441
442 // Loop over the columns species to be deltad
443 for (size_t j = 0; j < m_numSpecies; j++) {
444 // Calculate a value for the delta moles of species j. Note Xmol_[] and
445 // Tmoles are always positive or zero quantities.
446 double moles_j_base = phaseTotalMoles * Xmol_Base[j];
447 deltaMoles_j = 1.0E-7 * moles_j_base + 1.0E-13 * phaseTotalMoles + 1.0E-150;
448
449 // Now, update the total moles in the phase and all of the mole
450 // fractions based on this.
451 phaseTotalMoles = TMoles_base + deltaMoles_j;
452 for (size_t k = 0; k < m_numSpecies; k++) {
453 Xmol_[k] = Xmol_Base[k] * TMoles_base / phaseTotalMoles;
454 }
455 Xmol_[j] = (moles_j_base + deltaMoles_j) / phaseTotalMoles;
456
457 // Go get new values for the activity coefficients. Note this calls
458 // setState_PX();
461
462 // Revert to the base case Xmol_, v_totalMoles
463 v_totalMoles = TMoles_base;
464 Xmol_ = Xmol_Base;
465 }
466
467 // Go get base values for the activity coefficients. Note this calls
468 // setState_TPX() again; Just wanted to make sure that cantera is in sync
469 // with VolPhase after this call.
470 setMoleFractions(Xmol_Base);
473}
474
476{
477 // update the Ln Act Coeff Jacobian entries with respect to the mole number
478 // of species in the phase -> we always assume that they are out of date.
480
481 // Now copy over the values
482 for (size_t j = 0; j < m_numSpecies; j++) {
483 size_t jglob = IndSpecies[j];
484 for (size_t k = 0; k < m_numSpecies; k++) {
485 size_t kglob = IndSpecies[k];
486 np_LnACJac_VCS(kglob,jglob) = np_dLnActCoeffdMolNumber(k,j);
487 }
488 }
489}
490
492{
493 return v_totalMoles;
494}
495
496double vcs_VolPhase::molefraction(size_t k) const
497{
498 return Xmol_[k];
499}
500
501void vcs_VolPhase::setCreationMoleNumbers(span<const double> n_k,
502 span<const size_t> creationGlobalRxnNumbers)
503{
504 checkArraySize("vcs_VolPhase::setCreationMoleNumbers", n_k.size(), m_numSpecies);
505 checkArraySize("vcs_VolPhase::setCreationMoleNumbers", creationGlobalRxnNumbers.size(), m_numSpecies);
506 creationMoleNumbers_.assign(n_k.begin(), n_k.end());
507 for (size_t k = 0; k < m_numSpecies; k++) {
508 creationGlobalRxnNumbers_[k] = creationGlobalRxnNumbers[k];
509 }
510}
511
513 span<size_t> creationGlobalRxnNumbers) const
514{
515 checkArraySize("vcs_VolPhase::creationMoleNumbers", creationGlobalRxnNumbers.size(), m_numSpecies);
517 creationGlobalRxnNumbers.begin());
519}
520
521void vcs_VolPhase::setTotalMoles(const double totalMols)
522{
523 v_totalMoles = totalMols;
524 if (m_singleSpecies && (m_phiVarIndex == 0)) {
526 } else {
527 if (totalMols > 0.0) {
529 } else {
531 }
532 }
533}
534
536{
537 m_UpToDate = false;
538 if (stateCalc != -1) {
539 m_vcsStateStatus = stateCalc;
540 }
541}
542
544{
545 m_UpToDate = true;
546 m_vcsStateStatus = stateCalc;
547}
548
550{
551 return m_isIdealSoln;
552}
553
555{
556 return m_phiVarIndex;
557}
558
559void vcs_VolPhase::setPhiVarIndex(size_t phiVarIndex)
560{
561 m_phiVarIndex = phiVarIndex;
562 m_speciesUnknownType[m_phiVarIndex] = VCS_SPECIES_TYPE_INTERFACIALVOLTAGE;
563 if (m_singleSpecies && m_phiVarIndex == 0) {
564 m_existence = VCS_PHASE_EXIST_ALWAYS;
565 }
566}
567
569{
570 return m_existence;
571}
572
573void vcs_VolPhase::setExistence(const int existence)
574{
575 if (existence == VCS_PHASE_EXIST_NO || existence == VCS_PHASE_EXIST_ZEROEDPHASE) {
576 if (v_totalMoles != 0.0) {
577 throw CanteraError("vcs_VolPhase::setExistence",
578 "setting false existence for phase with moles");
579 }
580 } else if (v_totalMoles == 0.0 && (!m_singleSpecies || m_phiVarIndex != 0)) {
581 throw CanteraError("vcs_VolPhase::setExistence",
582 "setting true existence for phase with no moles");
583 }
584 if (m_singleSpecies && m_phiVarIndex == 0 && (existence == VCS_PHASE_EXIST_NO || existence == VCS_PHASE_EXIST_ZEROEDPHASE)) {
585 throw CanteraError("vcs_VolPhase::setExistence",
586 "Trying to set existence of an electron phase to false");
587 }
588 m_existence = existence;
589}
590
591size_t vcs_VolPhase::spGlobalIndexVCS(const size_t spIndex) const
592{
593 return IndSpecies[spIndex];
594}
595
596void vcs_VolPhase::setSpGlobalIndexVCS(const size_t spIndex,
597 const size_t spGlobalIndex)
598{
599 IndSpecies[spIndex] = spGlobalIndex;
600 if (spGlobalIndex >= m_numElemConstraints) {
601 creationGlobalRxnNumbers_[spIndex] = spGlobalIndex - m_numElemConstraints;
602 }
603}
604
605size_t vcs_VolPhase::elemGlobalIndex(const size_t e) const
606{
607 AssertThrow(e < m_numElemConstraints, " vcs_VolPhase::elemGlobalIndex");
608 return m_elemGlobalIndex[e];
609}
610
611void vcs_VolPhase::setElemGlobalIndex(const size_t eLocal, const size_t eGlobal)
612{
614 "vcs_VolPhase::setElemGlobalIndex");
615 m_elemGlobalIndex[eLocal] = eGlobal;
616}
617
619{
621}
622
623string vcs_VolPhase::elementName(size_t e) const
624{
625
626 if (e < m_elementNames.size()) {
627 return m_elementNames[e];
628 }
629 throw IndexError("vcs_VolPhase::elementName", "element", e, m_elementNames.size());
630}
631
632//! This function decides whether a phase has charged species or not.
633static bool hasChargedSpecies(const ThermoPhase* const tPhase)
634{
635 for (size_t k = 0; k < tPhase->nSpecies(); k++) {
636 if (tPhase->charge(k) != 0.0) {
637 return true;
638 }
639 }
640 return false;
641}
642
643//! This utility routine decides whether a Cantera ThermoPhase needs
644//! a constraint equation representing the charge neutrality of the
645//! phase. It does this by searching for charged species. If it
646//! finds one, and if the phase needs one, then it returns true.
647static bool chargeNeutralityElement(const ThermoPhase* const tPhase)
648{
649 int hasCharge = hasChargedSpecies(tPhase);
650 if (tPhase->chargeNeutralityNecessary() && hasCharge) {
651 return true;
652 }
653 return false;
654}
655
657{
658 size_t nebase = tPhase->nElements();
659 size_t ne = nebase;
660 size_t ns = tPhase->nSpecies();
661
662 // Decide whether we need an extra element constraint for charge
663 // neutrality of the phase
664 bool cne = chargeNeutralityElement(tPhase);
665 if (cne) {
667 ne++;
668 }
669
670 // Assign and resize structures
671 elemResize(ne);
672
675 }
676
677 size_t eFound = npos;
678 if (hasChargedSpecies(tPhase)) {
679 if (cne) {
680 // We need a charge neutrality constraint. We also have an Electron
681 // Element. These are duplicates of each other. To avoid trouble
682 // with possible range error conflicts, sometimes we eliminate the
683 // Electron condition. Flag that condition for elimination by
684 // toggling the ElActive variable. If we find we need it later, we
685 // will retoggle ElActive to true.
686 for (size_t eT = 0; eT < nebase; eT++) {
687 if (tPhase->elementName(eT) == "E") {
688 eFound = eT;
689 m_elementActive[eT] = 0;
691 }
692 }
693 } else {
694 for (size_t eT = 0; eT < nebase; eT++) {
695 if (tPhase->elementName(eT) == "E") {
696 eFound = eT;
698 }
699 }
700 }
701 if (eFound == npos) {
702 eFound = ne;
704 m_elementActive[ne] = 0;
705 string ename = "E";
706 m_elementNames[ne] = ename;
707 ne++;
708 elemResize(ne);
709 }
710 }
711
712 m_formulaMatrix.resize(ns, ne, 0.0);
714 elemResize(ne);
715
716 size_t e = 0;
717 for (size_t eT = 0; eT < nebase; eT++) {
718 m_elementNames[e] = tPhase->elementName(eT);
719 m_elementType[e] = tPhase->elementType(eT);
720 e++;
721 }
722
723 if (cne) {
724 string pname = tPhase->name();
725 if (pname == "") {
726 pname = fmt::format("phase{}", VP_ID_);
727 }
729 m_elementNames[e] = "cn_" + pname;
730 }
731
732 for (size_t k = 0; k < ns; k++) {
733 e = 0;
734 for (size_t eT = 0; eT < nebase; eT++) {
735 m_formulaMatrix(k,e) = tPhase->nAtoms(k, eT);
736 e++;
737 }
738 if (eFound != npos) {
739 m_formulaMatrix(k,eFound) = - tPhase->charge(k);
740 }
741 }
742
743 if (cne) {
744 for (size_t k = 0; k < ns; k++) {
746 }
747 }
748
749 // Here, we figure out what is the species types are The logic isn't set in
750 // stone, and is just for a particular type of problem that I'm solving
751 // first.
752 if (ns == 1 && tPhase->charge(0) != 0.0) {
754 setPhiVarIndex(0);
755 }
756
757 return ne;
758}
759
760int vcs_VolPhase::elementType(const size_t e) const
761{
762 return m_elementType[e];
763}
764
766{
767 return m_formulaMatrix;
768}
769
770int vcs_VolPhase::speciesUnknownType(const size_t k) const
771{
772 return m_speciesUnknownType[k];
773}
774
775int vcs_VolPhase::elementActive(const size_t e) const
776{
777 return m_elementActive[e];
778}
779
781{
782 return m_numSpecies;
783}
784
786{
787 return TP_ptr->type();
788}
789}
Header file for class ThermoPhase, the base class for phases with thermodynamic properties,...
A class for 2D arrays stored in column-major (Fortran-compatible) form.
Definition Array.h:32
Base class for exceptions thrown by Cantera classes.
An array index is out of range.
size_t nSpecies() const
Returns the number of species in the phase.
Definition Phase.h:247
int elementType(size_t m) const
Return the element constraint type Possible types include:
Definition Phase.cpp:89
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
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:562
string name() const
Return the name of the phase.
Definition Phase.cpp:20
Base class for a phase with thermodynamic properties.
bool chargeNeutralityNecessary() const
Returns the chargeNeutralityNecessity boolean.
This is the main structure used to hold the internal data used in vcs_solve_TP(), and to solve TP sys...
Definition vcs_solve.h:44
void setMoleFractions(span< const double > xmol)
Set the mole fractions from a conventional mole fraction vector.
vector< double > StarChemicalPotential
Vector of calculated Star chemical potentials for the current Temperature and pressure.
void setElectricPotential(const double phi)
set the electric potential of the phase
bool m_UpToDate_GStar
Boolean indicating whether GStar is up to date.
double electricPotential() const
Returns the electric field of the phase.
size_t m_phiVarIndex
If the potential is a solution variable in VCS, it acts as a species.
vector< double > Xmol_
Vector of the current mole fractions for species in the phase.
double Temp_
Current value of the temperature for this object, and underlying objects.
int speciesUnknownType(const size_t k) const
Returns the type of the species unknown.
size_t elemGlobalIndex(const size_t e) const
Returns the global index of the local element index for the phase.
void _updateGStar() const
Gibbs free energy calculation for standard states.
vector< double > SS0ChemicalPotential
Vector of calculated SS0 chemical potentials for the current Temperature.
void setMolesFromVCS(const int stateCalc, span< const double > molesSpeciesVCS={})
Set the moles within the phase.
size_t nSpecies() const
Return the number of species in the phase.
void setMolesOutOfDate(int stateCalc=-1)
Sets the mole flag within the object to out of date.
vector< string > m_elementNames
vector of strings containing the element constraint names
vector< int > m_elementActive
boolean indicating whether an element constraint is active for the current problem
vector< double > creationMoleNumbers_
Vector of current creationMoleNumbers_.
double _updateVolPM() const
Calculate the partial molar volumes of all species and return the total volume.
double m_totalVol
Total Volume of the phase. Units are m**3.
size_t ChargeNeutralityElement
This is the element number for the charge neutrality condition of the phase.
vector< size_t > m_elemGlobalIndex
Index of the element number in the global list of elements stored in VCS_SOLVE.
size_t VP_ID_
Original ID of the phase in the problem.
Array2D np_dLnActCoeffdMolNumber
Vector of the derivatives of the ln activity coefficient wrt to the current mole number multiplied by...
const Array2D & getFormulaMatrix() const
Get a constant form of the Species Formula Matrix.
vector< int > m_speciesUnknownType
Type of the species unknown.
void sendToVCS_ActCoeff(const int stateCalc, span< double > AC)
Fill in an activity coefficients vector within a VCS_SOLVE object.
bool m_UpToDate_VolStar
Boolean indicating whether Star volumes are up to date.
void updateFromVCS_MoleNumbers(const int stateCalc)
Update the moles within the phase, if necessary.
size_t phiVarIndex() const
Return the index of the species that represents the the voltage of the phase.
double v_totalMoles
Total mols in the phase. units are kmol.
bool m_singleSpecies
If true, this phase consists of a single species.
void setElemGlobalIndex(const size_t eLocal, const size_t eGlobal)
sets a local phase element to a global index value
int m_MFStartIndex
This is always equal to zero.
bool m_isIdealSoln
Boolean indicating whether the phase is an ideal solution and therefore its molar-based activity coef...
vector< double > ActCoeff
Vector of calculated activity coefficients for the current state.
int exists() const
Retrieve the kth Species structure for the species belonging to this phase.
vector< size_t > IndSpecies
Index into the species vectors.
size_t nElemConstraints() const
Returns the number of element constraints.
double m_phi
Value of the potential for the phase (Volts).
size_t spGlobalIndexVCS(const size_t spIndex) const
Return the Global VCS index of the kth species in the phase.
size_t transferElementsFM(const ThermoPhase *const tPhase)
Transfer all of the element information from the ThermoPhase object to the vcs_VolPhase object.
vector< int > m_elementType
Type of the element constraint.
span< const double > moleFractions() const
Return a const reference to the mole fractions stored in the object.
double GStar_calc_one(size_t kspec) const
Gibbs free energy calculation for standard state of one species.
void setMolesFromVCSCheck(const int vcsStateStatus, span< const double > molesSpeciesVCS, span< const double > TPhMoles)
Set the moles within the phase.
void _updateVolStar() const
Molar volume calculation for standard states.
int m_vcsStateStatus
Status.
bool m_UpToDate_G0
Boolean indicating whether G0 is up to date.
void _updateG0() const
Gibbs free energy calculation at a temperature for the reference state of each species.
double Pres_
Current value of the pressure for this object, and underlying objects.
vector< double > PartialMolarVol
Vector of the Partial molar Volumes of the species. units m3 / kmol.
double molefraction(size_t kspec) const
Returns the mole fraction of the kspec species.
Array2D m_formulaMatrix
Formula Matrix for the phase.
void _updateLnActCoeffJac()
Evaluation of Activity Coefficient Jacobians.
string elementName(size_t e) const
Name of the element constraint with index e.
void setTotalMoles(const double totalMols)
Sets the total moles in the phase.
void setCreationMoleNumbers(span< const double > n_k, span< const size_t > creationGlobalRxnNumbers)
Sets the creationMoleNum's within the phase object.
void setMolesCurrent(int vcsStateStatus)
Sets the mole flag within the object to be current.
size_t m_numElemConstraints
Number of element constraints within the problem.
vector< double > StarMolarVol
Vector of the Star molar Volumes of the species. units m3 / kmol.
void sendToVCS_LnActCoeffJac(Array2D &LnACJac_VCS)
Downloads the ln ActCoeff Jacobian into the VCS version of the ln ActCoeff Jacobian.
span< const double > creationMoleNumbers(span< size_t > creationGlobalRxnNumbers) const
Return a const reference to the creationMoleNumbers stored in the object.
double G0_calc_one(size_t kspec) const
Gibbs free energy calculation at a temperature for the reference state of a species,...
void _updateActCoeff() const
Evaluate the activity coefficients at the current conditions.
void setState_TP(const double temperature_Kelvin, const double pressure_PA)
Sets the temperature and pressure in this object and underlying ThermoPhase objects.
int m_existence
Current state of existence:
string eos_name() const
Return the name corresponding to the equation of state.
bool m_UpToDate_AC
Boolean indicating whether activity coefficients are up to date.
VCS_SOLVE * m_owningSolverObject
Backtrack value of VCS_SOLVE *.
void setMoleFractionsState(const double molNum, span< const double > moleFracVec, const int vcsStateStatus)
Set the moles and/or mole fractions within the phase.
ThermoPhase * TP_ptr
Vector of Species structures for the species belonging to this phase.
void _updateMoleFractionDependencies()
Updates the mole fraction dependencies.
double sendToVCS_VolPM(span< double > VolPM) const
Fill in the partial molar volume vector for VCS.
void sendToVCS_GStar(span< double > gstar) const
Fill in the standard state Gibbs free energy vector for VCS.
int elementType(const size_t e) const
Type of the element constraint with index e.
vector< size_t > creationGlobalRxnNumbers_
Vector of creation global reaction numbers for the phase stability problem.
void setSpGlobalIndexVCS(const size_t spIndex, const size_t spGlobalIndex)
set the Global VCS index of the kth species in the phase
size_t m_numSpecies
Number of species in the phase.
void setExistence(const int existence)
Set the existence flag in the object.
bool m_UpToDate
Boolean indicating whether the object has an up-to-date mole number vector and potential with respect...
bool m_UpToDate_VolPM
Boolean indicating whether partial molar volumes are up to date.
bool isIdealSoln() const
Returns whether the phase is an ideal solution phase.
double totalMoles() const
Return the total moles in the phase.
#define AssertThrow(expr, procedure)
Assertion must be true or an error is thrown.
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
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
static bool chargeNeutralityElement(const ThermoPhase *const tPhase)
This utility routine decides whether a Cantera ThermoPhase needs a constraint equation representing t...
static bool hasChargedSpecies(const ThermoPhase *const tPhase)
This function decides whether a phase has charged species or not.
bool vcs_doubleEqual(double d1, double d2)
Simple routine to check whether two doubles are equal up to roundoff error.
Definition vcs_util.cpp:89
void checkArraySize(const char *procedure, size_t available, size_t required)
Wrapper for throwing ArraySizeError.
Contains declarations for string manipulation functions within Cantera.
Header for the object representing each phase within vcs.
#define VCS_SPECIES_TYPE_INTERFACIALVOLTAGE
Unknown refers to the voltage level of a phase.
Definition vcs_defs.h:197
#define VCS_STATECALC_OLD
State Calculation based on the old or base mole numbers.
Definition vcs_defs.h:206
#define VCS_STATECALC_TMP
State Calculation based on a temporary set of mole numbers.
Definition vcs_defs.h:217
#define VCS_PHASE_EXIST_NO
Phase doesn't currently exist in the mixture.
Definition vcs_defs.h:147
#define VCS_PHASE_EXIST_ALWAYS
These defines are valid values for the phase existence flag.
Definition vcs_defs.h:141
#define VCS_ELEM_TYPE_ABSPOS
Normal element constraint consisting of positive coefficients for the formula matrix.
Definition vcs_defs.h:170
#define VCS_STATECALC_NEW
State Calculation based on the new or tentative mole numbers.
Definition vcs_defs.h:209
#define VCS_SPECIES_TYPE_MOLNUM
Unknown refers to mole number of a single species.
Definition vcs_defs.h:189
#define VCS_ELEM_TYPE_ELECTRONCHARGE
This refers to conservation of electrons.
Definition vcs_defs.h:176
#define VCS_ELEM_TYPE_CHARGENEUTRALITY
This refers to a charge neutrality of a single phase.
Definition vcs_defs.h:182
#define VCS_PHASE_EXIST_YES
Phase is a normal phase that currently exists.
Definition vcs_defs.h:144
#define VCS_PHASE_EXIST_ZEROEDPHASE
Phase currently is zeroed due to a programmatic issue.
Definition vcs_defs.h:153
Header file for the internal object that holds the vcs equilibrium problem (see Class VCS_SOLVE and C...