Cantera  2.3.0
vcs_rxnadj.cpp
Go to the documentation of this file.
1 /**
2  * @file vcs_rxnadj.cpp
3  * Routines for carrying out various adjustments to the reaction steps
4  */
5 
6 // This file is part of Cantera. See License.txt in the top-level directory or
7 // at http://www.cantera.org/license.txt for license and copyright information.
8 
12 
13 #include <cstdio>
14 
15 namespace Cantera
16 {
17 
18 size_t VCS_SOLVE::vcs_RxnStepSizes(int& forceComponentCalc, size_t& kSpecial)
19 {
20  size_t iphDel = npos;
21  size_t k = 0;
22  std::string ANOTE;
23  if (m_debug_print_lvl >= 2) {
24  plogf(" ");
25  for (int j = 0; j < 82; j++) {
26  plogf("-");
27  }
28  plogf("\n");
29  plogf(" --- Subroutine vcs_RxnStepSizes called - Details:\n");
30  plogf(" ");
31  for (int j = 0; j < 82; j++) {
32  plogf("-");
33  }
34  plogf("\n");
35  plogf(" --- Species KMoles Rxn_Adjustment DeltaG"
36  " | Comment\n");
37  }
38 
39  // We update the matrix dlnActCoeffdmolNumber[][] at the top of the loop,
40  // when necessary
41  if (m_useActCoeffJac) {
43  }
44 
45  // LOOP OVER THE FORMATION REACTIONS
46  for (size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
47  ANOTE = "Normal Calc";
48 
49  size_t kspec = m_indexRxnToSpecies[irxn];
51  m_deltaMolNumSpecies[kspec] = 0.0;
52  ANOTE = "ZeroedPhase: Phase is artificially zeroed";
54  if (m_molNumSpecies_old[kspec] == 0.0 && (!m_SSPhase[kspec])) {
55  // MULTISPECIES PHASE WITH total moles equal to zero
56  //
57  // If dg[irxn] is negative, then the multispecies phase should
58  // come alive again. Add a small positive step size to make it
59  // come alive.
60  if (m_deltaGRxn_new[irxn] < -1.0e-4) {
61  // First decide if this species is part of a multiphase that
62  // is nontrivial in size.
63  size_t iph = m_phaseID[kspec];
64  double tphmoles = m_tPhaseMoles_old[iph];
65  double trphmoles = tphmoles / m_totalMolNum;
66  vcs_VolPhase* Vphase = m_VolPhaseList[iph];
67  if (Vphase->exists() && (trphmoles > VCS_DELETE_PHASE_CUTOFF)) {
70  m_deltaMolNumSpecies[kspec] = 0.0;
71  ANOTE = fmt::sprintf("MultSpec (%s): Species not born due to STOICH/PHASEPOP even though DG = %11.3E",
73  } else {
75  ANOTE = fmt::sprintf("MultSpec (%s): small species born again DG = %11.3E",
77  }
78  } else {
79  ANOTE = fmt::sprintf("MultSpec (%s):still dead, no phase pop, even though DG = %11.3E",
81  m_deltaMolNumSpecies[kspec] = 0.0;
82  if (Vphase->exists() > 0 && trphmoles > 0.0) {
84  ANOTE = fmt::sprintf("MultSpec (%s): birthed species because it was zero in a small existing phase with DG = %11.3E",
86  }
87  }
88  } else {
89  ANOTE = fmt::sprintf("MultSpec (%s): still dead DG = %11.3E",
91  m_deltaMolNumSpecies[kspec] = 0.0;
92  }
93  } else {
94  // REGULAR PROCESSING
95  //
96  // First take care of cases where we want to bail out. Don't
97  // bother if superconvergence has already been achieved in this
98  // mode.
99  if (fabs(m_deltaGRxn_new[irxn]) <= m_tolmaj2) {
100  ANOTE = fmt::sprintf("Skipped: superconverged DG = %11.3E", m_deltaGRxn_new[irxn]);
101  if (m_debug_print_lvl >= 2) {
102  plogf(" --- %-12.12s", m_speciesName[kspec]);
103  plogf(" %12.4E %12.4E %12.4E | %s\n",
105  m_deltaGRxn_new[irxn], ANOTE);
106  }
107  continue;
108  }
109 
110  // Don't calculate for minor or nonexistent species if their
111  // values are to be decreasing anyway.
112  if ((m_speciesStatus[kspec] != VCS_SPECIES_MAJOR) && (m_deltaGRxn_new[irxn] >= 0.0)) {
113  ANOTE = fmt::sprintf("Skipped: IC = %3d and DG >0: %11.3E",
114  m_speciesStatus[kspec], m_deltaGRxn_new[irxn]);
115  if (m_debug_print_lvl >= 2) {
116  plogf(" --- %-12.12s", m_speciesName[kspec]);
117  plogf(" %12.4E %12.4E %12.4E | %s\n",
119  m_deltaGRxn_new[irxn], ANOTE);
120  }
121  continue;
122  }
123 
124  // Start of the regular processing
125  double s;
126  if (m_SSPhase[kspec]) {
127  s = 0.0;
128  } else {
129  s = 1.0 / m_molNumSpecies_old[kspec];
130  }
131  for (size_t j = 0; j < m_numComponents; ++j) {
132  if (!m_SSPhase[j] && m_molNumSpecies_old[j] > 0.0) {
133  s += pow(m_stoichCoeffRxnMatrix(j,irxn), 2) / m_molNumSpecies_old[j];
134  }
135  }
136  for (size_t j = 0; j < m_numPhases; j++) {
137  vcs_VolPhase* Vphase = m_VolPhaseList[j];
138  if (!Vphase->m_singleSpecies && m_tPhaseMoles_old[j] > 0.0) {
139  s -= pow(m_deltaMolNumPhase(j,irxn), 2) / m_tPhaseMoles_old[j];
140  }
141  }
142  if (s != 0.0) {
143  // Take into account of the derivatives of the activity
144  // coefficients with respect to the mole numbers, even in
145  // our diagonal approximation.
146  if (m_useActCoeffJac) {
147  double s_old = s;
148  s = vcs_Hessian_diag_adj(irxn, s_old);
149  ANOTE = fmt::sprintf("Normal calc: diag adjusted from %g "
150  "to %g due to act coeff", s_old, s);
151  }
152 
153  m_deltaMolNumSpecies[kspec] = -m_deltaGRxn_new[irxn] / s;
154  // New section to do damping of the m_deltaMolNumSpecies[]
155  for (size_t j = 0; j < m_numComponents; ++j) {
156  double stoicC = m_stoichCoeffRxnMatrix(j,irxn);
157  if (stoicC != 0.0) {
158  double negChangeComp = -stoicC * m_deltaMolNumSpecies[kspec];
159  if (negChangeComp > m_molNumSpecies_old[j]) {
160  if (m_molNumSpecies_old[j] > 0.0) {
161  ANOTE = fmt::sprintf("Delta damped from %g "
162  "to %g due to component %d (%10s) going neg", m_deltaMolNumSpecies[kspec],
163  -m_molNumSpecies_old[j] / stoicC, j, m_speciesName[j]);
164  m_deltaMolNumSpecies[kspec] = -m_molNumSpecies_old[j] / stoicC;
165  } else {
166  ANOTE = fmt::sprintf("Delta damped from %g "
167  "to %g due to component %d (%10s) zero", m_deltaMolNumSpecies[kspec],
168  -m_molNumSpecies_old[j] / stoicC, j, m_speciesName[j]);
169  m_deltaMolNumSpecies[kspec] = 0.0;
170  }
171  }
172  }
173  }
174  // Implement a damping term that limits m_deltaMolNumSpecies
175  // to the size of the mole number
176  if (-m_deltaMolNumSpecies[kspec] > m_molNumSpecies_old[kspec]) {
177  ANOTE = fmt::sprintf("Delta damped from %g "
178  "to %g due to %s going negative", m_deltaMolNumSpecies[kspec], -m_molNumSpecies_old[kspec],
179  m_speciesName[kspec]);
180  m_deltaMolNumSpecies[kspec] = -m_molNumSpecies_old[kspec];
181  }
182  } else {
183  // REACTION IS ENTIRELY AMONGST SINGLE SPECIES PHASES.
184  // DELETE ONE OF THE PHASES AND RECOMPUTE BASIS.
185  //
186  // Either the species L will disappear or one of the
187  // component single species phases will disappear. The sign
188  // of DG(I) will indicate which way the reaction will go.
189  // Then, we need to follow the reaction to see which species
190  // will zero out first. The species to be zeroed out will be
191  // "k".
192  double dss;
193  if (m_deltaGRxn_new[irxn] > 0.0) {
194  dss = m_molNumSpecies_old[kspec];
195  k = kspec;
196  for (size_t j = 0; j < m_numComponents; ++j) {
197  if (m_stoichCoeffRxnMatrix(j,irxn) > 0.0) {
198  double xx = m_molNumSpecies_old[j] / m_stoichCoeffRxnMatrix(j,irxn);
199  if (xx < dss) {
200  dss = xx;
201  k = j;
202  }
203  }
204  }
205  dss = -dss;
206  } else {
207  dss = 1.0e10;
208  for (size_t j = 0; j < m_numComponents; ++j) {
209  if (m_stoichCoeffRxnMatrix(j,irxn) < 0.0) {
210  double xx = -m_molNumSpecies_old[j] / m_stoichCoeffRxnMatrix(j,irxn);
211  if (xx < dss) {
212  dss = xx;
213  k = j;
214  }
215  }
216  }
217  }
218 
219  // Here we adjust the mole fractions according to DSS and
220  // the stoichiometric array to take into account that we are
221  // eliminating the kth species. DSS contains the amount of
222  // moles of the kth species that needs to be added back into
223  // the component species.
224  if (dss != 0.0) {
225  if ((k == kspec) && (m_SSPhase[kspec] != 1)) {
226  // Found out that we can be in this spot, when
227  // components of multispecies phases are zeroed,
228  // leaving noncomponent species of the same phase
229  // having all of the mole numbers of that phases. it
230  // seems that we can suggest a zero of the species
231  // and the code will recover.
232  ANOTE = fmt::sprintf("Delta damped from %g to %g due to delete %s", m_deltaMolNumSpecies[kspec],
233  -m_molNumSpecies_old[kspec], m_speciesName[kspec]);
234  m_deltaMolNumSpecies[kspec] = -m_molNumSpecies_old[kspec];
235  if (m_debug_print_lvl >= 2) {
236  plogf(" --- %-12.12s", m_speciesName[kspec]);
237  plogf(" %12.4E %12.4E %12.4E | %s\n",
239  m_deltaGRxn_new[irxn], ANOTE);
240  }
241  continue;
242  }
243 
244  // Delete the single species phase
245  for (size_t j = 0; j < m_numSpeciesTot; j++) {
246  m_deltaMolNumSpecies[j] = 0.0;
247  }
248  m_deltaMolNumSpecies[kspec] = dss;
249  for (size_t j = 0; j < m_numComponents; ++j) {
250  m_deltaMolNumSpecies[j] = dss * m_stoichCoeffRxnMatrix(j,irxn);
251  }
252 
253  iphDel = m_phaseID[k];
254  kSpecial = k;
255 
256  if (k != kspec) {
257  ANOTE = fmt::sprintf("Delete component SS phase %d named %s - SS phases only",
258  iphDel, m_speciesName[k]);
259  } else {
260  ANOTE = fmt::sprintf("Delete this SS phase %d - SS components only", iphDel);
261  }
262  if (m_debug_print_lvl >= 2) {
263  plogf(" --- %-12.12s", m_speciesName[kspec]);
264  plogf(" %12.4E %12.4E %12.4E | %s\n",
266  m_deltaGRxn_new[irxn], ANOTE);
267  plogf(" --- vcs_RxnStepSizes Special section to set up to delete %s",
268  m_speciesName[k]);
269  plogendl();
270  }
271  if (k != kspec) {
272  forceComponentCalc = 1;
273  if (m_debug_print_lvl >= 2) {
274  plogf(" --- Force a component recalculation \n");
275  plogendl();
276  }
277  }
278  if (m_debug_print_lvl >= 2) {
279  plogf(" ");
280  writeline('-', 82);
281  }
282  return iphDel;
283  }
284  }
285  } // End of regular processing
286  if (m_debug_print_lvl >= 2) {
287  plogf(" --- %-12.12s", m_speciesName[kspec]);
288  plogf(" %12.4E %12.4E %12.4E | %s\n",
290  m_deltaGRxn_new[irxn], ANOTE);
291  }
292  } // End of loop over m_speciesUnknownType
293  } // End of loop over non-component stoichiometric formation reactions
294  if (m_debug_print_lvl >= 2) {
295  plogf(" ");
296  writeline('-', 82);
297  }
298  return iphDel;
299 }
300 
302 {
303  warn_deprecated("VCS_SOLVE::vcs_rxn_adj_cg",
304  "Unused. To be removed after Cantera 2.3.");
305  int soldel = 0;
306  char ANOTE[128];
307  plogf(" ");
308  for (size_t j = 0; j < 77; j++) {
309  plogf("-");
310  }
311  plogf("\n --- Subroutine rxn_adj_cg() called\n");
312  plogf(" --- Species Moles Rxn_Adjustment | Comment\n");
313 
314  // Precalculation loop -> we calculate quantities based on loops over the
315  // number of species. We also evaluate whether the matrix is appropriate for
316  // this algorithm. If not, we bail out.
317  for (size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
318  sprintf(ANOTE, "Normal Calc");
319 
320  size_t kspec = m_indexRxnToSpecies[irxn];
321  if (m_molNumSpecies_old[kspec] == 0.0 && (!m_SSPhase[kspec])) {
322  // MULTISPECIES PHASE WITH total moles equal to zero
323  //
324  // HKM -> the statement below presupposes units in m_deltaGRxn_new[].
325  // It probably should be replaced with something more relative
326  if (m_deltaGRxn_new[irxn] < -1.0e-4) {
327  sprintf(ANOTE, "MultSpec: come alive DG = %11.3E", m_deltaGRxn_new[irxn]);
328  m_deltaMolNumSpecies[kspec] = 1.0e-10;
331  } else {
332  sprintf(ANOTE, "MultSpec: still dead DG = %11.3E", m_deltaGRxn_new[irxn]);
333  m_deltaMolNumSpecies[kspec] = 0.0;
334  }
335  } else {
336  // REGULAR PROCESSING
337  //
338  // First take care of cases where we want to bail out. Don't bother
339  // if superconvergence has already been achieved in this mode.
340  if (fabs(m_deltaGRxn_new[irxn]) <= m_tolmaj2) {
341  sprintf(ANOTE, "Skipped: converged DG = %11.3E\n", m_deltaGRxn_new[irxn]);
342  plogf(" --- ");
343  plogf("%-12.12s", m_speciesName[kspec]);
344  plogf(" %12.4E %12.4E | %s\n", m_molNumSpecies_old[kspec],
345  m_deltaMolNumSpecies[kspec], ANOTE);
346  continue;
347  }
348 
349  // Don't calculate for minor or nonexistent species if their values
350  // are to be decreasing anyway.
351  if (m_speciesStatus[kspec] <= VCS_SPECIES_MINOR && m_deltaGRxn_new[irxn] >= 0.0) {
352  sprintf(ANOTE, "Skipped: IC = %3d and DG >0: %11.3E\n", m_speciesStatus[kspec], m_deltaGRxn_new[irxn]);
353  plogf(" --- ");
354  plogf("%-12.12s", m_speciesName[kspec]);
355  plogf(" %12.4E %12.4E | %s\n", m_molNumSpecies_old[kspec],
356  m_deltaMolNumSpecies[kspec], ANOTE);
357  continue;
358  }
359 
360  // Start of the regular processing
361  double s = (m_SSPhase[kspec]) ? 0.0 : 1.0 / m_molNumSpecies_old[kspec];
362  for (size_t j = 0; j < m_numComponents; ++j) {
363  if (!m_SSPhase[j]) {
364  s += pow(m_stoichCoeffRxnMatrix(j,irxn), 2) / m_molNumSpecies_old[j];
365  }
366  }
367  for (size_t j = 0; j < m_numPhases; j++) {
368  if (!m_VolPhaseList[j]->m_singleSpecies && m_tPhaseMoles_old[j] > 0.0) {
369  s -= pow(m_deltaMolNumPhase(j,irxn), 2) / m_tPhaseMoles_old[j];
370  }
371  }
372  if (s != 0.0) {
373  m_deltaMolNumSpecies[kspec] = -m_deltaGRxn_new[irxn] / s;
374  } else {
375  // REACTION IS ENTIRELY AMONGST SINGLE SPECIES PHASES. DELETE
376  // ONE SOLID AND RECOMPUTE BASIS
377  //
378  // Either the species L will disappear or one of the component
379  // single species phases will disappear. The sign of DG(I) will
380  // indicate which way the reaction will go. Then, we need to
381  // follow the reaction to see which species will zero out first.
382  size_t k = npos;
383  double dss;
384  if (m_deltaGRxn_new[irxn] > 0.0) {
385  dss = m_molNumSpecies_old[kspec];
386  k = kspec;
387  for (size_t j = 0; j < m_numComponents; ++j) {
388  if (m_stoichCoeffRxnMatrix(j,irxn) > 0.0) {
389  double xx = m_molNumSpecies_old[j] / m_stoichCoeffRxnMatrix(j,irxn);
390  if (xx < dss) {
391  dss = xx;
392  k = j;
393  }
394  }
395  }
396  dss = -dss;
397  } else {
398  dss = 1.0e10;
399  for (size_t j = 0; j < m_numComponents; ++j) {
400  if (m_stoichCoeffRxnMatrix(j,irxn) < 0.0) {
401  double xx = -m_molNumSpecies_old[j] / m_stoichCoeffRxnMatrix(j,irxn);
402  if (xx < dss) {
403  dss = xx;
404  k = j;
405  }
406  }
407  }
408  }
409 
410  // Here we adjust the mole fractions according to DSS and the
411  // stoichiometric array to take into account that we are
412  // eliminating the kth species. DSS contains the amount of moles
413  // of the kth species that needs to be added back into the
414  // component species.
415  if (dss != 0.0) {
416  m_molNumSpecies_old[kspec] += dss;
417  m_tPhaseMoles_old[m_phaseID[kspec]] += dss;
418  for (size_t j = 0; j < m_numComponents; ++j) {
419  m_molNumSpecies_old[j] += dss * m_stoichCoeffRxnMatrix(j,irxn);
421  }
422  m_molNumSpecies_old[k] = 0.0;
423  m_tPhaseMoles_old[m_phaseID[k]] = 0.0;
424  plogf(" --- vcs_st2 Special section to delete ");
425  plogf("%-12.12s", m_speciesName[k]);
426  plogf("\n --- Immediate return - Restart iteration\n");
427 
428  // We need to immediately recompute the component basis,
429  // because we just zeroed it out.
430  if (k != kspec) {
431  soldel = 2;
432  } else {
433  soldel = 1;
434  }
435  return soldel;
436  }
437  }
438  } // End of regular processing
439  plogf(" --- ");
440  plogf("%-12.12s", m_speciesName[kspec]);
441  plogf(" %12.4E %12.4E | %s\n", m_molNumSpecies_old[kspec],
442  m_deltaMolNumSpecies[kspec], ANOTE);
443  } // End of loop over non-component stoichiometric formation reactions
444 
445  // When we form the Hessian we must be careful to ensure that it is a
446  // symmetric positive definite matrix, still. This means zeroing out columns
447  // when we zero out rows as well. I suggest writing a small program to make
448  // sure of this property.
449  plogf(" ");
450  for (size_t j = 0; j < 77; j++) {
451  plogf("-");
452  }
453  plogf("\n");
454  return soldel;
455 }
456 
457 double VCS_SOLVE::vcs_Hessian_diag_adj(size_t irxn, double hessianDiag_Ideal)
458 {
459  double diag = hessianDiag_Ideal;
460  double hessActCoef = vcs_Hessian_actCoeff_diag(irxn);
461  if (hessianDiag_Ideal <= 0.0) {
462  throw CanteraError("VCS_SOLVE::vcs_Hessian_diag_adj",
463  "We shouldn't be here");
464  }
465  if (hessActCoef >= 0.0) {
466  diag += hessActCoef;
467  } else if (fabs(hessActCoef) < 0.6666 * hessianDiag_Ideal) {
468  diag += hessActCoef;
469  } else {
470  diag -= 0.6666 * hessianDiag_Ideal;
471  }
472  return diag;
473 }
474 
476 {
477  size_t kspec = m_indexRxnToSpecies[irxn];
478  size_t kph = m_phaseID[kspec];
479  double np_kspec = std::max(m_tPhaseMoles_old[kph], 1e-13);
480  double* sc_irxn = m_stoichCoeffRxnMatrix.ptrColumn(irxn);
481 
482  // First the diagonal term of the Jacobian
483  double s = m_np_dLnActCoeffdMolNum(kspec,kspec) / np_kspec;
484 
485  // Next, the other terms. Note this only a loop over the components So, it's
486  // not too expensive to calculate.
487  for (size_t j = 0; j < m_numComponents; j++) {
488  if (!m_SSPhase[j]) {
489  for (size_t k = 0; k < m_numComponents; ++k) {
490  if (m_phaseID[k] == m_phaseID[j]) {
491  double np = m_tPhaseMoles_old[m_phaseID[k]];
492  if (np > 0.0) {
493  s += sc_irxn[k] * sc_irxn[j] * m_np_dLnActCoeffdMolNum(j,k) / np;
494  }
495  }
496  }
497  if (kph == m_phaseID[j]) {
498  s += sc_irxn[j] * (m_np_dLnActCoeffdMolNum(j,kspec) + m_np_dLnActCoeffdMolNum(kspec,j)) / np_kspec;
499  }
500  }
501  }
502  return s;
503 }
504 
505 void VCS_SOLVE::vcs_CalcLnActCoeffJac(const double* const moleSpeciesVCS)
506 {
507  // Loop over all of the phases in the problem
508  for (size_t iphase = 0; iphase < m_numPhases; iphase++) {
509  vcs_VolPhase* Vphase = m_VolPhaseList[iphase];
510 
511  // We don't need to call single species phases;
512  if (!Vphase->m_singleSpecies && !Vphase->isIdealSoln()) {
513  // update the mole numbers
514  Vphase->setMolesFromVCS(VCS_STATECALC_OLD, moleSpeciesVCS);
515 
516  // Download the resulting calculation into the full vector. This
517  // scatter calculation is carried out in the vcs_VolPhase object.
518  Vphase->sendToVCS_LnActCoeffJac(m_np_dLnActCoeffdMolNum);
519  }
520  }
521 }
522 
523 double VCS_SOLVE::deltaG_Recalc_Rxn(const int stateCalc, const size_t irxn, const double* const molNum, double* const ac,
524  double* const mu_i)
525 {
526  warn_deprecated("VCS_SOLVE::deltaG_Recalc_Rxn",
527  "Unused. To be removed after Cantera 2.3.");
528  size_t kspec = irxn + m_numComponents;
529  for (size_t iphase = 0; iphase < m_numPhases; iphase++) {
530  if (m_phaseParticipation(iphase,irxn)) {
531  vcs_chemPotPhase(stateCalc, iphase, molNum, ac, mu_i);
532  }
533  }
534  double deltaG = mu_i[kspec];
535  for (size_t k = 0; k < m_numComponents; k++) {
536  deltaG += m_stoichCoeffRxnMatrix(k,irxn) * mu_i[k];
537  }
538  return deltaG;
539 }
540 
541 double VCS_SOLVE::vcs_line_search(const size_t irxn, const double dx_orig, char* const ANOTE)
542 {
543  warn_deprecated("VCS_SOLVE::vcs_line_search",
544  "Unused. To be removed after Cantera 2.3.");
545  int its = 0;
546  size_t kspec = m_indexRxnToSpecies[irxn];
547  const int MAXITS = 10;
548  double dx = dx_orig;
549  double* sc_irxn = m_stoichCoeffRxnMatrix.ptrColumn(irxn);
550  vector_fp& molNumBase = m_molNumSpecies_old;
553 
554  // Calculate the deltaG value at the dx = 0.0 point
555  vcs_setFlagsVolPhases(false, VCS_STATECALC_OLD);
556  double deltaGOrig = deltaG_Recalc_Rxn(VCS_STATECALC_OLD, irxn, &molNumBase[0], &acBase[0], &m_feSpecies_old[0]);
557  double forig = fabs(deltaGOrig) + 1.0E-15;
558  if (deltaGOrig > 0.0) {
559  if (dx_orig > 0.0) {
560  dx = 0.0;
561  if (ANOTE) {
562  sprintf(ANOTE, "Rxn reduced to zero step size in line search: dx>0 dg > 0");
563  }
564  return dx;
565  }
566  } else if (deltaGOrig < 0.0) {
567  if (dx_orig < 0.0) {
568  dx = 0.0;
569  if (ANOTE) {
570  sprintf(ANOTE, "Rxn reduced to zero step size in line search: dx<0 dg < 0");
571  }
572  return dx;
573  }
574  } else if (deltaGOrig == 0.0) {
575  return 0.0;
576  }
577  if (dx_orig == 0.0) {
578  return 0.0;
579  }
580 
582  double molSum = molNumBase[kspec];
583  m_molNumSpecies_new[kspec] = molNumBase[kspec] + dx_orig;
584  for (size_t k = 0; k < m_numComponents; k++) {
585  m_molNumSpecies_new[k] = molNumBase[k] + sc_irxn[k] * dx_orig;
586  molSum += molNumBase[k];
587  }
588  vcs_setFlagsVolPhases(false, VCS_STATECALC_NEW);
589 
590  double deltaG1 = deltaG_Recalc_Rxn(VCS_STATECALC_NEW, irxn, &m_molNumSpecies_new[0],
591  &ac[0], &m_feSpecies_new[0]);
592 
593  // If deltaG hasn't switched signs when going the full distance then we are
594  // heading in the appropriate direction, and we should accept the current
595  // full step size
596  if (deltaG1 * deltaGOrig > 0.0) {
597  dx = dx_orig;
598  goto finalize;
599  }
600 
601  // If we have decreased somewhat, the deltaG return after finding a better
602  // estimate for the line search.
603  if (fabs(deltaG1) < 0.8 * forig) {
604  if (deltaG1 * deltaGOrig < 0.0) {
605  double slope = (deltaG1 - deltaGOrig) / dx_orig;
606  dx = -deltaGOrig / slope;
607  } else {
608  dx = dx_orig;
609  }
610  goto finalize;
611  }
612 
613  dx = dx_orig;
614  for (its = 0; its < MAXITS; its++) {
615  // Calculate the approximation to the total Gibbs free energy at
616  // the dx *= 0.5 point
617  dx *= 0.5;
618  m_molNumSpecies_new[kspec] = molNumBase[kspec] + dx;
619  for (size_t k = 0; k < m_numComponents; k++) {
620  m_molNumSpecies_new[k] = molNumBase[k] + sc_irxn[k] * dx;
621  }
622  vcs_setFlagsVolPhases(false, VCS_STATECALC_NEW);
623  double deltaG = deltaG_Recalc_Rxn(VCS_STATECALC_NEW, irxn, &m_molNumSpecies_new[0],
624  &ac[0], &m_feSpecies_new[0]);
625 
626  // If deltaG hasn't switched signs when going the full distance then we
627  // are heading in the appropriate direction, and we should accept the
628  // current step
629  if (deltaG * deltaGOrig > 0.0) {
630  goto finalize;
631  }
632 
633  // If we have decreased somewhat, the deltaG return after finding
634  // a better estimate for the line search.
635  if (fabs(deltaG) / forig < (1.0 - 0.1 * dx / dx_orig)) {
636  if (deltaG * deltaGOrig < 0.0) {
637  double slope = (deltaG - deltaGOrig) / dx;
638  dx = -deltaGOrig / slope;
639  }
640  goto finalize;
641  }
642  }
643 
644 finalize:
645  vcs_setFlagsVolPhases(false, VCS_STATECALC_NEW);
646  if (its >= MAXITS) {
647  sprintf(ANOTE, "Rxn reduced to zero step size from %g to %g (MAXITS)", dx_orig, dx);
648  return dx;
649  }
650  if (dx != dx_orig) {
651  sprintf(ANOTE, "Line Search reduced step size from %g to %g", dx_orig, dx);
652  }
653  return dx;
654 }
655 
656 }
size_t vcs_RxnStepSizes(int &forceComponentCalc, size_t &kSpecial)
Calculates formation reaction step sizes.
Definition: vcs_rxnadj.cpp:18
bool isIdealSoln() const
Returns whether the phase is an ideal solution phase.
std::vector< size_t > m_phaseID
Mapping from the species number to the phase number.
Definition: vcs_solve.h:1703
double vcs_Hessian_actCoeff_diag(size_t irxn)
Calculates the diagonal contribution to the Hessian due to the dependence of the activity coefficient...
Definition: vcs_rxnadj.cpp:475
double vcs_line_search(const size_t irxn, const double dx_orig, char *const ANOTE=0)
A line search algorithm is carried out on one reaction.
Definition: vcs_rxnadj.cpp:541
vector_int m_speciesUnknownType
Specifies the species unknown type.
Definition: vcs_solve.h:1511
double m_totalMolNum
Total number of kmoles in all phases.
Definition: vcs_solve.h:1584
bool m_singleSpecies
If true, this phase consists of a single species.
Definition: vcs_VolPhase.h:566
void vcs_chemPotPhase(const int stateCalc, const size_t iph, const double *const molNum, double *const ac, double *const mu_i, const bool do_deleted=false)
We calculate the dimensionless chemical potentials of all species in a single phase.
vector_fp m_molNumSpecies_old
Total moles of the species.
Definition: vcs_solve.h:1498
double vcs_Hessian_diag_adj(size_t irxn, double hessianDiag_Ideal)
Calculates the diagonal contribution to the Hessian due to the dependence of the activity coefficient...
Definition: vcs_rxnadj.cpp:457
#define VCS_SPECIES_MINOR
Species is a major species.
Definition: vcs_defs.h:129
Array2D m_stoichCoeffRxnMatrix
Stoichiometric coefficient matrix for the reaction mechanism expressed in Reduced Canonical Form...
Definition: vcs_solve.h:1441
int m_useActCoeffJac
Choice of Hessians.
Definition: vcs_solve.h:1833
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
std::vector< vcs_VolPhase * > m_VolPhaseList
Array of Phase Structures. Length = number of phases.
Definition: vcs_solve.h:1740
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:54
vector_fp m_feSpecies_new
Dimensionless new free energy for all the species in the mechanism at the new tentative T...
Definition: vcs_solve.h:1481
vector_fp m_deltaMolNumSpecies
Reaction Adjustments for each species during the current step.
Definition: vcs_solve.h:1559
doublereal * ptrColumn(size_t j)
Return a pointer to the top of column j, columns are contiguous in memory.
Definition: Array.h:314
size_t m_numRxnRdc
Current number of non-component species in the problem.
Definition: vcs_solve.h:1407
#define VCS_SMALL_MULTIPHASE_SPECIES
Relative value of multiphase species mole number for a multiphase species which is small...
Definition: vcs_defs.h:59
vector_fp m_deltaGRxn_new
Delta G(irxn) for the noncomponent species in the mechanism.
Definition: vcs_solve.h:1539
void setMolesFromVCS(const int stateCalc, const double *molesSpeciesVCS=0)
Set the moles within the phase.
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_SPECIES_ZEROEDPHASE
Species lies in a multicomponent phase that is zeroed atm.
Definition: vcs_defs.h:173
#define VCS_DELETE_PHASE_CUTOFF
Cutoff relative moles below which a phase is deleted from the equilibrium problem.
Definition: vcs_defs.h:65
size_t m_numSpeciesTot
Total number of species in the problems.
Definition: vcs_solve.h:1387
#define VCS_STATECALC_NEW
State Calculation based on the new or tentative mole numbers.
Definition: vcs_defs.h:323
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
vector_fp m_feSpecies_old
Free energy vector from the start of the current iteration.
Definition: vcs_solve.h:1472
int m_debug_print_lvl
Debug printing lvl.
Definition: vcs_solve.h:1863
#define VCS_SPECIES_MAJOR
Species is a major species.
Definition: vcs_defs.h:122
size_t m_numComponents
Number of components calculated for the problem.
Definition: vcs_solve.h:1396
#define VCS_SPECIES_STOICHZERO
Species lies in a multicomponent phase that is active, but species concentration is zero due to stoic...
Definition: vcs_defs.h:195
size_t m_numRxnMinorZeroed
Number of active species which are currently either treated as minor species.
Definition: vcs_solve.h:1411
std::vector< char > m_SSPhase
Boolean indicating whether a species belongs to a single-species phase.
Definition: vcs_solve.h:1707
Phase information and Phase calculations for vcs.
Definition: vcs_VolPhase.h:81
vector_fp m_tPhaseMoles_old
Total kmols of species in each phase.
Definition: vcs_solve.h:1592
std::vector< std::string > m_speciesName
Species string name for the kth species.
Definition: vcs_solve.h:1710
#define VCS_STATECALC_OLD
State Calculation based on the old or base mole numbers.
Definition: vcs_defs.h:320
Array2D m_deltaMolNumPhase
Change in the number of moles of phase, iphase, due to the noncomponent formation reaction...
Definition: vcs_solve.h:1518
int exists() const
int indicating whether the phase exists or not
vector_fp m_actCoeffSpecies_new
Molar-based Activity Coefficients for Species.
Definition: vcs_solve.h:1788
#define plogendl()
define this Cantera function to replace cout << endl;
Definition: vcs_internal.h:25
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:157
double deltaG_Recalc_Rxn(const int stateCalc, const size_t irxn, const double *const molNum, double *const ac, double *const mu_i)
This function recalculates the deltaG for reaction, irxn.
Definition: vcs_rxnadj.cpp:523
int vcs_rxn_adj_cg()
Calculates reaction adjustments using a full Hessian approximation.
Definition: vcs_rxnadj.cpp:301
vector_int m_speciesStatus
Major -Minor status vector for the species in the problem.
Definition: vcs_solve.h:1700
const char * vcs_speciesType_string(int speciesStatus, int length)
Returns a const char string representing the type of the species given by the first argument...
Definition: vcs_util.cpp:58
#define plogf
define this Cantera function to replace printf
Definition: vcs_internal.h:18
#define VCS_SPECIES_TYPE_INTERFACIALVOLTAGE
Unknown refers to the voltage level of a phase.
Definition: vcs_defs.h:309
Array2D m_phaseParticipation
This is 1 if the phase, iphase, participates in the formation reaction irxn, and zero otherwise...
Definition: vcs_solve.h:1522
Namespace for the Cantera kernel.
Definition: application.cpp:29
std::vector< size_t > m_indexRxnToSpecies
Mapping between the species index for noncomponent species and the full species index.
Definition: vcs_solve.h:1692
size_t m_numPhases
Number of Phases in the problem.
Definition: vcs_solve.h:1414
double m_tolmaj2
Below this, major species aren&#39;t refined any more.
Definition: vcs_solve.h:1635
vector_fp m_molNumSpecies_new
Tentative value of the mole number vector.
Definition: vcs_solve.h:1529
Array2D m_np_dLnActCoeffdMolNum
Change in the log of the activity coefficient with respect to the mole number multiplied by the phase...
Definition: vcs_solve.h:1805
vector_fp m_actCoeffSpecies_old
Molar-based Activity Coefficients for Species based on old mole numbers.
Definition: vcs_solve.h:1795
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
void vcs_CalcLnActCoeffJac(const double *const moleSpeciesVCS)
Recalculate all of the activity coefficients in all of the phases based on input mole numbers...
Definition: vcs_rxnadj.cpp:505