23MultiPhase::~MultiPhase()
25 for (
size_t i = 0; i <
m_phase.size(); i++) {
26 m_phase[i]->removeSpeciesLock();
34 "phases cannot be added after init() has been called.");
37 if (!p->compatibleWithMultiPhase()) {
38 throw CanteraError(
"MultiPhase::addPhase",
"Phase '{}'' is not "
39 "compatible with MultiPhase equilibrium solver", p->name());
50 m_nsp += p->nSpecies();
56 for (
size_t m = 0; m < p->nElements(); m++) {
57 string ename = p->elementName(m);
68 if (ename ==
"E" || ename ==
"e") {
79 if (
m_temp == 298.15 && p->temperature() > 2.0E-3) {
91 if (p->nSpecies() > 1) {
110 for (
size_t m = 0; m <
m_nel; m++) {
113 for (
size_t ip = 0; ip <
nPhases(); ip++) {
115 size_t nsp = p->nSpecies();
116 size_t mlocal = p->elementIndex(
m_enames[m],
false);
117 for (
size_t kp = 0; kp < nsp; kp++) {
118 if (mlocal !=
npos) {
119 m_atoms(m, k) = p->nAtoms(kp, mlocal);
122 m_snames.push_back(p->speciesName(kp));
146 m_phase[n]->setMoleFractions_NoNorm(
161 for (
size_t i = 0; i <
nPhases(); i++) {
162 double phasesum = 0.0;
163 size_t nsp =
m_phase[i]->nSpecies();
164 for (
size_t ik = 0; ik < nsp; ik++) {
176 for (
size_t i = 0; i <
nPhases(); i++) {
194 double phasesum = 0.0;
195 size_t nsp =
m_phase[p]->nSpecies();
196 for (
size_t ik = 0; ik < nsp; ik++) {
207 for (
size_t i = 0; i <
nPhases(); i++) {
208 size_t nsp =
m_phase[i]->nSpecies();
209 m_phase[i]->getChemPotentials(mu.subspan(loc, nsp));
220 for (
size_t i = 0; i <
nPhases(); i++) {
223 m_phase[i]->getChemPotentials(mu.subspan(loc,
m_phase[i]->nSpecies()));
225 m_phase[i]->getStandardChemPotentials(
226 mu.subspan(loc,
m_phase[i]->nSpecies()));
229 fill(mu.begin() + loc, mu.begin() + loc +
m_phase[i]->nSpecies(), not_mu);
248 for (
size_t i = 0; i <
nPhases(); i++) {
260 for (
size_t i = 0; i <
nPhases(); i++) {
272 for (
size_t i = 0; i <
nPhases(); i++) {
284 for (
size_t i = 0; i <
nPhases(); i++) {
296 for (
size_t i = 0; i <
nPhases(); i++) {
310 p->setState_TPX(
m_temp,
m_press, x.subspan(0, p->nSpecies()));
312 for (
size_t k = 0; k < p->nSpecies(); k++) {
320 vector<double> moles(kk, 0.0);
321 for (
size_t k = 0; k < kk; k++) {
338 double* dtmp = molNum.data();
339 for (
size_t ip = 0; ip <
nPhases(); ip++) {
340 double phasemoles =
m_moles[ip];
341 size_t nsp =
m_phase[ip]->nSpecies();
342 for (
size_t ik = 0; ik < nsp; ik++) {
343 *(dtmp++) *= phasemoles;
356 for (
size_t ip = 0; ip <
nPhases(); ip++) {
358 size_t nsp = p->nSpecies();
359 double phasemoles = 0.0;
360 for (
size_t ik = 0; ik < nsp; ik++) {
366 if (phasemoles > 0.0) {
382 for (
size_t eGlobal = 0; eGlobal <
m_nel; eGlobal++) {
391 for (
size_t eGlobal = 0; eGlobal <
m_nel; eGlobal++) {
394 for (
size_t ip = 0; ip <
nPhases(); ip++) {
395 size_t nspPhase =
m_phase[ip]->nSpecies();
396 double phasemoles =
m_moles[ip];
397 for (
size_t ik = 0; ik < nspPhase; ik++) {
398 size_t kGlobal = loc + ik;
400 for (
size_t eGlobal = 0; eGlobal <
m_nel; eGlobal++) {
411 for (
size_t i = 0; i <
nPhases(); i++) {
412 double vol = 1.0/
m_phase[i]->molarDensity();
420struct EquilPhaseGuard
422 explicit EquilPhaseGuard(
MultiPhase& mix) : m_mix(mix)
424 for (
size_t ip = 0; ip < m_mix.nPhases(); ++ip) {
425 m_mix.phase(ip).beginEquilibrate();
431 for (
size_t ip = 0; ip < m_mix.nPhases(); ++ip) {
432 m_mix.phase(ip).endEquilibrate();
443 int maxiter,
int loglevel)
454 return e.equilibrate(XY, err, maxsteps, loglevel);
455 }
else if (XY == HP) {
458 double Thigh = 2.0*
m_Tmax;
460 for (
int n = 0; n < maxiter; n++) {
468 e.equilibrate(TP, err, maxsteps, loglevel);
488 double cpb = (Hhigh - Hlow)/(Thigh - Tlow);
489 dt = (h0 - hnow)/cpb;
491 double dtmax = 0.5*fabs(Thigh - Tlow);
496 double tnew = sqrt(Tlow*Thigh);
500 double herr = fabs((h0 - hnow)/h0);
505 double tnew =
m_temp + dt;
521 double tnew = 0.5*(
m_temp + Thigh);
522 if (fabs(tnew -
m_temp) < 1.0) {
529 throw CanteraError(
"MultiPhase::equilibrate_MultiPhaseEquil",
530 "No convergence for T");
531 }
else if (XY == SP) {
534 double Thigh = 1.0e6;
535 for (
int n = 0; n < maxiter; n++) {
539 e.equilibrate(TP, err, maxsteps, loglevel);
542 Tlow = std::max(Tlow,
m_temp);
544 Thigh = std::min(Thigh,
m_temp);
546 double dt = (s0 - snow)*
m_temp/
cp();
547 double dtmax = 0.5*fabs(Thigh - Tlow);
548 dtmax = (dtmax > 500.0 ? 500.0 : dtmax);
556 double tnew =
m_temp + dt;
568 double tnew = 0.5*(
m_temp + Thigh);
573 throw CanteraError(
"MultiPhase::equilibrate_MultiPhaseEquil",
574 "No convergence for T");
575 }
else if (XY == TV) {
578 for (
int n = 0; n < maxiter; n++) {
583 e.equilibrate(TP, err, maxsteps, loglevel);
585 double verr = fabs((v0 - vnow)/v0);
592 double dVdP = (
volume() - vnow)/(0.01*pnow);
596 throw CanteraError(
"MultiPhase::equilibrate_MultiPhaseEquil",
603 double rtol,
int max_steps,
int max_iter,
604 int estimate_equil,
int log_level)
609 vector<double> initial_moles =
m_moles;
610 double initial_T =
m_temp;
613 EquilPhaseGuard phase_guard(*
this);
614 if (solver ==
"auto" || solver ==
"vcs") {
616 debuglog(
"Trying VCS equilibrium solver\n", log_level);
618 int ret = eqsolve.
equilibrate(ixy, estimate_equil, log_level-1,
622 "VCS solver failed. Return code: {}", ret);
624 debuglog(
"VCS solver succeeded\n", log_level);
626 }
catch (std::exception& err) {
627 debuglog(
"VCS solver failed.\n", log_level);
634 if (solver ==
"auto") {
641 if (solver ==
"auto" || solver ==
"gibbs") {
643 debuglog(
"Trying MultiPhaseEquil (Gibbs) equilibrium solver\n",
647 debuglog(
"MultiPhaseEquil solver succeeded\n", log_level);
649 }
catch (std::exception& err) {
650 debuglog(
"MultiPhaseEquil solver failed.\n", log_level);
661 if (solver !=
"auto") {
663 "Invalid solver specified: '" + solver +
"'");
681 throw IndexError(
"MultiPhase::checkElementIndex",
"elements", m,
m_nel);
694 for (
size_t e = 0; e <
m_nel; e++) {
702 throw CanteraError(
"MultiPhase::elementIndex",
"Element '{}' not found", name);
734 for (
int iph = 0; iph < (int)
nPhases(); iph++) {
735 if (
m_phase[iph]->name() == pName) {
742 throw CanteraError(
"MultiPhase::phaseIndex",
"Phase '{}' not found", pName);
773 for (
size_t ip = 0; ip <
nPhases(); ip++) {
775 p->getMoleFractions(span<double>(
m_moleFractions.data() + loc, p->nSpecies()));
776 loc += p->nSpecies();
784 for (
size_t p = 0; p <
nPhases(); p++) {
785 size_t nsp =
m_phase[p]->nSpecies();
799 for (
size_t ip = 0; ip < x.
nPhases(); ip++) {
801 s <<
"*************** " << x.
phase(ip).
name() <<
" *****************" << std::endl;
803 s <<
"*************** Phase " << ip <<
" *****************" << std::endl;
805 s <<
"Moles: " << x.
phaseMoles(ip) << std::endl;
Headers for the MultiPhase object that is used to set up multiphase equilibrium problems (see Chemica...
Header file for class ThermoPhase, the base class for phases with thermodynamic properties,...
Base class for exceptions thrown by Cantera classes.
void resize(size_t n, size_t m, double v=0.0) override
Resize the matrix.
An array index is out of range.
Multiphase chemical equilibrium solver.
A class for multiphase mixtures.
void getMoleFractions(span< double > x) const
Returns the global Species mole fractions.
void init()
Process phases and build atomic composition array.
size_t speciesIndex(size_t k, size_t p) const
Return the global index of the species belonging to phase number p with local index k within the phas...
bool solutionSpecies(size_t kGlob) const
Return true is species kGlob is a species in a multicomponent solution phase.
void getMoles(span< double > molNum) const
Get the mole numbers of all species in the multiphase object.
double nAtoms(const size_t kGlob, const size_t mGlob) const
Returns the Number of atoms of global element mGlob in global species kGlob.
void setMolesByName(const Composition &xMap)
Set the number of moles of species in the mixture.
DenseMatrix m_atoms
Global Stoichiometric Coefficient array.
double gibbs() const
The Gibbs function of the mixture [J].
void setMoles(span< const double > n)
Sets all of the global species mole numbers.
size_t m_nel
Number of distinct elements in all of the phases.
double speciesMoles(size_t kGlob) const
Returns the moles of global species k. units = kmol.
double m_temp
Current value of the temperature (kelvin)
void calcElemAbundances() const
Calculate the element abundance vector.
size_t nSpecies() const
Number of species, summed over all phases.
size_t checkElementIndex(size_t m) const
Check that the specified element index is in range.
double enthalpy() const
The enthalpy of the mixture [J].
double pressure() const
Pressure [Pa].
vector< size_t > m_spstart
Vector of ints containing of first species index in the global list of species for each phase.
vector< size_t > m_spphase
Mapping between the global species number and the phase ID.
double minTemp() const
Minimum temperature for which all solution phases have valid thermo data.
vector< double > m_moleFractions
Locally stored vector of mole fractions of all species comprising the MultiPhase object.
size_t phaseIndex(const string &pName, bool raise=true) const
Returns the index, given the phase name.
void getElemAbundances(span< double > elemAbundances) const
Retrieves a vector of element abundances.
vector< double > m_elemAbundances
Vector of element abundances.
void setPhaseMoleFractions(const size_t n, span< const double > x)
Set the Mole fractions of the nth phase.
double equilibrate_MultiPhaseEquil(int XY, double err, int maxsteps, int maxiter, int loglevel)
Set the mixture to a state of chemical equilibrium using the MultiPhaseEquil solver.
vector< bool > m_temp_OK
Vector of bools indicating whether temperatures are ok for phases.
double phaseCharge(size_t p) const
Charge (Coulombs) of phase with index p.
size_t nPhases() const
Number of phases.
size_t m_eloc
Global ID of the element corresponding to the electronic charge.
double entropy() const
The entropy of the mixture [J/K].
double moleFraction(const size_t kGlob) const
Returns the mole fraction of global species k.
void getChemPotentials(span< double > mu) const
Returns a vector of Chemical potentials.
string speciesName(size_t kGlob) const
Name of species with global index kGlob.
vector< shared_ptr< ThermoPhase > > m_phase
Vector of phase objects.
double m_press
Current value of the pressure (Pa)
bool tempOK(size_t p) const
Return true if the phase p has valid thermo data for the current temperature.
map< string, size_t > m_enamemap
Returns the global element index, given the element string name.
size_t speciesPhaseIndex(const size_t kGlob) const
Returns the phase index of the Kth "global" species.
void getValidChemPotentials(double not_mu, span< double > mu, bool standard=false) const
Returns a vector of Valid chemical potentials.
void setPressure(double P)
Set the pressure [Pa].
vector< string > m_enames
String names of the global elements.
void addPhase(shared_ptr< ThermoPhase > p, double moles)
Add a phase to the mixture.
double phaseMoles(const size_t n) const
Return the number of moles in phase n.
size_t m_nsp
Number of distinct species in all of the phases.
vector< int > m_atomicNumber
Atomic number of each global element.
double volume() const
The total mixture volume [m^3].
void uploadMoleFractionsFromPhases()
Update the locally-stored composition within this object to match the current compositions of the pha...
bool m_init
True if the init() routine has been called, and the MultiPhase frozen.
vector< string > m_snames
Vector of species names in the problem.
double m_Tmin
Minimum temperature for which thermo parameterizations are valid.
void updatePhases() const
Set the states of the phase objects to the locally-stored state within this MultiPhase object.
double charge() const
Total charge summed over all phases (Coulombs).
double cp() const
Heat capacity at constant pressure [J/K].
size_t elementIndex(const string &name, bool raise=true) const
Returns the index of the element with name name.
void setTemperature(const double T)
Set the temperature [K].
ThermoPhase & phase(size_t n)
Return a reference to phase n.
double maxTemp() const
Maximum temperature for which all solution phases have valid thermo data.
double IntEnergy() const
The internal energy of the mixture [J].
string elementName(size_t m) const
Returns the name of the global element m.
vector< double > m_moles
Vector of the number of moles in each phase.
void setPhaseMoles(const size_t n, const double moles)
Set the number of moles of phase with index n.
double elementMoles(size_t m) const
Total moles of global element m, summed over all phases.
string phaseName(size_t iph) const
Returns the name of the n'th phase.
double m_Tmax
Minimum temperature for which thermo parameterizations are valid.
string name() const
Return the name of the phase.
Base class for a phase with thermodynamic properties.
virtual string report(bool show_thermo=true, double threshold=-1e-14) const
returns a summary of the state of the phase as a string
Cantera's Interface to the Multiphase chemical equilibrium solver.
int equilibrate(int XY, int estimateEquil=0, int printLvl=0, double err=1.0e-6, int maxsteps=VCS_MAXSTEPS, int loglevel=-99)
Equilibrate the solution using the current element abundances stored in the MultiPhase object.
Composition parseCompString(const string &ss, const vector< string > &names)
Parse a composition string into a map consisting of individual key:composition pairs.
void equilibrate(const string &XY, const string &solver="auto", double rtol=1e-9, int max_steps=50000, int max_iter=100, int estimate_equil=0, int log_level=0)
Equilibrate a MultiPhase object.
void debuglog(const string &msg, int loglevel)
Write a message to the log only if loglevel > 0.
const double Faraday
Faraday constant [C/kmol].
Namespace for the Cantera kernel.
const size_t npos
index returned by functions to indicate "no position"
const double Undef
Fairly random number to be used to initialize variables against to see if they are subsequently defin...
int _equilflag(const char *xy)
map property strings to integers
std::ostream & operator<<(std::ostream &s, const Array2D &m)
Output the current contents of the Array2D object.
const U & getValue(const map< T, U > &m, const T &key, const U &default_val)
Const accessor for a value in a map.
map< string, double > Composition
Map from string names to doubles.
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...
Interface class for the vcsnonlinear solver.