Technical Guide

Technical guide

This page will document how the app calculates wave data, filters surf spots, and combines buoy, wind, and tide information.

Sections will be added here over time as the forecast logic is documented.

Temporary Experiments

NOAA wave test page

Use the temporary NOAA test page to verify that the app can pull a live GFS Wave subset for a small box north of Hanalei Bay, including a far-range 16-day request.

Swell Timing

How swell travel time is estimated from a buoy

The app estimates swell timing by treating the swell as a moving line of energy in deep water. It uses the buoy location, the destination shoreline target, and the swell period reported by the buoy.

First, the swell period is converted into an approximate deep-water group speed:

group speed (knots) ≈ 1.515 × swell period (seconds)

Next, the app converts the swell “from” direction into a travel direction by adding 180 degrees. That travel vector is compared against the line from the buoy to the coastline target.

Instead of only using straight-line distance, the app projects the buoy-to-target vector onto the swell travel axis. That produces a signed distance:

signed distance = dot(target - buoy, unitVector(travelDirection))

Travel time is then estimated by dividing that signed distance by the swell group speed:

arrival hours = signed distance / group speed

A positive result means the swell line has not reached the target yet. A negative result means that the swell line has already passed the target. That is why an east or southeast swell can show as “past Hanalei Bay” when viewed from a northwest buoy.

Pseudocode

travelDirection = swellFromDirection + 180
groupSpeedKnots = 1.515 * swellPeriodSeconds
signedDistance = dot(targetVectorFromBuoy, unitVector(travelDirection))
arrivalHours = signedDistance / groupSpeedKnots

Swell speed by period

These are the approximate deep-water group speeds used by the app when estimating travel time from a buoy.

Swell periodGroup speedApprox mph
8s12.1 kt13.9 mph
10s15.1 kt17.4 mph
12s18.2 kt20.9 mph
14s21.2 kt24.4 mph
16s24.2 kt27.9 mph
18s27.3 kt31.4 mph

Buoy Power

How buoy power and wave height are estimated

Forecast power in the app is a custom energy-style score based on swell height and swell period. It replaces Surfline's row power as the source of truth for filters and forecast displays.

The calculation starts with the idea that both height and period should matter a lot, especially for long-period reef swell, but neither should dominate too aggressively on its own:

swell power = swell height × swell period

In the formula above:

  • swell height is in feet
  • swell period is in seconds

This means the power score is not a direct physics unit like watts or kilowatts. It is a surf-forecast scoring metric that increases strongly with both size and period.

Forecast row power is then calculated from the matching swells for a spot: the biggest eligible swell power plus half of the second biggest eligible swell power.

Estimated surf height uses a different idea. Instead of reusing period directly, the app maps combined power to a simple linear display scale.

row power = biggest matching swell power + 0.5 × second biggest matching swell power

The power-to-height conversion is intentionally coarse. It is a surf-facing heuristic for filtering and display, not a spot-specific breaking-wave model.

Pseudocode

if swellHeightFeet == null or swellPeriodSeconds == null:
  return null

swellPower = swellHeightFeet * swellPeriodSeconds
rowPower = strongestMatchingSwellPower + 0.5 * secondStrongestMatchingSwellPower

Power To Height Bands

10 power => 1 ft
15 power => 1.5 ft
20 power => 2 ft
25 power => 2.5 ft
30 power => 3 ft
...
power / 10 => estimated surf height in feet
Estimated surfPower band
1 ft10-10
1.5 ft15-15
2 ft20-20
2.5 ft25-25
3 ft30-30
3.5 ft35-35
4 ft40-40
4.5 ft45-45
5 ft50-50
6 ft60-60
7 ft70-70
8 ft80-80
9 ft90-90
10 ft100-100
12 ft120-120
14 ft140-140
16 ft160-160
18 ft180-180
20 ft200-200
25 ft250-250
30 ft300-300
35 ft350-350
40 ft400-400

Example buoy power and wave-height values

These examples use the same formulas documented in this section so you can compare how power and estimated face height scale differently.

Buoy swellCalculationPowerEst. wave face height
2.0 ft @ 8s2.0 × 816.01.6 ft
2.5 ft @ 12s2.5 × 1230.03.0 ft
3.5 ft @ 8s3.5 × 828.02.8 ft
4.0 ft @ 10s4.0 × 1040.04.0 ft
4.9 ft @ 14.8s4.9 × 14.872.57.3 ft
5.4 ft @ 8s5.4 × 843.24.3 ft
6.0 ft @ 12s6.0 × 1272.07.2 ft
6.5 ft @ 8s6.5 × 852.05.2 ft
8.0 ft @ 18s8.0 × 18144.014.4 ft
7.8 ft @ 9s7.8 × 970.27.0 ft
10.0 ft @ 16s10.0 × 16160.016.0 ft
12.0 ft @ 18s12.0 × 18216.021.6 ft
18.0 ft @ 20s18.0 × 20360.036.0 ft

This power score is best used as a relative measure of swell energy. Higher numbers mean more potential surf energy offshore, but they do not directly guarantee a specific breaking wave height at the beach.

The estimated wave-height value is intended to be a more intuitive surf-facing number than power. It is still a coarse heuristic and should be treated as a generic offshore-to-surf estimate, not a spot-specific breaking-wave model.

Direction, refraction, island shadowing, and local bathymetry still determine how much of that energy actually turns into surf at a given spot and how big the final breaking waves appear.