1import torch
2import numpy as np
3import json
4from physicsnemo.models.mlp.fully_connected import FullyConnected
5
6# Load model
7model = FullyConnected(
8 in_features=14, out_features=8,
9 num_layers=6, layer_size=512,
10 activation_fn='silu', skip_connections=True,
11)
12
13# Option 1: Load from PhysicsNeMo native format
14model = FullyConnected.from_checkpoint("fan_surrogate.mdlus")
15
16# Option 2: Load from PyTorch state dict
17state = torch.load("model.pt", map_location="cpu")
18model.load_state_dict(state)
19model.eval()
20
21# Load scalers
22with open("scalers.json") as f:
23 scalers = json.load(f)
24sx_mean = np.array(scalers['scaler_X_mean'], dtype=np.float32)
25sx_scale = np.array(scalers['scaler_X_scale'], dtype=np.float32)
26sy_mean = np.array(scalers['scaler_y_mean'], dtype=np.float32)
27sy_scale = np.array(scalers['scaler_y_scale'], dtype=np.float32)
28
29# Predict
30INPUT_COLS = ["blade_inlet_angle_deg", "blade_turning_angle_deg", "chord_length_mm",
31 "blade_thickness_ratio", "stagger_angle_deg", "hub_tip_ratio",
32 "tip_clearance_ratio", "num_blades", "aspect_ratio", "solidity",
33 "sweep_angle_deg", "flow_coefficient", "rotational_speed_rpm", "tip_radius_mm"]
34LOG_IDX = [0, 2, 3]
35
36design = [55, 15, 100, 0.06, 45, 0.5, 0.015, 12, 2.5, 1.0, 0, 0.5, 3000, 300]
37x = np.array([design], dtype=np.float32)
38x_scaled = (x - sx_mean) / sx_scale
39
40with torch.no_grad():
41 y_scaled = model(torch.from_numpy(x_scaled)).numpy()
42
43y_proc = y_scaled * sy_scale + sy_mean
44for i in LOG_IDX:
45 y_proc[0, i] = np.expm1(y_proc[0, i])
46
47print(f"Pressure Rise: {y_proc[0,0]:.1f} Pa")
48print(f"Efficiency: {y_proc[0,1]:.3f}")
49print(f"Power: {y_proc[0,2]:.1f} W")
50print(f"Flow Rate: {y_proc[0,3]:.3f} m³/s")