21 enum stages {MAIN, EQUILIB_CHECK, ELEM_ABUND_CHECK,
22 RECHECK_DELETED, RETURN_A, RETURN_B};
28 void VCS_SOLVE::checkDelta1(
double*
const dsLocal,
29 double*
const delTPhMoles,
size_t kspec)
32 for (
size_t k = 0; k < kspec; k++) {
34 size_t iph = m_phaseID[k];
35 dchange[iph] += dsLocal[k];
38 for (
size_t iphase = 0; iphase < m_numPhases; iphase++) {
39 double denom = max(m_totalMolNum, 1.0E-4);
40 if (!
vcs_doubleEqual(dchange[iphase]/denom, delTPhMoles[iphase]/denom)) {
41 throw CanteraError(
"VCS_SOLVE::checkDelta1",
42 "we have found a problem");
47 int VCS_SOLVE::vcs_solve_TP(
int print_lvl,
int printDetails,
int maxit)
50 bool allMinorZeroedSpecies =
false;
53 int rangeErrorFound = 0;
54 bool giveUpOnElemAbund =
false;
55 int finalElemAbundAttempts = 0;
56 bool uptodate_minors =
true;
57 int forceComponentCalc = 1;
61 m_debug_print_lvl = printDetails;
62 if (printDetails > 0 && print_lvl == 0) {
70 m_sm.assign(m_nelem * m_nelem, 0.0);
71 m_ss.assign(m_nelem, 0.0);
72 m_sa.assign(m_nelem, 0.0);
73 m_aw.assign(m_nsp, 0.0);
74 m_wx.assign(m_nelem, 0.0);
76 int solveFail =
false;
83 plogf(
"VCS CALCULATION METHOD\n\n ");
84 plogf(
"MultiPhase Object\n");
85 plogf(
"\n\n%5d SPECIES\n%5d ELEMENTS\n", m_nsp, m_nelem);
86 plogf(
"%5d COMPONENTS\n", m_numComponents);
87 plogf(
"%5d PHASES\n", m_numPhases);
88 plogf(
" PRESSURE%22.8g %3s\n", m_pressurePA,
"Pa ");
89 plogf(
" TEMPERATURE%19.3f K\n", m_temperature);
92 plogf(
" PHASE1 INERTS%17.3f\n", TPhInertMoles[0]);
94 if (m_numPhases > 1) {
95 plogf(
" PHASE2 INERTS%17.3f\n", TPhInertMoles[1]);
97 plogf(
"\n ELEMENTAL ABUNDANCES CORRECT");
98 plogf(
" FROM ESTIMATE Type\n\n");
99 for (
size_t i = 0; i < m_nelem; ++i) {
100 writeline(
' ', 26,
false);
101 plogf(
"%-2.2s", m_elementName[i]);
102 plogf(
"%20.12E%20.12E %3d\n", m_elemAbundancesGoal[i], m_elemAbundances[i],
105 if (m_doEstimateEquil < 0) {
106 plogf(
"\n MODIFIED LINEAR PROGRAMMING ESTIMATE OF EQUILIBRIUM - forced\n");
107 }
else if (m_doEstimateEquil > 0) {
108 plogf(
"\n MODIFIED LINEAR PROGRAMMING ESTIMATE OF EQUILIBRIUM - where necessary\n");
110 if (m_doEstimateEquil == 0) {
111 plogf(
"\n USER ESTIMATE OF EQUILIBRIUM\n");
113 plogf(
" Stan. Chem. Pot. in J/kmol\n");
114 plogf(
"\n SPECIES FORMULA VECTOR ");
115 writeline(
' ', 41,
false);
116 plogf(
" STAN_CHEM_POT EQUILIBRIUM_EST. Species_Type\n\n");
117 writeline(
' ', 20,
false);
118 for (
size_t i = 0; i < m_nelem; ++i) {
119 plogf(
"%-4.4s ", m_elementName[i]);
123 for (
size_t i = 0; i < m_nsp; ++i) {
124 plogf(
" %-18.18s", m_speciesName[i]);
125 for (
size_t j = 0; j < m_nelem; ++j) {
126 plogf(
"% -7.3g ", m_formulaMatrix(i,j));
128 plogf(
" %3d ", m_phaseID[i]);
129 writeline(
' ', std::max(55-
int(m_nelem)*8, 0),
false);
130 plogf(
"%12.5E %12.5E", RT * m_SSfeSpecies[i], m_molNumSpecies_old[i]);
141 for (
size_t i = 0; i < m_nsp; ++i) {
142 if (m_molNumSpecies_old[i] < 0.0) {
143 plogf(
"On Input species %-12s has a negative MF, setting it small\n",
145 size_t iph = m_phaseID[i];
148 m_molNumSpecies_old[i] = tmp;
164 if (forceComponentCalc) {
165 int retn = solve_tp_component_calc(allMinorZeroedSpecies);
170 forceComponentCalc = 0;
176 if (m_VCount->Its > maxit) {
179 solve_tp_inner(iti, it1, uptodate_minors, allMinorZeroedSpecies,
180 forceComponentCalc, stage, printDetails > 0, ANOTE);
182 }
else if (stage == EQUILIB_CHECK) {
184 solve_tp_equilib_check(allMinorZeroedSpecies, uptodate_minors,
185 giveUpOnElemAbund, solveFail, iti, it1,
187 }
else if (stage == ELEM_ABUND_CHECK) {
189 solve_tp_elem_abund_check(iti, stage, lec, giveUpOnElemAbund,
190 finalElemAbundAttempts, rangeErrorFound);
191 }
else if (stage == RECHECK_DELETED) {
201 size_t npb = vcs_recheck_deleted();
215 }
else if (stage == RETURN_A) {
217 size_t npb = vcs_recheck_deleted();
231 }
else if (stage == RETURN_B) {
234 size_t npb = vcs_add_all_deleted();
237 if (m_debug_print_lvl >= 1) {
238 plogf(
" --- add_all_deleted(): some rxns not converged. RETURNING TO LOOP!\n");
253 m_molNumSpecies_new.assign(m_molNumSpecies_new.size(), 0.0);
254 for (
size_t kspec = 0; kspec < m_nsp; ++kspec) {
255 if (m_SSPhase[kspec]) {
256 m_molNumSpecies_new[kspec] = 1.0;
258 size_t iph = m_phaseID[kspec];
259 if (m_tPhaseMoles_old[iph] != 0.0) {
260 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec] / m_tPhaseMoles_old[iph];
266 size_t i = m_speciesLocalPhaseIndex[kspec];
267 m_molNumSpecies_new[kspec] = m_VolPhaseList[iph]->molefraction(i);
272 if (rangeErrorFound) {
278 m_VCount->Time_vcs_TP = tsecond;
279 m_VCount->T_Time_vcs_TP += m_VCount->Time_vcs_TP;
280 m_VCount->T_Calls_vcs_TP++;
281 m_VCount->T_Its += m_VCount->Its;
282 m_VCount->T_Basis_Opts += m_VCount->Basis_Opts;
283 m_VCount->T_Time_basopt += m_VCount->Time_basopt;
289 int VCS_SOLVE::solve_tp_component_calc(
bool& allMinorZeroedSpecies)
291 double test = -1.0e-10;
292 bool usedZeroedSpecies;
293 int retn = vcs_basopt(
false, &m_aw[0], &m_sa[0], &m_sm[0], &m_ss[0],
294 test, &usedZeroedSpecies);
304 allMinorZeroedSpecies = vcs_evaluate_speciesType();
307 if (! vcs_elabcheck(0)) {
308 debuglog(
" --- Element Abundance check failed\n", m_debug_print_lvl >= 2);
309 vcs_elcorr(&m_sm[0], &m_wx[0]);
316 debuglog(
" --- Element Abundance check passed\n", m_debug_print_lvl >= 2);
321 void VCS_SOLVE::solve_tp_inner(
size_t& iti,
size_t& it1,
322 bool& uptodate_minors,
323 bool& allMinorZeroedSpecies,
324 int& forceComponentCalc,
325 int& stage,
bool printDetails,
char* ANOTE)
334 if (!uptodate_minors) {
339 uptodate_minors =
true;
341 uptodate_minors =
false;
347 plogf(
" Iteration = %3d, Iterations since last evaluation of "
348 "optimal basis = %3d",
349 m_VCount->Its, it1 - 1);
351 plogf(
" (all species)\n");
353 plogf(
" (only major species)\n");
364 m_feSpecies_new = m_feSpecies_old;
365 m_actCoeffSpecies_new = m_actCoeffSpecies_old;
366 m_deltaGRxn_new = m_deltaGRxn_old;
367 m_deltaGRxn_Deficient = m_deltaGRxn_old;
368 m_tPhaseMoles_new = m_tPhaseMoles_old;
373 m_deltaMolNumSpecies.assign(m_deltaMolNumSpecies.size(), 0.0);
379 std::vector<size_t> phasePopPhaseIDs(0);
380 size_t iphasePop = vcs_popPhaseID(phasePopPhaseIDs);
381 if (iphasePop !=
npos) {
382 int soldel = vcs_popPhaseRxnStepSizes(iphasePop);
385 if (m_debug_print_lvl >= 2) {
386 plogf(
" --- vcs_popPhaseRxnStepSizes() was called but stoich "
387 "prevented phase %d popping\n");
395 size_t iphaseDelete =
npos;
397 if (iphasePop ==
npos) {
401 iphaseDelete = vcs_RxnStepSizes(forceComponentCalc, kspec);
402 }
else if (m_debug_print_lvl >= 2) {
403 plogf(
" --- vcs_RxnStepSizes not called because alternative"
404 "phase creation delta was used instead\n");
406 size_t doPhaseDeleteKspec =
npos;
407 size_t doPhaseDeleteIph =
npos;
410 m_deltaPhaseMoles.assign(m_deltaPhaseMoles.size(), 0.0);
426 if (iphaseDelete !=
npos) {
427 debuglog(
" --- Main Loop Treatment -> Circumvented due to Phase Deletion\n", m_debug_print_lvl >= 2);
428 for (
size_t k = 0; k < m_nsp; k++) {
429 m_molNumSpecies_new[k] = m_molNumSpecies_old[k] + m_deltaMolNumSpecies[k];
430 size_t iph = m_phaseID[k];
431 m_tPhaseMoles_new[iph] += m_deltaMolNumSpecies[k];
433 if (kspec >= m_numComponents) {
434 if (m_SSPhase[kspec] == 1) {
437 throw CanteraError(
"VCS_SOLVE::solve_tp_inner",
438 "we shouldn't be here!");
440 ++m_numRxnMinorZeroed;
441 allMinorZeroedSpecies = (m_numRxnMinorZeroed == m_numRxnRdc);
457 if (m_debug_print_lvl >= 2) {
458 plogf(
" --- Main Loop Treatment of each non-component species ");
460 plogf(
"- Full Calculation:\n");
462 plogf(
"- Major Components Calculation:\n");
464 plogf(
" --- Species IC ");
465 plogf(
" KMoles Tent_KMoles Rxn_Adj | Comment \n");
467 for (
size_t irxn = 0; irxn < m_numRxnRdc; irxn++) {
468 size_t kspec = m_indexRxnToSpecies[irxn];
469 double* sc_irxn = m_stoichCoeffRxnMatrix.ptrColumn(irxn);
470 size_t iph = m_phaseID[kspec];
471 vcs_VolPhase* Vphase = m_VolPhaseList[iph].get();
475 if (iphasePop !=
npos) {
476 if (iph == iphasePop) {
477 dx = m_deltaMolNumSpecies[kspec];
478 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec] + m_deltaMolNumSpecies[kspec];
479 sprintf(ANOTE,
"Phase pop");
482 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec];
487 dx = vcs_minor_alt_calc(kspec, irxn, &soldel_ret, ANOTE);
488 m_deltaMolNumSpecies[kspec] = dx;
491 bool resurrect = (m_deltaMolNumSpecies[kspec] > 0.0);
492 if (m_debug_print_lvl >= 3) {
493 plogf(
" --- %s currently zeroed (SpStatus=%-2d):",
494 m_speciesName[kspec], m_speciesStatus[kspec]);
495 plogf(
"%3d DG = %11.4E WT = %11.4E W = %11.4E DS = %11.4E\n",
496 irxn, m_deltaGRxn_new[irxn], m_molNumSpecies_new[kspec],
497 m_molNumSpecies_old[kspec], m_deltaMolNumSpecies[kspec]);
499 if (m_deltaGRxn_new[irxn] >= 0.0 || !resurrect) {
500 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec];
501 m_deltaMolNumSpecies[kspec] = 0.0;
503 sprintf(ANOTE,
"Species stays zeroed: DG = %11.4E", m_deltaGRxn_new[irxn]);
504 if (m_deltaGRxn_new[irxn] < 0.0) {
506 sprintf(ANOTE,
"Species stays zeroed even though dg neg due to "
507 "STOICH/PHASEPOP constraint: DG = %11.4E",
508 m_deltaGRxn_new[irxn]);
510 sprintf(ANOTE,
"Species stays zeroed even though dg neg: DG = %11.4E, ds zeroed",
511 m_deltaGRxn_new[irxn]);
515 for (
size_t j = 0; j < m_nelem; ++j) {
516 int elType = m_elType[j];
518 double atomComp = m_formulaMatrix(kspec,j);
519 if (atomComp > 0.0) {
520 double maxPermissible = m_elemAbundancesGoal[j] / atomComp;
522 sprintf(ANOTE,
"Species stays zeroed even though dG "
523 "neg, because of %s elemAbund",
524 m_elementName[j].c_str());
536 if (m_debug_print_lvl >= 2) {
537 plogf(
" --- Zeroed species changed to major: ");
538 plogf(
"%-12s\n", m_speciesName[kspec]);
541 allMinorZeroedSpecies =
false;
543 if (m_debug_print_lvl >= 2) {
544 plogf(
" --- Zeroed species changed to minor: ");
545 plogf(
"%-12s\n", m_speciesName[kspec]);
549 if (m_deltaMolNumSpecies[kspec] > 0.0) {
550 dx = m_deltaMolNumSpecies[kspec] * 0.01;
551 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec] + dx;
554 dx = m_molNumSpecies_new[kspec] - m_molNumSpecies_old[kspec];
556 m_deltaMolNumSpecies[kspec] = dx;
557 sprintf(ANOTE,
"Born:IC=-1 to IC=1:DG=%11.4E", m_deltaGRxn_new[irxn]);
559 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec];
560 m_deltaMolNumSpecies[kspec] = 0.0;
569 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec];
570 m_deltaMolNumSpecies[kspec] = 0.0;
572 sprintf(ANOTE,
"minor species not considered");
573 if (m_debug_print_lvl >= 2) {
574 plogf(
" --- %-12s%3d% 11.4E %11.4E %11.4E | %s\n",
575 m_speciesName[kspec], m_speciesStatus[kspec], m_molNumSpecies_old[kspec], m_molNumSpecies_new[kspec],
576 m_deltaMolNumSpecies[kspec], ANOTE);
594 dx = vcs_minor_alt_calc(kspec, irxn, &soldel_ret, ANOTE);
595 m_deltaMolNumSpecies[kspec] = dx;
596 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec] + dx;
600 if (m_debug_print_lvl >= 2) {
601 plogf(
" --- Delete minor species in multispec phase: %-12s\n",
602 m_speciesName[kspec]);
604 m_deltaMolNumSpecies[kspec] = 0.0;
610 size_t lnospec = vcs_delete_species(kspec);
612 stage = RECHECK_DELETED;
626 sprintf(ANOTE,
"Normal Major Calc");
631 if (fabs(m_deltaGRxn_new[irxn]) <= m_tolmaj2) {
632 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec];
633 m_deltaMolNumSpecies[kspec] = 0.0;
635 sprintf(ANOTE,
"major species is converged");
636 if (m_debug_print_lvl >= 2) {
637 plogf(
" --- %-12s %3d %11.4E %11.4E %11.4E | %s\n",
638 m_speciesName[kspec], m_speciesStatus[kspec], m_molNumSpecies_old[kspec], m_molNumSpecies_new[kspec],
639 m_deltaMolNumSpecies[kspec], ANOTE);
651 if ((m_deltaGRxn_new[irxn] * m_deltaMolNumSpecies[kspec]) <= 0.0) {
652 dx = m_deltaMolNumSpecies[kspec];
655 m_deltaMolNumSpecies[kspec] = 0.0;
656 sprintf(ANOTE,
"dx set to 0, DG flipped sign due to "
657 "changed initial point");
661 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec] + dx;
667 if (m_molNumSpecies_new[kspec] <= 0.0) {
668 sprintf(ANOTE,
"initial nonpos kmoles= %11.3E",
669 m_molNumSpecies_new[kspec]);
677 if (!m_SSPhase[kspec]) {
682 dx = -0.9 * m_molNumSpecies_old[kspec];
683 m_deltaMolNumSpecies[kspec] = dx;
684 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec] + dx;
689 dx = -m_molNumSpecies_old[kspec];
695 for (
size_t j = 0; j < m_numComponents; ++j) {
696 if (sc_irxn[j] != 0.0) {
697 m_wx[j] = m_molNumSpecies_old[j] + sc_irxn[j] * dx;
698 if (m_wx[j] <= m_molNumSpecies_old[j] * 0.01 - 1.0E-150) {
699 dx = std::max(dx, m_molNumSpecies_old[j] * -0.99 / sc_irxn[j]);
702 m_wx[j] = m_molNumSpecies_old[j];
705 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec] + dx;
706 if (m_molNumSpecies_new[kspec] > 0.0) {
707 m_deltaMolNumSpecies[kspec] = dx;
709 "zeroing SS phase created a neg component species "
710 "-> reducing step size instead");
714 iph = m_phaseID[kspec];
715 Vphase = m_VolPhaseList[iph].get();
716 sprintf(ANOTE,
"zeroing out SS phase: ");
722 m_molNumSpecies_new[kspec] = 0.0;
723 doPhaseDeleteIph = iph;
725 doPhaseDeleteKspec = kspec;
726 if (m_debug_print_lvl >= 2 && m_speciesStatus[kspec] >= 0) {
727 plogf(
" --- SS species changed to zeroedss: ");
728 plogf(
"%-12s\n", m_speciesName[kspec]);
731 ++m_numRxnMinorZeroed;
732 allMinorZeroedSpecies = (m_numRxnMinorZeroed == m_numRxnRdc);
734 for (
size_t kk = 0; kk < m_nsp; kk++) {
735 m_deltaMolNumSpecies[kk] = 0.0;
736 m_molNumSpecies_new[kk] = m_molNumSpecies_old[kk];
738 m_deltaMolNumSpecies[kspec] = dx;
739 m_molNumSpecies_new[kspec] = 0.0;
741 for (
size_t k = 0; k < m_numComponents; ++k) {
742 m_deltaMolNumSpecies[k] = 0.0;
744 for (iph = 0; iph < m_numPhases; iph++) {
745 m_deltaPhaseMoles[iph] = 0.0;
753 if (dx != 0.0 && (m_speciesUnknownType[kspec] !=
760 1.0E-14*(fabs(m_deltaMolNumSpecies[kspec]) + fabs(dx) + 1.0E-32),
761 "VCS_SOLVE::solve_tp_inner",
762 "ds[kspec] = {}, dx = {}, kspec = {}\nwe have a problem!",
763 m_deltaMolNumSpecies[kspec], dx, kspec);
764 for (
size_t k = 0; k < m_numComponents; ++k) {
765 m_deltaMolNumSpecies[k] += sc_irxn[k] * dx;
770 for (iph = 0; iph < m_numPhases; iph++) {
771 m_deltaPhaseMoles[iph] += dx * m_deltaMolNumPhase(iph,irxn);
775 checkDelta1(&m_deltaMolNumSpecies[0],
776 &m_deltaPhaseMoles[0], kspec+1);
779 if (m_debug_print_lvl >= 2) {
780 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec] + m_deltaMolNumSpecies[kspec];
781 plogf(
" --- %-12.12s%3d %11.4E %11.4E %11.4E | %s\n",
782 m_speciesName[kspec], m_speciesStatus[kspec],
783 m_molNumSpecies_old[kspec], m_molNumSpecies_new[kspec],
784 m_deltaMolNumSpecies[kspec], ANOTE);
787 if (doPhaseDeleteIph !=
npos) {
788 if (m_debug_print_lvl >= 2) {
789 plogf(
" --- %-12.12s Main Loop Special Case deleting phase with species:\n",
790 m_speciesName[doPhaseDeleteKspec]);
795 if (m_debug_print_lvl >= 2) {
796 for (
size_t k = 0; k < m_numComponents; k++) {
798 plogf(
"%-12.12s", m_speciesName[k]);
799 plogf(
" c %11.4E %11.4E %11.4E |\n",
800 m_molNumSpecies_old[k],
801 m_molNumSpecies_old[k]+m_deltaMolNumSpecies[k], m_deltaMolNumSpecies[k]);
805 plogf(
" --- Finished Main Loop\n");
814 for (
size_t k = 0; k < m_numComponents; ++k) {
815 if (m_molNumSpecies_old[k] > 0.0) {
816 double xx = -m_deltaMolNumSpecies[k] / m_molNumSpecies_old[k];
821 }
else if (m_deltaMolNumSpecies[k] < 0.0) {
824 size_t iph = m_phaseID[k];
825 m_deltaPhaseMoles[iph] -= m_deltaMolNumSpecies[k];
826 m_deltaMolNumSpecies[k] = 0.0;
830 if (par <= 1.01 && par > 0.0) {
833 if (m_debug_print_lvl >= 2) {
834 plogf(
" --- Reduction in step size due to component %s going negative = %11.3E\n",
835 m_speciesName[ll], par);
837 for (
size_t i = 0; i < m_nsp; ++i) {
838 m_deltaMolNumSpecies[i] *= par;
840 for (
size_t iph = 0; iph < m_numPhases; iph++) {
841 m_deltaPhaseMoles[iph] *= par;
846 checkDelta1(&m_deltaMolNumSpecies[0],
847 &m_deltaPhaseMoles[0], m_nsp);
854 for (
size_t kspec = 0; kspec < m_nsp; ++kspec) {
855 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec] + m_deltaMolNumSpecies[kspec];
856 if (m_molNumSpecies_new[kspec] < 0.0 && (m_speciesUnknownType[kspec]
858 throw CanteraError(
"VCS_SOLVE::solve_tp_inner",
859 "vcs_solve_TP: ERROR on step change wt[{}:{}]: {} < 0.0",
860 kspec, m_speciesName[kspec], m_molNumSpecies_new[kspec]);
865 for (
size_t iph = 0; iph < m_numPhases; iph++) {
866 m_tPhaseMoles_new[iph] = m_tPhaseMoles_old[iph] + m_deltaPhaseMoles[iph];
884 plogf(
" --- Total Old Dimensionless Gibbs Free Energy = %20.13E\n",
885 vcs_Total_Gibbs(&m_molNumSpecies_old[0], &m_feSpecies_old[0],
886 &m_tPhaseMoles_old[0]));
887 plogf(
" --- Total tentative Dimensionless Gibbs Free Energy = %20.13E\n",
888 vcs_Total_Gibbs(&m_molNumSpecies_new[0], &m_feSpecies_new[0],
889 &m_tPhaseMoles_new[0]));
892 bool forced = vcs_globStepDamp();
895 if (printDetails && forced) {
896 plogf(
" -----------------------------------------------------\n");
897 plogf(
" --- FORCER SUBROUTINE changed the solution:\n");
898 plogf(
" --- SPECIES Status INIT MOLES TENT_MOLES");
899 plogf(
" FINAL KMOLES INIT_DEL_G/RT TENT_DEL_G/RT FINAL_DELTA_G/RT\n");
900 for (
size_t i = 0; i < m_numComponents; ++i) {
901 plogf(
" --- %-12.12s", m_speciesName[i]);
902 plogf(
" %14.6E %14.6E %14.6E\n", m_molNumSpecies_old[i],
903 m_molNumSpecies_old[i] + m_deltaMolNumSpecies[i], m_molNumSpecies_new[i]);
905 for (
size_t kspec = m_numComponents; kspec < m_numSpeciesRdc; ++kspec) {
906 size_t irxn = kspec - m_numComponents;
907 plogf(
" --- %-12.12s", m_speciesName[kspec]);
908 plogf(
" %2d %14.6E%14.6E%14.6E%14.6E%14.6E%14.6E\n", m_speciesStatus[kspec],
909 m_molNumSpecies_old[kspec],
910 m_molNumSpecies_old[kspec]+m_deltaMolNumSpecies[kspec],
911 m_molNumSpecies_new[kspec], m_deltaGRxn_old[irxn],
912 m_deltaGRxn_tmp[irxn], m_deltaGRxn_new[irxn]);
914 writeline(
' ', 26,
false);
915 plogf(
"Norms of Delta G():%14.6E%14.6E\n",
916 l2normdg(&m_deltaGRxn_old[0]),
917 l2normdg(&m_deltaGRxn_new[0]));
918 plogf(
" Total kmoles of gas = %15.7E\n", m_tPhaseMoles_old[0]);
919 if ((m_numPhases > 1) && (!m_VolPhaseList[1]->m_singleSpecies)) {
920 plogf(
" Total kmoles of liquid = %15.7E\n", m_tPhaseMoles_old[1]);
922 plogf(
" Total kmoles of liquid = %15.7E\n", 0.0);
924 plogf(
" Total New Dimensionless Gibbs Free Energy = %20.13E\n",
925 vcs_Total_Gibbs(&m_molNumSpecies_new[0], &m_feSpecies_new[0],
926 &m_tPhaseMoles_new[0]));
927 plogf(
" -----------------------------------------------------\n");
936 plogf(
" --- Summary of the Update ");
938 plogf(
" (all species):");
940 plogf(
" (only major species):");
943 plogf(
" --- Species Status Initial_KMoles Final_KMoles Initial_Mu/RT");
944 plogf(
" Mu/RT Init_Del_G/RT Delta_G/RT\n");
945 for (
size_t i = 0; i < m_numComponents; ++i) {
946 plogf(
" --- %-12.12s", m_speciesName[i]);
948 plogf(
"%14.6E%14.6E%14.6E%14.6E\n", m_molNumSpecies_old[i],
949 m_molNumSpecies_new[i], m_feSpecies_old[i], m_feSpecies_new[i]);
951 for (
size_t i = m_numComponents; i < m_numSpeciesRdc; ++i) {
952 size_t l1 = i - m_numComponents;
953 plogf(
" --- %-12.12s", m_speciesName[i]);
954 plogf(
" %2d %14.6E%14.6E%14.6E%14.6E%14.6E%14.6E\n",
955 m_speciesStatus[i], m_molNumSpecies_old[i],
956 m_molNumSpecies_new[i], m_feSpecies_old[i], m_feSpecies_new[i],
957 m_deltaGRxn_old[l1], m_deltaGRxn_new[l1]);
959 for (
size_t kspec = m_numSpeciesRdc; kspec < m_nsp; ++kspec) {
960 size_t l1 = kspec - m_numComponents;
961 plogf(
" --- %-12.12s", m_speciesName[kspec]);
962 plogf(
" %2d %14.6E%14.6E%14.6E%14.6E%14.6E%14.6E\n",
963 m_speciesStatus[kspec], m_molNumSpecies_old[kspec],
964 m_molNumSpecies_new[kspec], m_feSpecies_old[kspec], m_feSpecies_new[kspec],
965 m_deltaGRxn_old[l1], m_deltaGRxn_new[l1]);
968 writeline(
' ', 56,
false);
969 plogf(
"Norms of Delta G():%14.6E%14.6E\n",
970 l2normdg(&m_deltaGRxn_old[0]),
971 l2normdg(&m_deltaGRxn_new[0]));
973 plogf(
" --- Phase_Name KMoles(after update)\n");
976 for (
size_t iph = 0; iph < m_numPhases; iph++) {
977 vcs_VolPhase* Vphase = m_VolPhaseList[iph].get();
978 plogf(
" --- %18s = %15.7E\n", Vphase->PhaseName, m_tPhaseMoles_new[iph]);
982 plogf(
" --- Total Old Dimensionless Gibbs Free Energy = %20.13E\n",
983 vcs_Total_Gibbs(&m_molNumSpecies_old[0], &m_feSpecies_old[0],
984 &m_tPhaseMoles_old[0]));
985 plogf(
" --- Total New Dimensionless Gibbs Free Energy = %20.13E\n",
986 vcs_Total_Gibbs(&m_molNumSpecies_new[0], &m_feSpecies_new[0],
987 &m_tPhaseMoles_new[0]));
988 debuglog(
" --- Troublesome solve\n", m_VCount->Its > 550);
1001 m_tPhaseMoles_old = m_tPhaseMoles_new;
1002 m_molNumSpecies_old = m_molNumSpecies_new;
1003 m_actCoeffSpecies_old = m_actCoeffSpecies_new;
1004 m_deltaGRxn_old = m_deltaGRxn_new;
1005 m_feSpecies_old = m_feSpecies_new;
1012 if (m_debug_print_lvl >= 2) {
1013 plogf(
" --- Increment counter increased, step is accepted: %4d\n",
1023 bool justDeletedMultiPhase =
false;
1024 for (
size_t iph = 0; iph < m_numPhases; iph++) {
1025 if (!m_VolPhaseList[iph]->m_singleSpecies && m_tPhaseMoles_old[iph] != 0.0 &&
1027 if (m_debug_print_lvl >= 1) {
1028 plogf(
" --- Setting microscopic phase %d to zero\n", iph);
1030 justDeletedMultiPhase =
true;
1031 vcs_delete_multiphase(iph);
1038 if (justDeletedMultiPhase) {
1039 bool usedZeroedSpecies;
1040 double test = -1.0e-10;
1041 int retn = vcs_basopt(
false, &m_aw[0], &m_sa[0], &m_sm[0], &m_ss[0],
1042 test, &usedZeroedSpecies);
1044 throw CanteraError(
"VCS_SOLVE::solve_tp_inner",
1045 "BASOPT returned with an error condition");
1055 if (m_debug_print_lvl >= 2) {
1056 plogf(
" --- Normal element abundance check");
1059 if (! vcs_elabcheck(0)) {
1060 debuglog(
" - failed -> redoing element abundances.\n", m_debug_print_lvl >= 2);
1061 vcs_elcorr(&m_sm[0], &m_wx[0]);
1065 uptodate_minors =
true;
1067 debuglog(
" - passed\n", m_debug_print_lvl >= 2);
1071 for (
size_t i = 0; i < m_numRxnRdc; ++i) {
1072 size_t k = m_indexRxnToSpecies[i];
1076 for (
size_t j = 0; j < m_numComponents; ++j) {
1077 bool doSwap =
false;
1079 doSwap = (m_molNumSpecies_old[k] * m_spSize[k]) >
1080 (m_molNumSpecies_old[j] * m_spSize[j] * 1.01);
1081 if (!m_SSPhase[k] && doSwap) {
1082 doSwap = m_molNumSpecies_old[k] > (m_molNumSpecies_old[j] * 1.01);
1086 doSwap = (m_molNumSpecies_old[k] * m_spSize[k]) >
1087 (m_molNumSpecies_old[j] * m_spSize[j] * 1.01);
1089 doSwap = m_molNumSpecies_old[k] > (m_molNumSpecies_old[j] * 1.01);
1092 doSwap = (m_molNumSpecies_old[k] * m_spSize[k]) >
1093 (m_molNumSpecies_old[j] * m_spSize[j] * 1.01);
1096 if (doSwap && m_stoichCoeffRxnMatrix(j,i) != 0.0) {
1097 if (m_debug_print_lvl >= 2) {
1098 plogf(
" --- Get a new basis because %s", m_speciesName[k]);
1099 plogf(
" is better than comp %s", m_speciesName[j]);
1100 plogf(
" and share nonzero stoic: %-9.1f\n",
1101 m_stoichCoeffRxnMatrix(j,i));
1103 forceComponentCalc = 1;
1108 debuglog(
" --- Check for an optimum basis passed\n", m_debug_print_lvl >= 2);
1109 stage = EQUILIB_CHECK;
1118 if (m_debug_print_lvl >= 2) {
1119 plogf(
" --- Reevaluate major-minor status of noncomponents:\n");
1121 m_numRxnMinorZeroed = 0;
1122 for (
size_t irxn = 0; irxn < m_numRxnRdc; irxn++) {
1123 size_t kspec = m_indexRxnToSpecies[irxn];
1124 int speciesType = vcs_species_type(kspec);
1127 plogf(
" --- major/minor species is now zeroed out: %s\n",
1128 m_speciesName[kspec]);
1130 ++m_numRxnMinorZeroed;
1134 plogf(
" --- Noncomponent turned from major to minor: ");
1135 }
else if (kspec < m_numComponents) {
1136 plogf(
" --- Component turned into a minor species: ");
1138 plogf(
" --- Zeroed Species turned into a "
1141 plogf(
"%s\n", m_speciesName[kspec]);
1143 ++m_numRxnMinorZeroed;
1146 if (m_debug_print_lvl >= 2) {
1148 plogf(
" --- Noncomponent turned from minor to major: ");
1149 }
else if (kspec < m_numComponents) {
1150 plogf(
" --- Component turned into a major: ");
1152 plogf(
" --- Noncomponent turned from zeroed to major: ");
1154 plogf(
"%s\n", m_speciesName[kspec]);
1159 m_speciesStatus[kspec] = speciesType;
1164 allMinorZeroedSpecies = (m_numRxnMinorZeroed == m_numRxnRdc);
1167 void VCS_SOLVE::solve_tp_equilib_check(
bool& allMinorZeroedSpecies,
1168 bool& uptodate_minors,
1169 bool& giveUpOnElemAbund,
int& solveFail,
1170 size_t& iti,
size_t& it1,
int maxit,
1171 int& stage,
bool& lec)
1173 if (! allMinorZeroedSpecies) {
1174 if (m_debug_print_lvl >= 2) {
1175 plogf(
" --- Equilibrium check for major species: ");
1177 for (
size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
1178 size_t kspec = irxn + m_numComponents;
1179 if (m_speciesStatus[kspec] ==
VCS_SPECIES_MAJOR && (fabs(m_deltaGRxn_new[irxn]) > m_tolmaj)) {
1180 if (m_VCount->Its >= maxit) {
1187 if (m_debug_print_lvl >= 2) {
1188 plogf(
"%s failed\n", m_speciesName[m_indexRxnToSpecies[irxn]]);
1192 iti = ((it1/4) *4) - it1;
1198 debuglog(
" MAJOR SPECIES CONVERGENCE achieved", m_debug_print_lvl >= 2);
1200 debuglog(
" MAJOR SPECIES CONVERGENCE achieved "
1201 "(because there are no major species)\n", m_debug_print_lvl >= 2);
1206 if (m_numRxnMinorZeroed != 0) {
1213 uptodate_minors =
true;
1215 if (m_debug_print_lvl >= 2) {
1216 plogf(
" --- Equilibrium check for minor species: ");
1218 for (
size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
1219 size_t kspec = irxn + m_numComponents;
1220 if (m_speciesStatus[kspec] ==
VCS_SPECIES_MINOR && (fabs(m_deltaGRxn_new[irxn]) > m_tolmin)) {
1221 if (m_VCount->Its >= maxit) {
1228 if (m_debug_print_lvl >= 2) {
1229 plogf(
"%s failed\n", m_speciesName[m_indexRxnToSpecies[irxn]]);
1239 if (m_debug_print_lvl >= 2) {
1240 plogf(
" CONVERGENCE achieved\n");
1251 if (!giveUpOnElemAbund) {
1252 if (m_debug_print_lvl >= 2) {
1253 plogf(
" --- Check the Full Element Abundances: ");
1258 if (! vcs_elabcheck(1)) {
1259 if (m_debug_print_lvl >= 2) {
1260 if (! vcs_elabcheck(0)) {
1263 plogf(
" passed for NC but failed for NE: RANGE ERROR\n");
1267 stage = ELEM_ABUND_CHECK;
1270 if (m_debug_print_lvl >= 2) {
1277 if (m_numSpeciesRdc != m_nsp) {
1278 stage = RECHECK_DELETED;
1287 void VCS_SOLVE::solve_tp_elem_abund_check(
size_t& iti,
int& stage,
bool& lec,
1288 bool& giveUpOnElemAbund,
1289 int& finalElemAbundAttempts,
1290 int& rangeErrorFound)
1297 rangeErrorFound = 0;
1298 if (! vcs_elabcheck(1)) {
1299 bool ncBefore = vcs_elabcheck(0);
1300 vcs_elcorr(&m_sm[0], &m_wx[0]);
1301 bool ncAfter = vcs_elabcheck(0);
1302 bool neAfter = vcs_elabcheck(1);
1318 if (finalElemAbundAttempts >= 3) {
1319 giveUpOnElemAbund =
true;
1320 stage = EQUILIB_CHECK;
1322 finalElemAbundAttempts++;
1329 }
else if (ncAfter) {
1332 if (m_debug_print_lvl >= 2) {
1333 plogf(
" --- vcs_solve_tp: RANGE SPACE ERROR ENCOUNTERED\n");
1334 plogf(
" --- vcs_solve_tp: - Giving up on NE Element Abundance satisfaction \n");
1335 plogf(
" --- vcs_solve_tp: - However, NC Element Abundance criteria is satisfied \n");
1336 plogf(
" --- vcs_solve_tp: - Returning the calculated equilibrium condition\n");
1338 rangeErrorFound = 1;
1339 giveUpOnElemAbund =
true;
1344 stage = EQUILIB_CHECK;
1351 stage = EQUILIB_CHECK;
1354 double VCS_SOLVE::vcs_minor_alt_calc(
size_t kspec,
size_t irxn,
bool* do_delete,
1357 double w_kspec = m_molNumSpecies_old[kspec];
1358 double dg_irxn = m_deltaGRxn_old[irxn];
1359 size_t iph = m_phaseID[kspec];
1363 if (w_kspec <= 0.0) {
1366 dg_irxn = std::max(dg_irxn, -200.0);
1368 sprintf(ANOTE,
"minor species alternative calc");
1370 if (dg_irxn >= 23.0) {
1371 double molNum_kspec_new = w_kspec * 1.0e-10;
1378 return molNum_kspec_new - w_kspec;
1380 if (fabs(dg_irxn) <= m_tolmin2) {
1386 double s = m_np_dLnActCoeffdMolNum(kspec,kspec) / m_tPhaseMoles_old[iph];
1397 double a =
clip(w_kspec * s, -1.0+1e-8, 100.0);
1398 double tmp =
clip(-dg_irxn / (1.0 + a), -200.0, 200.0);
1399 double wTrial = w_kspec * exp(tmp);
1400 double molNum_kspec_new = wTrial;
1402 if (wTrial > 100. * w_kspec) {
1403 double molNumMax = 0.0001 * m_tPhaseMoles_old[iph];
1404 if (molNumMax < 100. * w_kspec) {
1405 molNumMax = 100. * w_kspec;
1407 if (wTrial > molNumMax) {
1408 molNum_kspec_new = molNumMax;
1410 molNum_kspec_new = wTrial;
1412 }
else if (1.0E10 * wTrial < w_kspec) {
1413 molNum_kspec_new= 1.0E-10 * w_kspec;
1415 molNum_kspec_new = wTrial;
1424 return molNum_kspec_new - w_kspec;
1429 double dx = m_deltaGRxn_old[irxn]/ m_Faraday_dim;
1431 sprintf(ANOTE,
"voltage species alternative calc");
1437 int VCS_SOLVE::delta_species(
const size_t kspec,
double*
const delta_ptr)
1439 size_t irxn = kspec - m_numComponents;
1441 AssertThrowMsg(kspec >= m_numComponents,
"VCS_SOLVE::delta_species",
1442 "delete_species() ERROR: called for a component {}", kspec);
1446 double dx = *delta_ptr;
1447 double* sc_irxn = m_stoichCoeffRxnMatrix.ptrColumn(irxn);
1448 for (
size_t j = 0; j < m_numComponents; ++j) {
1449 if (m_molNumSpecies_old[j] > 0.0) {
1450 double tmp = sc_irxn[j] * dx;
1451 if (-tmp > m_molNumSpecies_old[j]) {
1453 dx = std::min(dx, - m_molNumSpecies_old[j] / sc_irxn[j]);
1459 if (m_molNumSpecies_old[j] <= 0.0 && sc_irxn[j] < 0.0) {
1467 m_molNumSpecies_old[kspec] += dx;
1468 size_t iph = m_phaseID[kspec];
1469 m_tPhaseMoles_old[iph] += dx;
1472 for (
size_t j = 0; j < m_numComponents; ++j) {
1473 double tmp = sc_irxn[j] * dx;
1476 m_molNumSpecies_old[j] += tmp;
1477 m_tPhaseMoles_old[iph] += tmp;
1479 m_molNumSpecies_old[j] = std::max(m_molNumSpecies_old[j], 0.0);
1486 int VCS_SOLVE::vcs_zero_species(
const size_t kspec)
1492 double dx = -m_molNumSpecies_old[kspec];
1494 retn = delta_species(kspec, &dx);
1495 if (!retn && m_debug_print_lvl >= 1) {
1496 plogf(
"vcs_zero_species: Couldn't zero the species %d, "
1497 "did delta of %g. orig conc of %g\n",
1498 kspec, dx, m_molNumSpecies_old[kspec] + dx);
1505 int VCS_SOLVE::vcs_delete_species(
const size_t kspec)
1507 const size_t klast = m_numSpeciesRdc - 1;
1508 const size_t iph = m_phaseID[kspec];
1509 vcs_VolPhase*
const Vphase = m_VolPhaseList[iph].get();
1510 const size_t irxn = kspec - m_numComponents;
1514 const int retn = vcs_zero_species(kspec);
1517 "Failed to delete a species!");
1523 --m_numRxnMinorZeroed;
1526 m_deltaGRxn_new[irxn] = 0.0;
1527 m_deltaGRxn_old[irxn] = 0.0;
1528 m_feSpecies_new[kspec] = 0.0;
1529 m_feSpecies_old[kspec] = 0.0;
1530 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec];
1533 if (kspec != klast) {
1534 vcs_switch_pos(
true, klast, kspec);
1539 &m_tPhaseMoles_old[0]);
1548 bool stillExists =
false;
1549 for (
size_t k = 0; k < m_numSpeciesRdc; k++) {
1551 m_phaseID[k] == iph && m_molNumSpecies_old[k] > 0.0) {
1557 vcs_delete_multiphase(iph);
1563 return (m_numRxnRdc == 0);
1566 void VCS_SOLVE::vcs_reinsert_deleted(
size_t kspec)
1568 size_t iph = m_phaseID[kspec];
1569 if (m_debug_print_lvl >= 2) {
1570 plogf(
" --- Add back a deleted species: %-12s\n", m_speciesName[kspec]);
1577 delta_species(kspec, &dx);
1580 if (m_SSPhase[kspec]) {
1582 --m_numRxnMinorZeroed;
1587 &m_molNumSpecies_old[0],
1588 &m_tPhaseMoles_old[0]);
1594 if (! m_SSPhase[kspec]) {
1597 for (
size_t k = 0; k < m_nsp; k++) {
1609 ++m_numRxnMinorZeroed;
1611 if (kspec != (m_numSpeciesRdc - 1)) {
1613 vcs_switch_pos(
true, (m_numSpeciesRdc - 1), kspec);
1617 bool VCS_SOLVE::vcs_delete_multiphase(
const size_t iph)
1620 bool successful =
true;
1624 if (m_debug_print_lvl >= 2) {
1625 plogf(
" --- delete_multiphase %d, %s\n", iph, Vphase->
PhaseName);
1629 for (
size_t kspec = m_numComponents; kspec < m_numSpeciesRdc; ++kspec) {
1630 if (m_phaseID[kspec] == iph) {
1633 double dx = - m_molNumSpecies_old[kspec];
1636 int retn = delta_species(kspec, &dxTent);
1639 if (m_debug_print_lvl >= 2) {
1640 plogf(
" --- delete_multiphase %d, %s ERROR problems deleting species %s\n",
1641 iph, Vphase->
PhaseName, m_speciesName[kspec]);
1642 plogf(
" --- delta attempted: %g achieved: %g "
1643 " Zeroing it manually\n", dx, dxTent);
1645 m_molNumSpecies_old[kspec] = 0.0;
1646 m_molNumSpecies_new[kspec] = 0.0;
1647 m_deltaMolNumSpecies[kspec] = 0.0;
1652 m_molNumSpecies_old[kspec] = 0.0;
1653 m_molNumSpecies_new[kspec] = 0.0;
1654 m_deltaMolNumSpecies[kspec] = 0.0;
1664 double dxPerm = 0.0, dxPerm2 = 0.0;
1665 for (
size_t kcomp = 0; kcomp < m_numComponents; ++kcomp) {
1666 if (m_phaseID[kcomp] == iph) {
1667 if (m_debug_print_lvl >= 2) {
1668 plogf(
" --- delete_multiphase One of the species is a component %d - %s with mole number %g\n",
1669 kcomp, m_speciesName[kcomp], m_molNumSpecies_old[kcomp]);
1671 if (m_molNumSpecies_old[kcomp] != 0.0) {
1672 for (
size_t kspec = m_numComponents; kspec < m_numSpeciesRdc; ++kspec) {
1673 size_t irxn = kspec - m_numComponents;
1674 if (m_phaseID[kspec] != iph) {
1675 if (m_stoichCoeffRxnMatrix(kcomp,irxn) != 0.0) {
1676 double dxWant = -m_molNumSpecies_old[kcomp] / m_stoichCoeffRxnMatrix(kcomp,irxn);
1677 if (dxWant + m_molNumSpecies_old[kspec] < 0.0) {
1678 dxPerm = -m_molNumSpecies_old[kspec];
1680 for (
size_t jcomp = 0; kcomp < m_numComponents; ++kcomp) {
1681 if (jcomp != kcomp) {
1682 if (m_phaseID[jcomp] == iph) {
1685 double dj = dxWant * m_stoichCoeffRxnMatrix(jcomp,irxn);
1686 if (dj + m_molNumSpecies_old[kcomp] < 0.0) {
1687 dxPerm2 = -m_molNumSpecies_old[kcomp] / m_stoichCoeffRxnMatrix(jcomp,irxn);
1689 if (fabs(dxPerm2) < fabs(dxPerm)) {
1696 if (dxPerm != 0.0) {
1697 delta_species(kspec, &dxPerm);
1703 if (m_molNumSpecies_old[kcomp] != 0.0) {
1704 if (m_debug_print_lvl >= 2) {
1705 plogf(
" --- delete_multiphase One of the species is a component %d - %s still with mole number %g\n",
1706 kcomp, m_speciesName[kcomp], m_molNumSpecies_old[kcomp]);
1707 plogf(
" --- zeroing it \n");
1709 m_molNumSpecies_old[kcomp] = 0.0;
1720 for (
size_t kspec = m_numSpeciesRdc; kspec < m_nsp; ++kspec) {
1721 if (m_phaseID[kspec] == iph) {
1722 m_molNumSpecies_old[kspec] = 0.0;
1723 m_molNumSpecies_new[kspec] = 0.0;
1724 m_deltaMolNumSpecies[kspec] = 0.0;
1729 if (m_debug_print_lvl >= 2) {
1730 plogf(
" --- Make %s", m_speciesName[kspec]);
1731 plogf(
" an active but zeroed species because its phase "
1734 if (kspec != (m_numSpeciesRdc - 1)) {
1736 vcs_switch_pos(
true, (m_numSpeciesRdc - 1), kspec);
1742 m_tPhaseMoles_old[iph] = 0.0;
1743 m_tPhaseMoles_new[iph] = 0.0;
1744 m_deltaPhaseMoles[iph] = 0.0;
1751 int VCS_SOLVE::vcs_recheck_deleted()
1754 if (m_debug_print_lvl >= 2) {
1755 plogf(
" --- Start rechecking deleted species in multispec phases\n");
1757 if (m_numSpeciesRdc == m_nsp) {
1764 for (
size_t kspec = m_numSpeciesRdc; kspec < m_nsp; ++kspec) {
1765 size_t iph = m_phaseID[kspec];
1766 m_feSpecies_new[kspec] = (m_SSfeSpecies[kspec] + log(m_actCoeffSpecies_old[kspec])
1767 - m_lnMnaughtSpecies[kspec]
1768 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iph]);
1775 for (
size_t iph = 0; iph < m_numPhases; iph++) {
1776 if (m_tPhaseMoles_old[iph] > 0.0) {
1779 xtcutoff[iph] = 0.0;
1805 for (
size_t irxn = m_numRxnRdc; irxn < m_numRxnTot; ++irxn) {
1806 size_t kspec = m_indexRxnToSpecies[irxn];
1807 size_t iph = m_phaseID[kspec];
1808 if (m_tPhaseMoles_old[iph] == 0.0) {
1809 if (m_deltaGRxn_new[irxn] < 0.0) {
1810 vcs_reinsert_deleted(kspec);
1813 m_molNumSpecies_old[kspec] = 0.0;
1815 }
else if (m_tPhaseMoles_old[iph] > 0.0) {
1816 if (m_deltaGRxn_new[irxn] < xtcutoff[iph]) {
1817 vcs_reinsert_deleted(kspec);
1825 size_t VCS_SOLVE::vcs_add_all_deleted()
1827 if (m_numSpeciesRdc == m_nsp) {
1836 m_molNumSpecies_new = m_molNumSpecies_old;
1837 for (
int cits = 0; cits < 3; cits++) {
1838 for (
size_t kspec = m_numSpeciesRdc; kspec < m_nsp; ++kspec) {
1839 size_t iph = m_phaseID[kspec];
1841 if (m_molNumSpecies_new[kspec] == 0.0) {
1847 m_feSpecies_new[kspec] = (m_SSfeSpecies[kspec] + log(m_actCoeffSpecies_new[kspec]) - m_lnMnaughtSpecies[kspec]
1848 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iph]);
1854 for (
size_t irxn = m_numRxnRdc; irxn < m_numRxnTot; ++irxn) {
1855 size_t kspec = m_indexRxnToSpecies[irxn];
1856 size_t iph = m_phaseID[kspec];
1857 if (m_tPhaseMoles_old[iph] > 0.0) {
1858 double maxDG = std::min(m_deltaGRxn_new[irxn], 690.0);
1859 double dx = m_tPhaseMoles_old[iph] * exp(- maxDG);
1860 m_molNumSpecies_new[kspec] = dx;
1864 for (
size_t irxn = m_numRxnRdc; irxn < m_numRxnTot; ++irxn) {
1865 size_t kspec = m_indexRxnToSpecies[irxn];
1866 size_t iph = m_phaseID[kspec];
1867 if (m_tPhaseMoles_old[iph] > 0.0) {
1868 double dx = m_molNumSpecies_new[kspec];
1869 size_t retn = delta_species(kspec, &dx);
1871 if (m_debug_print_lvl) {
1872 plogf(
" --- add_deleted(): delta_species() failed for species %s (%d) with mol number %g\n",
1873 m_speciesName[kspec], kspec, dx);
1877 retn = delta_species(kspec, &dx);
1878 if (retn == 0 && m_debug_print_lvl) {
1879 plogf(
" --- add_deleted(): delta_species() failed for species %s (%d) with mol number %g\n",
1880 m_speciesName[kspec], kspec, dx);
1884 if (m_debug_print_lvl >= 2) {
1886 plogf(
" --- add_deleted(): species %s added back in with mol number %g\n",
1887 m_speciesName[kspec], dx);
1889 plogf(
" --- add_deleted(): species %s failed to be added back in\n");
1899 for (
size_t irxn = m_numRxnRdc; irxn < m_numRxnTot; ++irxn) {
1900 size_t kspec = m_indexRxnToSpecies[irxn];
1901 size_t iph = m_phaseID[kspec];
1902 if (m_tPhaseMoles_old[iph] > 0.0 && fabs(m_deltaGRxn_old[irxn]) > m_tolmin) {
1903 if (((m_molNumSpecies_old[kspec] * exp(-m_deltaGRxn_old[irxn])) >
1907 if (m_debug_print_lvl >= 2) {
1908 plogf(
" --- add_deleted(): species %s with mol number %g not converged: DG = %g\n",
1909 m_speciesName[kspec], m_molNumSpecies_old[kspec],
1910 m_deltaGRxn_old[irxn]);
1918 bool VCS_SOLVE::vcs_globStepDamp()
1920 double* dptr = &m_deltaGRxn_new[0];
1924 for (
size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
1925 size_t kspec = irxn + m_numComponents;
1927 s2 += dptr[irxn] * m_deltaMolNumSpecies[kspec];
1933 dptr = &m_deltaGRxn_old[0];
1934 for (
size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
1935 size_t kspec = irxn + m_numComponents;
1937 s1 += dptr[irxn] * m_deltaMolNumSpecies[kspec];
1941 if (m_debug_print_lvl >= 2) {
1942 plogf(
" --- subroutine FORCE: Beginning Slope = %g\n", s1);
1943 plogf(
" --- subroutine FORCE: End Slope = %g\n", s2);
1947 if (m_debug_print_lvl >= 2) {
1948 plogf(
" --- subroutine FORCE produced no adjustments,");
1950 plogf(
" s1 positive but really small\n");
1952 plogf(
" failed s1 test\n");
1959 debuglog(
" --- subroutine FORCE produced no adjustments, s2 < 0\n", m_debug_print_lvl >= 2);
1965 if (fabs(s1 -s2) > 1.0E-200) {
1966 al = s1 / (s1 - s2);
1968 if (al >= 0.95 || al < 0.0) {
1969 if (m_debug_print_lvl >= 2) {
1970 plogf(
" --- subroutine FORCE produced no adjustments (al = %g)\n", al);
1974 if (m_debug_print_lvl >= 2) {
1975 plogf(
" --- subroutine FORCE produced a damping factor = %g\n", al);
1979 if (m_debug_print_lvl >= 2) {
1980 m_deltaGRxn_tmp = m_deltaGRxn_new;
1983 dptr = &m_molNumSpecies_new[0];
1984 for (
size_t kspec = 0; kspec < m_numSpeciesRdc; ++kspec) {
1985 m_molNumSpecies_new[kspec] = m_molNumSpecies_old[kspec] +
1986 al * m_deltaMolNumSpecies[kspec];
1988 for (
size_t iph = 0; iph < m_numPhases; iph++) {
1989 m_tPhaseMoles_new[iph] = m_tPhaseMoles_old[iph] + al * m_deltaPhaseMoles[iph];
1993 if (m_debug_print_lvl >= 2) {
1994 plogf(
" --- subroutine FORCE adjusted the mole "
1995 "numbers, AL = %10.3f\n", al);
2008 dptr = &m_deltaGRxn_new[0];
2010 for (
size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
2011 size_t kspec = irxn + m_numComponents;
2013 s2 += dptr[irxn] * m_deltaMolNumSpecies[kspec];
2017 if (m_debug_print_lvl >= 2) {
2018 plogf(
" --- subroutine FORCE: Adj End Slope = %g\n", s2);
2023 int VCS_SOLVE::vcs_basopt(
const bool doJustComponents,
double aw[],
double sa[],
double sm[],
2024 double ss[],
double test,
bool*
const usedZeroedSpecies)
2028 size_t jlose =
npos;
2031 if (m_debug_print_lvl >= 2) {
2033 for (
size_t i=0; i<77; i++) {
2037 plogf(
" --- Subroutine BASOPT called to ");
2038 if (doJustComponents) {
2039 plogf(
"calculate the number of components\n");
2041 plogf(
"reevaluate the components\n");
2043 if (m_debug_print_lvl >= 2) {
2045 plogf(
" --- Formula Matrix used in BASOPT calculation\n");
2046 plogf(
" --- Active | ");
2047 for (
size_t j = 0; j < m_nelem; j++) {
2048 plogf(
" %1d ", m_elementActive[j]);
2051 plogf(
" --- Species | ");
2052 for (
size_t j = 0; j < m_nelem; j++) {
2053 writelog(
" {:>8.8s}", m_elementName[j]);
2056 for (k = 0; k < m_nsp; k++) {
2057 writelog(
" --- {:>11.11s} | ", m_speciesName[k]);
2058 for (
size_t j = 0; j < m_nelem; j++) {
2059 plogf(
" %8.2g", m_formulaMatrix(k,j));
2070 size_t ncTrial = std::min(m_nelem, m_nsp);
2071 m_numComponents = ncTrial;
2072 *usedZeroedSpecies =
false;
2076 std::copy(m_molNumSpecies_old.begin(),
2077 m_molNumSpecies_old.begin() + m_nsp, aw);
2080 for (k = 0; k < m_nsp; k++) {
2090 while (jr < ncTrial) {
2098 k = vcs_basisOptMax(aw, jr, m_nsp);
2138 *usedZeroedSpecies =
true;
2139 double maxConcPossKspec = 0.0;
2140 double maxConcPoss = 0.0;
2141 size_t kfound =
npos;
2142 int minNonZeroes = 100000;
2143 int nonZeroesKspec = 0;
2144 for (
size_t kspec = ncTrial; kspec < m_nsp; kspec++) {
2146 maxConcPossKspec = 1.0E10;
2148 for (
size_t j = 0; j < m_nelem; ++j) {
2150 double nu = m_formulaMatrix(kspec,j);
2153 maxConcPossKspec = std::min(m_elemAbundancesGoal[j] / nu, maxConcPossKspec);
2157 if ((maxConcPossKspec >= maxConcPoss) || (maxConcPossKspec > 1.0E-5)) {
2158 if (nonZeroesKspec <= minNonZeroes) {
2159 if (kfound ==
npos || nonZeroesKspec < minNonZeroes) {
2164 if (m_SSfeSpecies[kspec] <= m_SSfeSpecies[kfound]) {
2169 minNonZeroes = std::min(minNonZeroes, nonZeroesKspec);
2170 maxConcPoss = std::max(maxConcPoss, maxConcPossKspec);
2174 if (kfound ==
npos) {
2177 for (
size_t kspec = ncTrial; kspec < m_nsp; kspec++) {
2178 if (aw[kspec] >= 0.0) {
2179 size_t irxn = kspec - ncTrial;
2180 if (m_deltaGRxn_new[irxn] < gmin) {
2181 gmin = m_deltaGRxn_new[irxn];
2190 if (aw[k] == test) {
2191 m_numComponents = jr;
2192 ncTrial = m_numComponents;
2193 size_t numPreDeleted = m_numRxnTot - m_numRxnRdc;
2194 if (numPreDeleted != (m_nsp - m_numSpeciesRdc)) {
2195 throw CanteraError(
"VCS_SOLVE::vcs_basopt",
"we shouldn't be here");
2197 m_numRxnTot = m_nsp - ncTrial;
2198 m_numRxnRdc = m_numRxnTot - numPreDeleted;
2199 m_numSpeciesRdc = m_nsp - numPreDeleted;
2200 for (
size_t i = 0; i < m_nsp; ++i) {
2201 m_indexRxnToSpecies[i] = ncTrial + i;
2203 if (m_debug_print_lvl >= 2) {
2204 plogf(
" --- Total number of components found = %3d (ne = %d)\n ",
2219 for (
size_t j = 0; j < m_nelem; ++j) {
2220 sm[j + jr*m_nelem] = m_formulaMatrix(k,j);
2226 for (
size_t j = 0; j < jl; ++j) {
2228 for (
size_t i = 0; i < m_nelem; ++i) {
2229 ss[j] += sm[i + jr*m_nelem] * sm[i + j*m_nelem];
2235 for (
size_t j = 0; j < jl; ++j) {
2236 for (
size_t i = 0; i < m_nelem; ++i) {
2237 sm[i + jr*m_nelem] -= ss[j] * sm[i + j*m_nelem];
2245 for (
size_t ml = 0; ml < m_nelem; ++ml) {
2246 sa[jr] += pow(sm[ml + jr*m_nelem], 2);
2250 if (sa[jr] > 1.0e-6) {
2257 if (m_debug_print_lvl >= 2) {
2258 plogf(
" --- %-12.12s", m_speciesName[k]);
2260 plogf(
"(Volts = %9.2g)", m_molNumSpecies_old[k]);
2262 plogf(
"(%9.2g)", m_molNumSpecies_old[k]);
2264 plogf(
" replaces %-12.12s", m_speciesName[jr]);
2266 plogf(
"(Volts = %9.2g)", m_molNumSpecies_old[jr]);
2268 plogf(
"(%9.2g)", m_molNumSpecies_old[jr]);
2270 plogf(
" as component %3d\n", jr);
2272 vcs_switch_pos(
false, jr, k);
2273 std::swap(aw[jr], aw[k]);
2274 }
else if (m_debug_print_lvl >= 2) {
2275 plogf(
" --- %-12.12s", m_speciesName[k]);
2277 plogf(
"(Volts = %9.2g) remains ", m_molNumSpecies_old[k]);
2279 plogf(
"(%9.2g) remains ", m_molNumSpecies_old[k]);
2281 plogf(
" as component %3d\n", jr);
2290 if (doJustComponents) {
2320 C.
resize(ncTrial, ncTrial);
2321 for (
size_t j = 0; j < ncTrial; ++j) {
2322 for (
size_t i = 0; i < ncTrial; ++i) {
2323 C(i, j) = m_formulaMatrix(j,i);
2326 for (
size_t i = 0; i < m_numRxnTot; ++i) {
2327 k = m_indexRxnToSpecies[i];
2328 for (
size_t j = 0; j < ncTrial; ++j) {
2329 m_stoichCoeffRxnMatrix(j,i) = - m_formulaMatrix(k,j);
2334 solve(C, m_stoichCoeffRxnMatrix.
ptrColumn(0), m_numRxnTot, m_nelem);
2340 for (
size_t j = 0; j < m_nelem; j++) {
2341 if (!m_elementActive[j] && !strcmp(m_elementName[j].c_str(),
"E")) {
2345 for (
size_t j = 0; j < m_nelem; j++) {
2346 if (m_elementActive[j] && !strncmp((m_elementName[j]).c_str(),
"cn_", 3)) {
2350 for (k = 0; k < m_nsp; k++) {
2352 for (
size_t j = 0; j < ncTrial; ++j) {
2353 for (
size_t i = 0; i < ncTrial; ++i) {
2355 C(i, j) = m_formulaMatrix(j,juse);
2357 C(i, j) = m_formulaMatrix(j,i);
2361 for (
size_t i = 0; i < m_numRxnTot; ++i) {
2362 k = m_indexRxnToSpecies[i];
2363 for (
size_t j = 0; j < ncTrial; ++j) {
2365 aw[j] = - m_formulaMatrix(k,juse);
2367 aw[j] = - m_formulaMatrix(k,j);
2372 solve(C, aw, 1, m_nelem);
2373 size_t i = k - ncTrial;
2374 for (
size_t j = 0; j < ncTrial; j++) {
2375 m_stoichCoeffRxnMatrix(j,i) = aw[j];
2381 for (
size_t i = 0; i < m_numRxnTot; i++) {
2383 for (
size_t j = 0; j < ncTrial; j++) {
2384 szTmp += fabs(m_stoichCoeffRxnMatrix(j,i));
2386 m_scSize[i] = szTmp;
2389 if (m_debug_print_lvl >= 2) {
2390 plogf(
" --- Components:");
2391 for (
size_t j = 0; j < ncTrial; j++) {
2394 plogf(
"\n --- Components Moles:");
2395 for (
size_t j = 0; j < ncTrial; j++) {
2397 plogf(
" % -10.3E", 0.0);
2399 plogf(
" % -10.3E", m_molNumSpecies_old[j]);
2402 plogf(
"\n --- NonComponent| Moles |");
2403 for (
size_t j = 0; j < ncTrial; j++) {
2404 plogf(
" %10.10s", m_speciesName[j]);
2407 for (
size_t i = 0; i < m_numRxnTot; i++) {
2408 plogf(
" --- %3d ", m_indexRxnToSpecies[i]);
2409 plogf(
"%-10.10s", m_speciesName[m_indexRxnToSpecies[i]]);
2411 plogf(
"|% -10.3E|", 0.0);
2413 plogf(
"|% -10.3E|", m_molNumSpecies_old[m_indexRxnToSpecies[i]]);
2415 for (
size_t j = 0; j < ncTrial; j++) {
2416 plogf(
" %+7.3f", m_stoichCoeffRxnMatrix(j,i));
2423 double sumMax = -1.0;
2426 for (
size_t i = 0; i < m_numRxnTot; ++i) {
2427 k = m_indexRxnToSpecies[i];
2429 for (
size_t j = 0; j < ncTrial; ++j) {
2431 sum = m_formulaMatrix(k,juse);
2432 for (
size_t n = 0; n < ncTrial; n++) {
2433 double numElements = m_formulaMatrix(n,juse);
2434 double coeff = m_stoichCoeffRxnMatrix(n,i);
2435 sum += coeff * numElements;
2438 sum = m_formulaMatrix(k,j);
2439 for (
size_t n = 0; n < ncTrial; n++) {
2440 double numElements = m_formulaMatrix(n,j);
2441 double coeff = m_stoichCoeffRxnMatrix(n,i);
2442 sum += coeff * numElements;
2445 if (fabs(sum) > sumMax) {
2453 if (fabs(sum) > 1.0E-6) {
2454 throw CanteraError(
"VCS_SOLVE::vcs_basopt",
"we have a prob");
2458 plogf(
" --- largest error in Stoich coeff = %g at rxn = %d ", sumMax, iMax);
2459 plogf(
"%-10.10s", m_speciesName[m_indexRxnToSpecies[iMax]]);
2460 plogf(
" element = %d ", jMax);
2461 plogf(
"%-5.5s", m_elementName[jMax]);
2464 for (
size_t i=0; i<77; i++) {
2476 m_deltaMolNumPhase.zero();
2477 m_phaseParticipation.zero();
2482 for (
size_t irxn = 0; irxn < m_numRxnTot; ++irxn) {
2483 double* scrxn_ptr = m_stoichCoeffRxnMatrix.ptrColumn(irxn);
2484 size_t kspec = m_indexRxnToSpecies[irxn];
2485 size_t iph = m_phaseID[kspec];
2486 m_deltaMolNumPhase(iph,irxn) = 1.0;
2487 m_phaseParticipation(iph,irxn)++;
2488 for (
size_t j = 0; j < ncTrial; ++j) {
2490 if (fabs(scrxn_ptr[j]) <= 1.0e-6) {
2493 m_deltaMolNumPhase(iph,irxn) += scrxn_ptr[j];
2494 m_phaseParticipation(iph,irxn)++;
2502 m_VCount->Time_basopt += tsecond;
2503 m_VCount->Basis_Opts++;
2507 size_t VCS_SOLVE::vcs_basisOptMax(
const double*
const molNum,
const size_t j,
2524 double big = molNum[j] * m_spSize[j] * 1.01;
2525 if (m_spSize[j] <= 0.0) {
2527 "spSize is nonpositive");
2529 for (
size_t i = j + 1; i < n; ++i) {
2530 if (m_spSize[i] <= 0.0) {
2532 "spSize is nonpositive");
2534 bool doSwap =
false;
2536 doSwap = (molNum[i] * m_spSize[i]) > big;
2537 if (!m_SSPhase[i] && doSwap) {
2538 doSwap = molNum[i] > (molNum[largest] * 1.001);
2542 doSwap = (molNum[i] * m_spSize[i]) > big;
2544 doSwap = molNum[i] > (molNum[largest] * 1.001);
2547 doSwap = (molNum[i] * m_spSize[i]) > big;
2552 big = molNum[i] * m_spSize[i] * 1.01;
2558 int VCS_SOLVE::vcs_species_type(
const size_t kspec)
const
2565 size_t iph = m_phaseID[kspec];
2566 int irxn = int(kspec) - int(m_numComponents);
2567 int phaseExist = m_VolPhaseList[iph]->exists();
2570 if (m_molNumSpecies_old[kspec] <= 0.0) {
2571 if (m_tPhaseMoles_old[iph] <= 0.0 && !m_SSPhase[kspec]) {
2577 for (
size_t j = 0; j < m_nelem; ++j) {
2579 double atomComp = m_formulaMatrix(kspec,j);
2580 if (atomComp > 0.0) {
2581 double maxPermissible = m_elemAbundancesGoal[j] / atomComp;
2583 if (m_debug_print_lvl >= 2) {
2584 plogf(
" --- %s can not be nonzero because"
2585 " needed element %s is zero\n",
2586 m_speciesName[kspec], m_elementName[j]);
2588 if (m_SSPhase[kspec]) {
2603 for (
size_t j = 0; j < m_numComponents; ++j) {
2604 double stoicC = m_stoichCoeffRxnMatrix(j,irxn);
2605 if (stoicC != 0.0) {
2606 double negChangeComp = - stoicC;
2607 if (negChangeComp > 0.0) {
2608 if (m_molNumSpecies_old[j] < 1.0E-60) {
2609 if (m_debug_print_lvl >= 2) {
2610 plogf(
" --- %s is prevented from popping into existence because"
2611 " a needed component to be consumed, %s, has a zero mole number\n",
2612 m_speciesName[kspec], m_speciesName[j]);
2614 if (m_SSPhase[kspec]) {
2620 }
else if (negChangeComp < 0.0) {
2621 if (m_VolPhaseList[m_phaseID[j]]->exists() <= 0) {
2622 if (m_debug_print_lvl >= 2) {
2623 plogf(
" --- %s is prevented from popping into existence because"
2624 " a needed component %s is in a zeroed-phase that would be "
2625 "popped into existence at the same time\n",
2626 m_speciesName[kspec], m_speciesName[j]);
2628 if (m_SSPhase[kspec]) {
2639 if (irxn >= 0 && m_deltaGRxn_old[irxn] >= 0.0) {
2641 if (m_SSPhase[kspec]) {
2655 if (m_tPhaseMoles_old[iph] > 0.0) {
2656 if (m_SSPhase[kspec]) {
2667 if (m_tPhaseMoles_old[iph] <= 0.0) {
2668 if (m_SSPhase[kspec]) {
2680 if (m_SSPhase[kspec]) {
2689 if (m_molNumSpecies_old[kspec] > (m_tPhaseMoles_old[iph] * 0.001)) {
2701 double szAdj = m_scSize[irxn] * std::sqrt((
double)m_numRxnTot);
2702 for (
size_t k = 0; k < m_numComponents; ++k) {
2703 if (!m_SSPhase[k] && m_stoichCoeffRxnMatrix(k,irxn) != 0.0 && m_molNumSpecies_old[kspec] * szAdj >= m_molNumSpecies_old[k] * 0.01) {
2711 void VCS_SOLVE::vcs_dfe(
const int stateCalc,
2712 const int ll,
const size_t lbot,
const size_t ltop)
2714 double* tPhMoles_ptr=0;
2715 double* actCoeff_ptr=0;
2716 double* feSpecies=0;
2719 feSpecies = &m_feSpecies_old[0];
2720 tPhMoles_ptr = &m_tPhaseMoles_old[0];
2721 actCoeff_ptr = &m_actCoeffSpecies_old[0];
2722 molNum = &m_molNumSpecies_old[0];
2724 feSpecies = &m_feSpecies_new[0];
2725 tPhMoles_ptr = &m_tPhaseMoles_new[0];
2726 actCoeff_ptr = &m_actCoeffSpecies_new[0];
2727 molNum = &m_molNumSpecies_new[0];
2730 "Subroutine vcs_dfe called with bad stateCalc value: {}", stateCalc);
2733 if (m_debug_print_lvl >= 2) {
2736 plogf(
" --- Subroutine vcs_dfe called for one species: ");
2737 plogf(
"%-12.12s", m_speciesName[lbot]);
2739 plogf(
" --- Subroutine vcs_dfe called for all species");
2741 }
else if (ll > 0) {
2742 plogf(
" --- Subroutine vcs_dfe called for components and minors");
2744 plogf(
" --- Subroutine vcs_dfe called for components and majors");
2747 plogf(
" using tentative solution");
2752 double* tlogMoles = &m_TmpPhase[0];
2756 double* tPhInertMoles = &TPhInertMoles[0];
2757 for (
size_t iph = 0; iph < m_numPhases; iph++) {
2758 tlogMoles[iph] = tPhInertMoles[iph];
2761 for (
size_t kspec = 0; kspec < m_nsp; kspec++) {
2763 size_t iph = m_phaseID[kspec];
2764 tlogMoles[iph] += molNum[kspec];
2767 for (
size_t iph = 0; iph < m_numPhases; iph++) {
2769 "VCS_SOLVE::vcs_dfe",
2770 "phase Moles may be off, iph = {}, {} {}",
2771 iph, tlogMoles[iph], tPhMoles_ptr[iph]);
2773 m_TmpPhase.assign(m_TmpPhase.size(), 0.0);
2774 for (
size_t iph = 0; iph < m_numPhases; iph++) {
2775 if (tPhMoles_ptr[iph] > 0.0) {
2776 tlogMoles[iph] = log(tPhMoles_ptr[iph]);
2783 l2 = m_numComponents;
2792 for (
size_t iphase = 0; iphase < m_numPhases; iphase++) {
2807 for (
size_t kspec = l1; kspec < l2; ++kspec) {
2808 size_t iphase = m_phaseID[kspec];
2810 AssertThrowMsg(molNum[kspec] == m_phasePhi[iphase],
"VCS_SOLVE::vcs_dfe",
2811 "We have an inconsistency!");
2812 AssertThrowMsg(m_chargeSpecies[kspec] == -1.0,
"VCS_SOLVE::vcs_dfe",
2813 "We have an unexpected situation!");
2814 feSpecies[kspec] = m_SSfeSpecies[kspec]
2815 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2817 if (m_SSPhase[kspec]) {
2818 feSpecies[kspec] = m_SSfeSpecies[kspec]
2819 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2822 feSpecies[kspec] = m_SSfeSpecies[kspec] - m_lnMnaughtSpecies[kspec]
2823 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2826 size_t iph = m_phaseID[kspec];
2827 if (tPhMoles_ptr[iph] > 0.0) {
2828 feSpecies[kspec] = m_SSfeSpecies[kspec]
2830 - tlogMoles[m_phaseID[kspec]] - m_lnMnaughtSpecies[kspec]
2831 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2833 feSpecies[kspec] = m_SSfeSpecies[kspec] - m_lnMnaughtSpecies[kspec]
2834 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2837 feSpecies[kspec] = m_SSfeSpecies[kspec]
2838 + log(actCoeff_ptr[kspec] * molNum[kspec])
2839 - tlogMoles[m_phaseID[kspec]] - m_lnMnaughtSpecies[kspec]
2840 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2848 for (
size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
2849 size_t kspec = m_indexRxnToSpecies[irxn];
2851 size_t iphase = m_phaseID[kspec];
2853 AssertThrowMsg(molNum[kspec] == m_phasePhi[iphase],
"VCS_SOLVE::vcs_dfe",
2854 "We have an inconsistency!");
2855 AssertThrowMsg(m_chargeSpecies[kspec] == -1.0,
"VCS_SOLVE::vcs_dfe",
2856 "We have an unexpected situation!");
2857 feSpecies[kspec] = m_SSfeSpecies[kspec]
2858 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2860 if (m_SSPhase[kspec]) {
2861 feSpecies[kspec] = m_SSfeSpecies[kspec]
2862 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2865 feSpecies[kspec] = m_SSfeSpecies[kspec] - m_lnMnaughtSpecies[kspec]
2866 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2869 size_t iph = m_phaseID[kspec];
2870 if (tPhMoles_ptr[iph] > 0.0) {
2871 feSpecies[kspec] = m_SSfeSpecies[kspec]
2873 - tlogMoles[m_phaseID[kspec]] - m_lnMnaughtSpecies[kspec]
2874 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2876 feSpecies[kspec] = m_SSfeSpecies[kspec] - m_lnMnaughtSpecies[kspec]
2877 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2880 feSpecies[kspec] = m_SSfeSpecies[kspec]
2881 + log(actCoeff_ptr[kspec] * molNum[kspec])
2882 - tlogMoles[m_phaseID[kspec]] - m_lnMnaughtSpecies[kspec]
2883 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2889 }
else if (ll > 0) {
2891 for (
size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
2892 size_t kspec = m_indexRxnToSpecies[irxn];
2894 size_t iphase = m_phaseID[kspec];
2896 AssertThrowMsg(molNum[kspec] == m_phasePhi[iphase],
"VCS_SOLVE::vcs_dfe",
2897 "We have an inconsistency!");
2898 AssertThrowMsg(m_chargeSpecies[kspec] == -1.0,
"VCS_SOLVE::vcs_dfe",
2899 "We have an unexpected situation!");
2900 feSpecies[kspec] = m_SSfeSpecies[kspec]
2901 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2903 if (m_SSPhase[kspec]) {
2904 feSpecies[kspec] = m_SSfeSpecies[kspec]
2905 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2908 feSpecies[kspec] = m_SSfeSpecies[kspec] - m_lnMnaughtSpecies[kspec]
2909 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2912 size_t iph = m_phaseID[kspec];
2913 if (tPhMoles_ptr[iph] > 0.0) {
2914 feSpecies[kspec] = m_SSfeSpecies[kspec]
2916 - tlogMoles[m_phaseID[kspec]] - m_lnMnaughtSpecies[kspec]
2917 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2919 feSpecies[kspec] = m_SSfeSpecies[kspec] - m_lnMnaughtSpecies[kspec]
2920 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2923 feSpecies[kspec] = m_SSfeSpecies[kspec]
2924 + log(actCoeff_ptr[kspec] * molNum[kspec])
2925 - tlogMoles[m_phaseID[kspec]] - m_lnMnaughtSpecies[kspec]
2926 + m_chargeSpecies[kspec] * m_Faraday_dim * m_phasePhi[iphase];
2935 double VCS_SOLVE::l2normdg(
double dgLocal[])
const
2937 if (m_numRxnRdc <= 0) {
2941 for (
size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
2942 size_t kspec = irxn + m_numComponents;
2944 dgLocal[irxn] < 0.0) {
2946 tmp += dgLocal[irxn] * dgLocal[irxn];
2950 return std::sqrt(tmp / m_numRxnRdc);
2953 double VCS_SOLVE::vcs_tmoles()
2955 for (
size_t i = 0; i < m_numPhases; i++) {
2956 m_tPhaseMoles_old[i] = TPhInertMoles[i];
2958 for (
size_t i = 0; i < m_nsp; i++) {
2960 m_tPhaseMoles_old[m_phaseID[i]] += m_molNumSpecies_old[i];
2964 for (
size_t i = 0; i < m_numPhases; i++) {
2965 sum += m_tPhaseMoles_old[i];
2967 if (m_tPhaseMoles_old[i] == 0.0) {
2973 m_totalMolNum = sum;
2974 return m_totalMolNum;
2977 void VCS_SOLVE::check_tmoles()
const
2980 for (
size_t i = 0; i < m_numPhases; i++) {
2981 double m_tPhaseMoles_old_a = TPhInertMoles[i];
2983 for (
size_t k = 0; k < m_nsp; k++) {
2985 m_tPhaseMoles_old_a += m_molNumSpecies_old[k];
2988 sum += m_tPhaseMoles_old_a;
2990 double denom = m_tPhaseMoles_old[i]+ m_tPhaseMoles_old_a + 1.0E-19;
2991 if (!
vcs_doubleEqual(m_tPhaseMoles_old[i]/denom, m_tPhaseMoles_old_a/denom)) {
2992 plogf(
"check_tmoles: we have found a problem with phase %d: %20.15g, %20.15g\n",
2993 i, m_tPhaseMoles_old[i], m_tPhaseMoles_old_a);
2998 void VCS_SOLVE::vcs_updateVP(
const int vcsState)
3000 for (
size_t i = 0; i < m_numPhases; i++) {
3004 &m_molNumSpecies_old[0],
3005 &m_tPhaseMoles_old[0]);
3008 &m_molNumSpecies_new[0],
3009 &m_tPhaseMoles_new[0]);
3012 "wrong stateCalc value: {}", vcsState);
3017 bool VCS_SOLVE::vcs_evaluate_speciesType()
3019 m_numRxnMinorZeroed = 0;
3020 if (m_debug_print_lvl >= 2) {
3021 plogf(
" --- Species Status decision is reevaluated: All species are minor except for:\n");
3022 }
else if (m_debug_print_lvl >= 5) {
3023 plogf(
" --- Species Status decision is reevaluated\n");
3025 for (
size_t kspec = 0; kspec < m_nsp; ++kspec) {
3026 m_speciesStatus[kspec] = vcs_species_type(kspec);
3027 if (m_debug_print_lvl >= 5) {
3028 plogf(
" --- %-16s: ", m_speciesName[kspec]);
3029 if (kspec < m_numComponents) {
3034 plogf(
" %10.3g ", m_molNumSpecies_old[kspec]);
3036 plogf(
"%s\n", sString);
3037 }
else if (m_debug_print_lvl >= 2) {
3039 switch (m_speciesStatus[kspec]) {
3043 plogf(
" --- Major Species : %-s\n", m_speciesName[kspec]);
3046 plogf(
" --- Purposely Zeroed-Phase Species (not in problem): %-s\n",
3047 m_speciesName[kspec]);
3050 plogf(
" --- Zeroed-MS Phase Species: %-s\n", m_speciesName[kspec]);
3053 plogf(
" --- Zeroed-SS Phase Species: %-s\n", m_speciesName[kspec]);
3056 plogf(
" --- Deleted-Small Species : %-s\n", m_speciesName[kspec]);
3059 plogf(
" --- Zeroed Species in an active MS phase (tmp): %-s\n",
3060 m_speciesName[kspec]);
3063 plogf(
" --- Zeroed Species in an active MS phase (Stoich Constraint): %-s\n",
3064 m_speciesName[kspec]);
3067 plogf(
" --- InterfaceVoltage Species: %-s\n", m_speciesName[kspec]);
3070 throw CanteraError(
"VCS_SOLVE::vcs_evaluate_speciesType",
3071 "Unknown type: {}", m_speciesStatus[kspec]);
3076 ++m_numRxnMinorZeroed;
3079 debuglog(
" ---\n", m_debug_print_lvl >= 2);
3080 return (m_numRxnMinorZeroed >= m_numRxnRdc);
3083 void VCS_SOLVE::vcs_deltag(
const int L,
const bool doDeleted,
3084 const int vcsState,
const bool alterZeroedPhases)
3086 size_t irxnl = m_numRxnRdc;
3088 irxnl = m_numRxnTot;
3093 double* molNumSpecies;
3094 double* actCoeffSpecies;
3096 deltaGRxn = &m_deltaGRxn_new[0];
3097 feSpecies = &m_feSpecies_new[0];
3098 molNumSpecies = &m_molNumSpecies_new[0];
3099 actCoeffSpecies = &m_actCoeffSpecies_new[0];
3101 deltaGRxn = &m_deltaGRxn_old[0];
3102 feSpecies = &m_feSpecies_old[0];
3103 molNumSpecies = &m_molNumSpecies_old[0];
3104 actCoeffSpecies = &m_actCoeffSpecies_old[0];
3106 throw CanteraError(
"VCS_SOLVE::vcs_deltag",
"bad vcsState");
3109 if (m_debug_print_lvl >= 2) {
3110 plogf(
" --- Subroutine vcs_deltag called for ");
3112 plogf(
"major noncomponents\n");
3113 }
else if (L == 0) {
3114 plogf(
"all noncomponents\n");
3116 plogf(
"minor noncomponents\n");
3122 for (
size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
3123 size_t kspec = irxn + m_numComponents;
3126 deltaGRxn[irxn] = feSpecies[m_indexRxnToSpecies[irxn]];
3127 double* dtmp_ptr = m_stoichCoeffRxnMatrix.ptrColumn(irxn);
3128 for (kspec = 0; kspec < m_numComponents; ++kspec) {
3129 deltaGRxn[irxn] += dtmp_ptr[kspec] * feSpecies[kspec];
3135 deltaGRxn[irxn] = std::max(0.0, deltaGRxn[irxn]);
3139 }
else if (L == 0) {
3141 for (
size_t irxn = 0; irxn < irxnl; ++irxn) {
3143 deltaGRxn[irxn] = feSpecies[m_indexRxnToSpecies[irxn]];
3144 double* dtmp_ptr = m_stoichCoeffRxnMatrix.ptrColumn(irxn);
3145 for (
size_t kspec = 0; kspec < m_numComponents; ++kspec) {
3146 deltaGRxn[irxn] += dtmp_ptr[kspec] * feSpecies[kspec];
3148 dtmp_ptr[kspec] < 0.0) {
3153 deltaGRxn[irxn] = std::max(0.0, deltaGRxn[irxn]);
3158 for (
size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
3159 size_t kspec = irxn + m_numComponents;
3162 deltaGRxn[irxn] = feSpecies[m_indexRxnToSpecies[irxn]];
3163 double* dtmp_ptr = m_stoichCoeffRxnMatrix.ptrColumn(irxn);
3164 for (kspec = 0; kspec < m_numComponents; ++kspec) {
3165 deltaGRxn[irxn] += dtmp_ptr[kspec] * feSpecies[kspec];
3167 dtmp_ptr[kspec] < 0.0) {
3172 deltaGRxn[irxn] = std::max(0.0, deltaGRxn[irxn]);
3217 if (alterZeroedPhases &&
false) {
3218 for (
size_t iph = 0; iph < m_numPhases; iph++) {
3223 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
3226 sum += molNumSpecies[kspec];
3239 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
3242 if (kspec >= m_numComponents) {
3243 size_t irxn = kspec - m_numComponents;
3244 deltaGRxn[irxn] =
clip(deltaGRxn[irxn], -50.0, 50.0);
3245 poly += exp(-deltaGRxn[irxn])/actCoeffSpecies[kspec];
3253 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
3255 if (kspec >= m_numComponents) {
3256 size_t irxn = kspec - m_numComponents;
3257 deltaGRxn[irxn] = 1.0 - poly;
3265 void VCS_SOLVE::vcs_printDeltaG(
const int stateCalc)
3267 double* deltaGRxn = &m_deltaGRxn_old[0];
3268 double* feSpecies = &m_feSpecies_old[0];
3269 double* molNumSpecies = &m_molNumSpecies_old[0];
3270 const double* tPhMoles_ptr = &m_tPhaseMoles_old[0];
3271 const double* actCoeff_ptr = &m_actCoeffSpecies_old[0];
3273 deltaGRxn = &m_deltaGRxn_new[0];
3274 feSpecies = &m_feSpecies_new[0];
3275 molNumSpecies = &m_molNumSpecies_new[0];
3276 actCoeff_ptr = &m_actCoeffSpecies_new[0];
3277 tPhMoles_ptr = &m_tPhaseMoles_new[0];
3280 bool zeroedPhase =
false;
3281 if (m_debug_print_lvl >= 2) {
3282 plogf(
" --- DELTA_G TABLE Components:");
3283 for (
size_t j = 0; j < m_numComponents; j++) {
3286 plogf(
"\n --- Components Moles:");
3287 for (
size_t j = 0; j < m_numComponents; j++) {
3288 plogf(
"%10.3g", m_molNumSpecies_old[j]);
3290 plogf(
"\n --- NonComponent| Moles | ");
3291 for (
size_t j = 0; j < m_numComponents; j++) {
3292 plogf(
"%-10.10s", m_speciesName[j]);
3295 for (
size_t i = 0; i < m_numRxnTot; i++) {
3296 plogf(
" --- %3d ", m_indexRxnToSpecies[i]);
3297 plogf(
"%-10.10s", m_speciesName[m_indexRxnToSpecies[i]]);
3301 plogf(
"|%10.3g|", m_molNumSpecies_old[m_indexRxnToSpecies[i]]);
3303 for (
size_t j = 0; j < m_numComponents; j++) {
3304 plogf(
" %6.2f", m_stoichCoeffRxnMatrix(j,i));
3309 for (
int i=0; i<77; i++) {
3315 writelog(
" --- DeltaG Table (J/kmol) Name PhID MoleNum MolFR "
3316 " ElectrChemStar ElectrChem DeltaGStar DeltaG(Pred) Stability\n");
3318 writeline(
'-', 132);
3320 for (
size_t kspec = 0; kspec < m_nsp; kspec++) {
3322 if (kspec >= m_numComponents) {
3323 irxn = kspec - m_numComponents;
3325 double mfValue = 1.0;
3326 size_t iphase = m_phaseID[kspec];
3327 const vcs_VolPhase* Vphase = m_VolPhaseList[iphase].get();
3333 zeroedPhase =
false;
3335 if (tPhMoles_ptr[iphase] > 0.0) {
3339 mfValue = molNumSpecies[kspec] / tPhMoles_ptr[iphase];
3342 size_t klocal = m_speciesLocalPhaseIndex[kspec];
3343 mfValue = Vphase->moleFraction(klocal);
3350 double feFull = feSpecies[kspec];
3353 feFull += log(actCoeff_ptr[kspec]) + log(mfValue);
3355 writelogf(
"%-24.24s", m_speciesName[kspec]);
3360 writelogf(
" % -12.4e", molNumSpecies[kspec]);
3363 writelogf(
" % -12.4e", feSpecies[kspec] * RT);
3366 writelogf(
" % -12.4e", deltaGRxn[irxn] * RT);
3367 writelogf(
" % -12.4e", (deltaGRxn[irxn] + feFull - feSpecies[kspec]) * RT);
3369 if (deltaGRxn[irxn] < 0.0) {
3370 if (molNumSpecies[kspec] > 0.0) {
3375 }
else if (deltaGRxn[irxn] > 0.0) {
3376 if (molNumSpecies[kspec] > 0.0) {
3388 writeline(
'-', 132);
3391 void VCS_SOLVE::vcs_switch_pos(
const bool ifunc,
const size_t k1,
const size_t k2)
3396 if (k1 >= m_nsp || k2 >= m_nsp) {
3397 plogf(
"vcs_switch_pos: ifunc = 0: inappropriate args: %d %d\n",
3402 vcs_VolPhase* pv1 = m_VolPhaseList[m_phaseID[k1]].get();
3403 vcs_VolPhase* pv2 = m_VolPhaseList[m_phaseID[k2]].get();
3404 size_t kp1 = m_speciesLocalPhaseIndex[k1];
3405 size_t kp2 = m_speciesLocalPhaseIndex[k2];
3412 std::swap(m_speciesName[k1], m_speciesName[k2]);
3413 std::swap(m_molNumSpecies_old[k1], m_molNumSpecies_old[k2]);
3414 std::swap(m_speciesUnknownType[k1], m_speciesUnknownType[k2]);
3415 std::swap(m_molNumSpecies_new[k1], m_molNumSpecies_new[k2]);
3416 std::swap(m_SSfeSpecies[k1], m_SSfeSpecies[k2]);
3417 std::swap(m_spSize[k1], m_spSize[k2]);
3418 std::swap(m_deltaMolNumSpecies[k1], m_deltaMolNumSpecies[k2]);
3419 std::swap(m_feSpecies_old[k1], m_feSpecies_old[k2]);
3420 std::swap(m_feSpecies_new[k1], m_feSpecies_new[k2]);
3421 std::swap(m_SSPhase[k1], m_SSPhase[k2]);
3422 std::swap(m_phaseID[k1], m_phaseID[k2]);
3423 std::swap(m_speciesMapIndex[k1], m_speciesMapIndex[k2]);
3424 std::swap(m_speciesLocalPhaseIndex[k1], m_speciesLocalPhaseIndex[k2]);
3425 std::swap(m_actConventionSpecies[k1], m_actConventionSpecies[k2]);
3426 std::swap(m_lnMnaughtSpecies[k1], m_lnMnaughtSpecies[k2]);
3427 std::swap(m_actCoeffSpecies_new[k1], m_actCoeffSpecies_new[k2]);
3428 std::swap(m_actCoeffSpecies_old[k1], m_actCoeffSpecies_old[k2]);
3429 std::swap(m_wtSpecies[k1], m_wtSpecies[k2]);
3430 std::swap(m_chargeSpecies[k1], m_chargeSpecies[k2]);
3431 std::swap(m_speciesThermoList[k1], m_speciesThermoList[k2]);
3432 std::swap(m_PMVolumeSpecies[k1], m_PMVolumeSpecies[k2]);
3434 for (
size_t j = 0; j < m_nelem; ++j) {
3435 std::swap(m_formulaMatrix(k1,j), m_formulaMatrix(k2,j));
3437 if (m_useActCoeffJac && k1 != k2) {
3438 for (
size_t i = 0; i < m_nsp; i++) {
3439 std::swap(m_np_dLnActCoeffdMolNum(k1,i), m_np_dLnActCoeffdMolNum(k2,i));
3441 for (
size_t i = 0; i < m_nsp; i++) {
3442 std::swap(m_np_dLnActCoeffdMolNum(i,k1), m_np_dLnActCoeffdMolNum(i,k2));
3445 std::swap(m_speciesStatus[k1], m_speciesStatus[k2]);
3450 size_t i1 = k1 - m_numComponents;
3451 size_t i2 = k2 - m_numComponents;
3452 if (i1 > m_numRxnTot || i2 >= m_numRxnTot) {
3453 plogf(
"switch_pos: ifunc = 1: inappropriate noncomp values: %d %d\n",
3456 for (
size_t j = 0; j < m_numComponents; ++j) {
3457 std::swap(m_stoichCoeffRxnMatrix(j,i1), m_stoichCoeffRxnMatrix(j,i2));
3459 std::swap(m_scSize[i1], m_scSize[i2]);
3460 for (
size_t iph = 0; iph < m_numPhases; iph++) {
3461 std::swap(m_deltaMolNumPhase(iph,i1), m_deltaMolNumPhase(iph,i2));
3462 std::swap(m_phaseParticipation(iph,i1),
3463 m_phaseParticipation(iph,i2));
3465 std::swap(m_deltaGRxn_new[i1], m_deltaGRxn_new[i2]);
3466 std::swap(m_deltaGRxn_old[i1], m_deltaGRxn_old[i2]);
3467 std::swap(m_deltaGRxn_tmp[i1], m_deltaGRxn_tmp[i2]);
3471 void VCS_SOLVE::vcs_setFlagsVolPhases(
const bool upToDate,
const int stateCalc)
3474 for (
size_t iph = 0; iph < m_numPhases; iph++) {
3475 m_VolPhaseList[iph]->setMolesOutOfDate(stateCalc);
3478 for (
size_t iph = 0; iph < m_numPhases; iph++) {
3479 m_VolPhaseList[iph]->setMolesCurrent(stateCalc);
3484 void VCS_SOLVE::vcs_setFlagsVolPhase(
const size_t iph,
const bool upToDate,
3485 const int stateCalc)
3488 m_VolPhaseList[iph]->setMolesOutOfDate(stateCalc);
3490 m_VolPhaseList[iph]->setMolesCurrent(stateCalc);
3494 void VCS_SOLVE::vcs_updateMolNumVolPhases(
const int stateCalc)
3496 for (
size_t iph = 0; iph < m_numPhases; iph++) {
3497 m_VolPhaseList[iph]->updateFromVCS_MoleNumbers(stateCalc);