mirror of
https://github.com/acamarata/nrel-spa.git
synced 2026-07-03 20:30:38 +00:00
style: fix prettier table formatting in wiki
This commit is contained in:
parent
13c1145fcc
commit
7b6b413908
6 changed files with 130 additions and 126 deletions
|
|
@ -9,7 +9,7 @@ Computes solar position for the given date and location. Returns raw numerical v
|
||||||
**Parameters:**
|
**Parameters:**
|
||||||
|
|
||||||
| Parameter | Type | Required | Description |
|
| Parameter | Type | Required | Description |
|
||||||
| --- | --- | --- | --- |
|
| ----------- | ----------------------- | -------- | ------------------------------------------------------------------------------------------------ |
|
||||||
| `date` | `Date` | Yes | UTC date and time. Uses UTC components internally. |
|
| `date` | `Date` | Yes | UTC date and time. Uses UTC components internally. |
|
||||||
| `latitude` | `number` | Yes | Observer latitude, -90 to 90. Negative = south. |
|
| `latitude` | `number` | Yes | Observer latitude, -90 to 90. Negative = south. |
|
||||||
| `longitude` | `number` | Yes | Observer longitude, -180 to 180. Negative = west. |
|
| `longitude` | `number` | Yes | Observer longitude, -180 to 180. Negative = west. |
|
||||||
|
|
@ -45,6 +45,7 @@ interface SpaAnglesResult {
|
||||||
```
|
```
|
||||||
|
|
||||||
**Throws:**
|
**Throws:**
|
||||||
|
|
||||||
- `TypeError` if `date` is not a valid Date, or `latitude`/`longitude` are not finite numbers
|
- `TypeError` if `date` is not a valid Date, or `latitude`/`longitude` are not finite numbers
|
||||||
- `RangeError` if `latitude` is outside [-90, 90] or `longitude` outside [-180, 180]
|
- `RangeError` if `latitude` is outside [-90, 90] or `longitude` outside [-180, 180]
|
||||||
- `RangeError` if `options.function` is not 0, 1, 2, or 3
|
- `RangeError` if `options.function` is not 0, 1, 2, or 3
|
||||||
|
|
@ -89,12 +90,12 @@ interface SpaFormattedAnglesResult {
|
||||||
Converts a fractional hour value to `HH:MM:SS` format.
|
Converts a fractional hour value to `HH:MM:SS` format.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
formatTime(5.417489) // "05:25:03"
|
formatTime(5.417489); // "05:25:03"
|
||||||
formatTime(12) // "12:00:00"
|
formatTime(12); // "12:00:00"
|
||||||
formatTime(23.9997) // "23:59:59"
|
formatTime(23.9997); // "23:59:59"
|
||||||
formatTime(-1) // "N/A"
|
formatTime(-1); // "N/A"
|
||||||
formatTime(NaN) // "N/A"
|
formatTime(NaN); // "N/A"
|
||||||
formatTime(Infinity) // "N/A"
|
formatTime(Infinity); // "N/A"
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -104,7 +105,7 @@ formatTime(Infinity) // "N/A"
|
||||||
All options are optional. Defaults match the NREL C reference implementation.
|
All options are optional. Defaults match the NREL C reference implementation.
|
||||||
|
|
||||||
| Option | Type | Default | Description |
|
| Option | Type | Default | Description |
|
||||||
| --- | --- | --- | --- |
|
| --------------- | ----------------- | ------------ | ----------------------------------------------------------------------------------------- |
|
||||||
| `elevation` | `number` | `0` | Observer elevation above sea level in meters. |
|
| `elevation` | `number` | `0` | Observer elevation above sea level in meters. |
|
||||||
| `pressure` | `number` | `1013` | Annual average atmospheric pressure in millibars. |
|
| `pressure` | `number` | `1013` | Annual average atmospheric pressure in millibars. |
|
||||||
| `temperature` | `number` | `15` | Annual average temperature in degrees Celsius. |
|
| `temperature` | `number` | `15` | Annual average temperature in degrees Celsius. |
|
||||||
|
|
@ -124,7 +125,7 @@ import { SPA_ZA, SPA_ZA_INC, SPA_ZA_RTS, SPA_ALL } from 'nrel-spa';
|
||||||
```
|
```
|
||||||
|
|
||||||
| Constant | Value | Outputs Computed |
|
| Constant | Value | Outputs Computed |
|
||||||
| --- | --- | --- |
|
| ------------ | ----- | -------------------------------------------------------------------------- |
|
||||||
| `SPA_ZA` | `0` | `zenith`, `azimuth` |
|
| `SPA_ZA` | `0` | `zenith`, `azimuth` |
|
||||||
| `SPA_ZA_INC` | `1` | `zenith`, `azimuth`, incidence angle (for solar panels on sloped surfaces) |
|
| `SPA_ZA_INC` | `1` | `zenith`, `azimuth`, incidence angle (for solar panels on sloped surfaces) |
|
||||||
| `SPA_ZA_RTS` | `2` | `zenith`, `azimuth`, `sunrise`, `solarNoon`, `sunset` |
|
| `SPA_ZA_RTS` | `2` | `zenith`, `azimuth`, `sunrise`, `solarNoon`, `sunset` |
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ nrel-spa/
|
||||||
**lib/spa.js** is the core mathematical engine. It is a direct JavaScript port of the NREL C source (`spa.c`), preserving function names, variable names, and the algorithm structure. The file is checked into git and shipped in the npm package.
|
**lib/spa.js** is the core mathematical engine. It is a direct JavaScript port of the NREL C source (`spa.c`), preserving function names, variable names, and the algorithm structure. The file is checked into git and shipped in the npm package.
|
||||||
|
|
||||||
**src/index.ts** is a thin TypeScript wrapper. It:
|
**src/index.ts** is a thin TypeScript wrapper. It:
|
||||||
|
|
||||||
- Loads `lib/spa.js` at runtime
|
- Loads `lib/spa.js` at runtime
|
||||||
- Validates input parameters, throwing `TypeError` or `RangeError` for invalid values
|
- Validates input parameters, throwing `TypeError` or `RangeError` for invalid values
|
||||||
- Validates `options.function` and throws `RangeError` for out-of-range codes
|
- Validates `options.function` and throws `RangeError` for out-of-range codes
|
||||||
|
|
@ -32,6 +33,7 @@ nrel-spa/
|
||||||
- Provides `formatTime()` as a standalone export
|
- Provides `formatTime()` as a standalone export
|
||||||
|
|
||||||
**src/types.ts** exports all public TypeScript interfaces and constants:
|
**src/types.ts** exports all public TypeScript interfaces and constants:
|
||||||
|
|
||||||
- `SpaOptions`: atmospheric and calculation parameters
|
- `SpaOptions`: atmospheric and calculation parameters
|
||||||
- `SpaResult` / `SpaFormattedResult`: base return types for `getSpa` / `calcSpa`
|
- `SpaResult` / `SpaFormattedResult`: base return types for `getSpa` / `calcSpa`
|
||||||
- `SpaAnglesResult` / `SpaFormattedAnglesResult`: per-angle entries in the `angles` array
|
- `SpaAnglesResult` / `SpaFormattedAnglesResult`: per-angle entries in the `angles` array
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Three implementations of the NREL Solar Position Algorithm exist in this ecosystem. This page documents their accuracy against the original C reference and their throughput on Node.js.
|
Three implementations of the NREL Solar Position Algorithm exist in this ecosystem. This page documents their accuracy against the original C reference and their throughput on Node.js.
|
||||||
|
|
||||||
| | [NREL C reference](https://midcdmz.nrel.gov/spa/) | [nrel-spa](https://www.npmjs.com/package/nrel-spa) | [solar-spa](https://www.npmjs.com/package/solar-spa) |
|
| | [NREL C reference](https://midcdmz.nrel.gov/spa/) | [nrel-spa](https://www.npmjs.com/package/nrel-spa) | [solar-spa](https://www.npmjs.com/package/solar-spa) |
|
||||||
| --- | --- | --- | --- |
|
| ---------------- | ------------------------------------------------- | -------------------------------------------------- | ---------------------------------------------------- |
|
||||||
| **Language** | C (gcc -O2) | JavaScript (JS port) | WebAssembly (Emscripten) |
|
| **Language** | C (gcc -O2) | JavaScript (JS port) | WebAssembly (Emscripten) |
|
||||||
| **Source** | Original C | Hand-ported | Compiled from same C |
|
| **Source** | Original C | Hand-ported | Compiled from same C |
|
||||||
| **Async init** | No | No | Yes (`await init()`) |
|
| **Async init** | No | No | Yes (`await init()`) |
|
||||||
|
|
@ -20,7 +20,7 @@ Tested across eight global locations and three dates spanning both hemispheres,
|
||||||
**Environment:** Node.js v24.6.0. Inputs: local midnight at each location. Atmospheric defaults: pressure 1013 mb, temperature varies by season, elevation as noted. `delta_t = 67` seconds (NREL default).
|
**Environment:** Node.js v24.6.0. Inputs: local midnight at each location. Atmospheric defaults: pressure 1013 mb, temperature varies by season, elevation as noted. `delta_t = 67` seconds (NREL default).
|
||||||
|
|
||||||
| Location | Date | Field | C Reference | nrel-spa | Δ (s) | solar-spa | Δ (s) |
|
| Location | Date | Field | C Reference | nrel-spa | Δ (s) | solar-spa | Δ (s) |
|
||||||
| --- | --- | --- | --- | --- | ---: | --- | ---: |
|
| ---------------------- | ------ | ---------- | ----------- | -------- | ---------: | --------- | ---------: |
|
||||||
| New York (40.7°N) | Jun 21 | Sunrise | 05:25:03 | 05:25:03 | 0.04 | 05:25:03 | 0.04 |
|
| New York (40.7°N) | Jun 21 | Sunrise | 05:25:03 | 05:25:03 | 0.04 | 05:25:03 | 0.04 |
|
||||||
| | | Solar noon | 12:57:56 | 12:57:56 | 0.40 | 12:57:56 | 0.40 |
|
| | | Solar noon | 12:57:56 | 12:57:56 | 0.40 | 12:57:56 | 0.40 |
|
||||||
| | | Sunset | 20:30:35 | 20:30:35 | 0.17 | 20:30:35 | 0.17 |
|
| | | Sunset | 20:30:35 | 20:30:35 | 0.17 | 20:30:35 | 0.17 |
|
||||||
|
|
@ -58,7 +58,7 @@ Polar night is handled correctly. Tromso in December returns the NREL sentinel v
|
||||||
**Environment:** Node.js v24.6.0, macOS. 200,000 iterations per measurement, with a 2,000-iteration warm-up before each run. Test case: New York summer solstice.
|
**Environment:** Node.js v24.6.0, macOS. 200,000 iterations per measurement, with a 2,000-iteration warm-up before each run. Test case: New York summer solstice.
|
||||||
|
|
||||||
| Mode | Implementation | ns/call | calls/s |
|
| Mode | Implementation | ns/call | calls/s |
|
||||||
| --- | --- | ---: | ---: |
|
| -------------------------------------------- | -------------- | ---------: | -------: |
|
||||||
| **SPA_ZA_RTS** (zenith + azimuth + rise/set) | nrel-spa | 84,497 | 11,835 |
|
| **SPA_ZA_RTS** (zenith + azimuth + rise/set) | nrel-spa | 84,497 | 11,835 |
|
||||||
| | solar-spa | 45,139 | 22,154 |
|
| | solar-spa | 45,139 | 22,154 |
|
||||||
| **SPA_ZA** (zenith + azimuth only) | nrel-spa | 9,284 | 107,711 |
|
| **SPA_ZA** (zenith + azimuth only) | nrel-spa | 9,284 | 107,711 |
|
||||||
|
|
@ -120,17 +120,20 @@ In short: with nrel-spa, UTC ISO strings are safe. With solar-spa, construct dat
|
||||||
## When to Use Each
|
## When to Use Each
|
||||||
|
|
||||||
**Use nrel-spa when:**
|
**Use nrel-spa when:**
|
||||||
|
|
||||||
- You need synchronous, zero-init execution (serverless functions, edge workers, middleware)
|
- You need synchronous, zero-init execution (serverless functions, edge workers, middleware)
|
||||||
- You are processing individual requests rather than large batches
|
- You are processing individual requests rather than large batches
|
||||||
- You want simple date handling with no machine-timezone surprises
|
- You want simple date handling with no machine-timezone surprises
|
||||||
- Bundle size matters (nrel-spa is smaller; no WASM blob)
|
- Bundle size matters (nrel-spa is smaller; no WASM blob)
|
||||||
|
|
||||||
**Use solar-spa when:**
|
**Use solar-spa when:**
|
||||||
|
|
||||||
- You are pre-computing thousands or millions of solar positions in a batch
|
- You are pre-computing thousands or millions of solar positions in a batch
|
||||||
- You have already paid the async init cost and want maximum throughput
|
- You have already paid the async init cost and want maximum throughput
|
||||||
- You need the full SPA output struct including incidence angle, equation of time, and sun transit altitude
|
- You need the full SPA output struct including incidence angle, equation of time, and sun transit altitude
|
||||||
|
|
||||||
**Use the C reference when:**
|
**Use the C reference when:**
|
||||||
|
|
||||||
- You are writing native code or a library that wraps native code
|
- You are writing native code or a library that wraps native code
|
||||||
- You need validated output for scientific publication
|
- You need validated output for scientific publication
|
||||||
- Runtime performance is the primary constraint
|
- Runtime performance is the primary constraint
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
The Solar Position Algorithm (SPA) was developed by Ibrahim Reda and Afshin Andreas at the National Renewable Energy Laboratory (NREL) and published in 2004. It is the reference algorithm for solar position calculation in scientific and engineering applications.
|
The Solar Position Algorithm (SPA) was developed by Ibrahim Reda and Afshin Andreas at the National Renewable Energy Laboratory (NREL) and published in 2004. It is the reference algorithm for solar position calculation in scientific and engineering applications.
|
||||||
|
|
||||||
**Citation:**
|
**Citation:**
|
||||||
|
|
||||||
> Reda, I., Andreas, A. (2004). "Solar Position Algorithm for Solar Radiation Applications." Solar Energy, 76(5), 577-589. https://doi.org/10.1016/j.solener.2003.12.003
|
> Reda, I., Andreas, A. (2004). "Solar Position Algorithm for Solar Radiation Applications." Solar Energy, 76(5), 577-589. https://doi.org/10.1016/j.solener.2003.12.003
|
||||||
|
|
||||||
**Original C source:** https://midcdmz.nrel.gov/spa/
|
**Original C source:** https://midcdmz.nrel.gov/spa/
|
||||||
|
|
@ -18,7 +19,7 @@ The algorithm achieves uncertainty of +/- 0.0003 degrees in solar zenith and azi
|
||||||
Validation test cases from `bin/test.js`:
|
Validation test cases from `bin/test.js`:
|
||||||
|
|
||||||
| Location | Date | Sunrise (C) | Sunrise (JS) | Noon (C) | Noon (JS) | Sunset (C) | Sunset (JS) |
|
| Location | Date | Sunrise (C) | Sunrise (JS) | Noon (C) | Noon (JS) | Sunset (C) | Sunset (JS) |
|
||||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| --------- | ---------- | ----------- | ------------ | -------- | --------- | ---------- | ----------- |
|
||||||
| New York | 2025-06-21 | 05:25:03 | 05:25:03 | 12:57:56 | 12:57:56 | 20:30:35 | 20:30:35 |
|
| New York | 2025-06-21 | 05:25:03 | 05:25:03 | 12:57:56 | 12:57:56 | 20:30:35 | 20:30:35 |
|
||||||
| New York | 2025-12-21 | 07:16:41 | 07:16:41 | 11:54:19 | 11:54:19 | 16:31:56 | 16:31:56 |
|
| New York | 2025-12-21 | 07:16:41 | 07:16:41 | 11:54:19 | 11:54:19 | 16:31:56 | 16:31:56 |
|
||||||
| London | 2025-06-21 | 04:43:07 | 04:43:07 | 13:02:22 | 13:02:22 | 21:21:37 | 21:21:37 |
|
| London | 2025-06-21 | 04:43:07 | 04:43:07 | 13:02:22 | 13:02:22 | 21:21:37 | 21:21:37 |
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ Standard sunrise and sunset use a zenith angle of approximately 90.833 degrees (
|
||||||
## Standard Twilight Definitions
|
## Standard Twilight Definitions
|
||||||
|
|
||||||
| Type | Zenith Angle | Description |
|
| Type | Zenith Angle | Description |
|
||||||
| --- | --- | --- |
|
| --------------------- | ------------ | ---------------------------------------------------------------- |
|
||||||
| Sunrise / Sunset | ~90.833 | Center of sun at horizon (accounting for refraction) |
|
| Sunrise / Sunset | ~90.833 | Center of sun at horizon (accounting for refraction) |
|
||||||
| Civil twilight | 96 | Sufficient light for outdoor activities without artificial light |
|
| Civil twilight | 96 | Sufficient light for outdoor activities without artificial light |
|
||||||
| Nautical twilight | 102 | Horizon visible; used for celestial navigation |
|
| Nautical twilight | 102 | Horizon visible; used for celestial navigation |
|
||||||
|
|
@ -36,7 +36,7 @@ console.log(result.angles[2].sunrise); // astronomical twilight begin
|
||||||
Expected output for New York, June 21, 2025:
|
Expected output for New York, June 21, 2025:
|
||||||
|
|
||||||
| Event | Time |
|
| Event | Time |
|
||||||
| --- | --- |
|
| --------------------------- | ------ |
|
||||||
| Astronomical twilight begin | ~03:57 |
|
| Astronomical twilight begin | ~03:57 |
|
||||||
| Nautical twilight begin | ~04:28 |
|
| Nautical twilight begin | ~04:28 |
|
||||||
| Civil twilight begin | ~04:53 |
|
| Civil twilight begin | ~04:53 |
|
||||||
|
|
@ -70,10 +70,7 @@ At high latitudes during summer (midnight sun), the sun may not set even at the
|
||||||
```javascript
|
```javascript
|
||||||
import { getSpa } from 'nrel-spa';
|
import { getSpa } from 'nrel-spa';
|
||||||
|
|
||||||
const r = getSpa(
|
const r = getSpa(new Date('2025-06-21T00:00:00Z'), 71, 25, 2, {}, [96]);
|
||||||
new Date('2025-06-21T00:00:00Z'),
|
|
||||||
71, 25, 2, {}, [96],
|
|
||||||
);
|
|
||||||
|
|
||||||
if (r.angles && !isFinite(r.angles[0].sunrise)) {
|
if (r.angles && !isFinite(r.angles[0].sunrise)) {
|
||||||
console.log('No civil twilight at this latitude/date');
|
console.log('No civil twilight at this latitude/date');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue