Cantera  2.0
vcs_nondim.cpp
Go to the documentation of this file.
1 /**
2  * @file vcs_nondim.cpp
3  * Nondimensionalization routines within VCSnonideal
4  */
5 /*
6  * Copyright (2007) 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 
15 #include "vcs_Exception.h"
16 
17 #include <cstdio>
18 #include <cstdlib>
19 #include <cmath>
20 
21 namespace VCSnonideal
22 {
23 
24 // Returns the multiplier for electric charge terms
25 /*
26  * This is basically equal to F/RT
27  *
28  * @param mu_units integer representing the dimensional units system
29  * @param TKelvin double Temperature in Kelvin
30  *
31  * @return Returns the value of F/RT
32  */
33 double VCS_SOLVE::vcs_nondim_Farad(int mu_units, double TKelvin) const
34 {
35  double Farad;
36  if (TKelvin <= 0.0) {
37  TKelvin = 293.15;
38  }
39  switch (mu_units) {
40  case VCS_UNITS_MKS:
41  case VCS_UNITS_KJMOL:
42  case VCS_UNITS_KCALMOL:
43  Farad = Cantera::ElectronCharge * Cantera::Avogadro /
44  (TKelvin * Cantera::GasConstant);
45  break;
46  case VCS_UNITS_UNITLESS:
47  Farad = Cantera::ElectronCharge * Cantera::Avogadro;
48  break;
49  case VCS_UNITS_KELVIN:
50  Farad = Cantera::ElectronCharge * Cantera::Avogadro/ TKelvin;
51  break;
52  default:
53  plogf("vcs_nondim_Farad error: unknown units: %d\n", mu_units);
54  plogendl();
55  exit(EXIT_FAILURE);
56  }
57  return Farad;
58 }
59 
60 // Returns the multiplier for the nondimensionalization of the equations
61 /*
62  * This is basically equal to RT
63  *
64  * @param mu_units integer representing the dimensional units system
65  * @param TKelvin double Temperature in Kelvin
66  *
67  * @return Returns the value of RT
68  */
69 double VCS_SOLVE::vcs_nondimMult_TP(int mu_units, double TKelvin) const
70 {
71  double rt;
72  if (TKelvin <= 0.0) {
73  TKelvin = 293.15;
74  }
75  switch (mu_units) {
76  case VCS_UNITS_KCALMOL:
77  rt = TKelvin * Cantera::GasConst_cal_mol_K * 1e-3;
78  break;
79  case VCS_UNITS_UNITLESS:
80  rt = 1.0;
81  break;
82  case VCS_UNITS_KJMOL:
83  rt = TKelvin * Cantera::GasConstant * 1e-6;
84  break;
85  case VCS_UNITS_KELVIN:
86  rt = TKelvin;
87  break;
88  case VCS_UNITS_MKS:
89  rt = TKelvin * Cantera::GasConstant;
90  break;
91  default:
92  plogf("vcs_nondimMult_TP error: unknown units: %d\n", mu_units);
93  plogendl();
94  exit(EXIT_FAILURE);
95  }
96  return rt;
97 }
98 
99 // Nondimensionalize the problem data
100 /*
101  * Nondimensionalize the free energies using the divisor, R * T
102  *
103  * Essentially the internal data can either be in dimensional form
104  * or in nondimensional form. This routine switches the data from
105  * dimensional form into nondimensional form.
106  *
107  * What we do is to divide by RT.
108  *
109  * @todo Add a scale factor based on the total mole numbers.
110  * The algorithm contains hard coded numbers based on the
111  * total mole number. If we ever were faced with a problem
112  * with significantly different total kmol numbers than one
113  * the algorithm would have problems.
114  */
116 {
117  double tf;
121  for (size_t i = 0; i < m_numSpeciesTot; ++i) {
122  /*
123  * Modify the standard state and total chemical potential data,
124  * FF(I), to make it dimensionless, i.e., mu / RT.
125  * Thus, we may divide it by the temperature.
126  */
127  m_SSfeSpecies[i] *= tf;
128  m_deltaGRxn_new[i] *= tf;
129  m_deltaGRxn_old[i] *= tf;
130  m_feSpecies_old[i] *= tf;
131  }
132 
134 
135  /*
136  * Scale the total moles if necessary:
137  * First find out the total moles
138  */
139  double tmole_orig = vcs_tmoles();
140 
141  /*
142  * Then add in the total moles of elements that are goals. Either one
143  * or the other is specified here.
144  */
145  double esum = 0.0;
146  for (size_t i = 0; i < m_numElemConstraints; ++i) {
147  if (m_elType[i] == VCS_ELEM_TYPE_ABSPOS) {
148  esum += fabs(m_elemAbundancesGoal[i]);
149  }
150  }
151  tmole_orig += esum;
152 
153  /*
154  * Ok now test out the bounds on the total moles that this program can
155  * handle. These are a bit arbitrary. However, it would seem that any
156  * reasonable input would be between these two numbers below.
157  */
158  if (tmole_orig < 1.0E-200 || tmole_orig > 1.0E200) {
159  plogf(" VCS_SOLVE::vcs_nondim_TP ERROR: Total input moles , %g, is outside the range handled by vcs. exit",
160  tmole_orig);
161  plogendl();
162  throw vcsError("VCS_SOLVE::vcs_nondim_TP", " Total input moles ," + Cantera::fp2str(tmole_orig) +
163  "is outside the range handled by vcs.\n");
164  }
165 
166  // Determine the scale of the problem
167  if (tmole_orig > 1.0E4) {
168  m_totalMoleScale = tmole_orig / 1.0E4;
169  } else if (tmole_orig < 1.0E-4) {
170  m_totalMoleScale = tmole_orig / 1.0E-4;
171  } else {
172  m_totalMoleScale = 1.0;
173  }
174 
175  if (m_totalMoleScale != 1.0) {
176  if (m_VCS_UnitsFormat == VCS_UNITS_MKS) {
177 #ifdef DEBUG_MODE
178  if (m_debug_print_lvl >= 2) {
179  plogf(" --- vcs_nondim_TP() called: USING A MOLE SCALE OF %g until further notice", m_totalMoleScale);
180  plogendl();
181  }
182 #endif
183  for (size_t i = 0; i < m_numSpeciesTot; ++i) {
186  }
187  }
188  for (size_t i = 0; i < m_numElemConstraints; ++i) {
190  }
191 
192  for (size_t iph = 0; iph < m_numPhases; iph++) {
193  TPhInertMoles[iph] *= (1.0 / m_totalMoleScale);
194  if (TPhInertMoles[iph] != 0.0) {
195  vcs_VolPhase* vphase = m_VolPhaseList[iph];
196  vphase->setTotalMolesInert(TPhInertMoles[iph]);
197  }
198  }
199  }
200  vcs_tmoles();
201  }
202  }
203 }
204 
205 // Redimensionalize the problem data
206 /*
207  * Redimensionalize the free energies using the multiplier R * T
208  *
209  * Essentially the internal data can either be in dimensional form
210  * or in nondimensional form. This routine switches the data from
211  * nondimensional form into dimensional form.
212  *
213  * What we do is to multiply by RT.
214  */
216 {
217  double tf;
221  for (size_t i = 0; i < m_numSpeciesTot; ++i) {
222  /*
223  * Modify the standard state and total chemical potential data,
224  * FF(I), to make it have units, i.e. mu = RT * mu_star
225  */
226  m_SSfeSpecies[i] *= tf;
227  m_deltaGRxn_new[i] *= tf;
228  m_deltaGRxn_old[i] *= tf;
229  m_feSpecies_old[i] *= tf;
230  }
231  m_Faraday_dim *= tf;
232  }
233  if (m_totalMoleScale != 1.0) {
234  if (m_VCS_UnitsFormat == VCS_UNITS_MKS) {
235 #ifdef DEBUG_MODE
236  if (m_debug_print_lvl >= 2) {
237  plogf(" --- vcs_redim_TP() called: getting rid of mole scale of %g", m_totalMoleScale);
238  plogendl();
239  }
240 #endif
241  for (size_t i = 0; i < m_numSpeciesTot; ++i) {
244  }
245  }
246  for (size_t i = 0; i < m_numElemConstraints; ++i) {
248  }
249 
250  for (size_t iph = 0; iph < m_numPhases; iph++) {
252  if (TPhInertMoles[iph] != 0.0) {
253  vcs_VolPhase* vphase = m_VolPhaseList[iph];
254  vphase->setTotalMolesInert(TPhInertMoles[iph]);
255  }
256  }
257  vcs_tmoles();
258  }
259  }
260 }
261 
262 // Computes the current elemental abundances vector
263 /*
264  * Computes the elemental abundances vector, m_elemAbundances[], and stores it
265  * back into the global structure
266  */
267 void VCS_SOLVE::vcs_printChemPotUnits(int unitsFormat) const
268 {
269  switch (unitsFormat) {
270  case VCS_UNITS_KCALMOL:
271  plogf("kcal/gmol");
272  break;
273  case VCS_UNITS_UNITLESS:
274  plogf("dimensionless");
275  break;
276  case VCS_UNITS_KJMOL:
277  plogf("kJ/gmol");
278  break;
279  case VCS_UNITS_KELVIN:
280  plogf("Kelvin");
281  break;
282  case VCS_UNITS_MKS:
283  plogf("J/kmol");
284  break;
285  default:
286  plogf("unknown units!");
287  exit(EXIT_FAILURE);
288  }
289 }
290 
291 }
292