[Input] Search current directory for referenced YAML input files

This commit is contained in:
Ray Speth 2019-01-14 10:48:45 -05:00
parent 2c58dd78c6
commit fdfbc58a1e
8 changed files with 43 additions and 15 deletions

View file

@ -78,6 +78,7 @@ if 'clean' in COMMAND_LINE_TARGETS:
for name in os.listdir('interfaces/cython/cantera/data/'):
if name != '__init__.py':
removeFile('interfaces/cython/cantera/data/' + name)
removeDirectory('interfaces/cython/cantera/test/data/test_subdir')
for name in os.listdir('interfaces/cython/cantera/test/data/'):
if name != '__init__.py':
removeFile('interfaces/cython/cantera/test/data/' + name)

View file

@ -228,9 +228,12 @@ public:
//! Create an AnyMap from a YAML file.
/*!
* Searches the Cantera include path for the file.
* Searches the directory containing the optionally-specified parent file
* first, followed by the current working directory and the Cantera include
* path.
*/
static AnyMap fromYamlFile(const std::string& name);
static AnyMap fromYamlFile(const std::string& name,
const std::string& parent_name="");
//! Create an AnyMap from a string containing a YAML document
static AnyMap fromYamlString(const std::string& yaml);

View file

@ -9,6 +9,7 @@ cantera/test/data/*.dat
cantera/test/data/*.csv
cantera/test/data/*.yaml
cantera/test/data/*.yml
cantera/test/data/test_subdir
setup.py
scripts/ctml_writer.py
scripts/ctml_writer

View file

@ -749,18 +749,37 @@ AnyMap AnyMap::fromYamlString(const std::string& yaml) {
return amap;
}
AnyMap AnyMap::fromYamlFile(const std::string& name) {
std::string fullName = findInputFile(name);
int mtime = get_modified_time(fullName);
AnyMap AnyMap::fromYamlFile(const std::string& name,
const std::string& parent_name)
{
std::string fullName;
// See if a file with this name exists in a path relative to the parent file
size_t islash = parent_name.find_last_of("/\\");
if (islash != npos) {
std::string parent_path = parent_name.substr(0, islash);
if (std::ifstream(parent_path + "/" + name).good()) {
fullName = parent_path + "/" + name;
}
}
// Otherwise, search the Cantera include path for the file
if (fullName.empty()) {
fullName = findInputFile(name);
}
// Check for an already-parsed YAML file with the same last-modified time,
// and return that if possible
int mtime = get_modified_time(fullName);
std::unique_lock<std::mutex> lock(yaml_cache_mutex);
auto iter = s_cache.find(fullName);
if (iter != s_cache.end() && iter->second.second == mtime) {
return iter->second.first;
}
if (!std::ifstream(fullName).good()) {
throw CanteraError("AnyMap::fromYamlFile", "Input file '{}' not found "
"on the Cantera search path.", name);
}
// Generate an AnyMap from the YAML file and store it in the cache
auto& cache_item = s_cache[fullName];
cache_item.second = mtime;
@ -777,6 +796,7 @@ AnyMap AnyMap::fromYamlFile(const std::string& name) {
s_cache.erase(fullName);
throw;
}
cache_item.first["__file__"] = fullName;
// Return a copy of the AnyMap
return cache_item.first;

View file

@ -111,12 +111,13 @@ void addReactions(Kinetics& kin, const AnyMap& phaseNode, const AnyMap& rootNode
throw CanteraError("setupKinetics", "Unknown rule '{}' for adding "
"species from the '{}' section.", rules[i], sections[i]);
}
const auto& slash = boost::ifind_first(sections[i], "/");
const auto& slash = boost::ifind_last(sections[i], "/");
if (slash) {
// specified section is in a different file
string fileName (sections[i].begin(), slash.begin());
string node(slash.end(), sections[i].end());
AnyMap reactions = AnyMap::fromYamlFile(fileName);
AnyMap reactions = AnyMap::fromYamlFile(fileName,
rootNode.getString("__file__", ""));
for (const auto& R : reactions[node].asVector<AnyMap>()) {
kin.addReaction(newReaction(R, kin));
}

View file

@ -431,11 +431,12 @@ void setupPhase(ThermoPhase& thermo, const AnyMap& phaseNode,
for (const auto& elemNode : phaseNode["elements"].asVector<AnyMap>()) {
const string& source = elemNode.begin()->first;
const auto& names = elemNode.begin()->second.asVector<string>();
const auto& slash = boost::ifind_first(source, "/");
const auto& slash = boost::ifind_last(source, "/");
if (slash) {
std::string fileName(source.begin(), slash.begin());
std::string node(slash.end(), source.end());
const AnyMap elements = AnyMap::fromYamlFile(fileName);
const AnyMap elements = AnyMap::fromYamlFile(fileName,
rootNode.getString("__file__", ""));
addElements(thermo, names,
elements[node].asMap("symbol"), false);
} else if (rootNode.hasKey(source)) {
@ -476,12 +477,13 @@ void setupPhase(ThermoPhase& thermo, const AnyMap& phaseNode,
for (const auto& speciesNode : phaseNode["species"].asVector<AnyMap>()) {
const string& source = speciesNode.begin()->first;
const auto& names = speciesNode.begin()->second;
const auto& slash = boost::ifind_first(source, "/");
const auto& slash = boost::ifind_last(source, "/");
if (slash) {
// source is a different input file
std::string fileName(source.begin(), slash.begin());
std::string node(slash.end(), source.end());
AnyMap species = AnyMap::fromYamlFile(fileName);
AnyMap species = AnyMap::fromYamlFile(fileName,
rootNode.getString("__file__", ""));
addSpecies(thermo, names, species[node]);
} else if (rootNode.hasKey(source)) {
// source is in the current file

View file

@ -24,7 +24,7 @@ phases:
thermo: ideal-gas
elements:
- default: [N, O]
- species-elements.yaml/isotopes: [Ar]
- test_subdir/species-elements.yaml/isotopes: [Ar]
species: [O2, NO, N2, AR]
note: replace Argon with custom element from a different file
state: {T: 900.0, P: 5 atm, Y: {O2: 0.4, N2: 0.4, AR: 0.2}}
@ -33,7 +33,7 @@ phases:
thermo: ideal-gas
species:
- species: [O2, N2]
- species-elements.yaml/species: [NO2, N2O]
- ../../test/data/test_subdir/species-elements.yaml/species: [NO2, N2O]
state: {T: 300.0, P: 1 atm, X: "N2O:0.3, O2:0.7"}
- name: species-all
@ -50,8 +50,8 @@ phases:
kinetics: gas
species:
- species: all
- species-elements.yaml/species: all
reactions: [reactions, species-elements.yaml/nox-reactions]
- test_subdir/species-elements.yaml/species: all
reactions: [reactions, test_subdir/species-elements.yaml/nox-reactions]
state: {T: 300.0, P: 1 atm, X: {AR: 0.2, O2: 0.7, N2: 0.1}}