Separator Pressure and Level Control¶
In this tutorial you will control a two-phase separator with two loops in DWSIM's Classic UI: a pressure controller that moves the gas outlet valve and a level controller that moves the liquid outlet valve. You will start the vessel from an empty, high-pressure state, watch both loops bring it to its setpoints, store that state, and then schedule two pressure setpoint changes as events. The pressure loop is fast and the level loop is slow, and each one disturbs the other; reading that interaction is the point of the page.
What you will learn
- How a vessel's pressure and level are set by the two valves that drain it, and why each needs its own loop
- How to size the gas and liquid valves so that the controllers work in the middle of their range
- How to choose the span of a loop whose valve sits at a few percent of opening, and how to program setpoint changes as events
Prerequisites
- Completed PID Level Control: wiring, direction, offset and span are used without explanation here
- The two-phase separator from Simple Flash Drum
Process Overview¶
A feed of air, carbon dioxide, water and methanol at 3 bar enters a vertical vessel through a valve; the gas leaves at the top through the pressure valve, the liquid at the bottom through the level valve, both to atmospheric lines:
- Feed at 273 K, 3.03 bar, 4.415 mol/s (Flow specification)
- FV-01, the feed valve, gas Kv 430, half open
- SG-01, the separator, 1 m³, 2 m tall, vertical
- PV-01, the gas valve, Kv 16, moved by PIC-01 to hold 2 bar
- LV-01, the liquid valve, Kv 3, moved by LIC-01 to hold 0.3 m
- Gas and Liquid at 1 atm (Pressure specifications)
Process Flow Diagram¶
graph LR
F["Feed<br/>273 K, 3.03 bar<br/>4.415 mol/s"] --> FV["FV-01<br/>Kv 430"]
FV --> SG["SG-01<br/>1 m³, 2 m"]
SG -->|gas| PV["PV-01<br/>Kv 16"]
SG -->|liquid| LV["LV-01<br/>Kv 3"]
PV --> G["Gas<br/>1 atm"]
LV --> L["Liquid<br/>1 atm"]
SG -. pressure .-> PIC["PIC-01<br/>SP 2 bar"]
PIC -. opening .-> PV
SG -. level .-> LIC["LIC-01<br/>SP 0.3 m"]
LIC -. opening .-> LV
Key Design Parameters¶
| Parameter | Value | Unit |
|---|---|---|
| Compounds | Air, Carbon dioxide, Water, Methanol | - |
| Property Package | Raoult's Law | - |
| Feed | 273.25 K, 302,600 Pa, 4.415 mol/s | - |
| Feed composition (molar) | 9.09 % air, 9.09 % CO2, 72.73 % water, 9.09 % methanol | - |
| FV-01 Kv (gas), opening | 430, 50 | m³/h, % |
| SG-01 volume, height | 1.0, 2.0 | m³, m |
| PV-01 Kv (gas) | 16 | m³/h |
| LV-01 Kv (liquid) | 3 | m³/h |
| PIC-01 | SP 2.0 bar, Kp 1, Ki 0.05, reverse, offset 13 %, span 20 % | - |
| LIC-01 | SP 0.3 m, Kp 3, Ki 0.05, reverse, offset 10 %, span 20 % | - |
| Integrator | 5 s step; 120 min (startup), 30 min (setpoints) | - |
Step-by-Step in the Classic UI¶
1. Set up the simulation¶
File > New Chemical Process Model: compounds Air, Carbon dioxide, Water, Methanol; property package Raoult's Law.
2. Build the flowsheet¶
Six material streams (Feed, 2, 3, Gas, 5, Liquid), three valves and one Gas-Liquid Separator connected as in the diagram. Feed: 273.25 K, 302600 Pa, 4.415 mol/s, composition as in the table. Valves: FV-01 Gas Kv 430 at 50 %, PV-01 Gas Kv 16, LV-01 Liquid Kv 3, all three with Opening vs Kv/Kvmax ticked and 50 % open for the steady state. Solve.
The steady state passes 0.023 kg/s of gas and 0.077 kg/s of liquid. The valves are wide open for the flows they carry, so the pressures barely drop: this steady state is a starting point, and nothing more.
3. Dynamic setup¶
Dynamic Mode on. SG-01, tab Dynamics: Volume 1 m³, Height 2 m, Vessel Orientation vertical, Initialize using Inlet Stream ticked. Feed: Dynamics specification Flow. Gas and Liquid: Pressure, both at 101325 Pa.
4. The two controllers¶
PIC-01: controlled variable SG-01 Operating Pressure in bar, manipulated variable PV-01 Opening, setpoint 2, reverse acting, output 0 to 100, offset 13, span 20, Kp 1, Ki 0.05.
LIC-01: controlled variable SG-01 Liquid Level in m, manipulated variable LV-01 Opening, setpoint 0.3, reverse acting, output 0 to 100, offset 10, span 20, Kp 3, Ki 0.05.
Why a span of 20 %
At 2 bar the gas valve passes 90 kg/h with 13 % of opening and the liquid valve passes 270 kg/h with 28 %. A span of 100 % would let a 10 % pressure error swing the gas valve by 10 % of opening, almost its whole working range, and the loop would slam between shut and wide open. A span of 20 % makes one unit of controller output worth 20 % of opening; with Kp 1 a 10 % error moves the valve by 2 %. Size the span to the range the valve really uses.

5. Startup run¶
Integrator Int1: 5 s step, 120 min. Monitor SG-01 Operating Pressure (bar) and Liquid Level (m), the mass flows of streams 3 and 5 (kg/h), and the openings of PV-01 and LV-01. Schedule Startup from the current state. Run.
The vessel starts at the feed pressure, 3.03 bar, almost empty. PIC-01 shuts PV-01 from 50 % to 13 % within the first minutes and the pressure lands on 2.00 bar by 10 min. The level rises at a steady 0.9 cm per minute while LV-01 stays shut, reaches 0.30 m at 30 min, overshoots to 0.33 m at 35 min and settles on 0.300 m by 55 min with LV-01 at 28 % passing 270 kg/h.
6. Store the state and schedule the setpoint changes¶
Store the current state as Steady with Store Current (Flowsheet States group of the toolbar). Event set SP: PIC-01 SetPointAbs = 5 at 00:03:00, and 2 at 00:10:00. Schedule Sch1: integrator Int1 (change its duration to 30 min), event set SP, initial state Steady. Run.
7. Read the interaction¶
At 3 min the setpoint jumps to 5 bar. PIC-01 shuts PV-01 completely and the pressure climbs at about 1.1 bar per minute, the rate at which 90 kg/h of gas fills a 1 m³ headspace: 2.5 bar at 4 min, 3.6 at 6, 4.7 at 8, 5.0 at 10. At 10 min the setpoint drops back to 2 bar: PV-01 opens to 51 %, the pressure falls to 1.65 bar at 12 min, and the loop brings it back to 2.00 bar by 20 min. Meanwhile the level wanders: 0.32 m while the pressure is rising, 0.28 m after the drop, back to 0.30 m by 20 min. The liquid valve sees the vessel pressure on its upstream side; when the pressure moves, the liquid flow moves with it, and LIC-01 has to catch up.

Results and Validation¶
| Variable | Expected | Unit |
|---|---|---|
| Pressure at the end of startup | 2.00 | bar |
| PV-01 opening at 2 bar | 13 | % |
| Level at the end of startup | 0.300 | m |
| LV-01 opening at 0.3 m | 28 | % |
| Time for the pressure to reach 5 bar after the step | about 7 min | - |
| Pressure minimum after the drop to 2 bar | 1.65 | bar |
| Level excursion during the pressure changes | 0.28 to 0.32 | m |
Expected results
The pressure loop settles in ten minutes and follows the setpoint changes as fast as the gas inventory allows; the level loop takes an hour to fill the vessel and holds 0.30 m within 2 cm through the pressure changes. Gas flow 90 kg/h and liquid flow 270 kg/h at steady state are the feed split.
Understanding the Results¶
The two loops have different natures. The pressure of a 1 m³ vessel fed with 90 kg/h of gas can only change as fast as the gas inventory does: shutting the outlet raises it at about 1 bar per minute, and no tuning makes it faster. Opening the valve wide drops it faster than that, which is why the return to 2 bar undershoots to 1.65 bar. The level of the same vessel fed with 270 kg/h of liquid moves at about a centimetre per minute: the level loop is ten times slower, and its gains reflect that.
They also interact through the valve equation. The liquid valve's driving force is the vessel pressure plus the liquid head minus the outlet pressure; when the pressure goes from 2 to 5 bar the liquid flow doubles at the same opening, the level falls, and LIC-01 closes the valve. When the pressure comes back the opposite happens. On a real separator this coupling is why the pressure loop is tuned first and kept steady, and the level loop is tuned with the pressure loop closed.
Reading the openings
A valve working at 13 % of opening is oversized for its duty; the sample's original Kv values (164 for the gas valve, 30 for the liquid valve) put the working points at 1 % and 3 %, where a fraction of a percent of opening is a large change in flow. Choosing Kv so that the design flow passes at 30 to 60 % of opening is the first thing to check when a loop refuses to settle.
Automating This Tutorial¶
Files in this repository
- Python script:
examples/dynamics/03_separator_control.py - Pre-built flowsheet:
examples/saved/dynamic_separator_control.dwxmz - In DWSIM: Samples list on the welcome screen,
Dynamic Simulation - Separator Pressure and Level Control(the same vessel with the original valve sizes and gains)
import os
import sys
import pythonnet
pythonnet.load("netfx") # DWSIM is a .NET Framework application
import clr # noqa: E402
DWSIM_BIN = os.environ.get("DWSIM_BIN")
if not DWSIM_BIN:
raise SystemExit("Set DWSIM_BIN to the DWSIM installation folder before running.")
for sub in ("", "unitops", "ppacks", "extenders"):
sys.path.append(os.path.join(DWSIM_BIN, sub))
clr.AddReference("DWSIM.Automation")
clr.AddReference("DWSIM.Automation.FluentAPI")
clr.AddReference("DWSIM.UnitOperations")
from DWSIM.Automation.FluentAPI import Flowsheet, PropertyPackages, Q
from DWSIM.UnitOperations.UnitOperations import Valve
from System import TimeSpan
fs = (Flowsheet.Create("SeparatorControl")
.WithCompounds("Air", "Carbon dioxide", "Water", "Methanol")
.WithPropertyPackage(PropertyPackages.Raoult))
feed = (fs.AddMaterialStream("Feed").At(Q.Kelvin(273.25), Q.Pascal(302600.0))
.WithMolarFlow(Q.MolPerSecond(4.415))
.SetCompoundMolarFlow("Air", 0.4013).SetCompoundMolarFlow("Carbon dioxide", 0.4013)
.SetCompoundMolarFlow("Water", 3.2111).SetCompoundMolarFlow("Methanol", 0.4013)
.AsFlowSpec())
s2 = fs.AddMaterialStream("2").AsPressureSpec()
s3 = fs.AddMaterialStream("3").AsPressureSpec()
gas = fs.AddMaterialStream("Gas").AsPressureSpec()
s5 = fs.AddMaterialStream("5").AsPressureSpec()
liq = fs.AddMaterialStream("Liquid").AsPressureSpec()
(fs.AddValve("FV-01").WithCalcMode(Valve.CalculationMode.Kv_Gas).WithKv(430.0)
.WithOpeningKvRelationship().WithOpeningPercent(50.0).ConnectFeed(feed, 0).ConnectProduct(s2, 0))
sep = (fs.AddSeparator("SG-01").WithVolume(Q.CubicMeters(1.0)).WithHeight(Q.Meters(2.0))
.InitializeFromInlet(True).ConnectFeed(s2, 0).ConnectProduct(s3, 0).ConnectProduct(s5, 1))
(fs.AddValve("PV-01").WithCalcMode(Valve.CalculationMode.Kv_Gas).WithKv(16.0)
.WithOpeningKvRelationship().WithOpeningPercent(50.0).ConnectFeed(s3, 0).ConnectProduct(gas, 0))
(fs.AddValve("LV-01").WithCalcMode(Valve.CalculationMode.Kv_Liquid).WithKv(3.0)
.WithOpeningKvRelationship().WithOpeningPercent(50.0).ConnectFeed(s5, 0).ConnectProduct(liq, 0))
fs.AutoLayout()
fs.Solve()
gas.Object.Phases[0].Properties.pressure = 101325.0
liq.Object.Phases[0].Properties.pressure = 101325.0
pic = (fs.AddPIDController("PIC-01").Controls("SG-01", "Operating Pressure", "bar")
.Manipulates("PV-01", "PROP_VA_5", "").WithSetPoint(2.0).WithTuning(1.0, 0.05, 0.0)
.WithOutputLimits(0.0, 100.0).WithOffset(13.0).ReverseActing(True))
pic.Object.ManipulatedVariableSpan = 20.0
lic = (fs.AddPIDController("LIC-01").Controls("SG-01", "Liquid Level", "m")
.Manipulates("LV-01", "PROP_VA_5", "").WithSetPoint(0.3).WithTuning(3.0, 0.05, 0.0)
.WithOutputLimits(0.0, 100.0).WithOffset(10.0).ReverseActing(True))
lic.Object.ManipulatedVariableSpan = 20.0
def integrator(name, minutes):
return (fs.Dynamics.DefineIntegrator(name)
.WithIntegrationStep(TimeSpan.FromSeconds(5)).WithDuration(TimeSpan.FromMinutes(minutes))
.Monitor("SG-01", "Operating Pressure", "bar", "pressure")
.Monitor("SG-01", "Liquid Level", "m", "level")
.Monitor("3", "PROP_MS_2", "kg/h", "gas flow").Monitor("5", "PROP_MS_2", "kg/h", "liquid flow")
.Monitor("PV-01", "PROP_VA_5", "", "PV opening").Monitor("LV-01", "PROP_VA_5", "", "LV opening"))
integrator("Long", 120)
integrator("Int1", 30)
fs.Dynamics.WithHistorian(True, 5000)
fs.Dynamics.DefineSchedule("Startup").WithIntegrator("Long").UseCurrentStateAsInitial(True).MakeCurrent()
r = fs.RunDynamics("Startup").Execute()
print(f"startup: pressure {r.GetSeries('pressure').Final:.3f} bar, level {r.GetSeries('level').Final:.3f} m")
fs.Dynamics.StoreCurrentStateAs("Steady")
(fs.Dynamics.DefineEventSet("SP")
.AddStepChange("PIC-01", "SetPointAbs", 5.0, Q.Minutes(3.0), "", "P1")
.AddStepChange("PIC-01", "SetPointAbs", 2.0, Q.Minutes(10.0), "", "P2"))
fs.Dynamics.DefineSchedule("Sch1").WithIntegrator("Int1").WithEventSet("SP").WithInitialState("Steady").MakeCurrent()
r = fs.RunDynamics("Sch1").Execute()
p = r.GetSeries("pressure")
print(f"pressure at 10 min {p.ValueAt(600.0):.2f} bar, minimum after the drop {p.Min:.2f} bar")
lv = r.GetSeries("level")
print(f"level excursion {lv.Min:.3f} to {lv.Max:.3f} m")
fs.Save("dynamic_separator_control.dwxmz")
Build the vessel and valves with dwsim.unitop.add and dwsim.unitop.connect, add the two PID controllers, then define integrators, the stored state, the event set and the schedules with the dwsim.dynamics.* tools.
Output may vary
Results depend on the LLM's reasoning quality and tool-use accuracy. Always verify the simulation matches your intent before relying on the numbers.
Use DWSIM (via the MCP server) to build a two-phase separator with pressure and
level control:
- Compounds Air, Carbon dioxide, Water, Methanol; Raoult's Law
- Feed at 273.25 K, 302600 Pa, 4.415 mol/s (9.09 % air, 9.09 % CO2, 72.73 % water,
9.09 % methanol), dynamics specification Flow
- Feed valve FV-01 (gas Kv 430, 50 %), vertical separator SG-01 (1 m3, 2 m, initialise
from the inlet), gas valve PV-01 (gas Kv 16), liquid valve LV-01 (liquid Kv 3);
outlets Gas and Liquid at 101325 Pa with Pressure specification
- PIC-01: SG-01 operating pressure (bar) -> PV-01 opening, SP 2 bar, reverse, offset
13 %, span 20, Kp 1, Ki 0.05; LIC-01: SG-01 liquid level (m) -> LV-01 opening,
SP 0.3 m, reverse, offset 10 %, span 20, Kp 3, Ki 0.05
- Integrator 5 s step; run 120 min from the current state; store the state as "Steady"
- Event set: PIC-01 setpoint 5 bar at 3 min, 2 bar at 10 min; run 30 min from "Steady"
- Report the pressure at 10 min, its minimum after the drop, and the level excursion
Exercises
- Double the feed to 8.83 mol/s at 5 min in a new event set. How far does the pressure move before PIC-01 catches it, and where do the two valve openings settle?
- Put LIC-01 in manual (event
ManualOverride= 1) and repeat the setpoint schedule. What does the level do during the pressure rise? - Return PV-01 to its original Kv of 164 and retune PIC-01 to hold 2 bar. What span and gains do you need, and how does the pressure trace compare?
Further Reading¶
Selected references from the DWSIM technical bibliography.
- W. L. Luyben. (1990). Process Modeling, Simulation and Control for Chemical Engineers. McGraw-Hill
- B. G. Liptak (ed.). (2006). Instrument Engineers' Handbook: Process Control and Optimization. CRC Press
Next Steps¶
In Events, Schedules and States, the events become the subject: steps and ramps, gauges with alarms, a cause-and-effect matrix and the stored states that make every run repeatable.