From d9847163e86a4131016a1a6a5f0cd7c0e12b34cc Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 23 Nov 2022 23:06:31 -0600 Subject: [PATCH] Adding ability to specify an input filename to the executable or to the python exec --- include/openmc/initialize.h | 4 +++ openmc/executor.py | 37 +++++++++++++++++++----- openmc/model/model.py | 1 - src/initialize.cpp | 24 +++++++++++---- tests/regression_tests/model_xml/test.py | 22 +++++++++++++- 5 files changed, 73 insertions(+), 15 deletions(-) diff --git a/include/openmc/initialize.h b/include/openmc/initialize.h index 5caccceda6..c37208e5e3 100644 --- a/include/openmc/initialize.h +++ b/include/openmc/initialize.h @@ -1,6 +1,8 @@ #ifndef OPENMC_INITIALIZE_H #define OPENMC_INITIALIZE_H +#include + #ifdef OPENMC_MPI #include "mpi.h" #endif @@ -19,6 +21,8 @@ void read_separate_xml_files(); //! Write some output that occurs right after initialization void initial_output(); + +std::string args_xml_filename {}; } // namespace openmc #endif // OPENMC_INITIALIZE_H diff --git a/openmc/executor.py b/openmc/executor.py index a73d896ffe..b143132139 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -9,7 +9,7 @@ from .plots import _get_plot_image def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, plot=False, restart_file=None, threads=None, tracks=False, event_based=None, - openmc_exec='openmc', mpi_args=None): + openmc_exec='openmc', mpi_args=None, input_file=None): """Converts user-readable flags in to command-line arguments to be run with the OpenMC executable via subprocess. @@ -42,6 +42,8 @@ def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, mpi_args : list of str, optional MPI execute command and any additional MPI arguments to pass, e.g. ['mpiexec', '-n', '8']. + input_file : str or Pathlike + Name of a single XML input file for the OpenMC executable to read. .. versionadded:: 0.13.0 @@ -82,6 +84,9 @@ def _process_CLI_arguments(volume=False, geometry_debug=False, particles=None, if mpi_args is not None: args = mpi_args + args + if input_file is not None: + args += ['-i', input_file] + return args @@ -118,7 +123,7 @@ def _run(args, output, cwd): raise RuntimeError(error_msg) -def plot_geometry(output=True, openmc_exec='openmc', cwd='.'): +def plot_geometry(output=True, openmc_exec='openmc', cwd='.', input_file=None): """Run OpenMC in plotting mode Parameters @@ -129,6 +134,8 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.'): Path to OpenMC executable cwd : str, optional Path to working directory to run in + input_file : str + Name of a single XML input file for the OpenMC executable to read. Raises ------ @@ -136,10 +143,13 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.'): If the `openmc` executable returns a non-zero status """ + args = [openmc_exec, '-p'] + if input_file is not None: + args += ['-i', input_file] _run([openmc_exec, '-p'], output, cwd) -def plot_inline(plots, openmc_exec='openmc', cwd='.'): +def plot_inline(plots, openmc_exec='openmc', cwd='.', input_file=None): """Display plots inline in a Jupyter notebook. .. versionchanged:: 0.13.0 @@ -155,6 +165,8 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.'): Path to OpenMC executable cwd : str, optional Path to working directory to run in + input_file : str + Name of a single XML input file for the OpenMC executable to read. Raises ------ @@ -171,7 +183,7 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.'): openmc.Plots(plots).export_to_xml(cwd) # Run OpenMC in geometry plotting mode - plot_geometry(False, openmc_exec, cwd) + plot_geometry(False, openmc_exec, cwd, input_file) if plots is not None: images = [_get_plot_image(p, cwd) for p in plots] @@ -179,7 +191,8 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.'): def calculate_volumes(threads=None, output=True, cwd='.', - openmc_exec='openmc', mpi_args=None): + openmc_exec='openmc', mpi_args=None, + input_file=None): """Run stochastic volume calculations in OpenMC. This function runs OpenMC in stochastic volume calculation mode. To specify @@ -210,6 +223,8 @@ def calculate_volumes(threads=None, output=True, cwd='.', cwd : str, optional Path to working directory to run in. Defaults to the current working directory. + input_file : str or Pathlike + Name of a single XML input file for the OpenMC executable to read. Raises ------ @@ -223,14 +238,16 @@ def calculate_volumes(threads=None, output=True, cwd='.', """ args = _process_CLI_arguments(volume=True, threads=threads, - openmc_exec=openmc_exec, mpi_args=mpi_args) + openmc_exec=openmc_exec, mpi_args=mpi_args, + input_file=input_file) _run(args, output, cwd) def run(particles=None, threads=None, geometry_debug=False, restart_file=None, tracks=False, output=True, cwd='.', - openmc_exec='openmc', mpi_args=None, event_based=False): + openmc_exec='openmc', mpi_args=None, event_based=False, + input_file=None): """Run an OpenMC simulation. Parameters @@ -265,6 +282,9 @@ def run(particles=None, threads=None, geometry_debug=False, .. versionadded:: 0.12 + input_file : str or Pathlike + Name of a single XML input file for the OpenMC executable to read. + Raises ------ RuntimeError @@ -275,6 +295,7 @@ def run(particles=None, threads=None, geometry_debug=False, args = _process_CLI_arguments( volume=False, geometry_debug=geometry_debug, particles=particles, restart_file=restart_file, threads=threads, tracks=tracks, - event_based=event_based, openmc_exec=openmc_exec, mpi_args=mpi_args) + event_based=event_based, openmc_exec=openmc_exec, mpi_args=mpi_args, + input_file=input_file) _run(args, output, cwd) diff --git a/openmc/model/model.py b/openmc/model/model.py index 2ed9bf668a..15effd3e4c 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -221,7 +221,6 @@ class Model: Geometry object """ - if separate_xmls or not Path(path).exists(): return cls.from_separate_xmls(*args, **kwargs) else: diff --git a/src/initialize.cpp b/src/initialize.cpp index dc5c0c3c11..02a4f9ab75 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -181,10 +181,11 @@ int parse_command_line(int argc, char* argv[]) } else if (arg == "-e" || arg == "--event") { settings::event_based = true; - + } else if (arg == "-i" || arg == "--input") { + i += 1; + args_xml_filename = std::string(argv[i]); } else if (arg == "-r" || arg == "--restart") { i += 1; - // Check what type of file this is hid_t file_id = file_open(argv[i], 'r', true); std::string filetype; @@ -295,9 +296,19 @@ int parse_command_line(int argc, char* argv[]) bool read_model_xml() { // get verbosity from settings node - std::string model_filename = settings::path_input + "model.xml"; - bool use_model_file = file_exists(model_filename); - if (!file_exists(model_filename)) return false; + + std::string xml_filename = "model.xml"; + if (!args_xml_filename.empty()) xml_filename = args_xml_filename; + std::string model_filename = settings::path_input + xml_filename; + + // check that the model file exists. If it does not and a custom filename was + // supplied by the user report an error + if (!file_exists(model_filename)) { + if (!args_xml_filename.empty()) { + fatal_error(fmt::format("The input file '{}' specified on the command line does not exist", args_xml_filename)); + } + return false; + } // attempt to open the document pugi::xml_document doc; @@ -325,6 +336,9 @@ bool read_model_xml() { title(); } + if (!args_xml_filename.empty()) + write_message(fmt::format("Reaging user-specified input '{}'...", args_xml_filename), 5); + else write_message("Reading model XML file...", 5); read_settings_xml(settings_root); diff --git a/tests/regression_tests/model_xml/test.py b/tests/regression_tests/model_xml/test.py index 289bd46552..342d7dca90 100644 --- a/tests/regression_tests/model_xml/test.py +++ b/tests/regression_tests/model_xml/test.py @@ -73,4 +73,24 @@ def test_model_xml(model, path, request): inputs = path + "/inputs_true.dat" results = path + "/results_true.dat" harness = ModelXMLTestHarness(request.getfixturevalue(model), inputs, results) - harness.main() \ No newline at end of file + harness.main() + +def test_input_arg(run_in_tmpdir): + + pincell = openmc.examples.pwr_pin_cell() + + pincell.settings.particles = 100 + + # export to separate XML files and run + pincell.export_to_xml(separate_xmls=True) + openmc.run() + + # now export to a single XML file with a custom name + pincell.export_to_xml(filename='pincell.xml', separate_xmls=False) + + # run by specifying that single file + openmc.run(input_file='pincell.xml') + + # now ensure we get an error for an incorrect filename + with pytest.raises(RuntimeError): + openmc.run(input_file='ex-em-ell.xml') \ No newline at end of file