2116 lines
83 KiB
C++
2116 lines
83 KiB
C++
/**
|
|
* @file vcs_solve.h
|
|
* Header file for the internal object that holds the vcs equilibrium problem
|
|
* (see Class \link Cantera::VCS_SOLVE VCS_SOLVE\endlink and \ref equilfunctions ).
|
|
*/
|
|
/*
|
|
* Copyright (2005) Sandia Corporation. Under the terms of
|
|
* Contract DE-AC04-94AL85000 with Sandia Corporation, the
|
|
* U.S. Government retains certain rights in this software.
|
|
*/
|
|
|
|
|
|
#ifndef _VCS_SOLVE_H
|
|
#define _VCS_SOLVE_H
|
|
|
|
/*
|
|
* Index of Symbols
|
|
* -------------------
|
|
* irxn -> refers to the species or rxn between the species and
|
|
* the components in the problem
|
|
* k -> refers to the species
|
|
* j -> refers to the element or component
|
|
*
|
|
* ### -> to be eliminated
|
|
*/
|
|
#include <vector>
|
|
#include <string>
|
|
|
|
#include "cantera/base/ct_defs.h"
|
|
#include "cantera/equil/vcs_defs.h"
|
|
#include "cantera/equil/vcs_DoubleStarStar.h"
|
|
#include "cantera/equil/vcs_IntStarStar.h"
|
|
#include "cantera/equil/vcs_internal.h"
|
|
|
|
namespace VCSnonideal
|
|
{
|
|
/*
|
|
* Forward references
|
|
*/
|
|
class vcs_VolPhase;
|
|
class VCS_SPECIES_THERMO;
|
|
class VCS_PROB;
|
|
class VCS_COUNTERS;
|
|
|
|
|
|
//! This is the main structure used to hold the internal data
|
|
//! used in vcs_solve_TP(), and to solve TP systems.
|
|
/*!
|
|
* The indices of information in this
|
|
* structure may change when the species basis changes or when
|
|
* phases pop in and out of existence. Both of these operations
|
|
* change the species ordering.
|
|
*
|
|
*/
|
|
class VCS_SOLVE
|
|
{
|
|
public:
|
|
//! Constructor for the VCS_SOLVE class
|
|
VCS_SOLVE();
|
|
|
|
//! Destructor
|
|
~VCS_SOLVE();
|
|
|
|
|
|
//! Initialize the sizes within the VCS_SOLVE object
|
|
/*!
|
|
* This resizes all of the internal arrays within the object. This routine
|
|
* operates in two modes. If all of the parameters are the same as it
|
|
* currently exists in the object, nothing is done by this routine; a quick
|
|
* exit is carried out and all of the data in the object persists.
|
|
*
|
|
* IF any of the parameters are different than currently exists in the
|
|
* object, then all of the data in the object must be redone. It may not
|
|
* be zeroed, but it must be redone.
|
|
*
|
|
* @param nspecies0 Number of species within the object
|
|
* @param nelements Number of element constraints within the problem
|
|
* @param nphase0 Number of phases defined within the problem.
|
|
*
|
|
*/
|
|
void vcs_initSizes(const size_t nspecies0, const size_t nelements, const size_t nphase0);
|
|
|
|
//! Solve an equilibrium problem
|
|
/*!
|
|
* This is the main interface routine to the equilibrium solver
|
|
*
|
|
* Input:
|
|
* @param vprob Object containing the equilibrium Problem statement
|
|
*
|
|
* @param ifunc Determines the operation to be done: Valid values:
|
|
* 0 -> Solve a new problem by initializing structures
|
|
* first. An initial estimate may or may not have
|
|
* been already determined. This is indicated in the
|
|
* VCS_PROB structure.
|
|
* 1 -> The problem has already been initialized and
|
|
* set up. We call this routine to resolve it
|
|
* using the problem statement and
|
|
* solution estimate contained in
|
|
* the VCS_PROB structure.
|
|
* 2 -> Don't solve a problem. Destroy all the private
|
|
* structures.
|
|
*
|
|
* @param ipr Printing of results
|
|
* ipr = 1 -> Print problem statement and final results to
|
|
* standard output
|
|
* 0 -> don't report on anything
|
|
* @param ip1 Printing of intermediate results
|
|
* IP1 = 1 -> Print intermediate results.
|
|
*
|
|
* @param maxit Maximum number of iterations for the algorithm
|
|
*
|
|
* Output:
|
|
*
|
|
* @return
|
|
* nonzero value: failure to solve the problem at hand.
|
|
* zero : success
|
|
*/
|
|
int vcs(VCS_PROB* vprob, int ifunc, int ipr, int ip1, int maxit);
|
|
|
|
//! Main routine that solves for equilibrium at constant T and P
|
|
//! using a variant of the VCS method
|
|
/*!
|
|
* This is the main routine that solves for equilibrium at constant T and P
|
|
* using a variant of the VCS method. Nonideal phases can be accommodated
|
|
* as well.
|
|
*
|
|
* Any number of single-species phases and multi-species phases
|
|
* can be handled by the present version.
|
|
*
|
|
* Input
|
|
* ------------
|
|
* @param print_lvl 1 -> Print results to standard output
|
|
* 0 -> don't report on anything
|
|
*
|
|
* @param printDetails 1 -> Print intermediate results.
|
|
*
|
|
* @param maxit Maximum number of iterations for the algorithm
|
|
*
|
|
* @return 0 = Equilibrium Achieved
|
|
* 1 = Range space error encountered. The element abundance criteria are
|
|
* only partially satisfied. Specifically, the first NC= (number of
|
|
* components) conditions are satisfied. However, the full NE
|
|
* (number of elements) conditions are not satisfied. The equilibrium
|
|
* condition is returned.
|
|
* -1 = Maximum number of iterations is exceeded. Convergence was not
|
|
* found.
|
|
*/
|
|
int vcs_solve_TP(int print_lvl, int printDetails, int maxit);
|
|
|
|
|
|
int vcs_PS(VCS_PROB* vprob, int iph, int printLvl, double& feStable);
|
|
|
|
void vcs_reinsert_deleted(size_t kspec);
|
|
|
|
//! Choose the optimum species basis for the calculations
|
|
/*!
|
|
* Choose the optimum component species basis for the calculations.
|
|
* This is done by choosing the species with the largest mole fraction
|
|
* not currently a linear combination of the previous components.
|
|
* Then, calculate the stoichiometric coefficient matrix for that
|
|
* basis.
|
|
*
|
|
* Rearranges the solution data to put the component data at the
|
|
* front of the species list.
|
|
*
|
|
* Then, calculates m_stoichCoeffRxnMatrix[irxn][jcomp] the formation reactions
|
|
* for all noncomponent species in the mechanism.
|
|
* Also calculates DNG(I) and DNL(I), the net mole change for each
|
|
* formation reaction.
|
|
* Also, initializes IR(I) to the default state.
|
|
*
|
|
* Input
|
|
* ---------
|
|
* @param doJustComponents If true, the m_stoichCoeffRxnMatrix[][] and
|
|
* m_deltaMolNumPhase[] are not calculated.
|
|
*
|
|
* @param aw Vector of mole fractions which will be used to construct an
|
|
* optimal basis from.
|
|
*
|
|
* @param sa Gram-Schmidt orthog work space (nc in length) sa[j]
|
|
* @param ss Gram-Schmidt orthog work space (nc in length) ss[j]
|
|
* @param sm QR matrix work space (nc*ne in length) sm[i+j*ne]
|
|
* @param test This is a small negative number dependent upon whether
|
|
* an estimate is supplied or not.
|
|
*
|
|
* Output
|
|
* ---------
|
|
* @param usedZeroedSpecies = If true, then a species with a zero concentration
|
|
* was used as a component. The problem may be
|
|
* converged. Or, the problem may have a range space
|
|
* error and may not have a proper solution.
|
|
*
|
|
* Internal Variables calculated by this routine:
|
|
* -----------------------------------------------
|
|
*
|
|
* m_numComponents
|
|
* Number of component species
|
|
*
|
|
* component species
|
|
* This routine calculates the m_numComponent species. It switches
|
|
* their positions in the species vector so that they occupy
|
|
* the first m_numComponent spots in the species vector.
|
|
*
|
|
* m_stoichCoeffRxnMatrix[irxn][jcomp]
|
|
* Stoichiometric coefficient matrix for the reaction mechanism
|
|
* expressed in Reduced Canonical Form.
|
|
* jcomp refers to the component number, and irxn
|
|
* refers to the irxn_th non-component species.
|
|
*
|
|
* m_deltaMolNumPhase[irxn]
|
|
* Change in the number of total number of moles of species in all phases
|
|
* due to the noncomponent formation reaction, irxn.
|
|
*
|
|
* m_deltaMolNumPhase[irxn][iphase]
|
|
* Change in the number of moles in phase, iphase, due to the
|
|
* noncomponent formation reaction, irxn.
|
|
*
|
|
* m_phaseParticipation[irxn]
|
|
* This is 1 if the phase, iphase, participates in the
|
|
* formation reaction, irxn, and zero otherwise.
|
|
*
|
|
* @return Returns VCS_SUCCESS if everything went ok. Returns
|
|
* VCS_FAILED_CONVERGENCE if there is a problem.
|
|
*/
|
|
int vcs_basopt(const bool doJustComponents, double aw[], double sa[], double sm[],
|
|
double ss[], double test, bool* const usedZeroedSpecies);
|
|
|
|
//! Choose a species to test for the next component
|
|
/*!
|
|
* We make the choice based on testing (molNum[i] * spSize[i]) for its maximum value.
|
|
* Preference for single species phases is also made.
|
|
*
|
|
* @param molNum Mole number vector
|
|
* @param j index into molNum[] that indicates where the search will start from
|
|
* Previous successful components are swapped into the front of
|
|
* molNum[].
|
|
* @param n Length of molNum[]
|
|
*/
|
|
size_t vcs_basisOptMax(const double* const molNum, const size_t j, const size_t n);
|
|
|
|
//! Evaluate the species category for the indicated species
|
|
/*!
|
|
* All evaluations are done using the "old" version of the solution.
|
|
*
|
|
* @param kspec Species to be evaluated
|
|
*
|
|
* @return Returns the calculated species type
|
|
*/
|
|
int vcs_species_type(const size_t kspec) const;
|
|
|
|
bool vcs_evaluate_speciesType();
|
|
|
|
//! We calculate the dimensionless chemical potentials of all species
|
|
//! in a single phase.
|
|
/*!
|
|
* We calculate the dimensionless chemical potentials of all species
|
|
* in a single phase.
|
|
*
|
|
* Note, for multispecies phases which are currently zeroed out,
|
|
* the chemical potential is filled out with the standard chemical
|
|
* potential.
|
|
*
|
|
* For species in multispecies phases whose concentration is zero,
|
|
* we need to set the mole fraction to a very low value.
|
|
* Its chemical potential
|
|
* is then calculated using the VCS_DELETE_MINORSPECIES_CUTOFF concentration
|
|
* to keep numbers positive.
|
|
*
|
|
* Formula:
|
|
* ---------------
|
|
*
|
|
* Ideal Mixtures:
|
|
*
|
|
* m_feSpecies(I) = m_SSfeSpecies(I) + ln(z(I)) - ln(m_tPhaseMoles[iph])
|
|
* + m_chargeSpecies[I] * Faraday_dim * m_phasePhi[iphase];
|
|
*
|
|
*
|
|
* ( This is equivalent to the adding the log of the
|
|
* mole fraction onto the standard chemical
|
|
* potential. )
|
|
*
|
|
* Non-Ideal Mixtures:
|
|
* ActivityConvention = 0:
|
|
*
|
|
* m_feSpecies(I) = m_SSfeSpecies(I)
|
|
* + ln(ActCoeff[I] * z(I)) - ln(m_tPhaseMoles[iph])
|
|
* + m_chargeSpecies[I] * Faraday_dim * m_phasePhi[iphase];
|
|
*
|
|
* ( This is equivalent to the adding the log of the
|
|
* mole fraction multiplied by the activity coefficient
|
|
* onto the standard chemical potential. )
|
|
*
|
|
* ActivityConvention = 1: -> molality activity formulation
|
|
*
|
|
* m_feSpecies(I) = m_SSfeSpecies(I)
|
|
* + ln(ActCoeff[I] * z(I)) - ln(m_tPhaseMoles[iph])
|
|
* - ln(Mnaught * m_units)
|
|
* + m_chargeSpecies[I] * Faraday_dim * m_phasePhi[iphase];
|
|
*
|
|
* note: m_SSfeSpecies(I) is the molality based standard state.
|
|
* However, ActCoeff[I] is the molar based activity coefficient
|
|
* We have used the formulas;
|
|
*
|
|
* ActCoeff_M[I] = ActCoeff[I] / Xmol[N]
|
|
* where Xmol[N] is the mole fraction of the solvent
|
|
* ActCoeff_M[I] is the molality based act coeff.
|
|
*
|
|
* note: This is equivalent to the "normal" molality formulation:
|
|
*
|
|
* m_feSpecies(I) = m_SSfeSpecies(I)
|
|
* + ln(ActCoeff_M[I] * m(I))
|
|
* + m_chargeSpecies[I] * Faraday_dim * m_phasePhi[iphase]
|
|
* where m[I] is the molality of the ith solute
|
|
*
|
|
* m[I] = Xmol[I] / ( Xmol[N] * Mnaught * m_units)
|
|
*
|
|
*
|
|
* note: z(I)/tPhMoles_ptr[iph] = Xmol[i] is the mole fraction
|
|
* of i in the phase.
|
|
*
|
|
*
|
|
* NOTE:
|
|
* As per the discussion in vcs_dfe(), for small species where the mole
|
|
* fraction is small:
|
|
*
|
|
* z(i) < VCS_DELETE_MINORSPECIES_CUTOFF
|
|
*
|
|
* The chemical potential is calculated as:
|
|
*
|
|
* m_feSpecies(I) = m_SSfeSpecies(I)
|
|
* + ln(ActCoeff[i](VCS_DELETE_MINORSPECIES_CUTOFF))
|
|
*
|
|
* Input
|
|
* --------
|
|
* iph : Phase to be calculated
|
|
* molNum(i) : Number of moles of species i
|
|
* (VCS species order)
|
|
* ff : standard state chemical potentials. These are the
|
|
* chemical potentials of the standard states at
|
|
* the same T and P as the solution.
|
|
* (VCS species order)
|
|
* Output
|
|
* -------
|
|
* ac[] : Activity coefficients for species in phase
|
|
* (VCS species order)
|
|
* mu_i[] : Dimensionless chemical potentials for phase species
|
|
* (VCS species order)
|
|
*
|
|
*/
|
|
void vcs_chemPotPhase(const int stateCalc, const size_t iph, const double* const molNum,
|
|
double* const ac, double* const mu_i,
|
|
const bool do_deleted = false);
|
|
|
|
//! Calculate the dimensionless chemical potentials of all species or
|
|
//! of certain groups of species, at a fixed temperature and pressure.
|
|
/*!
|
|
* We calculate the dimensionless chemical potentials of all species
|
|
* or certain groups of species here, at a fixed temperature and pressure,
|
|
* for the input mole vector z[] in the parameter list.
|
|
* Nondimensionalization is achieved by division by RT.
|
|
*
|
|
* Note, for multispecies phases which are currently zeroed out,
|
|
* the chemical potential is filled out with the standard chemical
|
|
* potential.
|
|
*
|
|
* For species in multispecies phases whose concentration is zero,
|
|
* we need to set the mole fraction to a very low value.
|
|
* Its chemical potential
|
|
* is then calculated using the VCS_DELETE_MINORSPECIES_CUTOFF concentration
|
|
* to keep numbers positive.
|
|
*
|
|
*
|
|
* Formula:
|
|
* ---------------
|
|
*
|
|
* Ideal Mixtures:
|
|
*
|
|
* m_feSpecies(I) = m_SSfeSpecies(I) + ln(z(I)) - ln(m_tPhaseMoles[iph])
|
|
* + Charge[I] * Faraday_dim * phasePhi[iphase];
|
|
*
|
|
* ( This is equivalent to the adding the log of the
|
|
* mole fraction onto the standard chemical
|
|
* potential. )
|
|
*
|
|
* Non-Ideal Mixtures: -> molar activity formulation
|
|
* ActivityConvention = 0:
|
|
*
|
|
* m_feSpecies(I) = m_SSfeSpecies(I)
|
|
* + ln(ActCoeff[I] * z(I)) - ln(m_tPhaseMoles[iph])
|
|
* + Charge[I] * Faraday_dim * phasePhi[iphase];
|
|
*
|
|
* ( This is equivalent to the adding the log of the
|
|
* mole fraction multiplied by the activity coefficient
|
|
* onto the standard chemical potential. )
|
|
*
|
|
* note: z(I)/tPhMoles_ptr[iph] = Xmol[i] is the mole fraction
|
|
* of i in the phase.
|
|
*
|
|
* ActivityConvention = 1: -> molality activity formulation
|
|
*
|
|
* m_feSpecies(I) = m_SSfeSpecies(I)
|
|
* + ln(ActCoeff[I] * z(I)) - ln(m_tPhaseMoles[iph])
|
|
* - ln(Mnaught * m_units)
|
|
* + Charge[I] * Faraday_dim * phasePhi[iphase];
|
|
*
|
|
* note: m_SSfeSpecies(I) is the molality based standard state.
|
|
* However, ActCoeff[I] is the molar based activity coefficient
|
|
* We have used the formulas;
|
|
*
|
|
* ActCoeff_M[I] = ActCoeff[I] / Xmol[N]
|
|
* where Xmol[N] is the mole fraction of the solvent
|
|
* ActCoeff_M[I] is the molality based act coeff.
|
|
*
|
|
* m_feSpecies(I) = m_SSfeSpecies(I)
|
|
* + ln(ActCoeff_M[I] * m(I))
|
|
* + Charge[I] * Faraday_dim * phasePhi[iphase];
|
|
* where m[I] is the molality of the ith solute
|
|
*
|
|
* m[I] = Xmol[I] / ( Xmol[N] * Mnaught * m_units)
|
|
*
|
|
*
|
|
* Handling of Small Species:
|
|
* ------------------------------
|
|
* As per the discussion above, for small species where the mole
|
|
* fraction
|
|
*
|
|
* z(i) < VCS_DELETE_MINORSPECIES_CUTOFF
|
|
*
|
|
* The chemical potential is calculated as:
|
|
*
|
|
* m_feSpecies(I)(I) = m_SSfeSpecies(I) + ln(ActCoeff[i](VCS_DELETE_MINORSPECIES_CUTOFF))
|
|
*
|
|
* Species in the following categories are treated as "small species"
|
|
*
|
|
* - VCS_SPECIES_DELETED
|
|
* - VCS_SPECIES_ACTIVEBUTZERO
|
|
* .
|
|
*
|
|
* Handling of Small Species:
|
|
* ------------------------------
|
|
* For species in multispecies phases which are currently not active, the
|
|
* treatment is different. These species are in the following species categories:
|
|
*
|
|
* - VCS_SPECIES_ZEROEDMS
|
|
* - VCS_SPECIES_ZEROEDPHASE
|
|
* .
|
|
*
|
|
* For these species, the ln( ActCoeff[I] X[I]) term is
|
|
* dropped altogether. The following equation is used.
|
|
*
|
|
* m_feSpecies(I) = m_SSfeSpecies(I)
|
|
* + Charge[I] * Faraday_dim * phasePhi[iphase];
|
|
*
|
|
*
|
|
* Handling of "Species" Representing Interfacial Voltages
|
|
* ---------------------------------------------------------
|
|
*
|
|
* These species have species types of VCS_SPECIES_TYPE_INTERFACIALVOLTAGE
|
|
* The chemical potentials for these "species" refer to electrons in
|
|
* metal electrodes. They have the following formula
|
|
*
|
|
* m_feSpecies(I) = m_SSfeSpecies(I) - F z[I] / RT
|
|
*
|
|
* F is Faraday's constant.
|
|
* R = gas constant
|
|
* T = temperature
|
|
* V = potential of the interface = phi_electrode - phi_solution
|
|
*
|
|
* For these species, the solution vector unknown, z[I], is V, the phase voltage, in volts.
|
|
*
|
|
* Input
|
|
* --------
|
|
* @param ll Determine which group of species gets updated
|
|
* ll = 0: Calculate for all species
|
|
* < 0: calculate for components and for major non-components
|
|
* 1: calculate for components and for minor non-components
|
|
*
|
|
* @param lbot Restricts the calculation of the chemical potential
|
|
* to the species between LBOT <= i < LTOP. Usually
|
|
* LBOT and LTOP will be equal to 0 and MR, respectively.
|
|
* @param ltop Top value of the loops
|
|
*
|
|
*
|
|
* @param stateCalc Determines whether z is old or new or tentative:
|
|
* 1: Use the tentative values for the total number of
|
|
* moles in the phases, i.e., use TG1 instead of TG etc.
|
|
* 0: Use the base values of the total number of
|
|
* moles in each system.
|
|
*
|
|
* Also needed:
|
|
* ff : standard state chemical potentials. These are the
|
|
* chemical potentials of the standard states at
|
|
* the same T and P as the solution.
|
|
* tg : Total Number of moles in the phase.
|
|
*/
|
|
void vcs_dfe(const int stateCalc, const int ll, const size_t lbot, const size_t ltop);
|
|
|
|
//! Print out a table of chemical potentials
|
|
/*!
|
|
* @param stateCalc Determines where to get the mole numbers from.
|
|
* - VCS_STATECALC_OLD -> from m_molNumSpecies_old
|
|
* - VCS_STATECALC_NEW -> from m_molNumSpecies_new
|
|
*/
|
|
void vcs_printSpeciesChemPot(const int stateCalc) const;
|
|
|
|
//! This routine uploads the state of the system into all of the
|
|
//! vcs_VolumePhase objects in the current problem.
|
|
/*!
|
|
* @param stateCalc Determines where to get the mole numbers from.
|
|
* - VCS_STATECALC_OLD -> from m_molNumSpecies_old
|
|
* - VCS_STATECALC_NEW -> from m_molNumSpecies_new
|
|
*/
|
|
void vcs_updateVP(const int stateCalc);
|
|
|
|
//! Utility function that evaluates whether a phase can be popped
|
|
//! into existence
|
|
/*!
|
|
* @param iphasePop id of the phase, which is currently zeroed,
|
|
*
|
|
* @return Returns true if the phase can come into existence
|
|
* and false otherwise.
|
|
*/
|
|
bool vcs_popPhasePossible(const size_t iphasePop) const;
|
|
|
|
|
|
//! Determine the list of problems that need to be checked to see if there are any phases pops
|
|
/*!
|
|
* This routine evaluates and fills in the following quantities
|
|
* phasePopProblemLists_
|
|
*
|
|
* @return Returns the number of problems that must be checked.
|
|
*/
|
|
int vcs_phasePopDeterminePossibleList();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Decision as to whether a phase pops back into existence
|
|
/*!
|
|
* @param phasePopPhaseIDs Vector containing the phase ids of the phases
|
|
* that will be popped this step.
|
|
*
|
|
* @return returns the phase id of the phase that pops back into
|
|
* existence. Returns -1 if there are no phases
|
|
*/
|
|
size_t vcs_popPhaseID(std::vector<size_t> &phasePopPhaseIDs);
|
|
|
|
//! Calculates the deltas of the reactions due to phases popping
|
|
//! into existence
|
|
/*!
|
|
* @param iphasePop Phase id of the phase that will come into existence
|
|
*
|
|
* @return Returns an int representing the status of the step
|
|
* - 0 : normal return
|
|
* - 1 : A single species phase species has been zeroed out
|
|
* in this routine. The species is a noncomponent
|
|
* - 2 : Same as one but, the zeroed species is a component.
|
|
*/
|
|
int vcs_popPhaseRxnStepSizes(const size_t iphasePop);
|
|
|
|
//! Calculates formation reaction step sizes.
|
|
/*!
|
|
* This is equation 6.4-16, p. 143 in Smith and Missen.
|
|
*
|
|
* Output
|
|
* -------
|
|
* m_deltaMolNumSpecies(irxn) : reaction adjustments, where irxn refers
|
|
* to the irxn'th species
|
|
* formation reaction. This adjustment is for species
|
|
* irxn + M, where M is the number of components.
|
|
*
|
|
* Special branching occurs sometimes. This causes the component basis
|
|
* to be reevaluated
|
|
*
|
|
* @param forceComponentCalc integer flagging whether a component recalculation needs
|
|
* to be carried out.
|
|
* @param kSpecial species number of phase being zeroed.
|
|
*
|
|
* @return Returns an int representing which phase may need to be zeroed
|
|
*/
|
|
size_t vcs_RxnStepSizes(int& forceComponentCalc, size_t& kSpecial);
|
|
|
|
//! Calculates the total number of moles of species in all phases.
|
|
/*!
|
|
* Calculates the total number of moles in all phases and updates
|
|
* the variable m_totalMolNum.
|
|
* Reconciles Phase existence flags with total moles in each phase.
|
|
*/
|
|
double vcs_tmoles();
|
|
#ifdef DEBUG_MODE
|
|
void check_tmoles() const;
|
|
#endif
|
|
|
|
//! This subroutine calculates reaction free energy changes for
|
|
//! all noncomponent formation reactions.
|
|
/*!
|
|
* Formation reactions are
|
|
* reactions which create each noncomponent species from the component
|
|
* species. m_stoichCoeffRxnMatrix[irxn][jcomp] are the stoichiometric
|
|
* coefficients for these reactions. A stoichiometric coefficient of
|
|
* one is assumed for species irxn in this reaction.
|
|
*
|
|
* INPUT
|
|
* @param l
|
|
* L < 0 : Calculate reactions corresponding to
|
|
* major noncomponent and zeroed species only
|
|
* L = 0 : Do all noncomponent reactions, i, between
|
|
* 0 <= i < irxnl
|
|
* L > 0 : Calculate reactions corresponding to
|
|
* minor noncomponent and zeroed species only
|
|
*
|
|
* @param doDeleted Do deleted species
|
|
* @param vcsState Calculate deltaG corresponding to either old or new
|
|
* free energies
|
|
* @param alterZeroedPhases boolean indicating whether we should
|
|
* add in a special section for zeroed phases.
|
|
*
|
|
* Note we special case one important issue.
|
|
* If the component has zero moles, then we do not
|
|
* allow deltaG < 0.0 for formation reactions which
|
|
* would lead to the loss of more of that same component.
|
|
* This dG < 0.0 condition feeds back into the algorithm in several
|
|
* places, and leads to a infinite loop in at least one case.
|
|
*/
|
|
void vcs_deltag(const int l, const bool doDeleted, const int vcsState,
|
|
const bool alterZeroedPhases = true);
|
|
|
|
void vcs_printDeltaG(const int stateCalc);
|
|
|
|
//! Calculate deltag of formation for all species in a single phase.
|
|
/*!
|
|
* Calculate deltag of formation for all species in a single
|
|
* phase. It is assumed that the fe[] is up to date for all species.
|
|
* However, if the phase is currently zeroed out, a subproblem
|
|
* is calculated to solve for AC[i] and pseudo-X[i] for that
|
|
* phase.
|
|
*
|
|
* @param iphase phase index of the phase to be calculated
|
|
* @param doDeleted boolean indicating whether to do deleted
|
|
* species or not
|
|
* @param stateCalc integer describing which set of free energies
|
|
* to use and where to stick the results.
|
|
* @param alterZeroedPhases boolean indicating whether we should
|
|
* add in a special section for zeroed phases.
|
|
*
|
|
* NOTE: this is currently not used used anywhere.
|
|
* It may be in the future?
|
|
*/
|
|
void vcs_deltag_Phase(const size_t iphase, const bool doDeleted,
|
|
const int stateCalc, const bool alterZeroedPhases = true);
|
|
|
|
//! Swaps the indices for all of the global data for two species, k1
|
|
//! and k2.
|
|
/*!
|
|
*
|
|
* @param ifunc: If true, switch the species data and the noncomponent reaction
|
|
* data. This must be called for a non-component species only.
|
|
* If false, switch the species data only. Typically, we use this
|
|
* option when determining the component species and at the
|
|
* end of the calculation, when we want to return unscrambled
|
|
* results. All rxn data will be out-of-date.
|
|
*
|
|
* @param k1 First species index
|
|
*
|
|
* @param k2 Second species index
|
|
*/
|
|
void vcs_switch_pos(const bool ifunc, const size_t k1, const size_t k2);
|
|
|
|
|
|
//! Birth guess returns the number of moles of a species
|
|
//! that is coming back to life.
|
|
/*!
|
|
* Birth guess returns the number of moles of a species
|
|
* that is coming back to life.
|
|
* Note, this routine is not applicable if the whole phase is coming
|
|
* back to life, not just one species in that phase.
|
|
*
|
|
* Do a minor alt calculation. But, cap the mole numbers at
|
|
* 1.0E-15.
|
|
* For SS phases use VCS_DELETE_SPECIES_CUTOFF * 100.
|
|
*
|
|
* The routine makes sure the guess doesn't reduce the concentration
|
|
* of a component by more than 1/3. Note this may mean that
|
|
* the vlaue coming back from this routine is zero or a
|
|
* very small number.
|
|
*
|
|
*
|
|
* @param kspec Species number that is coming back to life
|
|
*
|
|
* @return Returns the number of kmol that the species should
|
|
* have.
|
|
*/
|
|
double vcs_birthGuess(const int kspec);
|
|
|
|
int vcs_solve_phaseStability(const int iphase, int ifunc, double& funcval, int print_lvl);
|
|
|
|
//! Main program to test whether a deleted phase should be brought
|
|
//! back into existence
|
|
/*!
|
|
*
|
|
* @param iph Phase id of the deleted phase
|
|
*/
|
|
double vcs_phaseStabilityTest(const size_t iph);
|
|
|
|
//! Solve an equilibrium problem at a particular fixed temperature
|
|
//! and pressure
|
|
/*!
|
|
* The actual problem statement is assumed to be in the structure
|
|
* already. This is a wrapper around the solve_TP() function.
|
|
* In this wrapper, we nondimensionalize the system
|
|
* we calculate the standard state gibbs free energies of the
|
|
* species, and we decide whether to we need to use the
|
|
* initial guess algorithm.
|
|
*
|
|
* @param ipr = 1 -> Print results to standard output
|
|
* 0 -> don't report on anything
|
|
* @param ip1 = 1 -> Print intermediate results.
|
|
* 0 -> Dont print any intermediate results
|
|
* @param maxit Maximum number of iterations for the algorithm
|
|
* @param T Value of the Temperature (Kelvin)
|
|
* Param pres Value of the Pressure (units given by m_VCS_UnitsFormat variable
|
|
*
|
|
* @return Returns an integer representing the success of the algorithm
|
|
* 0 = Equilibrium Achieved
|
|
* 1 = Range space error encountered. The element abundance criteria are
|
|
* only partially satisfied. Specifically, the first NC= (number of
|
|
* components) conditions are satisfied. However, the full NE
|
|
* (number of elements) conditions are not satisfied. The equilibrium
|
|
* condition is returned.
|
|
* -1 = Maximum number of iterations is exceeded. Convergence was not
|
|
* found.
|
|
*/
|
|
int vcs_TP(int ipr, int ip1, int maxit, double T, double pres);
|
|
|
|
int vcs_evalSS_TP(int ipr, int ip1, double Temp, double pres);
|
|
|
|
//! Initialize the chemical potential of single species phases
|
|
/*!
|
|
* For single species phases, initialize the chemical
|
|
* potential with the value of the standard state chemical
|
|
* potential. This value doesn't change during the calculation
|
|
*/
|
|
void vcs_fePrep_TP();
|
|
|
|
//! Calculation of the total volume and the partial molar volumes
|
|
/*!
|
|
* This function calculates the partial molar volume
|
|
* for all species, kspec, in the thermo problem
|
|
* at the temperature TKelvin and pressure, Pres, pres is in atm.
|
|
* And, it calculates the total volume of the combined system.
|
|
*
|
|
* Input
|
|
* ---------------
|
|
* @param tkelvin Temperature in kelvin()
|
|
* @param pres Pressure in Pascal
|
|
* @param w w[] is the vector containing the current mole numbers
|
|
* in units of kmol.
|
|
*
|
|
* Output
|
|
* ----------------
|
|
* @param volPM[] For species in all phase, the entries are the
|
|
* partial molar volumes units of M**3 / kmol.
|
|
*
|
|
* @return The return value is the total volume of
|
|
* the entire system in units of m**3.
|
|
*/
|
|
double vcs_VolTotal(const double tkelvin, const double pres,
|
|
const double w[], double volPM[]);
|
|
|
|
//! This routine is mostly concerned with changing the private data
|
|
//! to be consistent with what's needed for solution. It is called one
|
|
//! time for each new problem structure definition.
|
|
/*!
|
|
* This routine is always followed by vcs_prep(). Therefore, tasks
|
|
* that need to be done for every call to vcsc() should be placed in
|
|
* vcs_prep() and not in this routine.
|
|
*
|
|
* The problem structure refers to:
|
|
*
|
|
* the number and identity of the species.
|
|
* the formula matrix and thus the number of components.
|
|
* the number and identity of the phases.
|
|
* the equation of state
|
|
* the method and parameters for determining the standard state
|
|
* The method and parameters for determining the activity coefficients.
|
|
*
|
|
* Tasks:
|
|
* 0) Fill in the SSPhase[] array.
|
|
* 1) Check to see if any multispecies phases actually have only one
|
|
* species in that phase. If true, reassign that phase and species
|
|
* to be a single-species phase.
|
|
* 2) Determine the number of components in the problem if not already
|
|
* done so. During this process the order of the species is changed
|
|
* in the private data structure. All references to the species
|
|
* properties must employ the ind[] index vector.
|
|
*
|
|
* @param printLvl Print level of the routine
|
|
*
|
|
* @return the return code
|
|
* VCS_SUCCESS = everything went OK
|
|
*
|
|
*/
|
|
int vcs_prep_oneTime(int printLvl);
|
|
|
|
//! Prepare the object for solution
|
|
/*!
|
|
* This routine is mostly concerned with changing the private data
|
|
* to be consistent with that needed for solution. It is called for
|
|
* every invocation of the vcs_solve() except for the cleanup invocation.
|
|
*
|
|
* Tasks:
|
|
* 1) Initialization of arrays to zero.
|
|
*
|
|
* return code
|
|
* VCS_SUCCESS = everything went OK
|
|
* VCS_PUB_BAD = There is an irreconcilable difference in the
|
|
* public data structure from when the problem was
|
|
* initially set up.
|
|
*/
|
|
int vcs_prep();
|
|
|
|
//! In this routine, we check for things that will cause the algorithm
|
|
//! to fail.
|
|
/*!
|
|
* We check to see if the problem is well posed. If it is not, we return
|
|
* false and print out error conditions.
|
|
*
|
|
* Current there is one condition. If all the element abundances are
|
|
* zero, the algorithm will fail.
|
|
*
|
|
* @param vprob VCS_PROB pointer to the definition of the equilibrium
|
|
* problem
|
|
*
|
|
* @return If true, the problem is well-posed. If false, the problem
|
|
* is not well posed.
|
|
*/
|
|
bool vcs_wellPosed(VCS_PROB* vprob);
|
|
|
|
//! Rearrange the constraint equations represented by the Formula
|
|
//! Matrix so that the operational ones are in the front
|
|
/*!
|
|
*
|
|
* This subroutine handles the rearrangement of the constraint
|
|
* equations represented by the Formula Matrix. Rearrangement is only
|
|
* necessary when the number of components is less than the number of
|
|
* elements. For this case, some constraints can never be satisfied
|
|
* exactly, because the range space represented by the Formula
|
|
* Matrix of the components can't span the extra space. These
|
|
* constraints, which are out of the range space of the component
|
|
* Formula matrix entries, are migrated to the back of the Formula
|
|
* matrix.
|
|
*
|
|
* A prototypical example is an extra element column in
|
|
* FormulaMatrix[],
|
|
* which is identically zero. For example, let's say that argon is
|
|
* has an element column in FormulaMatrix[], but no species in the
|
|
* mechanism
|
|
* actually contains argon. Then, nc < ne. Also, without perturbation
|
|
* of FormulaMatrix[] vcs_basopt[] would produce a zero pivot
|
|
* because the matrix
|
|
* would be singular (unless the argon element column was already the
|
|
* last column of FormulaMatrix[].
|
|
* This routine borrows heavily from vcs_basopt's algorithm. It
|
|
* finds nc constraints which span the range space of the Component
|
|
* Formula matrix, and assigns them as the first nc components in the
|
|
* formula matrix. This guarantees that vcs_basopt[] has a
|
|
* nonsingular matrix to invert.
|
|
*
|
|
* Other Variables
|
|
* @param aw aw[i[ Mole fraction work space (ne in length)
|
|
* @param sa sa[j] = Gram-Schmidt orthog work space (ne in length)
|
|
* @param sm sm[i+j*ne] = QR matrix work space (ne*ne in length)
|
|
* @param ss ss[j] = Gram-Schmidt orthog work space (ne in length)
|
|
*
|
|
*/
|
|
int vcs_elem_rearrange(double* const aw, double* const sa,
|
|
double* const sm, double* const ss);
|
|
|
|
//! Swaps the indices for all of the global data for two elements, ipos
|
|
//! and jpos.
|
|
/*!
|
|
* This function knows all of the element information with VCS_SOLVE, and
|
|
* can therefore switch element positions
|
|
*
|
|
* @param ipos first global element index
|
|
* @param jpos second global element index
|
|
*/
|
|
void vcs_switch_elem_pos(size_t ipos, size_t jpos);
|
|
|
|
//! Calculates reaction adjustments using a full Hessian approximation
|
|
/*!
|
|
* Calculates reaction adjustments. This does what equation 6.4-16, p. 143
|
|
* in Smith and Missen is suppose to do. However, a full matrix is
|
|
* formed and then solved via a conjugate gradient algorithm. No
|
|
* preconditioning is done.
|
|
*
|
|
* If special branching is warranted, then the program bails out.
|
|
*
|
|
* Output
|
|
* -------
|
|
* DS(I) : reaction adjustment, where I refers to the Ith species
|
|
* Special branching occurs sometimes. This causes the component basis
|
|
* to be reevaluated
|
|
* return = 0 : normal return
|
|
* 1 : A single species phase species has been zeroed out
|
|
* in this routine. The species is a noncomponent
|
|
* 2 : Same as one but, the zeroed species is a component.
|
|
*
|
|
* Special attention is taken to flag cases where the direction of the
|
|
* update is contrary to the steepest descent rule. This is an important
|
|
* attribute of the regular vcs algorithm. We don't want to violate this.
|
|
*
|
|
* NOTE: currently this routine is not used.
|
|
*/
|
|
int vcs_rxn_adj_cg(void);
|
|
|
|
//! Calculates the diagonal contribution to the Hessian due to
|
|
//! the dependence of the activity coefficients on the mole numbers.
|
|
/*!
|
|
* (See framemaker notes, Eqn. 20 - VCS Equations document)
|
|
*
|
|
* We allow the diagonal to be increased positively to any degree.
|
|
* We allow the diagonal to be decreased to 1/3 of the ideal solution
|
|
* value, but no more -> it must remain positive.
|
|
*
|
|
* NOTE: currently this routine is not used
|
|
*/
|
|
double vcs_Hessian_diag_adj(size_t irxn, double hessianDiag_Ideal);
|
|
|
|
//! Calculates the diagonal contribution to the Hessian due to
|
|
//! the dependence of the activity coefficients on the mole numbers.
|
|
/*!
|
|
* (See framemaker notes, Eqn. 20 - VCS Equations document)
|
|
*
|
|
* NOTE: currently this routine is not used
|
|
*/
|
|
double vcs_Hessian_actCoeff_diag(size_t irxn);
|
|
|
|
void vcs_CalcLnActCoeffJac(const double* const moleSpeciesVCS);
|
|
|
|
#ifdef DEBUG_MODE
|
|
//! A line search algorithm is carried out on one reaction
|
|
/*!
|
|
* In this routine we carry out a rough line search algorithm
|
|
* to make sure that the m_deltaGRxn_new doesn't switch signs prematurely.
|
|
*
|
|
* @param irxn Reaction number
|
|
* @param dx_orig Original step length
|
|
*
|
|
* @param ANOTE Output character string stating the conclusions of the
|
|
* line search
|
|
*
|
|
*/
|
|
double vcs_line_search(const size_t irxn, const double dx_orig,
|
|
char* const ANOTE);
|
|
#else
|
|
double vcs_line_search(const size_t irxn, const double dx_orig);
|
|
#endif
|
|
|
|
|
|
//! Print out a report on the state of the equilibrium problem to
|
|
//! standard output.
|
|
/*!
|
|
* @param iconv Indicator of convergence, to be printed out in the report:
|
|
* - 0 converged
|
|
* - 1 range space error
|
|
* - -1 not converged
|
|
*/
|
|
int vcs_report(int iconv);
|
|
|
|
//! Switch all species data back to the original order.
|
|
/*!
|
|
* This destroys the data based on reaction ordering.
|
|
*/
|
|
int vcs_rearrange();
|
|
|
|
//! Returns the multiplier for electric charge terms
|
|
/*
|
|
* This is basically equal to F/RT
|
|
*
|
|
* @param mu_units integer representing the dimensional units system
|
|
* @param TKelvin double Temperature in Kelvin
|
|
*
|
|
* @return Returns the value of F/RT
|
|
*/
|
|
double vcs_nondim_Farad(int mu_units, double TKelvin) const;
|
|
|
|
//! Returns the multiplier for the nondimensionalization of the equations
|
|
/*!
|
|
* This is basically equal to RT
|
|
*
|
|
* @param mu_units integer representing the dimensional units system
|
|
* @param TKelvin double Temperature in Kelvin
|
|
*
|
|
* @return Returns the value of RT
|
|
*/
|
|
double vcs_nondimMult_TP(int mu_units, double TKelvin) const;
|
|
|
|
//! Nondimensionalize the problem data
|
|
/*!
|
|
* Nondimensionalize the free energies using the divisor, R * T
|
|
*
|
|
* Essentially the internal data can either be in dimensional form
|
|
* or in nondimensional form. This routine switches the data from
|
|
* dimensional form into nondimensional form.
|
|
*
|
|
* What we do is to divide by RT.
|
|
*
|
|
* @todo Add a scale factor based on the total mole numbers.
|
|
* The algorithm contains hard coded numbers based on the
|
|
* total mole number. If we ever were faced with a problem
|
|
* with significantly different total kmol numbers than one
|
|
* the algorithm would have problems.
|
|
*/
|
|
void vcs_nondim_TP();
|
|
|
|
//! Redimensionalize the problem data
|
|
/*!
|
|
* Reddimensionalize the free energies using the multiplier R * T
|
|
*
|
|
* Essentially the internal data can either be in dimensional form
|
|
* or in nondimensional form. This routine switches the data from
|
|
* nondimensional form into dimensional form.
|
|
*
|
|
* What we do is to multiply by RT.
|
|
*/
|
|
void vcs_redim_TP();
|
|
|
|
//! Print the string representing the Chemical potential units
|
|
/*!
|
|
* This gets printed using plogf()
|
|
*
|
|
* @param unitsFormat Integer representing the units system
|
|
*/
|
|
void vcs_printChemPotUnits(int unitsFormat) const;
|
|
|
|
//! Computes the current elemental abundances vector
|
|
/*!
|
|
* Computes the elemental abundances vector, m_elemAbundances[], and stores it
|
|
* back into the global structure
|
|
*/
|
|
void vcs_elab();
|
|
|
|
bool vcs_elabcheck(int ibound);
|
|
void vcs_elabPhase(size_t iphase, double* const elemAbundPhase);
|
|
int vcs_elcorr(double aa[], double x[]);
|
|
|
|
|
|
//! Create an initial estimate of the solution to the thermodynamic
|
|
//! equilibrium problem.
|
|
/*!
|
|
* @return Return value indicates success:
|
|
* - 0: successful initial guess
|
|
* - -1: Unsuccessful initial guess; the elemental abundances aren't
|
|
* satisfied.
|
|
*/
|
|
int vcs_inest_TP();
|
|
|
|
//! Estimate the initial mole numbers by constrained linear programming
|
|
/*!
|
|
* This is done by running
|
|
* each reaction as far forward or backward as possible, subject
|
|
* to the constraint that all mole numbers remain
|
|
* non-negative. Reactions for which \f$ \Delta \mu^0 \f$ are
|
|
* positive are run in reverse, and ones for which it is negative
|
|
* are run in the forward direction. The end result is equivalent
|
|
* to solving the linear programming problem of minimizing the
|
|
* linear Gibbs function subject to the element and
|
|
* non-negativity constraints.
|
|
*/
|
|
int vcs_setMolesLinProg();
|
|
|
|
double vcs_Total_Gibbs(double* w, double* fe, double* tPhMoles);
|
|
|
|
//! Calculate the total dimensionless Gibbs free energy of a single phase
|
|
/*!
|
|
* -> Inert species are handled as if they had a standard free
|
|
* energy of zero and if they obeyed ideal solution/gas theory
|
|
*
|
|
* @param iphase ID of the phase
|
|
* @param w Species mole number vector for all species
|
|
* @param fe vector of partial molar free energies of all of the
|
|
* species
|
|
*/
|
|
double vcs_GibbsPhase(size_t iphase, const double* const w,
|
|
const double* const fe);
|
|
|
|
//! Transfer the results of the equilibrium calculation back to VCS_PROB
|
|
/*!
|
|
* The VCS_PUB structure is returned to the user.
|
|
*
|
|
* @param pub Pointer to VCS_PROB object that will get the results of the
|
|
* equilibrium calculation transfered to it.
|
|
*/
|
|
int vcs_prob_update(VCS_PROB* pub);
|
|
|
|
//! Fully specify the problem to be solved using VCS_PROB
|
|
/*!
|
|
* Use the contents of the VCS_PROB to specify the contents of the
|
|
* private data, VCS_SOLVE.
|
|
*
|
|
* @param pub Pointer to VCS_PROB that will be used to
|
|
* initialize the current equilibrium problem
|
|
*/
|
|
int vcs_prob_specifyFully(const VCS_PROB* pub);
|
|
|
|
//! Specify the problem to be solved using VCS_PROB, incrementally
|
|
/*!
|
|
* Use the contents of the VCS_PROB to specify the contents of the
|
|
* private data, VCS_SOLVE.
|
|
*
|
|
* It's assumed we are solving the same problem.
|
|
*
|
|
* @param pub Pointer to VCS_PROB that will be used to
|
|
* initialize the current equilibrium problem
|
|
*/
|
|
int vcs_prob_specify(const VCS_PROB* pub);
|
|
|
|
private:
|
|
|
|
//! Zero out the concentration of a species.
|
|
/*!
|
|
* Zero out the concentration of a species. Make sure to conserve
|
|
* elements and keep track of the total moles in all phases.
|
|
* w[]
|
|
* m_tPhaseMoles_old[]
|
|
*
|
|
* @param kspec Species index
|
|
*
|
|
* @return:
|
|
* 1: succeeded
|
|
* 0: failed.
|
|
*/
|
|
int vcs_zero_species(const size_t kspec);
|
|
|
|
//! Change a single species from active to inactive status
|
|
/*!
|
|
* Rearrange data when species is added or removed. The Lth species is
|
|
* moved to the back of the species vector. The back of the species
|
|
* vector is indicated by the value of MR, the current number of
|
|
* active species in the mechanism.
|
|
*
|
|
* @param kspec Species Index
|
|
* @return
|
|
* Returns 0 unless.
|
|
* The return is 1 when the current number of
|
|
* noncomponent species is equal to zero. A recheck of deleted species
|
|
* is carried out in the main code.
|
|
*/
|
|
int vcs_delete_species(const size_t kspec);
|
|
|
|
//! This routine handles the bookkeeping involved with the
|
|
//! deletion of multiphase phases from the problem.
|
|
/*!
|
|
* When they are deleted, all of their species become active
|
|
* species, even though their mole numbers are set to zero.
|
|
* The routine does not make the decision to eliminate multiphases.
|
|
*
|
|
* Note, species in phases with zero mole numbers are still
|
|
* considered active. Whether the phase pops back into
|
|
* existence or not is checked as part of the main iteration
|
|
* loop.
|
|
*
|
|
* @param iph Phase to be deleted
|
|
*
|
|
* @return Returns whether the operation was successful or not
|
|
*/
|
|
bool vcs_delete_multiphase(const size_t iph);
|
|
|
|
//! Change the concentration of a species by delta moles.
|
|
/*!
|
|
* Make sure to conserve elements and keep track of the total kmoles in all phases.
|
|
*
|
|
* @param kspec The species index
|
|
* @delta_ptr pointer to the delta for the species. This may change during
|
|
* the calculation
|
|
*
|
|
* @return
|
|
* 1: succeeded without change of dx
|
|
* 0: Had to adjust dx, perhaps to zero, in order to do the delta.
|
|
*/
|
|
int delta_species(const size_t kspec, double* const delta_ptr);
|
|
|
|
//! Provide an estimate for the deleted species in phases that
|
|
//! are not zeroed out
|
|
/*!
|
|
* Try to add back in all deleted species. An estimate of the kmol numbers
|
|
* are obtained and the species is added back into the equation system,
|
|
* into the old state vector.
|
|
*
|
|
* This routine is called at the end of the calculation, just before
|
|
* returning to the user.
|
|
*/
|
|
size_t vcs_add_all_deleted();
|
|
|
|
//! Recheck deleted species in multispecies phases.
|
|
/*!
|
|
* We are checking the equation:
|
|
*
|
|
* sum_u = sum_j_comp [ sigma_i_j * u_j ]
|
|
* = u_i_O + log((AC_i * W_i)/m_tPhaseMoles_old)
|
|
*
|
|
* by first evaluating:
|
|
*
|
|
* DG_i_O = u_i_O - sum_u.
|
|
*
|
|
* Then, if TL is zero, the phase pops into existence if DG_i_O < 0.
|
|
* Also, if the phase exists, then we check to see if the species
|
|
* can have a mole number larger than VCS_DELETE_SPECIES_CUTOFF
|
|
* (default value = 1.0E-32).
|
|
*
|
|
*/
|
|
int vcs_recheck_deleted();
|
|
|
|
//! Recheck deletion condition for multispecies phases.
|
|
/*!
|
|
* We assume here that DG_i_0 has been calculated for deleted species correctly
|
|
*
|
|
*
|
|
* m_feSpecies(I) = m_SSfeSpecies(I)
|
|
* + ln(ActCoeff[I])
|
|
* - ln(Mnaught * m_units)
|
|
* + m_chargeSpecies[I] * Faraday_dim * m_phasePhi[iphase];
|
|
*
|
|
* sum_u = sum_j_comp [ sigma_i_j * u_j ]
|
|
* = u_i_O + log((AC_i * W_i)/m_tPhaseMoles_old)
|
|
*
|
|
* DG_i_0 = m_feSpecies(I) - sum_m{ a_i_m DG_m }
|
|
*
|
|
*
|
|
* by first evaluating:
|
|
*
|
|
* DG_i_O = u_i_O - sum_u.
|
|
*
|
|
* Then, the phase pops into existence iff
|
|
*
|
|
* phaseDG = 1.0 - sum_i{exp(-DG_i_O)} < 0.0
|
|
*
|
|
* This formula works for both single species phases and for multispecies
|
|
* phases. It's an overkill for single species phases.
|
|
*
|
|
* @param iphase Phase index number
|
|
*
|
|
* @return Returns true if the phase is currently deleted
|
|
* but should be reinstated. Returns false otherwise.
|
|
*
|
|
* NOTE: this routine is currently not used in the code, and
|
|
* contains some basic changes that are incompatible.
|
|
*
|
|
* assumptions:
|
|
* 1) Vphase Existence is up to date
|
|
* 2) Vphase->IndSpecies is up to date
|
|
* 3) m_deltaGRxn_old[irxn] is up to date
|
|
*/
|
|
bool recheck_deleted_phase(const int iphase);
|
|
|
|
//! Minor species alternative calculation
|
|
/*!
|
|
* This is based upon the following approximation:
|
|
* The mole fraction changes due to these reactions don't affect
|
|
* the mole numbers of the component species. Therefore the following
|
|
* approximation is valid for a small component of an ideal phase:
|
|
*
|
|
* 0 = m_deltaGRxn_old(I) + log(molNum_new(I)/molNum_old(I))
|
|
*
|
|
* m_deltaGRxn_old contains the contribution from
|
|
*
|
|
* m_feSpecies_old(I) =
|
|
* m_SSfeSpecies(I) +
|
|
* log(ActCoeff[i] * molNum_old(I) / m_tPhaseMoles_old(iph))
|
|
* Thus,
|
|
*
|
|
* molNum_new(I)= molNum_old(I) * EXP(-m_deltaGRxn_old(I))
|
|
*
|
|
* Most of this section is mainly restricting the update to reasonable
|
|
* values.
|
|
* We restrict the update a factor of 1.0E10 up and 1.0E-10 down
|
|
* because we run into trouble with the addition operator due to roundoff
|
|
* if we go larger than ~1.0E15. Roundoff will then sometimes produce
|
|
* zero mole fractions.
|
|
*
|
|
* Note: This routine was generalized to incorporate
|
|
* nonideal phases and phases on the molality basis
|
|
*
|
|
* Input:
|
|
* ------
|
|
* @param kspec The current species and corresponding formation
|
|
* reaction number.
|
|
* @param irxn The current species and corresponding formation
|
|
* reaction number.
|
|
*
|
|
* Output:
|
|
* ---------
|
|
* @param do_delete: BOOLEAN which if true on return, then we branch
|
|
* to the section that deletes a species from the
|
|
* current set of active species.
|
|
*/
|
|
double vcs_minor_alt_calc(size_t kspec, size_t irxn, bool* do_delete
|
|
#ifdef DEBUG_MODE
|
|
, char* ANOTE
|
|
#endif
|
|
) const;
|
|
|
|
//! This routine optimizes the minimization of the total gibbs free
|
|
//! energy by making sure the slope of the following functional stays
|
|
//! negative:
|
|
/*!
|
|
* The slope of the following functional is equivalent to the slope
|
|
* of the total Gibbs free energy of the system:
|
|
*
|
|
* d_Gibbs/ds = sum_k( m_deltaGRxn * m_deltaMolNumSpecies[k] )
|
|
*
|
|
* along the current direction m_deltaMolNumSpecies[], by choosing a value, al: (0<al<1)
|
|
* such that the a parabola approximation to Gibbs(al) fit to the
|
|
* end points al = 0 and al = 1 is minimized.
|
|
* s1 = slope of Gibbs function at al = 0, which is the previous
|
|
* solution = d(Gibbs)/d(al).
|
|
* s2 = slope of Gibbs function at al = 1, which is the current
|
|
* solution = d(Gibbs)/d(al).
|
|
* Only if there has been an inflection point (i.e., s1 < 0 and s2 > 0),
|
|
* does this code section kick in. It finds the point on the parabola
|
|
* where the slope is equal to zero.
|
|
*
|
|
*/
|
|
bool vcs_globStepDamp();
|
|
|
|
//! Switch rows and columns of a square matrix
|
|
/*!
|
|
* Switches the row and column of a matrix.
|
|
* So that after
|
|
*
|
|
* J[k1][j] = J_old[k2][j] and J[j][k1] = J_old[j][k2]
|
|
* J[k2][j] = J_old[k1][j] and J[j][k2] = J_old[j][k1]
|
|
*
|
|
* @param Jac Double pointer to the Jacobian
|
|
* @param k1 first row/column value to be switched
|
|
* @param k2 second row/column value to be switched
|
|
*/
|
|
void vcs_switch2D(double* const* const Jac,
|
|
const size_t k1, const size_t k2) const;
|
|
|
|
//! Calculate the norm of a deltaGibbs free energy vector
|
|
/*!
|
|
* Positive DG for species which don't exist are ignored.
|
|
*
|
|
* @param dg Vector of local delta G's.
|
|
*/
|
|
double l2normdg(double dg[]) const;
|
|
|
|
#ifdef DEBUG_MODE
|
|
|
|
//! Print out and check the elemental abundance vector
|
|
void prneav() const;
|
|
|
|
void checkDelta1(double* const ds, double* const delTPhMoles, int kspec);
|
|
#endif
|
|
|
|
//! Estimate equilibrium compositions
|
|
/*!
|
|
* Estimates equilibrium compositions.
|
|
* Algorithm covered in a section of Smith and Missen's Book.
|
|
*
|
|
* Linear programming module is based on using dbolm.
|
|
*
|
|
* @param aw aw[i[ Mole fraction work space (ne in length)
|
|
* @param sa sa[j] = Gram-Schmidt orthog work space (ne in length)
|
|
* @param sm sm[i+j*ne] = QR matrix work space (ne*ne in length)
|
|
* @param ss ss[j] = Gram-Schmidt orthog work space (ne in length)
|
|
* @param test This is a small negative number.
|
|
*/
|
|
void vcs_inest(double* const aw, double* const sa, double* const sm,
|
|
double* const ss, double test);
|
|
|
|
|
|
//! Calculate the status of single species phases.
|
|
void vcs_SSPhase(void);
|
|
|
|
//! This function recalculates the deltaG for reaction, irxn
|
|
/*!
|
|
* This function recalculates the deltaG for reaction irxn,
|
|
* given the mole numbers in molNum. It uses the temporary
|
|
* space mu_i, to hold the recalculated chemical potentials.
|
|
* It only recalculates the chemical potentials for species in phases
|
|
* which participate in the irxn reaction.
|
|
*
|
|
* Input
|
|
* ------------
|
|
* @param irxn Reaction number
|
|
* @param molNum Current mole numbers of species to be used as
|
|
* input to the calculation (units = kmol)
|
|
* (length = totalNuMSpecies)
|
|
*
|
|
* Output
|
|
* ------------
|
|
* @param ac output Activity coefficients (length = totalNumSpecies)
|
|
* Note this is only partially formed. Only species in
|
|
* phases that participate in the reaction will be updated
|
|
* @param mu_i dimensionless chemical potentials (length - totalNumSpecies
|
|
* Note this is only partially formed. Only species in
|
|
* phases that participate in the reaction will be updated
|
|
*
|
|
* @return Returns the dimensionless deltaG of the reaction
|
|
*/
|
|
double deltaG_Recalc_Rxn(const int stateCalc,
|
|
const size_t irxn, const double* const molNum,
|
|
double* const ac, double* const mu_i);
|
|
|
|
//! Delete memory that isn't just resizable STL containers
|
|
/*!
|
|
* This gets called by the destructor or by InitSizes().
|
|
*/
|
|
void vcs_delete_memory();
|
|
|
|
//! Initialize the internal counters
|
|
/*!
|
|
* Initialize the internal counters containing the subroutine call
|
|
* values and times spent in the subroutines.
|
|
*
|
|
* ifunc = 0 Initialize only those counters appropriate for the top of
|
|
* vcs_solve_TP().
|
|
* = 1 Initialize all counters.
|
|
*/
|
|
void vcs_counters_init(int ifunc);
|
|
|
|
//! Create a report on the plog file containing timing and its information
|
|
/*!
|
|
* @param timing_print_lvl If 0, just report the iteration count.
|
|
* If larger than zero, report the timing information
|
|
*/
|
|
void vcs_TCounters_report(int timing_print_lvl = 1);
|
|
|
|
void vcs_setFlagsVolPhases(const bool upToDate, const int stateCalc);
|
|
|
|
void vcs_setFlagsVolPhase(const size_t iph, const bool upToDate, const int stateCalc);
|
|
|
|
//! Update all underlying vcs_VolPhase objects
|
|
/*!
|
|
* Update the mole numbers and the phase voltages of all phases in the
|
|
* vcs problem
|
|
*
|
|
* @param stateCalc Location of the update (either VCS_STATECALC_NEW or
|
|
* VCS_STATECALC_OLD).
|
|
*/
|
|
void vcs_updateMolNumVolPhases(const int stateCalc);
|
|
|
|
public:
|
|
//! Calculate the rank of a matrix and return the rows and columns that will generate an independent basis
|
|
//! for that rank
|
|
/*
|
|
* Choose the optimum component species basis for the calculations, finding the rank and
|
|
* set of linearly independent rows for that calculation.
|
|
* Then find the set of linearly indepedent element columns that can support that rank.
|
|
* This is done by taking the transpose of the matrix and redoing the same calculation.
|
|
* (there may be a better way to do this. I don't know.)
|
|
*
|
|
*
|
|
* Input
|
|
* ---------
|
|
*
|
|
* @param awtmp Vector of mole numbers which will be used to construct a
|
|
* ranking for how to pick the basis species. This is largely ignored
|
|
* here.
|
|
*
|
|
* @param numSpecies Number of species. This is the number of rows in the matrix.
|
|
*
|
|
* @param matrix Matrix. This is the formula matrix. Nominally, the rows are species, while
|
|
* the columns are element compositions. However, this routine
|
|
* is totally general, so that the rows and columns can be anything.
|
|
*
|
|
* @param numElemConstraints Number of element constraints
|
|
*
|
|
* Output
|
|
* ---------
|
|
* @param usedZeroedSpecies = If true, then a species with a zero concentration
|
|
* was used as a component.
|
|
*
|
|
*
|
|
* @param compRes Vector of rows which are linearly independent. (these are the components)
|
|
*
|
|
* @param elemComp Vector of columns which are linearly independent (These are the actionable element
|
|
* constraints).
|
|
*
|
|
* @return Returns number of components. This is the rank of the matrix
|
|
*/
|
|
int vcs_rank(const double * awtmp, size_t numSpecies, const double * matrix, size_t numElemConstraints,
|
|
std::vector<size_t> &compRes, std::vector<size_t> &elemComp, int * const usedZeroedSpecies) const;
|
|
|
|
|
|
public:
|
|
//! value of the number of species used to malloc data structures
|
|
size_t NSPECIES0;
|
|
|
|
//! value of the number of phases used to malloc data structures
|
|
size_t NPHASE0;
|
|
|
|
//! Total number of species in the problems
|
|
size_t m_numSpeciesTot;
|
|
|
|
//! Number of element constraints in the problem
|
|
/*!
|
|
* This is typically equal to the number of elements in the problem
|
|
*/
|
|
size_t m_numElemConstraints;
|
|
|
|
//! Number of components calculated for the problem
|
|
size_t m_numComponents;
|
|
|
|
//! Total number of non-component species in the problem
|
|
size_t m_numRxnTot;
|
|
|
|
//! Current number of species in the problems
|
|
/*!
|
|
* Species can be deleted if they aren't
|
|
* stable under the current conditions
|
|
*/
|
|
size_t m_numSpeciesRdc;
|
|
|
|
//! Current number of non-component species in the problem
|
|
/*!
|
|
* Species can be deleted if they aren't
|
|
* stable under the current conditions
|
|
*/
|
|
size_t m_numRxnRdc;
|
|
|
|
//! Number of active species which are currently either treated as
|
|
//! minor species
|
|
size_t m_numRxnMinorZeroed;
|
|
|
|
//! Number of Phases in the problem
|
|
size_t m_numPhases;
|
|
|
|
//! Formula matrix for the problem
|
|
/*!
|
|
* FormulaMatrix[j][kspec] = Number of elements, j, in the kspec species
|
|
*
|
|
* Both element and species indices are swapped.
|
|
*/
|
|
DoubleStarStar m_formulaMatrix;
|
|
|
|
//! Stoichiometric coefficient matrix for the reaction mechanism expressed in Reduced Canonical Form.
|
|
/*!
|
|
* This is the stoichiometric coefficient matrix for the
|
|
* reaction which forms species kspec from the component species. A
|
|
* stoichiometric coefficient of one is assumed for the species kspec in this mechanism.
|
|
*
|
|
* NOTE: kspec = irxn + m_numComponents
|
|
*
|
|
* m_stoichCoeffRxnMatrix[irxn][j] :
|
|
* j refers to the component number, and irxn refers to the irxn_th non-component species.
|
|
* The stoichiometric coefficients multilplied by the Formula coefficients of the
|
|
* component species add up to the negative value of the number of elements in
|
|
* the species kspec.
|
|
*
|
|
* length = [nspecies0][nelements0]
|
|
*/
|
|
DoubleStarStar m_stoichCoeffRxnMatrix;
|
|
|
|
//! Absolute size of the stoichiometric coefficients
|
|
/*!
|
|
* scSize[irxn] = abs(Size) of the stoichiometric
|
|
* coefficients. These are used to determine
|
|
* whether a given species should be
|
|
* handled by the alt_min treatment or
|
|
* should be handled as a major species.
|
|
*/
|
|
std::vector<double> m_scSize;
|
|
|
|
//! total size of the species
|
|
/*!
|
|
* This is used as a multiplier to the mole number in figuring out which
|
|
* species should be components.
|
|
*/
|
|
std::vector<double> m_spSize;
|
|
|
|
//! Standard state chemical potentials for species K at the current
|
|
//! temperature and pressure.
|
|
/*!
|
|
* The first NC entries are for components. The following NR entries are
|
|
* for the current non-component species in the mechanism.
|
|
*/
|
|
std::vector<double> m_SSfeSpecies;
|
|
|
|
//! Free energy vector from the start of the current iteration
|
|
/*!
|
|
* The free energies are saved at the start of the current iteration.
|
|
* Length = number of species
|
|
*/
|
|
std::vector<double> m_feSpecies_old;
|
|
|
|
//! Dimensionless new free energy for all the species in the mechanism
|
|
//! at the new tentatite T, P, and mole numbers.
|
|
/*!
|
|
* The first NC entries are for components. The following
|
|
* NR entries are for the current non-component species in the mechanism.
|
|
* Length = number of species
|
|
*/
|
|
std::vector<double> m_feSpecies_new;
|
|
|
|
//! Setting for whether to do an initial estimate
|
|
/*!
|
|
* Initial estimate: 0 Do not estimate the solution at all. Use the
|
|
* supplied mole numbers as is.
|
|
* 1 Only do an estimate if the element abundances
|
|
* aren't satisfied.
|
|
* -1 Force an estimate of the soln. Throw out the input
|
|
* mole numbers.
|
|
*/
|
|
int m_doEstimateEquil;
|
|
|
|
//! Total moles of the species
|
|
/*!
|
|
* Total number of moles of the kth species.
|
|
* Length = Total number of species = m
|
|
*/
|
|
std::vector<double> m_molNumSpecies_old;
|
|
|
|
//! Specifies the species unknown type
|
|
/*!
|
|
* There are two types. One is the straightforward
|
|
* species, with the mole number w[k], as the
|
|
* unknown. The second is the an interfacial
|
|
* voltage where w[k] refers to the interfacial
|
|
* voltage in volts.
|
|
* These species types correspond to metallic
|
|
* electrons corresponding to electrodes.
|
|
* The voltage and other interfacial conditions
|
|
* sets up an interfacial current, which is
|
|
* set to zero in this initial treatment.
|
|
* Later we may have non-zero interfacial currents.
|
|
*/
|
|
std::vector<int> m_speciesUnknownType;
|
|
|
|
//! Change in the number of moles of phase, iphase, due to the noncomponent formation
|
|
//! reaction, irxn, for species, k:
|
|
/*!
|
|
* m_deltaMolNumPhase[irxn][iphase] = k = nc + irxn
|
|
*/
|
|
DoubleStarStar m_deltaMolNumPhase;
|
|
|
|
//! This is 1 if the phase, iphase, participates in the formation reaction
|
|
//! irxn, and zero otherwise. PhaseParticipation[irxn][iphase]
|
|
IntStarStar m_phaseParticipation;
|
|
|
|
//! electric potential of the iph phase
|
|
std::vector<double> m_phasePhi;
|
|
|
|
//! Tentative value of the mole number vector. It's also used to store the
|
|
//! mole fraction vector.
|
|
//std::vector<double> wt;
|
|
std::vector<double> m_molNumSpecies_new;
|
|
|
|
//! Delta G(irxn) for the noncomponent species in the mechanism.
|
|
/*!
|
|
* Computed by the subroutine deltaG. m_deltaGRxn is the free
|
|
* energy change for the reaction which forms species K from the
|
|
* component species. This vector has length equal to the number
|
|
* of noncomponent species in the mechanism. It starts with
|
|
* the first current noncomponent species in the mechanism.
|
|
*/
|
|
std::vector<double> m_deltaGRxn_new;
|
|
|
|
//! Last deltag[irxn] from the previous step
|
|
std::vector<double> m_deltaGRxn_old;
|
|
|
|
//! Last deltag[irxn] from the previous step with additions for
|
|
//! possible births of zeroed phases.
|
|
std::vector<double> m_deltaGRxn_Deficient;
|
|
|
|
//! Temporary vector of Rxn DeltaG's
|
|
/*!
|
|
* This is used from time to time, for printing purposes
|
|
*/
|
|
std::vector<double> m_deltaGRxn_tmp;
|
|
|
|
//! Reaction Adjustments for each species during the current step
|
|
/*!
|
|
* delta Moles for each species during the current step.
|
|
* Length = number of species
|
|
*/
|
|
std::vector<double> m_deltaMolNumSpecies;
|
|
|
|
//! Element abundances vector
|
|
/*!
|
|
* Vector of moles of each element actually in the solution
|
|
* vector. Except for certain parts of the algorithm,
|
|
* this is a constant.
|
|
* Note other constraint conditions are added to this vector.
|
|
* This is input from the input file and
|
|
* is considered a constant from thereon.
|
|
* units = kmoles
|
|
*/
|
|
std::vector<double> m_elemAbundances;
|
|
|
|
//! Element abundances vector Goals
|
|
/*!
|
|
* Vector of moles of each element that are the goals of the
|
|
* simulation. This is a constant in the problem.
|
|
* Note other constraint conditions are added to this vector.
|
|
* This is input from the input file and
|
|
* is considered a constant from thereon.
|
|
* units = kmoles
|
|
*/
|
|
std::vector<double> m_elemAbundancesGoal;
|
|
|
|
//! Total number of kmoles in all phases
|
|
/*!
|
|
* This number includes the inerts.
|
|
* -> Don't use this except for scaling
|
|
* purposes
|
|
*/
|
|
double m_totalMolNum;
|
|
|
|
//! Total kmols of species in each phase
|
|
/*!
|
|
* This contains the total number of moles of species in each phase
|
|
*
|
|
* Length = number of phases
|
|
*/
|
|
std::vector<double> m_tPhaseMoles_old;
|
|
|
|
//! total kmols of species in each phase in the tentative soln vector
|
|
/*!
|
|
* This contains the total number of moles of species in each phase
|
|
* in the tentative solution vector
|
|
*
|
|
* Length = number of phases
|
|
*/
|
|
std::vector<double> m_tPhaseMoles_new;
|
|
|
|
//! Temporary vector of length NPhase
|
|
mutable std::vector<double> m_TmpPhase;
|
|
|
|
//! Temporary vector of length NPhase
|
|
mutable std::vector<double> m_TmpPhase2;
|
|
|
|
//! Change in the total moles in each phase
|
|
/*!
|
|
* Length number of phases.
|
|
*/
|
|
std::vector<double> m_deltaPhaseMoles;
|
|
|
|
//! Temperature (Kelvin)
|
|
double m_temperature;
|
|
|
|
//! Pressure (units are determined by m_VCS_UnitsFormat
|
|
/*!
|
|
* Values units
|
|
* -1: atm
|
|
* 0: atm
|
|
* 1: atm
|
|
* 2: atm
|
|
* 3: Pa
|
|
* Units being changed to Pa
|
|
*/
|
|
double m_pressurePA;
|
|
|
|
//! Total kmoles of inert to add to each phase
|
|
/*!
|
|
* TPhInertMoles[iph] = Total kmoles of inert to add to each phase
|
|
* length = number of phases
|
|
*/
|
|
std::vector<double> TPhInertMoles;
|
|
|
|
//! Tolerance requirement for major species
|
|
double m_tolmaj;
|
|
|
|
//! Tolerance requirements for minor species
|
|
double m_tolmin;
|
|
|
|
//! Below this, major species aren't refined any more
|
|
double m_tolmaj2;
|
|
|
|
//! Below this, minor species aren't refined any more
|
|
double m_tolmin2;
|
|
|
|
//! Index vector that keeps track of the species vector rearrangement
|
|
/*!
|
|
* At the end of each run, the species vector and associated data gets put back
|
|
* in the original order.
|
|
*
|
|
* Example
|
|
*
|
|
* k = m_speciesMapIndex[kspec]
|
|
*
|
|
* kspec = current order in the vcs_solve object
|
|
* k = original order in the vcs_prob object and in the MultiPhase object
|
|
*/
|
|
std::vector<size_t> m_speciesMapIndex;
|
|
|
|
//! Index that keeps track of the index of the species within the local
|
|
//! phase
|
|
/*!
|
|
* This returns the local index of the species within the phase. Its argument
|
|
* is the global species index within the VCS problem.
|
|
*
|
|
* k = m_speciesLocalPhaseIndex[kspec]
|
|
*
|
|
* k varies between 0 and the nSpecies in the phase
|
|
*
|
|
* Length = number of species
|
|
*/
|
|
std::vector<size_t> m_speciesLocalPhaseIndex;
|
|
|
|
//! Index vector that keeps track of the rearrangement of the elements
|
|
/*!
|
|
* At the end of each run, the element vector and associated data gets put back
|
|
* in the original order.
|
|
*
|
|
* Example
|
|
*
|
|
* e = m_elementMapIndex[eNum]
|
|
*
|
|
* eNum = current order in the vcs_solve object
|
|
* e = original order in the vcs_prob object and in the MultiPhase object
|
|
*/
|
|
std::vector<size_t> m_elementMapIndex;
|
|
|
|
//! Mapping between the species index for noncomponent species and the
|
|
//! full species index.
|
|
/*!
|
|
* ir[irxn] = Mapping between the reaction index for
|
|
* noncomponent formation reaction of a species
|
|
* and the full species
|
|
* index.
|
|
* - Initially set to a value of K = NC + I
|
|
* This vector has length equal to number
|
|
* of noncomponent species in the mechanism.
|
|
* It starts with the first current
|
|
* noncomponent species in the mechanism.
|
|
* kspec = ir[irxn]
|
|
*/
|
|
std::vector<size_t> m_indexRxnToSpecies;
|
|
|
|
//! Major -Minor status vector for the species in the problem
|
|
/*!
|
|
* The index for this is species. The reaction that this is referring
|
|
* to is
|
|
* kspec = irxn + m_numComponents
|
|
*
|
|
* kspec : 2 -> Component species VCS_SPECIES_COMPONENT
|
|
* -> deprecated, want to assign -2 to some
|
|
* component species. We can already determine
|
|
* whether the species is a component from
|
|
* its position in the species vector.
|
|
* 1 -> Major species VCS_SPECIES_MAJOR
|
|
* 0 -> Minor species VCS_SPECIES_MINOR
|
|
* -1 -> The species lies in a multicomponent phase
|
|
* that exists. Its concentration is currently
|
|
* very low, necessitating a different method
|
|
* of calculation.
|
|
* - VCS_SPECIES_ZEROEDPHASE
|
|
* -2 -> The species lies in a multicomponent phase
|
|
* which currently doesn't exist.
|
|
* Its concentration is currently zero.
|
|
* - VCS_SPECIES_ZEROEDMS
|
|
* -3 -> Species lies in a single-species phase which
|
|
* is currently zeroed out.
|
|
* - VCS_SPECIES_ZEROEDSS
|
|
* -4 -> Species has such a small mole fraction it is
|
|
* deleted even though its phase may possibly exist.
|
|
* The species is believed to have such a small
|
|
* mole fraction that it best to throw the
|
|
* calculation of it out. It will be added back in
|
|
* at the end of the calculation.
|
|
* - VCS_SPECIES_DELETED
|
|
* -5 -> Species refers to an electron in the metal
|
|
* The unknown is equal to the interfacial voltage
|
|
* drop across the interface on the SHE (standard
|
|
* hydrogen electrode) scale (volts).
|
|
* - VCS_SPECIES_INTERFACIALVOLTAGE
|
|
* -6 -> Species lies in a multicomponent phase that
|
|
* is zeroed atm and will stay deleted due to a
|
|
* choice from a higher level.
|
|
* These species will formally always have zero
|
|
* mole numbers in the solution vector.
|
|
* - VCS_SPECIES_ZEROEDPHASE
|
|
* -7 -> The species lies in a multicomponent phase which
|
|
* currently does exist. Its concentration is currently
|
|
* identically zero, though the phase exists. Note, this
|
|
* is a temporary condition that exists at the start
|
|
* of an equilibrium problem.
|
|
* The species is soon "birthed" or "deleted".
|
|
* - VCS_SPECIES_ACTIVEBUTZERO
|
|
* -8 -> The species lies in a multicomponent phase which
|
|
* currently does exist. Its concentration is currently
|
|
* identically zero, though the phase exists. This is
|
|
* a permanent condition due to stoich constraints
|
|
* - VCS_SPECIES_STOICHZERO
|
|
*
|
|
*/
|
|
std::vector<int> m_speciesStatus;
|
|
|
|
//! Mapping from the species number to the phase number
|
|
std::vector<size_t> m_phaseID;
|
|
|
|
//! Boolean indicating whether a species belongs to a single-species phase
|
|
// vector<bool> can't be used here because it doesn't work with std::swap
|
|
std::vector<char> m_SSPhase;
|
|
|
|
//! Species string name for the kth species
|
|
/*!
|
|
* Species string name for the kth species
|
|
*/
|
|
std::vector<std::string> m_speciesName;
|
|
|
|
//! Vector of strings containing the element names
|
|
/*!
|
|
* ElName[j] = String containing element names
|
|
*/
|
|
std::vector<std::string> m_elementName;
|
|
|
|
//! Type of the element constraint
|
|
/*!
|
|
* m_elType[j] = type of the element
|
|
* 0 VCS_ELEM_TYPE_ABSPOS Normal element that is positive
|
|
* or zero in all species.
|
|
* 1 VCS_ELEM_TPYE_ELECTRONCHARGE element dof that corresponds
|
|
* to the electronic charge DOF.
|
|
* 2 VCS_ELEM_TYPE_CHARGENEUTRALITY element dof that
|
|
* corresponds to a required charge
|
|
* neutrality constraint on the phase.
|
|
* The element abundance is always exactly zero.
|
|
* 3 VCS_ELEM_TYPE_OTHERCONSTRAINT Other constraint which may
|
|
* mean that a species has neg 0 or pos value
|
|
* of that constraint (other than charge)
|
|
*/
|
|
std::vector<int> m_elType;
|
|
|
|
//! Specifies whether an element constraint is active
|
|
/*!
|
|
* The default is true
|
|
* Length = nelements
|
|
*/
|
|
std::vector<int> m_elementActive;
|
|
|
|
//! Array of Phase Structures
|
|
/*!
|
|
* Length = number of phases
|
|
*/
|
|
std::vector<vcs_VolPhase*> m_VolPhaseList;
|
|
|
|
//! String containing the title of the run
|
|
std::string m_title;
|
|
|
|
//! This specifies the current state of units for the Gibbs free energy
|
|
//! properties in the program.
|
|
/*!
|
|
*. The default is to have this unitless
|
|
*/
|
|
char m_unitsState;
|
|
|
|
//! Multiplier for the mole numbers within the nondimensionless formulation
|
|
/*!
|
|
* All numbers within the main routine are on an absolute basis. This
|
|
* presents some problems wrt very large and very small mole numbers.
|
|
* We get around this by using a multiplier coming into and coming
|
|
* out of the equilibrium routines
|
|
*/
|
|
double m_totalMoleScale;
|
|
|
|
//! specifies the activity convention of the phase containing the species
|
|
/*!
|
|
* SpecActConvention[kspec]
|
|
* 0 = molar based
|
|
* 1 = molality based
|
|
* length = number of species
|
|
*/
|
|
std::vector<int> m_actConventionSpecies;
|
|
|
|
//! specifies the activity convention of the phase.
|
|
/*!
|
|
* 0 = molar based
|
|
* 1 = molality based
|
|
* length = number of phases
|
|
*/
|
|
std::vector<int> m_phaseActConvention;
|
|
|
|
//! specifies the ln(Mnaught) used to calculate the chemical potentials
|
|
/*!
|
|
* For molar based activity conventions
|
|
* this will be equal to 0.0
|
|
* length = number of species
|
|
*/
|
|
std::vector<double> m_lnMnaughtSpecies;
|
|
|
|
//! Molar-based Activity Coefficients for Species
|
|
/*!
|
|
*
|
|
* Length = number of species
|
|
*/
|
|
std::vector<double> m_actCoeffSpecies_new;
|
|
|
|
//! Molar-based Activity Coefficients for Species based on old mole numbers
|
|
/*!
|
|
* These activity coefficients are based on the m_molNumSpecies_old values
|
|
* Molar based activity coeffients.
|
|
* Length = number of species
|
|
*/
|
|
std::vector<double> m_actCoeffSpecies_old;
|
|
|
|
//! Change in the log of the activity coefficient with respect to the mole number
|
|
//! multiplied by the phase mole number
|
|
/*!
|
|
* length = [nspecies][nspecies]
|
|
*
|
|
* This is a temporary array that gets regenerated every time it's
|
|
* needed. It is not swapped wrt species.
|
|
*/
|
|
DoubleStarStar m_np_dLnActCoeffdMolNum;
|
|
|
|
//! Molecular weight of each species
|
|
/*!
|
|
* units = kg/kmol
|
|
* length = number of species
|
|
*
|
|
* note: this is a candidate for removal. I don't think we use it.
|
|
*/
|
|
std::vector<double> m_wtSpecies;
|
|
|
|
//! Charge of each species
|
|
/*!
|
|
* Length = number of species
|
|
*/
|
|
std::vector<double> m_chargeSpecies;
|
|
|
|
std::vector<std::vector<size_t> > phasePopProblemLists_;
|
|
|
|
//! Vector of pointers to thermostructures which identify the model
|
|
//! and parameters for evaluating the thermodynamic functions for that
|
|
//! particular species.
|
|
/*!
|
|
* SpeciesThermo[k] pointer to the thermo information for the kth species
|
|
*/
|
|
std::vector<VCS_SPECIES_THERMO*> m_speciesThermoList;
|
|
|
|
//! Choice of Hessians
|
|
/*!
|
|
* If this is true, then we will use a better approximation to the
|
|
* Hessian based on Jacobian of the ln(ActCoeff) with respect to mole
|
|
* numbers
|
|
*/
|
|
int m_useActCoeffJac;
|
|
|
|
//! Total volume of all phases
|
|
/*!
|
|
* units are m^3
|
|
*/
|
|
double m_totalVol;
|
|
|
|
//! Partial molar volumes of the species
|
|
/*!
|
|
* units = mks (m^3/kmol) -determined by m_VCS_UnitsFormat
|
|
* Length = number of species
|
|
*/
|
|
std::vector<double> m_PMVolumeSpecies;
|
|
|
|
//! dimensionless value of Faraday's constant
|
|
/*!
|
|
* F / RT (1/volt)
|
|
*/
|
|
double m_Faraday_dim;
|
|
|
|
//! Timing and iteration counters for the vcs object
|
|
VCS_COUNTERS* m_VCount;
|
|
|
|
|
|
//! Debug printing lvl
|
|
/*!
|
|
* Levels correspond to the following guidlines
|
|
* - 0 No printing at all
|
|
* - 1 Serious warnings or fatal errors get one line
|
|
* - 2 one line per eacdh successful vcs package call
|
|
* - 3 one line per every successful solve_TP calculation
|
|
* - 4 one line for every successful operation -> solve_TP gets a summary report
|
|
* - 5 each iteration in solve_TP gets a report with one line per species
|
|
* - 6 Each decision in solve_TP gets a line per species in addition to 4
|
|
* - 10 Additionally Hessian matrix is printed out
|
|
*
|
|
* Levels of printing above 4 are only accessible when DEBUG_MODE is turned on
|
|
*/
|
|
int m_debug_print_lvl;
|
|
|
|
//! printing level of timing information
|
|
/*!
|
|
* 1 allowing printing of timing
|
|
* 0 do not allow printing of timing -> everything is printed
|
|
* as a NA.
|
|
*/
|
|
int m_timing_print_lvl;
|
|
|
|
//! Units for the chemical potential data:
|
|
/*!
|
|
* VCS_UnitsFormat = Units for the chemical potential data:
|
|
* -1: kcal/mol
|
|
* 0: MU/RT
|
|
* 1: kJ/mol
|
|
* 2: Kelvin
|
|
* 3: J / kmol
|
|
* and pressure data:
|
|
* -1: Pa
|
|
* 0: Pa
|
|
* 1: Pa
|
|
* 2: pa
|
|
* 3: Pa
|
|
*/
|
|
int m_VCS_UnitsFormat;
|
|
|
|
friend class vcs_phaseStabilitySolve;
|
|
|
|
};
|
|
|
|
}
|
|
#endif
|
|
|