diff --git a/include/cantera/thermo/CoverageDependentSurfPhase.h b/include/cantera/thermo/CoverageDependentSurfPhase.h index cd5d2423430..2578329609f 100644 --- a/include/cantera/thermo/CoverageDependentSurfPhase.h +++ b/include/cantera/thermo/CoverageDependentSurfPhase.h @@ -17,30 +17,29 @@ namespace Cantera { - //! Set of parameters modifying SurfPhase enthalpy and entropy based on fractional surface coverages //! using a polynomial model. Linear model is a subset of the polynomial model. struct PolynomialDependency { //! Constructor - //! @param name_k_ name of a species whose thermodynamics are calculated - //! @param name_j_ name of a species whose coverage affects thermodynamics of the target species + //! @param k_ index of a species whose thermodynamics are calculated + //! @param j_ index of a species whose coverage affects thermodynamics of the target species //! @param enthalpy_coeffs_ array of polynomial coefficients describing enthalpy change //! containing 1st-order, 2nd-order, 3rd-order, and 4th-order //! coefficients as a function of coverage [J/kmol] //! @param entropy_coeffs_ array of polynomial coefficients describing entropy change //! containing 1st-order, 2nd-order, 3rd-order, and 4th-order //! coefficients as a function of coverage [J/kmol/K] - PolynomialDependency(std::string name_k_, std::string name_j_, + PolynomialDependency(size_t k_, size_t j_, vector_fp enthalpy_coeffs_, vector_fp entropy_coeffs_): - name_k(name_k_), name_j(name_j_), + k(k_), j(j_), enthalpy_coeffs(enthalpy_coeffs_), entropy_coeffs(entropy_coeffs_) {} PolynomialDependency() {} - //! name of a species whose thermodynamics are calculated - std::string name_k; - //! name of a species whose coverage affects thermodynamics of the target species - std::string name_j; + //! index of a species whose thermodynamics are calculated + size_t k; + //! index of a species whose coverage affects thermodynamics of the target species + size_t j; //! array of polynomial coefficients describing enthalpy change containing 1st-order, 2nd-order, //! 3rd-order, and 4th-order coefficients as a function of coverage [J/kmol] vector_fp enthalpy_coeffs; @@ -54,8 +53,8 @@ struct PolynomialDependency struct PiecewiseDependency { //! Constructor - //! @param name_k_ name of a species whose thermodynamics are calculated - //! @param name_j_ name of a species whose coverage affects thermodynamics of the target species + //! @param k_ index of a species whose thermodynamics are calculated + //! @param j_ index of a species whose coverage affects thermodynamics of the target species //! @param enthalpy_params_ array of three parameters to calculate coverage-dependent enthalpy: //! slope of enthalpy change in the first region [J/kmol], slope of //! enthalpy change in the second region [J/kmol], and coverage @@ -64,16 +63,16 @@ struct PiecewiseDependency //! slope of entropy change in the first region [J/kmol/K], slope of //! entropy change in the second region [J/kmol/K], and coverage //! dividing first and second region [dimensionless] - PiecewiseDependency(std::string name_k_, std::string name_j_, + PiecewiseDependency(size_t k_, size_t j_, vector_fp enthalpy_params_, vector_fp entropy_params_): - name_k(name_k_), name_j(name_j_), + k(k_), j(j_), enthalpy_params(enthalpy_params_), entropy_params(entropy_params_) {} PiecewiseDependency() {} - //! name of a species whose thermodynamics are calculated - std::string name_k; - //! name of a species whose coverage affects thermodynamics of the target species - std::string name_j; + //! index of a species whose thermodynamics are calculated + size_t k; + //! index of a species whose coverage affects thermodynamics of the target species + size_t j; //! array of three parameters to calculate coverage-dependent enthalpy: slope of enthalpy change //! in the first region [J/kmol], slope of enthalpy change in the second region [J/kmol], //! and coverage dividing first and second region [dimensionless] @@ -89,37 +88,27 @@ struct PiecewiseDependency struct InterpolativeDependency { //! Constructor - //! @param name_k_ name of a species whose thermodynamics are calculated - //! @param name_j_ name of a species whose coverage affects thermodynamics of the target species - //! @param enthalpy_coverages_ array of coverages for coverage-dependent enthalpy interpolation - //! [dimensionless] - //! @param enthalpies_ array of enthalpies at corresponding coverages in enthalpy-coverages - //! [J/kmol] - //! @param entropy_coverages_ array of coverages for coverage-dependent entropy interpolation - //! [dimensionless] - //! @param entropies_ array of entropies at corresponding coverages in entropy-coverages - //! [J/kmol/K] - InterpolativeDependency(std::string name_k_, std::string name_j_, - vector_fp enthalpy_coverages_, vector_fp enthalpies_, - vector_fp entropy_coverages_, vector_fp entropies_): - name_k(name_k_), name_j(name_j_), - enthalpy_coverages(enthalpy_coverages_), - enthalpies(enthalpies_), - entropy_coverages(entropy_coverages_), - entropies(entropies_) {} + //! @param k_ index of a species whose thermodynamics are calculated + //! @param j_ index of a species whose coverage affects thermodynamics of the target species + //! @param enthalpy_map_ map of as a key-value pair where coverage + //! is [dimensionless] and enthalpy has [J/kmol] unit + //! @param entropy_map_ map of as a key-value pair where coverage + //! is [dimensionless] and entropy has [J/kmol/K] unit + InterpolativeDependency(size_t k_, size_t j_, + std::map enthalpy_map_, + std::map entropy_map_): + k(k_), j(j_), + enthalpy_map(enthalpy_map_), + entropy_map(entropy_map_){} InterpolativeDependency() {} - //! name of a species whose thermodynamics are calculated - std::string name_k; - //! name of a species whose coverage affects thermodynamics of the target species - std::string name_j; - //! array of coverages for coverage-dependent enthalpy interpolation [dimensionless] - vector_fp enthalpy_coverages; - //! array of enthalpies at corresponding coverages in enthalpy-coverages [J/kmol] - vector_fp enthalpies; - //! array of coverages for coverage-dependent entropy interpolation [dimensionless] - vector_fp entropy_coverages; - //! array of entropies at corresponding coverages in entropy-coverages [J/kmol/K] - vector_fp entropies; + //! index of a species whose thermodynamics are calculated + size_t k; + //! index of a species whose coverage affects thermodynamics of the target species + size_t j; + //! map of coverage-enthalpy pairs for coverage-dependent enthalpy interpolation + std::map enthalpy_map; + //! map of coverage-entropy pairs for coverage-dependent entropy interpolation + std::map entropy_map; }; //! Set of parameters modifying SurfPhase heat capacity based on fractional surface coverages @@ -127,19 +116,19 @@ struct InterpolativeDependency struct HeatCapacityDependency { //! Constructor - //! @param name_k_ name of a species whose thermodynamics are calculated - //! @param name_j_ name of a species whose coverage affects thermodynamics of the target species + //! @param k_ index of a species whose thermodynamics are calculated + //! @param j_ index of a species whose coverage affects thermodynamics of the target species //! @param cpcov_a_ log model coefficient a [J/kmol/K] //! @param cpcov_b_ log model coefficient b [J/kmol/K] - HeatCapacityDependency(std::string name_k_, std::string name_j_, + HeatCapacityDependency(size_t k_, size_t j_, double cpcov_a_, double cpcov_b_): - name_k(name_k_), name_j(name_j_), + k(k_), j(j_), cpcov_a(cpcov_a_), cpcov_b(cpcov_b_) {} HeatCapacityDependency() {} - //! name of a species whose thermodynamics are calculated - std::string name_k; - //! name of a species whose coverage affects thermodynamics of the target species - std::string name_j; + //! index of a species whose thermodynamics are calculated + size_t k; + //! index of a species whose coverage affects thermodynamics of the target species + size_t j; double cpcov_a; //! log model coefficient a [J/kmol/K] double cpcov_b; //! log model coefficient b [J/kmol/K] }; @@ -147,16 +136,16 @@ struct HeatCapacityDependency class CoverageDependentSurfPhase : public SurfPhase { public: - //! Constructor. - //! @param n0 Site Density of the Surface Phase [kmol m^-2] - CoverageDependentSurfPhase(double n0 = 1.0); + //! Default constructor + CoverageDependentSurfPhase(); //! Construct and initialize a CoverageDependentSurfPhase ThermoPhase object directly //! from an input file //! @param infile name of the input file //! @param id name of the phase id in the file. If this is blank, the first phase //! in the file is used - explicit CoverageDependentSurfPhase(const std::string& infile, const std::string& id); + explicit CoverageDependentSurfPhase(const std::string& infile, + const std::string& id=""); //! Set the polynomial coverage dependece for species /*! @@ -245,25 +234,6 @@ class CoverageDependentSurfPhase : public SurfPhase virtual void initThermo(); virtual bool addSpecies(shared_ptr spec); - //! @copydoc SurfPhase::setCoverages - //! After setting coverages, covstateNum is incremented by 1. - virtual void setCoverages(const double* theta); - - //! @copydoc SurfPhase::setCoveragesNoNorm - //! After setting coverages, covstateNum is incremented by 1. - virtual void setCoveragesNoNorm(const double* theta); - - //! Return the covstateNum - int statecovNumber() const { - return m_covstateNum; - } - - //! Convert given eneregy to the quantity with its default unit of J/kmol. - double convertEnergy(double value, const std::string& src) const; - - //! Convert given energy per temperature to the quantity with its default unit of J/kmol/K. - double convertEnergy_T(double value, const std::string& src) const; - // Functions calculating reference state thermodyanmic properties-------------- //! Return the nondimensionalized reference state enthalpy. @@ -428,17 +398,8 @@ class CoverageDependentSurfPhase : public SurfPhase virtual double cp_mole() const; protected: - //! Temporary storage for the reference state enthalpies. - mutable vector_fp m_h_ref; - - //! Temporary storage for the reference state entropies. - mutable vector_fp m_s_ref; - - //! Temporary storage for the reference state heat capacities. - mutable vector_fp m_cp_ref; - - //! Temporary storage for the reference state chemical potentials. - mutable vector_fp m_mu_ref; + //! Temporary storage for the coverages. + mutable vector_fp m_cov; //! Temporary storage for the coverage-dependent enthalpies. mutable vector_fp m_h_cov; @@ -468,96 +429,29 @@ class CoverageDependentSurfPhase : public SurfPhase //! and coverage-dependent chemical potentials. mutable vector_fp m_chempot; - /*! Indicate the surface coverages have changed by incrementing the - * coverage state number by one. This function is called whenever - * the setCoverages() or setCoveragesNoNorm() was used to update the - * coverage array. - */ - void coverageChanged(); - //! Array of enthalpy and entropy coverage dependency parameters used in //! the linear and polynomial models. - mutable std::vector m_PolynomialDependency; + std::vector m_PolynomialDependency; //! Array of enthalpy and entropy coverage dependency parameters used in //! the piecewise linear model. - mutable std::vector m_PiecewiseDependency; + std::vector m_PiecewiseDependency; //! Array of enthalpy and entropy coverage dependency parameters used in //! the interpolative model. - mutable std::vector m_InterpolativeDependency; + std::vector m_InterpolativeDependency; //! Array of heat capacity coverage dependency parameters. - mutable std::vector m_HeatCapacityDependency; - - //! Storage for the linear and polynomial model coverage dependency - //! parameters for enthalpy. - mutable vector_fp m_polynomial_h; - - //! Storage for the linear and polynomial model coverage dependency - //! parameters for entropy. - mutable vector_fp m_polynomial_s; - - //! Storage for the piecewise linear model coverage dependency parameters - //! for enthalpy. - mutable vector_fp m_piecewise_h; - - //! Storage for the piecewise linear model coverage dependency parameters - //! for entropy. - mutable vector_fp m_piecewise_s; - - //! Storage for the interpolative model coverage array for enthalpy. - mutable vector_fp m_interpolative_hcov; - - //! Storage for the interpolative model enthalpy array. - mutable vector_fp m_interpolative_h; - - //! Storage for the interpolative model coverage array for entropy. - mutable vector_fp m_interpolative_scov; - - //! Storage for the interpolative model entropy array. - mutable vector_fp m_interpolative_s; - - //! Storage for the coverage-dependent heat capacity log model coefficients. - mutable double m_cpcov_a, m_cpcov_b; + std::vector m_HeatCapacityDependency; private: - //! Coverage state change variable. Whenever the coverage array changes, - //! this number is incremented. - int m_covstateNum; - - //! Last value of the coverage state number processed. - mutable int m_covstateNumlast; - - //! Flag indicating polynomial coverage-dependent model is being used. - mutable bool m_has_polynomial_dependency; - - //! Flag indicating piecewise linear coverage-dependent model is being used. - mutable bool m_has_piecewise_dependency; - - //! Flag indicating interpolative coverage-dependent model is being used. - mutable bool m_has_interpolative_dependency; - - //! Flag indicating coverage-dependent heat capacity is being calculated. - mutable bool m_has_heatcapacity_dependency; - - //! Flag indicating user has defined the reference coverage. - mutable bool m_has_ref_coverage; + //! Last value of the state number processed. + mutable int m_stateNumlast; //! Storage for the user-defined reference state coverage which has to be - //! greater than 0.0 and less than or equal to 1.0. + //! greater than 0.0 and less than or equal to 1.0. default = 1.0. mutable double m_theta_ref; - //! Update the species ideal reference state thermodynamic functions - /*! - * The polynomials for the ideal surface reference functions are only - * reevaluated if the temperature has changed. - * - * @param force Boolean, which if true, forces a reevaluation of the thermo - * polynomials. default = false. - */ - void _updateReferenceThermo(bool force=false) const; - //! Update the species coverage-dependent thermodynamic functions /*! * The coverage-dependent enthalpy and entropy are only reevaluated @@ -578,7 +472,7 @@ class CoverageDependentSurfPhase : public SurfPhase * reference state as well as coverage-dependent functions. * default = false. */ - void _updateThermo(bool force=false) const; + void _updateTotalThermo(bool force=false) const; }; diff --git a/include/cantera/thermo/SurfPhase.h b/include/cantera/thermo/SurfPhase.h index 1ffe6eb736b..d06e9ee485e 100644 --- a/include/cantera/thermo/SurfPhase.h +++ b/include/cantera/thermo/SurfPhase.h @@ -358,7 +358,7 @@ class SurfPhase : public ThermoPhase * * This routine normalizes the theta's to 1, before application */ - virtual void setCoverages(const doublereal* theta); + void setCoverages(const doublereal* theta); //! Set the surface site fractions to a specified state. /*! @@ -370,7 +370,7 @@ class SurfPhase : public ThermoPhase * @param theta This is the surface site fraction for the kth species in * the surface phase. This is a dimensionless quantity. */ - virtual void setCoveragesNoNorm(const doublereal* theta); + void setCoveragesNoNorm(const doublereal* theta); //! Set the coverages from a string of colon-separated name:value pairs. /*! @@ -431,7 +431,6 @@ class SurfPhase : public ThermoPhase */ mutable vector_fp m_logsize; -private: //! Update the species reference state thermodynamic functions /*! * The polynomials for the standard state functions are only reevaluated if diff --git a/src/thermo/CoverageDependentSurfPhase.cpp b/src/thermo/CoverageDependentSurfPhase.cpp index 6d7ed13f071..1eac4d457fd 100644 --- a/src/thermo/CoverageDependentSurfPhase.cpp +++ b/src/thermo/CoverageDependentSurfPhase.cpp @@ -21,158 +21,86 @@ using namespace std; namespace Cantera { -CoverageDependentSurfPhase::CoverageDependentSurfPhase(double n0): - m_covstateNum(-1), - m_covstateNumlast(0), - m_has_polynomial_dependency(false), - m_has_piecewise_dependency(false), - m_has_interpolative_dependency(false), - m_has_heatcapacity_dependency(false), - m_has_ref_coverage(false) +CoverageDependentSurfPhase::CoverageDependentSurfPhase(): + m_stateNumlast(-2), + m_theta_ref(1.0) { - setSiteDensity(n0); + setSiteDensity(1.0); setNDim(2); } CoverageDependentSurfPhase::CoverageDependentSurfPhase(const std::string& infile, - const std::string& id_): - m_covstateNum(-1), - m_covstateNumlast(0), - m_has_polynomial_dependency(false), - m_has_piecewise_dependency(false), - m_has_interpolative_dependency(false), - m_has_heatcapacity_dependency(false), - m_has_ref_coverage(false) + const std::string& id_) { + CoverageDependentSurfPhase(); initThermoFile(infile, id_); } void CoverageDependentSurfPhase::setPolynomialDependency(const PolynomialDependency& poly_deps) { - size_t k = speciesIndex(poly_deps.name_k); - size_t j = speciesIndex(poly_deps.name_j); - - if (k == npos) { - throw CanteraError("CoverageDependentSurfPhase::setPolynomialDependency", - "Unknown species '{}'.", poly_deps.name_k); - } - - if (j == npos) { - throw CanteraError("CoverageDependentSurfPhase::setPolynomialDependency", - "Unknown species '{}'.", poly_deps.name_k); - } - m_PolynomialDependency.push_back(poly_deps); - m_has_polynomial_dependency = true; } void CoverageDependentSurfPhase::setPiecewiseDependency(const PiecewiseDependency& plin_deps) { - size_t k = speciesIndex(plin_deps.name_k); - size_t j = speciesIndex(plin_deps.name_j); double hcov_change = plin_deps.enthalpy_params[2]; double scov_change = plin_deps.entropy_params[2]; - if (k == npos) { - throw CanteraError("CoverageDependentSurfPhase::setPiecewiseDependency", - "Unknown species '{}'.", plin_deps.name_k); - } - - if (j == npos) { - throw CanteraError("CoverageDependentSurfPhase::setPiecewiseDependency", - "Unknown species '{}'.", plin_deps.name_j); - } - if (hcov_change <= 0.0 || hcov_change > 1.0 || scov_change <= 0.0 || scov_change > 1.0) { throw CanteraError("CoverageDependentSurfPhase::setPiecewiseDependency", "Coverage where slope changes must be greater than 0.0 and less than or equal to 1.0."); } m_PiecewiseDependency.push_back(plin_deps); - m_has_piecewise_dependency = true; } void CoverageDependentSurfPhase::setInterpolativeDependency(const InterpolativeDependency& int_deps) { - size_t k = speciesIndex(int_deps.name_k); - size_t j = speciesIndex(int_deps.name_j); - - if (k == npos) { - throw CanteraError("CoverageDependentSurfPhase::setInterpolativeDependency", - "Unknown species '{}'.", int_deps.name_k); - } - if (int_deps.enthalpy_coverages.size() != int_deps.enthalpies.size()) { - throw CanteraError("CoverageDependentSurfPhase::setInterpolativeDependency", - "Sizes of coverages array and enthalpies array are not equal."); - } double hcov_last = 0.0; - for (const auto& hcov_now : int_deps.enthalpy_coverages) { - if (hcov_now < hcov_last) { + for (auto iter=int_deps.enthalpy_map.begin();iter!=int_deps.enthalpy_map.end();++iter){ + if (iter->first < hcov_last) { throw CanteraError("CoverageDependentSurfPhase::setInterpolativeDependency", - "Coverages are not in ascending order."); + "Coverages are not in ascending order."); } - hcov_last = hcov_now; + hcov_last = iter->first; } - if (int_deps.enthalpy_coverages.front() != 0.0) { + if (int_deps.enthalpy_map.count(0.0) == 0) { throw CanteraError("CoverageDependentSurfPhase::setInterpolativeDependency", "The first element of enthalpy-coverages array must be 0.0."); } - if (int_deps.enthalpy_coverages.back() != 1.0) { + if (int_deps.enthalpy_map.count(1.0) == 0) { throw CanteraError("CoverageDependentSurfPhase::setInterpolativeDependency", "The last element of enthalpy-coverages array must be 1.0."); } - if (j == npos) { - throw CanteraError("CoverageDependentSurfPhase::setInterpolativeDependency", - "Unknown species '{}'.", int_deps.name_j); - } - if (int_deps.entropy_coverages.size() != int_deps.entropies.size()) { - throw CanteraError("CoverageDependentSurfPhase::setInterpolativeDependency", - "Sizes of coverages array and entropies array are not equal."); - } double scov_last = 0.0; - for (const auto& scov_now : int_deps.entropy_coverages) { - if (scov_now < scov_last) { + for (auto iter=int_deps.entropy_map.begin();iter!=int_deps.entropy_map.end();++iter){ + if (iter->first < scov_last) { throw CanteraError("CoverageDependentSurfPhase::setInterpolativeDependency", - "Coverages are not in ascending order."); + "Coverages are not in ascending order."); } - scov_last = scov_now; + scov_last = iter->first; } - if (int_deps.entropy_coverages.front() != 0.0) { + if (int_deps.entropy_map.count(0.0) == 0) { throw CanteraError("CoverageDependentSurfPhase::setInterpolativeDependency", "The first element of entropy-coverages array must be 0.0."); } - if (int_deps.entropy_coverages.back() != 1.0) { + if (int_deps.entropy_map.count(1.0) == 0) { throw CanteraError("CoverageDependentSurfPhase::setInterpolativeDependency", "The last element of entropy-coverages array must be 1.0."); } m_InterpolativeDependency.push_back(int_deps); - m_has_interpolative_dependency = true; } void CoverageDependentSurfPhase::setHeatCapacityDependency(const HeatCapacityDependency& cpcov_deps) { - size_t k = speciesIndex(cpcov_deps.name_k); - size_t j = speciesIndex(cpcov_deps.name_j); - - if (k == npos) { - throw CanteraError("CoverageDependentSurfPhase::setHeatCapacityDependency", - "Unknown species '{}'.", cpcov_deps.name_k); - } - - if (j == npos) { - throw CanteraError("CoverageDependentSurfPhase::setHeatCapacityDependency", - "Unknown species '{}'.", cpcov_deps.name_j); - } - m_HeatCapacityDependency.push_back(cpcov_deps); - m_has_heatcapacity_dependency = true; } void CoverageDependentSurfPhase::initThermo() @@ -188,154 +116,105 @@ void CoverageDependentSurfPhase::initThermo() throw CanteraError("CoverageDependentSurfPhase::initThermo", "Reference state coverage must be greater than 0.0 and less than or equal to 1.0."); } - m_has_ref_coverage = true; } for (auto& item : m_species) { // Read enthalpy and entropy dependencies from species 'input' information // (i.e. as specified in a YAML input file) for both self- and cross- // interactions. if (item.second->input.hasKey("coverage-dependencies")) { - auto cov_map = item.second->input["coverage-dependencies"]; + auto& cov_map = item.second->input["coverage-dependencies"]; for (const auto& item2 : cov_map) { - auto cov_map2 = item2.second.as(); - // For linear and polynomial model - if (cov_map2["model"] == "Linear" || cov_map2["model"] == "Polynomial") { - m_polynomial_h = {0.0, 0.0, 0.0, 0.0}; - m_polynomial_s = {0.0, 0.0, 0.0, 0.0}; + size_t k = speciesIndex(item.first); + size_t j = speciesIndex(item2.first); + if (k == npos) { + throw CanteraError("CoverageDependentSurfPhase::initThermo", + "Unknown species '{}'.", item.first); + } + if (j == npos) { + throw CanteraError("CoverageDependentSurfPhase::initThermo", + "Unknown species '{}'.", item2.first); + } + auto& cov_map2 = item2.second.as(); + // For linear model + if (cov_map2["model"] == "linear") { + vector_fp h_coeffs (5, 0.0); + vector_fp s_coeffs (5, 0.0); if (cov_map2.hasKey("enthalpy")) { - auto enthalpy = cov_map2["enthalpy"].as(); - m_polynomial_h[0] = enthalpy; - } else { - if (cov_map2.hasKey("enthalpy-1st-order")) { - auto h_a = cov_map2["enthalpy-1st-order"].as(); - m_polynomial_h[0] = h_a; - } - if (cov_map2.hasKey("enthalpy-2nd-order")) { - auto h_b = cov_map2["enthalpy-2nd-order"].as(); - m_polynomial_h[1] = h_b; - } - if (cov_map2.hasKey("enthalpy-3rd-order")) { - auto h_c = cov_map2["enthalpy-3rd-order"].as(); - m_polynomial_h[2] = h_c; - } - if (cov_map2.hasKey("enthalpy-4th-order")) { - auto h_d = cov_map2["enthalpy-4th-order"].as(); - m_polynomial_h[3] = h_d; - } + double h_slope = cov_map2.convert("enthalpy", "J/kmol"); + h_coeffs[1] = h_slope; } - if (cov_map2.hasKey("enthalpy-unit")) { - auto enthalpy_unit = cov_map2["enthalpy-unit"].as(); - for (size_t i = 0; i < 4; i++) { - m_polynomial_h[i] = convertEnergy(m_polynomial_h[i], enthalpy_unit); - } + if (cov_map2.hasKey("entropy")) { + double s_slope = cov_map2.convert("entropy", "J/kmol/K"); + s_coeffs[1] = s_slope; } - if (cov_map2.hasKey("entropy")) { - auto entropy = cov_map2["entropy"].as(); - m_polynomial_s[0] = entropy; - } else { - if (cov_map2.hasKey("entropy-1st-order")) { - auto s_a = cov_map2["entropy-1st-order"].as(); - m_polynomial_s[0] = s_a; - } - if (cov_map2.hasKey("entropy-2nd-order")) { - auto s_b = cov_map2["entropy-2nd-order"].as(); - m_polynomial_s[1] = s_b; - } - if (cov_map2.hasKey("entropy-3rd-order")) { - auto s_c = cov_map2["entropy-3rd-order"].as(); - m_polynomial_s[2] = s_c; - } - if (cov_map2.hasKey("entropy-4th-order")) { - auto s_d = cov_map2["entropy-4th-order"].as(); - m_polynomial_s[3] = s_d; - } + PolynomialDependency poly_deps(k, j, h_coeffs, s_coeffs); + setPolynomialDependency(poly_deps); + // For polynomial(4th) model + } else if (cov_map2["model"] == "polynomial") { + vector_fp h_coeffs (5, 0.0); + vector_fp s_coeffs (5, 0.0); + if (cov_map2.hasKey("enthalpy-coefficients")) { + h_coeffs = cov_map2.convertVector("enthalpy-coefficients", "J/kmol"); + h_coeffs.insert(h_coeffs.begin(), 0.0); } - if (cov_map2.hasKey("entropy-unit")) { - auto entropy_unit = cov_map2["entropy-unit"].as(); - for (size_t i = 0; i < 4; i++) { - m_polynomial_s[i] = convertEnergy_T(m_polynomial_s[i], entropy_unit); - } + if (cov_map2.hasKey("entropy-coefficients")) { + s_coeffs = cov_map2.convertVector("entropy-coefficients", "J/kmol/K"); + s_coeffs.insert(s_coeffs.begin(), 0.0); } - PolynomialDependency poly_deps(item.first, item2.first, - m_polynomial_h, m_polynomial_s); + PolynomialDependency poly_deps(k, j, h_coeffs, s_coeffs); setPolynomialDependency(poly_deps); // For piecewise linear model - } else if (cov_map2["model"] == "Piecewise-Linear") { - m_piecewise_h = {0.0, 0.0, 0.5}; - m_piecewise_s = {0.0, 0.0, 0.5}; + } else if (cov_map2["model"] == "piecewise-linear") { + vector_fp h_piecewise = {0.0, 0.0, 0.5}; + vector_fp s_piecewise = {0.0, 0.0, 0.5}; if (cov_map2.hasKey("enthalpy-low")) { - auto enthalpy_low = cov_map2["enthalpy-low"].as(); - auto enthalpy_high = cov_map2["enthalpy-high"].as(); - auto enthalpy_change = cov_map2["enthalpy-change"].as(); - if (cov_map2.hasKey("enthalpy-unit")) { - auto enthalpy_unit = cov_map2["enthalpy-unit"].as(); - enthalpy_low = convertEnergy(enthalpy_low, enthalpy_unit); - enthalpy_high = convertEnergy(enthalpy_high, enthalpy_unit); - } - m_piecewise_h[0] = enthalpy_low; - m_piecewise_h[1] = enthalpy_high; - m_piecewise_h[2] = enthalpy_change; + h_piecewise[0] = cov_map2.convert("enthalpy-low", "J/kmol"); + h_piecewise[1] = cov_map2.convert("enthalpy-high", "J/kmol"); + h_piecewise[2] = cov_map2["enthalpy-change"].as(); } - if (cov_map2.hasKey("entropy-low")) { - auto entropy_low = cov_map2["entropy-low"].as(); - auto entropy_high = cov_map2["entropy-high"].as(); - auto entropy_change = cov_map2["entropy-change"].as(); - if (cov_map2.hasKey("entropy-unit")) { - auto entropy_unit = cov_map2["entropy-unit"].as(); - entropy_low = convertEnergy_T(entropy_low, entropy_unit); - entropy_high = convertEnergy_T(entropy_high, entropy_unit); - } - m_piecewise_s[0] = entropy_low; - m_piecewise_s[1] = entropy_high; - m_piecewise_s[2] = entropy_change; + s_piecewise[0] = cov_map2.convert("entropy-low", "J/kmol/K"); + s_piecewise[1] = cov_map2.convert("entropy-high", "J/kmol/K"); + s_piecewise[2] = cov_map2["entropy-change"].as(); } - PiecewiseDependency plin_deps(item.first, item2.first, - m_piecewise_h, - m_piecewise_s); + PiecewiseDependency plin_deps(k, j, h_piecewise, s_piecewise); setPiecewiseDependency(plin_deps); // For interpolative model - } else if (cov_map2["model"] == "Interpolative") { - m_interpolative_hcov = {0.0, 1.0}; - m_interpolative_h = {0.0, 0.0}; - m_interpolative_scov = {0.0, 1.0}; - m_interpolative_s = {0.0, 0.0}; - if (cov_map2.hasKey("enthalpy-coverages")) { - m_interpolative_hcov = cov_map2["enthalpy-coverages"].as(); - auto enthalpies = cov_map2["enthalpies"].as(); - if (cov_map2.hasKey("enthalpy-unit")) { - m_interpolative_h.resize(enthalpies.size()); - auto enthalpy_unit = cov_map2["enthalpy-unit"].as(); - for (size_t k = 0; k < enthalpies.size(); k++) { - m_interpolative_h[k] = convertEnergy(enthalpies[k], enthalpy_unit); - } - } else { - m_interpolative_h = enthalpies; + } else if (cov_map2["model"] == "interpolative") { + std::map hmap, smap; + if (cov_map2.hasKey("enthalpy-coverages") && cov_map2.hasKey("enthalpies")) { + auto hcovs = cov_map2["enthalpy-coverages"].as(); + vector_fp enthalpies = cov_map2.convertVector("enthalpies", "J/kmol"); + if (hcovs.size() != enthalpies.size()) { + throw CanteraError("CoverageDependentSurfPhase::setInterpolativeDependency", + "Sizes of coverages array and enthalpies array are not equal."); + } + for (size_t i = 0; i < hcovs.size(); i++) { + hmap.insert({hcovs[i], enthalpies[i]}); } + } else { + hmap.insert({0.0, 0.0}); + hmap.insert({1.0, 0.0}); } - - if (cov_map2.hasKey("entropy-coverages")) { - m_interpolative_scov = cov_map2["entropy-coverages"].as(); - auto entropies = cov_map2["entropies"].as(); - if (cov_map2.hasKey("entropy-unit")) { - m_interpolative_s.resize(entropies.size()); - auto entropy_unit = cov_map2["entropy-unit"].as(); - for (size_t k = 0; k < entropies.size(); k++) { - m_interpolative_s[k] = convertEnergy_T(entropies[k], entropy_unit); - } - } else { - m_interpolative_s = entropies; + if (cov_map2.hasKey("entropy-coverages") && cov_map2.hasKey("entropies")) { + auto scovs = cov_map2["entropy-coverages"].as(); + vector_fp entropies = cov_map2.convertVector("entropies", "J/kmol/K"); + if (scovs.size() != entropies.size()) { + throw CanteraError("CoverageDependentSurfPhase::setInterpolativeDependency", + "Sizes of coverages array and entropies array are not equal."); } + for (size_t i = 0; i < scovs.size(); i++) { + smap.insert({scovs[i], entropies[i]}); + } + } else { + smap.insert({0.0, 0.0}); + smap.insert({1.0, 0.0}); } - InterpolativeDependency int_deps(item.first, item2.first, - m_interpolative_hcov, - m_interpolative_h, - m_interpolative_scov, - m_interpolative_s); + InterpolativeDependency int_deps(k, j, hmap, smap); setInterpolativeDependency(int_deps); } else { throw CanteraError("CoverageDependentSurfPhase::initThermo", @@ -344,18 +223,10 @@ void CoverageDependentSurfPhase::initThermo() } // For coverage-dependent heat capacity parameters, if present if (cov_map2.hasKey("heat-capacity-a")) { - auto cpcov_a = cov_map2["heat-capacity-a"].as(); - auto cpcov_b = cov_map2["heat-capacity-b"].as(); - if (cov_map2.hasKey("heat-capacity-unit")){ - auto cpcov_unit = cov_map2["heat-capacity-unit"].as(); - m_cpcov_a = convertEnergy_T(cpcov_a, cpcov_unit); - m_cpcov_b = convertEnergy_T(cpcov_b, cpcov_unit); - } else { - m_cpcov_a = cpcov_a; - m_cpcov_b = cpcov_b; - } - HeatCapacityDependency cpcov_deps(item.first, item2.first, - m_cpcov_a, m_cpcov_b); + double cpcov_a = cov_map2.convert("heat-capacity-a", "J/kmol/K"); + double cpcov_b = cov_map2.convert("heat-capacity-b", "J/kmol/K"); + + HeatCapacityDependency cpcov_deps(k, j, cpcov_a, cpcov_b); setHeatCapacityDependency(cpcov_deps); } } @@ -367,10 +238,7 @@ bool CoverageDependentSurfPhase::addSpecies(shared_ptr spec) { bool added = SurfPhase::addSpecies(spec); if (added) { - m_h_ref.push_back(0.0); - m_s_ref.push_back(0.0); - m_cp_ref.push_back(0.0); - m_mu_ref.push_back(0.0); + m_cov.push_back(0.0); m_h_cov.push_back(0.0); m_s_cov.push_back(0.0); m_cp_cov.push_back(0.0); @@ -383,93 +251,45 @@ bool CoverageDependentSurfPhase::addSpecies(shared_ptr spec) return added; } -void CoverageDependentSurfPhase::setCoverages(const double* theta) -{ - SurfPhase::setCoverages(theta); - coverageChanged(); -} - -void CoverageDependentSurfPhase::setCoveragesNoNorm(const double* theta) -{ - SurfPhase::setCoveragesNoNorm(theta); - coverageChanged(); -} - -double CoverageDependentSurfPhase::convertEnergy(double value, - const std::string& src) const -{ - // Convert to J/kmol - Units usrc(src); - if (usrc.convertible(Units("J/kmol"))) { - value *= usrc.factor(); - } else if (src == "eV" || src == "meV" ) { - value *= Avogadro * usrc.factor(); - } else { - throw CanteraError("CoverageDependentSurfPhase::convertEnergy", - "Don't understand units '{}' as energy", src); - } - return value; -} - -double CoverageDependentSurfPhase::convertEnergy_T(double value, - const std::string& src) const -{ - // Convert to J/kmol/K - Units usrc(src); - if (usrc.convertible(Units("J/kmol/K"))) { - value *= usrc.factor(); - } else if (src == "eV/K" || src == "meV/K") { - value *= Avogadro * usrc.factor(); - } else { - throw CanteraError("CoverageDependentSurfPhase::convertEnergy_T", - "Don't understand units '{}' as energy over temperature", src); - } - return value; -} - -void CoverageDependentSurfPhase::coverageChanged() { - m_covstateNum++; -} - // Functions calculating reference state thermodyanmic properties-------------- void CoverageDependentSurfPhase::getGibbs_RT_ref(double* grt) const { - _updateReferenceThermo(); - scale(m_mu_ref.begin(), m_mu_ref.end(), grt, 1.0/RT()); + SurfPhase::_updateThermo(); + scale(m_mu0.begin(), m_mu0.end(), grt, 1.0/RT()); } void CoverageDependentSurfPhase::getEnthalpy_RT_ref(double* hrt) const { - _updateReferenceThermo(); - scale(m_h_ref.begin(), m_h_ref.end(), hrt, 1.0/RT()); + SurfPhase::_updateThermo(); + scale(m_h0.begin(), m_h0.end(), hrt, 1.0/RT()); } void CoverageDependentSurfPhase::getEntropy_R_ref(double* sr) const { - _updateReferenceThermo(); - scale(m_s_ref.begin(), m_s_ref.end(), sr, 1.0/GasConstant); + SurfPhase::_updateThermo(); + scale(m_s0.begin(), m_s0.end(), sr, 1.0/GasConstant); } void CoverageDependentSurfPhase::getCp_R_ref(double* cpr) const { - _updateReferenceThermo(); - scale(m_cp_ref.begin(), m_cp_ref.end(), cpr, 1.0/GasConstant); + SurfPhase::_updateThermo(); + scale(m_cp0.begin(), m_cp0.end(), cpr, 1.0/GasConstant); } // Functions calculating standard state thermodyanmic properties--------------- void CoverageDependentSurfPhase::getEnthalpy_RT(double* hrt) const { - _updateThermo(); + _updateTotalThermo(); scale(m_enthalpy.begin(), m_enthalpy.end(), hrt, 1.0/RT()); } void CoverageDependentSurfPhase::getEntropy_R(double* sr) const { - _updateThermo(); + _updateTotalThermo(); scale(m_entropy.begin(), m_entropy.end(), sr, 1.0/GasConstant); - if (m_has_ref_coverage) { + if (m_theta_ref != 1.0) { double tmp = -log(m_theta_ref); for (size_t k = 0; k < m_kk; k++) { sr[k] -= tmp; @@ -479,15 +299,15 @@ void CoverageDependentSurfPhase::getEntropy_R(double* sr) const void CoverageDependentSurfPhase::getCp_R(double* cpr) const { - _updateThermo(); + _updateTotalThermo(); scale(m_heatcapacity.begin(), m_heatcapacity.end(), cpr, 1.0/GasConstant); } void CoverageDependentSurfPhase::getGibbs_RT(double* grt) const { - _updateThermo(); + _updateTotalThermo(); scale(m_chempot.begin(), m_chempot.end(), grt, 1.0/RT()); - if (m_has_ref_coverage) { + if (m_theta_ref != 1.0) { double tmp = -log(m_theta_ref); for (size_t k = 0; k < m_kk; k++) { grt[k] += tmp; @@ -505,9 +325,9 @@ void CoverageDependentSurfPhase::getPureGibbs(double* g) const void CoverageDependentSurfPhase::getStandardChemPotentials(double* mu0) const { - _updateThermo(); + _updateTotalThermo(); copy(m_chempot.begin(), m_chempot.end(), mu0); - if (m_has_ref_coverage) { + if (m_theta_ref != 1.0) { double tmp = RT() * -log(m_theta_ref); for (size_t k = 0; k < m_kk; k++) { mu0[k] += tmp; @@ -519,48 +339,33 @@ void CoverageDependentSurfPhase::getStandardChemPotentials(double* mu0) const void CoverageDependentSurfPhase::getPartialMolarEnthalpies(double* hbar) const { - _updateThermo(); + _updateTotalThermo(); copy(m_enthalpy.begin(), m_enthalpy.end(), hbar); } void CoverageDependentSurfPhase::getPartialMolarEntropies(double* sbar) const { - _updateThermo(); + _updateTotalThermo(); copy(m_entropy.begin(), m_entropy.end(), sbar); - if (m_has_ref_coverage) { - for (size_t k = 0; k < m_kk; k++) { - sbar[k] -= GasConstant * log(std::max(concentration(k) * size(k)/m_n0, - SmallNumber) / m_theta_ref); - } - } else { - for (size_t k = 0; k < m_kk; k++) { - sbar[k] -= GasConstant * log(std::max(concentration(k) * size(k)/m_n0, - SmallNumber)); - } + for (size_t k = 0; k < m_kk; k++) { + sbar[k] -= GasConstant * log(std::max(m_cov[k], SmallNumber) + / m_theta_ref); } } void CoverageDependentSurfPhase::getPartialMolarCp(double* cpbar) const { - _updateThermo(); + _updateTotalThermo(); copy(m_heatcapacity.begin(), m_heatcapacity.end(), cpbar); } void CoverageDependentSurfPhase::getChemPotentials(double* mu) const { - _updateThermo(); + _updateTotalThermo(); copy(m_chempot.begin(), m_chempot.end(), mu); - if (m_has_ref_coverage) { - for (size_t k = 0; k < m_kk; k++) { - mu[k] += RT() * log(std::max(concentration(k) * size(k)/m_n0, - SmallNumber) / m_theta_ref); - } - } else { - for (size_t k = 0; k < m_kk; k++) { - mu[k] += RT() * log(std::max(concentration(k) * size(k)/m_n0, - SmallNumber)); - } + for (size_t k = 0; k < m_kk; k++) { + mu[k] += RT() * log(std::max(m_cov[k], SmallNumber) / m_theta_ref); } } @@ -568,192 +373,132 @@ void CoverageDependentSurfPhase::getChemPotentials(double* mu) const double CoverageDependentSurfPhase::enthalpy_mole() const { - if (m_n0 <= 0.0) { - return 0.0; - } - _updateThermo(); + _updateTotalThermo(); return mean_X(m_enthalpy); } double CoverageDependentSurfPhase::entropy_mole() const { - _updateThermo(); + _updateTotalThermo(); double entropy = 0.0; - if (m_has_ref_coverage) { - for (size_t k = 0; k < m_kk; k++) { - entropy += moleFraction(k) * (m_entropy[k] - - GasConstant * log(std::max(concentration(k) * size(k)/m_n0, - SmallNumber) / m_theta_ref)); - } - } else { - for (size_t k = 0; k < m_kk; k++) { - entropy += moleFraction(k) * (m_entropy[k] - - GasConstant * log(std::max(concentration(k) * size(k)/m_n0, - SmallNumber))); - } + for (size_t k = 0; k < m_kk; k++) { + entropy += moleFraction(k) * (m_entropy[k] - + GasConstant * log(std::max(m_cov[k], SmallNumber) / m_theta_ref)); } return entropy; } double CoverageDependentSurfPhase::cp_mole() const { - _updateThermo(); + _updateTotalThermo(); return mean_X(m_heatcapacity); } -void CoverageDependentSurfPhase::_updateReferenceThermo(bool force) const -{ - double tnow = temperature(); - if (m_tlast != tnow || force) { - m_spthermo.update(tnow, m_cp_ref.data(), m_h_ref.data(), m_s_ref.data()); - for (size_t k = 0; k < m_kk; k++) { - m_h_ref[k] *= GasConstant * tnow; - m_s_ref[k] *= GasConstant; - m_cp_ref[k] *= GasConstant; - m_mu_ref[k] = m_h_ref[k] - tnow * m_s_ref[k]; - } - } -} - void CoverageDependentSurfPhase::_updateCovDepThermo(bool force) const { - int covstateNumnow = statecovNumber(); + int stateNumnow = stateMFNumber(); double tnow = temperature(); - if (m_covstateNumlast != covstateNumnow || force) { + if (m_stateNumlast != stateNumnow || m_tlast != tnow || force) { for (size_t k = 0; k < m_kk; k++) { m_h_cov[k] = 0.0; m_s_cov[k] = 0.0; + m_cp_cov[k] = 0.0; } - vector_fp cov(m_kk, 0.0); - SurfPhase::getCoverages(cov.data()); + getCoverages(m_cov.data()); // For linear and polynomial model - if (m_has_polynomial_dependency) { - for (auto& item : m_PolynomialDependency) { - size_t k = speciesIndex(item.name_k); - size_t j = speciesIndex(item.name_j); - for (size_t i = 0; i < 4; i++) { - double h_coeff = item.enthalpy_coeffs[i]; - if (h_coeff != 0.0) { - double expo = double (i+1); - m_h_cov[k] += h_coeff * pow(cov[j], expo); - } - double s_coeff = item.entropy_coeffs[i]; - if (s_coeff != 0.0) { - double expo = double (i+1); - m_s_cov[k] += s_coeff * pow(cov[j], expo); - } - } - } + for (auto& item : m_PolynomialDependency) { + m_h_cov[item.k] += poly4(m_cov[item.j], item.enthalpy_coeffs.data()); + m_s_cov[item.k] += poly4(m_cov[item.j], item.entropy_coeffs.data()); } // For piecewise linear model - if (m_has_piecewise_dependency) { - for (auto& item : m_PiecewiseDependency) { - size_t k = speciesIndex(item.name_k); - size_t j = speciesIndex(item.name_j); - double h_slope_low = item.enthalpy_params[0]; - double h_slope_high = item.enthalpy_params[1]; - double h_cov_change = item.enthalpy_params[2]; - if (cov[j] <= h_cov_change) { - m_h_cov[k] += h_slope_low * cov[j]; - } else { - m_h_cov[k] += h_slope_high - * (cov[j] - h_cov_change) - + (h_cov_change * h_slope_low); - } - double s_slope_low = item.entropy_params[0]; - double s_slope_high = item.entropy_params[1]; - double s_cov_change = item.entropy_params[2]; - if (cov[j] <= s_cov_change) { - m_s_cov[k] += s_slope_low * cov[j]; - } else { - m_s_cov[k] += s_slope_high - * (cov[j] - s_cov_change) - + (s_cov_change * s_slope_low); - } + for (auto& item : m_PiecewiseDependency) { + double h_slope_low = item.enthalpy_params[0]; + double h_slope_high = item.enthalpy_params[1]; + double h_cov_change = item.enthalpy_params[2]; + if (m_cov[item.j] <= h_cov_change) { + m_h_cov[item.k] += h_slope_low * m_cov[item.j]; + } else { + m_h_cov[item.k] += h_slope_low * h_cov_change; + m_h_cov[item.k] += h_slope_high * (m_cov[item.j] - h_cov_change); + } + + double s_slope_low = item.entropy_params[0]; + double s_slope_high = item.entropy_params[1]; + double s_cov_change = item.entropy_params[2]; + if (m_cov[item.j] <= s_cov_change) { + m_s_cov[item.k] += s_slope_low * m_cov[item.j]; + } else { + m_s_cov[item.k] += s_slope_low * s_cov_change; + m_s_cov[item.k] += s_slope_high * (m_cov[item.j] - s_cov_change); } } // For interpolative model - if (m_has_interpolative_dependency) { - for (auto& item : m_InterpolativeDependency) { - size_t k = speciesIndex(item.name_k); - size_t j = speciesIndex(item.name_j); - vector_fp h_covs = item.enthalpy_coverages; - size_t i_inter = 0; - for (size_t i = 0; i < (h_covs.size()-1); i++) { - if (h_covs[i] <= cov[j] && cov[j] <= h_covs[i+1]) { - i_inter = i; - break; - } - } - double h_left = item.enthalpies[i_inter]; - double h_right = item.enthalpies[i_inter+1]; - m_h_cov[k] += (h_right - h_left) / - (h_covs[i_inter+1] - h_covs[i_inter]) - * (cov[j] - h_covs[i_inter]) - + h_left; - - vector_fp s_covs = item.entropy_coverages; - i_inter = 0; - for (size_t i = 0; i < (s_covs.size()-1); i++) { - if (s_covs[i] <= cov[j] && cov[j] <= s_covs[i+1]) { - i_inter = i; - break; - } - } - double s_left = item.entropies[i_inter]; - double s_right = item.entropies[i_inter+1]; - m_s_cov[k] += (s_right - s_left) / - (s_covs[i_inter+1] - s_covs[i_inter]) - * (cov[j] - s_covs[i_inter]) - + s_left; - } + for (auto& item : m_InterpolativeDependency) { + auto h_iter = item.enthalpy_map.upper_bound(m_cov[item.j]); + auto s_iter = item.entropy_map.upper_bound(m_cov[item.j]); + AssertThrowMsg(h_iter != m_cov.end(), + "CoverageDependentSurfPhase::_updateCovDepThermo", + "Coverage out of range: {}", m_cov[iterm.j]); + AssertThrowMsg(h_iter != m_cov.begin(), + "CoverageDependentSurfPhase::_updateCovDepThermo", + "Coverage out of range: {}", m_cov[iterm.j]); + AssertThrowMsg(s_iter != m_cov.end(), + "CoverageDependentSurfPhase::_updateCovDepThermo", + "Coverage out of range: {}", m_cov[iterm.j]); + AssertThrowMsg(s_iter != m_cov.begin(), + "CoverageDependentSurfPhase::_updateCovDepThermo", + "Coverage out of range: {}", m_cov[iterm.j]); + + double highHcov = h_iter->first; + double highH = h_iter->second; + double lowHcov = (--h_iter)->first; + double lowH = h_iter->second; + + double highScov = s_iter->first; + double highS = s_iter->second; + double lowScov = (--s_iter)->first; + double lowS = s_iter->second; + + m_h_cov[item.k] += (highH - lowH) / (highHcov - lowHcov) + * (m_cov[item.j] - lowHcov) + lowH; + + m_s_cov[item.k] += (highS - lowS) / (highScov - lowScov) + * (m_cov[item.j] - lowScov) + lowS; } - } - if (m_covstateNumlast != covstateNumnow || m_tlast != tnow || force) { // For coverage-depedent heat capacity - if (m_has_heatcapacity_dependency) { - for (size_t k = 0; k < m_kk; k++) { - m_cp_cov[k] = 0.0; - } - vector_fp cov(m_kk, 0.0); - SurfPhase::getCoverages(cov.data()); - - for (auto& item : m_HeatCapacityDependency) { - size_t k = speciesIndex(item.name_k); - size_t j = speciesIndex(item.name_j); - double a = item.cpcov_a; - double b = item.cpcov_b; - m_cp_cov[k] += (a * log(tnow) + b) * cov[j] * cov[j]; - double int_cp_tnow = tnow * (a * log(tnow) - a + b); - double int_cp_298 = 298.15 * (a * log(298.15) - a + b); - m_h_cov[k] += (int_cp_tnow - int_cp_298) * cov[j] * cov[j]; - double int_cp_T_tnow = log(tnow) * (a * log(tnow) + 2 * b); - double int_cp_T_298 = log(298.15) * (a * log(298.15) + 2 * b); - m_s_cov[k] += 0.5 * (int_cp_T_tnow - int_cp_T_298) * cov[j] * cov[j]; - } + for (auto& item : m_HeatCapacityDependency) { + double a = item.cpcov_a; + double b = item.cpcov_b; + m_cp_cov[item.k] += (a * log(tnow) + b) * m_cov[item.j] * m_cov[item.j]; + double int_cp_tnow = tnow * (a * log(tnow) - a + b); + double int_cp_298 = 298.15 * (a * log(298.15) - a + b); + m_h_cov[item.k] += (int_cp_tnow - int_cp_298) * m_cov[item.j] * m_cov[item.j]; + double int_cp_T_tnow = log(tnow) * (a * log(tnow) + 2 * b); + double int_cp_T_298 = log(298.15) * (a * log(298.15) + 2 * b); + m_s_cov[item.k] += 0.5 * (int_cp_T_tnow - int_cp_T_298) * m_cov[item.j] * m_cov[item.j]; } + + for (size_t k = 0; k < m_kk; k++) { + m_mu_cov[k] = m_h_cov[k] - tnow * m_s_cov[k]; + } + m_stateNumlast = stateNumnow; } - for (size_t k = 0; k < m_kk; k++) { - m_mu_cov[k] = m_h_cov[k] - tnow * m_s_cov[k]; - } - m_covstateNumlast = covstateNumnow; - m_tlast = tnow; } -void CoverageDependentSurfPhase::_updateThermo(bool force) const +void CoverageDependentSurfPhase::_updateTotalThermo(bool force) const { - _updateReferenceThermo(force); _updateCovDepThermo(force); + SurfPhase::_updateThermo(force); for (size_t k = 0; k < m_kk; k++) { - m_enthalpy[k] = m_h_ref[k] + m_h_cov[k]; - m_entropy[k] = m_s_ref[k] + m_s_cov[k]; - m_heatcapacity[k] = m_cp_ref[k] + m_cp_cov[k]; - m_chempot[k] = m_mu_ref[k] + m_mu_cov[k]; + m_enthalpy[k] = m_h0[k] + m_h_cov[k]; + m_entropy[k] = m_s0[k] + m_s_cov[k]; + m_heatcapacity[k] = m_cp0[k] + m_cp_cov[k]; + m_chempot[k] = m_mu0[k] + m_mu_cov[k]; } } diff --git a/test/data/copt_covdepsurf_example.yaml b/test/data/copt_covdepsurf_example.yaml index 13983bf1478..93fc6467398 100755 --- a/test/data/copt_covdepsurf_example.yaml +++ b/test/data/copt_covdepsurf_example.yaml @@ -1,14 +1,7 @@ units: {length: cm, quantity: mol, activation-energy: kcal/mol} phases: -- name: gas - thermo: ideal-gas - species: [O2, CO2, CO, N2] - transport: mixture-averaged - state: - T: 300.0 - P: 1.01325e+05 -- name: coverages_0 +- name: covdep thermo: coverage-dependent-surface species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] kinetics: surface @@ -18,105 +11,8 @@ phases: P: 1.01325e+05 coverages: {Pt: 0.5, OC_Pt: 0.5, CO2_Pt: 0.0, C_Pt: 0.0, O_Pt: 0.0} site-density: 2.72e-09 -- name: coverages_1 - thermo: coverage-dependent-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 625.0 - P: 1.01325e+05 - coverages: {Pt: 0.20, OC_Pt: 0.13, CO2_Pt: 0.21, C_Pt: 0.44, O_Pt: 0.02} - site-density: 2.72e-09 reference-state-coverage: 0.22 -- name: coverages_2 - thermo: coverage-dependent-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 427.0 - P: 1.01325e+05 - coverages: {Pt: 0.00, OC_Pt: 0.66, CO2_Pt: 0.12, C_Pt: 0.13, O_Pt: 0.09} - site-density: 2.72e-09 - reference-state-coverage: 0.5 -- name: coverages_3 - thermo: coverage-dependent-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 711.0 - P: 1.01325e+05 - coverages: {Pt: 0.07, OC_Pt: 0.13, CO2_Pt: 0.55, C_Pt: 0.15, O_Pt: 0.10} - site-density: 2.72e-09 -- name: coverages_4 - thermo: coverage-dependent-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 260.0 - P: 1.01325e+05 - coverages: {Pt: 0.11, OC_Pt: 0.07, CO2_Pt: 0.02, C_Pt: 0.68, O_Pt: 0.12} - site-density: 2.72e-09 - reference-state-coverage: 0.99 -- name: coverages_5 - thermo: coverage-dependent-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 903.0 - P: 1.01325e+05 - coverages: {Pt: 0.02, OC_Pt: 0.05, CO2_Pt: 0.10, C_Pt: 0.11, O_Pt: 0.72} - site-density: 2.72e-09 - reference-state-coverage: 0.8 -- name: coverages_6 - thermo: coverage-dependent-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 475.3 - P: 1.01325e+05 - coverages: {Pt: 0.19, OC_Pt: 0.25, CO2_Pt: 0.21, C_Pt: 0.19, O_Pt: 0.16} - site-density: 2.72e-09 - reference-state-coverage: 0.67 -- name: coverages_7 - thermo: coverage-dependent-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 748.3 - P: 1.01325e+05 - coverages: {Pt: 0.19, OC_Pt: 0.13, CO2_Pt: 0.27, C_Pt: 0.29, O_Pt: 0.12} - site-density: 2.72e-09 - reference-state-coverage: 0.0625 -- name: coverages_8 - thermo: coverage-dependent-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 100.1 - P: 1.01325e+05 - coverages: {Pt: 0.27, OC_Pt: 0.18, CO2_Pt: 0.20, C_Pt: 0.32, O_Pt: 0.03} - site-density: 2.72e-09 - reference-state-coverage: 0.1 -- name: coverages_9 - thermo: coverage-dependent-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 372.1 - P: 1.01325e+05 - coverages: {Pt: 0.03, OC_Pt: 0.01, CO2_Pt: 0.32, C_Pt: 0.30, O_Pt: 0.34} - site-density: 2.72e-09 - reference-state-coverage: 0.4 -- name: ideal_0 +- name: ideal thermo: ideal-surface species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] kinetics: surface @@ -126,170 +22,8 @@ phases: P: 1.01325e+05 coverages: {Pt: 0.5, OC_Pt: 0.5, CO2_Pt: 0.0, C_Pt: 0.0, O_Pt: 0.0} site-density: 2.72e-09 -- name: ideal_1 - thermo: ideal-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 625.0 - P: 1.01325e+05 - coverages: {Pt: 0.20, OC_Pt: 0.13, CO2_Pt: 0.21, C_Pt: 0.44, O_Pt: 0.02} - site-density: 2.72e-09 - reference-state-coverage: 0.22 -- name: ideal_2 - thermo: ideal-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 427.0 - P: 1.01325e+05 - coverages: {Pt: 0.00, OC_Pt: 0.66, CO2_Pt: 0.12, C_Pt: 0.13, O_Pt: 0.09} - site-density: 2.72e-09 - reference-state-coverage: 0.5 -- name: ideal_3 - thermo: ideal-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 711.0 - P: 1.01325e+05 - coverages: {Pt: 0.07, OC_Pt: 0.13, CO2_Pt: 0.55, C_Pt: 0.15, O_Pt: 0.10} - site-density: 2.72e-09 -- name: ideal_4 - thermo: ideal-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 260.0 - P: 1.01325e+05 - coverages: {Pt: 0.11, OC_Pt: 0.07, CO2_Pt: 0.02, C_Pt: 0.68, O_Pt: 0.12} - site-density: 2.72e-09 - reference-state-coverage: 0.99 -- name: ideal_5 - thermo: ideal-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 903.0 - P: 1.01325e+05 - coverages: {Pt: 0.02, OC_Pt: 0.05, CO2_Pt: 0.10, C_Pt: 0.11, O_Pt: 0.72} - site-density: 2.72e-09 - reference-state-coverage: 0.8 -- name: ideal_6 - thermo: ideal-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 475.3 - P: 1.01325e+05 - coverages: {Pt: 0.19, OC_Pt: 0.25, CO2_Pt: 0.21, C_Pt: 0.19, O_Pt: 0.16} - site-density: 2.72e-09 - reference-state-coverage: 0.67 -- name: ideal_7 - thermo: ideal-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 748.3 - P: 1.01325e+05 - coverages: {Pt: 0.19, OC_Pt: 0.13, CO2_Pt: 0.27, C_Pt: 0.29, O_Pt: 0.12} - site-density: 2.72e-09 - reference-state-coverage: 0.0625 -- name: ideal_8 - thermo: ideal-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 100.1 - P: 1.01325e+05 - coverages: {Pt: 0.27, OC_Pt: 0.18, CO2_Pt: 0.20, C_Pt: 0.32, O_Pt: 0.03} - site-density: 2.72e-09 - reference-state-coverage: 0.1 -- name: ideal_9 - thermo: ideal-surface - species: [Pt, OC_Pt, CO2_Pt, C_Pt, O_Pt] - kinetics: surface - reactions: [reactions] - state: - T: 372.1 - P: 1.01325e+05 - coverages: {Pt: 0.03, OC_Pt: 0.01, CO2_Pt: 0.32, C_Pt: 0.30, O_Pt: 0.34} - site-density: 2.72e-09 - reference-state-coverage: 0.4 species: -- name: N2 - composition: {N: 2} - thermo: - model: NASA7 - temperature-ranges: [200.0, 1000.0, 6000.0] - data: - - [3.53101, -1.23661e-04, -5.02999e-07, 2.43531e-09, -1.40881e-12, -1046.98, - 2.96747] - - [2.95258, 1.3969e-03, -4.92632e-07, 7.8601e-11, -4.60755e-15, -923.949, - 5.87189] - transport: - model: gas - geometry: linear - diameter: 3.621 - well-depth: 97.53 - polarizability: 1.76 - rotational-relaxation: 4.0 -- name: O2 - composition: {O: 2} - thermo: - model: NASA7 - temperature-ranges: [100.0, 1074.55, 5000.0] - data: - - [3.53732243, -1.21571647e-03, 5.31620254e-06, -4.89446434e-09, 1.45846258e-12, - -1038.58849, 4.68368183] - - [3.15382081, 1.67804371e-03, -7.69974236e-07, 1.51275462e-10, -1.08782414e-14, - -1040.81728, 6.16755832] - transport: - model: gas - geometry: linear - diameter: 3.467 - well-depth: 106.7 -- name: CO2 - composition: {C: 1, O: 2} - thermo: - model: NASA7 - temperature-ranges: [100.0, 978.22, 5000.0] - data: - - [3.28084453, 2.5018564e-03, 8.08192142e-06, -1.20510369e-08, 4.66542684e-12, - -4.84008303e+04, 6.00081438] - - [4.67427416, 2.60962879e-03, -9.85683184e-07, 1.95712276e-10, -1.49834931e-14, - -4.89512168e+04, -2.11077406] - transport: - model: gas - geometry: linear - diameter: 3.941 - well-depth: 195.201 -- name: CO - composition: {C: 1, O: 1} - thermo: - model: NASA7 - temperature-ranges: [100.0, 1571.65, 5000.0] - data: - - [3.5683795, -8.52120978e-04, 2.4891658e-06, -1.5632992e-09, 3.13591992e-13, - -1.42842549e+04, 3.57912359] - - [2.91308, 1.64655944e-03, -6.88605521e-07, 1.21035372e-10, -7.840028e-15, - -1.41808916e+04, 6.71038] - transport: - model: gas - geometry: linear - diameter: 3.69 - well-depth: 91.7 - polarizability: 1.76 - rotational-relaxation: 4.0 - name: Pt composition: {Pt: 1} thermo: @@ -311,26 +45,27 @@ species: - [1.3809066, 8.0571901e-03, -4.6430896e-06, 8.91170699e-10, -5.90048361e-14, -3.43319289e+04, -4.85318015] coverage-dependencies: - OC_Pt: {model: Piecewise-Linear, - enthalpy-low: 0.5, enthalpy-high: 1.0, - enthalpy-change: 0.4, enthalpy-unit: eV, - entropy-low: 0.1, entropy-high: -0.2, - entropy-change: 0.4, entropy-unit: meV/K, - heat-capacity-a: 0.020, heat-capacity-b: -0.156, - heat-capacity-unit: meV/K} - CO2_Pt: {model: Linear, - enthalpy: 0.48, enthalpy-unit: eV, - entropy: -0.031, entropy-unit: eV/K} - C_Pt: {model: Polynomial, - enthalpy-2nd-order: 3.86e4, enthalpy-unit: J/mol, - entropy-3rd-order: -1.26e4, entropy-unit: J/mol/K} - O_Pt: {model: Interpolative, - enthalpy-coverages: [0.0, 0.2, 0.5, 0.7, 0.9, 1.0], - enthalpies: [0.0, 0.5, 1.2, 2.7, 3.5, 4.0], - enthalpy-unit: kcal/mol, + OC_Pt: {model: linear, + units: {energy: eV, quantity: molec}, + enthalpy: 0.48, + entropy: -0.031} + CO2_Pt: {model: piecewise-linear, + units: {energy: kJ, quantity: mol}, + enthalpy-low: 0.5e2, enthalpy-high: 1.0e2, + enthalpy-change: 0.4, + entropy-low: 0.1e2, entropy-high: -0.2e2, + entropy-change: 0.4, + heat-capacity-a: 0.02e-1, heat-capacity-b: -0.156e-1} + C_Pt: {model: polynomial, + units: {energy: J, quantity: mol}, + enthalpy-coefficients: [0.0, -3.86e4, 0.0, 4.2e5], + entropy-coefficients: [0.8e3, 0.0, -1.26e4, 0.0]} + O_Pt: {model: interpolative, + units: {energy: kcal, quantity: mol}, + enthalpy-coverages: [0.0, 0.2, 0.4, 0.7, 0.9, 1.0], + enthalpies: [0.0, 0.5, 1.0, 2.7, 3.5, 4.0], entropy-coverages: [0.0, 0.5, 1.0], - entropies: [0.0, -0.7, -2.0], - entropy-unit: kcal/mol/K} + entropies: [0.0, -0.7, -2.0]} - name: CO2_Pt composition: {Pt: 1, C: 1, O: 2} thermo: @@ -342,14 +77,16 @@ species: - [5.99803259, 2.27485222e-03, -6.81092723e-07, 1.34432446e-10, -1.11509701e-14, -4.61838262e+04, -21.1649844] coverage-dependencies: - OC_Pt: {model: Piecewise-Linear, + OC_Pt: {model: piecewise-linear, + units: {energy: eV, quantity: molec}, enthalpy-low: 0.1, enthalpy-high: 0.3, - enthalpy-change: 0.5, enthalpy-unit: eV, + enthalpy-change: 0.5, entropy-low: -0.05, entropy-high: -0.1, - entropy-change: 0.5, entropy-unit: eV/K} - CO2_Pt: {model: Linear, - enthalpy: 0.73, enthalpy-unit: eV, - entropy: -0.44, entropy-unit: eV/K} + entropy-change: 0.5} + CO2_Pt: {model: linear, + units: {energy: eV, quantity: molec}, + enthalpy: 0.43, + entropy: -0.44} - name: C_Pt composition: {Pt: 1, C: 1} thermo: @@ -361,18 +98,17 @@ species: - [3.08076078, -6.87465602e-04, 5.17589597e-07, -9.73022048e-11, 6.24243898e-15, 5335.31839, -17.0991414] coverage-dependencies: - C_Pt: {model: Interpolative, + C_Pt: {model: interpolative, + units: {energy: eV, quantity: molec}, enthalpy-coverages: [0.0, 0.18, 0.67, 1.0], enthalpies: [0.0, 0.12, 0.70, 0.82], - enthalpy-unit: eV, entropy-coverages: [0.0, 0.11, 0.33, 0.77, 1.0], entropies: [0.0, 0.05, -0.12, -0.40, -0.55], - entropy-unit: eV/K, - heat-capacity-a: 0.07, heat-capacity-b: -0.21, - heat-capacity-unit: meV/K} - O_Pt: {model: Linear, - enthalpy: 0.12, enthalpy-unit: eV, - entropy: 0.09, entropy-unit: eV/K} + heat-capacity-a: 0.07e-3, heat-capacity-b: -0.21e-3} + O_Pt: {model: linear, + units: {energy: eV, quantity: molec}, + enthalpy: 0.12, + entropy: 0.09} - name: O_Pt composition: {Pt: 1, O: 1} thermo: @@ -384,15 +120,10 @@ species: - [1.89893619, 2.03295425e-03, -1.19976574e-06, 2.32680659e-10, -1.53508282e-14, -1.75144954e+04, -9.6410408] coverage-dependencies: - O_Pt: {model: Polynomial, - enthalpy-1st-order: 0.14, - enthalpy-2nd-order: -1.74, - enthalpy-4th-order: 2.11, - enthalpy-unit: eV, - entropy-1st-order: 0.07, - entropy-3rd-order: -0.0145, - entropy-4th-order: 0.023, - entropy-unit: eV/K} + O_Pt: {model: polynomial, + units: {energy: eV, quantity: molec}, + enthalpy-coefficients: [0.14, -1.74, 0.0, 2.11], + entropy-coefficients: [0.07, 0.0, -0.0145, 0.023]} reactions: - equation: Pt + Pt + O2 <=> O_Pt + O_Pt # Reaction 202 @@ -410,4 +141,3 @@ reactions: - equation: CO2 + Pt <=> CO2_Pt # Reaction 225 sticking-coefficient: {A: 5.0e-03, b: 0.0, Ea: 0.0} id: surface1-24 - diff --git a/test/thermo/CoverageDependentSurfPhase_Test.cpp b/test/thermo/CoverageDependentSurfPhase_Test.cpp index c75e3bf7fc0..a46acc70548 100644 --- a/test/thermo/CoverageDependentSurfPhase_Test.cpp +++ b/test/thermo/CoverageDependentSurfPhase_Test.cpp @@ -1,4 +1,6 @@ #include "gtest/gtest.h" +#include "cantera/thermo/SurfPhase.h" +#include "cantera/base/utilities.h" #include "cantera/thermo/CoverageDependentSurfPhase.h" #include "cantera/thermo/ThermoFactory.h" @@ -9,14 +11,29 @@ namespace Cantera class CoverageDependentSurfPhase_Test: public testing::Test { public: - CoverageDependentSurfPhase_Test() { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", "coverages_0")); + CoverageDependentSurfPhase_Test(): + test_Ts({500.0, 625.0, 427.0, 711.0, 260.0, + 903.0, 475.3, 748.3, 100.1, 372.1}), + test_covs({ + {0.00, 0.10, 0.50, 0.10, 0.30}, + {0.12, 0.07, 0.21, 0.17, 0.43}, + {0.00, 0.71, 0.08, 0.07, 0.14}, + {0.60, 0.10, 0.10, 0.10, 0.10}, + {0.20, 0.23, 0.57, 0.00, 0.00} + }) + { + test_phase.reset(newPhase("copt_covdepsurf_example.yaml", "covdep")); + surf_phase = dynamic_cast(test_phase.get()); } std::unique_ptr test_phase; - CoverageDependentSurfPhase* covdepsurf; + SurfPhase* surf_phase; + UnitSystem us; + + vector_fp test_Ts; + std::vector test_covs; }; -TEST_F(CoverageDependentSurfPhase_Test, construct_from_file) +TEST_F(CoverageDependentSurfPhase_Test, construct_from_yaml) { CoverageDependentSurfPhase* coveragedependentsurf_phase = dynamic_cast(test_phase.get()); EXPECT_TRUE(coveragedependentsurf_phase != NULL); @@ -24,489 +41,286 @@ TEST_F(CoverageDependentSurfPhase_Test, construct_from_file) TEST_F(CoverageDependentSurfPhase_Test, reference_enthalpies_RT) { - const double expected_result[10] = { - 4.895991737500073e-05, - 4.617646334628971e-05, - 5.963833377856196e-05, - 5.692092800682202e-05, - -9.815993386192746e-05, - 6.644423752958034e-05, - 5.2492790438840376e-05, - 6.225436283744746e-05, - -0.0035000916056617164, - 5.94838246127799e-05 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; vector_fp enthalpies_RT_ref(5); + vector_fp expected_result(5); for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); + test_phase->setTemperature(test_Ts[i]); test_phase->getEnthalpy_RT_ref(&enthalpies_RT_ref[0]); - EXPECT_NEAR(enthalpies_RT_ref[0], expected_result[i], 1.e-6); + surf_phase->getEnthalpy_RT_ref(&expected_result[0]); + EXPECT_NEAR(enthalpies_RT_ref[1], expected_result[1], 1.e-6); } } TEST_F(CoverageDependentSurfPhase_Test, reference_entropies_R) { - const double expected_result[10] = { - 17.30376125156932, - 18.782927044715542, - 16.336043707069322, - 19.692734172570507, - 13.687172677897806, - 21.46362710555691, - 16.985994108560934, - 20.063327006288937, - 9.714347806292915, - 15.544459107650459 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; vector_fp entropies_R_ref(5); + vector_fp expected_result(5); for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); + test_phase->setTemperature(test_Ts[i]); test_phase->getEntropy_R_ref(&entropies_R_ref[0]); - EXPECT_NEAR(entropies_R_ref[2], expected_result[i], 1.e-6); + surf_phase->getEntropy_R_ref(&expected_result[0]); + EXPECT_NEAR(entropies_R_ref[2], expected_result[2], 1.e-6); } } TEST_F(CoverageDependentSurfPhase_Test, reference_cp_R) { - const double expected_result[10] = { - 2.3911891432499996, - 2.6169441249003906, - 2.193392723419327, - 2.710068009615135, - 1.4902296533617059, - 2.80663483290828, - 2.3304807267205296, - 2.7387444952834965, - 0.37775961493433574, - 2.0046505063190665 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; vector_fp cps_R_ref(5); + vector_fp expected_result(5); for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); + test_phase->setTemperature(test_Ts[i]); test_phase->getCp_R_ref(&cps_R_ref[0]); - EXPECT_NEAR(cps_R_ref[3], expected_result[i], 1.e-6); + surf_phase->getCp_R_ref(&expected_result[0]); + EXPECT_NEAR(cps_R_ref[3], expected_result[3], 1.e-6); } } TEST_F(CoverageDependentSurfPhase_Test, reference_gibbs_RT) { - const double expected_result[10] = { - -35.75544525672188, - -29.27051136018905, - -41.389632097578534, - -26.191806426905902, - -66.68729427601727, - -21.54814904209595, - -37.46076589723343, - -25.089092853962732, - -172.1295537915689, - -47.14174199946188 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; vector_fp gibbs_RT_ref(5); + vector_fp expected_result(5); for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); + test_phase->setTemperature(test_Ts[i]); test_phase->getGibbs_RT_ref(&gibbs_RT_ref[0]); - EXPECT_NEAR(gibbs_RT_ref[4], expected_result[i], 1.e-6); + surf_phase->getGibbs_RT_ref(&expected_result[0]); + EXPECT_NEAR(gibbs_RT_ref[4], expected_result[4], 1.e-6); } } TEST_F(CoverageDependentSurfPhase_Test, standard_enthalpies_RT) { - const double expected_result[10] = { - 4.895991737500073e-05, - 4.617646334628971e-05, - 5.963833377856196e-05, - 5.692092800682202e-05, - -9.815993386192746e-05, - 6.644423752958034e-05, - 5.2492790438840376e-05, - 6.225436283744746e-05, - -0.0035000916056617164, - 5.94838246127799e-05 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; - vector_fp enthalpies_RT(5); - - for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); - test_phase->getEnthalpy_RT(&enthalpies_RT[0]); - EXPECT_NEAR(enthalpies_RT[0], expected_result[i], 1.e-6); + double h_slope = us.convertFrom(0.48, "eV/molec"); + double h_low = us.convertFrom(0.5e2, "kJ/mol"); + double h_high = us.convertFrom(1.0e2, "kJ/mol"); + vector_fp h_coeffs {0.0, 0.0, -3.86e4, 0.0, 4.2e5}; + for (size_t i = 0; i < h_coeffs.size(); i++) { + h_coeffs[i] = us.convertFrom(h_coeffs[i], "J/mol"); } + double h_int = us.convertFrom(0.75, "kcal/mol"); + double cp_a = us.convertFrom(0.02e-1, "kJ/mol/K"); + double cp_b = us.convertFrom(-0.156e-1, "kJ/mol/K"); + double int_cp_tnow = test_Ts[5] * (cp_a * log(test_Ts[5]) - cp_a + cp_b); + double int_cp_298 = 298.15 * (cp_a * log(298.15) - cp_a + cp_b); + + vector_fp enthalpies_RT(5); + vector_fp expected_result(5); + + test_phase->setTemperature(test_Ts[5]); + surf_phase->setCoverages(test_covs[0].data()); + test_phase->getEnthalpy_RT(&enthalpies_RT[0]); + test_phase->getEnthalpy_RT_ref(&expected_result[0]); + double RT = test_phase->RT(); + expected_result[1] += (h_slope * test_covs[0][1]) / RT; + expected_result[1] += (h_low * 0.4) / RT; + expected_result[1] += (h_high * (test_covs[0][2] - 0.4)) / RT; + expected_result[1] += ((int_cp_tnow - int_cp_298) * test_covs[0][2] * test_covs[0][2]) / RT; + expected_result[1] += poly4(test_covs[0][3], h_coeffs.data()) / RT; + expected_result[1] += h_int / RT; + EXPECT_NEAR(enthalpies_RT[1], expected_result[1], 1.e-6); } TEST_F(CoverageDependentSurfPhase_Test, standard_entropies_R) { - const double expected_result[10] = { - 7.262785047892177, - -211.88704374580803, - -104.49781910237925, - -264.41047258705385, - -564.1004252619438, - -668.1159683605337, - -191.9493546909492, - -212.12619995755966, - -143.45731583540848, - -390.8228284931619 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; - vector_fp entropies_R(5); - - for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); - test_phase->getEntropy_R(&entropies_R[0]); - EXPECT_NEAR(entropies_R[1], expected_result[i], 1.e-6); + double s_slope = us.convertFrom(-0.031, "eV/molec/K"); + double s_low = us.convertFrom(0.1e2, "kJ/mol/K"); + double s_high = us.convertFrom(-0.2e2, "kJ/mol/K"); + vector_fp s_coeffs {0.0, 0.8e3, 0.0, -1.26e4, 0.0}; + for (size_t i = 0; i < s_coeffs.size(); i++) { + s_coeffs[i] = us.convertFrom(s_coeffs[i], "J/mol/K"); } + double s_int = us.convertFrom(-0.42, "kcal/mol/K"); + double cp_a = us.convertFrom(0.02e-1, "kJ/mol/K"); + double cp_b = us.convertFrom(-0.156e-1, "kJ/mol/K"); + double int_cp_T_tnow = log(test_Ts[3]) * (cp_a * log(test_Ts[3]) + 2 * cp_b); + double int_cp_T_298 = log(298.15) * (cp_a * log(298.15) + 2 * cp_b); + double ref_cov = 0.22; + + vector_fp entropies_R(5); + vector_fp expected_result(5); + + test_phase->setTemperature(test_Ts[3]); + surf_phase->setCoverages(test_covs[0].data()); + test_phase->getEntropy_R(&entropies_R[0]); + test_phase->getEntropy_R_ref(&expected_result[0]); + expected_result[1] += (s_slope * test_covs[0][1]) / GasConstant; + expected_result[1] += (s_low * 0.4) / GasConstant; + expected_result[1] += (s_high * (test_covs[0][2] - 0.4)) / GasConstant; + expected_result[1] += poly4(test_covs[0][3], s_coeffs.data()) / GasConstant; + expected_result[1] += s_int / GasConstant; + expected_result[1] += 0.5 * (int_cp_T_tnow - int_cp_T_298) + * test_covs[0][2] * test_covs[0][2] / GasConstant; + expected_result[1] -= -log(ref_cov); + EXPECT_NEAR(entropies_R[1], expected_result[1], 1.e-6); } TEST_F(CoverageDependentSurfPhase_Test, standard_cp_R) { - const double expected_result[10] = { - 2.3911891432499996, - 3.1575801771450513, - 2.2353566973964605, - 2.7752564954964587, - 2.452060193173945, - 2.8440413820654813, - 2.42326223769133, - 2.9858976609594317, - 0.5113627141915665, - 2.218066003239782 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; - vector_fp cps_R(5); + double cp_a = us.convertFrom(0.02e-1, "kJ/mol/K"); + double cp_b = us.convertFrom(-0.156e-1, "kJ/mol/K"); - for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); - test_phase->getCp_R(&cps_R[0]); - EXPECT_NEAR(cps_R[3], expected_result[i], 1.e-6); - } + vector_fp cps_R(5); + vector_fp expected_result(5); + + test_phase->setTemperature(test_Ts[4]); + surf_phase->setCoverages(test_covs[0].data()); + test_phase->getCp_R(&cps_R[0]); + test_phase->getCp_R_ref(&expected_result[0]); + expected_result[1] += (cp_a * log(test_Ts[4]) + cp_b) + * test_covs[0][2] * test_covs[0][2] / GasConstant; + EXPECT_NEAR(cps_R[1], expected_result[1], 1.e-6); } TEST_F(CoverageDependentSurfPhase_Test, standard_gibbs_RT) { - const double expected_result[10] = { - 11.8756216200221, - 2202.4396179996957, - -477.3453796516724, - -316.51179756543485, - 3907.895845540286, - -1324.569049068033, - -13.293752588541661, - 922.4725337308008, - 1369.7551786229228, - 795.2766107464173 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; vector_fp gibbs_RT(5); + vector_fp expected_result(5); + vector_fp entropies_R(5); - for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); + for (size_t i = 0; i < 5; i++) { + test_phase->setTemperature(test_Ts[i]); + surf_phase->setCoverages(test_covs[i].data()); + test_phase->getEnthalpy_RT(&expected_result[0]); + test_phase->getEntropy_R(&entropies_R[0]); + expected_result[1] -= entropies_R[1]; test_phase->getGibbs_RT(&gibbs_RT[0]); - EXPECT_NEAR(gibbs_RT[3], expected_result[i], 1.e-6); + EXPECT_NEAR(gibbs_RT[1], expected_result[1], 1.e-6); } } TEST_F(CoverageDependentSurfPhase_Test, standard_gibbs) { - const double expected_result[10] = { - -148643656.49121934, - -228451988.4293846, - -403796393.1146004, - -634513292.1906644, - -355109634.2098712, - -4640855820.12355, - -660054096.9197942, - -744616318.8616358, - -161367473.42965755, - -1000153036.6544077 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; vector_fp gibbs(5); + vector_fp expected_result(5); - for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); + for (size_t i = 0; i < 5; i++) { + test_phase->setTemperature(test_Ts[i]); + surf_phase->setCoverages(test_covs[i].data()); test_phase->getPureGibbs(&gibbs[0]); - EXPECT_NEAR(gibbs[4], expected_result[i], 1.e-6); + test_phase->getGibbs_RT(&expected_result[0]); + expected_result[1] *= test_phase->RT(); + EXPECT_NEAR(gibbs[1], expected_result[1], 1.e-6); } } TEST_F(CoverageDependentSurfPhase_Test, standard_chempotentials) { - const double expected_result[10] = { - -274870452.00677145, - 856519725.4301237, - 145886101.04112163, - 1332157691.3398027, - 960092570.6206956, - 4779252095.107842, - 508906879.58705205, - 1080088611.4436927, - -145155906.70495453, - 952738760.7658446 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; vector_fp chempotentials_st(5); + vector_fp expected_result(5); - for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); + for (size_t i = 0; i < 5; i++) { + test_phase->setTemperature(test_Ts[i]); + surf_phase->setCoverages(test_covs[i].data()); test_phase->getStandardChemPotentials(&chempotentials_st[0]); - EXPECT_NEAR(chempotentials_st[1], expected_result[i], 1.e-6); + test_phase->getPureGibbs(&expected_result[0]); + EXPECT_NEAR(chempotentials_st[1], expected_result[1], 1.e-6); } } TEST_F(CoverageDependentSurfPhase_Test, partial_molar_enthalpies) { - const double expected_result[10] = { - -244677374.6145806, - -244559589.87957713, - -225109949.88732946, - -230926742.67340738, - -259357323.04774666, - -236935699.79515216, - -249650880.85754883, - -239699592.35303646, - -264552232.7353466, - -256393416.2056975 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; vector_fp partialmolar_enthalpies(5); + vector_fp expected_result(5); - for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); + for (size_t i = 0; i < 5; i++) { + test_phase->setTemperature(test_Ts[i]); + surf_phase->setCoverages(test_covs[i].data()); test_phase->getPartialMolarEnthalpies(&partialmolar_enthalpies[0]); - EXPECT_NEAR(partialmolar_enthalpies[1], expected_result[i], 1.e-6); + test_phase->getEnthalpy_RT(&expected_result[0]); + expected_result[1] *= test_phase->RT(); + EXPECT_NEAR(partialmolar_enthalpies[1], expected_result[1], 1.e-6); } } TEST_F(CoverageDependentSurfPhase_Test, partial_molar_entropies) { - const double expected_result[10] = { - 66149.30110602578, - -1744763.5646839596, - -865388.4229791872, - -2181467.65036173, - -4668081.580555751, - -5530117.33952245, - -1584429.4415132466, - -1746752.0200664676, - -1178512.8623860686, - -3211192.2824656786 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; vector_fp partialmolar_entropies(5); + vector_fp expected_result(5); - for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); + for (size_t i = 0; i < 5; i++) { + test_phase->setTemperature(test_Ts[i]); + surf_phase->setCoverages(test_covs[i].data()); test_phase->getPartialMolarEntropies(&partialmolar_entropies[0]); - EXPECT_NEAR(partialmolar_entropies[1], expected_result[i], 1.e-6); + test_phase->getEntropy_R(&expected_result[0]); + expected_result[1] -= log(test_covs[i][1]); + expected_result[1] *= GasConstant; + EXPECT_NEAR(partialmolar_entropies[1], expected_result[1], 1.e-6); } } TEST_F(CoverageDependentSurfPhase_Test, partial_molar_cp) { - const double expected_result[10] = { - 52706.65227577072, - 57448.35040870828, - 49270.05260539342, - 59840.103776506076, - 40036.68657757771, - 63083.2060679071, - 51595.35078424445, - 60671.1013954003, - 30734.96527336805, - 46407.802588887964 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; vector_fp partialmolar_cps(5); + vector_fp expected_result(5); - for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); + for (size_t i = 0; i < 5; i++) { + test_phase->setTemperature(test_Ts[i]); + surf_phase->setCoverages(test_covs[i].data()); test_phase->getPartialMolarCp(&partialmolar_cps[0]); - EXPECT_NEAR(partialmolar_cps[2], expected_result[i], 1.e-6); + test_phase->getCp_R(&expected_result[0]); + expected_result[1] *= GasConstant; + EXPECT_NEAR(partialmolar_cps[1], expected_result[1], 1.e-6); } } TEST_F(CoverageDependentSurfPhase_Test, chemical_potentials) { - const double expected_result[10] = { - -2822343946.108881, - 11440797412.804848, - -1701950970.6310093, - -1882300719.0459917, - 8447100310.246291, - -9961383229.998562, - -59098087.381852254, - 5731657082.504713, - 1139068374.937362, - 2456711091.0340676 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; vector_fp chempotentials(5); + vector_fp expected_result(5); - for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); + for (size_t i = 0; i < 5; i++) { + test_phase->setTemperature(test_Ts[i]); + surf_phase->setCoverages(test_covs[i].data()); test_phase->getChemPotentials(&chempotentials[0]); - EXPECT_NEAR(chempotentials[3], expected_result[i], 1.e-6); + test_phase->getStandardChemPotentials(&expected_result[0]); + expected_result[1] += log(test_covs[i][1]) * test_phase->RT(); + EXPECT_NEAR(chempotentials[1], expected_result[1], 1.e-6); } } TEST_F(CoverageDependentSurfPhase_Test, enthalpy_mole) { - const double expected_result[10] = { - -122338585.53843959, - -59309366.65989761, - -193558162.68747127, - -199642681.1436115, - 40537434.57875116, - -142791039.41545668, - -142518074.5167915, - -108002792.86461554, - -97942472.24175003, - -137479276.4811465 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; + vector_fp partialmolar_enthalpies(5); + double expected_result; - for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); - EXPECT_NEAR(test_phase->enthalpy_mole(), expected_result[i], 1.e-6); + for (size_t i = 0; i < 5; i++) { + test_phase->setTemperature(test_Ts[i]); + surf_phase->setCoverages(test_covs[i].data()); + test_phase->getPartialMolarEnthalpies(&partialmolar_enthalpies[0]); + expected_result = test_phase->mean_X(partialmolar_enthalpies); + EXPECT_NEAR(test_phase->enthalpy_mole(), expected_result, 1.e-6); } } TEST_F(CoverageDependentSurfPhase_Test, entropy_mole) { - const double expected_result[10] = { - 35956.532917352175, - -10176083.957783429, - -1043623.7221215261, - -12891288.513604177, - -22018125.06619569, - 4101773.9070109557, - -2257818.910081016, - -5537608.314706989, - -5452194.621248438, - -5486169.579651305 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; + vector_fp partialmolar_entropies(5); + double expected_result; - for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); - EXPECT_NEAR(test_phase->entropy_mole(), expected_result[i], 1.e-6); + for (size_t i = 0; i < 5; i++) { + test_phase->setTemperature(test_Ts[i]); + surf_phase->setCoverages(test_covs[i].data()); + test_phase->getPartialMolarEntropies(&partialmolar_entropies[0]); + expected_result = test_phase->mean_X(partialmolar_entropies); + EXPECT_NEAR(test_phase->entropy_mole(), expected_result, 1.e-6); } } TEST_F(CoverageDependentSurfPhase_Test, cp_mole) { - const double expected_result[10] = { - 20304.914543820392, - 29562.94897980166, - 36080.77976856744, - 44311.85551592095, - 19165.080781805933, - 28655.920516293252, - 28534.196335297413, - 32061.519786347304, - 10104.170506513487, - 28017.603867332116 - }; - - std::vector names = {"coverages_0", "coverages_1", - "coverages_2", "coverages_3", - "coverages_4", "coverages_5", - "coverages_6", "coverages_7", - "coverages_8", "coverages_9"}; + vector_fp partialmolar_cps(5); + double expected_result; - for (size_t i = 0; i < 10; i++) { - test_phase.reset(newPhase("copt_covdepsurf_example.yaml", names[i])); - EXPECT_NEAR(test_phase->cp_mole(), expected_result[i], 1.e-6); + for (size_t i = 0; i < 5; i++) { + test_phase->setTemperature(test_Ts[i]); + surf_phase->setCoverages(test_covs[i].data()); + test_phase->getPartialMolarCp(&partialmolar_cps[0]); + expected_result = test_phase->mean_X(partialmolar_cps); + EXPECT_NEAR(test_phase->cp_mole(), expected_result, 1.e-6); } } -} \ No newline at end of file +};