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