24 vcs_MultiPhaseEquil::vcs_MultiPhaseEquil(
MultiPhase* mix,
int printLvl) :
27 m_vsolve(mix, printLvl)
33 int printLvl, doublereal err,
34 int maxsteps,
int loglevel)
37 if ((XY != TV) && (XY != HV) && (XY != UV) && (XY != SV)) {
38 throw CanteraError(
"vcs_MultiPhaseEquil::equilibrate_TV",
39 "Wrong XY flag: {}", XY);
46 int strt = estimateEquil;
53 int printLvlSub = std::max(0, printLvl - 1);
54 for (
int n = 0; n < maxiter; n++) {
59 iSuccess =
equilibrate_TP(strt, printLvlSub, err, maxsteps, loglevel);
63 printLvlSub, err, maxsteps, loglevel);
67 printLvlSub, err, maxsteps, loglevel);
71 printLvlSub, err, maxsteps, loglevel);
91 double Verr = fabs((Vtarget - Vnow)/Vtarget);
98 double dVdP = (V2 - V1) / (P2 - P1);
103 Pnew = Pnow + (Vtarget - Vnow) / dVdP;
104 if (Pnew < 0.2 * Pnow) {
107 if (Pnew > 3.0 * Pnow) {
113 double dVdP = (
m_mix->
volume() - Vnow)/(0.01*Pnow);
114 Pnew = Pnow + 0.5*(Vtarget - Vnow)/dVdP;
115 if (Pnew < 0.5* Pnow) {
118 if (Pnew > 1.7 * Pnow) {
125 "No convergence for V");
129 int XY,
double Tlow,
double Thigh,
131 int printLvl, doublereal err,
132 int maxsteps,
int loglevel)
136 if (XY != HP && XY != UP) {
137 throw CanteraError(
"vcs_MultiPhaseEquil::equilibrate_HP",
140 int strt = estimateEquil;
147 if (Thigh <= 0.0 || Thigh > 1.0E6) {
151 doublereal cpb = 1.0;
152 doublereal Hlow =
Undef;
153 doublereal Hhigh =
Undef;
155 int printLvlSub = std::max(printLvl - 1, 0);
157 for (
int n = 0; n < maxiter; n++) {
162 iSuccess =
equilibrate_TP(strt, printLvlSub, err, maxsteps, loglevel);
167 double Tmoles = pmoles[0];
168 double HperMole = Hnow/Tmoles;
170 plogf(
"T = %g, Hnow = %g ,Tmoles = %g, HperMole = %g\n",
171 Tnow, Hnow, Tmoles, HperMole);
177 if (Hnow < Htarget) {
192 cpb = (Hhigh - Hlow)/(Thigh - Tlow);
193 dT = (Htarget - Hnow)/cpb;
194 double dTa = fabs(dT);
195 double dTmax = 0.5*fabs(Thigh - Tlow);
200 double Tnew = sqrt(Tlow*Thigh);
201 dT =
clip(Tnew - Tnow, -200.0, 200.0);
203 double acpb = std::max(fabs(cpb), 1.0E-6);
204 double denom = std::max(fabs(Htarget), acpb);
205 double Herr = Htarget - Hnow;
206 double HConvErr = fabs((Herr)/denom);
208 plogf(
" equilibrate_HP: It = %d, Tcurr = %g Hcurr = %g, Htarget = %g\n",
209 n, Tnow, Hnow, Htarget);
210 plogf(
" H rel error = %g, cp = %g, HConvErr = %g\n",
211 Herr, cpb, HConvErr);
214 if (HConvErr < err) {
216 plogf(
" equilibrate_HP: CONVERGENCE: Hfinal = %g Tfinal = %g, Its = %d \n",
218 plogf(
" H rel error = %g, cp = %g, HConvErr = %g\n",
219 Herr, cpb, HConvErr);
223 double Tnew = Tnow + dT;
229 if (!estimateEquil) {
232 double Tnew = 0.5*(Tnow + Thigh);
233 if (fabs(Tnew - Tnow) < 1.0) {
240 throw CanteraError(
"vcs_MultiPhaseEquil::equilibrate_HP",
241 "No convergence for T");
245 double Tlow,
double Thigh,
247 int printLvl, doublereal err,
248 int maxsteps,
int loglevel)
251 int strt = estimateEquil;
258 if (Thigh <= 0.0 || Thigh > 1.0E6) {
262 doublereal cpb = 1.0, dT;
263 doublereal Slow =
Undef;
264 doublereal Shigh =
Undef;
266 Tlow = std::min(Tnow, Tlow);
267 Thigh = std::max(Tnow, Thigh);
268 int printLvlSub = std::max(printLvl - 1, 0);
270 for (
int n = 0; n < maxiter; n++) {
275 int iSuccess =
equilibrate_TP(strt, printLvlSub, err, maxsteps, loglevel);
280 double Tmoles = pmoles[0];
281 double SperMole = Snow/Tmoles;
283 plogf(
"T = %g, Snow = %g ,Tmoles = %g, SperMole = %g\n",
284 Tnow, Snow, Tmoles, SperMole);
291 if (Snow < Starget) {
296 if (Slow > Starget && Snow < Slow) {
312 cpb = (Shigh - Slow)/(Thigh - Tlow);
313 dT = (Starget - Snow)/cpb;
314 double Tnew = Tnow + dT;
315 double dTa = fabs(dT);
316 double dTmax = 0.5*fabs(Thigh - Tlow);
317 if (Tnew > Thigh || Tnew < Tlow) {
318 dTmax = 1.5*fabs(Thigh - Tlow);
320 dTmax = std::min(dTmax, 300.);
325 double Tnew = sqrt(Tlow*Thigh);
329 double acpb = std::max(fabs(cpb), 1.0E-6);
330 double denom = std::max(fabs(Starget), acpb);
331 double Serr = Starget - Snow;
332 double SConvErr = fabs((Serr)/denom);
334 plogf(
" equilibrate_SP: It = %d, Tcurr = %g Scurr = %g, Starget = %g\n",
335 n, Tnow, Snow, Starget);
336 plogf(
" S rel error = %g, cp = %g, SConvErr = %g\n",
337 Serr, cpb, SConvErr);
340 if (SConvErr < err) {
342 plogf(
" equilibrate_SP: CONVERGENCE: Sfinal = %g Tfinal = %g, Its = %d \n",
344 plogf(
" S rel error = %g, cp = %g, HConvErr = %g\n",
345 Serr, cpb, SConvErr);
349 double Tnew = Tnow + dT;
355 if (!estimateEquil) {
358 double Tnew = 0.5*(Tnow + Thigh);
359 if (fabs(Tnew - Tnow) < 1.0) {
366 throw CanteraError(
"vcs_MultiPhaseEquil::equilibrate_SP",
367 "No convergence for T");
371 int printLvl, doublereal err,
372 int maxsteps,
int loglevel)
376 return equilibrate_TP(estimateEquil, printLvl, err, maxsteps, loglevel);
377 }
else if (XY == HP || XY == UP) {
386 estimateEquil, printLvl, err, maxsteps, loglevel);
387 }
else if (XY == SP) {
392 estimateEquil, printLvl, err, maxsteps, loglevel);
393 }
else if (XY == TV) {
396 estimateEquil, printLvl, err, maxsteps, loglevel);
397 }
else if (XY == HV) {
400 estimateEquil, printLvl, err, maxsteps, loglevel);
401 }
else if (XY == UV) {
404 estimateEquil, printLvl, err, maxsteps, loglevel);
405 }
else if (XY == SV) {
408 printLvl, err, maxsteps, loglevel);
411 "Unsupported Option");
416 int printLvl, doublereal err,
417 int maxsteps,
int loglevel)
419 int maxit = maxsteps;
428 throw CanteraError(
"vcs_MultiPhaseEquil::equilibrate_TP",
429 "Temperature less than zero on input");
432 throw CanteraError(
"vcs_MultiPhaseEquil::equilibrate_TP",
433 "Pressure less than zero on input");
450 plogf(
"\n Results from vcs:\n");
452 plogf(
"\nVCS FAILED TO CONVERGE!\n");
458 plogf(
"----------------------------------------"
459 "---------------------\n");
460 plogf(
" Name Mole_Number(kmol)");
461 plogf(
" Mole_Fraction Chem_Potential (J/kmol)\n");
462 plogf(
"--------------------------------------------------"
468 plogf(
"%15.3e\n", mu[i]);
475 plogf(
" -1.000e+300\n");
477 plogf(
"%15.3e\n", mu[i]);
480 plogf(
"%15.3e\n", mu[i]);
484 plogf(
"------------------------------------------"
485 "-------------------\n");
487 plogf(
"Total time = %12.6e seconds\n", te);
497 FILE* FP = fopen(reportFile.c_str(),
"w");
500 "Failure to open file");
510 for (
size_t iphase = 0; iphase < nphase; iphase++) {
513 VolPM.resize(nSpecies, 0.0);
518 double VolPhaseVolumes = 0.0;
519 for (
size_t k = 0; k < nSpecies; k++) {
522 VolPhaseVolumes *= TMolesPhase;
523 vol += VolPhaseVolumes;
526 fprintf(FP,
"--------------------- VCS_MULTIPHASE_EQUIL FINAL REPORT"
527 " -----------------------------\n");
530 fprintf(FP,
"Total Volume = %11.5g m**3\n", vol);
534 for (
size_t iphase = 0; iphase < nphase; iphase++) {
536 string phaseName = tref.
name();
540 activity.resize(nSpecies, 0.0);
541 ac.resize(nSpecies, 0.0);
542 mu0.resize(nSpecies, 0.0);
543 mu.resize(nSpecies, 0.0);
544 VolPM.resize(nSpecies, 0.0);
545 molalities.resize(nSpecies, 0.0);
552 double VolPhaseVolumes = 0.0;
553 for (
size_t k = 0; k < nSpecies; k++) {
556 VolPhaseVolumes *= TMolesPhase;
557 vol += VolPhaseVolumes;
559 if (actConvention == 1) {
565 fprintf(FP,
" Name, Phase, PhaseMoles, Mole_Fract, "
566 "Molalities, ActCoeff, Activity,"
567 "ChemPot_SS0, ChemPot, mole_num, PMVol, Phase_Volume\n");
569 fprintf(FP,
" , , (kmol), , "
571 " (J/kmol), (J/kmol), (kmol), (m**3/kmol), (m**3)\n");
573 for (
size_t k = 0; k < nSpecies; k++) {
575 fprintf(FP,
"%12s, %11s, %11.3e, %11.3e, %11.3e, %11.3e, %11.3e,"
576 "%11.3e, %11.3e, %11.3e, %11.3e, %11.3e\n",
578 phaseName.c_str(), TMolesPhase,
579 tref.
moleFraction(k), molalities[k], ac[k], activity[k],
580 mu0[k]*1.0E-6, mu[k]*1.0E-6,
582 VolPM[k], VolPhaseVolumes);
586 fprintf(FP,
" Name, Phase, PhaseMoles, Mole_Fract, "
587 "Molalities, ActCoeff, Activity,"
588 " ChemPotSS0, ChemPot, mole_num, PMVol, Phase_Volume\n");
590 fprintf(FP,
" , , (kmol), , "
592 " (J/kmol), (J/kmol), (kmol), (m**3/kmol), (m**3)\n");
594 for (
size_t k = 0; k < nSpecies; k++) {
597 for (
size_t k = 0; k < nSpecies; k++) {
599 fprintf(FP,
"%12s, %11s, %11.3e, %11.3e, %11.3e, %11.3e, %11.3e, "
600 "%11.3e, %11.3e,% 11.3e, %11.3e, %11.3e\n",
602 phaseName.c_str(), TMolesPhase,
604 activity[k], mu0[k]*1.0E-6, mu[k]*1.0E-6,
606 VolPM[k], VolPhaseVolumes);
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.
void getMolalities(doublereal *const molal) const
This function will return the molalities of the species.
A class for multiphase mixtures.
doublereal maxTemp() const
Maximum temperature for which all solution phases have valid thermo data.
doublereal minTemp() const
Minimum temperature for which all solution phases have valid thermo data.
size_t nSpecies() const
Number of species, summed over all phases.
doublereal pressure() const
Pressure [Pa].
doublereal enthalpy() const
The enthalpy of the mixture [J].
doublereal speciesMoles(size_t kGlob) const
Returns the moles of global species k. units = kmol.
doublereal IntEnergy() const
The internal energy of the mixture [J].
doublereal moleFraction(const size_t kGlob) const
Returns the mole fraction of global species k.
doublereal phaseMoles(const size_t n) const
Return the number of moles in phase n.
std::string speciesName(const size_t kGlob) const
Name of species with global index kGlob.
void setPressure(doublereal P)
Set the pressure [Pa].
doublereal entropy() const
The entropy of the mixture [J/K].
doublereal volume() const
The total mixture volume [m^3].
doublereal temperature() const
Temperature [K].
void getChemPotentials(doublereal *mu) const
Returns a vector of Chemical potentials.
thermo_t & phase(size_t n)
Return a reference to phase n.
void setTemperature(const doublereal T)
Set the temperature [K].
std::string name() const
Return the name of the phase.
size_t nSpecies() const
Returns the number of species in the phase.
std::string speciesName(size_t k) const
Name of the species with index k.
double moleFraction(size_t k) const
Return the mole fraction of a single species.
Base class for a phase with thermodynamic properties.
virtual void getActivities(doublereal *a) const
Get the array of non-dimensional activities at the current solution temperature, pressure,...
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
virtual void getActivityCoefficients(doublereal *ac) const
Get the array of non-dimensional molar-based activity coefficients at the current solution temperatur...
virtual void getPartialMolarVolumes(doublereal *vbar) const
Return an array of partial molar volumes for the species in the mixture.
virtual int activityConvention() const
This method returns the convention used in specification of the activities, of which there are curren...
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity for the species at their standard states at the...
int Its
Current number of iterations in the main loop of vcs_TP() to solve for thermo equilibrium.
int Basis_Opts
number of optimizations of the components basis set done
size_t m_numPhases
Number of Phases in the problem.
int m_doEstimateEquil
Setting for whether to do an initial estimate.
vector_int m_speciesUnknownType
Specifies the species unknown type.
int m_timing_print_lvl
printing level of timing information
std::vector< size_t > m_phaseID
Mapping from the species number to the phase number.
VCS_COUNTERS * m_VCount
Timing and iteration counters for the vcs object.
int vcs(int ipr, int ip1, int maxit)
Solve an equilibrium problem.
double m_pressurePA
Pressure.
std::vector< std::unique_ptr< vcs_VolPhase > > m_VolPhaseList
Array of Phase Structures. Length = number of phases.
int m_printLvl
Print level for print routines.
double m_temperature
Temperature (Kelvin)
The class provides the wall clock timer in seconds.
double secondsWC()
Returns the wall clock time in seconds since the last reset.
VCS_SOLVE m_vsolve
The object that contains the problem statement and does all of the equilibration work.
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...
void reportCSV(const std::string &reportFile)
Report the equilibrium answer in a comma separated table format.
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...
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...
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 m_printLvl
Print level from the VCSnonlinear package.
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...
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.
double totalMoles() const
Return the total moles in the phase.
Declarations for a simple class that implements an Ansi C wall clock timer (see Cantera::clockWC).
const double Undef
Fairly random number to be used to initialize variables against to see if they are subsequently defin...
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Namespace for the Cantera kernel.
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