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¶

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¶
-
User guide
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.
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. |
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.
ControlledObject: The flowsheet object whose property is controlled.
The flowsheet object whose property is controlled. The calculation resolves the object from ControlledObjectData. Not serialized.
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.
MaximumIterations: Maximum number of iterations.
Maximum number of iterations. The Python controller calculation does not use it.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Methods¶
Calculate(object): Calculates the object.
Calculates the object.
| Parameter | Type | Description |
|---|---|---|
args |
Object |
ClearHistory(): Clears the SP, PV and MV histories.
Clears the SP, PV and MV histories.
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.
CloseEditForm(): Closes the editor of this object, if it is open.
Closes the editor of this object, if it is open.
DisplayEditForm(): Opens the editor of this object.
Opens the editor of this object. A host that has no editor for it does nothing.
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"). |
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.
GetDisplayDescription(): Returns the description string for this controller type.
Returns the description string for this controller type.
GetDisplayName(): Returns the display name for this controller type.
Returns the display name for this controller type.
GetIconBitmapBytes(): Returns the raw bytes of the icon image for this controller.
Returns the raw bytes of the icon image for this controller.
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. |
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 |
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. |
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. |
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> |
SaveData(): Saves object data in a collection of XML elements.
Saves object data in a collection of XML elements.
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. |
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.
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.