# Piston (lift) check valve

Globe-pattern lift check valve: bulb body with seat-bridge bulge, oval bolted cover with a domed piston guide and centre plug, lifting eye on larger sizes, cast flow arrow, drain plug and nameplate. Used on small-bore and high-pressure lines where a swing check would chatter. Globe face-to-face from ASME B16.10.

**Standards:** BS 1868, API 602, ASME B16.34, ASME B16.10, ASME B16.5

## Installation

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

Copies `valves/check-valve-piston.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 { CheckValvePiston } from './components/deck-twin/valves/check-valve-piston'

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

## Props

| Prop | Type | Default | Range |
| --- | --- | --- | --- |
| `nps` | `number (NPS, in)` | `2` |  |
| `rating` | `150 \| 300 \| 600 \| 900 \| 1500 \| 2500` | `600` |  |
| `tag` | `string` | `""` |  |
| `...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 |
| --- | --- | --- | --- | --- | --- |
| `A` | Inlet | -0.146, 0.000, 0.000 | -1, 0, 0 | 2" | 600 |
| `B` | Outlet | 0.146, 0.000, 0.000 | 1, 0, 0 | 2" | 600 |

## P&ID

Check-valve bow-tie (downstream half filled, flow arrow) with the globe-pattern dot at the centre on some legends; on most P&IDs it is drawn exactly like any check valve.

tag CHV · tag NRV · ISO 10628-2 / ISO 14617-8 / PIP PIC001

Identify it from the valve code (lift / piston check, usually small-bore or high-pressure, NPS 2 and below) rather than the symbol. Swing and dual-plate checks use the same base symbol.

Check valve datasheet (BS 1868 / API 602 / ASME B16.34) fields and the props they set:

| Field | Prop |
| --- | --- |
| Size | `nps` |
| Pressure class | `rating` |
| Tag number | `tag` |

## Source

`valves/check-valve-piston.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/check-valve-piston.json has every file.

```tsx
// Piston (lift) check valve: globe-pattern body, guided piston disc under a bolted cover, cast flow arrow. BS 1868 / API 602 style, ASME B16.10 globe face-to-face.
import type { Kit, MatKey } from '../lib/kit'
import { KitMesh, type GroupProps } from '../lib/mesh'
import { port, type Port } from '../lib/ports'
import { faceToFace, type Rating } from '../lib/standards'
import { clamp, globeBody, plateText, plug, useKit2 } from './_body'

export interface CheckValvePistonProps {
  /** nominal pipe size, inches */
  nps?: number
  rating?: Rating
  body?: MatKey
  tag?: string
}

export const defaults = { nps: 2, rating: 600 as Rating, body: 'valveBody' as MatKey, tag: '' }

export function ports(p: CheckValvePistonProps = {}): Port[] {
  const { nps, rating } = { ...defaults, ...p }
  const L = faceToFace('globe', nps, rating)
  return [port('A', 'Inlet', [-L / 2, 0, 0], [-1, 0, 0], nps, rating), port('B', 'Outlet', [L / 2, 0, 0], [1, 0, 0], nps, rating)]
}

export function CheckValvePiston(props: CheckValvePistonProps & GroupProps) {
  const { nps, rating, body, tag, ...group } = { ...defaults, ...props }
  const [fixed] = useKit2((k) => build(k, nps, rating, body, tag), [nps, rating, body, tag])
  return (
    <group {...group}>
      <KitMesh data={fixed} />
    </group>
  )
}

export default CheckValvePiston

function build(k: Kit, nps: number, rating: Rating, M: MatKey, tag: string) {
  const L = faceToFace('globe', nps, rating)
  const g = globeBody(k, nps, rating, L, M, false, tag || plateText(nps, rating, 'LIFT CHECK'), false)
  const { yB, Rg, D, rj } = g
  // domed cover over the piston guide, centre boss with plug, lifting eye on larger sizes
  const rd = rj * 0.74
  const sy = clamp((Rg * 0.5) / rd, 0.25, 0.6)
  k.sphere(M, rd, [0, yB, 0], [1, sy, 1], 36)
  const yc = yB + rd * sy
  plug(k, M, [0, yc - 0.004, 0], 'y', Math.max(0.012, D * 0.12))
  if (nps >= 4) k.torus('flangeSteel', D * 0.15, D * 0.035, [rd * 0.45, yc - D * 0.08, 0], 'x', 8, 20)
}
```
