118 lines
5.0 KiB
Bash
Executable File
118 lines
5.0 KiB
Bash
Executable File
#!/bin/sh
|
|
# Generates tests/fixtures/nrlmsise00-cases.json: the seventeen standard NRLMSISE-00 test
|
|
# cases, with inputs and outputs at full precision, for a port to be validated against.
|
|
#
|
|
# Fetches Dominik Brodowski's C translation of the NRL Fortran, compiles it with a driver
|
|
# that prints more digits than its own test does, runs it, and throws the source away. What
|
|
# is committed is the numbers, which are facts about the model rather than anyone's code.
|
|
#
|
|
# The model itself is the work of Picone, Hedin and Drob at the US Naval Research
|
|
# Laboratory. Needs a C compiler and network access; rerun it only to regenerate.
|
|
#
|
|
# Usage: scripts/generate-msis-cases.sh
|
|
|
|
set -e
|
|
|
|
root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
|
|
out="$root/tests/fixtures/nrlmsise00-cases.json"
|
|
work=$(mktemp -d)
|
|
trap 'rm -rf "$work"' EXIT
|
|
|
|
base="https://raw.githubusercontent.com/magnific0/nrlmsise-00/master"
|
|
echo "fetching the reference from $base"
|
|
for f in nrlmsise-00.c nrlmsise-00.h nrlmsise-00_data.c; do
|
|
curl -sS --fail --max-time 120 -L "$base/$f" -o "$work/$f"
|
|
done
|
|
digest=$(cat "$work/nrlmsise-00.c" "$work/nrlmsise-00_data.c" | sha256sum | cut -d' ' -f1)
|
|
echo "source digest $digest"
|
|
|
|
cat > "$work/driver.c" <<'DRIVER'
|
|
/* Prints the seventeen standard cases as JSON, at seventeen significant digits.
|
|
*
|
|
* The cases are those of the reference distribution's own test_gtd7, which varies one
|
|
* input at a time from a common baseline: day 172, 29000 s UT, 400 km, 60 N, 70 W, local
|
|
* solar time 16 h, F10.7 and its average 150, ap 4. Cases 15 and 16 use the seven-element
|
|
* ap history instead of the daily value, which is the mode a real propagation runs in. */
|
|
#include <stdio.h>
|
|
#include "nrlmsise-00.h"
|
|
|
|
int main(void) {
|
|
struct nrlmsise_output output[17];
|
|
struct nrlmsise_input input[17];
|
|
struct nrlmsise_flags flags;
|
|
struct ap_array aph;
|
|
int i, j;
|
|
|
|
for (i = 0; i < 7; i++) aph.a[i] = 100;
|
|
flags.switches[0] = 0;
|
|
for (i = 1; i < 24; i++) flags.switches[i] = 1;
|
|
for (i = 0; i < 17; i++) {
|
|
input[i].doy = 172; input[i].year = 0; input[i].sec = 29000;
|
|
input[i].alt = 400; input[i].g_lat = 60; input[i].g_long = -70;
|
|
input[i].lst = 16; input[i].f107A = 150; input[i].f107 = 150; input[i].ap = 4;
|
|
}
|
|
input[1].doy = 81;
|
|
input[2].sec = 75000; input[2].alt = 1000;
|
|
input[3].alt = 100;
|
|
input[10].alt = 0; input[11].alt = 10; input[12].alt = 30;
|
|
input[13].alt = 50; input[14].alt = 70; input[16].alt = 100;
|
|
input[4].g_lat = 0;
|
|
input[5].g_long = 0;
|
|
input[6].lst = 4;
|
|
input[7].f107A = 70;
|
|
input[8].f107 = 180;
|
|
input[9].ap = 40;
|
|
input[15].ap_a = &aph; input[16].ap_a = &aph;
|
|
|
|
for (i = 0; i < 15; i++) gtd7(&input[i], &flags, &output[i]);
|
|
flags.switches[9] = -1;
|
|
for (i = 15; i < 17; i++) gtd7(&input[i], &flags, &output[i]);
|
|
|
|
printf("[\n");
|
|
for (i = 0; i < 17; i++) {
|
|
printf(" {\"case\": %d,\n", i);
|
|
printf(" \"day_of_year\": %d, \"seconds_of_day\": %.17e,\n",
|
|
input[i].doy, input[i].sec);
|
|
printf(" \"altitude_km\": %.17e, \"latitude_deg\": %.17e, \"longitude_deg\": %.17e,\n",
|
|
input[i].alt, input[i].g_lat, input[i].g_long);
|
|
printf(" \"local_solar_time_h\": %.17e,\n", input[i].lst);
|
|
printf(" \"f107_average\": %.17e, \"f107\": %.17e, \"ap_daily\": %.17e,\n",
|
|
input[i].f107A, input[i].f107, input[i].ap);
|
|
printf(" \"ap_history\": %s,\n", i >= 15 ? "[100,100,100,100,100,100,100]" : "null");
|
|
printf(" \"densities\": [");
|
|
for (j = 0; j < 9; j++) printf("%s%.17e", j ? ", " : "", output[i].d[j]);
|
|
printf("],\n \"temperatures\": [%.17e, %.17e]\n", output[i].t[0], output[i].t[1]);
|
|
printf(" }%s\n", i == 16 ? "" : ",");
|
|
}
|
|
printf("]\n");
|
|
return 0;
|
|
}
|
|
DRIVER
|
|
|
|
cc -O2 -o "$work/driver" "$work/nrlmsise-00.c" "$work/nrlmsise-00_data.c" "$work/driver.c" -lm
|
|
mkdir -p "$(dirname "$out")"
|
|
{
|
|
echo "{"
|
|
echo " \"what\": \"The seventeen standard NRLMSISE-00 test cases, for validating a port.\","
|
|
echo " \"model\": \"NRLMSISE-00, by Picone, Hedin and Drob at the US Naval Research Laboratory\","
|
|
echo " \"reference\": \"$base, Dominik Brodowski's C translation of the NRL Fortran\","
|
|
echo " \"reference_sha256\": \"$digest\","
|
|
echo " \"generated\": \"$(date -u +%Y-%m-%d)\","
|
|
echo " \"generated_by\": \"scripts/generate-msis-cases.sh\","
|
|
echo " \"densities\": \"He, O, N2, O2, Ar, total mass, H, N, anomalous O. Number densities in cm^-3 and the total in g/cm^3, which is what the model returns unless its metric switch is set; convert at the boundary.\","
|
|
echo " \"temperatures\": \"exospheric, then at the altitude asked for, in K.\","
|
|
echo " \"cases\":"
|
|
"$work/driver" | sed 's/^/ /'
|
|
echo "}"
|
|
} > "$out"
|
|
|
|
python3 -c "
|
|
import json, sys
|
|
cases = json.load(open('$out'))['cases']
|
|
assert len(cases) == 17, len(cases)
|
|
print(f'wrote tests/fixtures/nrlmsise00-cases.json: {len(cases)} cases')
|
|
for c in (0, 3, 16):
|
|
d = cases[c]
|
|
print(f\" case {d['case']:>2}: {d['altitude_km']:>6.0f} km -> total mass {d['densities'][5]:.6e} g/cm^3\")
|
|
"
|