diff --git a/.kessel/workflows/cmake.py b/.kessel/workflows/cmake.py index f5b52a8d78f..094ab9503e3 100644 --- a/.kessel/workflows/cmake.py +++ b/.kessel/workflows/cmake.py @@ -10,7 +10,8 @@ class Build(BuildEnvironment): spack_env = environment("singularity_eos_default") project_spec = environment("singularity-eos+tests") - xcap_spackages_checkout = environment(Path.cwd() / "extern" / "xcap_spackages", variable="XCAP_SPACKAGES_CHECKOUT") + xcap_spackages_checkout = environment( + Path.cwd() / "extern" / "xcap_spackages", variable="XCAP_SPACKAGES_CHECKOUT") def ci_message(self, args): pre_alloc_init = "" @@ -43,7 +44,8 @@ def env(self, args): super().prepare_env(args) if "KESSEL_DEPLOYMENT" not in self.environ: - self.exec(f"spack repo add {self.xcap_spackages_checkout}/v2/spack_repo/xcap || true") + self.exec( + f"spack repo add {self.xcap_spackages_checkout}/v2/spack_repo/xcap || true") # Handle spiner and ports-of-call submodule dependencies spiner_path = self.source_dir / "utils" / "spiner" @@ -52,7 +54,8 @@ def env(self, args): ports_of_call_path = self.source_dir / "utils" / "ports-of-call" if (ports_of_call_path / ".git").exists(): - self.exec(f"spack develop --no-clone -p {ports_of_call_path} ports-of-call@main") + self.exec( + f"spack develop --no-clone -p {ports_of_call_path} ports-of-call@main") super().install_env(args) @@ -62,7 +65,7 @@ def test(self, args): pushd {self.build_dir} if [[ -f sesame2spiner/sesame2spiner ]]; then echo "/usr/projects/data/eos/eos-developmental/Sn2162/v01/sn2162-v01.bin" > sesameFilesDir.txt - sesame2spiner/sesame2spiner -s materials.sp5 ../sesame2spiner/examples/unit_tests/*.dat + sesame2spiner/sesame2spiner -s materials.sp5 ../sesame2spiner/examples/unit_tests/mats.dat sesame2spiner/sesame2spiner -s duplicates.sp5 ../sesame2spiner/examples/duplicate-test/*.dat fi popd""") diff --git a/CHANGELOG.md b/CHANGELOG.md index 86c08afc012..0c379a63599 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ## Current develop ### Added (new features/APIs/variables/...) -- [[PR618]](https://github.com/lanl/singularity-eos/pull/618) Add PTDerivativesFromPreferred for computing derivatives of a mixture in a cell +- [[PR623]](https://github.com/lanl/singularity-eos/pull/623) Expanded the sesame2spiner syntax to support multiple material definitions in one input file. +- [[PR618]](https://github.com/lanl/singularity-eos/pull/618) Add PTDerivativesFromPreferred for computing derivatives of a mixture in a cell ### Fixed (Repair bugs, etc) diff --git a/sesame2spiner/examples/all_in_one.dat b/sesame2spiner/examples/all_in_one.dat new file mode 100644 index 00000000000..a94f25e72f8 --- /dev/null +++ b/sesame2spiner/examples/all_in_one.dat @@ -0,0 +1,47 @@ +# ====================================================================== +# © 2026. Triad National Security, LLC. All rights reserved. This +# program was produced under U.S. Government contract 89233218CNA000001 +# for Los Alamos National Laboratory (LANL), which is operated by Triad +# National Security, LLC for the U.S. Department of Energy/National +# Nuclear Security Administration. All rights in the program are +# reserved by Triad National Security, LLC, and the U.S. Department of +# Energy/National Nuclear Security Administration. The Government is +# granted for itself and others acting on its behalf a nonexclusive, +# paid-up, irrevocable worldwide license in this material to reproduce, +# prepare derivative works, distribute copies to the public, perform +# publicly and display publicly, and to permit others to do so. +# ====================================================================== + +# First material doesn't need +matid = 5030 +name = air +# These set the number of grid points per decade +# for each variable. The default is 50 points +# per decade. +numrho/decade = 40 +numT/decade = 40 +numSie/decade = 40 + + +matid=3720 +name=aluminum # define it again to test +rhomin = 1e-5 +Tmin = 1 + + +matid = 5762 + + +matid = 4272 +rhomin = 1e-5 +Tmin = 1 + + + +matid = 2961 +# These set the number of grid points per decade +# for each variable. The default is 50 points +# per decade. +numrho/decade = 30 +numT/decade = 25 +numSie/decade = 15 diff --git a/sesame2spiner/examples/unit_tests/mats.dat b/sesame2spiner/examples/unit_tests/mats.dat new file mode 100644 index 00000000000..60a360cc6c9 --- /dev/null +++ b/sesame2spiner/examples/unit_tests/mats.dat @@ -0,0 +1,51 @@ +# ====================================================================== +# © 2026. Triad National Security, LLC. All rights reserved. This +# program was produced under U.S. Government contract 89233218CNA000001 +# for Los Alamos National Laboratory (LANL), which is operated by Triad +# National Security, LLC for the U.S. Department of Energy/National +# Nuclear Security Administration. All rights in the program are +# reserved by Triad National Security, LLC, and the U.S. Department of +# Energy/National Nuclear Security Administration. The Government is +# granted for itself and others acting on its behalf a nonexclusive, +# paid-up, irrevocable worldwide license in this material to reproduce, +# prepare derivative works, distribute copies to the public, perform +# publicly and display publicly, and to permit others to do so. +# ====================================================================== + +# First material doesn't need +matid = 5030 +name = air + + +matid=3720 +name=Aluminum # can override name + + +matid=3337 +piecewiseRho = false +numrho/decade = 50 + + +matid = 5267 + + +matid=7592 +numrho/decade = 200 +numT/decade = 200 + + +matid = 2700 + + +matid = 5000 + + +matid=4272 +ionization = true + + +matid=2162 + + +matid = 2961 + diff --git a/sesame2spiner/generate_files.cpp b/sesame2spiner/generate_files.cpp index c3b5d48ae52..e5453f94c00 100644 --- a/sesame2spiner/generate_files.cpp +++ b/sesame2spiner/generate_files.cpp @@ -177,15 +177,7 @@ herr_t saveAllMaterials(const std::string &savename, herr_t status = H5_SUCCESS; for (auto const &filename : filenames) { - Params p(filename); - if (!p.Contains("matid")) { - std::cerr << "Material file " << filename << "is missing matid.\n" - << "Example input files:\n" - << EXAMPLESTRING << std::endl; - std::exit(1); - } - matids.push_back(p.Get("matid")); - params.push_back(p); + AddMaterials(params, matids, filename); } std::cout << "Saving to file " << savename << std::endl; diff --git a/sesame2spiner/parser.cpp b/sesame2spiner/parser.cpp index 8ffaed6c5bd..7e8b0568b24 100644 --- a/sesame2spiner/parser.cpp +++ b/sesame2spiner/parser.cpp @@ -19,7 +19,9 @@ #include #include #include +#include +#include "parse_cli.hpp" #include "parser.hpp" Params::Params(const std::string &input_file) { @@ -39,10 +41,22 @@ void Params::Parse(std::istream &s) { auto delimiter_pos = line.find("="); auto name = line.substr(0, delimiter_pos); auto value = line.substr(delimiter_pos + 1); + // make sure there's no trailing comment + auto comment_pos = value.find("#"); + if (comment_pos != std::string::npos) { + value.erase(comment_pos); + } params_[name] = value; } } +void Params::Print(std::ostream &s) const { + s << "\nParams for " << params_.at("name") << "\n"; + for (const auto &pair : params_) { + s << pair.first << " = " << pair.second << "\n"; + } +} + template <> std::string Params::Get(const std::string &key) const { return params_.at(key); @@ -74,3 +88,74 @@ bool Params::Get(const std::string &key) const { throw std::runtime_error("The value of " + key + " is not a boolean.\n"); } } + +void add_param(const Params &p, std::vector ¶ms, std::vector &matids, + const std::string &filename) { + + if (!p.Contains("matid")) { + if (p.Contains("name")) { + const auto &name = p.Get("name"); + std::cerr << "Material " << name << " in file " << filename << "is missing matid.\n" + << "Example input files:\n" + << EXAMPLESTRING << std::endl; + std::exit(1); + } else { + std::cerr << "A Material in file " << filename << "has no name.\n" + << "Example input files:\n" + << EXAMPLESTRING << std::endl; + std::exit(1); + } + } + matids.push_back(p.Get("matid")); + params.push_back(p); +} + +void parse_file(std::vector ¶ms, std::vector &matids, std::istream &s, + const std::string &filename) { + std::string line; + Params p; + size_t line_num = 1; + while (getline(s, line)) { + line.erase(std::remove_if(line.begin(), line.end(), isspace), line.end()); + if (line[0] == '#' || line.empty()) { + line_num++; + continue; + } + if (line[0] == '<') { + auto term = line.find('>'); + if (term == std::string::npos) { + std::cerr << "Missing closing > on line " << line_num << " of file " << filename + << "\n"; + std::exit(1); + } + + auto name = line.substr(1, term - 1); + if (!p.Empty()) add_param(p, params, matids, filename); + + p.Clear(); + p.Set("name", name); + } else { + auto delimiter_pos = line.find("="); + auto name = line.substr(0, delimiter_pos); + auto value = line.substr(delimiter_pos + 1); + // make sure there's no trailing comment + auto comment_pos = value.find("#"); + if (comment_pos != std::string::npos) { + value.erase(comment_pos); + } + p.Set(name, value); + } + line_num++; + } + if (!p.Empty()) add_param(p, params, matids, filename); +} + +void AddMaterials(std::vector ¶ms, std::vector &matids, + const std::string &input_file) { + std::ifstream config_file(input_file); + if (config_file.is_open()) { + parse_file(params, matids, config_file, input_file); + } else { + throw std::runtime_error("Couldn't open config file " + input_file + "\n"); + } +} \ No newline at end of file diff --git a/sesame2spiner/parser.hpp b/sesame2spiner/parser.hpp index 588b86d98bd..10b9a1e1d2f 100644 --- a/sesame2spiner/parser.hpp +++ b/sesame2spiner/parser.hpp @@ -19,11 +19,13 @@ #include #include #include +#include // Parse a simple parameter file with // "#" denoting comments. class Params { public: + Params() = default; Params(const std::string &input_file); Params(std::stringstream &input) { Parse(input); } @@ -34,10 +36,17 @@ class Params { T Get(const std::string &key, T default_value) const { return Contains(key) ? Get(key) : default_value; } + void Print(std::ostream &s) const; + void Clear() { params_.clear(); } + bool Empty() const { return params_.size() == 0; } + void Set(const std::string &key, const std::string &val) { params_[key] = val; } private: void Parse(std::istream &s); std::unordered_map params_; }; +void AddMaterials(std::vector ¶ms, std::vector &matids, + const std::string &input_file); + #endif // SESAME2SPINER_PARSER_HPP_