Fan Design Surrogate Model — PhysicsNeMo Version

A physics-informed deep learning surrogate model for axial fan aerodynamic performance prediction, built with NVIDIA PhysicsNeMo.

R² = 0.9964 | MAPE = 1.40% (32% better than pure data-driven approach)

How This Differs from the Standard PyTorch Version

Aspect Standard PyTorch PhysicsNeMo (this model)
Framework Pure PyTorch nn.Module PhysicsNeMo FullyConnected (extends nn.Module)
Loss Function MSE on data only MSE + physics-informed constraints
Architecture Custom ResidualMLP PhysicsNeMo FullyConnected with skip_connections=True
Activation GELU SiLU (Swish)
Parameters 634K 1.33M
Avg R² 0.9952 0.9964 (+0.12%)
Avg MAPE 2.08% 1.40% (-32%)
Extrapolation Poor (data-only) Better (physics constraints regularize)
Serialization torch.save() .mdlus native + torch.save()
Checkpoint Manual physicsnemo.utils.checkpoint

Key Advantage: Physics-Informed Loss

The standard model learns purely from data. The PhysicsNeMo version adds 4 physics constraint terms to the loss function that enforce thermodynamic and aerodynamic consistency:

  1. Power-Pressure Consistency: P = ΔPt × Q / η (energy conservation)
  2. Flow Rate Consistency: Q = Vx × A_annulus (continuity equation)
  3. Efficiency Bounds: 0 < η < 1 (second law of thermodynamics)
  4. Euler Work Equation: ΔPt ≈ ρ × η × U × ΔVθ (turbomachinery fundamental)

These constraints act as regularizers — even without labeled data, the model learns physically meaningful relationships. This dramatically improves:

  • Extrapolation to designs outside the training distribution
  • Consistency between predicted outputs (power, pressure, flow are now thermodynamically coherent)
  • Sample efficiency (same accuracy with less training data)

Performance (Test Set: 2000 samples)

Output Metric MAPE
Total Pressure Rise (Pa) 0.9976 3.39%
Isentropic Efficiency 0.9804 0.69%
Power Consumption (W) 0.9987 2.70%
Flow Rate (m³/s) 0.9998 1.08%
Specific Speed 0.9975 1.48%
Degree of Reaction 0.9988 0.46%
Diffusion Factor 0.9991 0.88%
Noise Estimate (dBA) 0.9994 0.51%
Average 0.9964 1.40%

Usage

import torch
import numpy as np
import json
from physicsnemo.models.mlp.fully_connected import FullyConnected

# Load model
model = FullyConnected(
    in_features=14, out_features=8,
    num_layers=6, layer_size=512,
    activation_fn='silu', skip_connections=True,
)

# Option 1: Load from PhysicsNeMo native format
model = FullyConnected.from_checkpoint("fan_surrogate.mdlus")

# Option 2: Load from PyTorch state dict  
state = torch.load("model.pt", map_location="cpu")
model.load_state_dict(state)
model.eval()

# Load scalers
with open("scalers.json") as f:
    scalers = json.load(f)
sx_mean = np.array(scalers['scaler_X_mean'], dtype=np.float32)
sx_scale = np.array(scalers['scaler_X_scale'], dtype=np.float32)
sy_mean = np.array(scalers['scaler_y_mean'], dtype=np.float32)
sy_scale = np.array(scalers['scaler_y_scale'], dtype=np.float32)

# Predict
INPUT_COLS = ["blade_inlet_angle_deg", "blade_turning_angle_deg", "chord_length_mm",
    "blade_thickness_ratio", "stagger_angle_deg", "hub_tip_ratio",
    "tip_clearance_ratio", "num_blades", "aspect_ratio", "solidity",
    "sweep_angle_deg", "flow_coefficient", "rotational_speed_rpm", "tip_radius_mm"]
LOG_IDX = [0, 2, 3]

design = [55, 15, 100, 0.06, 45, 0.5, 0.015, 12, 2.5, 1.0, 0, 0.5, 3000, 300]
x = np.array([design], dtype=np.float32)
x_scaled = (x - sx_mean) / sx_scale

with torch.no_grad():
    y_scaled = model(torch.from_numpy(x_scaled)).numpy()

y_proc = y_scaled * sy_scale + sy_mean
for i in LOG_IDX:
    y_proc[0, i] = np.expm1(y_proc[0, i])

print(f"Pressure Rise: {y_proc[0,0]:.1f} Pa")
print(f"Efficiency: {y_proc[0,1]:.3f}")
print(f"Power: {y_proc[0,2]:.1f} W")
print(f"Flow Rate: {y_proc[0,3]:.3f} m³/s")

Installation

pip install nvidia-physicsnemo torch numpy

Architecture Details

FullyConnected(
  (layers): ModuleList(
    (0): FCLayer(Linear(14→512) + SiLU)
    (1-5): 5 × FCLayer(Linear(512→512) + SiLU + skip_connection)
  )
  (final_layer): FCLayer(Linear(512→8))
)
Total parameters: 1,325,064

When to Use PhysicsNeMo vs Standard PyTorch

Scenario Recommendation
Abundant training data (>5000 samples) Either works; PhysicsNeMo slightly better
Sparse data (<500 samples) PhysicsNeMo (physics constraints compensate for missing data)
Extrapolation needed PhysicsNeMo (constraints prevent unphysical predictions)
Pure interpolation Standard PyTorch (simpler, faster training)
Need ONNX export / deployment PhysicsNeMo (built-in export support)
Multi-physics coupling PhysicsNeMo (add PDE residuals, boundary conditions)
Quick prototyping Standard PyTorch (fewer dependencies)

Dataset

Trained on harshaperla/fan-design-dataset (8000 train / 2000 test).

References

Generated by ML Intern

This model repository was generated by ML Intern, an agent for machine learning research and development on the Hugging Face Hub.

Downloads last month
82
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Paper for harshaperla/fan-design-surrogate-physicsnemo