24 VCS_SOLVE::VCS_SOLVE() :
28 m_numElemConstraints(0),
33 m_numRxnMinorZeroed(0),
44 m_totalMoleScale(1.0),
47 m_Faraday_dim(ElectronCharge *
Avogadro),
54 void VCS_SOLVE::vcs_initSizes(
const size_t nspecies0,
const size_t nelements,
58 if ((nspecies0 != NSPECIES0) || (nelements != m_numElemConstraints) || (nphase0 != NPHASE0)) {
65 NSPECIES0 = nspecies0;
67 m_numSpeciesTot = nspecies0;
68 m_numElemConstraints = nelements;
69 m_numComponents = nelements;
71 string ser =
"VCS_SOLVE: ERROR:\n\t";
73 plogf(
"%s Number of species is nonpositive\n", ser);
75 " Number of species is nonpositive\n");
78 plogf(
"%s Number of elements is nonpositive\n", ser);
80 " Number of species is nonpositive\n");
83 plogf(
"%s Number of phases is nonpositive\n", ser);
85 " Number of species is nonpositive\n");
92 m_stoichCoeffRxnMatrix.resize(nelements, nspecies0, 0.0);
93 m_scSize.resize(nspecies0, 0.0);
94 m_spSize.resize(nspecies0, 1.0);
95 m_SSfeSpecies.resize(nspecies0, 0.0);
96 m_feSpecies_new.resize(nspecies0, 0.0);
97 m_molNumSpecies_old.resize(nspecies0, 0.0);
99 m_deltaMolNumPhase.resize(nphase0, nspecies0, 0.0);
100 m_phaseParticipation.resize(nphase0, nspecies0, 0);
101 m_phasePhi.resize(nphase0, 0.0);
102 m_molNumSpecies_new.resize(nspecies0, 0.0);
103 m_deltaGRxn_new.resize(nspecies0, 0.0);
104 m_deltaGRxn_old.resize(nspecies0, 0.0);
105 m_deltaGRxn_Deficient.resize(nspecies0, 0.0);
106 m_deltaGRxn_tmp.resize(nspecies0, 0.0);
107 m_deltaMolNumSpecies.resize(nspecies0, 0.0);
108 m_feSpecies_old.resize(nspecies0, 0.0);
109 m_elemAbundances.resize(nelements, 0.0);
110 m_elemAbundancesGoal.resize(nelements, 0.0);
111 m_tPhaseMoles_old.resize(nphase0, 0.0);
112 m_tPhaseMoles_new.resize(nphase0, 0.0);
113 m_deltaPhaseMoles.resize(nphase0, 0.0);
114 m_TmpPhase.resize(nphase0, 0.0);
115 m_TmpPhase2.resize(nphase0, 0.0);
116 m_formulaMatrix.resize(nspecies0, nelements);
117 TPhInertMoles.resize(nphase0, 0.0);
120 m_speciesMapIndex.resize(nspecies0, 0);
121 m_speciesLocalPhaseIndex.resize(nspecies0, 0);
124 m_elementMapIndex.resize(nelements, 0);
129 m_indexRxnToSpecies.resize(nspecies0, 0);
132 m_speciesStatus.resize(nspecies0, 1);
134 m_SSPhase.resize(2*nspecies0, 0);
135 m_phaseID.resize(nspecies0, 0);
136 m_numElemConstraints = nelements;
137 m_elementName.resize(nelements);
138 m_speciesName.resize(nspecies0);
140 m_elementActive.resize(nelements, 1);
143 m_actConventionSpecies.resize(nspecies0, 0);
144 m_phaseActConvention.resize(nphase0, 0);
145 m_lnMnaughtSpecies.resize(nspecies0, 0.0);
146 m_actCoeffSpecies_new.resize(nspecies0, 1.0);
147 m_actCoeffSpecies_old.resize(nspecies0, 1.0);
148 m_wtSpecies.resize(nspecies0, 0.0);
149 m_chargeSpecies.resize(nspecies0, 0.0);
153 m_VolPhaseList.resize(nphase0, 0);
154 for (
size_t iph = 0; iph < nphase0; iph++) {
159 m_useActCoeffJac =
true;
160 if (m_useActCoeffJac) {
161 m_np_dLnActCoeffdMolNum.resize(nspecies0, nspecies0, 0.0);
164 m_PMVolumeSpecies.resize(nspecies0, 0.0);
168 vcs_counters_init(1);
171 m_timing_print_lvl = 0;
177 VCS_SOLVE::~VCS_SOLVE()
182 void VCS_SOLVE::vcs_delete_memory()
184 size_t nspecies = m_numSpeciesTot;
186 for (
size_t j = 0; j < m_numPhases; j++) {
187 delete m_VolPhaseList[j];
188 m_VolPhaseList[j] = 0;
191 for (
size_t j = 0; j < nspecies; j++) {
192 delete m_speciesThermoList[j];
193 m_speciesThermoList[j] = 0;
201 m_numElemConstraints = 0;
205 int VCS_SOLVE::vcs(
VCS_PROB* vprob,
int ifunc,
int ipr,
int ip1,
int maxit)
207 int retn = 0, iconv = 0;
210 int iprintTime = std::max(ipr, ip1);
211 iprintTime = std::min(iprintTime, m_timing_print_lvl);
214 plogf(
"vcs: Unrecognized value of ifunc, %d: bailing!\n",
222 size_t nspecies0 = vprob->
nspecies + 10;
223 size_t nelements0 = vprob->
ne;
224 size_t nphase0 = vprob->
NPhase;
225 vcs_initSizes(nspecies0, nelements0, nphase0);
228 plogf(
"vcs_priv_alloc returned a bad status, %d: bailing!\n",
234 retn = vcs_prob_specifyFully(vprob);
236 plogf(
"vcs_pub_to_priv returned a bad status, %d: bailing!\n",
243 retn = vcs_prep_oneTime(ip1);
245 plogf(
"vcs_prep_oneTime returned a bad status, %d: bailing!\n",
253 retn = vcs_prob_specify(vprob);
255 plogf(
"vcs_prob_specify returned a bad status, %d: bailing!\n",
265 plogf(
"vcs_prep returned a bad status, %d: bailing!\n", retn);
270 if (!vcs_wellPosed(vprob)) {
271 plogf(
"vcs has determined the problem is not well posed: Bailing\n");
282 iconv = vcs_TP(ipr, ip1, maxit, vprob->
T, vprob->
PresPA);
291 vcs_prob_update(vprob);
296 m_VCount->T_Time_vcs += te;
297 if (iprintTime > 0) {
298 vcs_TCounters_report(m_timing_print_lvl);
304 plogf(
"ERROR: FAILURE its = %d!\n", m_VCount->Its);
305 }
else if (iconv == 1) {
306 plogf(
"WARNING: RANGE SPACE ERROR encountered\n");
311 int VCS_SOLVE::vcs_prob_specifyFully(
const VCS_PROB* pub)
314 "vcs_pub_to_priv ERROR :ill defined interface -> bailout:\n\t";
318 if (NSPECIES0 < nspecies) {
319 plogf(
"%sPrivate Data is dimensioned too small\n", ser);
324 plogf(
"%sPrivate Data is dimensioned too small\n", ser);
327 size_t nelements = pub->
ne;
328 if (m_numElemConstraints < nelements) {
329 plogf(
"%sPrivate Data is dimensioned too small\n", ser);
334 m_numElemConstraints = nelements;
335 m_numSpeciesTot = nspecies;
336 m_numSpeciesRdc = m_numSpeciesTot;
340 m_numComponents = nelements;
346 if (nelements > nspecies) {
349 m_numRxnTot = nspecies - nelements;
351 m_numRxnRdc = m_numRxnTot;
354 m_numRxnMinorZeroed = 0;
362 for (
size_t i = 0; i < nspecies; i++) {
363 bool nonzero =
false;
364 for (
size_t j = 0; j < nelements; j++) {
371 plogf(
"vcs_prob_specifyFully:: species %d %s has a zero formula matrix!\n", i,
381 m_chargeSpecies = pub->
Charge;
384 for (
size_t kspec = 0; kspec < nspecies; kspec++) {
385 delete m_speciesThermoList[kspec];
388 if (m_speciesThermoList[kspec] == NULL) {
389 plogf(
" duplMyselfAsVCS_SPECIES_THERMO returned an error!\n");
398 m_doEstimateEquil = pub->
iest;
401 if (pub->
w.size() != 0) {
402 m_molNumSpecies_old = pub->
w;
404 m_doEstimateEquil = -1;
405 m_molNumSpecies_old.assign(m_molNumSpecies_old.size(), 0.0);
409 if (pub->
gai.size() != 0) {
410 for (
size_t i = 0; i < nelements; i++) {
411 m_elemAbundancesGoal[i] = pub->
gai[i];
413 m_elemAbundancesGoal[i] = 0.0;
417 if (m_doEstimateEquil == 0) {
419 for (
size_t j = 0; j < nelements; j++) {
420 m_elemAbundancesGoal[j] = 0.0;
421 for (
size_t kspec = 0; kspec < nspecies; kspec++) {
423 sum += m_molNumSpecies_old[kspec];
424 m_elemAbundancesGoal[j] += m_formulaMatrix(kspec,j) * m_molNumSpecies_old[kspec];
428 m_elemAbundancesGoal[j] = 0.0;
432 plogf(
"%sElement Abundances, m_elemAbundancesGoal[], not specified\n", ser);
445 m_temperature = pub->
T;
447 m_temperature = 293.15;
450 m_pressurePA = pub->
PresPA;
456 for (
size_t iph = 0; iph < nph; iph++) {
464 m_tolmaj2 = 0.01 * m_tolmaj;
465 m_tolmin2 = 0.01 * m_tolmin;
469 for (
size_t i = 0; i < nspecies; i++) {
470 m_speciesMapIndex[i] = i;
474 for (
size_t i = 0; i < nelements; i++) {
475 m_elementMapIndex[i] = i;
479 for (
size_t i = 0; i < nspecies; i++) {
485 if (pub->
PhaseID.size() != 0) {
486 std::vector<size_t> numPhSp(nph, 0);
487 for (
size_t kspec = 0; kspec < nspecies; kspec++) {
488 size_t iph = pub->
PhaseID[kspec];
490 plogf(
"%sSpecies to Phase Mapping, PhaseID, has a bad value\n",
492 plogf(
"\tPhaseID[%d] = %d\n", kspec, iph);
493 plogf(
"\tAllowed values: 0 to %d\n", nph - 1);
496 m_phaseID[kspec] = pub->
PhaseID[kspec];
497 m_speciesLocalPhaseIndex[kspec] = numPhSp[iph];
500 for (
size_t iph = 0; iph < nph; iph++) {
502 if (numPhSp[iph] != Vphase->
nSpecies()) {
503 plogf(
"%sNumber of species in phase %d, %s, doesn't match\n",
509 if (m_numPhases == 1) {
510 for (
size_t kspec = 0; kspec < nspecies; kspec++) {
511 m_phaseID[kspec] = 0;
512 m_speciesLocalPhaseIndex[kspec] = kspec;
515 plogf(
"%sSpecies to Phase Mapping, PhaseID, is not defined\n", ser);
522 m_elementActive.resize(nelements, 1);
525 for (
size_t i = 0; i < nelements; i++) {
526 m_elementName[i] = pub->
ElName[i];
528 m_elementActive[i] = pub->
ElActive[i];
529 if (!strncmp(m_elementName[i].c_str(),
"cn_", 3)) {
533 "we have an inconsistency!");
538 for (
size_t i = 0; i < nelements; i++) {
540 if (m_elemAbundancesGoal[i] != 0.0) {
541 if (fabs(m_elemAbundancesGoal[i]) > 1.0E-9) {
543 "Charge neutrality condition {} is signicantly " 544 "nonzero, {}. Giving up",
545 m_elementName[i], m_elemAbundancesGoal[i]);
547 if (m_debug_print_lvl >= 2) {
548 plogf(
"Charge neutrality condition %s not zero, %g. Setting it zero\n",
549 m_elementName[i], m_elemAbundancesGoal[i]);
551 m_elemAbundancesGoal[i] = 0.0;
559 for (
size_t i = 0; i < nspecies; i++) {
560 m_speciesName[i] = pub->
SpName[i];
565 for (
size_t iph = 0; iph < nph; iph++) {
571 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
579 for (
size_t iph = 0; iph < nph; iph++) {
590 double mnaught = m_wtSpecies[iSolvent] / 1000.;
591 for (
size_t k = 1; k < Vphase->
nSpecies(); k++) {
594 m_lnMnaughtSpecies[kspec] = log(mnaught);
600 if (pub->Title.size() == 0) {
601 m_title =
"Unspecified Problem Title";
603 m_title = pub->Title;
607 m_totalVol = pub->
Vol;
608 if (m_PMVolumeSpecies.size() != 0) {
609 m_PMVolumeSpecies = pub->
VolPM;
616 int VCS_SOLVE::vcs_prob_specify(
const VCS_PROB* pub)
618 string yo(
"vcs_prob_specify ERROR: ");
621 m_temperature = pub->
T;
622 m_pressurePA = pub->
PresPA;
623 m_doEstimateEquil = pub->
iest;
624 m_totalVol = pub->
Vol;
627 m_tolmaj2 = 0.01 * m_tolmaj;
628 m_tolmin2 = 0.01 * m_tolmin;
630 for (
size_t kspec = 0; kspec < m_numSpeciesTot; ++kspec) {
631 size_t k = m_speciesMapIndex[kspec];
632 m_molNumSpecies_old[kspec] = pub->
w[k];
633 m_molNumSpecies_new[kspec] = pub->
mf[k];
638 for (
size_t i = 0; i < m_numElemConstraints; i++) {
639 size_t j = m_elementMapIndex[i];
640 m_elemAbundancesGoal[i] = pub->
gai[j];
644 if (pub->Title.size() == 0) {
645 if (m_title.size() == 0) {
646 m_title =
"Unspecified Problem Title";
649 m_title = pub->Title;
655 bool status_change =
false;
656 for (
size_t iph = 0; iph < m_numPhases; iph++) {
661 plogf(
"%sPhase numbers have changed:%d %d\n",
667 plogf(
"%sSingleSpecies value have changed:%d %d\n",
673 plogf(
"%sGasPhase value have changed:%d %d\n",
681 plogf(
"%sNVolSpecies value have changed:%d %d\n",
687 plogf(
"%sPhaseName value have changed:%s %s\n",
693 status_change =
true;
699 if (TPhInertMoles[iph] > 0.0) {
722 m_totalVol = vcs_VolTotal(m_temperature, m_pressurePA,
723 &m_molNumSpecies_old[0], &m_PMVolumeSpecies[0]);
725 for (
size_t i = 0; i < m_numSpeciesTot; ++i) {
728 for (
size_t j = 0; j < m_numSpeciesTot; ++j) {
730 if (m_speciesMapIndex[j] == i) {
737 pub->
w[i] = m_molNumSpecies_old[k1];
742 pub->
VolPM[i] = m_PMVolumeSpecies[k1];
745 pub->
T = m_temperature;
746 pub->
PresPA = m_pressurePA;
747 pub->
Vol = m_totalVol;
749 for (
size_t iph = 0; iph < pub->
NPhase; iph++) {
760 for (
size_t k = 0; k < pubPhase->
nSpecies(); k++) {
762 pub->
mf[kT] = mfVector[k];
765 double tmp = m_molNumSpecies_old[k1];
768 "We have an inconsistency in voltage, {} {}",
775 "We have an inconsistency in mole fraction, {} {}",
779 sumMoles += pub->
w[kT];
784 "We have an inconsistency in total moles, {} {}",
794 void VCS_SOLVE::vcs_counters_init(
int ifunc)
797 m_VCount->Basis_Opts = 0;
798 m_VCount->Time_vcs_TP = 0.0;
799 m_VCount->Time_basopt = 0.0;
802 m_VCount->T_Basis_Opts = 0;
803 m_VCount->T_Calls_Inest = 0;
804 m_VCount->T_Calls_vcs_TP = 0;
805 m_VCount->T_Time_vcs_TP = 0.0;
806 m_VCount->T_Time_basopt = 0.0;
807 m_VCount->T_Time_inest = 0.0;
808 m_VCount->T_Time_vcs = 0.0;
812 double VCS_SOLVE::vcs_VolTotal(
const double tkelvin,
const double pres,
813 const double w[],
double volPM[])
816 for (
size_t iphase = 0; iphase < m_numPhases; iphase++) {
826 void VCS_SOLVE::disableTiming() {
bool vcs_doubleEqual(double d1, double d2)
Simple routine to check whether two doubles are equal up to roundoff error.
vector_fp VolPM
Partial Molar Volumes of species.
bool m_singleSpecies
If true, this phase consists of a single species.
VCS_SPECIES_THERMO * SpeciesThermo
Pointer to the thermo structure for this species.
double totalMolesInert() const
Returns the value of the total kmol of inert in the phase.
void setMoleFractionsState(const double molNum, const double *const moleFracVec, const int vcsStateStatus)
Set the moles and/or mole fractions within the phase.
const doublereal OneAtm
One atmosphere [Pa].
Declarations for a simple class that implements an Ansi C wall clock timer (see Cantera::clockWC).
double Vol
Volume of the entire system.
std::vector< std::string > ElName
vector of strings containing the element names
int p_activityConvention
Convention for the activity formulation.
int iest
Specification of the initial estimate method.
double electricPotential() const
Returns the electric field of the phase.
size_t spGlobalIndexVCS(const size_t spIndex) const
Return the Global VCS index of the kth species in the phase.
int vcs_timing_print_lvl
Global hook for turning on and off time printing.
The class provides the wall clock timer in seconds.
std::string PhaseName
String name for the phase.
std::vector< vcs_VolPhase * > VPhaseList
Array of phase structures.
int m_Iterations
Number of iterations. This is an output variable.
void setExistence(const int existence)
Set the existence flag in the object.
std::vector< size_t > PhaseID
Mapping between the species and the phases.
size_t VP_ID_
Original ID of the phase in the problem.
void setMolesFromVCS(const int stateCalc, const double *molesSpeciesVCS=0)
Set the moles within the phase.
Header file for the internal object that holds the vcs equilibrium problem (see Class VCS_SOLVE and E...
Header for the object representing each phase within vcs.
#define VCS_SPECIES_TYPE_MOLNUM
Unknown refers to mole number of a single species.
#define VCS_ELEM_TYPE_ABSPOS
Normal element constraint consisting of positive coefficients for the formula matrix.
vector_fp gai
Element abundances for jth element.
double tolmin
Tolerance requirement for minor species.
Array2D FormulaMatrix
Formula Matrix for the problem.
double tolmaj
Tolerance requirement for major species.
vector_int ElActive
Specifies whether an element constraint is active.
double secondsWC()
Returns the wall clock time in seconds since the last reset.
Properties of a single species.
vector_int SpeciesUnknownType
Specifies the species unknown type.
Header for the Interface class for the vcs thermo equilibrium solver package,.
int m_eqnState
Type of the equation of state.
virtual VCS_SPECIES_THERMO * duplMyselfAsVCS_SPECIES_THERMO()
Duplication function for derived classes.
vector_fp Charge
Charge of each species.
#define VCS_ELEM_TYPE_CHARGENEUTRALITY
This refers to a charge neutrality of a single phase.
void setElectricPotential(const double phi)
set the electric potential of the phase
size_t nspecies
Total number of species in the problems.
vector_fp w
Total number of moles of the kth species.
size_t nSpecies() const
Return the number of species in the phase.
Base class for exceptions thrown by Cantera classes.
#define VCS_SPECIES_MAJOR
Species is a major species.
bool m_gasPhase
If true, this phase is a gas-phase like phase.
double totalMoles() const
Return the total moles in the phase.
vector_fp WtSpecies
Molecular weight of species.
vector_fp mf
Mole fraction vector.
size_t phiVarIndex() const
Return the index of the species that represents the the voltage of the phase.
int m_NumBasisOptimizations
Number of basis optimizations used. This is an output variable.
Phase information and Phase calculations for vcs.
#define VCS_DIMENSIONAL_G
dimensioned
size_t ne
Number of element constraints in the equilibrium problem.
vector_fp m_gibbsSpecies
Vector of chemical potentials of the species.
const doublereal Avogadro
Avogadro's Number [number/kmol].
std::vector< VCS_SPECIES_THERMO * > SpeciesThermo
Vector of pointers to thermo structures which identify the model and parameters for evaluating the th...
#define VCS_STATECALC_OLD
State Calculation based on the old or base mole numbers.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
std::vector< std::string > SpName
Vector of strings containing the species names.
vector_int m_elType
vector of Element types
vcs_SpeciesProperties * speciesProperty(const size_t kindex)
Retrieve the kth Species structure for the species belonging to this phase.
Contains declarations for string manipulation functions within Cantera.
double sendToVCS_VolPM(double *const VolPM) const
Fill in the partial molar volume vector for VCS.
double T
Temperature (Kelvin)
#define plogf
define this Cantera function to replace printf
#define VCS_SPECIES_TYPE_INTERFACIALVOLTAGE
Unknown refers to the voltage level of a phase.
Class to keep track of time and iterations.
#define VCS_ELEM_TYPE_LATTICERATIO
Constraint associated with maintaining a fixed lattice stoichiometry in the solids.
#define VCS_STATECALC_TMP
State Calculation based on a temporary set of mole numbers.
size_t NPhase
Number of phases in the problem.
Namespace for the Cantera kernel.
const vector_fp & moleFractions() const
Return a const reference to the mole fractions stored in the object.
Interface class for the vcs thermo equilibrium solver package, which generally describes the problem ...
void setState_TP(const double temperature_Kelvin, const double pressure_PA)
Sets the temperature and pressure in this object and underlying ThermoPhase objects.
int vcs_debug_print_lvl
Debug print lvl.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
int speciesUnknownType(const size_t k) const
Returns the type of the species unknown.
double molefraction(size_t kspec) const
Returns the mole fraction of the kspec species.
void setTotalMolesInert(const double tMolesInert)
Sets the total moles of inert in the phase.
void setTotalMoles(const double totalMols)
Sets the total moles in the phase.