diff --git a/include/cantera/thermo/SpeciesThermoFactory.h b/include/cantera/thermo/SpeciesThermoFactory.h index 6e1fe1b55..bb284701a 100644 --- a/include/cantera/thermo/SpeciesThermoFactory.h +++ b/include/cantera/thermo/SpeciesThermoFactory.h @@ -17,6 +17,8 @@ namespace Cantera { class XML_Node; +class AnyMap; +class UnitSystem; //! Create a new SpeciesThermoInterpType object given a corresponding constant. /*! @@ -50,6 +52,15 @@ SpeciesThermoInterpType* newSpeciesThermoInterpType(const std::string& type, */ SpeciesThermoInterpType* newSpeciesThermoInterpType(const XML_Node& thermoNode); +//! Create a new SpeciesThermoInterpType object using the specified parameters +/*! + * @param thermo_node An AnyMap specifying the model type (e.g. "NASA") and any + * model parameters necessary to instantiate the object + * @param units Specification for the unit system to convert from + */ +unique_ptr newSpeciesThermo( + const AnyMap& thermo_node, const UnitSystem& units); + } #endif diff --git a/src/thermo/SpeciesThermoFactory.cpp b/src/thermo/SpeciesThermoFactory.cpp index a23cd2521..37089734c 100644 --- a/src/thermo/SpeciesThermoFactory.cpp +++ b/src/thermo/SpeciesThermoFactory.cpp @@ -20,6 +20,7 @@ #include "cantera/thermo/VPStandardStateTP.h" #include "cantera/base/ctml.h" #include "cantera/base/stringUtils.h" +#include "cantera/base/Units.h" using namespace std; @@ -141,6 +142,39 @@ static SpeciesThermoInterpType* newNasaThermoFromXML(vector nodes) return newSpeciesThermoInterpType(NASA, tmin, tmax, p0, &c[0]); } +void setupSpeciesThermo(SpeciesThermoInterpType& thermo, + const AnyMap& node, const UnitSystem& units) +{ + double Pref = OneAtm; + if (node.hasKey("reference-pressure")) { + Pref = units.convert(node.at("reference-pressure"), "Pa"); + } + thermo.setRefPressure(Pref); +} + +void setupNasaPoly(NasaPoly2& thermo, const AnyMap& node, + const UnitSystem& units) +{ + setupSpeciesThermo(thermo, node, units); + vector_fp Tranges = units.convert( + node.at("temperature-ranges").asVector(2, 3), "K"); + const auto& data = node.at("data").asVector(Tranges.size()-1); + for (const auto& poly : data) { + if (poly.size() != 7) { + throw CanteraError("setupNasaPoly", "Wrong number of coefficients " + "for NASA polynomial. Expected 7, but got {}", poly.size()); + } + } + thermo.setMinTemp(Tranges.front()); + thermo.setMaxTemp(Tranges.back()); + if (Tranges.size() == 3) { // standard 2 temperature range polynomial + thermo.setParameters(Tranges[1], data[0], data[1]); + } else { // Repeat data for single temperature range for both ranges + thermo.setParameters(Tranges[1], data[0], data[0]); + } +} + + //! Create a Shomate polynomial thermodynamic property parameterization for a //! species /*! @@ -339,4 +373,19 @@ SpeciesThermoInterpType* newSpeciesThermoInterpType(const XML_Node& thermo) } } + +unique_ptr newSpeciesThermo( + const AnyMap& node, const UnitSystem& units) +{ + std::string model = node.at("model").asString(); + if (model == "NASA7") { + unique_ptr thermo(new NasaPoly2()); + setupNasaPoly(*thermo, node, units); + return unique_ptr(move(thermo)); + } else { + throw CanteraError("newSpeciesThermo", + "Uknown thermo model '{}'", model); + } +} + } diff --git a/test/thermo/thermoParameterizations.cpp b/test/thermo/thermoParameterizations.cpp index 93a2254db..f614ffa0a 100644 --- a/test/thermo/thermoParameterizations.cpp +++ b/test/thermo/thermoParameterizations.cpp @@ -1,11 +1,13 @@ #include "gtest/gtest.h" #include "cantera/thermo/speciesThermoTypes.h" +#include "cantera/thermo/SpeciesThermoFactory.h" #include "cantera/thermo/IdealGasPhase.h" #include "cantera/thermo/ConstCpPoly.h" #include "cantera/thermo/NasaPoly2.h" #include "cantera/thermo/ShomatePoly.h" #include "cantera/thermo/PDSS_HKFT.h" #include "cantera/base/stringUtils.h" +#include "cantera/base/Units.h" #include "thermo_data.h" #include @@ -121,3 +123,43 @@ TEST(Shomate, modifyOneHf298) S.updatePropertiesTemp(298.15, &cp, &h, &s); EXPECT_DOUBLE_EQ(hf, h * 298.15 * GasConstant); } + +TEST(SpeciesThermo, NasaPoly2FromYaml1) { + AnyMap data = AnyMap::fromYamlString( + "model: NASA7\n" + "reference-pressure: 1 atm\n" + "temperature-ranges: [200, 1000, 6000]\n" + "data:\n" + "- [3.944031200E+00, -1.585429000E-03, 1.665781200E-05, -2.047542600E-08,\n" + " 7.835056400E-12, 2.896617900E+03, 6.311991700E+00]\n" + "- [4.884754200E+00, 2.172395600E-03, -8.280690600E-07, 1.574751000E-10,\n" + " -1.051089500E-14, 2.316498300E+03, -1.174169500E-01]\n"); + UnitSystem U; + double cp_R, h_RT, s_R; + auto st = newSpeciesThermo(data, U); + st->validate("NO2"); + st->updatePropertiesTemp(300, &cp_R, &h_RT, &s_R); + EXPECT_DOUBLE_EQ(st->refPressure(), OneAtm); + EXPECT_DOUBLE_EQ(cp_R, 4.47823303484); + EXPECT_DOUBLE_EQ(h_RT, 13.735827875868003); + EXPECT_DOUBLE_EQ(s_R, 28.913447733267262); +} + +TEST(SpeciesThermo, NasaPoly2FromYaml2) { + AnyMap data = AnyMap::fromYamlString( + "model: NASA7\n" + "reference-pressure: 1 atm\n" + "temperature-ranges: [200 K, 1000 K]\n" + "data:\n" + "- [3.944031200E+00, -1.585429000E-03, 1.665781200E-05, -2.047542600E-08,\n" + " 7.835056400E-12, 2.896617900E+03, 6.311991700E+00]\n"); + UnitSystem U; + double cp_R, h_RT, s_R; + auto st = newSpeciesThermo(data, U); + st->validate("NO2"); + st->updatePropertiesTemp(300, &cp_R, &h_RT, &s_R); + EXPECT_DOUBLE_EQ(st->maxTemp(), 1000); + EXPECT_DOUBLE_EQ(cp_R, 4.47823303484); + EXPECT_DOUBLE_EQ(h_RT, 13.735827875868003); + EXPECT_DOUBLE_EQ(s_R, 28.913447733267262); +}