# Wellhead choke (API 6A)

Angle-body wellhead choke: forged block body with side inlet and bottom outlet, hammer-nut bonnet with three lugs, stem position indicator and handwheel, an electro-hydraulic stepping actuator, or a positive (fixed bean) blanking cap. API 6B/6BX end flanges sized from bore and working pressure; the 5,000 psi 6B bolt pattern matches ASME Class 1500, which is the class the ports report (10,000 psi reports Class 2500, the closest).

**Standards:** API 6A, API 6B / 6BX

## Installation

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

Copies `wellhead/choke-valve.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 { ChokeValve } from './components/deck-twin/wellhead/choke-valve'

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

## Props

| Prop | Type | Default | Range |
| --- | --- | --- | --- |
| `bore` | `2.0625 \| 2.5625 \| 3.125 \| 4.0625` | `3.125` |  |
| `outletBore` | `2.0625 \| 2.5625 \| 3.125 \| 4.0625` | `3.125` |  |
| `pressureRating` | `5000 \| 10000` | `5000` |  |
| `operator` | `"handwheel" \| "actuator" \| "positive"` | `"handwheel"` |  |
| `opening` | `number` | `0.5` | 0 – 1 |
| `tag` | `string` | `"HCV-101"` |  |
| `...group` | position, rotation, scale… |  |  |

## Ports

Flange faces in the component's local frame, metres. Origin: pipe centreline, flow along X.

| Id | Label | Position | Direction | Size | Class |
| --- | --- | --- | --- | --- | --- |
| `inlet` | Inlet | -0.213, 0.000, 0.000 | -1, 0, 0 | 3" | 1500 |
| `outlet` | Outlet | 0.000, -0.253, 0.000 | 0, -1, 0 | 3" | 1500 |

## P&ID

An angle-body valve (side inlet, bottom outlet) or an in-line bow-tie with a diagonal arrow through it meaning adjustable restriction; a fixed (positive) choke has no arrow and a bean size note. Tagged HCV, PCV, FCV or CK.

tag CK · tag HCV · tag FCV · tag PCV · ISA HCV · ISA HV · ISA FV · ISA PV · ISO 10628-2 / PIP PIC001 valves; API 6A / API RP 14C wellhead conventions (adjustable choke: valve body with a diagonal arrow)

The diagonal arrow = variable choke. An angle body with a spring is a PSV, not a choke. A globe control valve with a dome actuator can also do choking duty; then it is control-valve.

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

| Field | Prop |
| --- | --- |
| Inlet bore | `bore` |
| Outlet bore | `outletBore` |
| Rated working pressure | `pressureRating` |
| Operator | `operator` |
| Tag number | `tag` |

## Typical suppliers

SLB (Cameron) · WOM (Worldwide Oilfield Machine) · Weatherford. The geometry is generic and sized from public standards. It is not vendor CAD.

## Source

`wellhead/choke-valve.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/choke-valve.json has every file.

```tsx
// API 6A angle-body choke: forged block, hammer-nut bonnet, adjustable stem with handwheel or stepping actuator, or positive (fixed bean). API 6A / API 6B-6BX.
import type { Kit } from '../lib/kit'
import { KitMesh, useKit, type GroupProps } from '../lib/mesh'
import { tagPlate } from '../lib/parts'
import { port, type Port } from '../lib/ports'
import { apiFlange, asmeEquivalent, boreNps, type Psi } from './_api6a'
import { angleChoke, chokeDims, openFace, type ChokeOp } from './_wellparts'

export interface ChokeValveProps {
  /** inlet nominal bore, inches */
  bore?: number
  /** outlet nominal bore, inches */
  outletBore?: number
  pressureRating?: Psi
  operator?: ChokeOp
  /** stem position, 0 closed … 1 open */
  opening?: number
  tag?: string
}

export const defaults = {
  bore: 3.125,
  outletBore: 3.125,
  pressureRating: 5000 as Psi,
  operator: 'handwheel' as ChokeOp,
  opening: 0.5,
  tag: 'HCV-101',
}

type P = typeof defaults

function dims(p: P) {
  const dIn = apiFlange(p.bore, p.pressureRating)
  const dOut = apiFlange(p.outletBore, p.pressureRating)
  return { dIn, dOut, ...chokeDims(dIn, dOut) }
}

export function ports(props: ChokeValveProps = {}): Port[] {
  const p = { ...defaults, ...props } as P
  const d = dims(p)
  const r = asmeEquivalent(p.pressureRating)
  return [port('inlet', 'Inlet', [-d.inlet, 0, 0], [-1, 0, 0], boreNps(d.dIn.bore), r), port('outlet', 'Outlet', [0, -d.outlet, 0], [0, -1, 0], boreNps(d.dOut.bore), r)]
}

export function ChokeValve(props: ChokeValveProps & GroupProps) {
  const { bore, outletBore, pressureRating, operator, opening, tag, ...group } = { ...defaults, ...props }
  const p = { bore, outletBore, pressureRating, operator, opening, tag } as P
  const data = useKit((k) => build(k, p), Object.values(p))
  return (
    <group {...group}>
      <KitMesh data={data} />
    </group>
  )
}

export default ChokeValve

function build(k: Kit, p: P) {
  const d = dims(p)
  angleChoke(k, d.dIn, d.dOut, p.operator, p.opening)
  k.at([-d.inlet, 0, 0], '-x', () => openFace(k, d.dIn))
  k.at([0, -d.outlet, 0], '-y', () => openFace(k, d.dOut))
  // body bore liners so the open ends read as hollow
  k.lathe('pipeBore', [[d.dIn.bore * 0.0127, d.inlet], [d.dIn.bore * 0.0127, 0]], [0, 0, 0], '-x', 20)
  k.lathe('pipeBore', [[d.dOut.bore * 0.0127, d.outlet], [d.dOut.bore * 0.0127, 0]], [0, 0, 0], '-y', 20)
  tagPlate(k, p.tag, [0, 0, d.B * 0.46 + 0.001], 'z', Math.min(0.12, d.B * 0.7))
}
```
