Skip to content

Commit

Permalink
Merge pull request #612 from idaholab/mat_docs
Browse files Browse the repository at this point in the history
Added tutorials for new material API.
  • Loading branch information
MicahGale authored Jan 22, 2025
2 parents 5275df6 + 98ff039 commit 82a059d
Show file tree
Hide file tree
Showing 12 changed files with 540 additions and 47 deletions.
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`).
* 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 @@ -76,6 +76,8 @@
"inherited-members": 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

0 comments on commit 82a059d

Please sign in to comment.