Made integrator quiet and fixed failing test caused by MPICommunicator types

This commit is contained in:
agnelson 2021-09-30 14:39:53 -05:00
parent 61d067f1f5
commit b335f82792
3 changed files with 58 additions and 59 deletions

View file

@ -114,11 +114,8 @@ def global_bounding_box():
def calculate_volumes(output=True):
"""Run stochastic volume calculation"""
if output:
with quiet_dll(output):
_dll.openmc_calculate_volumes()
else:
with quiet_dll():
_dll.openmc_calculate_volumes()
def current_batch():
@ -152,11 +149,9 @@ def export_properties(filename=None, output=True):
"""
if filename is not None:
filename = c_char_p(filename.encode())
if output:
with quiet_dll(output):
_dll.openmc_properties_export(filename)
else:
with quiet_dll():
_dll.openmc_properties_export(filename)
def finalize():
@ -272,11 +267,8 @@ def init(args=None, intracomm=None, output=True):
address = MPI._addressof(intracomm)
intracomm = c_void_p(address)
if output:
with quiet_dll(output):
_dll.openmc_init(argc, argv, intracomm)
else:
with quiet_dll():
_dll.openmc_init(argc, argv, intracomm)
openmc.lib.is_initialized = True
@ -378,11 +370,8 @@ def plot_geometry(output=True):
Whether or not to show output. Defaults to showing output
"""
if output:
with quiet_dll(output):
_dll.openmc_plot_geometry()
else:
with quiet_dll():
_dll.openmc_plot_geometry()
def reset():
@ -406,11 +395,8 @@ def run(output=True):
Whether or not to show output. Defaults to showing output
"""
if output:
with quiet_dll(output):
_dll.openmc_run()
else:
with quiet_dll():
_dll.openmc_run()
def simulation_init():
@ -529,27 +515,40 @@ class _FortranObjectWithID(_FortranObject):
@contextmanager
def quiet_dll():
"""This context manager allows us to suppress standard output from DLLs"""
sys.stdout.flush()
# Save the initial file descriptor states
initial_stdout = sys.stdout
initial_stdout_fno = os.dup(sys.stdout.fileno())
# Get a garbage descriptor so we can throw away output
devnull = os.open(os.devnull, os.O_WRONLY)
def quiet_dll(output=True):
"""This context manager allows us to suppress standard output from DLLs
# Get the current stdout stream and make a duplicate of it
new_stdout = os.dup(1)
# Copy the garbage output to the stdout stream
os.dup2(devnull, 1)
os.close(devnull)
# Now point stdout to the re-defined stdout
sys.stdout = os.fdopen(new_stdout, 'w')
Parameters
----------
output : bool
Denotes whether the output should be displayed (True) or not (False)
try:
.. versionadded:: 0.13.0
"""
if output:
yield
finally:
# Now we just clean up after ourselves and reset the streams
sys.stdout = initial_stdout
else:
sys.stdout.flush()
os.dup2(initial_stdout_fno, 1)
# Save the initial file descriptor states
initial_stdout = sys.stdout
initial_stdout_fno = os.dup(sys.stdout.fileno())
# Get a garbage descriptor so we can throw away output
devnull = os.open(os.devnull, os.O_WRONLY)
# Get the current stdout stream and make a duplicate of it
new_stdout = os.dup(1)
# Copy the garbage output to the stdout stream
os.dup2(devnull, 1)
os.close(devnull)
# Now point stdout to the re-defined stdout
sys.stdout = os.fdopen(new_stdout, 'w')
try:
yield
finally:
# Now we just clean up after ourselves and reset the streams
sys.stdout = initial_stdout
sys.stdout.flush()
os.dup2(initial_stdout_fno, 1)

View file

@ -52,8 +52,6 @@ class Model:
Tallies information
plots : openmc.Plots, optional
Plot information
intracomm : mpi4py.MPI.Intracomm or None, optional
MPI intracommunicator
Attributes
----------
@ -67,8 +65,10 @@ class Model:
Tallies information
plots : openmc.Plots
Plot information
intracomm : mpi4py.MPI.Intracomm or None
MPI intracommunicator
intracomm : mpi4py.MPI.Intracomm or openmc.DummyCommunicator
MPI intracommunicator; this defaults to the mpi4py world communicator
from if present, or a DummyCommunicator otherwise. If an alternative
communicator is desired, this parameter should be modified accordingly.
"""
@ -91,7 +91,7 @@ class Model:
if plots is not None:
self.plots = plots
self.intracomm = intracomm
self.intracomm = openmc.comm
# Store dictionaries to the materials and cells by ID and names
if materials is None:
@ -191,12 +191,8 @@ class Model:
@intracomm.setter
def intracomm(self, intracomm):
if intracomm is None:
self._intracomm = openmc.comm
else:
check_type('intracomm', intracomm,
(openmc.MPI.Comm, openmc.DummyCommunicator))
self._intracomm = intracomm
check_type('intracomm', intracomm, type(openmc.comm))
self._intracomm = intracomm
@classmethod
def from_xml(cls, geometry='geometry.xml', materials='materials.xml',
@ -272,7 +268,7 @@ class Model:
if isinstance(self.intracomm, openmc.DummyCommunicator):
# openmc.lib.init does not accept DummyCommunicator, and importing
# the DummyCommunicator class is overkill. Filter it here
# the DummyCommunicator class there is overkill. Filter it here
intracomm = None
else:
intracomm = self.intracomm
@ -288,7 +284,8 @@ class Model:
openmc.lib.finalize()
def deplete(self, timesteps, method='cecm', final_step=True,
operator_kwargs=None, directory='.', **integrator_kwargs):
operator_kwargs=None, directory='.', output=True,
**integrator_kwargs):
"""Deplete model using specified timesteps/power
.. versionchanged:: 0.13.0
@ -310,6 +307,8 @@ class Model:
directory : str, optional
Directory to write XML files to. If it doesn't exist already, it
will be created. Defaults to the current working directory
output : bool
Capture OpenMC output from standard out
integrator_kwargs : dict
Remaining keyword arguments passed to the depletion Integrator
initializer (e.g., :func:`openmc.deplete.integrator.cecm`).
@ -332,8 +331,9 @@ class Model:
started_initialized = self.is_initialized
with _change_directory(Path(directory)):
depletion_operator = \
dep.Operator(self.geometry, self.settings, **op_kwargs)
with openmc.lib.quiet_dll(output):
depletion_operator = \
dep.Operator(self.geometry, self.settings, **op_kwargs)
# Tell depletion_operator.finalize NOT to clear C API memory when
# it is done
@ -347,8 +347,8 @@ class Model:
**integrator_kwargs)
# Now perform the depletion
# TODO: add output parameter to integrate
integrator.integrate(final_step)
with openmc.lib.quiet_dll(output):
integrator.integrate(final_step)
# Now make the python Materials match the C API material data
for mat_id, mat in self._materials_by_id.items():

View file

@ -481,7 +481,7 @@ def test_deplete(run_in_tmpdir, pin_model_attributes, mpi_intracomm):
# and make sure we get the same answer
test_model.deplete([1e6], 'predictor', final_step=False,
operator_kwargs=op_kwargs,
power=1.)
power=1., output=False)
# Get the new Xe136 and U235 atom densities
after_xe = mats[0].get_nuclide_atom_densities()['Xe136'][1]
after_u = mats[0].get_nuclide_atom_densities()['U235'][1]
@ -501,7 +501,7 @@ def test_deplete(run_in_tmpdir, pin_model_attributes, mpi_intracomm):
test_model.init_lib(output=False)
test_model.deplete([1e6], 'predictor', final_step=False,
operator_kwargs=op_kwargs,
power=1.)
power=1., output=False)
# Get the new Xe136 and U235 atom densities
after_lib_xe = mats[0].get_nuclide_atom_densities()['Xe136'][1]
after_lib_u = mats[0].get_nuclide_atom_densities()['U235'][1]