diff --git a/Cantera/src/thermo/State.cpp b/Cantera/src/thermo/State.cpp index c3bbbb2c5..512be883a 100644 --- a/Cantera/src/thermo/State.cpp +++ b/Cantera/src/thermo/State.cpp @@ -6,7 +6,7 @@ */ /* - * $Author$ + * * $Date$ * $Revision$ * @@ -28,15 +28,26 @@ using namespace std; namespace Cantera { - State::State() : m_kk(0), m_temp(0.0), m_dens(0.001), m_mmw(0.0) {} + State::State() : + m_kk(0), + m_temp(0.0), + m_dens(0.001), + m_mmw(0.0), + m_stateNum(-1) + { + } - State::~State() {} + State::~State() + { + } State::State(const State& right) : m_kk(0), m_temp(0.0), m_dens(0.001), - m_mmw(0.0) { + m_mmw(0.0), + m_stateNum(-1) + { /* * Call the assignment operator. */ @@ -63,174 +74,214 @@ namespace Cantera { m_y = right.m_y; m_molwts = right.m_molwts; m_rmolwts = right.m_rmolwts; + m_stateNum = -1; /* * Return the reference to the current object */ return *this; } - doublereal State::moleFraction(int k) const { - if (k >= 0 && k < m_kk) { - return m_ym[k] * m_mmw; - } - else { - throw CanteraError("State:moleFraction", - "illegal species index number"); - } + doublereal State::moleFraction(const int k) const { + if (k >= 0 && k < m_kk) { + return m_ym[k] * m_mmw; + } + else { + throw CanteraError("State:moleFraction", + "illegal species index number"); + } + } + + void State::setMoleFractions(const doublereal* const x) { + doublereal sum = dot(x, x + m_kk, m_molwts.begin()); + doublereal rsum = 1.0/sum; + transform(x, x + m_kk, m_ym.begin(), timesConstant(rsum)); + transform(m_ym.begin(), m_ym.begin() + m_kk, m_molwts.begin(), + m_y.begin(), multiplies()); + doublereal norm = accumulate(x, x + m_kk, 0.0); + m_mmw = sum/norm; + + //! Call a routine to determin whether state has changed. + stateMFChangeCalc(); + } + + void State::setMoleFractions_NoNorm(const doublereal* const x) { + m_mmw = dot(x, x + m_kk, m_molwts.begin()); + doublereal rmmw = 1.0/m_mmw; + transform(x, x + m_kk, m_ym.begin(), timesConstant(rmmw)); + transform(m_ym.begin(), m_ym.begin() + m_kk, m_molwts.begin(), + m_y.begin(), multiplies()); + + //! Call a routine to determin whether state has changed. + stateMFChangeCalc(); + } + + doublereal State::massFraction(const int k) const { + if (k >= 0 && k < m_kk) { + return m_y[k]; + } + else { + throw CanteraError("State:massFraction", + "illegal species index number"); + } + } + + doublereal State::concentration(const int k) const { + if (k >= 0 && k < m_kk) { + return m_y[k] * m_dens * m_rmolwts[k] ; + } + else { + throw CanteraError("State:massFraction", + "illegal species index number"); + } + } + + void State::setMassFractions(const doublereal* const y) { + doublereal norm = 0.0, sum = 0.0; + //cblas_dcopy(m_kk, y, 1, m_y.begin(), 1); + norm = accumulate(y, y + m_kk, 0.0); + copy(y, y + m_kk, m_y.begin()); + scale(y, y + m_kk, m_y.begin(), 1.0/norm); + // for (k = 0; k != m_kk; ++k) { + // norm += y[k]; + // m_y[k] = y[k]; + //} + + //scale(m_kk, 1.0/norm, m_y.begin()); + transform(m_y.begin(), m_y.begin() + m_kk, m_rmolwts.begin(), + m_ym.begin(), multiplies()); + sum = accumulate(m_ym.begin(), m_ym.begin() + m_kk, 0.0); + // for (k = 0; k != m_kk; ++k) { + // m_ym[k] = m_y[k] * m_rmolwts[k]; + // sum += m_ym[k]; + // } + m_mmw = 1.0/sum; + + //! Call a routine to determin whether state has changed. + stateMFChangeCalc(); + } + + void State::setMassFractions_NoNorm(const doublereal* const y) { + doublereal sum = 0.0; + copy(y, y + m_kk, m_y.begin()); + transform(m_y.begin(), m_y.end(), m_rmolwts.begin(), m_ym.begin(), + multiplies()); + sum = accumulate(m_ym.begin(), m_ym.end(), 0.0); + //for (k = 0; k != m_kk; ++k) { + // m_y[k] = y[k]; + // m_ym[k] = m_y[k] * m_rmolwts[k]; + // sum += m_ym[k]; + //} + m_mmw = 1.0/sum; + + //! Call a routine to determine whether state has changed. + stateMFChangeCalc(); + } + + doublereal State::sum_xlogx() const { + return m_mmw* Cantera::sum_xlogx(m_ym.begin(), m_ym.end()) + log(m_mmw); + } + + doublereal State::sum_xlogQ(doublereal* Q) const { + return m_mmw * Cantera::sum_xlogQ(m_ym.begin(), m_ym.end(), Q); + } + + doublereal State::molarDensity() const { + return density()/meanMolecularWeight(); + } + + void State::setConcentrations(const doublereal* const c) { + int k; + doublereal sum = 0.0, norm = 0.0; + for (k = 0; k != m_kk; ++k) { + sum += c[k]*m_molwts[k]; + norm += c[k]; + } + m_mmw = sum/norm; + setDensity(sum); + doublereal rsum = 1.0/sum; + for (k = 0; k != m_kk; ++k) { + m_ym[k] = c[k] * rsum; + m_y[k] = m_ym[k] * m_molwts[k]; } - void State::setMoleFractions(const doublereal* x) { - doublereal sum = 0.0, norm = 0.0; - sum = dot(x, x + m_kk, m_molwts.begin()); - doublereal rsum = 1.0/sum; - transform(x, x + m_kk, m_ym.begin(), timesConstant(rsum)); - transform(m_ym.begin(), m_ym.begin() + m_kk, m_molwts.begin(), - m_y.begin(), multiplies()); - norm = accumulate(x, x + m_kk, 0.0); - //for (k = 0; k != m_kk; ++k) { - // m_ym[k] = x[k] / sum; - // m_y[k] = m_molwts[k]*m_ym[k]; - // norm += x[k]; - //} - m_mmw = sum/norm; + //! Call a routine to determin whether state has changed. + stateMFChangeCalc(); + } + + const doublereal* State::moleFractdivMMW() const { + return &m_ym[0]; + } + + void State::getConcentrations(doublereal* const c) const { + scale(m_ym.begin(), m_ym.end(), c, m_dens); + } + + doublereal State::mean_X(const doublereal* const Q) const { + return m_mmw*std::inner_product(m_ym.begin(), m_ym.end(), Q, 0.0); + } + + doublereal State::mean_Y(const doublereal* const Q) const { + return dot(m_y.begin(), m_y.end(), Q); + } + + void State::getMoleFractions(doublereal* const x) const { + scale(m_ym.begin(), m_ym.end(), x, m_mmw); + } + + void State::getMassFractions(doublereal* const y) const { + copy(m_y.begin(), m_y.end(), y); + } + + void State::setMolarDensity(const doublereal molarDensity) { + m_dens = molarDensity*meanMolecularWeight(); + } + + inline void State::stateMFChangeCalc(bool forcerChange) { + // Right now we assume that the mole fractions have changed every time + // the function is called + m_stateNum++; + if (m_stateNum > 1000000) m_stateNum = -10000000; + } + + + void State::init(const array_fp& mw) { + m_kk = mw.size(); + m_molwts.resize(m_kk); + m_rmolwts.resize(m_kk); + m_y.resize(m_kk, 0.0); + m_ym.resize(m_kk, 0.0); + copy(mw.begin(), mw.end(), m_molwts.begin()); + for (int k = 0; k < m_kk; k++) { + if (m_molwts[k] < 0.0) { + throw CanteraError("State::init", + "negative molecular weight for species number "+int2str(k)); + } + /* + * Some surface phases may define species representing + * empty sites that have zero molecular weight. Give them + * a very small molecular weight to avoid dividing by + * zero. + */ + if (m_molwts[k] < Tiny) m_molwts[k] = Tiny; + m_rmolwts[k] = 1.0/m_molwts[k]; } - void State::setMoleFractions_NoNorm(const doublereal* x) { - m_mmw = dot(x, x + m_kk, m_molwts.begin()); - doublereal rmmw = 1.0/m_mmw; - transform(x, x + m_kk, m_ym.begin(), timesConstant(rmmw)); - transform(m_ym.begin(), m_ym.begin() + m_kk, m_molwts.begin(), - m_y.begin(), multiplies()); - } + /* + * Now that we have resized the State object, let's fill it with + * a valid mass fraction vector that sums to one. The State object + * should never have a mass fraction vector that doesn't sum to one. + * We will assume that species 0 has a mass fraction of 1.0 and + * mass fraction of all other species is 0.0. + */ + m_y[0] = 1.0; + m_ym[0] = m_y[0] * m_rmolwts[0]; + m_mmw = 1.0 / m_ym[0]; + } - doublereal State::massFraction(int k) const { - if (k >= 0 && k < m_kk) { - return m_y[k]; - } - else { - throw CanteraError("State:massFraction", - "illegal species index number"); - } - } + // True if the number of species has been set and fixed + bool State::ready() const { + return (m_kk > 0); + } - doublereal State::concentration(int k) const { - if (k >= 0 && k < m_kk) { - return m_y[k] * m_dens * m_rmolwts[k] ; - } - else { - throw CanteraError("State:massFraction", - "illegal species index number"); - } - } - - void State::setMassFractions(const doublereal* y) { - doublereal norm = 0.0, sum = 0.0; - //cblas_dcopy(m_kk, y, 1, m_y.begin(), 1); - norm = accumulate(y, y + m_kk, 0.0); - copy(y, y + m_kk, m_y.begin()); - scale(y, y + m_kk, m_y.begin(), 1.0/norm); - // for (k = 0; k != m_kk; ++k) { - // norm += y[k]; - // m_y[k] = y[k]; - //} - - //scale(m_kk, 1.0/norm, m_y.begin()); - transform(m_y.begin(), m_y.begin() + m_kk, m_rmolwts.begin(), - m_ym.begin(), multiplies()); - sum = accumulate(m_ym.begin(), m_ym.begin() + m_kk, 0.0); - // for (k = 0; k != m_kk; ++k) { - // m_ym[k] = m_y[k] * m_rmolwts[k]; - // sum += m_ym[k]; - //} - m_mmw = 1.0/sum; - } - - void State::setMassFractions_NoNorm(const doublereal* y) { - doublereal sum = 0.0; - copy(y, y + m_kk, m_y.begin()); - transform(m_y.begin(), m_y.end(), m_rmolwts.begin(), m_ym.begin(), - multiplies()); - sum = accumulate(m_ym.begin(), m_ym.end(), 0.0); - //for (k = 0; k != m_kk; ++k) { - // m_y[k] = y[k]; - // m_ym[k] = m_y[k] * m_rmolwts[k]; - // sum += m_ym[k]; - //} - m_mmw = 1.0/sum; - } - - doublereal State::sum_xlogx() const { - return m_mmw* Cantera::sum_xlogx(m_ym.begin(), m_ym.end()) + log(m_mmw); - } - - doublereal State::sum_xlogQ(doublereal* Q) const { - return m_mmw * Cantera::sum_xlogQ(m_ym.begin(), m_ym.end(), Q); - } - - void State::setConcentrations(const doublereal* c) { - int k; - doublereal sum = 0.0, norm = 0.0; - for (k = 0; k != m_kk; ++k) { - sum += c[k]*m_molwts[k]; - norm += c[k]; - } - m_mmw = sum/norm; - setDensity(sum); - doublereal rsum = 1.0/sum; - for (k = 0; k != m_kk; ++k) { - m_ym[k] = c[k] * rsum; - m_y[k] = m_ym[k] * m_molwts[k]; - } - } - - void State::getConcentrations(doublereal* c) const { - scale(m_ym.begin(), m_ym.end(), c, m_dens); - } - - doublereal State::mean_Y(const doublereal* Q) const { - return dot(m_y.begin(), m_y.end(), Q); - } - - void State::getMoleFractions(doublereal* x) const { - scale(m_ym.begin(), m_ym.end(), x, m_mmw); - } - - void State::getMassFractions(doublereal* y) const { - copy(m_y.begin(), m_y.end(), y); - } - - void State::init(const array_fp& mw) { - m_kk = mw.size(); - m_molwts.resize(m_kk); - m_rmolwts.resize(m_kk); - m_y.resize(m_kk, 0.0); - m_ym.resize(m_kk, 0.0); - copy(mw.begin(), mw.end(), m_molwts.begin()); - for (int k = 0; k < m_kk; k++) { - if (m_molwts[k] < 0.0) { - throw CanteraError("State::init", - "negative molecular weight for species number "+int2str(k)); - } - /* - * Some surface phases may define species representing - * empty sites that have zero molecular weight. Give them - * a very small molecular weight to avoid dividing by - * zero. - */ - if (m_molwts[k] < Tiny) m_molwts[k] = Tiny; - m_rmolwts[k] = 1.0/m_molwts[k]; - } - - /* - * Now that we have resized the State object, let's fill it with - * a valid mass fraction vector that sums to one. The State object - * should never have a mass fraction vector that doesn't sum to one. - * We will assume that species 0 has a mass fraction of 1.0 and - * mass fraction of all other species is 0.0. - */ - m_y[0] = 1.0; - m_ym[0] = m_y[0] * m_rmolwts[0]; - m_mmw = 1.0 / m_ym[0]; - } } diff --git a/Cantera/src/thermo/State.h b/Cantera/src/thermo/State.h index c7bdda3b5..65411be10 100755 --- a/Cantera/src/thermo/State.h +++ b/Cantera/src/thermo/State.h @@ -6,7 +6,6 @@ */ /* - * $Author$ * $Date$ * $Revision$ * @@ -60,357 +59,374 @@ namespace Cantera { * * @ingroup phases */ - class State { + class State { - public: + public: - /** - * Constructor. - */ - State(); + /** + * Constructor. + */ + State(); - /** - * Destructor. Since no memory is allocated by methods of this - * class, the destructor does nothing. - */ - virtual ~State(); + /** + * Destructor. Since no memory is allocated by methods of this + * class, the destructor does nothing. + */ + virtual ~State(); - /** - * Copy Constructor for the State Class - * - * @param right Reference to the class to be copied. - */ - State(const State& right); + /** + * Copy Constructor for the State Class + * + * @param right Reference to the class to be copied. + */ + State(const State& right); - /** - * Assignment operator for the state class. - * - * @param right Reference to the class to be copied. - */ - State& operator=(const State& right); + /** + * Assignment operator for the state class. + * + * @param right Reference to the class to be copied. + */ + State& operator=(const State& right); - /// @name Species Information - /// - /// The only thing class State knows about the species is their - /// molecular weights. - //@{ + /// @name Species Information + /// + /// The only thing class State knows about the species is their + /// molecular weights. + //@{ - /// Return a read-only reference to the array of molecular - /// weights. - const array_fp& molecularWeights() const { return m_molwts; } + /// Return a read-only reference to the array of molecular + /// weights. + const array_fp& molecularWeights() const { return m_molwts; } - //@} - /// @name Composition - //@{ + //@} + /// @name Composition + //@{ - //! Get the species mole fraction vector. - /*! - * @param x On return, x contains the mole fractions. Must have a - * length greater than or equal to the number of species. - */ - void getMoleFractions(doublereal* x) const; + //! Get the species mole fraction vector. + /*! + * @param x On return, x contains the mole fractions. Must have a + * length greater than or equal to the number of species. + */ + void getMoleFractions(doublereal* const x) const; - //! The mole fraction of species k. - /*! - * If k is ouside the valid - * range, an exception will be thrown. Note that it is - * somewhat more efficent to call getMoleFractions if the - * mole fractions of all species are desired. - * @param k species index - */ - doublereal moleFraction(int k) const; + //! The mole fraction of species k. + /*! + * If k is ouside the valid + * range, an exception will be thrown. Note that it is + * somewhat more efficent to call getMoleFractions if the + * mole fractions of all species are desired. + * @param k species index + */ + doublereal moleFraction(const int k) const; - /** - * Set the mole fractions to the specified values, and then - * normalize them so that they sum to 1.0. - * @param x Array of unnormalized mole fraction values (input). - * Must have a length greater than or equal to the number of - * species. - * - * @param x Input vector of mole fractions. - * Length is m_kk. - */ - virtual void setMoleFractions(const doublereal* x); + /** + * Set the mole fractions to the specified values, and then + * normalize them so that they sum to 1.0. + * @param x Array of unnormalized mole fraction values (input). + * Must have a length greater than or equal to the number of + * species. + * + * @param x Input vector of mole fractions. + * Length is m_kk. + */ + virtual void setMoleFractions(const doublereal* const x); - /** - * Set the mole fractions to the specified values without - * normalizing. This is useful when the normalization - * condition is being handled by some other means, for example - * by a constraint equation as part of a larger set of - * equations. - * - * @param x Input vector of mole fractions. - * Length is m_kk. - */ - virtual void setMoleFractions_NoNorm(const doublereal* x); + /** + * Set the mole fractions to the specified values without + * normalizing. This is useful when the normalization + * condition is being handled by some other means, for example + * by a constraint equation as part of a larger set of + * equations. + * + * @param x Input vector of mole fractions. + * Length is m_kk. + */ + virtual void setMoleFractions_NoNorm(const doublereal* const x); - /** - * Get the species mass fractions. - * @param y On return, y - * contains the mass fractions. Array \a y must have a length - * greater than or equal to the number of species. - * - * @param y Output vector of mass fractions. - * Length is m_kk. - */ - void getMassFractions(doublereal* y) const; + /** + * Get the species mass fractions. + * @param y On return, y + * contains the mass fractions. Array \a y must have a length + * greater than or equal to the number of species. + * + * @param y Output vector of mass fractions. + * Length is m_kk. + */ + void getMassFractions(doublereal* const y) const; - //! Mass fraction of species k. - /*! - * If k is outside the valid - * range, an exception will be thrown. Note that it is - * somewhat more efficent to call getMassFractions if the - * mass fractions of all species are desired. - * - * @param k species index - */ - doublereal massFraction(int k) const; + //! Mass fraction of species k. + /*! + * If k is outside the valid + * range, an exception will be thrown. Note that it is + * somewhat more efficent to call getMassFractions if the + * mass fractions of all species are desired. + * + * @param k species index + */ + doublereal massFraction(const int k) const; - /** - * Set the mass fractions to the specified values, and then - * normalize them so that they sum to 1.0. - * @param y Array of unnormalized mass fraction values (input). - * Must have a length greater than or equal to the number of - * species. - * - * @param y Input vector of mass fractions. - * Length is m_kk. - */ - virtual void setMassFractions(const doublereal* y); + /** + * Set the mass fractions to the specified values, and then + * normalize them so that they sum to 1.0. + * @param y Array of unnormalized mass fraction values (input). + * Must have a length greater than or equal to the number of + * species. + * + * @param y Input vector of mass fractions. + * Length is m_kk. + */ + virtual void setMassFractions(const doublereal* const y); - /** - * Set the mass fractions to the specified values without - * normalizing. This is useful when the normalization - * condition is being handled by some other means, for example - * by a constraint equation as part of a larger set of - * equations. - * - * @param y Input vector of mass fractions. - * Length is m_kk. - */ - virtual void setMassFractions_NoNorm(const doublereal* y); + /** + * Set the mass fractions to the specified values without + * normalizing. This is useful when the normalization + * condition is being handled by some other means, for example + * by a constraint equation as part of a larger set of + * equations. + * + * @param y Input vector of mass fractions. + * Length is m_kk. + */ + virtual void setMassFractions_NoNorm(const doublereal* const y); - /** - * Get the species concentrations (kmol/m^3). @param c On - * return, \a c contains the concentrations for all species. - * Array \a c must have a length greater than or equal to the - * number of species. - */ - void getConcentrations(doublereal* c) const; + /** + * Get the species concentrations (kmol/m^3). @param c On + * return, \a c contains the concentrations for all species. + * Array \a c must have a length greater than or equal to the + * number of species. + */ + void getConcentrations(doublereal* const c) const; - /** - * Concentration of species k. If k is outside the valid - * range, an exception will be thrown. - * - * @param k Index of species - */ - doublereal concentration(int k) const; + /** + * Concentration of species k. If k is outside the valid + * range, an exception will be thrown. + * + * @param k Index of species + */ + doublereal concentration(const int k) const; - /** - * Set the concentrations to the specified values within the - * phase. - * - * @param c The input vector to this routine is in dimensional - * units. For volumetric phases c[k] is the - * concentration of the kth species in kmol/m3. - * For surface phases, c[k] is the concentration - * in kmol/m2. The length of the vector is the number - * of species in the phase. - */ - virtual void setConcentrations(const doublereal* c); + /** + * Set the concentrations to the specified values within the + * phase. + * + * @param c The input vector to this routine is in dimensional + * units. For volumetric phases c[k] is the + * concentration of the kth species in kmol/m3. + * For surface phases, c[k] is the concentration + * in kmol/m2. The length of the vector is the number + * of species in the phase. + */ + virtual void setConcentrations(const doublereal* const c); - /** - * Returns a read-only pointer to the start of the - * massFraction array - */ - const doublereal* massFractions() const { return &m_y[0]; } + /** + * Returns a read-only pointer to the start of the + * massFraction array + */ + const doublereal* massFractions() const { + return &m_y[0]; + } - /** - * Returns a read-only pointer to the start of the - * moleFraction/MW array. This array is the array of mole - * fractions, each divided by the mean molecular weight. - */ - const doublereal* moleFractdivMMW() const { return &m_ym[0];} + /** + * Returns a read-only pointer to the start of the + * moleFraction/MW array. This array is the array of mole + * fractions, each divided by the mean molecular weight. + */ + const doublereal* moleFractdivMMW() const; + + //@} + + /// @name Mean Properties + //@{ + /** + * Evaluate the mole-fraction-weighted mean of Q: + * \f[ \sum_k X_k Q_k. \f] + * Array Q should contain pure-species molar property + * values. + * + * @param Q input vector of length m_kk that is to be averaged. + * @return + * mole-freaction-weighted mean of Q + */ + doublereal mean_X(const doublereal* const Q) const; + + /** + * Evaluate the mass-fraction-weighted mean of Q: + * \f[ \sum_k Y_k Q_k \f] + * + * @param Q Array Q contains a vector of species property values in mass units. + * @return + * Return value containing the mass-fraction-weighted mean of Q. + */ + doublereal mean_Y(const doublereal* const Q) const; + + /** + * The mean molecular weight. Units: (kg/kmol) + */ + doublereal meanMolecularWeight() const { + return m_mmw; + } + + //! Evaluate \f$ \sum_k X_k \log X_k \f$. + /*! + * @return + * returns the indicated sum. units are dimensionless. + */ + doublereal sum_xlogx() const; + + //! Evaluate \f$ \sum_k X_k \log Q_k \f$. + /*! + * @param Q Vector of length m_kk to take the log average of + * @return Returns the indicated sum. + */ + doublereal sum_xlogQ(doublereal* const Q) const; + //@} + + /// @name Thermodynamic Properties + /// Class State only stores enough thermodynamic data to + /// specify the state. In addition to composition information, + /// it stores the temperature and + /// mass density. + //@{ + + /// Temperature (K). + doublereal temperature() const { + return m_temp; + } + + /// Density (kg/m^3). + virtual doublereal density() const { + return m_dens; + } + + /// Molar density (kmol/m^3). + doublereal molarDensity() const; + + //! Set the internally storred density (kg/m^3) of the phase + /*! + * Note the density of a phase is an indepedent variable. + * + * @param density Input density (kg/m^3). + */ + virtual void setDensity(const doublereal density) { + m_dens = density; + } + + //! Set the internally storred molar density (kmol/m^3) of the phase. + /*! + * @param molarDensity Input molar density (kmol/m^3). + */ + virtual void setMolarDensity(const doublereal molarDensity); + + //! Set the temperature (K). + /*! + * This function sets the internally storred temperature of the phase. + * + * @param temp Temperature in kelvin + */ + virtual void setTemperature(const doublereal temp) { + m_temp = temp; + } + //@} + + //! True if the number species has been set + bool ready() const; - //@} + void stateMFChangeCalc(bool forceChange = false); - /// @name Mean Properties - //@{ - /** - * Evaluate the mole-fraction-weighted mean of Q: - * \f[ \sum_k X_k Q_k. \f] - * Array Q should contain pure-species molar property - * values. - * - * @param Q input vector of length m_kk that is to be averaged. - * @return - * mole-freaction-weighted mean of Q - */ - doublereal mean_X(const doublereal* Q) const { - return m_mmw*std::inner_product(m_ym.begin(), m_ym.end(), Q, 0.0); - } + //! Return the state number + int stateMFNumber() const; - /** - * Evaluate the mass-fraction-weighted mean of Q: - * \f[ \sum_k Y_k Q_k \f] - * - * @param Q Array Q contains a vector of species property values in mass units. - * @return - * Return value containing the mass-fraction-weighted mean of Q. - */ - doublereal mean_Y(const doublereal* Q) const; + protected: - /** - * The mean molecular weight. Units: (kg/kmol) - */ - doublereal meanMolecularWeight() const { - return m_mmw; - } - - //! Evaluate \f$ \sum_k X_k \log X_k \f$. - /*! - * @return - * returns the indicated sum. units are dimensionless. - */ - doublereal sum_xlogx() const; - - //! Evaluate \f$ \sum_k X_k \log Q_k \f$. - /*! - * @param Q Vector of length m_kk to take the log average of - * @return Returns the indicated sum. - */ - doublereal sum_xlogQ(doublereal* Q) const; - //@} - - /// @name Thermodynamic Properties - /// Class State only stores enough thermodynamic data to - /// specify the state. In addition to composition information, - /// it stores the temperature and - /// mass density. - //@{ - - /// Temperature (K). - doublereal temperature() const { return m_temp; } - - /// Density (kg/m^3). - virtual doublereal density() const { return m_dens; } - - /// Molar density (kmol/m^3). - doublereal molarDensity() const { - return density()/meanMolecularWeight(); - } - - //! Set the internally storred density (kg/m^3) of the phase - /*! - * Note the density of a phase is an indepedent variable. - * - * @param density Input density (kg/m^3). - */ - virtual void setDensity(doublereal density) { - m_dens = density; - } - - //! Set the internally storred molar density (kmol/m^3) of the phase. - /*! - * @param molarDensity Input molar density (kmol/m^3). - */ - virtual void setMolarDensity(doublereal molarDensity) { - m_dens = molarDensity*meanMolecularWeight(); - } - - //! Set the temperature (K). - /*! - * This function sets the internally storred temperature of the phase. - * - * @param temp Temperature in kelvin - */ - virtual void setTemperature(doublereal temp) { - m_temp = temp; - } - //@} - - //! True if the number species has been set - bool ready() const { return (m_kk > 0); } - - protected: - - /** - * @internal - * Initialize. Make a local copy of the vector of - * molecular weights, and resize the composition arrays to - * the appropriate size. The only information an instance of - * State has about the species is their molecular weights. - * - * @param mw Vector of molecular weights of the species. - */ - void init(const array_fp& mw); //, density_is_independent = true); + /** + * @internal + * Initialize. Make a local copy of the vector of + * molecular weights, and resize the composition arrays to + * the appropriate size. The only information an instance of + * State has about the species is their molecular weights. + * + * @param mw Vector of molecular weights of the species. + */ + void init(const array_fp& mw); //, density_is_independent = true); - /** - * m_kk is the number of species in the phase - */ - int m_kk; + /** + * m_kk is the number of species in the phase + */ + int m_kk; - //! Set the molecular weight of a single species to a given value - /*! - * @param k id of the species - * @param mw Molecular Weight (kg kmol-1) - */ - void setMolecularWeight(int k, double mw) { - m_molwts[k] = mw; - m_rmolwts[k] = 1.0/mw; - } + //! Set the molecular weight of a single species to a given value + /*! + * @param k id of the species + * @param mw Molecular Weight (kg kmol-1) + */ + void setMolecularWeight(const int k, const double mw) { + m_molwts[k] = mw; + m_rmolwts[k] = 1.0/mw; + } - private: + private: - /** - * Temperature. This is an independent variable - * units = Kelvin - */ - doublereal m_temp; + /** + * Temperature. This is an independent variable + * units = Kelvin + */ + doublereal m_temp; - /** - * Density. This is an independent variable except in - * the incompressible degenerate case. Thus, - * the pressure is determined from this variable - * not the other way round. - * units = kg m-3 - */ - doublereal m_dens; + /** + * Density. This is an independent variable except in + * the incompressible degenerate case. Thus, + * the pressure is determined from this variable + * not the other way round. + * units = kg m-3 + */ + doublereal m_dens; - /** - * m_mmw is the mean molecular weight of the mixture - * (kg kmol-1) - */ - doublereal m_mmw; + /** + * m_mmw is the mean molecular weight of the mixture + * (kg kmol-1) + */ + doublereal m_mmw; - /** - * m_ym[k] = mole fraction of species k divided by the - * mean molecular weight of mixture. - */ - mutable array_fp m_ym; + /** + * m_ym[k] = mole fraction of species k divided by the + * mean molecular weight of mixture. + */ + mutable array_fp m_ym; - /** - * m_y[k] = mass fraction of species k - */ - mutable array_fp m_y; + /** + * m_y[k] = mass fraction of species k + */ + mutable array_fp m_y; - /** - * m_molwts[k] = molecular weight of species k (kg kmol-1) - */ - array_fp m_molwts; + /** + * m_molwts[k] = molecular weight of species k (kg kmol-1) + */ + array_fp m_molwts; - /** - * m_rmolwts[k] = inverse of the molecular weight of species k - * units = kmol kg-1. - */ - array_fp m_rmolwts; + /** + * m_rmolwts[k] = inverse of the molecular weight of species k + * units = kmol kg-1. + */ + array_fp m_rmolwts; - }; + //! State Change variable + /*! + * Whenever the mole fraction vector changes, this int is + * incremented. + */ + int m_stateNum; + + }; + + + inline int State::stateMFNumber() const { + return m_stateNum; + } }