19 bool VCS_SOLVE::vcs_popPhasePossible(
const size_t iphasePop)
const
24 int existence = Vphase->
exists();
26 printf(
"ERROR vcs_popPhasePossible called for a phase that exists!");
36 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
39 if (m_molNumSpecies_old[kspec] > 0.0) {
40 printf(
"ERROR vcs_popPhasePossible we shouldn't be here %lu %g > 0.0",
41 kspec, m_molNumSpecies_old[kspec]);
45 size_t irxn = kspec - m_numComponents;
46 if (kspec >= m_numComponents) {
47 bool iPopPossible =
true;
48 for (
size_t j = 0; j < m_numComponents; ++j) {
50 double stoicC = m_stoichCoeffRxnMatrix[irxn][j];
52 double negChangeComp = - stoicC * 1.0;
53 if (negChangeComp > 0.0) {
72 for (
size_t jrxn = 0; jrxn < m_numRxnRdc; jrxn++) {
73 bool foundJrxn =
false;
75 if (m_stoichCoeffRxnMatrix[jrxn][kspec] > 0.0) {
77 for (
size_t kcomp = 0; kcomp < m_numComponents; kcomp++) {
78 if (m_stoichCoeffRxnMatrix[jrxn][kcomp] < 0.0) {
90 else if (m_stoichCoeffRxnMatrix[jrxn][kspec] < 0.0) {
92 size_t jspec = jrxn + m_numComponents;
97 for (
size_t kcomp = 0; kcomp < m_numComponents; kcomp++) {
98 if (m_stoichCoeffRxnMatrix[jrxn][kcomp] > 0.0) {
115 int VCS_SOLVE::vcs_phasePopDeterminePossibleList()
121 std::vector<int> linkedPhases;
122 phasePopProblemLists_.clear();
134 std::vector< std::vector<size_t> > zeroedComponentLinkedPhasePops(m_numComponents);
138 for (
size_t j = 0; j < m_numComponents; j++) {
140 molComp = m_molNumSpecies_old[j];
141 if (molComp <= 0.0) {
142 std::vector<size_t> &jList = zeroedComponentLinkedPhasePops[j];
143 size_t iph = m_phaseID[j];
144 jList.push_back(iph);
145 for (
size_t irxn = 0; irxn < m_numRxnTot; irxn++) {
146 size_t kspec = irxn + m_numComponents;
147 iph = m_phaseID[kspec];
148 Vphase = m_VolPhaseList[iph];
149 int existence = Vphase->
exists();
151 stoicC = m_stoichCoeffRxnMatrix[irxn][j];
153 if (std::find(jList.begin(), jList.end(), iph) != jList.end()) {
154 jList.push_back(iph);
168 std::vector< std::vector<size_t> > zeroedPhaseLinkedZeroComponents(m_numPhases);
172 for (
size_t iph = 0; iph < m_numPhases; iph++) {
173 std::vector<size_t> &iphList = zeroedPhaseLinkedZeroComponents[iph];
175 Vphase = m_VolPhaseList[iph];
176 int existence = Vphase->
exists();
179 linkedPhases.clear();
181 for (
size_t k = 0; k < nsp; k++) {
183 size_t irxn = kspec - m_numComponents;
185 for (
size_t j = 0; j < m_numComponents; j++) {
187 molComp = m_molNumSpecies_old[j];
188 if (molComp <= 0.0) {
189 stoicC = m_stoichCoeffRxnMatrix[irxn][j];
191 bool foundPos =
false;
192 for (
size_t kk = 0; kk < nsp; kk++) {
194 if (kkspec >= m_numComponents) {
195 size_t iirxn = kkspec - m_numComponents;
196 if (m_stoichCoeffRxnMatrix[iirxn][j] > 0.0) {
202 if (std::find(iphList.begin(), iphList.end(), j) != iphList.end()) {
203 iphList.push_back(j);
218 for (
size_t iph = 0; iph < m_numPhases; iph++) {
219 Vphase = m_VolPhaseList[iph];
220 int existence = Vphase->
exists();
222 std::vector<size_t> &iphList = zeroedPhaseLinkedZeroComponents[iph];
223 std::vector<size_t> popProblem(0);
224 popProblem.push_back(iph);
225 for (
size_t i = 0; i < iphList.size(); i++) {
226 size_t j = iphList[i];
227 std::vector<size_t> &jList = zeroedComponentLinkedPhasePops[j];
228 for (
size_t jjl = 0; jjl < jList.size(); jjl++) {
229 size_t jph = jList[jjl];
230 if (std::find(popProblem.begin(), popProblem.end(), jph) != popProblem.end()) {
231 popProblem.push_back(jph);
235 phasePopProblemLists_.push_back(popProblem);
242 size_t VCS_SOLVE::vcs_popPhaseID(std::vector<size_t> & phasePopPhaseIDs)
244 size_t iphasePop =
npos;
246 doublereal FephaseMax = -1.0E30;
247 doublereal Fephase = -1.0E30;
253 if (m_debug_print_lvl >= 2) {
254 plogf(
" --- vcs_popPhaseID() called\n");
255 plogf(
" --- Phase Status F_e MoleNum\n");
256 plogf(
" --------------------------------------------------------------------------\n");
259 for (
size_t iph = 0; iph < m_numPhases; iph++) {
260 Vphase = m_VolPhaseList[iph];
261 int existence = Vphase->
exists();
268 if (m_debug_print_lvl >= 2) {
269 plogf(
" --- %18s %5d NA %11.3e\n",
272 m_tPhaseMoles_old[iph]);
283 irxn = kspec - m_numComponents;
284 doublereal deltaGRxn = m_deltaGRxn_old[irxn];
285 Fephase = exp(-deltaGRxn) - 1.0;
288 strcpy(anote,
" (ready to be birthed)");
290 if (Fephase > FephaseMax) {
292 FephaseMax = Fephase;
294 strcpy(anote,
" (chosen to be birthed)");
300 strcpy(anote,
" (not stable)");
301 if (m_tPhaseMoles_old[iph] > 0.0) {
302 printf(
"shouldn't be here\n");
309 if (m_debug_print_lvl >= 2) {
310 plogf(
" --- %18s %5d %10.3g %10.3g %s\n",
313 m_tPhaseMoles_old[iph], anote);
323 if (vcs_popPhasePossible(iph)) {
324 Fephase = vcs_phaseStabilityTest(iph);
326 if (Fephase > FephaseMax) {
328 FephaseMax = Fephase;
331 if (Fephase > FephaseMax) {
332 FephaseMax = Fephase;
336 if (m_debug_print_lvl >= 2) {
337 plogf(
" --- %18s %5d %11.3g %11.3g\n",
340 m_tPhaseMoles_old[iph]);
345 if (m_debug_print_lvl >= 2) {
346 plogf(
" --- %18s %5d blocked %11.3g\n",
348 existence, m_tPhaseMoles_old[iph]);
355 phasePopPhaseIDs.resize(0);
356 if (iphasePop !=
npos) {
357 phasePopPhaseIDs.push_back(iphasePop);
366 if (m_debug_print_lvl >= 2) {
367 plogf(
" ---------------------------------------------------------------------\n");
373 int VCS_SOLVE::vcs_popPhaseRxnStepSizes(
const size_t iphasePop)
379 size_t irxn = kspec - m_numComponents;
380 std::vector<size_t> creationGlobalRxnNumbers;
390 int existence = Vphase->
exists();
392 printf(
"ERROR vcs_popPhaseRxnStepSizes called for a phase that exists!");
396 if (m_debug_print_lvl >= 2) {
397 plogf(
" --- vcs_popPhaseRxnStepSizes() called to pop phase %s %d into existence\n",
404 double* dnPhase_irxn = m_deltaMolNumPhase[irxn];
405 for (
size_t j = 0; j < m_numComponents; ++j) {
407 if (m_molNumSpecies_old[j] > 0.0) {
408 s += SQUARE(m_stoichCoeffRxnMatrix[irxn][j]) / m_molNumSpecies_old[j];
412 for (
size_t j = 0; j < m_numPhases; j++) {
413 Vphase = m_VolPhaseList[j];
415 if (m_tPhaseMoles_old[j] > 0.0) {
416 s -= SQUARE(dnPhase_irxn[j]) / m_tPhaseMoles_old[j];
422 s = vcs_Hessian_diag_adj(irxn, s_old);
425 sprintf(anote,
"Normal calc: diag adjusted from %g "
426 "to %g due to act coeff", s_old, s);
429 m_deltaMolNumSpecies[kspec] = -m_deltaGRxn_new[irxn] / s;
433 m_deltaMolNumSpecies[kspec] = tPhaseMoles;
439 for (
size_t j = 0; j < m_numComponents; ++j) {
440 double stoicC = m_stoichCoeffRxnMatrix[irxn][j];
443 double negChangeComp = - stoicC * m_deltaMolNumSpecies[kspec];
444 if (negChangeComp > m_molNumSpecies_old[j]) {
445 if (m_molNumSpecies_old[j] > 0.0) {
447 sprintf(anote,
"Delta damped from %g "
448 "to %g due to component %lu (%10s) going neg", m_deltaMolNumSpecies[kspec],
449 -m_molNumSpecies_old[j]/stoicC, j, m_speciesName[j].c_str());
451 m_deltaMolNumSpecies[kspec] = - 0.5 * m_molNumSpecies_old[j] / stoicC;
454 sprintf(anote,
"Delta damped from %g "
455 "to %g due to component %lu (%10s) zero", m_deltaMolNumSpecies[kspec],
456 -m_molNumSpecies_old[j]/stoicC, j, m_speciesName[j].c_str());
458 m_deltaMolNumSpecies[kspec] = 0.0;
465 if (-m_deltaMolNumSpecies[kspec] > m_molNumSpecies_old[kspec]) {
467 sprintf(anote,
"Delta damped from %g "
468 "to %g due to %s going negative", m_deltaMolNumSpecies[kspec],
469 -m_molNumSpecies_old[kspec], m_speciesName[kspec].c_str());
471 m_deltaMolNumSpecies[kspec] = -m_molNumSpecies_old[kspec];
476 vector<doublereal> fracDelta(Vphase->
nSpecies());
477 vector<doublereal> X_est(Vphase->
nSpecies());
480 double sumFrac = 0.0;
481 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
482 sumFrac += fracDelta[k];
484 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
485 X_est[k] = fracDelta[k] / sumFrac;
488 doublereal deltaMolNumPhase = tPhaseMoles;
489 doublereal damp = 1.0;
490 m_deltaGRxn_tmp = m_molNumSpecies_old;
491 double* molNumSpecies_tmp =
DATA_PTR(m_deltaGRxn_tmp);
494 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
496 double delmol = deltaMolNumPhase * X_est[k];
497 if (kspec >= m_numComponents) {
498 irxn = kspec - m_numComponents;
499 for (
size_t j = 0; j < m_numComponents; ++j) {
500 double stoicC = m_stoichCoeffRxnMatrix[irxn][j];
503 molNumSpecies_tmp[j] += stoicC * delmol;
510 doublereal ratioComp = 0.0;
511 for (
size_t j = 0; j < m_numComponents; ++j) {
512 double deltaJ = m_molNumSpecies_old[j] - molNumSpecies_tmp[j];
513 if (molNumSpecies_tmp[j] < 0.0) {
516 double delta0 = m_molNumSpecies_old[j];
517 double dampj = delta0 / deltaJ * 0.9;
524 size_t jph = m_phaseID[j];
525 if ((jph != iphasePop) && (!m_SSPhase[j])) {
526 double fdeltaJ = fabs(deltaJ);
527 if (m_molNumSpecies_old[j] > 0.0) {
528 ratioComp = std::max(ratioComp, fdeltaJ/ m_molNumSpecies_old[j]);
539 if (ratioComp > 1.0E-30) {
540 if (ratioComp < 0.001) {
541 damp = 0.001 / ratioComp;
546 if (damp <= 1.0E-6) {
550 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
552 if (kspec < m_numComponents) {
555 m_deltaMolNumSpecies[kspec] = deltaMolNumPhase * X_est[k] * damp;
556 if (X_est[k] > 1.0E-3) {
569 double VCS_SOLVE::vcs_phaseStabilityTest(
const size_t iph)
574 size_t kspec, irxn, k, i, kc, kc_spec;
576 const size_t nsp = Vphase->
nSpecies();
577 doublereal deltaGRxn;
578 int minNumberIterations = 3;
580 minNumberIterations = 1;
584 bool doSuccessiveSubstitution =
true;
585 double funcPhaseStability;
586 vector<doublereal> X_est(nsp, 0.0);
587 vector<doublereal> delFrac(nsp, 0.0);
588 vector<doublereal> E_phi(nsp, 0.0);
589 vector<doublereal> fracDelta_new(nsp, 0.0);
590 vector<doublereal> fracDelta_old(nsp, 0.0);
591 vector<doublereal> fracDelta_raw(nsp, 0.0);
592 vector<size_t> creationGlobalRxnNumbers(nsp,
npos);
595 vector<doublereal> m_feSpecies_Deficient(m_numComponents, 0.0);
596 doublereal damp = 1.0;
597 doublereal dampOld = 1.0;
598 doublereal normUpdate = 1.0;
599 doublereal normUpdateOld = 1.0;
600 doublereal sum = 0.0;
601 doublereal dirProd = 0.0;
602 doublereal dirProdOld = 0.0;
612 std::vector<size_t> componentList;
614 for (k = 0; k < nsp; k++) {
616 if (kspec < m_numComponents) {
617 componentList.push_back(k);
621 for (k = 0; k < m_numComponents; k++) {
622 m_feSpecies_Deficient[k] = m_feSpecies_old[k];
627 if (doSuccessiveSubstitution) {
631 if (m_debug_print_lvl >= 2) {
632 plogf(
" --- vcs_phaseStabilityTest() called\n");
633 plogf(
" --- Its X_old[%2d] FracDel_old[%2d] deltaF[%2d] FracDel_new[%2d]"
634 " normUpdate damp FuncPhaseStability\n", KP, KP, KP, KP);
635 plogf(
" --------------------------------------------------------------"
636 "--------------------------------------------------------\n");
637 }
else if (m_debug_print_lvl == 1) {
638 plogf(
" --- vcs_phaseStabilityTest() called for phase %d\n", iph);
642 for (k = 0; k < nsp; k++) {
643 if (fracDelta_new[k] < 1.0E-13) {
644 fracDelta_new[k] = 1.0E-13;
647 bool converged =
false;
648 for (
int its = 0; its < 200 && (!converged); its++) {
651 normUpdateOld = normUpdate;
652 fracDelta_old = fracDelta_new;
653 dirProdOld = dirProd;
657 for (i = 0; i < componentList.size(); i++) {
658 kc = componentList[i];
660 fracDelta_old[kc] = 0.0;
661 for (k = 0; k < nsp; k++) {
663 if (kspec >= m_numComponents) {
664 irxn = kspec - m_numComponents;
665 fracDelta_old[kc] += m_stoichCoeffRxnMatrix[irxn][kc_spec] * fracDelta_old[k];
671 double sumFrac = 0.0;
672 for (k = 0; k < nsp; k++) {
673 sumFrac += fracDelta_old[k];
676 if (sumFrac <= 0.0) {
679 double sum_Xcomp = 0.0;
680 for (k = 0; k < nsp; k++) {
681 X_est[k] = fracDelta_old[k] / sumFrac;
683 if (kc_spec < m_numComponents) {
684 sum_Xcomp += X_est[k];
704 for (i = 0; i < componentList.size(); i++) {
705 kc = componentList[i];
708 m_feSpecies_Deficient[kc_spec] = m_feSpecies_old[kc_spec]
709 + log(m_actCoeffSpecies_new[kc_spec] * X_est[kc]);
711 m_feSpecies_Deficient[kc_spec] = m_feSpecies_old[kc_spec]
716 for (i = 0; i < componentList.size(); i++) {
717 kc = componentList[i];
720 for (k = 0; k < Vphase->
nSpecies(); k++) {
722 if (kspec >= m_numComponents) {
723 irxn = kspec - m_numComponents;
725 m_deltaGRxn_Deficient[irxn] = m_deltaGRxn_old[irxn];
727 double* dtmp_ptr = m_stoichCoeffRxnMatrix[irxn];
728 if (dtmp_ptr[kc_spec] != 0.0) {
729 m_deltaGRxn_Deficient[irxn] +=
730 dtmp_ptr[kc_spec] * (m_feSpecies_Deficient[kc_spec]- m_feSpecies_old[kc_spec]);
741 funcPhaseStability = sum_Xcomp - 1.0;
742 for (k = 0; k < nsp; k++) {
744 if (kspec >= m_numComponents) {
745 irxn = kspec - m_numComponents;
746 deltaGRxn = m_deltaGRxn_Deficient[irxn];
747 if (deltaGRxn > 50.0) {
750 if (deltaGRxn < -50.0) {
753 E_phi[k] = std::exp(-deltaGRxn) / m_actCoeffSpecies_new[kspec];
755 funcPhaseStability += E_phi[k];
764 for (k = 0; k < nsp; k++) {
766 double b = E_phi[k] / sum * (1.0 - sum_Xcomp);
767 if (kspec >= m_numComponents) {
768 irxn = kspec - m_numComponents;
769 fracDelta_raw[k] = b;
776 for (i = 0; i < componentList.size(); i++) {
777 kc = componentList[i];
779 fracDelta_raw[kc] = 0.0;
780 for (k = 0; k < nsp; k++) {
782 if (kspec >= m_numComponents) {
783 irxn = kspec - m_numComponents;
784 fracDelta_raw[kc] += m_stoichCoeffRxnMatrix[irxn][kc_spec] * fracDelta_raw[k];
794 doublereal sumADel = 0.0;
795 for (k = 0; k < nsp; k++) {
796 delFrac[k] = fracDelta_raw[k] - fracDelta_old[k];
797 sumADel += fabs(delFrac[k]);
802 for (k = 0; k < nsp; k++) {
803 dirProd += fracDelta_old[k] * delFrac[k];
805 bool crossedSign =
false;
806 if (dirProd * dirProdOld < 0.0) {
812 if (dampOld < 0.25) {
813 damp = 2.0 * dampOld;
816 if (normUpdate *1.5 > normUpdateOld) {
817 damp = 0.5 * dampOld;
818 }
else if (normUpdate *2.0 > normUpdateOld) {
819 damp = 0.8 * dampOld;
822 if (normUpdate > normUpdateOld * 2.0) {
823 damp = 0.6 * dampOld;
824 }
else if (normUpdate > normUpdateOld * 1.2) {
825 damp = 0.9 * dampOld;
829 for (k = 0; k < nsp; k++) {
830 if (fabs(damp * delFrac[k]) > 0.3*fabs(fracDelta_old[k])) {
831 damp = std::max(0.3*fabs(fracDelta_old[k]) / fabs(delFrac[k]),
832 1.0E-8/fabs(delFrac[k]));
834 if (delFrac[k] < 0.0) {
835 if (2.0 * damp * (-delFrac[k]) > fracDelta_old[k]) {
836 damp = fracDelta_old[k] / (2.0 * (-delFrac[k]));
839 if (delFrac[k] > 0.0) {
840 if (2.0 * damp * delFrac[k] > fracDelta_old[k]) {
841 damp = fracDelta_old[k] / (2.0 * delFrac[k]);
845 if (damp < 0.000001) {
849 for (k = 0; k < nsp; k++) {
850 fracDelta_new[k] = fracDelta_old[k] + damp * (delFrac[k]);
854 if (m_debug_print_lvl >= 2) {
855 plogf(
" --- %3d %12g %12g %12g %12g %12g %12g %12g\n", its, X_est[KP], fracDelta_old[KP],
856 delFrac[KP], fracDelta_new[KP], normUpdate, damp, funcPhaseStability);
860 if (normUpdate < 1.0E-5 * damp) {
862 if (its < minNumberIterations) {
883 printf(
"not done yet\n");
887 if (m_debug_print_lvl >= 2) {
888 plogf(
" ------------------------------------------------------------"
889 "-------------------------------------------------------------\n");
890 }
else if (m_debug_print_lvl == 1) {
891 if (funcPhaseStability > 0.0) {
892 plogf(
" --- phase %d with func = %g is to be born\n", iph, funcPhaseStability);
894 plogf(
" --- phase %d with func = %g stays dead\n", iph, funcPhaseStability);
898 return funcPhaseStability;
#define VCS_SPECIES_MINOR
Species is a major species.
std::string PhaseName
String name for the phase.
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.
#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.
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.
Phase information and Phase calculations for vcs.
#define VCS_DELETE_MINORSPECIES_CUTOFF
Cutoff relative mole number value, below which species are deleted from the equilibrium problem...
Internal declarations for the VCSnonideal package.
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.
#define VCS_DELETE_PHASE_CUTOFF
Cutoff relative moles below which a phase is deleted from the equilibrium problem.
size_t spGlobalIndexVCS(const size_t spIndex) const
Return the Global VCS index of the kth species in the phase.
#define VCS_SPECIES_MAJOR
Species is a major species.
double vcs_l2norm(const std::vector< double > vec)
determine the l2 norm of a vector of doubles
size_t nSpecies() const
Return the number of species in the phase.
bool m_singleSpecies
If true, this phase consists of a single species.
#define VCS_STATECALC_OLD
State Calculation based on the old or base mole numbers.
void sendToVCS_ActCoeff(const int stateCalc, double *const AC)
Fill in an activity coefficients vector within a VCS_SOLVE object.
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
int exists() const
int indicating whether the phase exists or not
#define plogf
define this Cantera function to replace printf
#define VCS_SPECIES_COMPONENT
Species is a component which can be nonzero.
void setMoleFractionsState(const double molNum, const double *const moleFracVec, const int vcsStateStatus)
Set the moles and/or mole fractions within the phase.