Add AnyValue::getMapWhere function

This commit is contained in:
Ray Speth 2019-02-06 19:26:43 -05:00
parent d77a5979a8
commit 672b55a72f
10 changed files with 42 additions and 70 deletions

View file

@ -123,6 +123,11 @@ public:
std::unordered_map<std::string, const AnyMap*> asMap(const std::string& name) const;
std::unordered_map<std::string, AnyMap*> asMap(const std::string& name);
//! For objects of type vector<AnyMap>, return the item where the given key
//! has the specified value. If value is the empty string, returns the first
//! item in the list.
AnyMap& getMapWhere(const std::string& key, const std::string& value);
//! @see AnyMap::applyUnits
void applyUnits(const UnitSystem& units);

View file

@ -55,6 +55,7 @@ cdef extern from "cantera/base/AnyMap.h" namespace "Cantera":
cdef cppclass CxxAnyValue "Cantera::AnyValue":
CxxAnyValue()
unordered_map[string, CxxAnyMap*] asMap(string) except +translate_exception
CxxAnyMap& getMapWhere(string, string) except +translate_exception
CxxAnyMap AnyMapFromYamlFile "Cantera::AnyMap::fromYamlFile" (string) except +translate_exception
CxxAnyMap AnyMapFromYamlString "Cantera::AnyMap::fromYamlString" (string) except +translate_exception

View file

@ -50,26 +50,12 @@ cdef class _SolutionBase:
elif source:
root = AnyMapFromYamlString(stringify(source))
phaseNodes = root[stringify("phases")].asMap(stringify("name"))
phaseNames = []
for item in phaseNodes:
phaseNames.append(pystr(item.first))
if not phaseNames:
raise ValueError("YAML document doesn't contain any phase definitions")
if phaseid:
if phaseid in phaseNames:
phaseNode = phaseNodes[stringify(phaseid)]
else:
raise ValueError("YAML document doesn't contain"
" a phase named '{}'".format(phaseid))
else:
phaseNode = phaseNodes[stringify(phaseNames[0])]
phaseNode = root[stringify("phases")].getMapWhere(stringify("name"),
stringify(phaseid))
# Thermo
if isinstance(self, ThermoPhase):
self._thermo = newPhase(deref(phaseNode), root)
self._thermo = newPhase(phaseNode, root)
self.thermo = self._thermo.get()
else:
self.thermo = NULL
@ -83,7 +69,7 @@ cdef class _SolutionBase:
for phase in phases:
# adjacent bulk phases for a surface phase
v.push_back(phase.thermo)
self._kinetics = newKinetics(v, deref(phaseNode), root)
self._kinetics = newKinetics(v, phaseNode, root)
self.kinetics = self._kinetics.get()
else:
self.kinetics = NULL

View file

@ -468,6 +468,20 @@ std::unordered_map<std::string, AnyMap*> AnyValue::asMap(const std::string& name
return mapped;
}
AnyMap& AnyValue::getMapWhere(const std::string& key, const std::string& value)
{
if (value == "") {
return asVector<AnyMap>().at(0);
}
for (auto& item : asVector<AnyMap>()) {
if (item.hasKey(key) && item[key].asString() == value) {
return item;
}
}
throw InputFileError("AnyValue::getMapWhere", *this,
"List does not contain a map where '{}' = '{}'", key, value);
}
void AnyValue::applyUnits(const UnitSystem& units)
{
if (is<AnyMap>()) {

View file

@ -80,19 +80,8 @@ unique_ptr<Kinetics> newKinetics(std::vector<ThermoPhase*>& phases,
if (extension == "yml" || extension == "yaml") {
AnyMap root = AnyMap::fromYamlFile(filename);
if (phase_name != "") {
auto phaseNodes = root["phases"].asMap("name");
if (phaseNodes.find(phase_name) == phaseNodes.end()) {
throw CanteraError("newKinetics",
"Couldn't find phase named '{}' in file '{}'.",
phase_name, filename);
}
return newKinetics(phases, *phaseNodes[phase_name], root);
} else {
// Use the first phase definition
auto& phaseNode = root["phases"].asVector<AnyMap>().at(0);
return newKinetics(phases, phaseNode, root);
}
AnyMap& phaseNode = root["phases"].getMapWhere("name", phase_name);
return newKinetics(phases, phaseNode, root);
} else {
XML_Node* root = get_XML_File(filename);
XML_Node* xphase = get_XML_NameID("phase", "#"+phase_name, root);

View file

@ -485,8 +485,8 @@ void IonsFromNeutralVPSSTP::initThermo()
if (m_input.hasKey("neutral-phase") && m_input.hasKey("__file__")) {
string neutralName = m_input["neutral-phase"].asString();
AnyMap infile = AnyMap::fromYamlFile(m_input["__file__"].asString());
auto phaseNodes = infile["phases"].asMap("name");
setNeutralMoleculePhase(newPhase(*phaseNodes.at(neutralName), infile));
AnyMap& phaseNode = infile["phases"].getMapWhere("name", neutralName);
setNeutralMoleculePhase(newPhase(phaseNode, infile));
}
size_t nElementsN = neutralMoleculePhase_->nElements();

View file

@ -290,15 +290,10 @@ void LatticeSolidPhase::initThermo()
{
if (m_input.hasKey("composition") && m_input.hasKey("__file__")) {
AnyMap infile = AnyMap::fromYamlFile(m_input["__file__"].asString());
auto phaseNodes = infile["phases"].asMap("name");
compositionMap composition = m_input["composition"].asMap<double>();
for (auto& item : composition) {
if (phaseNodes.count(item.first)) {
addLattice(newPhase(*phaseNodes.at(item.first), infile));
} else {
throw CanteraError("LatticeSolidPhase::initThermo",
"Could not find component phase named '{}'.", item.first);
}
AnyMap& node = infile["phases"].getMapWhere("name", item.first);
addLattice(newPhase(node, infile));
}
setLatticeStoichiometry(composition);
}

View file

@ -128,22 +128,10 @@ ThermoPhase* newPhase(const std::string& infile, std::string id)
if (extension == "yml" || extension == "yaml") {
AnyMap root = AnyMap::fromYamlFile(infile);
if (id != "") {
auto phases = root["phases"].asMap("name");
if (phases.find(id) == phases.end()) {
throw CanteraError("newPhase",
"Couldn't find phase named '{}' in file '{}'.", id, infile);
}
unique_ptr<ThermoPhase> t(newThermoPhase(phases[id]->at("thermo").asString()));
setupPhase(*t, *phases[id], root);
return t.release();
} else {
// Use the first phase definition
auto& phase = root["phases"].asVector<AnyMap>().at(0);
unique_ptr<ThermoPhase> t(newThermoPhase(phase["thermo"].asString()));
setupPhase(*t, phase, root);
return t.release();
}
AnyMap& phase = root["phases"].getMapWhere("name", id);
unique_ptr<ThermoPhase> t(newThermoPhase(phase["thermo"].asString()));
setupPhase(*t, phase, root);
return t.release();
} else {
XML_Node* root = get_XML_File(infile);
XML_Node* xphase = get_XML_NameID("phase", "#"+id, root);

View file

@ -685,12 +685,8 @@ void ThermoPhase::initThermoFile(const std::string& inputFile,
if (extension == "yml" || extension == "yaml") {
AnyMap root = AnyMap::fromYamlFile(inputFile);
auto phases = root["phases"].asMap("name");
if (phases.find(id) == phases.end()) {
throw CanteraError("newPhase",
"Couldn't find phase named '{}' in file '{}'.", id, inputFile);
}
setupPhase(*this, *phases[id], root);
auto& phase = root["phases"].getMapWhere("name", id);
setupPhase(*this, phase, root);
} else {
XML_Node* fxml = get_XML_File(inputFile);
XML_Node* fxml_phase = findXMLPhase(fxml, id);

View file

@ -174,11 +174,10 @@ TEST(Reaction, ChebyshevFromYaml)
TEST(Kinetics, GasKineticsFromYaml1)
{
AnyMap infile = AnyMap::fromYamlFile("ideal-gas.yaml");
auto phaseNodes = infile["phases"].asMap("name");
auto phaseNode = phaseNodes.at("simple-kinetics");
shared_ptr<ThermoPhase> thermo = newPhase(*phaseNode, infile);
auto& phaseNode = infile["phases"].getMapWhere("name", "simple-kinetics");
shared_ptr<ThermoPhase> thermo = newPhase(phaseNode, infile);
std::vector<ThermoPhase*> phases{thermo.get()};
auto kin = newKinetics(phases, *phaseNode, infile);
auto kin = newKinetics(phases, phaseNode, infile);
EXPECT_EQ(kin->nReactions(), (size_t) 2);
const auto& R = kin->reaction(0);
EXPECT_EQ(R->reactants.at("NO"), 1);
@ -191,11 +190,10 @@ TEST(Kinetics, GasKineticsFromYaml1)
TEST(Kinetics, GasKineticsFromYaml2)
{
AnyMap infile = AnyMap::fromYamlFile("ideal-gas.yaml");
auto phaseNodes = infile["phases"].asMap("name");
auto phaseNode = phaseNodes.at("remote-kinetics");
shared_ptr<ThermoPhase> thermo = newPhase(*phaseNode, infile);
auto& phaseNode = infile["phases"].getMapWhere("name", "remote-kinetics");
shared_ptr<ThermoPhase> thermo = newPhase(phaseNode, infile);
std::vector<ThermoPhase*> phases{thermo.get()};
auto kin = newKinetics(phases, *phaseNode, infile);
auto kin = newKinetics(phases, phaseNode, infile);
EXPECT_EQ(kin->nReactions(), (size_t) 3);
}