Public
Pool pump variable speed schedule optimizer
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

Pool Pump VSP Calculator — PLA-VSPcalc

A pool-pump variable-speed cost calculator + schedule optimizer — part of the APEX Pools / PLA toolset by name, but technically standalone (see below). Entirely client-side: pick a pump, filter, and electricity rate, and it estimates running cost, water turnover, and the cheapest schedule to hit a turnover target. Three tabs:

  • Setup — choose a pump (large variable- and single-speed library across Pentair / Hayward / Jandy / Sta-Rite / Waterway / value brands), enter speed programs (RPM + min/day) or a single-speed runtime; set pool volume, filter (DE / cartridge / sand library, or custom max GPM), and plumbing complexity (a head-loss derate); set the electricity rate by ZIP (→ state average), manual, or Time-of-Use (off/peak).
  • Results — live cost/day·month·year and turnover; a recommended optimized schedule (single- or two-speed skim+circulate) to hit a 1.0 / 1.5 / 2.0× turnover target at lowest cost, with one-tap "apply"; a per-speed cost breakdown; filter-overflow warnings; a turnover-time reference; and a Charts & Curves panel (daily schedule, power curve vs cube law, GPM vs filter limit, cost-per-turnover vs RPM).
  • Compare — save up to 8 configurations (current or optimized) and compare as cards or a table, plus an annual-cost bar chart.

Live: https://wohara010--9de0ccb6135711f183cd42dde27851f2.web.val.run

Standalone (despite the PLA- name)

Named for and branded to the APEX Pools business, but there's no runtime coupling to PLA — no shared database, no cross-val fetch. Unlike pool-pricing-calculator, this is fully self-contained (a field/customer pump-sizing tool). Its only state is browser localStorage.

Files

  • main.tsx (http) — the entire app. The handler just returns one big HTML string; all logic is client-side JS inside it. No API routes.

Storage

Browser localStorage only (key pla-vsp-state-v2): pump, filter, pool volume, head factor, rate/TOU settings, speed programs, recommender target, and the saved comparison list. No server-side storage, no auth, no cross-device sync.

Baked-in reference data (edit these to update)

  • VS — variable-speed pumps, each with a power curve [rpm, gpm, watts].
  • SS — single-speed pumps (watts / gpm / amps / volts).
  • FILTERS — DE / cartridge / sand filters + max GPM (+ custom).
  • SR — per-US-state residential $/kWh (EIA Aug 2025 / NEADA), plus a z2s() ZIP-prefix→state table.

These are point-in-time reference data — the rates are dated Aug 2025 and will go stale.

Cost & optimizer model

  • costSegs() is the single source of truth for all $ math. Segments are {watts, hrs}. Flat rate = watts/1000 × hrs × rate. TOU: off-peak hours are a shared daily budget the highest-wattage segments claim first (optimal placement + the app's stated scheduling assumption); hours beyond the off-peak window bill at peak. Per-segment costs always sum to the total.
  • interp() interpolates the pump curve at an RPM; effGPM() = min(rawGPM × headFactor, filterMax) — plumbing derate + filter cap. Over-pumping past the filter max adds cost, not turnover credit (the "over" flag/alerts).
  • recommendSchedule() searches single- and two-speed plans, capped at 16h/day, durations rounded up to 15-min steps, preferring the simpler single-speed unless two-speed saves ≥3%.

Env vars

None.

Gotchas / conventions

  1. All client-side — edit cost logic only in costSegs(); everything else derives from it.
  2. Reference tables go stale — updating pumps/filters/rates means editing VS / SS / FILTERS / SR (rates are EIA Aug 2025).
  3. localStorage-only state (pla-vsp-state-v2) — no server persistence, no PLA coupling.
  4. TOU is an assumption, not a real utility schedule (highest-wattage-off-peak-first).
  5. Turnover credit is filter-capped — flow above the filter's max GPM is billed but not counted.
  6. ZIP→state is an approximate prefix-range map; unmatched ZIPs fall back to manual rate entry.

Working on this val

  • This README is the context file; keep it accurate if the tabs, the baked-in pump/filter/rate tables, or the cost model change.
  • One file with an inline frontend and no backend — verify with a request to the live URL and by exercising Setup → Results → Compare.