20 bool VCS_SOLVE::vcs_popPhasePossible(
const size_t iphasePop)
const 24 "called for a phase that exists!");
30 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
33 "VCS_SOLVE::vcs_popPhasePossible",
34 "we shouldn't be here {}: {} > 0.0", kspec,
35 m_molNumSpecies_old[kspec]);
36 size_t irxn = kspec - m_numComponents;
37 if (kspec >= m_numComponents) {
38 bool iPopPossible =
true;
44 for (
size_t j = 0; j < m_numComponents; ++j) {
46 double stoicC = m_stoichCoeffRxnMatrix(j,irxn);
48 double negChangeComp = - stoicC;
49 if (negChangeComp > 0.0) {
68 for (
size_t jrxn = 0; jrxn < m_numRxnRdc; jrxn++) {
69 bool foundJrxn =
false;
71 if (m_stoichCoeffRxnMatrix(kspec,jrxn) > 0.0) {
75 for (
size_t kcomp = 0; kcomp < m_numComponents; kcomp++) {
83 }
else if (m_stoichCoeffRxnMatrix(kspec,jrxn) < 0.0) {
87 size_t jspec = jrxn + m_numComponents;
94 for (
size_t kcomp = 0; kcomp < m_numComponents; kcomp++) {
109 size_t VCS_SOLVE::vcs_popPhaseID(std::vector<size_t> & phasePopPhaseIDs)
111 size_t iphasePop =
npos;
112 doublereal FephaseMax = -1.0E30;
113 doublereal Fephase = -1.0E30;
116 if (m_debug_print_lvl >= 2) {
117 plogf(
" --- vcs_popPhaseID() called\n");
118 plogf(
" --- Phase Status F_e MoleNum\n");
119 plogf(
" --------------------------------------------------------------------------\n");
121 for (
size_t iph = 0; iph < m_numPhases; iph++) {
123 int existence = Vphase->
exists();
126 if (m_debug_print_lvl >= 2) {
127 plogf(
" --- %18s %5d NA %11.3e\n",
128 Vphase->
PhaseName, existence, m_tPhaseMoles_old[iph]);
134 size_t irxn = kspec - m_numComponents;
135 if (irxn > m_deltaGRxn_old.size()) {
137 "Index out of bounds due to logic error.");
139 doublereal deltaGRxn = m_deltaGRxn_old[irxn];
140 Fephase = exp(-deltaGRxn) - 1.0;
142 strcpy(anote,
" (ready to be birthed)");
143 if (Fephase > FephaseMax) {
145 FephaseMax = Fephase;
146 strcpy(anote,
" (chosen to be birthed)");
150 strcpy(anote,
" (not stable)");
152 "VCS_SOLVE::vcs_popPhaseID",
"shouldn't be here");
155 if (m_debug_print_lvl >= 2) {
156 plogf(
" --- %18s %5d %10.3g %10.3g %s\n",
158 m_tPhaseMoles_old[iph], anote);
162 if (vcs_popPhasePossible(iph)) {
163 Fephase = vcs_phaseStabilityTest(iph);
165 if (Fephase > FephaseMax) {
167 FephaseMax = Fephase;
170 FephaseMax = std::max(FephaseMax, Fephase);
172 if (m_debug_print_lvl >= 2) {
173 plogf(
" --- %18s %5d %11.3g %11.3g\n",
175 m_tPhaseMoles_old[iph]);
178 if (m_debug_print_lvl >= 2) {
179 plogf(
" --- %18s %5d blocked %11.3g\n",
181 existence, m_tPhaseMoles_old[iph]);
187 phasePopPhaseIDs.resize(0);
188 if (iphasePop !=
npos) {
189 phasePopPhaseIDs.push_back(iphasePop);
194 if (m_debug_print_lvl >= 2) {
195 plogf(
" ---------------------------------------------------------------------\n");
200 int VCS_SOLVE::vcs_popPhaseRxnStepSizes(
const size_t iphasePop)
206 size_t irxn = kspec - m_numComponents;
207 std::vector<size_t> creationGlobalRxnNumbers;
215 "called for a phase that exists!");
216 if (m_debug_print_lvl >= 2) {
217 plogf(
" --- vcs_popPhaseRxnStepSizes() called to pop phase %s %d into existence\n",
223 for (
size_t j = 0; j < m_numComponents; ++j) {
224 if (!m_SSPhase[j] && m_molNumSpecies_old[j] > 0.0) {
225 s += pow(m_stoichCoeffRxnMatrix(j,irxn), 2) / m_molNumSpecies_old[j];
228 for (
size_t j = 0; j < m_numPhases; j++) {
229 Vphase = m_VolPhaseList[j].get();
231 s -= pow(m_deltaMolNumPhase(j,irxn), 2) / m_tPhaseMoles_old[j];
236 s = vcs_Hessian_diag_adj(irxn, s_old);
237 m_deltaMolNumSpecies[kspec] = -m_deltaGRxn_new[irxn] / s;
241 m_deltaMolNumSpecies[kspec] = tPhaseMoles;
245 for (
size_t j = 0; j < m_numComponents; ++j) {
246 double stoicC = m_stoichCoeffRxnMatrix(j,irxn);
248 double negChangeComp = - stoicC * m_deltaMolNumSpecies[kspec];
249 if (negChangeComp > m_molNumSpecies_old[j]) {
250 if (m_molNumSpecies_old[j] > 0.0) {
251 m_deltaMolNumSpecies[kspec] = - 0.5 * m_molNumSpecies_old[j] / stoicC;
253 m_deltaMolNumSpecies[kspec] = 0.0;
260 if (-m_deltaMolNumSpecies[kspec] > m_molNumSpecies_old[kspec]) {
261 m_deltaMolNumSpecies[kspec] = -m_molNumSpecies_old[kspec];
268 double sumFrac = 0.0;
269 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
270 sumFrac += fracDelta[k];
272 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
273 X_est[k] = fracDelta[k] / sumFrac;
276 doublereal deltaMolNumPhase = tPhaseMoles;
277 doublereal damp = 1.0;
278 m_deltaGRxn_tmp = m_molNumSpecies_old;
279 double* molNumSpecies_tmp = m_deltaGRxn_tmp.data();
281 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
283 double delmol = deltaMolNumPhase * X_est[k];
284 if (kspec >= m_numComponents) {
285 irxn = kspec - m_numComponents;
286 if (irxn > m_stoichCoeffRxnMatrix.nColumns()) {
287 throw CanteraError(
"VCS_SOLVE::vcs_popPhaseRxnStepSizes",
288 "Index out of bounds due to logic error.");
290 for (
size_t j = 0; j < m_numComponents; ++j) {
291 double stoicC = m_stoichCoeffRxnMatrix(j,irxn);
293 molNumSpecies_tmp[j] += stoicC * delmol;
299 doublereal ratioComp = 0.0;
300 for (
size_t j = 0; j < m_numComponents; ++j) {
301 double deltaJ = m_molNumSpecies_old[j] - molNumSpecies_tmp[j];
302 if (molNumSpecies_tmp[j] < 0.0) {
305 double delta0 = m_molNumSpecies_old[j];
306 damp = std::min(damp, delta0 / deltaJ * 0.9);
310 size_t jph = m_phaseID[j];
311 if ((jph != iphasePop) && (!m_SSPhase[j])) {
312 double fdeltaJ = fabs(deltaJ);
313 if (m_molNumSpecies_old[j] > 0.0) {
314 ratioComp = std::max(ratioComp, fdeltaJ/ m_molNumSpecies_old[j]);
325 if (ratioComp > 1.0E-30 && ratioComp < 0.001) {
326 damp = 0.001 / ratioComp;
328 if (damp <= 1.0E-6) {
332 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
334 if (kspec < m_numComponents) {
337 m_deltaMolNumSpecies[kspec] = deltaMolNumPhase * X_est[k] * damp;
338 if (X_est[k] > 1.0E-3) {
349 double VCS_SOLVE::vcs_phaseStabilityTest(
const size_t iph)
353 const size_t nsp = Vphase->
nSpecies();
354 int minNumberIterations = 3;
356 minNumberIterations = 1;
360 bool doSuccessiveSubstitution =
true;
361 double funcPhaseStability;
367 vector<size_t> creationGlobalRxnNumbers(nsp,
npos);
368 m_deltaGRxn_Deficient = m_deltaGRxn_old;
369 vector_fp feSpecies_Deficient = m_feSpecies_old;
378 std::vector<size_t> componentList;
379 for (
size_t k = 0; k < nsp; k++) {
381 if (kspec < m_numComponents) {
382 componentList.push_back(k);
386 double normUpdate = 0.1 *
vcs_l2norm(fracDelta_new);
387 double damp = 1.0E-2;
389 if (doSuccessiveSubstitution) {
391 if (m_debug_print_lvl >= 2) {
392 plogf(
" --- vcs_phaseStabilityTest() called\n");
393 plogf(
" --- Its X_old[%2d] FracDel_old[%2d] deltaF[%2d] FracDel_new[%2d]" 394 " normUpdate damp FuncPhaseStability\n", KP, KP, KP, KP);
395 plogf(
" --------------------------------------------------------------" 396 "--------------------------------------------------------\n");
397 }
else if (m_debug_print_lvl == 1) {
398 plogf(
" --- vcs_phaseStabilityTest() called for phase %d\n", iph);
401 for (
size_t k = 0; k < nsp; k++) {
402 if (fracDelta_new[k] < 1.0E-13) {
403 fracDelta_new[k] =1.0E-13;
406 bool converged =
false;
407 double dirProd = 0.0;
408 for (
int its = 0; its < 200 && (!converged); its++) {
409 double dampOld = damp;
410 double normUpdateOld = normUpdate;
411 fracDelta_old = fracDelta_new;
412 double dirProdOld = dirProd;
416 for (
size_t i = 0; i < componentList.size(); i++) {
417 size_t kc = componentList[i];
419 fracDelta_old[kc] = 0.0;
420 for (
size_t k = 0; k < nsp; k++) {
422 if (kspec >= m_numComponents) {
423 size_t irxn = kspec - m_numComponents;
424 fracDelta_old[kc] += m_stoichCoeffRxnMatrix(kc_spec,irxn) * fracDelta_old[k];
430 double sumFrac = 0.0;
431 for (
size_t k = 0; k < nsp; k++) {
432 sumFrac += fracDelta_old[k];
436 if (sumFrac <= 0.0) {
439 double sum_Xcomp = 0.0;
440 for (
size_t k = 0; k < nsp; k++) {
441 X_est[k] = fracDelta_old[k] / sumFrac;
443 sum_Xcomp += X_est[k];
456 for (
size_t i = 0; i < componentList.size(); i++) {
457 size_t kc = componentList[i];
460 feSpecies_Deficient[kc_spec] = m_feSpecies_old[kc_spec]
461 + log(m_actCoeffSpecies_new[kc_spec] * X_est[kc]);
463 feSpecies_Deficient[kc_spec] = m_feSpecies_old[kc_spec]
468 for (
size_t i = 0; i < componentList.size(); i++) {
470 for (
size_t k = 0; k < Vphase->
nSpecies(); k++) {
472 if (kspec >= m_numComponents) {
473 size_t irxn = kspec - m_numComponents;
475 m_deltaGRxn_Deficient[irxn] = m_deltaGRxn_old[irxn];
477 if (m_stoichCoeffRxnMatrix(kc_spec,irxn) != 0.0) {
478 m_deltaGRxn_Deficient[irxn] +=
479 m_stoichCoeffRxnMatrix(kc_spec,irxn) * (feSpecies_Deficient[kc_spec]- m_feSpecies_old[kc_spec]);
487 funcPhaseStability = sum_Xcomp - 1.0;
488 for (
size_t k = 0; k < nsp; k++) {
490 if (kspec >= m_numComponents) {
491 size_t irxn = kspec - m_numComponents;
492 double deltaGRxn =
clip(m_deltaGRxn_Deficient[irxn], -50.0, 50.0);
493 E_phi[k] = std::exp(-deltaGRxn) / m_actCoeffSpecies_new[kspec];
495 funcPhaseStability += E_phi[k];
502 for (
size_t k = 0; k < nsp; k++) {
504 double b = E_phi[k] / sum * (1.0 - sum_Xcomp);
505 if (kspec >= m_numComponents) {
506 fracDelta_raw[k] = b;
512 for (
size_t i = 0; i < componentList.size(); i++) {
513 size_t kc = componentList[i];
515 fracDelta_raw[kc] = 0.0;
516 for (
size_t k = 0; k < nsp; k++) {
518 if (kspec >= m_numComponents) {
519 size_t irxn = kspec - m_numComponents;
520 fracDelta_raw[kc] += m_stoichCoeffRxnMatrix(kc_spec,irxn) * fracDelta_raw[k];
526 doublereal sumADel = 0.0;
527 for (
size_t k = 0; k < nsp; k++) {
528 delFrac[k] = fracDelta_raw[k] - fracDelta_old[k];
529 sumADel += fabs(delFrac[k]);
534 for (
size_t k = 0; k < nsp; k++) {
535 dirProd += fracDelta_old[k] * delFrac[k];
537 bool crossedSign =
false;
538 if (dirProd * dirProdOld < 0.0) {
543 if (dampOld < 0.25) {
544 damp = 2.0 * dampOld;
547 if (normUpdate *1.5 > normUpdateOld) {
548 damp = 0.5 * dampOld;
549 }
else if (normUpdate *2.0 > normUpdateOld) {
550 damp = 0.8 * dampOld;
553 if (normUpdate > normUpdateOld * 2.0) {
554 damp = 0.6 * dampOld;
555 }
else if (normUpdate > normUpdateOld * 1.2) {
556 damp = 0.9 * dampOld;
560 for (
size_t k = 0; k < nsp; k++) {
561 if (fabs(damp * delFrac[k]) > 0.3*fabs(fracDelta_old[k])) {
562 damp = std::max(0.3*fabs(fracDelta_old[k]) / fabs(delFrac[k]),
563 1.0E-8/fabs(delFrac[k]));
565 if (delFrac[k] < 0.0 && 2.0 * damp * (-delFrac[k]) > fracDelta_old[k]) {
566 damp = fracDelta_old[k] / (2.0 * -delFrac[k]);
568 if (delFrac[k] > 0.0 && 2.0 * damp * delFrac[k] > fracDelta_old[k]) {
569 damp = fracDelta_old[k] / (2.0 * delFrac[k]);
572 damp = std::max(damp, 0.000001);
573 for (
size_t k = 0; k < nsp; k++) {
574 fracDelta_new[k] = fracDelta_old[k] + damp * delFrac[k];
577 if (m_debug_print_lvl >= 2) {
578 plogf(
" --- %3d %12g %12g %12g %12g %12g %12g %12g\n", its, X_est[KP], fracDelta_old[KP],
579 delFrac[KP], fracDelta_new[KP], normUpdate, damp, funcPhaseStability);
582 if (normUpdate < 1.0E-5 * damp) {
584 if (its < minNumberIterations) {
599 throw CanteraError(
"VCS_SOLVE::vcs_phaseStabilityTest",
"not done yet");
601 if (m_debug_print_lvl >= 2) {
602 plogf(
" ------------------------------------------------------------" 603 "-------------------------------------------------------------\n");
604 }
else if (m_debug_print_lvl == 1) {
605 if (funcPhaseStability > 0.0) {
606 plogf(
" --- phase %d with func = %g is to be born\n", iph, funcPhaseStability);
608 plogf(
" --- phase %d with func = %g stays dead\n", iph, funcPhaseStability);
611 return funcPhaseStability;
void setCreationMoleNumbers(const double *const n_k, const std::vector< size_t > &creationGlobalRxnNumbers)
Sets the creationMoleNum's within the phase object.
bool m_singleSpecies
If true, this phase consists of a single species.
void setMoleFractionsState(const double molNum, const double *const moleFracVec, const int vcsStateStatus)
Set the moles and/or mole fractions within the phase.
#define VCS_SPECIES_MINOR
Species is a major species.
const size_t npos
index returned by functions to indicate "no position"
#define VCS_DELETE_ELEMENTABS_CUTOFF
Cutoff moles below which a phase or species which comprises the bulk of an element's total concentrat...
T clip(const T &value, const T &lower, const T &upper)
Clip value such that lower <= value <= upper.
size_t spGlobalIndexVCS(const size_t spIndex) const
Return the Global VCS index of the kth species in the phase.
const vector_fp & creationMoleNumbers(std::vector< size_t > &creationGlobalRxnNumbers) const
Return a const reference to the creationMoleNumbers stored in the object.
std::string PhaseName
String name for the phase.
#define VCS_STATECALC_PHASESTABILITY
State Calculation based on tentative mole numbers for a phase which is currently zeroed, but is being evaluated for whether it should pop back into existence.
Header file for the internal object that holds the vcs equilibrium problem (see Class VCS_SOLVE and E...
Header for the object representing each phase within vcs.
#define VCS_ELEM_TYPE_ABSPOS
Normal element constraint consisting of positive coefficients for the formula matrix.
#define VCS_DELETE_MINORSPECIES_CUTOFF
Cutoff relative mole number value, below which species are deleted from the equilibrium problem...
#define VCS_DELETE_PHASE_CUTOFF
Cutoff relative moles below which a phase is deleted from the equilibrium problem.
size_t nSpecies() const
Return the number of species in the phase.
Base class for exceptions thrown by Cantera classes.
void sendToVCS_ActCoeff(const int stateCalc, double *const AC)
Fill in an activity coefficients vector within a VCS_SOLVE object.
#define VCS_SPECIES_MAJOR
Species is a major species.
Phase information and Phase calculations for vcs.
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
double vcs_l2norm(const vector_fp &vec)
determine the l2 norm of a vector of doubles
#define VCS_STATECALC_OLD
State Calculation based on the old or base mole numbers.
int exists() const
int indicating whether the phase exists or not
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Contains declarations for string manipulation functions within Cantera.
#define plogf
define this Cantera function to replace printf
#define VCS_SPECIES_COMPONENT
Species is a component which can be nonzero.
Namespace for the Cantera kernel.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...