Skip to content

Summary of the main code snipplets used during my master's thesis "Embedding Neural Networks into Dynamic Power System Simulators"

License

Notifications You must be signed in to change notification settings

SPS-L/RamsesNN

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

8 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

RamsesNN

Embedding Neural Networks into Dynamic Power System Simulators

This repository contains the implementation and workflow for integrating Physics-Informed Neural Networks (PINNs) into the RAMSES power system simulator using the roseNNa inference library.

πŸ“‹ Overview

RamsesNN enables the use of neural networks trained in PyTorch to replace or augment traditional power system component models in RAMSES simulations. The workflow converts PyTorch models to ONNX format, processes them with roseNNa, and integrates them into RAMSES through custom Fortran injector models.

Key Features

  • Fast Inference: Uses roseNNa's optimized Fortran implementation (2-5x faster than PyTorch for small networks)
  • Minimal Intrusion: Seamlessly integrates into existing RAMSES workflows
  • Flexible Models: Supports both full and reduced-order power system models
  • ONNX Standard: Universal format compatible with PyTorch, TensorFlow, and Keras

Related Projects

  • roseNNa - Fast neural network inference library for Fortran/C
  • URAMSES - RAMSES power system simulator distribution

πŸš€ Complete Workflow

1. Train and Export Neural Network

Train your neural network in PyTorch and export it to ONNX format:

import torch

# Train your model
model = YourNeuralNetwork()
# ... training code ...

# Export to ONNX
init_cond = torch.randn(1, 10)  # Example input matching your network's input shape
torch.onnx.export(model, init_cond, "NN.onnx")

2. Convert ONNX Model with roseNNa

Navigate to the fLibrary/ directory in your roseNNa installation and follow these steps:

Prerequisites

Install required dependencies:

# Create conda environment for ONNX parsing
conda create -n roparse python=3.10 -y
conda activate roparse

# Install dependencies
pip install "numpy<2" onnx==1.15.0 onnxruntime==1.16.3
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install fypp

Shape Inference

ONNX models need shape inference for proper parsing. Create and run a helper script:

PowerShell (Windows):

$code = @"
import onnx, onnx.shape_inference
m = onnx.load(r'.\NN.onnx')
m_inf = onnx.shape_inference.infer_shapes(m)
onnx.save(m_inf, r'.\NN_inferred.onnx')
print('Wrote NN_inferred.onnx')
"@
Set-Content -Encoding ASCII infer_shapes.py $code
python .\infer_shapes.py

Bash (Linux/Mac):

cat > infer_shapes.py << 'EOF'
import onnx, onnx.shape_inference
m = onnx.load('./NN.onnx')
m_inf = onnx.shape_inference.infer_shapes(m)
onnx.save(m_inf, './NN_inferred.onnx')
print('Wrote NN_inferred.onnx')
EOF
python infer_shapes.py

Parse and Generate Fortran Code

# Clean previous files
rm -f onnxModel.txt onnxWeights.txt variables.fpp modelCreator.f90

# Parse ONNX model
python modelParserONNX.py -f "./NN.onnx" -w "./NN.onnx" -i "./NN_inferred.onnx"

# Verify output files were created
ls onnxModel.txt onnxWeights.txt variables.fpp

# Generate Fortran code via fypp preprocessor
python -m fypp ./modelCreator.fpp ./modelCreator.f90

# Fix C++ style namespace syntax for Fortran
sed -i 's/onnx:://g' modelCreator.f90  # Linux/Mac
# OR for Windows PowerShell:
# (Get-Content .\modelCreator.f90) -replace 'onnx::','' | Set-Content .\modelCreator.f90

Compile roseNNa Library

make library

This generates libcorelib.a, the core roseNNa library file.


πŸ”§ Integration into RAMSES

Required roseNNa Files

Add these files from roseNNa's fLibrary/ directory to your RAMSES project (URAMSES):

  • activation_funcs.f90
  • derived_types.f90
  • layers.f90
  • reader.f90
  • rosenna.f90
  • modelCreator.f90 (generated for your specific model)

Required Data Files

Place these generated files in your RAMSES executable directory:

  • onnxModel.txt - Model structure
  • onnxWeights.txt - Model weights

Note: If using multiple neural networks simultaneously, you'll need to modify the reader logic in rosenna.f90 to handle multiple model files.

Example: Norton Injector Model

The inj_norton.f90 model demonstrates a complete integration. Key components:

Module Setup

module inj_norton_mod
    use iso_fortran_env, only: real64, int32
    use MODELING
    use rosenna      ! Neural network library
    implicit none
    
    ! Neural network I/O arrays
    real(real64), allocatable :: pinn_input(:,:)    ! (1, n_in)
    real(real64), allocatable :: pinn_output(:,:)   ! (1, n_out)

Initialization

case (initialize)
    ! Define model dimensions (full or reduced)
    if (prm(5) < 1.5) then
        n_nn_input = 10
        n_nn_output = 9
    else
        n_nn_input = 8
        n_nn_output = 7
    end if
    
    ! Allocate arrays
    allocate(pinn_input(1, n_nn_input))
    allocate(pinn_output(1, n_nn_output))
    
    ! Initialize input with steady-state values
    pinn_input(1,1) = 0.01_real64      ! timestep
    pinn_input(1,2) = -0.81854824_real64  ! delta
    pinn_input(1,3) = omega            ! omega
    ! ... additional states ...
    
    ! Initialize roseNNa with model name
    nn_model_name = "full_frzd"  ! or "redv2" for reduced model
    call initialize_nnx(nn_model_name)

Inference Execution

case (evaluate_eqs)
    ! Update inputs based on current system state
    call inf_bus_equations(vx, vy, old_ix, old_iy, Xline, Rline, &
                          new_v_infty, new_v_infty_ang)
    
    pinn_input(1,8) = new_v_infty
    pinn_input(1,9) = new_v_infty_ang
    
    ! Neural network forward pass
    call use_model(pinn_input, pinn_output)
    
    ! Convert NN output to physical quantities
    call machine_solver(pinn_output(1,1:9), machine_output(1,1:6))
    
    ! Transform to xy coordinates
    call park_transform_dq_xy(machine_output(1,3), machine_output(1,4), &
                             pinn_output(1,1), ixnorton, iynorton)

πŸ–₯️ Platform-Specific Instructions

Windows with Visual Studio 2022

  1. Add source files to your project:

    • Right-click project β†’ Add β†’ Existing Item
    • Select the 6 roseNNa .f90 files listed above
  2. Configure module path:

    • Project β†’ Properties β†’ Fortran β†’ General β†’ Additional Include Directories
    • Add path to roseNNa's objFiles/ directory
  3. Link library:

    • Project β†’ Properties β†’ Linker β†’ Input β†’ Additional Dependencies
    • Add path to libcorelib.a

πŸ“ Repository Structure

RamsesNN/
β”œβ”€β”€ README.md                      # This file
β”œβ”€β”€ URAMSES/                       # RAMSES simulator files
β”‚   └── my_models/
β”‚       └── inj_norton.f90        # Example NN-integrated injector model
└── [additional model files]

πŸ”¬ Model Types Supported

Full Model (10 inputs, 9 outputs)

  • Inputs: timestep, Ξ΄, Ο‰, e_d, e_q, ψ_d, ψ_q, V_∞, ΞΈ_∞, v_f
  • Outputs: Ξ΄, Ο‰, e_d, e_q, ψ_d, ψ_q, V_∞, ΞΈ_∞, v_f

Reduced Model (8 inputs, 7 outputs)

  • Inputs: timestep, Ξ΄, Ο‰, e_d, e_q, V_∞, ΞΈ_∞, E_f
  • Outputs: Ξ΄, Ο‰, e_d, e_q, V_∞, ΞΈ_∞, E_f

πŸ“š Technical Details

Neural Network Architecture Support

roseNNa currently supports:

  • Multi-Layer Perceptrons (MLPs)
  • Convolutional Neural Networks (CNNs)
  • Recurrent Neural Networks (RNNs/LSTMs)

Performance

For small networks typical in physics applications:

  • 2-5x faster than PyTorch inference
  • Optimized for Fortran/C HPC environments
  • Minimal memory footprint

LSTM/RNN Conversion Note

When converting LSTMs to ONNX, you need two exports (with and without constant folding):

# Model structure (with optimization)
torch.onnx.export(model, (inp, hidden),
                  "model_structure.onnx",
                  export_params=True,
                  opset_version=12,
                  do_constant_folding=True,
                  input_names=['input', 'hidden_state', 'cell_state'],
                  output_names=['output'])

# Model weights (without optimization)
torch.onnx.export(model, (inp, hidden),
                  "model_weights.onnx",
                  export_params=True,
                  opset_version=12,
                  do_constant_folding=False,
                  input_names=['input', 'hidden_state', 'cell_state'],
                  output_names=['output'])

πŸ“– References

  • B. Gelford (2025). "Integrating neural networks into dynamic power system simulators", MSc Thesis, ETH Zurich.
  • A. Bati, S. H. Bryngelson (2024). "RoseNNa: A performant, portable library for neural network inference with application to computational fluid dynamics". Computer Physics Communications. DOI: 10.1016/j.cpc.2023.109052
  • P. Aristidou, S. Lebeau, and T. Van Cutsem (2016). "Power system dynamic simulations using a parallel two-level schur-complement decomposition". IEEE Transactions on Power Systems. doi: 10.1109/TPWRS.2015.2509023

πŸ“§ Contact

Author: Bruno Gelfort Web: https://sps-lab.org
Email: info@sps-lab.org


πŸ“„ License

This project follows the licensing terms of its dependencies:

  • roseNNa: MIT License
  • RAMSES: Academic Public License

🚧 Future Work

Planned additions to this repository:

  • Complete PINN training pipeline documentation
  • Additional example models for various power system components
  • Automated testing framework
  • Performance benchmarking tools
  • Multi-model integration examples

About

Summary of the main code snipplets used during my master's thesis "Embedding Neural Networks into Dynamic Power System Simulators"

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Fortran 91.0%
  • Python 8.7%
  • Other 0.3%