28 VCS_SOLVE::VCS_SOLVE() :
32 m_numElemConstraints(0),
37 m_numRxnMinorZeroed(0),
48 m_totalMoleScale(1.0),
51 m_Faraday_dim(ElectronCharge *
Avogadro),
54 m_timing_print_lvl(1),
55 m_VCS_UnitsFormat(VCS_UNITS_UNITLESS)
59 void VCS_SOLVE::vcs_initSizes(
const size_t nspecies0,
const size_t nelements,
63 if ((nspecies0 != NSPECIES0) || (nelements != m_numElemConstraints) || (nphase0 != NPHASE0)) {
70 NSPECIES0 = nspecies0;
72 m_numSpeciesTot = nspecies0;
73 m_numElemConstraints = nelements;
74 m_numComponents = nelements;
76 string ser =
"VCS_SOLVE: ERROR:\n\t";
78 plogf(
"%s Number of species is nonpositive\n", ser.c_str());
80 " Number of species is nonpositive\n");
83 plogf(
"%s Number of elements is nonpositive\n", ser.c_str());
85 " Number of species is nonpositive\n");
88 plogf(
"%s Number of phases is nonpositive\n", ser.c_str());
90 " Number of species is nonpositive\n");
93 m_VCS_UnitsFormat = VCS_UNITS_UNITLESS;
99 m_stoichCoeffRxnMatrix.resize(nelements, nspecies0, 0.0);
101 m_scSize.resize(nspecies0, 0.0);
102 m_spSize.resize(nspecies0, 1.0);
104 m_SSfeSpecies.resize(nspecies0, 0.0);
105 m_feSpecies_new.resize(nspecies0, 0.0);
106 m_molNumSpecies_old.resize(nspecies0, 0.0);
110 m_deltaMolNumPhase.resize(nphase0, nspecies0, 0.0);
111 m_phaseParticipation.resize(nphase0, nspecies0, 0);
112 m_phasePhi.resize(nphase0, 0.0);
114 m_molNumSpecies_new.resize(nspecies0, 0.0);
116 m_deltaGRxn_new.resize(nspecies0, 0.0);
117 m_deltaGRxn_old.resize(nspecies0, 0.0);
118 m_deltaGRxn_Deficient.resize(nspecies0, 0.0);
119 m_deltaGRxn_tmp.resize(nspecies0, 0.0);
120 m_deltaMolNumSpecies.resize(nspecies0, 0.0);
122 m_feSpecies_old.resize(nspecies0, 0.0);
123 m_elemAbundances.resize(nelements, 0.0);
124 m_elemAbundancesGoal.resize(nelements, 0.0);
126 m_tPhaseMoles_old.resize(nphase0, 0.0);
127 m_tPhaseMoles_new.resize(nphase0, 0.0);
128 m_deltaPhaseMoles.resize(nphase0, 0.0);
129 m_TmpPhase.resize(nphase0, 0.0);
130 m_TmpPhase2.resize(nphase0, 0.0);
132 m_formulaMatrix.resize(nspecies0, nelements);
134 TPhInertMoles.resize(nphase0, 0.0);
140 m_speciesMapIndex.resize(nspecies0, 0);
141 m_speciesLocalPhaseIndex.resize(nspecies0, 0);
146 m_elementMapIndex.resize(nelements, 0);
153 m_indexRxnToSpecies.resize(nspecies0, 0);
157 m_speciesStatus.resize(nspecies0, 1);
159 m_SSPhase.resize(2*nspecies0, 0);
160 m_phaseID.resize(nspecies0, 0);
162 m_numElemConstraints = nelements;
164 m_elementName.resize(nelements, std::string(
""));
165 m_speciesName.resize(nspecies0, std::string(
""));
169 m_elementActive.resize(nelements, 1);
174 m_actConventionSpecies.resize(nspecies0, 0);
175 m_phaseActConvention.resize(nphase0, 0);
176 m_lnMnaughtSpecies.resize(nspecies0, 0.0);
177 m_actCoeffSpecies_new.resize(nspecies0, 1.0);
178 m_actCoeffSpecies_old.resize(nspecies0, 1.0);
179 m_wtSpecies.resize(nspecies0, 0.0);
180 m_chargeSpecies.resize(nspecies0, 0.0);
186 m_VolPhaseList.resize(nphase0, 0);
187 for (
size_t iph = 0; iph < nphase0; iph++) {
194 m_useActCoeffJac =
true;
195 if (m_useActCoeffJac) {
196 m_np_dLnActCoeffdMolNum.resize(nspecies0, nspecies0, 0.0);
199 m_PMVolumeSpecies.resize(nspecies0, 0.0);
206 vcs_counters_init(1);
209 m_timing_print_lvl = 0;
216 VCS_SOLVE::~VCS_SOLVE()
221 void VCS_SOLVE::vcs_delete_memory()
223 size_t nspecies = m_numSpeciesTot;
225 for (
size_t j = 0; j < m_numPhases; j++) {
226 delete m_VolPhaseList[j];
227 m_VolPhaseList[j] = 0;
230 for (
size_t j = 0; j < nspecies; j++) {
231 delete m_speciesThermoList[j];
232 m_speciesThermoList[j] = 0;
240 m_numElemConstraints = 0;
244 int VCS_SOLVE::vcs(
VCS_PROB* vprob,
int ifunc,
int ipr,
int ip1,
int maxit)
246 int retn = 0, iconv = 0;
249 int iprintTime = std::max(ipr, ip1);
250 iprintTime = std::min(iprintTime, m_timing_print_lvl);
253 plogf(
"vcs: Unrecognized value of ifunc, %d: bailing!\n",
263 size_t nspecies0 = vprob->
nspecies + 10;
264 size_t nelements0 = vprob->
ne;
265 size_t nphase0 = vprob->
NPhase;
267 vcs_initSizes(nspecies0, nelements0, nphase0);
270 plogf(
"vcs_priv_alloc returned a bad status, %d: bailing!\n",
279 retn = vcs_prob_specifyFully(vprob);
281 plogf(
"vcs_pub_to_priv returned a bad status, %d: bailing!\n",
290 retn = vcs_prep_oneTime(ip1);
292 plogf(
"vcs_prep_oneTime returned a bad status, %d: bailing!\n",
302 retn = vcs_prob_specify(vprob);
304 plogf(
"vcs_prob_specify returned a bad status, %d: bailing!\n",
316 plogf(
"vcs_prep returned a bad status, %d: bailing!\n", retn);
323 if (!vcs_wellPosed(vprob)) {
324 plogf(
"vcs has determined the problem is not well posed: Bailing\n");
338 iconv = vcs_TP(ipr, ip1, maxit, vprob->
T, vprob->
PresPA);
350 vcs_prob_update(vprob);
357 m_VCount->T_Time_vcs += te;
358 if (iprintTime > 0) {
359 vcs_TCounters_report(m_timing_print_lvl);
368 plogf(
"ERROR: FAILURE its = %d!\n", m_VCount->Its);
369 }
else if (iconv == 1) {
370 plogf(
"WARNING: RANGE SPACE ERROR encountered\n");
375 int VCS_SOLVE::vcs_prob_specifyFully(
const VCS_PROB* pub)
378 "vcs_pub_to_priv ERROR :ill defined interface -> bailout:\n\t";
385 if (NSPECIES0 < nspecies) {
386 plogf(
"%sPrivate Data is dimensioned too small\n", ser);
391 plogf(
"%sPrivate Data is dimensioned too small\n", ser);
394 size_t nelements = pub->
ne;
395 if (m_numElemConstraints < nelements) {
396 plogf(
"%sPrivate Data is dimensioned too small\n", ser);
403 m_numElemConstraints = nelements;
404 m_numSpeciesTot = nspecies;
405 m_numSpeciesRdc = m_numSpeciesTot;
410 m_numComponents = nelements;
418 if (nelements > nspecies) {
421 m_numRxnTot = nspecies - nelements;
423 m_numRxnRdc = m_numRxnTot;
427 m_numRxnMinorZeroed = 0;
442 for (
size_t i = 0; i < nspecies; i++) {
443 bool nonzero =
false;
444 for (
size_t j = 0; j < nelements; j++) {
451 plogf(
"vcs_prob_specifyFully:: species %d %s has a zero formula matrix!\n", i,
465 m_chargeSpecies = pub->
Charge;
471 for (
size_t kspec = 0; kspec < nspecies; kspec++) {
472 delete m_speciesThermoList[kspec];
475 if (m_speciesThermoList[kspec] == NULL) {
476 plogf(
" duplMyselfAsVCS_SPECIES_THERMO returned an error!\n");
489 m_doEstimateEquil = pub->
iest;
494 if (pub->
w.size() != 0) {
495 m_molNumSpecies_old = pub->
w;
497 m_doEstimateEquil = -1;
498 m_molNumSpecies_old.assign(m_molNumSpecies_old.size(), 0.0);
504 if (pub->
gai.size() != 0) {
505 for (
size_t i = 0; i < nelements; i++) {
506 m_elemAbundancesGoal[i] = pub->
gai[i];
508 if (m_elemAbundancesGoal[i] < 1.0E-10) {
509 m_elemAbundancesGoal[i] = 0.0;
514 if (m_doEstimateEquil == 0) {
516 for (
size_t j = 0; j < nelements; j++) {
517 m_elemAbundancesGoal[j] = 0.0;
518 for (
size_t kspec = 0; kspec < nspecies; kspec++) {
520 sum += m_molNumSpecies_old[kspec];
521 m_elemAbundancesGoal[j] += m_formulaMatrix(kspec,j) * m_molNumSpecies_old[kspec];
525 if (m_elemAbundancesGoal[j] < 1.0E-10 * sum) {
526 m_elemAbundancesGoal[j] = 0.0;
531 plogf(
"%sElement Abundances, m_elemAbundancesGoal[], not specified\n", ser);
548 m_temperature = pub->
T;
550 m_temperature = 293.15;
553 m_pressurePA = pub->
PresPA;
560 for (
size_t iph = 0; iph < nph; iph++) {
575 m_tolmaj2 = 0.01 * m_tolmaj;
576 m_tolmin2 = 0.01 * m_tolmin;
582 for (
size_t i = 0; i < nspecies; i++) {
583 m_speciesMapIndex[i] = i;
590 for (
size_t i = 0; i < nelements; i++) {
591 m_elementMapIndex[i] = i;
597 for (
size_t i = 0; i < nspecies; i++) {
605 if (pub->
PhaseID.size() != 0) {
606 std::vector<size_t> numPhSp(nph, 0);
607 for (
size_t kspec = 0; kspec < nspecies; kspec++) {
608 size_t iph = pub->
PhaseID[kspec];
610 plogf(
"%sSpecies to Phase Mapping, PhaseID, has a bad value\n",
612 plogf(
"\tPhaseID[%d] = %d\n", kspec, iph);
613 plogf(
"\tAllowed values: 0 to %d\n", nph - 1);
616 m_phaseID[kspec] = pub->
PhaseID[kspec];
617 m_speciesLocalPhaseIndex[kspec] = numPhSp[iph];
620 for (
size_t iph = 0; iph < nph; iph++) {
622 if (numPhSp[iph] != Vphase->
nSpecies()) {
623 plogf(
"%sNumber of species in phase %d, %s, doesn't match\n",
629 if (m_numPhases == 1) {
630 for (
size_t kspec = 0; kspec < nspecies; kspec++) {
631 m_phaseID[kspec] = 0;
632 m_speciesLocalPhaseIndex[kspec] = kspec;
635 plogf(
"%sSpecies to Phase Mapping, PhaseID, is not defined\n", ser);
644 m_elementActive.resize(nelements, 1);
649 for (
size_t i = 0; i < nelements; i++) {
650 m_elementName[i] = pub->
ElName[i];
652 m_elementActive[i] = pub->
ElActive[i];
653 if (!strncmp(m_elementName[i].c_str(),
"cn_", 3)) {
657 "we have an inconsistency!");
662 for (
size_t i = 0; i < nelements; i++) {
664 if (m_elemAbundancesGoal[i] != 0.0) {
665 if (fabs(m_elemAbundancesGoal[i]) > 1.0E-9) {
667 "Charge neutrality condition " + m_elementName[i] +
668 " is signicantly nonzero, " +
fp2str(m_elemAbundancesGoal[i]) +
671 if (m_debug_print_lvl >= 2) {
672 plogf(
"Charge neutrality condition %s not zero, %g. Setting it zero\n",
673 m_elementName[i].c_str(), m_elemAbundancesGoal[i]);
675 m_elemAbundancesGoal[i] = 0.0;
685 for (
size_t i = 0; i < nspecies; i++) {
686 m_speciesName[i] = pub->
SpName[i];
692 for (
size_t iph = 0; iph < nph; iph++) {
693 *(m_VolPhaseList[iph]) = *(pub->
VPhaseList[iph]);
700 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
703 sProp->SpeciesThermo = m_speciesThermoList[kT];
710 for (
size_t iph = 0; iph < nph; iph++) {
724 double mnaught = m_wtSpecies[iSolvent] / 1000.;
725 for (
size_t k = 1; k < Vphase->
nSpecies(); k++) {
728 m_lnMnaughtSpecies[kspec] = log(mnaught);
736 if (pub->Title.size() == 0) {
737 m_title =
"Unspecified Problem Title";
739 m_title = pub->Title;
745 m_totalVol = pub->
Vol;
746 if (m_PMVolumeSpecies.size() != 0) {
747 m_PMVolumeSpecies = pub->
VolPM;
756 int VCS_SOLVE::vcs_prob_specify(
const VCS_PROB* pub)
758 string yo(
"vcs_prob_specify ERROR: ");
761 m_temperature = pub->
T;
762 m_pressurePA = pub->
PresPA;
764 m_doEstimateEquil = pub->
iest;
766 m_totalVol = pub->
Vol;
770 m_tolmaj2 = 0.01 * m_tolmaj;
771 m_tolmin2 = 0.01 * m_tolmin;
773 for (
size_t kspec = 0; kspec < m_numSpeciesTot; ++kspec) {
774 size_t k = m_speciesMapIndex[kspec];
775 m_molNumSpecies_old[kspec] = pub->
w[k];
776 m_molNumSpecies_new[kspec] = pub->
mf[k];
783 for (
size_t i = 0; i < m_numElemConstraints; i++) {
784 size_t j = m_elementMapIndex[i];
785 m_elemAbundancesGoal[i] = pub->
gai[j];
791 if (pub->Title.size() == 0) {
792 if (m_title.size() == 0) {
793 m_title =
"Unspecified Problem Title";
796 m_title = pub->Title;
807 bool status_change =
false;
808 for (
size_t iph = 0; iph < m_numPhases; iph++) {
813 plogf(
"%sPhase numbers have changed:%d %d\n", yo.c_str(),
819 plogf(
"%sSingleSpecies value have changed:%d %d\n", yo.c_str(),
826 plogf(
"%sGasPhase value have changed:%d %d\n", yo.c_str(),
835 plogf(
"%sNVolSpecies value have changed:%d %d\n", yo.c_str(),
842 plogf(
"%sPhaseName value have changed:%s %s\n", yo.c_str(),
849 status_change =
true;
856 if (TPhInertMoles[iph] > 0.0) {
885 m_totalVol = vcs_VolTotal(m_temperature, m_pressurePA,
888 for (
size_t i = 0; i < m_numSpeciesTot; ++i) {
893 for (
size_t j = 0; j < m_numSpeciesTot; ++j) {
895 if (m_speciesMapIndex[j] == i) {
903 pub->
w[i] = m_molNumSpecies_old[k1];
910 pub->
VolPM[i] = m_PMVolumeSpecies[k1];
913 pub->
T = m_temperature;
914 pub->
PresPA = m_pressurePA;
915 pub->
Vol = m_totalVol;
917 for (
size_t iph = 0; iph < pub->
NPhase; iph++) {
927 const std::vector<double> & mfVector = pubPhase->
moleFractions();
928 for (
size_t k = 0; k < pubPhase->
nSpecies(); k++) {
930 pub->
mf[kT] = mfVector[k];
933 double tmp = m_molNumSpecies_old[k1];
936 "We have an inconsistency in voltage, " +
944 "We have an inconsistency in mole fraction, " +
948 sumMoles += pub->
w[kT];
953 "We have an inconsistency in total moles, " +
965 void VCS_SOLVE::vcs_counters_init(
int ifunc)
968 m_VCount->Basis_Opts = 0;
969 m_VCount->Time_vcs_TP = 0.0;
970 m_VCount->Time_basopt = 0.0;
973 m_VCount->T_Basis_Opts = 0;
974 m_VCount->T_Calls_Inest = 0;
975 m_VCount->T_Calls_vcs_TP = 0;
976 m_VCount->T_Time_vcs_TP = 0.0;
977 m_VCount->T_Time_basopt = 0.0;
978 m_VCount->T_Time_inest = 0.0;
979 m_VCount->T_Time_vcs = 0.0;
983 double VCS_SOLVE::vcs_VolTotal(
const double tkelvin,
const double pres,
984 const double w[],
double volPM[])
987 for (
size_t iphase = 0; iphase < m_numPhases; iphase++) {
std::vector< int > ElActive
Specifies whether an element constraint is active.
std::vector< double > WtSpecies
Molecular weight of species.
bool vcs_doubleEqual(double d1, double d2)
Simple routine to check whether two doubles are equal up to roundoff error.
double sendToVCS_VolPM(double *const VolPM) const
Fill in the partial molar volume vector for VCS.
bool m_singleSpecies
If true, this phase consists of a single species.
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].
double totalMolesInert() const
returns the value of the total kmol of inert in the phase
Declarations for a simple class that implements an Ansi C wall clock timer (see Cantera::clockWC).
std::vector< int > SpeciesUnknownType
Specifies the species unknown type.
#define VCS_DATA_PTR(vvv)
Points to the data in a std::vector<> object.
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.
std::vector< double > w
Total number of moles of the kth species.
int speciesUnknownType(const size_t k) const
Returns the type of the species unknown.
size_t nSpecies() const
Return the number of 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.
double totalMoles() const
Return the total moles in 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.
double electricPotential() const
Returns the electric field of the phase.
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...
std::vector< double > VolPM
Partial Molar Volumes of species.
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.
size_t phiVarIndex() const
Return the index of the species that represents the the voltage of the phase.
double tolmin
Tolerance requirement for minor species.
Array2D FormulaMatrix
Formula Matrix for the problem.
double tolmaj
Tolerance requirement for major species.
int m_VCS_UnitsFormat
Units for the chemical potential data, pressure data, volume, and species amounts.
double secondsWC()
Returns the wall clock time in seconds since the last reset.
std::string fp2str(const double x, const std::string &fmt)
Convert a double into a c++ string.
Properties of a single species.
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.
const std::vector< double > & moleFractions() const
Return a const reference to the mole fractions stored in the object.
double molefraction(size_t kspec) const
Returns the mole fraction of the kspec 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.
std::vector< double > mf
Mole fraction vector.
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.
std::vector< double > Charge
Charge of each species.
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
std::vector< int > m_elType
vector of Element types
size_t ne
Number of element constraints in the equilibrium problem.
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 > gai
Element abundances for jth element.
std::vector< std::string > SpName
Vector of strings containing the species names.
vcs_SpeciesProperties * speciesProperty(const size_t kindex)
Retrieve the kth Species structure for the species belonging to this phase.
std::vector< double > m_gibbsSpecies
Vector of chemical potentials of the species.
Contains declarations for string manipulation functions within Cantera.
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.
size_t spGlobalIndexVCS(const size_t spIndex) const
Return the Global VCS index of the kth species in the phase.
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...
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.