FEA in three phases#
Every finite-element simulation, regardless of the solver, decomposes into three phases. femorph-solver’s user guide is organised around them because that organisation is the mental model of the subject and the library’s API mirrors it directly.
Describe the physics: geometry, discretisation, materials, loads, and constraints. The output is a system of equations ready to solve.
Turn the handle. A direct or iterative algorithm converts the equations into numbers — displacements for a static solve, eigenpairs for modal, a time history for transient.
Interpret. Compute derived quantities (stress, strain energy, reactions), visualise mode shapes, compare against a reference, write artefacts for downstream tools.
Pre-process#
The pre-processing phase asks one question:
Given what I want to model, what system of equations describes it?
That question decomposes into sub-problems:
Geometry & discretisation. Meshing happens upstream of femorph-solver — you arrive with a
pyvista.UnstructuredGridor amapdl_archive.Archivealready in hand. See The Model.Element choice. Which class of element interpolates the field? femorph-solver registers a kernel for each MAPDL-style element name; see Element library.
Constitutive laws. What material behaviour? Today linear elastic only; see Materials.
Element data. Cross-sections for BEAM / LINK / SHELL; see Real constants and sections.
Constraints & loads. Dirichlet displacements and nodal forces; see Boundary conditions and loads.
The output of pre-processing is a Model with a
fully-stamped grid, a material table, and the constraint / load
records. From it the library can assemble the global sparse matrices
K and M on demand (Model.stiffness_matrix() and
Model.mass_matrix()).
Solve#
The solve phase is where all the heavy compute lives. The API is deliberately small:
solve_static()—K u = Fwith Dirichlet BCs.solve_modal()—K ϕ = ω² M ϕ.solve_transient()—M ü + C u̇ + K u = F(t)with Newmark-β.solve_cyclic_modal()— sector modal with harmonic-index phase constraints.
Every solver accepts a thread_limit kwarg and dispatches internally
to a pluggable linear / eigen backend — see
Solvers and Performance.
Post-process#
The solve returns a lightweight dataclass (ModalResult,
StaticResult, etc.). From there the workflow is
conventional Python:
Index into
result.displacement/result.mode_shapesto get per-DOF values.Feed
result.frequencyinto a Campbell diagram.Call
Model.eel()for elastic strain at every element node.Attach result arrays to the model’s grid and hand the grid to pyvista for rendering or to VTK / Paraview for further analysis.
See Post-processing for the catalogue of recipes.
Why this structure?#
The three-phase decomposition is not femorph-solver’s invention. It’s the
organising principle of every FEM textbook (Bathe §1.2, Zienkiewicz
ch. 1-2, Cook §1.1) and of every industrial solver — MAPDL’s
/PREP7 → /SOLU → /POST1 split is the same shape. We
mirror it because it makes the library easier to learn: you already
know the structure, and the API method names line up with each phase.