Cantera  2.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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  * Copyright (2006) Sandia Corporation. Under the terms of
7  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
8  * U.S. Government retains certain rights in this software.
9  */
10 
14 
15 #include <cstdio>
16 
17 namespace Cantera
18 {
19 
20 size_t VCS_SOLVE::vcs_RxnStepSizes(int& forceComponentCalc, size_t& kSpecial)
21 {
22  size_t iphDel = npos;
23  size_t k = 0;
24 #ifdef DEBUG_MODE
25  char ANOTE[128];
26  if (m_debug_print_lvl >= 2) {
27  plogf(" ");
28  for (int j = 0; j < 82; j++) {
29  plogf("-");
30  }
31  plogf("\n");
32  plogf(" --- Subroutine vcs_RxnStepSizes called - Details:\n");
33  plogf(" ");
34  for (int j = 0; j < 82; j++) {
35  plogf("-");
36  }
37  plogf("\n");
38  plogf(" --- Species KMoles Rxn_Adjustment DeltaG"
39  " | Comment\n");
40  }
41 #else
42  char* ANOTE = 0;
43 #endif
44  /*
45  * We update the matrix dlnActCoeffdmolNumber[][] at the
46  * top of the loop, when necessary
47  */
48  if (m_useActCoeffJac) {
50  }
51  /************************************************************************
52  ******** LOOP OVER THE FORMATION REACTIONS *****************************
53  ************************************************************************/
54 
55  for (size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
56  if (DEBUG_MODE_ENABLED) {
57  sprintf(ANOTE, "Normal Calc");
58  }
59 
60  size_t kspec = m_indexRxnToSpecies[irxn];
61 
63  m_deltaMolNumSpecies[kspec] = 0.0;
64  if (DEBUG_MODE_ENABLED) {
65  sprintf(ANOTE, "ZeroedPhase: Phase is artificially zeroed");
66  }
68  if (m_molNumSpecies_old[kspec] == 0.0 && (!m_SSPhase[kspec])) {
69  /********************************************************************/
70  /******* MULTISPECIES PHASE WITH total moles equal to zero *********/
71  /*******************************************************************/
72  /*
73  * If dg[irxn] is negative, then the multispecies phase should
74  * come alive again. Add a small positive step size to
75  * make it come alive.
76  */
77  if (m_deltaGRxn_new[irxn] < -1.0e-4) {
78  /*
79  * First decide if this species is part of a multiphase that
80  * is nontrivial in size.
81  */
82  size_t iph = m_phaseID[kspec];
83  double tphmoles = m_tPhaseMoles_old[iph];
84  double trphmoles = tphmoles / m_totalMolNum;
85  vcs_VolPhase* Vphase = m_VolPhaseList[iph];
86  if (Vphase->exists() && (trphmoles > VCS_DELETE_PHASE_CUTOFF)) {
89  m_deltaMolNumSpecies[kspec] = 0.0;
90  if (DEBUG_MODE_ENABLED) {
91  sprintf(ANOTE, "MultSpec (%s): Species not born due to STOICH/PHASEPOP even though DG = %11.3E",
93  }
94  } else {
95  m_deltaMolNumSpecies[kspec] = m_totalMolNum * VCS_SMALL_MULTIPHASE_SPECIES * 10.0;
96  if (DEBUG_MODE_ENABLED) {
97  sprintf(ANOTE, "MultSpec (%s): small species born again DG = %11.3E",
99  }
100  }
101  } else {
102  if (DEBUG_MODE_ENABLED) {
103  sprintf(ANOTE, "MultSpec (%s):still dead, no phase pop, even though DG = %11.3E",
105  }
106  m_deltaMolNumSpecies[kspec] = 0.0;
107  if (Vphase->exists() > 0 && trphmoles > 0.0) {
109  if (DEBUG_MODE_ENABLED) {
110  sprintf(ANOTE,
111  "MultSpec (%s): birthed species because it was zero in a small existing phase with DG = %11.3E",
113  }
114  }
115  }
116 
117  } else {
118  if (DEBUG_MODE_ENABLED) {
119  sprintf(ANOTE, "MultSpec (%s): still dead DG = %11.3E", vcs_speciesType_string(m_speciesStatus[kspec], 15),
120  m_deltaGRxn_new[irxn]);
121  }
122  m_deltaMolNumSpecies[kspec] = 0.0;
123 
124  }
125  } else {
126  /********************************************************************/
127  /************************* REGULAR PROCESSING ***********************/
128  /********************************************************************/
129  /*
130  * First take care of cases where we want to bail out
131  *
132  *
133  * Don't bother if superconvergence has already been achieved
134  * in this mode.
135  */
136  if (fabs(m_deltaGRxn_new[irxn]) <= m_tolmaj2) {
137  if (DEBUG_MODE_ENABLED) {
138  sprintf(ANOTE, "Skipped: superconverged DG = %11.3E", m_deltaGRxn_new[irxn]);
139  if (m_debug_print_lvl >= 2) {
140  plogf(" --- %-12.12s", m_speciesName[kspec].c_str());
141  plogf(" %12.4E %12.4E %12.4E | %s\n",
143  m_deltaGRxn_new[irxn], ANOTE);
144  }
145  }
146  continue;
147  }
148  /*
149  * Don't calculate for minor or nonexistent species if
150  * their values are to be decreasing anyway.
151  */
152  if ((m_speciesStatus[kspec] != VCS_SPECIES_MAJOR) && (m_deltaGRxn_new[irxn] >= 0.0)) {
153  if (DEBUG_MODE_ENABLED) {
154  sprintf(ANOTE, "Skipped: IC = %3d and DG >0: %11.3E", m_speciesStatus[kspec], m_deltaGRxn_new[irxn]);
155  if (m_debug_print_lvl >= 2) {
156  plogf(" --- %-12.12s", m_speciesName[kspec].c_str());
157  plogf(" %12.4E %12.4E %12.4E | %s\n",
159  m_deltaGRxn_new[irxn], ANOTE);
160  }
161  }
162  continue;
163  }
164  /*
165  * Start of the regular processing
166  */
167  double s;
168  if (m_SSPhase[kspec]) {
169  s = 0.0;
170  } else {
171  s = 1.0 / m_molNumSpecies_old[kspec];
172  }
173  for (size_t j = 0; j < m_numComponents; ++j) {
174  if (!m_SSPhase[j]) {
175  if (m_molNumSpecies_old[j] > 0.0) {
176  s += pow(m_stoichCoeffRxnMatrix(j,irxn), 2) / m_molNumSpecies_old[j];
177  }
178  }
179  }
180  for (size_t j = 0; j < m_numPhases; j++) {
181  vcs_VolPhase* Vphase = m_VolPhaseList[j];
182  if (!Vphase->m_singleSpecies) {
183  if (m_tPhaseMoles_old[j] > 0.0) {
184  s -= pow(m_deltaMolNumPhase(j,irxn), 2) / m_tPhaseMoles_old[j];
185  }
186  }
187  }
188  if (s != 0.0) {
189  /*
190  * Take into account of the
191  * derivatives of the activity coefficients with respect to the
192  * mole numbers, even in our diagonal approximation.
193  */
194  if (m_useActCoeffJac) {
195  double s_old = s;
196  s = vcs_Hessian_diag_adj(irxn, s_old);
197  if (DEBUG_MODE_ENABLED && s_old != s) {
198  sprintf(ANOTE, "Normal calc: diag adjusted from %g "
199  "to %g due to act coeff", s_old, s);
200  }
201  }
202 
203  m_deltaMolNumSpecies[kspec] = -m_deltaGRxn_new[irxn] / s;
204  // New section to do damping of the m_deltaMolNumSpecies[]
205  for (size_t j = 0; j < m_numComponents; ++j) {
206  double stoicC = m_stoichCoeffRxnMatrix(j,irxn);
207  if (stoicC != 0.0) {
208  double negChangeComp = -stoicC * m_deltaMolNumSpecies[kspec];
209  if (negChangeComp > m_molNumSpecies_old[j]) {
210  if (m_molNumSpecies_old[j] > 0.0) {
211  if (DEBUG_MODE_ENABLED) {
212  sprintf(ANOTE, "Delta damped from %g "
213  "to %g due to component %lu (%10s) going neg", m_deltaMolNumSpecies[kspec],
214  -m_molNumSpecies_old[j] / stoicC, j, m_speciesName[j].c_str());
215  }
216  m_deltaMolNumSpecies[kspec] = -m_molNumSpecies_old[j] / stoicC;
217  } else {
218  if (DEBUG_MODE_ENABLED) {
219  sprintf(ANOTE, "Delta damped from %g "
220  "to %g due to component %lu (%10s) zero", m_deltaMolNumSpecies[kspec],
221  -m_molNumSpecies_old[j] / stoicC, j, m_speciesName[j].c_str());
222  }
223  m_deltaMolNumSpecies[kspec] = 0.0;
224  }
225  }
226  }
227  }
228  // Implement a damping term that limits m_deltaMolNumSpecies to the size of the mole number
229  if (-m_deltaMolNumSpecies[kspec] > m_molNumSpecies_old[kspec]) {
230  if (DEBUG_MODE_ENABLED) {
231  sprintf(ANOTE, "Delta damped from %g "
232  "to %g due to %s going negative", m_deltaMolNumSpecies[kspec], -m_molNumSpecies_old[kspec],
233  m_speciesName[kspec].c_str());
234  }
235  m_deltaMolNumSpecies[kspec] = -m_molNumSpecies_old[kspec];
236  }
237 
238  } else {
239  /* ************************************************************ */
240  /* **** REACTION IS ENTIRELY AMONGST SINGLE SPECIES PHASES **** */
241  /* **** DELETE ONE OF THE PHASES AND RECOMPUTE BASIS ********* */
242  /* ************************************************************ */
243  /*
244  * Either the species L will disappear or one of the
245  * component single species phases will disappear. The sign
246  * of DG(I) will indicate which way the reaction will go.
247  * Then, we need to follow the reaction to see which species
248  * will zero out first.
249  * -> The species to be zeroed out will be "k".
250  */
251  double dss;
252  if (m_deltaGRxn_new[irxn] > 0.0) {
253  dss = m_molNumSpecies_old[kspec];
254  k = kspec;
255  for (size_t j = 0; j < m_numComponents; ++j) {
256  if (m_stoichCoeffRxnMatrix(j,irxn) > 0.0) {
257  double xx = m_molNumSpecies_old[j] / m_stoichCoeffRxnMatrix(j,irxn);
258  if (xx < dss) {
259  dss = xx;
260  k = j;
261  }
262  }
263  }
264  dss = -dss;
265  } else {
266  dss = 1.0e10;
267  for (size_t j = 0; j < m_numComponents; ++j) {
268  if (m_stoichCoeffRxnMatrix(j,irxn) < 0.0) {
269  double xx = -m_molNumSpecies_old[j] / m_stoichCoeffRxnMatrix(j,irxn);
270  if (xx < dss) {
271  dss = xx;
272  k = j;
273  }
274  }
275  }
276  }
277  /*
278  * Here we adjust the mole fractions
279  * according to DSS and the stoichiometric array
280  * to take into account that we are eliminating
281  * the kth species. DSS contains the amount
282  * of moles of the kth species that needs to be
283  * added back into the component species.
284  */
285  if (dss != 0.0) {
286 
287  if ((k == kspec) && (m_SSPhase[kspec] != 1)) {
288  /*
289  * Found out that we can be in this spot, when components of multispecies phases
290  * are zeroed, leaving noncomponent species of the same phase having all of the
291  * mole numbers of that phases. it seems that we can suggest a zero of the species
292  * and the code will recover.
293  */
294  if (DEBUG_MODE_ENABLED) {
295  sprintf(ANOTE, "Delta damped from %g to %g due to delete %s", m_deltaMolNumSpecies[kspec],
296  -m_molNumSpecies_old[kspec], m_speciesName[kspec].c_str());
297  }
298  m_deltaMolNumSpecies[kspec] = -m_molNumSpecies_old[kspec];
299  if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
300  plogf(" --- %-12.12s", m_speciesName[kspec].c_str());
301  plogf(" %12.4E %12.4E %12.4E | %s\n",
303  m_deltaGRxn_new[irxn], ANOTE);
304  }
305  continue;
306  }
307  /*
308  * Delete the single species phase
309  */
310  for (size_t j = 0; j < m_numSpeciesTot; j++) {
311  m_deltaMolNumSpecies[j] = 0.0;
312  }
313  m_deltaMolNumSpecies[kspec] = dss;
314  for (size_t j = 0; j < m_numComponents; ++j) {
315  m_deltaMolNumSpecies[j] = dss * m_stoichCoeffRxnMatrix(j,irxn);
316  }
317 
318  iphDel = m_phaseID[k];
319  kSpecial = k;
320 
321  if (DEBUG_MODE_ENABLED) {
322  if (k != kspec) {
323  sprintf(ANOTE, "Delete component SS phase %lu named %s - SS phases only", iphDel,
324  m_speciesName[k].c_str());
325  } else {
326  sprintf(ANOTE, "Delete this SS phase %lu - SS components only", iphDel);
327  }
328  if (m_debug_print_lvl >= 2) {
329  plogf(" --- %-12.12s", m_speciesName[kspec].c_str());
330  plogf(" %12.4E %12.4E %12.4E | %s\n",
332  m_deltaGRxn_new[irxn], ANOTE);
333  plogf(" --- vcs_RxnStepSizes Special section to set up to delete %s",
334  m_speciesName[k].c_str());
335  plogendl();
336  }
337  }
338  if (k != kspec) {
339  forceComponentCalc = 1;
340  if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
341  plogf(" --- Force a component recalculation \n");
342  plogendl();
343  }
344  }
345  if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
346  plogf(" ");
347  writeline('-', 82);
348  }
349  return iphDel;
350  }
351  }
352  } /* End of regular processing */
353  if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
354  plogf(" --- %-12.12s", m_speciesName[kspec].c_str());
355  plogf(" %12.4E %12.4E %12.4E | %s\n",
357  m_deltaGRxn_new[irxn], ANOTE);
358  }
359  } /* End of loop over m_speciesUnknownType */
360  } /* End of loop over non-component stoichiometric formation reactions */
361  if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) {
362  plogf(" ");
363  writeline('-', 82);
364  }
365  return iphDel;
366 }
367 
369 {
370  int soldel = 0;
371 #ifdef DEBUG_MODE
372  char ANOTE[128];
373  plogf(" ");
374  for (size_t j = 0; j < 77; j++) {
375  plogf("-");
376  }
377  plogf("\n --- Subroutine rxn_adj_cg() called\n");
378  plogf(" --- Species Moles Rxn_Adjustment | Comment\n");
379 #else
380  char* ANOTE = 0;
381 #endif
382 
383  /*
384  * Precalculation loop -> we calculate quantities based on
385  * loops over the number of species.
386  * We also evaluate whether the matrix is appropriate for
387  * this algorithm. If not, we bail out.
388  */
389  for (size_t irxn = 0; irxn < m_numRxnRdc; ++irxn) {
390  if (DEBUG_MODE_ENABLED) {
391  sprintf(ANOTE, "Normal Calc");
392  }
393 
394  size_t kspec = m_indexRxnToSpecies[irxn];
395  if (m_molNumSpecies_old[kspec] == 0.0 && (!m_SSPhase[kspec])) {
396  /* *******************************************************************/
397  /* **** MULTISPECIES PHASE WITH total moles equal to zero ************/
398  /* *******************************************************************/
399  /*
400  * HKM -> the statment below presupposes units in m_deltaGRxn_new[]. It probably
401  * should be replaced with something more relativistic
402  */
403  if (m_deltaGRxn_new[irxn] < -1.0e-4) {
404  if (DEBUG_MODE_ENABLED) {
405  sprintf(ANOTE, "MultSpec: come alive DG = %11.3E", m_deltaGRxn_new[irxn]);
406  }
407  m_deltaMolNumSpecies[kspec] = 1.0e-10;
410  } else {
411  if (DEBUG_MODE_ENABLED) {
412  sprintf(ANOTE, "MultSpec: still dead DG = %11.3E", m_deltaGRxn_new[irxn]);
413  }
414  m_deltaMolNumSpecies[kspec] = 0.0;
415  }
416  } else {
417  /* ********************************************** */
418  /* **** REGULAR PROCESSING ********** */
419  /* ********************************************** */
420  /*
421  * First take care of cases where we want to bail out
422  *
423  *
424  * Don't bother if superconvergence has already been achieved
425  * in this mode.
426  */
427  if (fabs(m_deltaGRxn_new[irxn]) <= m_tolmaj2) {
428  if (DEBUG_MODE_ENABLED) {
429  sprintf(ANOTE, "Skipped: converged DG = %11.3E\n", m_deltaGRxn_new[irxn]);
430  plogf(" --- ");
431  plogf("%-12.12s", m_speciesName[kspec].c_str());
432  plogf(" %12.4E %12.4E | %s\n", m_molNumSpecies_old[kspec],
433  m_deltaMolNumSpecies[kspec], ANOTE);
434  }
435  continue;
436  }
437  /*
438  * Don't calculate for minor or nonexistent species if
439  * their values are to be decreasing anyway.
440  */
441  if (m_speciesStatus[kspec] <= VCS_SPECIES_MINOR && m_deltaGRxn_new[irxn] >= 0.0) {
442  if (DEBUG_MODE_ENABLED) {
443  sprintf(ANOTE, "Skipped: IC = %3d and DG >0: %11.3E\n", m_speciesStatus[kspec], m_deltaGRxn_new[irxn]);
444  plogf(" --- ");
445  plogf("%-12.12s", m_speciesName[kspec].c_str());
446  plogf(" %12.4E %12.4E | %s\n", m_molNumSpecies_old[kspec],
447  m_deltaMolNumSpecies[kspec], ANOTE);
448  }
449  continue;
450  }
451  /*
452  * Start of the regular processing
453  */
454  double s;
455  if (m_SSPhase[kspec]) {
456  s = 0.0;
457  } else {
458  s = 1.0 / m_molNumSpecies_old[kspec];
459  }
460  for (size_t j = 0; j < m_numComponents; ++j) {
461  if (!m_SSPhase[j]) {
462  s += pow(m_stoichCoeffRxnMatrix(j,irxn), 2) / m_molNumSpecies_old[j];
463  }
464  }
465  for (size_t j = 0; j < m_numPhases; j++) {
466  if (!(m_VolPhaseList[j])->m_singleSpecies) {
467  if (m_tPhaseMoles_old[j] > 0.0) {
468  s -= pow(m_deltaMolNumPhase(j,irxn), 2) / m_tPhaseMoles_old[j];
469  }
470  }
471  }
472  if (s != 0.0) {
473  m_deltaMolNumSpecies[kspec] = -m_deltaGRxn_new[irxn] / s;
474  } else {
475  /* ************************************************************ */
476  /* **** REACTION IS ENTIRELY AMONGST SINGLE SPECIES PHASES **** */
477  /* **** DELETE ONE SOLID AND RECOMPUTE BASIS ********* */
478  /* ************************************************************ */
479  /*
480  * Either the species L will disappear or one of the
481  * component single species phases will disappear. The sign
482  * of DG(I) will indicate which way the reaction will go.
483  * Then, we need to follow the reaction to see which species
484  * will zero out first.
485  */
486  size_t k;
487  double dss;
488  if (m_deltaGRxn_new[irxn] > 0.0) {
489  dss = m_molNumSpecies_old[kspec];
490  k = kspec;
491  for (size_t j = 0; j < m_numComponents; ++j) {
492  if (m_stoichCoeffRxnMatrix(j,irxn) > 0.0) {
493  double xx = m_molNumSpecies_old[j] / m_stoichCoeffRxnMatrix(j,irxn);
494  if (xx < dss) {
495  dss = xx;
496  k = j;
497  }
498  }
499  }
500  dss = -dss;
501  } else {
502  dss = 1.0e10;
503  for (size_t j = 0; j < m_numComponents; ++j) {
504  if (m_stoichCoeffRxnMatrix(j,irxn) < 0.0) {
505  double xx = -m_molNumSpecies_old[j] / m_stoichCoeffRxnMatrix(j,irxn);
506  if (xx < dss) {
507  dss = xx;
508  k = j;
509  }
510  }
511  }
512  }
513  /*
514  * Here we adjust the mole fractions
515  * according to DSS and the stoichiometric array
516  * to take into account that we are eliminating
517  * the kth species. DSS contains the amount
518  * of moles of the kth species that needs to be
519  * added back into the component species.
520  */
521  if (dss != 0.0) {
522  m_molNumSpecies_old[kspec] += dss;
523  m_tPhaseMoles_old[m_phaseID[kspec]] += dss;
524  for (size_t j = 0; j < m_numComponents; ++j) {
525  m_molNumSpecies_old[j] += dss * m_stoichCoeffRxnMatrix(j,irxn);
526  m_tPhaseMoles_old[m_phaseID[j]] += dss * m_stoichCoeffRxnMatrix(j,irxn);
527  }
528  m_molNumSpecies_old[k] = 0.0;
529  m_tPhaseMoles_old[m_phaseID[k]] = 0.0;
530  if (DEBUG_MODE_ENABLED) {
531  plogf(" --- vcs_st2 Special section to delete ");
532  plogf("%-12.12s", m_speciesName[k].c_str());
533  plogf("\n --- Immediate return - Restart iteration\n");
534  }
535  /*
536  * We need to immediately recompute the
537  * component basis, because we just zeroed
538  * it out.
539  */
540  if (k != kspec) {
541  soldel = 2;
542  } else {
543  soldel = 1;
544  }
545  return soldel;
546  }
547  }
548  } /* End of regular processing */
549  if (DEBUG_MODE_ENABLED) {
550  plogf(" --- ");
551  plogf("%-12.12s", m_speciesName[kspec].c_str());
552  plogf(" %12.4E %12.4E | %s\n", m_molNumSpecies_old[kspec],
553  m_deltaMolNumSpecies[kspec], ANOTE);
554  }
555  } /* End of loop over non-component stoichiometric formation reactions */
556 
557  /*
558  *
559  * When we form the Hessian we must be careful to ensure that it
560  * is a symmetric positive definite matrix, still. This means zeroing
561  * out columns when we zero out rows as well.
562  * -> I suggest writing a small program to make sure of this
563  * property.
564  */
565 
566  if (DEBUG_MODE_ENABLED) {
567  plogf(" ");
568  for (size_t j = 0; j < 77; j++) {
569  plogf("-");
570  }
571  plogf("\n");
572  }
573  return soldel;
574 }
575 
576 double VCS_SOLVE::vcs_Hessian_diag_adj(size_t irxn, double hessianDiag_Ideal)
577 {
578  double diag = hessianDiag_Ideal;
579  double hessActCoef = vcs_Hessian_actCoeff_diag(irxn);
580  if (hessianDiag_Ideal <= 0.0) {
581  throw CanteraError("VCS_SOLVE::vcs_Hessian_diag_adj",
582  "We shouldn't be here");
583  }
584  if (hessActCoef >= 0.0) {
585  diag += hessActCoef;
586  } else if (fabs(hessActCoef) < 0.6666 * hessianDiag_Ideal) {
587  diag += hessActCoef;
588  } else {
589  diag -= 0.6666 * hessianDiag_Ideal;
590  }
591  return diag;
592 }
593 
595 {
596  size_t kspec = m_indexRxnToSpecies[irxn];
597  size_t kph = m_phaseID[kspec];
598  double np_kspec = std::max(m_tPhaseMoles_old[kph], 1e-13);
599  double* sc_irxn = m_stoichCoeffRxnMatrix.ptrColumn(irxn);
600  /*
601  * First the diagonal term of the Jacobian
602  */
603  double s = m_np_dLnActCoeffdMolNum(kspec,kspec) / np_kspec;
604  /*
605  * Next, the other terms. Note this only a loop over the components
606  * So, it's not too expensive to calculate.
607  */
608  for (size_t l = 0; l < m_numComponents; l++) {
609  if (!m_SSPhase[l]) {
610  for (size_t k = 0; k < m_numComponents; ++k) {
611  if (m_phaseID[k] == m_phaseID[l]) {
612  double np = m_tPhaseMoles_old[m_phaseID[k]];
613  if (np > 0.0) {
614  s += sc_irxn[k] * sc_irxn[l] * m_np_dLnActCoeffdMolNum(l,k) / np;
615  }
616  }
617  }
618  if (kph == m_phaseID[l]) {
619  s += sc_irxn[l] * (m_np_dLnActCoeffdMolNum(l,kspec) + m_np_dLnActCoeffdMolNum(kspec,l)) / np_kspec;
620  }
621 
622  }
623  }
624  return s;
625 }
626 
627 void VCS_SOLVE::vcs_CalcLnActCoeffJac(const double* const moleSpeciesVCS)
628 {
629  /*
630  * Loop over all of the phases in the problem
631  */
632  for (size_t iphase = 0; iphase < m_numPhases; iphase++) {
633  vcs_VolPhase* Vphase = m_VolPhaseList[iphase];
634  /*
635  * We don't need to call single species phases;
636  */
637  if (!Vphase->m_singleSpecies && !Vphase->isIdealSoln()) {
638  /*
639  * update the mole numbers
640  */
641  Vphase->setMolesFromVCS(VCS_STATECALC_OLD, moleSpeciesVCS);
642  /*
643  * Download the resulting calculation into the full vector
644  * -> This scatter calculation is carried out in the
645  * vcs_VolPhase object.
646  */
647  Vphase->sendToVCS_LnActCoeffJac(m_np_dLnActCoeffdMolNum);
648  }
649  }
650 }
651 
652 double VCS_SOLVE::deltaG_Recalc_Rxn(const int stateCalc, const size_t irxn, const double* const molNum, double* const ac,
653  double* const mu_i)
654 {
655  size_t kspec = irxn + m_numComponents;
656  for (size_t iphase = 0; iphase < m_numPhases; iphase++) {
657  if (m_phaseParticipation(iphase,irxn)) {
658  vcs_chemPotPhase(stateCalc, iphase, molNum, ac, mu_i);
659  }
660  }
661  double deltaG = mu_i[kspec];
662  for (size_t k = 0; k < m_numComponents; k++) {
663  deltaG += m_stoichCoeffRxnMatrix(k,irxn) * mu_i[k];
664  }
665  return deltaG;
666 }
667 
668 double VCS_SOLVE::vcs_line_search(const size_t irxn, const double dx_orig, char* const ANOTE)
669 {
670  int its = 0;
671  size_t kspec = m_indexRxnToSpecies[irxn];
672  const int MAXITS = 10;
673  double dx = dx_orig;
674  double* sc_irxn = m_stoichCoeffRxnMatrix.ptrColumn(irxn);
675  double* molNumBase = VCS_DATA_PTR(m_molNumSpecies_old);
676  double* acBase = VCS_DATA_PTR(m_actCoeffSpecies_old);
677  double* ac = VCS_DATA_PTR(m_actCoeffSpecies_new);
678  /*
679  * Calculate the deltaG value at the dx = 0.0 point
680  */
681  vcs_setFlagsVolPhases(false, VCS_STATECALC_OLD);
682  double deltaGOrig = deltaG_Recalc_Rxn(VCS_STATECALC_OLD, irxn, molNumBase, acBase, VCS_DATA_PTR(m_feSpecies_old));
683  double forig = fabs(deltaGOrig) + 1.0E-15;
684  if (deltaGOrig > 0.0) {
685  if (dx_orig > 0.0) {
686  dx = 0.0;
687  if (DEBUG_MODE_ENABLED && ANOTE) {
688  sprintf(ANOTE, "Rxn reduced to zero step size in line search: dx>0 dg > 0");
689  }
690  return dx;
691  }
692  } else if (deltaGOrig < 0.0) {
693  if (dx_orig < 0.0) {
694  dx = 0.0;
695  if (DEBUG_MODE_ENABLED && ANOTE) {
696  sprintf(ANOTE, "Rxn reduced to zero step size in line search: dx<0 dg < 0");
697  }
698  return dx;
699  }
700  } else if (deltaGOrig == 0.0) {
701  return 0.0;
702  }
703  if (dx_orig == 0.0) {
704  return 0.0;
705  }
706 
708  double molSum = molNumBase[kspec];
709  m_molNumSpecies_new[kspec] = molNumBase[kspec] + dx_orig;
710  for (size_t k = 0; k < m_numComponents; k++) {
711  m_molNumSpecies_new[k] = molNumBase[k] + sc_irxn[k] * dx_orig;
712  molSum += molNumBase[k];
713  }
714  vcs_setFlagsVolPhases(false, VCS_STATECALC_NEW);
715 
718 
719  /*
720  * If deltaG hasn't switched signs when going the full distance
721  * then we are heading in the appropriate direction, and
722  * we should accept the current full step size
723  */
724  if (deltaG1 * deltaGOrig > 0.0) {
725  dx = dx_orig;
726  goto finalize;
727  }
728  /*
729  * If we have decreased somewhat, the deltaG return after finding
730  * a better estimate for the line search.
731  */
732  if (fabs(deltaG1) < 0.8 * forig) {
733  if (deltaG1 * deltaGOrig < 0.0) {
734  double slope = (deltaG1 - deltaGOrig) / dx_orig;
735  dx = -deltaGOrig / slope;
736  } else {
737  dx = dx_orig;
738  }
739  goto finalize;
740  }
741 
742  dx = dx_orig;
743 
744  for (its = 0; its < MAXITS; its++) {
745  /*
746  * Calculate the approximation to the total Gibbs free energy at
747  * the dx *= 0.5 point
748  */
749  dx *= 0.5;
750  m_molNumSpecies_new[kspec] = molNumBase[kspec] + dx;
751  for (size_t k = 0; k < m_numComponents; k++) {
752  m_molNumSpecies_new[k] = molNumBase[k] + sc_irxn[k] * dx;
753  }
754  vcs_setFlagsVolPhases(false, VCS_STATECALC_NEW);
757  /*
758  * If deltaG hasn't switched signs when going the full distance
759  * then we are heading in the appropriate direction, and
760  * we should accept the current step
761  */
762  if (deltaG * deltaGOrig > 0.0) {
763  goto finalize;
764  }
765  /*
766  * If we have decreased somewhat, the deltaG return after finding
767  * a better estimate for the line search.
768  */
769  if (fabs(deltaG) / forig < (1.0 - 0.1 * dx / dx_orig)) {
770  if (deltaG * deltaGOrig < 0.0) {
771  double slope = (deltaG - deltaGOrig) / dx;
772  dx = -deltaGOrig / slope;
773  }
774  goto finalize;
775  }
776  }
777 
778 finalize:
779  vcs_setFlagsVolPhases(false, VCS_STATECALC_NEW);
780  if (its >= MAXITS) {
781 #ifdef DEBUG_MODE
782  sprintf(ANOTE, "Rxn reduced to zero step size from %g to %g (MAXITS)", dx_orig, dx);
783  return dx;
784 #endif
785  }
786 #ifdef DEBUG_MODE
787  if (dx != dx_orig) {
788  sprintf(ANOTE, "Line Search reduced step size from %g to %g", dx_orig, dx);
789  }
790 #endif
791 
792  return dx;
793 }
794 
795 }
size_t vcs_RxnStepSizes(int &forceComponentCalc, size_t &kSpecial)
Calculates formation reaction step sizes.
Definition: vcs_rxnadj.cpp:20
std::vector< size_t > m_phaseID
Mapping from the species number to the phase number.
Definition: vcs_solve.h:1832
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:594
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:668
double m_totalMolNum
Total number of kmoles in all phases.
Definition: vcs_solve.h:1702
bool m_singleSpecies
If true, this phase consists of a single species.
Definition: vcs_VolPhase.h:584
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.
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:576
#define VCS_SPECIES_MINOR
Species is a major species.
Definition: vcs_defs.h:135
Array2D m_stoichCoeffRxnMatrix
Stoichiometric coefficient matrix for the reaction mechanism expressed in Reduced Canonical Form...
Definition: vcs_solve.h:1552
int m_useActCoeffJac
Choice of Hessians.
Definition: vcs_solve.h:1963
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
std::vector< double > m_feSpecies_new
Dimensionless new free energy for all the species in the mechanism at the new tentatite T...
Definition: vcs_solve.h:1593
#define VCS_DATA_PTR(vvv)
Points to the data in a std::vector<> object.
Definition: vcs_internal.h:18
std::vector< vcs_VolPhase * > m_VolPhaseList
Array of Phase Structures. Length = number of phases.
Definition: vcs_solve.h:1869
doublereal * ptrColumn(size_t j)
Return a pointer to the top of column j, columns are contiguous in memory.
Definition: Array.h:358
size_t m_numRxnRdc
Current number of non-component species in the problem.
Definition: vcs_solve.h:1519
#define VCS_SMALL_MULTIPHASE_SPECIES
Relative value of multiphase species mole number for a multiphase species which is small...
Definition: vcs_defs.h:63
std::vector< double > m_molNumSpecies_old
Total moles of the species.
Definition: vcs_solve.h:1612
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:182
std::vector< double > m_actCoeffSpecies_new
Molar-based Activity Coefficients for Species.
Definition: vcs_solve.h:1917
#define VCS_DELETE_PHASE_CUTOFF
Cutoff relative moles below which a phase is deleted from the equilibrium problem.
Definition: vcs_defs.h:69
size_t m_numSpeciesTot
Total number of species in the problems.
Definition: vcs_solve.h:1493
std::vector< int > m_speciesUnknownType
Specifies the species unknown type.
Definition: vcs_solve.h:1625
#define VCS_STATECALC_NEW
State Calculation based on the new or tentative mole numbers.
Definition: vcs_defs.h:368
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:99
bool isIdealSoln() const
Returns whether the phase is an ideal solution phase.
std::vector< double > m_tPhaseMoles_old
Total kmols of species in each phase.
Definition: vcs_solve.h:1710
int exists() const
int indicating whether the phase exists or not
int m_debug_print_lvl
Debug printing lvl.
Definition: vcs_solve.h:1995
#define VCS_SPECIES_MAJOR
Species is a major species.
Definition: vcs_defs.h:128
size_t m_numComponents
Number of components calculated for the problem.
Definition: vcs_solve.h:1502
std::vector< double > m_molNumSpecies_new
Tentative value of the mole number vector.
Definition: vcs_solve.h:1644
std::vector< double > m_actCoeffSpecies_old
Molar-based Activity Coefficients for Species based on old mole numbers.
Definition: vcs_solve.h:1924
int vcs_rxn_adj_cg(void)
Calculates reaction adjustments using a full Hessian approximation.
Definition: vcs_rxnadj.cpp:368
#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:202
size_t m_numRxnMinorZeroed
Number of active species which are currently either treated as minor species.
Definition: vcs_solve.h:1523
std::vector< char > m_SSPhase
Boolean indicating whether a species belongs to a single-species phase.
Definition: vcs_solve.h:1836
Phase information and Phase calculations for vcs.
Definition: vcs_VolPhase.h:86
std::vector< std::string > m_speciesName
Species string name for the kth species.
Definition: vcs_solve.h:1839
#define VCS_STATECALC_OLD
State Calculation based on the old or base mole numbers.
Definition: vcs_defs.h:365
Array2D m_deltaMolNumPhase
Change in the number of moles of phase, iphase, due to the noncomponent formation reaction...
Definition: vcs_solve.h:1632
#define plogendl()
define this Cantera function to replace cout << endl;
Definition: vcs_internal.h:31
std::vector< int > m_speciesStatus
Major -Minor status vector for the species in the problem.
Definition: vcs_solve.h:1829
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:652
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:96
std::vector< double > m_deltaMolNumSpecies
Reaction Adjustments for each species during the current step.
Definition: vcs_solve.h:1674
#define plogf
define this Cantera function to replace printf
Definition: vcs_internal.h:24
#define VCS_SPECIES_TYPE_INTERFACIALVOLTAGE
Unknown refers to the voltage level of a phase.
Definition: vcs_defs.h:352
Array2D m_phaseParticipation
This is 1 if the phase, iphase, participates in the formation reaction irxn, and zero otherwise...
Definition: vcs_solve.h:1636
std::vector< size_t > m_indexRxnToSpecies
Mapping between the species index for noncomponent species and the full species index.
Definition: vcs_solve.h:1821
size_t m_numPhases
Number of Phases in the problem.
Definition: vcs_solve.h:1526
double m_tolmaj2
Below this, major species aren't refined any more.
Definition: vcs_solve.h:1764
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:1934
std::vector< double > m_feSpecies_old
Free energy vector from the start of the current iteration.
Definition: vcs_solve.h:1584
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
std::vector< double > m_deltaGRxn_new
Delta G(irxn) for the noncomponent species in the mechanism.
Definition: vcs_solve.h:1654
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:627