|
|
|
|
|
""" |
|
|
Disturbance Simulation Example |
|
|
|
|
|
This example demonstrates how to apply process disturbances |
|
|
and observe the controller response. |
|
|
""" |
|
|
|
|
|
import numpy as np |
|
|
from tep import TEPSimulator, DISTURBANCE_NAMES |
|
|
from tep.simulator import ControlMode |
|
|
|
|
|
|
|
|
def main(): |
|
|
print("TEP Disturbance Simulation Example") |
|
|
print("=" * 50) |
|
|
|
|
|
|
|
|
sim = TEPSimulator( |
|
|
random_seed=12345, |
|
|
control_mode=ControlMode.CLOSED_LOOP |
|
|
) |
|
|
sim.initialize() |
|
|
|
|
|
|
|
|
print("\nAvailable disturbances:") |
|
|
for i, name in enumerate(DISTURBANCE_NAMES[:15], 1): |
|
|
print(f" IDV({i:2d}): {name}") |
|
|
|
|
|
|
|
|
print("\n" + "=" * 50) |
|
|
print("Example 1: IDV(1) - A/C Feed Ratio Step Change") |
|
|
print("=" * 50) |
|
|
|
|
|
result = sim.simulate( |
|
|
duration_hours=4.0, |
|
|
disturbances={1: (1.0, 1)}, |
|
|
record_interval=60 |
|
|
) |
|
|
|
|
|
print(f"\nDisturbance applied at t=1.0 hour") |
|
|
print(f"Simulation completed: {result.time[-1]:.1f} hours") |
|
|
|
|
|
|
|
|
idx_before = np.argmin(np.abs(result.time - 0.9)) |
|
|
idx_after = np.argmin(np.abs(result.time - 3.5)) |
|
|
|
|
|
print(f"\nKey measurements (before -> after disturbance):") |
|
|
print(f" Reactor temp: {result.measurements[idx_before, 8]:.1f} -> {result.measurements[idx_after, 8]:.1f} °C") |
|
|
print(f" Reactor level: {result.measurements[idx_before, 7]:.1f} -> {result.measurements[idx_after, 7]:.1f} %") |
|
|
print(f" A+C feed flow: {result.measurements[idx_before, 3]:.2f} -> {result.measurements[idx_after, 3]:.2f} kscmh") |
|
|
|
|
|
|
|
|
print("\n" + "=" * 50) |
|
|
print("Example 2: Multiple disturbances") |
|
|
print("=" * 50) |
|
|
|
|
|
sim.initialize() |
|
|
|
|
|
result = sim.simulate( |
|
|
duration_hours=6.0, |
|
|
disturbances={ |
|
|
1: (1.0, 1), |
|
|
4: (3.0, 1), |
|
|
}, |
|
|
record_interval=60 |
|
|
) |
|
|
|
|
|
print(f"\nDisturbance schedule:") |
|
|
print(f" IDV(1) applied at t=1.0 hour") |
|
|
print(f" IDV(4) applied at t=3.0 hours") |
|
|
print(f"Shutdown: {result.shutdown}") |
|
|
|
|
|
|
|
|
print("\n" + "=" * 50) |
|
|
print("Example 3: Real-time disturbance activation") |
|
|
print("=" * 50) |
|
|
|
|
|
sim.initialize() |
|
|
|
|
|
|
|
|
measurements_log = [] |
|
|
|
|
|
for i in range(7200): |
|
|
|
|
|
if i == 1800: |
|
|
print(f" Applying IDV(1) at t={sim.time*60:.1f} minutes") |
|
|
sim.set_disturbance(1, 1) |
|
|
|
|
|
|
|
|
if i == 5400: |
|
|
print(f" Removing IDV(1) at t={sim.time*60:.1f} minutes") |
|
|
sim.set_disturbance(1, 0) |
|
|
|
|
|
running = sim.step() |
|
|
if not running: |
|
|
print(" Process shutdown!") |
|
|
break |
|
|
|
|
|
|
|
|
if i % 60 == 0: |
|
|
measurements_log.append(sim.get_measurements().copy()) |
|
|
|
|
|
print(f"\nFinal time: {sim.time*60:.1f} minutes") |
|
|
print(f"Data points logged: {len(measurements_log)}") |
|
|
|
|
|
|
|
|
print("\n" + "=" * 50) |
|
|
print("Example 4: Random disturbances (IDV 8-12)") |
|
|
print("=" * 50) |
|
|
|
|
|
sim.initialize() |
|
|
|
|
|
|
|
|
sim.set_disturbance(8, 1) |
|
|
sim.set_disturbance(11, 1) |
|
|
|
|
|
result = sim.simulate(duration_hours=2.0, record_interval=60) |
|
|
|
|
|
temps = result.measurements[:, 8] |
|
|
print(f"\nReactor temperature with random disturbances:") |
|
|
print(f" Mean: {np.mean(temps):.2f} °C") |
|
|
print(f" Std: {np.std(temps):.2f} °C (increased due to disturbances)") |
|
|
|
|
|
print("\nExample complete!") |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |
|
|
|