API Documentation

This page is the full reference for the public Python API. It is auto-generated from the docstrings in the source.

Most users use fem2geo through YAML configs and never touch these modules directly. If you are writing a custom workflow in Python, the modules below are the building blocks every job is assembled from.

Model

The Model class is the main handler of fem2geo. It wraps a solver output mesh together with a schema and exposes cell-wise arrays (stress, strain, displacement, …) through canonical attribute names.

class fem2geo.model.Model(grid, schema)[source]

Interface to a FEM/BEM model for geomechanical post-processing.

Wraps a mesh loaded from VTK/VTU files and provides named access to stress, strain, kinematic, and scalar fields in ENU coordinates.

Parameters:
  • grid (pyvista.UnstructuredGrid) – Mesh with arrays renamed to canonical names by load_solver_output().

  • schema (ModelSchema) – Schema mapping canonical names to solver-specific array names and units.

See also

Model.from_file

Construct a Model directly from a VTK/VTU path.

avg_principals(name='stress')[source]

Eigenvectors of the the volume-weighted average of a tensor field.

Parameters:

name (str) – Canonical tensor name (default: 'stress').

Returns:

  • val (numpy.ndarray, shape (3,)) – Eigenvalues sorted ascending.

  • vec (numpy.ndarray, shape (3, 3)) – Eigenvectors as columns in ENU coordinates.

Return type:

tuple

avg_tensor(name)[source]

Cell-volume-weighted average of a tensor field.

\[\bar{T}_{ij} = \frac{\sum_c V_c\, T_{ij}^{(c)}}{\sum_c V_c}\]

where \(V_c\) is the volume of cell \(c\) and \(T_{ij}^{(c)}\) is the tensor value at that cell.

Parameters:

name (str) – Tensor name. Accepts schema tensors and computed properties: 'stress', 'stress_dev', 'strain', 'strain_rate', 'strain_plastic', 'strain_elastic'.

Returns:

Symmetric average tensor.

Return type:

numpy.ndarray, shape (3, 3)

property cell_centers: ndarray

Cell center coordinates, shape (N, 3).

property cell_volumes: ndarray

Cell volumes \(V_c\), shape (N,).

property cells: int

Number of cells in the mesh.

property darcy_vel: ndarray

Darcy velocity vector \(q_i\), shape (N, 3).

property dir_s1: ndarray

Maximum compressive principal stress direction \(\mathbf{n}_1\), shape (N, 3).

property dir_s2: ndarray

Intermediate principal stress direction \(\mathbf{n}_2\), shape (N, 3).

property dir_s3: ndarray

Minimum compressive principal stress direction \(\mathbf{n}_3\), shape (N, 3).

eigenvalues(name)[source]

Eigenvalues of a tensor field, sorted ascending (in continuum mechanics convention: compression is negative).

Parameters:

name (str) – Canonical tensor name (e.g. 'stress', 'strain_plastic').

Returns:

Eigenvalues per cell, column 0 smallest (most compressive).

Return type:

numpy.ndarray, shape (N, 3)

eigenvectors(name)[source]

Eigenvectors of a tensor field, sorted by ascending eigenvalue (in continuum mechanics convention: compression is negative).

Parameters:

name (str) – Canonical tensor name (e.g. 'stress', 'strain_plastic').

Returns:

Eigenvectors as columns per cell.

Return type:

numpy.ndarray, shape (N, 3, 3)

extract(center, radius)[source]

Extract cells whose nodes fall within a sphere.

Parameters:
  • center (array-like, shape (3,)) – Sphere center in model coordinates.

  • radius (float) – Sphere radius.

Return type:

Model

property fluid_pressure: ndarray

Fluid pressure \(p_f\), shape (N,).

classmethod from_file(path, schema='adeli')[source]

Load a model from a VTK/VTU file.

Parameters:
  • path (str or Path) – Path to the mesh file.

  • schema (ModelSchema or str) – Schema instance, name of a built-in schema (e.g. "adeli", "adeli2"), or path to a custom schema YAML file.

Return type:

Model

get(canonical)[source]

Look up a named array from cell or point data.

Parameters:

canonical (str)

Return type:

ndarray

property heat_flux: ndarray

Heat flux vector \(q^T_i\), shape (N, 3).

property i1_strain: ndarray

First strain invariant \(I_1(\varepsilon) = \mathrm{tr}\, \varepsilon\), shape (N,).

property i1_strain_rate: ndarray

First strain rate invariant \(I_1(\dot{\varepsilon}) = \mathrm{tr}\,\dot{\varepsilon}\), shape (N,).

property j2_strain: ndarray

Second deviatoric strain invariant \(J_2(\varepsilon) = \tfrac{1}{2} e_{ij} e_{ij}\), shape (N,).

property j2_strain_rate: ndarray

Second deviatoric strain rate invariant \(J_2(\dot{\varepsilon})\), shape (N,).

property j2_stress: ndarray

Second deviatoric stress invariant \(J_2(\sigma) = \tfrac{1}{2} s_{ij} s_{ij}\), shape (N,).

property mean_stress: ndarray

Mean stress (pressure) \(p = \tfrac{1}{3}\,\mathrm{tr}\,\sigma\), shape (N,).

property n_cells: int

Number of cells in the mesh.

property n_points: ndarray

Mesh node coordinates, shape (N_points, 3).

property plastic_eff: ndarray

Effective plastic strain \(\varepsilon^p_{\mathrm{eff}}\), shape (N, ).

property plastic_mode: ndarray

Plastic failure mode, shape (N,).

property plastic_vol: ndarray

Volumetric plastic strain \(\varepsilon^p_{\mathrm{vol}}\), shape (N,).

property plastic_yield: ndarray

Plastic yield indicator, shape (N,).

property points: ndarray

Mesh node coordinates, shape (N_points, 3).

save(path)[source]

Save the model grid to a VTK/VTU file.

Parameters:

path (str or Path) – Output file path.

Return type:

None

property strain: ndarray

Total strain tensor \(\varepsilon_{ij}\), shape (N, 3, 3).

property strain_elastic: ndarray

Elastic strain tensor, shape (N, 3, 3).

Loaded from schema if available, otherwise computed as

\[\varepsilon^e_{ij} = \varepsilon_{ij} - \varepsilon^p_{ij}\]
property strain_plastic: ndarray

Plastic strain tensor \(\varepsilon^p_{ij}\), shape (N, 3, 3).

Loaded from schema if available. Otherwise, reconstructed from plastic_eff and plastic_vol assuming isotropic flow rules.

property strain_rate: ndarray

Total strain rate tensor \(\dot{\varepsilon}_{ij}\), shape (N, 3, 3).

property stress: ndarray

Full stress tensor \(\sigma_{ij}\), shape (N, 3, 3).

Assembled from the schema tensor if available. Otherwise, reconstructed from principal values and directions.

property stress_dev: ndarray

Deviatoric stress tensor, shape (N, 3, 3).

\[s_{ij} = \sigma_{ij} - \tfrac{1}{3}\,\sigma_{kk}\,\delta_{ij}\]
property t: ndarray

Time field \(t\), shape (N,).

property temperature: ndarray

Temperature field \(T\), shape (N,).

property threshold_ratio: ndarray

Yield threshold ratio, shape (N,).

property u: ndarray

Displacement vector \(u_i\), shape (N, 3).

property v: ndarray

Velocity vector \(v_i\), shape (N, 3).

property val_s1: ndarray

Most compressive principal stress \(\sigma_1\), shape (N,).

Loaded from the grid if available, otherwise the smallest eigenvalue of the stress tensor.

property val_s2: ndarray

Intermediate principal stress \(\sigma_2\), shape (N,).

Loaded from the grid if available, otherwise computed as -(val_s1 + val_s3) (deviatoric trace-free condition).

property val_s3: ndarray

Least compressive principal stress \(\sigma_3\), shape (N,).

Loaded from the grid if available, otherwise the largest eigenvalue of the stress tensor.

property viscosity: ndarray

Effective viscosity \(\eta\), shape (N,).

Structural data

Lightweight containers for structural measurements loaded from CSVs. Used as the data entry of a site.

class fem2geo.data.CatalogData(x, y, z, attrs=<factory>)[source]

Point catalog with per-point numeric attributes.

Used for earthquake catalogs, sample locations, observation points, or any tabular dataset where each row has a position and a set of measured values.

Parameters:
class fem2geo.data.FaultData(planes, rakes)[source]

Fault slip data, represented as plane orientation plus rake.

Rake follows the Aki & Richards convention, measured in the fault plane from the strike direction, positive toward hanging-wall up-dip. Range is (-180, 180].

  • rake > 0: reverse/thrust component (hanging wall up).

  • rake < 0: normal component (hanging wall down).

  • rake = 0: pure left-lateral.

  • rake = ±180: pure right-lateral.

Parameters:
  • planes (numpy.ndarray, shape (N, 2)) – Strike and dip pairs in degrees, right-hand rule.

  • rakes (numpy.ndarray, shape (N,)) – Signed rake in degrees.

class fem2geo.data.FractureData(planes)[source]

Orientation measurements for planar features (joints, veins, dykes).

Parameters:

planes (numpy.ndarray, shape (N, 2)) – Strike and dip pairs in degrees, right-hand rule.

Schema

Maps solver-specific array names to the canonical names that fem2geo uses everywhere. Users writing custom schemas interact with ModelSchema through the load() dispatcher, which accepts a built-in name, a file path, an inline dict, or an existing instance.

class fem2geo.internal.schema.ModelSchema(name, fields, tensors=<factory>)[source]

Translates between solver-specific array names and canonical fem2geo names.

Parameters:
  • name (str) – Schema identifier (e.g. solver name).

  • fields (dict[str, ScalarEntry]) – Scalar and vector field mappings.

  • tensors (dict[str, TensorEntry]) – Symmetric tensor mappings, keyed by canonical name.

classmethod builtin(name)[source]

Load one of the bundled schemas by name.

Parameters:

name (str) – Schema name (e.g. "adeli"). Must match a YAML file under fem2geo/internal/schemas/.

Return type:

ModelSchema

fields: dict[str, ScalarEntry]
classmethod from_dict(d)[source]

Build a schema from a raw config dictionary.

Parameters:

d (dict) – Schema definition, normally loaded from YAML.

Return type:

ModelSchema

classmethod from_yaml(path)[source]

Load a schema from a YAML file on disk.

Parameters:

path (str or Path) – Path to the YAML schema file.

Return type:

ModelSchema

classmethod load(arg, base_dir=None)[source]

Load a schema from a built-in name, a file path, an inline dict, or pass through an existing instance.

  • If arg is already a ModelSchema, return it unchanged.

  • If arg is a dict, build a schema from it directly.

  • If arg looks like a path (contains a separator or ends in .yaml / .yml), resolve against base_dir and load the YAML file.

  • Otherwise treat it as a built-in schema name.

Parameters:
  • arg (str or Path or dict or ModelSchema) – Built-in name, path to a YAML file, inline schema definition, or a schema instance.

  • base_dir (str or Path, optional) – Directory used to resolve relative paths. Usually the directory of the config file that referenced the schema.

Return type:

ModelSchema

name: str
tensors: dict[str, TensorEntry]
class fem2geo.internal.schema.ScalarEntry(canonical, solver_key)[source]

Single scalar or vector field mapping.

Parameters:
  • canonical (str) – Internal fem2geo name for this field.

  • solver_key (str) – Array name used by the solver output file.

canonical: str
solver_key: str
class fem2geo.internal.schema.TensorEntry(canonical, voigt6=None, components=None)[source]

Symmetric 3x3 tensor mapping.

Either voigt6 (single packed array, Voigt order [xx, yy, zz, xy, yz, zx]) or components (dict of component labels to solver array names) must be set, not both.

Parameters:
  • canonical (str) – Internal fem2geo name for this tensor.

  • voigt6 (str, optional) – Solver array name for the packed (N, 6) representation.

  • components (dict[str, str], optional) – Map from component label to solver array name.

canonical: str
components: dict[str, str] | None = None
property is_packed: bool
voigt6: str | None = None

Tensor

Pure tensor math. These functions take numpy arrays (averaged tensors, plane orientations, fault rakes) and return scalars, vectors, or new tensors. They are solver-agnostic.

fem2geo.utils.tensor.axes_misfit(vecs_a, vecs_b)[source]

Angular misfit between two sets of principal axes.

Parameters:
  • vecs_a (array-like, shape (3, 3)) – Eigenvectors as columns (e.g. from Kostrov tensor).

  • vecs_b (array-like, shape (3, 3)) – Eigenvectors as columns (e.g. from model tensor).

Returns:

  • angles (numpy.ndarray, shape (3,)) – Misfit angle in degrees for each matched pair.

  • pairs (list of (int, int)) – Index pairs (i_a, i_b) giving the matching.

fem2geo.utils.tensor.dilation_tendency(sigma, strikes, dips, eps=1e-12)[source]

Dilation tendency \(T_d = (\sigma_1 - \sigma_n) / (\sigma_1 - \sigma_3)\).

Parameters:
  • sigma (array-like, shape (3, 3)) – Stress tensor in ENU coordinates.

  • strikes (float or array-like) – Strike angle(s) in degrees.

  • dips (float or array-like) – Dip angle(s) in degrees.

  • eps (float) – Threshold for treating \((\sigma_1 - \sigma_3)\) as zero (near-isotropic).

Returns:

Dilation tendency values. Scalar if input is scalar, array otherwise.

Return type:

numpy.ndarray or float

Notes

For \(\sigma_1\) = min(eigenvalues), \(\sigma_3\) = max(eigenvalues) and near-isotropic tensors where \(|\sigma_1 - \sigma_3| < \epsilon\), returns NaN.

fem2geo.utils.tensor.eigenvalues(tensors)[source]

Eigenvalues of an array of symmetric 3x3 tensors, sorted ascending.

Parameters:

tensors (array-like, shape (N, 3, 3))

Returns:

Eigenvalues per cell, column 0 smallest (most compressive).

Return type:

numpy.ndarray, shape (N, 3)

fem2geo.utils.tensor.eigenvectors(tensors)[source]

Eigenvectors of an array of symmetric 3x3 tensors.

Parameters:

tensors (array-like, shape (N, 3, 3))

Returns:

Eigenvectors as columns, sorted by ascending eigenvalue.

Return type:

numpy.ndarray, shape (N, 3, 3)

fem2geo.utils.tensor.kostrov_tensor(strikes, dips, rakes)[source]

Kostrov (1974) summed moment tensor from a fault population.

Each fault contributes a symmetric dyad 1/2(s*n + n*s) where s is the unit slip vector (from signed rake) and n is the fault normal. The sum gives a tensor whose eigenvectors are the bulk kinematic axes (shortening, intermediate, extension).

All faults are weighted equally (unit potency).

Parameters:
  • strikes (array-like, shape (N,)) – Strike in degrees (right-hand rule).

  • dips (array-like, shape (N,)) – Dip in degrees.

  • rakes (array-like, shape (N,)) – Signed rake in degrees (Aki & Richards, (-180, 180]).

Returns:

Symmetric Kostrov tensor in ENU coordinates.

Return type:

numpy.ndarray, shape (3, 3)

fem2geo.utils.tensor.reconstruct_from_principals(values, directions)[source]

Build symmetric tensors from principal values and directions.

Computes the dyad sum \(\sum_i v_i (d_i \otimes d_i)\) per cell.

Parameters:
  • values (array-like, shape (N, 3)) – Principal values per cell, columns ordered to match directions.

  • directions (array-like, shape (N, 3, 3)) – Principal directions stored as columns: directions[:, :, i] is the i-th eigenvector.

Return type:

numpy.ndarray, shape (N, 3, 3)

fem2geo.utils.tensor.resolved_rake(T, strikes, dips, eps=1e-12)[source]

Predicted slip rake from the resolved shear component of a tensor on each fault.

For each plane, resolves the in-plane shear component of the tensor and converts it to a signed rake (Aki & Richards). Faults where the shear magnitude is below eps get NaN.

Parameters:
  • T (array-like, shape (3, 3)) – Symmetric tensor in ENU coordinates (stress, strain, strain rate, …).

  • strikes (array-like, shape (N,)) – Strike angles in degrees.

  • dips (array-like, shape (N,)) – Dip angles in degrees.

  • eps (float) – Threshold below which the shear component is treated as zero.

Returns:

Predicted signed rake in degrees. NaN where the in-plane shear component is negligible.

Return type:

numpy.ndarray, shape (N,)

fem2geo.utils.tensor.resolved_shear_enu(sigma, plane=None, normal=None, eps=1e-12)[source]

Resolve shear traction of a stress tensor on a plane (ENU).

Parameters:
  • sigma (array-like, shape (3, 3)) – Stress tensor in ENU coordinates.

  • plane (array-like, shape (2,), optional) – [strike, dip] in degrees (right-hand rule).

  • normal (array-like, shape (3,), optional) – Plane unit normal in ENU coordinates [E, N, U].

  • eps (float) – Threshold for treating shear magnitude as zero.

Returns:

  • tau (float) – Shear traction magnitude (always non-negative).

  • tau_hat (numpy.ndarray, shape (3,)) – Directed unit shear traction vector in ENU. Vector carries kinematic sense.

Notes

tau_hat is the direction in which material on the positive-normal side of the plane is pushed by shear stress.

fem2geo.utils.tensor.rot_tensor(tensor, angle, axis)[source]

Rotate a 2nd-order tensor by a given axis and angle.

Parameters:
  • tensor (array-like, shape (3, 3)) – Tensor to rotate.

  • angle (float) – Rotation angle in degrees.

  • axis (int) – Axis index: 0=x(E), 1=y(N), 2=z(U).

Returns:

Rotated tensor.

Return type:

numpy.ndarray, shape (3, 3)

fem2geo.utils.tensor.slip_tendency(sigma, strikes, dips, eps=1e-12)[source]

Normalized slip tendency Ts’ for one or many planes.

Computes \(|\tau| / |\sigma_n|\) normalized by the maximum slip tendency achievable in the given stress state, so the result is always in [0, 1]. A value of 1 corresponds to the optimally oriented plane for slip (Morris et al., 1996).

The maximum slip tendency is found analytically from the three 2D Mohr circles defined by pairs of principal stresses.

Parameters:
  • sigma (array-like, shape (3, 3)) – Stress tensor in ENU coordinates.

  • strikes (float or array-like) – Strike angle(s) in degrees.

  • dips (float or array-like) – Dip angle(s) in degrees.

  • eps (float) – Threshold for treating sigma_n or Ts_max as zero.

Returns:

Normalized slip tendency in [0, 1]. Scalar if input is scalar, array otherwise.

Return type:

numpy.ndarray or float

References

Morris, A., Ferrill, D. A., & Henderson, D. B. (1996). Slip-tendency analysis and fault reactivation. Geology, 24(3), 275-278.

fem2geo.utils.tensor.summarized_tendency(sigma, strikes, dips, eps=1e-12)[source]

Summarized reactivation tendency: Ts’ + Td.

Sums the normalized slip tendency (Morris et al., 1996) and the dilation tendency (Ferrill et al., 1999). Both components are in [0, 1], so the result ranges from 0 (stable) to 2 (maximum reactivation potential).

Parameters:
  • sigma (array-like, shape (3, 3)) – Stress tensor in ENU coordinates.

  • strikes (float or array-like) – Strike angle(s) in degrees.

  • dips (float or array-like) – Dip angle(s) in degrees.

  • eps (float) – Threshold for near-zero denominators.

Returns:

Combined tendency values in [0, 2].

Return type:

numpy.ndarray or float

References

Ferrill, D. A., Smart, K. J., & Morris, A. P. (2020). Fault failure modes, deformation mechanisms, dilation tendency, slip tendency, and conduits v. seals. Geol. Soc. Lond. Spec. Publ., 496, 75-98.

fem2geo.utils.tensor.unpack_components(arrays)[source]

Assemble (N, 3, 3) symmetric tensors from a dict of component arrays.

Parameters:

arrays (dict[str, array-like]) – Maps component labels (xx, yy, zz, xy, yz, zx) to (N,) arrays.

Return type:

numpy.ndarray, shape (N, 3, 3)

fem2geo.utils.tensor.unpack_voigt6(tensor_voight)[source]

Unpack (N, 6) Voigt-ordered array into (N, 3, 3) symmetric tensors.

Voigt ordering: [xx, yy, zz, xy, yz, zx].

Parameters:

tensor_voight (array-like, shape (N, 6))

Return type:

numpy.ndarray, shape (N, 3, 3)

fem2geo.utils.tensor.validate_normals(normals)[source]

Validate and normalize ENU normal vectors.

Parameters:

normals (array-like, shape (3,) or (N, 3)) – Normal vector(s) in ENU coordinates.

Returns:

Unit normal vector(s), always 2-D.

Return type:

numpy.ndarray, shape (N, 3)

Transform

Geometric transformations between coordinate conventions: line and plane representations, ENU ↔ NED, rake ↔ spherical, grid builders for stereonet sampling.

fem2geo.utils.transform.enu2ned(v)[source]

Convert vector(s) from ENU to NED.

Swaps first two components and negates the third: [E, N, U] -> [N, E, D].

Parameters:

v (array-like, shape (..., 3))

Return type:

numpy.ndarray, same shape as input

fem2geo.utils.transform.grid_centers(mesh_strikes, mesh_dips)[source]

Compute cell-center strike/dip arrays from node grids.

Parameters:
Returns:

strikes_c, dips_c – Cell-center strike and dip arrays.

Return type:

numpy.ndarray

fem2geo.utils.transform.grid_nodes(n_strikes, n_dips)[source]

Create node grids for stereonet discretization.

Parameters:
  • n_strikes (int) – Number of strike bins. Nodes: n_strikes + 1 columns.

  • n_dips (int) – Number of dip bins. Nodes: n_dips + 1 rows.

Returns:

mesh_strikes, mesh_dips – Meshgrids of strike and dip nodes (degrees).

Return type:

numpy.ndarray

fem2geo.utils.transform.line_enu2rake(enu, strike, dip, check=False, tol=0.005)[source]

ENU axis on a plane to unsigned rake.

Projects the vector onto the plane’s strike and updip directions and returns the angle in [0, 180]. Since lines are axes (v and -v equivalent), the result is the same for both orientations.

Parameters:
  • enu (array-like, shape (3,) or (N, 3))

  • strike (float or array-like)

  • dip (float or array-like)

  • check (bool) – If True, verify the line lies in the plane (scalar input only).

  • tol (float) – Tolerance for the containment check.

Returns:

rake – Unsigned rake in degrees [0, 180].

Return type:

float or numpy.ndarray

fem2geo.utils.transform.line_enu2sphe(enu)[source]

ENU unit axis to spherical line coordinates.

Parameters:

enu (array-like, shape (3,) or (N, 3))

Returns:

  • plunge (float or numpy.ndarray, shape (N,))

  • azimuth (float or numpy.ndarray, shape (N,))

fem2geo.utils.transform.line_ned2sphe(ned)[source]

NED unit axis to spherical line coordinates.

Parameters:

ned (array-like, shape (3,) or (N, 3))

Returns:

  • plunge (float or numpy.ndarray, shape (N,)) – Plunge in degrees [0, 90].

  • azimuth (float or numpy.ndarray, shape (N,)) – Azimuth in degrees [0, 360). Returns 0 for vertical lines.

fem2geo.utils.transform.line_rake2sphe(strike, dip, rake)[source]

Unsigned rake on a plane to spherical line coordinates.

Parameters:
  • strike (float or array-like)

  • dip (float or array-like)

  • rake (float or array-like) – Unsigned rake in degrees [0, 180].

Returns:

  • plunge (float or numpy.ndarray, shape (N,))

  • azimuth (float or numpy.ndarray, shape (N,))

fem2geo.utils.transform.line_sphe2enu(plunge, azimuth)[source]

Spherical line coordinates to ENU unit axis.

Parameters:
  • plunge (float or array-like)

  • azimuth (float or array-like)

Return type:

numpy.ndarray, shape (3,) or (N, 3)

fem2geo.utils.transform.line_sphe2ned(plunge, azimuth)[source]

Spherical line coordinates to NED unit axis.

Parameters:
  • plunge (float or array-like) – Plunge in degrees (>= 0).

  • azimuth (float or array-like) – Azimuth in degrees, clockwise from North.

Returns:

NED direction cosines, canonicalized D >= 0.

Return type:

numpy.ndarray, shape (3,) or (N, 3)

fem2geo.utils.transform.ned2enu(v)[source]

Convert vector(s) from NED to ENU.

Same operation as enu2ned() (inverse mapping).

Parameters:

v (array-like, shape (..., 3))

Return type:

numpy.ndarray, same shape as input

fem2geo.utils.transform.plane_basis_enu(strike, dip)[source]

Orthonormal basis vectors of a fault plane in ENU.

Returns the strike direction, the dip vector (steepest descent line in the plane), and the plane normal_vec. All three are mutually orthogonal unit vectors forming a right-handed basis.

The dip vector plunges at the dip angle toward strike + 90°. The normal_vec points away from the dipping side (upward for non-vertical planes).

Parameters:
  • strike (float or array-like)

  • dip (float or array-like)

Returns:

  • strike_vec (numpy.ndarray, shape (3,) or (N, 3)) – Horizontal unit vector along the strike azimuth.

  • dip_vec (numpy.ndarray, shape (3,) or (N, 3)) – Unit vector plunging at the dip angle toward the dip direction.

  • normal_vec (numpy.ndarray, shape (3,) or (N, 3)) – Unit normal_vec to the plane (= strike_vec × dip_vec).

fem2geo.utils.transform.plane_pole2sphe(plunge, azimuth)[source]

Plane pole (plunge/azimuth) to strike/dip.

Parameters:
  • plunge (float or array-like)

  • azimuth (float or array-like)

Returns:

  • strike (float or numpy.ndarray)

  • dip (float or numpy.ndarray)

fem2geo.utils.transform.plane_sphe2enu(strike, dip)[source]

Plane (strike/dip) to ENU unit normal.

Computes the normal as the cross product of the strike direction (horizontal, azimuth = strike) and the dip vector (plunging with dip angle toward strike + 90°).

Parameters:
  • strike (float or array-like)

  • dip (float or array-like)

Return type:

numpy.ndarray, shape (3,) or (N, 3)

fem2geo.utils.transform.plane_sphe2ned(strike, dip)[source]

Plane (strike/dip) to NED unit normal, canonicalized Down >= 0.

Computes the normal as the cross product of the strike direction and the dip vector, both in NED coordinates.

Parameters:
  • strike (float or array-like)

  • dip (float or array-like)

Return type:

numpy.ndarray, shape (3,) or (N, 3)

fem2geo.utils.transform.slip_enu2rake(enu, strike, dip)[source]

Directed ENU vector to signed rake (Aki & Richards).

Projects the vector onto the fault plane’s strike and updip directions and returns rake in degrees.

Parameters:
  • enu (array-like, shape (3,) or (N, 3))

  • strike (float or array-like)

  • dip (float or array-like)

Returns:

rake – Signed rake in degrees (-180, 180].

Return type:

float or numpy.ndarray

fem2geo.utils.transform.slip_rake2enu(strike, dip, rake)[source]

Signed rake to directed slip vector in ENU.

Uses the Aki & Richards convention:

  • rake > 0: reverse/thrust (hanging wall up).

  • rake < 0: normal (hanging wall down).

  • rake = 0: pure left-lateral.

  • rake = +/-180: pure right-lateral.

Parameters:
  • strike (float or array-like)

  • dip (float or array-like)

  • rake (float or array-like) – Signed rake in degrees (-180, 180].

Returns:

Directed unit slip vector in ENU.

Return type:

numpy.ndarray, shape (3,) or (N, 3)

fem2geo.utils.transform.unit(v)[source]

Return the unit vector of v (single vector only).

Parameters:

v (array-like, shape (3,))

Return type:

numpy.ndarray, shape (3,)

Plots

Stereonet plotting. Every function takes a matplotlib Axes (with the stereonet projection) as its first argument and draws into it.

fem2geo.plots.get_style(default, *overrides, drop=('show', 'style'), **kw)[source]

Merge style dicts into a matplotlib-ready kwargs dict.

Parameters:
  • default (dict) – Base style.

  • *overrides (dict) – Successive override dicts (typically user config).

  • drop (tuple of str) – Keys to strip from the result.

  • **kw – Final per-call overrides (e.g. marker="o").

fem2geo.plots.stereo_arrow(ax, from_xy, to_xy, color='k', arrowsize=1.0, linewidth=1.0, alpha=1.0, label=None, **kwargs)[source]

Plot a directed arrow on a stereonet between two projected points.

fem2geo.plots.stereo_axes(ax, vecs, style, labels=None, markers=('o', 's', 'v'))[source]

Plot a 3-axis frame on a stereonet as line markers.

Parameters:
  • ax (mplstereonet axes)

  • vecs (numpy.ndarray) – Either (3, 3) for a single frame or (N, 3, 3) for N frames. Axes are stored as columns: vecs[..., :, i] is the i-th axis.

  • style (dict) – Base style. Marker is overridden per axis.

  • labels (tuple of str, optional) – Three labels for the legend.

  • markers (tuple of str) – Markers for axes 1, 2, 3. Defaults to circle, square, triangle.

fem2geo.plots.stereo_axes_contour(ax, vecs, style)[source]

Plot a 3-axis frame on a stereonet as density contours.

Parameters:
  • ax (mplstereonet axes)

  • vecs (numpy.ndarray) – Either (3, 3) for a single frame or (N, 3, 3) for N frames. Axes are columns: vecs[..., :, i] is the i-th axis.

  • style (dict) – Contour style (color, levels, sigma, linewidth).

fem2geo.plots.stereo_contour(ax, plunge, azimuth=None, color='k', levels=4, sigma=2, linewidth=1.0, **kwargs)[source]

Plot kernel density contour lines of line elements on a stereonet. Accepts separate arrays or a packed (N, 2) array.

fem2geo.plots.stereo_field(ax, mesh_strikes, mesh_dips, values, cmap='viridis', vmin=None, vmax=None, levels=None, cbar=True, cbar_label=None, cbar_kwargs=None)[source]

Draw a pre-computed scalar field on a stereonet as a pcolormesh.

Parameters:
  • ax (mplstereonet axes)

  • mesh_strikes (numpy.ndarray) – Node grids from grid_nodes().

  • mesh_dips (numpy.ndarray) – Node grids from grid_nodes().

  • values (numpy.ndarray) – Scalar values at cell centers, shape (n_dips, n_strikes).

  • cmap (str) – Colormap name.

  • vmin (float, optional) – Color scaling bounds.

  • vmax (float, optional) – Color scaling bounds.

  • levels (int or sequence of float, optional) – Discrete bins. If int, creates levels evenly-spaced bins between vmin and vmax. If a sequence, uses its values as bin edges directly. If None, draws a continuous colormap.

  • cbar (bool) – If True, attach a colorbar to the figure. If False, only draw the pcolormesh and return the mappable.

  • cbar_label (str, optional) – Colorbar label.

  • cbar_kwargs (dict, optional) – Extra kwargs forwarded to fig.colorbar.

Returns:

The pcolormesh mappable.

Return type:

mappable

fem2geo.plots.stereo_line(ax, plunge, azimuth=None, label=None, **kwargs)[source]

Plot line elements on a stereonet. Accepts separate arrays or a packed (N, 2) array.

fem2geo.plots.stereo_plane(ax, strike, dip=None, label=None, **kwargs)[source]

Plot great circles on a stereonet. Accepts separate arrays or a packed (N, 2) array.

fem2geo.plots.stereo_pole(ax, strike, dip=None, label=None, **kwargs)[source]

Plot poles to planes on a stereonet. Accepts separate arrays or a packed (N, 2) array.

fem2geo.plots.stereo_slip_arrow(ax, strike, dip, signed_rake, color='k', arrowsize=1.0, linewidth=1.0, length=0.08, label=None)[source]

Draw slip direction arrows on a stereonet for fault planes.

Each arrow is anchored at the slip line’s stereonet position and points toward the pole for reverse sense (rake > 0) or away for normal sense (rake < 0), following the Aki & Richards convention.

Parameters:
  • ax (mplstereonet axes)

  • strike (float or array-like) – Fault plane orientation(s) in degrees.

  • dip (float or array-like) – Fault plane orientation(s) in degrees.

  • signed_rake (float or array-like) – Signed rake in degrees (Aki & Richards, (-180, 180]).

  • color (str)

  • arrowsize (float) – Scales arrow head size.

  • linewidth (float)

  • length (float) – Arrow length in projected stereonet coordinates (radians).

  • label (str, optional) – Applied only to the first arrow.

Projector

Translates, scales, reprojects, and optionally rotates georeferenced data into a local model frame. Used by the project job.

class fem2geo.projector.Projector(src_crs, dst_crs, src_xy_units='deg', dst_xy_units='m', src_z_units='km', dst_z_units='m', src_z_positive='down', dst_z_positive='up', anchor_geo=None, anchor_local=None, rotation_deg=None)[source]

Transform georeferenced coordinates into a real-world or local cartesian frame.

A Projector holds a source/destination CRS pair, unit and sign conventions for XY and Z, and an optional alignment anchor that pins a chosen geographic point to a chosen local coordinate, with optional rotation around that anchor. Projector can be used to transform raw arrays, CatalogData objects, or meshes.

Parameters:
  • src_crs (str or pyproj.CRS) – Source and destination coordinate reference systems.

  • dst_crs (str or pyproj.CRS) – Source and destination coordinate reference systems.

  • src_xy_units (str) – "deg" for a geographic source, "m" or "km" for projected coordinates.

  • dst_xy_units (str) – "deg" for a geographic source, "m" or "km" for projected coordinates.

  • src_z_units (str) – "m" or "km".

  • dst_z_units (str) – "m" or "km".

  • src_z_positive (str) – "up" or "down".

  • dst_z_positive (str) – "up" or "down".

  • anchor_geo (tuple, optional) – (lon, lat, depth_km) of a reference point. Depth is positive downward. Must be set together with anchor_local.

  • anchor_local (tuple, optional) – (x, y, z) of the same reference point in the local frame, in dst_xy_units and following dst_z_positive.

  • rotation_deg (float, optional) – Counter-clockwise rotation around the anchor, in degrees. Requires an anchor.

transform(x, y, z)[source]

Transform arrays of source coordinates into the local frame.

Parameters:
  • x (array-like) – XY in the source CRS, in src_xy_units.

  • y (array-like) – XY in the source CRS, in src_xy_units.

  • z (array-like) – Z in src_z_units following src_z_positive.

Returns:

X, Y, Z – Coordinates in the local frame.

Return type:

numpy.ndarray

transform_catalog(cat)[source]

Project a CatalogData into the local frame.

Parameters:

cat (CatalogData) – Catalog in source coordinates.

Returns:

A new catalog with transformed coordinates. The original attrs are copied through unchanged.

Return type:

CatalogData

transform_mesh(mesh)[source]

Project a PyVista mesh into the local frame.

Mesh points are assumed to be ENU (Z positive up) with all three components in src_xy_units. Cell connectivity and data arrays are preserved; the input mesh is not modified.

Parameters:

mesh (pyvista.DataSet)

Returns:

A copy of the input mesh with transformed points.

Return type:

pyvista.DataSet

transform_points(points)[source]

Transform an (N, 3) array of source coordinates.

Column 0 is X in src_xy_units, column 1 is Y in src_xy_units, column 2 is Z in src_z_units following src_z_positive. XY and Z units are independent, unlike in transform_mesh().

Parameters:

points (array-like, shape (N, 3))

Returns:

Transformed coordinates in the local frame.

Return type:

numpy.ndarray, shape (N, 3)

Projections

Helpers for the project job: unit conversions, CRS reprojection, bounding-box filtering, and related utilities.

fem2geo.utils.projections.bbox_mask(lon, lat, depth_km, lon_range=None, lat_range=None, depth_range_km=None)[source]

Boolean mask from optional lon/lat/depth ranges. Any range left as None is ignored.

fem2geo.utils.projections.bbox_to_crs_bounds(bbox, crs)[source]

Convert a lon/lat bbox into (left, bottom, right, top) in a target CRS’s native units.

Parameters:
  • bbox (dict) – Mapping with optional lon and lat keys.

  • crs (str or pyproj.CRS) – Target CRS.

Returns:

(left, bottom, right, top), or None if bbox has neither lon nor lat set.

Return type:

tuple or None

fem2geo.utils.projections.bbox_to_src_bounds(bbox, crs, xy_units, z_units, z_positive)[source]

Convert a lon/lat/depth_km bbox into source-frame axis bounds.

Parameters:
  • bbox (dict) – Mapping with optional lon, lat, depth_km keys, each a [min, max] pair.

  • crs (str or pyproj.CRS) – Source CRS.

  • xy_units (str) – "deg" | "m" | "km".

  • z_units (str) – "m" | "km".

  • z_positive (str) – "up" | "down".

Returns:

[xmin, xmax, ymin, ymax, zmin, zmax] in source units and sign convention. Missing axes become -inf / inf.

Return type:

list

fem2geo.utils.projections.flip_z(z, src_positive, dst_positive)[source]

Convert a Z array between up/down sign conventions. Negates if the conventions differ, returns the input unchanged otherwise.

fem2geo.utils.projections.reproject_xy(x, y, src_crs, dst_crs)[source]

Reproject XY arrays from one CRS to another using pyproj.

Parameters:
  • x (array-like) – Coordinates in the source CRS, in its native units.

  • y (array-like) – Coordinates in the source CRS, in its native units.

  • src_crs (str or pyproj.CRS) – Source and destination CRSs (e.g. "epsg:4326").

  • dst_crs (str or pyproj.CRS) – Source and destination CRSs (e.g. "epsg:4326").

Returns:

X, Y – Coordinates in the destination CRS, in its native units.

Return type:

numpy.ndarray

fem2geo.utils.projections.rotate_xy(x, y, x0, y0, angle_deg)[source]

Rotate XY arrays counter-clockwise around a pivot.

fem2geo.utils.projections.to_lonlat(x, y, src_crs, src_xy_units)[source]

Back-project source XY to lon/lat (EPSG:4326) for bbox filtering.

If the source CRS is already geographic, returns the inputs unchanged (apart from array conversion). For projected sources, scales XY to meters using src_xy_units before reprojecting.

Parameters:
  • x (array-like) – Coordinates in the source CRS.

  • y (array-like) – Coordinates in the source CRS.

  • src_crs (str or pyproj.CRS)

  • src_xy_units (str) – "deg" for geographic sources, "m" or "km" for projected.

Returns:

lon, lat – Coordinates in degrees, EPSG:4326.

Return type:

numpy.ndarray

fem2geo.utils.projections.unit_factor(unit)[source]

Meters per unit for "m" or "km".

IO

File loaders for solver outputs, meshes, rasters, and structural CSVs.

fem2geo.internal.io.load_catalog_csv(path, columns)[source]

Read a point catalog from a CSV file.

The three coordinate columns become x, y, z; remaining numeric columns become attrs. Non-numeric columns are dropped with a warning. Empty cells in numeric columns are read as NaN.

Parameters:
  • path (str or Path) – CSV file with a header row.

  • columns (tuple of str) – (x_col, y_col, z_col) column names.

Return type:

CatalogData

fem2geo.internal.io.load_mesh(path)[source]

Read a PyVista mesh from a VTK file (.vtp, .vtu, .vtk).

Raises if the file is empty.

Return type:

DataSet

fem2geo.internal.io.load_raster(path, z_band=None, window=None)[source]

Read a GeoTIFF as a triangulated PolyData surface.

Each pixel center becomes a point in the raster’s own CRS. Bands are attached as point_data arrays. If z_band is given, that band drives the Z coordinate; otherwise Z is zero everywhere. An optional rasterio window restricts the read.

Parameters:
  • path (str or Path) – GeoTIFF file.

  • z_band (int, optional) – 1-indexed band to use as elevation.

  • window (rasterio.windows.Window, optional) – Sub-window to read. Defaults to the full raster.

Returns:

Triangulated surface with one point per pixel and point_data arrays for every band plus a valid mask.

Return type:

pyvista.PolyData

fem2geo.internal.io.load_solver_output(path, schema='adeli')[source]

Load a FEM result file and rename arrays to canonical names.

Scalar and vector fields are renamed one-to-one from the schema. Tensor arrays are renamed so they can be reassembled later by canonical key. Directional fields (dir_*) are normalized to unit vectors.

Parameters:

schema (ModelSchema | str)

Return type:

UnstructuredGrid

fem2geo.internal.io.load_structural_csv(path)[source]

Read structural measurements from a CSV file.

Files with strike/dip/rake columns produce FaultData; strike/dip only gives FractureData.

Return type:

FractureData | FaultData

Runner

Top-level entry point for YAML-driven jobs. run() loads a config file, dispatches to the requested job module, and writes the output. main() is the CLI entry point bound to the fem2geo command.

fem2geo.runner.load_config(path)[source]
Parameters:

path (Path)

Return type:

dict

fem2geo.runner.main()[source]
Return type:

None

fem2geo.runner.resolve_output(cfg, job_dir)[source]

Resolve the output directory and create it.

Returns the output block with dir resolved to an absolute Path. Creates the directory if it doesn’t exist.

Parameters:
  • cfg (dict) – Full job config as loaded from YAML.

  • job_dir (Path) – Directory containing the config file (used as default output directory).

Returns:

The output config with dir set to an absolute Path.

Return type:

dict

fem2geo.runner.run(job_path, output_dir=None)[source]

Load a job config file and dispatch to the appropriate job module.

Parameters:
  • job_path (Path) – Path to the job YAML file.

  • output_dir (Path, optional) – Override the output directory from the config. Useful for testing.

Raises:
Return type:

None