Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ MontePy Changelog
#Next Version#
--------------

**Features Added**

* Allow clearing default libraries by assigning ``None`` at material and problem scopes; unset values are omitted from serialization.

**Features Added**

Expand Down
43 changes: 40 additions & 3 deletions montepy/data_inputs/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,37 @@ def __getitem__(self, key):
except KeyError:
return None

def update(self, other=None, **kwargs):
"""Update the default libraries with the key/value pairs from other, overwriting existing keys.

Parameters
----------
other : dict or dict-like
Another dict or dict-like object to update from
**kwargs
Additional key-value pairs to update
"""
if other is not None:
if hasattr(other, "items"):
for key, value in other.items():
self[key] = value
else:
for key, value in other:
self[key] = value
for key, value in kwargs.items():
self[key] = value

def __setitem__(self, key, value):
key = self._validate_key(key)
if value is None:
# Setting to None means unset/delete the library
try:
del self[key]
except KeyError:
pass # Already unset, nothing to do
return
if not isinstance(value, (Library, str)):
raise TypeError(
f"Value must be a library or str. {value} of type: {type(value).__name__} given."
)
raise TypeError("Default library value must be a Library, str, or None")
if isinstance(value, str):
value = Library(value)
try:
Expand Down Expand Up @@ -252,16 +277,22 @@ class Material(data_input.DataInputAbstract, Numbered_MCNP_Object):
:func:`~montepy.data_inputs.material.Material.default_libraries` acts like a dictionary,
and can accept a string or a :class:`~montepy.particle.LibraryType` as keys.

To clear a default library, assign ``None``:

.. testcode::

print(mat.default_libraries["plib"])
mat.default_libraries[montepy.LibraryType.NEUTRON] = "00c"
print(mat.default_libraries["nlib"])
# Clear/unset the plib default
mat.default_libraries["plib"] = None
print(mat.default_libraries["plib"])

.. testoutput::

80p
00c
None

See Also
--------
Expand Down Expand Up @@ -437,16 +468,22 @@ def default_libraries(self):
:func:`~montepy.data_inputs.material.Material.default_libraries` acts like a dictionary,
and can accept a string or a :class:`~montepy.particle.LibraryType` as keys.

To clear a default library, assign ``None``:

.. testcode::

print(mat.default_libraries["plib"])
mat.default_libraries[montepy.LibraryType.NEUTRON] = "00c"
print(mat.default_libraries["nlib"])
# Clear/unset the plib default
mat.default_libraries["plib"] = None
print(mat.default_libraries["plib"])

.. testoutput::

None
00c
None

.. versionadded:: 1.0.0

Expand Down
4 changes: 3 additions & 1 deletion montepy/materials.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def default_libraries(self) -> dict[montepy.LibraryType, montepy.Library]:
^^^^^^^^

To set the default libraries for a problem you need to set this dictionary
to a Library or string.
to a Library or string. To clear a default library, assign ``None``.

.. testcode:: python

Expand All @@ -229,6 +229,8 @@ def default_libraries(self) -> dict[montepy.LibraryType, montepy.Library]:
problem.materials.default_libraries["nlib"] = "00c"
# set photo-atomic
problem.materials.default_libraries[montepy.LibraryType.PHOTO_ATOMIC] = montepy.Library("80p")
# clear/unset neutron default
problem.materials.default_libraries["nlib"] = None

.. versionadded:: 1.0.0

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ authors = [
{name = "Brenna Carbno", email="[email protected]"},
{name = "Benjaminas Marcinkevicius", email="[email protected]"},
{name = "Paul Ferney", email="[email protected]"},
{name = "Vikranth Udandarao", email="[email protected]"},
{name = "Digvijay Yeware", email="[email protected]"}
]
keywords = ["MCNP", "neutronics", "imcnp", "input file", "monte carlo", "radiation transport"]
Expand Down
27 changes: 27 additions & 0 deletions tests/test_material.py
Original file line number Diff line number Diff line change
Expand Up @@ -877,3 +877,30 @@ def test_bad_set_get(_, dl):

def test_dl_str(_, dl):
str(dl)

def test_default_libraries_none_setting(_, dl):
"""Test that setting default libraries to None unsets them."""
# Set a library first
dl["plib"] = "80p"
assert dl["plib"] == Library("80p")

# Set to None to unset
dl["plib"] = None
assert dl["plib"] is None

# Setting None on unset library should not error
dl["nlib"] = None
assert dl["nlib"] is None

# Test with enum keys
dl[LibraryType.PHOTO_ATOMIC] = "90p"
assert dl["plib"] == Library("90p")
dl[LibraryType.PHOTO_ATOMIC] = None
assert dl["plib"] is None

# Test update method with None
dl["nlib"] = "00c"
dl["plib"] = "80p"
dl.update({"plib": None})
assert dl["plib"] is None
assert dl["nlib"] == Library("00c")