Skip to content

Commit

Permalink
[Input] Allow use of subdirectories within Cantera data directories
Browse files Browse the repository at this point in the history
This provides the ability to organize data files included with Cantera
and differentiate data which is useful for different purposes, e.g. sample
data which is only meant to demonstrate capabilities and may not be
physically meaningful.

See Cantera/enhancements#22.

Fixes Cantera#774
  • Loading branch information
speth committed Jun 29, 2020
1 parent 3501d9b commit 340afde
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 50 deletions.
14 changes: 12 additions & 2 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ if 'clean' in COMMAND_LINE_TARGETS:
removeDirectory('interfaces/cython/Cantera.egg-info')
removeDirectory('interfaces/python_minimal/Cantera_minimal.egg-info')
for name in os.listdir('interfaces/cython/cantera/data/'):
if name != '__init__.py':
if os.path.isdir('interfaces/cython/cantera/data/' + name):
removeDirectory('interfaces/cython/cantera/data/' + name)
elif 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/'):
Expand Down Expand Up @@ -1614,14 +1616,22 @@ for xml in mglob(env, 'data/inputs', 'xml'):
for yaml in mglob(env, "data", "yaml"):
dest = pjoin("build", "data", yaml.name)
build(env.Command(dest, yaml.path, Copy("$TARGET", "$SOURCE")))
for subdir in os.listdir('data'):
if os.path.isdir(pjoin('data', subdir)):
for yaml in mglob(env, pjoin("data", subdir), "yaml"):
dest = pjoin("build", "data", subdir, yaml.name)
if not os.path.exists(pjoin("build", "data", subdir)):
os.makedirs(pjoin("build", "data", subdir))
build(env.Command(dest, yaml.path, Copy("$TARGET", "$SOURCE")))


if addInstallActions:
# Put headers in place
headerBase = 'include/cantera'
install(env.RecursiveInstall, '$inst_incdir', 'include/cantera')

# Data files
install('$inst_datadir', mglob(env, 'build/data', 'cti', 'xml', 'yaml'))
install(env.RecursiveInstall, '$inst_datadir', 'build/data')


### List of libraries needed to link to Cantera ###
Expand Down
File renamed without changes.
14 changes: 2 additions & 12 deletions interfaces/cython/.gitignore
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
cantera/*.cpp
cantera/*.c
cantera/data/*.cti
cantera/data/*.xml
cantera/data/*.yaml
cantera/data/*.yml
cantera/test/data/*.cti
cantera/test/data/*.xml
cantera/test/data/*.inp
cantera/test/data/*.dat
cantera/test/data/*.csv
cantera/test/data/*.yaml
cantera/test/data/*.yml
cantera/test/data/test_subdir
cantera/data
cantera/test/data
setup.py
scripts/ctml_writer.py
scripts/ctml_writer
Expand Down
2 changes: 1 addition & 1 deletion interfaces/cython/setup.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ setup(
'Topic :: Scientific/Engineering :: Chemistry',
],
package_data = {
'cantera.data': ['*.*'],
'cantera.data': ['*.*', '*/*.*'],
'cantera.test.data': ['*.*', '*/*.*'],
'cantera.examples': ['*/*.*'],
'cantera': ["@py_extension@", '*.pxd'],
Expand Down
2 changes: 1 addition & 1 deletion samples/cxx/LiC6_electrode/LiC6_electrode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ void calc_potentials()
suppress_deprecation_warnings();
double Tk = 273.15 + 25.0;

std::string filename = "LiC6_electrodebulk.yaml";
std::string filename = "sample-data/LiC6_electrodebulk.yaml";
std::string phasename = "LiC6_and_Vacancies";
std::unique_ptr<ThermoPhase> electrodebulk(newPhase(filename,phasename));
std::string intercalatingSpeciesName("Li(C6)");
Expand Down
67 changes: 43 additions & 24 deletions src/base/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ std::string Application::findInputFile(const std::string& name)
std::unique_lock<std::mutex> dirLock(dir_mutex);
string::size_type islash = name.find('/');
string::size_type ibslash = name.find('\\');
string::size_type icolon = name.find(':');
std::vector<string>& dirs = inputDirs;

// Expand "~/" to user's home directory, if possible
Expand All @@ -421,36 +422,54 @@ std::string Application::findInputFile(const std::string& name)
home = getenv("USERPROFILE"); // Windows systems
}
if (home) {
return home + name.substr(1, npos);
}
}

if (islash == string::npos && ibslash == string::npos) {
size_t nd = dirs.size();
for (size_t i = 0; i < nd; i++) {
string inname = dirs[i] + "/" + name;
std::ifstream fin(inname);
string full_name = home + name.substr(1, npos);
std::ifstream fin(full_name);
if (fin) {
return inname;
return full_name;
} else {
throw CanteraError("Application::findInputFile",
"Input file '{}' not found", name);
}
}
string msg = "\nInput file " + name + " not found in director";
msg += (nd == 1 ? "y " : "ies ");
for (size_t i = 0; i < nd; i++) {
msg += "\n'" + dirs[i] + "'";
if (i+1 < nd) {
msg += ", ";
}
}

// If this is an absolute path, just look for the file there
if (islash == 0 || ibslash == 0
|| (icolon == 1 && (ibslash == 2 || islash == 2)))
{
std::ifstream fin(name);
if (fin) {
return name;
} else {
throw CanteraError("Application::findInputFile",
"Input file '{}' not found", name);
}
msg += "\n\n";
msg += "To fix this problem, either:\n";
msg += " a) move the missing files into the local directory;\n";
msg += " b) define environment variable CANTERA_DATA to\n";
msg += " point to the directory containing the file.";
throw CanteraError("Application::findInputFile", msg);
}

return name;
// Search the Cantera data directories for the input file, and return
// the full path if a match is found
size_t nd = dirs.size();
for (size_t i = 0; i < nd; i++) {
string full_name = dirs[i] + "/" + name;
std::ifstream fin(full_name);
if (fin) {
return full_name;
}
}
string msg = "\nInput file " + name + " not found in director";
msg += (nd == 1 ? "y " : "ies ");
for (size_t i = 0; i < nd; i++) {
msg += "\n'" + dirs[i] + "'";
if (i+1 < nd) {
msg += ", ";
}
}
msg += "\n\n";
msg += "To fix this problem, either:\n";
msg += " a) move the missing files into the local directory;\n";
msg += " b) define environment variable CANTERA_DATA to\n";
msg += " point to the directory containing the file.";
throw CanteraError("Application::findInputFile", msg);
}

Application* Application::s_app = 0;
Expand Down
17 changes: 7 additions & 10 deletions src/base/application.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,23 +247,20 @@ class Application
/*!
* This routine will search for a file in the default locations specified
* for the application. See the routine setDefaultDirectories() listed
* above.
* above. The first directory searched is usually the current working
* directory.
*
* The default set of directories specified for the application will be
* searched if a '/' or an '\\' is not found in the name. If either is found
* then a relative path name is presumed, and the default directories are
* not searched.
* The default set of directories will not be searched if an absolute path
* (for example, one starting with `/` or `C:\`) or a path relative to the
* user's home directory (for example, starting with `~/`) is specified.
*
* The presence of the file is determined by whether the file can be
* opened for reading by the current user.
*
* @param name Name of the input file to be searched for
* @return The absolute path name of the first matching file is
* returned. If a relative path name is indicated, the relative path
* name is returned.
* @return The absolute path name of the first matching file
*
* If the file is not found, a message is written to stdout and a
* CanteraError exception is thrown.
* If the file is not found a CanteraError exception is thrown.
*
* @ingroup inputfiles
*/
Expand Down

0 comments on commit 340afde

Please sign in to comment.