# welleng
**Repository Path**: SpikeXue_admin/welleng
## Basic Information
- **Project Name**: welleng
- **Description**: well design library
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2021-10-25
- **Last Updated**: 2026-07-12
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# welleng
[](https://github.com/jonnymaserati/welleng/blob/main/LICENSE)
[](https://pypi.org/project/welleng/)
[](https://pepy.tech/project/welleng)
[](https://opensource.org/licenses/Apache-2.0)
[](https://github.com/jonnymaserati/welleng/actions)
[](https://doi.org/10.5281/zenodo.20968887)
[welleng] is a collection of tools for Wells/Drilling Engineers, with a focus on well trajectory design and analysis.
## Features
- **Survey listings** — generate and interpolate well trajectories using minimum curvature or maximum curvature methods
- **Well bore uncertainty** — ISCWSA MWD Rev 5.11 error model (validated 35/35 sources against all three ISCWSA example workbooks), legacy Rev4 for back-compat, and OWSG **gyro** tool stacks (north-seeking stationary, mixed continuous, gyro-MWD) driven by the new ISCWSA JSON schema and an Excel-formula interpreter
- **Clearance & Separation Factors** — the standard ISCWSA separation rule (within 0.5% of ISCWSA test data), the **exact combined-ellipsoid Mahalanobis method** (`MahalanobisClearance` — same collision/clear verdicts as the rule but up to ~1.47× less conservative, analytic and mesh-free), and a mesh-based method using the [Flexible Collision Library]
- **Well path creation** — the `connector` module builds trajectories between start/end locations automatically, backed by an analytic, vectorized closed-form curve-hold-curve (CLC) point-to-target solver (`sawaryn_analytical` — every solution + the minimum-measured-depth path) with radius-sweep and R1×R2 drillable-region tooling
- **Vertical section, TVD interpolation, project-ahead** — common survey planning tools
- **Torque and drag** — simple torque/drag model with architecture module
- **Visualization** — interactive 3D via [vedo]/VTK or browser-based via plotly (requires `easy` install)
- **Data exchange** — import/export Landmark .wbp files; read EDM datasets
- **World Magnetic Model** — auto-calculates magnetic field data when not supplied
### Selecting an error model
`Survey`/`SurveyHeader` take an `error_model` name — **switch models by changing the
string**. The **default and recommended model is `"ISCWSA MWD Rev5.11"`**: the current
ISCWSA standard, validated 35/35 sources against all three ISCWSA example workbooks.
Omit `error_model` (leave it `None`) for no uncertainty calculation.
```python
import welleng as we
we.error.get_error_models() # -> list every available model name
survey = we.survey.Survey(
md, inc, azi, header=header,
error_model="ISCWSA MWD Rev5.11", # the standard; change this string to switch
)
cov = survey.err.errors.cov_NEVs # NEV covariance per station
```
**Model families** (all selectable by name via `error_model=`):
- **Canonical ISCWSA MWD** — `"ISCWSA MWD Rev5.11"` (**default**, validated),
`"ISCWSA MWD Rev4"` (legacy, to reproduce older results). (The older
`"ISCWSA MWD Rev5"` name has been retired — use `"ISCWSA MWD Rev5.11"`.)
- **OWSG tool stacks** (Set A, JSON-driven) — the toolcode library:
`"MWD+SRGM"`, `"MWD+SRGM+SAG"`, `"MWD+SRGM+AX"` (axial-interference correction),
`"MWD+IFR1"` / `"MWD+IFR1+AX"` (in-field referencing), and the gyro stacks
`"GYRO-NS"` (north-seeking stationary), `"GYRO-NS-CT"` (mixed continuous),
`"GYRO-MWD"`. A `_Fl` suffix is the floating-rig variant.
> **Revisions.** welleng ships **Rev5-1 / Rev5.11** as the default. The older **OWSG
> Rev2** (2015) toolcodes can be regenerated from their workbooks with
> `python -m welleng.errors.tools.owsg_to_json`, but are not yet shipped as a
> selectable revision (tracked in `docs/dev/FUTURE_WORK.md`). Validate any model only
> against a **matching-revision** reference.
> **Error model update (welleng 0.10.0).** The MWD Rev 5 model has been brought
> into compliance with the ISCWSA Rev 5.11 example workbooks; select it as
> `"ISCWSA MWD Rev5.11"` (the older `"ISCWSA MWD Rev5"` name has since been
> retired). Its covariance differs slightly from welleng ≤ 0.9.x (the Rev 5.11
> corrections). `"ISCWSA MWD Rev4"` is unchanged for users who need to reproduce
> older results. See `welleng/errors/iscwsa_validate.py` for the validation harness
> used to audit against each ISCWSA example workbook.
> **Gyro support + JSON-driven tool models (welleng 0.11.0).** ISCWSA is
> moving its error-model standard from the legacy Excel workbooks to a
> machine-readable JSON schema at
> [`iscwsa/error-models`](https://github.com/iscwsa/error-models). welleng
> 0.11 ships ahead of that transition: a vendored copy of the schema
> (pinned to upstream SHA `c7af784` at
> `welleng/errors/iscwsa_schema/`), a ~95-line Excel-formula interpreter
> at `welleng/errors/interpreter.py`, and the full OWSG Set A library
> (~100 tool models, including the gyro stacks) generated as ISCWSA
> JSON at `welleng/errors/iscwsa_json/owsg_a/`. Use them via
> `Survey(error_model='GYRO-NS' | 'GYRO-NS-CT' | 'GYRO-MWD' | 'MWD+SRGM' | ...)`.
> See `examples/gyro_survey_example.py` for a side-by-side MWD/gyro
> position-uncertainty comparison.
>
> The legacy hand-coded MWD path is **untouched** — the canonical
> strings (`'ISCWSA MWD Rev4'`, `'ISCWSA MWD Rev5'`, `'ISCWSA MWD Rev5.11'`)
> still route through the production engine, so existing users see no
> behaviour change unless they opt in to a JSON-driven tool name.
> **Parallel-paths conformance harness.** Every term that exists in *both*
> the legacy hand-coded dispatcher and the new JSON+interpreter path is
> diff-tested at machine precision in CI (`tests/test_iscwsa_json_conformance.py`).
> The harness also catalogues schema gaps it surfaces — terms that don't
> evaluate against the current draft schema (cross-station references like
> `MDPrev` / `AzPrev` / `IncPrev`, per-tool calibration constants like
> `NoiseReductionFactor`). Run `python -m welleng.errors.conformance --summary`
> for the agreement matrix. Findings are filed upstream as schema-feedback
> on the ISCWSA Discussions board.
> **Absolute validation against SPE 90408.** The conformance harness above
> compares the two welleng paths (and so cancels any shared scale error); on
> top of that, the gyro weight functions are now checked against the
> *published* position covariances in SPE 90408-MS (Torkildsen et al. 2004)
> Appendix E — the first non-self-referential validation of welleng's gyro
> output. Example Models #1 (XY stationary), #3 (XY stationary→continuous
> hybrid), #5 (XYZ stationary→continuous) and #6 (XYZ stationary) reproduce
> the Appendix E covariances on ISCWSA Well #1 to within the paper's ±1%
> acceptance (the hybrid to ~0.1%), and Model #3 also on Well #2. See
> `tests/test_spe90408_appendix_e.py`. The propagation engine itself is
> independently exact — MWD `cov_NEVs` matches the ISCWSA reference to 5e-5.
> **Analytic curve-hold-curve solver (welleng 0.14.0).** The `Connector`'s CLC
> point-to-target case is now solved in closed form (Sawaryn 2021, SPE-204111-PA)
> rather than iteratively — `sawaryn_analytical` returns *every* solution and the
> minimum-measured-depth path in one batched eigenvalue solve (~0.02 ms/path),
> with a radius sweep that maps the feasible-radius trade-off and the R1×R2
> drillable region (fix one arc radius, read off the maximum usable other).
> **Breaking:** infeasible targets now raise rather than silently tightening below
> the design DLS; opt-in `on_infeasible='max_radius'` returns the gentlest feasible
> curve. Companion paper:
> [doi:10.5281/zenodo.21130979](https://doi.org/10.5281/zenodo.21130979).
## Support welleng
welleng is fuelled by copious amounts of coffee, so if you wish to supercharge development please donate generously:
## Cloud API
A hosted API for 3D well path planning is available at
[welleng.org](https://api.welleng.org/api/docs). Solve CLC (curve-line-curve)
paths via simple REST calls — no local install, no GPU required.
- Batch solving (up to 100K pairs)
- GPU-accelerated
- Free tier available
See the [interactive docs](https://api.welleng.org/api/docs) to try it out.
## Documentation
[Documentation] is available, though the library evolves quickly so the examples directory is often the best reference.
## Tech
[welleng] uses a number of open source projects:
* [trimesh] — loading and using triangular meshes
* [Flexible Collision Library] — fast collision detection
* [numpy] — scientific computing
* [scipy] — mathematics, science, and engineering
* [vedo] — 3D visualization based on VTK
* [magnetic-field-calculator] — BGS magnetic field calculator API
## Installation
The default install includes core dependencies (numpy, scipy, pandas, etc.) and covers survey generation, error models, and trajectory design. The `easy` extras add 3D visualization (vedo/VTK), magnetic field lookup, network analysis, and mesh import. The `all` extras add mesh-based collision detection, which requires compiled dependencies.
You'll receive an `ImportError` with a suggested install tag if a required optional dependency is missing.
### Default install (core functionality, no visualization)
```
pip install welleng
```
### Easy install (recommended — adds 3D visualization, magnetic field calculator, trimesh, networkx)
```
pip install welleng[easy]
```
### Full install (adds mesh collision detection — requires compiled dependencies)
First install the compiled dependencies. On Ubuntu:
```terminal
sudo apt-get update
sudo apt-get install libeigen3-dev libccd-dev octomap-tools
```
On macOS, use `brew`. On Windows, follow the [FCL install instructions](https://github.com/flexible-collision-library/fcl/blob/master/INSTALL). Then:
```terminal
pip install welleng[all]
```
### Developer install
The project uses [uv](https://github.com/astral-sh/uv) for dependency management:
```terminal
git clone https://github.com/jonnymaserati/welleng.git
cd welleng
uv sync --all-extras
```
Or with plain pip:
```terminal
pip install -e .[all]
```
### Windows
On Windows, `pip install welleng` should work for the default and easy installs. For the full install with mesh collision detection, follow the [FCL install instructions](https://github.com/flexible-collision-library/fcl/blob/master/INSTALL) to set up the compiled dependencies first.
### Colaboratory
For Google Colab, install dependencies with:
```python
!apt-get install -y libeigen3-dev libccd-dev octomap-tools
!pip install welleng[easy] plotly
```
The VTK-based 3D viewer doesn't work in Colab, but plotly does. Here's a quick example:
```python
import welleng as we
import plotly.graph_objects as go
# create a survey
s = we.survey.Survey(
md=[0., 500., 2000., 5000.],
inc=[0., 0., 30., 90],
azi=[0., 0., 30., 90.]
)
# interpolate every 30 m
s_interp = s.interpolate_survey(step=30)
fig = go.Figure()
fig.add_trace(go.Scatter3d(
x=s_interp.e, y=s_interp.n, z=s_interp.tvd,
mode='lines', name='interpolated'
))
fig.add_trace(go.Scatter3d(
x=s.e, y=s.n, z=s.tvd,
mode='markers', marker=dict(color='red'), name='survey stations'
))
fig.update_scenes(zaxis_autorange="reversed")
fig.show()
```
## Quick Start
Build a pair of well trajectories, compute error ellipses and clearance, and visualize (requires `pip install welleng[all]` for mesh clearance and visualization):
```python
import welleng as we
# construct well paths
connector_reference = we.survey.from_connections(
we.connector.Connector(
pos1=[0., 0., 0.], inc1=0., azi1=0.,
pos2=[-100., 0., 2000.], inc2=90, azi2=60,
),
step=50
)
connector_offset = we.survey.from_connections(
we.connector.Connector(
pos1=[0., 0., 0.], inc1=0., azi1=225.,
pos2=[-280., -600., 2000.], inc2=90., azi2=270.,
),
step=50
)
# create surveys with error models
survey_reference = we.survey.Survey(
md=connector_reference.md,
inc=connector_reference.inc_deg,
azi=connector_reference.azi_grid_deg,
header=we.survey.SurveyHeader(name="reference", azi_reference="grid"),
error_model='ISCWSA MWD Rev4'
)
survey_offset = we.survey.Survey(
md=connector_offset.md,
inc=connector_offset.inc_deg,
azi=connector_offset.azi_grid_deg,
start_nev=[100., 200., 0.],
header=we.survey.SurveyHeader(name="offset", azi_reference="grid"),
error_model='ISCWSA MWD Rev4'
)
# build well meshes
mesh_reference = we.mesh.WellMesh(survey_reference)
mesh_offset = we.mesh.WellMesh(survey_offset)
# calculate clearance
clearance_ISCWSA = we.clearance.IscwsaClearance(survey_reference, survey_offset)
clearance_mesh = we.clearance.MeshClearance(survey_reference, survey_offset, sigma=2.445)
# print minimum SF
print(f"Min SF (ISCWSA): {min(clearance_ISCWSA.sf):.2f}")
print(f"Min SF (mesh): {min(clearance_mesh.sf):.2f}")
# visualize
lines = we.visual.get_lines(clearance_mesh)
plot = we.visual.Plotter()
plot.add(mesh_reference, c='red')
plot.add(mesh_offset, c='blue')
plot.add(lines)
plot.show()
plot.close()
```
This results in a quick, interactive visualization of the well meshes. What's interesting about these results is that the ISCWSA method does not explicitly detect a collision in this scenario whereas the mesh method does.

For more examples, including how to build a well trajectory by joining up a series of sections created with the `welleng.connector` module (see pic below), check out the [examples] and follow the [jonnymaserati] blog.

Well trajectory generated by [build_a_well_from_sections.py]
It's possible to generate data for visualizing well trajectories with [welleng], as can be seen with the rendered scenes below.

ISCWSA Standard Set of Well Paths
The ISCWSA standard set of well paths for evaluating clearance scenarios have been rendered in [blender] above. See the [examples] for the code used to generate a [volve] scene, extracting the data from the [volve] EDM.xml file.
## Citation
**Author:** Jonathan Corcutt — Corcutt Beheer B.V., Wassenaar, Netherlands · ORCID [0009-0008-1953-7760](https://orcid.org/0009-0008-1953-7760).
If welleng supports your work, please cite the **software** (the concept DOI always resolves to the latest version):
> Corcutt, J. *welleng: open-source well-engineering tools.* Zenodo.
```bibtex
@software{corcutt_welleng,
author = {Corcutt, Jonathan},
title = {welleng: open-source well-engineering tools},
publisher = {Zenodo},
doi = {10.5281/zenodo.20968887},
url = {https://doi.org/10.5281/zenodo.20968887}
}
```
If your work relies on the **gyro error-model validation** specifically, please also cite:
> Corcutt, J. (2026). *Reproducing the ISCWSA Gyro Error-Model Test Cases: Implementation Clarifications, Reference-Data Inconsistencies, and an Open-Source Reference Implementation.* Zenodo.
```bibtex
@misc{corcutt2026gyro,
author = {Corcutt, Jonathan},
title = {Reproducing the {ISCWSA} Gyro Error-Model Test Cases: Implementation Clarifications, Reference-Data Inconsistencies, and an Open-Source Reference Implementation},
year = {2026},
publisher = {Zenodo},
doi = {10.5281/zenodo.20940515},
url = {https://doi.org/10.5281/zenodo.20940515}
}
```
If your work uses the **anti-collision (exact Mahalanobis separation factor) method**, please also cite:
> Corcutt, J. (2026). *Making the Exact Wellbore Anti-Collision Boundary Practical: an Efficient, Validated, Open Implementation, and the Cost of the Separation-Rule Approximation.* Zenodo.
```bibtex
@misc{corcutt2026anticollision,
author = {Corcutt, Jonathan},
title = {Making the Exact Wellbore Anti-Collision Boundary Practical: an Efficient, Validated, Open Implementation, and the Cost of the Separation-Rule Approximation},
year = {2026},
publisher = {Zenodo},
doi = {10.5281/zenodo.20976872},
url = {https://doi.org/10.5281/zenodo.20976872}
}
```
If your work uses the **analytical curve-hold-curve point-to-target solver** (`welleng.sawaryn_analytical`), please also cite:
> Corcutt, J. (2026). *An Open, Vectorized Closed-Form Solver for the 3D Curve-Hold-Curve Point-to-Target Problem.* Zenodo.
```bibtex
@misc{corcutt2026clc,
author = {Corcutt, Jonathan},
title = {An Open, Vectorized Closed-Form Solver for the 3D Curve-Hold-Curve Point-to-Target Problem},
year = {2026},
publisher = {Zenodo},
doi = {10.5281/zenodo.21130979},
url = {https://doi.org/10.5281/zenodo.21130979}
}
```
**Built on:** welleng stands on NumPy, SciPy, pandas, trimesh, FCL and more, and implements published methods (ISCWSA, Brooks, Sawaryn, …) — see [CITATIONS.md](CITATIONS.md) for the dependency and method references to credit.
## License
[Apache 2.0](LICENSE)
Please note the terms of the license. Although this software endeavors to be accurate, it should not be used as is for real wells. If you want a production version or wish to develop this software for a particular application, then please get in touch with [jonnycorcutt], but the intent of this library is to assist development.
[//]: # (These are reference links used in the body of this note and get stripped out when the markdown processor does its job.)
[jonnycorcutt]:
[welleng]:
[Flexible Collision Library]:
[trimesh]:
[python-fcl]:
[vedo]:
[numpy]:
[scipy]:
[examples]:
[blender]:
[volve]:
[ISCWSA]:
[build_a_well_from_sections.py]:
[magnetic-field-calculator]:
[jonnymaserati]:
[documentation]: