import json
from pathlib import Path
import openmc
from bluemira.base.file import get_bluemira_root
from bluemira.base.look_and_feel import bluemira_print
from bluemira.codes.openmc import DAGMCSolver
from bluemira.codes.openmc.sources import make_tokamak_source
from bluemira.equilibria.equilibrium import Equilibrium
from bluemira.materials.cache import establish_material_cache, get_cached_material
par = Path(__file__).parent
Running a DAGMC model in OpenMC
# OptimisedReactor can be exported by running examples/design/optimised_reactor.ex.py
# Change this to the name of your DAGMC model
dag_model_path = par / "OptimisedReactor.h5m"
meta_data_path = par / "OptimisedReactor.meta.json"
eq_data_path = par / "OptimisedReactor.eq.json"
# Fill me in eg "/a/path/to/"
cross_section_folder = ""
if not cross_section_folder:
raise ValueError("Please fill in the path to your cross_section xml file")
cross_section_xml = Path(cross_section_folder, "cross_sections.xml")
establish_material_cache([
Path(get_bluemira_root(), "examples", "design", "design_materials.py")
.resolve()
.as_posix(),
"matproplib",
])
omc_output_path = par / "omc"
# Ensure OpenMC output directory exists
omc_output_path.mkdir(parents=True, exist_ok=True)
Running the DAGMC model in OpenMC
params = {
"R_0": {"value": 9, "unit": "m"},
"profile_rho_ped": {"value": 0.94, "unit": "dimensionless"},
"P_fus": {"value": 2, "unit": "GW"},
"n_profile_alpha": {"value": 1.0, "unit": "dimensionless"},
"n_e_core": {"value": 1e20, "unit": "1/m³"},
"n_e_ped": {"value": 5e19, "unit": "1/m³"},
"n_e_sep": {"value": 3e19, "unit": "1/m³"},
"T_profile_alpha": {"value": 1.45, "unit": "dimensionless"},
"T_profile_beta": {"value": 2.0, "unit": "dimensionless"},
"T_e_core": {"value": 3.8e-15, "unit": "J"},
"T_e_ped": {"value": 8.8e-16, "unit": "J"},
"T_e_sep": {"value": 1.6e-17, "unit": "J"},
"T_ie_ratio": {"value": 1.0, "unit": "dimensionless"},
"n_i_fuel": {"value": 6e19, "unit": "1/m³"},
"n_e": {"value": 7e19, "unit": "1/m³"},
"shaf_shift": {"value": 0.6, "unit": "m"},
}
build_config = {
"cross_section_xml": cross_section_xml.as_posix(),
"photon_transport": True,
"electron_treatment": "ttb",
"export_dagmc_model": True,
"dagmc_export_dir": par,
"neutronics_output_path": par,
"particles": 10000,
"batches": 2,
"rel_max_lost_particles": 0.01,
"max_lost_particles": 10,
"converter_config": {
"converter_type": "fast_ctd",
"imprint_geometry": True,
"imprint_per_compound": True,
"minimum_include_volume": 0.001,
"fix_step_to_brep_geometry": False,
"merge_dist_tolerance": 0.001,
"lin_deflection_tol": 0.001,
"lin_deflection_is_absolute": False,
"angular_deflection_tol": 0.5,
"run_make_watertight": True,
"save_vtk_model": True,
"enable_ext_debug_logging": False,
"use_cached_files": False,
"clean_up_cached": False,
},
}
# load model materials
with open(meta_data_path) as meta_file:
bom = json.load(meta_file)["bom"]
materials = [
get_cached_material(mat_name).convert(
"openmc", {"temperature": 301, "pressure": 101325}
)
for mat_name in bom
]
# create tally function
def dagmc_tallys(
material_list, # noqa: ARG001
model: openmc.Geometry,
mesh_shape: tuple[float, ...] = (100, 100, 100),
):
"""Create tallys for openmc"""
# mesh that covers the geometry
mesh = openmc.RegularMesh.from_domain(model, dimension=mesh_shape)
mesh_filter = openmc.MeshFilter(mesh)
# name, scores, filters
return [
("heating", "heating", None),
("heating_on_mesh", "heating", [mesh_filter]),
("TBR", "(n,Xt)", None),
("tbr_on_mesh", "(n,Xt)", [mesh_filter]),
("flux_on_mesh", "flux", [mesh_filter]),
]
# load DAG model
solver = DAGMCSolver(
params,
build_config,
Equilibrium.from_eqdsk(eq_data_path, from_cocos="bluemira"),
source=make_tokamak_source,
dagmc_model_path=dag_model_path,
materials=materials,
tally_function=dagmc_tallys,
)
openmc_results, derived_results = solver.execute(run_mode="run")
Extracting the OpenMC results
This section extracts the results from the OpenMC simulation, including the total breeding ratio (TBR) and the heating deposited in the reactor.
bluemira_print(f"The reactor has a TBR of {derived_results.TBR}")
bluemira_print(f"Standard deviation on the TBR is {openmc_results.tbr_err}")
heating_cell_tally = openmc_results.statepoint.get_tally(name="heating")
bluemira_print(
f"The heating of {heating_cell_tally.mean.sum() / 1e6} MeV "
"per source particle is deposited"
)
bluemira_print(
"Standard deviation on the heating tally is"
f" {heating_cell_tally.std_dev.sum() / 1e3} keV"
)