This is a small regulatory control project for a non-isothermal CSTR (continuous stirred-tank reactor).
The simulation starts from a selected steady-state operating point. At this point, the reactor temperature and concentration stay constant.
In this project, the selected steady-state temperature is used as the target temperature Tset.
Then a sudden disturbance happens at t = 20 min, for example a change in feed concentration.
After the disturbance, the reactor temperature T moves away from the desired temperature Tset.
Now it is the PI controller's job to bring T back close to Tset by controlling the jacket temperature Tc.
I compare three cases:
- Open-loop: no PI controller, only the CSTR itself
- Manual PI: PI controller with manually chosen parameters
KpandKi - Optuna PI: PI controller with
KpandKiselected by Optuna
PI means proportional-integral control. It uses Kp and Ki to correct the temperature error.
Optuna is a Python optimization tool. In this project, it is used to search for good Kp and Ki values.
At first, the script 01_steady_state_scan.py scans the residence time tau from 1e-3 to 1e3, and the reactor temperature from 250 K to 500 K.
It looks for all steady states. Then the steady states are classified as stable or unstable. Approximate critical oscillation points and turning points are also marked.
Then the operating point candidates are selected with these filters:
taubetween 1 and 100 min- conversion
xA > 95% - reactor temperature
T < 340 K - stable operating point
- enough distance from critical points
The following operating point is selected:
tau = 19.97 min
Tset = 337.39 K
ca = 0.068 kmol/m³
A good controller should:
- keep
Tclose toTset - return close to
Tsetat the end - avoid too high reactor temperature
- avoid too much or strange movement of
Tc
This is translated into four score terms:
IAE: total temperature error over timefinal_offset: remaining error near the endT_max_penalty: penalty if the reactor gets too hotTc_move: penalty if the jacket temperature moves too much
The score is calculated as:
score = (
IAE
+ 100 * final_offset
+ 1000 * T_max_penalty
+ 100 * Tc_move
)The weights of the score are chosen after a simple score scan with 02_score_scan.py.
This script tests random Kp and Ki values and checks the typical size of the different score terms.
Based on this scan, the score weights were chosen so that all terms have a visible and suitable influence on the final score.
In 03_final_control.py, there are three types of cases:
-
Nominal case: used to tune the PI controller. Only the feed concentration is increased by 10% at
t = 20 min. -
Validation cases: used to test if the same PI controller parameters still work under other disturbances.
Examples:
-
feed concentration increases or decreases at
t = 20 min -
feed temperature increases or decreases at
t = 20 min -
heat-transfer coefficient
UAincreases or decreases att = 20 min -
combined process conditions
-
Stress case: all three conditions are changed at
t = 20 min: feed concentration, feed temperature, and heat-transfer coefficientUA.
Open-loop does not bring the reactor temperature back to Tset.
Manual PI works better than open-loop, but it does not fully bring T back to Tset.
Optuna PI has the best performance among all three cases. It brings T back close to Tset and has the smallest temperature deviation.
The Kp and Ki tuned on the nominal case also show acceptable performance in the validation cases.
In the stress test, although Tc reaches Tc_min, T still does not return to Tset.
This means the disturbance is very strong. Optuna can improve the controller parameters, but it is not a solution to all problems. There are physical limits, for example the jacket cooling capacity.
The CSTR model and parameter values are based on Chapter 6, The Energy Balance for Chemical Reactors, from Rawlings and Ekerdt, Chemical Reactor Analysis and Design Fundamentals, Nob Hill Publishing.
Source PDF: https://sites.engineering.ucsb.edu/~jbraw/chemreacfun/ch6/slides-enbal-2up.pdf
The Python code, controller tuning, score design and validation cases were created for this project.
This is a simplified CSTR model.
Main assumptions and limitations:
- perfectly mixed reactor
- incompressible liquid
- constant density and heat capacity
- inlet flow equals outlet flow
- first-order reaction with Arrhenius temperature dependence
- jacket temperature
Tccan be changed directly - disturbances are step changes at
t = 20 min Tcis limited betweenTc_minandTc_maxTccan change immediately withinTc_minandTc_max- simplified heat-transfer model
In reality, jacket temperature would change more slowly. This should be added in a later version.
Python is required.
Install packages:
pip install numpy pandas scipy matplotlib optunaRun the scripts in order:
python 01_steady_state_scan.py
python 02_score_scan.py
python 03_final_control.pyResults are saved in the outputs/ folder.
Possible next steps:
- full PID controller
- coolant dynamics
- actuator rate limit
- LMTD-based heat transfer
- startup simulation
- control near oscillatory operating regions

