21enum stages {MAIN, EQUILIB_CHECK, ELEM_ABUND_CHECK,
22 RECHECK_DELETED, RETURN_A, RETURN_B};
28void VCS_SOLVE::checkDelta1(
double*
const dsLocal,
29 double*
const delTPhMoles,
size_t kspec)
32 for (
size_t k = 0; k < kspec; k++) {
35 dchange[iph] += dsLocal[k];
38 for (
size_t iphase = 0; iphase <
m_numPhases; iphase++) {
40 if (!
vcs_doubleEqual(dchange[iphase]/denom, delTPhMoles[iphase]/denom)) {
41 throw CanteraError(
"VCS_SOLVE::checkDelta1",
42 "we have found a problem");
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;
62 if (printDetails > 0 && print_lvl == 0) {
73 m_aw.assign(
m_nsp, 0.0);
76 int solveFail =
false;
83 plogf(
"VCS CALCULATION METHOD\n\n ");
84 plogf(
"MultiPhase Object\n");
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);
106 plogf(
"\n MODIFIED LINEAR PROGRAMMING ESTIMATE OF EQUILIBRIUM - forced\n");
108 plogf(
"\n MODIFIED LINEAR PROGRAMMING ESTIMATE OF EQUILIBRIUM - where necessary\n");
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) {
123 for (
size_t i = 0; i <
m_nsp; ++i) {
125 for (
size_t j = 0; j <
m_nelem; ++j) {
129 writeline(
' ', std::max(55-
int(
m_nelem)*8, 0),
false);
141 for (
size_t i = 0; i <
m_nsp; ++i) {
143 plogf(
"On Input species %-12s has a negative MF, setting it small\n",
164 if (forceComponentCalc) {
165 int retn = solve_tp_component_calc(allMinorZeroedSpecies);
170 forceComponentCalc = 0;
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) {
215 }
else if (stage == RETURN_A) {
231 }
else if (stage == RETURN_B) {
238 plogf(
" --- add_all_deleted(): some rxns not converged. RETURNING TO LOOP!\n");
254 for (
size_t kspec = 0; kspec <
m_nsp; ++kspec) {
272 if (rangeErrorFound) {
289int 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);
321void 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",
351 plogf(
" (all species)\n");
353 plogf(
" (only major species)\n");
379 std::vector<size_t> phasePopPhaseIDs(0);
381 if (iphasePop !=
npos) {
386 plogf(
" --- vcs_popPhaseRxnStepSizes() was called but stoich "
387 "prevented phase %d popping\n");
395 size_t iphaseDelete =
npos;
397 if (iphasePop ==
npos) {
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;
426 if (iphaseDelete !=
npos) {
428 for (
size_t k = 0; k <
m_nsp; k++) {
437 throw CanteraError(
"VCS_SOLVE::solve_tp_inner",
438 "we shouldn't be here!");
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++) {
475 if (iphasePop !=
npos) {
476 if (iph == iphasePop) {
479 sprintf(ANOTE,
"Phase pop");
493 plogf(
" --- %s currently zeroed (SpStatus=%-2d):",
495 plogf(
"%3d DG = %11.4E WT = %11.4E W = %11.4E DS = %11.4E\n",
503 sprintf(ANOTE,
"Species stays zeroed: DG = %11.4E",
m_deltaGRxn_new[irxn]);
506 sprintf(ANOTE,
"Species stays zeroed even though dg neg due to "
507 "STOICH/PHASEPOP constraint: DG = %11.4E",
510 sprintf(ANOTE,
"Species stays zeroed even though dg neg: DG = %11.4E, ds zeroed",
515 for (
size_t j = 0; j <
m_nelem; ++j) {
519 if (atomComp > 0.0) {
522 sprintf(ANOTE,
"Species stays zeroed even though dG "
523 "neg, because of %s elemAbund",
537 plogf(
" --- Zeroed species changed to major: ");
541 allMinorZeroedSpecies =
false;
544 plogf(
" --- Zeroed species changed to minor: ");
572 sprintf(ANOTE,
"minor species not considered");
574 plogf(
" --- %-12s%3d% 11.4E %11.4E %11.4E | %s\n",
601 plogf(
" --- Delete minor species in multispec phase: %-12s\n",
612 stage = RECHECK_DELETED;
626 sprintf(ANOTE,
"Normal Major Calc");
635 sprintf(ANOTE,
"major species is converged");
637 plogf(
" --- %-12s %3d %11.4E %11.4E %11.4E | %s\n",
656 sprintf(ANOTE,
"dx set to 0, DG flipped sign due to "
657 "changed initial point");
668 sprintf(ANOTE,
"initial nonpos kmoles= %11.3E",
696 if (sc_irxn[j] != 0.0) {
709 "zeroing SS phase created a neg component species "
710 "-> reducing step size instead");
716 sprintf(ANOTE,
"zeroing out SS phase: ");
723 doPhaseDeleteIph = iph;
725 doPhaseDeleteKspec = kspec;
727 plogf(
" --- SS species changed to zeroedss: ");
734 for (
size_t kk = 0; kk <
m_nsp; kk++) {
761 "VCS_SOLVE::solve_tp_inner",
762 "ds[kspec] = {}, dx = {}, kspec = {}\nwe have a problem!",
781 plogf(
" --- %-12.12s%3d %11.4E %11.4E %11.4E | %s\n",
787 if (doPhaseDeleteIph !=
npos) {
789 plogf(
" --- %-12.12s Main Loop Special Case deleting phase with species:\n",
799 plogf(
" c %11.4E %11.4E %11.4E |\n",
805 plogf(
" --- Finished Main Loop\n");
830 if (par <= 1.01 && par > 0.0) {
834 plogf(
" --- Reduction in step size due to component %s going negative = %11.3E\n",
837 for (
size_t i = 0; i <
m_nsp; ++i) {
854 for (
size_t kspec = 0; kspec <
m_nsp; ++kspec) {
858 throw CanteraError(
"VCS_SOLVE::solve_tp_inner",
859 "vcs_solve_TP: ERROR on step change wt[{}:{}]: {} < 0.0",
884 plogf(
" --- Total Old Dimensionless Gibbs Free Energy = %20.13E\n",
887 plogf(
" --- Total tentative Dimensionless Gibbs Free Energy = %20.13E\n",
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");
914 writeline(
' ', 26,
false);
915 plogf(
"Norms of Delta G():%14.6E%14.6E\n",
922 plogf(
" Total kmoles of liquid = %15.7E\n", 0.0);
924 plogf(
" Total New Dimensionless Gibbs Free Energy = %20.13E\n",
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");
954 plogf(
" %2d %14.6E%14.6E%14.6E%14.6E%14.6E%14.6E\n",
962 plogf(
" %2d %14.6E%14.6E%14.6E%14.6E%14.6E%14.6E\n",
968 writeline(
' ', 56,
false);
969 plogf(
"Norms of Delta G():%14.6E%14.6E\n",
973 plogf(
" --- Phase_Name KMoles(after update)\n");
982 plogf(
" --- Total Old Dimensionless Gibbs Free Energy = %20.13E\n",
985 plogf(
" --- Total New Dimensionless Gibbs Free Energy = %20.13E\n",
1013 plogf(
" --- Increment counter increased, step is accepted: %4d\n",
1023 bool justDeletedMultiPhase =
false;
1028 plogf(
" --- Setting microscopic phase %d to zero\n", iph);
1030 justDeletedMultiPhase =
true;
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");
1056 plogf(
" --- Normal element abundance check");
1065 uptodate_minors =
true;
1077 bool doSwap =
false;
1100 plogf(
" and share nonzero stoic: %-9.1f\n",
1103 forceComponentCalc = 1;
1109 stage = EQUILIB_CHECK;
1119 plogf(
" --- Reevaluate major-minor status of noncomponents:\n");
1122 for (
size_t irxn = 0; irxn <
m_numRxnRdc; irxn++) {
1127 plogf(
" --- major/minor species is now zeroed out: %s\n",
1134 plogf(
" --- Noncomponent turned from major to minor: ");
1136 plogf(
" --- Component turned into a minor species: ");
1138 plogf(
" --- Zeroed Species turned into a "
1148 plogf(
" --- Noncomponent turned from minor to major: ");
1150 plogf(
" --- Component turned into a major: ");
1152 plogf(
" --- Noncomponent turned from zeroed to major: ");
1167void 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) {
1175 plogf(
" --- Equilibrium check for major species: ");
1177 for (
size_t irxn = 0; irxn <
m_numRxnRdc; ++irxn) {
1192 iti = ((it1/4) *4) - it1;
1200 debuglog(
" MAJOR SPECIES CONVERGENCE achieved "
1213 uptodate_minors =
true;
1216 plogf(
" --- Equilibrium check for minor species: ");
1218 for (
size_t irxn = 0; irxn <
m_numRxnRdc; ++irxn) {
1240 plogf(
" CONVERGENCE achieved\n");
1251 if (!giveUpOnElemAbund) {
1253 plogf(
" --- Check the Full Element Abundances: ");
1263 plogf(
" passed for NC but failed for NE: RANGE ERROR\n");
1267 stage = ELEM_ABUND_CHECK;
1278 stage = RECHECK_DELETED;
1287void 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;
1318 if (finalElemAbundAttempts >= 3) {
1319 giveUpOnElemAbund =
true;
1320 stage = EQUILIB_CHECK;
1322 finalElemAbundAttempts++;
1329 }
else if (ncAfter) {
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;
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;
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) {
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;
1431 sprintf(ANOTE,
"voltage species alternative calc");
1442 "delete_species() ERROR: called for a component {}", kspec);
1446 double dx = *delta_ptr;
1450 double tmp = sc_irxn[j] * dx;
1473 double tmp = sc_irxn[j] * dx;
1496 plogf(
"vcs_zero_species: Couldn't zero the species %d, "
1497 "did delta of %g. orig conc of %g\n",
1517 "Failed to delete a species!");
1533 if (kspec != klast) {
1548 bool stillExists =
false;
1597 for (
size_t k = 0; k <
m_nsp; k++) {
1620 bool successful =
true;
1625 plogf(
" --- delete_multiphase %d, %s\n", iph, Vphase->
PhaseName);
1640 plogf(
" --- delete_multiphase %d, %s ERROR problems deleting species %s\n",
1642 plogf(
" --- delta attempted: %g achieved: %g "
1643 " Zeroing it manually\n", dx, dxTent);
1664 double dxPerm = 0.0, dxPerm2 = 0.0;
1668 plogf(
" --- delete_multiphase One of the species is a component %d - %s with mole number %g\n",
1681 if (jcomp != kcomp) {
1689 if (fabs(dxPerm2) < fabs(dxPerm)) {
1696 if (dxPerm != 0.0) {
1705 plogf(
" --- delete_multiphase One of the species is a component %d - %s still with mole number %g\n",
1707 plogf(
" --- zeroing it \n");
1731 plogf(
" an active but zeroed species because its phase "
1755 plogf(
" --- Start rechecking deleted species in multispec phases\n");
1779 xtcutoff[iph] = 0.0;
1837 for (
int cits = 0; cits < 3; cits++) {
1872 plogf(
" --- add_deleted(): delta_species() failed for species %s (%d) with mol number %g\n",
1879 plogf(
" --- add_deleted(): delta_species() failed for species %s (%d) with mol number %g\n",
1886 plogf(
" --- add_deleted(): species %s added back in with mol number %g\n",
1889 plogf(
" --- add_deleted(): species %s failed to be added back in\n");
1908 plogf(
" --- add_deleted(): species %s with mol number %g not converged: DG = %g\n",
1924 for (
size_t irxn = 0; irxn <
m_numRxnRdc; ++irxn) {
1934 for (
size_t irxn = 0; irxn <
m_numRxnRdc; ++irxn) {
1942 plogf(
" --- subroutine FORCE: Beginning Slope = %g\n", s1);
1943 plogf(
" --- subroutine FORCE: End Slope = %g\n", s2);
1946 if (s1 > 0.0 || s2 <= 0.0) {
1953 if (fabs(s1 -s2) > 1.0E-200) {
1954 al = s1 / (s1 - s2);
1956 if (al >= 0.95 || al < 0.0) {
1961 plogf(
" --- subroutine FORCE produced a damping factor = %g\n", al);
1980 plogf(
" --- subroutine FORCE adjusted the mole "
1981 "numbers, AL = %10.3f\n", al);
1996 for (
size_t irxn = 0; irxn <
m_numRxnRdc; ++irxn) {
2004 plogf(
" --- subroutine FORCE: Adj End Slope = %g\n", s2);
2010 double ss[],
double test,
bool*
const usedZeroedSpecies)
2014 size_t jlose =
npos;
2019 for (
size_t i=0; i<77; i++) {
2023 plogf(
" --- Subroutine BASOPT called to ");
2024 if (doJustComponents) {
2025 plogf(
"calculate the number of components\n");
2027 plogf(
"reevaluate the components\n");
2031 plogf(
" --- Formula Matrix used in BASOPT calculation\n");
2032 plogf(
" --- Active | ");
2033 for (
size_t j = 0; j <
m_nelem; j++) {
2037 plogf(
" --- Species | ");
2038 for (
size_t j = 0; j <
m_nelem; j++) {
2042 for (k = 0; k <
m_nsp; k++) {
2044 for (
size_t j = 0; j <
m_nelem; j++) {
2058 *usedZeroedSpecies =
false;
2066 for (k = 0; k <
m_nsp; k++) {
2076 while (jr < ncTrial) {
2124 *usedZeroedSpecies =
true;
2125 double maxConcPossKspec = 0.0;
2126 double maxConcPoss = 0.0;
2127 size_t kfound =
npos;
2128 int minNonZeroes = 100000;
2129 int nonZeroesKspec = 0;
2130 for (
size_t kspec = ncTrial; kspec <
m_nsp; kspec++) {
2132 maxConcPossKspec = 1.0E10;
2134 for (
size_t j = 0; j <
m_nelem; ++j) {
2143 if ((maxConcPossKspec >= maxConcPoss) || (maxConcPossKspec > 1.0E-5)) {
2144 if (nonZeroesKspec <= minNonZeroes) {
2145 if (kfound ==
npos || nonZeroesKspec < minNonZeroes) {
2155 minNonZeroes = std::min(minNonZeroes, nonZeroesKspec);
2156 maxConcPoss = std::max(maxConcPoss, maxConcPossKspec);
2160 if (kfound ==
npos) {
2163 for (
size_t kspec = ncTrial; kspec <
m_nsp; kspec++) {
2164 if (aw[kspec] >= 0.0) {
2165 size_t irxn = kspec - ncTrial;
2176 if (aw[k] == test) {
2181 throw CanteraError(
"VCS_SOLVE::vcs_basopt",
"we shouldn't be here");
2186 for (
size_t i = 0; i <
m_nsp; ++i) {
2190 plogf(
" --- Total number of components found = %3d (ne = %d)\n ",
2205 for (
size_t j = 0; j <
m_nelem; ++j) {
2212 for (
size_t j = 0; j < jl; ++j) {
2214 for (
size_t i = 0; i <
m_nelem; ++i) {
2221 for (
size_t j = 0; j < jl; ++j) {
2222 for (
size_t i = 0; i <
m_nelem; ++i) {
2231 for (
size_t ml = 0; ml <
m_nelem; ++ml) {
2232 sa[jr] += pow(sm[ml + jr*
m_nelem], 2);
2236 if (sa[jr] > 1.0e-6) {
2256 plogf(
" as component %3d\n", jr);
2259 std::swap(aw[jr], aw[k]);
2267 plogf(
" as component %3d\n", jr);
2276 if (doJustComponents) {
2306 C.
resize(ncTrial, ncTrial);
2307 for (
size_t j = 0; j < ncTrial; ++j) {
2308 for (
size_t i = 0; i < ncTrial; ++i) {
2314 for (
size_t j = 0; j < ncTrial; ++j) {
2326 for (
size_t j = 0; j <
m_nelem; j++) {
2331 for (
size_t j = 0; j <
m_nelem; j++) {
2336 for (k = 0; k <
m_nsp; k++) {
2338 for (
size_t j = 0; j < ncTrial; ++j) {
2339 for (
size_t i = 0; i < ncTrial; ++i) {
2349 for (
size_t j = 0; j < ncTrial; ++j) {
2359 size_t i = k - ncTrial;
2360 for (
size_t j = 0; j < ncTrial; j++) {
2369 for (
size_t j = 0; j < ncTrial; j++) {
2376 plogf(
" --- Components:");
2377 for (
size_t j = 0; j < ncTrial; j++) {
2380 plogf(
"\n --- Components Moles:");
2381 for (
size_t j = 0; j < ncTrial; j++) {
2383 plogf(
" % -10.3E", 0.0);
2388 plogf(
"\n --- NonComponent| Moles |");
2389 for (
size_t j = 0; j < ncTrial; j++) {
2397 plogf(
"|% -10.3E|", 0.0);
2401 for (
size_t j = 0; j < ncTrial; j++) {
2409 double sumMax = -1.0;
2415 for (
size_t j = 0; j < ncTrial; ++j) {
2418 for (
size_t n = 0; n < ncTrial; n++) {
2421 sum += coeff * numElements;
2425 for (
size_t n = 0; n < ncTrial; n++) {
2428 sum += coeff * numElements;
2431 if (fabs(sum) > sumMax) {
2439 if (fabs(sum) > 1.0E-6) {
2440 throw CanteraError(
"VCS_SOLVE::vcs_basopt",
"we have a prob");
2444 plogf(
" --- largest error in Stoich coeff = %g at rxn = %d ", sumMax, iMax);
2446 plogf(
" element = %d ", jMax);
2450 for (
size_t i=0; i<77; i++) {
2468 for (
size_t irxn = 0; irxn <
m_numRxnTot; ++irxn) {
2474 for (
size_t j = 0; j < ncTrial; ++j) {
2476 if (fabs(scrxn_ptr[j]) <= 1.0e-6) {
2510 double big = molNum[j] *
m_spSize[j] * 1.01;
2513 "spSize is nonpositive");
2515 for (
size_t i = j + 1; i < n; ++i) {
2518 "spSize is nonpositive");
2520 bool doSwap =
false;
2522 doSwap = (molNum[i] *
m_spSize[i]) > big;
2524 doSwap = molNum[i] > (molNum[largest] * 1.001);
2528 doSwap = (molNum[i] *
m_spSize[i]) > big;
2530 doSwap = molNum[i] > (molNum[largest] * 1.001);
2533 doSwap = (molNum[i] *
m_spSize[i]) > big;
2538 big = molNum[i] *
m_spSize[i] * 1.01;
2563 for (
size_t j = 0; j <
m_nelem; ++j) {
2566 if (atomComp > 0.0) {
2570 plogf(
" --- %s can not be nonzero because"
2571 " needed element %s is zero\n",
2591 if (stoicC != 0.0) {
2592 double negChangeComp = - stoicC;
2593 if (negChangeComp > 0.0) {
2596 plogf(
" --- %s is prevented from popping into existence because"
2597 " a needed component to be consumed, %s, has a zero mole number\n",
2606 }
else if (negChangeComp < 0.0) {
2609 plogf(
" --- %s is prevented from popping into existence because"
2610 " a needed component %s is in a zeroed-phase that would be "
2611 "popped into existence at the same time\n",
2698 const int ll,
const size_t lbot,
const size_t ltop)
2700 double* tPhMoles_ptr=0;
2701 double* actCoeff_ptr=0;
2702 double* feSpecies=0;
2716 "Subroutine vcs_dfe called with bad stateCalc value: {}", stateCalc);
2722 plogf(
" --- Subroutine vcs_dfe called for one species: ");
2725 plogf(
" --- Subroutine vcs_dfe called for all species");
2727 }
else if (ll > 0) {
2728 plogf(
" --- Subroutine vcs_dfe called for components and minors");
2730 plogf(
" --- Subroutine vcs_dfe called for components and majors");
2733 plogf(
" using tentative solution");
2744 tlogMoles[iph] = tPhInertMoles[iph];
2747 for (
size_t kspec = 0; kspec <
m_nsp; kspec++) {
2750 tlogMoles[iph] += molNum[kspec];
2755 "VCS_SOLVE::vcs_dfe",
2756 "phase Moles may be off, iph = {}, {} {}",
2757 iph, tlogMoles[iph], tPhMoles_ptr[iph]);
2761 if (tPhMoles_ptr[iph] > 0.0) {
2762 tlogMoles[iph] = log(tPhMoles_ptr[iph]);
2778 for (
size_t iphase = 0; iphase <
m_numPhases; iphase++) {
2793 for (
size_t kspec = l1; kspec < l2; ++kspec) {
2797 "We have an inconsistency!");
2799 "We have an unexpected situation!");
2813 if (tPhMoles_ptr[iph] > 0.0) {
2824 + log(actCoeff_ptr[kspec] * molNum[kspec])
2834 for (
size_t irxn = 0; irxn <
m_numRxnRdc; ++irxn) {
2840 "We have an inconsistency!");
2842 "We have an unexpected situation!");
2856 if (tPhMoles_ptr[iph] > 0.0) {
2867 + log(actCoeff_ptr[kspec] * molNum[kspec])
2875 }
else if (ll > 0) {
2877 for (
size_t irxn = 0; irxn <
m_numRxnRdc; ++irxn) {
2883 "We have an inconsistency!");
2885 "We have an unexpected situation!");
2899 if (tPhMoles_ptr[iph] > 0.0) {
2910 + log(actCoeff_ptr[kspec] * molNum[kspec])
2927 for (
size_t irxn = 0; irxn <
m_numRxnRdc; ++irxn) {
2930 dgLocal[irxn] < 0.0) {
2932 tmp += dgLocal[irxn] * dgLocal[irxn];
2944 for (
size_t i = 0; i <
m_nsp; i++) {
2963void VCS_SOLVE::check_tmoles()
const
2969 for (
size_t k = 0; k <
m_nsp; k++) {
2974 sum += m_tPhaseMoles_old_a;
2978 plogf(
"check_tmoles: we have found a problem with phase %d: %20.15g, %20.15g\n",
2998 "wrong stateCalc value: {}", vcsState);
3007 plogf(
" --- Species Status decision is reevaluated: All species are minor except for:\n");
3009 plogf(
" --- Species Status decision is reevaluated\n");
3011 for (
size_t kspec = 0; kspec <
m_nsp; ++kspec) {
3022 plogf(
"%s\n", sString);
3032 plogf(
" --- Purposely Zeroed-Phase Species (not in problem): %-s\n",
3045 plogf(
" --- Zeroed Species in an active MS phase (tmp): %-s\n",
3049 plogf(
" --- Zeroed Species in an active MS phase (Stoich Constraint): %-s\n",
3056 throw CanteraError(
"VCS_SOLVE::vcs_evaluate_speciesType",
3070 const int vcsState,
const bool alterZeroedPhases)
3079 double* molNumSpecies;
3080 double* actCoeffSpecies;
3092 throw CanteraError(
"VCS_SOLVE::vcs_deltag",
"bad vcsState");
3096 plogf(
" --- Subroutine vcs_deltag called for ");
3098 plogf(
"major noncomponents\n");
3099 }
else if (L == 0) {
3100 plogf(
"all noncomponents\n");
3102 plogf(
"minor noncomponents\n");
3108 for (
size_t irxn = 0; irxn <
m_numRxnRdc; ++irxn) {
3115 deltaGRxn[irxn] += dtmp_ptr[kspec] * feSpecies[kspec];
3121 deltaGRxn[irxn] = std::max(0.0, deltaGRxn[irxn]);
3125 }
else if (L == 0) {
3127 for (
size_t irxn = 0; irxn < irxnl; ++irxn) {
3132 deltaGRxn[irxn] += dtmp_ptr[kspec] * feSpecies[kspec];
3134 dtmp_ptr[kspec] < 0.0) {
3139 deltaGRxn[irxn] = std::max(0.0, deltaGRxn[irxn]);
3144 for (
size_t irxn = 0; irxn <
m_numRxnRdc; ++irxn) {
3151 deltaGRxn[irxn] += dtmp_ptr[kspec] * feSpecies[kspec];
3153 dtmp_ptr[kspec] < 0.0) {
3158 deltaGRxn[irxn] = std::max(0.0, deltaGRxn[irxn]);
3203 if (alterZeroedPhases &&
false) {
3209 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
3212 sum += molNumSpecies[kspec];
3225 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
3230 deltaGRxn[irxn] =
clip(deltaGRxn[irxn], -50.0, 50.0);
3231 poly += exp(-deltaGRxn[irxn])/actCoeffSpecies[kspec];
3239 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
3243 deltaGRxn[irxn] = 1.0 - poly;
3251void VCS_SOLVE::vcs_printDeltaG(
const int stateCalc)
3266 bool zeroedPhase =
false;
3268 plogf(
" --- DELTA_G TABLE Components:");
3272 plogf(
"\n --- Components Moles:");
3276 plogf(
"\n --- NonComponent| Moles | ");
3295 for (
int i=0; i<77; i++) {
3301 writelog(
" --- DeltaG Table (J/kmol) Name PhID MoleNum MolFR "
3302 " ElectrChemStar ElectrChem DeltaGStar DeltaG(Pred) Stability\n");
3304 writeline(
'-', 132);
3306 for (
size_t kspec = 0; kspec <
m_nsp; kspec++) {
3311 double mfValue = 1.0;
3319 zeroedPhase =
false;
3321 if (tPhMoles_ptr[iphase] > 0.0) {
3325 mfValue = molNumSpecies[kspec] / tPhMoles_ptr[iphase];
3329 mfValue = Vphase->moleFraction(klocal);
3336 double feFull = feSpecies[kspec];
3339 feFull += log(actCoeff_ptr[kspec]) + log(mfValue);
3346 writelogf(
" % -12.4e", molNumSpecies[kspec]);
3349 writelogf(
" % -12.4e", feSpecies[kspec] * RT);
3352 writelogf(
" % -12.4e", deltaGRxn[irxn] * RT);
3353 writelogf(
" % -12.4e", (deltaGRxn[irxn] + feFull - feSpecies[kspec]) * RT);
3355 if (deltaGRxn[irxn] < 0.0) {
3356 if (molNumSpecies[kspec] > 0.0) {
3361 }
else if (deltaGRxn[irxn] > 0.0) {
3362 if (molNumSpecies[kspec] > 0.0) {
3374 writeline(
'-', 132);
3383 plogf(
"vcs_switch_pos: ifunc = 0: inappropriate args: %d %d\n",
3420 for (
size_t j = 0; j <
m_nelem; ++j) {
3424 for (
size_t i = 0; i <
m_nsp; i++) {
3427 for (
size_t i = 0; i <
m_nsp; i++) {
3439 plogf(
"switch_pos: ifunc = 1: inappropriate noncomp values: %d %d\n",
3457void VCS_SOLVE::vcs_setFlagsVolPhases(
const bool upToDate,
const int stateCalc)
3470void VCS_SOLVE::vcs_setFlagsVolPhase(
const size_t iph,
const bool upToDate,
3471 const int stateCalc)
Headers for the DenseMatrix object, which deals with dense rectangular matrices and description of th...
void zero()
Set all of the entries to zero.
doublereal * ptrColumn(size_t j)
Return a pointer to the top of column j, columns are contiguous in memory.
Base class for exceptions thrown by Cantera classes.
A class for full (non-sparse) matrices with Fortran-compatible data storage, which adds matrix operat...
void resize(size_t n, size_t m, doublereal v=0.0)
Resize the matrix.
int Its
Current number of iterations in the main loop of vcs_TP() to solve for thermo equilibrium.
double T_Time_basopt
Total Time spent in basopt.
int T_Basis_Opts
Total number of optimizations of the components basis set done.
double T_Time_vcs_TP
Current time spent in vcs_TP.
int Basis_Opts
number of optimizations of the components basis set done
int T_Its
Total number of iterations in the main loop of vcs_TP() to solve for thermo equilibrium.
int T_Calls_vcs_TP
Current number of calls to vcs_TP.
double Time_basopt
Current Time spent in basopt.
double Time_vcs_TP
Current time spent in vcs_TP.
size_t m_numPhases
Number of Phases in the problem.
int m_doEstimateEquil
Setting for whether to do an initial estimate.
vector_fp m_phasePhi
electric potential of the iph phase
vector_fp m_scSize
Absolute size of the stoichiometric coefficients.
void vcs_deltag(const int L, const bool doDeleted, const int vcsState, const bool alterZeroedPhases=true)
This subroutine calculates reaction free energy changes for all noncomponent formation reactions.
double m_tolmaj2
Below this, major species aren't refined any more.
std::vector< std::string > m_speciesName
Species string name for the kth species.
Array2D m_np_dLnActCoeffdMolNum
Change in the log of the activity coefficient with respect to the mole number multiplied by the phase...
void vcs_updateMolNumVolPhases(const int stateCalc)
Update all underlying vcs_VolPhase objects.
vector_int m_elType
Type of the element constraint.
size_t m_nelem
Number of element constraints in the problem.
int m_useActCoeffJac
Choice of Hessians.
void vcs_updateVP(const int stateCalc)
This routine uploads the state of the system into all of the vcs_VolumePhase objects in the current p...
size_t vcs_add_all_deleted()
Provide an estimate for the deleted species in phases that are not zeroed out.
bool vcs_globStepDamp()
This routine optimizes the minimization of the total Gibbs free energy by making sure the slope of th...
vector_int m_speciesStatus
Major -Minor status vector for the species in the problem.
int vcs_basopt(const bool doJustComponents, double aw[], double sa[], double sm[], double ss[], double test, bool *const usedZeroedSpecies)
Choose the optimum species basis for the calculations.
int vcs_elcorr(double aa[], double x[])
vector_int m_actConventionSpecies
specifies the activity convention of the phase containing the species
size_t vcs_basisOptMax(const double *const molNum, const size_t j, const size_t n)
Choose a species to test for the next component.
vector_fp m_molNumSpecies_old
Total moles of the species.
Array2D m_phaseParticipation
This is 1 if the phase, iphase, participates in the formation reaction irxn, and zero otherwise.
vector_fp m_molNumSpecies_new
Tentative value of the mole number vector.
vector_fp m_elemAbundances
Element abundances vector.
double l2normdg(double dg[]) const
Calculate the norm of a deltaGibbs free energy vector.
int delta_species(const size_t kspec, double *const delta_ptr)
Change the concentration of a species by delta moles.
vector_int m_speciesUnknownType
Specifies the species unknown type.
vector_fp m_deltaGRxn_tmp
Temporary vector of Rxn DeltaG's.
vector_fp m_deltaGRxn_old
Last deltag[irxn] from the previous step.
double m_tolmin2
Below this, minor species aren't refined any more.
void vcs_elab()
Computes the current elemental abundances vector.
size_t vcs_popPhaseID(std::vector< size_t > &phasePopPhaseIDs)
Decision as to whether a phase pops back into existence.
double vcs_Total_Gibbs(double *w, double *fe, double *tPhMoles)
Calculate the total dimensionless Gibbs free energy.
size_t m_numRxnMinorZeroed
Number of active species which are currently either treated as minor species.
vector_fp m_tPhaseMoles_new
total kmols of species in each phase in the tentative soln vector
vector_fp m_feSpecies_new
Dimensionless new free energy for all the species in the mechanism at the new tentative T,...
vector_fp m_tPhaseMoles_old
Total kmols of species in each phase.
size_t m_numSpeciesRdc
Current number of species in the problems.
int vcs_delete_species(const size_t kspec)
Change a single species from active to inactive status.
int m_debug_print_lvl
Debug printing lvl.
void vcs_counters_init(int ifunc)
Initialize the internal counters.
vector_fp m_elemAbundancesGoal
Element abundances vector Goals.
void vcs_reinsert_deleted(size_t kspec)
vector_fp TPhInertMoles
Total kmoles of inert to add to each phase.
std::vector< size_t > m_phaseID
Mapping from the species number to the phase number.
std::vector< size_t > m_indexRxnToSpecies
Mapping between the species index for noncomponent species and the full species index.
Array2D m_formulaMatrix
Formula matrix for the problem.
vector_fp m_wtSpecies
Molecular weight of each species.
vector_fp m_deltaPhaseMoles
Change in the total moles in each phase.
int vcs_solve_TP(int print_lvl, int printDetails, int maxit)
Main routine that solves for equilibrium at constant T and P using a variant of the VCS method.
std::vector< size_t > m_speciesLocalPhaseIndex
Index that keeps track of the index of the species within the local phase.
Array2D m_stoichCoeffRxnMatrix
Stoichiometric coefficient matrix for the reaction mechanism expressed in Reduced Canonical Form.
size_t m_numRxnRdc
Current number of non-component species in the problem.
VCS_COUNTERS * m_VCount
Timing and iteration counters for the vcs object.
std::vector< std::unique_ptr< VCS_SPECIES_THERMO > > m_speciesThermoList
Vector of pointers to thermo structures which identify the model and parameters for evaluating the th...
size_t m_numComponents
Number of components calculated for the problem.
int vcs_species_type(const size_t kspec) const
Evaluate the species category for the indicated species.
double m_pressurePA
Pressure.
vector_fp m_chargeSpecies
Charge of each species. Length = number of species.
vector_fp m_feSpecies_old
Free energy vector from the start of the current iteration.
vector_int m_elementActive
Specifies whether an element constraint is active.
double m_Faraday_dim
dimensionless value of Faraday's constant, F / RT (1/volt)
int vcs_recheck_deleted()
Recheck deleted species in multispecies phases.
std::vector< char > m_SSPhase
Boolean indicating whether a species belongs to a single-species phase.
double m_tolmin
Tolerance requirements for minor species.
size_t m_nsp
Total number of species in the problems.
std::vector< std::unique_ptr< vcs_VolPhase > > m_VolPhaseList
Array of Phase Structures. Length = number of phases.
vector_fp m_spSize
total size of the species
bool vcs_elabcheck(int ibound)
bool vcs_delete_multiphase(const size_t iph)
This routine handles the bookkeeping involved with the deletion of multiphase phases from the problem...
int vcs_zero_species(const size_t kspec)
Zero out the concentration of a species.
size_t vcs_RxnStepSizes(int &forceComponentCalc, size_t &kSpecial)
Calculates formation reaction step sizes.
vector_fp m_deltaMolNumSpecies
Reaction Adjustments for each species during the current step.
vector_fp m_SSfeSpecies
Standard state chemical potentials for species K at the current temperature and pressure.
Array2D m_deltaMolNumPhase
Change in the number of moles of phase, iphase, due to the noncomponent formation reaction,...
std::vector< size_t > m_speciesMapIndex
Index vector that keeps track of the species vector rearrangement.
double vcs_minor_alt_calc(size_t kspec, size_t irxn, bool *do_delete, char *ANOTE=0) const
Minor species alternative calculation.
vector_fp m_actCoeffSpecies_old
Molar-based Activity Coefficients for Species based on old mole numbers.
double vcs_tmoles()
Calculates the total number of moles of species in all phases.
void vcs_switch_pos(const bool ifunc, const size_t k1, const size_t k2)
Swaps the indices for all of the global data for two species, k1 and k2.
vector_fp m_PMVolumeSpecies
Partial molar volumes of the species.
vector_fp m_deltaGRxn_new
Delta G(irxn) for the noncomponent species in the mechanism.
void vcs_dfe(const int stateCalc, const int ll, const size_t lbot, const size_t ltop)
Calculate the dimensionless chemical potentials of all species or of certain groups of species,...
vector_fp m_lnMnaughtSpecies
specifies the ln(Mnaught) used to calculate the chemical potentials
int vcs_popPhaseRxnStepSizes(const size_t iphasePop)
Calculates the deltas of the reactions due to phases popping into existence.
size_t m_numRxnTot
Total number of non-component species in the problem.
vector_fp m_deltaGRxn_Deficient
Last deltag[irxn] from the previous step with additions for possible births of zeroed phases.
double m_temperature
Temperature (Kelvin)
vector_fp m_TmpPhase
Temporary vector of length NPhase.
double m_tolmaj
Tolerance requirement for major species.
vector_fp m_actCoeffSpecies_new
Molar-based Activity Coefficients for Species.
bool vcs_evaluate_speciesType()
This routine evaluates the species type for all species.
std::vector< std::string > m_elementName
Vector of strings containing the element names.
double m_totalMolNum
Total number of kmoles in all phases.
The class provides the wall clock timer in seconds.
double secondsWC()
Returns the wall clock time in seconds since the last reset.
Phase information and Phase calculations for vcs.
double electricPotential() const
Returns the electric field of the phase.
size_t nSpecies() const
Return the number of species in the phase.
void setMolesFromVCSCheck(const int vcsStateStatus, const double *molesSpeciesVCS, const double *const TPhMoles)
Set the moles within the phase.
void updateFromVCS_MoleNumbers(const int stateCalc)
Update the moles within the phase, if necessary.
bool m_singleSpecies
If true, this phase consists of a single species.
int exists() const
int indicating whether the phase exists or not
size_t spGlobalIndexVCS(const size_t spIndex) const
Return the Global VCS index of the kth species in the phase.
std::string PhaseName
String name for the phase.
void setTotalMoles(const double totalMols)
Sets the total moles in the phase.
void sendToVCS_ActCoeff(const int stateCalc, double *const AC)
Fill in an activity coefficients vector within a VCS_SOLVE object.
void setSpGlobalIndexVCS(const size_t spIndex, const size_t spGlobalIndex)
set the Global VCS index of the kth species in the phase
void setExistence(const int existence)
Set the existence flag in the object.
Declarations for a simple class that implements an Ansi C wall clock timer (see Cantera::clockWC).
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
void writelog(const std::string &fmt, const Args &... args)
Write a formatted message to the screen.
void writelogf(const char *fmt, const Args &... args)
Write a formatted message to the screen.
Namespace for the Cantera kernel.
const size_t npos
index returned by functions to indicate "no position"
void debuglog(const std::string &msg, int loglevel)
Write a message to the log only if loglevel > 0.
const char * vcs_speciesType_string(int speciesStatus, int length=100)
Returns a const char string representing the type of the species given by the first argument.
bool vcs_doubleEqual(double d1, double d2)
Simple routine to check whether two doubles are equal up to roundoff error.
std::vector< int > vector_int
Vector of ints.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
const double GasConstant
Universal Gas Constant [J/kmol/K].
T clip(const T &value, const T &lower, const T &upper)
Clip value such that lower <= value <= upper.
int solve(DenseMatrix &A, double *b, size_t nrhs=1, size_t ldb=0)
Solve Ax = b. Array b is overwritten on exit with x.
void writelogendl()
Write an end of line character to the screen and flush output.
Contains declarations for string manipulation functions within Cantera.
Header for the object representing each phase within vcs.
#define VCS_SPECIES_INTERFACIALVOLTAGE
Species refers to an electron in the metal.
#define VCS_SPECIES_TYPE_INTERFACIALVOLTAGE
Unknown refers to the voltage level of a phase.
#define VCS_STATECALC_OLD
State Calculation based on the old or base mole numbers.
#define VCS_DELETE_MINORSPECIES_CUTOFF
Cutoff relative mole number value, below which species are deleted from the equilibrium problem.
#define VCS_RELDELETE_SPECIES_CUTOFF
Cutoff relative mole fraction value, below which species are deleted from the equilibrium problem.
#define VCS_SPECIES_COMPONENT
Species is a component which can be nonzero.
#define VCS_SPECIES_MAJOR
Species is a major species.
#define VCS_PHASE_EXIST_NO
Phase doesn't currently exist in the mixture.
#define VCS_PHASE_EXIST_ALWAYS
#define VCS_SPECIES_STOICHZERO
Species lies in a multicomponent phase that is active, but species concentration is zero due to stoic...
#define VCS_ELEM_TYPE_ABSPOS
Normal element constraint consisting of positive coefficients for the formula matrix.
#define VCS_STATECALC_NEW
State Calculation based on the new or tentative mole numbers.
#define VCS_SPECIES_TYPE_MOLNUM
Unknown refers to mole number of a single species.
#define VCS_SPECIES_ZEROEDMS
Species lies in a multicomponent phase with concentration zero.
#define VCS_SPECIES_ZEROEDPHASE
Species lies in a multicomponent phase that is zeroed atm.
#define VCS_SPECIES_ACTIVEBUTZERO
Species lies in a multicomponent phase that is active, but species concentration is zero.
#define VCS_SPECIES_ZEROEDSS
Species is a SS phase, that is currently zeroed out.
#define VCS_DELETE_PHASE_CUTOFF
Cutoff relative moles below which a phase is deleted from the equilibrium problem.
#define VCS_SPECIES_DELETED
Species has such a small mole fraction it is deleted even though its phase may possibly exist.
#define VCS_SPECIES_MINOR
Species is a major species.
#define VCS_PHASE_EXIST_YES
Phase is a normal phase that currently exists.
#define VCS_PHASE_EXIST_ZEROEDPHASE
Phase currently is zeroed due to a programmatic issue.
#define plogf
define this Cantera function to replace printf
Header file for the internal object that holds the vcs equilibrium problem (see Class VCS_SOLVE and C...