AfemeCorePython Python API

AirFrame 0.0.20261017 · import AfemeCorePython
AFEME finite element solver Python bindings (C++ API + pybind11)

Module functions

getVersion() -> str
Get AFEME version
getSubversion() -> str
Get AFEME subversion
getBuildDate() -> str
Get AFEME build date (YYYYMMDD)
calculateBeamSectionProperties(coords: Annotated[numpy.ArrayLike, numpy.float64]) -> dict
Calculate properties of a beam cross section the same way the solver does.

The polyline is one outer loop followed by any number of holes, each loop closed by repeating
its first point. Section axes: X (side) and Y (vertical), origin at the element node.

Args:
    coords (ndarray): Polyline coordinates, shape (N, 2)

Returns:
    dict: area, centroid (x, y), inertiaX, inertiaY, inertiaXY (around centroidal axes parallel to
          the section axes), principalAngle (radians), principalInertia1, principalInertia2,
          torsionConstant, shearCenter (x, y)

Raises:
    AfemeError: If the section is not valid

class AFEME

Finite element solver for structural analysis.

Supports context manager protocol for automatic cleanup:
    with AFEME() as solver:
        solver.addMaterial(...)

Every failing call raises AfemeError (a RuntimeError) with the solver's description of the error.
Nodes and elements are numbered from 0 in the order they are added.
AFEME() -> None
Create a new AFEME solver instance.
setCallback(callback: object, printProgressBar: bool = True) -> None
Receive the solver's messages in Python instead of on the console.

Args:
    callback (callable): callback(kind, text, newLine), kind being 'message', 'warning' or 'error';
                         None to print to the console again
    printProgressBar (bool): Pass progress bar messages too (default True)
getErrorDescription(code: int) -> str
Get the description of a solver error code.
addMaterial(youngModulus: float, poissonRatio: float, density: float) -> int
Add material definition.

Args:
    youngModulus (float): Young's modulus (Pa)
    poissonRatio (float): Poisson's ratio
    density (float): Material density (kg/m^3)
updateMaterial(material: int, youngModulus: float, poissonRatio: float, density: float) -> None
Update material values.

Args:
    material (int): Material index
    youngModulus (float): Young's modulus
    poissonRatio (float): Poisson's ratio
    density (float): Material density
addBeamProperty(material: int, coords: Annotated[numpy.ArrayLike, numpy.float64]) -> int
Add beam property.

Args:
    material (int): Material index
    coords (ndarray): Section polyline, shape (N, 2): one outer loop and any holes, each
                      closed by repeating its first point (see calculateBeamSectionProperties)
addShellProperty(material: int, thickness: float) -> int
Add shell property.

Args:
    material (int): Material index
    thickness (float): Shell thickness (m)
addSolidProperty(material: int) -> None
Add solid property.

Args:
    material (int): Material index
addPointMassProperty(mass: float, Ixx: float = 0.0, Iyy: float = 0.0, Izz: float = 0.0, Ixy: float = 0.0, Ixz: float = 0.0, Iyz: float = 0.0) -> None
Add point mass property.

Args:
    mass (float): Mass
    Ixx, Iyy, Izz, Ixy, Ixz, Iyz (float): Inertia tensor at the center of gravity, in the local
                                          axes of the property (products default to 0)
updateShellProperty(property: int, material: int, thickness: float) -> int
Update shell property values.

Args:
    property (int): Property index
    material (int): Material index
    thickness (float): Shell thickness (m)
updateSolidProperty(property: int, material: int) -> int
Update solid property material.

Args:
    property (int): Property index
    material (int): Material index
allocateNodes(numNodes: int) -> None
Reserve memory for nodes added one at a time (speeds up addNode).
addNode(x: float, y: float, z: float) -> None
Add a node (x, y, z)
storeNodes(xyz: Annotated[numpy.ArrayLike, numpy.float64]) -> None
Store all nodes at once (replaces the nodes added before).

Args:
    xyz (ndarray): Node coordinates, shape (N, 3)
getNumNodes() -> int
Get number of nodes.
addBeamElement(property: int, nodeIndices: Annotated[numpy.ArrayLike, numpy.int32], upVector: Annotated[numpy.ArrayLike, numpy.float64]) -> None
Add beam element.

Args:
    property (int): Property index
    nodeIndices (array): Node indices [n0, n1]
    upVector (array): Vector of the section's vertical direction [ux, uy, uz]
addTriaElement(property: int, nodeIndices: Annotated[numpy.ArrayLike, numpy.int32]) -> None
Add triangular shell element.

Args:
    property (int): Property index
    nodeIndices (array): Node indices [n0, n1, n2]
addQuadElement(property: int, nodeIndices: Annotated[numpy.ArrayLike, numpy.int32]) -> None
Add quadrilateral shell element.

Args:
    property (int): Property index
    nodeIndices (array): Node indices [n0, n1, n2, n3]
addTetraElement(property: int, nodeIndices: Annotated[numpy.ArrayLike, numpy.int32]) -> None
Add tetrahedral solid element.

Args:
    property (int): Property index
    nodeIndices (array): Node indices [n0, n1, n2, n3]
addHexaElement(property: int, nodeIndices: Annotated[numpy.ArrayLike, numpy.int32]) -> None
Add hexahedral solid element.

Args:
    property (int): Property index
    nodeIndices (array): Node indices [n0..n7]
addWedgeElement(property: int, nodeIndices: Annotated[numpy.ArrayLike, numpy.int32]) -> None
Add wedge (triangular prism) solid element.

Args:
    property (int): Property index
    nodeIndices (array): Node indices [n0..n5]: bottom triangle, then top triangle
addPointMassElement(property: int, node: int, rotation: object = None) -> None
Add point mass element.

Args:
    property (int): Point mass property index
    node (int): Node index
    rotation (ndarray, optional): 3x3 rotation from the property's local axes to global axes
getNumElements() -> int
Get number of elements.
addConstraint(node: int, dof: int) -> int
Add constraint to nodal DOF.

Args:
    node (int): Node index
    dof (int): DOF index (0-5: Tx,Ty,Tz,Rx,Ry,Rz)
addRigidMpc(masterNode: int, slaveNodes: Annotated[numpy.ArrayLike, numpy.int32], tieRotations: bool = True) -> int
Add rigid multi-point constraint (MPC): slave nodes follow master node as one rigid body.

Args:
    masterNode (int): Master node index
    slaveNodes (array): Slave node indices (1D array)
    tieRotations (bool): Rotations of slave nodes follow master node too (default True)
addAverageMpc(masterNode: int, slaveNodes: Annotated[numpy.ArrayLike, numpy.int32], weights: object = None) -> int
Add average multi-point constraint (MPC): master node follows weighted average motion of slave nodes.

Args:
    masterNode (int): Master node index
    slaveNodes (array): Slave node indices (1D array)
    weights (array): Optional weight of each slave node (1D array, equal weights if not given)
addForce(nodeIndex: int, nodalDofIndex: int, value: float, loadCaseIndex: int = 0) -> int
Apply force to node DOF. In a transient response it stays applied in every following step
(clearLoad() first to change it).

Args:
    nodeIndex (int): Node index
    nodalDofIndex (int): DOF index (0-5)
    value (float): Force value (N)
    loadCaseIndex (int): Load case index, linear static only (default: 0)
addPressure(elemIndex: int, faceIndex: int, value: float, loadCaseIndex: int = 0) -> int
Apply pressure to element face. In a transient response it stays applied in every following step
(clearLoad() first to change it).

Args:
    elemIndex (int): Element index
    faceIndex (int): Face index
    value (float): Pressure value (Pa)
    loadCaseIndex (int): Load case index, linear static only (default: 0)
getNumLoadCases() -> int
Get number of load cases.
setStorageSystem(storageType: StorageSystem) -> None
Set storage of the system matrices.
setPressureDistributionType(distributionType: PressureDistribution) -> None
Set how pressures are passed to face nodes.
setEigenvaluePerformanceMode(mode: EigenvaluePerformanceMode) -> None
Set eigenvalue solver favoring speed or accuracy.
setNfaNumModes(numModes: int) -> None
Set number of modes of the natural frequencies analysis (0: all within the frequency limits).
getNfaNumModes() -> int
setNfaLowerFreq(frequency: float) -> None
Set lower frequency limit (Hz).
getNfaLowerFreq() -> float
setNfaUpperFreq(frequency: float) -> None
Set upper frequency limit (Hz; 0: no limit, the lowest numModes modes).
getNfaUpperFreq() -> float
setLbaNumModes(numModes: int) -> None
Set number of modes of the buckling analysis (0: all within the eigenvalue limits).
getLbaNumModes() -> int
setLbaLowerEigenvalue(eigenvalue: float) -> None
Set lower eigenvalue (load factor) limit.
getLbaLowerEigenvalue() -> float
setLbaUpperEigenvalue(eigenvalue: float) -> None
Set upper eigenvalue (load factor) limit (0 with a lower limit that is not negative: no limit).
getLbaUpperEigenvalue() -> float
setLbaPressureLoadStiffness(include: bool) -> None
Include the load stiffness of pressures in buckling (default True): a pressure stays normal to its face,
so its force turns with the face as the structure deflects. False: pressures act as fixed nodal forces,
right for a pressure standing for a load that keeps its direction, such as a contact.
getLbaPressureLoadStiffness() -> bool
setStepSize(stepSize: float) -> None
Set time step of the transient response (s).
getStepSize() -> float
setStructuralDampingCoefficient(coefficient: float) -> None
Set structural damping coefficient of the transient response.
getStructuralDampingCoefficient() -> float
setStructuralDampingConversionFrequency(frequency: float) -> None
Set frequency (Hz) at which structural damping is converted to viscous damping.
getStructuralDampingConversionFrequency() -> float
runLinearStatic() -> None
Run linear static analysis (every load case).
runNaturalFrequencies(numModes: int, frequencyMin: float, frequencyMax: float) -> None
Run natural frequencies (modal) analysis.

Args:
    numModes (int): Number of modes to extract (0: all modes within the frequency limits)
    frequencyMin (float): Minimum frequency (Hz)
    frequencyMax (float): Maximum frequency (Hz) (0: no limit, the lowest numModes modes)

If numModes or frequencyMax is 0, the modes are counted first, which takes
longer than giving both.
runNaturalFrequenciesAnalysis() -> None
Run natural frequencies analysis with the limits set by setNfa*.
runLinearBuckling(numModes: int, eigenvalueMin: float = 0.0, eigenvalueMax: float = 0.0) -> None
Run linear buckling analysis of the load case 0 (the preload).

Args:
    numModes (int): Number of modes (0: all modes within the eigenvalue limits)
    eigenvalueMin (float): Lower eigenvalue (load factor) limit (default 0)
    eigenvalueMax (float): Upper limit (default 0: no limit, the lowest numModes modes)

Results: eigenvalues (load factors) and mode shapes with AnalysisType.LINEAR_BUCKLING; the
displacements and stresses of the preload with the same analysis type.
runLinearBucklingAnalysis() -> None
Run linear buckling analysis with the limits set by setLba*.
initializeTransientResponse() -> None
Initialize transient response analysis (time step and damping set before). Then for each step:
change the loads if they vary in time (clearLoad(), then addForce/addPressure: applied loads
stay until cleared), call runTransientResponseStep() and read the results of the step with
AnalysisType.TRANSIENT_RESPONSE.
runTransientResponseStep() -> None
Run one time step of the transient response with the loads applied at that time.
getNumSteps() -> int
Get number of transient steps run, the initial one included.
getProgress() -> float
Get progress of the running analysis (0 to 1).
requestStop() -> None
Ask the running analysis to stop (from another thread).
requestPause() -> None
Ask the running analysis to pause (from another thread).
requestResume() -> None
Resume a paused analysis.
getNumModes(analysisType: AnalysisType = <AnalysisType.NATURAL_FREQUENCIES: 1>) -> int
Get number of modes extracted.

Args:
    analysisType (AnalysisType): NATURAL_FREQUENCIES (default) or LINEAR_BUCKLING

Returns:
    int: Number of modes
getFrequency(modeIndex: int) -> float
Get natural frequency for mode.

Args:
    modeIndex (int): Mode index

Returns:
    float: Frequency in Hz
getFrequencies() -> numpy.NDArray[numpy.float64]
Get all natural frequencies (Hz) as an array.
getEigenvalue(modeIndex: int, analysisType: AnalysisType = <AnalysisType.NATURAL_FREQUENCIES: 1>) -> float
Get eigenvalue of a mode: squared circular frequency, or buckling load factor.

Args:
    modeIndex (int): Mode index
    analysisType (AnalysisType): NATURAL_FREQUENCIES (default) or LINEAR_BUCKLING
getEigenvalues(analysisType: AnalysisType = <AnalysisType.NATURAL_FREQUENCIES: 1>) -> numpy.NDArray[numpy.float64]
Get the eigenvalues of all modes as an array.
getEigenvectorValue(node: int, dof: int, modeIndex: int, analysisType: AnalysisType = <AnalysisType.NATURAL_FREQUENCIES: 1>) -> float
Get mode shape value of a node and DOF.

Args:
    node (int): Node index
    dof (int): DOF index (0-5)
    modeIndex (int): Mode index
    analysisType (AnalysisType): NATURAL_FREQUENCIES (default) or LINEAR_BUCKLING
getEigenvector(modeIndex: int, analysisType: AnalysisType = <AnalysisType.NATURAL_FREQUENCIES: 1>) -> numpy.NDArray[numpy.float64]
Get mode shape of all nodes, shape (numNodes, 6).
getDisplacementValue(node: int, dof: int, caseOrModeIndex: int = 0, analysisType: AnalysisType = <AnalysisType.NONE: 0>) -> float
Get displacement value for a node and DOF.

Args:
    node (int): Node index
    dof (int): DOF index (0-5)
    caseOrModeIndex (int): Load case index (linear static), unused otherwise
    analysisType (AnalysisType): LINEAR_STATIC, LINEAR_BUCKLING (preload) or TRANSIENT_RESPONSE
                                 (current step); default NONE: the analysis run last

Returns:
    float: Displacement value
getDisplacements(caseIndex: int = 0, analysisType: AnalysisType = <AnalysisType.NONE: 0>) -> numpy.NDArray[numpy.float64]
Get displacements of all nodes, shape (numNodes, 6).

Args:
    caseIndex (int): Load case index (linear static; default 0)
    analysisType (AnalysisType): As for getDisplacementValue (default NONE: the analysis run last)
getVonMisesStress(elemIndex: int, caseIndex: int = 0, analysisType: AnalysisType = <AnalysisType.LINEAR_STATIC: 2>) -> float
Get maximum Von Mises stress of an element.

Args:
    elemIndex (int): Element index
    caseIndex (int): Load case index (linear static; default 0)
    analysisType (AnalysisType): LINEAR_STATIC (default), LINEAR_BUCKLING (preload) or
                                 TRANSIENT_RESPONSE (current step)
getVonMisesStresses(caseIndex: int = 0, analysisType: AnalysisType = <AnalysisType.LINEAR_STATIC: 2>) -> numpy.NDArray[numpy.float64]
Get maximum Von Mises stress of all elements, shape (numElements,).
getNumDofs() -> int
Get number of DOFs in system.

Returns:
    int: Number of DOFs
releaseLicense() -> None
Give the license back to the license server now (the next run takes it again).
getLicenseStamp() -> str
Get the line naming the registered user and the license type, as put on results.
clear() -> None
Clear all data
clearMaterials() -> None
Clear materials
clearProperties() -> None
Clear properties
clearNodes() -> None
Clear nodes
clearElements() -> None
Clear elements
clearConstraints() -> None
Clear constraints
clearMpcs() -> None
Clear multi-point constraints
clearLoad() -> None
Clear loads
exception AfemeError(RuntimeError)

Enumerations

enum AnalysisType
Analysis types (whose results to read)
NONE0The analysis run last
NATURAL_FREQUENCIES1Natural frequencies analysis
LINEAR_STATIC2Linear static analysis
LINEAR_BUCKLING3Linear buckling analysis
TRANSIENT_RESPONSE4Transient response analysis
enum StorageSystem
Storage of the system matrices
SPARSE0Sparse (default)
DENSE1Dense
enum PressureDistribution
How a pressure is passed to the nodes of a face
EQUAL0Equally to the face nodes
SHAPE_FUNCTION1According to the shape functions
enum EigenvaluePerformanceMode
Eigenvalue solver favoring speed or accuracy
SPEED0Speed
ACCURACY1Accuracy