Quickstart#
A complete pre-process → solve → post-process cycle in ~20 lines of native Python. No MAPDL deck, no APDL syntax — femorph-solver drives its own mesh, material, and boundary-condition primitives, powered by a C++ assembly core.
The mesh is a quarter-arc sector of an annular disk that ships
bundled with the wheel (femorph_solver.examples.quarter_arc_sector()).
import pyvista as pv
import femorph_solver as fs
# --- Pre-process ------------------------------------------------
grid = fs.examples.quarter_arc_sector() # bundled HEX8 mesh
model = fs.Model.from_grid(grid)
model.assign("HEX8", {"EX": 2.1e11, "PRXY": 0.30, "DENS": 7850.0})
# Pin every grid point on the bottom face (z = min).
pts = grid.points
model.fix(where=pts[:, 2] <= pts[:, 2].min() + 1e-9)
# --- Solve ------------------------------------------------------
result = model.modal_solve(n_modes=10)
# --- Post-process ----------------------------------------------
print(f"First 5 modal frequencies (Hz): {result.frequency[:5]}")
deformed = grid.copy()
deformed["u"] = result.mode_shapes[:, 0].reshape(-1, 3)
deformed.warp_by_vector("u", factor=0.2, inplace=True)
pv.Plotter().add_mesh(deformed, color="lightblue").show()
What the three phases did#
Pre-process. Loaded a bundled mesh, declared an 8-node hexahedral element kernel (
femorph_solver.ElementType.HEX8), and stamped a steel material in a singleassign()call.fix()pinned every grid point on the lowest-z face using a boolean predicate — no per-node loop.Solve.
modal_solve()assembled sparseK/Mvia the C++ kernel, then handed off to the registered linear backend (Pardiso → CHOLMOD → SuperLU auto-chain) for shift-invert Lanczos.Post-process. Pulled the first mode shape off the result, reshaped it into a vector field, warped the grid, and rendered.
The native primitives#
femorph_solver.Model exposes a small, composable set of
verbs. Each is keyword-driven and accepts Python-native inputs
(boolean masks, scalar keyword components, element names from the
neutral topology-first taxonomy):
Call |
What it does |
|---|---|
|
Build a model directly on a |
|
Declare an element kernel ( |
|
Pin every grid point selected by a boolean mask. Also accepts
|
|
Keyword-driven nodal force or moment vector. |
|
Full \(K\phi = \omega^2 M\phi\) modal sweep with
shift-invert Lanczos. Returns a
|
|
Linear static |
|
Cyclic-symmetry modal sweep per harmonic index. |
Model also plugs into the materials library
via femorph_solver.materials:
from femorph_solver.materials import fetch, UnitSystem
steel = fetch("SS304", units=UnitSystem.SI)
model.assign("HEX8", steel)
Next steps#
Quickstart — more runnable examples.
User guide — conceptual walk-through of each phase.
Analyses — deeper demos per analysis type (static / modal / cyclic / transient).
Elements — per-element kernel demos.
MAPDL interop — if your starting point is a MAPDL CDB deck, start there. The compatibility layer is first-class but secondary to the native API above.