SMR startup simulation (outdated)
Contents
Overview
In order to test and demonstrate the time dependent calculation capabilities of the Kraken framework in a reasonably realistic context, a time dependent simulation was conducted of the initial rise to power of a small modular reactor (SMR) core. The simulation used the Ants nodal neutronics code to resolve the evolution of neutronics and the xenon fission poison chain in the system and the SUBCHANFLOW thermal hydraulics code to solve the coolant flow and heat transfer in fuel rods.
The modelled SMR is the same 37 assembly Er-UO2 fuelled core that has been previously used for the demonstration of the depletion capabilities of Kraken:
The transient starts from critical hot zero power (HZP) conditions (actually from 1 % power level) with all control rod banks at approximately 50 % insertion. The boron concentration in the coolant corresponds to the critical boron at all rods out (ARO) hot full power (HFP) conditions. The control rods are withdrawn from the core in a stepwise manner over 38 hours to allow for the accumulation of xenon in the core:
To reformulate the simulation setup:
- Evaluate (in a time-independent simulation) critical boron at hot full power all rods out conditions with convergence in
- Neutronics
- Thermal hydraulics
- Fuel temperature
- Xenon
- Using that critical boron, evaluate (in a time-independent simulation) critical control rod position at 1 % power level with convergence in
- Neutronics
- Thermal hydraulics
- Fuel temperature
- Xenon
- Save initial conditions from the 1 % power level time-independent calculation.
- Start a time dependent simulation from 1 % power level and slowly withdraw the control rods fully from the core.
If the time-independent and time-dependent calculation methodologies produce equivalent steady state solutions and have been correctly implemented, the simulation should (in the end) end up in the same state as the time-independent HFP ARO calculation.
Evaluating HFP ARO critical boron
Cerberus input for HPF ARO boron iteration
from os import environ from pathlib import Path import numpy as np import cerberus as cb from cerberus.solvers import CodeInput from cerberus.solvers import Solver from cerberus.interpolation import Interpolator from numpy.core.fromnumeric import size # Verbosity for terminal output of Cerberus cb.LOG.set_verbosity(1) # Create and start solvers solver_defs = [["SCF", environ["SCFWRAP_EXE_PATH"], [], ["./Inputs/scf/input.txt"]], ["ANTS", environ["ANTS_EXE_PATH"], ["--cerberus","--port"], ["./Inputs/Ants8g.inp"]]] solvers = {} port_number = 2211 for name, solver_path, params, inputs in solver_defs: # Create input solver_input = CodeInput(name, inputs) # Create solver solver = Solver(name, solver_path, params) solver.input = solver_input solver.initialize(port_number) # Add to solver dict solvers[name] = solver port_number += 1 # Alias variables for solvers scf = solvers["SCF"] ants = solvers["ANTS"] # Get SCF fields needed for coupled calculation scf_cool_temperature = scf.get_transferrable("scf_of_cool_temperature_chan") scf_cool_density = scf.get_transferrable("scf_of_cool_density_chan") scf_fuel_temperature = scf.get_transferrable("scf_of_fuel_temperature_vol_ave") scf_power = scf.get_transferrable("scf_if_fuel_power") # Initialize SCF power field (50 MW divided uniformly over SCF cells) scf_power.value_vec = 50e6/scf_power.n_values*np.ones(scf_power.n_values) # Get Ants fields needed for coupled calculation ants_cool_temperature = ants.get_transferrable("Ants_if_coolant_temperature") ants_cool_density = ants.get_transferrable("Ants_if_coolant_density") ants_fuel_temperature = ants.get_transferrable("Ants_if_fuel_temperature") ants_power = ants.get_transferrable("Ants_of_supernode_power") ants_boron = ants.get_transferrable("Ants_ov_boron") # Create interpolators that handle data transfer between SCF and Ants interp_ct = Interpolator.from_file(scf_cool_temperature, ants_cool_temperature, "./Inputs/scf_to_ants.txt") interp_cd = Interpolator.from_file(scf_cool_density, ants_cool_density, "./Inputs/scf_to_ants.txt") interp_ft = Interpolator.from_file(scf_fuel_temperature, ants_fuel_temperature, "./Inputs/scf_to_ants.txt") interp_p = Interpolator.from_file(ants_power, scf_power, "./Inputs/ants_to_scf.txt") ################################################################################ ################################################################################ # --- Coupled solution max_iter = 50 for i in range(max_iter): # --- TH solution and communication scf_power.communicate() scf_power.write_simple(suffix_in=f"{i+1}") scf.solve() scf_cool_density.communicate() scf_cool_temperature.communicate() scf_fuel_temperature.communicate() # --- Transfers from SCF to Ants fields interp_ct.interpolate() interp_cd.interpolate() interp_ft.interpolate() # --- Neutronics solution and communication ants_cool_density.communicate() ants_cool_temperature.communicate() ants_fuel_temperature.communicate() ants.solve() ants_power.communicate() ants_boron.communicate() # --- Transfers from Ants to SCF interp_p.interpolate() print(f"Finished iteration {i+1}, boron is {ants_boron.value_vec[0]}") # Choose field/value names to save to_save = ["Ants_ov_keff", "Ants_ov_boron"] # Output path. Create folder if necessary output_path = Path(f"./output") output_path.mkdir(exist_ok=True) for name in to_save: tra = ants.get_transferrable(name) tra.communicate() tra.write_simple(suffix_in="final", folder_path=output_path)