| from pathlib import Path |
| import math |
| import yaml |
| import numpy as np |
|
|
|
|
| ROOT = Path(__file__).resolve().parents[1] |
|
|
|
|
| def main(): |
| cfg = yaml.safe_load((ROOT / "conf/config.yaml").read_text()) |
| rng = np.random.default_rng(cfg["seed"]) |
| ncol = cfg["data"]["columns"] |
| nwin = cfg["data"]["windows_per_column"] |
| steps = cfg["data"]["window_steps"] |
| levels = cfg["data"]["levels"] |
| dt = cfg["data"]["step_hours"] * 3600.0 |
| total_steps = nwin * steps + 64 |
| sigma = np.linspace(0.02, 0.995, levels, dtype=np.float32) |
| pressure = 100000.0 * sigma |
| interfaces = np.linspace(0.0, 100000.0, levels + 1, dtype=np.float32) |
| layer_mass = np.diff(interfaces) / 9.80665 |
| time = np.arange(total_steps + 1, dtype=np.float32) |
| states = np.empty((ncol, total_steps + 1, 68), dtype=np.float32) |
| surface = np.empty((ncol, total_steps, 3), dtype=np.float32) |
| advection = np.empty((ncol, total_steps + 1, 68), dtype=np.float32) |
| for c in range(ncol): |
| phase = 2.0 * math.pi * c / ncol |
| sl0 = 2.82e5 + 1.25e5 * (1.0 - sigma) + 1400.0 * np.sin(math.pi * sigma + phase) |
| qt0 = 0.0175 * sigma ** 2.6 + 0.00012 + 0.0004 * np.sin(2 * math.pi * sigma + phase) |
| states[c, 0] = np.concatenate((sl0, np.maximum(qt0, 2e-5))) |
| solar = np.maximum(0.0, np.sin(2.0 * math.pi * (time[:-1] % 8.0) / 8.0 + phase)) |
| surface[c, :, 0] = 30.0 + 18.0 * np.sin(2 * math.pi * time[:-1] / 8.0 + phase) |
| surface[c, :, 1] = 92.0 + 34.0 * np.sin(2 * math.pi * time[:-1] / 8.0 + phase - 0.5) |
| surface[c, :, 2] = 760.0 * solar |
| vertical = np.sin(math.pi * sigma) |
| for t in range(total_steps + 1): |
| wave = math.sin(2 * math.pi * t / 16.0 + phase) |
| advection[c, t, :levels] = (0.010 * wave * vertical + rng.normal(0, 0.0003, levels)) |
| advection[c, t, levels:] = (1.4e-9 * wave * vertical + rng.normal(0, 4e-11, levels)) |
| for t in range(total_steps): |
| adv = 0.5 * (advection[c, t] + advection[c, t + 1]) |
| sl, qt = np.split(states[c, t], 2) |
| shf, lhf, solin = surface[c, t] |
| heat = 2.0e-7 * (300000.0 - sl) + 1.0e-5 * shf * sigma + 1.0e-7 * solin * vertical |
| moist = 1.4e-7 * (0.012 * sigma ** 2.4 - qt) + 2.5e-11 * lhf * sigma |
| next_state = states[c, t] + dt * (adv + np.concatenate((heat, moist))) |
| next_state[levels:] = np.maximum(next_state[levels:], 1e-6) |
| states[c, t + 1] = next_state |
| initial, targets, surf_windows, adv_windows, source = [], [], [], [], [] |
| for c in range(ncol): |
| for w in range(nwin): |
| start = w * steps |
| initial.append(states[c, start]) |
| targets.append(states[c, start:start + steps + 1]) |
| surf_windows.append(surface[c, start:start + steps]) |
| adv_windows.append(advection[c, start:start + steps + 1]) |
| source.append(c) |
| out = ROOT / cfg["data"]["file"] |
| out.parent.mkdir(parents=True, exist_ok=True) |
| np.savez_compressed(out, initial=np.array(initial), target=np.array(targets), |
| surface=np.array(surf_windows), advection=np.array(adv_windows), |
| layer_mass=layer_mass, pressure=pressure, source=np.array(source), |
| long_state=states, long_surface=surface, long_advection=advection, |
| dt_seconds=np.float32(dt), format_version=cfg["data"]["format_version"]) |
| print(f"saved {out}: windows={len(initial)}, T={steps}, levels={levels}") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|