montepy.data_inputs.material module#
Classes:
|
A class to represent an MCNP material. |
Data:
The default number of spaces to indent on a new line by. |
|
The maximum number of elements to print in a material string descripton. |
- class montepy.data_inputs.material.Material(input: Input | str = None, number: int = None)#
Bases:
DataInputAbstract
,Numbered_MCNP_Object
A class to represent an MCNP material.
Examples
First it might be useful to load an example problem:
import montepy problem = montepy.read_input("foo.imcnp") mat = problem.materials[1] print(mat)
MATERIAL: 1, ['hydrogen', 'oxygen']
Materials are iterable#
Materials look like a list of tuples, and is iterable. Whether or not the material is defined in mass fraction or atom fraction is stored for the whole material in
is_atom_fraction()
. The fractions (atom or mass) of the componenets are always positive, because MontePy believes in physics.assert mat.is_atom_fraction # ensures it is in atom_fraction for nuclide, fraction in mat: print("nuclide", nuclide, fraction)
This would display:
nuclide H-1 (80c) 2.0 nuclide O-16 (80c) 1.0
As a list, Materials can be indexed:
oxygen, ox_frac = mat[1] mat[1] = (oxygen, ox_frac + 1e-6) del mat[1]
If you need just the nuclides or just the fractions of components in this material see:
nuclides()
andvalues()
.You can check if a Nuclide is in a Material#
You can check if a
Nuclide
orElement
is in a Material within
.>>> montepy.Nuclide("H-1") in mat True >>> "H-1" in mat True >>> montepy.Element(1) in mat True >>> montepy.Element(92) in mat False
Add New Component#
The easiest way to add new components to a material is with
add_nuclide()
.# add boric acid to water boric_acid_frac = 1e-6 mat[0] # Add by nuclide object mat.add_nuclide(oxygen, ox_frac + 3 * boric_acid_frac) # add by nuclide Name or ZAID mat.add_nuclide("B-10.80c", 1e-6) print(mat)
MATERIAL: 1, ['hydrogen', 'oxygen', 'boron']
Default Libraries#
Also materials have the concept of
default_libraries()
. These are the libraries set byNLIB
,PLIB
, etc., which are used when a library of the correctLibraryType
is not provided with the nuclide.default_libraries()
acts like a dictionary, and can accept a string or aLibraryType
as keys.print(mat.default_libraries["plib"]) mat.default_libraries[montepy.LibraryType.NEUTRON] = "00c" print(mat.default_libraries["nlib"])
80p 00c
Changed in version 1.0.0:
Added number parameter to constructor.
- This was the primary change for this release. For more details on what changed see Migration plan for MontePy 1.0.0.
Switched to list-like data-structure
Added ability to search by Nuclide
Added Support for default libraries (e.g.,
nlib=80c
).
- type input:
Union
[Input
,str
]- param input:
The Input syntax object this will wrap and parse.
- type input:
Union[Input, str]
- type number:
int
- param number:
The number to set for this object.
- type number:
int
Methods:
add_nuclide
(nuclide, fraction)Add a new component to this material of the given nuclide, and fraction.
Adds thermal scattering law to the material
append
(nuclide_frac_pair)Appends the tuple to this material.
change_libraries
(new_library)Change the library for all nuclides in the material.
clear
()Clears all nuclide components from this material.
clone
([starting_number, step])Create a new independent instance of this object with a new number.
contains_all
(*nuclides[, threshold, strict])Checks if this material contains of all of the given nuclides.
contains_any
(*nuclides[, threshold, strict])Checks if this material contains any of the given nuclide.
find
([name, element, A, meta_state, ...])Finds all components that meet the given criteria.
find_vals
([name, element, A, meta_state, ...])A wrapper for
find()
that only returns the fractions of the components.format_for_mcnp_input
(mcnp_version)Creates a list of strings representing this MCNP_Object that can be written to file.
Get the elements that are contained in this material.
get_nuclide_library
(nuclide, library_type)Figures out which nuclear data library will be used for the given nuclide in this given material in this given problem.
link_to_problem
(problem)Links the input to the parent problem for this input.
mcnp_str
([mcnp_version])Returns a string of this input as it would appear in an MCNP input file.
Normalizes the components fractions so that they sum to 1.0.
update_pointers
(data_inputs)Updates pointer to the thermal scattering data
validate
()Validates that the object is in a usable state.
wrap_string_for_mcnp
(string, mcnp_version, ...)Wraps the list of the words to be a well formed MCNP input.
Attributes:
A generator of the cells that use this material.
The syntax tree object holding the data classifier.
The comments associated with this input if any.
The syntax tree actually holding the data.
The default libraries that are used when a nuclide doesn't have a relevant library specified.
If true this constituent is in atom fraction, not weight fraction.
Any comments that come before the beginning of the input proper.
The internal dictionary containing all the components of this material.
Get just the fractions, or values from this material.
The current number of the object that will be written out to a new input.
The material number that was used in the read file
A dictionary of the additional parameters for the object.
The particle class part of the input identifier as a parsed list.
The text part of the input identifier parsed from the input.
The modifier to a name prefix that was parsed from the input.
The thermal scattering law for this material
The trailing comments and padding of an input.
Get just the fractions, or values from this material.
- static wrap_string_for_mcnp(string, mcnp_version, is_first_line, suppress_blank_end=True) list[str] #
Wraps the list of the words to be a well formed MCNP input.
multi-line inputs will be handled by using the indentation format, and not the “&” method.
- Parameters:
string (str) – A long string with new lines in it, that needs to be chunked appropriately for MCNP inputs
mcnp_version (tuple) – the tuple for the MCNP that must be formatted for.
is_first_line (bool) – If true this will be the beginning of an MCNP input. The first line will not be indented.
suppress_blank_end (bool) – Whether or not to suppress any blank lines that would be added to the end. Good for anywhere but cell modifiers in the cell block.
- Returns:
A list of strings that can be written to an input file, one item to a line.
- Return type:
list
- add_nuclide(nuclide: Nuclide | Nucleus | Element | str | Integral, fraction: float)#
Add a new component to this material of the given nuclide, and fraction.
Added in version 1.0.0.
- Parameters:
nuclide (Nuclide, str, int) – The nuclide to add, which can be a string Identifier, or ZAID.
fraction (float) – the fraction of this component being added.
- add_thermal_scattering(law)#
Adds thermal scattering law to the material
- Parameters:
law (str) – the law that is mcnp formatted
- append(nuclide_frac_pair: tuple[Nuclide, float])#
Appends the tuple to this material.
Added in version 1.0.0.
- Parameters:
nuclide_frac_pair (tuple[Nuclide, float]) – a tuple of the nuclide and the fraction to add.
- change_libraries(new_library: str | Library)#
Change the library for all nuclides in the material.
Added in version 1.0.0.
- Parameters:
new_library (Union[str, Library]) – the new library to set all Nuclides to use.
- clear()#
Clears all nuclide components from this material.
Added in version 1.0.0.
- clone(starting_number=None, step=None)#
Create a new independent instance of this object with a new number.
This relies mostly on
copy.deepcopy
.Notes
If starting_number, or step are not specified
starting_number()
, andstep()
are used as default values, if this object is tied to a problem. For instance aMaterial
will useproblem.materials
default information. Otherwise1
will be used as default valuesAdded in version 0.5.0.
- Parameters:
starting_number (int) – The starting number to request for a new object number.
step (int) – the step size to use to find a new valid number.
- Returns:
a cloned copy of this object.
- Return type:
type(self)
- contains_all(*nuclides: Nuclide | Nucleus | Element | str | Integral, threshold: float = 0.0, strict: bool = False) bool #
Checks if this material contains of all of the given nuclides.
A boolean “and” is used for this comparison. That is this material must contain all nuclides at or above the given threshold in order to return true.
Examples
import montepy problem = montepy.read_input("tests/inputs/test.imcnp") # try to find LEU materials for mat in problem.materials: if mat.contains_all("U-235", threshold=0.02): # your code here pass # try to find a uranium for mat in problem.materials: if mat.contains_all("U"): pass
Notes
The difference between
contains_all()
andcontains_any()
is only for how they handle being given multiple nuclides. This does not impact how given Elements will match daughter Nuclides. This is handled instead bystrict
.Notes
For details on how to use the
strict
argument see the examples in:find()
.Added in version 1.0.0.
- Parameters:
*nuclides (Union[Nuclide, Nucleus, Element, str, int]) – a plurality of nuclides to check for.
threshold (float) – the minimum concentration of a nuclide to be considered. The material components are not first normalized.
strict (bool) – If True this does not let an elemental nuclide match all child isotopes, isomers, nor will an isotope match all isomers, nor will a blank library match all libraries.
- Returns:
whether or not this material contains all components given above the threshold.
- Return type:
bool
- Raises:
TypeError – if any argument is of the wrong type.
ValueError – if the fraction is not positive or zero, or if nuclide cannot be interpreted as a Nuclide.
- contains_any(*nuclides: Nuclide | Nucleus | Element | str | Integral, threshold: float = 0.0, strict: bool = False) bool #
Checks if this material contains any of the given nuclide.
A boolean “or” is used for this comparison. That is, this material must contain any nuclides at or above the given threshold in order to return true.
Examples
import montepy problem = montepy.read_input("tests/inputs/test.imcnp") # try to find any fissile materials for mat in problem.materials: if mat.contains_any("U-235", "U-233", "Pu-239", threshold=1e-6): pass
Notes
For details on how to use the
strict
argument see the examples in:find()
.Added in version 1.0.0.
- Parameters:
*nuclides (Union[Nuclide, Nucleus, Element, str, int]) – a plurality of nuclides to check for.
threshold (float) – the minimum concentration of a nuclide to be considered. The material components are not first normalized.
strict (bool) – If True this does not let an elemental nuclide match all child isotopes, isomers, nor will an isotope match all isomers, nor will a blank library match all libraries.
- Returns:
whether or not this material contains all components given above the threshold.
- Return type:
bool
- Raises:
TypeError – if any argument is of the wrong type.
ValueError – if the fraction is not positive or zero, or if nuclide cannot be interpreted as a Nuclide.
- find(name: str = None, element: Element | str | Integral | slice = None, A: int | slice = None, meta_state: int | slice = None, library: str | slice = None, strict: bool = False) Generator[tuple[int, tuple[Nuclide, float]]] #
Finds all components that meet the given criteria.
The criteria are additive, and a component must match all criteria. That is the boolean and operator is used. Slices can be specified at most levels allowing to search by a range of values. For numerical quantities slices are rather intuitive, and follow the same rules that list indices do. For elements slices are by Z number only. For the library the slicing is done using string comparisons.
Examples
import montepy mat = montepy.Material() mat.number = 1 # make non-sense material for nuclide in ["U-235.80c", "U-238.70c", "Pu-239.00c", "O-16.00c", "C-0", "C-12.00c", "Fe-56"]: mat.add_nuclide(nuclide, 0.1) print("Get all uranium nuclides.") print(list(mat.find(element = "U"))) print("Get all transuranics") print(list(mat.find(element = slice(92, 100)))) print("Get all ENDF/B-VIII.0") print(list(mat.find(library = slice("00c", "09c"))))
This would print:
Get all uranium nuclides. [(0, (Nuclide('U-235.80c'), 0.1)), (1, (Nuclide('U-238.70c'), 0.1))] Get all transuranics [(0, (Nuclide('U-235.80c'), 0.1)), (1, (Nuclide('U-238.70c'), 0.1)), (2, (Nuclide('Pu-239.00c'), 0.1))] Get all ENDF/B-VIII.0 [(2, (Nuclide('Pu-239.00c'), 0.1)), (3, (Nuclide('O-16.00c'), 0.1)), (5, (Nuclide('C-12.00c'), 0.1))]
Strict (Explicit) Matching#
Generally this functions treats ambiguity implicitly, and will match as many nuclides as possible. This is generally useful, but not always. By default when only an element is given all daughter nuclides match, as seen above. However, MCNP does provide some “natural” or “elemental” nuclear data, and it would be helpful to find these sometimes. For instance, you may want to find all instances of elemental nuclides, and replace them with explicit isotopes (for instance migrating from ENDF/B-VII.1 to ENDF/B-VIII). In these cases the
strict
argument is needed. Whenstrict
is True an ambiguousA
will only match elemental data:print("Strict: False", list(mat.find(element="C"))) print("Strict: True", list(mat.find(element="C", strict=True)))
will print:
Strict: False [(4, (Nuclide('C-0'), 0.1)), (5, (Nuclide('C-12.00c'), 0.1))] Strict: True [(4, (Nuclide('C-0'), 0.1))]
Similarly to find nuclides with no library defined you can use strict:
print("Strict: False", list(mat.find(library=None))) print("Strict: True", list(mat.find(library=None, strict=True)))
This would print:
Strict: False [(0, (Nuclide('U-235.80c'), 0.1)), (1, (Nuclide('U-238.70c'), 0.1)), (2, (Nuclide('Pu-239.00c'), 0.1)), (3, (Nuclide('O-16.00c'), 0.1)), (4, (Nuclide('C-0'), 0.1)), (5, (Nuclide('C-12.00c'), 0.1)), (6, (Nuclide('Fe-56'), 0.1))] Strict: True [(4, (Nuclide('C-0'), 0.1)), (6, (Nuclide('Fe-56'), 0.1))]
Added in version 1.0.0.
- type name:
- param name:
The name to pass to Nuclide to search by a specific Nuclide. If an element name is passed this will only match elemental nuclides.
- type name:
str
- type element:
- param element:
the element to filter by, slices must be slices of integers. This will match all nuclides that are based on this element. e.g., “U” will match U-235 and U-238.
- type element:
Element, str, int, slice
- type A:
- param A:
the filter for the nuclide A number.
- type A:
int, slice
- type meta_state:
- param meta_state:
the metastable isomer filter.
- type meta_state:
int, slice
- type library:
- param library:
the libraries to limit the search to.
- type library:
str, slice
- type strict:
- param strict:
When true this will strictly match elements as only elements (when no A is given), and only match blank libraries when no library is given.
- type strict:
bool
- returns:
a generator of all matching nuclides, as their index and then a tuple of their nuclide, and fraction pairs that match.
- rtype:
Generator[tuple[int, tuple[Nuclide, float]]]
- find_vals(name: str = None, element: Element | str | int | slice = None, A: int | slice = None, meta_state: int | slice = None, library: str | slice = None, strict: bool = False) Generator[float] #
A wrapper for
find()
that only returns the fractions of the components.For more examples see that function.
Examples
import montepy mat = montepy.Material() mat.number = 1 # make non-sense material for nuclide in ["U-235.80c", "U-238.70c", "Pu-239.00c", "O-16.00c"]: mat.add_nuclide(nuclide, 0.1) # get fraction that is uranium print(sum(mat.find_vals(element= "U")))
which would intuitively print:
0.2
Added in version 1.0.0.
- Parameters:
name (str) – The name to pass to Nuclide to search by a specific Nuclide. If an element name is passed this will only match elemental nuclides.
element (Element, str, int, slice) – the element to filter by, slices must be slices of integers. This will match all nuclides that are based on this element. e.g., “U” will match U-235 and U-238.
A (int, slice) – the filter for the nuclide A number.
meta_state (int, slice) – the metastable isomer filter.
library (str, slice) – the libraries to limit the search to.
strict (bool) – whether to strictly match elements as only elements (when no A is given), and only match blank libraries when no library is given.
- Returns:
a generator of fractions whose nuclide matches the criteria.
- Return type:
Generator[float]
- format_for_mcnp_input(mcnp_version)#
Creates a list of strings representing this MCNP_Object that can be written to file.
- Parameters:
mcnp_version (tuple[int]) – The tuple for the MCNP version that must be exported to.
- Returns:
a list of strings for the lines that this input will occupy.
- Return type:
list
- get_material_elements()#
Get the elements that are contained in this material.
This is sorted by the most common element to the least common.
- Returns:
a sorted list of elements by total fraction
- Return type:
list[Element]
- get_nuclide_library(nuclide: Nuclide, library_type: LibraryType) Library | None #
Figures out which nuclear data library will be used for the given nuclide in this given material in this given problem.
This follows the MCNP lookup process and returns the first Library to meet these rules.
The library extension for the nuclide. For example if the nuclide is
1001.80c
forLibraryType("nlib")
,Library("80c")
will be returned.Next if a relevant nuclide library isn’t provided the
default_libraries()
will be used.Finally if the two other options failed
M0
will be checked. These are stored inmontepy.materials.Materials.default_libraries()
.
Notes
The final backup is that MCNP will use the first matching library in
XSDIR
. Currently MontePy doesn’t support reading anXSDIR
file and so it will return none in this case.Added in version 1.0.0.
- Parameters:
nuclide (Union[Nuclide, str]) – the nuclide to check.
library_type (LibraryType) – the LibraryType to check against.
- Returns:
the library that will be used in this scenario by MCNP.
- Return type:
Union[Library, None]
- Raises:
TypeError – If arguments of the wrong type are given.
- link_to_problem(problem: MCNP_Problem)#
Links the input to the parent problem for this input.
This is done so that inputs can find links to other objects.
- Parameters:
problem (MCNP_Problem) – The problem to link this input to.
- mcnp_str(mcnp_version: tuple[int] = None)#
Returns a string of this input as it would appear in an MCNP input file.
..versionadded:: 1.0.0
- Parameters:
mcnp_version (tuple[int]) – The tuple for the MCNP version that must be exported to.
- Returns:
The string that would have been printed in a file
- Return type:
str
- normalize()#
Normalizes the components fractions so that they sum to 1.0.
Added in version 1.0.0.
- update_pointers(data_inputs: list[DataInput])#
Updates pointer to the thermal scattering data
- Parameters:
data_inputs (list[DataInput]) – a list of the data inputs in the problem
- validate()#
Validates that the object is in a usable state.
- property cells: Generator[montepy.cell.Cell]#
A generator of the cells that use this material.
- Returns:
an iterator of the Cell objects which use this.
- Return type:
Generator[Cell]
- property classifier#
The syntax tree object holding the data classifier.
For example this would container information like
M4
, orF104:n
.- Returns:
the classifier for this data_input.
- Return type:
- property comments: list[PaddingNode]#
The comments associated with this input if any.
This includes all
C
comments before this card that aren’t part of another card, and any comments that are inside this card.- Returns:
a list of the comments associated with this comment.
- Return type:
list
- property data#
The syntax tree actually holding the data.
- Returns:
The syntax tree with the information.
- Return type:
- property default_libraries#
The default libraries that are used when a nuclide doesn’t have a relevant library specified.
Default Libraries#
Also materials have the concept of
default_libraries()
. These are the libraries set byNLIB
,PLIB
, etc., which are used when a library of the correctLibraryType
is not provided with the nuclide.default_libraries()
acts like a dictionary, and can accept a string or aLibraryType
as keys.print(mat.default_libraries["plib"]) mat.default_libraries[montepy.LibraryType.NEUTRON] = "00c" print(mat.default_libraries["nlib"])
None 00c
Added in version 1.0.0.
- property is_atom_fraction: bool#
If true this constituent is in atom fraction, not weight fraction.
Changed in version 1.0.0: This property is now settable.
- Return type:
bool
- property leading_comments: list[PaddingNode]#
Any comments that come before the beginning of the input proper.
- Returns:
the leading comments.
- Return type:
list
- property material_components#
The internal dictionary containing all the components of this material.
Deprecated since version 0.4.1: MaterialComponent has been deprecated as part of a redesign for the material interface due to a critical bug in how MontePy handles duplicate nuclides. See Migration plan for MontePy 1.0.0.
- Raises:
DeprecationWarning – This has been fully deprecated and cannot be used.
- property nuclides#
Get just the fractions, or values from this material.
This acts like a list. It is iterable, and indexable.
Examples
import montepy mat = montepy.Material() mat.number = 5 enrichment = 0.04 # define UO2 with enrichment of 4.0% mat.add_nuclide("8016.00c", 2/3) mat.add_nuclide("U-235.00c", 1/3 * enrichment) mat.add_nuclide("U-238.00c", 2/3 * (1 - enrichment)) for nuc in mat.nuclides: print(repr(nuc)) # iterables can be used with other functions max_zaid = max(mat.nuclides)
this would print:
Nuclide('O-16.00c') Nuclide('U-235.00c') Nuclide('U-238.00c')
# get value by index print(repr(mat.nuclides[0])) # set the value, and double enrichment mat.nuclides[1] = montepy.Nuclide("U-235.80c")
Nuclide('O-16.00c')
Added in version 1.0.0.
- Return type:
Generator[Nuclide]
- property number#
The current number of the object that will be written out to a new input.
- Return type:
int
- property old_number: int#
The material number that was used in the read file
- Return type:
int
- property parameters: dict[str, str]#
A dictionary of the additional parameters for the object.
e.g.:
1 0 -1 u=1 imp:n=0.5
has the parameters{"U": "1", "IMP:N": "0.5"}
- Returns:
a dictionary of the key-value pairs of the parameters.
- Return type:
unknown
- Rytpe:
dict
- property particle_classifiers#
The particle class part of the input identifier as a parsed list.
This is parsed from the input that was read.
For example: the classifier for
F7:n
is:n
, andimp:n,p
is:n,p
This will be parsed as a list:[<Particle.NEUTRON: 'N'>, <Particle.PHOTON: 'P'>]
.- Returns:
the particles listed in the input if any. Otherwise None
- Return type:
list
- property prefix#
The text part of the input identifier parsed from the input.
For example: for a material like:
m20
the prefix ism
. this will always be lower case. Can also be called the mnemonic.- Returns:
The prefix read from the input
- Return type:
str
- property prefix_modifier#
The modifier to a name prefix that was parsed from the input.
For example: for a transform:
*tr5
the modifier is*
- Returns:
the prefix modifier that was parsed if any. None if otherwise.
- Return type:
str
- property thermal_scattering: ThermalScatteringLaw#
The thermal scattering law for this material
- Return type:
- property trailing_comment: list[PaddingNode]#
The trailing comments and padding of an input.
Generally this will be blank as these will be moved to be a leading comment for the next input.
- Returns:
the trailing
c
style comments and intermixed padding (e.g., new lines)- Return type:
list
- property values#
Get just the fractions, or values from this material.
This acts like a list. It is iterable, and indexable.
Examples
import montepy mat = montepy.Material() mat.number = 5 enrichment = 0.04 # define UO2 with enrichment of 4.0% mat.add_nuclide("8016.00c", 2/3) mat.add_nuclide("U-235.00c", 1/3 * enrichment) mat.add_nuclide("U-238.00c", 2/3 * (1 - enrichment)) for val in mat.values: print(val) # iterables can be used with other functions max_frac = max(mat.values) print("max", max_frac)
This would print:
0.6666666666666666 0.013333333333333332 0.6399999999999999 max 0.6666666666666666
# get value by index print(mat.values[0]) # set the value, and double enrichment mat.values[1] *= 2.0 print(mat.values[1])
This would print:
0.6666666666666666 0.026666666666666665
Added in version 1.0.0.
- Return type:
Generator[float]
- Parameters:
input (InitInput)
number (int)
- montepy.data_inputs.material.DEFAULT_INDENT: int = 6#
The default number of spaces to indent on a new line by.
This is used for adding new material components. By default all components made from scratch are added to their own line with this many leading spaces.
- montepy.data_inputs.material.MAX_PRINT_ELEMENTS: int = 5#
The maximum number of elements to print in a material string descripton.