diff --git a/armi/materials/__init__.py b/armi/materials/__init__.py index f231e44b6..84fd7028f 100644 --- a/armi/materials/__init__.py +++ b/armi/materials/__init__.py @@ -23,25 +23,24 @@ As the fundamental macroscopic building blocks of any physical object, these are highly important to reactor analysis. -This module handles the dynamic importing of all the materials defined here at the framework -level as well as in all the attached plugins. It is expected that most teams will -have special material definitions that they will want to define. +This module handles the dynamic importing of all the materials defined here at the +framework level as well as in all the attached plugins. It is expected that most teams +will have special material definitions that they will want to define. It may also make sense in the future to support user-input materials that are not hard-coded into the app. The base class for all materials is in :py:mod:`armi.materials.material`. """ -import pkgutil -import importlib from typing import List +import importlib import inspect +import pkgutil from armi.materials.material import Material -# this will frequently be updated by the CONF_MATERIAL_NAMESPACE_ORDER setting -# during reactor construction (see armi.reactor.reactors.factory) -# This may also be replaced by a more global material registry at some point. +# This will frequently be updated by the CONF_MATERIAL_NAMESPACE_ORDER setting +# during reactor construction (see armi.reactor.reactors.factory). _MATERIAL_NAMESPACE_ORDER = ["armi.materials"] @@ -49,9 +48,23 @@ def setMaterialNamespaceOrder(order): """ Set the material namespace order at the Python interpreter, global level. - .. impl:: Materials can be searched across packages in a defined namespace. - :id: I_ARMI_MAT_NAMESPACE - :implements: R_ARMI_MAT_NAMESPACE + .. impl:: Material collections are defined with an order of precedence in the case + of duplicates. + :id: I_ARMI_MAT_ORDER + :implements: R_ARMI_MAT_ORDER + + An ARMI application will need materials. Materials can be imported from + any code the application has access to, like plugin packages. This leads to + the situation where one ARMI application will want to import multiple + collections of materials. To handle this, ARMI keeps a list of material + namespaces. This is an ordered list of importable packages that ARMI + can search for a particular material by name. + + This automatic exploration of an importable package saves the user the + tedium have having to import or include hundreds of materials manually somehow. + But it comes with a caveat; the list is ordered. If two different namespaces in + the list include a material with the same name, the first one found in the list + is chosen, i.e. earlier namespaces in the list have precedence. """ global _MATERIAL_NAMESPACE_ORDER _MATERIAL_NAMESPACE_ORDER = order @@ -120,30 +133,41 @@ def resolveMaterialClassByName(name: str, namespaceOrder: List[str] = None): Find the first material class that matches a name in an ordered namespace. Names can either be fully resolved class paths (e.g. ``armi.materials.uZr:UZr``) - or simple class names (e.g. ``UZr``). In the latter case, the ``CONF_MATERIAL_NAMESPACE_ORDER`` - setting to allows users to choose which particular material of a common name (like UO2 or HT9) - gets used. + or simple class names (e.g. ``UZr``). In the latter case, the + ``CONF_MATERIAL_NAMESPACE_ORDER`` setting to allows users to choose which + particular material of a common name (like UO2 or HT9) gets used. Input files usually specify a material like UO2. Which particular implementation gets used (Framework's UO2 vs. a user plugins UO2 vs. the Kentucky Transportation Cabinet's UO2) is up to the user at runtime. - .. impl:: Material collections are defined with an order of precedence in the case of duplicates. - :id: I_ARMI_MAT_ORDER - :implements: R_ARMI_MAT_ORDER + .. impl:: Materials can be searched across packages in a defined namespace. + :id: I_ARMI_MAT_NAMESPACE + :implements: R_ARMI_MAT_NAMESPACE + + During the runtime of an ARMI application, but particularly during the + construction of the reactor in memory, materials will be requested by name. At + that point, this code is called to search for that material name. The search + goes through the ordered list of Python namespaces provided. The first time an + instance of that material is found, it is returned. In this way, the first + items in the material namespace list take precedence. + + When a material name is passed to this function, it may be either a simple + name like the string ``"UO2"`` or it may be much more specific, like + ``armi.materials.uraniumOxide:UO2``. Parameters ---------- name : str The material class name to find, e.g. ``"UO2"``. Optionally, a module path - and class name can be provided with a colon separator as ``module:className``, e.g. - ``armi.materials.uraniumOxide:UO2`` for direct specification. + and class name can be provided with a colon separator as ``module:className``, + e.g. ``armi.materials.uraniumOxide:UO2`` for direct specification. namespaceOrder : list of str, optional - A list of namespaces in order of preference in which to search for the material. - If not passed, the value in the global ``MATERIAL_NAMESPACE_ORDER`` will be used, - which is often set by the ``CONF_MATERIAL_NAMESPACE_ORDER`` setting (e.g. - during reactor construction). Any value passed into this argument will be ignored - if the ``name`` is provided with a ``modulePath``. + A list of namespaces in order of preference in which to search for the + material. If not passed, the value in the global ``MATERIAL_NAMESPACE_ORDER`` + will be used, which is often set by the ``CONF_MATERIAL_NAMESPACE_ORDER`` + setting (e.g. during reactor construction). Any value passed into this argument + will be ignored if the ``name`` is provided with a ``modulePath``. Returns ------- diff --git a/armi/materials/material.py b/armi/materials/material.py index cdf4af64f..9ba80ec59 100644 --- a/armi/materials/material.py +++ b/armi/materials/material.py @@ -34,16 +34,29 @@ class Material: """ - A material is made up of elements or isotopes. It has bulk properties like mass density. + A material is made up of elements or isotopes. It has bulk properties like density. .. impl:: The abstract material class. :id: I_ARMI_MAT_PROPERTIES :implements: R_ARMI_MAT_PROPERTIES + The ARMI Materials library is based on the Object-Oriented Programming design + approach, and uses this generic ``Material`` base class. In this class we + define a large number of material properties like density, heat capacity, or + linear expansion coefficient. Specific materials then subclass this base class to + assign particular values to those properties. + .. impl:: Materials generate nuclide mass fractions at instantiation. :id: I_ARMI_MAT_FRACS :implements: R_ARMI_MAT_FRACS + An ARMI material is meant to be able to represent real world materials that + might be used in the construction of a nuclear reactor. As such, they are + not just individual nuclides, but practical materials like a particular + concrete, steel, or water. One of the main things that will be needed to + describe such a material is the exact nuclide fractions. As such, the + constructor of every Material subclass attempts to set these mass fractions. + Attributes ---------- parent : Component @@ -108,6 +121,11 @@ def name(self): .. impl:: The name of a material is accessible. :id: I_ARMI_MAT_NAME :implements: R_ARMI_MAT_NAME + + Every instance of an ARMI material must have a simple, human-readable + string name. And, if possible, we want this string to match the class + name. (This, of course, puts some limits on both the string and the + class name.) These names are easily retrievable as a class property. """ return self._name @@ -725,6 +743,11 @@ def linearExpansion(self, Tk=None, Tc=None): .. impl:: Fluid materials are not thermally expandable. :id: I_ARMI_MAT_FLUID :implements: R_ARMI_MAT_FLUID + + ARMI does not model thermal expansion of fluids. The ``Fluid`` superclass + therefore sets the thermal expansion coefficient to zero. All fluids + subclassing the ``Fluid`` material will inherit this method which sets the + linear expansion coefficient to zero at all temperatures. """ return 0.0 diff --git a/armi/materials/void.py b/armi/materials/void.py index eff62c309..de0ef63b8 100644 --- a/armi/materials/void.py +++ b/armi/materials/void.py @@ -26,6 +26,12 @@ class Void(material.Fluid): .. impl:: Define a void material with zero density. :id: I_ARMI_MAT_VOID :implements: R_ARMI_MAT_VOID + + To help with expansion, it is sometimes useful to put a small section of void + material into the reactor model. This is not meant to represent a true void, + that would cause negative pressure in a system, but just as a bookkeeping tool. + Sometimes this helps users define the geometry of an expanding and conctracting + reactor. It is called a "void" because it has zero density at all temperatures. """ def pseudoDensity(self, Tk: float = None, Tc: float = None) -> float: