Materials#

Material properties are set on femorph_solver.Model either through 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 femorph_solver.interop.mapdl.APDL.

Native API#

The native primitive is Model.assign(), which declares an element kernel and its material in a single call:

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 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 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:

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 \(M\).

GXY

Transverse shear modulus

Reserved for future shell / beam transverse-shear paths.

ALPX

Thermal expansion coefficient

Reserved for future thermal-strain coupling.

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 Model.assign() to register more than one material:

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 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 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#