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.