From 716e397c2eb038afabefe5bfec92cffd2e94f81c Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Mon, 12 Apr 2021 17:01:32 -0400 Subject: [PATCH] [Input] Refactor to reduce Python manipulations of AnyMap Eliminates the 'mergeAnyMap' function, and introduces a 'parameters' method for classes to return an AnyMap which can optionally contain the user-provided input data, rather than needing to create the AnyMap in advance and add the user-created fields separately. --- include/cantera/base/AnyMap.h | 4 ++ include/cantera/base/Solution.h | 3 + include/cantera/kinetics/Kinetics.h | 4 +- include/cantera/kinetics/Reaction.h | 18 ++++-- include/cantera/thermo/Species.h | 3 +- .../cantera/thermo/SpeciesThermoInterpType.h | 17 ++++-- include/cantera/thermo/ThermoPhase.h | 15 +++-- include/cantera/transport/TransportBase.h | 4 +- include/cantera/transport/TransportData.h | 15 ++++- interfaces/cython/cantera/_cantera.pxd | 17 ++---- interfaces/cython/cantera/base.pyx | 9 +-- interfaces/cython/cantera/reaction.pyx | 4 +- interfaces/cython/cantera/speciesthermo.pyx | 4 +- interfaces/cython/cantera/thermo.pyx | 7 +-- interfaces/cython/cantera/transport.pyx | 4 +- interfaces/cython/cantera/utils.pyx | 16 ----- src/base/AnyMap.cpp | 9 +++ src/base/Solution.cpp | 15 +++++ src/base/YamlWriter.cpp | 60 +------------------ src/kinetics/Kinetics.cpp | 9 ++- src/kinetics/Reaction.cpp | 34 +++++++---- src/thermo/Species.cpp | 49 ++++++++------- src/thermo/SpeciesThermoInterpType.cpp | 12 +++- src/thermo/ThermoPhase.cpp | 10 ++++ src/transport/TransportBase.cpp | 6 +- src/transport/TransportData.cpp | 10 ++++ test/kinetics/kineticsFromYaml.cpp | 3 +- test/thermo/thermoParameterizations.cpp | 15 ++--- test/thermo/thermoToYaml.cpp | 4 +- 29 files changed, 196 insertions(+), 184 deletions(-) diff --git a/include/cantera/base/AnyMap.h b/include/cantera/base/AnyMap.h index c86ce4f4a..61cc22c94 100644 --- a/include/cantera/base/AnyMap.h +++ b/include/cantera/base/AnyMap.h @@ -437,6 +437,10 @@ public: //! Erase all items in the mapping void clear(); + //! Add items from `other` to this AnyMap. If keys in `other` also exist in + //! this AnyMap, the `keepExisting` option determines which item is used. + void update(const AnyMap& other, bool keepExisting=true); + //! Return a string listing the keys in this AnyMap, e.g. for use in error //! messages std::string keys_str() const; diff --git a/include/cantera/base/Solution.h b/include/cantera/base/Solution.h index 155c2d674..cf4ae4b52 100644 --- a/include/cantera/base/Solution.h +++ b/include/cantera/base/Solution.h @@ -14,6 +14,7 @@ namespace Cantera class ThermoPhase; class Kinetics; class Transport; +class AnyMap; //! A container class holding managers for all pieces defining a phase class Solution : public std::enable_shared_from_this @@ -61,6 +62,8 @@ public: return m_transport; } + AnyMap parameters(bool withInput=false) const; + protected: shared_ptr m_thermo; //!< ThermoPhase manager shared_ptr m_kinetics; //!< Kinetics manager diff --git a/include/cantera/kinetics/Kinetics.h b/include/cantera/kinetics/Kinetics.h index 39838ec90..a355f8a68 100644 --- a/include/cantera/kinetics/Kinetics.h +++ b/include/cantera/kinetics/Kinetics.h @@ -704,10 +704,10 @@ public: */ virtual void init() {} - //! Store the parameters for a phase definition which are needed to + //! Return the parameters for a phase definition which are needed to //! reconstruct an identical object using the newKinetics function. This //! excludes the reaction definitions, which are handled separately. - virtual void getParameters(AnyMap& phaseNode); + AnyMap parameters(); /** * Resize arrays with sizes that depend on the total number of species. diff --git a/include/cantera/kinetics/Reaction.h b/include/cantera/kinetics/Reaction.h index ec66de22d..9598c3e1f 100644 --- a/include/cantera/kinetics/Reaction.h +++ b/include/cantera/kinetics/Reaction.h @@ -57,6 +57,14 @@ public: //! valid. virtual void validate(); + //! Return the parameters such that an identical Reaction could be reconstructed + //! using the newReaction() function. Behavior specific to derived classes is + //! handled by the getParameters() method. + //! @param withInput If true, include additional input data fields associated + //! with the object, such as user-defined fields from a YAML input file, as + //! contained in the #input attribute. + AnyMap parameters(bool withInput=true) const; + //! Get validity flag of reaction bool valid() const { return m_valid; @@ -67,11 +75,6 @@ public: m_valid = valid; } - //! Store the parameters of a Reaction needed to reconstruct an identical - //! object using the newReaction(AnyMap&, Kinetics&) function. Does not - //! include user-defined fields available in the #input map. - virtual void getParameters(AnyMap& reactionNode) const; - //! Type of the reaction. The valid types are listed in the file, //! reaction_defs.h, with constants ending in `RXN`. /*! @@ -117,6 +120,11 @@ public: Units rate_units; protected: + //! Store the parameters of a Reaction needed to reconstruct an identical + //! object using the newReaction(AnyMap&, Kinetics&) function. Does not + //! include user-defined fields available in the #input map. + virtual void getParameters(AnyMap& reactionNode) const; + //! Flag indicating whether reaction is set up correctly bool m_valid; }; diff --git a/include/cantera/thermo/Species.h b/include/cantera/thermo/Species.h index c2120a4c5..201c52f10 100644 --- a/include/cantera/thermo/Species.h +++ b/include/cantera/thermo/Species.h @@ -15,6 +15,7 @@ namespace Cantera class SpeciesThermoInterpType; class TransportData; class XML_Node; +class ThermoPhase; //! Contains data about a single chemical species /*! @@ -35,7 +36,7 @@ public: Species& operator=(const Species& other) = delete; ~Species(); - void getParameters(AnyMap& speciesNode, bool withInput=true) const; + AnyMap parameters(const ThermoPhase* phase=0, bool withInput=true) const; //! The name of the species std::string name; diff --git a/include/cantera/thermo/SpeciesThermoInterpType.h b/include/cantera/thermo/SpeciesThermoInterpType.h index 60baab1dc..1b4a1ea8d 100644 --- a/include/cantera/thermo/SpeciesThermoInterpType.h +++ b/include/cantera/thermo/SpeciesThermoInterpType.h @@ -227,10 +227,14 @@ public: doublereal& refPressure, doublereal* const coeffs) const; - //! Store the parameters of the species thermo object such that an identical - //! species thermo object could be reconstructed using the - //! newSpeciesThermo() function. - virtual void getParameters(AnyMap& thermo) const; + //! Return the parameters of the species thermo object such that an + //! identical species thermo object could be reconstructed using the + //! newSpeciesThermo() function. Behavior specific to derived classes is + //! handled by the getParameters() method. + //! @param withInput If true, include additional input data fields associated + //! with the object, such as user-defined fields from a YAML input file, as + //! returned by the input() method. + AnyMap parameters(bool withInput=true) const; //! Report the 298 K Heat of Formation of the standard state of one species //! (J kmol-1) @@ -273,6 +277,11 @@ public: AnyMap& input(); protected: + //! Store the parameters of the species thermo object such that an identical + //! species thermo object could be reconstructed using the + //! newSpeciesThermo() function. + virtual void getParameters(AnyMap& thermo) const; + //! lowest valid temperature doublereal m_lowT; //! Highest valid temperature diff --git a/include/cantera/thermo/ThermoPhase.h b/include/cantera/thermo/ThermoPhase.h index 2c5171d11..1f79d4960 100644 --- a/include/cantera/thermo/ThermoPhase.h +++ b/include/cantera/thermo/ThermoPhase.h @@ -1709,10 +1709,12 @@ public: virtual void setParameters(const AnyMap& phaseNode, const AnyMap& rootNode=AnyMap()); - //! Store the parameters of a ThermoPhase object such that an identical - //! one could be reconstructed using the newPhase(AnyMap&) function. This - //! does not include user-defined fields available in input(). - virtual void getParameters(AnyMap& phaseNode) const; + //! Returns the parameters of a ThermoPhase object such that an identical + //! one could be reconstructed using the newPhase(AnyMap&) function. + //! @param withInput If true, include additional input data fields associated + //! with the phase description, such as user-defined fields from a YAML input + //! file, as returned by the input() method. + AnyMap parameters(bool withInput=true) const; //! Get phase-specific parameters of a Species object such that an //! identical one could be reconstructed and added to this phase. @@ -1872,6 +1874,11 @@ public: //@} protected: + //! Store the parameters of a ThermoPhase object such that an identical + //! one could be reconstructed using the newPhase(AnyMap&) function. This + //! does not include user-defined fields available in input(). + virtual void getParameters(AnyMap& phaseNode) const; + //! Fills `names` and `data` with the column names and species thermo //! properties to be included in the output of the reportCSV method. virtual void getCsvReportData(std::vector& names, diff --git a/include/cantera/transport/TransportBase.h b/include/cantera/transport/TransportBase.h index ace86afb3..5733fe6e5 100644 --- a/include/cantera/transport/TransportBase.h +++ b/include/cantera/transport/TransportBase.h @@ -602,11 +602,11 @@ public: */ virtual void setParameters(const int type, const int k, const doublereal* const p); - //! Store the parameters for a phase definition which are needed to + //! Return the parameters for a phase definition which are needed to //! reconstruct an identical object using the newTransport function. This //! excludes the individual species transport properties, which are handled //! separately. - virtual void getParameters(AnyMap& phaseNode); + AnyMap parameters() const; //! Sets the velocity basis /*! diff --git a/include/cantera/transport/TransportData.h b/include/cantera/transport/TransportData.h index 715de3a28..4cf099089 100644 --- a/include/cantera/transport/TransportData.h +++ b/include/cantera/transport/TransportData.h @@ -24,12 +24,21 @@ public: virtual void validate(const Species& species) {} - //! Store the parameters needed to reconstruct a TransportData object. Does - //! not include user-defined fields available in #input. - virtual void getParameters(AnyMap& transportNode) const; + //! Return the parameters such that an identical species transport object + //! could be reconstructed using the newTransportData() function. Behavior + //! specific to derived classes is handled by the getParameters() method. + //! @param withInput If true, include additional input data fields associated + //! with the object, such as user-defined fields from a YAML input file, as + //! stored in the #input attribute. + AnyMap parameters(bool withInput) const; //! Input data used for specific models AnyMap input; + +protected: + //! Store the parameters needed to reconstruct a TransportData object. Does + //! not include user-defined fields available in #input. + virtual void getParameters(AnyMap& transportNode) const; }; //! Transport data for a single gas-phase species which can be used in diff --git a/interfaces/cython/cantera/_cantera.pxd b/interfaces/cython/cantera/_cantera.pxd index 9ccc00b33..cb9dce619 100644 --- a/interfaces/cython/cantera/_cantera.pxd +++ b/interfaces/cython/cantera/_cantera.pxd @@ -125,8 +125,7 @@ cdef extern from "cantera/thermo/SpeciesThermoInterpType.h": double refPressure() void reportParameters(size_t&, int&, double&, double&, double&, double* const) except +translate_exception int nCoeffs() except +translate_exception - void getParameters(CxxAnyMap&) except +translate_exception - CxxAnyMap& input() + CxxAnyMap parameters(cbool) except +translate_exception cdef extern from "cantera/thermo/SpeciesThermoFactory.h": cdef CxxSpeciesThermo* CxxNewSpeciesThermo "Cantera::newSpeciesThermoInterpType"\ @@ -145,8 +144,7 @@ cdef extern from "cantera/thermo/Species.h" namespace "Cantera": Composition composition double charge double size - void getParameters(CxxAnyMap&) except +translate_exception - CxxAnyMap input + CxxAnyMap parameters(CxxThermoPhase*) except +translate_exception cdef shared_ptr[CxxSpecies] CxxNewSpecies "newSpecies" (XML_Node&) cdef vector[shared_ptr[CxxSpecies]] CxxGetSpecies "getSpecies" (XML_Node&) @@ -162,6 +160,7 @@ cdef extern from "cantera/base/Solution.h" namespace "Cantera": void setThermo(shared_ptr[CxxThermoPhase]) void setKinetics(shared_ptr[CxxKinetics]) void setTransport(shared_ptr[CxxTransport]) + CxxAnyMap parameters(cbool) except +translate_exception cdef shared_ptr[CxxSolution] CxxNewSolution "Cantera::Solution::create" () @@ -178,8 +177,6 @@ cdef extern from "cantera/thermo/ThermoPhase.h" namespace "Cantera": # miscellaneous string type() string phaseOfMatter() except +translate_exception - CxxAnyMap& input() - void getParameters(CxxAnyMap&) except +translate_exception void getSpeciesParameters(string, CxxAnyMap&) except +translate_exception string report(cbool, double) except +translate_exception cbool hasPhaseTransition() @@ -369,7 +366,7 @@ cdef extern from "cantera/kinetics/Reaction.h" namespace "Cantera": string equation() string type() void validate() except +translate_exception - void getParameters(CxxAnyMap&) except +translate_exception + CxxAnyMap parameters(cbool) except +translate_exception int reaction_type Composition reactants Composition products @@ -379,7 +376,6 @@ cdef extern from "cantera/kinetics/Reaction.h" namespace "Cantera": cbool duplicate cbool allow_nonreactant_orders cbool allow_negative_orders - CxxAnyMap input cdef cppclass CxxReaction2 "Cantera::Reaction2" (CxxReaction): CxxReaction2() @@ -491,7 +487,6 @@ cdef extern from "cantera/kinetics/Kinetics.h" namespace "Cantera": void addReaction(shared_ptr[CxxReaction]) except +translate_exception void modifyReaction(int, shared_ptr[CxxReaction]) except +translate_exception void invalidateCache() except +translate_exception - void getParameters(CxxAnyMap&) except +translate_exception shared_ptr[CxxReaction] reaction(size_t) except +translate_exception cbool isReversible(int) except +translate_exception @@ -517,7 +512,6 @@ cdef extern from "cantera/transport/TransportBase.h" namespace "Cantera": cdef cppclass CxxTransport "Cantera::Transport": CxxTransport(CxxThermoPhase*) string transportType() - void getParameters(CxxAnyMap&) except +translate_exception double viscosity() except +translate_exception double thermalConductivity() except +translate_exception double electricalConductivity() except +translate_exception @@ -537,8 +531,7 @@ cdef extern from "cantera/transport/DustyGasTransport.h" namespace "Cantera": cdef extern from "cantera/transport/TransportData.h" namespace "Cantera": cdef cppclass CxxTransportData "Cantera::TransportData": CxxTransportData() - CxxAnyMap input - void getParameters(CxxAnyMap&) except +translate_exception + CxxAnyMap parameters(cbool) except +translate_exception cdef cppclass CxxGasTransportData "Cantera::GasTransportData" (CxxTransportData): CxxGasTransportData() diff --git a/interfaces/cython/cantera/base.pyx b/interfaces/cython/cantera/base.pyx index 103c1bf5c..1b4094ebe 100644 --- a/interfaces/cython/cantera/base.pyx +++ b/interfaces/cython/cantera/base.pyx @@ -230,14 +230,7 @@ cdef class _SolutionBase: definition. """ def __get__(self): - cdef CxxAnyMap params - if self.thermo: - self.thermo.getParameters(params) - if self.kinetics: - self.kinetics.getParameters(params) - if self.transport: - self.transport.getParameters(params) - return mergeAnyMap(params, self.thermo.input()) + return anymapToPython(self.base.parameters(True)) def write_yaml(self, filename, phases=None, units=None, precision=None, skip_user_defined=None): diff --git a/interfaces/cython/cantera/reaction.pyx b/interfaces/cython/cantera/reaction.pyx index 6b351f44e..928cf9dba 100644 --- a/interfaces/cython/cantera/reaction.pyx +++ b/interfaces/cython/cantera/reaction.pyx @@ -327,9 +327,7 @@ cdef class Reaction: definition. """ def __get__(self): - cdef CxxAnyMap params - self.reaction.getParameters(params) - return mergeAnyMap(params, self.reaction.input) + return anymapToPython(self.reaction.parameters(True)) def __repr__(self): return '<{}: {}>'.format(self.__class__.__name__, self.equation) diff --git a/interfaces/cython/cantera/speciesthermo.pyx b/interfaces/cython/cantera/speciesthermo.pyx index f3c72ecb5..a44024272 100644 --- a/interfaces/cython/cantera/speciesthermo.pyx +++ b/interfaces/cython/cantera/speciesthermo.pyx @@ -88,9 +88,7 @@ cdef class SpeciesThermo: property input_data: def __get__(self): - cdef CxxAnyMap params - self.spthermo.getParameters(params) - return mergeAnyMap(params, self.spthermo.input()) + return anymapToPython(self.spthermo.parameters(True)) def cp(self, T): """ diff --git a/interfaces/cython/cantera/thermo.pyx b/interfaces/cython/cantera/thermo.pyx index 688888a0e..0abf68f89 100644 --- a/interfaces/cython/cantera/thermo.pyx +++ b/interfaces/cython/cantera/thermo.pyx @@ -264,11 +264,8 @@ cdef class Species: property input_data: def __get__(self): - cdef CxxAnyMap params - self.species.getParameters(params) - if self._phase: - self._phase.thermo.getSpeciesParameters(self.species.name, params) - return mergeAnyMap(params, self.species.input) + cdef CxxThermoPhase* phase = self._phase.thermo if self._phase else NULL + return anymapToPython(self.species.parameters(phase)) def __repr__(self): return ''.format(self.name) diff --git a/interfaces/cython/cantera/transport.pyx b/interfaces/cython/cantera/transport.pyx index e3f06f164..1f7f16ed4 100644 --- a/interfaces/cython/cantera/transport.pyx +++ b/interfaces/cython/cantera/transport.pyx @@ -58,9 +58,7 @@ cdef class GasTransportData: property input_data: def __get__(self): - cdef CxxAnyMap params - self.data.getParameters(params) - return mergeAnyMap(params, self.data.input) + return anymapToPython(self.data.parameters(True)) property geometry: """ diff --git a/interfaces/cython/cantera/utils.pyx b/interfaces/cython/cantera/utils.pyx index 78845e086..7978dba11 100644 --- a/interfaces/cython/cantera/utils.pyx +++ b/interfaces/cython/cantera/utils.pyx @@ -119,19 +119,3 @@ cdef anymapToPython(CxxAnyMap& m): m.applyUnits() return {pystr(item.first): anyvalueToPython(item.first, item.second) for item in m.ordered()} - - -cdef mergeAnyMap(CxxAnyMap& primary, CxxAnyMap& extra): - """ - Combine two AnyMaps into a single Python dict. Items from the second map - are included only if there is no corresponding key in the first map. - - Used to combine generated data representing the current state of the object - (primary) with user-supplied fields (extra) not directly used by Cantera. - """ - out = {pystr(item.first): anyvalueToPython(item.first, item.second) - for item in primary.ordered()} - for item in extra: - if not primary.hasKey(item.first): - out[pystr(item.first)] = anyvalueToPython(item.first, item.second) - return out diff --git a/src/base/AnyMap.cpp b/src/base/AnyMap.cpp index 0a39ed4a0..0e5c464a1 100644 --- a/src/base/AnyMap.cpp +++ b/src/base/AnyMap.cpp @@ -1356,6 +1356,15 @@ void AnyMap::clear() m_data.clear(); } +void AnyMap::update(const AnyMap& other, bool keepExisting) +{ + for (const auto& item : other) { + if (!keepExisting || !hasKey(item.first)) { + (*this)[item.first] = item.second; + } + } +} + std::string AnyMap::keys_str() const { fmt::memory_buffer b; diff --git a/src/base/Solution.cpp b/src/base/Solution.cpp index 7366fccad..989034b3b 100644 --- a/src/base/Solution.cpp +++ b/src/base/Solution.cpp @@ -58,6 +58,21 @@ void Solution::setTransport(shared_ptr transport) { } } +AnyMap Solution::parameters(bool withInput) const +{ + AnyMap out = m_thermo->parameters(false); + if (m_kinetics) { + out.update(m_kinetics->parameters()); + } + if (m_transport) { + out.update(m_transport->parameters()); + } + if (withInput) { + out.update(m_thermo->input()); + } + return out; +} + shared_ptr newSolution(const std::string& infile, const std::string& name, const std::string& transport, diff --git a/src/base/YamlWriter.cpp b/src/base/YamlWriter.cpp index 77e5f1811..ad4ddf6ba 100644 --- a/src/base/YamlWriter.cpp +++ b/src/base/YamlWriter.cpp @@ -54,27 +54,8 @@ std::string YamlWriter::toYamlString() const std::vector phaseDefs(m_phases.size()); size_t nspecies_total = 0; for (size_t i = 0; i < m_phases.size(); i++) { - m_phases[i]->thermo()->getParameters(phaseDefs[i]); + phaseDefs[i] = m_phases[i]->parameters(!m_skip_user_defined); nspecies_total += m_phases[i]->thermo()->nSpecies(); - const auto& kin = m_phases[i]->kinetics(); - if (kin) { - kin->getParameters(phaseDefs[i]); - if (phaseDefs[i].hasKey("kinetics") && kin->nReactions() == 0) { - phaseDefs[i]["reactions"] = "none"; - } - } - const auto& tran = m_phases[i]->transport(); - if (tran) { - tran->getParameters(phaseDefs[i]); - } - - if (!m_skip_user_defined) { - for (const auto& item : m_phases[i]->thermo()->input()) { - if (!phaseDefs[i].hasKey(item.first)) { - phaseDefs[i][item.first] = item.second; - } - } - } } output["phases"] = phaseDefs; @@ -86,31 +67,7 @@ std::string YamlWriter::toYamlString() const const auto thermo = phase->thermo(); for (const auto& name : thermo->speciesNames()) { const auto& species = thermo->species(name); - AnyMap speciesDef; - species->getParameters(speciesDef, !m_skip_user_defined); - - thermo->getSpeciesParameters(name, speciesDef); - if (!m_skip_user_defined - && species->input.hasKey("equation-of-state")) { - auto& eosIn = species->input["equation-of-state"].asVector(); - for (const auto& eos : eosIn) { - auto& out = speciesDef["equation-of-state"].getMapWhere( - "model", eos["model"].asString(), true); - for (const auto& item : eos) { - if (!out.hasKey(item.first)) { - out[item.first] = item.second; - } - } - } - } - - if (!m_skip_user_defined) { - for (const auto& item : species->input) { - if (!speciesDef.hasKey(item.first)) { - speciesDef[item.first] = item.second; - } - } - } + AnyMap speciesDef = species->parameters(thermo.get(), !m_skip_user_defined); if (speciesDefIndex.count(name) == 0) { speciesDefs.emplace_back(speciesDef); @@ -135,18 +92,7 @@ std::string YamlWriter::toYamlString() const } std::vector reactions; for (size_t i = 0; i < kin->nReactions(); i++) { - const auto reaction = kin->reaction(i); - AnyMap reactionDef; - reaction->getParameters(reactionDef); - if (!m_skip_user_defined) { - for (const auto& item : reaction->input) { - if (!reactionDef.hasKey(item.first)) { - reactionDef[item.first] = item.second; - } - } - } - - reactions.push_back(std::move(reactionDef)); + reactions.push_back(kin->reaction(i)->parameters(!m_skip_user_defined)); } allReactions[phase->name()] = std::move(reactions); } diff --git a/src/kinetics/Kinetics.cpp b/src/kinetics/Kinetics.cpp index ee6f40a95..02874970c 100644 --- a/src/kinetics/Kinetics.cpp +++ b/src/kinetics/Kinetics.cpp @@ -494,12 +494,17 @@ void Kinetics::addPhase(ThermoPhase& thermo) resizeSpecies(); } -void Kinetics::getParameters(AnyMap& phaseNode) +AnyMap Kinetics::parameters() { + AnyMap out; string name = KineticsFactory::factory()->canonicalize(kineticsType()); if (name != "none") { - phaseNode["kinetics"] = name; + out["kinetics"] = name; + if (nReactions() == 0) { + out["reactions"] = "none"; + } } + return out; } void Kinetics::resizeSpecies() diff --git a/src/kinetics/Reaction.cpp b/src/kinetics/Reaction.cpp index cfb78ee75..10e699b5a 100644 --- a/src/kinetics/Reaction.cpp +++ b/src/kinetics/Reaction.cpp @@ -102,6 +102,28 @@ void Reaction::validate() } } +AnyMap Reaction::parameters(bool withInput) const +{ + AnyMap out; + getParameters(out); + if (withInput) { + out.update(input); + } + + static bool reg = AnyMap::addOrderingRules("Reaction", + {{"head", "type"}, + {"head", "equation"}, + {"tail", "duplicate"}, + {"tail", "orders"}, + {"tail", "negative-orders"}, + {"tail", "nonreactant-orders"} + }); + if (reg) { + out["__type__"] = "Reaction"; + } + return out; +} + void Reaction::getParameters(AnyMap& reactionNode) const { reactionNode["equation"] = equation(); @@ -118,18 +140,6 @@ void Reaction::getParameters(AnyMap& reactionNode) const if (allow_nonreactant_orders) { reactionNode["nonreactant-orders"] = true; } - - static bool reg = AnyMap::addOrderingRules("Reaction", - {{"head", "type"}, - {"head", "equation"}, - {"tail", "duplicate"}, - {"tail", "orders"}, - {"tail", "negative-orders"}, - {"tail", "nonreactant-orders"} - }); - if (reg) { - reactionNode["__type__"] = "Reaction"; - } } std::string Reaction::reactantString() const diff --git a/src/thermo/Species.cpp b/src/thermo/Species.cpp index 6e6359bae..f8e012daf 100644 --- a/src/thermo/Species.cpp +++ b/src/thermo/Species.cpp @@ -4,10 +4,12 @@ #include "cantera/thermo/Species.h" #include "cantera/thermo/SpeciesThermoInterpType.h" #include "cantera/thermo/SpeciesThermoFactory.h" +#include "cantera/thermo/ThermoPhase.h" #include "cantera/transport/TransportData.h" #include "cantera/base/stringUtils.h" #include "cantera/base/ctexceptions.h" #include "cantera/base/ctml.h" +#include "cantera/base/global.h" #include #include #include @@ -33,8 +35,9 @@ Species::~Species() { } -void Species::getParameters(AnyMap& speciesNode, bool withInput) const +AnyMap Species::parameters(const ThermoPhase* phase, bool withInput) const { + AnyMap speciesNode; speciesNode["name"] = name; speciesNode["composition"] = composition; speciesNode["composition"].setFlowStyle(); @@ -45,34 +48,30 @@ void Species::getParameters(AnyMap& speciesNode, bool withInput) const if (size != 1) { speciesNode["size"] = size; } - - AnyMap thermoNode; - if (thermo && thermo->reportType() != 0) { - thermo->getParameters(thermoNode); - } - if (thermo && withInput) { - for (const auto& item : thermo->input()) { - if (!thermoNode.hasKey(item.first)) { - thermoNode[item.first] = item.second; - } + if (thermo) { + AnyMap thermoNode = thermo->parameters(withInput); + if (thermoNode.size()) { + speciesNode["thermo"] = std::move(thermoNode); } } - if (thermoNode.size()) { - speciesNode["thermo"] = std::move(thermoNode); - } - if (transport) { - AnyMap transportNode; - transport->getParameters(transportNode); - if (withInput) { - for (const auto& item : transport->input) { - if (!transportNode.hasKey(item.first)) { - transportNode[item.first] = item.second; - } - } - } - speciesNode["transport"] = std::move(transportNode); + speciesNode["transport"] = transport->parameters(withInput); } + if (phase) { + phase->getSpeciesParameters(name, speciesNode); + } + if (withInput && input.hasKey("equation-of-state")) { + auto& eosIn = input["equation-of-state"].asVector(); + for (const auto& eos : eosIn) { + auto& out = speciesNode["equation-of-state"].getMapWhere( + "model", eos["model"].asString(), true); + out.update(eos); + } + } + if (withInput) { + speciesNode.update(input); + } + return speciesNode; } shared_ptr newSpecies(const XML_Node& species_node) diff --git a/src/thermo/SpeciesThermoInterpType.cpp b/src/thermo/SpeciesThermoInterpType.cpp index 01f633123..53625e3a1 100644 --- a/src/thermo/SpeciesThermoInterpType.cpp +++ b/src/thermo/SpeciesThermoInterpType.cpp @@ -52,9 +52,19 @@ void SpeciesThermoInterpType::reportParameters(size_t& index, int& type, throw NotImplementedError("SpeciesThermoInterpType::reportParameters"); } +AnyMap SpeciesThermoInterpType::parameters(bool withInput) const +{ + AnyMap out; + getParameters(out); + if (withInput) { + out.update(m_input); + } + return out; +} + void SpeciesThermoInterpType::getParameters(AnyMap& thermo) const { - if (m_Pref != OneAtm) { + if (m_Pref != OneAtm && reportType() != 0) { thermo["reference-pressure"].setQuantity(m_Pref, "Pa"); } } diff --git a/src/thermo/ThermoPhase.cpp b/src/thermo/ThermoPhase.cpp index 64a729ea6..0c70202b0 100644 --- a/src/thermo/ThermoPhase.cpp +++ b/src/thermo/ThermoPhase.cpp @@ -1189,6 +1189,16 @@ void ThermoPhase::setParameters(const AnyMap& phaseNode, const AnyMap& rootNode) m_input = phaseNode; } +AnyMap ThermoPhase::parameters(bool withInput) const +{ + AnyMap out; + getParameters(out); + if (withInput) { + out.update(m_input); + } + return out; +} + void ThermoPhase::getParameters(AnyMap& phaseNode) const { phaseNode["name"] = name(); diff --git a/src/transport/TransportBase.cpp b/src/transport/TransportBase.cpp index 5af328b9d..0030ce9af 100644 --- a/src/transport/TransportBase.cpp +++ b/src/transport/TransportBase.cpp @@ -53,12 +53,14 @@ void Transport::setParameters(const int type, const int k, throw NotImplementedError("Transport::setParameters"); } -void Transport::getParameters(AnyMap& phaseNode) +AnyMap Transport::parameters() const { + AnyMap out; string name = TransportFactory::factory()->canonicalize(transportType()); if (name != "") { - phaseNode["transport"] = name; + out["transport"] = name; } + return out; } void Transport::setThermo(ThermoPhase& thermo) diff --git a/src/transport/TransportData.cpp b/src/transport/TransportData.cpp index 03886c723..523719ed8 100644 --- a/src/transport/TransportData.cpp +++ b/src/transport/TransportData.cpp @@ -14,6 +14,16 @@ namespace Cantera { +AnyMap TransportData::parameters(bool withInput) const +{ + AnyMap out; + getParameters(out); + if (withInput) { + out.update(input); + } + return out; +} + void TransportData::getParameters(AnyMap &transportNode) const { } diff --git a/test/kinetics/kineticsFromYaml.cpp b/test/kinetics/kineticsFromYaml.cpp index 3641ce21e..7db21dde4 100644 --- a/test/kinetics/kineticsFromYaml.cpp +++ b/test/kinetics/kineticsFromYaml.cpp @@ -329,8 +329,7 @@ public: void duplicateReaction(size_t i) { auto kin = soln->kinetics(); iOld = i; - AnyMap rdata1; - kin->reaction(iOld)->getParameters(rdata1); + AnyMap rdata1 = kin->reaction(iOld)->parameters(); AnyMap rdata2 = AnyMap::fromYamlString(rdata1.toYamlString()); duplicate = newReaction(rdata2, *kin); kin->addReaction(duplicate); diff --git a/test/thermo/thermoParameterizations.cpp b/test/thermo/thermoParameterizations.cpp index 68ac34b8b..b4a5be7e9 100644 --- a/test/thermo/thermoParameterizations.cpp +++ b/test/thermo/thermoParameterizations.cpp @@ -245,8 +245,7 @@ TEST(SpeciesThermo, Mu0PolyFromYaml) { TEST(SpeciesThermo, NasaPoly2ToYaml) { shared_ptr soln = newSolution("../data/simplephases.cti", "nasa1"); auto original = soln->thermo()->species("H2O")->thermo; - AnyMap h2o_data1; - original->getParameters(h2o_data1); + AnyMap h2o_data1 = original->parameters(); AnyMap h2o_data2 = AnyMap::fromYamlString(h2o_data1.toYamlString()); auto duplicate = newSpeciesThermo(h2o_data2); double cp1, cp2, h1, h2, s1, s2; @@ -263,8 +262,7 @@ TEST(SpeciesThermo, NasaPoly2ToYaml) { TEST(SpeciesThermo, ShomatePolyToYaml) { shared_ptr soln = newSolution("../data/simplephases.cti", "shomate1"); auto original = soln->thermo()->species("CO2")->thermo; - AnyMap co2_data1; - original->getParameters(co2_data1); + AnyMap co2_data1 = original->parameters(); AnyMap co2_data2 = AnyMap::fromYamlString(co2_data1.toYamlString()); auto duplicate = newSpeciesThermo(co2_data2); double cp1, cp2, h1, h2, s1, s2; @@ -281,8 +279,7 @@ TEST(SpeciesThermo, ShomatePolyToYaml) { TEST(SpeciesThermo, ConstCpToYaml) { shared_ptr soln = newSolution("../data/simplephases.cti", "simple1"); auto original = soln->thermo()->species("H2O")->thermo; - AnyMap h2o_data1; - original->getParameters(h2o_data1); + AnyMap h2o_data1 = original->parameters(); AnyMap h2o_data2 = AnyMap::fromYamlString(h2o_data1.toYamlString()); auto duplicate = newSpeciesThermo(h2o_data2); double cp1, cp2, h1, h2, s1, s2; @@ -300,8 +297,7 @@ TEST(SpeciesThermo, PiecewiseGibbsToYaml) { shared_ptr soln = newSolution("../data/thermo-models.yaml", "debye-huckel-beta_ij"); auto original = soln->thermo()->species("OH-")->thermo; - AnyMap oh_data; - original->getParameters(oh_data); + AnyMap oh_data = original->parameters(); auto duplicate = newSpeciesThermo(AnyMap::fromYamlString(oh_data.toYamlString())); double cp1, cp2, h1, h2, s1, s2; for (double T : {274, 300, 330, 340}) { @@ -317,8 +313,7 @@ TEST(SpeciesThermo, PiecewiseGibbsToYaml) { TEST(SpeciesThermo, Nasa9PolyToYaml) { shared_ptr soln = newSolution("airNASA9.cti"); auto original = soln->thermo()->species("N2+")->thermo; - AnyMap n2p_data1; - original->getParameters(n2p_data1); + AnyMap n2p_data1 = original->parameters(); AnyMap n2p_data2 = AnyMap::fromYamlString(n2p_data1.toYamlString()); auto duplicate = newSpeciesThermo(n2p_data2); double cp1, cp2, h1, h2, s1, s2; diff --git a/test/thermo/thermoToYaml.cpp b/test/thermo/thermoToYaml.cpp index d53cfff15..fde4a64cd 100644 --- a/test/thermo/thermoToYaml.cpp +++ b/test/thermo/thermoToYaml.cpp @@ -15,7 +15,7 @@ public: // to check for here, clear it so that the only parameters are those // added by the overrides of getParameters. thermo->input().clear(); - thermo->getParameters(data); + data = thermo->parameters(); data.applyUnits(); speciesData.resize(thermo->nSpecies()); @@ -41,7 +41,7 @@ TEST_F(ThermoToYaml, simpleIdealGas) setup("ideal-gas.yaml", "simple"); thermo->setState_TP(1010, 2e5); double rho = thermo->density(); - thermo->getParameters(data); + data = thermo->parameters(); data.applyUnits(); ASSERT_EQ(data["thermo"], "ideal-gas");