Cantera  2.1.2
vcs_setMolesLinProg.cpp
Go to the documentation of this file.
1 /*!
2  * @file vcs_setMolesLinProg.cpp
3  */
4 /*
5  * Copyright (2005) Sandia Corporation. Under the terms of
6  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
7  * U.S. Government retains certain rights in this software.
8  */
9 
14 
15 using namespace std;
16 
17 namespace VCSnonideal
18 {
19 
20 #ifdef DEBUG_MODE
21 static void printProgress(const vector<string> &spName,
22  const vector<double> &soln,
23  const vector<double> &ff)
24 {
25  int nsp = soln.size();
26  double sum = 0.0;
27  plogf(" --- Summary of current progress:\n");
28  plogf(" --- Name Moles - SSGibbs \n");
29  plogf(" -------------------------------------------------------------------------------------\n");
30  for (int k = 0; k < nsp; k++) {
31  plogf(" --- %20s %12.4g - %12.4g\n", spName[k].c_str(), soln[k], ff[k]);
32  sum += soln[k] * ff[k];
33  }
34  plogf(" --- Total sum to be minimized = %g\n", sum);
35 }
36 #endif
37 
38 int VCS_SOLVE::vcs_setMolesLinProg()
39 {
40  size_t ik, irxn;
41  double test = -1.0E-10;
42 
43 #ifdef DEBUG_MODE
44  std::string pprefix(" --- seMolesLinProg ");
45  if (m_debug_print_lvl >= 2) {
46  plogf(" --- call setInitialMoles\n");
47  }
48 #endif
49 
50 
51  // m_mu are standard state chemical potentials
52  // Boolean on the end specifies standard chem potentials
53  // m_mix->getValidChemPotentials(not_mu, DATA_PTR(m_mu), true);
54  // -> This is already done coming into the routine.
55  double dg_rt;
56 
57  int idir;
58  double nu;
59  double delta_xi, dxi_min = 1.0e10;
60  bool redo = true;
61  int retn;
62  int iter = 0;
63  bool abundancesOK = true;
64  bool usedZeroedSpecies;
65 
66  std::vector<double> sm(m_numElemConstraints*m_numElemConstraints, 0.0);
67  std::vector<double> ss(m_numElemConstraints, 0.0);
68  std::vector<double> sa(m_numElemConstraints, 0.0);
69  std::vector<double> wx(m_numElemConstraints, 0.0);
70  std::vector<double> aw(m_numSpeciesTot, 0.0);
71 
72  for (ik = 0; ik < m_numSpeciesTot; ik++) {
73  if (m_speciesUnknownType[ik] != VCS_SPECIES_INTERFACIALVOLTAGE) {
74  m_molNumSpecies_old[ik] = max(0.0, m_molNumSpecies_old[ik]);
75  }
76  }
77 
78 #ifdef DEBUG_MODE
79  if (m_debug_print_lvl >= 2) {
80  printProgress(m_speciesName, m_molNumSpecies_old, m_SSfeSpecies);
81  }
82 #endif
83 
84  while (redo) {
85 
86  if (!vcs_elabcheck(0)) {
87 #ifdef DEBUG_MODE
88  if (m_debug_print_lvl >= 2) {
89  plogf("%s Mole numbers failing element abundances\n", pprefix.c_str());
90  plogf("%sCall vcs_elcorr to attempt fix\n", pprefix.c_str());
91  }
92 #endif
93  retn = vcs_elcorr(VCS_DATA_PTR(sm), VCS_DATA_PTR(wx));
94  if (retn >= 2) {
95  abundancesOK = false;
96  } else {
97  abundancesOK = true;
98  }
99  } else {
100  abundancesOK = true;
101  }
102  /*
103  * Now find the optimized basis that spans the stoichiometric
104  * coefficient matrix, based on the current composition, m_molNumSpecies_old[]
105  * We also calculate sc[][], the reaction matrix.
106  */
107  retn = vcs_basopt(false, VCS_DATA_PTR(aw), VCS_DATA_PTR(sa),
108  VCS_DATA_PTR(sm), VCS_DATA_PTR(ss),
109  test, &usedZeroedSpecies);
110  if (retn != VCS_SUCCESS) {
111  return retn;
112  }
113 
114 #ifdef DEBUG_MODE
115  if (m_debug_print_lvl >= 2) {
116  plogf("iteration %d\n", iter);
117  }
118 #endif
119  redo = false;
120  iter++;
121  if (iter > 15) {
122  break;
123  }
124 
125  // loop over all reactions
126  for (irxn = 0; irxn < m_numRxnTot; irxn++) {
127 
128  // dg_rt is the Delta_G / RT value for the reaction
129  ik = m_numComponents + irxn;
130  dg_rt = m_SSfeSpecies[ik];
131  dxi_min = 1.0e10;
132  const double* sc_irxn = m_stoichCoeffRxnMatrix[irxn];
133  for (size_t jcomp = 0; jcomp < m_numElemConstraints; jcomp++) {
134  dg_rt += m_SSfeSpecies[jcomp] * sc_irxn[jcomp];
135  }
136  // fwd or rev direction.
137  // idir > 0 implies increasing the current species
138  // idir < 0 implies decreasing the current species
139  idir = (dg_rt < 0.0 ? 1 : -1);
140  if (idir < 0) {
141  dxi_min = m_molNumSpecies_old[ik];
142  }
143 
144  for (size_t jcomp = 0; jcomp < m_numComponents; jcomp++) {
145  nu = sc_irxn[jcomp];
146 
147  // set max change in progress variable by
148  // non-negativity requirement
149  if (nu*idir < 0) {
150  delta_xi = fabs(m_molNumSpecies_old[jcomp]/nu);
151  // if a component has nearly zero moles, redo
152  // with a new set of components
153  if (!redo) {
154  if (delta_xi < 1.0e-10 && (m_molNumSpecies_old[ik] >= 1.0E-10)) {
155 #ifdef DEBUG_MODE
156  if (m_debug_print_lvl >= 2) {
157  plogf(" --- Component too small: %s\n", m_speciesName[jcomp].c_str());
158  }
159 #endif
160  redo = true;
161  }
162  }
163  if (delta_xi < dxi_min) {
164  dxi_min = delta_xi;
165  }
166  }
167  }
168 
169  // step the composition by dxi_min, check against zero, since
170  // we are zeroing components and species on every step.
171  // Redo the iteration, if a component went from positive to zero on this step.
172  double dsLocal = idir*dxi_min;
173  m_molNumSpecies_old[ik] += dsLocal;
174  m_molNumSpecies_old[ik] = max(0.0, m_molNumSpecies_old[ik]);
175  for (size_t jcomp = 0; jcomp < m_numComponents; jcomp++) {
176  bool full = false;
177  if (m_molNumSpecies_old[jcomp] > 1.0E-15) {
178  full = true;
179  }
180  m_molNumSpecies_old[jcomp] += sc_irxn[jcomp] * dsLocal;
181  m_molNumSpecies_old[jcomp] = max(0.0, m_molNumSpecies_old[jcomp]);
182  if (full) {
183  if (m_molNumSpecies_old[jcomp] < 1.0E-60) {
184  redo = true;
185  }
186  }
187  }
188  }
189 
190  // set the moles of the phase objects to match
191  // updateMixMoles();
192  // Update the phase objects with the contents of the m_molNumSpecies_old vector
193  // vcs_updateVP(0);
194 #ifdef DEBUG_MODE
195  if (m_debug_print_lvl >= 2) {
196  printProgress(m_speciesName, m_molNumSpecies_old, m_SSfeSpecies);
197  }
198 #endif
199  }
200 
201 #ifdef DEBUG_MODE
202  if (m_debug_print_lvl == 1) {
203  printProgress(m_speciesName, m_molNumSpecies_old, m_SSfeSpecies);
204  plogf(" --- setInitialMoles end\n");
205  }
206 #endif
207  retn = 0;
208  if (!abundancesOK) {
209  retn = -1;
210  } else if (iter > 15) {
211  retn = 1;
212  }
213  return retn;
214 }
215 
216 }
#define VCS_DATA_PTR(vvv)
Points to the data in a std::vector<> object.
Definition: vcs_internal.h:24
#define VCS_SPECIES_INTERFACIALVOLTAGE
Species refers to an electron in the metal.
Definition: vcs_defs.h:189
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.
Internal declarations for the VCSnonideal package.
#define VCS_SUCCESS
Definition: vcs_defs.h:37
#define plogf
define this Cantera function to replace printf
Definition: vcs_internal.h:30