forked from gsn/predictor
updated downloader
This commit is contained in:
parent
ca95e06ab7
commit
8e9f117799
30 changed files with 1209 additions and 698 deletions
|
|
@ -4,30 +4,100 @@ import "math"
|
|||
|
||||
func lerp(a, b, t float64) float64 { return a + t*(b-a) }
|
||||
|
||||
// Interpolate 16‑point (time, p, lat, lon)
|
||||
// ghInterp returns interpolated geopotential height at given time/pressure/lat/lon
|
||||
func (d *dataset) ghInterp(ti, pi int, y0, y1, x0, x1 int, wy, wx float64) float64 {
|
||||
g00 := d.cube.val(0, ti, pi, y0, x0)
|
||||
g10 := d.cube.val(0, ti, pi, y0, x1)
|
||||
g01 := d.cube.val(0, ti, pi, y1, x0)
|
||||
g11 := d.cube.val(0, ti, pi, y1, x1)
|
||||
return (1-wy)*((1-wx)*float64(g00)+wx*float64(g10)) + wy*((1-wx)*float64(g01)+wx*float64(g11))
|
||||
}
|
||||
|
||||
// searchAltLevel uses geopotential height to find pressure level bracket for target altitude.
|
||||
func (d *dataset) searchAltLevel(alt float64, ti, y0, y1, x0, x1 int, wy, wx float64) (int, float64) {
|
||||
levels := d.ds.Levels
|
||||
nLevels := len(levels)
|
||||
|
||||
lo, hi := 0, nLevels-1
|
||||
for lo < hi-1 {
|
||||
mid := (lo + hi) / 2
|
||||
ghMid := d.ghInterp(ti, mid, y0, y1, x0, x1, wy, wx)
|
||||
if ghMid < alt {
|
||||
lo = mid
|
||||
} else {
|
||||
hi = mid
|
||||
}
|
||||
}
|
||||
|
||||
ghLo := d.ghInterp(ti, lo, y0, y1, x0, x1, wy, wx)
|
||||
ghHi := d.ghInterp(ti, hi, y0, y1, x0, x1, wy, wx)
|
||||
|
||||
wp := 0.0
|
||||
if ghHi != ghLo {
|
||||
wp = (alt - ghLo) / (ghHi - ghLo)
|
||||
}
|
||||
if wp < 0 {
|
||||
wp = 0
|
||||
}
|
||||
if wp > 1 {
|
||||
wp = 1
|
||||
}
|
||||
|
||||
return lo, wp
|
||||
}
|
||||
|
||||
// uv выполняет интерполяцию ветра по 4 измерениям (time, pressure, lat, lon).
|
||||
func (d *dataset) uv(lat, lon, alt float64, tHours float64) (float64, float64) {
|
||||
if lon < 0 {
|
||||
lon += 360
|
||||
}
|
||||
iy := (lat + 90) * 2
|
||||
|
||||
inv := d.ds.InvResolution()
|
||||
|
||||
// GRIB scan north→south: index 0 = 90°N
|
||||
iy := (90 - lat) * inv
|
||||
y0 := int(math.Floor(iy))
|
||||
if y0 < 0 {
|
||||
y0 = 0
|
||||
}
|
||||
if y0 >= d.cube.lat-1 {
|
||||
y0 = d.cube.lat - 2
|
||||
}
|
||||
y1 := y0 + 1
|
||||
wy := iy - float64(y0)
|
||||
ix := lon * 2
|
||||
|
||||
ix := lon * inv
|
||||
x0 := int(math.Floor(ix)) % d.cube.lon
|
||||
x1 := (x0 + 1) % d.cube.lon
|
||||
wx := ix - float64(x0)
|
||||
// For 3-hourly data (step = 3 hours)
|
||||
// Convert tHours to 3-hour index (e.g., 1.5 hours -> index 0.5, interpolate between 0 and 1)
|
||||
it0 := int(math.Floor(tHours / 3.0))
|
||||
wt := (tHours - float64(it0*3)) / 3.0 // Interpolation weight within 3-hour window
|
||||
|
||||
// Время: tHours делим на шаг, чтобы получить индекс в кубе
|
||||
tIdx := tHours / float64(d.ds.TimeStep)
|
||||
it0 := int(math.Floor(tIdx))
|
||||
if it0 < 0 {
|
||||
it0 = 0
|
||||
}
|
||||
if it0 >= d.cube.t-1 {
|
||||
it0 = d.cube.t - 2
|
||||
}
|
||||
wt := tIdx - float64(it0)
|
||||
|
||||
// ISA: высота → давление → индекс уровня
|
||||
levels := d.ds.Levels
|
||||
p := pressureFromAlt(alt)
|
||||
ip0 := 0
|
||||
for ip0+1 < len(pressureLevels) && pressureLevels[ip0+1] > p {
|
||||
for ip0+1 < len(levels) && levels[ip0+1] > p {
|
||||
ip0++
|
||||
}
|
||||
ip1 := ip0 + 1
|
||||
wp := (pressureLevels[ip0] - p) / (pressureLevels[ip0] - pressureLevels[ip1])
|
||||
if ip1 >= len(levels) {
|
||||
ip1 = len(levels) - 1
|
||||
}
|
||||
wp := 0.0
|
||||
if levels[ip0] != levels[ip1] {
|
||||
wp = (levels[ip0] - p) / (levels[ip0] - levels[ip1])
|
||||
}
|
||||
|
||||
fetch := func(ti, pi int) (float64, float64) {
|
||||
u00 := d.cube.val(1, ti, pi, y0, x0)
|
||||
u10 := d.cube.val(1, ti, pi, y0, x1)
|
||||
|
|
@ -41,6 +111,7 @@ func (d *dataset) uv(lat, lon, alt float64, tHours float64) (float64, float64) {
|
|||
vxy := (1-wy)*((1-wx)*float64(v00)+wx*float64(v10)) + wy*((1-wx)*float64(v01)+wx*float64(v11))
|
||||
return uxy, vxy
|
||||
}
|
||||
|
||||
u0p0, v0p0 := fetch(it0, ip0)
|
||||
u0p1, v0p1 := fetch(it0, ip1)
|
||||
u1p0, v1p0 := fetch(it0+1, ip0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue