PINN-TC / scripts /fake_data.py
zhangrenchao's picture
Upload folder using huggingface_hub
2f3c9e4 verified
Raw
History Blame Contribute Delete
4.28 kB
"""Generate sparse structured observations and collocation coordinates lazily."""
import argparse
import importlib.util
from pathlib import Path
import numpy as np
import yaml
ROOT = Path(__file__).resolve().parents[1]
def load_model_module():
spec = importlib.util.spec_from_file_location("pinn_tc_model", ROOT / "model/pinn-tc.py")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def structured_observations(config, mode):
data = config["data"]
extent = float(data["horizontal_extent_m"])
levels = np.linspace(float(data["pressure_min_pa"]), float(data["pressure_max_pa"]), int(data["pressure_levels"]))
times = np.asarray(data["observation_times_s"], dtype=np.float64)
if times.shape != (int(data["time_steps"]),) or not np.array_equal(times, [-10800.0, 0.0, 10800.0]):
raise ValueError("paper observation times must be [-3h, 0h, +3h]")
line = np.linspace(-extent, extent, int(data["observation_line_points"]))
coordinates = []
for time_index, time in enumerate(times):
active_mode = ("Cross" if time_index % 2 == 0 else "Plus") if mode == "Switch" else mode
for pressure in levels[:: int(data["observation_pressure_stride"])]:
if active_mode == "Plus":
coordinates.extend((y, x, time, pressure) for y, x in zip(np.zeros_like(line), line))
coordinates.extend((y, x, time, pressure) for y, x in zip(line, np.zeros_like(line)))
elif active_mode == "Cross":
coordinates.extend((y, x, time, pressure) for y, x in zip(line, line))
coordinates.extend((y, x, time, pressure) for y, x in zip(line, -line))
else:
raise ValueError("observation mode must be Cross, Plus, or Switch")
edge = np.linspace(-extent, extent, int(data["boundary_points_per_edge"]))
coordinates.extend((-extent, value, time, pressure) for value in edge)
coordinates.extend((extent, value, time, pressure) for value in edge)
coordinates.extend((value, -extent, time, pressure) for value in edge[1:-1])
coordinates.extend((value, extent, time, pressure) for value in edge[1:-1])
return np.unique(np.asarray(coordinates, dtype=np.float32), axis=0)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--mode", choices=("Cross", "Plus", "Switch"))
parser.add_argument("--force", action="store_true")
args = parser.parse_args()
config = yaml.safe_load((ROOT / "conf/config.yaml").read_text())
mode = args.mode or config["data"]["observation_mode"]
output = ROOT / config["data"]["root"]
output.mkdir(parents=True, exist_ok=True)
path = output / "training_points.npz"
if path.exists() and not args.force:
print(f"exists={path.relative_to(ROOT)} (use --force to regenerate)")
return
module = load_model_module()
observations = structured_observations(config, mode)
targets = module.analytic_vortex_numpy(observations)[:, :3]
rng = np.random.default_rng(int(config["seed"]))
count = int(config["data"]["collocation_points"])
collocation = np.column_stack((
rng.uniform(-config["data"]["horizontal_extent_m"], config["data"]["horizontal_extent_m"], (count, 2)),
rng.uniform(-config["data"]["time_extent_s"], config["data"]["time_extent_s"], count),
rng.uniform(config["data"]["pressure_min_pa"], config["data"]["pressure_max_pa"], count),
)).astype(np.float32)
# The first two random columns already follow the required [y, x] order.
np.savez(path, observation_coordinates=observations, observation_targets=targets,
collocation_coordinates=collocation, input_order=np.asarray(module.INPUT_ORDER),
supervised_order=np.asarray(module.OUTPUT_ORDER[:3]), observation_mode=np.asarray(mode),
dense_shape=np.asarray([data_dim := int(config["data"]["grid_points"]), data_dim,
int(config["data"]["pressure_levels"]), int(config["data"]["time_steps"])]))
print(f"generated={path.relative_to(ROOT)} observations={len(observations)} collocation={len(collocation)} mode={mode}")
if __name__ == "__main__":
main()