Skip to main content

FEM Core

NGSolve/Netgen finite-element model-building core — pure Python, no PySide6 or Qt dependency. Runs headlessly (no display required).

Python Version License

Features

  • 🧱 Layered FEM pipeline — mesh → function space → weak-form assembly, each stage a swappable service
  • 🧩 Typed, serializable models — FemModel, FemFormulation, BoundaryCondition, ... with to_dict()/from_dict()
  • 🌊 Physics formulations — linear elasticity, (complex) Helmholtz, Reissner-Mindlin plates, Naghdi shells, and CUSTOM symbolic weak forms
  • 🎯 Domain facades — AcousticModel, PlateModel, ShellModel builders in physics vocabulary
  • 🧮 Studies — static, modal and frequency-sweep analyses through one StudyManager
  • 📐 Stress — stresses, membrane forces, moments and shear forces as CoefficientFunctions
  • 🗂️ Geometry import — STEP/IGES/BREP with deterministic, geometry-sorted region indices
  • 💾 Results and projects — HDF5 result files and shared FemProject documents, with the fem-core-run / fem-core-view CLIs
  • 🔒 Safe expressions — boundary and custom-form expressions parsed by a restricted AST walker, never eval()
  • 🧪 Dependency-injectable services — every service behind a Protocol, so tests can mock NGSolve/Netgen
  • 📊 Visualization — VTK post-processing (.vtu, .png, interactive) via the companion package fem-post

Scope

fem-core builds the mesh, function space and forms, and solves them with static, modal or frequency-sweep studies. Transient (time-stepping) analysis is out of scope for now.

Installation

pip install fem-core            # from PyPI
pip install "fem-core[viz]"     # plus fem-post (VTK post-processing)
pip install "fem-core[pardiso]" # plus MKL, for the PARDISO solver (x86-64 Linux/Windows)

fem-core is MIT-licensed. The optional pardiso extra installs Intel's MKL (with tbb and intel-openmp), which is proprietary software under Intel's own licences, not MIT; fem-core works without it.

For development, from the repo root:

uv sync
source .venv/bin/activate

Quick Start

from netgen.occ import Box, OCCGeometry, Pnt

from fem_core.enums import BoundaryConditionType, FemDimension, FormulationType, FunctionSpaceType, StudyType
from fem_core.managers.fem_model_manager import FemModelManager
from fem_core.managers.study_manager import StudyManager
from fem_core.models.boundary_condition import BoundaryCondition
from fem_core.models.fem_formulation import FemFormulation
from fem_core.models.fem_model import FemModel
from fem_core.models.formulation_parameters import LinearElasticityParameters
from fem_core.models.function_space_config import FunctionSpaceConfig
from fem_core.models.mesh_config import MeshConfig
from fem_core.models.study import Study
from fem_core.models.study_parameters import ModalStudyParameters, StaticStudyParameters

geo = OCCGeometry(Box(Pnt(0, 0, 0), Pnt(100, 20, 10)))

model = FemModel(
    name="Bracket",
    dimension=FemDimension.DIM_3D,
    formulation=FemFormulation(
        formulation_type=FormulationType.LINEAR_ELASTICITY,
        parameters=LinearElasticityParameters(E=210e9, nu=0.3, body_force_y=-9.81),
    ),
    function_space=FunctionSpaceConfig(space_type=FunctionSpaceType.VECTOR_H1, order=2),
    mesh_config=MeshConfig(maxh=5.0),
    boundary_conditions=[BoundaryCondition(bc_type=BoundaryConditionType.DIRICHLET, region="fixed_face")],
)

manager = FemModelManager()
managed = manager.build_model(model, geo=geo.shape)  # mesh -> function space -> forms

studies = StudyManager(manager)
static = studies.create_study(managed.model_id, Study(parameters=StaticStudyParameters()))
studies.run_study(static.study_id)
static.result.gridfunction

modal = studies.create_study(
    managed.model_id, Study(study_type=StudyType.MODAL, parameters=ModalStudyParameters(num_modes=6))
)
studies.run_study(modal.study_id)
modal.result.eigenvalues  # omega^2, ascending

Facades build the same FemModel from domain vocabulary:

from fem_core.facades.acoustic_model import AcousticModel

fem_model = (
    AcousticModel(name="Cabin Acoustics", speed_of_sound=343.0, density=1.225)
    .add_sound_hard_wall("rigid_walls")
    .add_impedance_boundary("absorber_panel", impedance=415.0 + 50.0j)
    .to_fem_model()
)

Saved projects and results can be solved or viewed from the command line:

fem-core-run beam.cadw
fem-core-view beam.results.h5 --study Modes --png modes.png

Documentation

  • User Guide — studies, undo/redo, result storage, projects, geometry import, 2D/shell/plate models, stress, subdomains, visualization
  • Architecture — layers, services, managers, facades and key design decisions
  • Development — testing and releasing
  • fem-post — VTK post-processing
  • Examples and validations

License

MIT — see LICENSE.

Metadata

Release files for fem-core 0.1.15

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fem-core 0.1.15
File Size Uploaded
fem_core-0.1.15.tar.gz 337.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fem-core 0.1.15
File Interpreter ABI Platform
fem_core-0.1.15-py3-none-any.whl Python 3 none any Details

Total release size: 457.0 kB

Release files / fem_core-0.1.15.tar.gz

Download URL fem_core-0.1.15.tar.gz
Size 337.0 kB
Tags Source
SHA-256 checksum
How to use checksums
d0fbbbddb85b03c6d1dbc01ec18a5fb9174a26ff0fdc109b10f9d3e9d6251690
BLAKE2b-256 checksum
How to use checksums
bba4ff34ba243a5c774996dd081b238fe1830ed2459bd78f387b0825f6360799
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Release files / fem_core-0.1.15-py3-none-any.whl

Download URL fem_core-0.1.15-py3-none-any.whl
Size 120.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
263ded8c7964de3bd3093a37e031563040fc3f4bc4bd37b0e5123a53bb5f59f5
BLAKE2b-256 checksum
How to use checksums
5068d9473973bcca6c6e7ee650ac653f8332912f453a51f83cfee975000f7612
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.18

2 release files

0.1.17

2 release files

0.1.16

2 release files

This release

0.1.15 This release

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page