Skip to main content

A Python API for the FEBio finite element solver.

Project description

PyPI - Version

Overview

This is a Python package for generating FEBio input files and converting XPLT files to HDF5. We rely heavily on pydantic and pydantic-xml for type validation and XML serialization. Many of FEBio's features are covered, but not all.

Our design focuses on:

๐—˜๐—ฎ๐˜€๐˜† ๐—ถ๐—ป๐˜€๐˜๐—ฎ๐—น๐—น๐—ฎ๐˜๐—ถ๐—ผ๐—ป

Python wheels are built and uploaded to PyPI for installation with pip or other tools. Installation from source is simplified with the powerful and user-friendly ๐˜ถ๐˜ท package manager.

๐—ฅ๐˜‚๐—ป๐˜๐—ถ๐—บ๐—ฒ ๐—ฉ๐—ฎ๐—น๐—ถ๐—ฑ๐—ฎ๐˜๐—ฒ๐—ฑ ๐—–๐—น๐—ฎ๐˜€๐˜€๐—ฒ๐˜€ ๐—ณ๐—ผ๐—ฟ ๐— ๐—ผ๐—ฑ๐—ฒ๐—น ๐—–๐—ผ๐—บ๐—ฝ๐—ผ๐—ป๐—ฒ๐—ป๐˜๐˜€

All the components necessary to construct an FEBio model are defined as classes inheriting from the ๐˜‰๐˜ข๐˜ด๐˜ฆ๐˜”๐˜ฐ๐˜ฅ๐˜ฆ๐˜ญ provided by the popular ๐˜ฑ๐˜บ๐˜ฅ๐˜ข๐˜ฏ๐˜ต๐˜ช๐˜ค library, which allows for enforcement of type and value constraints at runtime. This enables the definition of โ€œguard railsโ€ when defining these components to help ensure a valid FEBio model is created.

๐—ง๐˜†๐—ฝ๐—ฒ ๐—›๐—ถ๐—ป๐˜๐˜€ ๐˜๐—ผ ๐—ฒ๐—ป๐—ต๐—ฎ๐—ป๐—ฐ๐—ฒ ๐—œ๐——๐—˜ ๐—ฒ๐˜…๐—ฝ๐—ฒ๐—ฟ๐—ถ๐—ฒ๐—ป๐—ฐ๐—ฒ

Modern integrated development environments in combination with a linter, formatter, and/or a language server protocol can aid code development by providing auto-completion, highlighting syntax and type errors and style violations, and formatting code based on a style standard. This functionality is greatly enhanced when a Python library provides โ€œtype hints.โ€ When present, in-line help provided by these tools can bypass the need to consult the documentation directly.

๐— ๐—ถ๐—ป๐—ถ๐—บ๐—ฎ๐—น ๐——๐—ฒ๐—ฝ๐—ฒ๐—ป๐—ฑ๐—ฒ๐—ป๐—ฐ๐—ถ๐—ฒ๐˜€

By utilizing a small dependency set, ๐˜ฑ๐˜บ๐˜ง๐˜ฆ๐˜ฃ๐˜ช๐˜ฐ should "play nice" with the wider Python ecosystem, allowing users to build solutions with the libraries of their choice.

๐——๐—ผ๐—ฐ๐˜‚๐—บ๐—ฒ๐—ป๐˜๐—ฎ๐˜๐—ถ๐—ผ๐—ป ๐˜ƒ๐—ถ๐—ฎ ๐—ฆ๐—ฝ๐—ต๐—ถ๐—ป๐˜…

Organized and searchable documentation is automatically generated with Sphinx.

๐—ง๐—ฒ๐˜€๐˜๐—ถ๐—ป๐—ด

The FEBio development team has helped us develop continuous integration tasks to test our library with the latest FEBio release. We are still working on full code test coverage but once complete this will help maintain compatibility and functionality with future releases.

Getting Started

Installation

From PyPi

With pip:

Create a virtual environment:

/path/to/compatible-python -m venv .venv

where /path/to/compatible-python is the path to a compatible python executable.

Activate the virtual environment:

On Linux or macOS:

source .venv/bin/activate

On Windows (cmd):

.\.venv\Scripts\activate.bat

On Windows (powershell):

.\.venv\Scripts\Activate.ps1

Install the package:

pip install pyfebio

From Source (with uv manager)

Clone with https:

git clone https://github.com/CompOrthoBiomech/pyfebio.git

Or,

Clone with ssh:

git clone git@github.com:CompOrthoBiomech/pyfebio.git

Install uv:

Install uv from here

Sync the uv environment

In top-level repository directory:

uv sync

This will create a virtual environment and install the package.

Testing

We rely on FEBio to check our generated models are valid. Therefore, you will need to have FEBio installed and available in your PATH.

To run all the tests, execute the following command:

cd src
pytest

For tests that depend on running finite element simulations, you can find them in the pytest tmp_path directory, which varies by operating system.

For the latest run:

on Linux,

cd /tmp/pytest-of-[USER]/pytest-current/[TEST_FUNCTION_NAME]current

FAQs

  • Why are array quantities defined as comma-delimited strings?

    • pydantic-xml serializes list element types as follows

      from pydantic_xml import BaseXmlModel, element
      
      class ExampleList(BaseXmlModel):
          a: list[int] = element(default=[])
          
      obj = ExampleList(a=[1, 2])
      

      as

      <ExampleList>
          <a>1</a>
          <a>2</a>
      </ExampleList>
      

      whereas, FEBio expects <a>1,2</a>. The current workaround is to convert the list into a string that is validated vs regex constraints. This is not ideal. There may be a way to have custom (de)serialization functions that do the conversion from list to delimited string instead. It may also be possible to define and XML style sheet via XLST, but I am not so well-versed in XML.

  • Why do I need to use the material.MaterialParameter class to assign a simple primitive value like c1=10.0?

    • We need to support the option of defining these values as "map" or "math" as well, which require this class definition. That said, it would preferable to type the parameters as MaterialParameter | float with the appropriate primitive type. Unfortunately, pydantic-xml does not allow mixing custom class and primitive type definitions, so this is our compromise.
  • Why is there no support for geometry and/or mesh generation?

    • We want to keep pyfebio minimal such that you can use the libraries you prefer for these tasks.
    • That said, we may add some simple numpy based approaches in the future as this is already a dependency.

Example

import pyfebio

# Instantiate a model tree with default values
# This contains empty mesh, material, loads, boundary, etc. sections
my_model = pyfebio.model.Model()

# Let's create a single hex8 element explicitly
# Normally, you would use the meshio functions to import
nodes_list = [
    [0.0, 0.0, 0.0],
    [1.0, 0.0, 0.0],
    [1.0, 1.0, 0.0],
    [0.0, 1.0, 0.0],
    [0.0, 0.0, 1.0],
    [1.0, 0.0, 1.0],
    [1.0, 1.0, 1.0],
    [0.0, 1.0, 1.0],
]

elements_list = [[1, 2, 3, 4, 5, 6, 7, 8]]

# Add Nodes to an pyfebio.Nodes object
nodes = pyfebio.mesh.Nodes(name="nodes")
for i, node in enumerate(nodes_list):
    nodes.add_node(pyfebio.mesh.Node(id=i + 1, text=",".join(map(str, node))))

# Add Elements to an pyfebio.Elements object
elements = pyfebio.mesh.Elements(name="box", type="hex8")
for i, element in enumerate(elements_list):
    elements.add_element(pyfebio.mesh.Hex8Element(id=i + 1, text=",".join(map(str, element))))

# Append nodes and elements to the model's mesh section
my_model.mesh_.nodes.append(nodes)
my_model.mesh_.elements.append(elements)

# Let's make a node set for top and bottom
bottom_nodes = [1, 2, 3, 4]
top_nodes = [5, 6, 7, 8]
top_node_set = pyfebio.mesh.NodeSet(name="top", text=",".join(map(str, top_nodes)))
bottom_node_set = pyfebio.mesh.NodeSet(name="bottom", text=",".join(map(str, bottom_nodes)))

# Append the node sets to the model's mesh section
my_model.mesh_.node_sets.append(top_node_set)
my_model.mesh_.node_sets.append(bottom_node_set)

# We need a material
# the use of pyfebio.material.MaterialParameter is our solution
# to handle mapped, math, or directly specified values
my_material = pyfebio.material.CoupledMooneyRivlin(
    id=1,
    name="cartilage",
    c1=pyfebio.material.MaterialParameter(text=10.0),
    c2=pyfebio.material.MaterialParameter(text=1.0),
    k=pyfebio.material.MaterialParameter(text=1000.0),
)

# Define a solid domain for the box to assign the material
solid_domain = pyfebio.meshdomains.SolidDomain(name="box", mat="cartilage")

# add the solid domain
my_model.meshdomains_.add_solid_domain(solid_domain)

# add the material
my_model.material_.add_material(my_material)

# Fix the bottom nodes (1 means BC DoF is active)
fixed_bottom = pyfebio.boundary.BCZeroDisplacement(node_set="bottom", x_dof=1, y_dof=1, z_dof=1)

# Displace the top nodes in z
# We need to create a boundary.Value object that references a load curve
displacement_value = pyfebio.boundary.Value(lc=1, text=-0.2)
move_top = pyfebio.boundary.BCPrescribedDisplacement(node_set="top", dof="z", value=displacement_value)

# Add boundary conditions
my_model.boundary_.add_bc(fixed_bottom)
my_model.boundary_.add_bc(move_top)

# Now, create the loadcurve 1 we referenced
curve_points = pyfebio.loaddata.CurvePoints(points=["0.0,0.0", "1.0,1.0"])
load_curve1 = pyfebio.loaddata.LoadCurve(id=1, points=curve_points)
# And, add it to model
my_model.loaddata_.add_load_curve(load_curve1)

# Save the model to disk
my_model.save("my_model.feb")

# And run it
pyfebio.model.run_model("my_model.feb")

Short Example Simulation

Features

Brief overview, see module documentation for more details. Unchecked are not yet implemented.

โœ… Implemented and tested

โ˜‘๏ธ Implemented but untested

โŒ Not yet implemented

  • Control

    • โœ… All control settings
  • Mesh Section

    • โœ… Nodes
    • โœ… Solid Elements:
      • โœ… tet4
      • โœ… tet10
      • โœ… tet15
      • โœ… hex8
      • โœ… hex20
      • โœ… hex27
      • โœ… penta6
      • โ˜‘๏ธ penta15
      • โœ… pyra5
    • โœ… Shell Elements:
      • โœ… tri3
      • โœ… tri6
      • โœ… quad4
      • โœ… quad8
      • โœ…๏ธ q4ans
      • โœ… q4eas
    • โœ… Beam Elements:
      • โœ… line2
      • โœ… line3
    • โœ… Node, Element, Surface Sets
  • MeshDomain

    • โœ… Solid Domain
    • โœ… Shell Domain
    • โœ… Beam Domain (only "elastic-truss")
    • โ˜‘๏ธ Granular control for integration schemes, etc.
  • MeshData Section

    • โ˜‘๏ธ Node Data
      • โ˜‘๏ธ Scalar
      • โ˜‘๏ธ Vector3
    • โ˜‘๏ธ Element Data
      • โ˜‘๏ธ Scalar
      • โ˜‘๏ธ Vector3
    • โŒ Surface Data
      • โŒ Scalar
      • โŒ Vector3
  • MeshAdaptor

    • โ˜‘๏ธ Erosion
    • โœ… MMG3d Remeshing
    • โœ… hex_refine
    • โœ… hex_refine2d
    • โ˜‘๏ธ Criteria
    • โ˜‘๏ธ element selection
    • โ˜‘๏ธ math
    • โ˜‘๏ธ min-max filter
    • โœ… relative error
    • โœ… stress
    • โ˜‘๏ธ contact gap
    • โ˜‘๏ธ damage
    • โ˜‘๏ธ max variable
  • Material

    • โœ… Unconstrained Formulation Materials
    • โœ… Uncoupled Formulation Materials
    • โ˜‘๏ธ Prestrain Material
    • โœ… Unconstrained Fiber models
    • โœ… Uncoupled Fiber models
    • โœ… Material Axis
      • โœ… Vector Definition
      • โœ… Fiber Vector
    • โ˜‘๏ธ Continuous Fiber Distributions
    • โ˜‘๏ธ Integration Schemes
    • โ˜‘๏ธ Element-wise, mapped, or math parameter defintion
    • โœ… Biphasic Materials
    • โœ… Viscoelastic Materials
    • โ˜‘๏ธ Biphasic-solute Materials
    • โœ… Multiphasic Materials
    • โŒ Chemical Reactions
    • โŒ Active Contraction Materials
    • โŒ Damage Materials
    • โŒ First-order Homogenization
  • Rigid

    • โœ… Constraints
      • โœ… Fixed Displacement and Rotation
      • โœ… Prescribed Displacement and Rotation
      • โœ… Precribed Rotation about Vector
      • โœ… Prescribed Euler Rotation
    • โœ… Connectors
      • โœ… Spherical Joint
      • โœ… Revolute Joint
      • โœ… Prismatic Joint
      • โœ… Cylindrical Joint
      • โœ… Planar Joint
      • โœ… Lock
      • โœ… Spring
      • โœ… Damper
      • โœ… Angular Damper
      • โœ… Contractile Force
    • โœ… Loads
      • โœ… Force
      • โœ… Moment
      • โœ… Follower Force
      • โœ… Follower Moment
      • โœ… Cable Load
    • โœ… Initial Conditions
      • โœ… Initial Velocity
      • โœ… Initial Angular Velocity
  • Initial

    • โ˜‘๏ธ Initial Velocity
    • โ˜‘๏ธ Initial Pre-strain
    • โœ… Initial Concentration
    • โœ… Initial Fluid Pressure
  • Loads

    • โœ… Nodal Loads
      • โœ… nodal_load
      • โœ… nodal_force
      • โœ… nodal_target_force
      • โœ… Nodal Fluid Flux
    • โœ… Surface Loads
      • โœ… Traction Load
      • โœ… Pressure Load
      • โœ… Fluid Flux
    • โœ… Body Loads
      • โœ… Constant Body Force
      • โœ… Non-Constant Body Force
      • โœ… Centrifugal Body Force
      • โœ… Moving Frame
      • โœ… Mass Damping
      • โŒ Heat Source
      • โŒ Surface Attraction
      • โŒ Fluid Centrifugal Force
      • โŒ Fluid Moving Frame
  • LoadData

    • โœ… Load Curves
      • โ˜‘๏ธ All Options
    • โ˜‘๏ธ PID Controllers
    • โœ… Math Controllers
  • Boundary

    • โœ… Fixed Displacement (solid)
    • โœ… Prescribed Displacement (solid)
    • โœ… Fixed Displacement (shell)
    • โœ…๏ธ Prescribed Displacement (shell)
    • โœ…๏ธ Precribed Deformation Gradient
    • โœ…๏ธ Displacement Along Normals
    • โœ…๏ธ Fix to Rigid Body
    • โœ… Rigid Node Set Deformation (rotation about axis)
    • โœ… Zero Fluid Pressure
    • โœ… Prescribed Fluid Pressure
    • โœ… Zero Concentration
    • โœ… Prescribed Concentration
    • โœ… Linear Constraint
  • Constraints

    • โ˜‘๏ธ Symmetry Plane
    • โ˜‘๏ธ Prestrain
    • โ˜‘๏ธ In-Situ Stretch
  • Contact

    • โœ… Sliding
      • โœ… Elastic
      • โœ… Facet-Facet
      • โœ… Node-Facet
    • โœ… Biphasic
    • โœ… Sliding2
    • โœ… Contact Potential Formulation
    • โœ… Tie
      • โœ… Elastic
      • โœ… Facet-Facet
      • โœ… Node-Facet
      • โœ… Biphasic
  • Step

    • โœ… Multistep Analysis
  • Output

    • โ˜‘๏ธ Log File Configuration
    • โœ… Plot File Configuration
    • โœ… Node Variables
    • โœ… Element Variables
    • โœ… Rigid Body Variables
    • โ˜‘๏ธ Rigid Connector Variables
  • XPLT

    • โœ… Convert XPLT to HDF5

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyfebio-0.2.1.tar.gz (36.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyfebio-0.2.1-py3-none-any.whl (43.7 kB view details)

Uploaded Python 3

File details

Details for the file pyfebio-0.2.1.tar.gz.

File metadata

  • Download URL: pyfebio-0.2.1.tar.gz
  • Upload date:
  • Size: 36.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pyfebio-0.2.1.tar.gz
Algorithm Hash digest
SHA256 22ecd0a294301f01099b5dd647570101b7a8fe638988b8aafeeb3364e104ecf3
MD5 d92611590e09c1c8766ac02f9336d489
BLAKE2b-256 ab01d6f01a79e13960097ba279b88740325cc1a8ae74d9e50ea207a302e2af35

See more details on using hashes here.

File details

Details for the file pyfebio-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: pyfebio-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 43.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pyfebio-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b6b70fb94f48837669d9175912a29d230baa6bf26ac141f69601758d118a5099
MD5 603d28ba802fdc5d823ddab957a71802
BLAKE2b-256 4fe670ff856dd169ff697fd57ffbcb5c4a3fcf06807443921fcff9219359df6c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page