# Globe valve

Flanged RF globe valve with a bulb body, seat-bridge bulge, bolted bonnet, outside screw & yoke and a rising stem under a non-rising handwheel (bevel gear from NPS 10). Cast flow arrow, drain plug and nameplate. Face-to-face from ASME B16.10 for the class; `open` lifts the stem by the disc lift.

**Standards:** API 623, BS 1873, ASME B16.34, ASME B16.10, ASME B16.5

## Installation

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

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

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

## Props

| Prop | Type | Default | Range |
| --- | --- | --- | --- |
| `nps` | `number (NPS, in)` | `4` |  |
| `rating` | `150 \| 300 \| 600 \| 900 \| 1500 \| 2500` | `300` |  |
| `operator` | `"auto" \| "handwheel" \| "gear"` | `"auto"` |  |
| `open` | `number` | `1` | 0 – 1 |
| `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.178, 0.000, 0.000 | -1, 0, 0 | 4" | 300 |
| `B` | Outlet | 0.178, 0.000, 0.000 | 1, 0, 0 | 4" | 300 |

## P&ID

Bow-tie across the line with a solid black dot at the centre where the triangles meet, and a handwheel stem with a T. Often found as the bypass around a control valve or as a throttling valve.

tag HV · tag HCV · ISO 10628-2 / ISO 14617-8 / PIP PIC001

Solid dot = globe; open circle = ball; plain bow-tie = gate. A bow-tie with a dome actuator is a control valve, which is a globe body too: the actuator decides.

Globe valve datasheet (API 623 / BS 1873 / ASME B16.34) fields and the props they set:

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

## Typical suppliers

Velan. The geometry is generic and sized from public standards. It is not vendor CAD.

## Source

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

```tsx
// Flanged globe valve: bulb body, bolted bonnet, outside screw & yoke, rising stem, handwheel or bevel gear. BS 1873 / API 623, ASME B16.10.
import type { Kit, MatKey } from '../lib/kit'
import { KitMesh, type GroupProps } from '../lib/mesh'
import { port, type Port } from '../lib/ports'
import { faceToFace, handwheelDia, pipeOD, pipeWall, type Rating } from '../lib/standards'
import { clamp, globeBody, osyYoke, plateText, useKit2 } from './_body'

export interface GlobeValveProps {
  /** nominal pipe size, inches */
  nps?: number
  rating?: Rating
  /** auto: bevel gear from NPS 10 */
  operator?: 'auto' | 'handwheel' | 'gear'
  /** disc lift, 0 closed … 1 open */
  open?: number
  body?: MatKey
  tag?: string
}

export const defaults = { nps: 4, rating: 300 as Rating, operator: 'auto' as 'auto' | 'handwheel' | 'gear', open: 1, body: 'valveBody' as MatKey, tag: '' }

/** typical: full lift is a quarter of the seat bore */
const lift = (nps: number) => Math.max(0.012, (pipeOD(nps) / 2 - pipeWall(nps, '80')) * 0.5)

export function ports(p: GlobeValveProps = {}): 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 GlobeValve(props: GlobeValveProps & GroupProps) {
  const { nps, rating, operator, open, body, tag, ...group } = { ...defaults, ...props }
  const gear = operator === 'gear' || (operator === 'auto' && nps >= 10)
  const [fixed, moving] = useKit2((k, mv) => build(k, mv, nps, rating, gear, body, tag), [nps, rating, gear, body, tag])
  return (
    <group {...group}>
      <KitMesh data={fixed} />
      <KitMesh data={moving} position-y={-(1 - clamp(open, 0, 1)) * lift(nps)} />
    </group>
  )
}

export default GlobeValve

function build(k: Kit, mv: Kit, nps: number, rating: Rating, gear: boolean, body: MatKey, tag: string) {
  const L = faceToFace('globe', nps, rating)
  const g = globeBody(k, nps, rating, L, body, false, tag || plateText(nps, rating))
  const { yB, stemR, D } = g
  const y = osyYoke(k, body, yB, D, stemR, Math.max(0.1, 0.06 + D * 1.3)).top
  const hw = handwheelDia('globe', nps, rating)
  let top: number
  if (gear) {
    const gb = clamp(D * 0.8, 0.14, 0.4)
    k.rbox(body, [gb, gb * 0.7, gb * 0.8], gb * 0.08, [0, y + gb * 0.35, 0])
    k.cyl(body, gb * 0.22, gb * 0.7, [0, y + gb * 0.3, gb * 0.6], 'z', 16)
    k.handwheel('handwheel', Math.max(0.35, hw), [0, y + gb * 0.3, gb * 1.0], 'z', 5)
    top = y + gb * 0.7 + lift(nps) + 0.03
    k.cyl('stainless', stemR * 1.8, top - y - gb * 0.7 + 0.02, [0, (top + y + gb * 0.7) / 2 + 0.01, 0], 'y', 14, undefined, true)
    k.disc('stainless', stemR * 1.8, [0, top + 0.02, 0], 'y', 14)
  } else {
    k.handwheel('handwheel', hw, [0, y + 0.01, 0], 'y', hw > 0.35 ? 6 : 5)
    k.hex('nut', stemR * 3.2, stemR * 1.4, [0, y + 0.01 + hw * 0.07, 0])
    top = y + 0.02 + hw * 0.07 + lift(nps) + 0.02
  }
  mv.cyl('stainless', stemR, top - yB, [0, (top + yB) / 2, 0], 'y', 12)
  mv.cyl('stainless', stemR * 1.12, 0.006, [0, top, 0], 'y', 12)
}
```
