Skip to content

Commit

Permalink
Improve some class names, minor refactoring (#159)
Browse files Browse the repository at this point in the history
  • Loading branch information
mhinkkan authored Sep 4, 2024
1 parent 3d4f475 commit 7ed07b8
Show file tree
Hide file tree
Showing 12 changed files with 75 additions and 70 deletions.
8 changes: 6 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,13 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named "sphinx.ext.*") or your custom ones.
extensions = [
"sphinx.ext.napoleon", "sphinx.ext.viewcode", "numpydoc",
"sphinx_copybutton", "sphinx.ext.mathjax", "sphinx_gallery.gen_gallery"
"sphinx.ext.intersphinx", "sphinx.ext.napoleon", "sphinx.ext.viewcode",
"numpydoc", "sphinx_copybutton", "sphinx.ext.mathjax",
"sphinx_gallery.gen_gallery"
]
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None),
}

extensions.append("autoapi.extension")
autoapi_type = "python"
Expand Down
10 changes: 5 additions & 5 deletions docs/source/control/control_system.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Common
Data Flow
---------

The two figures below shows the structure and data flow in a typical simulation model as well as an example of the internal structure of the discrete-time control system. The text in italics refers to the default object names used in the software. In the discrete-time control system, the signals are collected into the following SimpleNamespace objects:
The two figures below show the structure and data flow in a typical simulation model as well as an example of the internal structure of a discrete-time control system. The text in italics refers to the default object names used in the software. In discrete-time control systems, the signals are collected into the following :class:`types.SimpleNamespace` objects:

- The object `fbk` contains feedback signals for the controllers. These signals can be measured quantities (such as the measured DC-bus voltage `fbk.u_dc`) as well as estimated quantities (such as the estimated stator flux linkage `fbk.psi_s`).

Expand All @@ -24,20 +24,20 @@ These objects `fbk` and `ref` may propagate through several blocks (implemented
:align: center
:alt: Block diagram of the control system.

Block diagram exemplifying the internal structure of a typical cascade control system. The object `ref` at the controller output should contain the sampling period `T_s` and the converter duty ratios `d_c_abc` for the carrier comparison. The observer does not necessarily exist in all control systems (or it can be replaced with, e.g., a phase-locked loop).
Block diagram exemplifying the internal structure of a typical cascade control system. The object `ref` at the control system output should contain the sampling period `T_s` and the converter duty ratios `d_c_abc` for the carrier comparison. The observer does not necessarily exist in all control systems (or it can be replaced with, e.g., a phase-locked loop).

Main Control Loop
-----------------

By default, discrete-time control systems run the following scheme in their main control loops:
A template for the main control loop is available in the base class for discrete-time control systems in :class:`motulator.common.control.ControlSystem`. The main control loop in this template has the following steps:

1. Get the feedback signals `fbk` for the controllers from the outputs of the continuous-time system model `mdl`. This step may contain first getting the measurements and then optionally computing the observer outputs (or otherwise manipulating the measured signals).
2. Get the reference signals `ref` and compute the controller outputs based on the feedback signals `fbk`. Cascade control systems may contain multiple controllers, where the output of the outer controller is the reference signal for the inner controller.
3. Update the states of the control system for the next sampling instant.
4. Save the feedback signals `fbk` and the reference signals `ref` so they can be accessed after the simulation.
5. Return the sampling period `T_s` and the duty ratios `d_c_abc` for the carrier comparison.

A template of this main control loop is available in the base class for control systems in :class:`motulator.common.control.ControlSystem`. Using this template is not necessary, but it may simplify the implementation of new control systems.
Using this template is not compulsory, but it may simplify the implementation of new control systems.

2DOF PI Controller
------------------
Expand All @@ -54,7 +54,7 @@ The figure below shows a 2DOF PI controller with an optional feedforward term. I
u &= k_\mathrm{t}r - k_\mathrm{p}y + u_\mathrm{i} + u_\mathrm{ff}
:label: 2dof_pi
where :math:`r` is the reference signal, :math:`y` is the measured (or estimated) feedback signal, :math:`u_\mathrm{i}` is the the integral state, and :math:`u_\mathrm{ff}` is the optional feedforward signal. Furthermore, :math:`k_\mathrm{t}` is the reference-feedforward gain, :math:`k_\mathrm{p}` is the proportional gain, and :math:`k_\mathrm{i}` is the integral gain. Setting :math:`k_\mathrm{t} = k_\mathrm{p}` and :math:`u_\mathrm{ff} = 0` results in the standard PI controller. This 2DOF PI controller can also be understood as a state feedback controller with integral action and reference feedforward [#Fra1997]_.
where :math:`r` is the reference signal, :math:`y` is the measured (or estimated) feedback signal, :math:`u_\mathrm{i}` is the the integral state, and :math:`u_\mathrm{ff}` is the optional feedforward signal. Furthermore, :math:`k_\mathrm{t}` is the reference-feedforward gain, :math:`k_\mathrm{p}` is the proportional gain, and :math:`k_\mathrm{i}` is the integral gain. Setting :math:`k_\mathrm{t} = k_\mathrm{p}` and :math:`u_\mathrm{ff} = 0` results in the standard PI controller. This 2DOF PI controller can also be understood as a state-feedback controller with integral action and reference feedforward [#Fra1997]_.

.. figure:: figs/2dof_pi.svg
:width: 100%
Expand Down
4 changes: 2 additions & 2 deletions examples/grid/grid_following/plot_gfl_10kva.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@
# %%
# Configure the control system.

cfg = control.GFLControlCfg(
cfg = control.GridFollowingControlCfg(
L=.2*base.L, nom_u=base.u, nom_w=base.w, max_i=1.5*base.i)
ctrl = control.GFLControl(cfg)
ctrl = control.GridFollowingControl(cfg)

# %%
# Set the time-dependent reference and disturbance signals.
Expand Down
4 changes: 2 additions & 2 deletions examples/grid/grid_following/plot_gfl_dc_bus_10kva.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
# Configure the control system.

# Create the control system
cfg = control.GFLControlCfg(
cfg = control.GridFollowingControlCfg(
L=.2*base.L, nom_u=base.u, nom_w=base.w, max_i=1.5*base.i)
ctrl = control.GFLControl(cfg)
ctrl = control.GridFollowingControl(cfg)

# Add the DC-bus voltage controller to the control system
ctrl.dc_bus_voltage_ctrl = control.DCBusVoltageController(
Expand Down
4 changes: 2 additions & 2 deletions examples/grid/grid_following/plot_gfl_lcl_10kva.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@
# %%
# Configure the control system.

cfg = control.GFLControlCfg(
cfg = control.GridFollowingControlCfg(
L=.073*base.L, nom_u=base.u, nom_w=base.w, max_i=1.5*base.i)
ctrl = control.GFLControl(cfg)
ctrl = control.GridFollowingControl(cfg)

# %%
# Set the time-dependent reference and disturbance signals.
Expand Down
4 changes: 2 additions & 2 deletions examples/grid/grid_forming/plot_gfm_obs_13kva.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
# Configure the control system.

# Set the configuration parameters
cfg = control.ObserverBasedGFMControlCfg(
cfg = control.ObserverBasedGridFormingControlCfg(
L=.35*base.L,
R=.05*base.Z,
nom_u=base.u,
Expand All @@ -48,7 +48,7 @@
R_a=.2*base.Z)

# Create the control system
ctrl = control.ObserverBasedGFMControl(cfg)
ctrl = control.ObserverBasedGridFormingControl(cfg)

# %%
# Set the references for converter output voltage magnitude and active power.
Expand Down
4 changes: 2 additions & 2 deletions examples/grid/grid_forming/plot_gfm_rfpsc_13kva.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@
# Configure the control system.

# Control configuration parameters
cfg = control.RFPSCControlCfg(
cfg = control.PowerSynchronizationControlCfg(
nom_u=base.u, nom_w=base.w, max_i=1.3*base.i, T_s=100e-6, R_a=.2*base.Z)

# Create the control system
ctrl = control.RFPSCControl(cfg)
ctrl = control.PowerSynchronizationControl(cfg)

# %%
# Set the references for converter output voltage magnitude and active power.
Expand Down
21 changes: 11 additions & 10 deletions motulator/grid/control/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,24 @@
from motulator.grid.control._common import (
CurrentLimiter, DCBusVoltageController, GridConverterControlSystem, PLL)
from motulator.grid.control._grid_following import (
CurrentController, CurrentRefCalc, GFLControl, GFLControlCfg)
CurrentController, CurrentReference, GridFollowingControl,
GridFollowingControlCfg)
from motulator.grid.control._observer_gfm import (
ObserverBasedGFMControl, ObserverBasedGFMControlCfg)
ObserverBasedGridFormingControl, ObserverBasedGridFormingControlCfg)
from motulator.grid.control._power_synchronization import (
RFPSCControl, RFPSCControlCfg)
PowerSynchronizationControl, PowerSynchronizationControlCfg)

__all__ = [
"CurrentController",
"CurrentLimiter",
"CurrentRefCalc",
"CurrentReference",
"DCBusVoltageController",
"GFLControl",
"GFLControlCfg",
"GridFollowingControl",
"GridFollowingControlCfg",
"GridConverterControlSystem",
"ObserverBasedGFMControl",
"ObserverBasedGFMControlCfg",
"ObserverBasedGridFormingControl",
"ObserverBasedGridFormingControlCfg",
"PLL",
"RFPSCControl",
"RFPSCControlCfg",
"PowerSynchronizationControl",
"PowerSynchronizationControlCfg",
]
46 changes: 23 additions & 23 deletions motulator/grid/control/_grid_following.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Grid-following control methods for grid converters."""
"""Grid-following control methods."""

from dataclasses import dataclass

Expand All @@ -11,9 +11,9 @@

# %%
@dataclass
class GFLControlCfg:
class GridFollowingControlCfg:
"""
Grid-following control configuration
Grid-following control configuration.
Parameters
----------
Expand All @@ -22,7 +22,7 @@ class GFLControlCfg:
nom_u : float
Nominal grid voltage (V), line-to-neutral peak value.
nom_w : float
Nominal grid frequency (rad/s).
Nominal grid angular frequency (rad/s).
max_i : float
Maximum current (A), peak value.
T_s : float, optional
Expand All @@ -43,31 +43,32 @@ class GFLControlCfg:


# %%
class GFLControl(GridConverterControlSystem):
class GridFollowingControl(GridConverterControlSystem):
"""
Grid-following control for power converters.
Grid-following control.
Parameters
----------
cfg : GFLControlCfg
Control configuration.
cfg : GridFollowingControlCfg
Control system configuration.
Attributes
----------
current_ctrl : CurrentController
Current controller.
pll : PLL
Phase locked loop.
current_reference : CurrentRefCalc
Current reference calculator.
Phase-locked loop.
current_reference : CurrentReference
Current reference generator.
"""

def __init__(self, cfg):
super().__init__(cfg.T_s)
self.cfg = cfg
self.current_ctrl = CurrentController(cfg)
self.pll = PLL(cfg.alpha_pll, cfg.nom_u, cfg.nom_w)
self.current_reference = CurrentRefCalc(cfg)
self.current_reference = CurrentReference(cfg)

def get_feedback_signals(self, mdl):
fbk = super().get_feedback_signals(mdl)
Expand Down Expand Up @@ -109,8 +110,8 @@ class CurrentController(ComplexPIController):
Parameters
----------
cfg : GFLControlCfg
Control configuration parameters.
cfg : GridFollowingControlCfg
Control system configuration.
"""

Expand All @@ -122,18 +123,18 @@ def __init__(self, cfg):


# %%
class CurrentRefCalc:
class CurrentReference:
"""
Current controller reference generator
Current reference generator.
This class is used to generate the current references for the current
controllers based on the active and reactive power references. The current
limiting algorithm is used to limit the current references.
This class generates the current reference based on the active and reactive
power references. The current limiting algorithm is used to limit the
current reference.
Parameters
----------
cfg : GFLControlCfg
Control configuration parameters.
cfg : GridFollowingControlCfg
Control system configuration.
"""

Expand All @@ -143,7 +144,6 @@ def __init__(self, cfg):

def get_current_reference(self, ref):
"""Current reference generator."""
ref.i_c = 2*ref.p_g/(3*self.nom_u_g) - 2j*ref.q_g/(3*self.nom_u_g)
ref.i_c = 2*(ref.p_g - 1j*ref.q_g)/(3*self.nom_u_g)
ref.i_c = self.current_limiter(ref.i_c)

return ref
14 changes: 7 additions & 7 deletions motulator/grid/control/_observer_gfm.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Disturbance-observer-based grid-forming control for grid converters."""
"""Disturbance-observer-based grid-forming control."""

from dataclasses import dataclass

Expand All @@ -10,7 +10,7 @@

# %%
@dataclass
class ObserverBasedGFMControlCfg:
class ObserverBasedGridFormingControlCfg:
"""
Disturbance-observer-based grid-forming control configuration.
Expand All @@ -21,15 +21,15 @@ class ObserverBasedGFMControlCfg:
nom_u : float
Nominal grid voltage (V), line-to-neutral peak value.
nom_w : float
Nominal grid frequency (rad/s).
Nominal grid angular frequency (rad/s).
max_i : float
Maximum current (A), peak value.
R : float, optional
Total series resistance (Ω). The default is 0.
R_a : float, optional
Active resistance (Ω). The default is 0.25*nom_u/max_i.
T_s : float, optional
Sampling period of the controller (s). The default is 100e-6.
Sampling period (s). The default is 100e-6.
alpha_c : float, optional
Current control bandwidth (rad/s). The default is 2*pi*400.
alpha_o : float, optional
Expand All @@ -53,16 +53,16 @@ def __post_init__(self):


# %%
class ObserverBasedGFMControl(GridConverterControlSystem):
class ObserverBasedGridFormingControl(GridConverterControlSystem):
"""
Disturbance-observer-based grid-forming control for grid converters.
Disturbance-observer-based grid-forming control.
This implements the RFPSC-type grid-forming mode of the control method
described in [#Nur2024]_. Transparent current control is also implemented.
Parameters
----------
cfg : ObserverBasedGFMControlCfg
cfg : ObserverBasedGridFormingControlCfg
Controller configuration parameters.
Notes
Expand Down
20 changes: 10 additions & 10 deletions motulator/grid/control/_power_synchronization.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Power synchronization control for grid-connected converters."""
"""Power-synchronization control for grid-connected converters."""

from dataclasses import dataclass

Expand All @@ -11,24 +11,24 @@

# %%
@dataclass
class RFPSCControlCfg:
class PowerSynchronizationControlCfg:
"""
Power synchronization control configuration.
Reference-feedforward power-synchronization control configuration.
Parameters
----------
nom_u : float
Nominal grid voltage (V), line-to-neutral peak value.
nom_w : float
Nominal grid frequency (rad/s).
Nominal grid angular frequency (rad/s).
max_i : float
Maximum current (A), peak value.
R_a : float, optional
Active resistance (Ω). The default is 0.25*nom_u/max_i.
T_s : float, optional
Sampling period of the controller (s). The default is 100e-6.
Sampling period (s). The default is 100e-6.
w_b : float, optional
Current low-pass filter bandwidth (rad/s). The default is 2*pi*5.
Low-pass filter bandwidth (rad/s). The default is 2*pi*5.
"""
nom_u: float
Expand All @@ -45,12 +45,12 @@ def __post_init__(self):


# %%
class RFPSCControl(GridConverterControlSystem):
class PowerSynchronizationControl(GridConverterControlSystem):
"""
Reference-feedforward power synchronization control for grid converters.
Reference-feedforward power-synchronization control.
This implements the reference-feedforward power synchronization control
(RFPSC) method [#Har2020]_.
This implements the reference-feedforward power-synchronization control
method [#Har2020]_.
Parameters
----------
Expand Down
6 changes: 3 additions & 3 deletions motulator/grid/model/_converter_system.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""
Continuous-time grid converter system model.
This interconnects the subsystems of a converter with a grid and provides
an interface to the solver. More complicated systems could be modeled using
a similar template. Peak-valued complex space vectors are used.
This interconnects the subsystems of a converter with a grid and provides an
interface to the solver. More complicated systems could be modeled using a
similar template. Peak-valued complex space vectors are used.
"""
from motulator.common.model import Model
Expand Down

0 comments on commit 7ed07b8

Please sign in to comment.