16 bool VCS_SOLVE::vcs_popPhasePossible(
const size_t iphasePop)
const
21 "called for a phase that exists!");
29 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
32 "VCS_SOLVE::vcs_popPhasePossible",
33 "we shouldn't be here " +
int2str(kspec) +
" "+
34 fp2str(m_molNumSpecies_old[kspec]) +
" > 0.0");
35 size_t irxn = kspec - m_numComponents;
36 if (kspec >= m_numComponents) {
37 bool iPopPossible =
true;
43 for (
size_t j = 0; j < m_numComponents; ++j) {
45 double stoicC = m_stoichCoeffRxnMatrix(j,irxn);
47 double negChangeComp = - stoicC;
48 if (negChangeComp > 0.0) {
67 for (
size_t jrxn = 0; jrxn < m_numRxnRdc; jrxn++) {
68 bool foundJrxn =
false;
70 if (m_stoichCoeffRxnMatrix(kspec,jrxn) > 0.0) {
73 for (
size_t kcomp = 0; kcomp < m_numComponents; kcomp++) {
74 if (m_stoichCoeffRxnMatrix(kcomp,jrxn) < 0.0) {
85 else if (m_stoichCoeffRxnMatrix(kspec,jrxn) < 0.0) {
87 size_t jspec = jrxn + m_numComponents;
93 for (
size_t kcomp = 0; kcomp < m_numComponents; kcomp++) {
94 if (m_stoichCoeffRxnMatrix(kcomp,jrxn) > 0.0) {
110 int VCS_SOLVE::vcs_phasePopDeterminePossibleList()
113 phasePopProblemLists_.clear();
125 std::vector< std::vector<size_t> > zeroedComponentLinkedPhasePops(m_numComponents);
129 for (
size_t j = 0; j < m_numComponents; j++) {
131 if (m_molNumSpecies_old[j] <= 0.0) {
132 std::vector<size_t> &jList = zeroedComponentLinkedPhasePops[j];
133 size_t iph = m_phaseID[j];
134 jList.push_back(iph);
135 for (
size_t irxn = 0; irxn < m_numRxnTot; irxn++) {
136 size_t kspec = irxn + m_numComponents;
137 iph = m_phaseID[kspec];
139 int existence = Vphase->
exists();
141 if (m_stoichCoeffRxnMatrix(j,irxn) > 0.0) {
142 if (std::find(jList.begin(), jList.end(), iph) != jList.end()) {
143 jList.push_back(iph);
157 std::vector< std::vector<size_t> > zeroedPhaseLinkedZeroComponents(m_numPhases);
158 std::vector<int> linkedPhases;
162 for (
size_t iph = 0; iph < m_numPhases; iph++) {
163 std::vector<size_t> &iphList = zeroedPhaseLinkedZeroComponents[iph];
166 if (Vphase->
exists() < 0) {
168 linkedPhases.clear();
170 for (
size_t k = 0; k < nsp; k++) {
172 size_t irxn = kspec - m_numComponents;
174 for (
size_t j = 0; j < m_numComponents; j++) {
176 if (m_molNumSpecies_old[j] <= 0.0) {
177 if (m_stoichCoeffRxnMatrix(j,irxn) < 0.0) {
178 bool foundPos =
false;
179 for (
size_t kk = 0; kk < nsp; kk++) {
181 if (kkspec >= m_numComponents) {
182 size_t iirxn = kkspec - m_numComponents;
183 if (m_stoichCoeffRxnMatrix(j,iirxn) > 0.0) {
189 if (std::find(iphList.begin(), iphList.end(), j) != iphList.end()) {
190 iphList.push_back(j);
205 for (
size_t iph = 0; iph < m_numPhases; iph++) {
207 if (Vphase->
exists() < 0) {
208 std::vector<size_t> &iphList = zeroedPhaseLinkedZeroComponents[iph];
209 std::vector<size_t> popProblem(0);
210 popProblem.push_back(iph);
211 for (
size_t i = 0; i < iphList.size(); i++) {
212 size_t j = iphList[i];
213 std::vector<size_t> &jList = zeroedComponentLinkedPhasePops[j];
214 for (
size_t jjl = 0; jjl < jList.size(); jjl++) {
215 size_t jph = jList[jjl];
216 if (std::find(popProblem.begin(), popProblem.end(), jph) != popProblem.end()) {
217 popProblem.push_back(jph);
221 phasePopProblemLists_.push_back(popProblem);
228 size_t VCS_SOLVE::vcs_popPhaseID(std::vector<size_t> & phasePopPhaseIDs)
230 size_t iphasePop =
npos;
231 doublereal FephaseMax = -1.0E30;
232 doublereal Fephase = -1.0E30;
236 if (m_debug_print_lvl >= 2) {
237 plogf(
" --- vcs_popPhaseID() called\n");
238 plogf(
" --- Phase Status F_e MoleNum\n");
239 plogf(
" --------------------------------------------------------------------------\n");
244 for (
size_t iph = 0; iph < m_numPhases; iph++) {
246 int existence = Vphase->
exists();
247 if (DEBUG_MODE_ENABLED) {
251 if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
252 plogf(
" --- %18s %5d NA %11.3e\n",
255 m_tPhaseMoles_old[iph]);
265 size_t irxn = kspec - m_numComponents;
266 doublereal deltaGRxn = m_deltaGRxn_old[irxn];
267 Fephase = exp(-deltaGRxn) - 1.0;
269 if (DEBUG_MODE_ENABLED) {
270 strcpy(anote,
" (ready to be birthed)");
272 if (Fephase > FephaseMax) {
274 FephaseMax = Fephase;
275 if (DEBUG_MODE_ENABLED) {
276 strcpy(anote,
" (chosen to be birthed)");
280 if (DEBUG_MODE_ENABLED && Fephase < 0.0) {
281 strcpy(anote,
" (not stable)");
283 "VCS_SOLVE::vcs_popPhaseID",
"shouldn't be here");
286 if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
287 plogf(
" --- %18s %5d %10.3g %10.3g %s\n",
290 m_tPhaseMoles_old[iph], anote);
299 if (vcs_popPhasePossible(iph)) {
300 Fephase = vcs_phaseStabilityTest(iph);
302 if (Fephase > FephaseMax) {
304 FephaseMax = Fephase;
307 FephaseMax = std::max(FephaseMax, Fephase);
309 if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
310 plogf(
" --- %18s %5d %11.3g %11.3g\n",
313 m_tPhaseMoles_old[iph]);
316 if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
317 plogf(
" --- %18s %5d blocked %11.3g\n",
319 existence, m_tPhaseMoles_old[iph]);
325 phasePopPhaseIDs.resize(0);
326 if (iphasePop !=
npos) {
327 phasePopPhaseIDs.push_back(iphasePop);
335 if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
336 plogf(
" ---------------------------------------------------------------------\n");
341 int VCS_SOLVE::vcs_popPhaseRxnStepSizes(
const size_t iphasePop)
347 size_t irxn = kspec - m_numComponents;
348 std::vector<size_t> creationGlobalRxnNumbers;
356 "called for a phase that exists!");
357 if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
358 plogf(
" --- vcs_popPhaseRxnStepSizes() called to pop phase %s %d into existence\n",
364 for (
size_t j = 0; j < m_numComponents; ++j) {
366 if (m_molNumSpecies_old[j] > 0.0) {
367 s += pow(m_stoichCoeffRxnMatrix(j,irxn), 2) / m_molNumSpecies_old[j];
371 for (
size_t j = 0; j < m_numPhases; j++) {
372 Vphase = m_VolPhaseList[j];
374 if (m_tPhaseMoles_old[j] > 0.0) {
375 s -= pow(m_deltaMolNumPhase(j,irxn), 2) / m_tPhaseMoles_old[j];
381 s = vcs_Hessian_diag_adj(irxn, s_old);
382 m_deltaMolNumSpecies[kspec] = -m_deltaGRxn_new[irxn] / s;
386 m_deltaMolNumSpecies[kspec] = tPhaseMoles;
392 for (
size_t j = 0; j < m_numComponents; ++j) {
393 double stoicC = m_stoichCoeffRxnMatrix(j,irxn);
396 double negChangeComp = - stoicC * m_deltaMolNumSpecies[kspec];
397 if (negChangeComp > m_molNumSpecies_old[j]) {
398 if (m_molNumSpecies_old[j] > 0.0) {
399 m_deltaMolNumSpecies[kspec] = - 0.5 * m_molNumSpecies_old[j] / stoicC;
401 m_deltaMolNumSpecies[kspec] = 0.0;
408 if (-m_deltaMolNumSpecies[kspec] > m_molNumSpecies_old[kspec]) {
409 m_deltaMolNumSpecies[kspec] = -m_molNumSpecies_old[kspec];
414 vector<doublereal> fracDelta(Vphase->
nSpecies());
415 vector<doublereal> X_est(Vphase->
nSpecies());
418 double sumFrac = 0.0;
419 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
420 sumFrac += fracDelta[k];
422 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
423 X_est[k] = fracDelta[k] / sumFrac;
426 doublereal deltaMolNumPhase = tPhaseMoles;
427 doublereal damp = 1.0;
428 m_deltaGRxn_tmp = m_molNumSpecies_old;
429 double* molNumSpecies_tmp =
DATA_PTR(m_deltaGRxn_tmp);
432 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
434 double delmol = deltaMolNumPhase * X_est[k];
435 if (kspec >= m_numComponents) {
436 irxn = kspec - m_numComponents;
437 for (
size_t j = 0; j < m_numComponents; ++j) {
438 double stoicC = m_stoichCoeffRxnMatrix(j,irxn);
441 molNumSpecies_tmp[j] += stoicC * delmol;
448 doublereal ratioComp = 0.0;
449 for (
size_t j = 0; j < m_numComponents; ++j) {
450 double deltaJ = m_molNumSpecies_old[j] - molNumSpecies_tmp[j];
451 if (molNumSpecies_tmp[j] < 0.0) {
454 double delta0 = m_molNumSpecies_old[j];
455 damp = std::min(damp, delta0 / deltaJ * 0.9);
459 size_t jph = m_phaseID[j];
460 if ((jph != iphasePop) && (!m_SSPhase[j])) {
461 double fdeltaJ = fabs(deltaJ);
462 if (m_molNumSpecies_old[j] > 0.0) {
463 ratioComp = std::max(ratioComp, fdeltaJ/ m_molNumSpecies_old[j]);
474 if (ratioComp > 1.0E-30) {
475 if (ratioComp < 0.001) {
476 damp = 0.001 / ratioComp;
481 if (damp <= 1.0E-6) {
485 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
487 if (kspec < m_numComponents) {
490 m_deltaMolNumSpecies[kspec] = deltaMolNumPhase * X_est[k] * damp;
491 if (X_est[k] > 1.0E-3) {
504 double VCS_SOLVE::vcs_phaseStabilityTest(
const size_t iph)
510 const size_t nsp = Vphase->
nSpecies();
511 int minNumberIterations = 3;
513 minNumberIterations = 1;
517 bool doSuccessiveSubstitution =
true;
518 double funcPhaseStability;
519 vector<doublereal> X_est(nsp, 0.0);
520 vector<doublereal> delFrac(nsp, 0.0);
521 vector<doublereal> E_phi(nsp, 0.0);
522 vector<doublereal> fracDelta_new(nsp, 0.0);
523 vector<doublereal> fracDelta_old(nsp, 0.0);
524 vector<doublereal> fracDelta_raw(nsp, 0.0);
525 vector<size_t> creationGlobalRxnNumbers(nsp,
npos);
526 m_deltaGRxn_Deficient = m_deltaGRxn_old;
528 vector<doublereal> m_feSpecies_Deficient(m_numComponents, 0.0);
529 doublereal damp = 1.0;
530 doublereal dampOld = 1.0;
531 doublereal normUpdate = 1.0;
532 doublereal normUpdateOld = 1.0;
533 doublereal sum = 0.0;
534 doublereal dirProd = 0.0;
535 doublereal dirProdOld = 0.0;
545 std::vector<size_t> componentList;
547 for (
size_t k = 0; k < nsp; k++) {
549 if (kspec < m_numComponents) {
550 componentList.push_back(k);
554 for (
size_t k = 0; k < m_numComponents; k++) {
555 m_feSpecies_Deficient[k] = m_feSpecies_old[k];
560 if (doSuccessiveSubstitution) {
562 if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
563 plogf(
" --- vcs_phaseStabilityTest() called\n");
564 plogf(
" --- Its X_old[%2d] FracDel_old[%2d] deltaF[%2d] FracDel_new[%2d]"
565 " normUpdate damp FuncPhaseStability\n", KP, KP, KP, KP);
566 plogf(
" --------------------------------------------------------------"
567 "--------------------------------------------------------\n");
568 }
else if (DEBUG_MODE_ENABLED && m_debug_print_lvl == 1) {
569 plogf(
" --- vcs_phaseStabilityTest() called for phase %d\n", iph);
572 for (
size_t k = 0; k < nsp; k++) {
573 if (fracDelta_new[k] < 1.0E-13) {
574 fracDelta_new[k] =1.0E-13;
577 bool converged =
false;
578 for (
int its = 0; its < 200 && (!converged); its++) {
581 normUpdateOld = normUpdate;
582 fracDelta_old = fracDelta_new;
583 dirProdOld = dirProd;
587 for (
size_t i = 0; i < componentList.size(); i++) {
588 size_t kc = componentList[i];
590 fracDelta_old[kc] = 0.0;
591 for (
size_t k = 0; k < nsp; k++) {
593 if (kspec >= m_numComponents) {
594 size_t irxn = kspec - m_numComponents;
595 fracDelta_old[kc] += m_stoichCoeffRxnMatrix(kc_spec,irxn) * fracDelta_old[k];
601 double sumFrac = 0.0;
602 for (
size_t k = 0; k < nsp; k++) {
603 sumFrac += fracDelta_old[k];
606 if (sumFrac <= 0.0) {
609 double sum_Xcomp = 0.0;
610 for (
size_t k = 0; k < nsp; k++) {
611 X_est[k] = fracDelta_old[k] / sumFrac;
613 sum_Xcomp += X_est[k];
633 for (
size_t i = 0; i < componentList.size(); i++) {
634 size_t kc = componentList[i];
637 m_feSpecies_Deficient[kc_spec] = m_feSpecies_old[kc_spec]
638 + log(m_actCoeffSpecies_new[kc_spec] * X_est[kc]);
640 m_feSpecies_Deficient[kc_spec] = m_feSpecies_old[kc_spec]
645 for (
size_t i = 0; i < componentList.size(); i++) {
647 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
649 if (kspec >= m_numComponents) {
650 size_t irxn = kspec - m_numComponents;
652 m_deltaGRxn_Deficient[irxn] = m_deltaGRxn_old[irxn];
654 if (m_stoichCoeffRxnMatrix(kc_spec,irxn) != 0.0) {
655 m_deltaGRxn_Deficient[irxn] +=
656 m_stoichCoeffRxnMatrix(kc_spec,irxn) * (m_feSpecies_Deficient[kc_spec]- m_feSpecies_old[kc_spec]);
667 funcPhaseStability = sum_Xcomp - 1.0;
668 for (
size_t k = 0; k < nsp; k++) {
670 if (kspec >= m_numComponents) {
671 size_t irxn = kspec - m_numComponents;
672 double deltaGRxn =
clip(m_deltaGRxn_Deficient[irxn], -50.0, 50.0);
673 E_phi[k] = std::exp(-deltaGRxn) / m_actCoeffSpecies_new[kspec];
675 funcPhaseStability += E_phi[k];
684 for (
size_t k = 0; k < nsp; k++) {
686 double b = E_phi[k] / sum * (1.0 - sum_Xcomp);
687 if (kspec >= m_numComponents) {
688 fracDelta_raw[k] = b;
695 for (
size_t i = 0; i < componentList.size(); i++) {
696 size_t kc = componentList[i];
698 fracDelta_raw[kc] = 0.0;
699 for (
size_t k = 0; k < nsp; k++) {
701 if (kspec >= m_numComponents) {
702 size_t irxn = kspec - m_numComponents;
703 fracDelta_raw[kc] += m_stoichCoeffRxnMatrix(kc_spec,irxn) * fracDelta_raw[k];
713 doublereal sumADel = 0.0;
714 for (
size_t k = 0; k < nsp; k++) {
715 delFrac[k] = fracDelta_raw[k] - fracDelta_old[k];
716 sumADel += fabs(delFrac[k]);
721 for (
size_t k = 0; k < nsp; k++) {
722 dirProd += fracDelta_old[k] * delFrac[k];
724 bool crossedSign =
false;
725 if (dirProd * dirProdOld < 0.0) {
731 if (dampOld < 0.25) {
732 damp = 2.0 * dampOld;
735 if (normUpdate *1.5 > normUpdateOld) {
736 damp = 0.5 * dampOld;
737 }
else if (normUpdate *2.0 > normUpdateOld) {
738 damp = 0.8 * dampOld;
741 if (normUpdate > normUpdateOld * 2.0) {
742 damp = 0.6 * dampOld;
743 }
else if (normUpdate > normUpdateOld * 1.2) {
744 damp = 0.9 * dampOld;
748 for (
size_t k = 0; k < nsp; k++) {
749 if (fabs(damp * delFrac[k]) > 0.3*fabs(fracDelta_old[k])) {
750 damp = std::max(0.3*fabs(fracDelta_old[k]) / fabs(delFrac[k]),
751 1.0E-8/fabs(delFrac[k]));
753 if (delFrac[k] < 0.0) {
754 if (2.0 * damp * (-delFrac[k]) > fracDelta_old[k]) {
755 damp = fracDelta_old[k] / (2.0 * (-delFrac[k]));
758 if (delFrac[k] > 0.0) {
759 if (2.0 * damp * delFrac[k] > fracDelta_old[k]) {
760 damp = fracDelta_old[k] / (2.0 * delFrac[k]);
764 damp = std::max(damp, 0.000001);
765 for (
size_t k = 0; k < nsp; k++) {
766 fracDelta_new[k] = fracDelta_old[k] + damp * (delFrac[k]);
769 if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
770 plogf(
" --- %3d %12g %12g %12g %12g %12g %12g %12g\n", its, X_est[KP], fracDelta_old[KP],
771 delFrac[KP], fracDelta_new[KP], normUpdate, damp, funcPhaseStability);
774 if (normUpdate < 1.0E-5 * damp) {
776 if (its < minNumberIterations) {
797 throw CanteraError(
"VCS_SOLVE::vcs_phaseStabilityTest",
"not done yet");
799 if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
800 plogf(
" ------------------------------------------------------------"
801 "-------------------------------------------------------------\n");
802 }
else if (DEBUG_MODE_ENABLED && m_debug_print_lvl == 1) {
803 if (funcPhaseStability > 0.0) {
804 plogf(
" --- phase %d with func = %g is to be born\n", iph, funcPhaseStability);
806 plogf(
" --- phase %d with func = %g stays dead\n", iph, funcPhaseStability);
809 return funcPhaseStability;
void setCreationMoleNumbers(const double *const n_k, const std::vector< size_t > &creationGlobalRxnNumbers)
Sets the creationMoleNum's within the phase object.
const std::vector< double > & creationMoleNumbers(std::vector< size_t > &creationGlobalRxnNumbers) const
Return a const reference to the creationMoleNumbers stored in the object.
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
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.
#define VCS_SPECIES_MINOR
Species is a major species.
const size_t npos
index returned by functions to indicate "no position"
#define VCS_DELETE_ELEMENTABS_CUTOFF
Cutoff moles below which a phase or species which comprises the bulk of an element's total concentrat...
#define VCS_DATA_PTR(vvv)
Points to the data in a std::vector<> object.
size_t nSpecies() const
Return the number of species in the phase.
T clip(const T &value, const T &lower, const T &upper)
Clip value such that lower <= value <= upper.
std::string PhaseName
String name for the phase.
#define VCS_STATECALC_PHASESTABILITY
State Calculation based on tentative mole numbers for a phase which is currently zeroed, but is being evaluated for whether it should pop back into existence.
#define AssertThrowMsg(expr, procedure, message)
Assertion must be true or an error is thrown.
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_ELEM_TYPE_ABSPOS
Normal element constraint consisting of positive coefficients for the formula matrix.
#define VCS_DELETE_MINORSPECIES_CUTOFF
Cutoff relative mole number value, below which species are deleted from the equilibrium problem...
std::string fp2str(const double x, const std::string &fmt)
Convert a double into a c++ string.
double vcs_l2norm(const std::vector< double > vec)
determine the l2 norm of a vector of doubles
#define VCS_DELETE_PHASE_CUTOFF
Cutoff relative moles below which a phase is deleted from the equilibrium problem.
Base class for exceptions thrown by Cantera classes.
void sendToVCS_ActCoeff(const int stateCalc, double *const AC)
Fill in an activity coefficients vector within a VCS_SOLVE object.
int exists() const
int indicating whether the phase exists or not
#define VCS_SPECIES_MAJOR
Species is a major species.
Phase information and Phase calculations for vcs.
#define VCS_STATECALC_OLD
State Calculation based on the old or base mole numbers.
Contains declarations for string manipulation functions within Cantera.
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
#define plogf
define this Cantera function to replace printf
#define VCS_SPECIES_COMPONENT
Species is a component which can be nonzero.
size_t spGlobalIndexVCS(const size_t spIndex) const
Return the Global VCS index of the kth species in the phase.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...