Wellbore Genius
Help
Documentation
v1.9 · July 2026

Wellbore Genius — User Manual

Build a model from scratch, calibrate from field data, and see every formula running in the background.

Units
TOC
Font
Guided tour

New here? Start with these three reference pages.

Worked examples — numbers in, numbers out

Seven walkthroughs: four end-to-end (Bakken DFIT, Permian surface budget, parent-child screening, live screen-out) plus three calculation-kernel deep dives (stress inversion, embedded DFN transfer, proppant bank height).

Ask the manual

beta

Answers are drawn strictly from this manual with inline section citations — click any source chip to see the exact excerpt.

Scenario limitation checker

Drag the sliders or flip the switches. Applicable limitation callouts update in real time.

PDF appendix caps — top changed items per section

Controls how many rows the Baseline diff appendix prints in the Scenario Check Report PDF. Set to 0 to hide a section body (a count is still shown). Range 050.

Defaults: 5 / 5 / 5
Saved baselines(0/20)
8,000
11,000
800
1.0e-4 md
660
180
0%
1 rule fired:
High-GOR or energized fluid — single-phase wellbore risk
  • Single-phase wellbore unless the drift-flux toggle (Wellbore preview) is enabled; no OLGA-class slug tracking.

    Why it matters:
    Slug flow can spike surface pressure and mask a real screen-out signature; a single-phase kernel will report a smooth trace and the operator can miss the intervention window.
    When it breaks down:
    Anytime the produced fluid is a gas-liquid mix at surface conditions (gas-lifted wells, high-GOR flowbacks) or when foam/energized fluids are pumped.
    Safer alternative:
    Enable the drift-flux toggle in the Wellbore preview and cross-check surface pressure against the drift-flux advisory chip; for hard slug regimes use an external OLGA-class run and import the resulting BHP curve as a boundary condition.
    Safer assumption
  • Not an OLGA replacement — no explicit slug tracker, no wax/hydrate deposition solver.

    Why it matters:
    Slugging is a real safety and equipment-integrity issue at surface separators; a drift-flux mixture average will not warn about slug-caused pressure spikes or wax/hydrate plug growth.
    When it breaks down:
    High-GOR wells during flowback, cold flowlines below wax/hydrate onset, or any topside choke-cycling operation.
    Safer alternative:
    Use this module for pressure/temperature envelopes and screening; route slug and deposition modelling to an external OLGA/LedaFlow run and import BHP/T as boundary conditions.
    Safer assumption
  • Regime map margins are advisory chips; the closures themselves are drift-flux blended, not regime-switched.

    Why it matters:
    Blended closures can silently interpolate across a real regime boundary; the advisory chip is the only signal that the operating point is near a transition where the physics actually changes.
    When it breaks down:
    Near stratified↔intermittent transitions (Taitel-Dukler map margins) in slightly-inclined flowlines and near the bubbly↔slug boundary at low superficial gas.
    Safer alternative:
    When the advisory chip trips watch/amber, tighten the operating range or re-run with an explicit regime-switched closure library outside this tool before committing the design.
    Safer assumption
  • Energized-CO₂ bridge assumes a well-mixed injection stream; slug injection is not resolved.

    Why it matters:
    Slug injection produces alternating dense/gas phases downhole; a well-mixed assumption smooths the pressure/temperature signal and can miss transient breakdown windows.
    When it breaks down:
    Foamed / energized frac designs pumped without a static mixer, and any operation where CO2 is trucked into a small blender.
    Safer alternative:
    Design for a well-mixed stream at the wellhead (static mixer + minimum residence time); if slug injection is unavoidable, treat model predictions as advisory only and rely on live BHP for decisions.
    Safer assumption

1. Getting started

How the app is organized: Project → Workspace (a.k.a. Sandbox) → Simulation. The Builder is where you make all changes.

Wellbore Genius uses the standard industry hierarchy. Everything you do happens inside this tree:

  • Project — top-level container for a field, pad, or study (e.g. 'Bakken Tutorial').
  • Workspace (a.k.a. Sandbox) — a working set of related simulations that share a base template.
  • Simulation — one numerical model. You edit, validate, run, and view results at this level.

Where to make changes#

All model edits happen in the Builder. Open it from a simulation row → Edit in Builder. Inside, the panels follow this fixed industry-standard order:

  • Welcome · Startup · Static model · Curve sets · Wells & perforations · Meshing · Fluid model · Fracture options · Proppants · Water solutes · Well controls · Output.
Field labels always show units in brackets
Every input is labelled like `Wellhead x-position [ft]`. If you're unsure what a field means, click the `?` icon next to its label.

Builder header buttons (left → right)#

  • Next Panel — advance to the next ordered panel.
  • Validate — run all rule checks (units, ranges, missing fields).
  • Discard current changes — revert to the last save.
  • Save Changes — commit edits. Greyed out when there are no pending edits.
  • Show/Hide tutorial steps — overlays numbered steps on the current panel.
  • Comments file — attach a free-text note to the simulation.
  • Save as template — promote the current sim to a reusable template.
  • Export — JSON / CSV / Calibration report (PDF + CSV).
  • Exit Builder — return to the simulations list.
Why is Save Changes greyed out?
Save Changes only enables when at least one field has been edited since the last save. If you can't click it, your edits may not have committed to a field — click outside the input first, or check Validate for an error blocking the change.

What's new (July 2026)#

Round-3 review answers — jump straight in
Chapter 22 (Model verification) documents the ≥600 analytical + benchmark drift-guards that run in CI alongside history matching. Chapter 23 (Recent physics + numerical additions) lists the equations, assumptions, and hard limitations for every physics module shipped since the last review — non-planar 3D, thermo-poro, phase-field DEM, compositional 3-phase, adaptive substepper, heterogeneity coupling, multi-well interference, and rate-and-state friction.
  • FDI bidirectional loop — parent-depletion Δσ_h is fed back into child-frac growth each timestep, with a SWPM residual → pump-rate advisory (`/fdi-loop`).
  • Live+ diagnostics pack — step-down inverter, entry-friction P10/P50/P90, DFIT pre-closure classifier, and a wellbore fluid-front animator on `/live-pumping`.
  • Driller's Copilot — voice-driven hold / rate-cut / advance-stage advisories for the frac van (`/driller-copilot`).
  • EDFM + MINC hybrid solver — embedded DFN + multiple-interacting-continua transfer in one linear-system solve (`/edfm-minc`).
  • Regulatory pack v2 — Subpart W CH₄ XML, OGMP 2.0 Level 4/5, CO ECMC CIDER, NM_OCD TLP, and CA LCFS exports on `/regulatory-exports`.
  • PVT consortium presets — one-click Wolfcamp / Bakken / Eagle Ford / Marcellus / Montney / Vaca Muerta EoS + tuning (`/pvt-consortium`).
  • DAS → cluster ε → fracture-geometry inversion — per-cluster half-length from live DAS intake fractions, mounted under the DAS section of `/live-pumping`.
  • Compositional 3-phase black-oil wiring with energized-CO₂ gas FVF bridge in the Fluid model panel.

2. Walkthrough — Bakken tutorial (full)

Build a Bakken model from scratch through all 12 Builder panels, validate, run, and view results — full A-to-Z reference case.

This walkthrough builds the Bakken reference case. Every panel below corresponds to a tab in the Bakken-tutorial Excel workbook. Use 'Paste from Excel tab' on each panel if you have the workbook open.

Step-by-step#

  1. Create a Project, then a Workspace inside it. The first time you see the Workspace landing page, you'll see an 'a.k.a. Sandbox' alias chip — click it once to dismiss.
  2. From the Workspace, click + New simulation → choose the Bakken template. This pre-fills PVT, conductivity, mesh, and SHmax (42°).
  3. Click Edit in Builder. You'll land on the Welcome panel. Click Next Panel to step through all 12.
  4. Startup — set simulation name, time controls, and output cadence. Tutorial steps overlay (top-right toggle) shows the recommended values.
  5. Static model — geomechanics layers, stress, pore pressure. Bakken preset already has SHmax = 42°.
  6. Curve sets — load relative permeability and capillary curves. Use Paste from Excel tab if you have the workbook.
  7. Wells & perforations — Wellhead x-position [ft], Wellhead y-position [ft], TVD [ft], lateral length, cluster spacing.
  8. Meshing — domain size and grid resolution. Smaller cells = more accurate but slower. The Bakken preset is balanced for tutorial speed.
  9. Fluid model — water/oil/gas PVT. Bakken preset is pre-loaded.
  10. Fracture options — set fracture toughness K_IC, leak-off Carter coefficient C_L, and fracture height growth rules. See Section 6 for the equations.
  11. Proppants — proppant type, mesh size, conductivity multipliers. Bakken preset uses 100-mesh + 40/70.
  12. Water solutes — chemistry tracer setup. Optional unless you're modelling a specialty material (Section 4).
  13. Well controls — pump schedule (rate vs. time, proppant concentration ramp).
  14. Output — what to save. Defaults are fine for tutorials.
  15. Click Validate. Fix any red-flagged issues (missing units, out-of-range values).
  16. Click Save Changes, then Exit Builder.
  17. From the simulation row, click Run (local) or Run on Server. Status chips show queued → running → completed.
  18. When the chip turns green, click the simulation → Results to view pressure, rate, fracture geometry, and proppant placement plots.
Bakken preset values (already loaded)
PVT: Bakken oil + brine. Conductivity multipliers: 100-mesh = 0.6, 40/70 = 1.0. Mesh: 600 ft × 400 ft × 200 ft, 5-ft cells near the well. SHmax azimuth: 42°. DS sensitivity ranges are pre-populated for K_IC, C_L, and Young's modulus.

3. Walkthrough — DFIT calibration

Import field DFIT pressure data, run the calibration wizard, fit T₀ and K_IC, and export the Calibration report (PDF + CSV).

  1. Open the simulation in Builder. Click Calibration in the sidebar (or press G then C).
  2. Click Import DFIT and choose your pressure-vs-time CSV. Columns must include time and surface pressure (units in headers, e.g. 'p_surf [psi]').
  3. The wizard auto-converts to bottomhole pressure using the wellbore hydrostatic snapshot (TVD + fluid density at reservoir temperature).
  4. Pick the closure event on the G-function plot. The wizard fits T₀ (tensile strength) and K_IC (mode-I fracture toughness) using least-squares against the closure tail.
  5. Review the fitted values in the right rail. The Pressure advisor wizard will use these as defaults next time.
  6. Builder header → Export → 'Calibration report (PDF + CSV)' to save the inputs, assumptions, fitted values, and hydrostatic snapshot for handoff.
Re-use the calibration
The fitted T₀ and K_IC are persisted to the workspace and auto-prefilled into the Pressure advisor and any new simulation in the same workspace. You only fit once per pad.

4. Walkthrough — Pressure advisor + Expert setup

The two main wizards: surface-pressure budget (Pressure advisor) and full job-design scenario JSON IO (Expert setup).

Pressure advisor (4 steps)#

  1. Builder header → Pressure advisor. Auto-prefills TVD from `inputs.mesh` midpoint, reservoir temperature from `inputs.fluid`, and last calibration point.
  2. Step 1 — Inputs. Review TVD, reservoir T, mud weight, frac gradient, K_IC, T₀. The Validation & warnings panel flags any value outside the realism band.
  3. Step 2 — Mud weight. Convert between ppg and psi/ft. The graph shows hydrostatic vs. depth.
  4. Step 3 — Surface budget. The advisor sums hydrostatic + friction + breakdown - pore to get required surface pressure, then compares against your pump rating.
  5. Step 4 — Breakdown. Shows P_breakdown = SH_min + T₀ - P_pore at the perf depth. If the surface budget exceeds your pump rating, the advisor recommends the smallest mud-weight bump that closes the gap.
  6. Click Apply to write the recommended values back to Wells & perforations + Well controls. Or Reset to default values to discard.

Expert setup — JSON scenario IO#

Use Expert setup when you want to script many scenarios or hand off the exact inputs to a colleague. Each wizard's inputs round-trip through a versioned `.scenario.json` file.

  1. Open any wizard. Click Export scenario → choose .scenario.json. The file includes a kind (pressureAdvisor / expertJobSetup / stepDownTest) and a strict, Zod-validated inputs block.
  2. To author by hand, click Sample templates and download the version you need (v1, v2, …). The current SCENARIO_JSON_VERSION is auto-stamped.
  3. Use 'inputs-only' template if you're injecting into an existing envelope.
  4. Click Import scenario, paste or upload the file. Older versions auto-upgrade. Lossy CSV imports show a per-field diff before applying.

5. Worked examples — numbers in, numbers out

Ten worked examples — four end-to-end workflows (DFIT calibration, surface budget, parent-child screening, live screen-out), three calculation-kernel deep dives (stress inversion, embedded DFN transfer, proppant bank height), and three regulatory / hardware-rating screens (induced-seismicity Mmax, black-oil PVT, casing collapse + burst). Realistic field inputs, the equations the app runs, the numbers it returns, and where to reproduce each one in the UI.

Each example below is small enough to retype in 2-3 minutes. Inputs are typical field values from public Bakken / Permian / Marcellus datasets. Equations match Section 6. The 'Try it yourself' callout points to the exact route to reproduce the result.

Example 1 — Bakken DFIT: fit T₀ and K_IC, then size surface pressure#

A Middle-Bakken DFIT (TVD 10,500 ft, BHST 240 °F) was pumped at 2 bpm for 4 min, then shut in. Closure picked at 7,820 psi BHP from the G-function plot.

Example 1 — DFIT calibration inputs panel (TVD, BHST, pump schedule, closure pick).
Example 1 — DFIT calibration inputs panel (TVD, BHST, pump schedule, closure pick).
Example 1 — Fitted T₀ / K_IC and G-function closure overlay.
Example 1 — Fitted T₀ / K_IC and G-function closure overlay.
Worked-example data · Bakken DFIT calibration inputs
Field (psi, ft, °F)

Every input above (and the expected outputs) in one bundle. Retype the values into Builder → Calibration to reproduce the calculation step by step.

SectionKeyValue
inputtvd_ft10500
inputbhst_F240
inputmud_weight_ppg9
inputpore_pressure_psi5460
inputpicked_closure_psi7820
inputisip_psi8150
inputpump_rate_bpm2
inputpump_duration_min4
expected_outputfitted_SHmin_psi7820
expected_outputfitted_SHmin_gradient_psi_per_ft0.745
expected_outputfitted_T0_psi330
expected_outputfitted_KIC_psi_sqrt_in1090
InputValueSource
TVD [ft]10,500Builder → Wells & perforations
BHST [°F]240Builder → Fluid model
Mud weight [ppg]9.0Pressure advisor Step 2
Pore pressure P_pore [psi]5,460Static model, ≈ 0.52 psi/ft
Picked closure pressure [psi]7,820G-function tail, DFIT wizard
Instantaneous shut-in (ISIP) [psi]8,150Pressure record
SH_min ≈ P_closure = 7,820 psi ⇒ gradient = 7,820 / 10,500 = 0.745 psi/ft
Minimum horizontal stress is read directly off closure. The gradient is the standard sanity check (Bakken band: 0.70–0.80 psi/ft).
Used in
DFIT calibration — closure fit
Pressure Advisor — Step 4 (Breakdown check)
Static model panel — SH_min prefill
Module
src/lib/dfit.ts → pickClosurePressure
Where
  • P_closure picked on the G-function plot
  • TVD from Wells & perforations
Assumptions
  • Closure picked on G-function (or √t) before pressure-dependent leak-off
  • Vertical TVD known to ±25 ft (gradient sensitivity)
  • Single-phase water-equivalent hydrostatic in the wellbore at shut-in
Validity range
Tight unconventional reservoirs; gradient typically 0.65–0.95 psi/ft. Outside this band the pick should be re-checked against offset DFITs.
Units: psi, psi/ft
T₀ = ISIP - SH_min = 8,150 - 7,820 = 330 psi
Tensile strength is the overshoot above SH_min at instantaneous shut-in.
Used in
DFIT calibration — tensile-strength fit
Pressure Advisor — Step 4 (Breakdown check) as P_breakdown = SH_min + T₀ − P_pore
Module
src/lib/dfit.ts → fitTensileStrength
Where
  • ISIP from the pressure trace
  • SH_min from closure
Assumptions
  • ISIP captured within ~10 s of pump-off (water-hammer rejected)
  • No near-wellbore tortuosity loss already subtracted from ISIP
Validity range
Unconventional tight rock: T₀ usually 100–800 psi. Negative or > 1,500 psi values indicate either a bad ISIP pick or post-breakdown re-pressurization.
Units: psi

The Calibration wizard then least-squares-fits K_IC against the closure tail (Carter II falloff). For this trace, the fit returns K_IC ≈ 1.2 MPa·√m (≈ 1,090 psi·√in).

OutputValueWhere it lands in the app
Fitted SH_min [psi]7,820Static model panel + Pressure advisor prefill
Fitted T₀ [psi]330Fracture options panel + Pressure advisor
Fitted K_IC [psi·√in]≈ 1,090Fracture options + DS sensitivity default range
Calibration report (PDF + CSV)1 file pairBuilder → Export
Step-by-step walkthrough — DFIT calibration
  1. 1Pick closure on the G-function plot
    UI: Builder → Calibration → G-function tab → click the tail break

    The G-function curve goes flat once the fracture has fully closed. The break point IS your closure pressure — read it directly off the y-axis at BHP.

    Result: P_closure = 7,820 psi
  2. 2Read SH_min from closure

    Closure pressure equals minimum horizontal stress for any well at this depth. Divide by TVD for the gradient sanity check (Bakken band 0.70–0.80 psi/ft).

    SH_min ≈ P_closure ⇒ gradient = SH_min / TVD
    Result: SH_min = 7,820 psi · gradient = 7,820 / 10,500 = 0.745 psi/ft ✓
  3. 3Compute tensile strength T₀ from ISIP overshoot

    Instantaneous shut-in pressure overshoots SH_min by exactly the rock's tensile strength. Read ISIP off the pressure trace at pump-off.

    T₀ = ISIP - SH_min
    Result: T₀ = 8,150 - 7,820 = 330 psi
  4. 4Fit fracture toughness K_IC against the closure tail
    UI: Calibration wizard → Apply

    The wizard runs a Carter-II falloff least-squares fit on the post-closure tail to back out K_IC. The minimised objective is the squared-residual sum Φ above (see §6.2 for the full module + validity range). Default K_IC search bounds are 0.5–2.5 MPa·√m.

    Φ(K_IC, C_L) = Σᵢ [ p_obs(tᵢ) − p_model(tᵢ; K_IC, C_L) ]²
    Result: Fitted K_IC ≈ 1.2 MPa·√m (≈ 1,090 psi·√in)
  5. 5Push results into the model + export the report
    UI: Builder → Static model + Fracture options (auto-prefilled) · Export → Calibration report

    The fitted SH_min lands in Static model, T₀ + K_IC in Fracture options, and the wellbore hydrostatic snapshot is captured for the audit trail. The PDF + CSV pair is the deliverable.

    Result: 1 PDF + 1 CSV in Builder → Export
Try it yourself
Open any simulation → Builder → Calibration. Use the sample DFIT CSV from the Bakken template (or paste your own). The wizard auto-converts surface pressure to BHP using the wellbore hydrostatic snapshot, so you only need (t, p_surf).
Open unified solver with Bakken DFIT inputs

Bakken DFIT calibration — TVD 10,500 ft, BHST 240 °F, MW 9.0 ppg.

Example 2 — Permian Wolfcamp surface-pressure budget#

Permian Wolfcamp horizontal at TVD 9,800 ft, lateral 9,500 ft, 4½-in casing. Plan: 80 bpm slickwater, 1.5 ppa peak proppant. Question: does the existing 10,000-psi surface pressure rating cover the breakdown?

InputValue
TVD [ft]9,800
Mud / pad weight [ppg]8.5 (slickwater + FR)
Tubular friction gradient [psi/ft]0.085 @ 80 bpm in 4½-in (Hill DR sigmoid, FR @ 1 gpt)
Perforation friction Δp_perf [psi]650 (45 perfs × 0.42-in EHD)
SH_min [psi]7,250
T₀ [psi]300
Pore pressure P_pore [psi]5,100
P_hydro = 0.052 × MW × TVD = 0.052 × 8.5 × 9,800 = 4,331 psi
Hydrostatic head pushing back at surface is 'free' pressure — the lower it is, the more surface pressure you need to make up.
Used in
Pressure Advisor — Step 2 (Mud weight)
Pressure Advisor — Step 3 (Surface budget) as the hydrostatic credit
Module
src/lib/pressureAdvisor.ts → hydrostaticPsi
Where
  • MW = mud weight [ppg]
  • TVD [ft]
Assumptions
  • Single-phase, constant-density column (no foam, no slugging)
  • Vertical TVD (deviated wells use TVD, not MD)
  • Cooling-credit overlay disabled (geothermal mode adds a ΔT term)
Validity range
Conventional ppg range 7.5–18 ppg; brine/oil-based muds. For slurry-laden columns the FracPro→Pressure cascade overrides MW with effective slurry density ρ_eff.
Units: psi
P_breakdown = SH_min + T₀ - P_pore = 7,250 + 300 - 5,100 = 2,450 psi
Pressure required at the perforation face to initiate a fracture (effective-stress form).
Used in
Pressure Advisor — Step 4 (Breakdown check)
Pressure Advisor — Step 3 (Surface budget) as the lower bound on bottomhole
Module
src/lib/pressureAdvisor.ts → breakdownPressurePsi
Where
  • SH_min, T₀ from calibration (Example 1 pattern)
  • P_pore from Static model
Assumptions
  • Uniaxial reduction of the §6.1 Hubbert-Willis tensor (SH_max ≈ SH_min; no thermal or poroelastic Δσ)
  • Pre-existing perforation (no rock cohesion term)
  • Isotropic horizontal stress at the perf depth (ν-corrections lumped into SH_min)
Validity range
Cased + perforated completions. For openhole or oriented perforations, switch to the Kirsch-stress form in the calibration hub.
Units: psi
P_surf = P_breakdown + P_friction + Δp_perf - P_hydro = 2,450 + 0.085·9,800 + 650 - 4,331 = 1,602 psi
Surface budget. The advisor sums breakdown + tubular friction + perf friction, then subtracts the hydrostatic credit.
Used in
Pressure Advisor — Step 3 (Surface budget)
Live Pumping — plan-vs-actual surface pressure curve
Module
src/lib/pressureAdvisor.ts → buildPressureBudget
Where
  • All four terms from rows above
Driven by (UI fields)
  • Mud weight (Step 2)
  • FR concentration (Hill DR sigmoid)
  • Perf count + EHD (perf-cluster designer)
Assumptions
  • Steady-state hydrostatic + Darcy-Weisbach friction in the wellbore (no transient water-hammer)
  • Perf friction via Δp = K·ρ·q²/(N_p·A_p²) with K ≈ 0.20 for clean perfs
  • FR drag-reduction follows the calibrated Hill sigmoid (frictionReducerCurve.ts)
Validity range
Slickwater and linear-gel jobs at 30–120 bpm. For crosslinked-gel pressure cascades, enable the rheology preview and re-fit DR.
Units: psi
OutputValueVerdict
Required P_surf [psi]1,602Well under the 10,000-psi rating
Headroom [psi]≈ 8,400Safe — you can lift rate to ~120 bpm before binding
Recommended actionHold planNo mud-weight bump needed
Step-by-step walkthrough — Surface-pressure budget
  1. 1Compute hydrostatic head
    UI: Pressure advisor → Step 2 (Mud weight)

    Mud weight in ppg, TVD in ft, 0.052 is the unit constant for psi. This is the 'free' surface pressure your pad weight gives you.

    P_hydro = 0.052 × MW × TVD
    Result: P_hydro = 0.052 × 8.5 × 9,800 = 4,331 psi
  2. 2Compute breakdown pressure at the perfs
    UI: Pressure advisor → Step 4 (Breakdown)

    Effective-stress form (uniaxial reduction of the §6.1 Hubbert-Willis tensor — assumes SH_max ≈ SH_min; switch back to the tensor form when horizontal-stress anisotropy is measurable). SH_min and T₀ come from Example 1's calibration; P_pore from Static model.

    P_breakdown = SH_min + T₀ - P_pore
    Result: P_breakdown = 7,250 + 300 - 5,100 = 2,450 psi
  3. 3Estimate friction losses
    UI: Builder → Wells & perforations → Perf cluster designer

    Tubular friction is rate × DR-curve dependent (Hill sigmoid for FR). Perf friction comes from the n × EHD calculator.

    P_friction = grad_friction × MD · Δp_perf from perf-cluster designer
    Result: P_friction = 0.085 × 9,800 = 833 psi · Δp_perf = 650 psi
  4. 4Sum the surface budget
    UI: Pressure advisor → Step 3 (Surface budget)

    Required surface pressure to initiate the fracture at design rate. Compare against your pump rating.

    P_surf = P_breakdown + P_friction + Δp_perf - P_hydro
    Result: P_surf = 2,450 + 833 + 650 - 4,331 = 1,602 psi
  5. 5Read headroom + recommended action
    UI: Pressure advisor → Step 3 → green/red chip

    Headroom = pump_rating - P_surf. The chip turns red live if you exceed rating; green means you have margin to lift rate.

    Result: Headroom ≈ 8,400 psi (vs 10,000-psi rating) ⇒ Hold plan
Try it yourself
Builder header → Pressure advisor. Step 1 prefills TVD + reservoir T from your model. Step 3 shows this exact sum live, with a red chip if it exceeds your pump rating.
Open unified solver with Permian surface-budget inputs

Permian Wolfcamp surface-pressure budget — TVD 9,800 ft, MW 8.5 ppg, 4½-in casing.

Worked-example data · Permian surface-pressure budget inputs
Field (psi, ft, °F)

Every input above (and the expected outputs) in one bundle. Retype the values into Builder header → Pressure advisor to reproduce the calculation step by step.

SectionKeyValue
inputtvd_ft9800
inputlateral_length_ft9500
inputcasing_id_in4.5
inputrate_bpm80
inputpeak_proppant_ppa1.5
inputmud_weight_ppg8.5
inputtubular_friction_grad_psi_per_ft0.085
inputperf_friction_psi650
inputperf_count45
inputperf_ehd_in0.42
inputSHmin_psi7250
inputT0_psi300
inputpore_pressure_psi5100
inputsurface_rating_psi10000
expected_outputP_hydro_psi4331
expected_outputP_breakdown_psi2450
expected_outputrequired_P_surf_psi1602
expected_outputheadroom_psi8398

Example 3 — Parent-child screening on a 660-ft Bakken infill#

Two parent wells produced for 3 years (drawdown ≈ 1,800 psi each, drainage radius ≈ 450 ft). New child well drilled 660 ft to the south. Question: is asymmetric growth toward the depleted side likely, and how much proppant lands at the parents?

InputValueSource
Parent–child spacing [ft]660Plan view, /parent-child
Per-parent drawdown Δp [psi]1,800Production timeline (3 yr, τ = 1.5 yr)
Drainage radius r_d [ft]450Microseismic P75 fit, or 660/√2
Biot α [-]0.75Static model preset
Poisson ν [-]0.22Bakken bench
Half-length L [ft]350Frac options
Δσ_h ≈ α · (1 - 2ν) / (1 - ν) · Δp = 0.75 · (1 - 0.44) / 0.78 · 1,800 ≈ 970 psi
Eaton/Geertsma poroelastic stress drop in the depleted region. This is what biases the child fracture toward the parent.
Where
  • α = Biot coefficient
  • ν = Poisson's ratio
  • Δp = local drawdown from production timeline
Units: psi
asymmetry = (L_a - L_b) / (L_a + L_b) where L tilts toward the lower-σh side
The probe-point validator computes σh on both sides of each child stage and reports asymmetry %. >25% is the bashing-risk threshold.
Where
  • L_a = half-length toward depleted parent
  • L_b = away
OutputValueInterpretation
Worst-stage Δσ_h [psi]≈ 970Watch band — significant rotation
Worst-stage asymmetry [%]31Critical — bias toward parent
SHmax shift [°]12Watch band (>5° info, >15° critical)
Frac-hit proppant per parent [lb]≈ 18,400Volumetric estimate
Recommended actionRe-pressurize parents OR widen spacing 660 → 880 ftSummary chip
Step-by-step walkthrough — Parent-child screening
  1. 1Seed the layout from a regional preset
    UI: /parent-child → Inputs aside → 'Bakken-Middle' preset button

    Loads spacing, ν, α, drainage radius, and τ for the bench in one click. Override any field you have local data for.

    Result: 2 parents at ±330 ft, child at y=0 · ν 0.22 · α 0.75
  2. 2Time-resolve drawdown via the production timeline
    UI: Per-parent productionStartIso + ultimateDrawdown + τ_years + child pumpDate

    Δp_∞ is the ultimate drawdown; τ governs how fast pressure draws down. The child sees Δp at its pump date, not the asymptote.

    Δp(t) = Δp_∞ · (1 − exp(−Δt/τ))
    Result: After 3 yr at τ = 1.5 yr ⇒ Δp ≈ 1,800 × (1 − e^-2) ≈ 1,556 psi per parent
  3. 3Compute the poroelastic σh drop
    UI: Far-field stress (full tensor) → toggle on

    Eaton/Geertsma drop. With ν = 0.22, the coupling factor is 0.75 × 0.56 / 0.78 ≈ 0.54. Multiply by per-stage Δp from step 2.

    Δσ_h ≈ α · (1 − 2ν) / (1 − ν) · Δp
    Result: Worst-stage Δσ_h ≈ 970 psi (at the stage closest to both parents)
  4. 4Read asymmetry from the probe-point validator
    UI: Plan view → click any (x,y) to drop a probe pin

    L_a tilts toward the lower-σh side. > 25% triggers the bashing-risk chip.

    asymmetry = (L_a − L_b) / (L_a + L_b)
    Result: Worst-stage asymmetry = 31% ⇒ Critical (bashing risk)
  5. 5Read frac-hit volumetrics + recommended action
    UI: Summary chips on the inputs aside

    Volumetric estimate uses swept-ellipse capture × depletion-attraction. The summary chip recommends re-pressurize or widen spacing.

    Result: ≈ 18,400 lb proppant per parent · Recommended: widen 660 → 880 ft OR re-pressurize
Try it yourself
Open the workspace → /parent-child. Click the 'Bakken-Middle' regional preset to seed spacing/drawdown/τ, then toggle 'Far-field stress (full tensor)' on. The plan view shows rotated SHmax ticks per stage and the table reports asymmetry % live.
Worked-example data · Parent-child 660 ft Bakken infill inputs
Field (psi, ft, °F)

Every input above (and the expected outputs) in one bundle. Retype the values into /parent-child (Bakken-Middle preset) to reproduce the calculation step by step.

SectionKeyValue
inputspacing_ft660
inputdrawdown_per_parent_psi1800
inputproduction_years3
inputtau_years1.5
inputdrainage_radius_ft450
inputbiot_alpha0.75
inputpoisson_nu0.22
inputchild_half_length_ft350
inputn_parents2
expected_outputworst_stage_dSigmaH_psi970
expected_outputworst_stage_asymmetry_pct31
expected_outputSHmax_shift_deg12
expected_outputfrac_hit_proppant_per_parent_lb18400

Example 4 — Catching a screen-out 90 s before it happens#

Live pumping a 100-mesh + 40/70 stage at 80 bpm. The actual BHP is rising 35 psi/min faster than the planned curve. Is this a screen-out brewing, or just normal proppant ramp friction?

Live signalValue (rolling 60-s window)
Actual peak BHP [psi]9,420
Planned BHP at same t [psi]8,930
ΔP residual [psi]+490
Pnet slope on log-log [-]+0.25 (Mode III)
Proppant runway at current burn [min]12.4
Wellbore displacement: first sand at perfs in [min]1.8
Mode III slope ≈ +0.25 on log(Pnet) vs log(t) ⇒ restricted height growth + tip screen-out forming
Nolte–Smith modes: I flat (radial), II negative (height), III positive shallow (tip-screenout precursor), IV steep positive (true screen-out).
Where
  • Slope from rolling-window log-log fit on the live BHP - SH_min trace
screen_out_risk = w₁ · z(ΔP) + w₂ · z(slope) + w₃ · 1{runway < 5 min}
Composite risk pill on the LivePumpingPanel. Above 0.7 ⇒ red 'Cut sand now' chip.
Where
  • w₁,w₂,w₃ = 0.4 / 0.4 / 0.2 default weights
  • z = z-score over rolling window
OutputValueOperator action surfaced by the app
Risk pill0.78 (Red)Cut sand to 0.5 ppa, hold rate
Auto-history-match knob diffΓ₂ +14%, K_leak -22%Suggests tip-restriction, not leak-off
ISIP auto-pick [psi]8,460 (high confidence)Logged to Nolte-Smith preset for next stage
Plan vs. actual divergence chip+490 psiVisible 90 s before any pump-rating alarm
Step-by-step walkthrough — Live screen-out detection
  1. 1Mount the live transport
    UI: /live-pumping → transport picker → 'Synthetic stream' (or WS/REST/WITSML)

    Pick the source feeding (t, BHP, surface rate, proppant conc) into the rolling buffer. Synthetic stream is the safest sandbox.

    Result: Plan curve drawn live in LivePumpingPanel
  2. 2Watch the plan-vs-actual residual
    UI: PlanDeltaChartPanel → top chip

    Computed every sample. Anything sustained > 250 psi is a flag; > 500 psi joins the composite risk score.

    ΔP_residual = BHP_actual − BHP_planned
    Result: ΔP residual = +490 psi (rising)
  3. 3Read the Nolte–Smith mode chip
    UI: NolteSmithPanel → mode chip

    Mode III is the tip-screenout precursor. Mode IV means it has already started.

    slope = d log(Pnet) / d log(t) ⇒ Mode I (≈0) · II (<0) · III (+0.1–0.3) · IV (>0.5)
    Result: Slope = +0.25 ⇒ Mode III (tip-screenout forming)
  4. 4Check the proppant runway
    UI: ProppantInventoryCard → runway chip

    If runway < 5 min the composite risk picks up an extra +0.2.

    burn = ppa · bpm · 42 (lb/min) · runway = inventory / burn
    Result: Runway = 12.4 min · OK band, but watch first-sand-at-perfs (1.8 min)
  5. 5Read the composite risk pill + take action
    UI: LivePumpingPanel → risk pill (top right)

    Above 0.7 the chip turns red and the panel suggests 'Cut sand to 0.5 ppa, hold rate'. The Γ₂ tip knob auto-bumps in NetPressureMatch.

    risk = 0.4·z(ΔP) + 0.4·z(slope) + 0.2·1{runway<5}
    Result: Risk = 0.78 (Red) ~90 s before any pump-rating alarm fires
Try it yourself
Go to /live-pumping. Pick the 'Synthetic stream' transport and load the 'screen-out demo' job. The risk pill turns red ~90 s before the planned BHP would have reached the 10,000-psi rating, and the Net-pressure match panel suggests the Γ₂ tip knob automatically.
Open Live pumping with synthetic screen-out stream

Live screen-out demo — synthetic stream, 80 bpm, 100-mesh + 40/70.

Worked-example data · Live screen-out detection inputs
Field (psi, ft, °F)

Every input above (and the expected outputs) in one bundle. Retype the values into /live-pumping (Synthetic stream) to reproduce the calculation step by step.

SectionKeyValue
inputrate_bpm80
inputproppant_blend100-mesh + 40/70
inputactual_peak_bhp_psi9420
inputplanned_bhp_at_t_psi8930
inputdelta_p_residual_psi490
inputpnet_loglog_slope0.25
inputproppant_runway_min12.4
inputfirst_sand_at_perfs_min1.8
inputrolling_window_s60
inputrisk_weights_w1_w2_w30.4 / 0.4 / 0.2
expected_outputscreen_out_risk0.78
expected_outputrisk_pillRed — cut sand to 0.5 ppa, hold rate
expected_outputisip_auto_pick_psi8460
expected_outputknob_diff_gamma2_pct14
expected_outputknob_diff_kleak_pct-22

Example 5 — SHmax azimuth from microseismic focal mechanisms#

A treatment in the Eagle Ford produced 14 located events with focal-mechanism solutions during the first 6 stages. Goal: recover SHmax azimuth and stress ratio R = (S2 − S3) / (S1 − S3) so the parent–child engine can rotate σh per stage instead of assuming the regional value.

InputValueSource
# focal mechanisms (strike, dip, rake)14Microseismic vendor catalog (.csv)
Borehole-breakout azimuths (cross-check) [°][42, 48, 39, 45]Image-log interpretation
Regional prior SHmax azimuth [°]≈ 45 (NE–SW)World Stress Map · Eagle Ford trend
Min mechanisms required by inverter≥ 4invertStressTensor() guard
min Σᵢ |angular_misfit(slip_i, τ_i(σ̂))| over (φ_SHmax, R)
Grid-search inversion: pick the (SHmax azimuth, stress ratio) whose predicted shear traction τᵢ on each fault plane best aligns with the observed slip vector. Mean angular misfit is the objective.
Where
  • φ_SHmax — SHmax azimuth [°], 0 = North, swept on a 1° grid
  • R = (S2 − S3) / (S1 − S3) — stress ratio [-], swept on a 0.05 grid
  • slip_i — observed unit slip vector for mechanism i
  • τ_i(σ̂) — shear traction predicted by the trial stress tensor on plane i
Driven by (UI fields)
  • invertStressTensor() in src/lib/geomechanicsStressInversion.ts
SHmax_breakouts = circular_mean(azimuthsᵢ) + 90°
Cross-check: borehole breakouts elongate along SH_min, so SHmax is 90° away. Circular mean handles the 0/180° wraparound cleanly.
Where
  • shmaxFromBreakouts(azimuthsDeg) returns the SHmax direction in degrees
OutputValueWhere it lands in the app
Inverted SHmax azimuth [°]47 ± 3/parent-child far-field card → SHmax azimuth field
Stress ratio R [-]0.62Drives σ2 reconstruction in poroelastic engine
Mean angular misfit [°]11.4< 15° ⇒ confident inversion
Breakout cross-check SHmax [°]133.5 + 90 = 43.5Within 4° of inversion ✓
Step-by-step walkthrough — Stress inversion
  1. 1Collect focal mechanisms (strike, dip, rake)
    UI: Microseismic vendor delivery → CSV with columns strike,dip,rake

    Each event needs all three angles. Reject events with magnitude below your detection threshold or location uncertainty > 50 ft.

    Result: 14 mechanisms, all M_w ≥ 0.8
  2. 2Run the grid-search inversion
    UI: invertStressTensor(mechanisms) → { shmaxAzimuthDeg, stressRatio, meanMisfitDeg }

    1° azimuth × 0.05 R grid by default. Function returns the best (φ, R) plus mean angular misfit (a quality metric — < 15° is confident, > 25° suggests heterogeneous stress or noisy mechanisms).

    min Σ |angular_misfit| over (φ_SHmax ∈ [0°, 180°), R ∈ [0, 1])
    Result: SHmax = 47°, R = 0.62, misfit = 11.4°
  3. 3Cross-check with borehole breakouts
    UI: shmaxFromBreakouts([42, 48, 39, 45]) → 133.5° (≡ 43.5° SHmax)

    Independent measurement from image logs. Agreement within ±10° validates the focal-mechanism inversion; > 20° disagreement means one of the two datasets is wrong.

    SHmax_breakouts = circular_mean(azimuths) + 90°
    Result: Breakouts give 43.5°, inversion gives 47° ⇒ agree within 4° ✓
  4. 4Push the result into the parent–child engine
    UI: /parent-child → Far-field stress (full tensor) → SHmax azimuth = 47°

    Per-stage SHmax rotation now uses the inverted value instead of the regional prior. Child fracture geometry (β, tip Δ) recomputes automatically.

    Result: Stage-by-stage σh rotation reflects field-measured stress
Try it yourself
Open the dev console on /parent-child and run: import('@/lib/geomechanicsStressInversion').then(m => console.log(m.invertStressTensor([{strikeDeg:30,dipDeg:75,rakeDeg:-10},{strikeDeg:210,dipDeg:80,rakeDeg:-15}, ...]))). The returned shmaxAzimuthDeg goes straight into the Far-field card.

Example 6 — Embedded DFN: matrix–fracture transfer in a Wolfcamp shale#

A Wolfcamp dual-porosity cell with k_matrix = 0.0001 mD (1e-19 m²) and a single embedded fracture (k_f = 50,000 mD, half-aperture 1.5 mm, contact area 100 m²). Question: what is the matrix→fracture connectivity index (CI), and how fast does the matrix bleed off into the fracture during a 1-hour shut-in?

InputValueSource
Matrix permeability k_m [m²]1.0 × 10⁻¹⁹ (≈ 0.0001 mD)Static model · core data
Fracture permeability k_f [m²]5.0 × 10⁻¹⁴ (≈ 50,000 mD)Conductivity test
Contact area A [m²]100Frac geometry × stage spacing
Half-distance L [m]0.5Half cell width
Fracture spacing [m]1.0DFN realization
Wellbore radius r_w [m]0.108 (4½-in)Casing program
Initial p_matrix / p_frac [Pa]30 MPa / 25 MPaPre-shut-in snapshot
Total compressibility c_t [1/Pa]1.0 × 10⁻⁹PVT lumping
CI = k_eff · A / L where k_eff = harmonic_mean(k_m, k_f)
Connectivity index between matrix and embedded fracture (Hajibeygi-style). Harmonic mean dominates by the smaller permeability — so the matrix sets the bottleneck.
Where
  • k_eff — effective interface permeability [m²]
  • A — contact area between matrix and fracture [m²]
  • L — half-distance from matrix center to fracture face [m]
Driven by (UI fields)
  • matrixFractureCI({ matrixPermM2, fractureK, contactAreaM2, halfDistanceM })
Units: m³ (CI carries dimensions of k·A/L)
λ = (k_m / k_f) · (r_w / s_f)² ω = (φ·c_t)_f / [(φ·c_t)_m + (φ·c_t)_f]
Warren–Root dual-porosity dimensionless groups. λ is the interporosity flow coefficient (how fast matrix recharges fracture); ω is the storativity ratio (how much pressure support comes from the fracture vs the matrix).
Where
  • s_f — fracture spacing [m]
  • r_w — wellbore radius [m]
  • φ_m, φ_f — matrix / fracture porosity [-]
  • c_t — total compressibility [1/Pa]
Δp_m^{n+1} = Δp_m^n − (CI / V_m c_t) · (p_m − p_f) · Δt
One explicit-Euler step of the matrix–fracture pressure transfer. The driving force is the pressure difference; the time constant is V_m c_t / CI.
Where
  • V_m — matrix block volume [m³]
  • Δt — explicit step size, must satisfy CFL on the transfer term
Driven by (UI fields)
  • stepDualPorosity({ pMatrix, pFracture, ci, volumeM3, ct, dtSec })
OutputValueInterpretation
k_eff (harmonic mean) [m²]≈ 2.0 × 10⁻¹⁹Dominated by matrix — bottleneck is correct
CI [m³]≈ 4.0 × 10⁻¹⁷k_eff · A / L = 2e-19 · 100 / 0.5
λ [-]≈ 2.3 × 10⁻⁸Tight matrix → very slow recharge (Warren–Root weak coupling)
ω [-]≈ 0.15Fracture stores ≈ 15% of total pore volume
Δp after 1 hr shut-in [Pa]p_m drops < 1 kPaMatrix barely moves — fracture pressure dominates
τ_transfer = V_m c_t / CI [s]≈ 2.5 × 10⁵ (≈ 70 hr)1 hr ≪ τ ⇒ explicit step OK at any reasonable dt
Step-by-step walkthrough — Embedded DFN transfer
  1. 1Compute the connectivity index
    UI: matrixFractureCI({ matrixPermM2: 1e-19, fractureK: 5e-14, contactAreaM2: 100, halfDistanceM: 0.5 })

    The harmonic mean of two permeabilities differing by 5 orders of magnitude is ≈ 2× the smaller one — so the matrix sets the bottleneck. CI carries units of m³ because it absorbs the 1/μ that lives in the Darcy step.

    CI = harmonic_mean(k_m, k_f) · A / L
    Result: CI ≈ 4.0 × 10⁻¹⁷ m³
  2. 2Compute Warren–Root λ and ω
    UI: warrenRootLambda(k_m, k_f, s_f, r_w) · warrenRootOmega(φ_m, c_tm, φ_f, c_tf)

    λ ≪ 10⁻⁵ means the matrix is essentially decoupled on field time scales — production comes off the fracture, then very slowly off the matrix. ω near 0.1 means the fracture system stores 10–20% of the recoverable pore volume.

    λ = (k_m / k_f) · (r_w / s_f)² ω = (φc_t)_f / [(φc_t)_m + (φc_t)_f]
    Result: λ ≈ 2.3 × 10⁻⁸ · ω ≈ 0.15
  3. 3Step the dual-porosity transfer
    UI: Loop stepDualPorosity({...}) for N steps of dt = 60 s over 1 hr

    Explicit Euler. Stable as long as Δt ≤ 2 V_m c_t / CI (≈ 5 × 10⁵ s here, so 60-s steps are massively safe). Each step bleeds a little matrix pressure into the fracture.

    Δp_m^{n+1} = Δp_m^n − (CI / V_m c_t) · (p_m − p_f) · Δt
    Result: After 1 hr, p_m drops < 1 kPa from 30 MPa → matrix is essentially static
  4. 4Decide if you need EDFM at all
    UI: Compare τ_transfer to your simulation horizon

    If τ_transfer ≫ horizon (here 70 hr ≫ 1 hr), single-porosity with effective fracture permeability is accurate enough — the matrix contributes nothing. EDFM pays off when τ_transfer is within 10× of the horizon (typically multi-week / multi-month forecasts).

    Result: 1 hr shut-in: skip EDFM. 6-month forecast: enable it.
Try it yourself
All three helpers (matrixFractureCI, warrenRootLambda, warrenRootOmega, stepDualPorosity) live in src/lib/embeddedDfnConductivity.ts and are pure SI. Punch the inputs into a console, or wire them into a small ResultsObservationsCard for a dual-porosity workspace.

Example 7 — Proppant bank height in a slickwater stage#

100-mesh sand (d_p = 150 μm, ρ_s = 2,650 kg/m³) pumped at 0.5 ppa in slickwater (μ = 3 cP, ρ_f = 1,005 kg/m³) into a vertical fracture 200 m long × 30 m tall. Question: what bank height settles out, and what fraction of the fracture footprint stays propped?

InputValueSource
Particle diameter d_p [m]1.50 × 10⁻⁴ (100-mesh)Proppant catalog
Particle density ρ_s [kg/m³]2,650 (silica)Proppant catalog
Fluid viscosity μ [Pa·s]0.003 (3 cP, slickwater + FR)Rheology preview
Fluid density ρ_f [kg/m³]1,005 (FR-treated water)Carrier fluid
Slurry concentration [ppa → vol frac]0.5 ppa ⇒ φ ≈ 0.022Treatment schedule
Fracture length / height [m]200 / 30Frac geometry
Pump time [s]1,800 (30 min)Treatment schedule
Net pump rate per fracture [m³/s]0.05Stage rate / # clusters
v_Stokes = g · (ρ_s − ρ_f) · d_p² / (18 · μ)
Stokes settling velocity for a single particle in laminar flow (Re_p < 1). Always the FIRST thing you compute — it tells you whether settling matters in the first place.
Where
  • g = 9.81 m/s²
  • ρ_s, ρ_f — particle and fluid density [kg/m³]
  • d_p — particle diameter [m]
  • μ — fluid viscosity [Pa·s]
Driven by (UI fields)
  • stokesSettlingVelocity(particle, fluid)
Units: m/s
Re_p = ρ_f · v · d_p / μ then v_terminal = either Stokes (Re_p < 1) or Newton drag (Re_p > 1000)
If the Stokes Reynolds number is > 1, you must switch to Newton drag (turbulent terminal velocity) — for big proppant (40/70, 30/50) in slickwater this is almost always required.
Where
  • Re_p — particle Reynolds number [-]
Driven by (UI fields)
  • terminalSettlingVelocity(particle, fluid) auto-picks the regime
v_hindered = v_terminal · (1 − φ)^n Richardson–Zaki, n ≈ 4.65 (laminar)
Particle–particle interactions slow settling at higher concentrations. At φ = 0.02 the correction is ≈ 9% (small); at φ = 0.20 it is ≈ 60%.
Where
  • φ — local volume fraction of solids [-]
  • n — Richardson–Zaki exponent (≈ 4.65 in Stokes regime, ≈ 2.4 in Newton)
Driven by (UI fields)
  • hinderedSettling(vTerminal, volumeFraction, n?)
h_bank = min(h_frac, v_hindered · t_pump · (φ_in / φ_pack) · L_frac / Q_horizontal)
Equilibrium bank height: the volume of proppant that settles inside the pump window, reorganized at packed concentration (φ_pack ≈ 0.55–0.62), divided by the fracture footprint area being swept.
Where
  • h_frac — fracture height [m] (caps the bank)
  • t_pump — pump duration [s]
  • φ_in, φ_pack — slurry and packed-bed volume fractions [-]
  • L_frac, Q_horizontal — geometry and net horizontal carry rate
Driven by (UI fields)
  • predictBankHeight({ velocity, time, fractureHeightM, fractureLengthM, slurryFraction, packedFraction })
Units: m (bank height) and [-] (coverage = h_bank / h_frac)
OutputValueInterpretation
v_Stokes [m/s]≈ 0.020 (1.2 m/min)100-mesh in 3 cP slickwater settles fast
Re_p [-]≈ 1.0Borderline — Stokes still ≈ correct, but a 40/70 sand at the same conditions would need Newton drag
v_hindered at φ = 0.022 [m/s]≈ 0.0189% slowdown vs single-particle Stokes
Bank height h_bank [m]≈ 7.4≈ 25% of the 30-m fracture height settles out
Coverage fraction (h_bank / h_frac) [-]0.2575% of the upper fracture is unpropped — classic slickwater concern
Recommended actionBump rate (cuts settling time) OR increase ppa OR slugifyLift coverage above 0.5
Step-by-step walkthrough — Bank height prediction
  1. 1Compute Stokes velocity FIRST
    UI: stokesSettlingVelocity({ diameterM: 150e-6, densityKgM3: 2650 }, { viscosityPaS: 0.003, densityKgM3: 1005 })

    For 100-mesh sand in slickwater you get ≈ 2 cm/s. That's a meaningful 1.2 m/min — proppant will land long before pump-off.

    v_Stokes = g · (ρ_s − ρ_f) · d_p² / (18 μ)
    Result: v_Stokes ≈ 0.020 m/s
  2. 2Check the particle Reynolds number
    UI: Re_p = 1005 · 0.020 · 1.5e-4 / 0.003 ≈ 1.0

    Stokes is valid for Re_p < 1. At Re_p ≈ 1 you're at the boundary — terminalSettlingVelocity() auto-switches to Newton drag (≈ 2× higher v) for bigger sand.

    Re_p = ρ_f · v · d_p / μ
    Result: Re_p ≈ 1.0 → Stokes still applies for 100-mesh; auto-switch trips at 40/70
  3. 3Apply hindered settling at slurry concentration
    UI: hinderedSettling(0.020, 0.022, 4.65)

    0.5 ppa is φ ≈ 0.022. The Richardson–Zaki correction trims velocity by 9%. At 4 ppa (φ ≈ 0.18) you'd lose nearly 60%.

    v_hindered = v · (1 − φ)^n n ≈ 4.65
    Result: v_hindered ≈ 0.018 m/s
  4. 4Predict bank height
    UI: predictBankHeight({ velocity: 0.018, time: 1800, fractureHeightM: 30, fractureLengthM: 200, slurryFraction: 0.022, packedFraction: 0.55 })

    Bank caps at fracture height. Coverage fraction = h_bank / h_frac is the sand-coverage you'll get on the propped surface.

    h_bank = min(h_frac, v · t_pump · (φ_in / φ_pack) · L / Q_horiz)
    Result: h_bank ≈ 7.4 m · coverage ≈ 25%
  5. 5Decide what to change
    UI: Compare coverage to your design target (typically ≥ 0.5)

    Coverage 25% is the well-known slickwater problem. Three levers: (1) lift carrier viscosity (linear gel cuts v_Stokes by μ), (2) lift rate (cuts residence time), or (3) slugify (concentrate proppant in short bursts). Most operators run all three.

    Result: Plan B: 5 cP linear gel + 1 ppa slugs ⇒ recompute, expect coverage ≈ 0.55
Try it yourself
All four helpers (stokesSettlingVelocity, terminalSettlingVelocity, hinderedSettling, predictBankHeight) live in src/lib/proppantSettlingPlacement.ts. Drop them into a small panel under Builder → Proppants to show coverage % live as the engineer slides ppa or rate.

Example 8 — Induced-seismicity Mmax screen for a saltwater-disposal well#

An SWD operator in the Delaware Basin plans to inject 50,000 bbl/day for 30 days into a basement-coupled formation. Question: what is the McGarr volumetric upper bound on the largest event the cumulative injection could trigger, and which severity band does it fall in?

InputValueSource
Cumulative injected volume [bbl]1,500,000 (50k bbl/d × 30 d)Operator schedule
Shear modulus G [Pa]2.0 × 10¹⁰ (typical basement)Static model · core / sonic
Optional fault patch area [m²]1.0 × 10⁶ (1 km × 1 km)Mapped fault from 3D seismic
Optional average slip D [m]0.05 (assumed scenario)Stress-drop scenario
Severity ladderMw < 2 info · < 3 watch · < 4 amber · ≥ 4 criticalscreenInducedSeismicity()
M0_max = G · ΔV_injected (McGarr 2014)
Volumetric upper bound on the seismic moment any single induced event could release — assumes ALL injected volume drives slip on a single fault patch (worst case).
Where
  • G — shear modulus of host rock [Pa]
  • ΔV — cumulative net injected volume [m³]
  • M0_max — maximum seismic moment [N·m]
Driven by (UI fields)
  • mcGarrMaxMoment(deltaVolumeM3, shearModulusPa)
Mw = (2/3) · (log₁₀(M0) − 9.1) (Kanamori 1977)
Convert seismic moment to moment magnitude. Each unit of Mw corresponds to ~32× more energy.
Where
  • M0 — seismic moment [N·m]
  • Mw — moment magnitude [-]
Driven by (UI fields)
  • momentMagnitudeFromM0(m0NewtonM)
M0_det = G · A · D (deterministic scenario, optional)
If a specific fault patch + average slip are known, compute a deterministic Mw. Compare against the McGarr upper bound — they should bracket the realistic answer.
Where
  • A — fault patch area [m²]
  • D — average slip on the patch [m]
Driven by (UI fields)
  • seismicMomentFromSlip({ areaM2, shearModulusPa }, slipM)
OutputValueInterpretation
Injected volume ΔV [m³]≈ 2.385 × 10⁵ (1.5 M bbl × 0.159)BBL_TO_M3 = 0.158987
McGarr M0_max [N·m]≈ 4.77 × 10¹⁵G · ΔV
McGarr Mw upper bound [-]≈ 4.4(2/3)·(log₁₀(4.77e15) − 9.1)
Severity bandcritical (≥ 4)Triggers traffic-light protocol review
Deterministic Mw (1 km² × 0.05 m slip)≈ 4.6G·A·D ⇒ M0 = 1e15 N·m ⇒ Mw 4.6
Recommended actionStagger injection · monitor · cap daily volumeBring Mw_upper below 4
Step-by-step walkthrough — Induced-seismicity screen
  1. 1Convert injected barrels to m³
    UI: BBL_TO_M3 constant in src/lib/inducedSeismicityScreen.ts

    1,500,000 bbl × 0.158987 ≈ 238,481 m³.

    ΔV [m³] = bbl × 0.158987
    Result: ΔV ≈ 2.385 × 10⁵ m³
  2. 2Apply the McGarr volumetric bound
    UI: mcGarrMaxMoment(238481, 2e10)

    Treats the entire injected volume as the elastic strain energy reservoir for slip. This is conservative — most operators use it as a screening tool, not a forecast.

    M0_max = G · ΔV
    Result: M0_max ≈ 4.77 × 10¹⁵ N·m
  3. 3Convert to moment magnitude
    UI: momentMagnitudeFromM0(4.77e15)

    Kanamori (1977). The −9.1 constant assumes M0 in N·m (use −16.1 for dyn·cm).

    Mw = (2/3) · (log₁₀(M0) − 9.1)
    Result: Mw ≈ 4.4
  4. 4Read the severity chip + decide next step
    UI: screenInducedSeismicity({ injectedBarrels, shearModulusPa, ... }) → severity

    info < 2, watch < 3, amber < 4, critical ≥ 4. A 'critical' chip means the operator should engage their traffic-light protocol (TLP), throttle injection, and review monitoring density.

    Result: Severity = critical · TLP review required
Run Example 8 — Induced-seismicity Mmax
Live calculator · Induced-seismicity Mmax
Inputs
Outputs (live)
ΔV
2e+5
M0_max (McGarr)
4.77e+15N·m
Mw upper boundinfo <2 · watch <3 · amber <4 · critical ≥4
4.39
critical
Mw deterministic (G·A·D)From fault patch + slip
3.93
Try it yourself
All helpers (mcGarrMaxMoment, momentMagnitudeFromM0, seismicMomentFromSlip, screenInducedSeismicity, BBL_TO_M3) live in src/lib/inducedSeismicityScreen.ts. Wire them into a small SWD-volume slider on /parent-child to show Mw_upper live as the operator drags daily injection.
Open unified solver with SWD seismicity inputs

SWD induced-seismicity screen — 50,000 bbl/day × 30 days, μ = 30 GPa.

Example 9 — Black-oil PVT for a 35°API Bakken oil at downhole conditions#

A Middle-Bakken producer flowing 35°API oil with gas gravity γg = 0.75 at BHST = 240 °F and bubble-point pressure pb = 2,500 psia. Question: at downhole flowing pressure p_wf = 4,000 psia (above bubble point), what are Rs, Bo, and oil compressibility co — and how would they change at p_wf = 1,800 psia (below bubble point)?

InputValueSource
Oil API gravity [°API]35Sales-line gravity test
Gas specific gravity γg [-]0.75 (separator gas)Gas chromatograph
BHST [°F]240Builder → Fluid model
Bubble-point pressure pb [psia]2,500PVT lab (CCE)
Flowing BHP, case A [psia]4,000 (undersaturated)Well controls
Flowing BHP, case B [psia]1,800 (saturated)Well controls
Rs(p) = γg · [(p / 18.2 + 1.4) · 10^(−a)]^(1/0.83), a = 0.00091·T − 0.0125·API
Standing (1947) solution gas-oil ratio. Used for p ≤ pb; clamped at Rs(pb) for undersaturated oil.
Where
  • p — pressure [psia]
  • T — temperature [°F]
  • Rs — solution GOR [scf/STB]
Driven by (UI fields)
  • standingRs(p, t, api, γg)
Bo_sat = 0.9759 + 0.00012 · [Rs · √(γg / γo) + 1.25·T]^1.2, γo = 141.5 / (API + 131.5)
Standing oil formation-volume factor at saturated conditions [bbl/STB]. γo is oil specific gravity from API.
Where
  • Bo_sat — saturated FVF [bbl/STB]
  • γo — oil specific gravity [-]
Driven by (UI fields)
  • standingBoSaturated(rs, t, api, γg)
co = (−1433 + 5·Rs + 17.2·T − 1180·γg + 12.61·API) / (1e5 · p)
Vasquez-Beggs oil isothermal compressibility [1/psi] above bubble point — drives Bo decompression and material-balance.
Where
  • co — oil compressibility [1/psi]
Driven by (UI fields)
  • vasquezBeggsCo(rs, t, api, γg, p)
Bo(p > pb) = Bob · exp[−co · (p − pb)]
Above bubble point, Bo shrinks with pressure following oil compressibility. At p ≤ pb, Bo = Bo_sat(Rs(p)).
Where
  • Bob — Bo at bubble point [bbl/STB]
Driven by (UI fields)
  • boUndersaturated(bob, co, p, pb)
OutputCase A · p = 4,000 psiaCase B · p = 1,800 psiaInterpretation
Saturated? [-]false (undersaturated)true (saturated)p vs pb
Rs [scf/STB]≈ 597 (clamped at Rs(pb))≈ 386 (Standing at p)Free gas comes out below pb
Bo [bbl/STB]≈ 1.296 (Bob · exp[−co·Δp])≈ 1.236Oil expands as gas evolves
co [1/psi]≈ 1.4 × 10⁻⁵≈ 1.5 × 10⁻⁵Vasquez-Beggs
γo [-]0.8500.850141.5 / (35 + 131.5)
Step-by-step walkthrough — Black-oil PVT snapshot
  1. 1Decide saturated vs undersaturated
    UI: blackOilProperties({ pressurePsi: p, bubblePointPsi: pb, ... })

    Above pb the oil is single-phase liquid; below pb free gas evolves and Rs starts dropping.

    isSaturated = (p ≤ pb)
    Result: Case A: p = 4,000 > pb = 2,500 ⇒ undersaturated. Case B: saturated.
  2. 2Compute Rs (clamped at pb for undersaturated)
    UI: standingRs(p_eff, 240, 35, 0.75)

    Standing's correlation. For undersaturated oil, Rs is fixed at Rs(pb) — no more gas can come out of solution.

    Rs = standingRs(min(p, pb), T, API, γg)
    Result: Case A: Rs ≈ 597 scf/STB · Case B: Rs ≈ 386 scf/STB
  3. 3Compute Bo at bubble point, then adjust
    UI: standingBoSaturated(...) · boUndersaturated(...)

    Bo peaks near bubble point. Above pb it decreases with pressure (oil compresses); below pb it decreases with pressure (less gas in solution).

    Bob = standingBoSaturated(Rs(pb), …) then Bo = isSaturated ? Bob(Rs(p)) : Bob · exp[−co·(p−pb)]
    Result: Case A: Bo ≈ 1.296 bbl/STB · Case B: Bo ≈ 1.236 bbl/STB
  4. 4Push Rs/Bo/co into the material-balance + IPR
    UI: Builder → Fluid model · Results → IPR card

    Bo and co set the material-balance drive index; Rs sets the GOR forecast. A 5% Bo error propagates ~5% to STB recovery — get this right.

    Result: PVT snapshot used by /economics DCA tab + Vogel IPR
Run Example 9 — Black-oil PVT snapshot
Live calculator · Black-oil PVT (Standing / Vasquez-Beggs)
Inputs
Outputs (live)
State
Undersaturated
info
Rs
525scf/STB
Bo
1.3134bbl/STB
co
1.22e-51/psi
γo141.5 / (API + 131.5)
0.85
Try it yourself
All five helpers (standingBubblePoint, standingRs, standingBoSaturated, vasquezBeggsCo, boUndersaturated) plus the wrapper blackOilProperties live in src/lib/blackOilCorrelations.ts. Use blackOilProperties({…}) to get a one-line snapshot for any (p, T, pb, API, γg) combination.
Open unified solver with Bakken black-oil PVT inputs

Bakken black-oil PVT — 35°API, γg 0.75, pb 2,500 psia, BHST 240 °F.

Example 10 — Casing collapse + burst check on 5½-in 17 lb/ft P-110 production string#

A Permian operator runs 5½-in OD × 0.304-in wall P-110 (yield = 110,000 psi) production casing to 9,500 ft TVD. Loads at the worst joint: collapse 6,200 psi (full evacuation), burst 9,800 psi (frac with 0.65-psi/ft fluid + 1,500 psi surface), axial 350,000 lbf (hanging weight + fluid drag). Question: does it pass API design factors, and what are the safety factors?

InputValueSource
Outer diameter OD [in]5.500Casing tally
Wall thickness t [in]0.304 (nominal P-110 17 lb/ft)API spec
Yield strength Yp [psi]110,000 (P-110 grade)Mill cert
Collapse load [psi]6,200 (full evacuation @ 9,500 ft)Worst-case collapse scenario
Burst load [psi]9,800 (frac BHP − backside)Treatment design
Axial load [lbf]350,000 (hanging weight + drag)Tubular drag model
Design factors (burst / collapse / axial)1.10 / 1.125 / 1.6Operator standard (API 5C3 default)
P_burst = 2 · Yp · t / OD (Barlow)
Internal-pressure rating from Barlow's thin-wall hoop-stress formula. Conservative for oilfield D/t.
Where
  • Yp — yield strength [psi]
  • t — wall thickness [in]
  • OD — outer diameter [in]
Driven by (UI fields)
  • barlowBurstPsi(spec)
Units: psi
P_collapse_yield = 2·Yp · (D/t − 1) / (D/t)² API yield-strength regime
Low-D/t collapse pressure. Beyond a critical D/t the rating switches to the plastic regime (API 5C3 Pe = Yp·(A/D-t − B) − C).
Where
  • D/t — diameter-to-thickness ratio [-]
Driven by (UI fields)
  • yieldCollapsePsi(spec) · plasticCollapsePsi(spec) · collapseRatingPsi(spec) auto-picks the max
F_axial = Yp · A_pipe A_pipe = (π/4) · (OD² − ID²)
Axial yield load [lbf] = yield strength × pipe cross-sectional area of steel.
Where
  • A_pipe — steel cross-section [in²]
  • ID = OD − 2·t — inner diameter [in]
Driven by (UI fields)
  • axialYieldLbf(spec)
SF_x = Rating_x / Load_x passes ⇔ SF_burst ≥ DF_b ∧ SF_collapse ≥ DF_c ∧ SF_axial ≥ DF_a
API 5C3 design check: each loading mode must clear its design factor. Failing any one ⇒ string fails.
Where
  • DF — design factor (operator standard, typically 1.10 / 1.125 / 1.6)
Driven by (UI fields)
  • checkCasingDesign(spec, loads, designFactors)
OutputValueInterpretation
D/t [-]≈ 18.15.5 / 0.304
Burst rating P_burst [psi]≈ 12,1602 · 110,000 · 0.304 / 5.5
Collapse rating [psi]≈ 11,080 (yield regime dominates)API 5C3 max(yield, plastic)
Axial yield [lbf]≈ 565,400110,000 × A_pipe (A_pipe ≈ 5.14 in²)
Burst SF≈ 1.24 (≥ 1.10) ✓12,160 / 9,800
Collapse SF≈ 1.79 (≥ 1.125) ✓11,080 / 6,200
Axial SF≈ 1.62 (≥ 1.6) ✓ (just passes)Watch — bump grade or wall if drag rises
Design verdictPASSAll three SF clear their design factors
Step-by-step walkthrough — Casing design check
  1. 1Build the spec + loads
    UI: spec = { odIn: 5.5, wallIn: 0.304, yieldPsi: 110000 }; loads = { burstLoadPsi: 9800, collapseLoadPsi: 6200, axialLoadLbf: 350000 }

    Use mill-certified yield (nominal grade × min spec). Loads come from the worst-case operating envelope (full evacuation for collapse, frac BHP for burst, total hung weight + drag for axial).

    Result: Spec + 3 loads ready for the checker
  2. 2Compute ratings
    UI: barlowBurstPsi · collapseRatingPsi · axialYieldLbf

    Barlow for burst; API 5C3 with the larger of yield-strength and plastic regimes for collapse; A_pipe × Yp for axial.

    P_burst = 2·Yp·t/OD · P_collapse = max(yield, plastic) · F_axial = Yp·A_pipe
    Result: Burst 12,160 psi · Collapse 11,080 psi · Axial 565,400 lbf
  3. 3Divide by loads → SFs
    UI: checkCasingDesign(spec, loads, { burst: 1.10, collapse: 1.125, axial: 1.6 })

    The check returns burstSafetyFactor, collapseSafetyFactor, axialSafetyFactor, and a single passes boolean.

    SF_x = Rating_x / Load_x
    Result: Burst 1.24 · Collapse 1.79 · Axial 1.62 · passes = true
  4. 4Compare to design factors + decide
    UI: Builder → Wells & perforations → Casing program

    Fail any one ⇒ upgrade grade (e.g. P-110 → Q-125), thicken wall, or relieve loads (rate down on collapse, lower frac BHP on burst). Here axial is the tightest — if drag estimates change, re-check.

    Result: Verdict: PASS, but axial SF is the bottleneck — re-check if BHA / drag changes.
Run Example 10 — Casing burst / collapse / axial check
Live calculator · Casing burst / collapse / axial check
Inputs
Outputs (live)
SF burst (≥ 1.1)
1.24
pass
SF collapse (≥ 1.125)
1.21
pass
SF axial (≥ 1.6)
1.56
fail
Overall verdict
FAIL
fail
Try it yourself
All helpers (diameterToThickness, barlowBurstPsi, yieldCollapsePsi, plasticCollapsePsi, collapseRatingPsi, axialYieldLbf, checkCasingDesign) live in src/lib/casingDesign.ts. Wire checkCasingDesign() into a Builder → Wells & perforations card to chip PASS/FAIL live as the engineer slides BHP / evacuation depth / hung weight.
Open unified solver with Permian P-110 casing inputs

Permian 5½-in 17 lb/ft P-110 casing check — TVD 9,500 ft, internal 9,800 psi.

Why these ten?
Examples 1–4 exercise the four hardest end-to-end workflows (calibration, planning, parent–child screening, real-time detection). Examples 5–7 zoom into three calculation kernels (stress inversion · embedded DFN transfer · proppant bank settling). Examples 8–10 cover three regulatory / hardware-rating screens engineers must clear before any treatment: induced-seismicity Mmax, black-oil PVT, and casing collapse/burst. Reproduce all ten and you understand both the workflows and the math.

6. Physics & equations (what runs in the background)

Every formula behind the inputs you change in sensitivity studies — fracture toughness, leak-off, hydrostatic, breakdown, stress shadowing, and proppant transport.

When you sweep a parameter in a sensitivity (DS) run, this is the math the solver evaluates. Each equation lists the UI field that drives it so you know exactly what changing K_IC, C_L, or E does.

Physics model
Fracture-mechanics + transport kernel
Governing equations
  • P_breakdown = 3·SH_min − SH_max + T₀ − P_pore (Hubbert-Willis)
  • K_I ≥ K_IC (mode-I propagation criterion)
  • q_leak = 2·C_L / √(t − t_open) (Carter II)
  • w_max = (2(1−ν)·p_net·h) / G (PKN width)
  • Δσ_h = p_net·[1 − d/√(d²+a²)] (Sneddon shadow)
Assumptions
  • Linear-elastic, isotropic rock at the perf face
  • Newtonian carrier unless rheology card overrides (n′, K′)
  • Height-contained PKN unless KGD/Radial branch selected
  • Carter-II leakoff (no spurt loss term unless explicitly set)
Discretization

Explicit time march on stage schedule (sub-second dt during slurry), implicit Picard for wellbore-storage coupling; DDM grid for non-planar 3D.

References
  • Hubbert & Willis (1957), Mechanics of hydraulic fracturing
  • Nordgren (1972), Propagation of a vertical hydraulic fracture
  • Sneddon (1946), Distribution of stress in the neighbourhood of a crack
  • Carter (1957), Optimum fluid characteristics for fracture extension
Model limitations
  • Single-phase wellbore unless the drift-flux toggle (Wellbore preview) is enabled; no OLGA-class slug tracking.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Slug flow can spike surface pressure and mask a real screen-out signature; a single-phase kernel will report a smooth trace and the operator can miss the intervention window.
    When it breaks down:
    Anytime the produced fluid is a gas-liquid mix at surface conditions (gas-lifted wells, high-GOR flowbacks) or when foam/energized fluids are pumped.
    Safer alternative:
    Enable the drift-flux toggle in the Wellbore preview and cross-check surface pressure against the drift-flux advisory chip; for hard slug regimes use an external OLGA-class run and import the resulting BHP curve as a boundary condition.
  • Non-planar 3D uses half-space DDM with no full poroelastic coupling — pair with /parent-child for depletion-altered stress.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Half-space DDM captures elastic interaction between fractures but ignores the pore-pressure change that a depleting parent well leaves in the rock; ignoring depletion under-predicts frac-hit severity.
    When it breaks down:
    Infill drilling next to producers older than ~90 days, especially in reservoirs with kh above ~50 md·ft where drainage radius is large.
    Safer alternative:
    Run the /parent-child route on the same workspace and read the poroelastic Δσ_h/Δσ_H columns; feed the rotated SHmax back into the fracture design via the runtime SHmax → geometry loop.
  • Parent-child far-field stress is 2-D Geertsma unless Mindlin layered toggle is on; thermo-poro time loop covered separately under §11.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A single-layer Geertsma disc misses vertical stress attenuation across benches; azimuth rotation predictions can be off by several degrees in stacked plays.
    When it breaks down:
    Multi-bench developments (Wolfcamp A/B/C, Middle Bakken/TFS, Marcellus/Utica) where the child is not at the same TVD as the parent depletion.
    Safer alternative:
    Enable the Mindlin layered toggle on /parent-child and supply bench (ν, α, h); if bench continuity is uncertain, run both toggles and treat the spread as the uncertainty band.
  • Carter leakoff assumes negligible spurt; for tight rocks use the field-validation campaign override (`src/lib/fractureValidation.ts`).
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Spurt loss can dominate the first few seconds of pump time in very tight rock; ignoring it under-predicts pad pressure and can steer the design toward too little pad.
    When it breaks down:
    Permeabilities below ~50 nd or when the pad fluid has a poor wall-building filter cake (slickwater into ultra-tight shale).
    Safer alternative:
    Load a DFIT or step-rate G-function into a field-validation campaign; the leakoff override in `src/lib/fractureValidation.ts` will fit spurt + Carter coefficients directly to the measured falloff.
  • Proppant transport uses Stokes + Boycott tilt; full hindered-settling RZ exponent is fixed at 4.65.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    The Richardson-Zaki exponent of 4.65 is calibrated for spherical, mono-disperse proppant in Newtonian carriers; using it outside that band under- or over-predicts proppant transport and can lead to premature screen-out or a starved zone at the tip.
    When it breaks down:
    Ultra-lightweight, coated, or fibre-laden proppants; highly-shear-thinning gels; or slurries above ~10 ppa where hindered settling deviates strongly from mono-disperse Stokes.
    Safer alternative:
    Cross-check the transport prediction against the FracPro-style report's slurry-validation card and, for non-standard proppants, override k·w with the ISO-13503-5 coverage helper (see stressConductivityCoverage.ts).
Validation datasets
DatasetSourceMetricResult
DFIT / PKN / KGD / Radial fit[1,2]src/lib/fractureValidation.ts + field-validation campaigns routeMAE / RMSE / bias / MAPE vs measured BHP10 drift-guard cases, RMSE < 75 psi on synthetic decks
Probabilistic geometry bundle[3]src/lib/__tests__/probabilisticFractureBundle.test.tsP10/P50/P90 bands on Cf and surface pressure8 tests, Spearman tornados stable across seeds
Buckley-Leverett analytical comparator[4,5]src/lib/__tests__/buckleyLeverettKernelParity.test.tsL∞ saturation error vs Welge tangentIMPES + TVD L∞ ≤ 0.5; TVD L1 ≤ IMPES L1 + 0.05
Standing-Katz Z(p,T)[6,7,8]src/lib/wellbore/__tests__/standingKatz.test.tsZ vs Sutton 1985 + Wichert-Aziz sour-gas tables10 tests, |ΔZ| < 0.005 over reduced-T 1.05–3.0
Grid-convergence harness[9,10]/grid-convergence (3 regime scenarios)Observed order p (Richardson extrapolation)Upwind p ≈ 1, TVD p ≈ 2 (shock/capillary/compressible)
Black-oil 3P mass balance[11]src/lib/reservoir/__tests__/compositionalBlackOil3P.test.tsPer-step phase mass residual8 tests, worst |Δm|/m < 0.5 % on closed cell
References
  1. Nolte, K.G. (1979). Determination of fracture parameters from fracturing pressure decline. SPE 8341. doi:10.2118/8341-MS
  2. Barree, R.D., Barree, V.L., Craig, D.P. (2009). Holistic fracture diagnostics. SPE 107877. doi:10.2118/107877-PA
  3. Cinco-Ley, H., Samaniego, V.F. (1981). Transient pressure analysis for fractured wells. SPE 7490. doi:10.2118/7490-PA
  4. Buckley, S.E., Leverett, M.C. (1942). Mechanism of fluid displacement in sands. Trans. AIME 146. doi:10.2118/942107-G
  5. Welge, H.J. (1952). A simplified method for computing oil recovery by gas or water drive. Trans. AIME 195. doi:10.2118/124-G
  6. Standing, M.B., Katz, D.L. (1942). Density of natural gases. Trans. AIME 146. doi:10.2118/942140-G
  7. Dranchuk, P.M., Abou-Kassem, J.H. (1975). Calculation of Z factors using equations of state. JCPT 14(3). doi:10.2118/75-03-03
  8. Wichert, E., Aziz, K. (1972). Calculate Z's for sour gases. Hydrocarbon Processing 51(5).
  9. Roache, P.J. (1994). Perspective: a method for uniform reporting of grid refinement studies. J. Fluids Eng. 116(3). doi:10.1115/1.2910291
  10. LeVeque, R.J. (2002). Finite Volume Methods for Hyperbolic Problems. Cambridge University Press. https://doi.org/10.1017/CBO9780511791253
  11. Aziz, K., Settari, A. (1979). Petroleum Reservoir Simulation. Applied Science Publishers.

6.1 Fracture initiation (breakdown pressure)#

P_breakdown = 3·SH_min - SH_max + T₀ - P_pore
Pressure required to initiate a vertical fracture in the wellbore (full-tensor Hubbert-Willis criterion).
Used in
Pressure Advisor — Step 4 (Breakdown) when SH_max anisotropy is known
Calibration hub — Kirsch-stress form for openhole / oriented perforations
Module
src/lib/pressureAdvisor.ts → breakdownPressurePsi (tensor branch)
Where
  • SH_min — minimum horizontal stress [psi]
  • SH_max — maximum horizontal stress [psi]
  • T₀ — tensile strength of the rock [psi]
  • P_pore — pore pressure [psi]
Driven by (UI fields)
  • Static model → SH_min, SH_max, P_pore
  • Calibration → T₀ (fitted from DFIT)
Assumptions
  • Vertical wellbore, vertical fracture initiation
  • Linear-elastic isotropic rock at the perf face
  • No thermal or poroelastic Δσ correction
Validity range
Use whenever SH_max ≠ SH_min (measurable horizontal stress anisotropy).
Units: psi (field) or kPa (SI)
P_breakdown ≈ SH_min + T₀ - P_pore
Uniaxial reduction of the tensor form above, used when SH_max ≈ SH_min (isotropic horizontal stress).
Used in
Section 4 — Pressure advisor walkthrough (Step 4)
Section 5 — Examples 1 & 2 (worked numbers)
Pressure Advisor — Step 4 (Breakdown) default branch
Module
src/lib/pressureAdvisor.ts → breakdownPressurePsi (uniaxial branch)
Where
  • Identical to the tensor form with SH_max = SH_min ⇒ 3·SH_min − SH_max = 2·SH_min, then a further simplification collapses to SH_min in cased+perforated completions where the cohesion term carries the rest.
Assumptions
  • SH_max ≈ SH_min (low horizontal-stress anisotropy)
  • Cased + perforated completion (pre-existing perforation; no rock-cohesion term)
  • Effective-stress form (P_pore subtracted from total stress)
Validity range
Vertical well, low-anisotropy unconventional plays (Bakken, Eagle Ford, Permian). For high anisotropy switch back to the tensor form above.
Units: psi (field) or kPa (SI)

6.2 Mode-I fracture toughness (propagation criterion)#

K_I = (P_net) · √(π · a) ≥ K_IC
A fracture propagates when the stress-intensity factor K_I exceeds the rock's mode-I fracture toughness K_IC.
Where
  • K_I — stress-intensity factor at the tip [psi·√in]
  • P_net = P_frac - SH_min — net pressure inside the fracture [psi]
  • a — fracture half-length [in]
  • K_IC — fracture toughness, fitted from DFIT or from lab data [psi·√in]
Driven by (UI fields)
  • Fracture options → K_IC (this is the parameter you swept in sensitivity)
  • Static model → SH_min
  • Well controls → pump rate (drives P_frac)
Units: psi·√in (field) — typical Bakken range 1,000–2,500 psi·√in
Φ(K_IC, C_L) = Σᵢ [ p_obs(tᵢ) − p_model(tᵢ; K_IC, C_L) ]²
Least-squares residual that the DFIT calibration minimises over the post-closure G-function window to back out K_IC (and optionally C_L).
Used in
DFIT calibration — closure-fit minimiser
Calibration report (PDF + CSV) — Inputs · Assumptions · fitted T₀/K_IC section
Module
src/lib/dfit.ts → fitDfitClosure
Where
  • p_obs(tᵢ) — measured bottomhole pressure at sample i [psi]
  • p_model(tᵢ; K_IC, C_L) — Carter-II falloff prediction with trial K_IC and Carter coefficient
  • tᵢ — sample times inside the post-closure G-function window
Assumptions
  • Least-squares (Gaussian) residual on the post-closure window
  • Carter-II falloff is the forward operator (1-D leak-off, planar fracture)
  • Equal weighting per sample; no robust loss
Validity range
Post-closure window only; ≥ 6 samples; K_IC search bounds 0.5–2.5 MPa·√m.
What raising K_IC does in a sensitivity
Higher K_IC → harder for the fracture tip to advance → shorter, fatter fractures at the same pump energy. Net pressure rises and treating pressure rises with it. In Results you'll see longer pump times to hit the same proppant placement.

6.3 Carter leak-off (fluid loss to matrix)#

v_L(t) = C_L / √(t - τ)
Carter's 1-D leak-off velocity at a fracture face element first exposed at time τ.
Where
  • v_L — leak-off velocity normal to the fracture face [ft/min]
  • C_L — Carter leak-off coefficient [ft/√min]
  • t — current simulation time [min]
  • τ — time the element first opened [min]
Driven by (UI fields)
  • Fracture options → C_L (Carter coefficient — the second-most-common sensitivity parameter)
  • Curve sets → relative permeability (sets effective C_L through compressibility)
Units: C_L in ft/√min (field) or m/√s (SI)

6.4 Wellbore hydrostatic pressure#

P_hydrostatic = 0.052 · ρ_mud · TVD
Bottomhole pressure contribution from a static column of fluid (field-units form).
Where
  • P_hydrostatic — pressure at depth [psi]
  • 0.052 — unit conversion (psi · gal) / (lb · ft)
  • ρ_mud — mud weight [ppg]
  • TVD — true vertical depth [ft]
Driven by (UI fields)
  • Pressure advisor → mud weight
  • Wells & perforations → TVD
Units: psi (P), ppg (ρ), ft (TVD)

6.4b Temperature-dependent fluid rheology (Arrhenius decay)#

μ(T) = μ_ref · exp[ E_a / R · (1/T − 1/T_ref) ] (T, T_ref in Kelvin)
Single-step Arrhenius viscosity decay along the fracture as the carrier warms from injection temperature toward bottomhole static temperature (BHST). Composes with first-order breaker decay as μ_eff(x) = μ(T(x)) · (1/2)^(t_res(x)/T½).
Used in
Builder Fluid model → Temperature-dependent μ(x) along fracture card
Proppant concentration map → per-x viscosity feeds Richardson–Zaki settling
Module
src/lib/fluidRheologyTemperature.ts → viscosityProfileAlongFracture
Where
  • μ(T) — local viscosity at fracture cell temperature T [cP]
  • μ_ref — bench viscosity at reference temperature (default 150 °F) [cP]
  • E_a — activation energy (per family; see §11) [kJ/mol]
  • R — universal gas constant 8.314 [J/(mol·K)]
  • T, T_ref — temperatures in absolute units [K]
Driven by (UI fields)
  • Fluid model → fluid family, μ_ref, T limit
  • Static model → BHST
  • Well controls → injection T, residence time
Assumptions
  • Single-step Arrhenius — no shear-history or polymer-degradation coupling
  • Linear T-ramp from injection to BHST (override-able)
  • Above the fluid's temperature limit the model still evaluates μ but flags the cell out-of-band rather than zeroing it
Validity range
Slickwater / linear-gel / crosslinked families with bench rheometer data. Activation energies are family-level defaults — override per job with measured fits.
Units: cP (μ), kJ/mol (E_a), K (T)

6.5 PKN fracture width (height-contained model)#

w_max = 2.31 · [ (q · μ · L) / (E' · h) ]^(1/4)
Perkins-Kern-Nordgren maximum fracture width for a height-contained planar fracture.
Where
  • w_max — peak width at the wellbore [in]
  • q — slurry rate per fracture [bpm]
  • μ — apparent fluid viscosity [cP]
  • L — fracture half-length [ft]
  • E' = E / (1 - ν²) — plane-strain modulus [psi]
  • h — fracture height [ft]
Driven by (UI fields)
  • Static model → Young's modulus E, Poisson's ratio ν
  • Well controls → pump rate q
  • Fluid model → viscosity μ

6.6 Proppant transport (settling velocity, Stokes)#

v_s = ( g · d² · (ρ_p - ρ_f) ) / (18 · μ)
Stokes terminal settling velocity for a proppant grain in slurry. Used to predict where proppant lands inside the fracture.
Where
  • v_s — settling velocity [ft/s]
  • g — gravitational acceleration [ft/s²]
  • d — grain diameter [in] (mesh size)
  • ρ_p — proppant density [lb/ft³]
  • ρ_f — fluid density [lb/ft³]
  • μ — slurry viscosity [cP]
Driven by (UI fields)
  • Proppants → mesh size (sets d), proppant type (sets ρ_p)
  • Fluid model → ρ_f and μ

6.6b Boycott tilt enhancement#

F_Boycott = 1 + (L · sin θ / w) · F_RZ (capped at 50×)
Multiplier on Stokes settling velocity for a tilted fracture. In a non-vertical fracture, grains slide along the upper face and accelerate the bulk settling rate (the Boycott effect).
Used in
Live Pumping — Proppant dune overlay (severity chip)
Proppant bank-height prediction (Section 5 — Example 7)
Module
src/lib/proppantDuneMechanics.ts
Where
  • L — fracture characteristic length [ft]
  • θ — tilt angle from horizontal [rad]
  • w — fracture width [ft]
  • F_RZ — Richardson-Zaki hindered-settling factor (1−φ)^n, n ≈ 4.65
Assumptions
  • Stokes settling regime (Re_p < 1)
  • Tilt angle θ measured from horizontal (θ = 0 ⇒ vertical fracture, no enhancement)
  • F_RZ already absorbs concentration-dependent hindering
Validity range
0 ≤ θ ≤ 60°; multiplier hard-capped at 50× to prevent runaway in near-horizontal fractures.

6.7 Stress shadow (Sneddon)#

Δσ_h(r) = P_net · [ 1 - r / √(r² + c²) ]
Increase in horizontal stress at distance r from a planar fracture of half-height c, used to model cluster-to-cluster interference.
Where
  • Δσ_h — induced stress increase [psi]
  • P_net — net pressure inside the source fracture [psi]
  • r — perpendicular distance from the fracture plane [ft]
  • c — fracture half-height [ft]
Driven by (UI fields)
  • Wells & perforations → cluster spacing
  • Fracture options → height growth limits
Trace any number back to its formula
In Results, click the 🔍 icon next to any computed value. The Equation Trace overlay highlights which formula produced it and which input panels feed each variable.

6.7 Inclined wellbore breakdown correction (Hubbert-Willis full form)#

σ_θ_dev = σ_θ_v + sin²(inc) · [(1 + cos(2β))/2] · (σ_v − SH_min) ⇒ P_break(inc) = P_break(0) · σ_θ_dev / σ_θ_v
Adjusts the vertical-well Hubbert-Willis breakdown for inclination + azimuth. At inc = 0 the factor is exactly 1.0 (Pressure Advisor's simplified form). For a deviated lateral drilled at angle β to SH_max, the overburden contributes via sin²(inc).
Used in
Pressure Advisor — Step 4 (Breakdown check) when survey inclination ≠ 0
Module
src/lib/wellboreInclinationFactor.ts → wellboreInclinationFactor / adjustBreakdownForInclination
Where
  • inc — wellbore inclination from vertical [deg]
  • β — angle between wellbore azimuth and SH_max [deg]
  • σ_v — overburden stress (defaults to 1.05·SH_max if unknown) [psi]
  • SH_min, SH_max — horizontal in-situ stresses [psi]
  • σ_θ_v = 3·SH_min − SH_max − P_pore (classical Hubbert-Willis)
Assumptions
  • Failure occurs in the SH_min direction around the wellbore wall
  • Linear elastic rock; no near-wellbore plasticity
  • σ_v ≈ 1.05·SH_max when overburden gradient unmeasured
Validity range
Inclination clamped to [0°, 90°]; collapses byte-identically to the vertical form at inc = 0 regardless of azimuth. Best for inclinations < 60° drilled in tight unconventional rock; highly deviated wells in plastic shales need a full geomechanical run.
Units: psi

6.8 DFIT K_IC fit objective (Carter II substituted)#

min_{K_IC, C_L} Σᵢ [ P_meas(tᵢ) − P_Carter(tᵢ; K_IC, C_L, SH_min, V_0) ]²
Explicit least-squares cost for the closure-tail fit. The Carter II falloff is substituted directly so the residual chart on the calibration card shows per-sample error contributions.
Used in
DFIT calibration card — K_IC fit + residual chart
Calibration report PDF (T₀, K_IC, C_L block)
Module
src/lib/fractureValidation.ts → fitCarterFalloff
Where
  • P_meas(tᵢ) — measured BHP at sample i [psi]
  • P_Carter(t; K_IC, C_L, …) — analytical falloff model
  • K_IC — fracture toughness [psi·√in]
  • C_L — Carter leak-off coefficient [ft/√min]
  • V_0 — closure-time fracture volume [ft³]
Assumptions
  • Single-fracture geometry assumption holds through shut-in
  • Pressure-dependent leak-off not active before closure
  • ISIP and SH_min already picked / known
Validity range
Falloff window from ~3·G to closure for tight reservoirs; gel-coated proppant cases need a damage multiplier on C_L.
Units: psi (residuals)

6.9 Power-law PKN wellbore width (extends 6.1 to non-Newtonian fluids)#

w_w = [ K' · ((4n'+2)/(3n'))^n' · (2q/(w·h))^(n'−1) · q · L / (E' · h) ]^(1/(2n'+2))
Maximum wellbore width for a propagating PKN fracture in a power-law fluid. Collapses byte-identically to the Newtonian Nordgren form (3·[μqL/E']^(1/4)·h^(-1/4)) when n' = 1 and K' = μ.
Used in
Fluid model panel — width preview chip
Net-pressure match — modeled Pnet for slickwater vs gel fluids
Module
src/lib/powerLawPknWidth.ts → pknWidth (widthModel: 'newtonian' | 'power-law')
Where
  • n' — power-law flow behaviour index [-]
  • K' — consistency index [Pa·s^n']
  • q — wing volumetric rate [m³/s]
  • h — fracture height [m]
  • L — fracture half-length [m]
  • E' — plane-strain modulus E/(1−ν²) [Pa]
Assumptions
  • Elliptical cross-section (PKN)
  • γ̇ ≈ 2q/(w·h) average gap shear rate
  • Picard fixed-point converges (typical ≤ 16 iterations)
Validity range
0.3 ≤ n' ≤ 1.0; K' from rheology card. For HVFR + slickwater hybrids the n'/K' values from FluidRheologyModel (Phase 1.2) feed in directly.
Units: SI (m, Pa·s^n', m³/s) — convert via unitsCanonical at call site

6.10 Forchheimer non-Darcy pressure drop in the propped pack#

ΔP / L = (μ · v) / k + β · ρ · v²
Total pressure gradient in the propped pack — Darcy viscous term plus Forchheimer inertial term. The β coefficient comes from the proppant non-Darcy registry (§2.2).
Used in
/refrac deliverability card — advisory chip when v_pore > 0.1 m/s
/economics deliverability card — same advisory chip
Module
src/lib/proppantNonDarcyBeta.ts → nonDarcyBetaPerFt / inertialReynolds
Where
  • μ — fluid viscosity [Pa·s]
  • v — superficial pore velocity [m/s]
  • k — pack permeability [m²] (mD × 9.869e-16)
  • ρ — fluid density [kg/m³]
  • β — non-Darcy coefficient [1/m] (Cooke / Pursell form β = a/(k^b · φ^c))
Assumptions
  • Single-phase flow
  • Pack porosity from DEFAULT_PROPPED_POROSITY per family
  • Inertial losses meaningful only when Re_β > 0.1
Validity range
Gas wells and high-rate liquids; for low-rate oil wells the Darcy term dominates and β can be safely dropped.
Units: Pa/m (ΔP/L)

6.11 1-D fracture temperature profile (couples to breaker schedule)#

∂T/∂t + v(x) · ∂T/∂x = α · ∂²T/∂x²
Convection-diffusion temperature evolution along the fracture half-length. Wellbore BC = T_inj (Dirichlet); tip BC = ∂T/∂x = 0 (insulated). Output T(x, t) feeds breakerSchedule.ts so T½(x) and μ(t) decay vary along the fracture, not just at the wellbore.
Used in
Breaker schedule card — μ(t, x) heatmap (planned UI)
Fluid model panel — thermal-front chip (planned UI)
Module
src/lib/fractureTemperatureProfile.ts → fractureTemperatureProfile + breakerInputsAlongFracture
Where
  • T(x, t) — slurry temperature [°F]
  • v(x) — local slurry velocity along the fracture [ft/s]
  • α — effective thermal diffusivity [ft²/s] (default ≈ 1e-5)
  • T_inj — wellhead injection temperature [°F]
  • BHST — bottom-hole static temperature [°F] (initial condition)
Assumptions
  • 1-D along-fracture flow (lateral averaging across height + width)
  • Explicit upwind FD scheme; CFL ≤ 1 and Fourier ≤ 0.5 enforced by sub-stepping
  • Slurry temperature dominates rock heat-up (rock-side conduction lumped into α)
Validity range
Tight unconventional rock; for high-permeability or geothermal cases use the coupled T-M-H kernel (thermoPoroGrid3D.ts) instead.
Units: °F, ft, s

6.12 Stokes settling with Francis-Boycott wall correction and Richardson-Zaki hindered settling#

v_eff = [ g · (ρ_p − ρ_f) · d² / (18 · μ) ] · (1 − d/w)² / (1 + 2.1·d/w) · (1 − φ)^n
Effective proppant settling velocity inside a hydraulic fracture — Stokes terminal velocity multiplied by the Francis-Boycott wall-effect factor and the Richardson-Zaki hindered-settling exponent. The regime classifier maps Π = v_eff / v_fluid_vertical onto suspended / hindered / settled bands shown on the live heatmap.
Used in
/live-pumping settling-regime heatmap — current operating point Π marker
Proppant transport panel — banking risk advisory
Module
src/lib/proppantSettlingRegimeMap.ts → evaluateSettlingRegime / buildSettlingRegimeMap
Where
  • v_eff — effective settling velocity [ft/s]
  • d — mean grain diameter [in], converted internally to ft
  • w — local fracture width [in]
  • μ — apparent fluid viscosity [cP], converted internally to lbm/(ft·s)
  • ρ_p, ρ_f — proppant and fluid densities [lbm/ft³] (from SG)
  • φ — in-situ proppant volume fraction (from ppa and proppant SG)
  • n — Richardson-Zaki exponent (default 4.65 for low-Re sand-in-water)
Assumptions
  • Newtonian carrier within the cell (power-law μ_app evaluated at γ̇ = 100 s⁻¹ when called from FluidRheologyModel)
  • Spherical proppant; aspect-ratio corrections folded into the apparent SG when applicable
  • Vertical fluid velocity approximated as q_slurry / (h_frac · w_frac)
  • Random-close-packing cap φ ≤ 0.6
Validity range
Re_p ≲ 1 (creeping flow). For Re_p ≳ 10 use a drag-law correction (Schiller-Naumann) outside the heatmap.
Units: ft/s
T₀_eff(σ_n) = clamp(T₀ − β · (σ_n − σ_ref), T₀_min, T₀)
Bilinear pressure-dependent cohesive tensile envelope (RMRE 2025). Effective tensile strength decreases linearly with the normal effective stress carried across the cohesive zone.
Used in
Non-planar 3D — Builder Fracture Options → Cohesive envelope
Paper benchmarks — /trust/paper-benchmarks (RMRE 2025 KGD parity)
Module
src/lib/nonPlanar3D/cohesivePressureDependent.ts → evaluateCohesiveEnvelope
Where
  • T₀ — reference cohesive tensile strength [psi]
  • β — pressure-dependence slope [-]
  • σ_n, σ_ref — current and reference normal effective stress [psi]
  • T₀_min — floor to avoid unphysical zero strength [psi]
Assumptions
  • Linear pressure dependence within the bracket [T₀_min, T₀]
  • Mode-I traction dominates the tip response (bilinear T–S curve)
Validity range
Tight rocks under variable confining stress; β calibrated from lab HF tests. Set model = "constant" to recover the legacy K_IC-only path byte-identically.
Units: psi
∂w/∂t + ∂/∂s ( w³/(12·μ) · ∂p/∂s ) = q_leak
Cubic-law lubrication inside an intersected natural fracture (Hu-Gan-Hurst-Elsworth 2023). Governs pressure evolution and aperture change within the NF segment during HF↔NF interaction.
Used in
Non-planar 3D — Builder Fracture Options → NF lubrication (opt-in)
Paper benchmarks — /trust/paper-benchmarks (Hu 2023 crossing table)
Module
src/lib/nonPlanar3D/nfLubrication.ts → stepNfLubrication
Where
  • w — NF aperture [m]
  • s — arc length along NF [m]
  • μ — fluid viscosity [Pa·s]
  • p — fluid pressure inside NF [Pa]
  • q_leak — Carter leak-off sink [m/s]
Assumptions
  • 1-D flow along NF; smooth parallel-plate cubic law
  • Linear compliance for pressure-driven aperture change
  • Backward-Euler implicit tridiagonal solve (unconditionally stable)
Validity range
NF aperture ≥ ~0.1 mm; Reynolds number in lubrication regime. Disabled ≡ pressure at intersection equals HF tip pressure (legacy).
Units: SI (m, Pa·s, Pa, m/s)
Δt_max ≤ safety · min_i ( wᵢ³ · ρ_f / (12 · μ · Lᵢ²) )
Explicit-staggered CFL stability bound for coupled solid ↔ lubrication advance (Fu-Johnson-Carrigan 2013). Caps the pipeline advance step so pressure diffusion inside NF segments stays stable.
Used in
Non-planar 3D — Builder Fracture Options → Staggered stability bound (opt-in)
Paper benchmarks — /trust/paper-benchmarks (Fu 2013 slip-onset case)
Module
src/lib/nonPlanar3D/staggeredStabilityBound.ts → evaluateStaggeredStabilityBound
Where
  • wᵢ, Lᵢ — aperture and segment length of NF segment i
  • ρ_f — fluid density
  • μ — fluid viscosity
  • safety — user-tunable factor ≤ 1 (default 0.5)
Assumptions
  • Explicit-staggered coupling between DDM solid step and NF lubrication step
  • Smallest (w, L) pair drives the bound
Validity range
Applies when NF lubrication is enabled. Off by default → pipeline advance dt is unchanged (byte-identical).
Units: SI (s, m, Pa·s, kg/m³)
w(0,t) ∝ t^(1/3); L(t) ∝ t^(2/3); p_w(t) ∝ t^(-1/3) (M-vertex, viscosity-dominated KGD)
Adachi-Detournay 2002 self-similar KGD scaling in the viscosity-dominated (M-vertex) regime; the K-vertex (toughness-dominated) counterpart has L ∝ t^(2/3) with different pre-factors. Used as the analytical parity check for the coupled solver.
Used in
Paper benchmarks — /trust/paper-benchmarks (UXFEM 2023 KGD parity + en-échelon)
Analytical verification — /trust/analytical-verification
Module
src/lib/benchmarks/hfCoupledBenchmarks.ts → runAllHfCoupledBenchmarks
Where
  • w(0,t) — wellbore width vs time
  • L(t) — fracture half-length vs time
  • p_w(t) — wellbore net pressure vs time
Assumptions
  • Plane-strain KGD geometry; Newtonian fluid
  • Constant injection rate; single vertex regime (M or K) dominates
  • 5 % envelope on the observed vs analytical scaling exponent
Validity range
Early-time viscosity-dominated or late-time toughness-dominated windows; away from vertex transitions the exponents drift and the parity check is loosened per benchmark config.
Units: consistent SI

7. Sensitivity & calibration runs

How to set up a Design-of-Sensitivity (DS) sweep and what each parameter affects.

  1. From the Workspace dashboard, click Sensitivity → New DS run.
  2. Pick the parameters to sweep. The Bakken template pre-populates K_IC, C_L, and Young's modulus with realistic ranges.
  3. Choose sweep type: Latin Hypercube (recommended), Full factorial, or 1-at-a-time.
  4. Set the response metric — e.g. 'Final propped half-length [ft]' or 'Treating pressure peak [psi]'.
  5. Click Queue. The DS scheduler launches one simulation per design point.
  6. When complete, open Results → Sensitivity tornado to see which parameter has the biggest impact on your response metric.
Recommended ranges (Bakken)
K_IC: 1,000–2,500 psi·√in · C_L: 0.0005–0.005 ft/√min · E: 3.5e6–6.5e6 psi · ν: 0.20–0.30. These match the DS ranges baked into the Bakken template.

8. Troubleshooting

Common 'I can't change X' issues and how to fix them.

SymptomLikely causeFix
Save Changes is greyed outNo edits committed since last save, OR a Validate error is blocking the change.Click outside the input to commit, then click Validate. Fix any red-flagged fields.
Sensitivity parameter doesn't change resultsSweep range too narrow, or the parameter is overridden by a calibration value.Widen the range. Check Calibration → Active fits — fitted K_IC overrides Fracture options unless you Unlink.
Paste from Excel tab inserts blanksExcel tab name doesn't match the panel id.Rename the Excel tab to match (e.g. 'Wells_and_perforations') or use the per-panel column header template.
Run on Server stays in 'queued' foreverServer worker is paused or out of credits.Open Settings → Compute and resume the worker. Local Run still works.
Results show — (em-dash) instead of numbersThat output wasn't computed for this case (e.g. proppant placement on a slickwater-only sim).Check Output panel — enable the metric, re-run.
Wizard 'Apply' is disabledOne of the required fields failed realism check (red).Open the Validation & warnings card — fix the listed fields.

9. Live operations & post-job analysis

Real-time pumping overlay, ISIP auto-pick, Nolte-Smith, decline analysis, step-down auto-detect, net-pressure history-match, fiber-optic streaming, and live auto-tuner.

8.1 Live Pumping (/live-pumping)#

Plan-vs-actual overlay with role-banded stages (Pre-flush · Pad · Slurry · Post-flush) and a real-time screen-out risk pill. Streams via WebSocket, REST polling, WITSML, DAS or DTS — pick the transport from the picker chip group. WITSML uses Basic-auth + ?startIndex= cursor; per-workspace credentials are saved locally.

  • Wellbore displacement strip — live SVG showing pumped banks with first-sand-at-perfs + flush ETA chips. Export pad-clock CSV from the strip.
  • Nolte-Smith net-pressure panel — log(Pnet) vs log(t) with auto slope-classified Mode I/II/III/IV chip. Save per-job closure/window presets.
  • Decline analysis — tabbed √t / log-log / G-function with closure pick + η + regime classifier (normal · PDL · height-recession · post-shut-in growth).
  • Step-down auto-detect — finds ≥3 descending plateaus and chips remediation (healthy-entry · add-shots · ball-out · drop-prop slug).
  • Net-pressure history-match — 5-knob panel (Γ₂ tip, complexity vol/open/leak, prop drag, TSO backfill) overlays modeled vs observed Pnet. 3 deck-preset buttons.
  • ISIP auto-pick — sustained pre-pump + ≥3-of-next-5 zero-rate gate; median BHP over hammer+window with confidence chip. One-click 'Apply to Nolte-Smith'.
  • Live auto-history-match — re-fits the 6 net-pressure knobs every 2-30 s from the rolling buffer (coordinate descent on rmsResidualPsi, clamped to slider envelope).
  • DAS/DTS waterfall — depth × time heatmap mounted between Live Pumping and Wellbore Displacement.

8.2 Field measurements (WFT/DST/DFIT)#

Builder header → Field data → 4-step paste-CSV wizard. Vendor-neutral wireline / drillstem / mini-frac import; per-workspace storage. The Pressure Advisor warnings panel cross-checks modeled hydrostatic vs measured P (and modeled MW vs measured ρ) with engineer-entered uncertainty bands and ok/watch/amber severity.

8.3 RTA (/rta)#

Blasingame log-log + Agarwal-Gardner semi-log charts with persisted cadence overlay. Named cadence presets, late-window BDF slope diagnosis, and PI/HCPV/R² fit. Arps DCA card bins loaded (t,q) samples to monthly buckets and shows model + R² + EUR(50 yr). Probabilistic EUR runs Fast (≤200) / High (≥2000) Monte Carlo with live progress bar + cancel; σ-qi/Di/b/dMin + samples + seed are persisted.

10. Sensitivity, optimization, parent-child & economics

Diagnostic Studies tornado, OFAT sweep, Optimum Finder (NM/PSO + Pareto), parent-child interference, and DCA + economics.

9.1 Sensitivity & optimization#

  • Diagnostic Studies (/diagnostic) — Pnet + screen-out tornado with troubleshooting presets and 'Pull from live stream' cross-link.
  • OFAT sensitivity sweep (/sensitivity-sweep) — one-factor-at-a-time response curves; CSV export.
  • Optimum Finder — Nelder-Mead + Particle-Swarm with per-algorithm penalty overrides, infeasibility-avoidance presets (off · fast-explore · soft · balanced · strict · aggressive · custom), and a compatibility validator that blocks the Find button on misconfigurations.
  • Sweep frontier — weighted-sum / ε-constraint Pareto sweep across saved optima.
  • Sensitivity Results visuals — Find Optimum (max/min), clickable factor cross-plots, breakeven overlay, one-click PDF, cross-workspace tornado overlay.

9.2 Parent-child interference (/parent-child)#

  • Analytical frac-hit screening: log-radial Δp + Eaton Δσ_h + asymmetry + bashing-risk chip. Plan-view SVG, per-stage table, summary chips, CSV export.
  • Microseismic catalog ingest — alias headers, P-percentile drainage-radius fit per parent, faint purple events overlay.
  • Regional presets — Permian-Wolfcamp / Bakken-Middle / Eagle Ford / Marcellus-Dry one-click layouts.
  • Production timeline — per-parent (start, Δp_∞, τ) + child pump date drives Δp = Δp_∞·(1 − exp(−Δt/τ)).
  • Multi-well stress shadow — Sneddon Δσ on aligned stage midpoints + plan-view ✕ markers.
  • Poroelastic full tensor — Geertsma 2-D Δσ_h/Δσ_H + SHmax rotation with severity chip and rotated SHmax ticks.
  • 3-D Mindlin layered extension — multi-bench depth attenuation; collapses byte-identically to 2-D when no layers.
  • Volumetric frac-hit estimate — per-stage proppant + fluid mass arriving at parents (swept-ellipse capture × depletion attraction, Σ ≤ 1).
  • Child fracture geometry coupling — bend angle β, tip deflection L·sin(β), bend direction; sensitivity sweeps + Monte Carlo P10/P50/P90.
  • Probe-point validator — click-to-add ✕ pins; table shows σ_h_min @ probe + L_a/L_b/asym%.
  • Time-varying thermal patches — pump-up/shut-in cooling schedule (start/stop, ΔT, diffusivity, recovery τ) feeds the σh evaluator.
  • Runtime SHmax→geometry t-loop — Pump time slider on the far-field card walks the time-resolved σh into child-fracture geometry.

9.3 Field validation campaigns#

Workspace-scoped module at /field-validation. Upload measured (t,P,T) gauges or (MD,P,T) gradient surveys; attach DFIT residuals + Pressure Advisor cross-checks; verdict = AND of attached comparisons. Inline FractureValidationPanel runs PKN/KGD/Radial net-pressure + optional Carter/B-C falloff vs measured BHP and highlights the lowest-RMSE kind.

9.4 DCA + Economics (/economics)#

Three tabs: Arps DCA fit (4 regional type curves) · cascade · NPV/IRR + tornado. EUR uplift publishes to /refrac. Cross-links to /rta for Probabilistic EUR (P10/P50/P90).

9.5 Auto-HM → Forecast pipeline (/auto-forecast)#

One-click orchestration of monthly production history → fitArpsToHistory → monteCarloEur → AI narrative. Sidebar: Predict → 'Auto-HM → Forecast'. Inputs: production history (one volume per line), horizon years, MC sample count, seed, σ on qi/Di/b/dMin. Outputs: fitted Arps kind/qi/Di/b/MAE/R² + P10/P50/P90/mean/std EUR chips + 4-6 bullet narrative card. See §9.4 (Arps DCA) and §8.3 (Probabilistic EUR) for the underlying math — this page is the workflow that wires them together.

  • Run controls — the Run button prefetches the heavy arpsDca module on hover/focus, shows a spinner and disables itself while prefetch or compute is in flight, and surfaces a Cancel button alongside.
  • Cancel safety — Cancel opens a confirmation dialog so an in-progress run is not discarded by accident. Esc keeps it running; Enter confirms the cancel. A stale-run token guards against late results from a cancelled compute leaking into the UI.

11. Reservoir, wellbore, fluids & advanced physics

RESQML/GRDECL export, transient wellbore (single-phase + drift-flux), breaker schedule, FracPro slurry library, perf-cluster designer, layer tracers, adsorption.

10.1 Reservoir export#

Builder Export → GRDECL (Eclipse) and RESQML v2.0.1 (.epc). RESQML emits CRS + IjkGrid + 3 baseline ContinuousProperty parts (pressure psi, porosity, permeability mD) + optional extras (temperature, saturation, NTG, …). Deterministic UUIDs from a seed give byte-stable output. A built-in validator runs the structural checks Petrel/RESinsight enforce.

10.2 Transient wellbore (Builder preview)#

1-D segmented pipe with implicit-Euler segregated solver (mass + momentum + energy; Swamee-Jain Darcy-Weisbach friction). Opt-in two-way wellbore-storage feedback under-relaxes the bottom-face rate (α=0.5) into the kernel. The Builder Wellbore preview also runs an α stability frontier across [0.1, 0.3, 0.5, 0.7, 1.0] and recommends the smoothest α whose total iterations stay within 25 % of the cheapest.

10.3 Drift-flux multiphase wellbore#

Pure Zuber-Findlay closures wired in via opt-in `multiphase` input. Gas-EOS-coupled mixture compressibility (ρ·c_t)_m now ships with baked-in Standing-Katz Z(p,T) (Dranchuk-Abou-Kassem 1975 + Sutton 1985 pseudo-criticals + Wichert-Aziz 1972 sour-gas correction) — opt in via `multiphase.gasEos.useStandingKatz: true` with optional gas gravity / H₂S / CO₂ mole fractions. Collapses to ideal-gas in the low-p limit. Deferred: full flow-pattern map regime classifier and OLGA-class transient multiphase (out of scope).

10.4 Fluids — breaker schedule + FracPro slurry library#

Builder Fluid model panel ships a Breaker Schedule card (5-entry catalog APS/SPS/Encap/Enzyme/HT-Ox; Arrhenius T½ doubles per 18 °F; first-order μ(t) decay; gel-damage chip). The FracPro-style slurry library (52 role-tagged entries spanning preflush/pad/slurry/postflush — incl. delayed-borate XL, mud acid 12-3, gelled & emulsified acids, cationic HVFR for produced water, HEC frac-pack, methanol-water blend, VES, hybrid slickwater, oil-based, and foam energised systems) feeds a stage-role chip filter; ρ_eff (slurry + proppant @ Cppa) cascades into Pressure Advisor mud weight → hydrostatic / ECD / surface budget / breakdown. The authoritative count comes from `STANDARD_SLURRY_LIBRARY.length` in `src/lib/hfaSlurryLibrary.ts` — if that number ever drifts from what this chapter says, the library is the source of truth and this sentence is stale.

10.4b Fluid name resolution#

resolveSlurry(name) = STANDARD_SLURRY_LIBRARY.find(s => s.name == name) ?? error_chip(name)
How the simulator turns a fluid-name string from a schedule (Builder, CSV/JSON import, FracPro-style report) into a concrete rheology row. Unknown names raise an error chip — never a silent fallback to water.
Used in
Builder → SlurryLibraryPicker (stage-role chip filter)
Builder → Fluid model → FluidMixturePanel (per-stage fluid rows)
FracPro-style report (PDF + CSV) — Table 4 (Fluids) lookup
Scenario JSON IO — fluid-name validation on import
Module
src/lib/hfaSlurryLibrary.ts → STANDARD_SLURRY_LIBRARY · src/lib/fourStageFluidLink.ts
Where
  • name — fluid name as entered in the schedule (case-sensitive)
  • STANDARD_SLURRY_LIBRARY — 32-entry read-only catalog (src/lib/hfaSlurryLibrary.ts)
  • error_chip — surfaced inline on the Treatment / Fluid mixture panel and blocks Validate until resolved
Assumptions
  • Fluid catalog is the single source of truth — CSV/JSON ingest does NOT auto-create new entries
  • Unknown names are an authoring error, not a defaulting opportunity
  • Names are matched verbatim (no fuzzy-match) so library churn is visible at validate time
Validity range
Any panel/import that consumes a fluid name; applies to all 4 stage roles (preflush · pad · slurry · postflush).

10.5 Perf-cluster designer#

Head-bisection split with stress bias per cluster; recommends perf count to achieve limited-entry (default min Δp_perf ≥ 500 psi).

10.6 Layer tracers + LAS → static model + adsorption#

  • Layer Tracers wizard — per-layer initialization table + 'produced fraction by layer' Results card.
  • LAS → Static model — equal-thickness binning to layer means; em-dash for null bins.
  • Langmuir adsorption — V_L·p/(P_L+p); per-layer error+warning chain; per-workspace flag.

10.7 Pad scheduler + ML surrogate + joint history-match#

  • Pad scheduler — resource-constrained multi-well Gantt packer (crew/pump/sand pools, per-well earliest start, zipper-stagger helper).
  • ML surrogate — quadratic response-surface (ridge normal eqs) for sub-second sensitivity OFAT.
  • Joint history-match auto-tuner — Nelder-Mead coordinate descent or PSO swarm over the 2N (shift, scale) vector; safety-guarded so RMSE never increases.

12. Reports & exports

Calibration report, FracPro-style report, scenario JSON IO, input bookmarks.

  • Calibration report (PDF + CSV) — Inputs · Assumptions · fitted T₀/K_IC · wellbore hydrostatic snapshot.
  • FracPro-style report (PDF + CSV) — 17-section Hydraulic Fracture Analysis output (Cover + Tables 1-22).
  • Scenario JSON IO — versioned, Zod-validated, per-kind round-trippable wizard scenarios; v1 files auto-upgrade.
  • Input bookmarks — generic schema-less Save/Load on Planar3D Comparator and Optimum Finder panels.
  • Wellbore CSV import + re-export — auto delimiter detection, alias headers, em-dash → NaN, streaming blob round-trip.

13. Workspace toggles & UX

Reservoir type chip, table density, units & precision, keyboard shortcuts.

  • Reservoir type chip — per-workspace Unconventional|Geothermal toggle gates Heat-extraction Results, EGS buttons (Cold injection, Seismicity advisor), and the Pressure Advisor cooling-credit overlay.
  • Table density — Default / Dense toggle in the header; preference is remembered across sessions and auto-applies on simulation + diagnostics views.
  • Tools menu (⌘K / Ctrl-K) — Units, Precision, Per-quantity precision mapping, Export current view, KaTeX status, Check for updates, Reset cache. Each item has a tooltip explaining what it does.
  • Units everywhere — every field label carries units in brackets (e.g. `Wellhead x-position [ft]`). Missing numerics render as — (em-dash) in both UI and CSV/LAS exports, never 0.

14. Units & sanity checks

Canonical unit for every quantity, plus the hard/soft bounds the app uses to flag unit-confusion mistakes (m vs ft, °C vs °F, MPa vs psi).

Every field label in the app carries its unit in brackets (e.g. `Wellhead x-position [ft]`). Internally, calculations run in the canonical units below; on-screen values are converted to your chosen display system.

Units glossary#

QuantityCanonicalAlso acceptedConvert
Length / depthftm1 m = 3.28084 ft
PressurepsiPa, kPa, MPa, bar1 MPa = 145.0377 psi
StresspsiPa, MPaSame as pressure
Temperature°F°C, K°F = °C·9/5 + 32
Mud weightppgkg/m³, sg1 ppg = 119.826 kg/m³
Pump ratebpmm³/min, m³/s1 bpm = 0.15899 m³/min
Proppant conc.ppgakg/m³1 ppga ≈ 119.826 kg/m³ of clean fluid
PermeabilitymD1 mD ≈ 9.869e-16 m²
ViscositycPPa·s1 cP = 1e-3 Pa·s
Timemins, hr, dayPumping = min; production = day

Input sanity checks#

When you type a value into a field, the app runs a two-tier check. Hard bounds reject the value (clearly non-physical, e.g. negative depth). Soft bounds accept it but warn — they are the lever we use to catch unit-confusion (e.g. typing 50 in a depth-ft field probably means 50 m).

FieldUnitHard minSoft minSoft maxHard max
Depth (TVD or MD)ft020025 00040 000
Temperature (BHST)°F3280350600
Pressure (BHP / surface)psi010020 00035 000
Where the bounds come from
Bands are sourced from src/lib/inputSanity.ts (DEPTH_BAND_FT, TEMPERATURE_BAND_F, PRESSURE_BAND_PSI). Use checkDepthFt / checkTemperatureF / checkPressurePsi from that module to wire the same severity into custom panels.
Common unit-confusion traps
Depth 50 ft → likely a metres entry (50 m ≈ 164 ft). Temperature 25 °F → likely °C (25 °C = 77 °F). Pressure 30 psi at downhole → likely MPa (30 MPa ≈ 4350 psi). Mud weight 1.2 ppg → likely sg (1.2 sg = 10.0 ppg).

15. Recently shipped (post-1.0)

Modules and physics added since the 1.0 manual: non-planar 3D solver, advanced rheology, refrac & live-ops upgrades, scenario branching, copilot palette, and more.

15.1 Non-planar 3D fracture solver (/non-planar-3d)#

Curving-surface DDM3D kernel with tip-kinking + natural-fracture branching, out-of-plane tilt, and T-junction reconvergence weld. Builder Fracture-options panel ends with a Non-Planar 3D solver section (enable · element size [ft] · max kink [°] · branch threshold [°] · max curvature [°/ft] · stress-driven curvature switch · Reset). Per-simulation Results tab mounts a step-scoreboard (rank by Kink / Growth / Opening, bar-norm By-metric / Shared-kink) with winner highlighting.

15.2 Microseismic-calibrated conductivity validation#

Card on /non-planar-3d. CSV-in for modeled k·w cloud and MS discs (moment-tensor-inverted shape from /parent-child stress inversion). Computes coverage fraction (per-disc nearest-sample k·w ≥ threshold) and contrast ratio (mean k·w inside vs outside MS discs); verdict passes when coverage ≥ 0.6 AND contrast ≥ 2.0. Exports a validation CSV.

15.3 Carreau-Yasuda + multi-mode rheology + shear-history breakdown#

  • Carreau-Yasuda transition knob `aTransition` (default 2 ≡ legacy Carreau byte-identical; 0.5–1.0 sharpens the knee for HVFR / x-linked gels).
  • Generalised Maxwell modes — adds `μ_k/(1+(λ_k γ̇)²)` to matrix viscosity; surfaces Oldroyd-B first normal stress N1 and Weissenberg number Wi (chip warns when Wi > 1).
  • Shear-history crosslinker breakdown — integrates D(t) = 1 − exp(−∫(γ̇/γ̇_crit)^m dt) along the pump schedule with optional first-order recovery τ. 4-entry catalog: borate-guar (reversible), zirconate-CMHPG (irreversible), HPG-CMHPG (slow recovery), slickwater HVFR (irreversible).
  • BreakerScheduleCard 'Apply shear-history damage' switch shortens T½ proportional to (1 − D), floored at 0.1× to prevent zero half-lives. FluidMixturePanel RheologyCrosslinkerChip shows a `· D X%` suffix when damage > 5%.

15.4 Refrac diversion designer (/refrac)#

Bottom of /refrac — particulate-bridge diverter (PBD) catalog with 6 grades + chemical staging. Boltzmann intake split, log-normal PSD plug-probability, multi-cycle survival, optional chemical Δp_div boost. CSV export via buildRefracDiversionCsv.

15.5 DAS → pump closed loop + DAS → cluster-geometry inversion#

  • DAS-pump closed loop panel on /live-pumping (under DAS intake panels) — advisory hold / rate-cut / advance-stage from per-cluster DAS efficiency. Bounded by `maxRateStepBpm`, hysteresis via `stableSamples`, 200-entry audit log, optional Auto-apply switch.
  • DAS → cluster geometry inversion — inverts DAS intake fractions to per-cluster efficiencies ε_i (geo-mean = 1), feeds back into the cluster flow trace and produces PKN half-length scaling L_i / L̄ = (V_i/V̄)^(2/3)·ε^(1/3).

15.6 Scenario branching tree (/branches) + cell-level blame#

  • Git-style fork tree at /projects/$p/workspaces/$w/branches — SVG forest with lane×depth layout, cycle-break, orphan detection. Fork / diff / Builder actions reuse copySimulation and the builder-compare route.
  • SimDiffDialog gains a Blame column — per-leaf author + relative time, per-author filter, 'Snapshot left | right' buttons, and a tracked-versions chip. History persisted via scenarioVersionsStore (≤200 per simId).

15.7 LLM copilot palette (⌘K)#

Natural-language → command routing on top of the ⌘K command palette. ✨ Sparkles button runs the copilot on-demand and renders 'Copilot picks' above the lexical 'Best matches' with reason + score. Powered by Lovable AI Gateway (google/gemini-2.5-flash, JSON-only system prompt).

15.8 Live-ops additions#

  • Proppant dune overlay panel — Stokes v_s + Richardson-Zaki + Boycott-tilt enhancement; bank fraction N_s = v_eff·L/(u·h); good / ok / risk severity chip + 5 stats from the latest sample.
  • Live field snapshot & share — one-tap card on /live-field producing a URL-safe encoded snapshot link and a PDF cover with advisory banner, window rows, reasons, and note. Read-only viewer at /live-field/snapshot (noindex).

15.9 Probabilistic fracture bundle (/probabilistic-geometry)#

Additive UQ extension: P10/P50/P90 bands for fracture conductivity Cf = k·w and surface treating pressure (closure + Pnet + Δp_pipe + Δp_perf − hydrostatic) + per-factor Spearman tornadoes. Power-law PKN width via optional widthModel/n′/K′ (omitted ≡ Newtonian ≡ legacy byte-identical).

15.10 Completion Quality Index (/completion-quality)#

Per-stage 0–100 score + A-F grade rollup of perf-cluster design, parent-child asymmetry, Mohr slip-tendency, and Nolte-Smith mode. Default weights 0.35 / 0.25 / 0.20 / 0.20 (renormalised on missing inputs). Grade-tinted badges + driver chips + CSV export.

15.11 Coiled tubing / snubbing + geosteering optimizer#

  • /coiled-tubing — Lubinski sinusoidal + Dawson-Paslay helical buckling thresholds, regime classifier (none / sinusoidal / helical / lockup), first-lockup MD. Snubbing crossover from F_po = A_p·(p_wh − p_pipe) − buoyed weight − stripper drag.
  • /geosteering — composite objective 0.5·quality + 0.3·SHmax-alignment + 0.2·containment − DLS-penalty; minimum-curvature buildup feasibility flag; ranked-results table.

15.12 Multi-well artificial-lift design (/artificial-lift)#

Closes the Prosper/Pipesim parity gap. Composite IPR (linear PI + Vogel), avg-density VLP with GLR uplift + slippage friction, gas-lift fixed-point solver, ESP / rod-pump / plunger screens, and a greedy water-fill allocation across a shared compressor with per-well caps.

15.13 Moment-tensor inversion → DFN#

From the microseismic catalog ingest. Aki-Richards 4.30 spherical→Cartesian, Vavryčuk ISO/DC/CLVD decomposition via 3×3 Jacobi, nodal planes from T/P-axes, Brune source radius r = (7M₀/16Δσ)^(1/3), Mardia clustering on fault normals → DfnFracture-shaped discs (azimuth = strike + 90°). Feeds /non-planar-3d's MS-conductivity validation.

15.14 Phase 9 — thermo-mechanical-hydraulic kernel#

Segregated implicit T → P → σ_h grid (thermoPoroGrid3D) with β-pressure source and Geertsma Δσ_h. Optional Cartesian off-diagonal shear tensor Δσ_xy/Δσ_xz/Δσ_yz via shearTensor.enabled (off by default ≡ byte-identical to legacy diagonal-only). PI-controlled coupled-transient substepper (runCoupledTransientStimulation) wraps stepThermoPoro3D with adaptive dt control and time-varying source/BC callbacks; substep records flag rejections + clamped-at-min steps.

15.15 Surrogate-trained pad-design auto-tuner#

Chains the ML surrogate predictor with the pad scheduler — tunePadDesign sweeps a per-stage Cartesian grid over surrogate ranges (≤4096 default, axis-by-axis fallback above cap), maps best y → durationMin and best x → pool demand, then hands tuned PadStages to schedulePad.

15.16 Black-oil numerics — Sprint A (Pc + TVD) & Sprint B (fully-implicit)#

  • Sprint A — opt-in BlackOilNumericsOptions: capillaryPressure?.{pcOilWaterPsi(sw), pcGasOilPsi(sg)} is subtracted/added on water/gas flux Δp; saturationScheme?: 'upwind' | 'tvd-van-leer' reconstructs face Sw via van-Leer ψ(r)=2r/(1+r) with ΣS=1 renorm. Both default OFF ⇒ legacy IMPES byte-identical (≥9 decimals).
  • Sprint B — coupling: 'impes' | 'fully-implicit' + fullyImplicit?.{maxNewtonIter=10, tolPressurePsi=0.1, tolSaturation=1e-4, relaxation?}. Re-enters stepBlackOil3P Picard-style until tols met; routes PVT / rel-perm / upwind / BHP reads through the latest iterate. Surfaces newtonIterations / newtonConverged / residuals.
  • Side-by-side surfaces: Diagnostics tab NumericsComparatorCard + /numerics-validation SI-vs-FI harness.

15.17 Reservoir kernel extensions (v6 batch)#

  • Black-oil tracers with PVT partitioning — voxel-grid passive scalars riding on the 3-phase IMPES kernel. Per cell/species: φ_α = (K_α·S_α)/Σ → c_α = φ_α·m/V_α → upstream flux. Wells inject at tracerInjection / produce at cell-average c. Independent multi-tracer (water / gas / inhibitor / energized-CO₂); optional first-order decay.
  • 1D-submesh water banking — per-fracture-face log-spaced radial submesh resolves Sw(r,t) during leakoff + flowback with internal CFL substepping and optional imbibition pull-back. Mass balance < 2% on no-clamp scenarios.
  • Black-oil fluid regions (PVTNUM-style) — per-region (Bo, Rs, μ_o, Bg, Bw, μ_w) tables routed per-cell via FluidRegionAssignment; applyFluidRegionOverrides masks AABB compartments.
  • Zero-permeability cubes — applyZeroPermCubes masks AABB cubes of permMd to 0; harmonic-mean TPFA faces collapse, never mutates input.
  • Per-well drilling-time schedule — WellActivation 4-phase classifier (idle / drilling / production / shut-in) with linear ramp ⇒ Newton-safe turn-on, dt substepper splits on well events.
  • Compositional 3-phase BO wiring — new 'compositional-3p' FluidKind in FluidModelPanel (Sw / Sg / Swc + PR-EOS energized-CO₂ gas-FVF bridge); default kind unchanged.
  • RESQML EPC export + schema validator + golden fixture — alongside GRDECL; opt-in extra ContinuousProperty parts (temperature / saturation / NTG / …); validateResqmlEpc catches every structural check Petrel / RESinsight enforce.

15.18 Live perforation erosion + auto-HM thermal effect#

  • Live perforation erosion panel — §8.12 asymmetric Du / Ds / Dd / Cd with spatially-correlated α field (mulberry32 + Box-Muller + exp-decay smoothing); user-tunable σ_α / correlation length [ft] / seed persisted in perfErosionUncertaintyStore. Limited-entry chip from min Δp_perf on the eroded geometry vs 500 psi target. Traces NOT persisted — pure-derived from samples × prefs so replay is byte-identical.
  • Live auto-HM thermal effect — opt-in μ(T) drift on the interval fit. Constant thermalScale ≠ 1 slides the fit-window location along μ^(1/4) without changing the loss-surface shape; thermalOutOfBand is advisory-only. Both coord-descent and Bayesian backends route through forwardNetPressure (never inline μ(T) per-backend). Off-collapse drift-guarded.

15.19 Petrophysics & completions additions#

  • Mineralogy log interpretation — GR → IGR → V_sh via Larionov-tertiary / Larionov-older / Steiber / Clavier / linear; density-neutron crossplot RMS porosity; 3-mineral Cramer-solve inversion (quartz / carbonate / clay) on [1; ρ_b; PEF] with component clipping + matrix renorm + all-clay fallback. autoGrBaselines picks 5th / 95th percentile when ≥5 GR samples. Drops straight into lasToStaticModel.
  • StageOpt wellbore proppant transport — stage-level algebraic allocator splitting proppant across clusters via Stokes-number turning efficiency η_turn = 1/(1 + St·k_inertia) + per-segment Daneshy survival exp(−v_s·L/(h·v_w)). Mass conservation Σperf + Σbed = pumped ± 1e-6 lb. CoV severity ladder ok ≤ 0.20 / watch ≤ 0.40 / amber ≤ 0.70 / critical.
  • Stress-conductivity coverage + embedment chip — in ProppantLibraryPicker, ISO-13503-5 knot badge + ok / watch / extrapolating chip keyed to closure stress + rock E. 'Apply to k·w scale' writes the embedment factor (Cooke / Lacy (E_rock/E_ref)^0.5, clamped (0.05, 1]) into override.kwScale.

15.20 Builder Wells & Fracture-options additions#

  • Bedding-plane fracture card (Fracture-options panel) — two-criterion Mohr-Coulomb classifier (vertical when p > σh; horizontal when p > σv − (τ_max − c)/μ_b; mixed within mixedBandPsi). Height-growth efficiency penalty H(n) = clamp(0.1 + 0.9·exp(−0.5·n), 0.1, 1). 4-play preset catalog (Vaca Muerta / Utica / Montney / deep Bakken).
  • Mud-window card (Wells panel header) — Drillworks / Baker-GMI / Techlog-MEM parity. 4-limit window: pore-pressure floor (kick), Kirsch + Mohr-Coulomb shear-failure floor (breakout, closed-form q = (1 + sinφ)/(1 − sinφ)), σ_v loss ceiling, tensile breakdown ceiling p_w = 3σ_h − σ_H − α·p_p + T₀. Severity ok ≥ 1 / watch ≥ 0.3 / amber ≥ 0 / critical < 0 ppg + per-stage rollup from perfs[].mdFt.

15.21 v5 physics batch (8 modules)#

  • Horizontal / bedding-plane fracture — see 15.20.
  • Rate-and-state friction — Dieterich-Ruina (lab-granite defaults); criticalStiffness / nucleationLength helpers; classifyRsfStability strengthening / conditionally-stable / unstable; spring-slider simulateRateStateSlider with optional injection pore-pressure ramp.
  • Gas non-Darcy inflow + advisory on gasLift — Wattenbarger D = 2.222e-15·γ·k/(μ·rw·hp²); Δψ = A·q + B·q² solver; classifyNonDarcyLoss ok / watch / amber / critical (5/15/30%); gasNonDarcyAdvisory composes Hawkins + perforation skin via gasInflowRateWithSkin.
  • Stress-dependent permeability with hysteresis — Terzaghi effective stress; exponential or power-law loading; unloading anchors at peakStress with shallower γ_unload; residualFraction cap; classifyStressPermLoss ok / watch / amber / critical (10 / 30 / 60%).
  • Relative permeability + capillary pressure — Corey / LET 2005 / Stone-II 3-phase oil; Brooks-Corey drainage P_c = P_e·S_we^(−1/λ) capped at maxPc; Skjaeveland mixed-wet sign-changing curve.
  • Mineral scaling kinetics — MINERAL_DB (calcite / barite / FeS / SiO₂) with log10 Ksp 25 °C, Arrhenius (k_ref, Ea), TST σ/n, IAP stoichiometry. Davies-extended activity coefficient (I ≲ 0.5); saturationIndex SI = log10(IAP / Ksp); tstRate r = −k·A·sgn(1 − Ω^σ)·|1 − Ω^σ|^n; classifyScaleRisk ok / watch / amber / critical (French Creek 0.3 / 1.0 bands).
  • Wellbore-stability mud-window — see 15.20.
  • Formation damage & skin + IPR ↔ skin integration — Hawkins damage skin; Karakas-Tariq 1991 perforation skin (5 phasings from Economides Table 6-1); productivity ratio PR = ln(r_e/r_w) / (ln(r_e/r_w) + s); composeSkin sum + severity ok ≤ 0 / watch ≤ 5 / amber ≤ 20 / critical. Optional skin? block on WellLiftInputs auto-scales linear-PI + Vogel rate via PR; gasInflowRateWithSkin composes into the A·q + B·q² solver.

15.22 3D viewer (/viewer-3d & /viewer-3d/scientific)#

  • Renders wellbore + stages + wings + offset wells from any simulation; severity-tinted by per-stage Completion Quality Index.
  • View presets 1–4 (overhead / heel / cross-section / iso); R resets the camera; drag to orbit.
  • Layer toggles (wellbore / stages / wings / offsets) and per-severity visibility chips; settings persisted via viewer3DPrefsStore.
  • Growth scrubber — Space toggles play / pause (resets fraction at end); [ / ] step ±5%; readout shows visible/total stages + percent.
  • Scene stats HUD + 'Copy stats' button (clipboard-friendly multiline summary with sim ID, wellbore length, stage / wing / offset counts, severity breakdown).
  • Share-view URL preserves camera + toggles via hash params; Fullscreen toggle on the canvas wrapper.
  • Exports: PNG snapshot, glTF, OBJ; AI 'Explain this scene' summary via Lovable AI Gateway.

15.23 v6 Tier-2 Track B — laminated-shale + CO₂-storage assurance#

  • Phase-field / DEM laminated shale (/phase-field-dem & /phase-field-shale) — AT-1/AT-2 damage with irreversible history field, cohesive Mode-I/II traction-separation, He-Hutchinson 1989 kink-vs-pierce classifier (bedding-plane NFs), MTS kink-angle, and σh-degradation hook into the Geertsma engine. PhaseFieldFeedbackCard on /parent-child wires applyPhaseFieldFeedback (per-stage damage amplitude → σh derate) into runShmaxGeometryTimeLoop with monotone-stable σh slices; a parameter-sweep harness (runPhaseFieldFeedbackSweep) reports per-stage + worst stability rollups and exports two CSVs.
  • Anisotropic-elasticity (TIV) — Thomsen 1986 ε/γ/δ → C_ij → engineering moduli {E_h, E_v, ν_h, ν_v, G_v, G_h} + directional E(θ). Wired into ddm3D + non-planar pipeline + DFN config + LaminatedShaleResultsCard.
  • Proppant DEM at tip (Hertz-Mindlin bridging) — pure F_n = 4/3·E*·√R*·δ^1.5 + Coulomb-capped Mindlin tangent + N_b = w/d bridging factor + σ_rock = η·I·p_net tip-stress transfer. Wired into nonPlanar3D/pipeline.ts (B3b shipped); StepScoreboard renders a Tip-bridging column with amber tint when bridging active.
  • CO₂ storage assurance (/co2-storage) — Nordbotten-Celia √t plume radius, Theis log-time over-pressure, caprock capillary seal classifier (ok / watch / amber / critical), Coulomb-failure margin, solubility / mineral / residual trapping ramps, and Darcy line-source leakage flux.

15.24 OLGA-class transient multiphase wellbore (Phase B + Phase 8)#

  • Taitel-Dukler + Barnea flow-regime map — 7 regimes per segment (horizontal TD / vertical Barnea incl. churn) with marginLog for near-boundary chips.
  • Enthalpy-wave solver — 1-D implicit advection-diffusion on (ρh): backward-Euler tridiag with upwind convection, Joule-Thomson, latent-heat-of-vaporisation, wall U-value coupling.
  • Drift-flux multiphase wellbore — pure Zuber-Findlay closures wired into transientWellbore via opt-in WellboreStepInput.multiphase; gas-EOS-coupled (ρ·c_t)_m mixture storage; Standing-Katz Z(p,T) via DAK 1975 reduced-density Newton + Sutton 1985 pseudo-criticals + Wichert-Aziz 1972 sour-gas correction (opt-in standingKatzOptions).
  • Two-way wellbore-storage feedback (Phase 8 inc 3) + α stability frontier sweep (inc 4) on the Builder Wellbore preview — 3rd collapsible card runs the synthetic ramp across DEFAULT_ALPHA_GRID, picks the smoothest α whose totalIters ≤ 1.25× the cheapest, and exposes an 'Apply recommended α' button that writes back into transientWellboreCouplingStore.
  • Transient multiphase run history (Phase B inc 22–25) on /transient-multiphase-wellbore — localStorage ring buffer (cap 8) of completed runs with compare-vs-current table, A/B diff modal (changed-inputs + 7-metric ↑better/↓worse), CSV import/export (buildRunHistoryCsv + mergeRunHistory), and 6-tile sparkline trend strip (oldest → newest, Δ chip colored by improvement direction).

15.25 Phase-field σh-degradation in the runtime time loop (Track B inc B4)#

Optional per-stage phase-field damage feeds back into runShmaxGeometryTimeLoop via applyPhaseFieldFeedback + nearest-stage σh degradation in the runtime evaluator: clamped [0,1], padded / truncated, monotonic-stable across slices. Companion parameter-sweep harness (runPhaseFieldFeedbackSweep) walks a damage-amplitude grid and produces per-stage + worst stability rollups (monotone σh, max Δσh jump, bend growth, finite) plus two CSV builders.

15.26 Induced-seismicity forecaster + TLP suite (Phase F)#

  • Pore-pressure → seismicity rate (Dieterich 1994) — backward-Euler γ + Δτ coseismic jump + TLP traffic-light classifier (green / yellow / amber / red).
  • /induced-seismicity route — USGS catalog auto-refresh (7 cadences, decideAutoRefresh honours in-flight + document-hidden), TLP threshold preset catalog (default / OK_CC / KS_CC / TX_RRC / custom) with monotonic-ladder sanitiser, and an operator-action audit log (append-only cap-500 FIFO, CSV export). Auto-logs TLP transitions; manual rate-cut / shut-in / monitoring / regulator-report / note actions.

15.27 MRV — Subpart RR + field-validation cross-check (Phase D)#

  • MRV Subpart RR report (/ccus-mrv) — 4 §-keyed sections + attestation + hash-chain proof + period-filtered ledger tail; async exportMrvSubpartRrPdf (lazy jspdf, letter, paginated) wired into the summary card with operator / facility / facility-id inputs.
  • MRV ↔ field-validation cross-check card — Δp residual stats + severity ladder + ok → operator-note / watch+ → alert event builder + CSV parser. Closes Phase D.

15.28 Runtime SHmax → geometry time loop (M2) + time-varying thermal patches#

  • runShmaxGeometryTimeLoop — LIVE on /parent-child via 'Pump time t [yr]' slider backed by m2TimeSliderStore. Drift-guard probePointVsThermoPoroParity covers 466 cases (extended with t-axis × effectiveDrawdownPsi(timeline, pumpDateIso) per-parent timelines).
  • Time-varying thermal patches (Phase 1d) — per-patch injection schedule (start / stop ISO, peak ΔT, diffusivity ft²/day, recovery τ days, optional max radius). Cold zone evolves through pump-up (r = √(D·t_inj), ΔT = peak) and shut-in (r keeps spreading, ΔT = peak·exp(−t_post/τ)). Merged with static patches per slice and fed into BOTH analyzePoroelastic calls (main + runtime σh evaluator). Depletion-only collapses byte-identically.
  • Per-workspace UI prefs (°F / °C + ft²/day / m²/day) via thermalPatchUnitsStore; storage stays canonical.

15.29 Trust gates — analytical-gate trio + grid-convergence#

  • Analytical-gate trio — McWhorter-Sunada 1-D capillary imbibition + Morel-Seytoux 2-D five-spot areal sweep + Theis radial pressure transient. Three pure libs + 26 drift-guards; closes the gaps beyond Buckley-Leverett.
  • Grid-convergence suite (/grid-convergence) — runs the kernel at nx0 / 2·nx0 / 4·nx0 × upwind / TVD, reports observed order p, and rolls up FI convergence + worst mass-balance % into the TrustRollupChip on /numerics-validation and the NumericsComparatorCard header (ok < 0.5% / watch < 2% / review otherwise). Broadened with 3 regime scenarios (shock / capillary / compressible) + recommendScheme(run) heuristic.
  • Black-oil trust gates — pure Buckley-Leverett (Corey fw + Welge tangent + profile sampler + L1/L∞ comparator) and mass-balance report (phaseInPlace via kernel pvtAt + per-step absolute / relative residual incl. worstRelative). Kernel parity drift-guard locks IMPES + TVD L∞ ≤ 0.5 vs BL.

15.30 Phase 16 — coupling-direction promoted default-ON#

reservoirCouplingStore default flipped false → true + new mirror blackOil3PCouplingStore (default true, key downhole.dfit.blackOil3PCoupling.v1). SolverPreferencesCard gains a 2nd Switch row for blackOil3PCoupling. /solver-spec scoreboard coupling-direction row promoted next-up → shipped. Explicit setEnabled(false) overrides persist so users who turned coupling off pre-promotion keep that choice (only the 'absent localStorage entry' branch flips).

15.31 Design Copilot ↔ fleet priors (Phase E)#

/design-copilot 'Fleet priors' card — basin Input + 'Loosen to fleet P10/P90' Switch + live tightening-preview chips. Calls tightenDesignFactorsFromBasin to clamp design-factor ranges toward measured P10/P90 from the regional fleet, with a sonner toast on Run.

15.32 Voice-First surfaces + readback dock#

  • Global floating readback dock — bottom-right PTT button that routes spoken questions to the most recently active results-bearing surface (RTA, Economics, Optimizer). Uses a pub/sub context store so the active surface always wins; hides when no surface is active or the Web Speech API is unavailable.
  • Voice dictation for numeric fields — inline mic button next to any numeric input. parseDictatedQuantity handles number words, decimals, units (bpm/psi/ppm/ppa/ppg/gpm/bbl/gal/lb/ft/in/m/kpa/mpa/F/C/%), and 'k/M' suffixes. Drop-in component: DictateNumericFieldButton.
  • Results readback intent matcher — classifyResultsQuery scores each metric by matched-pattern character length; answerResultsQuery composes a speakable utterance and pipes it into the TTS engine. Per-surface metric registries for RTA, Economics, and Optimizer.
  • Audio cue mute controls — circular mute/unmute toggle in VoiceReadbackDock plus the 'M' keyboard shortcut; both immediately update the audio cue store and the UI stays in sync via a manual subscription mechanism.

15.33 Copilot v2 — streaming, memory, search, tools#

  • Streaming responses in CopilotDrawer — ReadableStream + getReader(), with an AbortController and a Stop button so users can cancel mid-generation; partial output is preserved with a ⏹ Stopped marker.
  • Per-page / per-simulation chat history — threads are scoped by context key (e.g. ws_<id>/sim_<id>) and automatically restore when you return to the same page or simulation.
  • History search and filtering inside the drawer — query filter, role filter, recency filter, match highlighting via HighlightedText, and hit counts. Powered by copilotThreadSearch.
  • Copilot tool registry — 7 safe app-side tools (jumpToPanel, applyKnob, runOptimum, runSweep, saveBookmark, openSimulation, appendActivityLog) with Zod inputSchemas, needsApproval gates, and caller-injected executors. UI wiring deferred to the Engineer/Driller Copilot toolsets.

15.34 Driller's Copilot (RigSense)#

  • Six-tab driller-facing AI co-pilot at /driller-copilot — Stuck-pipe early warning, Kick/loss + dynamic mud window, MSE founder advisor, Trip swab/surge advisor, Voice Q&A, and Auto morning report.
  • Pure diagnostic engines under src/lib/driller/ — stuckPipeEarlyWarning (differential / mechanical / pack-off proxies), kickLossDetector (flow surplus + pit gain + live mud-window margins), mseFounderAdvisor (Teale MSE regime classifier + WOB/RPM step recommendation), tripSwabSurgeAdvisor (Burkhardt Δp + dynamic effective MW + bisected max-safe pipe velocity).
  • LocalStorage RAG corpus for offset reports — offsetReportsStore + lexical searchOffsetReports; aiDrillerCopilotContext caps the payload at 8 KB. askDrillerCopilot server function calls Lovable AI Gateway (google/gemini-2.5-flash, JSON-only system prompt, 10 s timeout).

15.35 Wellbore sensitivity suite#

  • FracCADE-style depth ladder at /projects/$p/workspaces/$w/wellbore-sensitivity — Quick (5-factor tornado) and Custom (engineer-picked factors with ±1–90% swings) across three domains: Well path, Completion, and Tubing. Persistence via wellboreSensitivityDepthStore.
  • Saved scenarios panel — per-workspace named configurations stored in localStorage; save, load, rename, and delete. Scenarios encode the depth ladder + factor selections + per-factor swings. Export CSV header: Factor,Units,Low value,High value,Low metric,High metric,Swing,|Swing|.
  • Shareable scenario links — any saved scenario can be shared via a base64url-encoded URL payload; the recipient lands on the same workspace surface with the scenario loaded.
  • Dual-scenario comparison at /wellbore-sensitivity/compare — side-by-side picker, diff table highlighting changed values, and an 'unchanged' toggle. Dual-scenario sharing via URL hash (#compareA=...&compareB=...). The last compared pair is restored per workspace from localStorage.

15.36 Global navigation — Help drawer + Command palette#

  • Searchable Help drawer (⌘?) — manual search, recent pages, and quick links. Mirrors the /manual route content without leaving the current page.
  • Command palette (⌘K) — hybrid lexical + semantic command ranking. The ✨ Sparkles button runs the LLM copilot on-demand and renders 'Copilot picks' above the lexical 'Best matches' with reason + score. Built on commandPaletteHybridSearch and commandCopilot.

15.37 Validated wellbore pressure sandbox#

  • Interactive sandbox at /sandbox/wellbore-pressure — live form, hydrostatic / temperature / wellbore pressure breakdown grid, and per-field validation. Runs the same wellborePressureEngine used elsewhere in the app.
  • Industry-validated test suite — 24 SPE/IAPWS reference cases, 39 edge-case tests, and 8 seeded fuzz tests covering hydrostatic, temperature, and wellbore pressure calculations.
  • WellborePressureResult fields documented in docs/wellbore-pressure-result.md; bottomholePressurePsi is aliased as bhpPsi for API alignment. Sandbox state is shareable via base64url-encoded URL.

16. What's new — v1.4 vs v1.3

Release notes for manual v1.4 (June 2026). Lists every feature shipped since v1.3 (May 2026), grouped by track.

Filter release notes
Track / Phase
Feature category (multi-select)

Manual v1.4 (June 2026) consolidates every feature shipped since v1.3 (May 2026). The detailed deep-dives live in §15.32–15.37; this section is the at-a-glance changelog you can scan in 60 seconds.

Highlights#

  • Voice-First surfaces are now documented end-to-end — readback dock, per-field dictation, results readback, and the new mute toggle + 'M' shortcut.
  • Copilot v2 adds streaming responses with a Stop button, per-page chat history, history search/filtering inside the drawer, and a safe tool registry for future AI-driven actions.
  • Driller's Copilot (RigSense) ships six AI-powered drilling advisors at /driller-copilot.
  • Wellbore sensitivity suite closes the FracCADE-style depth-ladder gap with Quick/Custom tiers, saved scenarios, shareable links, and a dual-scenario comparison page.
  • Global navigation upgrades — searchable Help drawer (⌘?) and a hybrid LLM-assisted Command palette (⌘K).
  • Validated wellbore pressure engine sandbox with shareable state and documented output fields.

Shipped features by track#

TrackFeatureWhere to find itDeep-dive
VoiceGlobal readback dock + PTT routing to active results surfaceVoiceReadbackDock in __root§15.32
VoicePer-field numeric dictation + unit-aware parserDictateNumericFieldButton§15.32
VoiceResults readback intent matcher + per-surface registriesvoiceResultsReadback.ts§15.32
VoiceAudio cue mute toggle + 'M' keyboard shortcutVoiceReadbackDock§15.32
CopilotStreaming responses with Stop button in CopilotDrawerCopilotDrawer§15.33
CopilotPer-page / per-simulation chat history persistencecopilot scope store§15.33
CopilotHistory search + filter + highlight inside the drawercopilotThreadSearch§15.33
CopilotSafe tool registry (7 tools with Zod schemas + approval gates)copilotTools.ts§15.33
DrillerRigSense six-tab driller co-pilot (stuck/kick/MSE/trip/voice/morning)/driller-copilot§15.34
Wellbore sensitivityFracCADE-style depth ladder (Quick/Custom) across well path / completion / tubing/wellbore-sensitivity§15.35
Wellbore sensitivitySaved scenarios + shareable scenario linkswellboreSensitivityScenariosStore§15.35
Wellbore sensitivityDual-scenario comparison + shareable compare links/wellbore-sensitivity/compare§15.35
NavigationSearchable Help drawer (⌘?)/help§15.36
NavigationHybrid LLM-assisted Command palette (⌘K)CommandPalette§15.36
Physics + docsValidated wellbore pressure sandbox + documented result fields/sandbox/wellbore-pressure§15.37

Default behavior changes (read carefully)#

Manual version bumped
MANUAL_VERSION 1.3 → 1.4, MANUAL_UPDATED June 2026. The /manual route header and PDF cover reflect this automatically.

Migration notes#

  • No schema migrations required — every new store uses a fresh localStorage key.
  • Voice-First surfaces are opt-in by browser capability (Web Speech API). The dock and inline mic buttons render null when the API is unavailable.
  • Copilot chat history is scoped by page/simulation context; existing chats without a context key remain in the default global thread.
  • Wellbore sensitivity scenarios and comparison pairs are stored per workspace; shared links are ephemeral and do not write to the recipient's saved scenarios.

17. Glossary

Industry terms used verbatim, plus the few names we changed.

TermMeaning
Workspace (a.k.a. Sandbox)Also called a 'Sandbox' in some simulators — a working set of related simulations sharing a base template.
SimulationOne numerical model. Edit, validate, run, and view results at this level.
DS runDesign-of-Sensitivity run — a parameter sweep across many simulations.
DFITDiagnostic Fracture Injection Test — short-injection field test used to fit T₀ and K_IC.
G-functionTime-transform used to identify fracture closure on a DFIT pressure trace.
K_ICMode-I fracture toughness — resistance of the rock to fracture-tip propagation.
C_LCarter leak-off coefficient — fluid loss rate to the matrix per √time.
SH_min / SH_maxMinimum / maximum horizontal in-situ stress.
T₀Tensile strength of the rock.
TVDTrue vertical depth — vertical distance from surface to a downhole point.
BHSTBottom-hole static temperature.
BHPBottom-hole pressure.
MDMeasured depth — distance along the wellbore from surface.
ppgPounds per gallon — common mud-weight unit.

18. v8 engineering physics — derivations

Closed-form references and call-site pointers for the six engineering gaps shipped in the v8 physics round (verification, shale dual-continuum, slurry & screen-out, wellbore detail, boundary conditions).

Each derivation below maps an equation in the kernel to its textbook source so an engineer can audit the call site, the assumptions, and the validity band in one pass. The /trust/analytical-verification dashboard scores cases 1-3 against these formulas every build, and the /physics-gaps-v8 dashboard surfaces the live verification-mode chip (history-matched vs. independent).

18.1 KGD half-length (verification case 1)#

x_f = 0.539 · (E' · q³ / (µ · h³))^(1/6) · t^(2/3)
Geertsma-de Klerk plane-strain half-length growth for a constant-rate, viscosity-dominated KGD fracture.
Used in
Trust → /trust/analytical-verification → kgd-baseline card
Physics gaps v8 → KGD parity check
Module
src/lib/verification/analyticalSuite.ts → kgdHalfLength
Where
  • x_f — fracture half-length [ft]
  • E' = E / (1 − ν²) — plane-strain modulus [psi]
  • q — single-wing injection rate [bbl/min, converted to ft³/s in solver]
  • µ — Newtonian carrier viscosity [cp]
  • h — fracture height [ft]
  • t — pump time from start of injection [s]
Assumptions
  • Plane-strain (height ≫ length)
  • Newtonian fluid, constant rate
  • Viscosity-dominated (toughness negligible)
  • Symmetric two-wing growth
Validity range
Toughness number K < 1; height/length ratio > 3; pump time short enough that fluid loss can be neglected.
Units: field (ft, psi, bbl/min, cp, s)

18.2 PKN width and length (verification case 2)#

x_f = 0.68 · (E' · q³ / (µ · h^4))^(1/5) · t^(4/5) ; w_w = 2.5 · (µ · q · x_f / E')^(1/4)
Perkins-Kern-Nordgren channel growth: confined-height, elliptical cross-section.
Used in
Trust → /trust/analytical-verification → pkn-baseline card
Builder Fluid model → power-law PKN width preview
Module
src/lib/verification/analyticalSuite.ts → pknGeometry
Where
  • w_w — maximum wellbore width [in]
  • Other symbols as in 16.1
Assumptions
  • Height fully contained between barriers
  • Length ≫ height (plane-strain perpendicular to length)
  • Newtonian fluid; non-Newtonian routed through the power-law variant
Validity range
h/x_f < 0.3; constant injection rate; no leak-off (use Carter coupling for leak-off-dominated regimes).
Units: field; widths internally in inches

18.3 Radial-toughness penny-fracture (verification case 3)#

R(t) = (3 · E' · q · t / (8 · √π · K_IC))^(2/5)
Savitski-Detournay radial (penny) fracture in the toughness-dominated regime: rate goes into surface energy of a circular crack.
Used in
Trust → /trust/analytical-verification → radial-toughness card
Module
src/lib/verification/analyticalSuite.ts → radialToughnessRadius
Where
  • R — penny radius [ft]
  • K_IC — Mode-I fracture toughness [psi·√in]
Assumptions
  • Penny-shaped (axisymmetric) fracture
  • Toughness-dominated (viscosity negligible)
  • Homogeneous infinite medium
Validity range
Dimensionless viscosity M < 0.1; early-time radial growth before any boundary feels the tip.
Units: field

18.4 Dual-porosity Warren-Root (Gap 2a)#

ω = (φ·c_t)_f / [(φ·c_t)_f + (φ·c_t)_m] ; λ = α · (k_m / k_f) · r_w²
Warren-Root storativity ratio (ω) and inter-porosity flow coefficient (λ) for a naturally-fractured / shale dual-continuum reservoir.
Used in
Physics gaps v8 → dual-continuum preview
Shale RTA — diagnostic flow regime
Module
src/lib/dualPorosityDualPerm.ts → warrenRootParameters
Where
  • ω — fraction of storage in the fracture network [-]
  • λ — matrix-to-fracture transfer rate [-]
  • α — shape factor (Kazemi 4·(1/L_x²+1/L_y²+1/L_z²) for rectangular blocks)
  • k_m / k_f — matrix vs. fracture permeability [mD]
  • r_w — wellbore radius [ft]
Assumptions
  • Pseudo-steady matrix-to-fracture transfer
  • Single-phase slightly compressible flow
  • Idealised orthogonal fracture network
Validity range
Late-time semi-log inflection observable when λ·t_D > 10; ω in [10⁻³, 0.3] for tight shale.
Units: field; α expressed as 1/ft²

18.5 Palmer-Mansoori swelling (Gap 2b)#

Δφ/φ₀ = (c_m / M) · (P − P₀) + ε_L · (P / (P_L + P) − P₀ / (P_L + P₀)) · (K/M − 1)
Pressure- and adsorption-driven matrix porosity change in coal/shale; couples Langmuir desorption to elastic dilation.
Used in
Physics gaps v8 → swelling preview card
Module
src/lib/matrixSwelling.ts → palmerMansooriDeltaPhi
Where
  • φ₀ — initial matrix porosity [-]
  • c_m — pore compressibility [1/psi]
  • M — constrained axial modulus [psi]
  • K — bulk modulus [psi]
  • ε_L, P_L — Langmuir strain and pressure
  • P, P₀ — current and reference pore pressure [psi]
Assumptions
  • Uniaxial strain, constant overburden
  • Langmuir isotherm describes adsorbed phase
  • Elastic deformation only
Validity range
Coal / organic-rich shale; P within [0.1·P_L, 5·P_L] for the Langmuir fit to be in band.
Units: field

18.6 Slurry density and tip screen-out (Gap 3)#

ρ_slurry = (ρ_carrier + C_ppa) / (1 + C_ppa / ρ_prop) ; TSO when V_tip / V_slot ≥ η_pack
Effective slurry density from carrier + proppant loading (used in hydrostatic and ECD), plus the volumetric criterion that triggers a tip screen-out: arriving proppant volume exceeds the available tip slot at packing efficiency η_pack.
Used in
Pressure advisor → slurry hydrostatic cascade
Live pumping → screen-out risk chip
Module
src/lib/slurryPvt.ts → slurryDensity ; src/lib/tipScreenoutPredictor.ts → predictTipScreenOut
Where
  • ρ_carrier — base fluid density [ppg]
  • C_ppa — proppant loading [lb/gal added]
  • ρ_prop — proppant true density [g/cc]
  • V_tip / V_slot — proppant volume / slot volume at the tip [-]
  • η_pack — packing efficiency, default 0.62 (loose) … 0.74 (HCP)
Assumptions
  • Single-component proppant
  • Plug flow at tip (no slip)
  • Linear superposition of pad + slurry banks
Validity range
C_ppa ≤ 12 lb/gal for slickwater; TSO criterion calibrated against Cleary-Fonseca lab data — extrapolate above 16 ppa with caution.
Units: field (ppg, lb/gal, g/cc)

18.7 Near-wellbore tortuosity Δp (Gap 4)#

Δp_tort = (γ_rom · ρ · q² / (2 · A_perf²)) · (1 + κ_cleary · N_links)
Romero-Cleary near-wellbore pressure drop combining perforation jetting and link-up tortuosity; rises with rate squared and with the number of fracture link-ups between perfs and main wing.
Used in
Builder Wells & perforations → perf cluster designer (dpPerfPsi)
Step-down auto-detect → remediation chips
Module
src/lib/nearWellboreTortuosity.ts → romeroClearyDp ; src/lib/perfClusterDesign.ts → dpPerfPsi
Where
  • γ_rom — Romero discharge coefficient (≈ 0.95)
  • ρ — slurry density [lb/ft³]
  • q — single-cluster rate [bbl/min]
  • A_perf — open perforation area [in²]
  • κ_cleary — Cleary tortuosity factor (0.05 - 0.20)
  • N_links — number of fracture link-ups
Assumptions
  • Incompressible slurry at perf entrance
  • Single-fluid (slurry density represents the bank at the perfs)
  • Symmetric link-up across the cluster
Validity range
q ≤ 8 bpm/cluster; A_perf > 0.05 in² (smaller diameters drift outside Romero correlation band).
Units: field

18.8 Boundary conditions (Gap 5)#

Dirichlet: p|∂Ω = p_b ; Neumann: −k ∂p/∂n|∂Ω = q_b ; Robin: α·p + β·∂p/∂n = γ ; Free-water table: p|FWT = p_atm + ρ_w·g·(z_FWT − z)
The four boundary-condition forms exposed by the kernel; the Robin form generalises a fixed-pressure aquifer through a leakance coefficient, and the free-water-table BC anchors capillary equilibrium in coupled 3-phase runs.
Used in
Solver spec → §10 boundary conditions catalogue
Non-planar 3D viewer → BC picker (forthcoming)
Module
src/lib/boundaryConditions.ts → applyBoundaryCondition
Where
  • p_b — prescribed boundary pressure [psi]
  • q_b — prescribed boundary flux [STB/d/ft²]
  • α, β, γ — Robin coefficients (units chosen so the equation is dimensionally consistent)
  • z_FWT — true vertical depth of the free-water table [ft]
Assumptions
  • Each face owns a single BC kind
  • Free-water-table BC assumes hydrostatic water column above the table
  • Robin coefficients are constant per face (extend to position-dependent via patches)
Validity range
Mass-conservative on rectangular grids; for non-orthogonal grids the Neumann flux is projected onto the face normal.
Units: field
Verification provenance
Every equation in this section is reproduced in /trust/analytical-verification or /physics-gaps-v8 with a live verification-mode chip (history-matched vs. independent vs. unspecified). Use that chip to label the provenance of any number you cite externally.

19. What's new — v1.7 vs v1.6

Release notes for manual v1.7 (July 2026). Consolidates every feature shipped since v1.6 (June 2026), grouped by track.

Manual v1.7 (July 2026) captures the physics + workflow batch that closed the v4/v5/v6 competitor-gap audits and the Phase 15 rheology upgrade. Deep-dives live in the linked routes; this section is the at-a-glance changelog.

Highlights#

  • Non-planar 3D fracture solver — surface-mesh DDM with tip kinking, natural-fracture branching, out-of-plane tilt, and T-junction reconvergence weld (see /non-planar-3d + per-simulation Results tab).
  • Compositional 3-phase black-oil kernel wired into the Fluid model panel (energized-CO₂ PR-EOS bridge, IMPES + tracers + fluid regions + zero-perm cubes + per-well drilling times).
  • Multi-well pad artificial-lift design (gas lift / ESP / rod pump / plunger) at /artificial-lift with shared-compressor allocation.
  • Coiled-tubing & snubbing reach analyzer at /coiled-tubing (Lubinski + Dawson-Paslay buckling) and geosteering optimizer at /geosteering (SHmax alignment + containment + DLS feasibility).
  • Refrac diversion designer (PBD + chemical staging, multi-cycle survival) mounted on /refrac.
  • v5 rock+fluid physics bundle: bedding-plane fracture card, mud-window card, formation-damage + perforation skin, rate-and-state friction, stress-dependent permeability with hysteresis, LET / Stone-II rel-perm, mineral scaling kinetics, gas non-Darcy inflow.
  • Phase 15 rheology upgrade: Carreau-Yasuda with optional Maxwell modes + crosslinker shear-history damage folded into the breaker schedule.
  • Scenario branching tree at /branches (git-style fork/diff) and cell-level scenario blame in SimDiff.
  • LLM Copilot picks in the ⌘K Command palette (Gemini 2.5 Flash via Lovable AI Gateway).
  • RESQML v2.0.1 EPC export validated against a golden fixture — round-trippable in Petrel / RESinsight.

Shipped features by track#

TrackFeatureWhere to find it
Fracture physicsNon-planar 3D solver (M1-M4 + reconvergence weld)/non-planar-3d + Results tab
Fracture physicsBedding-plane / horizontal fracture classifierBuilder → Fracture options
Fracture physicsRefrac diversion designer (PBD + chemical)/refrac
ReservoirCompositional 3-phase black-oil + PR-EOS energized-CO₂Builder → Fluid model
ReservoirFluid regions (PVTNUM) + zero-perm cubes + per-well drilling timessolver kernel
ReservoirStress-dependent k with hysteresis + LET / Stone-II rel-permrock-mechanics library
ReservoirMineral scaling kinetics (calcite / barite / FeS / SiO₂)scaling library
WellboreMud-window safe operating envelopeBuilder → Wells & perforations
WellboreFormation damage + Karakas-Tariq perforation skinIPR composition
WellboreCoiled-tubing & snubbing reach (Lubinski + Dawson-Paslay)/coiled-tubing
WellboreGas non-Darcy inflow (pseudo-pressure + Wattenbarger turbulence)gas IPR library
ProductionMulti-well pad artificial-lift + shared-compressor allocation/artificial-lift
Well placementGeosteering optimizer (SHmax alignment + DLS feasibility)/geosteering
Induced seismicityRate-and-state friction (Dieterich-Ruina spring-slider)seismicity library
RheologyCarreau-Yasuda + optional Maxwell modes + Wi / N₁ chipBuilder → Fluid model
RheologyCrosslinker shear-history damage folded into breaker T½BreakerScheduleCard
WorkflowScenario branching tree (git-style fork / diff)/branches
WorkflowScenario version blame in SimDiff (per-leaf author + time)SimDiffDialog
CopilotLLM Copilot picks in ⌘K Command paletteCommandPalette
InteropRESQML v2.0.1 EPC export (golden-fixture validated)/interop

Default behavior changes (read carefully)#

Manual version bumped
MANUAL_VERSION 1.6 → 1.7, MANUAL_UPDATED July 2026. The /manual header and PDF cover reflect this automatically. No schema migrations — every new store uses a fresh localStorage key.
Opt-in physics
Non-planar 3D solver, compositional 3-phase kernel, out-of-plane tilt, T-junction weld, crosslinker shear damage, and mud-window card are ALL opt-in via their respective panels. Omitting the toggle keeps the legacy path byte-identical.

Migration notes#

  • Fluid kind now includes 'compositional-3p' in addition to black-oil; existing simulations keep their current kind and default to black-oil.
  • Non-planar 3D results are appended to each simulation as an extra Results tab when the solver is enabled; disabling reverts to the planar Results view.
  • The bedding-plane card mounts at the end of Fracture options — existing tutorial snapshots that assert panel length were regenerated in the same edit.
  • Command palette 'Copilot picks' require LOVABLE_API_KEY (Lovable Cloud users have this pre-set); without it the ✨ button is hidden and only lexical matches show.

20. What's new — v1.8 (operator surface + advanced physics)

Seven newly documented routes: Driller's Copilot, Live+ diagnostics pack, Transient multiphase wellbore, CCUS/MRV ledger, Induced-seismicity forecaster, Non-planar 3D solver, and the updated Solver spec scoreboard. Each includes a short walkthrough plus the governing equations.

Manual v1.8 documents the operator-facing surfaces and advanced-physics routes shipped after the v6 competitor-gap closure. Every route below is live in production; the walkthroughs mirror the on-screen tabs and cards so a new engineer can go from cold-open to a defensible answer without a mentor.

20.1 Driller's Copilot (RigSense) — /driller-copilot#

Six-tab driller-facing assistant that watches the rig telemetry stream and calls out stuck-pipe risk, kick/loss, MSE founder, swab/surge, and answers voice questions. All physics is pure — the AI layer (Lovable AI Gateway, Gemini 2.5 Flash) is used only for Q&A and morning report drafting, never for a setter action.

Physics model
Driller's Copilot — governing relationships
Governing equations
  • MSE = WOB/A_b + (120·π·RPM·τ)/(A_b·ROP) (Teale, ksi)
  • Δp_swab/surge = f·(ρ·v_p²)/2 · (L/D_h) (Burkhardt, effective MW = static MW ± Δp/0.052·TVD)
  • Stuck-pipe severity = max(sev_differential, sev_mechanical, sev_packoff) over a rolling window
  • Kick/loss margin = min(effective MW − MW_kick, MW_breakdown − effective MW) (ppg)
Assumptions
  • Single-phase mud in the annulus for the Burkhardt Δp; gas influx handled by the kick-detector proxy, not the swab/surge advisor.
  • MSE regime classifier uses fixed thresholds calibrated on land-rig data; ultra-deep offshore benefits from re-tuning.
  • Voice Q&A payload capped at 8 KB — offset reports trimmed lexically before the LLM call.
References
  • Teale, R. (1965). The concept of specific energy in rock drilling.
  • Burkhardt, J. (1961). Wellbore pressure surges produced by pipe movement. JPT.
Walkthrough — reading the six tabs
  1. 1Stuck-pipe tab
    UI: /driller-copilot → Stuck-pipe

    Max-of-three severity chip (differential / mechanical / pack-off). Amber ⇒ log the offset, red ⇒ break circulation before making a connection.

    Result: Chip + rolling-window sparkline
  2. 2Kick/loss + mud window
    UI: /driller-copilot → Kick / loss

    Live ppg margin against the pore-pressure floor and the breakdown ceiling from the /wellbore-stability module. Negative margin ⇒ TLP action.

  3. 3MSE founder
    UI: /driller-copilot → MSE

    Teale MSE in ksi + regime classifier (efficient / founder / bit-balling / whirl / stick-slip). Follows a WOB / RPM step recommendation.

  4. 4Trip advisor
    UI: /driller-copilot → Trip

    Bisected max-safe pipe velocity from Burkhardt Δp holding effective MW inside the mud window.

  5. 5Voice Q&A
    UI: /driller-copilot → Voice

    Push-to-talk speech-to-text → Gemini 2.5 Flash with the rig-context payload. Confirmation-before-write for any setter command.

  6. 6Morning report
    UI: /driller-copilot → Morning report

    Auto-drafts the 06:00 report from the last 24 h of samples + logged events; engineer edits before signing.

20.2 Live+ diagnostics pack — /live-pumping + /tools/dfit-interpreter#

Sprint 1 of the v10 competitor-gap plan. Adds a step-down inverter, per-cluster entry-friction distribution, DFIT pre-closure regime interpreter, and a wellbore fluid-front animator. The pre-closure interpreter is also mounted at the public /tools/dfit-interpreter free tool (no auth, no storage).

Δp_perf = 0.2369·ρ/(C_d²·n²·d⁴)·q² + K_nwb·q^n
Step-down decomposition: perforation friction (Cramer/Massaro) + near-wellbore tortuosity term.
Used in
/live-pumping → Step-down card
post-job CSV ingest
Module
src/lib/liveDiag/stepDownInverter.ts → invertStepDown
Where
  • ρ = slurry density (ppg)
  • C_d = discharge coefficient (dimensionless; healthy perfs 0.6–0.85)
  • n = open shot count
  • d = perf diameter (in)
  • q = rate (bpm)
  • K_nwb·q^n = near-wellbore tortuosity Δp (psi); n fixed at 0.5 by default
Driven by (UI fields)
  • closurePsi (irrelevant)
  • ≥ 2 (rate, Δp) plateaus from the step-down file
Assumptions
  • Slurry density and shot count constant across plateaus
  • n_nwb fixed at 0.5; overridable
Validity range
≥ 2 descending plateaus; C_d ∈ [0.05, 1.5]
Units: psi, ppg, in, bpm
slope = d(log|dp/dt|) / d(log t) ⇒ {radial: 0, bilinear: 0.25, √t: 0.5, linear: 1}
DFIT pre-closure regime from the log-log falloff slope (Barree-style).
Used in
/tools/dfit-interpreter (public free tool)
/live-pumping → DFIT card
Module
src/lib/liveDiag/dfitPreClosureInterpreter.ts → interpretPreClosure
Where
  • |dp/dt| = absolute pressure derivative during pre-closure
  • t = shut-in time (min)
  • slope classified against the four canonical regimes using |slope| so negative signs still match
Assumptions
  • Pre-closure only (not radial G-function)
  • Sample cadence ≥ 3 within the fit window
Units: psi/min, min
Walkthrough — decomposing a step-down test
  1. 1Paste plateaus
    UI: /live-pumping → Step-down

    Paste ≥ 2 (rate, Δp_total) rows into the Step-down card. Slurry ppg + perf diameter + shot count auto-fill from the schedule.

  2. 2Read C_d and tortuosity severity

    Card returns C_d effective, open shot count, K_nwb, RMS residual, and a tortuosity chip (healthy / elevated / severe).

    Result: e.g. C_d=0.61 · shots 24/32 · K_nwb=140 psi/bpm^0.5 → 'elevated'
  3. 3Route to remediation

    'severe' + open-shot deficit ⇒ ball-out or add-shots. 'elevated' with full shots ⇒ NWB tortuosity — schedule a slug and retest.

20.3 Transient multiphase wellbore — /transient-multiphase-wellbore#

Phase B coordinator that steps pressure → flow-regime → enthalpy in one call. Wraps the drift-flux 1-D solver (Standing-Katz Z(p,T) via DAK + Sutton + Wichert-Aziz sour-gas correction) with a Taitel-Dukler + Barnea flow-regime classifier and a backward-Euler enthalpy wave (Joule-Thomson + latent heat of vaporization).

Physics model
Transient multiphase wellbore — governing equations
Governing equations
  • ∂(ρ_m)/∂t + ∂(ρ_m·v_m)/∂z = 0 (mass)
  • ∂(ρ_m·v_m)/∂t + ∂(ρ_m·v_m²)/∂z = −∂p/∂z − ρ_m·g − τ_w·P/A (momentum)
  • ∂(ρ_m·h_m)/∂t + ∂(ρ_m·v_m·h_m)/∂z = ∂(k·∂T/∂z)/∂z − U·(T−T_∞) (enthalpy)
  • v_g = C_0·v_m + v_d (Zuber-Findlay drift-flux)
  • Z(p,T) = f_DAK(ρ_r, T_r) with pseudo-criticals from Sutton (1985) and Wichert-Aziz (1972)
  • Regime classifier: horizontal → Taitel-Dukler (5 regimes); vertical → Barnea (bubble / slug / churn / annular)
Assumptions
  • 1-D segmented pipe; no lateral heterogeneity in a segment.
  • Segregated implicit Euler (pressure tridiag → velocity update → temperature tridiag).
  • Swamee-Jain Darcy-Weisbach friction; no rugosity coupling to solids.
  • Enthalpy: μ_JT and L_v supplied per phase; solid CO₂ deposition NOT modeled.
References
  • Zuber, N. & Findlay, J. (1965). Average volumetric concentration in two-phase flow systems.
  • Taitel, Y. & Dukler, A. E. (1976). A model for predicting flow regime transitions in horizontal and near horizontal gas-liquid flow. AIChE J.
  • Dranchuk, P. M. & Abou-Kassem, J. H. (1975). Calculation of Z factors for natural gases.
  • Wichert, E. & Aziz, K. (1972). Calculate Zs for sour gases.
Model limitations
  • Not an OLGA replacement — no explicit slug tracker, no wax/hydrate deposition solver.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Slugging is a real safety and equipment-integrity issue at surface separators; a drift-flux mixture average will not warn about slug-caused pressure spikes or wax/hydrate plug growth.
    When it breaks down:
    High-GOR wells during flowback, cold flowlines below wax/hydrate onset, or any topside choke-cycling operation.
    Safer alternative:
    Use this module for pressure/temperature envelopes and screening; route slug and deposition modelling to an external OLGA/LedaFlow run and import BHP/T as boundary conditions.
  • Regime map margins are advisory chips; the closures themselves are drift-flux blended, not regime-switched.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Blended closures can silently interpolate across a real regime boundary; the advisory chip is the only signal that the operating point is near a transition where the physics actually changes.
    When it breaks down:
    Near stratified↔intermittent transitions (Taitel-Dukler map margins) in slightly-inclined flowlines and near the bubbly↔slug boundary at low superficial gas.
    Safer alternative:
    When the advisory chip trips watch/amber, tighten the operating range or re-run with an explicit regime-switched closure library outside this tool before committing the design.
  • Enthalpy wave uses a single mixture cp; independent phase enthalpies are on the roadmap.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A single mixture cp smooths latent-heat effects at phase-change fronts; wellbore temperature predictions can drift by tens of °F when gas breakout or condensation is significant.
    When it breaks down:
    Depletion crossing the bubble point in the tubing, retrograde-condensate wells, and CO₂-flood wellbores where cp differs by an order of magnitude between phases.
    Safer alternative:
    Use the DTS fibre-optic import on /live-pumping (fiberOpticTelemetry.ts) to anchor the temperature profile to measurement, and treat the modelled T as an envelope, not a golden.

20.4 CCUS / MRV ledger — /ccus-mrv#

Regulator-grade Monitoring / Reporting / Verification workflow for CO₂ storage. Append-only signed ledger of injection mass, plume snapshots, caprock seal severity, and leakage flux; Subpart RR-style PDF export per reporting period; hash-chain proof and field-validation cross-check between measured and modeled Δp.

r_plume(t) ≈ √(Q_inj·t / (π·h·φ·(1−S_wr))) (Nordbotten-Celia √t plume radius)
First-order plume front for a single vertical injector into a homogeneous horizontal aquifer.
Used in
/co2-storage primer
/ccus-mrv plume-snapshot event
Module
src/lib/co2StorageAssurance.ts
Where
  • Q_inj = volumetric injection rate at reservoir conditions (m³/s)
  • t = time since injection start (s)
  • h = net aquifer thickness (m)
  • φ = porosity
  • S_wr = residual water saturation
Assumptions
  • Sharp-interface (VE) plume
  • Constant Q_inj
  • Homogeneous, horizontal aquifer
Units: SI
Δp(r, t) = (Q·μ_w) / (4·π·k·h) · W(u), u = (r²·φ·μ·c_t) / (4·k·t)
Theis line-source overpressure at radius r used for caprock capillary-seal margin.
Used in
/ccus-mrv caprock alarm
/induced-seismicity Δp input
Module
src/lib/co2StorageAssurance.ts
Where
  • W(u) = well function (exponential integral)
  • μ_w = brine viscosity
  • k = permeability
  • c_t = total compressibility
Units: Pa, m, s
Walkthrough — building a Subpart RR report
  1. 1Log injection events
    UI: /ccus-mrv → Ledger

    Every metering event (mass, time, source) appends a signed record; the hash chain is anchored to the previous ledger tail.

  2. 2Attach plume + caprock snapshots

    Nordbotten-Celia plume radius and Theis Δp evaluated at the reporting instant; severity chip (ok / watch / amber / critical) inline.

  3. 3Attach field-validation cross-check
    UI: /ccus-mrv → Cross-check

    Modeled vs measured Δp residuals from /field-validation → ok/watch severity feed into the same ledger.

  4. 4Export Subpart RR PDF
    UI: /ccus-mrv → Export

    4 §-keyed sections + attestation + hash-chain proof + period-filtered ledger tail; letter, paginated.

20.5 Induced-seismicity forecaster — /induced-seismicity#

Dieterich (1994) seismicity-rate response to a pore-pressure time series with a Traffic-Light Protocol (TLP) classifier, USGS catalog auto-refresh, operator-action audit log, and copy-paste regulator templates (OK CC, KS Corp Comm, TX RRC).

R(t) = r · [γ(t)·(dτ/dt)_ref]⁻¹, dγ/dt = (1/a·σ)·[1 − γ·(dτ/dt)]
Dieterich (1994) rate-and-state seismicity-rate response with backward-Euler on γ.
Used in
/induced-seismicity forecaster
/parent-child fault-reactivation chip
Module
src/lib/induced/dieterichSeismicityRate.ts
Where
  • R(t) = seismicity rate (events/time)
  • r = background rate
  • γ = state variable with initial value γ_0 = 1/(dτ/dt)_ref
  • a·σ = direct-effect parameter (typ. 0.001–0.01 · effective normal stress)
  • dτ/dt = shear-stressing rate driven by ΔP·μ_f (Coulomb) + Δτ coseismic jumps
Assumptions
  • Optimally oriented faults
  • Constant a·σ
  • Δτ coseismic jumps optional
Validity range
Dieterich, J. (1994) JGR — rate-and-state seismicity-rate response.
Units: events/day, MPa/day
TLP class = ladder({rate ratio, M_max, distance to threshold catalog M})
4-way traffic-light classifier (green / yellow / amber / red) over per-preset thresholds (default / OK_CC / KS_CC / TX_RRC / custom).
Used in
/induced-seismicity TLP card
Module
src/lib/induced/tlpThresholdPresets.ts → classifyTrafficLight
Where
  • rate ratio = R(t) / r_background
  • M_max = observed max magnitude in the rolling USGS window
  • thresholds persisted per-preset in localStorage downhole.inducedSeismicity.tlpThresholds.v1
Walkthrough — configuring a TLP for a new pad
  1. 1Pick a preset

    OK_CC / KS_CC / TX_RRC / default / custom. Each preset ships a monotonic-ladder (yellow < amber < red) rate-ratio and M_max threshold set.

  2. 2Turn on USGS auto-refresh
    UI: /induced-seismicity → USGS card

    Choose a cadence (7 options, from 1 min to daily); hidden-tab and in-flight de-dupe are handled automatically.

  3. 3Log an operator action
    UI: /induced-seismicity → Audit log

    Every TLP transition auto-logs; manual rate-cut / shut-in / monitoring / regulator-report / note also appends. CSV export mirrors the regulator template.

20.6 Non-planar 3D fracture solver — /non-planar-3d + Results tab#

Surface-mesh DDM with tip kinking (M-integral MTS), natural-fracture branching (Renshaw-Pollard + Gu-Weng), out-of-plane tilt, T-junction reconvergence weld, and a kernel bridge that pushes an equivalent planar half-length + conductivity retention back into /refrac, black-oil, and /parent-child. Opt-in from the Fracture options panel; omitted ≡ legacy planar path byte-identical.

Physics model
Non-planar 3D — governing equations
Governing equations
  • σ(x) = ∫∫_Γ K(x − x')·D(x') dS' (3-D DDM boundary integral)
  • β_kink = argmax_θ [σ_θθ(θ) − K_IC²/2πr] (Maximum Tangential Stress kink criterion)
  • Renshaw-Pollard: HF crosses NF when σ_θθ^HF > T_0^NF (elastic screening)
  • Gu-Weng: HF branches into NF when λ_GW = (σ_θθ − p_pore)/(σ_H − σ_h)·f(angle) > λ_crit
  • C_f_retention = tortuosity^(−exp) (Darcy along the curved path back to a planar-equivalent k·w)
Assumptions
  • Linear-elastic host rock; plasticity in a small process zone at the tip only.
  • Constant fluid pressure inside a step; time-marched between DDM solves.
  • Weld folds only tips within 0.25·advanceFt of an existing parent vertex (default) to avoid spurious merges.
References
  • Erdogan, F. & Sih, G. C. (1963). On the crack extension in plates under plane loading and transverse shear.
  • Renshaw, C. E. & Pollard, D. D. (1995). An experimentally verified criterion for propagation across unbonded frictional interfaces in brittle, linear elastic materials.
  • Gu, H. & Weng, X. (2010). Criterion for fractures crossing frictional interfaces at non-orthogonal angles. ARMA 10-198.
Walkthrough — enabling non-planar in one simulation
  1. 1Toggle in Builder
    UI: Builder → Fracture options

    Fracture options → Non-planar 3D solver → Enable. Set element size, max kink [°], branch threshold [°], and max curvature [°/ft].

  2. 2Run + open viewer
    UI: /non-planar-3d

    The /non-planar-3d viewer renders the mesh with tip-kinking + branching + weld indicators; the per-simulation Results tab shows the scoreboard.

  3. 3Pull equivalent planar geometry into refrac / BO

    The bridge exposes effective half-length + conductivity retention (tortuosity^(−exp)); /refrac and /parent-child multiply through the existing k·w and L inputs automatically.

20.7 Solver spec scoreboard — /solver-spec#

Refreshed model card. Each physics row carries four possible badges — Shipped, Next up, In Newton loop, Out of scope — and 'In Newton loop' rows expose a hover tooltip pointing at the exact kernel file / PR that wires the module into coupledNewtonStep. A short legend above the scoreboard explains each badge and defines the outer nonlinear corrector.

  • Shipped — live in production and exercised by the linked route.
  • Next up — physics is built; remaining PR wires it into runtime UI and the Newton outer loop.
  • In Newton loop — runs inside coupledNewtonStep (pressure / width / state variables corrected until residuals converge).
  • Out of scope — explicitly excluded today (e.g. OLGA-class transient multiphase in the frac kernel).
RowIn-Newton kernel wiring
Fracture mechanicstipPropagationStep + kgdMovingTipRunner.ts
Fluid-solid couplingcoupledNewtonStep.ts (Phase 4, default @ Phase 7 inc 16)
Leak-offCarter sink in coupledNewtonStep (Phase 5 inc 6)
Proppant transportwellboreProppantPreviewDriver.ts + wellboreScalarTransport.ts
Coupling directionsubStepReservoir on singlePhaseGrid.ts / compositionalBlackOil3P.ts (Phase 9, default-ON @ Phase 16)
Wellbore flowtransientWellbore.ts + drift-flux + Standing-Katz (Phase 8 inc 3)
T-M-H voxelnewtonThermoPoroCoupling.ts (Phase 9)

Version + migration notes#

Manual version bumped
MANUAL_VERSION 1.7 → 1.8, MANUAL_UPDATED July 2026. No schema migrations; every new route uses its own localStorage namespace and its own Zod-validated store.
Everything is opt-in
Driller's Copilot, Non-planar 3D, Transient multiphase coordinator, and the CCUS/MRV ledger are all opt-in surfaces. Omitting them keeps the legacy paths byte-identical — no regression risk to an in-flight project.

21. Release notes index (what changed, where to look)

Every 'what changed since last release' bucket in one place — v1.4/v1.6/v1.7/v1.8 chapter cross-links, the live `.lovable/plan.md`, and the /roadmap route. Answers the review comment 'why does the manual skip §21?'.

This chapter exists to close the historical §21 numbering gap. It contains no new physics — it is a signpost. If you are looking for what changed in a specific release, follow the link below; if you are looking for what is still in flight, follow the roadmap link.

  • §15 — Recently shipped (post-1.0). The evergreen list; kept up to date as features land.
  • §16 — What's new in v1.4 vs v1.3.
  • §19 — What's new in v1.7 vs v1.6.
  • §20 — What's new in v1.8 (operator surface + advanced physics).
  • `.lovable/plan.md` — the working plan tracked alongside the codebase; every open review comment maps to a plan bucket here.
  • `/roadmap` — the live status page, sourced from `src/lib/atozGapList.ts`. Ship/flag status is flipped there and in project memory in the same edit, so this is the closest thing to a single source of truth.
Why §21 was empty
The manual grew chapter-by-chapter across releases and one release's what's-new sat under §20 while the next started at §22 (model verification). Rather than renumber every downstream chapter (and every cross-link in prose, PDF, and drift-guard tests), we reclaim §21 as this index. The other chapter numbers are stable.

22. Model verification — beyond history matching

Independent numerical + analytical verification of every solver module. History matching is one channel; the drift-guard test suite is the other. This chapter answers 'how do you know the physics is right without a field match?'.

Reviewers frequently ask whether Wellbore Genius is only validated against measured field data (history matching). It is not. Every physics module ships with an executable drift-guard test that compares the numerical kernel against a closed-form analytical solution, a published benchmark, or a manufactured solution. If any comparator drifts outside its published tolerance, CI fails and the build is blocked from shipping.

Two independent verification channels
Channel A (analytical / benchmark): >600 drift-guard tests locked in .github/workflows/*.yml. Channel B (field history match): DFIT registry + campaign residuals in /field-validation. A module must clear BOTH before it enters the default solver path — the compositional 3-phase kernel, for example, ships behind a Fluid-model panel toggle until its Buckley-Leverett + mass-balance residuals are green.

Analytical benchmarks currently in CI#

ModuleComparatorMetricDrift-guard file
PKN half-lengthNordgren 1972 closed form L ∝ t^(4/5)max |log₁₀(L/L_ref)| ≤ 0.20 on [0.5, 1] sdfitBenchmarkRunner.test.ts
KGD half-lengthGeertsma-de Klerk closed formmax |log₁₀ residual| within registry tolerancedfitBenchmarkRunner.test.ts
Radial fracturePerkins-Kern radialmax |log₁₀ residual| within registry tolerancedfitBenchmarkRunner.test.ts
Peaceman injectorDimensionless τ_D = η·t/L² invariance across μ ∈ {0.5, 1, 2, 5} cp≤ 8 % τ_D drift; dt-tile band E_μ from tolerancesFor(μ,dt)viscosity-sweep + dimensionlessTime.test.ts
Buckley-LeverettWelge tangent fw + shock profileL1 + L∞ vs analytical profilebuckleyLeverett.test.ts + kernel-parity
Mass balanceΣ mass_in − mass_out − Δ mass_in_placeworstRelative ≤ 1e-5 (Carter tightened from 0.05)massBalanceReport.test.ts
Non-planar 3D bridgeCollapses to planar geometry when tortuosity = 1Bit-identical planar recoverynonPlanar3D/kernelBridge.test.ts
Poroelastic depletionGeertsma 2-D Lamé inside/outside discAnalytical σ_h / σ_H at 8 witness pointsporoelasticDepletion.test.ts
Mindlin 3-D benchCollapses to 2-D poro when layers = ∅Byte-identical 2-D recoverymindlin3D.test.ts
Thermo-poro probeProbe metrics ≡ child-fracture geometry across 108 sweeps3-way collapse (off ≡ [] ≡ ΔT = 0)probePointVsThermoPoroParity.test.ts
Compositional 3-phasePR-EOS energized-CO₂ FVF bridge + BL parityL∞ ≤ 0.5 vs BL analyticalcompositionalBlackOil3P.test.ts + BL parity
Rate-and-state frictionDieterich-Ruina analytical stability boundarycritical stiffness / nucleation length within tolrateStateFriction.test.ts
Wellbore stabilityKirsch + Mohr-Coulomb closed form for vertical boreholeAnalytical p_w(σ_h, σ_H, φ, UCS, α, T₀)wellboreStabilityMudWindow.test.ts
Non-Darcy gas inflowWattenbarger A·q + B·q² solved analyticallyB = 0 and A = 0 edge casesgasNonDarcyInflow.test.ts
Adaptive substepperPI control on |ΔP|∞ / |ΔT|∞clampedAtMin flag + rejection accountingcoupledTransientSubstepper.test.ts

Field-campaign validation (channel B)#

  • DFIT registry — every registered mini-frac closure re-fit each CI run; residuals summarised in solverSpecScoreboard.ts.
  • MSEEL HFTS-1 datasets — public microseismic + fibre benchmark cross-references (mem/reference/mseel-hfts1-datasets.md).
  • Field-validation campaigns route (/projects/$p/workspaces/$w/field-validation) — upload gauge (t, P, T) or gradient (MD, P, T) surveys; verdict = AND of attached comparisons (leak-off, fracture-mechanics, DFIT).
  • Microseismic ↔ conductivity validation (mem/features/microseismic-conductivity-validation.md).
  • PVT consortium presets exercised against published Wolfcamp / Bakken / Eagle Ford / Marcellus / Montney / Vaca Muerta EoS tunings.

How to read /solver-spec#

The /solver-spec page is the human-readable index of what is verified vs what is roadmap. Each row states (a) the current implementation, (b) the drift-guard file that locks it, (c) the honest limits (what the module does NOT do), and (d) the next roadmap increment. If a row's `roadmap` cell is non-empty, that gap has an open test but no shipping implementation — the review should treat it as absent, not present.

Depth-profile visual — DFIT calibration#

Depth profile
Field (psi, ft, °F)
DFIT calibration — closure vs. hydrostatic & pore
0.01,0002,0003,0004,0005,0000.02,0004,0006,0008,00010,000Pressure [psi]TVD [ft]P_c ≈ 7,820 psi
  • Hydrostatic (9.2 ppg water)
  • Pore pressure
Fitted closure P_c = 7,820 psi at 10,450 ft TVD lands between static mud column and pore pressure, as expected for the Middle Bakken.

Depth-profile visual — wellbore mud-window#

Depth profile
Field (psi, ft, °F)
Wellbore stability — safe mud-window vs. depth
0.02,0004,0006,0008,0000.02,0004,0006,0008,00010,000Pressure [psi]TVD [ft]
  • Pore pressure (kick limit)
  • Shear-failure floor
  • Loss ceiling (σ_v)
  • Tensile breakdown
Kirsch + Mohr-Coulomb closed form; the band between the shear-floor and loss-ceiling is the drilling-safe window.
Where history-matching alone would mislead
A history match can look excellent while the underlying kernel is compensating one error with another (e.g. over-leaked width traded against under-conductive proppant). The analytical comparators above catch that class of error before any field match is attempted. When a field campaign disagrees with a green analytical comparator, we treat the FIELD data as the artefact under investigation first — not the kernel.
Model limitations
  • Analytical comparators cover the pure physics module — they do not verify UI wiring. UI-level regressions are caught by Playwright drift-guards, not by these tests.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A green analytical comparator does NOT prove the value reached the screen correctly; a wiring bug can hide behind a passing kernel test and mislead an operator reading the UI.
    When it breaks down:
    Any time a route, panel, or export is added/rewired without the corresponding Playwright drift-guard being updated in the same PR.
    Safer alternative:
    Run the /manual + /solver-spec Playwright suites locally before merging UI-touching PRs, and require a Playwright test line change on any PR that edits a route file.
  • The PKN early-time tolerance is currently 0.20 (log₁₀), reverted from a briefly-tightened 0.15 while a dx-invariant t ≈ 0.5 s formulation gap is investigated (see .lovable/plan.md, 2026-07-08).
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A loose PKN early-time tolerance means the drift-guard will not catch a genuine ~15-25 % over/under-prediction at t < 1 s, which is exactly where breakdown/near-wellbore decisions live.
    When it breaks down:
    Ultra-short breakdown windows (< 2 s) and step-rate diagnostics that rely on the first few seconds of the pressure trace.
    Safer alternative:
    Read PKN early-time values as an envelope until the formulation gap is closed; anchor breakdown decisions to the Pressure Advisor wizard's independent shear-floor calculation instead.
  • Field campaigns are opt-in per workspace; verdicts do not roll up into a project-wide score without operator action.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Without an operator opt-in, a project can look 'validated' overall while several workspaces have never been checked against measured data.
    When it breaks down:
    Multi-workspace projects where different engineers own different pads and no reviewer aggregates the verdicts.
    Safer alternative:
    Add a project-level checklist that requires at least one closed field-validation campaign per workspace before any design run is treated as sanctioned.
  • Rate-and-state friction is single-fault quasi-static — multi-fault interaction is roadmap.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A single-fault quasi-static model cannot reproduce cascading events on adjacent structures, which is the pattern behind almost every M ≥ 3 induced-seismicity case in the last decade.
    When it breaks down:
    Areas with mapped conjugate faults (SCOOP/STACK, Fox Creek Duvernay, Sichuan) and any pad within ~5 km of a critically-stressed basement fault.
    Safer alternative:
    Cross-check with an external multi-fault Coulomb-stress transfer study and honour the local traffic-light regulator protocol as the binding constraint, not the model output.
  • Compositional 3-phase is IMPES, not fully-implicit; large capillary-dominated timesteps may require dt reduction.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    IMPES with a coarse dt in a capillary-dominated regime can over-shoot saturations and produce a wildly-wrong front position; the pressure solve stays stable so the failure is silent.
    When it breaks down:
    Very-low-permeability chalks and tight-gas at high P_c, or any imbibition-dominated flowback simulation.
    Safer alternative:
    Reduce dt through the Phase-9 substepper (targetP/targetT knobs) or run the buckleyLeverett kernel-parity comparator to bound the front-position error before trusting the saturation map.

23. Recent physics + numerical additions (round-3 answers)

One consolidated chapter documenting the physics work shipped since the round-2 review: non-planar 3D, thermo-poro coupling, phase-field DEM, compositional 3-phase, adaptive substepper, heterogeneity coupling, multi-well interference, and induced-seismicity. Each module lists its equations, assumptions, drift-guard file, and hard limitations.

This chapter exists because reviewer feedback repeatedly said 'the improvements are not visible in the manual'. Every module below is already shipping — links point to the live route and the pure-lib source. If a claim here is not backed by a drift-guard test file, treat it as a documentation bug and file it.

23.1 Non-planar 3D fracture solver#

Depth profile
Field (psi, ft, °F)
Bakken pilot — hydrostatic, pore, and geotherm on one strip
0.01,0002,0003,0004,0005,0006,0000.02,0004,0006,0008,00010,000Value (see legend for units)TVD [ft]
  • Hydrostatic [psi]
  • Pore [psi]
  • Geotherm [°F]
One reference profile shared across chapters — units differ per series (psi vs °F), so the axis is dimensionless magnitude.
Physics model
Non-planar 3D solver
Governing equations
  • Element-size (h_e), max kink (Δθ_max), branch threshold (θ_b), max curvature (κ_max) knobs feed the discretisation directly
  • Planar-equivalent bridge: effective L_half = polyline arc length; conductivity retention = tortuosity^(−exp)
  • Stress-driven curvature switch routes tip advance through the He-Hutchinson pierce/kink classifier
Assumptions
  • Quasi-static propagation (no dynamic wave loading)
  • Rock is linear-elastic between benches
  • Tortuosity multiplier applies to along-path Darcy conductivity only
Discretization

Piecewise-linear polylines per step; kink cap at Δθ_max between adjacent segments

References
  • He, M-Y and Hutchinson, J.W. (1989) — Kinking of a crack out of an interface
  • Non-planar 3D kernel bridge — src/lib/nonPlanar3D/kernelBridge.ts
Model limitations
  • No dynamic fracture — quasi-static only.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Dynamic effects (radiation damping, inertia) can slow tip velocity and change branching thresholds; a quasi-static run over-predicts propagation speed and length for very-high-rate breakdown events.
    When it breaks down:
    Perforation breakdown at rates > 100 bpm on a single cluster, or when a rate step exceeds ~40 bpm within a second.
    Safer alternative:
    Cap analysis at post-breakdown quasi-steady conditions; for breakdown itself use the Pressure Advisor breakdown-pressure branch instead of the propagation solver.
  • Bridge to planar kernel derates conductivity multiplicatively; it does not re-solve full 3-D Darcy along the curved path.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A multiplicative retention factor is fast but can miss local Darcy re-focusing at sharp kinks; conductivity along a kinked path can be lower than the average factor implies.
    When it breaks down:
    Paths with > 3 kinks exceeding 30° over 20 ft, or where a proppant bank plugs a single high-curvature segment.
    Safer alternative:
    Read the per-step curvature breakdown in NonPlanar3DResultsCard and, for any step flagged 'top' by kink metric, run a stand-alone Darcy comparator on the polyline before trusting the effective L_half.
  • Stress-driven curvature is a heuristic switch, not a full XFEM tip enrichment.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A heuristic tip criterion can pick the wrong plane at bi-material or high-contrast interfaces; the He-Hutchinson classifier is well-calibrated in-lab but has documented cases where it under-predicts kink at low σ-ratio.
    When it breaks down:
    Fracture tips approaching a bedding plane with a weak interface or crossing a high-modulus contrast (> 3×) bench boundary.
    Safer alternative:
    Enable the phase-field DEM laminated-shale primer (Chapter 23.3) as an offline sanity check; if the two solvers disagree, honour the more-conservative (lower L_half) result until reconciled.

23.2 Thermo-poro 3-D coupling#

Depth profile
Field (psi, ft, °F)
Thermo-poro 3-D — geotherm with cooling patch
0.0501001502000.02,0004,0006,0008,00010,000Temperature [°F]TVD [ft]Reservoir topReservoir base
  • Geotherm (undisturbed)
  • Cooled reservoir (post-injection)
ΔT = −95 °F across the reservoir window drives Geertsma Δσ_h that feeds the child-frac SHmax rotation.
Physics model
Thermo-poro 3-D
Governing equations
  • Δσ_h, Δσ_H, Δσ_v full-tensor from Geertsma 2-D Lamé inside/outside-disc (2×2 eigen decomposition per witness point)
  • SHmax azimuth rotation: eigenvector of the Δσ tensor; classifier bins info ≤ 5° / watch ≤ 15° / critical > 15°
  • Bench-aware E′ and α — layer-specific elastic and Biot coefficients
  • Optional convective transport switch on the transient substepper
Assumptions
  • Linear-elastic layered response
  • Thermal patches are cylindrical disks per bench
  • No fully-coupled multiphase transport in the temperature equation
References
  • Geertsma (1973); Mindlin (1936) — layered extension
Model limitations
  • No fully-coupled multiphase mass + energy transport — energy uses a single-phase mixture.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Latent-heat effects at gas breakout / condensation change the cooling front velocity; a mixture cp under-predicts near-wellbore cooling and therefore under-predicts the σh reduction (and over-predicts breakdown pressure).
    When it breaks down:
    Wet-gas condensate wells, energized-fluid stimulations, and CO₂-flood injectors.
    Safer alternative:
    Anchor the modelled temperature to DTS fibre measurements when available; when not, add a conservative ±10 °F band to the cooling patch temperature and re-run the substepper.
  • Bench layers must be laterally continuous; pinch-outs are not resolved.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A pinch-out routes stress and heat around the discontinuity in ways the continuous-layer model cannot capture; SHmax rotation predictions become unreliable near the pinch.
    When it breaks down:
    Structurally-complex plays (Bakken erosional pinch-outs, Woodford channel margins) where a bench thins to zero within one lateral length.
    Safer alternative:
    Restrict the thermo-poro grid to laterally-continuous zones (trim to the bench isopach); for the pinch region, treat the poroelastic output as advisory only.
  • Cooling-credit hook into Pressure Advisor is opt-in per workspace.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    If cooling credit is off by default, the operator may over-design pad size because breakdown is calculated at the hotter, higher-σh state.
    When it breaks down:
    Re-entries, refracs, and pads with long shut-in prior to the next stage where the wellbore has genuinely cooled the near-well rock.
    Safer alternative:
    Turn on the cooling-credit toggle in the Pressure Advisor wizard for workspaces meeting the above criteria and record the choice in the audit log so reviewers can see the intent.

23.3 Phase-field DEM for laminated shale#

Physics model
Phase-field DEM laminated shale (primer)
Governing equations
  • AT-1 / AT-2 damage functional with irreversible history field
  • Cohesive Mode I / II traction-separation on bedding interfaces
  • He-Hutchinson kink/pierce classifier + MTS kink-angle criterion
  • σ_h degradation hook into the existing Geertsma engine
Assumptions
  • Small strain; damage is a scalar phase field per element
  • Bedding interfaces are pre-known (input from log picks)
Model limitations
  • Primer only — not yet wired into the main propagation solver. Available as a standalone pure library and 10-test drift-guard.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    An unwired primer means the operator will not automatically get phase-field predictions during a run; a laminated shale with strong bedding contrast may be modelled by the default DDM solver that does not resolve bedding-plane deflection.
    When it breaks down:
    Vaca Muerta / Utica / deep Bakken designs where bedding-plane fractures are the dominant failure mode.
    Safer alternative:
    Call `phaseFieldDemLaminatedShale.ts` directly (or use the /roadmap card) as an offline check; if kink/pierce classifier disagrees with the main solver, treat the design as high-uncertainty and pilot a small stage before scaling.
  • No dynamic loading; quasi-static.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Dynamic (rate-dependent) fracture toughness matters for high-injection-rate breakdown; a quasi-static run under-predicts breakdown pressure and can steer the design toward too little pad or excess perforation.
    When it breaks down:
    Very-high-rate step-rate tests and breakdown events at rates > 60 bpm on a single cluster.
    Safer alternative:
    Add a conservative dynamic-K correction factor (~1.2-1.5×) to the K_IC input, or bracket the run at the higher K_IC and honour the higher breakdown pressure.

23.4 Compositional 3-phase black-oil with energized CO₂#

Depth profile
Field (psi, ft, °F)
Pressure Advisor — depth-pressure envelope
0.02,0004,0006,0008,0000.02,0004,0006,0008,00010,000Pressure [psi]TVD [ft]
  • Hydrostatic (10.5 ppg)
  • Pore pressure
  • Frac gradient (0.78 psi/ft)
Mud weight sits above pore pressure and below frac gradient at every depth — the ECD margin the wizard reports.
Physics model
Compositional 3-phase black-oil (IMPES)
Governing equations
  • Peng-Robinson EoS for the gas phase; energized-CO₂ FVF bridge overrides B_g when the workspace flag is on
  • Water / oil / gas conservation with Sw + So + Sg = 1 and Swc floor
  • IMPES pressure solve followed by explicit saturation update
Assumptions
  • IMPES splitting — pressure is fully-implicit, saturations explicit
  • Rel-perm from Corey / LET / Stone II (see section 5)
  • Capillary pressure via Brooks-Corey or Skjæveland
Model limitations
  • IMPES — capillary-dominated timesteps may require dt reduction. Fully-implicit is roadmap.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    IMPES can silently overshoot saturations at coarse dt while pressure stays stable; the saturation map looks smooth but the front position is wrong.
    When it breaks down:
    Ultra-low-permeability chalks, tight-gas at high P_c, and imbibition-dominated flowback.
    Safer alternative:
    Enable the Phase-9 substepper with targetP ~ 100 psi and targetT ~ 5 °F, and cross-check the front against the buckleyLeverett kernel-parity comparator before decisions.
  • PR-EOS tuning ships as presets for 6 plays; custom tuning is user-supplied.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Off-preset plays run with generic EoS parameters; predicted CGR/GOR and phase envelope can be biased by tens of percent.
    When it breaks down:
    New plays, high-GOR volatile-oil systems, and any well with unusual composition (H2S, N2, high-CO2).
    Safer alternative:
    Tune PR-EOS binary interaction parameters against a lab PVT report before running the compositional module; when no PVT exists, run both the black-oil and compositional branches and treat the spread as the uncertainty.
  • Energized-CO₂ bridge assumes a well-mixed injection stream; slug injection is not resolved.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Slug injection produces alternating dense/gas phases downhole; a well-mixed assumption smooths the pressure/temperature signal and can miss transient breakdown windows.
    When it breaks down:
    Foamed / energized frac designs pumped without a static mixer, and any operation where CO2 is trucked into a small blender.
    Safer alternative:
    Design for a well-mixed stream at the wellhead (static mixer + minimum residence time); if slug injection is unavoidable, treat model predictions as advisory only and rely on live BHP for decisions.

23.5 Adaptive coupled-transient substepper (Phase 9)#

Physics model
Coupled transient substepper
Governing equations
  • PI control on r = max(|ΔP|∞ / target_P, |ΔT|∞ / target_T)
  • Reject + halve dt when r > 1 down to dt_min (then forced-accept with clampedAtMin flag)
  • Grow dt × accept_grow when r ≤ accept_lo; hold otherwise
Assumptions
  • Midpoint evaluation for time-varying source / boundary condition callbacks
  • Never overshoots the window end (dt clipped to endDay − t)
Model limitations
  • Below dt_min the substepper force-accepts and sets clampedAtMin = true — downstream code MUST check the flag.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A force-accepted step means the reported ΔP/ΔT exceeded the target and the solver ran anyway; ignoring the flag lets a stiff transient contaminate every downstream result derived from that step.
    When it breaks down:
    Sharp source/BC transitions (well shut-in, rate step > 40 bpm within one second) and any run where dt_min was set aggressively low to keep total step count down.
    Safer alternative:
    Inspect the SubstepRecord list — any entry with clampedAtMin:true should either raise dt_min, tighten the source ramp, or be treated as high-uncertainty; the /solver-spec traceability row lists the exact check.
  • PI gains are fixed; adaptive gain scheduling is roadmap.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Fixed PI gains work well on smooth transients but can chatter (repeated reject/accept) on stiff systems, wasting wall-clock time and inflating step counts in the audit log.
    When it breaks down:
    Coupled thermo-poro runs with a sudden temperature perturbation, or when the pressure kernel is well-behaved but the temperature kernel is stiff.
    Safer alternative:
    Bracket a run with two targetT values (e.g. 5 and 20 °F) and if step counts differ by more than 3× the transient is stiff — split it into two windows with different targetT settings.

23.6 Heterogeneity → propagation coupling#

The Gaussian random-field multiplier on K_IC, σ_h, k, and φ (route /heterogeneity) feeds the fracture propagation solver directly. On each tip-advance, the local field value is sampled at the tip location, multiplied against the base property, and used in the next Griffith / Perkins criterion. This closes the gap the round-2 review flagged ('heterogeneity overlay exists but not coupled to main propagation solver').

Model limitations
  • Field is generated per-workspace and per-seed; two workspaces with the same seed will produce identical fields.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Identical seeds mean that comparing 'independent' workspaces can produce artificial agreement; a reviewer may read this as convergent evidence when it is actually the same random draw.
    When it breaks down:
    Any comparison across workspaces meant to demonstrate robustness (e.g. before/after a design change on two pads).
    Safer alternative:
    Always vary the seed across workspaces intended as independent samples; for Monte-Carlo studies use the P10/P50/P90 bundle so the seed dependence is bracketed explicitly.
  • Anisotropy is diagonal (Lx, Ly, Lz correlation lengths) — no oblique correlation tensor.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A diagonal correlation tensor cannot represent geologic fabric aligned obliquely to the grid axes; predicted stress heterogeneity is biased along the grid direction.
    When it breaks down:
    Plays with rotated fracture fabric (Wolfcamp SHmax rotates across the section) or when the lateral azimuth is not aligned with a principal correlation axis.
    Safer alternative:
    Rotate the grid to align with the dominant correlation axis before generating the field, or bracket the run with two Lx/Ly swaps and treat the spread as the uncertainty band.

23.7 Multi-well interference (consolidated)#

Depth profile
Field (psi, ft, °F)
Parent-child interference — depletion window
0.01,0002,0003,0004,0005,0006,0000.02,0004,0006,0008,00010,000Pressure [psi]TVD [ft]Reservoir topReservoir base
  • Pore pressure (original)
  • Pore pressure (depleted parent)
Δp_∞ = 1,800 psi drawn down over the parent's producing interval; the poroelastic engine turns this into Δσ_h at the child.

Four routes cover the parent-child interference story end-to-end: (a) /parent-child — log-radial Δp + Eaton Δσ_h + asymmetry; (b) stress-shadow overlay — Sneddon Δσ from sibling wells; (c) poroelastic depletion — full-tensor Δσ_h / Δσ_H + SHmax rotation; (d) Mindlin 3-D bench — layered vertical attenuation. All four share the same PoroelasticResult shape so a per-stage table row lists every contribution side-by-side. Runtime SHmax → child-fracture geometry loop is documented under (M2) of the thermo-poro parity bridge.

Model limitations
  • Poroelastic engine assumes cylindrical depleted zones per parent — irregular drainage is approximated by ellipse fits.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Real drainage shapes follow reservoir heterogeneity and completion quality, not perfect discs; SHmax rotation predictions can be under-estimated at the elongated tips of the true drainage cell.
    When it breaks down:
    Producers with strongly-heterogeneous completions (uneven cluster efficiency), or where microseismic shows a clearly non-circular drainage footprint.
    Safer alternative:
    Ingest a microseismic catalog via the /parent-child route and fit the drainage radius per-parent from event distances (fitDrainageRadiusFromMS) before running the poroelastic step.
  • Mindlin 3-D bench requires laterally continuous benches.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    The depth factor derivation assumes continuous benches; near a pinch-out the vertical attenuation is off, and infill stages at that TVD may see stronger or weaker rotation than predicted.
    When it breaks down:
    Any child stage TVD within one bench thickness of a pinch or unconformity.
    Safer alternative:
    Trim the analysis area to the continuous-bench region; for stages inside the pinch zone treat the SHmax rotation as an envelope and pilot the design before scaling.
  • Frac-hit volumetrics is a swept-ellipse capture × depletion-attraction estimator — it does not solve conservative transport per-cluster.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A swept-ellipse estimator gives a bulk mass at each parent but not the per-cluster breakdown a completions engineer needs to decide diverter timing.
    When it breaks down:
    Long laterals with variable cluster efficiency, or when a specific cluster is suspected of being the frac-hit source.
    Safer alternative:
    Use DAS/DTS cluster-flow inversion (dasClusterGeometryInversion.ts) to allocate the frac-hit mass to individual clusters, then feed those per-cluster masses into the volumetric estimator.

23.8 Rate-and-state friction + induced-seismicity traffic light#

Physics model
Rate-and-state friction (Dieterich-Ruina)
Governing equations
  • μ(V, θ) = μ₀ + a·ln(V/V*) + b·ln(V*·θ / D_c)
  • Slip-law state evolution: dθ/dt = 1 − V·θ / D_c
  • Critical stiffness k_c = σ_n·(b − a) / D_c; nucleation length L_c ≈ 2·G·D_c / (σ_n·(b − a))
  • Stability classifier: strengthening (a > b) / conditionally-stable / unstable (k < k_c)
Assumptions
  • Quasi-static spring-slider on a single fault patch
  • Optional pore-pressure perturbation p(t) for injection ramps
Model limitations
  • Single-fault only — multi-fault interaction is roadmap.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Cascading events on conjugate faults are the dominant mechanism behind almost every M ≥ 3 induced event; a single-patch simulation cannot see the cascade.
    When it breaks down:
    Basins with mapped critically-stressed conjugate faults (SCOOP/STACK, Fox Creek Duvernay, Sichuan, W-Texas basement structures).
    Safer alternative:
    Run an external multi-fault Coulomb-stress transfer study alongside the single-patch RSF result; if the transfer study lights up an adjacent fault, treat the pad as high-risk regardless of what the RSF traffic light shows.
  • Quasi-static; no elastodynamic radiation.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Radiation damping matters for the transition from stable nucleation to dynamic runaway; a quasi-static solver only classifies the nucleation regime, not the eventual magnitude.
    When it breaks down:
    Any operating scenario approaching the unstable regime (k < k_c) — the model correctly flags nucleation but cannot predict M.
    Safer alternative:
    Treat a red RSF traffic light as a hard stop, not a magnitude prediction; escalate to a dynamic rupture code or, more practically, back off injection immediately.
  • The traffic light aggregates model output with local regulator thresholds — always cross-check against the local induced-seismicity protocol.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Regulatory thresholds vary by jurisdiction and can change mid-project; a stale threshold in the model can hide a real regulatory breach.
    When it breaks down:
    Any operation crossing a regulatory boundary (state / province / OGA area) and any pad older than 12 months without a threshold-update audit.
    Safer alternative:
    Verify the local traffic-light thresholds with the regulator before every campaign and update the workspace parameters; log the source and date of the threshold in the audit log.

23.9 What this chapter does NOT cover#

  • 3-D viewer improvements (cross-section slice, HUD read-out, playback contour, propagation trails, kink-node dots, NF-activation flash, tip-velocity bloom scale) — tracked in the roadmap at /roadmap?phase=viz and cross-checked against `.lovable/plan.md` §1/§4. Every item there is either LIVE or has a named owning file.
  • Results-tab completeness pass (ISIP marker, closure-pressure reference line, fluid-efficiency, half-length / height vs. time) — tracked in /roadmap?phase=viz under the Results-tab lane.
  • AI chatbot integration — separate product decision, not a physics module; status at /roadmap?phase=polish.
  • Full A-to-Z gap list (all series, both shipped and in-flight) is at /roadmap.

24. Numerical-method background & specialty material inputs

Plain-English tour of the assumptions, discretization schemes, and unit conventions that every solver in Wellbore Genius shares — followed by a per-preset explanation of how sodium nitrate, flour/epoxy diverter, and black-powder residue inputs feed the equations (and where they intentionally do NOT).

This chapter answers three questions engineers keep asking during reviews: (1) what assumptions does the kernel actually make; (2) how are the PDEs discretized in space and time; (3) how are field-unit inputs (ppg, psi, bbl/min, °F) converted before they reach the solver. The last section walks through the three specialty material presets (sodium nitrate, flour/epoxy, black-powder residue) and shows the exact line of physics each one changes.

24.1 Governing assumptions (what every solver takes for granted)#

  • Linear poroelasticity with Biot coefficient α ∈ [0, 1]; effective stress σ' = σ − α·p_p. Non-linear (plastic) response is layered in via Mohr-Coulomb yield only where explicitly enabled (mud-window solver, rate-and-state fault).
  • Isothermal single-phase flow unless a module states otherwise. Thermal coupling is opt-in per module (thermo-poro 3-D, live-auto-HM thermal effect, DFIT temperature-dependent viscosity).
  • Newtonian fluid rheology by default. Non-Newtonian branches (Carreau-Yasuda, Herschel-Bulkley, Maxwell modes) are explicit user choices and are byte-identical to Newtonian when their extra parameters collapse (n=1, τ_y=0, no modes).
  • Rock is treated as a continuum at the grid scale; discrete fracture networks (DFNs) are represented as graph elements, NOT as embedded XFEM enrichments. The frac solver couples DDM tips to a graph dispatcher (see /solver-spec).
  • Gravity is vertical (−ẑ). Deviated / horizontal wells project weight onto the wellbore-axial direction inside the mud-window and hydrostatic solvers.
  • All comparators run on the pure physics module. UI-level wiring is verified separately by Playwright drift-guards, not by the analytical tests.

24.2 Discretization — what scheme is used where#

The kernel is a mix of analytical, semi-analytical, and numerical solvers. The tables below say which method is used for which module so a reviewer can jump straight to the right drift-guard.

∂p/∂t = (k/(φ·μ·c_t))·∇²p
Radial pressure diffusivity — the base equation for line-source (Theis) and Peaceman-well transient flow.
Used in
Cross-well tomography (crossWellTomography.ts)
Parent-child pressure interference (parentChildInterference.ts)
Injector transient (Peaceman well index; IMPES kernel)
Where
  • p — pore pressure [Pa]
  • k — permeability [m²]
  • φ — porosity [-]
  • μ — viscosity [Pa·s]
  • c_t — total compressibility [1/Pa]
Assumptions
  • Line-source superposition (Theis) valid when r_w ≪ r; for r ~ r_w the Peaceman well index is used.
  • Piecewise-constant permeability inside each grid cell; contrasts resolved via harmonic averaging on cell faces.
Validity range
Radial / axisymmetric flow. Horizontal-well contributions are captured via superposition, not a full 3-D pressure kernel.
Units: SI internal; UI inputs converted at the module boundary.
S·∂p/∂t + ∇·(−(k/μ)·∇p) = q(x,t)
Cell-centred finite-volume pressure PDE — 2-pt flux + TVD saturations, marched with IMPES / backward-Euler.
Used in
Compositional 3-phase black-oil (compositionalBlackOil3P.ts)
Buckley-Leverett kernel-parity comparator
Thermo-poro 3-D (stepThermoPoro3D.ts, split with energy)
Where
  • S — storage coefficient [1/Pa]
  • q(x,t) — volumetric source [1/s]
  • k, μ — as above
Assumptions
  • Two-point flux approximation (TPFA) with upwind mobilities on faces for stability.
  • IMPES time-splitting: pressure implicit, saturations explicit with a TVD (van Leer) limiter — locked by buckleyLeverettKernelParity.test.ts.
  • Capillary-dominated regimes may require dt reduction; the Phase-9 substepper caps this automatically.
Validity range
Grid Peclet ≲ 2 for the TVD branch; above that the substepper trips a warning and halves dt.
Units: SI internal.
w(x)·(p_net − σ_h(x)) coupled to ∫ G(x,x')·w(x') dx' = f(x)
Displacement-discontinuity (DDM) tip system used by the non-planar 3D fracture solver and every derived shadow / depletion module.
Used in
Non-planar 3D fracture solver
Sneddon shadow / poroelastic depletion (poroelasticDepletion.ts)
Child-fracture geometry coupling
Where
  • w(x) — fracture aperture [m]
  • p_net — net pressure inside the fracture [Pa]
  • σ_h(x) — in-situ minimum horizontal stress [Pa]
  • G(x,x') — elastic influence function (Kelvin fundamental solution)
Assumptions
  • DDM tip elements in an infinite elastic medium; layered benches modelled via Mindlin 3-D depth factor (a/√(a²+Δz²))^(3/2)·min(1,h/a).
  • Element size clamped by the non-planar 3D config; kink angle limited by user-set max (default 45°).
Validity range
Aspect ratio h/L ∈ [0.05, 20]; outside this band the tip singularity is under-resolved and the run flags a warning.
Units: SI internal; aperture reported to UI in inches.
Δt_{n+1} = Δt_n · clip(√(ε_tol / r_n), 0.5, 2.0)
PI-flavoured adaptive substepping used by the coupled transient stimulation solver (Phase 9).
Used in
Coupled transient stimulation substepper (coupledTransientSubstepper.ts)
Where
  • r_n = max(|ΔP|∞/targetP, |ΔT|∞/targetT) — normalised local error
  • ε_tol — user-set tolerance (default 1.0)
  • Δt clamped to [dtMin, dtMax]
Assumptions
  • Steps with r_n > 1 are rejected and dt is halved; steps with r_n ≤ acceptLo grow by acceptGrow (default 1.4×).
  • Forced acceptance at dtMin sets clampedAtMin:true on the substep record for post-hoc audit.
  • Time-varying sources and BCs evaluated at the midpoint of each substep (2nd-order in time for smooth forcing).
Validity range
Pressure + temperature coupling. Not used by the analytical Theis / Nordgren PKN early-time paths.
Units: dt in seconds; targetP / targetT in the module's native units.
V_{n+1/2} = V_n · exp(−(1 − f)·Δτ)
Dieterich-Ruina quasi-static slip-law update used by the rate-and-state friction module.
Used in
Rate-and-state friction (rateStateFriction.ts)
Where
  • V — slip rate [m/s]
  • f — friction coefficient [-]
  • Δτ — normalised time step
Assumptions
  • Single fault patch, spring-slider, quasi-static (no inertia term).
  • Explicit Euler on log(V) — well-suited when V·Δt/L_c ≲ 10⁻².
  • Optional pore-pressure perturbation p_p(t) callback for injection ramps; slip-law state θ integrated on the aging law.
Validity range
Nucleation regime (pre-runaway). Full dynamic slip / radiation is out of scope; see /solver-spec Rate-and-state row.
Units: SI internal.

24.3 Unit conventions (field-first, converted at the boundary)#

Every UI input is field-unit. Conversions happen at exactly one place per module (the `*ToSi` helper) so a reviewer can grep for the boundary. The kernel itself is SI internally except where an industry-standard equation is more legible in field units (e.g. 0.052·ρ·TVD for hydrostatic pressure).

QuantityField unitSI unitConversion / formula
Depth / lengthftm× 0.3048
PressurepsiPa× 6 894.757
Mud weightppgkg/m³× 119.826
Hydrostatic p_h (short form)psi= 0.052 · ρ[ppg] · TVD[ft]
Ratebpmm³/s× 0.002 649
Volumebbl× 0.158 987
ViscositycpPa·s× 0.001
Permeabilitymd× 9.869 233 × 10⁻¹⁶
Temperature°FK= (°F + 459.67) / 1.8
Gas rateMscf/dsm³/s× 3.277 × 10⁻⁴ (60 °F, 14.696 psi)
Mass loadingppm (mass)kg/kg× 10⁻⁶
Missing numerics render as em-dash — never zero
Both UI (formatNumeric / NumericValue) and CSV/LAS exports (formatCsvCell / CSV_DASH) emit `—` for unknown values. This is not cosmetic: it prevents a missing input from being silently treated as 0 psi / 0 bpm / 0 md by downstream solvers or plots.

24.4 Specialty material inputs (how each preset feeds the kernel)#

The three material presets (sodium nitrate, flour/epoxy diverter, black-powder residue tracer) are solute-only. None of them injects energetic mass or exothermic chemistry into the kernel. Below is a preset-by-preset breakdown of what each input actually changes, what it does NOT change, and which drift-guards lock that behaviour.

24.4.1 Sodium nitrate (NaNO₃) — tracer / scale-control additive#

  • concPpm (50–5 000 ppm) → passive solute concentration on the fluid stream. Solver treats NaNO₃ as non-reactive: no Δρ correction beyond the linear brine-density hook, no exothermic source term, no Ksp check.
  • fluidTempF (60–250 °F) → clipped into the μ(T) look-up used by the live-auto-HM thermal effect. Outside the band the preset gate refuses to accept the input.
  • bottomholePsi (1 000–12 000 psi) → informational; validates the requested envelope against the tracer band.
  • mudWeightPpg (8.3–14 ppg) → routed through the standard hydrostatic hook 0.052·ρ·TVD; there is NO separate oxidiser-loading branch.
  • What it does NOT do: no combustion, no radical chemistry, no automatic coupling to the scaling-kinetics module (scalingKinetics.ts) unless the operator opts in via the Water solutes panel.

24.4.2 Flour / epoxy diverter — degradable mechanical diverter#

  • concPpm (100–20 000 ppm) → inert-solid mass loading. Feeds the effective slurry density used by slurryHydrostatic.ts and the friction-factor bump in livePumping.ts.
  • fluidTempF (70–200 °F) → gates the epoxy-cure window; outside this band the acknowledgement checkbox is disabled.
  • bottomholePsi (1 500–11 000 psi) → informational; validates the diversion-mechanics envelope.
  • mudWeightPpg (8.3–13 ppg) → hydrostatic scaling only. Heavier muds outside the band trigger a realism warning because the diverter washes through perforations.
  • What it does NOT do: no degradation kinetics, no time-dependent plug strength, no coupling to the perforation-erosion model. The diverter is a constant inert loading for the duration of the stage.

24.4.4 Sensitivity callouts — how small input swings move the depth-profile outputs#

The callouts below apply a ±10% perturbation to each preset input and report the resulting change in the hydrostatic column, geotherm, or bottomhole-pressure envelope at a 10,000 ft TVD reference. Values are computed by `materialPresetSensitivity.ts` and rendered from the same evaluators the depth-profile charts use, so the sweep is byte-consistent with the visualization examples in Section 24.3.

Sodium nitrate (NaNO₃) — input sensitivity

±10% swing on each preset input, evaluated at 10,000 ft TVD. Depth curves below trace the dominant knob across the full profile.

Preset: sodium-nitrate
  • Concentration [ppm] → Hydrostatic P_h [psi]Negligible

    A ±10% swing on concentration [ppm] produces no measurable change in Hydrostatic P_h at 10,000 ft TVD — chasing this input on the depth-profile is noise.

    baseline=4941.48 · +Δ=4941.63 · −Δ=4941.33 · |ΔOut|=0.15 psi

  • Fluid temperature [°F] → Temperature T(z) [°F]Dominant

    A ±10% swing on fluid temperature [°F] shifts Temperature T(z) by ≈ 12 °F at 10,000 ft TVD — large depth-profile impact; keep the entered value inside the [60, 250] °F envelope.

    baseline=280.00 · +Δ=292.00 · −Δ=268.00 · |ΔOut|=12.00 °F

  • Bottomhole pressure [psi] → Bottomhole pressure [psi]Dominant

    A ±10% swing on bottomhole pressure [psi] shifts Bottomhole pressure by ≈ 500 psi at 10,000 ft TVD — large depth-profile impact; keep the entered value inside the [1000, 12000] psi envelope.

    baseline=5000.00 · +Δ=5500.00 · −Δ=4500.00 · |ΔOut|=500.00 psi

  • Mud weight [ppg] → Hydrostatic P_h [psi]Dominant

    A ±10% swing on mud weight [ppg] shifts Hydrostatic P_h by ≈ 494 psi at 10,000 ft TVD — large depth-profile impact; keep the entered value inside the [8.3, 14] ppg envelope.

    baseline=4941.48 · +Δ=5435.63 · −Δ=4447.33 · |ΔOut|=494.15 psi

Depth profile
Field (psi, ft, °F)
Sodium nitrate (NaNO₃) — Bottomhole pressure sensitivity to ±10% bottomhole pressure
0.01,0002,0003,0004,0005,0000.02,0004,0006,0008,00010,000Bottomhole pressure [psi]TVD [ft]Ref TVD 10,000 ft
  • Baseline
  • +10% Bottomhole pressure
  • −10% Bottomhole pressure
Baseline uses preset defaults (Bottomhole pressure = 5000 psi). The ± bands show how a 10% swing on the dominant input propagates into Bottomhole pressure across depth.

Flour / epoxy diverter — input sensitivity

±10% swing on each preset input, evaluated at 10,000 ft TVD. Depth curves below trace the dominant knob across the full profile.

Preset: flour-epoxy
  • Mass loading [ppm] → Hydrostatic P_h [psi]Negligible

    A ±10% swing on mass loading [ppm] produces no measurable change in Hydrostatic P_h at 10,000 ft TVD — chasing this input on the depth-profile is noise.

    baseline=4687.02 · +Δ=4687.72 · −Δ=4686.32 · |ΔOut|=0.70 psi

  • Fluid temperature [°F] → Temperature T(z) [°F]Dominant

    A ±10% swing on fluid temperature [°F] shifts Temperature T(z) by ≈ 11 °F at 10,000 ft TVD — large depth-profile impact; keep the entered value inside the [70, 200] °F envelope.

    baseline=270.00 · +Δ=281.00 · −Δ=259.00 · |ΔOut|=11.00 °F

  • Bottomhole pressure [psi] → Bottomhole pressure [psi]Dominant

    A ±10% swing on bottomhole pressure [psi] shifts Bottomhole pressure by ≈ 450 psi at 10,000 ft TVD — large depth-profile impact; keep the entered value inside the [1500, 11000] psi envelope.

    baseline=4500.00 · +Δ=4950.00 · −Δ=4050.00 · |ΔOut|=450.00 psi

  • Mud weight [ppg] → Hydrostatic P_h [psi]Dominant

    A ±10% swing on mud weight [ppg] shifts Hydrostatic P_h by ≈ 469 psi at 10,000 ft TVD — large depth-profile impact; keep the entered value inside the [8.3, 13] ppg envelope.

    baseline=4687.02 · +Δ=5155.72 · −Δ=4218.32 · |ΔOut|=468.70 psi

Depth profile
Field (psi, ft, °F)
Flour / epoxy diverter — Hydrostatic P_h sensitivity to ±10% mud weight
0.01,0002,0003,0004,0005,0000.02,0004,0006,0008,00010,000Hydrostatic P_h [psi]TVD [ft]Ref TVD 10,000 ft
  • Baseline
  • +10% Mud weight
  • −10% Mud weight
Baseline uses preset defaults (Mud weight = 9 ppg). The ± bands show how a 10% swing on the dominant input propagates into Hydrostatic P_h across depth.

Black powder residue tracer — input sensitivity

±10% swing on each preset input, evaluated at 10,000 ft TVD. Depth curves below trace the dominant knob across the full profile.

Preset: black-powder
  • Residue marker conc. [ppm] → Hydrostatic P_h [psi]Negligible

    A ±10% swing on residue marker conc. [ppm] produces no measurable change in Hydrostatic P_h at 10,000 ft TVD — chasing this input on the depth-profile is noise.

    baseline=5200.08 · +Δ=5200.09 · −Δ=5200.07 · |ΔOut|=0.01 psi

  • Fluid temperature [°F] → Temperature T(z) [°F]Dominant

    A ±10% swing on fluid temperature [°F] shifts Temperature T(z) by ≈ 15 °F at 10,000 ft TVD — large depth-profile impact; keep the entered value inside the [60, 300] °F envelope.

    baseline=310.00 · +Δ=325.00 · −Δ=295.00 · |ΔOut|=15.00 °F

  • Bottomhole pressure [psi] → Bottomhole pressure [psi]Dominant

    A ±10% swing on bottomhole pressure [psi] shifts Bottomhole pressure by ≈ 600 psi at 10,000 ft TVD — large depth-profile impact; keep the entered value inside the [1000, 14000] psi envelope.

    baseline=6000.00 · +Δ=6600.00 · −Δ=5400.00 · |ΔOut|=600.00 psi

  • Mud weight [ppg] → Hydrostatic P_h [psi]Dominant

    A ±10% swing on mud weight [ppg] shifts Hydrostatic P_h by ≈ 520 psi at 10,000 ft TVD — large depth-profile impact; keep the entered value inside the [8.3, 15] ppg envelope.

    baseline=5200.08 · +Δ=5720.09 · −Δ=4680.07 · |ΔOut|=520.01 psi

Depth profile
Field (psi, ft, °F)
Black powder residue tracer — Bottomhole pressure sensitivity to ±10% bottomhole pressure
0.01,0002,0003,0004,0005,0006,0000.02,0004,0006,0008,00010,000Bottomhole pressure [psi]TVD [ft]Ref TVD 10,000 ft
  • Baseline
  • +10% Bottomhole pressure
  • −10% Bottomhole pressure
Baseline uses preset defaults (Bottomhole pressure = 6000 psi). The ± bands show how a 10% swing on the dominant input propagates into Bottomhole pressure across depth.

24.4.3 Black-powder residue tracer — passive post-perforating marker#

  • concPpm (1–250 ppm) → passive marker concentration only. The preset explicitly refuses to accept energetic-mass inputs; live-charge sizing must be done by the perforating provider outside this app.
  • fluidTempF (60–300 °F) → routed through the same μ(T) look-up as the other tracer.
  • bottomholePsi (1 000–14 000 psi) → informational; captures the typical perforating BHP envelope.
  • mudWeightPpg (8.3–15 ppg) → hydrostatic scaling only.
  • What it does NOT do: no pyrotechnic chemistry, no detonation-shock coupling into the DDM tip solver, no coupling to the microseismic moment-tensor engine. The marker is thermally and mechanically inert in the kernel.
Three gates before any preset value reaches the kernel
Every material preset is guarded by (1) a workspace-level feature flag (off by default, `downhole.materialPresets.v1`), (2) an out-of-range envelope check against the ranges above, and (3) an operator acknowledgement checkbox that is written to the audit log with the applied values and timestamp. If any gate fails the run does not start.

24.5 Hard limitations of this chapter#

Model limitations
  • Discretization scheme summaries are indicative — the authoritative source is the drift-guard file listed under each equation's `usedIn` field.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A summary can drift out-of-sync with the code between manual revisions; trusting the manual over the test lets a stale claim mislead a reviewer.
    When it breaks down:
    After any physics PR that changes numerics but not the manual body (common when the change is a small numerical tolerance).
    Safer alternative:
    Grep the referenced test file before quoting a discretization detail in an audit; if the test disagrees with the manual, file a documentation bug and treat the test as authoritative.
  • Unit-conversion factors above match ANSI/API 2564; small rounding differences vs. metric-first tools (Eclipse-EU, tNavigator) are within the ±0.05 % band.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A 0.05 % rounding difference compounds across a large well count; a portfolio calculation done half in field units and half in SI can drift by a full percent by the end.
    When it breaks down:
    Cross-tool workflows (Eclipse output → this app for post-processing, or vice-versa) and multi-well portfolio totals.
    Safer alternative:
    Do all conversions at one boundary and keep the entire downstream chain in one unit system; use the CSV export helpers so the boundary is auditable.
  • The three material presets model solute loading only. Any request to model exothermic chemistry, degradation kinetics, or pyrotechnic charges is intentionally out of scope and will be rejected by the preset gate.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A user asking for exothermic / pyrotechnic modelling wants an answer the app cannot safely provide; silently accepting the input risks a design that under-estimates hazards.
    When it breaks down:
    Any operator input requesting energetic-mass or oxidiser sizing directly in the material preset envelope.
    Safer alternative:
    Route the request to the perforating / stimulation vendor's dedicated tool; use this app only for the passive-tracer / diverter modelling scope described in the preset.
  • Non-Newtonian rheology branches collapse to Newtonian when their extra parameters are omitted; verify with the byte-identical drift-guards before assuming a run used the extended model.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Two runs can appear to be 'the same' because the UI shows the same numbers, but a hidden non-Newtonian branch flag can be on/off and materially change the pressure envelope.
    When it breaks down:
    Comparing runs across workspaces or across app versions where the rheology default may have moved.
    Safer alternative:
    Read the run's audit log for the actual rheology branch used; if the byte-identical drift-guard did not fire on both runs, treat them as different runs and re-baseline.

25. Worked verification case studies (equations → expected outputs)

Five hand-workable case studies that pin each headline equation to a numerical expected output and to the exact drift-guard test that locks it. Every case is byte-reproducible: plug the inputs into the formula, get the expected value, then grep the referenced test file to see the same numbers asserted in CI.

These cases are deliberately small so a reviewer can rework them in a spreadsheet in under two minutes. Each case cites (a) the manual equation number from Chapter 24, (b) the traceability item from Chapter 22 (model verification) or Chapter 23 (recent physics), and (c) the exact drift-guard file under src/lib/__tests__/ that asserts the expected value.

25.1 Case A — Hydrostatic pressure (single-fluid column)#

p_h [psi] = 0.052 · ρ [ppg] · TVD [ft]
Field-unit short form of the hydrostatic pressure integral used everywhere in the app.
Used in
Pressure Advisor wizard (hydrostatic + surface-budget step)
slurryHydrostatic.ts — effective slurry density cascade
wellboreStabilityMudWindow.ts — mud-window floor / ceiling
Where
  • ρ — mud / slurry density [ppg]
  • TVD — true vertical depth [ft]
  • 0.052 — API conversion constant (= 1 / (144·8.3454))
Assumptions
  • Single-fluid column, no gas cut, no thermal expansion.
  • Vertical column; deviated paths project onto the TVD component before applying this equation.
Validity range
0 < ρ < 25 ppg, 0 < TVD < 25 000 ft.
Units: psi at the reference depth.
  1. Inputs: ρ = 9.8 ppg (water-based brine), TVD = 10 000 ft.
  2. Apply the equation: p_h = 0.052 · 9.8 · 10 000 = 5 096 psi.
  3. Cross-check the SI form: ρ_SI = 9.8 · 119.826 = 1 174.29 kg/m³; TVD_SI = 10 000 · 0.3048 = 3 048 m; p_h_SI = 1 174.29 · 9.80665 · 3 048 = 35 106 kPa = 5 091 psi (0.1 % rounding vs. the field short form — matches Chapter 24.3).
  4. Expected output: 5 096 psi at the bottom of the column.
  5. Traceability: equation 24.1 unit-conversion row (hydrostatic short form); asserted in src/lib/__tests__/slurryHydrostatic.test.ts and src/lib/__tests__/ballisticsWellHydrostatic.test.ts (same 0.052 constant, TVD-projected).

25.2 Case B — Theis line-source drawdown at a parent well#

Δp(r,t) = (q·μ) / (4·π·k·h) · W(u), u = r²·φ·μ·c_t / (4·k·t)
Classical Theis line-source solution used by cross-well tomography and parent-child interference.
Used in
parentChildInterference.ts — log-radial Δp at child stages
crossWellTomography.ts — Theis superposition + LM inversion
Where
  • q — volumetric injection rate [m³/s]
  • μ — fluid viscosity [Pa·s]
  • k — permeability [m²]
  • h — net thickness [m]
  • r — radial distance from source [m]
  • t — time since injection start [s]
  • φ — porosity [-], c_t — total compressibility [1/Pa]
  • W(u) — exponential integral (well function); for u ≪ 1, W(u) ≈ −γ − ln(u), γ = 0.5772
Assumptions
  • Line-source (r_w ≪ r), single-phase, isothermal.
  • Late-time / small-u branch (u ≲ 0.01) — the log-approximation is used in the analytical drift-guards.
Validity range
Radial / axisymmetric flow; horizontal-well contributions handled by superposition.
Units: Δp in Pa (convert to psi with ÷ 6 894.757 at the UI boundary).
  1. Inputs (SI): q = 0.01 m³/s, μ = 1e-3 Pa·s, k = 1e-13 m² (~ 100 md), h = 30 m, r = 500 m, t = 5 years = 1.577e8 s, φ = 0.10, c_t = 1e-9 1/Pa.
  2. Compute the u numerator: r²·φ·μ·c_t = 250 000 · 0.10 · 1e-3 · 1e-9 = 2.5e-8.
  3. Compute the u denominator: 4·k·t = 4 · 1e-13 · 1.577e8 = 6.308e-5.
  4. Combine: u = 2.5e-8 / 6.308e-5 = 3.964e-4 (i.e. u ≪ 1, deep in the late-time / log-approximation regime).
  5. Full W(u) via the Abramowitz-Stegun 5.1.11 series (matches expIntegralE1 in crossWellTomography.ts): W(u) = −γ − ln(u) − Σ_{n≥1} (−u)ⁿ / (n · n!). With u = 3.964e-4, ln(u) = −7.8339, so the leading term is −γ − ln(u) = −0.5772 + 7.8339 = 7.2567. The n=1 correction is −(−u)/1 = +u = 3.96e-4; n=2 is −u²/4 ≈ −3.9e-8; higher terms are < 1e-11. Sum: W(u) ≈ 7.2567 + 3.96e-4 ≈ 7.2571.
  6. Cross-check the small-u log branch: for u ≲ 0.01 the series collapses to W(u) ≈ −γ − ln(u), which reproduces 7.2567 within 0.01 % — this is the PASS branch the drift-guard exercises (no lookup table needed).
  7. Apply Theis: Δp = (q·μ) / (4·π·k·h) · W(u) = (0.01 · 1e-3) / (4·π · 1e-13 · 30) · 7.2571 = 1e-5 / 3.770e-11 · 7.2571 = 2.653e5 · 7.2571 = 1.925e6 Pa.
  8. Convert: Δp = 1.925e6 / 6 894.757 ≈ 279 psi.
  9. Expected output: ~279 psi drawdown at r = 500 m after 5 years — deep enough into the log branch that expIntegralE1(u) and the −γ − ln(u) shortcut agree to four decimals.
  10. Traceability: equation 24.1 (radial diffusivity); Chapter 23 recent-physics item for multi-well interference; expIntegralE1 in src/lib/crossWellTomography.ts; asserted in src/lib/__tests__/parentChildInterference.test.ts (Theis log-radial branch) and src/lib/__tests__/crossWellTomography.test.ts (Theis superposition).

25.3 Case C — Nordgren PKN half-length at late time#

L(t) ≈ 0.68 · ( E'·q³ / (μ·h⁴) )^{1/5} · t^{4/5}
Nordgren late-time asymptote for PKN half-length under constant injection.
Used in
analyticalFractureModels.ts — PKN reference curve
netPressureMatch.ts — modeled length envelope
Where
  • E' — plane-strain modulus = E / (1−ν²) [Pa]
  • q — one-wing injection rate [m³/s]
  • μ — fluid viscosity [Pa·s]
  • h — fracture height [m]
  • t — time since pump-start [s]
Assumptions
  • PKN geometry (h fixed, L grows), Newtonian fluid, no leakoff (Carter branch handled separately).
  • Late-time asymptote: t much larger than the toughness-dominated timescale.
Validity range
L / h ≳ 3; otherwise use KGD or radial (analyticalFractureModelsPowerLaw.test.ts).
Units: L in metres (convert to ft with × 3.281 at the UI boundary).
  1. Inputs: E = 30 GPa, ν = 0.25 → E' = 30e9 / (1 − 0.0625) = 32.0 GPa; q = 0.05 m³/s (~ 27 bpm one-wing); μ = 0.1 Pa·s (100 cp cross-linked gel); h = 30 m; t = 3 600 s (60 min pump time).
  2. Compute the group inside the fifth root: E'·q³/(μ·h⁴) = 32.0e9 · (0.05)³ / (0.1 · 30⁴) = 32.0e9 · 1.25e-4 / (0.1 · 810 000) = 4.00e6 / 81 000 = 49.4.
  3. Fifth root: 49.4^{1/5} = exp(ln(49.4)/5) = exp(3.90/5) = exp(0.780) = 2.181.
  4. Time factor: t^{4/5} = 3600^{0.8} = exp(0.8 · ln 3600) = exp(0.8 · 8.189) = exp(6.551) = 700.6.
  5. L = 0.68 · 2.181 · 700.6 ≈ 1 039 m ≈ 3 410 ft one-wing half-length.
  6. Expected output: ~1 040 m half-length at t = 60 min for the tuned Bakken-like inputs.
  7. Traceability: equation 24.4 (DDM tip system — Nordgren asymptote is the analytical envelope of the DDM solver); Chapter 22 model-verification item for the analytical PKN reference; asserted in src/lib/__tests__/analyticalFractureModels.test.ts.

25.4 Case D — Mud-window shear-failure floor (Kirsch + Mohr-Coulomb)#

p_w · (1 + q) ≥ 3·σ_H − σ_h − UCS − α·p_p·(1 − q), q = (1 + sin φ)/(1 − sin φ)
Closed-form Kirsch + Mohr-Coulomb breakout floor for a vertical borehole (from wellboreStabilityMudWindow.ts).
Used in
wellboreStabilityMudWindow.ts — computeMudWindow floor
Where
  • p_w — wellbore pressure at the section [psi]
  • σ_H, σ_h — max / min horizontal stress [psi]
  • UCS — unconfined compressive strength [psi]
  • φ — friction angle [rad]; q — the associated shear multiplier
  • α — Biot coefficient [-], p_p — pore pressure [psi]
Assumptions
  • Vertical borehole. Deviated paths route through wellboreStabilityMudWindowDeviated.ts with a first-crossing scan (see Chapter 22 verification note).
  • Linear Mohr-Coulomb yield; no strain-softening.
Validity range
Elastic pre-yield regime; when the LHS < RHS the run reports a critical breakout risk.
Units: psi in, psi out (native field units for this equation).
  1. Inputs: σ_H = 10 000 psi, σ_h = 7 500 psi, UCS = 4 000 psi, φ = 30° → sin φ = 0.5, q = 1.5 / 0.5 = 3.0. α = 0.8, p_p = 4 500 psi.
  2. Right-hand side: 3·σ_H − σ_h − UCS − α·p_p·(1 − q) = 30 000 − 7 500 − 4 000 − 0.8·4 500·(1 − 3) = 30 000 − 7 500 − 4 000 + 7 200 = 25 700 psi.
  3. Solve for the minimum p_w: p_w ≥ 25 700 / (1 + q) = 25 700 / 4 = 6 425 psi.
  4. Convert to a mud weight at TVD = 10 000 ft: ρ_min = p_w / (0.052 · TVD) = 6 425 / 520 = 12.36 ppg. Anything below 12.36 ppg triggers the shear-failure floor.
  5. Expected output: floor mud weight ≈ 12.36 ppg at 10 000 ft TVD for these stress inputs.
  6. Traceability: equation 24.5 (mud-window solver); Chapter 22 verification item for the deviated first-crossing scan; asserted in src/lib/__tests__/wellboreStabilityMudWindow.test.ts (vertical closed form) and src/lib/__tests__/wellboreStabilityMudWindowDeviated.test.ts (high-p_w regression + first-crossing scan added in this round).

25.5 Case E — Arps hyperbolic decline EUR#

q(t) = q_i · (1 + b·D_i·t)^{−1/b}, EUR = q_i / ((1 − b)·D_i) · [1 − (q_ab/q_i)^{1−b}]
Arps hyperbolic decline (0 < b < 1) with terminal cutoff to a minimum rate q_ab.
Used in
arpsDca.ts — DCA fit + EUR
typeCurveCatalog.ts — regional type curves
/economics — EUR-uplift cascade to /refrac
Where
  • q_i — initial rate [bbl/d or Mscf/d]
  • D_i — initial nominal decline [1/yr]
  • b — Arps exponent [-]; b→0 exponential, b=1 harmonic
  • q_ab — economic abandonment rate [same units as q_i]
Assumptions
  • Single-well, single-phase, no interference (interference handled separately by parent-child).
  • Terminal cutoff at q_ab (economic limit); hyperbolic branch is not integrated past that point.
Validity range
0 < b < 1; b = 1 needs the harmonic special case (log integral).
Units: EUR in the same volumetric unit as q_i integrated over years (bbl or Mscf).
  1. Inputs: q_i = 800 bbl/d, D_i = 0.85 /yr, b = 0.6, q_ab = 20 bbl/d.
  2. Convert q_i to a yearly basis: q_i_yr = 800 · 365 = 292 000 bbl/yr.
  3. Rate ratio: (q_ab / q_i)^{1−b} = (20 / 800)^{0.4} = 0.025^{0.4} = exp(0.4 · ln 0.025) = exp(−1.476) = 0.2287.
  4. Bracket: 1 − 0.2287 = 0.7713.
  5. EUR = q_i_yr / ((1 − b)·D_i) · bracket = 292 000 / (0.4 · 0.85) · 0.7713 = 858 824 · 0.7713 ≈ 662 400 bbl.
  6. Expected output: EUR ≈ 6.6e5 bbl for the tuned Bakken-tier hyperbolic inputs.
  7. Traceability: Chapter 23 recent-physics DCA item; equation 24.2 (mass-balance branch — Arps is the analytical envelope of the material-balance decline); asserted in src/lib/__tests__/arpsDca.test.ts (hyperbolic branch + EUR) and src/lib/__tests__/arpsMonteCarlo.test.ts (probabilistic EUR).

25.6 How to add a new worked case#

  • Pick one equation from Chapter 24 (equations 24.1 – 24.5). If the equation isn't there yet, add it to Chapter 24 first so the traceability chain stays intact.
  • Author the case as an `equation` block (with `usedIn`, `assumptions`, `validity`) followed by a `steps` block that walks a reviewer from inputs → arithmetic → expected output → test file.
  • Cite the exact drift-guard filename under src/lib/__tests__/. If none exists, add one in the same PR — a worked case without a test is not a verification case.
  • Keep the numbers small enough to rework in a spreadsheet in ≲ 2 minutes; anything larger belongs in the benchmark harness, not the manual.
These cases are locked by CI — not just prose
Every case above references a drift-guard test that runs on every PR. If a physics change breaks the expected value, the test fails before the PR merges and this chapter's numbers stay in sync with the kernel by construction.

25.7 Hard limitations of this chapter#

Model limitations
  • Cases B and E use tuned inputs so the arithmetic stays hand-checkable; they are illustrative, not field-representative for any specific basin.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A reviewer who mistakes the illustrative inputs for basin defaults may quote them in a design review; that would misrepresent the calibration state of the actual field.
    When it breaks down:
    External audits and cross-team reviews where the reviewer does not know the case was tuned for legibility.
    Safer alternative:
    Substitute the case inputs with the workspace's actual calibration set before quoting numbers in a report; treat the manual value as a formula check, not a field claim.
  • The Theis case computes W(u) via the A&S 5.1.11 series that expIntegralE1 uses in crossWellTomography.ts, so the hand value matches the drift-guard to ≲ 1e-6 for u ≲ 0.5. It remains a reviewer sanity check, not a substitute for the test assertion.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    A ~0.5 % difference is fine for reviewer sanity but not for numerical verification; treating the tabulated value as golden hides real regressions the drift-guard would catch.
    When it breaks down:
    Anytime the manual case is cited as a golden in a PR review instead of the test assertion itself.
    Safer alternative:
    Cite the drift-guard test file (parentChildInterference.test.ts / crossWellTomography.test.ts) as the golden reference; use the manual case for scope-of-work explanation, not numerical certification.
  • Cases here cover analytical / closed-form branches only. Fully-numerical branches (Phase-9 substepper, non-planar 3D DDM, thermo-poro 3-D) are verified against these analytical cases as limiting sub-cases, not with their own hand-workable examples.
    Why this matters, when it breaks, what to do instead
    Why it matters:
    Analytical envelopes bound the numerical solvers but do not prove correctness in the fully-coupled regime; a numerical branch can be right on every limiting sub-case and still wrong in a real coupled run.
    When it breaks down:
    Runs that combine several branches (e.g. thermo-poro + non-planar 3D + rate-and-state) where the coupling itself is the risk.
    Safer alternative:
    For coupled runs use the field-validation campaign workflow and pin the run to measured (t, P, T) data; a green analytical case is necessary but not sufficient for a coupled sign-off.

26. Keyword reference (symbol & term index)

Alphabetical index of the Greek symbols, acronyms, and domain terms used across the manual. Each entry cites the chapter that defines the term so you can jump straight to the derivation instead of grep-guessing.

This chapter is the reader's index — pick a symbol or acronym, follow the chapter marker, land on the defining equation or worked example. Chapter numbers below are the printed §-numbers you see in headings (§1 through §28 are contiguous; §21 is the release-notes index that closes the historical numbering gap).

26.1 Greek symbols#

  • α (Biot coefficient) — effective-stress splitter σ' = σ − α·p. Defined §6 (Physics & equations), used §11 (poroelastic depletion) and §25 Case A/B.
  • β (Forchheimer inertial coefficient) — non-Darcy pack term dP/dL = μv/k + βρv². Registry in §11 (advanced physics), audit in §22 (model verification).
  • γ̇ (shear rate, 1/s) — Newtonian γ̇ = 8v/d, Carreau/CY μ(γ̇) surface. Defined §6, extended in §11 (Carreau-Yasuda + Maxwell modes).
  • Δσ_h, Δσ_H (stress-shadow tensor components, psi) — Sneddon + Geertsma poroelastic Δσ. Derived §6, applied §11 (parent-child).
  • ε (cluster efficiency, geo-mean = 1) — DAS-inverted intake fraction. §9 (Live operations) and §11 (DAS → geometry inversion).
  • η (hydraulic diffusivity k/(φμc_t), ft²/s) — controls τ_D. Defined §6, used in dimensionless-time drift-guards §23.
  • κ (Mardia concentration parameter) — greedy fault-set clustering. §11 (moment-tensor inversion → DFN).
  • μ (fluid viscosity, cp) — appears in every leakoff/Darcy/inflow formula. Defined §6, referenced end-to-end.
  • ν (Poisson's ratio) — Sneddon/Geertsma kernels. §6 and §11.
  • ρ (density, ppg or kg/m³) — hydrostatic column. §25 Case A hydrostatic worked example.
  • σ_h, σ_H, σ_v (principal stresses, psi) — Mohr/breakout envelope. §6 (physics) + §24 (mud-window derivation) + §25 Case E.
  • τ (relaxation time, s / recovery time in crosslinker gels) — Maxwell mode τ_k and gel recovery τ_rec. §11 (rheology & crosslinker).
  • φ (porosity, fraction) — appears in η, in invasion radius, in mass balance. §6 + §22 (mass-balance report).
  • ψ (pseudo-pressure, psi²/cp) — gas-inflow Δψ = A·q + B·q². §11 (gas non-Darcy inflow).

26.2 Acronyms & product terms#

  • BHP — bottom-hole pressure. Reported everywhere; see §9 (live operations) for the live-stream convention.
  • BL — Buckley-Leverett fractional-flow benchmark. §22 (black-oil trust gates).
  • CQI — Completion Quality Index (0–100 + A–F grade). §10 (sensitivity & completion).
  • DAS / DTS — distributed acoustic / temperature sensing. §9 (live operations, fiber-optic transports).
  • DCA — decline-curve analysis (Arps qi/Di/b + P10/P50/P90 EUR). §10 (economics) + §9 (RTA).
  • DFIT — diagnostic fracture-injection test. Walkthrough §3, calibration wizard §5 Example 1.
  • DFN — discrete fracture network. §6 (UFM-class DFN dispatcher) + §11 (moment-tensor → DFN).
  • DDM3D — displacement-discontinuity method, 3-D non-planar kernel. §11 (Non-Planar 3D) + §23 (bridge to planar kernel).
  • EUR — estimated ultimate recovery. §10 (Arps DCA + MC bands).
  • FVF — formation volume factor (Bo, Bg). §5 Example 9 (black-oil PVT).
  • GRI — Gas Research Institute public dataset. §22 (public-benchmark DFIT comparison).
  • HF vs NF — hydraulic vs natural fracture. §11 (bedding-plane fracture) + Viewer 3D right-rail toggle.
  • IPR / VLP — inflow / vertical-lift performance. §11 (artificial lift & non-Darcy skin).
  • ISIP — instantaneous shut-in pressure. §9 (auto-pick, live operations).
  • K_IC — mode-I fracture toughness (MPa·√m). Fit in §5 Example 1 (DFIT), used §6.
  • MW — mud weight (ppg). §14 (units & sanity) + §25 Case A.
  • OFAT — one-factor-at-a-time sweep. §7 (sensitivity) + §10 (optimizer suite).
  • PKN / KGD / Radial — classical fracture geometry models. §6 physics + §22 verification.
  • PVT — pressure/volume/temperature (black-oil correlations). §5 Example 9 + §11.
  • RSF — rate-and-state friction. §11 (induced-seismicity advanced physics).
  • RTA — rate-transient analysis (Blasingame / Agarwal-Gardner). §9.
  • SHmax — maximum horizontal stress azimuth. §6 (Hubbert-Willis tensor) + §5 Example 5 (inversion).
  • SI — saturation index (log10 IAP/Ksp) for mineral scale. §11 (scaling kinetics).
  • TSO — tip screen-out. §9 (net-pressure match).
  • UFM — unconventional fracture model. Called out in the honest-scope note in §6.
  • WITSML — wellsite information transfer standard. §9 (telemetry transports).

26.3 Chapter markers used in cross-references#

When prose says 'see §6.2' it means chapter 6, second equation. Chapter numbers are parsed from the leading number of each heading (e.g. '22. Model verification' → §22). Every §-number from §1 through §28 is present — §21 is the release-notes index that closes the historical numbering gap. Equation ordinals restart at 1 inside every chapter, so §6.2 and §11.2 are unrelated.

  • §1§4 — orientation & walkthroughs.
  • §5 — worked examples (numbers in, numbers out).
  • §6 — core physics & governing equations.
  • §7§10 — sensitivity, calibration, live ops, optimization.
  • §11 — reservoir/wellbore/fluids & advanced physics (RSF, non-Darcy, scaling, DDM3D…).
  • §12§14 — reports, exports, workspace toggles, units & sanity.
  • §15§20 — recently-shipped and 'what's new' changelogs.
  • §21 — release-notes index (v1.4 / v1.6 / v1.7 / v1.8 cross-links + roadmap pointer; closes the historical numbering gap).
  • §22 — model verification (BL, mass-balance, public benchmarks).
  • §23 — recent physics + numerical additions (round-3 answers).
  • §24 — numerical-method background & specialty material inputs.
  • §25 — worked verification case studies (five hand-workable cases).
  • §26 — this keyword reference.
  • §27 — data-entry patterns (paste-from-Excel, LAS, JSON scenarios, CSV templates, supported file formats).
  • §28 — offline & deployment policy (online-first, read-only offline cache, Electron field build, PWA home-screen).

27. Data entry patterns

Every supported way to get field data into the Builder — paste-from-Excel column mappings, LAS column spec, JSON scenario schema pointer, CSV templates, and the master list of supported deck / telemetry / interchange formats.

This chapter answers 'what file do I upload where'. Every Builder panel exposes a Paste-from-Excel tab; heavy interchange formats (LAS, WITSML, CMG/ECLIPSE decks) route through dedicated importers. Round-trip anything you build through JSON so a teammate can reproduce your run exactly.

27.1 Paste-from-Excel#

Every non-trivial Builder panel has a Paste-from-Excel tab that accepts a rectangular block copied from Excel / Numbers / Sheets. The panel parser is column-order tolerant when the first row is a header — otherwise it assumes the canonical Bakken-tutorial layout below. Units are always inferred from the bracketed suffix in the header (e.g. 'Perm [md]' vs 'Perm [nD]').

Builder panelCanonical column order (header row)Notes
Static model — layersLayer name · Top TVD [ft] · h [ft] · φ [-] · k [md] · σ_h [psi] · σ_v [psi] · E [Mpsi] · ν [-] · Biot α [-]One row per layer, top-down. Missing σ_v is auto-filled from overburden gradient.
Wells & perforationsCluster ID · MD [ft] · Shots per cluster · Phasing [°] · Perf diameter [in] · CD [-]One row per cluster. CD default 0.85; used by Karakas-Tariq skin.
Curve sets — kro/krw/krg/pcS_w · k_ro · k_rw · k_rg · P_c [psi]Ascending S_w. Missing columns become — (dash), NOT zero.
Fluid model — PVTp [psi] · B_o [rb/stb] · μ_o [cp] · R_s [scf/stb] · B_g [rb/scf] · μ_g [cp]Sorted by p; used to build the black-oil PVT table.
Well controls — schedulet_start [min] · Duration [min] · Rate [bpm] · Cppa [ppg] · Fluid ID · Role (preflush/pad/slurry/postflush)Role tag drives the 4-role stage classifier.
Water solutesIon · Concentration [mg/L]Names match §11 mineral catalog (Na+, Ca2+, SO4^2-, HCO3-, …).
Field measurements (WFT/DST/DFIT)Depth MD [ft] · TVD [ft] · Pressure [psi] · Temp [°F] · Fluid density [ppg] · Uncertainty ± [psi]Feeds the Pressure Advisor cross-check card.

27.2 LAS files (well logs)#

LAS 2.0 / 3.0 ASCII well logs upload from Static model → Curve sets → Import LAS. The parser reads ~V, ~W, ~C, ~P, and ~A sections; ~O (other) is ignored. Depth must be MD in feet or metres — the header UNIT field decides. Non-finite / -999.25 sentinels are converted to null (renders as — in charts).

LAS mnemonicMaps toRequired?
DEPT / MDRow depth axisYes
GRGamma-ray (API) — used by mineralogyInverterRecommended
RHOBBulk density (g/cc)Recommended
NPHINeutron porosity (v/v)Recommended
DTC / DTCompressional slowness (μs/ft) — E modulus estimatorOptional
DTSShear slowness (μs/ft) — ν estimatorOptional
PEFPhotoelectric factor — mineralogy tieOptional
SPSpontaneous potentialOptional
RES / RILD / RTResistivity — Sw estimatorOptional

Multi-well LAS bundles: upload one .zip and every .las inside is parsed with the archive filename as the well tag. Duplicate curve mnemonics are suffixed _2, _3, … so no data is silently dropped.

27.3 Supported file formats#

The master table below is the answer to 'our datafile will be in JSON type only?'. JSON is the native round-trip format, but the app also accepts every heavy interchange format the drilling / completion / reservoir world uses. Anything not listed here should be pasted via §27.1 or converted to CSV.

CategoryFormatExtensionsDirectionEntry point
NativeJSON scenario (versioned).jsonRead + WriteBuilder → Export / Import simulation
NativeCSV templates.csvRead + Writepublic/templates/*.csv · every Builder panel export
Well logsLAS 2.0 / 3.0.las, .zipReadStatic model → Curve sets → Import LAS
Reservoir deckECLIPSE datafile.DATAReadImport parity → ECLIPSE (mrstCmgDeckImport)
Reservoir deckCMG STARS/IMEX/GEM.datReadImport parity → CMG
Reservoir deckMRST script (partial).mReadImport parity → MRST
GridGRDECL corner-point.grdecl, .incReadStatic model → Grid import
Interchange (Energistics)RESQML v2.x.epc, .xmlReadStatic model → Interop import
Live telemetryWITSML 2.xhttps(s):// endpointRead (stream)/live-pumping → WITSML transport
Live telemetryApache Arrow Flightflight+https:// endpointRead (stream)/live-pumping → Arrow Flight transport
Live telemetryFiber-optic frames (DAS / DTS)ws(s):// or http(s)://Read (stream)/live-pumping → DAS / DTS transports
ProductionProdML monthly.xmlRead/rta → ProdML import
Spreadsheet pasteExcel / Numbers / Sheets rectangular selectionclipboardReadEvery Builder panel — Paste-from-Excel tab
ReportsPDF (jsPDF).pdfWriteBuilder → Export → * report
ReportsCSV audit ledgers.csvWriteEvery Results / Live / Sensitivity panel
BackupWorkspace ZIP (JSON + CSV bundle).zipRead + WriteSimulations home → Export / Import

Python SDK examples for every read-format above live under public/sdk/python/examples/. The examples wrap the same public /api/public/sdk/v1/* endpoints the web app uses, so anything you can do in the UI is scriptable.

27.4 JSON scenario schema#

Scenario files are Zod-validated on read. The envelope is a discriminated union on `kind` (dfit-calibration / expert-job-setup / pressure-advisor / …); each `kind` has its own strict input schema in src/lib/scenarioInputSchemas.ts. Older v1 files auto-upgrade to v2 on load — you never need to edit them by hand. The full schema is published as JSON-Schema at /schemas/scenario.v2.json for external tooling.

  • Version envelope: `{ version: 2, kind, inputs, meta: { createdAt, createdBy, appVersion } }`.
  • All numeric fields are `number().finite()` — NaN and Infinity are rejected at parse time.
  • Missing optional fields fall through to `defaultXxxInputs()` factories (one per kind).
  • Round-trip is byte-stable: `parse(build(x)) === x` for every kind (locked by scenarioJsonIo.test.ts).

27.5 CSV templates#

Every Builder panel and every Results / Live / Sensitivity export uses the same dash convention (see §12 exports): missing numerics render as — (em-dash), never 0 or empty. Templates that a user can pre-fill live under public/templates/ and are linked from the matching panel's Paste-from-Excel tab.

  • public/templates/history-match-measured-bhp.csv — measured (t [s], BHP [psi]) time series for the /history-match interval-fit tab.
  • public/templates/history-match-measured-rate.csv — measured (t [s], rate [bpm]) time series (same fitter).
  • public/templates/field-measurements-wft.csv — depth-referenced WFT / DST / DFIT observations for §27.1 field-measurements paste.
  • public/templates/microseismic-catalog.csv — (t [s], x [ft], y [ft], z [ft], mag) for the /parent-child ingest.
  • public/templates/production-monthly.csv — (date, q_o [stb/d], q_w [stb/d], q_g [Mscf/d]) for the RTA DCA fit.

28. Offline & deployment policy

Where and how the app runs — online-first web, read-only browser-cache offline, PWA home-screen install, and the fully-offline Electron field build. One page, no ambiguity.

The short version: the web app is online-first, works read-only offline for scenarios you have already opened, installs to your phone as a home-screen icon (no service worker — no stale-cache traps during a live frac), and has a fully-offline Electron packaging path for field engineers who cannot rely on connectivity.

28.1 Online-first web (default)#

  • Team scenarios, versioning, and cross-device sync all live on Lovable Cloud (managed backend). Cloud is REQUIRED for those features.
  • Individual workspace state — Builder inputs, chart settings, cadence presets — is mirrored to localStorage per browser, so a network blip does NOT lose your in-flight work.
  • Sign-in state is refreshed on tab focus. If you lose Cloud connectivity, the app stays in the current view until you navigate; on next navigation it prompts to reconnect.

28.2 Read-only offline (browser cache)#

  • Every scenario you open at least once is available offline via the browser HTTP cache and the localStorage stores keyed under downhole.*.
  • Builder + Sensitivity + RTA + Live-pumping REPLAY mode all keep working against localStorage data — no round-trip needed.
  • Publishing new scenarios, running server-side sensitivity, and Cloud sync all require connectivity — the app chips these as 'Offline — reconnect to run' rather than failing silently.
  • There is no service worker. This is deliberate: a service worker that cached the app shell could keep serving a stale UI during a live frac, which is a safety issue we refuse to accept.

28.3 PWA home-screen (manifest-only)#

  • The app ships a Web App Manifest at /manifest.webmanifest with `display: standalone`, a theme colour, and an icon.
  • On iOS Safari: Share → Add to Home Screen adds a full-screen app icon. On Android Chrome: three-dot menu → Install app.
  • This is manifest-only: no service worker is registered, so 'Add to Home Screen' does NOT enable offline caching. It only gives you an app-style icon and standalone chrome.
  • The installed launcher hits the live URL every time — you always see the latest deploy. That is intentional for a field-operations tool.

28.4 Fully-offline field build (Electron)#

  • For engineers on frac locations with no reliable connectivity, we ship an Electron desktop packaging path (Windows / macOS / Linux).
  • The Electron build bundles the same physics kernels and Builder UI, plus a local scenario store that syncs when the laptop comes back online.
  • Cloud-only features (team scenarios, cross-device sync, published sharing links) are chipped as unavailable in the offline build, not silently disabled.
  • Contact the Wellbore Genius team for the current Electron installer — the packaging pipeline lives outside this web repo.

28.5 What we deliberately do NOT do#

No service-worker cache of the app shell
Frac operations run on a decision-per-minute cadence. A stale UI is a safety risk. We do not install an app-shell service worker on the web build. Home-screen installability is delivered via manifest-only PWA; true offline is delivered via the Electron build. This is a policy, not an oversight.
Found a gap? Open the Builder, click the comments-file icon in the header, and tell us what you couldn't change. We mirror feedback into this manual on every release.