# Wellhead (casing head and spools)

Surface wellhead without a tree, on a conductor and landing plate. It has a casing head plus casing and tubing head spools (one to three sections by height), studded annulus outlets with gate valves, B16.5 crossovers and gauges on one side and VR-plugged blind outlets on the other, hanger lockdown screws, secondary-seal test ports and the SCSSV control-line exit. The top is either a blind flange with a bleed valve and gauge, or an open ring-joint face ready for a tree or BOP. The `annulus-*` ports are numbered from the tubing head down.

**Standards:** API 6A, API 6B / 6BX, ASME B16.5

## Installation

```bash
npx -y https://decktwin.com/cli/deck-twin-0.2.2.tgz add wellhead-housing
```

Copies `wellhead/wellhead-housing.tsx`, any helper files it imports and the shared `lib/` into `src/components/deck-twin/`. Needs `three`, `@react-three/fiber` and `@react-three/drei`.

## Usage

```tsx
import { Canvas } from '@react-three/fiber'
import { OrbitControls } from '@react-three/drei'
import { Stage } from './components/deck-twin/lib/stage'
import { WellheadHousing } from './components/deck-twin/wellhead/wellhead-housing'

export default function Scene() {
  return (
    <Canvas shadows camera={{ position: [8, 5, 9], fov: 35 }}>
      <Stage>
        <WellheadHousing />
      </Stage>
      <OrbitControls makeDefault />
    </Canvas>
  )
}
```

## Props

| Prop | Type | Default | Range |
| --- | --- | --- | --- |
| `pressureRating` | `5000 \| 10000` | `5000` |  |
| `wellheadHeight` | `number (m)` | `1.1` | 0.5 – 2 |
| `top` | `"blind" \| "open"` | `"blind"` |  |
| `tag` | `string` | `"WH-101"` |  |
| `...group` | position, rotation, scale… |  |  |

## Ports

Flange faces in the component's local frame, metres. Origin: centre of the footprint at deck level (y = 0).

| Id | Label | Position | Direction | Size | Class |
| --- | --- | --- | --- | --- | --- |
| `annulus-a` | A annulus | 0.773, 0.838, 0.000 | 1, 0, 0 | 2" | 1500 |
| `annulus-b` | B annulus | 0.547, 0.284, -0.547 | 0.71, 0, -0.71 | 2" | 1500 |

## P&ID

A stack of rectangles (casing head at the bottom, casing and tubing head spools above) on the conductor, each with side annulus outlets carrying gate valves and gauges; a blind flange or tree adapter on top.

tag WH · tag W · ISA PI · ISA PT · ISO 10628-2 / PIP PIC001 valves; API 6A / API RP 14C wellhead conventions

Only annulus side outlets and no wing / choke means a wellhead without a tree (suspended well, or below a BOP). With a valve stack and choke on top it is a christmas-tree. ISA codes here: PI = annulus; PT = annulus.

Wellhead datasheet (API 6A) fields and the props they set:

| Field | Prop |
| --- | --- |
| Rated working pressure | `pressureRating` |
| Top connection | `top` |
| Tag number | `tag` |

## Typical suppliers

Sentry Wellhead Systems · Baker Hughes (Vetco Gray) · SLB (Cameron). The geometry is generic and sized from public standards. It is not vendor CAD.

## Source

`wellhead/wellhead-housing.tsx`. This is the component file only: it imports shared code, so install it with the command above rather than pasting it alone. https://decktwin.com/r/wellhead-housing.json has every file.

```tsx
// Surface wellhead without a tree: casing head, casing / tubing head spools, annulus outlet valves, lockdown screws, test ports, top blind or open. API 6A.
import type { Kit } from '../lib/kit'
import { KitMesh, useKit, type GroupProps } from '../lib/mesh'
import { gauge, tagPlate } from '../lib/parts'
import { port, type Port } from '../lib/ports'
import type { Psi } from './_api6a'
import { buildWellhead, wellheadLayout } from './_wellhead'
import { G, bore, flangeAt, joint, needleValve, openFace } from './_wellparts'

export interface WellheadHousingProps {
  pressureRating?: Psi
  /** casing head + spools height, m (< 0.6 compact, ≤ 1.3 two sections, else three) */
  wellheadHeight?: number
  /** tubing head top: blind flange with gauge, or open face ready for a tree / BOP */
  top?: 'blind' | 'open'
  tag?: string
}

export const defaults = { pressureRating: 5000 as Psi, wellheadHeight: 1.1, top: 'blind' as 'blind' | 'open', tag: 'WH-101' }

type P = typeof defaults

export function ports(props: WellheadHousingProps = {}): Port[] {
  const p = { ...defaults, ...props } as P
  const W = wellheadLayout({ psi: p.pressureRating, height: p.wellheadHeight, crossovers: true })
  return W.outlets.map((o) => port(o.id, `${o.id.replace('annulus-', '').toUpperCase()} annulus`, o.face, o.u, o.nps, o.rating, 'utility'))
}

export function WellheadHousing(props: WellheadHousingProps & GroupProps) {
  const { pressureRating, wellheadHeight, top, tag, ...group } = { ...defaults, ...props }
  const p = { pressureRating, wellheadHeight, top, tag } as P
  const data = useKit((k) => build(k, p), Object.values(p))
  return (
    <group {...group}>
      <KitMesh data={data} />
    </group>
  )
}

export default WellheadHousing

function build(k: Kit, p: P) {
  const W = buildWellhead(k, { psi: p.pressureRating, height: p.wellheadHeight, crossovers: true })
  const F = W.F11
  const sp = W.spools[W.spools.length - 1]
  const rb = Math.max(sp.ft.od, sp.fb?.od ?? 0) * 0.36
  bore(k, Math.min(rb * 0.55, 0.16), sp.y0 + 0.05, W.T - G)
  k.at([0, W.T, 0], undefined, () => {
    if (p.top === 'blind') {
      joint(k, F, 0)
      flangeAt(k, F, 0, 1, 'flangeSteel')
      // test / bleed port with needle valve and gauge, lifting eye
      needleValve(k, [0, G + F.t, 0], 'y')
      k.rod('stainless', [0, G + F.t + 0.105, 0], [0, G + F.t + 0.16, 0], 0.008, 8)
      gauge(k, [0, G + F.t + 0.22, 0], 'z', 0.1, 'bar', p.pressureRating >= 10000 ? 1000 : 400)
      k.torus('flangeSteel', 0.05, 0.014, [F.od * 0.3, G + F.t + 0.05, 0], 'z', 8, 20)
      k.box('flangeSteel', [0.06, 0.04, 0.04], [F.od * 0.3, G + F.t + 0.01, 0])
    } else openFace(k, F)
  })
  tagPlate(k, p.tag, [0, (sp.y0 + W.T) / 2, -rb - 0.003], '-z', 0.16)
}
```
