mcpField
L
loopstructural

loopstructural

github.com/steadfastasartData & databases7361 installsUpdated 6w ago
Repository

About loopstructural

loopstructural is a skill for building constrained implicit geological models from observations of continuous scalar fields. It guides users through coordinate conventions, model evaluation, and grid or isosurface export, with validation checks for inputs and outputs.

Key features

  1. 01Build constrained FDI and PLI foliations
  2. 02Evaluate geological feature values
  3. 03Export grids and isosurfaces to VTK
  4. 04Validate coordinates and constraints
  5. 05Report failed or empty exports

Use cases

  1. 01Create a geological model from CSV constraints
  2. 02Evaluate a modeled feature on a grid
  3. 03Export a model grid for visualization
  4. 04Check constraint data before modeling

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/steadfastasart/geoscience-skills --skill loopstructural

After installing, type/loopstructuralin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
geological_features.md
interpolators.md
scripts/
build_model.py

Details

From the project README

Constrained implicit geological models

Use LoopStructural when observations constrain continuous geological scalar fields. A scalar value labels an interface; it is not automatically an age, measured depth or elevation. Record the coordinate CRS, shared XYZ units, positive-Z convention, feature order and meaning of each scalar level.

A constrained planar model

This synthetic example uses metre coordinates with a nonzero origin and an asymmetric box. Its scalar field is Z - 3030 + 0.1*(X - 1050) - 0.05*(Y - 2100) in metres. Scalar observations and gradient constraints anchor both level and orientation; a single point alone cannot define a geological surface.

from itertools import product
from LoopStructural import GeologicalModel
import numpy as np
import pandas as pd

origin = np.array([1000., 2000., 3000.])
maximum = np.array([1100., 2200., 3060.])
xyz = np.array(list(product([1010., 1050., 1090.], [2020., 2180.], [3010., 3050.])))
data = pd.DataFrame(xyz, columns=['X', 'Y', 'Z'])
data['feature_name'] = 'strat'
data['val'] = xyz[:, 2] - 3030 + .1 * (xyz[:, 0] - 1050) - .05 * (xyz[:, 1] - 2100)
data[['gx', 'gy', 'gz']] = [.1, -.05, 1.]
model = GeologicalModel(origin, maximum)
model.data = data
model.create_and_add_foliation('strat', interpolatortype='FDI', nelements=1000)
model.update()
query = np.array([[1020., 2040., 3020.], [1080., 2160., 3040.], [1050., 2100., 3030.]])
values = model.evaluate_feature_value('strat', query)

The expected values are approximately −10, +10 and 0. Pass world coordinates to model.evaluate_feature_value(..., scale=True) (the default). Direct feature evaluation has a different local-coordinate contract. GeologicalModel 1.8 accepts the two bounds positionally; do not assume origin= and maximum= constructor keywords from older examples still work.

Evaluate a VTK grid

Continue with the model above. regular_grid returns an N×3 array; disable shuffling and use Fortran ordering for VTK's x-fastest points. Write actual scalar values into point data before saving.

import pyvista as pv

shape = (9, 7, 5)
points = model.regular_grid(nsteps=shape, shuffle=False, order='F')
grid = pv.StructuredGrid()
grid.points = points
grid.dimensions = shape
grid.point_data['strat'] = model.evaluate_feature_value('strat', points)
surface = grid.contour([0.], scalars='strat')
if not np.isfinite(grid['strat']).all() or surface.n_cells == 0:
    raise ValueError('Model evaluation or requested isosurface is invalid')

Use grid.save('model.vtk') or surface.save('strat.vtk') when export is requested. A rendered surface is a discretized level set; check constraint residuals and mesh convergence before interpreting small structures.

CSV helper and conditional models

The model builder supports constrained FDI/PLI foliations and grid/isosurface export. It validates finite coordinates, complete constraints and positive 3D extents, and reports failed or empty exports with a nonzero exit status. Provide explicit bounds for planar or zero-span input geometry rather than inventing an extent.

python scripts/build_model.py constraints.csv --grid --output model.vtk \
  --origin 1000 2000 3000 --maximum 1100 2200 3060 --nsteps 9 7 5

Resolve the command relative to this installed skill directory. The helper requires X,Y,Z,feature_name, plus val and/or complete gx,gy,gz or nx,ny,nz constraints; each feature needs a scalar level anchor. Missing vector rows are all NaN, not zero vectors.

Read interpolation and validation for numerical choices, and fault/fold requirements only when those structures are needed. Faults, fold frames and uncertainty ensembles need explicit kinematics/data and a separate configured model; they are not created by a nominal CSV column or by this foliation helper.

Verification scope

LoopStructural 1.8.0 with loop-interpolation 0.0.2 was exercised with FDI and PLI planar models, world-coordinate evaluation, asymmetric grid ordering, isosurface and VTK readback, plus malformed-input/CLI failures. This validates the entrypoint and export path, not fault-network inversion, folded geology, uncertainty estimates or the geological adequacy of sparse field constraints.

Official model source, checked 2026-09-14 against the installed 1.8.0 API.

Comments

Markdown supported