# Neqsim Process Extraction

> Extracts process simulation data from unstructured sources (text, tables, PFDs, data sheets, STID/E3D line lists) and converts it to NeqSim JSON builder format or PipingRouteBuilder route models. USE WHEN: a user provides a process description, PFD, operating data, line-list table, or design document and wants a running NeqSim simulation. Covers equipment mapping, stream wiring, route hydraulics, unit conversion, composition normalization, and confidence scoring.

- Skill: `equinor/neqsim-process-extraction` (Agent Skill)
- Install (CLI): `npx skillmds@latest add equinor/neqsim-process-extraction`
- Raw SKILL.md: https://api.skillmd.com/api/skills/equinor/neqsim-process-extraction/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: equinor (https://skillmd.com/u/equinor)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/equinor/neqsim-process-extraction

---


# NeqSim Process Extraction Skill

Convert unstructured engineering information into the canonical NeqSim JSON format
accepted by `ProcessSystem.fromJson()` and `ProcessSystem.fromJsonAndRun()`.

## Core Principle

> **Extract structured data into a constrained JSON schema. Do NOT write NeqSim Java/Python code.**
>
> The JSON schema is finite and well-defined. `ProcessSystem.fromJson()` handles all
> NeqSim API calls deterministically. Errors come back as structured, actionable messages.
>
> **P&ID operational workflow:** When the source is a P&ID and the user asks
> about a valve action, active train, isolation boundary, bypass, drain, vent,
> or control-loop behavior, load `neqsim-pid-process-operations`. Extract both
> the steady-state topology and the model delta needed to simulate the action.
>
> **Exception for route hydraulics:** When the source is a STID/E3D/P&ID/stress-isometric
> line-list table with serial pipe segments, use
> `neqsim.process.equipment.pipeline.routing.PipingRouteBuilder` rather than the generic
> JSON process builder. The route builder preserves line-list segment metadata, K-value
> minor losses, elevations, and explicit connection topology.
>
> **Architecture decision (MANDATORY):** Before assembling JSON, classify the process
> complexity. Small/medium processes (≤ ~15 units, single recycle loop) use a single
> `ProcessSystem`. Large processes (multiple plant areas, cross-area recycles, different
> fluids) must be split into multiple `ProcessSystem` objects composed inside a
> `ProcessModule`, or use pre-built `ProcessModuleBaseClass` implementations.
> See **Section 16** for the decision guide.

---

## 1. Target JSON Schema

Every extraction must produce JSON matching this format:

```json
{
  "fluid": {
    "model": "SRK",
    "temperature": 323.15,
    "pressure": 65.0,
    "mixingRule": "classic",
    "multiPhaseCheck": false,
    "components": {
      "methane": 0.80,
      "ethane": 0.08,
      "propane": 0.05,
      "CO2": 0.03,
      "n-butane": 0.02,
      "nitrogen": 0.01,
      "n-pentane": 0.005,
      "n-hexane": 0.005
    }
  },
  "process": [
    {"type": "Stream", "name": "well stream", "properties": {"flowRate": [75000.0, "kg/hr"]}},
    {"type": "ThreePhaseSeparator", "name": "inlet separator", "inlet": "well stream"},
    {"type": "Compressor", "name": "export compressor", "inlet": "inlet separator.gasOut",
     "properties": {"outletPressure": 120.0, "isentropicEfficiency": 0.78}},
    {"type": "ThrottlingValve", "name": "letdown valve", "inlet": "inlet separator.oilOut",
     "properties": {"outletPressure": 15.0}}
  ],
  "autoRun": true
}
```

### Field Reference

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `fluid.model` | string | Yes | EOS model: `SRK`, `PR`, `CPA`, `GERG2008`, `PCSAFT`, `UMRPRU` |
| `fluid.temperature` | number | Yes | Temperature in **Kelvin** |
| `fluid.pressure` | number | Yes | Pressure in **bara** |
| `fluid.mixingRule` | string | Yes | Usually `"classic"` for SRK/PR, `"CLASSIC_TX_CPA"` for CPA |
| `fluid.multiPhaseCheck` | boolean | No | Set `true` for water+HC or 3-phase systems |
| `fluid.components` | object | Yes | Component name → mole fraction (must sum to ~1.0) |
| `process[].type` | string | Yes | Equipment type from the Equipment Type Table below |
| `process[].name` | string | Yes | Unique equipment tag / display name |
| `process[].inlet` | string | Conditional | Stream reference (dot-notation). Required for all except 1st Stream |
| `process[].properties` | object | No | Equipment-specific settings (see Properties Reference) |
| `autoRun` | boolean | No | Set `true` to auto-run after building |

### Multiple Fluids (Named)

For processes with different feed compositions, use the `fluids` map:

```json
{
  "fluids": {
    "gas_feed": { "model": "SRK", "temperature": 323.15, "pressure": 80.0, "mixingRule": "classic", "components": {"methane": 0.90, "ethane": 0.05, "propane": 0.03, "n-butane": 0.02} },
    "water_feed": { "model": "CPA", "temperature": 293.15, "pressure": 80.0, "mixingRule": "CLASSIC_TX_CPA", "components": {"water": 0.999, "MEG": 0.001} }
  },
  "process": [
    {"type": "Stream", "name": "gas inlet", "fluidRef": "gas_feed", "properties": {"flowRate": [50000.0, "kg/hr"]}},
    {"type": "Stream", "name": "water inlet", "fluidRef": "water_feed", "properties": {"flowRate": [5000.0, "kg/hr"]}}
  ]
}
```

---

## 2. Equipment Type Mapping

Map natural language equipment names to NeqSim JSON `type` values.
Use the **longest matching keyword** to avoid false matches.

### Separation

| Natural Language Synonyms | NeqSim `type` |
|---------------------------|---------------|
| separator, 2-phase separator, two-phase separator, flash drum, flash vessel, KO drum, knock-out drum, knockout drum, scrubber, inlet scrubber, suction scrubber, slug catcher, production scrubber, gas scrubber | `Separator` |
| 3-phase separator, three-phase separator, production separator, test separator, oil-water-gas separator, 3-phase test separator | `ThreePhaseSeparator` |

### Compression & Expansion

| Natural Language Synonyms | NeqSim `type` |
|---------------------------|---------------|
| compressor, gas compressor, export compressor, recompressor, booster compressor, LP compressor, HP compressor, 1st stage compressor, 2nd stage compressor, 3rd stage compressor, centrifugal compressor, reciprocating compressor | `Compressor` |
| expander, turbo-expander, turboexpander, power recovery turbine | `Expander` |

### Heat Transfer

| Natural Language Synonyms | NeqSim `type` |
|---------------------------|---------------|
| cooler, gas cooler, aftercooler, after-cooler, intercooler, air cooler, fin fan cooler, air-fin cooler, trim cooler, export cooler, overhead condenser | `Cooler` |
| heater, pre-heater, preheater, line heater, electric heater, fired heater, reboiler, trim heater | `Heater` |
| heat exchanger, shell and tube, shell-and-tube, plate heat exchanger, plate-fin exchanger, FWHE, gas-gas exchanger, cross-exchanger, economizer | `HeatExchanger` |

### Valves

| Natural Language Synonyms | NeqSim `type` |
|---------------------------|---------------|
| valve, throttling valve, choke valve, choke, JT valve, Joule-Thomson valve, letdown valve, control valve, pressure control valve, PCV, backpressure valve, production choke, wellhead choke | `ThrottlingValve` |

### Pumps

| Natural Language Synonyms | NeqSim `type` |
|---------------------------|---------------|
| pump, centrifugal pump, export pump, booster pump, injection pump, feed pump, charge pump, transfer pump, multiphase pump | `Pump` |

### Piping Routes

| Natural Language Synonyms | NeqSim target |
|---------------------------|---------------|
| line list, line-list, route table, STID route, E3D route, stress isometric, pipe run list, serial piping route, compressor suction route, compressor discharge route | `PipingRouteBuilder` |

`PipingRouteBuilder` is not a JSON equipment type. It is a Java/Python-accessible
builder for serial route hydraulics. Use it when the input table has from/to
nodes, pipe lengths, sizes, elevations, fittings, valves, and K values. Extract
the route rows first, then build the route model and export `route.toJson()` for
traceability.

For P&ID valve-action studies, classify each valve before mapping it to NeqSim:
control valves become `ThrottlingValve` equipment, isolation and shutdown valves
become scenario switches or boundary states, check valves become directed route
constraints, and BDV/PSV/vent valves become relief or blowdown paths.

### Mixing & Splitting

| Natural Language Synonyms | NeqSim `type` |
|---------------------------|---------------|
| mixer, mixing tee, junction, merge, combine | `Mixer` |
| splitter, tee, flow divider, bypass tee | `Splitter` |
| manifold, production manifold, gathering manifold, commingling manifold, subsea manifold, inlet/export header | `Manifold` |

**Always model a manifold as `Manifold`, not `Mixer`/`Splitter`.** Add all inlet
streams with `addStream(...)`, then **route downstream from a split stream, not
`getMixedStream()`.** A single-destination gathering manifold sets one split
(`setSplitFactors([1.0])`) and routes `getSplitStream(0)`; a distributing
manifold sets `setSplitFactors([...])` (fractions summing to 1) and reads each
outlet with `getSplitStream(i)`. `getMixedStream()` is the internal commingled
stream (before the split) — for inspection only. The `Manifold` also carries
header / branch diameters for hydraulics and mechanical design.

### Streams

| Natural Language Synonyms | NeqSim `type` |
|---------------------------|---------------|
| stream, feed, inlet, well stream, feed gas, feed stream, input, source | `Stream` |

### Other Equipment

| Natural Language Synonyms | NeqSim `type` |
|---------------------------|---------------|
| tank, storage tank, atmospheric tank, settling tank, buffer tank | `Tank` |
| flare, flare stack, flare header, HP flare, LP flare | `Flare` |
| recycle, recirculation | `Recycle` |
| ejector, jet pump, steam ejector, gas ejector | `Ejector` |
| TEG absorber, glycol contactor, TEG contactor, dehydration absorber | `SimpleTEGAbsorber` |
| reservoir, simple reservoir | `SimpleReservoir` |
| electrolyzer, water electrolyzer, PEM electrolyzer | `Electrolyzer` |
| CO2 electrolyzer | `CO2Electrolyzer` |
| fuel cell | `FuelCell` |
| wind turbine | `WindTurbine` |
| solar panel, PV panel | `SolarPanel` |
| battery storage, battery, BESS | `BatteryStorage` |
| ammonia reactor, Haber-Bosch reactor, ammonia synthesis | `AmmoniaSynthesisReactor` |
| distillation column, fractionation column, distillation tower, deethanizer, demethanizer, depropanizer, debutanizer, stripper column, stabilizer column | `DistillationColumn` |
| pipe, pipe segment, pipeline, flowline, adiabatic pipe | `AdiabaticPipe` |
| stream saturator, saturator, water saturator | `StreamSaturatorUtil` |

---

## 3. Stream Wiring (Dot-Notation)

Equipment is connected via dot-notation references in the `inlet` field.

### Port Reference Table

| Upstream Equipment Type | Port Syntax | Resolves To |
|-------------------------|-------------|-------------|
| `Stream` | `"feed"` (name only, no port) | The stream directly |
| `Separator` | `"HP Sep.gasOut"` | Gas outlet stream |
| `Separator` | `"HP Sep.liquidOut"` | Liquid outlet stream |
| `ThreePhaseSeparator` | `"Inlet Sep.gasOut"` | Gas outlet |
| `ThreePhaseSeparator` | `"Inlet Sep.oilOut"` | Oil outlet |
| `ThreePhaseSeparator` | `"Inlet Sep.waterOut"` | Water outlet |
| `ThreePhaseSeparator` | `"Inlet Sep.liquidOut"` | Oil outlet (alias) |
| `Compressor` | `"Comp.outlet"` | Outlet stream |
| `Cooler` | `"Cooler.outlet"` | Outlet stream |
| `Heater` | `"Heater.outlet"` | Outlet stream |
| `ThrottlingValve` | `"Valve.outlet"` | Outlet stream |
| `Pump` | `"Pump.outlet"` | Outlet stream |
| `Expander` | `"Expander.outlet"` | Outlet stream |
| `Mixer` | `"Mixer.outlet"` | Outlet stream |
| `Splitter` | `"Splitter.outlet"` | Outlet stream (first split) |
| `Splitter` | `"Splitter.split0"` | Split port 0 |
| `Splitter` | `"Splitter.split1"` | Split port 1 |
| `Splitter` | `"Splitter.splitN"` | Split port N (zero-indexed) |
| `HeatExchanger` | `"HX.outlet"` | Outlet stream |
| `DistillationColumn` | `"Column.gasOut"` | Gas (overhead) outlet |
| `DistillationColumn` | `"Column.liquidOut"` | Liquid (bottoms) outlet |
| `Tank` | `"Tank.outlet"` | Outlet stream |

### Wiring Rules

1. **First equipment MUST be a `Stream`** — it gets the fluid from the `fluid` section
2. **Every subsequent equipment MUST have an `inlet` reference** pointing to a previously defined equipment
3. **For separators, specify the port** — `gasOut`, `liquidOut`, `oilOut`, `waterOut`
4. **For single-outlet equipment** — use `"name.outlet"` or just `"name"` (default resolves to outlet)
5. **Do NOT create circular references** — the JSON builder does not support recycle loops directly (add `Recycle` equipment for convergence)
6. **Branching is supported** — multiple equipment can reference different ports of the same separator
7. **Mixer multi-inlet: use `"inlets"` (plural)** — Mixers require `"inlets": ["stream1", "stream2"]` (array). Do NOT use `"inlet"` with an array — it will fail with "Array must have size 1"
8. **Separator name without port returns null** — `resolveStreamReference("HP Sep")` returns `null`. Always use `"HP Sep.gasOut"` or `"HP Sep.liquidOut"`

### Branching Example

```json
{"type": "ThreePhaseSeparator", "name": "inlet sep", "inlet": "feed"},
{"type": "Compressor", "name": "gas comp", "inlet": "inlet sep.gasOut", ...},
{"type": "ThrottlingValve", "name": "oil valve", "inlet": "inlet sep.oilOut", ...},
{"type": "Pump", "name": "water pump", "inlet": "inlet sep.waterOut", ...}
```

### Mixer Multi-Inlet Example

```json
{"type": "Stream", "name": "gas 1", "properties": {"flowRate": [10000.0, "kg/hr"]}},
{"type": "Stream", "name": "gas 2", "properties": {"flowRate": [5000.0, "kg/hr"]}},
{"type": "Mixer", "name": "gas mixer", "inlets": ["gas 1", "gas 2"]},
{"type": "Cooler", "name": "mixed cooler", "inlet": "gas mixer", "properties": {"outletTemperature": [25.0, "C"]}}
```

> **CRITICAL**: Use `"inlets"` (plural key, with array value) for Mixer/multi-inlet equipment. Using `"inlet"` with an array value will fail.

---

## 4. Equipment Properties Reference

### Stream

| Property | Type | Unit | Example |
|----------|------|------|---------|
| `flowRate` | `[number, "unit"]` | kg/hr, MSm3/day, Am3/hr | `[75000.0, "kg/hr"]` |
| `temperature` | number | Kelvin | `353.15` (= 80°C) |
| `pressure` | number | bara | `65.0` |

### Compressor

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `outletPressure` | number (bara) | — | Discharge pressure |
| `isentropicEfficiency` | number (0-1) | 0.75 | Isentropic efficiency |
| `polytropicEfficiency` | number (0-1) | — | Polytropic efficiency (alternative) |
| `usePolytropicCalc` | boolean | false | Use polytropic head calculation |

### Cooler / Heater

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `outTemperature` | number (K) | — | Outlet temperature in Kelvin |
| `outletTemperature` | `[number, "unit"]` | — | Outlet temperature with unit (e.g., `[25.0, "C"]`) |

**Property Unit Arrays:** Equipment properties can be specified with units using the `[value, "unit"]` array format. This applies to any property that accepts a unit string, such as `outletTemperature`, `flowRate`, etc. The JSON builder uses Java reflection to find matching setter methods.

### ThrottlingValve

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `outletPressure` | number (bara) | — | Downstream pressure |

### Pump

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `outletPressure` | number (bara) | — | Discharge pressure |
| `isentropicEfficiency` | number (0-1) | 0.75 | Isentropic efficiency |

### Separator / ThreePhaseSeparator

No required properties. Operates at inlet conditions.

### Splitter

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `splitNumber` | integer | — | Number of outlet streams |
| `splitFactors` | `[number, ...]` | — | Split factors per outlet (e.g., `[0.5, 0.5]`) |

### DistillationColumn

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `numberOfTrays` | integer | 10 | Number of theoretical trays |
| `hasReboiler` | boolean | true | Whether column has a reboiler |
| `hasCondenser` | boolean | true | Whether column has a condenser |

### HeatExchanger (Multi-Inlet)

`HeatExchanger` supports two inlets (hot and cold side):

```json
{"type": "HeatExchanger", "name": "gas-gas HX",
 "inlets": ["hot stream", "cold stream"]}
```

The first inlet becomes the feed stream; the second is set via `setFeedStream(1, stream)`.

### AdiabaticPipe

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `length` | number (m) | — | Pipe length in meters |
| `diameter` | number (m) | — | Pipe inner diameter in meters |

### Route-Level Piping Line Lists

When the source has a line-list or stress-isometric table, extract these fields
before constructing the route:

| Extracted field | Required | Notes |
|-----------------|----------|-------|
| `segment_id` | Yes | Line number, row id, or generated `S1`, `S2` |
| `from_node`, `to_node` | Yes | Equipment tag, nozzle, tee, manifold, or route node |
| `length`, `length_unit` | Yes | Straight pipe length, not equivalent length |
| `internal_diameter`, `diameter_unit` | Yes | Convert NPS/schedule to internal diameter first |
| `wall_thickness`, `wall_thickness_unit` | No | Store if schedule or stress iso gives it |
| `elevation_change`, `elevation_unit` | No | Positive uphill, negative downhill |
| `roughness`, `roughness_unit` | No | Use default roughness when only piping class is known |
| `minor_losses` | No | Fittings/valves as `{type, k_value}` rows |
| `source_ref` | Yes | Drawing/page/row reference for traceability |

Route extraction workflow:

1. Sort rows in hydraulic flow order from upstream to downstream.
2. Convert NPS/schedule to internal diameter before calling `addSegment(...)`.
3. Convert every valve, bend, tee, reducer, strainer, and entry/exit loss to K.
4. For a route-only study, build the route with `PipingRouteBuilder.build(feedStream)`
  and run the returned `ProcessSystem`.
5. For a full plant model, call `route.addToProcessSystem(process, inletStream)`
  and pass the returned outlet stream to the downstream equipment. Use the overload
  with source-equipment metadata when the inlet is an upstream equipment outlet stream.
6. Save `route.toJson()` and pressure-drop results in the task folder.

Reference guide: `docs/process/piping_route_builder.md`.

---

## 5. Component Name Mapping

Map common aliases to NeqSim database names. The NeqSim name is case-sensitive.

### Hydrocarbon Components

| Common Aliases | NeqSim Name |
|----------------|-------------|
| C1, CH4, methane | `methane` |
| C2, C2H6, ethane | `ethane` |
| C3, C3H8, propane | `propane` |
| iC4, i-C4, isobutane | `i-butane` |
| nC4, n-C4, butane, normal-butane | `n-butane` |
| iC5, i-C5, isopentane | `i-pentane` |
| nC5, n-C5, pentane, normal-pentane | `n-pentane` |
| nC6, n-C6, hexane | `n-hexane` |
| nC7, n-C7, heptane | `n-heptane` |
| nC8, n-C8, octane | `n-octane` |
| nC9, n-C9, nonane | `n-nonane` |
| nC10, n-C10, decane | `nC10` |
| nC11 through nC24 | `nC11` through `nC24` |

### Non-Hydrocarbon Components

| Common Aliases | NeqSim Name |
|----------------|-------------|
| CO2, carbon dioxide | `CO2` |
| H2S, hydrogen sulfide, hydrogen sulphide | `H2S` |
| N2, nitrogen | `nitrogen` |
| H2, hydrogen | `hydrogen` |
| O2, oxygen | `oxygen` |
| Ar, argon | `argon` |
| He, helium | `helium` |
| H2O, water | `water` |
| Hg, mercury | `mercury` |
| COS, carbonyl sulfide | `COS` |
| SO2, sulfur dioxide | `SO2` |

### Chemical Additives

| Common Aliases | NeqSim Name |
|----------------|-------------|
| MEG, monoethylene glycol, ethylene glycol | `MEG` |
| DEG, diethylene glycol | `DEG` |
| TEG, triethylene glycol | `TEG` |
| MeOH, methanol | `methanol` |
| EtOH, ethanol | `ethanol` |
| MDEA, methyldiethanolamine | `MDEA` |

### Aromatics

| Common Aliases | NeqSim Name |
|----------------|-------------|
| benzene, C6H6 | `benzene` |
| toluene, C7H8, methylbenzene | `toluene` |
| cyclohexane, c-C6, cy-C6 | `c-hexane` |
| cyclopentane, c-C5, cy-C5 | `c-C5` |

---

## 6. Unit Conversion Rules

All NeqSim JSON values must be in standard units. Convert before inserting into JSON.

### Temperature

| Input Unit | To Kelvin | Formula |
|------------|-----------|---------|
| °C, degC, Celsius | K | `T_K = T_C + 273.15` |
| °F, degF, Fahrenheit | K | `T_K = (T_F - 32) × 5/9 + 273.15` |
| K, Kelvin | K | Identity |
| °R, Rankine | K | `T_K = T_R × 5/9` |

### Pressure

| Input Unit | To bara | Formula |
|------------|---------|---------|
| barg, bar gauge | bara | `P_bara = P_barg + 1.01325` |
| bara, bar absolute | bara | Identity |
| psia, psi absolute | bara | `P_bara = P_psia × 0.0689476` |
| psig, psi gauge | bara | `P_bara = (P_psig + 14.696) × 0.0689476` |
| kPa, kilopascal | bara | `P_bara = P_kPa / 100.0` |
| MPa, megapascal | bara | `P_bara = P_MPa × 10.0` |
| atm, atmosphere | bara | `P_bara = P_atm × 1.01325` |

### Flow Rate

Flow rate in JSON uses the `[value, "unit"]` array format. Supported unit strings:

| Unit String | Description |
|-------------|-------------|
| `"kg/hr"` | Kilograms per hour (mass flow) |
| `"kg/min"` | Kilograms per minute |
| `"kg/sec"` | Kilograms per second |
| `"m3/hr"` | Cubic meters per hour (volume flow) |
| `"Am3/hr"` | Actual cubic meters per hour |
| `"Sm3/hr"` | Standard cubic meters per hour |
| `"MSm3/day"` | Million standard cubic meters per day |
| `"idSm3/day"` | Ideal standard cubic meters per day |
| `"mole/sec"` | Moles per second |
| `"mole/hr"` | Moles per hour |

### Composition: Weight% to Mole Fraction Conversion

NeqSim uses **mole fractions** (summing to 1.0) in the JSON `components` field. If the source provides weight% (wt%), mass fractions, or ppm-by-weight, convert as follows:

**Formula:**

For each component $i$ with weight fraction $w_i$ and molar mass $M_i$:

$$x_i = \frac{w_i / M_i}{\sum_j (w_j / M_j)}$$

**Common Molar Masses (g/mol):**

| Component | NeqSim Name | $M$ (g/mol) |
|-----------|-------------|-------------|
| Methane | `methane` | 16.04 |
| Ethane | `ethane` | 30.07 |
| Propane | `propane` | 44.10 |
| n-Butane | `n-butane` | 58.12 |
| i-Butane | `i-butane` | 58.12 |
| n-Pentane | `n-pentane` | 72.15 |
| n-Hexane | `n-hexane` | 86.18 |
| CO2 | `CO2` | 44.01 |
| H2S | `H2S` | 34.08 |
| Nitrogen | `nitrogen` | 28.01 |
| Water | `water` | 18.02 |
| MEG | `MEG` | 62.07 |
| TEG | `TEG` | 150.17 |
| MDEA | `MDEA` | 119.16 |

**Worked Example:**

Input: 70 wt% methane, 20 wt% ethane, 10 wt% propane

| Component | $w_i$ | $M_i$ | $w_i / M_i$ | $x_i$ (mole frac) |
|-----------|--------|--------|-------------|-------------------|
| methane | 0.70 | 16.04 | 0.04364 | 0.8370 |
| ethane | 0.20 | 30.07 | 0.00665 | 0.1275 |
| propane | 0.10 | 44.10 | 0.00227 | 0.0355 |
| **Total** | 1.00 | | 0.05216 | **1.0000** |

Result JSON: `{"methane": 0.837, "ethane": 0.128, "propane": 0.035}`

**ppm-by-weight:** Convert ppm_w to weight fraction first: $w_i = \text{ppm}_w \times 10^{-6}$

**Volume% (gas at standard conditions):** Volume% ≈ mole% for ideal gas behavior. Use directly as mole fractions.

---

## 7. EOS Model Selection

Choose the thermodynamic model based on the fluid system:

| Fluid System | Recommended Model | Mixing Rule |
|-------------|-------------------|-------------|
| Dry gas, lean gas, simple hydrocarbons | `SRK` | `"classic"` |
| Oil systems, general hydrocarbons | `PR` | `"classic"` |
| Water + hydrocarbons, MEG/methanol, polar | `CPA` | `"CLASSIC_TX_CPA"` |
| Fiscal metering, custody transfer | `GERG2008` | (none needed) |
| Polymer/associating fluids | `PCSAFT` | `"classic"` |

### Decision Rules

1. **If water or glycol is present** → use `CPA` with mixing rule `"CLASSIC_TX_CPA"` and set `multiPhaseCheck: true`
2. **If accuracy for gas density/Z-factor is critical** → use `GERG2008`
3. **If heavy oil (C20+)** → use `PR` or `SRK` with `"classic"` mixing rule
4. **Default / unknown** → use `SRK` with `"classic"` mixing rule

---

## 8. Extraction Workflow

Follow this step-by-step process for every extraction:

### Step 1: Identify the Source Type

- **Text description** — paragraph or bullet list describing a process
- **Table / spreadsheet** — heat & mass balance, operating data, well test
- **PFD / sketch** — process flow diagram (described or as image)
- **Data sheet** — equipment data sheet with design conditions
- **Mixed** — combination of above

### Step 2: Extract Fluid Composition

1. Look for: mole fractions, mol%, weight%, component tables
2. Map component names to NeqSim names using the Component Name Mapping table
3. Normalize to mole fractions summing to 1.0
4. If weight% given, note it as an assumption (NeqSim uses mole fractions)
5. If no composition given, flag as missing and use a placeholder

### Step 3: Extract Equipment List

1. Scan for equipment keywords using the Equipment Type Mapping table
2. Match the **longest keyword first** (e.g., "three-phase separator" before "separator")
3. Assign unique names/tags (use P&ID tags if provided, or generate descriptive names)
4. Record the NeqSim `type` for each

### Step 4: Extract Stream Connectivity

1. Look for phrases indicating flow direction: "enters", "goes to", "feeds", "is routed to", "flows to", "passes through"
2. Identify which phase exits which equipment: "gas from the separator", "oil from the 3-phase separator", "compressed gas"
3. Build dot-notation references: `"equipment_name.port"`
4. Verify no orphan streams (every equipment except feed has an inlet)

### Step 5: Extract Operating Conditions

1. Pressures: look for `bara`, `barg`, `bar`, `psi`, `MPa`, `kPa`, `atm`
2. Temperatures: look for `°C`, `°F`, `K`, `degC`, `degF`
3. Flow rates: look for `kg/hr`, `t/h`, `MMSCFD`, `MSm3/d`, `Am3/hr`
4. Convert all to NeqSim standard units (K, bara)
5. Assign to the correct equipment property

### Step 6: Assemble JSON

1. Build the `fluid` section with model, T, P, mixing rule, and components
2. Build the `process` array in topological order (upstream before downstream)
3. First element MUST be a `Stream` with the feed fluid
4. Wire all equipment with `inlet` references
5. Set `autoRun: true`

### Step 7: Validate and Report

1. Check composition sums to ~1.0 (within 0.01)
2. Check all stream references point to existing equipment
3. Check no circular references
4. Compute confidence score (see Confidence Scoring below)
5. List all assumptions made
6. List all missing information detected

---

## 9. Confidence Scoring

Score the extraction confidence on a 0.0–1.0 scale:

| Criterion | Points |
|-----------|--------|
| Fluid composition explicitly provided | +0.25 |
| Feed temperature specified | +0.10 |
| Feed pressure specified | +0.10 |
| Feed flow rate specified | +0.10 |
| All equipment have explicit operating conditions | +0.15 |
| Stream topology clearly described | +0.15 |
| Equipment tags/names from source (not generated) | +0.05 |
| EOS model specified or inferable from context | +0.05 |
| No conflicting information in source | +0.05 |

### Confidence Bands

| Score | Label | Recommendation |
|-------|-------|----------------|
| 0.80–1.00 | **High** | Run directly, review results |
| 0.60–0.79 | **Medium** | Run but flag assumptions for user review |
| 0.40–0.59 | **Low** | More information needed — show what's missing |
| 0.00–0.39 | **Very Low** | Cannot produce reliable simulation — ask user |

---

## 10. Assumption Defaults

When information is not specified, use these engineering defaults and **always track them**:

| Parameter | Default Value | Assumption Text |
|-----------|---------------|-----------------|
| EOS model | SRK | "Default SRK EOS (not specified in source)" |
| Mixing rule | classic | "Classic mixing rule assumed" |
| Feed temperature | 288.15 K (15°C) | "Standard temperature assumed (15°C)" |
| Feed pressure | 1.01325 bara | "Atmospheric pressure assumed" |
| Feed flow rate | 50000 kg/hr | "Default flow rate 50000 kg/hr assumed" |
| Compressor efficiency | 0.75 (isentropic) | "Default isentropic efficiency 0.75 assumed" |
| Cooler outlet temp | 308.15 K (35°C) | "Default cooler outlet 35°C assumed" |
| Composition (no data) | 90% CH4, 5% C2, 3% C3, 2% nC4 | "Placeholder lean gas composition used" |

---

## 11. Process Templates

When the extracted topology matches a known pattern, use a template for better reliability.

### Template: Gas Dew Point Control

**Pattern:** cooler → separator → compressor

```json
{
  "fluid": { "model": "SRK", "temperature": "$FEED_T_K$", "pressure": "$FEED_P$", "mixingRule": "classic", "components": "$COMPOSITION$" },
  "process": [
    {"type": "Stream", "name": "feed", "properties": {"flowRate": ["$FLOW$", "kg/hr"]}},
    {"type": "Cooler", "name": "dew point cooler", "inlet": "feed", "properties": {"outTemperature": "$COOLER_T_K$"}},
    {"type": "Separator", "name": "cold separator", "inlet": "dew point cooler.outlet"},
    {"type": "Compressor", "name": "export compressor", "inlet": "cold separator.gasOut", "properties": {"outletPressure": "$EXPORT_P$", "isentropicEfficiency": 0.78}}
  ],
  "autoRun": true
}
```

### Template: Two-Stage HP/LP Separation

**Pattern:** 3-phase sep → gas compression + oil letdown → LP sep → recompression

```json
{
  "fluid": { "model": "SRK", "temperature": "$FEED_T_K$", "pressure": "$HP_P$", "mixingRule": "classic", "components": "$COMPOSITION$" },
  "process": [
    {"type": "Stream", "name": "well stream", "properties": {"flowRate": ["$FLOW$", "kg/hr"]}},
    {"type": "ThreePhaseSeparator", "name": "HP separator", "inlet": "well stream"},
    {"type": "Cooler", "name": "gas cooler", "inlet": "HP separator.gasOut", "properties": {"outTemperature": 308.15}},
    {"type": "Compressor", "name": "export compressor", "inlet": "gas cooler.outlet", "properties": {"outletPressure": "$EXPORT_P$", "isentropicEfficiency": 0.78}},
    {"type": "ThrottlingValve", "name": "HP-LP valve", "inlet": "HP separator.oilOut", "properties": {"outletPressure": "$LP_P$"}},
    {"type": "Separator", "name": "LP separator", "inlet": "HP-LP valve.outlet"},
    {"type": "Compressor", "name": "LP recompressor", "inlet": "LP separator.gasOut", "properties": {"outletPressure": "$HP_P$", "isentropicEfficiency": 0.75}}
  ],
  "autoRun": true
}
```

### Template: Multi-Stage Compression with Intercooling

**Pattern:** compressor → cooler → scrubber → compressor → cooler → scrubber → ... (N stages)

Build dynamically with equal pressure ratio per stage:

- `ratio_per_stage = (P_out / P_in) ^ (1/N)`
- `stage_P[i] = P_in × ratio_per_stage^i`
- Each stage: `Compressor` → `Cooler` (to intercooler temp) → `Separator` (scrub condensate)
- Last stage: `Compressor` only (no aftercooler/scrubber, unless specified)

### Template: Gas Cooling and JT Expansion

**Pattern:** cooler → separator → JT valve → cold separator

```json
{
  "fluid": { "model": "SRK", "temperature": "$FEED_T_K$", "pressure": "$FEED_P$", "mixingRule": "classic", "components": "$COMPOSITION$" },
  "process": [
    {"type": "Stream", "name": "feed", "properties": {"flowRate": ["$FLOW$", "kg/hr"]}},
    {"type": "Cooler", "name": "pre-cooler", "inlet": "feed", "properties": {"outTemperature": "$PRECOOL_T_K$"}},
    {"type": "Separator", "name": "inlet scrubber", "inlet": "pre-cooler.outlet"},
    {"type": "ThrottlingValve", "name": "JT valve", "inlet": "inlet scrubber.gasOut", "properties": {"outletPressure": "$JT_P$"}},
    {"type": "Separator", "name": "cold separator", "inlet": "JT valve.outlet"}
  ],
  "autoRun": true
}
```

### Template: Simple Oil Stabilization

**Pattern:** 3-phase sep → valve → flash drum → valve → atmospheric flash

```json
{
  "fluid": { "model": "SRK", "temperature": "$FEED_T_K$", "pressure": "$HP_P$", "mixingRule": "classic", "multiPhaseCheck": true, "components": "$COMPOSITION$" },
  "process": [
    {"type": "Stream", "name": "well fluid", "properties": {"flowRate": ["$FLOW$", "kg/hr"]}},
    {"type": "ThreePhaseSeparator", "name": "production separator", "inlet": "well fluid"},
    {"type": "ThrottlingValve", "name": "1st stage valve", "inlet": "production separator.oilOut", "properties": {"outletPressure": "$STAGE2_P$"}},
    {"type": "Separator", "name": "2nd stage separator", "inlet": "1st stage valve.outlet"},
    {"type": "ThrottlingValve", "name": "2nd stage valve", "inlet": "2nd stage separator.liquidOut", "properties": {"outletPressure": "$STAGE3_P$"}},
    {"type": "Separator", "name": "stabilizer", "inlet": "2nd stage valve.outlet"}
  ],
  "autoRun": true
}
```

### Template: Subsea Tieback (Well → Pipeline → Platform)

**Pattern:** well stream → choke → pipeline → separator

```json
{
  "fluid": { "model": "SRK", "temperature": "$WELLHEAD_T_K$", "pressure": "$WELLHEAD_P$", "mixingRule": "classic", "multiPhaseCheck": true, "components": "$COMPOSITION$" },
  "process": [
    {"type": "Stream", "name": "well stream", "properties": {"flowRate": ["$FLOW$", "kg/hr"]}},
    {"type": "ThrottlingValve", "name": "production choke", "inlet": "well stream", "properties": {"outletPressure": "$CHOKE_P$"}},
    {"type": "Heater", "name": "pipeline heat loss", "inlet": "production choke.outlet", "properties": {"outTemperature": "$ARRIVAL_T_K$"}},
    {"type": "ThreePhaseSeparator", "name": "inlet separator", "inlet": "pipeline heat loss.outlet"}
  ],
  "autoRun": true
}
```

### Template: TEG Dehydration

**Pattern:** wet gas → TEG absorber ← lean TEG; dry gas out, rich TEG out

**Note:** `SimpleTEGAbsorber` requires two input streams added via `addGasInStream()` and `addSolventInStream()`. The JSON builder currently wires via the `inlet` field, so for TEG dehydration, build the lean TEG stream as a separate feed with a TEG+water fluid.

```json
{
  "fluids": {
    "wet_gas": {
      "model": "SRK", "temperature": "$FEED_T_K$", "pressure": "$FEED_P$",
      "mixingRule": "classic",
      "components": "$GAS_COMPOSITION_WITH_WATER$"
    },
    "lean_teg": {
      "model": "CPA", "temperature": "$TEG_T_K$", "pressure": "$FEED_P$",
      "mixingRule": "CLASSIC_TX_CPA",
      "components": {"TEG": 0.99, "water": 0.01}
    }
  },
  "process": [
    {"type": "Stream", "name": "wet gas feed", "fluidRef": "wet_gas", "properties": {"flowRate": ["$GAS_FLOW$", "kg/hr"]}},
    {"type": "Stream", "name": "lean TEG", "fluidRef": "lean_teg", "properties": {"flowRate": ["$TEG_FLOW$", "kg/hr"]}},
    {"type": "SimpleTEGAbsorber", "name": "TEG absorber", "inlet": "wet gas feed",
      "properties": {"numberOfStages": "$STAGES$", "stageEfficiency": 0.5}},
    {"type": "Heater", "name": "TEG reboiler sim", "inlet": "TEG absorber.liquidOut",
      "properties": {"outTemperature": "$REBOILER_T_K$"}}
  ],
  "autoRun": true
}
```

**Typical defaults:** 3–5 stages, stage efficiency 0.5, lean TEG flow 5–10× water to remove, reboiler at ~200°C (473 K). TEG purity: 99–99.5 wt%.

### Template: NGL Recovery (Turbo-Expander + Demethanizer)

**Pattern:** gas inlet → cooler → expander → demethanizer column; overhead = sales gas, bottoms = NGL

```json
{
  "fluid": { "model": "SRK", "temperature": "$FEED_T_K$", "pressure": "$FEED_P$", "mixingRule": "classic", "components": "$COMPOSITION$" },
  "process": [
    {"type": "Stream", "name": "inlet gas", "properties": {"flowRate": ["$FLOW$", "kg/hr"]}},
    {"type": "Cooler", "name": "gas chiller", "inlet": "inlet gas", "properties": {"outTemperature": "$CHILLER_T_K$"}},
    {"type": "Separator", "name": "cold separator", "inlet": "gas chiller.outlet"},
    {"type": "Expander", "name": "turbo-expander", "inlet": "cold separator.gasOut", "properties": {"outletPressure": "$EXPANDER_P$", "isentropicEfficiency": 0.85}},
    {"type": "ThrottlingValve", "name": "liquid JT valve", "inlet": "cold separator.liquidOut", "properties": {"outletPressure": "$EXPANDER_P$"}},
    {"type": "Mixer", "name": "column feed mixer", "inlets": ["turbo-expander.outlet", "liquid JT valve.outlet"]},
    {"type": "Separator", "name": "demethanizer sim", "inlet": "column feed mixer.outlet"},
    {"type": "Compressor", "name": "residue compressor", "inlet": "demethanizer sim.gasOut", "properties": {"outletPressure": "$SALES_P$", "isentropicEfficiency": 0.78}}
  ],
  "autoRun": true
}
```

**Note:** For a rigorous demethanizer, replace the Separator with a `Column` (DistillationColumn). The simplified version uses a cold separator as a proxy. Typical expander outlet: 15–25 bara, efficiency 0.82–0.88, chiller to –30°C to –40°C.

### Template: Acid Gas Removal (Amine Sweetening)

**Pattern:** sour gas → amine absorber ← lean amine; sweet gas out, rich amine to regenerator

**Note:** Uses `SimpleTEGAbsorber` which works for generic absorption. For amine-specific thermodynamics, the CPA EOS with MDEA is recommended.

```json
{
  "fluids": {
    "sour_gas": {
      "model": "CPA", "temperature": "$FEED_T_K$", "pressure": "$FEED_P$",
      "mixingRule": "CLASSIC_TX_CPA",
      "components": "$SOUR_GAS_COMPOSITION$"
    },
    "lean_amine": {
      "model": "CPA", "temperature": "$AMINE_T_K$", "pressure": "$FEED_P$",
      "mixingRule": "CLASSIC_TX_CPA",
      "components": {"MDEA": 0.40, "water": 0.60}
    }
  },
  "process": [
    {"type": "Stream", "name": "sour gas feed", "fluidRef": "sour_gas", "properties": {"flowRate": ["$GAS_FLOW$", "kg/hr"]}},
    {"type": "Stream", "name": "lean amine", "fluidRef": "lean_amine", "properties": {"flowRate": ["$AMINE_FLOW$", "kg/hr"]}},
    {"type": "SimpleTEGAbsorber", "name": "amine absorber", "inlet": "sour gas feed",
      "properties": {"numberOfStages": "$STAGES$", "stageEfficiency": 0.5}},
    {"type": "Heater", "name": "amine regenerator sim", "inlet": "amine absorber.liquidOut",
      "properties": {"outTemperature": "$REGEN_T_K$"}}
  ],
  "autoRun": true
}
```

**Typical defaults:** 10–20 stages, MDEA 40–50 wt%, amine circulation rate 50–100 L/kg acid gas, regenerator at 120–130°C. Use CPA EOS with mixing rule "CLASSIC_TX_CPA" for polar systems.

### Template: Produced Water Treatment (Degassing)

**Pattern:** produced water → heater → 3-phase separator → water stripper or flash drum

```json
{
  "fluid": { "model": "CPA", "temperature": "$FEED_T_K$", "pressure": "$FEED_P$", "mixingRule": "CLASSIC_TX_CPA", "multiPhaseCheck": true,
    "components": "$WATER_OIL_GAS_COMPOSITION$" },
  "process": [
    {"type": "Stream", "name": "produced water", "properties": {"flowRate": ["$FLOW$", "kg/hr"]}},
    {"type": "Heater", "name": "water heater", "inlet": "produced water", "properties": {"outTemperature": "$HEATER_T_K$"}},
    {"type": "ThreePhaseSeparator", "name": "water degasser", "inlet": "water heater.outlet"},
    {"type": "ThrottlingValve", "name": "flash valve", "inlet": "water degasser.waterOut", "properties": {"outletPressure": "$FLASH_P$"}},
    {"type": "Separator", "name": "atmospheric flash", "inlet": "flash valve.outlet"}
  ],
  "autoRun": true
}
```

**Typical defaults:** Produced water at 60–80°C, degassing at 1–3 bara. Use CPA EOS with mixing rule "CLASSIC_TX_CPA" when water is a major component. Composition: primarily water (>95 mol%) with dissolved methane, CO2, and trace hydrocarbons.

---

## 12. Worked Examples

### Example 1: Simple Text Description

**Input:**
> "Feed gas at 80 bara and 40°C enters a cooler to 15°C. The cooled stream goes to a separator. Gas from the separator is compressed to 120 bara."

**Extraction:**

| Step | Extracted |
|------|-----------|
| Composition | NOT PROVIDED → flag as missing, use placeholder |
| Feed T | 40°C → `313.15` K |
| Feed P | 80 bara → `80.0` |
| Cooler | Target 15°C → `outTemperature: 288.15` |
| Separator | After cooler, takes gas port |
| Compressor | 120 bara → `outletPressure: 120.0` |

**Output JSON:**
```json
{
  "fluid": {
    "model": "SRK", "temperature": 313.15, "pressure": 80.0,
    "mixingRule": "classic",
    "components": {"methane": 0.90, "ethane": 0.05, "propane": 0.03, "n-butane": 0.02}
  },
  "process": [
    {"type": "Stream", "name": "feed gas", "properties": {"flowRate": [50000.0, "kg/hr"]}},
    {"type": "Cooler", "name": "gas cooler", "inlet": "feed gas", "properties": {"outTemperature": 288.15}},
    {"type": "Separator", "name": "scrubber", "inlet": "gas cooler.outlet"},
    {"type": "Compressor", "name": "export compressor", "inlet": "scrubber.gasOut", "properties": {"outletPressure": 120.0, "isentropicEfficiency": 0.75}}
  ],
  "autoRun": true
}
```

**Report:**
- Confidence: 0.50 (temper

…(truncated)
