diff --git a/include/openmc/initialize.h b/include/openmc/initialize.h index d3d12d45df..5caccceda6 100644 --- a/include/openmc/initialize.h +++ b/include/openmc/initialize.h @@ -11,8 +11,12 @@ int parse_command_line(int argc, char* argv[]); #ifdef OPENMC_MPI void initialize_mpi(MPI_Comm intracomm); #endif + +//! Read material, geometry, settings, and tallies from a single XML file bool read_model_xml(); -void read_input_xml(); +//! Read inputs from separate XML files +void read_separate_xml_files(); +//! Write some output that occurs right after initialization void initial_output(); } // namespace openmc diff --git a/openmc/geometry.py b/openmc/geometry.py index 630106628d..d036df9c74 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -256,9 +256,9 @@ class Geometry: ---------- path : str, optional Path to geometry XML file - materials : dict - Dictionary mapping material ID strings to :class:`openmc.Material` - instances (defined in :math:`openmc.Geometry.from_xml`) + materials : openmc.Materials or None + Materials used to assign to cells. If None, an attempt is made to + generate it from the materials.xml file. Returns ------- diff --git a/openmc/model/model.py b/openmc/model/model.py index 559def5702..2ed9bf668a 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -205,8 +205,24 @@ class Model: self._plots.append(plot) @classmethod - def from_xml(cls, *args, separate_xmls=True, **kwargs): - if separate_xmls: + def from_xml(cls, *args, path='model.xml', separate_xmls=True, **kwargs): + """Generate geometry from XML file + + Parameters + ---------- + path : str, optional + Path to model XML file + separate_xmls : bool + Whether or not to read from a single or separate XML files + + Returns + ------- + openmc.Geometry + Geometry object + + """ + + if separate_xmls or not Path(path).exists(): return cls.from_separate_xmls(*args, **kwargs) else: return cls.from_model_xml(*args, **kwargs) @@ -228,7 +244,7 @@ class Model: model.settings = openmc.Settings.from_xml_element(root.find('settings')) model.materials = openmc.Materials.from_xml_element(root.find('materials')) materials = {str(m.id): m for m in model.materials} - model.geometry = .Geometry.from_xml_element(root.find('geometry'), materials) + model.geometry = openmc.Geometry.from_xml_element(root.find('geometry'), materials) # gather meshses from other classes before reading the tally node meshes = {} @@ -442,8 +458,8 @@ class Model: depletion_operator.cleanup_when_done = True depletion_operator.finalize() - def export_to_xml(self, directory='.', remove_surfs=False, separate_xmls=True): - """Export model to separate XML files. + def export_to_xml(self, directory='.', remove_surfs=False, separate_xmls=True, filename='model.xml'): + """Export model to an XML file(s). Parameters ---------- @@ -453,6 +469,8 @@ class Model: remove_surfs : bool Whether or not to remove redundant surfaces from the geometry when exporting. + filename : str + Name of the single XML file to create (only used :math:`separate_xmls` if False) .. versionadded:: 0.13.1 @@ -460,11 +478,15 @@ class Model: Whether or not to write a single model.xml file or many XML files. """ if separate_xmls: - self.export_to_separate_xmls(directory, remove_surfs) + if filename != 'model.xml': + warnings.warn('Export filename parameter {filename} is ignored ' + 'because the model is being written to separate XML files.') + self._export_to_separate_xmls(directory, remove_surfs) else: - self.export_to_single_xml(directory, remove_surfs) + filename = Path(directory) / Path(filename) + self._export_to_single_xml(filename, remove_surfs) - def export_to_separate_xmls(self, directory='.', remove_surfs=False): + def _export_to_separate_xmls(self, directory='.', remove_surfs=False): """Export model to separate XML files. Parameters @@ -501,7 +523,7 @@ class Model: if self.plots: self.plots.export_to_xml(d) - def export_to_single_xml(self, directory='.', remove_surfs=False): + def _export_to_single_xml(self, path='model.xml', remove_surfs=False): """Export model to XML files. Parameters @@ -516,10 +538,9 @@ class Model: .. versionadded:: 0.13.1 """ # Create directory if required - d = Path(directory) - if not d.is_dir(): - d.mkdir(parents=True) - d /= 'model.xml' + xml_path = Path(path) + if not xml_path.parent.exists: + raise RuntimeError(f'The directory "{xml_path}" does not exist.') if remove_surfs: warnings.warn("remove_surfs kwarg will be deprecated soon, please " @@ -541,7 +562,7 @@ class Model: materials = openmc.Materials(self.geometry.get_all_materials() .values()) - with open(d, 'w', encoding='utf-8', errors='xmlcharrefreplace') as fh: + with open(xml_path, 'w', encoding='utf-8', errors='xmlcharrefreplace') as fh: # write the XML header fh.write("\n") fh.write("\n") diff --git a/openmc/plots.py b/openmc/plots.py index b1f1927876..0a04516259 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -911,6 +911,12 @@ class Plots(cv.CheckedList): def to_xml_element(self): """Create a 'plots' element to be written to an XML file. + + Returns + ------- + element : xml.etree.ElementTree.Element + XML element containing all plot elements + """ # Reset xml element tree self._plots_file.clear() diff --git a/src/initialize.cpp b/src/initialize.cpp index 3f6e69ecde..dc5c0c3c11 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -106,7 +106,7 @@ int openmc_init(int argc, char* argv[], const void* intracomm) openmc::openmc_set_seed(DEFAULT_SEED); // Read XML input files - if (!read_model_xml()) read_input_xml(); + if (!read_model_xml()) read_separate_xml_files(); // Write some initial output under the header if needed initial_output(); @@ -371,7 +371,7 @@ bool read_model_xml() { return true; } -void read_input_xml() +void read_separate_xml_files() { read_settings_xml(); read_cross_sections_xml(); diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index 928bf0715f..87557ddc53 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -530,21 +530,20 @@ def test_calc_volumes(run_in_tmpdir, pin_model_attributes, mpi_intracomm): test_model.finalize_lib() -def test_model_xml(): +def test_model_xml(run_in_tmpdir): - with cdtemp(): - # load a model from examples - pwr_model = openmc.examples.pwr_core() + # load a model from examples + pwr_model = openmc.examples.pwr_core() - # export to separate XMLs manually - pwr_model.settings.export_to_xml('settings_ref.xml') - pwr_model.materials.export_to_xml('materials_ref.xml') - pwr_model.geometry.export_to_xml('geometry_ref.xml') + # export to separate XMLs manually + pwr_model.settings.export_to_xml('settings_ref.xml') + pwr_model.materials.export_to_xml('materials_ref.xml') + pwr_model.geometry.export_to_xml('geometry_ref.xml') - # now write and read a model.xml file - pwr_model.export_to_xml(separate_xmls=False) - new_model = openmc.Model.from_xml(separate_xmls=False) + # now write and read a model.xml file + pwr_model.export_to_xml(separate_xmls=False) + new_model = openmc.Model.from_xml(separate_xmls=False) - # make sure we can also export this again to separate - # XML files - new_model.export_to_xml(separate_xmls=True) \ No newline at end of file + # make sure we can also export this again to separate + # XML files + new_model.export_to_xml(separate_xmls=True) \ No newline at end of file