Skip to content

Python Controller

Controller for dynamic simulations whose control law is an IronPython script. At each control step the script receives the process variable as PV and must set MV (the manipulated variable value, in its units) and SP (the setpoint); the controller then writes MV to the manipulated object.

DWSIM.UnitOperations.SpecialOps.PythonController
Assembly DWSIM.UnitOperations.dll · Object ← BaseClass ← SpecialOpBaseClass ← PythonController

At a glance

Python Controller in the example flowsheet

This object has no stream connections; it acts on other objects through their properties.

Example

This code runs on every build of this site, and the output below is what it printed.

    fs = (Flowsheet.Create("PythonControllerExample")
          .WithCompound("Water")
          .WithPropertyPackage(PropertyPackages.SteamTables))

    inlet = (fs.AddMaterialStream("Inlet").At(Q.Celsius(25.0), Q.Pascal(130000.0))
             .WithMassFlow(Q.KgPerSecond(10.0)).AsFlowSpec())
    s1 = fs.AddMaterialStream("S-1").AsPressureSpec()
    s2 = fs.AddMaterialStream("S-2").AsPressureSpec()
    outlet = fs.AddMaterialStream("Outlet").AsPressureSpec()
    (fs.AddValve("V-01").WithCalcMode(Valve.CalculationMode.Kv_Liquid).WithKv(100.0)
       .WithOpeningPercent(50.0).ConnectFeed(inlet).ConnectProduct(s1))
    tank = (fs.AddTank("T-01").WithVolume(Q.CubicMeters(2.0)).WithHeight(Q.Meters(2.0))
            .ConnectFeed(s1).ConnectProduct(s2))
    valve = (fs.AddValve("V-02").WithCalcMode(Valve.CalculationMode.Kv_Liquid).WithKv(400.0)
             .WithOpeningKvRelationship().WithOpeningPercent(50.0)
             .ConnectFeed(s2).ConnectProduct(outlet))
    fs.AutoLayout()
    fs.Solve()
    outlet.Object.Phases[0].Properties.pressure = 101325.0

    builder = fs.AddUnitOperation(ObjectType.Controller_Python, "LC-PY")
    lc = builder.Object.__implementation__

    def variable(obj, prop, units):
        info = SpecialOpObjectInfo()
        info.ID = obj.Object.Name
        info.Name = obj.Object.GraphicObject.Tag
        info.PropertyName = prop
        info.ObjectType = obj.Object.GetDisplayName()
        info.Units = units
        return info

    lc.ControlledObjectData = variable(tank, "Liquid Level", "m")
    lc.ManipulatedObjectData = variable(valve, "PROP_VA_5", "")     # opening, %
    lc.ControlledObject, lc.ManipulatedObject = tank.Object, valve.Object
    lc.Output = 29.0                                              # starting valve opening, %

    # Runs once per control step. In: PV (display units), Me (this controller).
    # Out: MV (manipulated variable, display units) and SP (setpoint).
    lc.PythonScript = """
SP = 1.0          # m
Kc = 40.0         # % per m
Ti = 100.0        # s
dt = 5.0          # s, the integration step
pv_prev = Me.PVValue if Me.PVValue > 0.0 else PV
# velocity form PI: the previous output carries the integral
MV = Me.Output + Kc * (PV - pv_prev) + Kc / Ti * (PV - SP) * dt
MV = min(100.0, max(0.0, MV))
"""

    (fs.Dynamics.DefineIntegrator("Int1")
       .WithIntegrationStep(TimeSpan.FromSeconds(5.0)).WithDuration(TimeSpan.FromMinutes(20.0))
       .Monitor("T-01", "Liquid Level", "m", "level")
       .Monitor("V-02", "PROP_VA_5", "", "opening"))
    (fs.Dynamics.DefineEventSet("FeedStep")
       .AddStepChange("Inlet", "PROP_MS_2", 15.0, Q.Seconds(600.0), "kg/s", "feed 10 -> 15 kg/s"))
    (fs.Dynamics.DefineSchedule("Run").WithIntegrator("Int1").WithEventSet("FeedStep")
       .UseCurrentStateAsInitial(True).MakeCurrent())
    result = fs.RunDynamics("Run").Execute()

    level, opening = result.GetSeries("level"), result.GetSeries("opening")
    after = [v for t, v in zip(level.TimeSeconds, level.Values) if t >= 600.0]
    print(f"Level                 = {level.Initial:.3f} m at the start, {level.ValueAt(595.0):.3f} m before the step")
    print(f"Peak level after step = {max(after):.3f} m")
    print(f"Final level           = {level.Final:.3f} m (setpoint {lc.SetPoint:.1f} m)")
    print(f"Valve opening         = {opening.ValueAt(595.0):.1f} % before, {opening.Final:.1f} % at the end")

Output

Level                 = 0.010 m at the start, 1.003 m before the step
Peak level after step = 1.182 m
Final level           = 1.000 m (setpoint 1.0 m)
Valve opening         = 28.9 % before, 43.3 % at the end

DWSIM 10.2.11.0, generated 2026-10-08.

Properties

IDs accepted by GetPropertyValue, SetPropertyValue, the sensitivity analysis, the optimizer, the Adjust block and dynamic events. Units are SI; pass another unit system to GetPropertyValue to get them converted.

ID Name Unit (SI) Input
Active yes
SetPoint Set Point yes
Output Controller Output yes

Learn more

API members

Public members declared by this class. Inherited members are documented on the base classes.

Constructors

PythonController(): Initializes a new default instance of the PythonController class.

Initializes a new default instance of the PythonController class.

public PythonController()
Public Sub New()

PythonController(string, string): Initializes a new instance of the PythonController class with a name and description.

Initializes a new instance of the PythonController class with a name and description.

Parameter Type Description
name String The name of this controller.
description String A brief description of this controller.
public PythonController(string name, string description)
Public Sub New(name As String, description As String)

Properties

Active: Gets or sets whether the controller acts during a dynamic run.

Gets or sets whether the controller acts during a dynamic run. The integrator skips an inactive controller. Default True.

public bool Active { get; set; }
Public Property Active As Boolean

ControlledObject: The flowsheet object whose property is controlled.

The flowsheet object whose property is controlled. The calculation resolves the object from ControlledObjectData. Not serialized.

public BaseClass ControlledObject { get; set; }
Public Property ControlledObject As BaseClass

ManipulatedObject: The flowsheet object whose property the controller manipulates.

The flowsheet object whose property the controller manipulates. The calculation resolves the object from ManipulatedObjectData. Not serialized.

public BaseClass ManipulatedObject { get; set; }
Public Property ManipulatedObject As BaseClass

MaximumIterations: Maximum number of iterations.

Maximum number of iterations. The Python controller calculation does not use it.

public int MaximumIterations { get; set; }
Public Property MaximumIterations As Integer

MobileCompatible: Gets a value indicating whether this controller is compatible with mobile interfaces.

Gets a value indicating whether this controller is compatible with mobile interfaces.

public override bool MobileCompatible { get; }
Public Overrides ReadOnly Property MobileCompatible As Boolean

MVHistory: Controller outputs recorded at each control step, in the manipulated variable's units, for the history chart.

Controller outputs recorded at each control step, in the manipulated variable's units, for the history chart.

public List<double> MVHistory { get; set; }
Public Property MVHistory As List(Of Double)

MVValue: Manipulated variable value written to the manipulated object at the last step, in SI units.

Manipulated variable value written to the manipulated object at the last step, in SI units.

public double MVValue { get; set; }
Public Property MVValue As Double

ObjectClass: Gets or sets the simulation object class, which is always Logical for special operations.

Gets or sets the simulation object class, which is always Logical for special operations.

public override SimulationObjectClass ObjectClass { get; set; }
Public Overrides Property ObjectClass As SimulationObjectClass

Output: Controller output of the last step: the MV value returned by the script, in the manipulated variable's units.

Controller output of the last step: the MV value returned by the script, in the manipulated variable's units.

public double Output { get; set; }
Public Property Output As Double

PVHistory: Process variable values recorded at each control step, divided by BaseSP, for the history chart.

Process variable values recorded at each control step, divided by BaseSP, for the history chart.

public List<double> PVHistory { get; set; }
Public Property PVHistory As List(Of Double)

PVValue: Process (controlled) variable value read at the last step, in the controlled variable's units.

Process (controlled) variable value read at the last step, in the controlled variable's units.

public double PVValue { get; set; }
Public Property PVValue As Double

PythonScript: IronPython source of the control law.

IronPython source of the control law. The script sees Flowsheet, Me/This and PV, and must define MV and SP.

public string PythonScript { get; set; }
Public Property PythonScript As String

ReferenceObject: Reference object, linked from ReferencedObjectData when the flowsheet loads.

Reference object, linked from ReferencedObjectData when the flowsheet loads. The calculation does not use it. Not serialized.

public BaseClass ReferenceObject { get; set; }
Public Property ReferenceObject As BaseClass

ResetRequested: Set to True by the dynamic runner when a fresh run starts, so the script (through Me or This) can reinitialize its...

Set to True by the dynamic runner when a fresh run starts, so the script (through Me or This) can reinitialize its own state. The controller itself never clears it.

public bool ResetRequested { get; set; }
Public Property ResetRequested As Boolean

SetPoint: Gets or sets the controller setpoint, in the controlled variable's units.

Gets or sets the controller setpoint, in the controlled variable's units. Same value as AdjustValue; the script overwrites it with SP at every step.

public double SetPoint { get; set; }
Public Property SetPoint As Double

SPHistory: Setpoint values recorded at each control step, divided by BaseSP, for the history chart.

Setpoint values recorded at each control step, divided by BaseSP, for the history chart.

public List<double> SPHistory { get; set; }
Public Property SPHistory As List(Of Double)

SPValue: Setpoint value at the last step, in the controlled variable's units.

Setpoint value at the last step, in the controlled variable's units.

public double SPValue { get; set; }
Public Property SPValue As Double

SupportsDynamicMode: Gets a value indicating whether this controller runs in dynamic mode.

Gets a value indicating whether this controller runs in dynamic mode. Always True.

public override bool SupportsDynamicMode { get; }
Public Overrides ReadOnly Property SupportsDynamicMode As Boolean

Methods

Calculate(object): Calculates the object.

Calculates the object.

Parameter Type Description
args Object
public override void Calculate(object args = null)
Public Overrides Sub Calculate(args As Object = Nothing)

ClearHistory(): Clears the SP, PV and MV histories.

Clears the SP, PV and MV histories.

public void ClearHistory()
Public Sub ClearHistory()

CloneXML(): Creates a deep copy of this object by round-tripping through XML serialization.

Creates a deep copy of this object by round-tripping through XML serialization.

public override object CloneXML()
Public Overrides Function CloneXML() As Object

CloseEditForm(): Closes the editor of this object, if it is open.

Closes the editor of this object, if it is open.

public override void CloseEditForm()
Public Overrides Sub CloseEditForm()

DisplayEditForm(): Opens the editor of this object.

Opens the editor of this object. A host that has no editor for it does nothing.

public override void DisplayEditForm()
Public Overrides Sub DisplayEditForm()

GetChartModel(string): Builds the history chart with the normalized setpoint and process variable and the controller output per control step.

Builds the history chart with the normalized setpoint and process variable and the controller output per control step.

Parameter Type Description
name String The chart name, shown as the subtitle ("History").
public override object GetChartModel(string name)
Public Overrides Function GetChartModel(name As String) As Object

GetChartModelNames(): Returns the names of the charts this controller can embed in the flowsheet.

Returns the names of the charts this controller can embed in the flowsheet.

public override List<string> GetChartModelNames()
Public Overrides Function GetChartModelNames() As List(Of String)

GetDisplayDescription(): Returns the description string for this controller type.

Returns the description string for this controller type.

public override string GetDisplayDescription()
Public Overrides Function GetDisplayDescription() As String

GetDisplayName(): Returns the display name for this controller type.

Returns the display name for this controller type.

public override string GetDisplayName()
Public Overrides Function GetDisplayName() As String

GetIconBitmapBytes(): Returns the raw bytes of the icon image for this controller.

Returns the raw bytes of the icon image for this controller.

public override byte[] GetIconBitmapBytes()
Public Overrides Function GetIconBitmapBytes() As Byte()

GetProperties(PropertyType): Get a list of all properties of the object.

Get a list of all properties of the object.

Parameter Type Description
proptype PropertyType Type of the property.
public override string[] GetProperties(PropertyType proptype)
Public Overrides Function GetProperties(proptype As PropertyType) As String()

GetPropertyDescription(string): Readable names for the property identifiers, which are the .NET property names.

Readable names for the property identifiers, which are the .NET property names.

Parameter Type Description
prop String
public override string GetPropertyDescription(string prop)
Public Overrides Function GetPropertyDescription(prop As String) As String

GetPropertyUnit(string, IUnitsOfMeasure): Gets the units of a property.

Gets the units of a property.

Parameter Type Description
prop String Property identifier.
su IUnitsOfMeasure Units system to use. Null to use the default (SI) system.
public override string GetPropertyUnit(string prop, IUnitsOfMeasure su = null)
Public Overrides Function GetPropertyUnit(prop As String, su As IUnitsOfMeasure = Nothing) As String

GetPropertyValue(string, IUnitsOfMeasure): Gets the value of a property.

Gets the value of a property.

Parameter Type Description
prop String Property identifier.
su IUnitsOfMeasure Units system to use. Null to use the default (SI) system.
public override object GetPropertyValue(string prop, IUnitsOfMeasure su = null)
Public Overrides Function GetPropertyValue(prop As String, su As IUnitsOfMeasure = Nothing) As Object

LoadData(List<XElement>): Loads object data stored in a collection of XML elements.

Loads object data stored in a collection of XML elements.

Parameter Type Description
data List<XElement>
public override bool LoadData(List<XElement> data)
Public Overrides Function LoadData(data As List(Of XElement)) As Boolean

SaveData(): Saves object data in a collection of XML elements.

Saves object data in a collection of XML elements.

public override List<XElement> SaveData()
Public Overrides Function SaveData() As List(Of XElement)

SetPropertyValue(string, object, IUnitsOfMeasure): Sets the value of a property.

Sets the value of a property.

Parameter Type Description
prop String Property identifier.
propval Object Property value to set at the specified units.
su IUnitsOfMeasure Units system to use. Null to use the default (SI) system.
public override bool SetPropertyValue(string prop, object propval, IUnitsOfMeasure su = null)
Public Overrides Function SetPropertyValue(prop As String, propval As Object, su As IUnitsOfMeasure = Nothing) As Boolean

UpdateEditForm(): Redraws the editor of this object with the current values, if it is open.

Redraws the editor of this object with the current values, if it is open.

public override void UpdateEditForm()
Public Overrides Sub UpdateEditForm()

Fields

BaseSP: Setpoint magnitude |SP| captured at the first control step, used to normalize the PV and SP histories.

Setpoint magnitude |SP| captured at the first control step, used to normalize the PV and SP histories. Nothing until the first step.

public double? BaseSP
Public BaseSP As Double?

f: The classic (WinForms) editor window open for this controller, if any.

The classic (WinForms) editor window open for this controller, if any. Not saved with the flowsheet.

public object f
Public f As Object