Cantera  2.1.2
vcs_MultiPhaseEquil.cpp
Go to the documentation of this file.
1 /**
2  * @file vcs_MultiPhaseEquil.cpp
3  * Driver routine for the VCSnonideal equilibrium solver package
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 
12 #include "cantera/equil/vcs_prob.h"
16 
18 
20 #include "cantera/base/clockWC.h"
27 
28 #include <cstdio>
29 
30 using namespace Cantera;
31 using namespace std;
32 
33 namespace VCSnonideal
34 {
35 vcs_MultiPhaseEquil::vcs_MultiPhaseEquil() :
36  m_vprob(0),
37  m_mix(0),
38  m_printLvl(0),
39  m_vsolvePtr(0)
40 {
41 }
42 
43 vcs_MultiPhaseEquil::vcs_MultiPhaseEquil(Cantera::MultiPhase* mix, int printLvl) :
44  m_vprob(0),
45  m_mix(0),
46  m_printLvl(printLvl),
47  m_vsolvePtr(0)
48 {
49  /*
50  * Create a VCS_PROB object that describes the equilibrium problem.
51  * The constructor just mallocs the necessary objects and sizes them.
52  */
53  m_vprob = new VCS_PROB(mix->nSpecies(),
54  mix->nElements(),
55  mix->nPhases());
56  m_mix = mix;
58  /*
59  * Work out the details of the VCS_VPROB construction and
60  * Transfer the current problem to VCS_PROB object
61  */
62  int res = vcs_Cantera_to_vprob(mix, m_vprob);
63  if (res != 0) {
64  plogf("problems\n");
65  }
66 }
67 
68 vcs_MultiPhaseEquil::~vcs_MultiPhaseEquil()
69 {
70  delete m_vprob;
71  m_vprob = 0;
72  if (m_vsolvePtr) {
73  delete m_vsolvePtr;
74  m_vsolvePtr = 0;
75  }
76 }
77 
78 int vcs_MultiPhaseEquil::equilibrate_TV(int XY, doublereal xtarget,
79  int estimateEquil,
80  int printLvl, doublereal err,
81  int maxsteps, int loglevel)
82 {
83  addLogEntry("problem type","fixed T, V");
84  // doublereal dt = 1.0e3;
85  doublereal Vtarget = m_mix->volume();
86  doublereal dVdP;
87  if ((XY != TV) && (XY != HV) && (XY != UV) && (XY != SV)) {
88  throw CanteraError("vcs_MultiPhaseEquil::equilibrate_TV",
89  "Wrong XY flag:" + int2str(XY));
90  }
91  int maxiter = 100;
92  int iSuccess = 0;
93  int innerXY;
94  double Pnow;
95  if (XY == TV) {
96  m_mix->setTemperature(xtarget);
97  }
98  double Pnew;
99  int strt = estimateEquil;
100  double P1 = 0.0;
101  double V1 = 0.0;
102  double V2 = 0.0;
103  double P2 = 0.0;
104  doublereal Tlow = 0.5 * m_mix->minTemp();
105  doublereal Thigh = 2.0 * m_mix->maxTemp();
106  doublereal Vnow, Verr;
107  int printLvlSub = std::max(0, printLvl - 1);
108  for (int n = 0; n < maxiter; n++) {
109  Pnow = m_mix->pressure();
110 
111  beginLogGroup("iteration "+int2str(n));
112  switch (XY) {
113  case TV:
114  iSuccess = equilibrate_TP(strt, printLvlSub, err, maxsteps, loglevel);
115  break;
116  case HV:
117  innerXY = HP;
118  iSuccess = equilibrate_HP(xtarget, innerXY, Tlow, Thigh, strt,
119  printLvlSub, err, maxsteps, loglevel);
120  break;
121  case UV:
122  innerXY = UP;
123  iSuccess = equilibrate_HP(xtarget, innerXY, Tlow, Thigh, strt,
124  printLvlSub, err, maxsteps, loglevel);
125  break;
126  case SV:
127  innerXY = SP;
128  iSuccess = equilibrate_SP(xtarget, Tlow, Thigh, strt,
129  printLvlSub, err, maxsteps, loglevel);
130  break;
131  default:
132  break;
133  }
134  strt = false;
135  Vnow = m_mix->volume();
136  if (n == 0) {
137  V2 = Vnow;
138  P2 = Pnow;
139  } else if (n == 1) {
140  V1 = Vnow;
141  P1 = Pnow;
142  } else {
143  P2 = P1;
144  V2 = V1;
145  P1 = Pnow;
146  V1 = Vnow;
147  }
148 
149  Verr = fabs((Vtarget - Vnow)/Vtarget);
150  addLogEntry("P",fp2str(Pnow));
151  addLogEntry("V rel error",fp2str(Verr));
152  endLogGroup();
153 
154  if (Verr < err) {
155  addLogEntry("P iterations",int2str(n));
156  addLogEntry("Final P",fp2str(Pnow));
157  addLogEntry("V rel error",fp2str(Verr));
158  goto done;
159  }
160  // find dV/dP
161  if (n > 1) {
162  dVdP = (V2 - V1) / (P2 - P1);
163  if (dVdP == 0.0) {
164  throw CanteraError("vcs_MultiPhase::equilibrate_TV",
165  "dVdP == 0.0");
166  } else {
167  Pnew = Pnow + (Vtarget - Vnow) / dVdP;
168  if (Pnew < 0.2 * Pnow) {
169  Pnew = 0.2 * Pnow;
170  }
171  if (Pnew > 3.0 * Pnow) {
172  Pnew = 3.0 * Pnow;
173  }
174  }
175 
176  } else {
177  m_mix->setPressure(Pnow*1.01);
178  dVdP = (m_mix->volume() - Vnow)/(0.01*Pnow);
179  Pnew = Pnow + 0.5*(Vtarget - Vnow)/dVdP;
180  if (Pnew < 0.5* Pnow) {
181  Pnew = 0.5 * Pnow;
182  }
183  if (Pnew > 1.7 * Pnow) {
184  Pnew = 1.7 * Pnow;
185  }
186 
187  }
188  m_mix->setPressure(Pnew);
189  }
190  throw CanteraError("vcs_MultiPhase::equilibrate_TV",
191  "No convergence for V");
192 
193 done:
194  ;
195  return iSuccess;
196 }
197 
198 int vcs_MultiPhaseEquil::equilibrate_HP(doublereal Htarget,
199  int XY, double Tlow, double Thigh,
200  int estimateEquil,
201  int printLvl, doublereal err,
202  int maxsteps, int loglevel)
203 {
204  int maxiter = 100;
205  int iSuccess;
206  if (XY != HP && XY != UP) {
207  throw CanteraError("vcs_MultiPhaseEquil::equilibrate_HP",
208  "Wrong XP" + XY);
209  }
210  int strt = estimateEquil;
211 
212  // Lower bound on T. This will change as we progress in the calculation
213  if (Tlow <= 0.0) {
214  Tlow = 0.5 * m_mix->minTemp();
215  }
216  // Upper bound on T. This will change as we progress in the calculation
217  if (Thigh <= 0.0 || Thigh > 1.0E6) {
218  Thigh = 2.0 * m_mix->maxTemp();
219  }
220  addLogEntry("problem type","fixed H,P");
221  addLogEntry("H target",fp2str(Htarget));
222 
223  doublereal cpb = 1.0, dT, dTa, dTmax, Tnew;
224  doublereal Hnow;
225  doublereal Hlow = Undef;
226  doublereal Hhigh = Undef;
227  doublereal Herr, HConvErr;
228  doublereal Tnow = m_mix->temperature();
229  int printLvlSub = std::max(printLvl - 1, 0);
230 
231  for (int n = 0; n < maxiter; n++) {
232 
233 
234  // start with a loose error tolerance, but tighten it as we get
235  // close to the final temperature
236  beginLogGroup("iteration "+int2str(n));
237 
238  try {
239  Tnow = m_mix->temperature();
240  iSuccess = equilibrate_TP(strt, printLvlSub, err, maxsteps, loglevel);
241  strt = 0;
242  if (XY == UP) {
243  Hnow = m_mix->IntEnergy();
244  } else {
245  Hnow = m_mix->enthalpy();
246  }
247  double pmoles[10];
248  pmoles[0] = m_mix->phaseMoles(0);
249  double Tmoles = pmoles[0];
250  double HperMole = Hnow/Tmoles;
251  if (printLvl > 0) {
252  plogf("T = %g, Hnow = %g ,Tmoles = %g, HperMole = %g",
253  Tnow, Hnow, Tmoles, HperMole);
254  plogendl();
255  }
256 
257  // the equilibrium enthalpy monotonically increases with T;
258  // if the current value is below the target, then we know the
259  // current temperature is too low. Set the lower bounds.
260 
261 
262  if (Hnow < Htarget) {
263  if (Tnow > Tlow) {
264  Tlow = Tnow;
265  Hlow = Hnow;
266  }
267  }
268  // the current enthalpy is greater than the target; therefore the
269  // current temperature is too high. Set the high bounds.
270  else {
271  if (Tnow < Thigh) {
272  Thigh = Tnow;
273  Hhigh = Hnow;
274  }
275  }
276  if (Hlow != Undef && Hhigh != Undef) {
277  cpb = (Hhigh - Hlow)/(Thigh - Tlow);
278  dT = (Htarget - Hnow)/cpb;
279  dTa = fabs(dT);
280  dTmax = 0.5*fabs(Thigh - Tlow);
281  if (dTa > dTmax) {
282  dT *= dTmax/dTa;
283  }
284  } else {
285  Tnew = sqrt(Tlow*Thigh);
286  dT = Tnew - Tnow;
287  if (dT < -200.) {
288  dT = -200;
289  }
290  if (dT > 200.) {
291  dT = 200.;
292  }
293  }
294  double acpb = std::max(fabs(cpb), 1.0E-6);
295  double denom = std::max(fabs(Htarget), acpb);
296  Herr = Htarget - Hnow;
297  HConvErr = fabs((Herr)/denom);
299  addLogEntry("H",fp2str(Hnow));
300  addLogEntry("Herr",fp2str(Herr));
301  addLogEntry("H rel error",fp2str(HConvErr));
302  addLogEntry("lower T bound",fp2str(Tlow));
303  addLogEntry("upper T bound",fp2str(Thigh));
304  endLogGroup(); // iteration
305  if (printLvl > 0) {
306  plogf(" equilibrate_HP: It = %d, Tcurr = %g Hcurr = %g, Htarget = %g\n",
307  n, Tnow, Hnow, Htarget);
308  plogf(" H rel error = %g, cp = %g, HConvErr = %g\n",
309  Herr, cpb, HConvErr);
310  }
311 
312  if (HConvErr < err) { // || dTa < 1.0e-4) {
313  addLogEntry("T iterations",int2str(n));
314  addLogEntry("Final T",fp2str(m_mix->temperature()));
315  addLogEntry("H rel error",fp2str(Herr));
316  if (printLvl > 0) {
317  plogf(" equilibrate_HP: CONVERGENCE: Hfinal = %g Tfinal = %g, Its = %d \n",
318  Hnow, Tnow, n);
319  plogf(" H rel error = %g, cp = %g, HConvErr = %g\n",
320  Herr, cpb, HConvErr);
321  }
322  goto done;
323  }
324  Tnew = Tnow + dT;
325  if (Tnew < 0.0) {
326  Tnew = 0.5*Tnow;
327  }
328  m_mix->setTemperature(Tnew);
329 
330  } catch (CanteraError err) {
331  if (!estimateEquil) {
332  addLogEntry("no convergence",
333  "try estimating composition at the start");
334  strt = -1;
335  } else {
336  Tnew = 0.5*(Tnow + Thigh);
337  if (fabs(Tnew - Tnow) < 1.0) {
338  Tnew = Tnow + 1.0;
339  }
340  m_mix->setTemperature(Tnew);
341  addLogEntry("no convergence",
342  "trying T = "+fp2str(Tnow));
343  }
344  endLogGroup();
345  }
346 
347  }
348  addLogEntry("reached max number of T iterations",int2str(maxiter));
349  endLogGroup();
350  throw CanteraError("MultiPhase::equilibrate_HP",
351  "No convergence for T");
352 done:
353  ;
354  return iSuccess;
355 }
356 
357 int vcs_MultiPhaseEquil::equilibrate_SP(doublereal Starget,
358  double Tlow, double Thigh,
359  int estimateEquil,
360  int printLvl, doublereal err,
361  int maxsteps, int loglevel)
362 {
363  int maxiter = 100;
364  int strt = estimateEquil;
365 
366  // Lower bound on T. This will change as we progress in the calculation
367  if (Tlow <= 0.0) {
368  Tlow = 0.5 * m_mix->minTemp();
369  }
370  // Upper bound on T. This will change as we progress in the calculation
371  if (Thigh <= 0.0 || Thigh > 1.0E6) {
372  Thigh = 2.0 * m_mix->maxTemp();
373  }
374  addLogEntry("problem type","fixed S,P");
375  addLogEntry("S target",fp2str(Starget));
376 
377  doublereal cpb = 1.0, dT, dTa, dTmax, Tnew;
378  doublereal Snow;
379  doublereal Slow = Undef;
380  doublereal Shigh = Undef;
381  doublereal Serr, SConvErr;
382  doublereal Tnow = m_mix->temperature();
383  if (Tnow < Tlow) {
384  Tlow = Tnow;
385  }
386  if (Tnow > Thigh) {
387  Thigh = Tnow;
388  }
389  int printLvlSub = std::max(printLvl - 1, 0);
390 
391  for (int n = 0; n < maxiter; n++) {
392 
393  // start with a loose error tolerance, but tighten it as we get
394  // close to the final temperature
395  beginLogGroup("iteration "+int2str(n));
396 
397  try {
398  Tnow = m_mix->temperature();
399  int iSuccess = equilibrate_TP(strt, printLvlSub, err, maxsteps, loglevel);
400  strt = 0;
401  Snow = m_mix->entropy();
402  double pmoles[10];
403  pmoles[0] = m_mix->phaseMoles(0);
404  double Tmoles = pmoles[0];
405  double SperMole = Snow/Tmoles;
406  plogf("T = %g, Snow = %g ,Tmoles = %g, SperMole = %g\n",
407  Tnow, Snow, Tmoles, SperMole);
408 
409  // the equilibrium entropy monotonically increases with T;
410  // if the current value is below the target, then we know the
411  // current temperature is too low. Set the lower bounds to the
412  // current condition.
413  if (Snow < Starget) {
414  if (Tnow > Tlow) {
415  Tlow = Tnow;
416  Slow = Snow;
417  } else {
418  if (Slow > Starget) {
419  if (Snow < Slow) {
420  Thigh = Tlow;
421  Shigh = Slow;
422  Tlow = Tnow;
423  Slow = Snow;
424  }
425  }
426  }
427  }
428  // the current enthalpy is greater than the target; therefore the
429  // current temperature is too high. Set the high bounds.
430  else {
431  if (Tnow < Thigh) {
432  Thigh = Tnow;
433  Shigh = Snow;
434  }
435  }
436  if (Slow != Undef && Shigh != Undef) {
437  cpb = (Shigh - Slow)/(Thigh - Tlow);
438  dT = (Starget - Snow)/cpb;
439  Tnew = Tnow + dT;
440  dTa = fabs(dT);
441  dTmax = 0.5*fabs(Thigh - Tlow);
442  if (Tnew > Thigh || Tnew < Tlow) {
443  dTmax = 1.5*fabs(Thigh - Tlow);
444  }
445  dTmax = std::min(dTmax, 300.);
446  if (dTa > dTmax) {
447  dT *= dTmax/dTa;
448  }
449  } else {
450  Tnew = sqrt(Tlow*Thigh);
451  dT = Tnew - Tnow;
452  }
453 
454  double acpb = std::max(fabs(cpb), 1.0E-6);
455  double denom = std::max(fabs(Starget), acpb);
456  Serr = Starget - Snow;
457  SConvErr = fabs((Serr)/denom);
459  addLogEntry("S",fp2str(Snow));
460  addLogEntry("Serr",fp2str(Serr));
461  addLogEntry("S rel error",fp2str(SConvErr));
462  addLogEntry("lower T bound",fp2str(Tlow));
463  addLogEntry("upper T bound",fp2str(Thigh));
464  endLogGroup(); // iteration
465  if (printLvl > 0) {
466  plogf(" equilibrate_SP: It = %d, Tcurr = %g Scurr = %g, Starget = %g\n",
467  n, Tnow, Snow, Starget);
468  plogf(" S rel error = %g, cp = %g, SConvErr = %g\n",
469  Serr, cpb, SConvErr);
470  }
471 
472  if (SConvErr < err) { // || dTa < 1.0e-4) {
473  addLogEntry("T iterations",int2str(n));
474  addLogEntry("Final T",fp2str(m_mix->temperature()));
475  addLogEntry("S rel error",fp2str(Serr));
476  if (printLvl > 0) {
477  plogf(" equilibrate_SP: CONVERGENCE: Sfinal = %g Tfinal = %g, Its = %d \n",
478  Snow, Tnow, n);
479  plogf(" S rel error = %g, cp = %g, HConvErr = %g\n",
480  Serr, cpb, SConvErr);
481  }
482  return iSuccess;
483  }
484  Tnew = Tnow + dT;
485  if (Tnew < 0.0) {
486  Tnew = 0.5*Tnow;
487  }
488  m_mix->setTemperature(Tnew);
489 
490  } catch (CanteraError err) {
491  if (!estimateEquil) {
492  addLogEntry("no convergence",
493  "try estimating composition at the start");
494  strt = -1;
495  } else {
496  Tnew = 0.5*(Tnow + Thigh);
497  if (fabs(Tnew - Tnow) < 1.0) {
498  Tnew = Tnow + 1.0;
499  }
500  m_mix->setTemperature(Tnew);
501  addLogEntry("no convergence",
502  "trying T = "+fp2str(Tnow));
503  }
504  endLogGroup();
505  }
506 
507  }
508  addLogEntry("reached max number of T iterations",int2str(maxiter));
509  endLogGroup();
510  throw CanteraError("MultiPhase::equilibrate_SP",
511  "No convergence for T");
512 }
513 
514 int vcs_MultiPhaseEquil::equilibrate(int XY, int estimateEquil,
515  int printLvl, doublereal err,
516  int maxsteps, int loglevel)
517 {
518  int iSuccess;
519  doublereal xtarget;
520  if (XY == TP) {
521  iSuccess = equilibrate_TP(estimateEquil, printLvl, err, maxsteps, loglevel);
522  } else if (XY == HP || XY == UP) {
523  if (XY == HP) {
524  xtarget = m_mix->enthalpy();
525  } else {
526  xtarget = m_mix->IntEnergy();
527  }
528  double Tlow = 0.5 * m_mix->minTemp();
529  double Thigh = 2.0 * m_mix->maxTemp();
530  iSuccess = equilibrate_HP(xtarget, XY, Tlow, Thigh,
531  estimateEquil, printLvl, err, maxsteps, loglevel);
532  } else if (XY == SP) {
533  xtarget = m_mix->entropy();
534  double Tlow = 0.5 * m_mix->minTemp();
535  double Thigh = 2.0 * m_mix->maxTemp();
536  iSuccess = equilibrate_SP(xtarget, Tlow, Thigh,
537  estimateEquil, printLvl, err, maxsteps, loglevel);
538 
539  } else if (XY == TV) {
540  xtarget = m_mix->temperature();
541  iSuccess = equilibrate_TV(XY, xtarget,
542  estimateEquil, printLvl, err, maxsteps, loglevel);
543  } else if (XY == HV) {
544  xtarget = m_mix->enthalpy();
545  iSuccess = equilibrate_TV(XY, xtarget,
546  estimateEquil, printLvl, err, maxsteps, loglevel);
547  } else if (XY == UV) {
548  xtarget = m_mix->IntEnergy();
549  iSuccess = equilibrate_TV(XY, xtarget,
550  estimateEquil, printLvl, err, maxsteps, loglevel);
551  } else if (XY == SV) {
552  xtarget = m_mix->entropy();
553  iSuccess = equilibrate_TV(XY, xtarget, estimateEquil,
554  printLvl, err, maxsteps, loglevel);
555  } else {
556  throw CanteraError(" vcs_MultiPhaseEquil::equilibrate",
557  "Unsupported Option");
558  }
559  return iSuccess;
560 }
561 
563  int printLvl, doublereal err,
564  int maxsteps, int loglevel)
565 {
566  int maxit = maxsteps;
567  clockWC tickTock;
568 
569  if (m_vprob == 0) {
570  m_vprob = new VCS_PROB(m_mix->nSpecies(),
571  m_mix->nElements(),
572  m_mix->nPhases());
573  }
574  m_printLvl = printLvl;
575  m_vprob->m_printLvl = printLvl;
576 
577 
578  /*
579  * Extract the current state information
580  * from the MultiPhase object and
581  * Transfer it to VCS_PROB object.
582  */
584  if (res != 0) {
585  plogf("problems\n");
586  }
587 
588 
589  // Set the estimation technique
590  if (estimateEquil) {
591  m_vprob->iest = estimateEquil;
592  } else {
593  m_vprob->iest = 0;
594  }
595 
596  // Check obvious bounds on the temperature and pressure
597  // NOTE, we may want to do more here with the real bounds
598  // given by the ThermoPhase objects.
599  double T = m_mix->temperature();
600  if (T <= 0.0) {
601  throw CanteraError("vcs_MultiPhaseEquil::equilibrate",
602  "Temperature less than zero on input");
603  }
604  double pres = m_mix->pressure();
605  if (pres <= 0.0) {
606  throw CanteraError("vcs_MultiPhaseEquil::equilibrate",
607  "Pressure less than zero on input");
608  }
609 
610  beginLogGroup("vcs_MultiPhaseEquil::equilibrate_TP", loglevel);
611  addLogEntry("problem type","fixed T,P");
612  addLogEntry("Temperature", T);
613  addLogEntry("Pressure", pres);
614 
615 
616  /*
617  * Print out the problem specification from the point of
618  * view of the vprob object.
619  */
621 
622  /*
623  * Call the thermo Program
624  */
625  int ip1 = m_printLvl;
626  int ipr = std::max(0, m_printLvl-1);
627  if (m_printLvl >= 3) {
628  ip1 = m_printLvl - 2;
629  } else {
630  ip1 = 0;
631  }
632  if (!m_vsolvePtr) {
633  m_vsolvePtr = new VCS_SOLVE();
634  }
635  int iSuccess = m_vsolvePtr->vcs(m_vprob, 0, ipr, ip1, maxit);
636 
637  /*
638  * Transfer the information back to the MultiPhase object.
639  * Note we don't just call setMoles, because some multispecies
640  * solution phases may be zeroed out, and that would cause a problem
641  * for that routine. Also, the mole fractions of such zeroed out
642  * phases actually contain information about likely reemergent
643  * states.
644  */
646  size_t kGlob = 0;
647  for (size_t ip = 0; ip < m_vprob->NPhase; ip++) {
648  double phaseMole = 0.0;
649  Cantera::ThermoPhase& tref = m_mix->phase(ip);
650  for (size_t k = 0; k < tref.nSpecies(); k++, kGlob++) {
651  phaseMole += m_vprob->w[kGlob];
652  }
653  //phaseMole *= 1.0E-3;
654  m_mix->setPhaseMoles(ip, phaseMole);
655  }
656 
657  double te = tickTock.secondsWC();
658  if (printLvl > 0) {
659  plogf("\n Results from vcs:\n");
660  if (iSuccess != 0) {
661  plogf("\nVCS FAILED TO CONVERGE!\n");
662  }
663  plogf("\n");
664  plogf("Temperature = %g Kelvin\n", m_vprob->T);
665  plogf("Pressure = %g Pa\n", m_vprob->PresPA);
666  plogf("\n");
667  plogf("----------------------------------------"
668  "---------------------\n");
669  plogf(" Name Mole_Number");
670  if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_MKS) {
671  plogf("(kmol)");
672  } else {
673  plogf("(gmol)");
674  }
675  plogf(" Mole_Fraction Chem_Potential");
676  if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_KCALMOL) {
677  plogf(" (kcal/mol)\n");
678  } else if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_UNITLESS) {
679  plogf(" (Dimensionless)\n");
680  } else if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_KJMOL) {
681  plogf(" (kJ/mol)\n");
682  } else if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_KELVIN) {
683  plogf(" (Kelvin)\n");
684  } else if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_MKS) {
685  plogf(" (J/kmol)\n");
686  }
687  plogf("--------------------------------------------------"
688  "-----------\n");
689  for (size_t i = 0; i < m_vprob->nspecies; i++) {
690  plogf("%-12s", m_vprob->SpName[i].c_str());
692  plogf(" %15.3e %15.3e ", 0.0, m_vprob->mf[i]);
693  plogf("%15.3e\n", m_vprob->m_gibbsSpecies[i]);
694  } else {
695  plogf(" %15.3e %15.3e ", m_vprob->w[i], m_vprob->mf[i]);
696  if (m_vprob->w[i] <= 0.0) {
697  size_t iph = m_vprob->PhaseID[i];
698  vcs_VolPhase* VPhase = m_vprob->VPhaseList[iph];
699  if (VPhase->nSpecies() > 1) {
700  plogf(" -1.000e+300\n");
701  } else {
702  plogf("%15.3e\n", m_vprob->m_gibbsSpecies[i]);
703  }
704  } else {
705  plogf("%15.3e\n", m_vprob->m_gibbsSpecies[i]);
706  }
707  }
708  }
709  plogf("------------------------------------------"
710  "-------------------\n");
711  if (printLvl > 2) {
712  if (m_vsolvePtr->m_timing_print_lvl > 0) {
713  plogf("Total time = %12.6e seconds\n", te);
714  }
715  }
716  }
717  endLogGroup();
718  return iSuccess;
719 }
720 
721 void vcs_MultiPhaseEquil::reportCSV(const std::string& reportFile)
722 {
723  size_t k;
724  size_t istart;
725  size_t nSpecies;
726 
727  double vol = 0.0;
728  string sName;
729  size_t nphase = m_vprob->NPhase;
730 
731  FILE* FP = fopen(reportFile.c_str(), "w");
732  if (!FP) {
733  plogf("Failure to open file\n");
734  exit(EXIT_FAILURE);
735  }
736  double Temp = m_mix->temperature();
737  double pres = m_mix->pressure();
738  double* mf = VCS_DATA_PTR(m_vprob->mf);
739 #ifdef DEBUG_MODE
740  double* fe = VCS_DATA_PTR(m_vprob->m_gibbsSpecies);
741 #endif
742  std::vector<double> VolPM;
743  std::vector<double> activity;
744  std::vector<double> ac;
745  std::vector<double> mu;
746  std::vector<double> mu0;
747  std::vector<double> molalities;
748 
749 
750  vol = 0.0;
751  for (size_t iphase = 0; iphase < nphase; iphase++) {
752  istart = m_mix->speciesIndex(0, iphase);
753  Cantera::ThermoPhase& tref = m_mix->phase(iphase);
754  nSpecies = tref.nSpecies();
755  VolPM.resize(nSpecies, 0.0);
757  vcs_VolPhase* volP = m_vprob->VPhaseList[iphase];
758 
759  double TMolesPhase = volP->totalMoles();
760  double VolPhaseVolumes = 0.0;
761  for (k = 0; k < nSpecies; k++) {
762  VolPhaseVolumes += VolPM[k] * mf[istart + k];
763  }
764  VolPhaseVolumes *= TMolesPhase;
765  vol += VolPhaseVolumes;
766  }
767 
768  fprintf(FP,"--------------------- VCS_MULTIPHASE_EQUIL FINAL REPORT"
769  " -----------------------------\n");
770  fprintf(FP,"Temperature = %11.5g kelvin\n", Temp);
771  fprintf(FP,"Pressure = %11.5g Pascal\n", pres);
772  fprintf(FP,"Total Volume = %11.5g m**3\n", vol);
773  fprintf(FP,"Number Basis optimizations = %d\n", m_vprob->m_NumBasisOptimizations);
774  fprintf(FP,"Number VCS iterations = %d\n", m_vprob->m_Iterations);
775 
776  for (size_t iphase = 0; iphase < nphase; iphase++) {
777  istart = m_mix->speciesIndex(0, iphase);
778  Cantera::ThermoPhase& tref = m_mix->phase(iphase);
779  Cantera::ThermoPhase* tp = &tref;
780  string phaseName = tref.name();
781  vcs_VolPhase* volP = m_vprob->VPhaseList[iphase];
782  double TMolesPhase = volP->totalMoles();
783  //AssertTrace(TMolesPhase == m_mix->phaseMoles(iphase));
784  nSpecies = tref.nSpecies();
785  activity.resize(nSpecies, 0.0);
786  ac.resize(nSpecies, 0.0);
787 
788  mu0.resize(nSpecies, 0.0);
789  mu.resize(nSpecies, 0.0);
790  VolPM.resize(nSpecies, 0.0);
791  molalities.resize(nSpecies, 0.0);
792 
793  int actConvention = tp->activityConvention();
794  tp->getActivities(VCS_DATA_PTR(activity));
797 
800  double VolPhaseVolumes = 0.0;
801  for (k = 0; k < nSpecies; k++) {
802  VolPhaseVolumes += VolPM[k] * mf[istart + k];
803  }
804  VolPhaseVolumes *= TMolesPhase;
805  vol += VolPhaseVolumes;
806 
807 
808  if (actConvention == 1) {
809  MolalityVPSSTP* mTP = static_cast<MolalityVPSSTP*>(tp);
810  mTP->getMolalities(VCS_DATA_PTR(molalities));
812 
813  if (iphase == 0) {
814  fprintf(FP," Name, Phase, PhaseMoles, Mole_Fract, "
815  "Molalities, ActCoeff, Activity,"
816  "ChemPot_SS0, ChemPot, mole_num, PMVol, Phase_Volume\n");
817 
818  fprintf(FP," , , (kmol), , "
819  " , , ,"
820  " (J/kmol), (J/kmol), (kmol), (m**3/kmol), (m**3)\n");
821  }
822  for (k = 0; k < nSpecies; k++) {
823  sName = tp->speciesName(k);
824  fprintf(FP,"%12s, %11s, %11.3e, %11.3e, %11.3e, %11.3e, %11.3e,"
825  "%11.3e, %11.3e, %11.3e, %11.3e, %11.3e\n",
826  sName.c_str(),
827  phaseName.c_str(), TMolesPhase,
828  mf[istart + k], molalities[k], ac[k], activity[k],
829  mu0[k]*1.0E-6, mu[k]*1.0E-6,
830  mf[istart + k] * TMolesPhase,
831  VolPM[k], VolPhaseVolumes);
832  }
833 
834  } else {
835  if (iphase == 0) {
836  fprintf(FP," Name, Phase, PhaseMoles, Mole_Fract, "
837  "Molalities, ActCoeff, Activity,"
838  " ChemPotSS0, ChemPot, mole_num, PMVol, Phase_Volume\n");
839 
840  fprintf(FP," , , (kmol), , "
841  " , , ,"
842  " (J/kmol), (J/kmol), (kmol), (m**3/kmol), (m**3)\n");
843  }
844  for (k = 0; k < nSpecies; k++) {
845  molalities[k] = 0.0;
846  }
847  for (k = 0; k < nSpecies; k++) {
848  sName = tp->speciesName(k);
849  fprintf(FP,"%12s, %11s, %11.3e, %11.3e, %11.3e, %11.3e, %11.3e, "
850  "%11.3e, %11.3e,% 11.3e, %11.3e, %11.3e\n",
851  sName.c_str(),
852  phaseName.c_str(), TMolesPhase,
853  mf[istart + k], molalities[k], ac[k],
854  activity[k], mu0[k]*1.0E-6, mu[k]*1.0E-6,
855  mf[istart + k] * TMolesPhase,
856  VolPM[k], VolPhaseVolumes);
857  }
858  }
859 
860 #ifdef DEBUG_MODE
861  /*
862  * Check consistency: These should be equal
863  */
864  tp->getChemPotentials(fe+istart);
865  for (k = 0; k < nSpecies; k++) {
866  if (!vcs_doubleEqual(fe[istart+k], mu[k])) {
867  fprintf(FP,"ERROR: incompatibility!\n");
868  fclose(FP);
869  plogf("ERROR: incompatibility!\n");
870  exit(EXIT_FAILURE);
871  }
872  }
873 #endif
874 
875  }
876  fclose(FP);
877 }
878 
879 //! print char repeatedly to log file
880 /*!
881  * @param letter letter to be repeated
882  * @param num Number of times repeated
883  */
884 static void print_char(const char letter, const int num)
885 {
886  for (int i = 0; i < num; i++) {
887  plogf("%c", letter);
888  }
889 }
890 
891 /*
892  * HKM -> Work on transferring the current value of the voltages into the
893  * equilibrium problem.
894  */
896  VCSnonideal::VCS_PROB* vprob)
897 {
898  VCS_SPECIES_THERMO* ts_ptr = 0;
899 
900  /*
901  * Calculate the total number of species and phases in the problem
902  */
903  size_t totNumPhases = mphase->nPhases();
904  size_t totNumSpecies = mphase->nSpecies();
905 
906  // Problem type has yet to be worked out.
907  vprob->prob_type = 0;
908  vprob->nspecies = totNumSpecies;
909  vprob->ne = 0;
910  vprob->NPhase = totNumPhases;
911  vprob->m_VCS_UnitsFormat = VCS_UNITS_MKS;
912  // Set the initial estimate to a machine generated estimate for now
913  // We will work out the details later.
914  vprob->iest = -1;
915  vprob->T = mphase->temperature();
916  vprob->PresPA = mphase->pressure();
917  vprob->Vol = mphase->volume();
918  vprob->Title = "MultiPhase Object";
919 
920  Cantera::ThermoPhase* tPhase = 0;
921 
922  bool gasPhase;
923  int printLvl = vprob->m_printLvl;
924 
925  /*
926  * Loop over the phases, transferring pertinent information
927  */
928  int kT = 0;
929  for (size_t iphase = 0; iphase < totNumPhases; iphase++) {
930 
931  /*
932  * Get the thermophase object - assume volume phase
933  */
934  tPhase = &(mphase->phase(iphase));
935  size_t nelem = tPhase->nElements();
936 
937  /*
938  * Query Cantera for the equation of state type of the
939  * current phase.
940  */
941  int eos = tPhase->eosType();
942  if (eos == cIdealGas) {
943  gasPhase = true;
944  } else {
945  gasPhase = false;
946  }
947 
948  /*
949  * Find out the number of species in the phase
950  */
951  size_t nSpPhase = tPhase->nSpecies();
952  /*
953  * Find out the name of the phase
954  */
955  string phaseName = tPhase->name();
956 
957  /*
958  * Call the basic vcs_VolPhase creation routine.
959  * Properties set here:
960  * ->PhaseNum = phase number in the thermo problem
961  * ->GasPhase = Boolean indicating whether it is a gas phase
962  * ->NumSpecies = number of species in the phase
963  * ->TMolesInert = Inerts in the phase = 0.0 for cantera
964  * ->PhaseName = Name of the phase
965  */
966 
967  vcs_VolPhase* VolPhase = vprob->VPhaseList[iphase];
968  VolPhase->resize(iphase, nSpPhase, nelem, phaseName.c_str(), 0.0);
969  VolPhase->m_gasPhase = gasPhase;
970  /*
971  * Tell the vcs_VolPhase pointer about cantera
972  */
973  VolPhase->p_VCS_UnitsFormat = vprob->m_VCS_UnitsFormat;
974  VolPhase->setPtrThermoPhase(tPhase);
975  VolPhase->setTotalMoles(0.0);
976  /*
977  * Set the electric potential of the volume phase from the
978  * ThermoPhase object's value.
979  */
980  VolPhase->setElectricPotential(tPhase->electricPotential());
981  /*
982  * Query the ThermoPhase object to find out what convention
983  * it uses for the specification of activity and Standard State.
984  */
985  VolPhase->p_activityConvention = tPhase->activityConvention();
986  /*
987  * Assign the value of eqn of state
988  * -> Handle conflicts here.
989  */
990  switch (eos) {
991  case cIdealGas:
992  VolPhase->m_eqnState = VCS_EOS_IDEAL_GAS;
993  break;
994  case cIncompressible:
995  VolPhase->m_eqnState = VCS_EOS_CONSTANT;
996  break;
997  case cSurf:
998  throw CanteraError("VCSnonideal", "cSurf not handled yet.");
999  case cStoichSubstance:
1000  VolPhase->m_eqnState = VCS_EOS_STOICH_SUB;
1001  break;
1002  case cPureFluid:
1003  if (printLvl > 1) {
1004  plogf("cPureFluid not recognized yet by VCSnonideal\n");
1005  }
1006  break;
1007  case cEdge:
1008  throw CanteraError("VCSnonideal", "cEdge not handled yet.");
1009  case cIdealSolidSolnPhase0:
1010  case cIdealSolidSolnPhase1:
1011  case cIdealSolidSolnPhase2:
1012  VolPhase->m_eqnState = VCS_EOS_IDEAL_SOLN;
1013  break;
1014  default:
1015  if (printLvl > 1) {
1016  plogf("Unknown Cantera EOS to VCSnonideal: %d\n", eos);
1017  }
1018  VolPhase->m_eqnState = VCS_EOS_UNK_CANTERA;
1019  if (!VolPhase->usingCanteraCalls()) {
1020  plogf("vcs functions asked for, but unimplemented\n");
1021  exit(EXIT_FAILURE);
1022  }
1023  break;
1024  }
1025 
1026  /*
1027  * Transfer all of the element information from the
1028  * ThermoPhase object to the vcs_VolPhase object.
1029  * Also decide whether we need a new charge neutrality
1030  * element in the phase to enforce a charge neutrality
1031  * constraint.
1032  * We also decide whether this is a single species phase
1033  * with the voltage being the independent variable setting
1034  * the chemical potential of the electrons.
1035  */
1036  VolPhase->transferElementsFM(tPhase);
1037 
1038  /*
1039  * Combine the element information in the vcs_VolPhase
1040  * object into the vprob object.
1041  */
1042  vprob->addPhaseElements(VolPhase);
1043 
1044  VolPhase->setState_TP(vprob->T, vprob->PresPA);
1045  vector<double> muPhase(tPhase->nSpecies(),0.0);
1046  tPhase->getChemPotentials(&muPhase[0]);
1047  double tMoles = 0.0;
1048  /*
1049  * Loop through each species in the current phase
1050  */
1051  for (size_t k = 0; k < nSpPhase; k++) {
1052  /*
1053  * Obtain the molecular weight of the species from the
1054  * ThermoPhase object
1055  */
1056  vprob->WtSpecies[kT] = tPhase->molecularWeight(k);
1057 
1058  /*
1059  * Obtain the charges of the species from the
1060  * ThermoPhase object
1061  */
1062  vprob->Charge[kT] = tPhase->charge(k);
1063 
1064  /*
1065  * Set the phaseid of the species
1066  */
1067  vprob->PhaseID[kT] = iphase;
1068 
1069  /*
1070  * Transfer the Species name
1071  */
1072  string stmp = mphase->speciesName(kT);
1073  vprob->SpName[kT] = stmp;
1074  /*
1075  * Transfer the type of unknown
1076  */
1077  vprob->SpeciesUnknownType[kT] = VolPhase->speciesUnknownType(k);
1078 
1079  if (vprob->SpeciesUnknownType[kT] == VCS_SPECIES_TYPE_MOLNUM) {
1080  /*
1081  * Set the initial number of kmoles of the species
1082  * and the mole fraction vector
1083  */
1084  vprob->w[kT] = mphase->speciesMoles(kT);
1085  tMoles += vprob->w[kT];
1086  vprob->mf[kT] = mphase->moleFraction(kT);
1087  } else if (vprob->SpeciesUnknownType[kT] == VCS_SPECIES_TYPE_INTERFACIALVOLTAGE) {
1088  vprob->w[kT] = tPhase->electricPotential();
1089  vprob->mf[kT] = mphase->moleFraction(kT);
1090  } else {
1091  throw CanteraError(" vcs_Cantera_to_vprob() ERROR",
1092  "Unknown species type: " + int2str(vprob->SpeciesUnknownType[kT]));
1093  }
1094 
1095 
1096  /*
1097  * transfer chemical potential vector
1098  */
1099  vprob->m_gibbsSpecies[kT] = muPhase[k];
1100  /*
1101  * Transfer the species information from the
1102  * volPhase structure to the VPROB structure
1103  * This includes:
1104  * FormulaMatrix[][]
1105  * VolPhase->IndSpecies[]
1106  */
1107  vprob->addOnePhaseSpecies(VolPhase, k, kT);
1108 
1109  /*
1110  * Get a pointer to the thermo object
1111  */
1112  ts_ptr = vprob->SpeciesThermo[kT];
1113  /*
1114  * Fill in the vcs_SpeciesProperty structure
1115  */
1116  vcs_SpeciesProperties* sProp = VolPhase->speciesProperty(k);
1117  sProp->NumElements = vprob->ne;
1118  sProp->SpName = vprob->SpName[kT];
1119  sProp->SpeciesThermo = ts_ptr;
1120  sProp->WtSpecies = tPhase->molecularWeight(k);
1121  sProp->FormulaMatrixCol.resize(vprob->ne, 0.0);
1122  for (size_t e = 0; e < vprob->ne; e++) {
1123  sProp->FormulaMatrixCol[e] = vprob->FormulaMatrix[e][kT];
1124  }
1125  sProp->Charge = tPhase->charge(k);
1126  sProp->SurfaceSpecies = false;
1127  sProp->VolPM = 0.0;
1128 
1129  /*
1130  * Transfer the thermo specification of the species
1131  * vprob->SpeciesThermo[]
1132  */
1133  ts_ptr->UseCanteraCalls = VolPhase->usingCanteraCalls();
1134  ts_ptr->m_VCS_UnitsFormat = VolPhase->p_VCS_UnitsFormat;
1135  /*
1136  * Add lookback connectivity into the thermo object first
1137  */
1138  ts_ptr->IndexPhase = iphase;
1139  ts_ptr->IndexSpeciesPhase = k;
1140  ts_ptr->OwningPhase = VolPhase;
1141  /*
1142  * get a reference to the Cantera species thermo.
1143  */
1144  SpeciesThermo& sp = tPhase->speciesThermo();
1145 
1146  int spType = sp.reportType(k);
1147 
1148  if (spType == SIMPLE) {
1149  double c[4];
1150  double minTemp, maxTemp, refPressure;
1151  sp.reportParams(k, spType, c, minTemp, maxTemp, refPressure);
1152  ts_ptr->SS0_Model = VCS_SS0_CONSTANT;
1153  ts_ptr->SS0_T0 = c[0];
1154  ts_ptr->SS0_H0 = c[1];
1155  ts_ptr->SS0_S0 = c[2];
1156  ts_ptr->SS0_Cp0 = c[3];
1157  if (gasPhase) {
1158  ts_ptr->SSStar_Model = VCS_SSSTAR_IDEAL_GAS;
1160  } else {
1161  ts_ptr->SSStar_Model = VCS_SSSTAR_CONSTANT;
1162  ts_ptr->SSStar_Vol_Model = VCS_SSVOL_CONSTANT;
1163  }
1164  ts_ptr->Activity_Coeff_Model = VCS_AC_CONSTANT;
1165  ts_ptr->Activity_Coeff_Params = NULL;
1166  } else {
1167  if (vprob->m_printLvl > 2) {
1168  plogf("vcs_Cantera_convert: Species Type %d not known \n",
1169  spType);
1170  }
1171  ts_ptr->SS0_Model = VCS_SS0_NOTHANDLED;
1172  ts_ptr->SSStar_Model = VCS_SSSTAR_NOTHANDLED;
1173  if (!(ts_ptr->UseCanteraCalls)) {
1174  plogf("Cantera calls not being used -> exiting\n");
1175  exit(EXIT_FAILURE);
1176  }
1177  }
1178 
1179  /*
1180  * Transfer the Volume Information -> NEEDS WORK
1181  */
1182  if (gasPhase) {
1184  ts_ptr->SSStar_Vol_Params = NULL;
1185  ts_ptr->SSStar_Vol0 = 82.05 * 273.15 / 1.0;
1186 
1187  } else {
1188  std::vector<double> phaseTermCoeff(nSpPhase, 0.0);
1189  int nCoeff;
1190  tPhase->getParameters(nCoeff, VCS_DATA_PTR(phaseTermCoeff));
1191  ts_ptr->SSStar_Vol_Model = VCS_SSVOL_CONSTANT;
1192  ts_ptr->SSStar_Vol0 = phaseTermCoeff[k];
1193  }
1194  kT++;
1195  }
1196 
1197  /*
1198  * Now go back through the species in the phase and assign
1199  * a valid mole fraction to all phases, even if the initial
1200  * estimate of the total number of moles is zero.
1201  */
1202  if (tMoles > 0.0) {
1203  for (size_t k = 0; k < nSpPhase; k++) {
1204  size_t kTa = VolPhase->spGlobalIndexVCS(k);
1205  vprob->mf[kTa] = vprob->w[kTa] / tMoles;
1206  }
1207  } else {
1208  /*
1209  * Perhaps, we could do a more sophisticated treatment below.
1210  * But, will start with this.
1211  */
1212  for (size_t k = 0; k < nSpPhase; k++) {
1213  size_t kTa = VolPhase->spGlobalIndexVCS(k);
1214  vprob->mf[kTa]= 1.0 / (double) nSpPhase;
1215  }
1216  }
1217 
1218  VolPhase->setMolesFromVCS(VCS_STATECALC_OLD, VCS_DATA_PTR(vprob->w));
1219  /*
1220  * Now, calculate a sample naught gibbs free energy calculation
1221  * at the specified temperature.
1222  */
1223  double R = vcsUtil_gasConstant(vprob->m_VCS_UnitsFormat);
1224  for (size_t k = 0; k < nSpPhase; k++) {
1225  vcs_SpeciesProperties* sProp = VolPhase->speciesProperty(k);
1226  ts_ptr = sProp->SpeciesThermo;
1227  ts_ptr->SS0_feSave = VolPhase->G0_calc_one(k)/ R;
1228  ts_ptr->SS0_TSave = vprob->T;
1229  }
1230 
1231  }
1232 
1233  /*
1234  * Transfer initial element abundances to the vprob object.
1235  * We have to find the mapping index from one to the other
1236  *
1237  */
1238  vprob->gai.resize(vprob->ne, 0.0);
1239  vprob->set_gai();
1240 
1241  /*
1242  * Printout the species information: PhaseID's and mole nums
1243  */
1244  if (vprob->m_printLvl > 1) {
1245  plogf("\n");
1246  print_char('=', 80);
1247  plogf("\n");
1248  print_char('=', 16);
1249  plogf(" Cantera_to_vprob: START OF PROBLEM STATEMENT ");
1250  print_char('=', 20);
1251  plogf("\n");
1252  print_char('=', 80);
1253  plogf("\n");
1254  plogf(" Phase IDs of species\n");
1255  plogf(" species phaseID phaseName ");
1256  plogf(" Initial_Estimated_kMols\n");
1257  for (size_t i = 0; i < vprob->nspecies; i++) {
1258  size_t iphase = vprob->PhaseID[i];
1259 
1260  vcs_VolPhase* VolPhase = vprob->VPhaseList[iphase];
1261  plogf("%16s %5d %16s", vprob->SpName[i].c_str(), iphase,
1262  VolPhase->PhaseName.c_str());
1264  plogf(" Volts = %-10.5g\n", vprob->w[i]);
1265  } else {
1266  plogf(" %-10.5g\n", vprob->w[i]);
1267  }
1268  }
1269 
1270  /*
1271  * Printout of the Phase structure information
1272  */
1273  plogf("\n");
1274  print_char('-', 80);
1275  plogf("\n");
1276  plogf(" Information about phases\n");
1277  plogf(" PhaseName PhaseNum SingSpec GasPhase EqnState NumSpec");
1278  plogf(" TMolesInert Tmoles(kmol)\n");
1279 
1280  for (size_t iphase = 0; iphase < vprob->NPhase; iphase++) {
1281  vcs_VolPhase* VolPhase = vprob->VPhaseList[iphase];
1282  std::string sEOS = string16_EOSType(VolPhase->m_eqnState);
1283  plogf("%16s %5d %5d %8d %16s %8d %16e ", VolPhase->PhaseName.c_str(),
1284  VolPhase->VP_ID_, VolPhase->m_singleSpecies,
1285  VolPhase->m_gasPhase, sEOS.c_str(),
1286  VolPhase->nSpecies(), VolPhase->totalMolesInert());
1287  plogf("%16e\n", VolPhase->totalMoles());
1288  }
1289 
1290  plogf("\n");
1291  print_char('=', 80);
1292  plogf("\n");
1293  print_char('=', 16);
1294  plogf(" Cantera_to_vprob: END OF PROBLEM STATEMENT ");
1295  print_char('=', 20);
1296  plogf("\n");
1297  print_char('=', 80);
1298  plogf("\n\n");
1299  }
1300 
1301  return VCS_SUCCESS;
1302 }
1303 
1305  VCSnonideal::VCS_PROB* vprob)
1306 {
1307  size_t totNumPhases = mphase->nPhases();
1308  size_t kT = 0;
1309  std::vector<double> tmpMoles;
1310  // Problem type has yet to be worked out.
1311  vprob->prob_type = 0;
1312  // Whether we have an estimate or not gets overwritten on
1313  // the call to the equilibrium solver.
1314  vprob->iest = -1;
1315  vprob->T = mphase->temperature();
1316  vprob->PresPA = mphase->pressure();
1317  vprob->Vol = mphase->volume();
1318  Cantera::ThermoPhase* tPhase = 0;
1319 
1320  for (size_t iphase = 0; iphase < totNumPhases; iphase++) {
1321  tPhase = &(mphase->phase(iphase));
1322  vcs_VolPhase* volPhase = vprob->VPhaseList[iphase];
1323  /*
1324  * Set the electric potential of the volume phase from the
1325  * ThermoPhase object's value.
1326  */
1327  volPhase->setElectricPotential(tPhase->electricPotential());
1328 
1329  volPhase->setState_TP(vprob->T, vprob->PresPA);
1330  vector<double> muPhase(tPhase->nSpecies(),0.0);
1331  tPhase->getChemPotentials(&muPhase[0]);
1332  /*
1333  * Loop through each species in the current phase
1334  */
1335  size_t nSpPhase = tPhase->nSpecies();
1336  // volPhase->TMoles = 0.0;
1337  tmpMoles.resize(nSpPhase);
1338  for (size_t k = 0; k < nSpPhase; k++) {
1339  tmpMoles[k] = mphase->speciesMoles(kT);
1340  vprob->w[kT] = mphase->speciesMoles(kT);
1341  vprob->mf[kT] = mphase->moleFraction(kT);
1342 
1343  /*
1344  * transfer chemical potential vector
1345  */
1346  vprob->m_gibbsSpecies[kT] = muPhase[k];
1347 
1348  kT++;
1349  }
1350  if (volPhase->phiVarIndex() != npos) {
1351  size_t kphi = volPhase->phiVarIndex();
1352  size_t kglob = volPhase->spGlobalIndexVCS(kphi);
1353  vprob->w[kglob] = tPhase->electricPotential();
1354  }
1355  volPhase->setMolesFromVCS(VCS_STATECALC_OLD, VCS_DATA_PTR(vprob->w));
1356  if ((nSpPhase == 1) && (volPhase->phiVarIndex() == 0)) {
1358  } else if (volPhase->totalMoles() > 0.0) {
1359  volPhase->setExistence(VCS_PHASE_EXIST_YES);
1360  } else {
1361  volPhase->setExistence(VCS_PHASE_EXIST_NO);
1362  }
1363 
1364  }
1365  /*
1366  * Transfer initial element abundances to the vprob object.
1367  * Put them in the front of the object. There may be
1368  * more constraints than there are elements. But, we
1369  * know the element abundances are in the front of the
1370  * vector.
1371  */
1372  vprob->set_gai();
1373 
1374  /*
1375  * Printout the species information: PhaseID's and mole nums
1376  */
1377  if (vprob->m_printLvl > 1) {
1378  plogf("\n");
1379  print_char('=', 80);
1380  plogf("\n");
1381  print_char('=', 20);
1382  plogf(" Cantera_to_vprob: START OF PROBLEM STATEMENT ");
1383  print_char('=', 20);
1384  plogf("\n");
1385  print_char('=', 80);
1386  plogf("\n\n");
1387  plogf(" Phase IDs of species\n");
1388  plogf(" species phaseID phaseName ");
1389  plogf(" Initial_Estimated_kMols\n");
1390  for (size_t i = 0; i < vprob->nspecies; i++) {
1391  size_t iphase = vprob->PhaseID[i];
1392 
1393  vcs_VolPhase* VolPhase = vprob->VPhaseList[iphase];
1394  plogf("%16s %5d %16s", vprob->SpName[i].c_str(), iphase,
1395  VolPhase->PhaseName.c_str());
1397  plogf(" Volts = %-10.5g\n", vprob->w[i]);
1398  } else {
1399  plogf(" %-10.5g\n", vprob->w[i]);
1400  }
1401  }
1402 
1403  /*
1404  * Printout of the Phase structure information
1405  */
1406  plogf("\n");
1407  print_char('-', 80);
1408  plogf("\n");
1409  plogf(" Information about phases\n");
1410  plogf(" PhaseName PhaseNum SingSpec GasPhase EqnState NumSpec");
1411  plogf(" TMolesInert Tmoles(kmol)\n");
1412 
1413  for (size_t iphase = 0; iphase < vprob->NPhase; iphase++) {
1414  vcs_VolPhase* VolPhase = vprob->VPhaseList[iphase];
1415  std::string sEOS = string16_EOSType(VolPhase->m_eqnState);
1416  plogf("%16s %5d %5d %8d %16s %8d %16e ", VolPhase->PhaseName.c_str(),
1417  VolPhase->VP_ID_, VolPhase->m_singleSpecies,
1418  VolPhase->m_gasPhase, sEOS.c_str(),
1419  VolPhase->nSpecies(), VolPhase->totalMolesInert());
1420  plogf("%16e\n", VolPhase->totalMoles());
1421  }
1422 
1423  plogf("\n");
1424  print_char('=', 80);
1425  plogf("\n");
1426  print_char('=', 20);
1427  plogf(" Cantera_to_vprob: END OF PROBLEM STATEMENT ");
1428  print_char('=', 20);
1429  plogf("\n");
1430  print_char('=', 80);
1431  plogf("\n\n");
1432  }
1433 
1434  return VCS_SUCCESS;
1435 }
1436 
1438 {
1439  size_t nsp = m_vsolvePtr->m_numSpeciesTot;
1440  nu.resize(nsp, 0.0);
1441  for (size_t i = 0; i < nsp; i++) {
1442  nu[i] = 0.0;
1443  }
1444  size_t nc = numComponents();
1445  // scMatrix [nrxn][ncomp]
1447  const std::vector<size_t>& indSpecies = m_vsolvePtr->m_speciesMapIndex;
1448  if (rxn > nsp - nc) {
1449  return;
1450  }
1451  size_t j = indSpecies[rxn + nc];
1452  nu[j] = 1.0;
1453  for (size_t kc = 0; kc < nc; kc++) {
1454  j = indSpecies[kc];
1455  nu[j] = scMatrix[rxn][kc];
1456  }
1457 
1458 }
1459 
1461 {
1462  size_t nc = npos;
1463  if (m_vsolvePtr) {
1465  }
1466  return nc;
1467 }
1468 
1470 {
1471  size_t nec = npos;
1472  if (m_vsolvePtr) {
1474  }
1475  return nec;
1476 }
1477 
1478 size_t vcs_MultiPhaseEquil::component(size_t m) const
1479 {
1480  size_t nc = numComponents();
1481  if (m < nc) {
1482  return m_vsolvePtr->m_speciesMapIndex[m];
1483  } else {
1484  return npos;
1485  }
1486 }
1487 
1488 int vcs_MultiPhaseEquil::determine_PhaseStability(int iph, double& funcStab, int printLvl, int loglevel)
1489 {
1490  clockWC tickTock;
1491  size_t nsp = m_mix->nSpecies();
1492  size_t nel = m_mix->nElements();
1493  size_t nph = m_mix->nPhases();
1494  if (m_vprob == 0) {
1495  m_vprob = new VCS_PROB(nsp, nel, nph);
1496  }
1497  m_printLvl = printLvl;
1498  m_vprob->m_printLvl = printLvl;
1499 
1500  /*
1501  * Extract the current state information
1502  * from the MultiPhase object and
1503  * Transfer it to VCS_PROB object.
1504  */
1506  if (res != 0) {
1507  plogf("problems\n");
1508  }
1509 
1510 
1511 
1512  // Check obvious bounds on the temperature and pressure
1513  // NOTE, we may want to do more here with the real bounds
1514  // given by the ThermoPhase objects.
1515  double T = m_mix->temperature();
1516  if (T <= 0.0) {
1517  throw CanteraError("vcs_MultiPhaseEquil::determine_PhaseStability",
1518  "Temperature less than zero on input");
1519  }
1520  double pres = m_mix->pressure();
1521  if (pres <= 0.0) {
1522  throw CanteraError("vcs_MultiPhaseEquil::determine_PhaseStability",
1523  "Pressure less than zero on input");
1524  }
1525 
1526  beginLogGroup("vcs_MultiPhaseEquil::determine_PhaseStability", loglevel);
1527  addLogEntry("problem type", "fixed T,P");
1528  addLogEntry("Temperature", T);
1529  addLogEntry("Pressure", pres);
1530 
1531  /*
1532  * Print out the problem specification from the point of
1533  * view of the vprob object.
1534  */
1536 
1537  /*
1538  * Call the thermo Program
1539  */
1540  if (!m_vsolvePtr) {
1541  m_vsolvePtr = new VCS_SOLVE();
1542  }
1543  int iStable = m_vsolvePtr->vcs_PS(m_vprob, iph, printLvl, funcStab);
1544 
1545  /*
1546  * Transfer the information back to the MultiPhase object.
1547  * Note we don't just call setMoles, because some multispecies
1548  * solution phases may be zeroed out, and that would cause a problem
1549  * for that routine. Also, the mole fractions of such zeroed out
1550  * phases actually contain information about likely reemergent
1551  * states.
1552  */
1554  // for (int i = 0; i < m_vprob->nspecies; i++) {
1555  // plogf("%d %15.3e\n", m_vprob->m_gibbsSpecies[i]);
1556  //}
1558  //for (int i = 0; i < m_vprob->nspecies; i++) {
1559  // plogf("%d %15.3e\n", m_vprob->m_gibbsSpecies[i]);
1560  //}
1561 
1562  double te = tickTock.secondsWC();
1563  if (printLvl > 0) {
1564  plogf("\n Results from vcs_PS:\n");
1565 
1566  plogf("\n");
1567  plogf("Temperature = %g Kelvin\n", m_vprob->T);
1568  plogf("Pressure = %g Pa\n", m_vprob->PresPA);
1569  std::string sss = m_mix->phaseName(iph);
1570  if (iStable) {
1571  plogf("Phase %d named %s is stable, function value = %g > 0\n", iph, sss.c_str(), funcStab);
1572  } else {
1573  plogf("Phase %d named %s is not stable + function value = %g < 0\n", iph, sss.c_str(), funcStab);
1574  }
1575  plogf("\n");
1576  plogf("----------------------------------------"
1577  "---------------------\n");
1578  plogf(" Name Mole_Number");
1579  if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_MKS) {
1580  plogf("(kmol)");
1581  } else {
1582  plogf("(gmol)");
1583  }
1584  plogf(" Mole_Fraction Chem_Potential");
1585  if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_KCALMOL) {
1586  plogf(" (kcal/mol)\n");
1587  } else if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_UNITLESS) {
1588  plogf(" (Dimensionless)\n");
1589  } else if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_KJMOL) {
1590  plogf(" (kJ/mol)\n");
1591  } else if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_KELVIN) {
1592  plogf(" (Kelvin)\n");
1593  } else if (m_vprob->m_VCS_UnitsFormat == VCS_UNITS_MKS) {
1594  plogf(" (J/kmol)\n");
1595  }
1596  plogf("-------------------------------------------------------------\n");
1597  for (size_t i = 0; i < m_vprob->nspecies; i++) {
1598  plogf("%-12s", m_vprob->SpName[i].c_str());
1600  plogf(" %15.3e %15.3e ", 0.0, m_vprob->mf[i]);
1601  plogf("%15.3e\n", m_vprob->m_gibbsSpecies[i]);
1602  } else {
1603  plogf(" %15.3e %15.3e ", m_vprob->w[i], m_vprob->mf[i]);
1604  if (m_vprob->w[i] <= 0.0) {
1605  plogf("%15.3e\n", m_vprob->m_gibbsSpecies[i]);
1606  } else {
1607  plogf("%15.3e\n", m_vprob->m_gibbsSpecies[i]);
1608  }
1609  }
1610  }
1611  plogf("------------------------------------------"
1612  "-------------------\n");
1613  if (printLvl > 2) {
1614  if (m_vsolvePtr->m_timing_print_lvl > 0) {
1615  plogf("Total time = %12.6e seconds\n", te);
1616  }
1617  }
1618  }
1619  endLogGroup("vcs_MultiPhaseEquil::determine_PhaseStability");
1620 
1621  return iStable;
1622 }
1623 
1624 }
std::vector< VCS_SPECIES_THERMO * > SpeciesThermo
Vector of pointers to thermo structures which identify the model and parameters for evaluating the th...
Definition: vcs_prob.h:204
int speciesUnknownType(const size_t k) const
Returns the type of the species unknown.
#define VCS_PHASE_EXIST_NO
Phase doesn't currently exist in the mixture.
Definition: vcs_defs.h:241
std::vector< double > WtSpecies
Molecular weight of species.
Definition: vcs_prob.h:190
doublereal molecularWeight(size_t k) const
Molecular weight of species k.
Definition: Phase.cpp:484
vcs_SpeciesProperties * speciesProperty(const size_t kindex)
Retrieve the kth Species structure for the species belonging to this phase.
ThermoPhase object for the ideal molal equation of state (see Thermodynamic Properties and class Idea...
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
Definition: stringUtils.cpp:40
size_t VP_ID_
Original ID of the phase in the problem.
Definition: vcs_VolPhase.h:592
double vcsUtil_gasConstant(int mu_units)
Returns the value of the gas constant in the units specified by parameter.
Definition: vcs_util.cpp:506
double SSStar_Vol0
parameter that is used in the VCS_SSVOL_CONSTANT model.
int equilibrate_HP(doublereal Htarget, int XY, double Tlow, double Thigh, int estimateEquil=0, int printLvl=0, doublereal err=1.0E-6, int maxsteps=VCS_MAXSTEPS, int loglevel=-99)
Equilibrate the solution using the current element abundances stored in the MultiPhase object using e...
doublereal electricPotential() const
Returns the electric potential of this phase (V).
Definition: ThermoPhase.h:391
size_t m_numComponents
Number of components calculated for the problem.
Definition: vcs_solve.h:1506
int iest
Specification of the initial estimate method.
Definition: vcs_prob.h:159
int SS0_Model
Integer representing the models for the species standard state Naught temperature dependence...
double SS0_S0
Base entropy used in the VCS_SS0_CONSTANT_CP model.
std::vector< double > w
Total number of moles of the kth species.
Definition: vcs_prob.h:73
size_t nElements() const
Number of elements.
Definition: Phase.cpp:139
Cantera::MultiPhase * m_mix
Pointer to the MultiPhase mixture that will be equilibrated.
void beginLogGroup(const std::string &title, int loglevel)
Create a new group for log messages.
Definition: global.cpp:90
virtual void getParameters(int &n, doublereal *const c) const
Get the equation of state parameters in a vector.
Definition: ThermoPhase.h:1471
size_t numComponents() const
reports the number of components in the equilibration problem
int equilibrate_TP(int estimateEquil=0, int printLvl=0, doublereal err=1.0e-6, int maxsteps=VCS_MAXSTEPS, int loglevel=-99)
Equilibrate the solution using the current element abundances stored in the MultiPhase object using c...
Declarations for a simple class that implements an Ansi C wall clock timer (see Cantera::clockWC).
int SSStar_Vol_Model
Models for the standard state volume of each species.
*std::vector< double > FormulaMatrixCol
Column of the formula matrix, comprising the element composition of the species.
bool UseCanteraCalls
If true, this object will call Cantera to do its member calculations.
void setPhaseMoles(const size_t n, const doublereal moles)
Set the number of moles of phase with index n.
std::string PhaseName
String name for the phase.
Definition: vcs_VolPhase.h:707
doublereal speciesMoles(size_t kGlob) const
Returns the moles of global species k. units = kmol.
Definition: MultiPhase.cpp:261
#define VCS_PHASE_EXIST_ALWAYS
Always exists because it contains inerts which can't exist in any other phase.
Definition: vcs_defs.h:228
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:173
std::string speciesName(const size_t kGlob) const
Name of species with global index kGlob.
Definition: MultiPhase.cpp:969
size_t IndexSpeciesPhase
Index of this species in the current phase.
int SSStar_Model
Integer value representing the star state model.
void prob_report(int print_lvl)
Print out the problem specification in all generality as it currently exists in the VCS_PROB object...
Definition: vcs_prob.cpp:184
#define VCS_DATA_PTR(vvv)
Points to the data in a std::vector<> object.
Definition: vcs_internal.h:24
int Activity_Coeff_Model
Integer value representing the activity coefficient model These are defined in vcs_VolPhase.h and start with VCS_AC_...
void setExistence(const int existence)
Set the existence flag in the object.
doublereal phaseMoles(const size_t n) const
Return the number of moles in phase n.
doublereal temperature() const
Temperature [K].
Definition: MultiPhase.h:335
#define VCS_SSVOL_IDEALGAS
Models for the standard state volume of each species.
Definition: vcs_VolPhase.h:34
std::string SpName
Name of the species.
int m_NumBasisOptimizations
Number of basis optimizations used. This is an output variable.
Definition: vcs_prob.h:210
size_t numElemConstraints() const
Reports the number of element constraints in the equilibration problem.
The class provides the wall clock timer in seconds.
Definition: clockWC.h:51
int m_timing_print_lvl
printing level of timing information
Definition: vcs_solve.h:2006
std::vector< int > SpeciesUnknownType
Specifies the species unknown type.
Definition: vcs_prob.h:106
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity for the species at their standard states at the...
Definition: ThermoPhase.h:711
void set_gai()
Calculate the element abundance vector from the mole numbers.
Definition: vcs_prob.cpp:155
virtual void getPartialMolarVolumes(doublereal *vbar) const
Return an array of partial molar volumes for the species in the mixture.
Definition: ThermoPhase.h:669
std::vector< double > m_gibbsSpecies
Vector of chemical potentials of the species.
Definition: vcs_prob.h:60
size_t transferElementsFM(const Cantera::ThermoPhase *const tPhase)
Transfer all of the element information from the ThermoPhase object to the vcs_VolPhase object...
int equilibrate(int XY, int estimateEquil=0, int printLvl=0, doublereal err=1.0e-6, int maxsteps=VCS_MAXSTEPS, int loglevel=-99)
Equilibrate the solution using the current element abundances stored in the MultiPhase object...
int p_activityConvention
Convention for the activity formulation.
Definition: vcs_VolPhase.h:649
Properties of a single species.
#define VCS_PHASE_EXIST_YES
Phase is a normal phase that currently exists.
Definition: vcs_defs.h:231
vcs_VolPhase * OwningPhase
Pointer to the owning phase object.
std::string name() const
Return the name of the phase.
Definition: Phase.cpp:129
Pure Virtual base class for the species thermo manager classes.
friend int vcs_Cantera_update_vprob(Cantera::MultiPhase *mphase, VCSnonideal::VCS_PROB *vprob)
Translate a MultiPhase information into a VCS_PROB problem definition object.
void getChemPotentials(doublereal *mu) const
Returns a vector of Chemical potentials.
Definition: MultiPhase.cpp:320
virtual int reportType(size_t index=npos) const =0
This utility function reports the type of parameterization used for the species with index number ind...
int vcs_Cantera_to_vprob(Cantera::MultiPhase *mphase, VCSnonideal::VCS_PROB *vprob)
Translate a MultiPhase object into a VCS_PROB problem definition object.
std::vector< double > Charge
Charge of each species.
Definition: vcs_prob.h:193
const doublereal Undef
Fairly random number to be used to initialize variables against to see if they are subsequently defin...
Definition: ct_defs.h:147
void reportCSV(const std::string &reportFile)
Report the equilibrium answer in a comma separated table format.
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:101
const int cSurf
A surface phase. Used by class SurfPhase.
Definition: mix_defs.h:40
size_t NPhase
Number of phases in the problem.
Definition: vcs_prob.h:50
bool usingCanteraCalls() const
Returns whether the object is using cantera calls.
Contains const definitions for types of species reference-state thermodynamics managers (see Species ...
int vcs_Cantera_update_vprob(Cantera::MultiPhase *mphase, VCSnonideal::VCS_PROB *vprob)
Translate a MultiPhase information into a VCS_PROB problem definition object.
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_TYPE_MOLNUM
Unknown refers to mole number of a single species.
Definition: vcs_defs.h:359
std::vector< size_t > m_speciesMapIndex
Index vector that keeps track of the species vector rearrangement.
Definition: vcs_solve.h:1785
Phase information and Phase calculations for vcs.
Definition: vcs_VolPhase.h:97
void uploadMoleFractionsFromPhases()
Update the locally-stored composition within this object to match the current compositions of the pha...
A class for multiphase mixtures.
Definition: MultiPhase.h:54
virtual void getActivities(doublereal *a) const
Get the array of non-dimensional activities at the current solution temperature, pressure, and solution concentration.
void addPhaseElements(vcs_VolPhase *volPhase)
Add elements to the local element list.
Definition: vcs_prob.cpp:318
Internal declarations for the VCSnonideal package.
doublereal entropy() const
The entropy of the mixture [J/K].
Definition: MultiPhase.cpp:399
#define VCS_SUCCESS
Definition: vcs_defs.h:37
double secondsWC()
Returns the wall clock time in seconds since the last reset.
Definition: clockWC.cpp:35
double SS0_Cp0
Base heat capacity used in the VCS_SS0_CONSTANT_CP model.
std::string fp2str(const double x, const std::string &fmt)
Convert a double into a c++ string.
Definition: stringUtils.cpp:29
size_t m_numSpeciesTot
Total number of species in the problems.
Definition: vcs_solve.h:1497
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
Definition: ThermoPhase.h:595
double G0_calc_one(size_t kspec) const
Gibbs free energy calculation at a temperature for the reference state of a species, return a value for one species.
Header for the Interface class for the vcs thermo equilibrium solver package,.
int prob_type
Problem type. I.e., the identity of what is held constant.
Definition: vcs_prob.h:34
std::vector< size_t > PhaseID
Mapping between the species and the phases.
Definition: vcs_prob.h:168
int m_printLvl
Print level from the VCSnonlinear package.
Header file for an ideal solid solution model with incompressible thermodynamics (see Thermodynamic P...
void * SSStar_Vol_Params
Pointer to a list of parameters that is malloced for volume models.
size_t nspecies
Total number of species in the problems.
Definition: vcs_prob.h:37
double SS0_T0
Base temperature used in the VCS_SS0_CONSTANT_CP model.
void setTemperature(const doublereal T)
Set the temperature [K].
Definition: MultiPhase.cpp:917
DoubleStarStar FormulaMatrix
Formula Matrix for the problem.
Definition: vcs_prob.h:93
size_t component(size_t m) const
Return the index of the ith component.
size_t spGlobalIndexVCS(const size_t spIndex) const
Return the Global VCS index of the kth species in the phase.
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:68
int m_VCS_UnitsFormat
Units for the chemical potential data, pressure data, volume, and species amounts.
Definition: vcs_prob.h:151
#define SIMPLE
Constant Cp thermo.
doublereal IntEnergy() const
The internal energy of the mixture [J].
Definition: MultiPhase.cpp:386
size_t m_numElemConstraints
Number of element constraints in the problem.
Definition: vcs_solve.h:1503
void setTotalMoles(const double totalMols)
Sets the total moles in the phase.
const int cEdge
An edge between two 2D surfaces.
Definition: mix_defs.h:58
int m_printLvl
Print level for print routines.
Definition: vcs_prob.h:213
size_t phiVarIndex() const
Return the index of the species that represents the the voltage of the phase.
double Vol
Volume of the entire system.
Definition: vcs_prob.h:126
double PresPA
Pressure.
Definition: vcs_prob.h:119
void setPressure(doublereal P)
Set the pressure [Pa].
Definition: MultiPhase.h:393
VCSnonideal::VCS_PROB * m_vprob
Object which contains the problem statement.
This is the main structure used to hold the internal data used in vcs_solve_TP(), and to solve TP sys...
Definition: vcs_solve.h:50
doublereal moleFraction(const size_t kGlob) const
Returns the mole fraction of global species k.
double SS0_TSave
Internal storage of the last temperature used in the calculation of the reference naught Gibbs free e...
void endLogGroup(const std::string &title)
Close the current group of log messages.
Definition: global.cpp:115
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:252
Interface class for the vcsnonlinear solver.
void addLogEntry(const std::string &tag, const std::string &value)
Add an entry to an HTML log file.
Definition: global.cpp:95
size_t nSpecies() const
Return the number of species in the phase.
std::vector< vcs_VolPhase * > VPhaseList
Array of phase structures.
Definition: vcs_prob.h:196
bool m_singleSpecies
If true, this phase consists of a single species.
Definition: vcs_VolPhase.h:595
void resize(const size_t phaseNum, const size_t numSpecies, const size_t numElem, const char *const phaseName, const double molesInert=0.0)
The resize() function fills in all of the initial information if it is not given in the constructor...
bool vcs_doubleEqual(double d1, double d2)
Simple routine to check whether two doubles are equal up to roundoff error.
Definition: vcs_util.cpp:645
#define VCS_STATECALC_OLD
State Calculation based on the old or base mole numbers.
Definition: vcs_defs.h:381
size_t addOnePhaseSpecies(vcs_VolPhase *volPhase, size_t k, size_t kT)
This routines adds entries for the formula matrix for one species.
Definition: vcs_prob.cpp:367
void setMolesFromVCS(const int stateCalc, const double *molesSpeciesVCS=0)
Set the moles within the phase.
static void print_char(const char letter, const int num)
print char repeatedly to log file
int p_VCS_UnitsFormat
Units for the chemical potential data, pressure data, volume, and species amounts.
Definition: vcs_VolPhase.h:641
#define plogendl()
define this Cantera function to replace cout << endl;
Definition: vcs_internal.h:37
doublereal enthalpy() const
The enthalpy of the mixture [J].
Definition: MultiPhase.cpp:373
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:165
doublereal maxTemp() const
Maximum temperature for which all solution phases have valid thermo data.
Definition: MultiPhase.h:258
void * Activity_Coeff_Params
Pointer to a list of parameters that is malloced for activity coefficient models. ...
DoubleStarStar m_stoichCoeffRxnMatrix
Stoichiometric coefficient matrix for the reaction mechanism expressed in Reduced Canonical Form...
Definition: vcs_solve.h:1556
double SS0_feSave
Internal storage of the last calculation of the reference naught Gibbs free energy at SS0_TSave...
double totalMolesInert() const
returns the value of the total kmol of inert in the phase
virtual int eosType() const
Equation of state type flag.
Definition: ThermoPhase.h:151
int determine_PhaseStability(int iph, double &funcStab, int printLvl=0, int logLevel=-99)
Determine the phase stability of a phase at the current conditions.
std::string phaseName(const size_t iph) const
Returns the name of the n'th phase.
Definition: MultiPhase.cpp:984
void setElectricPotential(const double phi)
set the electric potential of the phase
virtual void getActivityCoefficients(doublereal *ac) const
Get the array of non-dimensional molar-based activity coefficients at the current solution temperatur...
Definition: ThermoPhase.h:553
void getMolalities(doublereal *const molal) const
This function will return the molalities of the species.
virtual int activityConvention() const
This method returns the convention used in specification of the activities, of which there are curren...
int equilibrate_TV(int XY, doublereal xtarget, int estimateEquil=0, int printLvl=0, doublereal err=1.0E-6, int maxsteps=VCS_MAXSTEPS, int logLevel=-99)
Equilibrate the solution using the current element abundances stored in the MultiPhase object using c...
Contains declarations for string manipulation functions within Cantera.
Interface class for the vcs thermo equilibrium solver package, which generally describes the problem ...
Definition: vcs_prob.h:27
std::vector< std::string > SpName
Vector of strings containing the species names.
Definition: vcs_prob.h:171
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
Definition: ct_defs.h:36
std::string string16_EOSType(int EOSType)
Return a string representing the equation of state.
int m_Iterations
Number of iterations. This is an output variable.
Definition: vcs_prob.h:207
double totalMoles() const
Return the total moles in the phase.
VCSnonideal::VCS_SOLVE * m_vsolvePtr
Pointer to the object that does all of the equilibration work.
#define plogf
define this Cantera function to replace printf
Definition: vcs_internal.h:30
void setPtrThermoPhase(Cantera::ThermoPhase *tp_ptr)
Set the pointer for Cantera's ThermoPhase parameter.
std::vector< double > gai
Element abundances for jth element.
Definition: vcs_prob.h:87
virtual SpeciesThermo & speciesThermo(int k=-1)
Return a changeable reference to the calculation manager for species reference-state thermodynamic pr...
#define VCS_SPECIES_TYPE_INTERFACIALVOLTAGE
Unknown refers to the voltage level of a phase.
Definition: vcs_defs.h:368
void setState_TP(const double temperature_Kelvin, const double pressure_PA)
Sets the temperature and pressure in this object and underlying ThermoPhase objects.
void getStoichVector(size_t rxn, Cantera::vector_fp &nu)
Get the stoichiometric reaction coefficients for a single reaction index.
virtual void reportParams(size_t index, int &type, doublereal *const c, doublereal &minTemp, doublereal &maxTemp, doublereal &refPressure) const =0
This utility function reports back the type of parameterization and all of the parameters for the spe...
thermo_t & phase(size_t n)
Return a reference to phase n.
Definition: MultiPhase.cpp:236
doublereal minTemp() const
Minimum temperature for which all solution phases have valid thermo data.
Definition: MultiPhase.h:251
doublereal pressure() const
Pressure [Pa].
Definition: MultiPhase.h:378
size_t ne
Number of element constraints in the equilibrium problem.
Definition: vcs_prob.h:43
int equilibrate_SP(doublereal Starget, double Tlow, double Thigh, int estimateEquil=0, int printLvl=0, doublereal err=1.0E-6, int maxsteps=VCS_MAXSTEPS, int loglevel=-99)
Equilibrate the solution using the current element abundances stored in the MultiPhase object using c...
size_t IndexPhase
Index of the phase that this species belongs to.
size_t nSpecies() const
Number of species, summed over all phases.
Definition: MultiPhase.h:125
size_t speciesIndex(size_t k, size_t p) const
Return the global index of the species belonging to phase number p with local index k within the phas...
Definition: MultiPhase.h:231
int m_eqnState
Type of the equation of state.
Definition: vcs_VolPhase.h:608
double T
Temperature (Kelvin)
Definition: vcs_prob.h:112
double SS0_H0
Base enthalpy used in the VCS_SS0_CONSTANT_CP model.
const int cIdealGas
Equation of state types:
Definition: mix_defs.h:37
std::string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:246
Chemical equilibrium.
int vcs(VCS_PROB *vprob, int ifunc, int ipr, int ip1, int maxit)
Solve an equilibrium problem.
Definition: vcs_solve.cpp:247
doublereal volume() const
The total mixture volume [m^3].
Definition: MultiPhase.cpp:570
A class for 2D double arrays stored in column-major (Fortran-compatible) form.
bool m_gasPhase
If true, this phase is a gas-phase like phase.
Definition: vcs_VolPhase.h:602
size_t nElements() const
Number of elements.
Definition: MultiPhase.h:99
std::vector< double > mf
Mole fraction vector.
Definition: vcs_prob.h:80
friend int vcs_Cantera_to_vprob(Cantera::MultiPhase *mphase, VCSnonideal::VCS_PROB *vprob)
Translate a MultiPhase object into a VCS_PROB problem definition object.
doublereal charge(size_t k) const
Dimensionless electrical charge of a single molecule of species k The charge is normalized by the the...
Definition: Phase.h:504
size_t nPhases() const
Number of phases.
Definition: MultiPhase.h:415