Materials ========= Material properties are set on :class:`femorph_solver.Model` either through :meth:`~femorph_solver.Model.assign` (the native API), which takes a property dict and stores it under a material id, or — for users porting an existing deck — through the APDL-dialect wrapper :class:`femorph_solver.interop.mapdl.APDL`. Native API ---------- The native primitive is :meth:`Model.assign`, which declares an element kernel and its material in a single call: .. code-block:: python import femorph_solver as fs model = fs.Model.from_grid(grid) model.assign( fs.ELEMENTS.HEX8, {"EX": 2.1e11, "PRXY": 0.30, "DENS": 7850.0}, ) The first argument is an :data:`~femorph_solver.ELEMENTS` spec; the second is a property dict whose keys are the scalar property names listed below. Units are whatever's consistent across ``EX``, the element geometry, and any forces — femorph-solver does not track units. Supported properties -------------------- The :class:`femorph_solver.MaterialProperty` enum enumerates every property name femorph-solver's element kernels currently look up. Accepting the enum member or the raw string is equivalent: .. list-table:: :widths: 15 55 30 :header-rows: 1 * - Token - Meaning - Used by * - ``EX`` - Young's modulus - All solids, beams, shells, plane, truss. * - ``PRXY`` - Poisson's ratio (isotropic) - All solids, beams, shells, plane. * - ``DENS`` - Mass density - Every element that contributes to :math:`M`. * - ``GXY`` - Transverse shear modulus - Reserved for future shell / beam transverse-shear paths. * - ``ALPX`` - Thermal expansion coefficient - Reserved for future thermal-strain coupling. .. code-block:: python from femorph_solver import MaterialProperty as MP model.assign(fs.ELEMENTS.HEX8, {MP.EX: 2.1e11, MP.PRXY: 0.30, MP.DENS: 7850.0}) Multiple materials ------------------ Pass ``mat_id=`` to :meth:`Model.assign` to register more than one material: .. code-block:: python model.assign(fs.ELEMENTS.HEX8, {"EX": 2.1e11, "PRXY": 0.30, "DENS": 7850.0}, mat_id=1) model.assign(fs.ELEMENTS.HEX8, {"EX": 7.0e10, "PRXY": 0.33, "DENS": 2700.0}, mat_id=2) When a foreign deck is loaded (CDB / BDF / INP / FEM), each element arrives with a material id already stamped; the readers populate the material table for you. Introspection ------------- The current material table is available as :attr:`Model.materials`:: model.materials # {1: {'EX': 2.1e11, 'PRXY': 0.3, 'DENS': 7850.0}, # 2: {'EX': 7.0e10, 'PRXY': 0.33, 'DENS': 2700.0}} Element kernels read the matching dict directly, so any additional scalar you stash under a known property name is visible to them. Per-element-class formulation knobs (e.g. ``_HEX8_INTEGRATION``, ``_HEX20_INTEGRATION``, ``_HEX20_MASS``, ``_QUAD4_PLANE_MODE``, ``_PYR13_INTEGRATION``, ``_PYR13_PYRAMID_RULE``) live in the same dict; the cleanest way to set them is via the ``ELEMENTS`` spec classes (see the :doc:`element library `), which write the appropriate underscore-prefixed key for you. Limitations (today) ------------------- - **Linear isotropic only.** Orthotropic / anisotropic tensors, rate dependence, plasticity, temperature-dependent curves are not yet implemented. - **Tensor-valued constitutive blocks** (``DMATRIX`` / ``ANEL`` in the foreign-deck readers) aren't round-tripped yet; they are parsed on load but ignored during assembly. See also -------- - :doc:`real-constants` — per-element-type geometric data. - :doc:`/user-guide/pre-processing/elements/index` — which properties each element class reads.