M .task/backlog.data M .task/completed.data M .task/pending.data M .task/undo.data A Class_Work/nuce2101/exam2/NUCE2101_SABO/Submission.pdf A Class_Work/nuce2101/exam2/NUCE2101_SABO/problem1.py A Class_Work/nuce2101/exam2/NUCE2101_SABO/problem1_equal_loading.png A Class_Work/nuce2101/exam2/NUCE2101_SABO/problem1_unequal_loading.png
322 lines
11 KiB
Python
322 lines
11 KiB
Python
import numpy as np
|
|
import matplotlib.pyplot as plt
|
|
from scipy.integrate import odeint
|
|
|
|
# Problem 1: Two-Loop Reactor System
|
|
|
|
print("=== Problem 1: Two-Loop Reactor with Steam Generators ===\n")
|
|
|
|
# Given Parameters
|
|
mu = None # Reactor Water Mass Fraction (RWMF) - to be determined or specified
|
|
|
|
# Base parameters
|
|
C_0 = 33.33 # Base Heat Capacity [%-sec/°F]
|
|
tau_0 = 0.75 * C_0 # Base Time Constant [sec/(%-sec/°F)] * C_0 = [sec]
|
|
|
|
# Initial steady state temperature
|
|
T_hot_initial = 450 # °F (reactor outlet / hot leg temperature)
|
|
T_cold_1_initial = 450 # °F (cold leg 1 temperature)
|
|
T_cold_2_initial = 450 # °F (cold leg 2 temperature)
|
|
|
|
print("Base Parameters:")
|
|
print(f"C_0 (Base Heat Capacity) = {C_0:.2f} %-sec/°F")
|
|
print(f"tau_0 (Base Time Constant) = {tau_0:.2f} sec")
|
|
print(f"\nInitial Steady State:")
|
|
print(f"T_hot = {T_hot_initial} °F")
|
|
print(f"T_cold_1 = {T_cold_1_initial} °F")
|
|
print(f"T_cold_2 = {T_cold_2_initial} °F")
|
|
|
|
|
|
# System parameters as functions of mu (RWMF)
|
|
def calculate_system_parameters(mu):
|
|
"""
|
|
Calculate system parameters based on Reactor Water Mass Fraction (mu)
|
|
|
|
Parameters:
|
|
mu: Reactor Water Mass Fraction (RWMF)
|
|
|
|
Returns:
|
|
dict: Dictionary containing all calculated parameters
|
|
"""
|
|
# Reactor parameters
|
|
tau_r = mu * tau_0 # Reactor time constant [sec]
|
|
C_r = mu * C_0 # Reactor heat capacity [%-sec/°F]
|
|
|
|
# Steam Generator parameters (each)
|
|
tau_sg = (1 - mu) * tau_r / 2 # Steam Generator water time constant [sec]
|
|
C_sg = (1 - mu) * C_0 / 2 # Steam Generator heat capacity [%-sec/°F]
|
|
|
|
params = {
|
|
"mu": mu,
|
|
"tau_r": tau_r,
|
|
"C_r": C_r,
|
|
"tau_sg": tau_sg,
|
|
"C_sg": C_sg,
|
|
"C_0": C_0,
|
|
"tau_0": tau_0,
|
|
}
|
|
|
|
return params
|
|
|
|
|
|
# Example: Calculate parameters for mu = 0.5 (50% of water in reactor)
|
|
if mu is None:
|
|
mu_example = 0.5
|
|
print(f"\n--- Example with mu = {mu_example} ---")
|
|
params = calculate_system_parameters(mu_example)
|
|
|
|
print(f"\nReactor Parameters:")
|
|
print(f" tau_r (Reactor time constant) = {params['tau_r']:.2f} sec")
|
|
print(f" C_r (Reactor heat capacity) = {params['C_r']:.2f} %-sec/°F")
|
|
|
|
print(f"\nSteam Generator Parameters (each):")
|
|
print(f" tau_sg (SG water time constant) = {params['tau_sg']:.2f} sec")
|
|
print(f" C_sg (SG heat capacity) = {params['C_sg']:.2f} %-sec/°F")
|
|
|
|
# System description
|
|
print(f"\n" + "=" * 60)
|
|
print("System Description:")
|
|
print("=" * 60)
|
|
print(
|
|
"""
|
|
Two-Loop Reactor System:
|
|
- Reactor (hot leg) at T_hot
|
|
- Steam Generator 1 with cold leg at T_cold_1
|
|
- Steam Generator 2 with cold leg at T_cold_2
|
|
- Each loop: pump → reactor → steam generator → back to pump
|
|
- Lumped reactor volume with combined hot branches
|
|
- Equal mass flow rates in each loop
|
|
- Ignore loop transport times
|
|
|
|
Key Assumptions:
|
|
- Each SG + cold loop has same water mass and flow rate
|
|
- Reactor and hot branches lumped into single water volume
|
|
- System initially at equilibrium (100% power, balanced)
|
|
- Constant average temperature maintained
|
|
"""
|
|
)
|
|
|
|
# Part A: Differential Equations
|
|
print(f"\n" + "=" * 60)
|
|
print("Part A: Differential Equations")
|
|
print("=" * 60)
|
|
|
|
|
|
def get_differential_equations(mu):
|
|
"""
|
|
Develop differential equations for T_hot, T_cold1, T_cold2
|
|
|
|
Key insight: Flow heat capacity rate W = C_0 / (2 * tau_0)
|
|
This is the (mass flow rate * specific heat) for each loop
|
|
"""
|
|
params = calculate_system_parameters(mu)
|
|
|
|
# Flow heat capacity rate for each loop (same for both loops)
|
|
W = C_0 / (2 * tau_0)
|
|
|
|
print(f"\nFor mu = {mu}:")
|
|
print(f"Flow heat capacity rate (each loop): W = {W:.4f} %-sec/°F")
|
|
print(f"C_r = {params['C_r']:.2f}, C_sg = {params['C_sg']:.2f}")
|
|
|
|
print(f"\nDifferential Equations:")
|
|
print(f" C_r * dT_hot/dt = P_r - W*(T_hot - T_cold1) - W*(T_hot - T_cold2)")
|
|
print(f" C_sg * dT_cold1/dt = W*(T_hot - T_cold1) - Qdot1")
|
|
print(f" C_sg * dT_cold2/dt = W*(T_hot - T_cold2) - Qdot2")
|
|
print(f"\nwhere:")
|
|
print(f" P_r = reactor power (positive for heat generation)")
|
|
print(f" Qdot1, Qdot2 = SG heat removal rates (positive for heat removal)")
|
|
print(f" W = {W:.4f} %-sec/°F (flow heat capacity rate per loop)")
|
|
|
|
# Matrix form: dT/dt = A*T + B
|
|
print(f"\n--- Matrix Form: dT/dt = A*T + B ---")
|
|
|
|
# Coefficient matrix A
|
|
A = np.array(
|
|
[
|
|
[-2 * W / params["C_r"], W / params["C_r"], W / params["C_r"]],
|
|
[W / params["C_sg"], -W / params["C_sg"], 0],
|
|
[W / params["C_sg"], 0, -W / params["C_sg"]],
|
|
]
|
|
)
|
|
|
|
print(f"\nMatrix A (coefficients):")
|
|
print(f" [{A[0,0]:7.4f} {A[0,1]:7.4f} {A[0,2]:7.4f}]")
|
|
print(f" [{A[1,0]:7.4f} {A[1,1]:7.4f} {A[1,2]:7.4f}]")
|
|
print(f" [{A[2,0]:7.4f} {A[2,1]:7.4f} {A[2,2]:7.4f}]")
|
|
|
|
# For general case with P_r, Qdot1, Qdot2
|
|
print(f"\nVector B (forcing terms, depends on P_r, Qdot1, Qdot2):")
|
|
print(f" [P_r/C_r, -Qdot1/C_sg, -Qdot2/C_sg]^T")
|
|
print(
|
|
f" [P_r/{params['C_r']:.2f}, -Qdot1/{params['C_sg']:.2f}, -Qdot2/{params['C_sg']:.2f}]^T"
|
|
)
|
|
|
|
return W, params
|
|
|
|
|
|
# Part D: Transient Simulation Setup
|
|
print(f"\n" + "=" * 60)
|
|
print("Part D: Transient Simulation (0 to 30 seconds)")
|
|
print("=" * 60)
|
|
|
|
|
|
def reactor_odes(y, t, W, C_r, C_sg, P_r, Q1, Q2):
|
|
"""
|
|
ODE system for two-loop reactor
|
|
y = [T_hot, T_cold1, T_cold2]
|
|
|
|
Parameters:
|
|
P_r: Reactor power (heat generation rate)
|
|
Q1, Q2: Steam generator heat removal rates (Qdot_1, Qdot_2)
|
|
"""
|
|
T_hot, T_cold1, T_cold2 = y
|
|
|
|
# Reactor energy balance
|
|
dT_hot_dt = (P_r - W * (T_hot - T_cold1) - W * (T_hot - T_cold2)) / C_r
|
|
|
|
# Steam generator 1 energy balance (Q1 is heat removal rate)
|
|
dT_cold1_dt = (W * (T_hot - T_cold1) - Q1) / C_sg
|
|
|
|
# Steam generator 2 energy balance (Q2 is heat removal rate)
|
|
dT_cold2_dt = (W * (T_hot - T_cold2) - Q2) / C_sg
|
|
|
|
return [dT_hot_dt, dT_cold1_dt, dT_cold2_dt]
|
|
|
|
|
|
def simulate_transient(mu, Q1_percent, Q2_percent, t_max=30):
|
|
"""
|
|
Simulate reactor transient
|
|
|
|
Parameters:
|
|
mu: Reactor Water Mass Fraction
|
|
Q1_percent: Steam generator 1 heat removal rate (% of nominal)
|
|
Q2_percent: Steam generator 2 heat removal rate (% of nominal)
|
|
t_max: Simulation time (seconds)
|
|
"""
|
|
params = calculate_system_parameters(mu)
|
|
W = C_0 / (2 * tau_0)
|
|
|
|
# Initial conditions (steady state at 100% power balanced)
|
|
T_hot_0 = T_hot_initial
|
|
T_cold1_0 = T_cold_1_initial
|
|
T_cold2_0 = T_cold_2_initial
|
|
y0 = [T_hot_0, T_cold1_0, T_cold2_0]
|
|
|
|
# Power levels (normalized - 100% = 1.0 in appropriate units)
|
|
P_r = 100.0 # Reactor power (heat generation rate)
|
|
Q1 = Q1_percent # SG1 heat removal rate
|
|
Q2 = Q2_percent # SG2 heat removal rate
|
|
|
|
# Time array
|
|
t = np.linspace(0, t_max, 500)
|
|
|
|
# Solve ODE system
|
|
solution = odeint(
|
|
reactor_odes, y0, t, args=(W, params["C_r"], params["C_sg"], P_r, Q1, Q2)
|
|
)
|
|
|
|
T_hot = solution[:, 0]
|
|
T_cold1 = solution[:, 1]
|
|
T_cold2 = solution[:, 2]
|
|
|
|
# Calculate average temperature (mass-weighted, depends on mu)
|
|
T_ave = mu * T_hot + (1 - mu) * (T_cold1 + T_cold2) / 2
|
|
|
|
return t, T_hot, T_cold1, T_cold2, T_ave
|
|
|
|
|
|
# Example: Show how to set up simulations
|
|
print("\nSimulation cases to run:")
|
|
print("1. mu=0.5, Q1=50%, Q2=50% (equally loaded)")
|
|
print("2. mu=0.75, Q1=50%, Q2=50% (equally loaded)")
|
|
print("3. mu=0.5, Q1=60%, Q2=40% (unequally loaded)")
|
|
print("4. mu=0.75, Q1=60%, Q2=40% (unequally loaded)")
|
|
print("\nNote: Percentages are fractions of reactor power (P_r = 100%)")
|
|
|
|
# Run example simulation
|
|
print("\n--- Running Example: mu=0.5, Equal Loading ---")
|
|
W_example, params_example = get_differential_equations(0.5)
|
|
|
|
# Run all simulations and create plots
|
|
print("\n" + "=" * 60)
|
|
print("Running Simulations and Creating Plots")
|
|
print("=" * 60)
|
|
|
|
# Case 1 & 2: Equally loaded (Q1=50%, Q2=50%)
|
|
fig1, axes1 = plt.subplots(2, 2, figsize=(14, 10))
|
|
fig1.suptitle(
|
|
"Equally Loaded Steam Generators (Q1=50%, Q2=50%)", fontsize=14, fontweight="bold"
|
|
)
|
|
|
|
for idx, mu in enumerate([0.5, 0.75]):
|
|
print(f"\nSimulating mu={mu}, Q1=50%, Q2=50%")
|
|
t, T_hot, T_cold1, T_cold2, T_ave = simulate_transient(mu, 50.0, 50.0)
|
|
|
|
# Plot temperatures
|
|
ax = axes1[idx, 0]
|
|
ax.plot(t, T_hot, "r-", linewidth=2, label="T_hot")
|
|
ax.plot(t, T_cold1, "b-", linewidth=2, label="T_cold1")
|
|
ax.plot(t, T_cold2, "g-", linewidth=2, label="T_cold2")
|
|
ax.plot(t, T_ave, "k--", linewidth=2, label="T_ave")
|
|
ax.set_xlabel("Time (sec)", fontsize=10)
|
|
ax.set_ylabel("Temperature (°F)", fontsize=10)
|
|
ax.set_title(f"mu = {mu} (RWMF)", fontsize=11, fontweight="bold")
|
|
ax.grid(True, alpha=0.3)
|
|
ax.legend(loc="best")
|
|
|
|
# Plot temperature differences
|
|
ax = axes1[idx, 1]
|
|
ax.plot(t, T_hot - T_cold1, "b-", linewidth=2, label="ΔT1 = T_hot - T_cold1")
|
|
ax.plot(t, T_hot - T_cold2, "g-", linewidth=2, label="ΔT2 = T_hot - T_cold2")
|
|
ax.set_xlabel("Time (sec)", fontsize=10)
|
|
ax.set_ylabel("Temperature Difference (°F)", fontsize=10)
|
|
ax.set_title(f"Temperature Differences (mu = {mu})", fontsize=11, fontweight="bold")
|
|
ax.grid(True, alpha=0.3)
|
|
ax.legend(loc="best")
|
|
|
|
plt.tight_layout()
|
|
plt.savefig("problem1_equal_loading.png", dpi=300, bbox_inches="tight")
|
|
print("Plot saved: problem1_equal_loading.png")
|
|
plt.close()
|
|
|
|
# Case 3 & 4: Unequally loaded (Q1=60%, Q2=40%)
|
|
fig2, axes2 = plt.subplots(2, 2, figsize=(14, 10))
|
|
fig2.suptitle(
|
|
"Unequally Loaded Steam Generators (Q1=60%, Q2=40%)", fontsize=14, fontweight="bold"
|
|
)
|
|
|
|
for idx, mu in enumerate([0.5, 0.75]):
|
|
print(f"\nSimulating mu={mu}, Q1=60%, Q2=40%")
|
|
t, T_hot, T_cold1, T_cold2, T_ave = simulate_transient(mu, 60.0, 40.0)
|
|
|
|
# Plot temperatures
|
|
ax = axes2[idx, 0]
|
|
ax.plot(t, T_hot, "r-", linewidth=2, label="T_hot")
|
|
ax.plot(t, T_cold1, "b-", linewidth=2, label="T_cold1")
|
|
ax.plot(t, T_cold2, "g-", linewidth=2, label="T_cold2")
|
|
ax.plot(t, T_ave, "k--", linewidth=2, label="T_ave")
|
|
ax.set_xlabel("Time (sec)", fontsize=10)
|
|
ax.set_ylabel("Temperature (°F)", fontsize=10)
|
|
ax.set_title(f"mu = {mu} (RWMF)", fontsize=11, fontweight="bold")
|
|
ax.grid(True, alpha=0.3)
|
|
ax.legend(loc="best")
|
|
|
|
# Plot temperature differences
|
|
ax = axes2[idx, 1]
|
|
ax.plot(t, T_hot - T_cold1, "b-", linewidth=2, label="ΔT1 = T_hot - T_cold1")
|
|
ax.plot(t, T_hot - T_cold2, "g-", linewidth=2, label="ΔT2 = T_hot - T_cold2")
|
|
ax.set_xlabel("Time (sec)", fontsize=10)
|
|
ax.set_ylabel("Temperature Difference (°F)", fontsize=10)
|
|
ax.set_title(f"Temperature Differences (mu = {mu})", fontsize=11, fontweight="bold")
|
|
ax.grid(True, alpha=0.3)
|
|
ax.legend(loc="best")
|
|
|
|
plt.tight_layout()
|
|
plt.savefig("problem1_unequal_loading.png", dpi=300, bbox_inches="tight")
|
|
print("Plot saved: problem1_unequal_loading.png")
|
|
plt.close()
|
|
|
|
print("\n" + "=" * 60)
|
|
print("Simulation Complete!")
|
|
print("=" * 60)
|