diff --git a/openmc/material.py b/openmc/material.py index 420a08521..af42e2e24 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -1449,6 +1449,41 @@ class Materials(cv.CheckedList): for material in self: material.make_isotropic_in_lab() + def _write_xml(self, file): + """Writes XML content of the materials to an open file handle. + + Parameters + ---------- + file : IOTextWrapper + Open file handle to write content into. + """ + # Write the header and the opening tag for the root element. + file.write("\n") + file.write('\n') + + # Write the element. + if self.cross_sections is not None: + element = ET.Element('cross_sections') + element.text = str(self.cross_sections) + clean_indentation(element, level=1) + element.tail = element.tail.strip(' ') + file.write(' ') + reorder_attributes(element) # TODO: Remove when support is Python 3.8+ + ET.ElementTree(element).write(file, encoding='unicode') + + # Write the elements. + for material in sorted(self, key=lambda x: x.id): + element = material.to_xml_element() + clean_indentation(element, level=1) + element.tail = element.tail.strip(' ') + file.write(' ') + reorder_attributes(element) # TODO: Remove when support is Python 3.8+ + ET.ElementTree(element).write(file, encoding='unicode') + + # Write the closing tag for the root element. + file.write('\n') + + def export_to_xml(self, path: PathLike = 'materials.xml'): """Export material collection to an XML file. @@ -1468,32 +1503,7 @@ class Materials(cv.CheckedList): # one go. with open(str(p), 'w', encoding='utf-8', errors='xmlcharrefreplace') as fh: - - # Write the header and the opening tag for the root element. - fh.write("\n") - fh.write('\n') - - # Write the element. - if self.cross_sections is not None: - element = ET.Element('cross_sections') - element.text = str(self.cross_sections) - clean_indentation(element, level=1) - element.tail = element.tail.strip(' ') - fh.write(' ') - reorder_attributes(element) # TODO: Remove when support is Python 3.8+ - ET.ElementTree(element).write(fh, encoding='unicode') - - # Write the elements. - for material in sorted(self, key=lambda x: x.id): - element = material.to_xml_element() - clean_indentation(element, level=1) - element.tail = element.tail.strip(' ') - fh.write(' ') - reorder_attributes(element) # TODO: Remove when support is Python 3.8+ - ET.ElementTree(element).write(fh, encoding='unicode') - - # Write the closing tag for the root element. - fh.write('\n') + self._write_xml(fh) @classmethod def from_xml(cls, path: PathLike = 'materials.xml'): diff --git a/openmc/model/model.py b/openmc/model/model.py index 98136b2d5..5a1b86a1f 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -5,11 +5,16 @@ import os from pathlib import Path from numbers import Integral from tempfile import NamedTemporaryFile +<<<<<<< HEAD import warnings +======= +from xml.etree import ElementTree as ET +>>>>>>> d42935a08 (Writing all main nodes to a single XML file) import h5py import openmc +import openmc._xml as xml from openmc.dummy_comm import DummyCommunicator from openmc.executor import _process_CLI_arguments from openmc.checkvalue import check_type, check_value @@ -404,7 +409,7 @@ class Model: Parameters ---------- directory : str - Directory to write XML files to. If it doesn't exist already, it + Directory to write the model.xml file to. If it doesn't exist already, it will be created. remove_surfs : bool Whether or not to remove redundant surfaces from the geometry when @@ -416,8 +421,8 @@ class Model: d = Path(directory) if not d.is_dir(): d.mkdir(parents=True) + d /= 'model.xml' - self.settings.export_to_xml(d) if remove_surfs: warnings.warn("remove_surfs kwarg will be deprecated soon, please " "set the Geometry.merge_surfaces attribute instead.") @@ -425,22 +430,33 @@ class Model: # Can be used to modify tallies in case any surfaces are redundant redundant_surfaces = self.geometry.remove_redundant_surfaces() - self.geometry.export_to_xml(d) + settings_element = self.settings.to_xml_element() + geometry_element = self.geometry.to_xml_element() # If a materials collection was specified, export it. Otherwise, look # for all materials in the geometry and use that to automatically build # a collection. if self.materials: - self.materials.export_to_xml(d) + materials = self.materials else: materials = openmc.Materials(self.geometry.get_all_materials() .values()) - materials.export_to_xml(d) - if self.tallies: - self.tallies.export_to_xml(d) - if self.plots: - self.plots.export_to_xml(d) + with open(d, 'w', encoding='utf-8', + errors='xmlcharrefreplace') as fh: + # Write the materials collection to the open XML file first. + # This will write the XML header also + materials._write_xml(fh) + # Write remaining elements as a tree + ET.ElementTree(geometry_element).write(fh, encoding='unicode') + ET.ElementTree(settings_element).write(fh, encoding='unicode') + + if self.tallies: + tallies_element = self.tallies.to_xml_element() + ET.ElementTree(tallies_element).write(fh, encoding='unicode') + if self.plots: + plots_element = self.plots.to_xml_element() + ET.ElementTree(plots_element).write(fh, encoding='unicode') def import_properties(self, filename): """Import physical properties diff --git a/openmc/settings.py b/openmc/settings.py index 29e19db2e..dd0041351 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1595,7 +1595,7 @@ class Settings: clean_indentation(element) return element - + def export_to_xml(self, path: PathLike = 'settings.xml'): """Export simulation settings to an XML file.