Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
- Added `Node` class to the PowerElectronics module to separate nodes from circuit components.
- Refactored Jacobian assembly in `PowerElectronics` module to reuse the CSR pattern.
- Refactored Jacobian assembly in `PhasorDyanmcics` module to reuse the CSR pattern.
- Added component model developer checklist to a README file.

## v0.1

- Refactored code to support adding different model families.
Expand Down
77 changes: 76 additions & 1 deletion GridKit/Model/PhasorDynamics/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,82 @@
# Phasor dynamics

This directory contains an implementation of a system model using phasor
dynamics. Aside from all of the modeling aspects, one additional part of
dynamics.

## Modeling checklist

In current GridKit architecture each component model is implemented in six
files:
- `MyModel.cpp`: Basic compilation unit for the case when model does not
provide Jacobian.
- `MyModel.hpp`: Component model declaration.
- `MyModelData.hpp`: Definitions of model data including model parameters,
model connection ports and model outputs (monitored
variables).
- `MyModelDependencyTracking.cpp`: Compilation unit for Jacobian evaluation
using dependency tracking data type (a.k.a
tapeless automatic differentiation).
- `MyModelEnzyme.cpp`: Compilation unit for Jacobian evaluation with Enzyme.
- `MyModelImpl.hpp`: Actual model implementation.

In essence, a component model developer needs to implement model data
structures in `MyModelData.hpp` file and model equations in `MyModelImpl.hpp`
file. The remaining four files are just supporting infrastructure for
compilation and testing.

We recommend developers follow these steps when adding new component models:
1. Create a subdirectory within appropriate model family directory.
2. Create a README file in markdown format that contains all information
needed to implement the model. This should include:
1. List of model parameters in a table format.
2. List of _derived_ model parameters with mathematical expression
describing how they are obtained from instantiation parameters.
3. Model internal variables. Use separate tables for differential and
algebraic variables.
4. Model external variables (always algebraic in phasor dynamics).
5. Model differential and algebraic equations (in separate subsections).
6. Model initialization procedure with equations in order in which
initialization computations are performed.
7. List of model outputs with equations for computing those outputs
where applicable.
3. Create all six `MyModel*.*pp` implementation files and `CMakeLists.txt`
file, which specifies build requirements (files to compile, files to
include, libraries to link and location to install to). Ensure the code
builds correctly.
- You may want to start with a "dummy" implementation first to make sure
the build and installation works correctly before proceeding to the
implementation.
4. Create unit tests in `tests/UnitTesting/PhasorDynamics` directory. The
implementation consists of `MyModelTests.hpp` with implementation of
individual unit tests, the test driver in `runMyModelTests.cpp`, and
`CMakeLists.txt` with build and installation configuration of tests. Unit
test should be include:
1. Constructor tests (smoke tests).
2. Residual evaluation test (substitute variables in the residual that
check all computations in the residual function; avoid zeros and ones
as inputs).
3. Jacobian evaluation test (Enzyme generated Jacobian must match Jacobian
created using dependency tracking variables).
4. Initialization test (verify that component correctly sets initial
values).
5. Combined initialization and residual evaluation test (initialization
should ensure residual evaluates to zero within prescribed tolerance).
5. Once model is tested, add it to the system composer. This requires following steps:
1. Add header file `MyModel.hpp` to `ComponentLibrary.hpp`, so that
`MyModel` declaration is visible to the `SystemModel` class.
3. Modify `SystemModelJsonParser.hpp` so that `MyModel` is recognized by the
parser.
4. Modify `SystemModelData.hpp` so that `MyModelData` is visible to the system
model.
5. Modify `SystemModel.hpp` so that `MyModel` components can be connected by the
system composer.
7. Recommended: Create an example in `examples/PhasorDynamics` using the new component.



## Input file parser

Aside from all of the modeling aspects, one additional part of
note is the experimental JSON parsing functionality which can take in a JSON
object (described in `INPUT_FORMAT.md`) and yields a system model. This
is implemented with the [nlohmann/json](https://github.com/nlohmann/json)
Expand Down
11 changes: 6 additions & 5 deletions GridKit/Model/PowerElectronics/MicrogridBusDQ/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@

The Bus used for the Microgrid found in references 1 and 2.
The bus model used for the microgrid found in Pogaku et al.[^1] and Bidram et al.[^2]

Parameters:
+ $RN$ - Virtual Resistance

Variables (External):
+ $v_{D}$ - Incoming Bus Voltage (D)
+ $v_{Q}$ - Incoming Bus Voltage (Q)
+ $v_{D}$ - Bus voltage along direct axis
+ $v_{Q}$ - Bus voltage along quadrature axis

Equations (External, Residuals):
+ $\frac{-v_D}{RN}$
Expand All @@ -15,5 +15,6 @@ Equations (External, Residuals):
There are no internal variables to this system. Only residuals to be added from existing externals. As $RN \rightarrow \infty$ then the bus represent Kirchhoff's current law.


1. Pogaku, Nagaraju, Milan Prodanovic, and Timothy C. Green. "Modeling, analysis and testing of autonomous operation of an inverter-based microgrid." IEEE Transactions on power electronics 22.2 (2007): 613-625.
2. Bidram, Ali, Frank L. Lewis, and Ali Davoudi. "Distributed control systems for small-scale power networks: Using multiagent cooperative control theory." IEEE Control systems magazine 34.6 (2014): 56-77.
[^1]: Pogaku, Nagaraju, Milan Prodanovic, and Timothy C. Green. "Modeling, analysis and testing of autonomous operation of an inverter-based microgrid." IEEE Transactions on power electronics 22.2 (2007): 613-625.

[^2]: Bidram, Ali, Frank L. Lewis, and Ali Davoudi. "Distributed control systems for small-scale power networks: Using multiagent cooperative control theory." IEEE Control systems magazine 34.6 (2014): 56-77.
20 changes: 10 additions & 10 deletions GridKit/Model/PowerElectronics/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
This sub-directory provides components utilized within the PowerElectronicsModel composer. All components are treated equally and only the composer can view and distribute data to components. Components have no knowledge nor require the existence of any other component.
Each component evaluates a set of equations to form residuals. There are two types of variables.
+ Internal Variables. Variables only need by the component.
+ External Variables. Variables shared between multiple components.
+ Internal Variables $y$. Variables only need by the component.
+ External Variables $w$. Variables shared between multiple components.

Each equation is associated to a variable. The residuals generated by external components are assumed to add together to form the final system.
Arbitrary amounts of components can be handle and residuals evaluated.
Expand All @@ -16,25 +16,25 @@ Example with two components is as follows.
Component 1:
```math
\begin{align}
0 = f_1(\frac{dy_{1}}{dt}, y_1 ,z) & \qquad \text{(Internal Equations)}\\
c_1(y_1,z) & \qquad \text{(External Residuals)}\\
0 = f_1\left(\frac{dy_{1}}{dt}, y_1 , w \right) & \qquad \text{(Internal Equations Residual)}\\
c_1(y_1, w) & \qquad \text{(External Coupling Term)}\\
\end{align}
```
Component 2:
```math
\begin{align}
0 = f_2(\frac{dy_{2}}{dt}, y_2 ,z) & \qquad \text{(Internal Equations)}\\
c_2(y_2,z) & \qquad \text{(External Residuals)}\\
0 = f_2\left(\frac{dy_{2}}{dt}, y_2 ,w\right) & \qquad \text{(Internal Equations Residual)}\\
c_2(y_2,w) & \qquad \text{(External Coupling Term)}\\
\end{align}
```

The composition of components 1 and 2:
```math
\begin{align}
0 = f_1(\frac{dy_{1}}{dt}, y_1 ,z) & \qquad \text{(Internal Equations)}\\
0 = f_2(\frac{dy_{2}}{dt}, y_2 ,z) &\\
0 = c_1(y_1, z) + c_2(y_2,z) & \qquad \text{(Composed External Residuals)}\\
0 = f_1\left(\frac{dy_{1}}{dt}, y_1 ,w\right) & \qquad \text{(Internal Equations Residuals)}\\
0 = f_2\left(\frac{dy_{2}}{dt}, y_2 ,w\right) &\\
0 = c_1(y_1, w) + c_2(y_2,w) & \qquad \text{(External Coupling Residuals)}\\
\end{align}
```

Note the dimensions of \(y\) can be \(0\) if there are no internal equations (an example seen in Resistors and MicrogridBus).
Note the dimensions of $y$ can be $0$ if there are no internal equations (an example seen in Resistors and MicrogridBus).
4 changes: 2 additions & 2 deletions tests/UnitTests/PhasorDynamics/GenClassicalTests.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ namespace GridKit
return success.report(__func__);
}

/*
*Verifies the residual evaluates to zero for the initial conditions
/**
* Verifies the residual evaluates to zero for the initial conditions
*/
TestOutcome zeroInitialResidual()
{
Expand Down