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) {
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) {
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;
429 "Temperature less than zero on input");
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);
std::vector< size_t > m_phaseID
Mapping from the species number to the phase number.
ThermoPhase object for the ideal molal equation of state (see Thermodynamic Properties and class Idea...
int Its
Current number of iterations in the main loop of vcs_TP() to solve for thermo equilibrium.
vector_int m_speciesUnknownType
Specifies the species unknown type.
int Basis_Opts
number of optimizations of the components basis set done
int vcs(int ipr, int ip1, int maxit)
Solve an equilibrium 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...
VCS_COUNTERS * m_VCount
Timing and iteration counters for the vcs object.
MultiPhase * m_mix
Pointer to the MultiPhase mixture that will be equilibrated.
Declarations for a simple class that implements an Ansi C wall clock timer (see Cantera::clockWC).
doublereal speciesMoles(size_t kGlob) const
Returns the moles of global species k. units = kmol.
doublereal temperature() const
Temperature [K].
doublereal moleFraction(size_t k) const
Return the mole fraction of a single species.
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
size_t nSpecies() const
Number of species, summed over all phases.
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...
int m_printLvl
Print level from the VCSnonlinear package.
T clip(const T &value, const T &lower, const T &upper)
Clip value such that lower <= value <= upper.
size_t nSpecies() const
Returns the number of species in the phase.
doublereal volume() const
The total mixture volume [m^3].
The class provides the wall clock timer in seconds.
doublereal pressure() const
Pressure [Pa].
std::vector< std::unique_ptr< vcs_VolPhase > > m_VolPhaseList
Array of Phase Structures. Length = number of phases.
virtual void getPartialMolarVolumes(doublereal *vbar) const
Return an array of partial molar volumes for the species in the mixture.
void reportCSV(const std::string &reportFile)
Report the equilibrium answer in a comma separated table format.
const doublereal Undef
Fairly random number to be used to initialize variables against to see if they are subsequently defin...
virtual void getActivities(doublereal *a) const
Get the array of non-dimensional activities at the current solution temperature, pressure, and solution concentration.
Base class for a phase with thermodynamic properties.
Contains const definitions for types of species reference-state thermodynamics managers (see Species ...
Header for the object representing each phase within vcs.
int m_doEstimateEquil
Setting for whether to do an initial estimate.
A class for multiphase mixtures.
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...
void getMolalities(doublereal *const molal) const
This function will return the molalities of the species.
doublereal moleFraction(const size_t kGlob) const
Returns the mole fraction of global species k.
double secondsWC()
Returns the wall clock time in seconds since the last reset.
std::string speciesName(size_t k) const
Name of the species with index k.
Header file for an ideal solid solution model with incompressible thermodynamics (see Thermodynamic P...
doublereal maxTemp() const
Maximum temperature for which all solution phases have valid thermo data.
virtual int activityConvention() const
This method returns the convention used in specification of the activities, of which there are curren...
void setTemperature(const doublereal T)
Set the temperature [K].
size_t nSpecies() const
Return the number of species in the phase.
Base class for exceptions thrown by Cantera classes.
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...
void getChemPotentials(doublereal *mu) const
Returns a vector of Chemical potentials.
int m_timing_print_lvl
printing level of timing information
virtual void getActivityCoefficients(doublereal *ac) const
Get the array of non-dimensional molar-based activity coefficients at the current solution temperatur...
int m_printLvl
Print level for print routines.
double totalMoles() const
Return the total moles in the phase.
void setPressure(doublereal P)
Set the pressure [Pa].
double m_temperature
Temperature (Kelvin)
Interface class for the vcsnonlinear solver.
Phase information and Phase calculations for vcs.
VCS_SOLVE m_vsolve
The object that contains the problem statement and does all of the equilibration work.
doublereal entropy() const
The entropy of the mixture [J/K].
double m_pressurePA
Pressure.
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
doublereal minTemp() const
Minimum temperature for which all solution phases have valid thermo data.
doublereal IntEnergy() const
The internal energy of the mixture [J].
std::string name() const
Return the name of the phase.
Contains declarations for string manipulation functions within Cantera.
virtual void getStandardChemPotentials(doublereal *mu) const
Get the array of chemical potentials at unit activity for the species at their standard states at the...
#define plogf
define this Cantera function to replace printf
#define VCS_SPECIES_TYPE_INTERFACIALVOLTAGE
Unknown refers to the voltage level of a phase.
thermo_t & phase(size_t n)
Return a reference to phase n.
doublereal phaseMoles(const size_t n) const
Return the number of moles in phase n.
Namespace for the Cantera kernel.
size_t m_numPhases
Number of Phases in the problem.
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...
doublereal enthalpy() const
The enthalpy of the mixture [J].
std::string speciesName(const size_t kGlob) const
Name of species with global index kGlob.