# `Sidereon.GNSS.PPPCorrections`
[🔗](https://github.com/neilberkman/sidereon-ex/blob/main/lib/sidereon/gnss/ppp_corrections.ex#L1)

Precomputed, state-independent PPP per-range corrections for the static-arc
float/fixed solve: solid-earth tide, carrier-phase wind-up, and satellite
antenna PCO/PCV.

All three depend only on epoch geometry (Sun/Moon direction, satellite
position, and a fixed reference receiver position), not on the estimated
receiver coordinates, so they are computed once before the Gauss-Newton loop
at the seed/approx position and looked up by the row builders and the shared
`range_corrections_m` chokepoint. The Rust core owns the modeling and
orchestration; this module keeps the Sidereon API shape, marshals parsed ANTEX
calibration data across the NIF, and rebuilds the unchanged public maps.

# `t`

```elixir
@type t() :: %{
  tide: %{optional(NaiveDateTime.t()) =&gt; vec3()},
  windup_m: %{optional({String.t(), NaiveDateTime.t()}) =&gt; float()},
  sat_pco_ecef: %{optional({String.t(), NaiveDateTime.t()}) =&gt; vec3()},
  sat_pcv_m: %{optional({String.t(), NaiveDateTime.t()}) =&gt; float()},
  pole_tide: %{optional(NaiveDateTime.t()) =&gt; vec3()},
  ocean_loading: %{optional(NaiveDateTime.t()) =&gt; vec3()}
}
```

# `vec3`

```elixir
@type vec3() :: {float(), float(), float()}
```

# `build`

```elixir
@spec build(Sidereon.GNSS.SP3.t(), [map()], vec3(), keyword() | map()) ::
  {:ok, t()} | {:error, term()}
```

Build the precomputed correction tables for the arc.

`config` keys (all optional; absent = that correction is off):

  * `:solid_earth_tide` - `true` to compute the per-epoch tide displacement.
  * `:phase_windup` - `true` to compute per-(sat,epoch) wind-up metres.
  * `:satellite_antenna` - `%{antex: %Antex{}, freq1: "G01", freq2: "G02"}` to
    compute per-(sat,epoch) satellite PCO (ECEF vector) and nadir PCV (metres).
  * `:pole_tide` - `%{xp_arcsec:, yp_arcsec:}` IERS polar-motion of the date to
    add the solid-earth pole-tide displacement (folded into the `tide` table).
  * `:ocean_loading` - `%{amplitude_m: rows, phase_deg: rows}` BLQ block, three
    rows (radial, west, south) of constituent coefficients, to add the ocean
    tide loading displacement (folded into the `tide` table). The engine does
    not embed BLQ data; the caller supplies the per-station block.

`ref_pos` is the reference receiver ECEF `{x,y,z}` (the solve seed/approx).

# `empty`

```elixir
@spec empty() :: t()
```

Empty correction tables (no precomputed corrections).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
