Download scripts/common.py from OneScience-Group/ComPhy-TaylorGreenVortex: direct link, hf CLI and curl.
- Browser
- Download file 3.33 kB
-
https://huggingface.co/OneScience-Group/ComPhy-TaylorGreenVortex/resolve/main/scripts/common.py
- Command line
-
hf download hf://OneScience-Group/ComPhy-TaylorGreenVortex/scripts/common.py
-
curl -L -o common.py https://huggingface.co/OneScience-Group/ComPhy-TaylorGreenVortex/resolve/main/scripts/common.py
3.33 kB
| """Configuration, read-only validation and unambiguous metric reductions.""" | |
| import hashlib | |
| import json | |
| from pathlib import Path | |
| import numpy as np | |
| import torch | |
| import yaml | |
| from model.comphy_tgv import ComPhyTaylorGreenVortex | |
| ROOT = Path(__file__).resolve().parents[1] | |
| def resolve(path): | |
| p = Path(path) | |
| return p if p.is_absolute() else ROOT / p | |
| def load_config(path): | |
| with open(path) as f: | |
| cfg = yaml.safe_load(f) | |
| if cfg['training']['steps'] != 100000 or cfg['training']['interior_points'] != 1000: | |
| raise ValueError('Formal experiment requires 100000 steps and 1000 interior points.') | |
| if cfg['model']['hidden_layers'] != 2 or cfg['model']['hidden_units'] != 64: | |
| raise ValueError('Table 5 requires two hidden layers of 64 units.') | |
| return cfg | |
| def build_model(cfg, device): | |
| dtype = getattr(torch, cfg['training']['dtype']) | |
| return ComPhyTaylorGreenVortex(**cfg['model']).to(device=device, dtype=dtype) | |
| def load_reference(path): | |
| """Validation only. No torch tensors with gradients are created here.""" | |
| with np.load(path, allow_pickle=False) as data: | |
| coordinates = data['coordinates'].copy() | |
| target = data['target'].copy() | |
| if coordinates.shape != (36864, 3) or target.shape != coordinates.shape: | |
| raise ValueError('Expected coordinates and target [36864,3].') | |
| if coordinates.dtype != np.float64 or target.dtype != np.float64: | |
| raise ValueError('Reference must be float64.') | |
| if not np.isfinite(coordinates).all() or not np.isfinite(target).all(): | |
| raise ValueError('Reference has nonfinite values.') | |
| coordinates.flags.writeable = False | |
| target.flags.writeable = False | |
| return coordinates, target | |
| def metrics(prediction, target): | |
| error = np.asarray(prediction, dtype=np.float64) - target | |
| if not np.isfinite(error).all(): | |
| raise FloatingPointError('Nonfinite prediction.') | |
| e2 = float(np.mean(np.sum(error**2, axis=1))) | |
| return {'l2_error': e2, 'max_error': float(np.abs(error).max()), | |
| 'l2_norm': float(np.sqrt(e2)), 'scalar_mse': e2/3, | |
| 'relative_l2': float(np.linalg.norm(error)/np.linalg.norm(target)), | |
| 'per_variable_mse': dict(zip(('u','v','p'), np.mean(error**2, axis=0).tolist())), | |
| 'per_variable_max': dict(zip(('u','v','p'), np.abs(error).max(axis=0).tolist()))} | |
| def predict(model, coordinates, batch_size): | |
| model.eval() | |
| p = next(model.parameters()) | |
| blocks = [] | |
| for start in range(0, len(coordinates), batch_size): | |
| q = torch.tensor(coordinates[start:start+batch_size], device=p.device, dtype=p.dtype) | |
| # forward is strictly the momentum module, never an average/ensemble. | |
| blocks.append(model(q).cpu().double().numpy()) | |
| return np.concatenate(blocks) | |
| def atomic_json(path, payload): | |
| path = Path(path) | |
| path.parent.mkdir(parents=True, exist_ok=True) | |
| temp = path.with_suffix(path.suffix + '.tmp') | |
| temp.write_text(json.dumps(payload, indent=2, ensure_ascii=False, allow_nan=False)+'\n') | |
| temp.replace(path) | |
| def atomic_checkpoint(path, payload): | |
| path = Path(path) | |
| temp = path.with_suffix(path.suffix + '.tmp') | |
| torch.save(payload, temp) | |
| temp.replace(path) | |
| def sha256(path): | |
| return hashlib.sha256(Path(path).read_bytes()).hexdigest() | |