Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added tutorials for new material API. #612

Merged
merged 20 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
1 change: 0 additions & 1 deletion doc/source/api/montepy.particle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ montepy.particle module

.. automodule:: montepy.particle
:members:
:inherited-members:
:undoc-members:
:show-inheritance:
1 change: 0 additions & 1 deletion doc/source/api/montepy.surfaces.surface_type.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ montepy.surfaces.surface\_type module

.. automodule:: montepy.surfaces.surface_type
:members:
:inherited-members:
:undoc-members:
:show-inheritance:
2 changes: 1 addition & 1 deletion doc/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ MontePy Changelog
**Features Added**

* Redesigned how Materials hold Material_Components. See :ref:`migrate 0 1` (:pull:`507`).
* Made it easier to create an Isotope, or now Nuclide: ``montepy.Nuclide("H-1.80c")`` (:issue:`505`).
* Made it easier to create an Isotope (now Nuclide): ``montepy.Nuclide("H-1.80c")`` (:issue:`505`).
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clever way to get the green check. I like it.

* When a typo in an object attribute is made an Error is raised rather than silently having no effect (:issue:`508`).
* Improved material printing to avoid very long lists of components (:issue:`144`).
* Allow querying for materials by components (:issue:`95`).
Expand Down
2 changes: 2 additions & 0 deletions doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
# Display the version
display_version = True

linkcheck_ignore = ["https://nucleardata.lanl.gov/.*"]

# -- External link configuration ---------------------------------------------
UM63 = (
"https://mcnp.lanl.gov/pdf_files/TechReport_2022_LANL_LA-UR-22-30006"
Expand Down
7 changes: 7 additions & 0 deletions doc/source/dev_standards.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ Design Philosophy
#. Defer to vanilla python, and only use the standard library. Currently the only dependencies are `numpy <https://numpy.org/>`_ and `sly <https://github.com/dabeaz/sly>`_.
There must be good justification for breaking from this convention and complicating things for the user.

Style Guide
-----------

#. Thou shall be `PEP 8 <https://peps.python.org/pep-0008/>`_, and use `black <https://black.readthedocs.io/en/stable/index.html>`_.
#. Spaces not tabs with 4 spaces for an indent.
#. External imports before internal imports with a blank line in between. All imports are alphabetized.

Doc Strings
-----------

Expand Down
15 changes: 15 additions & 0 deletions doc/source/developing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -690,3 +690,18 @@ Users are more like to use this dynamic code.
In general this philosophy is: if it's not the source of truth,
it should be a generator.

Constants and Meta Data Structures
----------------------------------

MontePy uses constants and data structures to utilize meta-programming
and remove redundant code.
Typical constants can be found in :mod:`montepy.constants`.

Here are the other data structures to be aware of:

* :class:`~montepy.mcnp_problem.MCNP_Problem` ``_NUMBERED_OBJ_MAP``: maps a based numbered object to its collection
class. This is used for loading all problem numbered object collections in an instance.
* :func:`montepy.data_inputs.data_parser.PREFIX_MATCHES` is a set of the data object classes. The prefix is taken from
the classes. A data object must be a member of this class for it to automatically parse new data objects.
* :class:`~montepy.cell.Cell` ``_INPUTS_TO_PROPERTY`` maps a cell modifier class to the attribute to load it into for a
cell. The boolean is whether multiple input instances are allowed.
186 changes: 163 additions & 23 deletions doc/source/migrations/migrate0_1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,43 +21,47 @@ and can be advantageous.
See :issue:`504` for more details.
Due to this it was decided that the best way forward was to abandon the old design,
and to create a brand new data structure.
This means that backwards compatibility *will* be broken,
and so this fix is leading to a major version release.
This means that backwards compatibility *was* broken,
and so this fix led to a major version release.


Deprecations
------------
The following properties and objects are currently deprecated,
and will be removed in MontePy 1.0.0.
The following properties and objects are currently deprecated
and were removed in MontePy 1.0.0.

* :func:`montepy.data_inputs.material.Material.material_components`.
* :func:`~montepy.data_inputs.material.Material.material_components`.
This is the dictionary that caused this design problem.

* :class:`montepy.data_inputs.material_components.MaterialComponents`
This is the class that stores information in the above dictionary.
It is largely excess object wrapping, that makes the material interface
* :class:`~montepy.data_inputs.material_component.MaterialComponent`:
This was the class that stores information in the above dictionary.
It was largely excess object wrapping that made the material interface
overly complex.

* :class:`montepy.data_inputs.Isotope` will be renamed to ``Nuclide``.
This is to better align with MCNP documentation,
and better reflect that the nuclear data for a nuclide can represent
* :class:`~montepy.data_inputs.isotope.Isotope` was renamed to :class:`~montepy.data_inputs.nuclide.Nuclide`.
This is to better align with MCNP documentation
and to better reflect that the nuclear data for a nuclide can represent
isotopic, isomeric, or atomic data.


New Interface & Migration
-------------------------

For more details, see the new :ref:`mat_tutorial` tutorial in the getting started guide,
as well as the example in the :class:`~montepy.data_inputs.material.Material` documentation.

.. note::

This design is not finalized and is subject to change.
This is the currently planned design for ``1.0.0a1``.
If you have input you can `join the discussion <https://github.com/idaholab/MontePy/discussions/475>`_.
This is also where alpha-testing will be announced.
For feedback on the alpha test, please `join this discussion <https://github.com/idaholab/MontePy/discussions/604>`_.

``material_components`` removal
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Material composition data has moved from ``Material.material_components`` to the ``Material`` itself.
Material composition data has moved from ``Material.material_components`` to the
:class:`~montepy.data_inputs.material.Material` itself.
``Material`` is now a list-like iterable.
It is a list of tuples which are ``(nuclide, fraction)`` pairs.

Expand All @@ -76,37 +80,173 @@ Searching Components
^^^^^^^^^^^^^^^^^^^^

Finding a specific ``Nuclide`` in a ``Material`` is now much easier.
First there will be a ``Material.find`` method that takes either a ``Nuclide`` string,
First, there is a :func:`~montepy.data_inputs.material.Material.find` method that takes either a ``Nuclide`` string,
or various over search criteria (e.g., ``element``),
and creates a generator of all matching component tuples.

If you want to check if a ``Material`` contains a specific ``Nuclide``
you can simply test ``nuclide in material``.
The ``Material.contains`` function will provide more options,
such as setting a minimum threshold, and testing for multiple nuclides at once.
The :func:`~montepy.data_inputs.material.Material.contains` function will provide more options,
such as setting a minimum threshold and testing for multiple nuclides at once.

Adding Nuclides
^^^^^^^^^^^^^^^
Adding a new nuclide will be easiest with the ``add_nuclide`` function.

Editing Nuclide Compositon
^^^^^^^^^^^^^^^^^^^^^^^^^^
Adding a new nuclide is easiest with the :func:`~montepy.data_inputs.material.Material.add_nuclide` function.

Editing Nuclide Composition
^^^^^^^^^^^^^^^^^^^^^^^^^^^

Editing a material composition will be very similar to editing a ``list``.
Existing components can be set to a nuclide component nuclide.
Also existing components can be deleted with ``del``.
For just editing the fractions or nuclides the functions:
:func:`~montepy.data_inputs.material.Material.nuclides`
and :func:`~montepy.data_inputs.material.Material.values` provide the easiest interface.


``Isotope`` Deprecation and Removal
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The decision was made to remove the name ``Isotope``.
The decision was made to remove the name :class:`montepy.data_inputs.isotope.Isotope`.
This is because not all material components are an isotope,
they may be an isomer, or event an element.
Rather the MCNP generalized terminology of ``Nuclide`` was adopted.
Rather the MCNP generalized terminology of :class:`montepy.data_inputs.nuclide.Nuclide` was adopted.
The idea of a specific nuclide, e.g., ``H-1`` was separated from an
MCNP material component e.g., ``1001.80c``.
The actual ``Nuclide`` information was moved to a new class: ``Nucleus``,
The actual ``Nuclide`` information was moved to a new class: :class:`~montepy.data_inputs.nuclide.Nucleus`
that is immutable.
The ``Nuclide`` wraps this and adds a ``Library`` object to specify the nuclear data that is used.
The :class:`~montepy.data_inputs.nuclide.Nuclide` wraps this and adds a :class:`~montepy.data_inputs.nuclide.Library` object to specify the nuclear data that is used.
It makes sense to be able to change a library.
It does not make sense to change the intrinsic properties of a nuclide (i.e., ``Z``, ``A``, etc.).


Code Comparison between 0.x and 1.x
-----------------------------------

Here are some example code blocks of various material operations in both versions.

Iterating over Material Components
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In MontePy 0.x
""""""""""""""

.. testcode::
:skipif: True

import montepy
problem = montepy.read_input("foo.imcnp")
mat = problem.materials[1]
for component in mat.material_components.values():
print(component.fraction, component.isotope)

This would print:

.. testoutput::

2.0 H-1 (80c)
1.0 O-16 (80c)

In MontePy 1.x
""""""""""""""

.. testcode::

import montepy
problem = montepy.read_input("foo.imcnp")
mat = problem.materials[1]
for nuclide, fraction in mat:
print(fraction, nuclide)

Would print:

.. testoutput::

2.0 H-1 (80c)
1.0 O-16 (80c)

Adding Material Components
^^^^^^^^^^^^^^^^^^^^^^^^^^

Appending and editing the material components in a material in MontePy 0.x
was rather clunky. That was a large part of the motivation for this release.

In MontePy 0.x
""""""""""""""
.. testcode::
:skipif: True

from montepy.data_inputs.isotope import Isotope
from montepy.data_inputs.material_component import MaterialComponent
#construct new isotope
new_isotope = Isotope("5010.80c")
# construct new component
comp = MaterialComponent(new_isotope, 1e-6)
# add actual component to material
mat.material_components[new_isotope] = comp

In MontePy 1.x
""""""""""""""

.. testcode::

mat.add_nuclide("B-10.80c", 1e-6)


Finding, Editing, and Deleting a Component
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Accessing a specific component is another reason for this release.
As you may have noticed, ``material_components`` is a dictionary with the keys being an ``Isotope``.
Due to a bug in MontePy 0.x, the exact instance of an Isotope must be passed as the key to access that item.

In MontePy 0.x
""""""""""""""

.. testcode::
:skipif: True

target_isotope = Isotope("5010.80c")
key = None
for isotope in mat.material_components:
if isotope.element == target_isotope.element and isotope.A == target_isotope.A:
key = isotope
break
# get material component object
comp = mat[key]
# edit it. This will update the material because everything is a pointer
comp.fraction = 2e-6
# delete the component
del mat[key]


In MontePy 1.x
""""""""""""""

.. testcode::

target_isotope = montepy.Nuclide("B-10.80c")
for comp_idx, (nuc, fraction) in mat.find(target_isotope):
break
# update fraction
mat.values[comp_idx] = 2e-6
# delete component
del mat[comp_idx]

















Loading
Loading