26 int printLvl,
double err,
27 int maxsteps,
int loglevel)
29 double Vtarget =
m_mix->volume();
30 if ((XY != TV) && (XY != HV) && (XY != UV) && (XY != SV)) {
31 throw CanteraError(
"vcs_MultiPhaseEquil::equilibrate_TV",
32 "Wrong XY flag: {}", XY);
37 m_mix->setTemperature(xtarget);
39 int strt = estimateEquil;
44 double Tlow = 0.5 *
m_mix->minTemp();
45 double Thigh = 2.0 *
m_mix->maxTemp();
46 int printLvlSub = std::max(0, printLvl - 1);
47 for (
int n = 0; n < maxiter; n++) {
48 double Pnow =
m_mix->pressure();
52 iSuccess =
equilibrate_TP(strt, printLvlSub, err, maxsteps, loglevel);
56 printLvlSub, err, maxsteps, loglevel);
60 printLvlSub, err, maxsteps, loglevel);
64 printLvlSub, err, maxsteps, loglevel);
70 double Vnow =
m_mix->volume();
84 double Verr = fabs((Vtarget - Vnow)/Vtarget);
91 double dVdP = (V2 - V1) / (P2 - P1);
96 Pnew = Pnow + (Vtarget - Vnow) / dVdP;
97 if (Pnew < 0.2 * Pnow) {
100 if (Pnew > 3.0 * Pnow) {
105 m_mix->setPressure(Pnow*1.01);
106 double dVdP = (
m_mix->volume() - Vnow)/(0.01*Pnow);
107 Pnew = Pnow + 0.5*(Vtarget - Vnow)/dVdP;
108 if (Pnew < 0.5* Pnow) {
111 if (Pnew > 1.7 * Pnow) {
115 m_mix->setPressure(Pnew);
118 "No convergence for V");
122 double Thigh,
int estimateEquil,
int printLvl,
double err,
int maxsteps,
127 if (XY != HP && XY != UP) {
128 throw CanteraError(
"vcs_MultiPhaseEquil::equilibrate_HP",
131 int strt = estimateEquil;
135 Tlow = 0.5 *
m_mix->minTemp();
138 if (Thigh <= 0.0 || Thigh > 1.0E6) {
139 Thigh = 2.0 *
m_mix->maxTemp();
144 double Hhigh =
Undef;
145 double Tnow =
m_mix->temperature();
146 int printLvlSub = std::max(printLvl - 1, 0);
148 for (
int n = 0; n < maxiter; n++) {
152 Tnow =
m_mix->temperature();
153 iSuccess =
equilibrate_TP(strt, printLvlSub, err, maxsteps, loglevel);
155 double Hnow = (XY == UP) ?
m_mix->IntEnergy() :
m_mix->enthalpy();
157 pmoles[0] =
m_mix->phaseMoles(0);
158 double Tmoles = pmoles[0];
159 double HperMole = Hnow/Tmoles;
161 plogf(
"T = %g, Hnow = %g ,Tmoles = %g, HperMole = %g\n",
162 Tnow, Hnow, Tmoles, HperMole);
168 if (Hnow < Htarget) {
183 cpb = (Hhigh - Hlow)/(Thigh - Tlow);
184 dT = (Htarget - Hnow)/cpb;
185 double dTa = fabs(dT);
186 double dTmax = 0.5*fabs(Thigh - Tlow);
191 double Tnew = sqrt(Tlow*Thigh);
192 dT =
clip(Tnew - Tnow, -200.0, 200.0);
194 double acpb = std::max(fabs(cpb), 1.0E-6);
195 double denom = std::max(fabs(Htarget), acpb);
196 double Herr = Htarget - Hnow;
197 double HConvErr = fabs((Herr)/denom);
199 plogf(
" equilibrate_HP: It = %d, Tcurr = %g Hcurr = %g, Htarget = %g\n",
200 n, Tnow, Hnow, Htarget);
201 plogf(
" H rel error = %g, cp = %g, HConvErr = %g\n",
202 Herr, cpb, HConvErr);
205 if (HConvErr < err) {
207 plogf(
" equilibrate_HP: CONVERGENCE: Hfinal = %g Tfinal = %g, Its = %d \n",
209 plogf(
" H rel error = %g, cp = %g, HConvErr = %g\n",
210 Herr, cpb, HConvErr);
214 double Tnew = Tnow + dT;
218 m_mix->setTemperature(Tnew);
220 if (!estimateEquil) {
223 double Tnew = 0.5*(Tnow + Thigh);
224 if (fabs(Tnew - Tnow) < 1.0) {
227 m_mix->setTemperature(Tnew);
231 throw CanteraError(
"vcs_MultiPhaseEquil::equilibrate_HP",
232 "No convergence for T");
236 int estimateEquil,
int printLvl,
double err,
int maxsteps,
int loglevel)
239 int strt = estimateEquil;
243 Tlow = 0.5 *
m_mix->minTemp();
246 if (Thigh <= 0.0 || Thigh > 1.0E6) {
247 Thigh = 2.0 *
m_mix->maxTemp();
250 double cpb = 1.0, dT;
252 double Shigh =
Undef;
253 double Tnow =
m_mix->temperature();
254 Tlow = std::min(Tnow, Tlow);
255 Thigh = std::max(Tnow, Thigh);
256 int printLvlSub = std::max(printLvl - 1, 0);
258 for (
int n = 0; n < maxiter; n++) {
262 Tnow =
m_mix->temperature();
263 int iSuccess =
equilibrate_TP(strt, printLvlSub, err, maxsteps, loglevel);
265 double Snow =
m_mix->entropy();
267 pmoles[0] =
m_mix->phaseMoles(0);
268 double Tmoles = pmoles[0];
269 double SperMole = Snow/Tmoles;
271 plogf(
"T = %g, Snow = %g ,Tmoles = %g, SperMole = %g\n",
272 Tnow, Snow, Tmoles, SperMole);
279 if (Snow < Starget) {
284 if (Slow > Starget && Snow < Slow) {
300 cpb = (Shigh - Slow)/(Thigh - Tlow);
301 dT = (Starget - Snow)/cpb;
302 double Tnew = Tnow + dT;
303 double dTa = fabs(dT);
304 double dTmax = 0.5*fabs(Thigh - Tlow);
305 if (Tnew > Thigh || Tnew < Tlow) {
306 dTmax = 1.5*fabs(Thigh - Tlow);
308 dTmax = std::min(dTmax, 300.);
313 double Tnew = sqrt(Tlow*Thigh);
317 double acpb = std::max(fabs(cpb), 1.0E-6);
318 double denom = std::max(fabs(Starget), acpb);
319 double Serr = Starget - Snow;
320 double SConvErr = fabs((Serr)/denom);
322 plogf(
" equilibrate_SP: It = %d, Tcurr = %g Scurr = %g, Starget = %g\n",
323 n, Tnow, Snow, Starget);
324 plogf(
" S rel error = %g, cp = %g, SConvErr = %g\n",
325 Serr, cpb, SConvErr);
328 if (SConvErr < err) {
330 plogf(
" equilibrate_SP: CONVERGENCE: Sfinal = %g Tfinal = %g, Its = %d \n",
332 plogf(
" S rel error = %g, cp = %g, HConvErr = %g\n",
333 Serr, cpb, SConvErr);
337 double Tnew = Tnow + dT;
341 m_mix->setTemperature(Tnew);
343 if (!estimateEquil) {
346 double Tnew = 0.5*(Tnow + Thigh);
347 if (fabs(Tnew - Tnow) < 1.0) {
350 m_mix->setTemperature(Tnew);
354 throw CanteraError(
"vcs_MultiPhaseEquil::equilibrate_SP",
355 "No convergence for T");
359 double err,
int maxsteps,
int loglevel)
363 return equilibrate_TP(estimateEquil, printLvl, err, maxsteps, loglevel);
364 }
else if (XY == HP || XY == UP) {
366 xtarget =
m_mix->enthalpy();
368 xtarget =
m_mix->IntEnergy();
370 double Tlow = 0.5 *
m_mix->minTemp();
371 double Thigh = 2.0 *
m_mix->maxTemp();
373 estimateEquil, printLvl, err, maxsteps, loglevel);
374 }
else if (XY == SP) {
375 xtarget =
m_mix->entropy();
376 double Tlow = 0.5 *
m_mix->minTemp();
377 double Thigh = 2.0 *
m_mix->maxTemp();
379 estimateEquil, printLvl, err, maxsteps, loglevel);
380 }
else if (XY == TV) {
381 xtarget =
m_mix->temperature();
383 estimateEquil, printLvl, err, maxsteps, loglevel);
384 }
else if (XY == HV) {
385 xtarget =
m_mix->enthalpy();
387 estimateEquil, printLvl, err, maxsteps, loglevel);
388 }
else if (XY == UV) {
389 xtarget =
m_mix->IntEnergy();
391 estimateEquil, printLvl, err, maxsteps, loglevel);
392 }
else if (XY == SV) {
393 xtarget =
m_mix->entropy();
395 printLvl, err, maxsteps, loglevel);
398 "Unsupported Option");
403 int maxsteps,
int loglevel)
405 int maxit = maxsteps;
408 m_vsolve.m_doEstimateEquil = estimateEquil;
412 if (
m_mix->temperature() <= 0.0) {
413 throw CanteraError(
"vcs_MultiPhaseEquil::equilibrate_TP",
414 "Temperature less than zero on input");
416 if (
m_mix->pressure() <= 0.0) {
417 throw CanteraError(
"vcs_MultiPhaseEquil::equilibrate_TP",
418 "Pressure less than zero on input");
429 int iSuccess =
m_vsolve.solve_TP(ipr, ip1, maxit);
432 vector<double> mu(
m_mix->nSpecies());
433 m_mix->getChemPotentials(mu);
434 plogf(
"\n Results from vcs:\n");
436 plogf(
"\nVCS FAILED TO CONVERGE!\n");
442 plogf(
"----------------------------------------"
443 "---------------------\n");
444 plogf(
" Name Mole_Number(kmol)");
445 plogf(
" Mole_Fraction Chem_Potential (J/kmol)\n");
446 plogf(
"--------------------------------------------------"
448 for (
size_t i = 0; i <
m_mix->nSpecies(); i++) {
451 plogf(
" %15.3e %15.3e ", 0.0,
m_mix->moleFraction(i));
452 plogf(
"%15.3e\n", mu[i]);
454 plogf(
" %15.3e %15.3e ",
m_mix->speciesMoles(i),
m_mix->moleFraction(i));
455 if (
m_mix->speciesMoles(i) <= 0.0) {
459 plogf(
" -1.000e+300\n");
461 plogf(
"%15.3e\n", mu[i]);
464 plogf(
"%15.3e\n", mu[i]);
468 plogf(
"------------------------------------------"
469 "-------------------\n");
ThermoPhase object for the ideal molal equation of state (see Thermodynamic Properties and class Idea...
Header file for an ideal solid solution model with incompressible thermodynamics (see Thermodynamic P...
Base class for exceptions thrown by Cantera classes.
A class for multiphase mixtures.
VCS_SOLVE m_vsolve
The object that contains the problem statement and does all of the equilibration work.
int equilibrate_SP(double Starget, double Tlow, double Thigh, int estimateEquil=0, int printLvl=0, double 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...
vcs_MultiPhaseEquil(MultiPhase *mix, int printLvl)
Constructor for the multiphase equilibrium solver.
int equilibrate_TP(int estimateEquil=0, int printLvl=0, double 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...
int equilibrate(int XY, int estimateEquil=0, int printLvl=0, double 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 equilibrate_TV(int XY, double xtarget, int estimateEquil=0, int printLvl=0, double 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...
int m_printLvl
Print level from the VCSnonlinear package.
int equilibrate_HP(double Htarget, int XY, double Tlow, double Thigh, int estimateEquil=0, int printLvl=0, double 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...
MultiPhase * m_mix
Pointer to the MultiPhase mixture that will be equilibrated.
Phase information and Phase calculations for vcs.
size_t nSpecies() const
Return the number of species in the phase.
T clip(const T &value, const T &lower, const T &upper)
Clip value such that lower <= value <= upper.
Namespace for the Cantera kernel.
const double Undef
Fairly random number to be used to initialize variables against to see if they are subsequently defin...
Contains const definitions for types of species reference-state thermodynamics managers (see Species ...
Contains declarations for string manipulation functions within Cantera.
Interface class for the vcsnonlinear solver.
Header for the object representing each phase within vcs.
#define VCS_SPECIES_TYPE_INTERFACIALVOLTAGE
Unknown refers to the voltage level of a phase.
#define plogf
define this Cantera function to replace printf