# Input Units: the units OpenStaad reads from you

Every number your script **sends** to OpenSTAAD — a node coordinate in `CreateNode`, a load in
`AddNodalLoad`, a distributed force in `AddMemberUniformForce` — is interpreted in the model's
**input units**: whatever the model's current `UNIT` command says, such as `UNIT MMS KN` or
`UNIT FEET KIP`. Unlike base units, your script can read them and change them.

Getting this wrong is silent. Send `3.048` while the input length unit is meters and you have a
3.048 m node; send the same number while it is millimeters and you have a 3 mm one. Nothing raises,
nothing warns.

This page is only about input units, the **set** side. For the units of values you get **back**, see
[Base Units](/docs/base_units); for how the two fit together, see
[Unit Systems](/docs/unit_systems).

---

## Reading the input units

```python
from openstaad import ops

s = ops.connect()

print(s.GetInputUnitForLength())    # e.g. "Meter"
print(s.GetInputUnitForForce())     # e.g. "KiloNewton"
```

Read them before sending anything. They are a property of the open model's current `UNIT` command,
so they can differ from what you expect if the model was authored, or last changed, by someone else.

Input units are **independent of base units**. A session can have English base units and metric
input units at the same time: reads come back in inches while writes are taken as meters. A model
can be authored in `UNIT METER KN`, show meters everywhere in the STAAD.Pro interface, and still
return inches through OpenSTAAD, because its base unit is English. This is working as designed.

---

## Setting the input units

`SetInputUnits()` sets length and force together; `SetInputUnitForLength()` and
`SetInputUnitForForce()` set one at a time. All three take integer codes:

| Code | Length | Force |
|---|---|---|
| 0 | Inch | Kilopound |
| 1 | Feet | Pound |
| 2 | Feet (same as `1`) | Kilogram |
| 3 | CentiMeter | Metric Ton |
| 4 | Meter | Newton |
| 5 | MilliMeter | KiloNewton |
| 6 | DeciMeter | MegaNewton |
| 7 | KiloMeter | DecaNewton |

> Length code `2` is listed upstream as a duplicate of `Feet`, and testing confirms it: with English
> base units, `SetInputUnitForLength(2)` makes `GetInputUnitForLength()` return `"Feet"`, and a node
> sent at `x = 1` comes back as `12.0` in. Use `1` for feet and ignore `2`.

```python
s.SetInputUnits(4, 5)                 # Meter, KiloNewton
print(s.GetInputUnitForLength())      # -> "Meter"
print(s.GetInputUnitForForce())       # -> "KiloNewton"
```

### SetInputUnits changes what you send, not what you get back

They change how values you **write** are interpreted, and how the model **displays** them. They do
not touch how values you read look, but they are **not harmless** — every value you send after
calling them is taken in the new units, silently:

```python
# English base units; input units set to Meter, KiloNewton
s.SetInputUnits(4, 5)
s.GetNodeCoordinates(2)               # (120.0, 0, 0): still inches (base)
s.CreateNode(3, 3.048, 0, 0)          # 3.048 is taken as METERS
s.GetNodeCoordinates(3)               # (119.99976, 0, 0): returned in inches
```

If you need values back in a different unit, no input-unit setting will do it: convert them
yourself. See [Base Units](/docs/base_units).

---

## Derived quantities you send

The same rule holds for derived quantities. A distributed load sent as `-2` with input units m/kN is
stored and returned as `-0.01142` kip/in in an English-base model, because `-2` kN/m is
`-0.01142` kip/in.

What we measured (STAAD.Pro 2025 25.0.1.424, openstaad 0.0.15), with **English** base units:

| Sent value | Input units at send time | Returned (in / kip) |
|---|---|---|
| Node x = 120 | in / kip | 120.0 in |
| Node x = 3.048 | m / kN | 119.99976 in |
| Nodal FY = −10, MZ = 100 | in / kip | −10.0 kip, 100.0 kip·in |
| Nodal FY = −10, MZ = 10 | m / kN | −2.24809 kip, 88.5073 kip·in |
| UDL w = −0.5 | in / kip | −0.5 kip/in |
| UDL w = −2 | m / kN | −0.01142 kip/in |
| Conc. P = −5 at d1 = 60 | in / kip | −5.0 kip at 60.0 in |
| Conc. P = −5 at d1 = 1.5 | m / kN | −1.124 kip at 59.055 in |

The same model with **Metric** base units returns each value in m / kN, whichever input units it was
sent in: a UDL sent as `-0.5` in kip/in reads `-87.56342` kN/m, and one sent as `-2` in kN/m reads
`-2.0` kN/m. Every returned value was identical whether it was read with input units set to in/kip
or to m/kN: input units never change what you read.

---

## Align input units with base units before writing

The simplest safe habit is to set the input units to match the base units before writing, so sent
and returned values share one system:

```python
if s.GetBaseUnit() == "English":
    s.SetInputUnits(0, 0)   # Inch, Kilopound
else:
    s.SetInputUnits(4, 5)   # Meter, KiloNewton
```

If you change them for a while, put them back. Anything else that writes to the same session, or the
next script, inherits whatever you left.

**A precision note:** when STAAD returns a value in inches that was sent in meters, it converts with
**39.37 in/m**, not the exact `1 / 0.0254`. The result is off in the 6th significant digit — 3.048 m
returns as 119.99976 in, not 120. The opposite direction (in → m) and every force conversion were
exact in testing. Values written under one input unit and read after a base-unit switch came back
exact, which suggests STAAD keeps each value in the units it was sent in and converts when it
returns it. Compare round-tripped values with a tolerance, never with `==`.

---

## Checklist

- Read `GetInputUnitForLength()` / `GetInputUnitForForce()` before sending values; every sent value
  is interpreted in those units.
- Prefer aligning input units with base units before writing.
- Never assume `SetInputUnits()` is harmless: it changes how all later writes are interpreted, even
  though it leaves already-read values untouched.
- Restore the input units you found if you change them for one operation.
- Compare round-tripped values with a tolerance — STAAD converts length with 39.37 in/m, not the
  exact inverse of 0.0254.

---

## Further reading

- [Unit Systems](/docs/unit_systems) — how base units and input units work together.
- [Base Units](/docs/base_units) — the units of every value you get back.
- [SetInputUnits](/docs/session-file-root#SetInputUnits) — the function reference, alongside
  `SetInputUnitForLength`, `SetInputUnitForForce`, `GetInputUnitForLength` and `GetInputUnitForForce`.

Source: https://www.openstaad.com/docs/input_units
