diff --git a/process/core/init.py b/process/core/init.py index 9b81fbfd5..12322d70e 100644 --- a/process/core/init.py +++ b/process/core/init.py @@ -18,7 +18,6 @@ from process.core.solver.constraints import ConstraintManager from process.data_structure.build_variables import init_build_variables from process.data_structure.buildings_variables import init_buildings_variables -from process.data_structure.ccfe_hcpb_module import init_ccfe_hcpb_module from process.data_structure.constraint_variables import init_constraint_variables from process.data_structure.current_drive_variables import init_current_drive_variables from process.data_structure.dcll_variables import init_dcll_module @@ -266,7 +265,6 @@ def init_all_module_vars(): init_buildings_variables() init_divertor_variables() data_structure.global_variables.init_global_variables() - init_ccfe_hcpb_module() init_heat_transport_variables() init_ife_variables() init_impurity_radiation_module() diff --git a/process/core/model.py b/process/core/model.py index b2b57c254..67392ec89 100644 --- a/process/core/model.py +++ b/process/core/model.py @@ -2,6 +2,7 @@ from dataclasses import dataclass, fields from process.data_structure.blanket_variables import BlanketData +from process.data_structure.ccfe_hcpb_variables import CCFEHCPBData from process.data_structure.cost_2015_variables import Cost2015Data from process.data_structure.cost_variables import CostData from process.data_structure.cs_fatigue_variables import CSFatigueData @@ -29,6 +30,7 @@ class DataStructure: structure: StructureData = initialise_later times: TimesData = initialise_later reinke: ReinkeData = initialise_later + ccfe_hcpb: CCFEHCPBData = initialise_later def __post_init__(self): for f in fields(self): diff --git a/process/data_structure/__init__.py b/process/data_structure/__init__.py index b6e4a5e1d..9dc212a3b 100644 --- a/process/data_structure/__init__.py +++ b/process/data_structure/__init__.py @@ -2,7 +2,7 @@ blanket_variables, build_variables, buildings_variables, - ccfe_hcpb_module, + ccfe_hcpb_variables, constraint_variables, cost_2015_variables, cost_variables, @@ -40,7 +40,7 @@ "blanket_variables", "build_variables", "buildings_variables", - "ccfe_hcpb_module", + "ccfe_hcpb_variables", "constraint_variables", "cost_2015_variables", "cost_variables", diff --git a/process/data_structure/ccfe_hcpb_module.py b/process/data_structure/ccfe_hcpb_module.py deleted file mode 100644 index 80d5cbb27..000000000 --- a/process/data_structure/ccfe_hcpb_module.py +++ /dev/null @@ -1,95 +0,0 @@ -""" -This module contains the PROCESS CCFE HCPB blanket model -based on CCFE HCPB model from the PROCESS engineering paper -PROCESS Engineering paper (M. Kovari et al.) -### References -- Kovari et al., Fusion Engineering and Design 104 (2016) 9-20 -""" - -# Smeared densities of build sections - -armour_density: float = None -"""FW armour density [kg/m3]""" - - -fw_density: float = None -"""FW density [kg/m3]""" - - -blanket_density: float = None -"""Blanket density [kg/m3]""" - - -shield_density: float = None -"""Shield density [kg/m3]""" - - -vv_density: float = None -"""Vacuum vessel density [kg/m3]""" - - -x_blanket: float = None -"""Blanket exponent (tonne/m2)""" - - -x_shield: float = None -"""Shield exponent (tonne/m2)""" - - -tfc_nuc_heating: float = None -"""Unit nuclear heating in TF coil (W per W of fusion power)""" - - -fw_armour_u_nuc_heating: float = None -"""Unit heating of FW and armour in FW armour (W/kg per W of fusion power)""" - - -shld_u_nuc_heating: float = None -"""Unit nuclear heating in shield (W per W of fusion power)""" - - -pnuc_tot_blk_sector: float = None -"""Total nuclear power deposited in blanket covered sector (FW, BLKT, SHLD, TF) (MW)""" - - -exp_blanket: float = None -"""Exponential factors in nuclear heating calcs""" - - -exp_shield1: float = None -"""Exponential factors in nuclear heating calcs""" - - -exp_shield2: float = None -"""Exponential factors in nuclear heating calcs""" - - -def init_ccfe_hcpb_module(): - global \ - armour_density, \ - fw_density, \ - blanket_density, \ - shield_density, \ - vv_density, \ - x_blanket, \ - x_shield, \ - tfc_nuc_heating, \ - fw_armour_u_nuc_heating, \ - shld_u_nuc_heating, \ - exp_blanket, \ - exp_shield1, \ - exp_shield2 - - armour_density = 0.0 - fw_density = 0.0 - blanket_density = 0.0 - shield_density = 0.0 - vv_density = 0.0 - x_blanket = 0.0 - x_shield = 0.0 - tfc_nuc_heating = 0.0 - fw_armour_u_nuc_heating = 6.25e-7 - shld_u_nuc_heating = 0.0 - exp_blanket = 0.0 - exp_shield1 = 0.0 - exp_shield2 = 0.0 diff --git a/process/data_structure/ccfe_hcpb_variables.py b/process/data_structure/ccfe_hcpb_variables.py new file mode 100644 index 000000000..d985b0e10 --- /dev/null +++ b/process/data_structure/ccfe_hcpb_variables.py @@ -0,0 +1,57 @@ +""" +This module contains the PROCESS CCFE HCPB blanket model +based on CCFE HCPB model from the PROCESS engineering paper +PROCESS Engineering paper (M. Kovari et al.) +### References +- Kovari et al., Fusion Engineering and Design 104 (2016) 9-20 +""" + +from dataclasses import dataclass + + +@dataclass +class CCFEHCPBData: + armour_density: float = 0.0 + """FW armour density [kg/m3]""" + + fw_density: float = 0.0 + """FW density [kg/m3]""" + + blanket_density: float = 0.0 + """Blanket density [kg/m3]""" + + shield_density: float = 0.0 + """Shield density [kg/m3]""" + + vv_density: float = 0.0 + """Vacuum vessel density [kg/m3]""" + + x_blanket: float = 0.0 + """Blanket exponent (tonne/m2)""" + + x_shield: float = 0.0 + """Shield exponent (tonne/m2)""" + + tfc_nuc_heating: float = 0.0 + """Unit nuclear heating in TF coil (W per W of fusion power)""" + + fw_armour_u_nuc_heating: float = 6.25e-7 + """Unit heating of FW and armour in FW armour (W/kg per W of fusion power)""" + + shld_u_nuc_heating: float = 0.0 + """Unit nuclear heating in shield (W per W of fusion power)""" + + pnuc_tot_blk_sector: float = None + """Total nuclear power deposited in blanket covered sector (FW, BLKT, SHLD, TF) (MW)""" + + exp_blanket: float = 0.0 + """Exponential factors in nuclear heating calcs""" + + exp_shield1: float = 0.0 + """Exponential factors in nuclear heating calcs""" + + exp_shield2: float = 0.0 + """Exponential factors in nuclear heating calcs""" + + +CREATE_DICTS_FROM_DATACLASS = CCFEHCPBData diff --git a/process/models/blankets/hcpb.py b/process/models/blankets/hcpb.py index d770cdef0..abaef3d86 100644 --- a/process/models/blankets/hcpb.py +++ b/process/models/blankets/hcpb.py @@ -10,7 +10,6 @@ from process.core.exceptions import ProcessValueError from process.data_structure import ( build_variables, - ccfe_hcpb_module, current_drive_variables, divertor_variables, heat_transport_variables, @@ -135,11 +134,11 @@ def run(self, output: bool = False): self.data.fwbs.p_fw_nuclear_heat_total_mw = self.nuclear_heating_fw( m_fw_total=self.data.fwbs.m_fw_total, - fw_armour_u_nuc_heating=ccfe_hcpb_module.fw_armour_u_nuc_heating, + fw_armour_u_nuc_heating=self.data.ccfe_hcpb.fw_armour_u_nuc_heating, p_fusion_total_mw=physics_variables.p_fusion_total_mw, ) - self.data.fwbs.p_blkt_nuclear_heat_total_mw, ccfe_hcpb_module.exp_blanket = ( + self.data.fwbs.p_blkt_nuclear_heat_total_mw, self.data.ccfe_hcpb.exp_blanket = ( self.nuclear_heating_blanket( m_blkt_total=self.data.fwbs.m_blkt_total, p_fusion_total_mw=physics_variables.p_fusion_total_mw, @@ -147,16 +146,16 @@ def run(self, output: bool = False): ) ( self.data.fwbs.p_shld_nuclear_heat_mw, - ccfe_hcpb_module.exp_shield1, - ccfe_hcpb_module.exp_shield2, - ccfe_hcpb_module.shld_u_nuc_heating, + self.data.ccfe_hcpb.exp_shield1, + self.data.ccfe_hcpb.exp_shield2, + self.data.ccfe_hcpb.shld_u_nuc_heating, ) = self.nuclear_heating_shield( itart=physics_variables.itart, dr_shld_outboard=build_variables.dr_shld_outboard, dr_shld_inboard=build_variables.dr_shld_inboard, - shield_density=ccfe_hcpb_module.shield_density, + shield_density=self.data.ccfe_hcpb.shield_density, whtshld=self.data.fwbs.whtshld, - x_blanket=ccfe_hcpb_module.x_blanket, + x_blanket=self.data.ccfe_hcpb.x_blanket, p_fusion_total_mw=physics_variables.p_fusion_total_mw, ) @@ -170,7 +169,7 @@ def run(self, output: bool = False): # Split neutron power to main wall between fw, bkt, shld and TF with same # fractions as before. # Total nuclear power deposited in the blanket sector (MW) - ccfe_hcpb_module.pnuc_tot_blk_sector = ( + self.data.ccfe_hcpb.pnuc_tot_blk_sector = ( self.data.fwbs.p_fw_nuclear_heat_total_mw + self.data.fwbs.p_blkt_nuclear_heat_total_mw + self.data.fwbs.p_shld_nuclear_heat_mw @@ -195,7 +194,7 @@ def run(self, output: bool = False): self.data.fwbs.p_fw_nuclear_heat_total_mw = ( ( self.data.fwbs.p_fw_nuclear_heat_total_mw - / ccfe_hcpb_module.pnuc_tot_blk_sector + / self.data.ccfe_hcpb.pnuc_tot_blk_sector ) * self.data.fwbs.f_p_blkt_multiplication * f_geom_blanket @@ -206,7 +205,7 @@ def run(self, output: bool = False): self.data.fwbs.p_blkt_nuclear_heat_total_mw = ( ( self.data.fwbs.p_blkt_nuclear_heat_total_mw - / ccfe_hcpb_module.pnuc_tot_blk_sector + / self.data.ccfe_hcpb.pnuc_tot_blk_sector ) * self.data.fwbs.f_p_blkt_multiplication * f_geom_blanket @@ -218,7 +217,7 @@ def run(self, output: bool = False): self.data.fwbs.p_shld_nuclear_heat_mw = ( ( self.data.fwbs.p_shld_nuclear_heat_mw - / ccfe_hcpb_module.pnuc_tot_blk_sector + / self.data.ccfe_hcpb.pnuc_tot_blk_sector ) * self.data.fwbs.f_p_blkt_multiplication * f_geom_blanket @@ -228,7 +227,10 @@ def run(self, output: bool = False): # Power to the TF coils (MW) # The power deposited in the CP conductor is added back here self.data.fwbs.p_tf_nuclear_heat_mw = ( - (self.data.fwbs.p_tf_nuclear_heat_mw / ccfe_hcpb_module.pnuc_tot_blk_sector) + ( + self.data.fwbs.p_tf_nuclear_heat_mw + / self.data.ccfe_hcpb.pnuc_tot_blk_sector + ) * self.data.fwbs.f_p_blkt_multiplication * f_geom_blanket * physics_variables.p_neutron_total_mw @@ -462,12 +464,12 @@ def nuclear_heating_magnets(self, output: bool): # Calculate smeared densities of blanket sections # gaseous He coolant in armour, FW & blanket: He mass is neglected - ccfe_hcpb_module.armour_density = constants.DEN_TUNGSTEN * (1.0 - vffwm) - ccfe_hcpb_module.fw_density = self.data.fwbs.den_steel * (1.0 - vffwm) - ccfe_hcpb_module.blanket_density = ( + self.data.ccfe_hcpb.armour_density = constants.DEN_TUNGSTEN * (1.0 - vffwm) + self.data.ccfe_hcpb.fw_density = self.data.fwbs.den_steel * (1.0 - vffwm) + self.data.ccfe_hcpb.blanket_density = ( self.data.fwbs.m_blkt_total / self.data.fwbs.vol_blkt_total ) - ccfe_hcpb_module.shield_density = ( + self.data.ccfe_hcpb.shield_density = ( self.data.fwbs.whtshld / self.data.fwbs.vol_shld_total ) # Picking the largest value for VV thickness @@ -475,9 +477,9 @@ def nuclear_heating_magnets(self, output: bool): d_vv_all = max(d_vv_all, build_variables.dr_vv_outboard) if d_vv_all > 1.0e-6: - ccfe_hcpb_module.vv_density = self.data.fwbs.m_vv / self.data.fwbs.vol_vv + self.data.ccfe_hcpb.vv_density = self.data.fwbs.m_vv / self.data.fwbs.vol_vv else: - ccfe_hcpb_module.vv_density = 0.0 + self.data.ccfe_hcpb.vv_density = 0.0 # Calculation of average blanket/shield thickness [m] if physics_variables.itart == 1: @@ -500,18 +502,18 @@ def nuclear_heating_magnets(self, output: bool): # Exponents (tonne/m2) # Blanket exponent (/1000 for kg -> tonnes) - ccfe_hcpb_module.x_blanket = ( - ccfe_hcpb_module.armour_density * self.data.fwbs.fw_armour_thickness - + ccfe_hcpb_module.fw_density + self.data.ccfe_hcpb.x_blanket = ( + self.data.ccfe_hcpb.armour_density * self.data.fwbs.fw_armour_thickness + + self.data.ccfe_hcpb.fw_density * (build_variables.dr_fw_inboard + build_variables.dr_fw_outboard) / 2.0 - + ccfe_hcpb_module.blanket_density * th_blanket_av + + self.data.ccfe_hcpb.blanket_density * th_blanket_av ) / 1000.0 # Shield exponent(/1000 for kg -> tonnes) - ccfe_hcpb_module.x_shield = ( - ccfe_hcpb_module.shield_density * th_shield_av - + ccfe_hcpb_module.vv_density + self.data.ccfe_hcpb.x_shield = ( + self.data.ccfe_hcpb.shield_density * th_shield_av + + self.data.ccfe_hcpb.vv_density * (build_variables.dr_vv_inboard + build_variables.dr_vv_outboard) / 2.0 ) / 1000.0 @@ -520,25 +522,25 @@ def nuclear_heating_magnets(self, output: bool): if physics_variables.itart == 1: # Nuclear heating in outobard TF coil legs (whttflgs) # Unit heating (W/kg/GW of fusion power) x legs mass only (kg) - ccfe_hcpb_module.tfc_nuc_heating = ( + self.data.ccfe_hcpb.tfc_nuc_heating = ( e - * np.exp(-a * ccfe_hcpb_module.x_blanket) - * np.exp(-b * ccfe_hcpb_module.x_shield) + * np.exp(-a * self.data.ccfe_hcpb.x_blanket) + * np.exp(-b * self.data.ccfe_hcpb.x_shield) * tfcoil_variables.whttflgs ) else: # Nuclear heating in TF coil # Unit heating (W/kg/GW of fusion power) x total mass (kg) - ccfe_hcpb_module.tfc_nuc_heating = ( + self.data.ccfe_hcpb.tfc_nuc_heating = ( e - * np.exp(-a * ccfe_hcpb_module.x_blanket) - * np.exp(-b * ccfe_hcpb_module.x_shield) + * np.exp(-a * self.data.ccfe_hcpb.x_blanket) + * np.exp(-b * self.data.ccfe_hcpb.x_shield) * tfcoil_variables.m_tf_coils_total ) # Total heating (MW) self.data.fwbs.p_tf_nuclear_heat_mw = ( - ccfe_hcpb_module.tfc_nuc_heating + self.data.ccfe_hcpb.tfc_nuc_heating * (physics_variables.p_fusion_total_mw / 1000.0) / 1.0e6 ) @@ -549,19 +551,19 @@ def nuclear_heating_magnets(self, output: bool): self.outfile, "Shield line density (tonne/m2)", "(x_shield)", - ccfe_hcpb_module.x_shield, + self.data.ccfe_hcpb.x_shield, ) po.ovarre( self.outfile, "Blanket line density (tonne/m2)", "(x_blanket)", - ccfe_hcpb_module.x_blanket, + self.data.ccfe_hcpb.x_blanket, ) po.ovarre( self.outfile, "Unit nuclear heating in TF coil (W/GW)", "(tfc_nuc_heating)", - ccfe_hcpb_module.tfc_nuc_heating, + self.data.ccfe_hcpb.tfc_nuc_heating, ) po.ovarre( self.outfile, @@ -1467,21 +1469,21 @@ def write_output(self): self.outfile, "Blanket exponential factor", "(exp_blanket)", - ccfe_hcpb_module.exp_blanket, + self.data.ccfe_hcpb.exp_blanket, "OP ", ) po.ovarre( self.outfile, "Shield: first exponential", "(exp_shield1)", - ccfe_hcpb_module.exp_shield1, + self.data.ccfe_hcpb.exp_shield1, "OP ", ) po.ovarre( self.outfile, "Shield: second exponential", "(exp_shield2)", - ccfe_hcpb_module.exp_shield2, + self.data.ccfe_hcpb.exp_shield2, "OP ", ) po.ovarre( @@ -1621,19 +1623,3 @@ def write_output(self): "(m_div_plate)", divertor_variables.m_div_plate, ) - - -def init_ccfe_hcpb_module(): - ccfe_hcpb_module.armour_density = 0.0 - ccfe_hcpb_module.fw_density = 0.0 - ccfe_hcpb_module.blanket_density = 0.0 - ccfe_hcpb_module.shield_density = 0.0 - ccfe_hcpb_module.vv_density = 0.0 - ccfe_hcpb_module.x_blanket = 0.0 - ccfe_hcpb_module.x_shield = 0.0 - ccfe_hcpb_module.tfc_nuc_heating = 0.0 - ccfe_hcpb_module.fw_armour_u_nuc_heating = 6.25e-7 - ccfe_hcpb_module.shld_u_nuc_heating = 0.0 - ccfe_hcpb_module.exp_blanket = 0.0 - ccfe_hcpb_module.exp_shield1 = 0.0 - ccfe_hcpb_module.exp_shield2 = 0.0 diff --git a/tests/unit/models/blankets/test_ccfe_hcpb.py b/tests/unit/models/blankets/test_ccfe_hcpb.py index 7b71c4e11..7be8102f9 100644 --- a/tests/unit/models/blankets/test_ccfe_hcpb.py +++ b/tests/unit/models/blankets/test_ccfe_hcpb.py @@ -4,7 +4,6 @@ from process.data_structure import ( build_variables, - ccfe_hcpb_module, current_drive_variables, divertor_variables, global_variables, @@ -340,35 +339,43 @@ def test_nuclear_heating_magnets(nuclearheatingmagnetsparam, monkeypatch, ccfe_h monkeypatch.setattr(global_variables, "verbose", nuclearheatingmagnetsparam.verbose) monkeypatch.setattr( - ccfe_hcpb_module, "armour_density", nuclearheatingmagnetsparam.armour_density + ccfe_hcpb.data.ccfe_hcpb, + "armour_density", + nuclearheatingmagnetsparam.armour_density, ) monkeypatch.setattr( - ccfe_hcpb_module, "fw_density", nuclearheatingmagnetsparam.fw_density + ccfe_hcpb.data.ccfe_hcpb, "fw_density", nuclearheatingmagnetsparam.fw_density ) monkeypatch.setattr( - ccfe_hcpb_module, "blanket_density", nuclearheatingmagnetsparam.blanket_density + ccfe_hcpb.data.ccfe_hcpb, + "blanket_density", + nuclearheatingmagnetsparam.blanket_density, ) monkeypatch.setattr( - ccfe_hcpb_module, "shield_density", nuclearheatingmagnetsparam.shield_density + ccfe_hcpb.data.ccfe_hcpb, + "shield_density", + nuclearheatingmagnetsparam.shield_density, ) monkeypatch.setattr( - ccfe_hcpb_module, "vv_density", nuclearheatingmagnetsparam.vv_density + ccfe_hcpb.data.ccfe_hcpb, "vv_density", nuclearheatingmagnetsparam.vv_density ) monkeypatch.setattr( - ccfe_hcpb_module, "x_blanket", nuclearheatingmagnetsparam.x_blanket + ccfe_hcpb.data.ccfe_hcpb, "x_blanket", nuclearheatingmagnetsparam.x_blanket ) monkeypatch.setattr( - ccfe_hcpb_module, "x_shield", nuclearheatingmagnetsparam.x_shield + ccfe_hcpb.data.ccfe_hcpb, "x_shield", nuclearheatingmagnetsparam.x_shield ) monkeypatch.setattr( - ccfe_hcpb_module, "tfc_nuc_heating", nuclearheatingmagnetsparam.tfc_nuc_heating + ccfe_hcpb.data.ccfe_hcpb, + "tfc_nuc_heating", + nuclearheatingmagnetsparam.tfc_nuc_heating, ) ccfe_hcpb.nuclear_heating_magnets(False) @@ -385,35 +392,35 @@ def test_nuclear_heating_magnets(nuclearheatingmagnetsparam, monkeypatch, ccfe_h nuclearheatingmagnetsparam.expected_f_a_fw_coolant_outboard ) - assert ccfe_hcpb_module.armour_density == pytest.approx( + assert ccfe_hcpb.data.ccfe_hcpb.armour_density == pytest.approx( nuclearheatingmagnetsparam.expected_armour_density ) - assert ccfe_hcpb_module.fw_density == pytest.approx( + assert ccfe_hcpb.data.ccfe_hcpb.fw_density == pytest.approx( nuclearheatingmagnetsparam.expected_fw_density ) - assert ccfe_hcpb_module.blanket_density == pytest.approx( + assert ccfe_hcpb.data.ccfe_hcpb.blanket_density == pytest.approx( nuclearheatingmagnetsparam.expected_blanket_density ) - assert ccfe_hcpb_module.shield_density == pytest.approx( + assert ccfe_hcpb.data.ccfe_hcpb.shield_density == pytest.approx( nuclearheatingmagnetsparam.expected_shield_density ) - assert ccfe_hcpb_module.vv_density == pytest.approx( + assert ccfe_hcpb.data.ccfe_hcpb.vv_density == pytest.approx( nuclearheatingmagnetsparam.expected_vv_density ) - assert ccfe_hcpb_module.x_blanket == pytest.approx( + assert ccfe_hcpb.data.ccfe_hcpb.x_blanket == pytest.approx( nuclearheatingmagnetsparam.expected_x_blanket ) - assert ccfe_hcpb_module.x_shield == pytest.approx( + assert ccfe_hcpb.data.ccfe_hcpb.x_shield == pytest.approx( nuclearheatingmagnetsparam.expected_x_shield ) - assert ccfe_hcpb_module.tfc_nuc_heating == pytest.approx( + assert ccfe_hcpb.data.ccfe_hcpb.tfc_nuc_heating == pytest.approx( nuclearheatingmagnetsparam.expected_tfc_nuc_heating ) @@ -479,7 +486,7 @@ def test_nuclear_heating_fw(nuclearheatingfwparam, monkeypatch, ccfe_hcpb): ) monkeypatch.setattr( - ccfe_hcpb_module, + ccfe_hcpb.data.ccfe_hcpb, "fw_armour_u_nuc_heating", nuclearheatingfwparam.fw_armour_u_nuc_heating, )