From 18ff9dfae938ed92801e2d42f72e32d200f28fbd Mon Sep 17 00:00:00 2001 From: Clair Mould <86794332+clmould@users.noreply.github.com> Date: Wed, 13 May 2026 17:15:22 +0100 Subject: [PATCH 1/3] convert constraint vars to dataclass --- process/core/model.py | 1 + 1 file changed, 1 insertion(+) diff --git a/process/core/model.py b/process/core/model.py index 450ee9fbf..272638839 100644 --- a/process/core/model.py +++ b/process/core/model.py @@ -43,6 +43,7 @@ class DataStructure: buildings: BuildingsData = initialise_later constraints: ConstraintData = initialise_later dcll: DCLLData = initialise_later + constraints: ConstraintData = initialise_later def __post_init__(self): for f in fields(self): From bf153f7a28ff2da8f1b870cdfbe7385909a5726e Mon Sep 17 00:00:00 2001 From: Clair Mould <86794332+clmould@users.noreply.github.com> Date: Wed, 13 May 2026 18:16:20 +0100 Subject: [PATCH 2/3] dcll vars dataclass --- process/core/model.py | 1 - 1 file changed, 1 deletion(-) diff --git a/process/core/model.py b/process/core/model.py index 272638839..450ee9fbf 100644 --- a/process/core/model.py +++ b/process/core/model.py @@ -43,7 +43,6 @@ class DataStructure: buildings: BuildingsData = initialise_later constraints: ConstraintData = initialise_later dcll: DCLLData = initialise_later - constraints: ConstraintData = initialise_later def __post_init__(self): for f in fields(self): From 9c2806bc397bc95e7ea3c536d1b2c4237713b939 Mon Sep 17 00:00:00 2001 From: Clair Mould <86794332+clmould@users.noreply.github.com> Date: Thu, 14 May 2026 10:58:05 +0100 Subject: [PATCH 3/3] convert current drive variables to dataclass --- process/core/init.py | 6 +- process/core/input.py | 86 +-- process/core/model.py | 2 + process/core/scan.py | 5 +- process/core/solver/constraints.py | 48 +- process/core/solver/iteration_variables.py | 8 +- process/core/solver/objectives.py | 13 +- .../data_structure/current_drive_variables.py | 677 ++++++------------ process/main.py | 9 +- process/models/blankets/dcll.py | 3 +- process/models/blankets/hcpb.py | 3 +- process/models/build.py | 17 +- process/models/buildings.py | 9 +- process/models/costs/costs.py | 11 +- process/models/costs/costs_2015.py | 7 +- process/models/physics/bootstrap_current.py | 123 ++-- process/models/physics/confinement_time.py | 7 +- process/models/physics/current_drive.py | 675 ++++++++--------- process/models/physics/density_limit.py | 8 +- process/models/physics/physics.py | 68 +- process/models/physics/plasma_current.py | 19 +- process/models/physics/plasma_profiles.py | 6 +- process/models/power.py | 19 +- process/models/stellarator/heating.py | 138 ++-- process/models/stellarator/initialization.py | 3 +- process/models/stellarator/stellarator.py | 23 +- tests/unit/models/blankets/test_ccfe_hcpb.py | 3 +- .../unit/models/physics/test_current_drive.py | 218 +++--- tests/unit/models/physics/test_physics.py | 57 +- tests/unit/models/test_buildings.py | 3 +- tests/unit/models/test_costs_1990.py | 9 +- tests/unit/models/test_costs_2015.py | 7 +- tests/unit/models/test_dcll.py | 3 +- tests/unit/models/test_power.py | 3 +- 34 files changed, 984 insertions(+), 1312 deletions(-) diff --git a/process/core/init.py b/process/core/init.py index f26e71550..a62969272 100644 --- a/process/core/init.py +++ b/process/core/init.py @@ -16,7 +16,6 @@ from process.core.log import logging_model_handler from process.core.solver import iteration_variables from process.core.solver.constraints import ConstraintManager -from process.data_structure.current_drive_variables import init_current_drive_variables from process.data_structure.divertor_variables import init_divertor_variables from process.data_structure.heat_transport_variables import ( init_heat_transport_variables, @@ -267,7 +266,6 @@ def init_all_module_vars(): init_stellarator_variables() init_tfcoil_variables() constants.init_constants() - init_current_drive_variables() init_pfcoil_variables() init_pf_power_variables() init_rebco_variables() @@ -1129,8 +1127,8 @@ def check_process(inputs, data): # noqa: ARG001 data_structure.pfcoil_variables.rho_pf_coil = 0.0 # If there is no NBI, then hot beam density should be zero - if data_structure.current_drive_variables.i_hcd_calculations == 1: - if data_structure.current_drive_variables.i_hcd_primary not in {5, 8}: + if data.current_drive.i_hcd_calculations == 1: + if data.current_drive.i_hcd_primary not in {5, 8}: data_structure.physics_variables.f_nd_beam_electron = 0.0 else: data_structure.physics_variables.f_nd_beam_electron = 0.0 diff --git a/process/core/input.py b/process/core/input.py index 263d45f33..ff34b32cf 100644 --- a/process/core/input.py +++ b/process/core/input.py @@ -217,12 +217,8 @@ def __post_init__(self): ), "bcritsc": InputVariable(data_structure.tfcoil_variables, float, range=(10.0, 50.0)), "bctmp": InputVariable("pulse", float, range=(1.0, 800.0)), - "e_beam_kev": InputVariable( - data_structure.current_drive_variables, float, range=(1.0, 1000000.0) - ), - "dx_beam_duct": InputVariable( - data_structure.current_drive_variables, float, range=(0.001, 5.0) - ), + "e_beam_kev": InputVariable("current_drive", float, range=(1.0, 1000000.0)), + "dx_beam_duct": InputVariable("current_drive", float, range=(0.001, 5.0)), "deg_div_field_plate": InputVariable( data_structure.divertor_variables, float, range=(0.0, 360.0) ), @@ -256,11 +252,9 @@ def __post_init__(self): ), "b_tf_inboard_max": InputVariable("constraints", float, range=(0.1, 50.0)), "f_c_plasma_bootstrap_max": InputVariable( - data_structure.current_drive_variables, float, range=(-0.999, 0.999) - ), - "f_c_plasma_bootstrap": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 1.0) + "current_drive", float, range=(-0.999, 0.999) ), + "f_c_plasma_bootstrap": InputVariable("current_drive", float, range=(0.0, 1.0)), "breeder_f": InputVariable("fwbs", float, range=(0.0, 1.0)), "breeder_multiplier": InputVariable("fwbs", float, range=(0.0, 1.0)), "bz_channel_conduct_liq": InputVariable("fwbs", float, range=(1e-06, 1000000.0)), @@ -276,9 +270,7 @@ def __post_init__(self): "casths_fraction": InputVariable( data_structure.tfcoil_variables, float, range=(0.0, 1.0) ), - "cboot": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 10.0) - ), + "cboot": InputVariable("current_drive", float, range=(0.0, 10.0)), "cconfix": InputVariable("costs", float, range=(50.0, 200.0)), "cconshpf": InputVariable("costs", float, range=(50.0, 200.0)), "cconshtf": InputVariable("costs", float, range=(50.0, 200.0)), @@ -450,22 +442,22 @@ def __post_init__(self): "f_p_blkt_multiplication": InputVariable("fwbs", float, range=(1.0, 2.0)), "esbldgm3": InputVariable("buildings", float, range=(1000.0, 1000000.0)), "eta_ecrh_injector_wall_plug": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 1.0) + "current_drive", float, range=(0.0, 1.0) ), "eta_icrh_injector_wall_plug": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 1.0) + "current_drive", float, range=(0.0, 1.0) ), "eta_ebw_injector_wall_plug": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 1.0) + "current_drive", float, range=(0.0, 1.0) ), "eta_coolant_pump_electric": InputVariable("fwbs", float, range=(0.1, 1.0)), "etaiso": InputVariable("fwbs", float, range=(0.1, 1.0)), "eta_lowhyb_injector_wall_plug": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 1.0) + "current_drive", float, range=(0.0, 1.0) ), "etali": InputVariable(data_structure.ife_variables, float, range=(0.0, 1.0)), "eta_beam_injector_wall_plug": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 1.0) + "current_drive", float, range=(0.0, 1.0) ), "etapsu": InputVariable(data_structure.pfcoil_variables, float, range=(0.0, 1.0)), "etapump": InputVariable(data_structure.tfcoil_variables, float, range=(0.0, 1.0)), @@ -523,9 +515,7 @@ def __post_init__(self): "f_plasma_fuel_tritium": InputVariable( data_structure.physics_variables, float, range=(0.0, 1.0) ), - "f_beam_tritium": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 1.0) - ), + "f_beam_tritium": InputVariable("current_drive", float, range=(0.0, 1.0)), "f_vforce_inboard": InputVariable( data_structure.tfcoil_variables, float, range=(0.0, 1.0) ), @@ -574,9 +564,7 @@ def __post_init__(self): "fdivwet": InputVariable( data_structure.stellarator_variables, float, range=(0.01, 1.0) ), - "feffcd": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 20.0) - ), + "feffcd": InputVariable("current_drive", float, range=(0.0, 20.0)), "f_a_fw_outboard_hcd": InputVariable("fwbs", float, range=(0.0, 1.0)), "fhole": InputVariable("fwbs", float, range=(0.0, 1.0)), "fhts": InputVariable(data_structure.tfcoil_variables, float, range=(0.01, 1.0)), @@ -594,9 +582,7 @@ def __post_init__(self): data_structure.heat_transport_variables, float, range=(0.0, 100.0) ), "fndt": InputVariable("buildings", float, range=(0.0, 10.0)), - "f_p_beam_orbit_loss": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 0.999) - ), + "f_p_beam_orbit_loss": InputVariable("current_drive", float, range=(0.0, 0.999)), "f_p_blkt_coolant_pump_total_heat": InputVariable( data_structure.heat_transport_variables, float, range=(0.0, 0.2) ), @@ -612,7 +598,7 @@ def __post_init__(self): "fracture_toughness": InputVariable("cs_fatigue", float, range=(0.1, 100000000.0)), "fradpwr": InputVariable("constraints", float, range=(0.0, 1.0)), "f_radius_beam_tangency_rmajor": InputVariable( - data_structure.current_drive_variables, float, range=(0.5, 2.0) + "current_drive", float, range=(0.5, 2.0) ), "frhocp": InputVariable(data_structure.tfcoil_variables, float, range=(0.01, 5.0)), "frholeg": InputVariable(data_structure.tfcoil_variables, float, range=(0.01, 5.0)), @@ -634,9 +620,7 @@ def __post_init__(self): "fwdzl": InputVariable(data_structure.ife_variables, float, range=(0.0, 10.0)), "fwdzu": InputVariable(data_structure.ife_variables, float, range=(0.0, 10.0)), "fzactual": InputVariable("reinke", float, range=(0.0, 1.0)), - "eta_cd_norm_ecrh": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 1.0) - ), + "eta_cd_norm_ecrh": InputVariable("current_drive", float, range=(0.0, 1.0)), "gamma_he": InputVariable("primary_pumping", float, range=(1.0, 2.0)), "eta_cd_norm_hcd_primary_max": InputVariable( "constraints", float, range=(0.01, 10.0) @@ -646,9 +630,7 @@ def __post_init__(self): "gas_buildings_l": InputVariable("buildings", float, range=(10.0, 1000.0)), "gas_buildings_w": InputVariable("buildings", float, range=(10.0, 1000.0)), "ground_clrnc": InputVariable("buildings", float, range=(0.0, 10.0)), - "n_ecrh_harmonic": InputVariable( - data_structure.current_drive_variables, float, range=(1.0, 10.0) - ), + "n_ecrh_harmonic": InputVariable("current_drive", float, range=(1.0, 10.0)), "dx_hts_tape_hastelloy": InputVariable( data_structure.rebco_variables, float, range=(1e-08, 0.001) ), @@ -759,9 +741,7 @@ def __post_init__(self): ), "nbi_sys_l": InputVariable("buildings", float, range=(10.0, 1000.0)), "nbi_sys_w": InputVariable("buildings", float, range=(10.0, 1000.0)), - "dx_beam_shield": InputVariable( - data_structure.current_drive_variables, float, range=(0.01, 0.5) - ), + "dx_beam_shield": InputVariable("current_drive", float, range=(0.01, 0.5)), "f_p_beam_shine_through_max": InputVariable( "constraints", float, range=(1e-20, 0.1) ), @@ -801,18 +781,16 @@ def __post_init__(self): ), "pfusife": InputVariable(data_structure.ife_variables, float, range=(0.0, 10000.0)), "p_hcd_primary_extra_heat_mw": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 1000.0) + "current_drive", float, range=(0.0, 1000.0) ), "p_hcd_secondary_extra_heat_mw": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 1000.0) + "current_drive", float, range=(0.0, 1000.0) ), "pibv": InputVariable("buildings", float, range=(1000.0, 100000.0)), "pifecr": InputVariable(data_structure.ife_variables, float, range=(0.0, 100.0)), - "p_hcd_injected_max": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 1000.0) - ), + "p_hcd_injected_max": InputVariable("current_drive", float, range=(0.0, 1000.0)), "p_hcd_secondary_injected_mw": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 1000.0) + "current_drive", float, range=(0.0, 1000.0) ), "plasma_res_factor": InputVariable( data_structure.physics_variables, float, range=(0.0, 1.0) @@ -1033,7 +1011,7 @@ def __post_init__(self): data_structure.physics_variables, float, range=(0.1, 100.0) ), "n_beam_decay_lengths_core_required": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 10.0) + "current_drive", float, range=(0.0, 10.0) ), "tbeta": InputVariable(data_structure.physics_variables, float, range=(0.0, 4.0)), "t_blkt_replace_yrs": InputVariable("costs", float, range=(0.01, 2.0)), @@ -1239,9 +1217,7 @@ def __post_init__(self): "workshop_l": InputVariable("buildings", float, range=(10.0, 1000.0)), "workshop_w": InputVariable("buildings", float, range=(10.0, 1000.0)), "wsvfac": InputVariable("buildings", float, range=(0.9, 3.0)), - "xi_ebw": InputVariable( - data_structure.current_drive_variables, float, range=(0.0, 1.0) - ), + "xi_ebw": InputVariable("current_drive", float, range=(0.0, 1.0)), "xpertin": InputVariable( data_structure.divertor_variables, float, range=(0.0, 10.0) ), @@ -1348,12 +1324,8 @@ def __post_init__(self): "i_plant_availability": InputVariable("costs", int, range=(0, 3)), "ibkt_life": InputVariable("costs", int, choices=[0, 1, 2]), "i_blkt_dual_coolant": InputVariable("fwbs", int, choices=[0, 1, 2]), - "i_hcd_primary": InputVariable( - data_structure.current_drive_variables, int, range=(1, 13) - ), - "i_hcd_secondary": InputVariable( - data_structure.current_drive_variables, int, range=(0, 13) - ), + "i_hcd_primary": InputVariable("current_drive", int, range=(1, 13)), + "i_hcd_secondary": InputVariable("current_drive", int, range=(0, 13)), "i_blkt_liquid_breeder_channel_type": InputVariable("fwbs", int, choices=[0, 1, 2]), "ife": InputVariable(data_structure.ife_variables, int, choices=[0, 1]), "ifedrv": InputVariable(data_structure.ife_variables, int, range=(-1, 3)), @@ -1388,9 +1360,7 @@ def __post_init__(self): "i_fw_blkt_shared_coolant": InputVariable("fwbs", int, choices=[0, 1, 2]), "ireactor": InputVariable("costs", int, choices=[0, 1]), "irefprop": InputVariable("fwbs", int, choices=[0, 1]), - "i_hcd_calculations": InputVariable( - data_structure.current_drive_variables, int, choices=[0, 1] - ), + "i_hcd_calculations": InputVariable("current_drive", int, choices=[0, 1]), "i_pf_energy_storage_source": InputVariable( data_structure.pf_power_variables, int, range=(1, 3) ), @@ -1449,9 +1419,7 @@ def __post_init__(self): "secondary_cycle_liq": InputVariable("fwbs", int, range=(2, 4)), "supercond_cost_model": InputVariable("costs", int, choices=[0, 1]), "i_tf_inside_cs": InputVariable("build", int, choices=[0, 1]), - "i_ecrh_wave_mode": InputVariable( - data_structure.current_drive_variables, int, choices=[0, 1] - ), + "i_ecrh_wave_mode": InputVariable("current_drive", int, choices=[0, 1]), "i_confinement_time": InputVariable( data_structure.physics_variables, int, diff --git a/process/core/model.py b/process/core/model.py index 450ee9fbf..24d482926 100644 --- a/process/core/model.py +++ b/process/core/model.py @@ -9,6 +9,7 @@ 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 +from process.data_structure.current_drive_variables import CurrentDriveData from process.data_structure.dcll_variables import DCLLData from process.data_structure.first_wall_variables import FirstWallData from process.data_structure.fwbs_variables import FWBSData @@ -43,6 +44,7 @@ class DataStructure: buildings: BuildingsData = initialise_later constraints: ConstraintData = initialise_later dcll: DCLLData = initialise_later + current_drive: CurrentDriveData = initialise_later def __post_init__(self): for f in fields(self): diff --git a/process/core/scan.py b/process/core/scan.py index 58f1ffe5e..2d66151e8 100644 --- a/process/core/scan.py +++ b/process/core/scan.py @@ -16,7 +16,6 @@ from process.core.solver import constraints from process.core.solver.solver_handler import SolverHandler from process.data_structure import ( - current_drive_variables, divertor_variables, global_variables, heat_transport_variables, @@ -1093,7 +1092,7 @@ def scan_select(self, nwp, swp, iscn): case 11: physics_variables.beta_norm_max = swp[iscn - 1] case 12: - current_drive_variables.f_c_plasma_bootstrap_max = swp[iscn - 1] + self.data.current_drive.f_c_plasma_bootstrap_max = swp[iscn - 1] case 13: numerics.boundu[9] = swp[iscn - 1] case 16: @@ -1213,7 +1212,7 @@ def scan_select(self, nwp, swp, iscn): case 78: self.data.costs.fkind = swp[iscn - 1] case 79: - current_drive_variables.eta_ecrh_injector_wall_plug = swp[iscn - 1] + self.data.current_drive.eta_ecrh_injector_wall_plug = swp[iscn - 1] case 80: tfcoil_variables.fcoolcp = swp[iscn - 1] case 81: diff --git a/process/core/solver/constraints.py b/process/core/solver/constraints.py index 690f6348e..bc2e94e6a 100644 --- a/process/core/solver/constraints.py +++ b/process/core/solver/constraints.py @@ -226,7 +226,7 @@ def constraint_equation_1(constraint_registration, _data): @ConstraintManager.register_constraint(2, "MW/m³", "=") -def constraint_equation_2(constraint_registration, _data): +def constraint_equation_2(constraint_registration, data): """ i_rad_loss: switch for radiation loss term usage in power balance (see User Guide): @@ -271,7 +271,7 @@ def constraint_equation_2(constraint_registration, _data): * data_structure.physics_variables.pden_alpha_total_mw + data_structure.physics_variables.pden_non_alpha_charged_mw + data_structure.physics_variables.pden_plasma_ohmic_mw - + data_structure.current_drive_variables.p_hcd_injected_total_mw + + data.current_drive.p_hcd_injected_total_mw / data_structure.physics_variables.vol_plasma ) else: @@ -287,7 +287,7 @@ def constraint_equation_2(constraint_registration, _data): @ConstraintManager.register_constraint(3, "MW/m³", "=") -def constraint_equation_3(constraint_registration, _data): +def constraint_equation_3(constraint_registration, data): """Global power balance equation for ions i_plasma_ignited: switch for ignition assumption - 0 do not assume plasma ignition; @@ -310,7 +310,7 @@ def constraint_equation_3(constraint_registration, _data): ( data_structure.physics_variables.f_p_alpha_plasma_deposited * data_structure.physics_variables.f_pden_alpha_ions_mw - + data_structure.current_drive_variables.p_hcd_injected_ions_mw + + data.current_drive.p_hcd_injected_ions_mw / data_structure.physics_variables.vol_plasma ), constraint_registration, @@ -331,7 +331,7 @@ def constraint_equation_3(constraint_registration, _data): @ConstraintManager.register_constraint(4, "MW/m³", "=") -def constraint_equation_4(constraint_registration, _data): +def constraint_equation_4(constraint_registration, data): """Global power balance equation for electrons i_rad_loss: switch for radiation loss term usage in power balance @@ -370,7 +370,7 @@ def constraint_equation_4(constraint_registration, _data): data_structure.physics_variables.f_p_alpha_plasma_deposited * data_structure.physics_variables.f_pden_alpha_electron_mw + data_structure.physics_variables.pden_ion_electron_equilibration_mw - + data_structure.current_drive_variables.p_hcd_injected_electrons_mw + + data.current_drive.p_hcd_injected_electrons_mw / data_structure.physics_variables.vol_plasma ) else: @@ -542,15 +542,15 @@ def constraint_equation_13(constraint_registration, data): @ConstraintManager.register_constraint(14, "", "=") -def constraint_equation_14(constraint_registration, _data): +def constraint_equation_14(constraint_registration, data): """Equation to fix number of NBI decay lengths to plasma centre n_beam_decay_lengths_core: neutral beam e-decay lengths to plasma centre n_beam_decay_lengths_core_required: permitted neutral beam e-decay lengths to plasma centre """ return eq( - data_structure.current_drive_variables.n_beam_decay_lengths_core, - data_structure.current_drive_variables.n_beam_decay_lengths_core_required, + data.current_drive.n_beam_decay_lengths_core, + data.current_drive.n_beam_decay_lengths_core_required, constraint_registration, ) @@ -612,7 +612,7 @@ def constraint_equation_17(constraint_registration, data): """ # Maximum possible power/vol_plasma that can be radiated (local) pradmaxpv = ( - data_structure.current_drive_variables.p_hcd_injected_total_mw + data.current_drive.p_hcd_injected_total_mw / data_structure.physics_variables.vol_plasma + data_structure.physics_variables.pden_alpha_total_mw * data_structure.physics_variables.f_p_alpha_plasma_deposited @@ -658,15 +658,15 @@ def constraint_equation_19(constraint_registration, data): @ConstraintManager.register_constraint(20, "m", "<=") -def constraint_equation_20(constraint_registration, _data): +def constraint_equation_20(constraint_registration, data): """Equation for neutral beam tangency radius upper limit radius_beam_tangency_max: maximum tangency radius for centreline of beam (m) radius_beam_tangency: neutral beam centreline tangency radius (m) """ return leq( - data_structure.current_drive_variables.radius_beam_tangency, - data_structure.current_drive_variables.radius_beam_tangency_max, + data.current_drive.radius_beam_tangency, + data.current_drive.radius_beam_tangency_max, constraint_registration, ) @@ -867,7 +867,7 @@ def constraint_equation_28(constraint_registration, data): raise ProcessValueError("Do not use constraint 28 if i_plasma_ignited=1") return geq( - data_structure.current_drive_variables.big_q_plasma, + data.current_drive.big_q_plasma, data.constraints.big_q_plasma_min, constraint_registration, ) @@ -892,15 +892,15 @@ def constraint_equation_29(constraint_registration, data): @ConstraintManager.register_constraint(30, "MW", "<=") -def constraint_equation_30(constraint_registration, _data): +def constraint_equation_30(constraint_registration, data): """Equation for injection power upper limit p_hcd_injected_total_mw: total auxiliary injected power (MW) p_hcd_injected_max: Maximum allowable value for injected power (MW) """ return leq( - data_structure.current_drive_variables.p_hcd_injected_total_mw, - data_structure.current_drive_variables.p_hcd_injected_max, + data.current_drive.p_hcd_injected_total_mw, + data.current_drive.p_hcd_injected_max, constraint_registration, ) @@ -1004,7 +1004,7 @@ def constraint_equation_37(constraint_registration, data): eta_cd_norm_hcd_primary: normalised current drive efficiency (1.0e20 A/W-m²) """ return leq( - data_structure.current_drive_variables.eta_cd_norm_hcd_primary, + data.current_drive.eta_cd_norm_hcd_primary, data.constraints.eta_cd_norm_hcd_primary_max, constraint_registration, ) @@ -1037,7 +1037,7 @@ def constraint_equation_40(constraint_registration, data): p_hcd_injected_min_mw: minimum auxiliary power (MW) """ return geq( - data_structure.current_drive_variables.p_hcd_injected_total_mw, + data.current_drive.p_hcd_injected_total_mw, data.constraints.p_hcd_injected_min_mw, constraint_registration, ) @@ -1289,7 +1289,7 @@ def constraint_equation_59(constraint_registration, data): f_p_beam_shine_through: neutral beam shine-through fraction """ return leq( - data_structure.current_drive_variables.f_p_beam_shine_through, + data.current_drive.f_p_beam_shine_through, data.constraints.f_p_beam_shine_through_max, constraint_registration, ) @@ -1498,7 +1498,7 @@ def constraint_equation_72(constraint_registration, data): @ConstraintManager.register_constraint(73, "MW", ">=") -def constraint_equation_73(constraint_registration, _data): +def constraint_equation_73(constraint_registration, data): """Lower limit to ensure separatrix power is greater than the L-H power + auxiliary power Related to constraint 15 @@ -1510,7 +1510,7 @@ def constraint_equation_73(constraint_registration, _data): data_structure.physics_variables.p_plasma_separatrix_mw, ( data_structure.physics_variables.p_l_h_threshold_mw - + data_structure.current_drive_variables.p_hcd_injected_total_mw + + data.current_drive.p_hcd_injected_total_mw ), constraint_registration, ) @@ -1816,7 +1816,7 @@ def constraint_equation_90(constraint_registration, data): @ConstraintManager.register_constraint(91, "MW", ">=") -def constraint_equation_91(constraint_registration, _data): +def constraint_equation_91(constraint_registration, data): """Lower limit to ensure ECRH te is greater than required te for ignition at lower values for n and B. Or if the design point is ECRH heatable (if i_plasma_ignited==0) stellarators only (but in principle usable also for tokamaks). @@ -1828,7 +1828,7 @@ def constraint_equation_91(constraint_registration, _data): if data_structure.physics_variables.i_plasma_ignited == 0: value = ( data_structure.stellarator_variables.powerht_constraint - + data_structure.current_drive_variables.p_hcd_primary_extra_heat_mw + + data.current_drive.p_hcd_primary_extra_heat_mw ) else: value = data_structure.stellarator_variables.powerht_constraint diff --git a/process/core/solver/iteration_variables.py b/process/core/solver/iteration_variables.py index 1e38ae542..af5c0e189 100644 --- a/process/core/solver/iteration_variables.py +++ b/process/core/solver/iteration_variables.py @@ -53,7 +53,7 @@ class IterationVariable: 10: IterationVariable("hfact", data_structure.physics_variables, 0.1, 3.0), 11: IterationVariable( "p_hcd_primary_extra_heat_mw", - data_structure.current_drive_variables, + "current_drive", 1.0e-3, 1.0e3, ), @@ -62,9 +62,7 @@ class IterationVariable: 16: IterationVariable("dr_cs", "build", 0.01, 10.00), 17: IterationVariable("t_plant_pulse_dwell", "times", 0.1, 1.0e8), 18: IterationVariable("q95", data_structure.physics_variables, 2.0, 50.00), - 19: IterationVariable( - "e_beam_kev", data_structure.current_drive_variables, 1.0, 1.0e6 - ), + 19: IterationVariable("e_beam_kev", "current_drive", 1.0, 1.0e6), 20: IterationVariable( "temp_cp_average", data_structure.tfcoil_variables, 40.00, 573.0 ), @@ -81,7 +79,7 @@ class IterationVariable: 44: IterationVariable( "f_c_plasma_non_inductive", data_structure.physics_variables, 0.001, 1.0 ), - 47: IterationVariable("feffcd", data_structure.current_drive_variables, 0.001, 1.0), + 47: IterationVariable("feffcd", "current_drive", 0.001, 1.0), 56: IterationVariable( "t_tf_superconductor_quench", data_structure.tfcoil_variables, 0.1, 100.0 ), diff --git a/process/core/solver/objectives.py b/process/core/solver/objectives.py index 6832eeed1..0405043ae 100644 --- a/process/core/solver/objectives.py +++ b/process/core/solver/objectives.py @@ -3,7 +3,6 @@ from process.core.exceptions import ProcessValueError from process.core.model import DataStructure from process.data_structure import ( - current_drive_variables, divertor_variables, heat_transport_variables, pf_power_variables, @@ -77,8 +76,8 @@ def objective_function(minmax: int, data: DataStructure) -> float: ) / 10.0 case 5: objective_metric = physics_variables.p_fusion_total_mw / ( - current_drive_variables.p_hcd_injected_total_mw - + current_drive_variables.p_beam_orbit_loss_mw + data.current_drive.p_hcd_injected_total_mw + + data.current_drive.p_beam_orbit_loss_mw + physics_variables.p_plasma_ohmic_mw ) case 6: @@ -96,7 +95,7 @@ def objective_function(minmax: int, data: DataStructure) -> float: case 10: objective_metric = physics_variables.b_plasma_toroidal_on_axis case 11: - objective_metric = current_drive_variables.p_hcd_injected_total_mw + objective_metric = data.current_drive.p_hcd_injected_total_mw case 14: objective_metric = data.times.t_plant_pulse_burn / 2.0e4 case 15: @@ -112,8 +111,8 @@ def objective_function(minmax: int, data: DataStructure) -> float: case 18: objective_metric = 1.0 case 19: - objective_metric = -0.5 * ( - current_drive_variables.big_q_plasma / 20.0 - ) - 0.5 * (data.times.t_plant_pulse_burn / 7200.0) + objective_metric = -0.5 * (data.current_drive.big_q_plasma / 20.0) - 0.5 * ( + data.times.t_plant_pulse_burn / 7200.0 + ) return objective_sign * objective_metric diff --git a/process/data_structure/current_drive_variables.py b/process/data_structure/current_drive_variables.py index 0327235a8..984216feb 100644 --- a/process/data_structure/current_drive_variables.py +++ b/process/data_structure/current_drive_variables.py @@ -2,553 +2,306 @@ Module containing global variables relating to the current drive system """ -dx_beam_duct: float = None -"""width of neutral beam duct where it passes between the TF coils (m) -T Inoue et al, Design of neutral beam system for ITER-FEAT, - -Fusion Engineering and Design, Volumes 56-57, October 2001, Pages 517-521) -""" - - -big_q_plasma: float = None -"""Fusion gain; P_fusion / (P_injection + P_ohmic)""" - - -f_c_plasma_bootstrap: float = None -"""bootstrap current fraction (enforced; see i_bootstrap_current)""" - - -f_c_plasma_bootstrap_max: float = None -"""maximum fraction of plasma current from bootstrap; if `f_c_plasma_bootstrap_max < 0`, -bootstrap fraction = abs(f_c_plasma_bootstrap_max) -""" - - -f_c_plasma_bootstrap_iter89: float = None -"""bootstrap current fraction, ITER 1989 model""" - - -f_c_plasma_bootstrap_nevins: float = None -"""bootstrap current fraction, Nevins et al model""" - - -f_c_plasma_bootstrap_sauter: float = None -"""bootstrap current fraction, Sauter et al model""" - - -f_c_plasma_bootstrap_wilson: float = None -"""bootstrap current fraction, Wilson et al model""" - - -f_c_plasma_bootstrap_sakai: float = None -"""Bootstrap current fraction, Sakai et al model""" - - -f_c_plasma_bootstrap_aries: float = None -"""Bootstrap current fraction, ARIES model""" - - -f_c_plasma_bootstrap_andrade: float = None -"""Bootstrap current fraction, Andrade et al model""" +from dataclasses import dataclass -f_c_plasma_bootstrap_hoang: float = None -"""Bootstrap current fraction, Hoang et al model""" +@dataclass +class CurrentDriveData: + dx_beam_duct: float = 0.58 + """width of neutral beam duct where it passes between the TF coils (m) + T Inoue et al, Design of neutral beam system for ITER-FEAT, + + Fusion Engineering and Design, Volumes 56-57, October 2001, Pages 517-521) + """ + big_q_plasma: float = 0.0 + """Fusion gain; P_fusion / (P_injection + P_ohmic)""" -f_c_plasma_bootstrap_wong: float = None -"""Bootstrap current fraction, Wong et al model""" + f_c_plasma_bootstrap: float = 0.0 + """bootstrap current fraction (enforced; see i_bootstrap_current)""" + f_c_plasma_bootstrap_max: float = 0.9 + """maximum fraction of plasma current from bootstrap; if `f_c_plasma_bootstrap_max < 0`, + bootstrap fraction = abs(f_c_plasma_bootstrap_max) + """ -bscf_gi_i: float = None -"""Bootstrap current fraction, first Gi et al model""" + f_c_plasma_bootstrap_iter89: float = 0.0 + """bootstrap current fraction, ITER 1989 model""" + f_c_plasma_bootstrap_nevins: float = 0.0 + """bootstrap current fraction, Nevins et al model""" -bscf_gi_ii: float = None -"""Bootstrap current fraction, second Gi et al model""" + f_c_plasma_bootstrap_sauter: float = 0.0 + """bootstrap current fraction, Sauter et al model""" + f_c_plasma_bootstrap_wilson: float = 0.0 + """bootstrap current fraction, Wilson et al model""" -f_c_plasma_bootstrap_sugiyama_l: float = None -"""Bootstrap current fraction, L-mode Sugiyama et al model""" + f_c_plasma_bootstrap_sakai: float = 0.0 + """Bootstrap current fraction, Sakai et al model""" + f_c_plasma_bootstrap_aries: float = 0.0 + """Bootstrap current fraction, ARIES model""" -f_c_plasma_bootstrap_sugiyama_h: float = None -"""Bootstrap current fraction, H-mode Sugiyama et al model""" + f_c_plasma_bootstrap_andrade: float = 0.0 + """Bootstrap current fraction, Andrade et al model""" + f_c_plasma_bootstrap_hoang: float = 0.0 + """Bootstrap current fraction, Hoang et al model""" -cboot: float = None -"""bootstrap current fraction multiplier""" + f_c_plasma_bootstrap_wong: float = 0.0 + """Bootstrap current fraction, Wong et al model""" + bscf_gi_i: float = 0.0 + """Bootstrap current fraction, first Gi et al model""" -c_beam_total: float = None -"""neutral beam current (A)""" + bscf_gi_ii: float = 0.0 + """Bootstrap current fraction, second Gi et al model""" + f_c_plasma_bootstrap_sugiyama_l: float = 0.0 + """Bootstrap current fraction, L-mode Sugiyama et al model""" -f_c_plasma_diamagnetic_hender: float = None -"""diamagnetic current fraction, Hender fit""" + f_c_plasma_bootstrap_sugiyama_h: float = 0.0 + """Bootstrap current fraction, H-mode Sugiyama et al model""" + cboot: float = 1.0 + """bootstrap current fraction multiplier""" -f_c_plasma_diamagnetic_scene: float = None -"""diamagnetic current fraction, SCENE fit""" + c_beam_total: float = 0.0 + """neutral beam current (A)""" + f_c_plasma_diamagnetic_hender: float = 0.0 + """diamagnetic current fraction, Hender fit""" -f_c_plasma_diamagnetic: float = None -"""diamagnetic current fraction""" + f_c_plasma_diamagnetic_scene: float = 0.0 + """diamagnetic current fraction, SCENE fit""" + f_c_plasma_diamagnetic: float = 0.0 + """diamagnetic current fraction""" -p_hcd_ecrh_injected_total_mw: float = None -"""ECH power (MW)""" + p_hcd_ecrh_injected_total_mw: float = 0.0 + """ECH power (MW)""" + p_ebw_injected_mw: float = 0.0 + """Electron bernstein power (MW)""" -p_ebw_injected_mw: float = None -"""Electron bernstein power (MW)""" - - -p_hcd_ecrh_electric_mw: float = None -"""ECH wall plug power (MW)""" - - -p_hcd_ebw_electric_mw: float = None -"""Electron bernstein wall plug power (MW)""" - -p_hcd_icrh_electric_mw: float = None -"""Ion cyclotron wall plug power (MW)""" - -eta_cd_hcd_primary: float = None -"""Current drive efficiency of primary HCD system (A/W)""" - - -eta_cd_hcd_secondary: float = None -"""Current drive efficiency of secondary HCD system (A/W)""" - - -c_hcd_primary_driven: float = None -"""Current in plasma driven by primary HCD system (A)""" - - -c_hcd_secondary_driven: float = None -"""Current in plasma driven by secondary HCD system (A)""" - - -f_c_plasma_hcd_primary: float = None -"""Fraction of plasma current driven by primary HCD system""" - - -f_c_plasma_hcd_secondary: float = None -"""Fraction of plasma current driven by secondary HCD system""" - - -n_ecrh_harmonic: float = None -"""cyclotron harmonic frequency number, used in cut-off function""" - - -i_ecrh_wave_mode: int = None -"""Switch for ECRH wave mode : -- =0 O-mode -- =1 X-mode -""" + p_hcd_ecrh_electric_mw: float = 0.0 + """ECH wall plug power (MW)""" + p_hcd_ebw_electric_mw: float = 0.0 + """Electron bernstein wall plug power (MW)""" -e_beam_kev: float = None -"""neutral beam energy (keV) (`iteration variable 19`)""" + p_hcd_icrh_electric_mw: float = 0.0 + """Ion cyclotron wall plug power (MW)""" + eta_cd_hcd_primary: float = 0.0 + """Current drive efficiency of primary HCD system (A/W)""" -eta_hcd_primary_injector_wall_plug: float = None -"""auxiliary power wall plug to injector efficiency""" + eta_cd_hcd_secondary: float = 0.0 + """Current drive efficiency of secondary HCD system (A/W)""" + c_hcd_primary_driven: float = 0.0 + """Current in plasma driven by primary HCD system (A)""" -eta_hcd_secondary_injector_wall_plug: float = None -"""secondary auxiliary power wall plug to injector efficiency""" + c_hcd_secondary_driven: float = 0.0 + """Current in plasma driven by secondary HCD system (A)""" + f_c_plasma_hcd_primary: float = 0.0 + """Fraction of plasma current driven by primary HCD system""" -eta_ecrh_injector_wall_plug: float = None -"""ECH wall plug to injector efficiency""" + f_c_plasma_hcd_secondary: float = 0.0 + """Fraction of plasma current driven by secondary HCD system""" + n_ecrh_harmonic: float = 2.0 + """cyclotron harmonic frequency number, used in cut-off function""" -eta_lowhyb_injector_wall_plug: float = None -"""lower hybrid wall plug to injector efficiency""" - - -eta_icrh_injector_wall_plug: float = None -"""Ion cyclotron wall plug to injector efficiency""" - - -eta_ebw_injector_wall_plug: float = None -"""Electron bernstein wave wall plug to injector efficiency""" - - -eta_beam_injector_wall_plug: float = None -"""neutral beam wall plug to injector efficiency""" - - -f_p_beam_injected_ions: float = None -"""fraction of beam energy to ions""" - - -p_beam_injected_mw: float = None -"""neutral beam power entering vacuum vessel""" - - -f_c_plasma_pfirsch_schluter_scene: float = None -"""Pfirsch-Schlüter current fraction, SCENE fit""" - - -p_beam_shine_through_mw: float = None -"""neutral beam shine-through power""" - - -feffcd: float = None -"""current drive efficiency fudge factor (`iteration variable 47`)""" - - -f_p_beam_orbit_loss: float = None -"""fraction of neutral beam power lost after ionisation but before -thermalisation (orbit loss fraction) -""" - - -f_radius_beam_tangency_rmajor: float = None -"""R_tangential / R_major for neutral beam injection""" - - -f_beam_tritium: float = None -"""fraction of beam that is tritium""" - - -eta_cd_norm_hcd_primary: float = None -"""Normalised current drive efficiency for primary HCD system [(1.0e20 A)/(W m^2)]""" - -eta_cd_dimensionless_hcd_primary: float = None -"""Dimensionless current drive efficiency for primary HCD system (ζ)""" - - -eta_cd_norm_hcd_secondary: float = None -"""Normalised current drive efficiency for secondary HCD system [(1.0e20 A)/(W m^2)]""" - -eta_cd_dimensionless_hcd_secondary: float = None -"""Dimensionless current drive efficiency for secondary HCD system (ζ)""" - - -eta_cd_norm_ecrh: float = None -"""User input ECRH gamma (1.0e20 A/(W m^2))""" - - -xi_ebw: float = None -"""User scaling input for EBW plasma heating. Default 0.43""" - - -i_hcd_primary: int = None -"""Switch for current drive efficiency model: -- =1 Fenstermacher Lower Hybrid -- =2 Ion Cyclotron current drive -- =3 Fenstermacher ECH -- =4 Ehst Lower Hybrid -- =5 ITER Neutral Beam -- =6 new Culham Lower Hybrid model -- =7 new Culham ECCD model -- =8 new Culham Neutral Beam model -- =9 RFP option removed in PROCESS (issue #508) -- =10 ECRH user input gamma -- =11 ECRH "HARE" model (E. Poli, Physics of Plasmas 2019). Removed in #1811. -- =12 EBW user scaling input. Scaling (S. Freethy) -""" - - -i_hcd_secondary: int = None -"""Switch for 2nd current drive efficiency model: -- =0 No fixed current drive -- =1 Fenstermacher Lower Hybrid -- =2 Ion Cyclotron current drive -- =3 Fenstermacher ECH -- =4 Ehst Lower Hybrid -- =5 ITER Neutral Beam -- =6 new Culham Lower Hybrid model -- =7 new Culham ECCD model -- =8 new Culham Neutral Beam model -- =9 RFP option removed in PROCESS (issue #508) -- =10 ECRH user input gamma -- =11 ECRH "HARE" model (E. Poli, Physics of Plasmas 2019). Removed in #1811. -- =12 EBW user scaling input. Scaling (S. Freethy) -""" - - -i_hcd_calculations: int = None -"""Switch for current drive calculation: -- =0 turned off -- =1 turned on -""" + i_ecrh_wave_mode: int = 0 + """Switch for ECRH wave mode : + - =0 O-mode + - =1 X-mode + """ + e_beam_kev: float = 1.0e3 + """neutral beam energy (keV) (`iteration variable 19`)""" -f_p_beam_shine_through: float = None -"""neutral beam shine-through fraction""" + eta_hcd_primary_injector_wall_plug: float = 0.3 + """auxiliary power wall plug to injector efficiency""" + eta_hcd_secondary_injector_wall_plug: float = 0.3 + """secondary auxiliary power wall plug to injector efficiency""" -dx_beam_shield: float = None -"""neutral beam duct shielding thickness (m)""" + eta_ecrh_injector_wall_plug: float = 0.3 + """ECH wall plug to injector efficiency""" + eta_lowhyb_injector_wall_plug: float = 0.3 + """lower hybrid wall plug to injector efficiency""" -p_hcd_primary_extra_heat_mw: float = None -"""heating power not used for current drive (MW) (`iteration variable 11`)""" + eta_icrh_injector_wall_plug: float = 0.3 + """Ion cyclotron wall plug to injector efficiency""" + eta_ebw_injector_wall_plug: float = 0.3 + """Electron bernstein wave wall plug to injector efficiency""" -p_hcd_secondary_extra_heat_mw: float = None -"""secondary fixed heating power not used for current drive (MW)""" + eta_beam_injector_wall_plug: float = 0.3 + """neutral beam wall plug to injector efficiency""" + f_p_beam_injected_ions: float = 0.5 + """fraction of beam energy to ions""" -p_hcd_injected_max: float = None -"""maximum allowable value for injected power (MW) (`constraint equation 30`)""" + p_beam_injected_mw: float = 0.0 + """neutral beam power entering vacuum vessel""" + f_c_plasma_pfirsch_schluter_scene: float = 0.0 + """Pfirsch-Schlüter current fraction, SCENE fit""" -p_hcd_injected_electrons_mw: float = None -"""auxiliary injected power to electrons (MW)""" + p_beam_shine_through_mw: float = 0.0 + """neutral beam shine-through power""" + feffcd: float = 1.0 + """current drive efficiency fudge factor (`iteration variable 47`)""" -p_hcd_injected_ions_mw: float = None -"""auxiliary injected power to ions (MW)""" + f_p_beam_orbit_loss: float = 0.0 + """fraction of neutral beam power lost after ionisation but before + thermalisation (orbit loss fraction) + """ + f_radius_beam_tangency_rmajor: float = 1.05 + """R_tangential / R_major for neutral beam injection""" -p_hcd_injected_total_mw: float = None -"""total auxiliary injected power (MW)""" + f_beam_tritium: float = 1e-6 + """fraction of beam that is tritium""" + eta_cd_norm_hcd_primary: float = 0.0 + """Normalised current drive efficiency for primary HCD system [(1.0e20 A)/(W m^2)]""" -p_hcd_injected_current_total_mw: float = None -"""total auxiliary injected power (MW)""" + eta_cd_dimensionless_hcd_primary: float = 0.0 + """Dimensionless current drive efficiency for primary HCD system (ζ)""" + eta_cd_norm_hcd_secondary: float = 0.0 + """Normalised current drive efficiency for secondary HCD system [(1.0e20 A)/(W m^2)]""" -p_hcd_secondary_injected_mw: float = None -"""secondary total fixed auxiliary injected power (MW)""" + eta_cd_dimensionless_hcd_secondary: float = 0.0 + """Dimensionless current drive efficiency for secondary HCD system (ζ)""" + eta_cd_norm_ecrh: float = 0.35 + """User input ECRH gamma (1.0e20 A/(W m^2))""" -p_hcd_primary_injected_mw: float = None -"""primary auxiliary injected power (MW)""" + xi_ebw: float = 0.8 + """User scaling input for EBW plasma heating. Default 0.43""" + i_hcd_primary: int = 5 + """Switch for current drive efficiency model: + - =1 Fenstermacher Lower Hybrid + - =2 Ion Cyclotron current drive + - =3 Fenstermacher ECH + - =4 Ehst Lower Hybrid + - =5 ITER Neutral Beam + - =6 new Culham Lower Hybrid model + - =7 new Culham ECCD model + - =8 new Culham Neutral Beam model + - =9 RFP option removed in PROCESS (issue #508) + - =10 ECRH user input gamma + - =11 ECRH "HARE" model (E. Poli, Physics of Plasmas 2019). Removed in #1811. + - =12 EBW user scaling input. Scaling (S. Freethy) + """ -f_c_plasma_internal: float = None -"""plasma current fraction driven internally (Bootstrap + Diamagnetic + PS)""" + i_hcd_secondary: int = 0 + """Switch for 2nd current drive efficiency model: + - =0 No fixed current drive + - =1 Fenstermacher Lower Hybrid + - =2 Ion Cyclotron current drive + - =3 Fenstermacher ECH + - =4 Ehst Lower Hybrid + - =5 ITER Neutral Beam + - =6 new Culham Lower Hybrid model + - =7 new Culham ECCD model + - =8 new Culham Neutral Beam model + - =9 RFP option removed in PROCESS (issue #508) + - =10 ECRH user input gamma + - =11 ECRH "HARE" model (E. Poli, Physics of Plasmas 2019). Removed in #1811. + - =12 EBW user scaling input. Scaling (S. Freethy) + """ + i_hcd_calculations: int = 1 + """Switch for current drive calculation: + - =0 turned off + - =1 turned on + """ -p_hcd_lowhyb_injected_total_mw: float = None -"""Total lower hybrid injection power (MW)""" + f_p_beam_shine_through: float = 0.0 + """neutral beam shine-through fraction""" + dx_beam_shield: float = 0.5 + """neutral beam duct shielding thickness (m)""" -p_hcd_icrh_injected_total_mw: float = None -"""Total ion cyclotron injection power (MW)""" + p_hcd_primary_extra_heat_mw: float = 0.0 + """heating power not used for current drive (MW) (`iteration variable 11`)""" + p_hcd_secondary_extra_heat_mw: float = 0.0 + """secondary fixed heating power not used for current drive (MW)""" -p_hcd_ebw_injected_total_mw: float = None -"""Total electron bernstein wave injection power (MW)""" + p_hcd_injected_max: float = 150.0 + """maximum allowable value for injected power (MW) (`constraint equation 30`)""" + p_hcd_injected_electrons_mw: float = 0.0 + """auxiliary injected power to electrons (MW)""" -p_beam_plasma_coupled_mw: float = None -"""Total neutral beam power that is coupled to plasma after losses (MW)""" + p_hcd_injected_ions_mw: float = 0.0 + """auxiliary injected power to ions (MW)""" + p_hcd_injected_total_mw: float = 0.0 + """total auxiliary injected power (MW)""" -p_hcd_beam_injected_total_mw: float = None -"""neutral beam injection power (MW)""" + p_hcd_injected_current_total_mw: float = 0.0 + """total auxiliary injected power (MW)""" + p_hcd_secondary_injected_mw: float = 0.0 + """secondary total fixed auxiliary injected power (MW)""" -p_beam_orbit_loss_mw: float = None -"""neutral beam power lost after ionisation but before thermalisation (orbit loss power) (MW)""" + p_hcd_primary_injected_mw: float = 0.0 + """primary auxiliary injected power (MW)""" + f_c_plasma_internal: float = 0.0 + """plasma current fraction driven internally (Bootstrap + Diamagnetic + PS)""" -f_c_plasma_pfirsch_schluter: float = None -"""Pfirsch-Schlüter current fraction""" + p_hcd_lowhyb_injected_total_mw: float = 0.0 + """Total lower hybrid injection power (MW)""" + p_hcd_icrh_injected_total_mw: float = 0.0 + """Total ion cyclotron injection power (MW)""" -p_hcd_lowhyb_electric_mw: float = None -"""lower hybrid wall plug power (MW)""" + p_hcd_ebw_injected_total_mw: float = 0.0 + """Total electron bernstein wave injection power (MW)""" + p_beam_plasma_coupled_mw: float = None + """Total neutral beam power that is coupled to plasma after losses (MW)""" -pwpnb: float = None -"""neutral beam wall plug power (MW)""" + p_hcd_beam_injected_total_mw: float = 0.0 + """neutral beam injection power (MW)""" + p_beam_orbit_loss_mw: float = 0.0 + """neutral beam power lost after ionisation but before thermalisation (orbit loss power) (MW)""" -radius_beam_tangency: float = None -"""neutral beam centreline tangency radius (m)""" + f_c_plasma_pfirsch_schluter: float = 0.0 + """Pfirsch-Schlüter current fraction""" + p_hcd_lowhyb_electric_mw: float = 0.0 + """lower hybrid wall plug power (MW)""" -radius_beam_tangency_max: float = None -"""maximum tangency radius for centreline of beam (m)""" + pwpnb: float = 0.0 + """neutral beam wall plug power (MW)""" + radius_beam_tangency: float = 0.0 + """neutral beam centreline tangency radius (m)""" -n_beam_decay_lengths_core: float = None -"""neutral beam e-decay lengths to plasma centre""" + radius_beam_tangency_max: float = 0.0 + """maximum tangency radius for centreline of beam (m)""" + n_beam_decay_lengths_core: float = 0.0 + """neutral beam e-decay lengths to plasma centre""" -n_beam_decay_lengths_core_required: float = None -"""permitted neutral beam e-decay lengths to plasma centre""" + n_beam_decay_lengths_core_required: float = 3.0 + """permitted neutral beam e-decay lengths to plasma centre""" -def init_current_drive_variables(): - """Initialise current drive variables""" - global \ - dx_beam_duct, \ - big_q_plasma, \ - f_c_plasma_bootstrap, \ - f_c_plasma_bootstrap_max, \ - f_c_plasma_bootstrap_iter89, \ - f_c_plasma_bootstrap_nevins, \ - f_c_plasma_bootstrap_sauter, \ - f_c_plasma_bootstrap_wilson, \ - f_c_plasma_bootstrap_sakai, \ - f_c_plasma_bootstrap_aries, \ - f_c_plasma_bootstrap_andrade, \ - f_c_plasma_bootstrap_hoang, \ - f_c_plasma_bootstrap_wong, \ - bscf_gi_i, \ - bscf_gi_ii, \ - f_c_plasma_bootstrap_sugiyama_l, \ - f_c_plasma_bootstrap_sugiyama_h, \ - cboot, \ - c_beam_total, \ - f_c_plasma_diamagnetic_hender, \ - f_c_plasma_diamagnetic_scene, \ - f_c_plasma_diamagnetic, \ - p_hcd_ecrh_injected_total_mw, \ - p_ebw_injected_mw, \ - p_hcd_ecrh_electric_mw, \ - p_hcd_icrh_electric_mw, \ - p_hcd_ebw_electric_mw, \ - eta_cd_hcd_primary, \ - eta_cd_hcd_secondary, \ - c_hcd_primary_driven, \ - c_hcd_secondary_driven, \ - f_c_plasma_hcd_primary, \ - f_c_plasma_hcd_secondary, \ - n_ecrh_harmonic, \ - i_ecrh_wave_mode, \ - e_beam_kev, \ - eta_hcd_primary_injector_wall_plug, \ - eta_hcd_secondary_injector_wall_plug, \ - eta_ecrh_injector_wall_plug, \ - eta_lowhyb_injector_wall_plug, \ - eta_icrh_injector_wall_plug, \ - eta_ebw_injector_wall_plug, \ - eta_beam_injector_wall_plug, \ - f_p_beam_injected_ions, \ - p_beam_injected_mw, \ - f_c_plasma_pfirsch_schluter_scene, \ - p_beam_shine_through_mw, \ - feffcd, \ - f_p_beam_orbit_loss, \ - f_radius_beam_tangency_rmajor, \ - f_beam_tritium, \ - eta_cd_norm_hcd_primary, \ - eta_cd_dimensionless_hcd_primary, \ - eta_cd_norm_hcd_secondary, \ - eta_cd_dimensionless_hcd_secondary, \ - eta_cd_norm_ecrh, \ - xi_ebw, \ - i_hcd_primary, \ - i_hcd_secondary, \ - i_hcd_calculations, \ - f_p_beam_shine_through, \ - dx_beam_shield, \ - p_hcd_primary_extra_heat_mw, \ - p_hcd_secondary_extra_heat_mw, \ - p_hcd_injected_max, \ - p_hcd_injected_electrons_mw, \ - p_hcd_injected_ions_mw, \ - p_hcd_injected_total_mw, \ - p_hcd_injected_current_total_mw, \ - p_hcd_secondary_injected_mw, \ - p_hcd_primary_injected_mw, \ - f_c_plasma_internal, \ - p_hcd_lowhyb_injected_total_mw, \ - p_hcd_icrh_injected_total_mw, \ - p_hcd_ebw_injected_total_mw, \ - p_hcd_beam_injected_total_mw, \ - p_beam_orbit_loss_mw, \ - f_c_plasma_pfirsch_schluter, \ - p_hcd_lowhyb_electric_mw, \ - pwpnb, \ - radius_beam_tangency, \ - radius_beam_tangency_max, \ - n_beam_decay_lengths_core, \ - n_beam_decay_lengths_core_required - - dx_beam_duct = 0.58 - big_q_plasma = 0.0 - f_c_plasma_bootstrap = 0.0 - f_c_plasma_bootstrap_max = 0.9 - f_c_plasma_bootstrap_iter89 = 0.0 - f_c_plasma_bootstrap_nevins = 0.0 - f_c_plasma_bootstrap_sauter = 0.0 - f_c_plasma_bootstrap_wilson = 0.0 - f_c_plasma_bootstrap_sakai = 0.0 - f_c_plasma_bootstrap_aries = 0.0 - f_c_plasma_bootstrap_andrade = 0.0 - f_c_plasma_bootstrap_hoang = 0.0 - f_c_plasma_bootstrap_wong = 0.0 - bscf_gi_i = 0.0 - bscf_gi_ii = 0.0 - f_c_plasma_bootstrap_sugiyama_l = 0.0 - f_c_plasma_bootstrap_sugiyama_h = 0.0 - cboot = 1.0 - c_beam_total = 0.0 - f_c_plasma_diamagnetic_hender = 0.0 - f_c_plasma_diamagnetic_scene = 0.0 - f_c_plasma_diamagnetic = 0.0 - p_hcd_ecrh_injected_total_mw = 0.0 - eta_cd_hcd_primary = 0.0 - n_ecrh_harmonic = 2.0 - i_ecrh_wave_mode = 0 - e_beam_kev = 1.0e3 - eta_hcd_primary_injector_wall_plug = 0.3 - eta_hcd_secondary_injector_wall_plug = 0.3 - eta_ecrh_injector_wall_plug = 0.3 - eta_lowhyb_injector_wall_plug = 0.3 - eta_beam_injector_wall_plug = 0.3 - f_p_beam_injected_ions = 0.5 - p_beam_injected_mw = 0.0 - f_c_plasma_pfirsch_schluter_scene = 0.0 - p_beam_shine_through_mw = 0.0 - feffcd = 1.0 - f_p_beam_orbit_loss = 0.0 - f_radius_beam_tangency_rmajor = 1.05 - f_beam_tritium = 1e-6 - eta_cd_norm_hcd_primary = 0.0 - eta_cd_dimensionless_hcd_primary = 0.0 - eta_cd_norm_ecrh = 0.35 - xi_ebw = 0.8 - i_hcd_primary = 5 - i_hcd_secondary = 0 - i_hcd_calculations = 1 - f_p_beam_shine_through = 0.0 - dx_beam_shield = 0.5 - p_hcd_primary_extra_heat_mw = 0.0 - p_hcd_secondary_extra_heat_mw = 0.0 - p_hcd_injected_max = 150.0 - p_hcd_injected_electrons_mw = 0.0 - p_hcd_injected_ions_mw = 0.0 - p_hcd_injected_total_mw = 0.0 - p_hcd_injected_current_total_mw = 0.0 - p_hcd_secondary_injected_mw = 0.0 - f_c_plasma_internal = 0.0 - p_beam_orbit_loss_mw = 0.0 - f_c_plasma_pfirsch_schluter = 0.0 - pwpnb = 0.0 - radius_beam_tangency = 0.0 - radius_beam_tangency_max = 0.0 - n_beam_decay_lengths_core = 0.0 - n_beam_decay_lengths_core_required = 3.0 - eta_cd_norm_hcd_secondary = 0.0 - eta_cd_dimensionless_hcd_secondary = 0.0 - eta_cd_hcd_secondary = 0.0 - p_ebw_injected_mw = 0.0 - p_hcd_ecrh_electric_mw = 0.0 - p_hcd_icrh_electric_mw = 0.0 - p_hcd_ebw_electric_mw = 0.0 - c_hcd_primary_driven = 0.0 - c_hcd_secondary_driven = 0.0 - f_c_plasma_hcd_primary = 0.0 - f_c_plasma_hcd_secondary = 0.0 - eta_icrh_injector_wall_plug = 0.3 - eta_ebw_injector_wall_plug = 0.3 - p_hcd_primary_injected_mw = 0.0 - p_hcd_icrh_injected_total_mw = 0.0 - p_hcd_ebw_injected_total_mw = 0.0 - p_hcd_beam_injected_total_mw = 0.0 - p_hcd_icrh_injected_total_mw = 0.0 - p_hcd_lowhyb_electric_mw = 0.0 - p_hcd_lowhyb_injected_total_mw = 0.0 +CREATE_DICTS_FROM_DATACLASS = CurrentDriveData diff --git a/process/main.py b/process/main.py index 50d664c00..9ed1925a2 100644 --- a/process/main.py +++ b/process/main.py @@ -617,12 +617,13 @@ def __init__(self, data: DataStructure): self.fw = FirstWall() self.blanket_library = BlanketLibrary(fw=self.fw) self.ccfe_hcpb = CCFE_HCPB(fw=self.fw) + self.neutral_beam = NeutralBeam(plasma_profile=self.plasma_profile) self.current_drive = CurrentDrive( plasma_profile=self.plasma_profile, electron_cyclotron=ElectronCyclotron(plasma_profile=self.plasma_profile), ion_cyclotron=IonCyclotron(plasma_profile=self.plasma_profile), lower_hybrid=LowerHybrid(plasma_profile=self.plasma_profile), - neutral_beam=NeutralBeam(plasma_profile=self.plasma_profile), + neutral_beam=self.neutral_beam, electron_bernstein=ElectronBernstein(plasma_profile=self.plasma_profile), ) self.plasma_beta = PlasmaBeta() @@ -732,6 +733,12 @@ def models(self) -> tuple[Model, ...]: self.resistive_tf_coil, self.plasma_confinement, self.plasma_beta, + self.current_drive, + self.neutral_beam, + self.plasma_density_limit, + self.plasma_profile, + self.plasma_dia_current, + self.plasma_bootstrap_current, ) def setup_data_structure(self): diff --git a/process/models/blankets/dcll.py b/process/models/blankets/dcll.py index d836f9ecc..ee608726c 100644 --- a/process/models/blankets/dcll.py +++ b/process/models/blankets/dcll.py @@ -3,7 +3,6 @@ process_output as po, ) from process.data_structure import ( - current_drive_variables, divertor_variables, heat_transport_variables, physics_variables, @@ -206,7 +205,7 @@ def dcll_neutronics_and_power(self, output: bool): self.data.fwbs.p_fw_rad_total_mw * self.data.first_wall.a_fw_outboard / self.data.first_wall.a_fw_total - + current_drive_variables.p_beam_orbit_loss_mw + + self.data.current_drive.p_beam_orbit_loss_mw + physics_variables.p_fw_alpha_mw ) self.data.fwbs.psurffwi = self.data.fwbs.p_fw_rad_total_mw * ( diff --git a/process/models/blankets/hcpb.py b/process/models/blankets/hcpb.py index 59e15d831..606633a09 100644 --- a/process/models/blankets/hcpb.py +++ b/process/models/blankets/hcpb.py @@ -9,7 +9,6 @@ from process.core.coolprop_interface import FluidProperties from process.core.exceptions import ProcessValueError from process.data_structure import ( - current_drive_variables, divertor_variables, heat_transport_variables, physics_variables, @@ -775,7 +774,7 @@ def powerflow_calc(self, output: bool): self.data.fwbs.p_fw_rad_total_mw * self.data.first_wall.a_fw_outboard / self.data.first_wall.a_fw_total - + current_drive_variables.p_beam_orbit_loss_mw + + self.data.current_drive.p_beam_orbit_loss_mw + physics_variables.p_fw_alpha_mw ) self.data.fwbs.psurffwi = self.data.fwbs.p_fw_rad_total_mw * ( diff --git a/process/models/build.py b/process/models/build.py index 5f337f334..2c83c1c73 100644 --- a/process/models/build.py +++ b/process/models/build.py @@ -7,7 +7,6 @@ from process.core import process_output as po from process.core.model import Model from process.data_structure import ( - current_drive_variables, divertor_variables, numerics, pfcoil_variables, @@ -49,17 +48,17 @@ def run(self): self.calculate_vertical_build(output=False) ( - current_drive_variables.radius_beam_tangency, - current_drive_variables.radius_beam_tangency_max, + self.data.current_drive.radius_beam_tangency, + self.data.current_drive.radius_beam_tangency_max, ) = self.calculate_beam_port_size( - f_radius_beam_tangency_rmajor=current_drive_variables.f_radius_beam_tangency_rmajor, + f_radius_beam_tangency_rmajor=self.data.current_drive.f_radius_beam_tangency_rmajor, rmajor=physics_variables.rmajor, n_tf_coils=tfcoil_variables.n_tf_coils, dx_tf_inboard_out_toroidal=tfcoil_variables.dx_tf_inboard_out_toroidal, dr_tf_outboard=self.data.build.dr_tf_outboard, r_tf_outboard_mid=self.data.build.r_tf_outboard_mid, - dx_beam_duct=current_drive_variables.dx_beam_duct, - dx_beam_shield=current_drive_variables.dx_beam_shield, + dx_beam_duct=self.data.current_drive.dx_beam_duct, + dx_beam_shield=self.data.current_drive.dx_beam_shield, ) def calculate_beam_port_size( @@ -2322,8 +2321,8 @@ def calculate_radial_build(self, output: bool): if ( CurrentDriveModel( - current_drive_variables.i_hcd_primary - or current_drive_variables.i_hcd_secondary + self.data.current_drive.i_hcd_primary + or self.data.current_drive.i_hcd_secondary ).method == CurrentDriveMethodType.NEUTRAL_BEAM ): @@ -2331,5 +2330,5 @@ def calculate_radial_build(self, output: bool): self.mfile, "Width of neutral beam duct where it passes between the TF coils (m)", "(dx_beam_duct)", - current_drive_variables.dx_beam_duct, + self.data.current_drive.dx_beam_duct, ) diff --git a/process/models/buildings.py b/process/models/buildings.py index d62fa45fc..da859a540 100644 --- a/process/models/buildings.py +++ b/process/models/buildings.py @@ -6,7 +6,6 @@ from process.core import process_output as po from process.core.model import Model from process.data_structure import ( - current_drive_variables, divertor_variables, heat_transport_variables, pfcoil_variables, @@ -469,9 +468,9 @@ def bldgs_sizes(self, output, tf_radial_dim, tf_vertical_dim): # Heating and Current Drive facility # Dimensions based upon estimates from M. Henderson, HCD Development Group - # current_drive_variables.i_hcd_primary = switch for current drive model + # self.data.current_drive.i_hcd_primary = switch for current drive model if ( - CurrentDriveModel(current_drive_variables.i_hcd_primary).method + CurrentDriveModel(self.data.current_drive.i_hcd_primary).method == CurrentDriveMethodType.NEUTRAL_BEAM ): # NBI technology will be situated within the reactor building @@ -1024,7 +1023,7 @@ def bldgs_sizes(self, output, tf_radial_dim, tf_vertical_dim): self.data.buildings.reactor_hall_h, ) if ( - CurrentDriveModel(current_drive_variables.i_hcd_primary).method + CurrentDriveModel(self.data.current_drive.i_hcd_primary).method == CurrentDriveMethodType.NEUTRAL_BEAM ): po.ocmmnt( @@ -1118,7 +1117,7 @@ def bldgs_sizes(self, output, tf_radial_dim, tf_vertical_dim): hotcell_vol_ext, ) po.oblnkl(self.outfile) - if current_drive_variables.i_hcd_primary not in {5, 8}: + if self.data.current_drive.i_hcd_primary not in {5, 8}: po.ovarre( self.outfile, "HCD (EC/EBW) building footprint (m2)", diff --git a/process/models/costs/costs.py b/process/models/costs/costs.py index 0a0510df7..435154613 100644 --- a/process/models/costs/costs.py +++ b/process/models/costs/costs.py @@ -7,7 +7,6 @@ from process.core.exceptions import ProcessValueError from process.core.model import Model from process.data_structure import ( - current_drive_variables, divertor_variables, heat_transport_variables, ife_variables, @@ -1869,7 +1868,7 @@ def acc223(self): self.data.costs.c2231 = ( 1.0e-6 * self.data.costs.ucech - * (1.0e6 * current_drive_variables.p_hcd_ecrh_injected_total_mw) ** exprf + * (1.0e6 * self.data.current_drive.p_hcd_ecrh_injected_total_mw) ** exprf ) if self.data.costs.ifueltyp == 1: @@ -1880,18 +1879,18 @@ def acc223(self): # Account 223.2 : Lower Hybrid or ICH - if current_drive_variables.i_hcd_primary != 2: + if self.data.current_drive.i_hcd_primary != 2: self.data.costs.c2232 = ( 1.0e-6 * self.data.costs.uclh - * (1.0e6 * current_drive_variables.p_hcd_lowhyb_injected_total_mw) + * (1.0e6 * self.data.current_drive.p_hcd_lowhyb_injected_total_mw) ** exprf ) else: self.data.costs.c2232 = ( 1.0e-6 * self.data.costs.ucich - * (1.0e6 * current_drive_variables.p_hcd_lowhyb_injected_total_mw) + * (1.0e6 * self.data.current_drive.p_hcd_lowhyb_injected_total_mw) ** exprf ) @@ -1909,7 +1908,7 @@ def acc223(self): self.data.costs.c2233 = ( 1.0e-6 * self.data.costs.ucnbi - * (1.0e6 * current_drive_variables.p_beam_injected_mw) ** exprf + * (1.0e6 * self.data.current_drive.p_beam_injected_mw) ** exprf ) if self.data.costs.ifueltyp == 1: diff --git a/process/models/costs/costs_2015.py b/process/models/costs/costs_2015.py index 3dbadee30..24d429a73 100644 --- a/process/models/costs/costs_2015.py +++ b/process/models/costs/costs_2015.py @@ -6,7 +6,6 @@ from process.core import process_output as po from process.core.model import Model from process.data_structure import ( - current_drive_variables, global_variables, heat_transport_variables, pf_power_variables, @@ -494,7 +493,7 @@ def calc_building_costs(self): 28000.0e0 * self.data.costs.light_build_cost_per_vol ) # Scale with neutral beam wall plug power (MW) - self.data.costs_2015.s_k[2] = current_drive_variables.pwpnb + self.data.costs_2015.s_k[2] = self.data.current_drive.pwpnb self.data.costs_2015.s_kref[2] = 120.0e0 self.data.costs_2015.s_cost[2] = ( self.data.costs_2015.s_cost_factor[2] @@ -938,7 +937,7 @@ def calc_remaining_subsystems(self): # Increased to 90 Mdollar because of press release self.data.costs_2015.s_cref[40] = 90.0e6 # Scale with total aux injected power (MW) - self.data.costs_2015.s_k[40] = current_drive_variables.p_hcd_injected_total_mw + self.data.costs_2015.s_k[40] = self.data.current_drive.p_hcd_injected_total_mw self.data.costs_2015.s_kref[40] = 50.0e0 self.data.costs_2015.s_cost[40] = ( self.data.costs_2015.s_cost_factor[40] @@ -1106,7 +1105,7 @@ def calc_remaining_subsystems(self): # Cost of ITER NB H and CD self.data.costs_2015.s_cref[52] = 814.0e6 # Scale with total auxiliary injected power (MW) - self.data.costs_2015.s_k[52] = current_drive_variables.p_hcd_injected_total_mw + self.data.costs_2015.s_k[52] = self.data.current_drive.p_hcd_injected_total_mw self.data.costs_2015.s_kref[52] = 50.0e0 self.data.costs_2015.s_cost[52] = ( self.data.costs_2015.s_cost_factor[52] diff --git a/process/models/physics/bootstrap_current.py b/process/models/physics/bootstrap_current.py index ee2701503..e40a2a8a7 100644 --- a/process/models/physics/bootstrap_current.py +++ b/process/models/physics/bootstrap_current.py @@ -14,7 +14,6 @@ from process.core.exceptions import ProcessValueError from process.core.model import Model from process.data_structure import ( - current_drive_variables, physics_variables, ) from process.models.physics.plasma_profiles import PlasmaProfile @@ -84,8 +83,8 @@ def run(self) -> None: If an illegal value of i_bootstrap_current is provided. """ # Calculate bootstrap current fraction using various models - current_drive_variables.f_c_plasma_bootstrap_iter89 = ( - current_drive_variables.cboot + self.data.current_drive.f_c_plasma_bootstrap_iter89 = ( + self.data.current_drive.cboot * self.bootstrap_fraction_iter89( aspect=physics_variables.aspect, beta=physics_variables.beta_total_vol_avg, @@ -98,8 +97,8 @@ def run(self) -> None: ) ) - current_drive_variables.f_c_plasma_bootstrap_nevins = ( - current_drive_variables.cboot + self.data.current_drive.f_c_plasma_bootstrap_nevins = ( + self.data.current_drive.cboot * self.bootstrap_fraction_nevins( alphan=physics_variables.alphan, alphat=physics_variables.alphat, @@ -117,8 +116,8 @@ def run(self) -> None: ) # Wilson scaling uses thermal poloidal beta, not total - current_drive_variables.f_c_plasma_bootstrap_wilson = ( - current_drive_variables.cboot + self.data.current_drive.f_c_plasma_bootstrap_wilson = ( + self.data.current_drive.cboot * self.bootstrap_fraction_wilson( alphaj=physics_variables.alphaj, alphap=physics_variables.alphap, @@ -132,15 +131,15 @@ def run(self) -> None: ) ( - current_drive_variables.f_c_plasma_bootstrap_sauter, + self.data.current_drive.f_c_plasma_bootstrap_sauter, physics_variables.j_plasma_bootstrap_sauter_profile, ) = self.bootstrap_fraction_sauter(self.plasma_profile) - current_drive_variables.f_c_plasma_bootstrap_sauter *= ( - current_drive_variables.cboot + self.data.current_drive.f_c_plasma_bootstrap_sauter *= ( + self.data.current_drive.cboot ) - current_drive_variables.f_c_plasma_bootstrap_sakai = ( - current_drive_variables.cboot + self.data.current_drive.f_c_plasma_bootstrap_sakai = ( + self.data.current_drive.cboot * self.bootstrap_fraction_sakai( beta_poloidal=physics_variables.beta_poloidal_vol_avg, q95=physics_variables.q95, @@ -152,8 +151,8 @@ def run(self) -> None: ) ) - current_drive_variables.f_c_plasma_bootstrap_aries = ( - current_drive_variables.cboot + self.data.current_drive.f_c_plasma_bootstrap_aries = ( + self.data.current_drive.cboot * self.bootstrap_fraction_aries( beta_poloidal=physics_variables.beta_poloidal_vol_avg, ind_plasma_internal_norm=physics_variables.ind_plasma_internal_norm, @@ -163,8 +162,8 @@ def run(self) -> None: ) ) - current_drive_variables.f_c_plasma_bootstrap_andrade = ( - current_drive_variables.cboot + self.data.current_drive.f_c_plasma_bootstrap_andrade = ( + self.data.current_drive.cboot * self.bootstrap_fraction_andrade( beta_poloidal=physics_variables.beta_poloidal_vol_avg, core_pressure=physics_variables.pres_plasma_thermal_on_axis, @@ -172,8 +171,8 @@ def run(self) -> None: inverse_aspect=physics_variables.eps, ) ) - current_drive_variables.f_c_plasma_bootstrap_hoang = ( - current_drive_variables.cboot + self.data.current_drive.f_c_plasma_bootstrap_hoang = ( + self.data.current_drive.cboot * self.bootstrap_fraction_hoang( beta_poloidal=physics_variables.beta_poloidal_vol_avg, pressure_index=physics_variables.alphap, @@ -181,8 +180,8 @@ def run(self) -> None: inverse_aspect=physics_variables.eps, ) ) - current_drive_variables.f_c_plasma_bootstrap_wong = ( - current_drive_variables.cboot + self.data.current_drive.f_c_plasma_bootstrap_wong = ( + self.data.current_drive.cboot * self.bootstrap_fraction_wong( beta_poloidal=physics_variables.beta_poloidal_vol_avg, density_index=physics_variables.alphan, @@ -191,8 +190,8 @@ def run(self) -> None: elongation=physics_variables.kappa, ) ) - current_drive_variables.bscf_gi_i = ( - current_drive_variables.cboot + self.data.current_drive.bscf_gi_i = ( + self.data.current_drive.cboot * self.bootstrap_fraction_gi_I( beta_poloidal=physics_variables.beta_poloidal_vol_avg, pressure_index=physics_variables.alphap, @@ -204,8 +203,8 @@ def run(self) -> None: ) ) - current_drive_variables.bscf_gi_ii = ( - current_drive_variables.cboot + self.data.current_drive.bscf_gi_ii = ( + self.data.current_drive.cboot * self.bootstrap_fraction_gi_II( beta_poloidal=physics_variables.beta_poloidal_vol_avg, pressure_index=physics_variables.alphap, @@ -214,8 +213,8 @@ def run(self) -> None: effective_charge=physics_variables.n_charge_plasma_effective_vol_avg, ) ) - current_drive_variables.f_c_plasma_bootstrap_sugiyama_l = ( - current_drive_variables.cboot + self.data.current_drive.f_c_plasma_bootstrap_sugiyama_l = ( + self.data.current_drive.cboot * self.bootstrap_fraction_sugiyama_l_mode( eps=physics_variables.eps, beta_poloidal=physics_variables.beta_poloidal_vol_avg, @@ -226,8 +225,8 @@ def run(self) -> None: q0=physics_variables.q0, ) ) - current_drive_variables.f_c_plasma_bootstrap_sugiyama_h = ( - current_drive_variables.cboot + self.data.current_drive.f_c_plasma_bootstrap_sugiyama_h = ( + self.data.current_drive.cboot * self.bootstrap_fraction_sugiyama_h_mode( eps=physics_variables.eps, beta_poloidal=physics_variables.beta_poloidal_vol_avg, @@ -249,7 +248,7 @@ def run(self) -> None: model = BootstrapCurrentFractionModel( int(physics_variables.i_bootstrap_current) ) - current_drive_variables.f_c_plasma_bootstrap = ( + self.data.current_drive.f_c_plasma_bootstrap = ( self.get_bootstrap_current_fraction_value(model) ) except ValueError: @@ -258,8 +257,8 @@ def run(self) -> None: i_bootstrap_current=physics_variables.i_bootstrap_current, ) from None - @staticmethod def get_bootstrap_current_fraction_value( + self, model: BootstrapCurrentFractionModel, ) -> float: """Get the plasma current bootstrap fraction (f_BS) for the specified model. @@ -275,20 +274,20 @@ def get_bootstrap_current_fraction_value( The bootstrap current fraction value. """ model_map = { - BootstrapCurrentFractionModel.USER_INPUT: current_drive_variables.f_c_plasma_bootstrap, - BootstrapCurrentFractionModel.ITER_89: current_drive_variables.f_c_plasma_bootstrap_iter89, - BootstrapCurrentFractionModel.NEVINS: current_drive_variables.f_c_plasma_bootstrap_nevins, - BootstrapCurrentFractionModel.WILSON: current_drive_variables.f_c_plasma_bootstrap_wilson, - BootstrapCurrentFractionModel.SAUTER: current_drive_variables.f_c_plasma_bootstrap_sauter, - BootstrapCurrentFractionModel.SAKAI: current_drive_variables.f_c_plasma_bootstrap_sakai, - BootstrapCurrentFractionModel.ARIES: current_drive_variables.f_c_plasma_bootstrap_aries, - BootstrapCurrentFractionModel.ANDRADE: current_drive_variables.f_c_plasma_bootstrap_andrade, - BootstrapCurrentFractionModel.HOANG: current_drive_variables.f_c_plasma_bootstrap_hoang, - BootstrapCurrentFractionModel.WONG: current_drive_variables.f_c_plasma_bootstrap_wong, - BootstrapCurrentFractionModel.GI_1: current_drive_variables.bscf_gi_i, - BootstrapCurrentFractionModel.GI_2: current_drive_variables.bscf_gi_ii, - BootstrapCurrentFractionModel.SUGIYAMA_L_MODE: current_drive_variables.f_c_plasma_bootstrap_sugiyama_l, - BootstrapCurrentFractionModel.SUGIYAMA_H_MODE: current_drive_variables.f_c_plasma_bootstrap_sugiyama_h, + BootstrapCurrentFractionModel.USER_INPUT: self.data.current_drive.f_c_plasma_bootstrap, + BootstrapCurrentFractionModel.ITER_89: self.data.current_drive.f_c_plasma_bootstrap_iter89, + BootstrapCurrentFractionModel.NEVINS: self.data.current_drive.f_c_plasma_bootstrap_nevins, + BootstrapCurrentFractionModel.WILSON: self.data.current_drive.f_c_plasma_bootstrap_wilson, + BootstrapCurrentFractionModel.SAUTER: self.data.current_drive.f_c_plasma_bootstrap_sauter, + BootstrapCurrentFractionModel.SAKAI: self.data.current_drive.f_c_plasma_bootstrap_sakai, + BootstrapCurrentFractionModel.ARIES: self.data.current_drive.f_c_plasma_bootstrap_aries, + BootstrapCurrentFractionModel.ANDRADE: self.data.current_drive.f_c_plasma_bootstrap_andrade, + BootstrapCurrentFractionModel.HOANG: self.data.current_drive.f_c_plasma_bootstrap_hoang, + BootstrapCurrentFractionModel.WONG: self.data.current_drive.f_c_plasma_bootstrap_wong, + BootstrapCurrentFractionModel.GI_1: self.data.current_drive.bscf_gi_i, + BootstrapCurrentFractionModel.GI_2: self.data.current_drive.bscf_gi_ii, + BootstrapCurrentFractionModel.SUGIYAMA_L_MODE: self.data.current_drive.f_c_plasma_bootstrap_sugiyama_l, + BootstrapCurrentFractionModel.SUGIYAMA_H_MODE: self.data.current_drive.f_c_plasma_bootstrap_sugiyama_h, } return model_map[model] @@ -1282,27 +1281,27 @@ def output(self): self.outfile, "Bootstrap current fraction multiplier", "(cboot)", - current_drive_variables.cboot, + self.data.current_drive.cboot, ) po.ovarrf( self.outfile, f"Bootstrap fraction ({BootstrapCurrentFractionModel.ITER_89.full_name})", "(f_c_plasma_bootstrap_iter89)", - current_drive_variables.f_c_plasma_bootstrap_iter89, + self.data.current_drive.f_c_plasma_bootstrap_iter89, "OP ", ) po.ovarrf( self.outfile, f"Bootstrap fraction ({BootstrapCurrentFractionModel.NEVINS.full_name})", "(f_c_plasma_bootstrap_nevins)", - current_drive_variables.f_c_plasma_bootstrap_nevins, + self.data.current_drive.f_c_plasma_bootstrap_nevins, "OP ", ) po.ovarrf( self.outfile, f"Bootstrap fraction ({BootstrapCurrentFractionModel.WILSON.full_name})", "(f_c_plasma_bootstrap_wilson)", - current_drive_variables.f_c_plasma_bootstrap_wilson, + self.data.current_drive.f_c_plasma_bootstrap_wilson, "OP ", ) @@ -1310,7 +1309,7 @@ def output(self): self.outfile, f"Bootstrap fraction ({BootstrapCurrentFractionModel.SAUTER.full_name})", "(f_c_plasma_bootstrap_sauter)", - current_drive_variables.f_c_plasma_bootstrap_sauter, + self.data.current_drive.f_c_plasma_bootstrap_sauter, "OP ", ) for point in range(len(physics_variables.j_plasma_bootstrap_sauter_profile)): @@ -1326,49 +1325,49 @@ def output(self): self.outfile, f"Bootstrap fraction ({BootstrapCurrentFractionModel.SAKAI.full_name})", "(f_c_plasma_bootstrap_sakai)", - current_drive_variables.f_c_plasma_bootstrap_sakai, + self.data.current_drive.f_c_plasma_bootstrap_sakai, "OP ", ) po.ovarrf( self.outfile, f"Bootstrap fraction ({BootstrapCurrentFractionModel.ARIES.full_name})", "(f_c_plasma_bootstrap_aries)", - current_drive_variables.f_c_plasma_bootstrap_aries, + self.data.current_drive.f_c_plasma_bootstrap_aries, "OP ", ) po.ovarrf( self.outfile, f"Bootstrap fraction ({BootstrapCurrentFractionModel.ANDRADE.full_name})", "(f_c_plasma_bootstrap_andrade)", - current_drive_variables.f_c_plasma_bootstrap_andrade, + self.data.current_drive.f_c_plasma_bootstrap_andrade, "OP ", ) po.ovarrf( self.outfile, f"Bootstrap fraction ({BootstrapCurrentFractionModel.HOANG.full_name})", "(f_c_plasma_bootstrap_hoang)", - current_drive_variables.f_c_plasma_bootstrap_hoang, + self.data.current_drive.f_c_plasma_bootstrap_hoang, "OP ", ) po.ovarrf( self.outfile, f"Bootstrap fraction ({BootstrapCurrentFractionModel.WONG.full_name})", "(f_c_plasma_bootstrap_wong)", - current_drive_variables.f_c_plasma_bootstrap_wong, + self.data.current_drive.f_c_plasma_bootstrap_wong, "OP ", ) po.ovarrf( self.outfile, f"Bootstrap fraction ({BootstrapCurrentFractionModel.GI_1.full_name})", "(bscf_gi_i)", - current_drive_variables.bscf_gi_i, + self.data.current_drive.bscf_gi_i, "OP ", ) po.ovarrf( self.outfile, f"Bootstrap fraction ({BootstrapCurrentFractionModel.GI_2.full_name})", "(bscf_gi_ii)", - current_drive_variables.bscf_gi_ii, + self.data.current_drive.bscf_gi_ii, "OP ", ) po.ovarrf( @@ -1376,7 +1375,7 @@ def output(self): f"Bootstrap fraction" f" ({BootstrapCurrentFractionModel.SUGIYAMA_L_MODE.full_name})", "(f_c_plasma_bootstrap_sugiyama_l)", - current_drive_variables.f_c_plasma_bootstrap_sugiyama_l, + self.data.current_drive.f_c_plasma_bootstrap_sugiyama_l, "OP ", ) po.ovarrf( @@ -1384,7 +1383,7 @@ def output(self): f"Bootstrap fraction" f" ({BootstrapCurrentFractionModel.SUGIYAMA_H_MODE.full_name})", "(f_c_plasma_bootstrap_sugiyama_h)", - current_drive_variables.f_c_plasma_bootstrap_sugiyama_h, + self.data.current_drive.f_c_plasma_bootstrap_sugiyama_h, "OP ", ) @@ -1393,7 +1392,7 @@ def output(self): self.outfile, "Pfirsch-Schlueter fraction (SCENE)", "(f_c_plasma_pfirsch_schluter_scene)", - current_drive_variables.f_c_plasma_pfirsch_schluter_scene, + self.data.current_drive.f_c_plasma_pfirsch_schluter_scene, "OP ", ) # Error to catch if bootstap fraction limit has been enforced @@ -1419,21 +1418,21 @@ def output(self): self.outfile, "Bootstrap fraction (enforced)", "(f_c_plasma_bootstrap.)", - current_drive_variables.f_c_plasma_bootstrap, + self.data.current_drive.f_c_plasma_bootstrap, "OP ", ) po.ovarrf( self.outfile, "Diamagnetic fraction (enforced)", "(f_c_plasma_diamagnetic.)", - current_drive_variables.f_c_plasma_diamagnetic, + self.data.current_drive.f_c_plasma_diamagnetic, "OP ", ) po.ovarrf( self.outfile, "Pfirsch-Schlueter fraction (enforced)", "(f_c_plasma_pfirsch_schluter.)", - current_drive_variables.f_c_plasma_pfirsch_schluter, + self.data.current_drive.f_c_plasma_pfirsch_schluter, "OP ", ) diff --git a/process/models/physics/confinement_time.py b/process/models/physics/confinement_time.py index 23c5ac3e4..e02a511ff 100644 --- a/process/models/physics/confinement_time.py +++ b/process/models/physics/confinement_time.py @@ -11,7 +11,6 @@ from process.core.exceptions import ProcessValueError from process.core.model import Model from process.data_structure import ( - current_drive_variables, physics_variables, stellarator_variables, ) @@ -1189,7 +1188,7 @@ def fhz(hfact: float) -> float: kappa=physics_variables.kappa, kappa95=physics_variables.kappa95, p_non_alpha_charged_mw=physics_variables.p_non_alpha_charged_mw, - p_hcd_injected_total_mw=current_drive_variables.p_hcd_injected_total_mw, + p_hcd_injected_total_mw=self.data.current_drive.p_hcd_injected_total_mw, plasma_current=physics_variables.plasma_current, pden_plasma_core_rad_mw=physics_variables.pden_plasma_core_rad_mw, rmajor=physics_variables.rmajor, @@ -1216,7 +1215,7 @@ def fhz(hfact: float) -> float: # (i.e. whether device is ignited) if physics_variables.i_plasma_ignited == 0: fhz_value -= ( - current_drive_variables.p_hcd_injected_total_mw + self.data.current_drive.p_hcd_injected_total_mw / physics_variables.vol_plasma ) @@ -1477,7 +1476,7 @@ def output_confinement_comparison(self, istell: int): kappa=physics_variables.kappa, kappa95=physics_variables.kappa95, p_non_alpha_charged_mw=physics_variables.p_non_alpha_charged_mw, - p_hcd_injected_total_mw=current_drive_variables.p_hcd_injected_total_mw, + p_hcd_injected_total_mw=self.data.current_drive.p_hcd_injected_total_mw, plasma_current=physics_variables.plasma_current, pden_plasma_core_rad_mw=physics_variables.pden_plasma_core_rad_mw, rmajor=physics_variables.rmajor, diff --git a/process/models/physics/current_drive.py b/process/models/physics/current_drive.py index 113096a36..666b13ba9 100644 --- a/process/models/physics/current_drive.py +++ b/process/models/physics/current_drive.py @@ -13,7 +13,6 @@ from process.core.exceptions import ProcessError, ProcessValueError from process.core.model import Model from process.data_structure import ( - current_drive_variables, heat_transport_variables, physics_variables, ) @@ -134,13 +133,19 @@ def full_name(self): return self._full_name_ -class NeutralBeam: +class NeutralBeam(Model): """Class for calculating neutral beam current drive parameters""" def __init__(self, plasma_profile: PlasmaProfile): self.outfile = constants.NOUT self.plasma_profile = plasma_profile + def output(self): + """This model doesn't have any output""" + + def run(self): + """This model doesn't need to be run""" + def iternb(self): """Routine to calculate ITER Neutral Beam current drive parameters @@ -170,23 +175,23 @@ def iternb(self): # Check argument sanity if ( 1 + physics_variables.eps - ) < current_drive_variables.f_radius_beam_tangency_rmajor: + ) < self.data.current_drive.f_radius_beam_tangency_rmajor: raise ProcessValueError( "Imminent negative square root argument; NBI will miss plasma " "completely", eps=physics_variables.eps, - f_radius_beam_tangency_rmajor=current_drive_variables.f_radius_beam_tangency_rmajor, + f_radius_beam_tangency_rmajor=self.data.current_drive.f_radius_beam_tangency_rmajor, ) # Calculate beam path length to centre dpath = physics_variables.rmajor * np.sqrt( (1.0 + physics_variables.eps) ** 2 - - current_drive_variables.f_radius_beam_tangency_rmajor**2 + - self.data.current_drive.f_radius_beam_tangency_rmajor**2 ) # Calculate beam stopping cross-section sigstop = self.sigbeam( - current_drive_variables.e_beam_kev / physics_variables.m_beam_amu, + self.data.current_drive.e_beam_kev / physics_variables.m_beam_amu, physics_variables.temp_plasma_electron_vol_avg_kev, physics_variables.nd_plasma_electrons_vol_avg, physics_variables.f_nd_alpha_electron, @@ -196,7 +201,7 @@ def iternb(self): ) # Calculate number of decay lengths to centre - current_drive_variables.n_beam_decay_lengths_core = ( + self.data.current_drive.n_beam_decay_lengths_core = ( dpath * physics_variables.nd_plasma_electrons_vol_avg * sigstop ) @@ -209,7 +214,7 @@ def iternb(self): # Power split to ions / electrons f_p_beam_injected_ions = self.cfnbi( afast=physics_variables.m_beam_amu, - efast=current_drive_variables.e_beam_kev, + efast=self.data.current_drive.e_beam_kev, te=physics_variables.temp_plasma_electron_density_weighted_kev, ne=physics_variables.nd_plasma_electrons_vol_avg, n_charge_plasma_effective_mass_weighted_vol_avg=physics_variables.n_charge_plasma_effective_mass_weighted_vol_avg, @@ -217,13 +222,13 @@ def iternb(self): ) # Current drive efficiency - effnbss = current_drive_variables.f_radius_beam_tangency_rmajor * self.etanb( + effnbss = self.data.current_drive.f_radius_beam_tangency_rmajor * self.etanb( physics_variables.m_beam_amu, physics_variables.alphan, physics_variables.alphat, physics_variables.aspect, physics_variables.nd_plasma_electrons_vol_avg, - current_drive_variables.e_beam_kev, + self.data.current_drive.e_beam_kev, physics_variables.rmajor, physics_variables.temp_plasma_electron_density_weighted_kev, physics_variables.n_charge_plasma_effective_vol_avg, @@ -260,25 +265,25 @@ def culnbi(self) -> tuple[float, float, float]: """ if ( 1.0e0 + physics_variables.eps - ) < current_drive_variables.f_radius_beam_tangency_rmajor: + ) < self.data.current_drive.f_radius_beam_tangency_rmajor: raise ProcessValueError( "Imminent negative square root argument; NBI will miss plasma " "completely", eps=physics_variables.eps, - f_radius_beam_tangency_rmajor=current_drive_variables.f_radius_beam_tangency_rmajor, + f_radius_beam_tangency_rmajor=self.data.current_drive.f_radius_beam_tangency_rmajor, ) # Calculate beam path length to centre dpath = physics_variables.rmajor * np.sqrt( (1.0e0 + physics_variables.eps) ** 2 - - current_drive_variables.f_radius_beam_tangency_rmajor**2 + - self.data.current_drive.f_radius_beam_tangency_rmajor**2 ) # Calculate beam stopping cross-section sigstop = self.sigbeam( - current_drive_variables.e_beam_kev / physics_variables.m_beam_amu, + self.data.current_drive.e_beam_kev / physics_variables.m_beam_amu, physics_variables.temp_plasma_electron_vol_avg_kev, physics_variables.nd_plasma_electrons_vol_avg, physics_variables.f_nd_alpha_electron, @@ -289,7 +294,7 @@ def culnbi(self) -> tuple[float, float, float]: # Calculate number of decay lengths to centre - current_drive_variables.n_beam_decay_lengths_core = ( + self.data.current_drive.n_beam_decay_lengths_core = ( dpath * physics_variables.nd_plasma_electron_line * sigstop ) @@ -304,7 +309,7 @@ def culnbi(self) -> tuple[float, float, float]: f_p_beam_injected_ions = self.cfnbi( afast=physics_variables.m_beam_amu, - efast=current_drive_variables.e_beam_kev, + efast=self.data.current_drive.e_beam_kev, te=physics_variables.temp_plasma_electron_density_weighted_kev, ne=physics_variables.nd_plasma_electrons_vol_avg, n_charge_plasma_effective_mass_weighted_vol_avg=physics_variables.n_charge_plasma_effective_mass_weighted_vol_avg, @@ -320,8 +325,8 @@ def culnbi(self) -> tuple[float, float, float]: physics_variables.aspect, physics_variables.nd_plasma_electrons_vol_avg, physics_variables.nd_plasma_electron_line, - current_drive_variables.e_beam_kev, - current_drive_variables.f_radius_beam_tangency_rmajor, + self.data.current_drive.e_beam_kev, + self.data.current_drive.f_radius_beam_tangency_rmajor, fshine, physics_variables.rmajor, physics_variables.rminor, @@ -1646,32 +1651,32 @@ def current_drive(self): ProcessValueError If an invalid current drive switch is encountered. """ - current_drive_variables.p_hcd_ecrh_injected_total_mw = 0.0e0 - current_drive_variables.p_hcd_beam_injected_total_mw = 0.0e0 - current_drive_variables.p_hcd_lowhyb_injected_total_mw = 0.0e0 - current_drive_variables.p_hcd_icrh_injected_total_mw = 0.0e0 - current_drive_variables.p_hcd_ebw_injected_total_mw = 0.0e0 - current_drive_variables.c_beam_total = 0.0e0 - current_drive_variables.p_beam_orbit_loss_mw = 0.0e0 + self.data.current_drive.p_hcd_ecrh_injected_total_mw = 0.0e0 + self.data.current_drive.p_hcd_beam_injected_total_mw = 0.0e0 + self.data.current_drive.p_hcd_lowhyb_injected_total_mw = 0.0e0 + self.data.current_drive.p_hcd_icrh_injected_total_mw = 0.0e0 + self.data.current_drive.p_hcd_ebw_injected_total_mw = 0.0e0 + self.data.current_drive.c_beam_total = 0.0e0 + self.data.current_drive.p_beam_orbit_loss_mw = 0.0e0 p_hcd_primary_ions_mw = 0.0 p_hcd_primary_electrons_mw = 0.0 p_hcd_secondary_electrons_mw = 0.0 p_hcd_secondary_ions_mw = 0.0 - primary_cdm = CurrentDriveModel(current_drive_variables.i_hcd_primary) - secondary_cdm = CurrentDriveModel(current_drive_variables.i_hcd_secondary) + primary_cdm = CurrentDriveModel(self.data.current_drive.i_hcd_primary) + secondary_cdm = CurrentDriveModel(self.data.current_drive.i_hcd_secondary) # To stop issues with input file we force # zero secondary heating if no injection method - if current_drive_variables.i_hcd_secondary == 0: - current_drive_variables.p_hcd_secondary_extra_heat_mw = 0.0 + if self.data.current_drive.i_hcd_secondary == 0: + self.data.current_drive.p_hcd_secondary_extra_heat_mw = 0.0 # i_hcd_calculations | switch for current drive calculation # = 0 | turned off # = 1 | turned on - if current_drive_variables.i_hcd_calculations != 0: + if self.data.current_drive.i_hcd_calculations != 0: # Put electron density in desired units (10^-20 m-3) dene20 = physics_variables.nd_plasma_electrons_vol_avg * 1.0e-20 @@ -1687,7 +1692,7 @@ def current_drive(self): physics_variables.rmajor, dene20, ) - * current_drive_variables.feffcd + * self.data.current_drive.feffcd ), 2: lambda: ( self.ion_cyclotron.ion_cyclotron_ipdg89( @@ -1696,7 +1701,7 @@ def current_drive(self): rmajor=physics_variables.rmajor, dene20=dene20, ) - * current_drive_variables.feffcd + * self.data.current_drive.feffcd ), 3: lambda: ( self.electron_cyclotron.electron_cyclotron_fenstermacher( @@ -1705,7 +1710,7 @@ def current_drive(self): dene20=dene20, dlamee=physics_variables.dlamee, ) - * current_drive_variables.feffcd + * self.data.current_drive.feffcd ), 4: lambda: ( self.lower_hybrid.lower_hybrid_ehst( @@ -1715,20 +1720,20 @@ def current_drive(self): dene20=dene20, zeff=physics_variables.n_charge_plasma_effective_vol_avg, ) - * current_drive_variables.feffcd + * self.data.current_drive.feffcd ), 5: lambda: ( - self.neutral_beam.iternb()[0] * current_drive_variables.feffcd + self.neutral_beam.iternb()[0] * self.data.current_drive.feffcd ), - 6: lambda: self.lower_hybrid.cullhy() * current_drive_variables.feffcd, + 6: lambda: self.lower_hybrid.cullhy() * self.data.current_drive.feffcd, 7: lambda: ( - self.electron_cyclotron.culecd() * current_drive_variables.feffcd + self.electron_cyclotron.culecd() * self.data.current_drive.feffcd ), 8: lambda: ( - self.neutral_beam.culnbi()[0] * current_drive_variables.feffcd + self.neutral_beam.culnbi()[0] * self.data.current_drive.feffcd ), 10: lambda: ( - current_drive_variables.eta_cd_norm_ecrh + self.data.current_drive.eta_cd_norm_ecrh / (dene20 * physics_variables.rmajor) ), 12: lambda: ( @@ -1737,10 +1742,10 @@ def current_drive(self): rmajor=physics_variables.rmajor, dene20=dene20, b_plasma_toroidal_on_axis=physics_variables.b_plasma_toroidal_on_axis, - n_ecrh_harmonic=current_drive_variables.n_ecrh_harmonic, - xi_ebw=current_drive_variables.xi_ebw, + n_ecrh_harmonic=self.data.current_drive.n_ecrh_harmonic, + xi_ebw=self.data.current_drive.xi_ebw, ) - * current_drive_variables.feffcd + * self.data.current_drive.feffcd ), 13: lambda: ( self.electron_cyclotron.electron_cyclotron_freethy( @@ -1749,10 +1754,10 @@ def current_drive(self): rmajor=physics_variables.rmajor, nd_plasma_electrons_vol_avg=physics_variables.nd_plasma_electrons_vol_avg, b_plasma_toroidal_on_axis=physics_variables.b_plasma_toroidal_on_axis, - n_ecrh_harmonic=current_drive_variables.n_ecrh_harmonic, - i_ecrh_wave_mode=current_drive_variables.i_ecrh_wave_mode, + n_ecrh_harmonic=self.data.current_drive.n_ecrh_harmonic, + i_ecrh_wave_mode=self.data.current_drive.i_ecrh_wave_mode, ) - * current_drive_variables.feffcd + * self.data.current_drive.feffcd ), } @@ -1760,104 +1765,104 @@ def current_drive(self): if secondary_cdm.method == CurrentDriveMethodType.NEUTRAL_BEAM: _, f_p_beam_injected_ions, f_p_beam_shine_through = ( self.neutral_beam.iternb() - if current_drive_variables.i_hcd_secondary == 5 + if self.data.current_drive.i_hcd_secondary == 5 else self.neutral_beam.culnbi() ) - current_drive_variables.f_p_beam_injected_ions = f_p_beam_injected_ions - current_drive_variables.f_p_beam_shine_through = f_p_beam_shine_through + self.data.current_drive.f_p_beam_injected_ions = f_p_beam_injected_ions + self.data.current_drive.f_p_beam_shine_through = f_p_beam_shine_through # Calculate eta_cd_hcd_secondary based on the selected model - if current_drive_variables.i_hcd_secondary in hcd_models: - current_drive_variables.eta_cd_hcd_secondary = hcd_models[ - current_drive_variables.i_hcd_secondary + if self.data.current_drive.i_hcd_secondary in hcd_models: + self.data.current_drive.eta_cd_hcd_secondary = hcd_models[ + self.data.current_drive.i_hcd_secondary ]() - elif current_drive_variables.i_hcd_secondary != 0: + elif self.data.current_drive.i_hcd_secondary != 0: raise ProcessValueError( f"Current drive switch is invalid: " - f"{current_drive_variables.i_hcd_secondary = }" + f"{self.data.current_drive.i_hcd_secondary = }" ) # Calculate eta_cd_hcd_primary based on the selected model - if current_drive_variables.i_hcd_primary in hcd_models: - current_drive_variables.eta_cd_hcd_primary = hcd_models[ - current_drive_variables.i_hcd_primary + if self.data.current_drive.i_hcd_primary in hcd_models: + self.data.current_drive.eta_cd_hcd_primary = hcd_models[ + self.data.current_drive.i_hcd_primary ]() else: raise ProcessValueError( f"Current drive switch is invalid: " - f"{current_drive_variables.i_hcd_primary = }" + f"{self.data.current_drive.i_hcd_primary = }" ) # Calculate the normalised current drive efficieny for the primary # heating method - current_drive_variables.eta_cd_norm_hcd_primary = self.calculate_normalised_current_drive_efficiency( - eta_cd_hcd=current_drive_variables.eta_cd_hcd_primary, + self.data.current_drive.eta_cd_norm_hcd_primary = self.calculate_normalised_current_drive_efficiency( + eta_cd_hcd=self.data.current_drive.eta_cd_hcd_primary, nd_plasma_electrons_vol_avg=physics_variables.nd_plasma_electrons_vol_avg, rmajor=physics_variables.rmajor, ) # Calculate the normalised current drive efficieny for the secondary # heating method - current_drive_variables.eta_cd_norm_hcd_secondary = self.calculate_normalised_current_drive_efficiency( - eta_cd_hcd=current_drive_variables.eta_cd_hcd_secondary, + self.data.current_drive.eta_cd_norm_hcd_secondary = self.calculate_normalised_current_drive_efficiency( + eta_cd_hcd=self.data.current_drive.eta_cd_hcd_secondary, nd_plasma_electrons_vol_avg=physics_variables.nd_plasma_electrons_vol_avg, rmajor=physics_variables.rmajor, ) # Calculate the driven current for the secondary heating method - current_drive_variables.c_hcd_secondary_driven = ( - current_drive_variables.eta_cd_hcd_secondary - * current_drive_variables.p_hcd_secondary_injected_mw + self.data.current_drive.c_hcd_secondary_driven = ( + self.data.current_drive.eta_cd_hcd_secondary + * self.data.current_drive.p_hcd_secondary_injected_mw * 1.0e6 ) # Calculate the fraction of the plasma current driven by the secondary # heating method - current_drive_variables.f_c_plasma_hcd_secondary = ( - current_drive_variables.c_hcd_secondary_driven + self.data.current_drive.f_c_plasma_hcd_secondary = ( + self.data.current_drive.c_hcd_secondary_driven / physics_variables.plasma_current ) # Calculate the injected power for the primary heating method - current_drive_variables.p_hcd_primary_injected_mw = ( + self.data.current_drive.p_hcd_primary_injected_mw = ( 1.0e-6 * ( physics_variables.f_c_plasma_auxiliary - - current_drive_variables.f_c_plasma_hcd_secondary + - self.data.current_drive.f_c_plasma_hcd_secondary ) * physics_variables.plasma_current - / current_drive_variables.eta_cd_hcd_primary + / self.data.current_drive.eta_cd_hcd_primary ) # Calculate the driven current for the primary heating method - current_drive_variables.c_hcd_primary_driven = ( - current_drive_variables.eta_cd_hcd_primary - * current_drive_variables.p_hcd_primary_injected_mw + self.data.current_drive.c_hcd_primary_driven = ( + self.data.current_drive.eta_cd_hcd_primary + * self.data.current_drive.p_hcd_primary_injected_mw * 1.0e6 ) # Calculate the fraction of the plasma current driven by the primary # heating method - current_drive_variables.f_c_plasma_hcd_primary = ( - current_drive_variables.c_hcd_primary_driven + self.data.current_drive.f_c_plasma_hcd_primary = ( + self.data.current_drive.c_hcd_primary_driven / physics_variables.plasma_current ) # Calculate the dimensionless current drive efficiency for the primary heating method (ζ) - current_drive_variables.eta_cd_dimensionless_hcd_primary = self.calculate_dimensionless_current_drive_efficiency( + self.data.current_drive.eta_cd_dimensionless_hcd_primary = self.calculate_dimensionless_current_drive_efficiency( nd_plasma_electrons_vol_avg=physics_variables.nd_plasma_electrons_vol_avg, rmajor=physics_variables.rmajor, temp_plasma_electron_vol_avg_kev=physics_variables.temp_plasma_electron_vol_avg_kev, - c_hcd_driven=current_drive_variables.c_hcd_primary_driven, - p_hcd_injected=current_drive_variables.p_hcd_primary_injected_mw * 1.0e6, + c_hcd_driven=self.data.current_drive.c_hcd_primary_driven, + p_hcd_injected=self.data.current_drive.p_hcd_primary_injected_mw * 1.0e6, ) - if current_drive_variables.p_hcd_secondary_injected_mw > 0.0: + if self.data.current_drive.p_hcd_secondary_injected_mw > 0.0: # Calculate the dimensionless current drive efficiency for the secondary # heating method (ζ) - current_drive_variables.eta_cd_dimensionless_hcd_secondary = self.calculate_dimensionless_current_drive_efficiency( + self.data.current_drive.eta_cd_dimensionless_hcd_secondary = self.calculate_dimensionless_current_drive_efficiency( nd_plasma_electrons_vol_avg=physics_variables.nd_plasma_electrons_vol_avg, rmajor=physics_variables.rmajor, temp_plasma_electron_vol_avg_kev=physics_variables.temp_plasma_electron_vol_avg_kev, - c_hcd_driven=current_drive_variables.c_hcd_secondary_driven, - p_hcd_injected=current_drive_variables.p_hcd_secondary_injected_mw + c_hcd_driven=self.data.current_drive.c_hcd_secondary_driven, + p_hcd_injected=self.data.current_drive.p_hcd_secondary_injected_mw * 1.0e6, ) @@ -1870,24 +1875,24 @@ def current_drive(self): if secondary_cdm.method == CurrentDriveMethodType.LOWER_HYBRID: # Injected power p_hcd_secondary_electrons_mw = ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw ) # Wall plug power heat_transport_variables.p_hcd_secondary_electric_mw = ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw - ) / current_drive_variables.eta_lowhyb_injector_wall_plug + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw + ) / self.data.current_drive.eta_lowhyb_injector_wall_plug # Wall plug to injector efficiency - current_drive_variables.eta_hcd_secondary_injector_wall_plug = ( - current_drive_variables.eta_lowhyb_injector_wall_plug + self.data.current_drive.eta_hcd_secondary_injector_wall_plug = ( + self.data.current_drive.eta_lowhyb_injector_wall_plug ) - current_drive_variables.p_hcd_lowhyb_injected_total_mw += ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw + self.data.current_drive.p_hcd_lowhyb_injected_total_mw += ( + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw ) # ========================================================== @@ -1896,24 +1901,24 @@ def current_drive(self): if secondary_cdm.method == CurrentDriveMethodType.ION_CYCLOTRON: # Injected power p_hcd_secondary_ions_mw = ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw ) # Wall plug power heat_transport_variables.p_hcd_secondary_electric_mw = ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw - ) / current_drive_variables.eta_icrh_injector_wall_plug + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw + ) / self.data.current_drive.eta_icrh_injector_wall_plug # Wall plug to injector efficiency - current_drive_variables.eta_hcd_secondary_injector_wall_plug = ( - current_drive_variables.eta_icrh_injector_wall_plug + self.data.current_drive.eta_hcd_secondary_injector_wall_plug = ( + self.data.current_drive.eta_icrh_injector_wall_plug ) - current_drive_variables.p_hcd_icrh_injected_total_mw += ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw + self.data.current_drive.p_hcd_icrh_injected_total_mw += ( + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw ) # ========================================================== @@ -1922,24 +1927,24 @@ def current_drive(self): if secondary_cdm.method == CurrentDriveMethodType.ELECTRON_CYCLOTRON: # Injected power p_hcd_secondary_electrons_mw = ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw ) # Wall plug power heat_transport_variables.p_hcd_secondary_electric_mw = ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw - ) / current_drive_variables.eta_ecrh_injector_wall_plug + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw + ) / self.data.current_drive.eta_ecrh_injector_wall_plug # Wall plug to injector efficiency - current_drive_variables.eta_hcd_secondary_injector_wall_plug = ( - current_drive_variables.eta_ecrh_injector_wall_plug + self.data.current_drive.eta_hcd_secondary_injector_wall_plug = ( + self.data.current_drive.eta_ecrh_injector_wall_plug ) - current_drive_variables.p_hcd_ecrh_injected_total_mw += ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw + self.data.current_drive.p_hcd_ecrh_injected_total_mw += ( + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw ) # ========================================================== @@ -1948,24 +1953,24 @@ def current_drive(self): if secondary_cdm.method == CurrentDriveMethodType.ELECTRON_BERNSTEIN: # Injected power p_hcd_secondary_electrons_mw = ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw ) # Wall plug power heat_transport_variables.p_hcd_secondary_electric_mw = ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw - ) / current_drive_variables.eta_ebw_injector_wall_plug + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw + ) / self.data.current_drive.eta_ebw_injector_wall_plug # Wall plug to injector efficiency - current_drive_variables.eta_hcd_secondary_injector_wall_plug = ( - current_drive_variables.eta_ebw_injector_wall_plug + self.data.current_drive.eta_hcd_secondary_injector_wall_plug = ( + self.data.current_drive.eta_ebw_injector_wall_plug ) - current_drive_variables.p_hcd_ebw_injected_total_mw += ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw + self.data.current_drive.p_hcd_ebw_injected_total_mw += ( + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw ) # ========================================================== @@ -1976,75 +1981,75 @@ def current_drive(self): # (power due to particles that are ionised but not thermalised) [MW]: # This includes a second order term in shinethrough*(first orbit loss) - current_drive_variables.f_p_beam_orbit_loss = min( - 0.999, current_drive_variables.f_p_beam_orbit_loss + self.data.current_drive.f_p_beam_orbit_loss = min( + 0.999, self.data.current_drive.f_p_beam_orbit_loss ) # Should never be needed # Shinethrough power (atoms that are not ionised) [MW]: - current_drive_variables.p_beam_shine_through_mw = ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw - ) * (current_drive_variables.f_p_beam_shine_through) + self.data.current_drive.p_beam_shine_through_mw = ( + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw + ) * (self.data.current_drive.f_p_beam_shine_through) # First orbit loss - current_drive_variables.p_beam_orbit_loss_mw = ( - current_drive_variables.f_p_beam_orbit_loss + self.data.current_drive.p_beam_orbit_loss_mw = ( + self.data.current_drive.f_p_beam_orbit_loss * ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw - - current_drive_variables.p_beam_shine_through_mw + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw + - self.data.current_drive.p_beam_shine_through_mw ) ) # Power deposited - current_drive_variables.p_beam_plasma_coupled_mw = ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw - - current_drive_variables.p_beam_shine_through_mw - - current_drive_variables.p_beam_orbit_loss_mw + self.data.current_drive.p_beam_plasma_coupled_mw = ( + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw + - self.data.current_drive.p_beam_shine_through_mw + - self.data.current_drive.p_beam_orbit_loss_mw ) p_hcd_secondary_ions_mw = ( - current_drive_variables.p_beam_plasma_coupled_mw - * current_drive_variables.f_p_beam_injected_ions + self.data.current_drive.p_beam_plasma_coupled_mw + * self.data.current_drive.f_p_beam_injected_ions ) p_hcd_secondary_electrons_mw = ( - current_drive_variables.p_beam_plasma_coupled_mw - * (1.0e0 - current_drive_variables.f_p_beam_injected_ions) + self.data.current_drive.p_beam_plasma_coupled_mw + * (1.0e0 - self.data.current_drive.f_p_beam_injected_ions) ) - current_drive_variables.pwpnb = ( + self.data.current_drive.pwpnb = ( ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw ) - / current_drive_variables.eta_beam_injector_wall_plug + / self.data.current_drive.eta_beam_injector_wall_plug ) # neutral beam wall plug power heat_transport_variables.p_hcd_secondary_electric_mw = ( - current_drive_variables.pwpnb + self.data.current_drive.pwpnb ) - current_drive_variables.eta_hcd_secondary_injector_wall_plug = ( - current_drive_variables.eta_beam_injector_wall_plug + self.data.current_drive.eta_hcd_secondary_injector_wall_plug = ( + self.data.current_drive.eta_beam_injector_wall_plug ) - current_drive_variables.c_beam_total = ( + self.data.current_drive.c_beam_total = ( 1.0e-3 * ( ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw ) * 1.0e6 ) - / current_drive_variables.e_beam_kev + / self.data.current_drive.e_beam_kev ) # Neutral beam current (A) - current_drive_variables.p_hcd_beam_injected_total_mw += ( - current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw + self.data.current_drive.p_hcd_beam_injected_total_mw += ( + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw ) # ========================================================== @@ -2052,30 +2057,30 @@ def current_drive(self): # Lower hybrid cases if primary_cdm.method == CurrentDriveMethodType.LOWER_HYBRID: p_hcd_primary_electrons_mw = ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw ) - current_drive_variables.p_hcd_lowhyb_injected_total_mw += ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw + self.data.current_drive.p_hcd_lowhyb_injected_total_mw += ( + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw ) # Wall plug power heat_transport_variables.p_hcd_primary_electric_mw = ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw - ) / current_drive_variables.eta_lowhyb_injector_wall_plug + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw + ) / self.data.current_drive.eta_lowhyb_injector_wall_plug # Wall plug to injector efficiency - current_drive_variables.eta_hcd_primary_injector_wall_plug = ( - current_drive_variables.eta_lowhyb_injector_wall_plug + self.data.current_drive.eta_hcd_primary_injector_wall_plug = ( + self.data.current_drive.eta_lowhyb_injector_wall_plug ) # Wall plug power - current_drive_variables.p_hcd_lowhyb_electric_mw = ( - current_drive_variables.p_hcd_lowhyb_injected_total_mw - / current_drive_variables.eta_lowhyb_injector_wall_plug + self.data.current_drive.p_hcd_lowhyb_electric_mw = ( + self.data.current_drive.p_hcd_lowhyb_injected_total_mw + / self.data.current_drive.eta_lowhyb_injector_wall_plug ) # =========================================================== @@ -2083,30 +2088,30 @@ def current_drive(self): # Ion cyclotron cases if primary_cdm.method == CurrentDriveMethodType.ION_CYCLOTRON: p_hcd_primary_ions_mw = ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw ) # Wall plug power heat_transport_variables.p_hcd_primary_electric_mw = ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw - ) / current_drive_variables.eta_icrh_injector_wall_plug + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw + ) / self.data.current_drive.eta_icrh_injector_wall_plug # Wall plug to injector efficiency - current_drive_variables.eta_hcd_primary_injector_wall_plug = ( - current_drive_variables.eta_icrh_injector_wall_plug + self.data.current_drive.eta_hcd_primary_injector_wall_plug = ( + self.data.current_drive.eta_icrh_injector_wall_plug ) - current_drive_variables.p_hcd_icrh_injected_total_mw += ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw + self.data.current_drive.p_hcd_icrh_injected_total_mw += ( + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw ) # Wall plug power - current_drive_variables.p_hcd_icrh_electric_mw = ( - current_drive_variables.p_hcd_icrh_injected_total_mw - / current_drive_variables.eta_icrh_injector_wall_plug + self.data.current_drive.p_hcd_icrh_electric_mw = ( + self.data.current_drive.p_hcd_icrh_injected_total_mw + / self.data.current_drive.eta_icrh_injector_wall_plug ) # =========================================================== @@ -2115,29 +2120,29 @@ def current_drive(self): if primary_cdm.method == CurrentDriveMethodType.ELECTRON_CYCLOTRON: p_hcd_primary_electrons_mw = ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw ) # Wall plug to injector efficiency heat_transport_variables.p_hcd_primary_electric_mw = ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw - ) / current_drive_variables.eta_ecrh_injector_wall_plug + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw + ) / self.data.current_drive.eta_ecrh_injector_wall_plug - current_drive_variables.eta_hcd_primary_injector_wall_plug = ( - current_drive_variables.eta_ecrh_injector_wall_plug + self.data.current_drive.eta_hcd_primary_injector_wall_plug = ( + self.data.current_drive.eta_ecrh_injector_wall_plug ) - current_drive_variables.p_hcd_ecrh_injected_total_mw += ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw + self.data.current_drive.p_hcd_ecrh_injected_total_mw += ( + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw ) # Wall plug power - current_drive_variables.p_hcd_ecrh_electric_mw = ( - current_drive_variables.p_hcd_ecrh_injected_total_mw - / current_drive_variables.eta_ecrh_injector_wall_plug + self.data.current_drive.p_hcd_ecrh_electric_mw = ( + self.data.current_drive.p_hcd_ecrh_injected_total_mw + / self.data.current_drive.eta_ecrh_injector_wall_plug ) # =========================================================== @@ -2146,29 +2151,29 @@ def current_drive(self): if primary_cdm.method == CurrentDriveMethodType.ELECTRON_BERNSTEIN: p_hcd_primary_electrons_mw = ( - current_drive_variables.p_ebw_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw + self.data.current_drive.p_ebw_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw ) # Wall plug to injector efficiency heat_transport_variables.p_hcd_primary_electric_mw = ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw - ) / current_drive_variables.eta_ebw_injector_wall_plug + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw + ) / self.data.current_drive.eta_ebw_injector_wall_plug - current_drive_variables.eta_hcd_primary_injector_wall_plug = ( - current_drive_variables.eta_ebw_injector_wall_plug + self.data.current_drive.eta_hcd_primary_injector_wall_plug = ( + self.data.current_drive.eta_ebw_injector_wall_plug ) - current_drive_variables.p_hcd_ebw_injected_total_mw += ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw + self.data.current_drive.p_hcd_ebw_injected_total_mw += ( + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw ) # Wall plug power - current_drive_variables.p_hcd_ebw_electric_mw = ( - current_drive_variables.p_ebw_injected_mw - / current_drive_variables.eta_ebw_injector_wall_plug + self.data.current_drive.p_hcd_ebw_electric_mw = ( + self.data.current_drive.p_ebw_injected_mw + / self.data.current_drive.eta_ebw_injector_wall_plug ) # =========================================================== @@ -2177,96 +2182,96 @@ def current_drive(self): # Account for first orbit losses # (power due to particles that are ionised but not thermalised) [MW]: # This includes a second order term in shinethrough*(first orbit loss) - current_drive_variables.f_p_beam_orbit_loss = min( - 0.999, current_drive_variables.f_p_beam_orbit_loss + self.data.current_drive.f_p_beam_orbit_loss = min( + 0.999, self.data.current_drive.f_p_beam_orbit_loss ) # Should never be needed # Shinethrough power (atoms that are not ionised) [MW]: - current_drive_variables.p_beam_shine_through_mw = ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw - ) * (current_drive_variables.f_p_beam_shine_through) + self.data.current_drive.p_beam_shine_through_mw = ( + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw + ) * (self.data.current_drive.f_p_beam_shine_through) # First orbit loss - current_drive_variables.p_beam_orbit_loss_mw = ( - current_drive_variables.f_p_beam_orbit_loss + self.data.current_drive.p_beam_orbit_loss_mw = ( + self.data.current_drive.f_p_beam_orbit_loss * ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw - - current_drive_variables.p_beam_shine_through_mw + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw + - self.data.current_drive.p_beam_shine_through_mw ) ) # Power deposited - current_drive_variables.p_beam_plasma_coupled_mw = ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw - - current_drive_variables.p_beam_shine_through_mw - - current_drive_variables.p_beam_orbit_loss_mw + self.data.current_drive.p_beam_plasma_coupled_mw = ( + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw + - self.data.current_drive.p_beam_shine_through_mw + - self.data.current_drive.p_beam_orbit_loss_mw ) p_hcd_primary_ions_mw = ( - current_drive_variables.p_beam_plasma_coupled_mw - * current_drive_variables.f_p_beam_injected_ions + self.data.current_drive.p_beam_plasma_coupled_mw + * self.data.current_drive.f_p_beam_injected_ions ) p_hcd_primary_electrons_mw = ( - current_drive_variables.p_beam_plasma_coupled_mw - * (1.0e0 - current_drive_variables.f_p_beam_injected_ions) + self.data.current_drive.p_beam_plasma_coupled_mw + * (1.0e0 - self.data.current_drive.f_p_beam_injected_ions) ) - current_drive_variables.pwpnb = ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw - ) / current_drive_variables.eta_beam_injector_wall_plug + self.data.current_drive.pwpnb = ( + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw + ) / self.data.current_drive.eta_beam_injector_wall_plug # Neutral beam wall plug power heat_transport_variables.p_hcd_primary_electric_mw = ( - current_drive_variables.pwpnb + self.data.current_drive.pwpnb ) - current_drive_variables.eta_hcd_primary_injector_wall_plug = ( - current_drive_variables.eta_beam_injector_wall_plug + self.data.current_drive.eta_hcd_primary_injector_wall_plug = ( + self.data.current_drive.eta_beam_injector_wall_plug ) - current_drive_variables.c_beam_total = ( + self.data.current_drive.c_beam_total = ( 1.0e-3 * ( ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw ) * 1.0e6 ) - / current_drive_variables.e_beam_kev + / self.data.current_drive.e_beam_kev ) # Neutral beam current (A) - current_drive_variables.p_hcd_beam_injected_total_mw += ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw + self.data.current_drive.p_hcd_beam_injected_total_mw += ( + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw ) # =========================================================== # Total injected power that contributed to heating - current_drive_variables.p_hcd_injected_total_mw = ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_primary_extra_heat_mw - + current_drive_variables.p_hcd_secondary_injected_mw - + current_drive_variables.p_hcd_secondary_extra_heat_mw + self.data.current_drive.p_hcd_injected_total_mw = ( + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_primary_extra_heat_mw + + self.data.current_drive.p_hcd_secondary_injected_mw + + self.data.current_drive.p_hcd_secondary_extra_heat_mw ) # Total injected power that contributed to current drive - current_drive_variables.p_hcd_injected_current_total_mw = ( - current_drive_variables.p_hcd_primary_injected_mw - + current_drive_variables.p_hcd_secondary_injected_mw + self.data.current_drive.p_hcd_injected_current_total_mw = ( + self.data.current_drive.p_hcd_primary_injected_mw + + self.data.current_drive.p_hcd_secondary_injected_mw ) # Total injected power given to electrons - current_drive_variables.p_hcd_injected_electrons_mw = ( + self.data.current_drive.p_hcd_injected_electrons_mw = ( p_hcd_primary_electrons_mw + p_hcd_secondary_electrons_mw ) # Total injected power given to ions - current_drive_variables.p_hcd_injected_ions_mw = ( + self.data.current_drive.p_hcd_injected_ions_mw = ( p_hcd_primary_ions_mw + p_hcd_secondary_ions_mw ) @@ -2281,11 +2286,11 @@ def current_drive(self): heat_transport_variables.p_hcd_electric_total_mw = 0.0e0 # Ratio of fusion to input (injection+ohmic) power - current_drive_variables.big_q_plasma = ( + self.data.current_drive.big_q_plasma = ( physics_variables.p_fusion_total_mw / ( - current_drive_variables.p_hcd_injected_total_mw - + current_drive_variables.p_beam_orbit_loss_mw + self.data.current_drive.p_hcd_injected_total_mw + + self.data.current_drive.p_beam_orbit_loss_mw + physics_variables.p_plasma_ohmic_mw ) ) @@ -2398,12 +2403,12 @@ def output(self): self.outfile, "Fusion gain factor (Qₚₗₐₛₘₐ)", "(big_q_plasma)", - current_drive_variables.big_q_plasma, + self.data.current_drive.big_q_plasma, "OP ", ) po.oblnkl(self.outfile) - if current_drive_variables.i_hcd_calculations == 0: + if self.data.current_drive.i_hcd_calculations == 0: po.ocmmnt(self.outfile, "No current drive used") po.oblnkl(self.outfile) return @@ -2412,12 +2417,12 @@ def output(self): self.outfile, "Primary current drive efficiency model", "(i_hcd_primary)", - current_drive_variables.i_hcd_primary, + self.data.current_drive.i_hcd_primary, ) po.ocmmnt( self.outfile, - f"{CurrentDriveModel(current_drive_variables.i_hcd_primary).full_name}", + f"{CurrentDriveModel(self.data.current_drive.i_hcd_primary).full_name}", ) po.oblnkl(self.outfile) @@ -2426,69 +2431,69 @@ def output(self): self.outfile, "Absolute current drive efficiency of primary system (η) [A/W]", "(eta_cd_hcd_primary)", - current_drive_variables.eta_cd_hcd_primary, + self.data.current_drive.eta_cd_hcd_primary, "OP ", ) po.ovarre( self.outfile, "Normalised current drive efficiency of primary system (γ) [10²⁰ A / Wm²]", # noqa: RUF001 "(eta_cd_norm_hcd_primary)", - current_drive_variables.eta_cd_norm_hcd_primary, + self.data.current_drive.eta_cd_norm_hcd_primary, "OP ", ) po.ovarre( self.outfile, "Dimensionless current drive efficiency of primary system (ζ)", "(eta_cd_dimensionless_hcd_primary)", - current_drive_variables.eta_cd_dimensionless_hcd_primary, + self.data.current_drive.eta_cd_dimensionless_hcd_primary, "OP ", ) po.ovarre( self.mfile, "EBW coupling efficiency", "(xi_ebw)", - current_drive_variables.xi_ebw, + self.data.current_drive.xi_ebw, ) - if current_drive_variables.i_hcd_primary == 10: + if self.data.current_drive.i_hcd_primary == 10: po.ovarre( self.outfile, "ECRH plasma heating efficiency", "(eta_cd_norm_ecrh)", - current_drive_variables.eta_cd_norm_ecrh, + self.data.current_drive.eta_cd_norm_ecrh, ) po.ovarre( self.outfile, "Power injected into plasma by primary system for current drive (MW)", "(p_hcd_primary_injected_mw)", - current_drive_variables.p_hcd_primary_injected_mw, + self.data.current_drive.p_hcd_primary_injected_mw, "OP ", ) po.ovarre( self.outfile, "Extra power injected into plasma by primary system (MW)", "(p_hcd_primary_extra_heat_mw)", - current_drive_variables.p_hcd_primary_extra_heat_mw, + self.data.current_drive.p_hcd_primary_extra_heat_mw, "OP ", ) po.ovarre( self.outfile, "Current driven in plasma by primary system (A)", "(c_hcd_primary_driven)", - current_drive_variables.c_hcd_primary_driven, + self.data.current_drive.c_hcd_primary_driven, "OP ", ) po.ovarre( self.outfile, "Fraction of plasma current driven by primary system", "(f_c_plasma_hcd_primary)", - current_drive_variables.f_c_plasma_hcd_primary, + self.data.current_drive.f_c_plasma_hcd_primary, "OP ", ) po.ovarre( self.outfile, "Wall plug to injector efficiency of primary system", "(eta_hcd_primary_injector_wall_plug)", - current_drive_variables.eta_hcd_primary_injector_wall_plug, + self.data.current_drive.eta_hcd_primary_injector_wall_plug, "IP ", ) po.ovarre( @@ -2499,32 +2504,32 @@ def output(self): "OP ", ) - if current_drive_variables.i_hcd_primary in {12, 13}: + if self.data.current_drive.i_hcd_primary in {12, 13}: po.oblnkl(self.outfile) po.ovarre( self.outfile, "ECRH / EBW harmonic number", "(n_ecrh_harmonic)", - current_drive_variables.n_ecrh_harmonic, + self.data.current_drive.n_ecrh_harmonic, ) po.ovarre( self.outfile, "EBW coupling efficiency", "(xi_ebw)", - current_drive_variables.xi_ebw, + self.data.current_drive.xi_ebw, ) - if current_drive_variables.i_hcd_primary == 13: + if self.data.current_drive.i_hcd_primary == 13: po.ovarin( self.outfile, "Electron cyclotron cutoff wave mode switch", "(i_ecrh_wave_mode)", - current_drive_variables.i_ecrh_wave_mode, + self.data.current_drive.i_ecrh_wave_mode, ) po.oblnkl(self.outfile) if ( - CurrentDriveModel(current_drive_variables.i_hcd_primary).method + CurrentDriveModel(self.data.current_drive.i_hcd_primary).method == CurrentDriveMethodType.NEUTRAL_BEAM ): po.oblnkl(self.outfile) @@ -2535,17 +2540,17 @@ def output(self): self.outfile, "Neutral beam energy (keV)", "(e_beam_kev)", - current_drive_variables.e_beam_kev, + self.data.current_drive.e_beam_kev, ) if ( - CurrentDriveModel(current_drive_variables.i_hcd_primary).method + CurrentDriveModel(self.data.current_drive.i_hcd_primary).method == CurrentDriveMethodType.NEUTRAL_BEAM ): po.ovarre( self.outfile, "Neutral beam current (A)", "(c_beam_total)", - current_drive_variables.c_beam_total, + self.data.current_drive.c_beam_total, "OP ", ) @@ -2553,86 +2558,86 @@ def output(self): self.outfile, "Neutral beam wall plug efficiency", "(eta_beam_injector_wall_plug)", - current_drive_variables.eta_beam_injector_wall_plug, + self.data.current_drive.eta_beam_injector_wall_plug, ) po.ovarre( self.outfile, "Beam decay lengths to centre", "(n_beam_decay_lengths_core)", - current_drive_variables.n_beam_decay_lengths_core, + self.data.current_drive.n_beam_decay_lengths_core, "OP ", ) po.ovarre( self.outfile, "Beam shine-through fraction", "(f_p_beam_shine_through)", - current_drive_variables.f_p_beam_shine_through, + self.data.current_drive.f_p_beam_shine_through, "OP ", ) if ( - CurrentDriveModel(current_drive_variables.i_hcd_primary).method + CurrentDriveModel(self.data.current_drive.i_hcd_primary).method == CurrentDriveMethodType.NEUTRAL_BEAM ): po.ovarrf( self.outfile, "Beam first orbit loss power (MW)", "(p_beam_orbit_loss_mw)", - current_drive_variables.p_beam_orbit_loss_mw, + self.data.current_drive.p_beam_orbit_loss_mw, "OP ", ) po.ovarrf( self.outfile, "Beam shine-through power [MW]", "(p_beam_shine_through_mw)", - current_drive_variables.p_beam_shine_through_mw, + self.data.current_drive.p_beam_shine_through_mw, "OP ", ) po.ovarrf( self.outfile, "Maximum allowable beam power (MW)", "(p_hcd_injected_max)", - current_drive_variables.p_hcd_injected_max, + self.data.current_drive.p_hcd_injected_max, ) po.oblnkl(self.outfile) po.ovarrf( self.outfile, "Beam power entering vacuum vessel (MW)", "(p_beam_injected_mw)", - current_drive_variables.p_beam_injected_mw, + self.data.current_drive.p_beam_injected_mw, "OP ", ) po.ovarre( self.outfile, "Fraction of beam energy to ions", "(f_p_beam_injected_ions)", - current_drive_variables.f_p_beam_injected_ions, + self.data.current_drive.f_p_beam_injected_ions, "OP ", ) po.ovarre( self.outfile, "Beam duct shielding thickness (m)", "(dx_beam_shield)", - current_drive_variables.dx_beam_shield, + self.data.current_drive.dx_beam_shield, ) po.ovarre( self.outfile, "Beam tangency radius / Plasma major radius", "(f_radius_beam_tangency_rmajor)", - current_drive_variables.f_radius_beam_tangency_rmajor, + self.data.current_drive.f_radius_beam_tangency_rmajor, ) po.ovarre( self.outfile, "Beam centreline tangency radius (m)", "(radius_beam_tangency)", - current_drive_variables.radius_beam_tangency, + self.data.current_drive.radius_beam_tangency, "OP ", ) po.ovarre( self.outfile, "Maximum possible tangency radius (m)", "(radius_beam_tangency_max)", - current_drive_variables.radius_beam_tangency_max, + self.data.current_drive.radius_beam_tangency_max, "OP ", ) @@ -2642,12 +2647,12 @@ def output(self): self.outfile, "Secondary current drive efficiency model", "(i_hcd_secondary)", - current_drive_variables.i_hcd_secondary, + self.data.current_drive.i_hcd_secondary, ) po.ocmmnt( self.outfile, - f"{CurrentDriveModel(current_drive_variables.i_hcd_secondary).full_name}", + f"{CurrentDriveModel(self.data.current_drive.i_hcd_secondary).full_name}", ) po.oblnkl(self.outfile) @@ -2655,64 +2660,64 @@ def output(self): self.outfile, "Absolute current drive efficiency of secondary system (η) [A/W]", "(eta_cd_hcd_secondary)", - current_drive_variables.eta_cd_hcd_secondary, + self.data.current_drive.eta_cd_hcd_secondary, "OP ", ) po.ovarre( self.outfile, "Normalised current drive efficiency of secondary system (γ) [10²⁰ A / Wm²]", # noqa: RUF001 "(eta_cd_norm_hcd_secondary)", - current_drive_variables.eta_cd_norm_hcd_secondary, + self.data.current_drive.eta_cd_norm_hcd_secondary, "OP ", ) po.ovarre( self.outfile, "Dimensionless current drive efficiency of secondary system (ζ)", "(eta_cd_dimensionless_hcd_secondary)", - current_drive_variables.eta_cd_dimensionless_hcd_secondary, + self.data.current_drive.eta_cd_dimensionless_hcd_secondary, "OP ", ) - if current_drive_variables.i_hcd_secondary == 10: + if self.data.current_drive.i_hcd_secondary == 10: po.ovarre( self.outfile, "ECRH plasma heating efficiency", "(eta_cd_norm_ecrh)", - current_drive_variables.eta_cd_norm_ecrh, + self.data.current_drive.eta_cd_norm_ecrh, ) po.ovarre( self.outfile, "Power injected into plasma by secondary system (MW)", "(p_hcd_secondary_injected_mw)", - current_drive_variables.p_hcd_secondary_injected_mw, + self.data.current_drive.p_hcd_secondary_injected_mw, "OP ", ) po.ovarre( self.outfile, "Extra power injected into plasma by secondary system (MW)", "(p_hcd_secondary_extra_heat_mw)", - current_drive_variables.p_hcd_secondary_extra_heat_mw, + self.data.current_drive.p_hcd_secondary_extra_heat_mw, "OP ", ) po.ovarre( self.outfile, "Current driven in plasma by secondary system (A)", "(c_hcd_secondary_driven)", - current_drive_variables.c_hcd_secondary_driven, + self.data.current_drive.c_hcd_secondary_driven, "OP ", ) po.ovarre( self.outfile, "Fraction of plasma current driven by secondary system", "(f_c_plasma_hcd_secondary)", - current_drive_variables.f_c_plasma_hcd_secondary, + self.data.current_drive.f_c_plasma_hcd_secondary, "OP ", ) po.ovarre( self.outfile, "Wall plug to injector efficiency of secondary system", "(eta_hcd_secondary_injector_wall_plug)", - current_drive_variables.eta_hcd_secondary_injector_wall_plug, + self.data.current_drive.eta_hcd_secondary_injector_wall_plug, "IP ", ) po.ovarre( @@ -2726,7 +2731,7 @@ def output(self): po.oblnkl(self.outfile) if ( - CurrentDriveModel(current_drive_variables.i_hcd_secondary).method + CurrentDriveModel(self.data.current_drive.i_hcd_secondary).method == CurrentDriveMethodType.NEUTRAL_BEAM ): po.oblnkl(self.outfile) @@ -2737,17 +2742,17 @@ def output(self): self.outfile, "Neutral beam energy (keV)", "(e_beam_kev)", - current_drive_variables.e_beam_kev, + self.data.current_drive.e_beam_kev, ) if ( - CurrentDriveModel(current_drive_variables.i_hcd_primary).method + CurrentDriveModel(self.data.current_drive.i_hcd_primary).method == CurrentDriveMethodType.NEUTRAL_BEAM ): po.ovarre( self.outfile, "Neutral beam current (A)", "(c_beam_total)", - current_drive_variables.c_beam_total, + self.data.current_drive.c_beam_total, "OP ", ) @@ -2755,86 +2760,86 @@ def output(self): self.outfile, "Neutral beam wall plug efficiency", "(eta_beam_injector_wall_plug)", - current_drive_variables.eta_beam_injector_wall_plug, + self.data.current_drive.eta_beam_injector_wall_plug, ) po.ovarre( self.outfile, "Beam decay lengths to centre", "(n_beam_decay_lengths_core)", - current_drive_variables.n_beam_decay_lengths_core, + self.data.current_drive.n_beam_decay_lengths_core, "OP ", ) po.ovarre( self.outfile, "Beam shine-through fraction", "(f_p_beam_shine_through)", - current_drive_variables.f_p_beam_shine_through, + self.data.current_drive.f_p_beam_shine_through, "OP ", ) if ( - CurrentDriveModel(current_drive_variables.i_hcd_primary).method + CurrentDriveModel(self.data.current_drive.i_hcd_primary).method == CurrentDriveMethodType.NEUTRAL_BEAM ): po.ovarrf( self.outfile, "Beam first orbit loss power (MW)", "(p_beam_orbit_loss_mw)", - current_drive_variables.p_beam_orbit_loss_mw, + self.data.current_drive.p_beam_orbit_loss_mw, "OP ", ) po.ovarrf( self.outfile, "Beam shine-through power [MW]", "(p_beam_shine_through_mw)", - current_drive_variables.p_beam_shine_through_mw, + self.data.current_drive.p_beam_shine_through_mw, "OP ", ) po.ovarrf( self.outfile, "Maximum allowable beam power (MW)", "(p_hcd_injected_max)", - current_drive_variables.p_hcd_injected_max, + self.data.current_drive.p_hcd_injected_max, ) po.oblnkl(self.outfile) po.ovarrf( self.outfile, "Beam power entering vacuum vessel (MW)", "(p_beam_injected_mw)", - current_drive_variables.p_beam_injected_mw, + self.data.current_drive.p_beam_injected_mw, "OP ", ) po.ovarre( self.outfile, "Fraction of beam energy to ions", "(f_p_beam_injected_ions)", - current_drive_variables.f_p_beam_injected_ions, + self.data.current_drive.f_p_beam_injected_ions, "OP ", ) po.ovarre( self.outfile, "Beam duct shielding thickness (m)", "(dx_beam_shield)", - current_drive_variables.dx_beam_shield, + self.data.current_drive.dx_beam_shield, ) po.ovarre( self.outfile, "Beam tangency radius / Plasma major radius", "(f_radius_beam_tangency_rmajor)", - current_drive_variables.f_radius_beam_tangency_rmajor, + self.data.current_drive.f_radius_beam_tangency_rmajor, ) po.ovarre( self.outfile, "Beam centreline tangency radius (m)", "(radius_beam_tangency)", - current_drive_variables.radius_beam_tangency, + self.data.current_drive.radius_beam_tangency, "OP ", ) po.ovarre( self.outfile, "Maximum possible tangency radius (m)", "(radius_beam_tangency_max)", - current_drive_variables.radius_beam_tangency_max, + self.data.current_drive.radius_beam_tangency_max, "OP ", ) @@ -2846,27 +2851,27 @@ def output(self): self.outfile, "Total injected heating power that drove plasma current (MW)", "(p_hcd_injected_current_total_mw)", - current_drive_variables.p_hcd_injected_current_total_mw, + self.data.current_drive.p_hcd_injected_current_total_mw, ) po.ovarre( self.outfile, "Total injected heating power across all systems (MW)", "(p_hcd_injected_total_mw)", - current_drive_variables.p_hcd_injected_total_mw, + self.data.current_drive.p_hcd_injected_total_mw, "OP ", ) po.ovarre( self.outfile, "Total injected heating power given to the electrons (MW)", "(p_hcd_injected_electrons_mw)", - current_drive_variables.p_hcd_injected_electrons_mw, + self.data.current_drive.p_hcd_injected_electrons_mw, "OP ", ) po.ovarre( self.outfile, "Total injected heating power given to the ions (MW)", "(p_hcd_injected_ions_mw)", - current_drive_variables.p_hcd_injected_ions_mw, + self.data.current_drive.p_hcd_injected_ions_mw, "OP ", ) @@ -2874,7 +2879,7 @@ def output(self): self.outfile, "Upper limit on total plasma injected power (MW)", "(p_hcd_injected_max)", - current_drive_variables.p_hcd_injected_max, + self.data.current_drive.p_hcd_injected_max, "OP ", ) @@ -2884,35 +2889,35 @@ def output(self): self.outfile, "Injected power into plasma from lower hybrid systems (MW)", "(p_hcd_lowhyb_injected_total_mw)", - current_drive_variables.p_hcd_lowhyb_injected_total_mw, + self.data.current_drive.p_hcd_lowhyb_injected_total_mw, "OP ", ) po.ovarre( self.outfile, "Injected power into plasma from ion cyclotron systems (MW)", "(p_hcd_icrh_injected_total_mw)", - current_drive_variables.p_hcd_icrh_injected_total_mw, + self.data.current_drive.p_hcd_icrh_injected_total_mw, "OP ", ) po.ovarre( self.outfile, "Injected power into plasma from electron cyclotron systems (MW)", "(p_hcd_ecrh_injected_total_mw)", - current_drive_variables.p_hcd_ecrh_injected_total_mw, + self.data.current_drive.p_hcd_ecrh_injected_total_mw, "OP ", ) po.ovarre( self.outfile, "Injected power into plasma from neutral beam systems (MW)", "(p_hcd_beam_injected_total_mw)", - current_drive_variables.p_hcd_beam_injected_total_mw, + self.data.current_drive.p_hcd_beam_injected_total_mw, "OP ", ) po.ovarre( self.outfile, "Injected power into plasma from lower hybrid systems (MW)", "(p_hcd_ebw_injected_total_mw)", - current_drive_variables.p_hcd_ebw_injected_total_mw, + self.data.current_drive.p_hcd_ebw_injected_total_mw, "OP ", ) @@ -2921,21 +2926,21 @@ def output(self): self.outfile, "Bootstrap fraction", "(f_c_plasma_bootstrap)", - current_drive_variables.f_c_plasma_bootstrap, + self.data.current_drive.f_c_plasma_bootstrap, "OP ", ) po.ovarrf( self.outfile, "Diamagnetic fraction", "(f_c_plasma_diamagnetic)", - current_drive_variables.f_c_plasma_diamagnetic, + self.data.current_drive.f_c_plasma_diamagnetic, "OP ", ) po.ovarrf( self.outfile, "Pfirsch-Schlueter fraction", "(f_c_plasma_pfirsch_schluter)", - current_drive_variables.f_c_plasma_pfirsch_schluter, + self.data.current_drive.f_c_plasma_pfirsch_schluter, "OP ", ) po.ovarrf( @@ -2964,8 +2969,8 @@ def output(self): if ( abs( - current_drive_variables.f_c_plasma_bootstrap - - current_drive_variables.f_c_plasma_bootstrap_max + self.data.current_drive.f_c_plasma_bootstrap + - self.data.current_drive.f_c_plasma_bootstrap_max ) < 1.0e-8 ): diff --git a/process/models/physics/density_limit.py b/process/models/physics/density_limit.py index 503e38df8..260601d9c 100644 --- a/process/models/physics/density_limit.py +++ b/process/models/physics/density_limit.py @@ -14,8 +14,8 @@ from process.core import constants from process.core import process_output as po from process.core.exceptions import ProcessValueError +from process.core.model import Model from process.data_structure import ( - current_drive_variables, divertor_variables, physics_variables, ) @@ -61,7 +61,7 @@ def full_name(self): return self._full_name_ -class PlasmaDensityLimit: +class PlasmaDensityLimit(Model): """Class to hold plasma density limit calculations for plasma processing.""" def __init__(self): @@ -80,7 +80,7 @@ def run(self): b_plasma_toroidal_on_axis=physics_variables.b_plasma_toroidal_on_axis, i_density_limit=physics_variables.i_density_limit, p_plasma_separatrix_mw=physics_variables.p_plasma_separatrix_mw, - p_hcd_injected_total_mw=current_drive_variables.p_hcd_injected_total_mw, + p_hcd_injected_total_mw=self.data.current_drive.p_hcd_injected_total_mw, plasma_current=physics_variables.plasma_current, prn1=divertor_variables.prn1, qcyl=physics_variables.qstar, @@ -620,7 +620,7 @@ def calculate_density_limit( i_density_limit - 1 ] - def output_density_limit_information(self): + def output(self): """Output density limit information to file.""" po.oheadr(self.outfile, "Plasma density limits") po.ovarin( diff --git a/process/models/physics/physics.py b/process/models/physics/physics.py index 0379e2af3..cde24511a 100644 --- a/process/models/physics/physics.py +++ b/process/models/physics/physics.py @@ -18,7 +18,6 @@ from process.core.exceptions import ProcessValueError from process.core.model import Model from process.data_structure import ( - current_drive_variables, divertor_variables, impurity_radiation_module, numerics, @@ -506,32 +505,32 @@ def run(self): # ***************************** # # Pfirsch-Schlüter scaling for diamagnetic current - current_drive_variables.f_c_plasma_pfirsch_schluter_scene = ps_fraction_scene( + self.data.current_drive.f_c_plasma_pfirsch_schluter_scene = ps_fraction_scene( physics_variables.beta_total_vol_avg ) if physics_variables.i_pfirsch_schluter_current == 1: - current_drive_variables.f_c_plasma_pfirsch_schluter = ( - current_drive_variables.f_c_plasma_pfirsch_schluter_scene + self.data.current_drive.f_c_plasma_pfirsch_schluter = ( + self.data.current_drive.f_c_plasma_pfirsch_schluter_scene ) self.plasma_bootstrap_current.run() physics_variables.err242 = 0 if ( - current_drive_variables.f_c_plasma_bootstrap - > current_drive_variables.f_c_plasma_bootstrap_max + self.data.current_drive.f_c_plasma_bootstrap + > self.data.current_drive.f_c_plasma_bootstrap_max ) and physics_variables.i_bootstrap_current != 0: - current_drive_variables.f_c_plasma_bootstrap = min( - current_drive_variables.f_c_plasma_bootstrap, - current_drive_variables.f_c_plasma_bootstrap_max, + self.data.current_drive.f_c_plasma_bootstrap = min( + self.data.current_drive.f_c_plasma_bootstrap, + self.data.current_drive.f_c_plasma_bootstrap_max, ) physics_variables.err242 = 1 - current_drive_variables.f_c_plasma_internal = ( - current_drive_variables.f_c_plasma_bootstrap - + current_drive_variables.f_c_plasma_diamagnetic - + current_drive_variables.f_c_plasma_pfirsch_schluter + self.data.current_drive.f_c_plasma_internal = ( + self.data.current_drive.f_c_plasma_bootstrap + + self.data.current_drive.f_c_plasma_diamagnetic + + self.data.current_drive.f_c_plasma_pfirsch_schluter ) # Plasma driven current fraction (Bootstrap + Diamagnetic @@ -541,11 +540,11 @@ def run(self): # the current drive proportion) physics_variables.err243 = 0 if ( - current_drive_variables.f_c_plasma_internal + self.data.current_drive.f_c_plasma_internal > physics_variables.f_c_plasma_non_inductive ): - current_drive_variables.f_c_plasma_internal = min( - current_drive_variables.f_c_plasma_internal, + self.data.current_drive.f_c_plasma_internal = min( + self.data.current_drive.f_c_plasma_internal, physics_variables.f_c_plasma_non_inductive, ) physics_variables.err243 = 1 @@ -557,12 +556,12 @@ def run(self): # Fraction of plasma current produced by auxiliary current drive physics_variables.f_c_plasma_auxiliary = ( physics_variables.f_c_plasma_non_inductive - - current_drive_variables.f_c_plasma_internal + - self.data.current_drive.f_c_plasma_internal ) # Auxiliary current drive power calculations - if current_drive_variables.i_hcd_calculations != 0: + if self.data.current_drive.i_hcd_calculations != 0: self.current_drive.current_drive() # ***************************** # @@ -591,7 +590,7 @@ def run(self): # Calculate neutral beam slowing down effects # If ignited, then ignore beam fusion effects - if (current_drive_variables.c_beam_total != 0.0e0) and ( # noqa: RUF069 + if (self.data.current_drive.c_beam_total != 0.0e0) and ( # noqa: RUF069 physics_variables.i_plasma_ignited == 0 ): ( @@ -602,14 +601,14 @@ def run(self): physics_variables.beamfus0, physics_variables.betbm0, physics_variables.b_plasma_total, - current_drive_variables.c_beam_total, + self.data.current_drive.c_beam_total, physics_variables.nd_plasma_electrons_vol_avg, physics_variables.nd_plasma_fuel_ions_vol_avg, physics_variables.dlamie, - current_drive_variables.e_beam_kev, + self.data.current_drive.e_beam_kev, physics_variables.f_plasma_fuel_deuterium, physics_variables.f_plasma_fuel_tritium, - current_drive_variables.f_beam_tritium, + self.data.current_drive.f_beam_tritium, physics_variables.temp_plasma_electron_density_weighted_kev, physics_variables.vol_plasma, physics_variables.n_charge_plasma_effective_mass_weighted_vol_avg, @@ -758,7 +757,7 @@ def run(self): # i.e. excludes neutrons and radiation, and also NBI orbit loss power, # which is assumed to be absorbed by the first wall pinj = ( - current_drive_variables.p_hcd_injected_total_mw + self.data.current_drive.p_hcd_injected_total_mw if physics_variables.i_plasma_ignited == 0 else 0.0 ) @@ -851,7 +850,7 @@ def run(self): kappa=physics_variables.kappa, kappa95=physics_variables.kappa95, p_non_alpha_charged_mw=physics_variables.p_non_alpha_charged_mw, - p_hcd_injected_total_mw=current_drive_variables.p_hcd_injected_total_mw, + p_hcd_injected_total_mw=self.data.current_drive.p_hcd_injected_total_mw, plasma_current=physics_variables.plasma_current, pden_plasma_core_rad_mw=physics_variables.pden_plasma_core_rad_mw, rmajor=physics_variables.rmajor, @@ -1014,7 +1013,7 @@ def run(self): * physics_variables.p_alpha_total_mw + physics_variables.p_non_alpha_charged_mw + physics_variables.p_plasma_ohmic_mw - + current_drive_variables.p_hcd_injected_total_mw + + self.data.current_drive.p_hcd_injected_total_mw ) physics_variables.f_p_plasma_separatrix_rad = ( 1.0e6 @@ -1099,8 +1098,7 @@ def calculate_current_profile_index_wesson(qstar: float, q0: float) -> float: """ return qstar / q0 - 1.0 - @staticmethod - def plasma_composition(): + def plasma_composition(self): """Calculates various plasma component fractional makeups. This subroutine determines the various plasma component fractional makeups. @@ -1326,8 +1324,8 @@ def plasma_composition(): # Average atomic masses of injected fuel species in the neutral beams # Only deuterium and tritium in the beams physics_variables.m_beam_amu = ( - constants.M_DEUTERON_AMU * (1.0 - current_drive_variables.f_beam_tritium) - ) + (constants.M_TRITON_AMU * current_drive_variables.f_beam_tritium) + constants.M_DEUTERON_AMU * (1.0 - self.data.current_drive.f_beam_tritium) + ) + (constants.M_TRITON_AMU * self.data.current_drive.f_beam_tritium) # ====================================================================== @@ -1377,12 +1375,12 @@ def plasma_composition(): + (4.0 * physics_variables.nd_plasma_alphas_vol_avg / constants.M_ALPHA_AMU) + (physics_variables.nd_plasma_protons_vol_avg / constants.M_PROTON_AMU) + ( - (1.0 - current_drive_variables.f_beam_tritium) + (1.0 - self.data.current_drive.f_beam_tritium) * physics_variables.nd_beam_ions / constants.M_DEUTERON_AMU ) + ( - current_drive_variables.f_beam_tritium + self.data.current_drive.f_beam_tritium * physics_variables.nd_beam_ions / constants.M_TRITON_AMU ) @@ -1738,7 +1736,7 @@ def outplas(self): po.oblnkl(self.outfile) if stellarator_variables.istell == 0: - self.density_limit.output_density_limit_information() + self.density_limit.output() po.oheadr(self.outfile, "Plasma Reactions :") @@ -2235,14 +2233,14 @@ def outplas(self): self.outfile, "Injection power to ions (MW)", "(p_hcd_injected_ions_mw)", - current_drive_variables.p_hcd_injected_ions_mw, + self.data.current_drive.p_hcd_injected_ions_mw, "OP ", ) po.ovarre( self.outfile, "Injection power to electrons (MW)", "(p_hcd_injected_electrons_mw)", - current_drive_variables.p_hcd_injected_electrons_mw, + self.data.current_drive.p_hcd_injected_electrons_mw, "OP ", ) if physics_variables.i_plasma_ignited == 1: @@ -3104,7 +3102,7 @@ def run(self): # R. D. Stambaugh scaling law physics_variables.beta_norm_max_stambaugh = ( self.calculate_beta_norm_max_stambaugh( - f_c_plasma_bootstrap=current_drive_variables.f_c_plasma_bootstrap, + f_c_plasma_bootstrap=self.data.current_drive.f_c_plasma_bootstrap, kappa=physics_variables.kappa, aspect=physics_variables.aspect, ) diff --git a/process/models/physics/plasma_current.py b/process/models/physics/plasma_current.py index de6905d5c..293029019 100644 --- a/process/models/physics/plasma_current.py +++ b/process/models/physics/plasma_current.py @@ -17,7 +17,6 @@ from process.core.exceptions import ProcessValueError from process.core.model import Model from process.data_structure import ( - current_drive_variables, physics_variables, stellarator_variables, ) @@ -1121,12 +1120,12 @@ def __init__(self): def run(self): """Calculate plasma diamagnetic current fractions using scalings.""" # Hender scaling for diamagnetic current at tight physics_variables.aspect ratio - current_drive_variables.f_c_plasma_diamagnetic_hender = ( + self.data.current_drive.f_c_plasma_diamagnetic_hender = ( self.diamagnetic_fraction_hender(physics_variables.beta_total_vol_avg) ) # SCENE scaling for diamagnetic current - current_drive_variables.f_c_plasma_diamagnetic_scene = ( + self.data.current_drive.f_c_plasma_diamagnetic_scene = ( self.diamagnetic_fraction_scene( physics_variables.beta_total_vol_avg, physics_variables.q95, @@ -1138,15 +1137,15 @@ def run(self): physics_variables.i_diamagnetic_current == PlasmaDiamagneticCurrentModel.HENDER_ST_FIT ): - current_drive_variables.f_c_plasma_diamagnetic = ( - current_drive_variables.f_c_plasma_diamagnetic_hender + self.data.current_drive.f_c_plasma_diamagnetic = ( + self.data.current_drive.f_c_plasma_diamagnetic_hender ) elif ( physics_variables.i_diamagnetic_current == PlasmaDiamagneticCurrentModel.SCENE_FIT ): - current_drive_variables.f_c_plasma_diamagnetic = ( - current_drive_variables.f_c_plasma_diamagnetic_scene + self.data.current_drive.f_c_plasma_diamagnetic = ( + self.data.current_drive.f_c_plasma_diamagnetic_scene ) def output(self): @@ -1170,20 +1169,20 @@ def output(self): self.outfile, "Diamagnetic fraction (Hender)", "(f_c_plasma_diamagnetic_hender)", - current_drive_variables.f_c_plasma_diamagnetic_hender, + self.data.current_drive.f_c_plasma_diamagnetic_hender, "OP ", ) po.ovarrf( self.outfile, "Diamagnetic fraction (SCENE)", "(f_c_plasma_diamagnetic_scene)", - current_drive_variables.f_c_plasma_diamagnetic_scene, + self.data.current_drive.f_c_plasma_diamagnetic_scene, "OP ", ) po.oblnkl(self.outfile) if ( physics_variables.i_diamagnetic_current == PlasmaDiamagneticCurrentModel.NONE - and current_drive_variables.f_c_plasma_diamagnetic_scene > 0.01e0 + and self.data.current_drive.f_c_plasma_diamagnetic_scene > 0.01e0 ): # Error to show if diamagnetic current is above 1% but not used logger.error( diff --git a/process/models/physics/plasma_profiles.py b/process/models/physics/plasma_profiles.py index 7dd853d70..8e36c5932 100644 --- a/process/models/physics/plasma_profiles.py +++ b/process/models/physics/plasma_profiles.py @@ -11,13 +11,14 @@ from process.core import constants from process.core.exceptions import ProcessValueError +from process.core.model import Model from process.data_structure import divertor_variables, physics_variables from process.models.physics.profiles import NeProfile, PlasmaProfileShapeType, TeProfile logger = logging.getLogger(__name__) -class PlasmaProfile: +class PlasmaProfile(Model): """Plasma profile class. Initiates the electron density and electron temperature profiles and handles the required physics variables. """ @@ -47,6 +48,9 @@ def run(self): """ self.parameterise_plasma() + def output(self): + """This model doesn't have any output""" + def parameterise_plasma(self): """Initializes the density and temperature profile averages and peak values, given the main diff --git a/process/models/power.py b/process/models/power.py index 7c0f20c33..4d03e3d0f 100644 --- a/process/models/power.py +++ b/process/models/power.py @@ -12,7 +12,6 @@ from process.core.exceptions import ProcessValueError from process.core.model import Model from process.data_structure import ( - current_drive_variables, heat_transport_variables, numerics, pf_power_variables, @@ -857,7 +856,7 @@ def component_thermal_powers(self): # Heat lost in power supplies for heating and current drive heat_transport_variables.p_hcd_electric_loss_mw = ( heat_transport_variables.p_hcd_electric_total_mw - - current_drive_variables.p_hcd_injected_total_mw + - self.data.current_drive.p_hcd_injected_total_mw ) # Liquid metal breeder/coolant @@ -883,9 +882,9 @@ def component_thermal_powers(self): + self.data.fwbs.p_blkt_nuclear_heat_total_mw + heat_transport_variables.p_blkt_breeder_pump_mw + self.data.primary_pumping.p_fw_blkt_coolant_pump_mw - + current_drive_variables.p_beam_orbit_loss_mw + + self.data.current_drive.p_beam_orbit_loss_mw + physics_variables.p_fw_alpha_mw - + current_drive_variables.p_beam_shine_through_mw + + self.data.current_drive.p_beam_shine_through_mw ) else: # No secondary liquid metal breeder/coolant @@ -894,9 +893,9 @@ def component_thermal_powers(self): + self.data.fwbs.p_fw_rad_total_mw + self.data.fwbs.p_blkt_nuclear_heat_total_mw + self.data.primary_pumping.p_fw_blkt_coolant_pump_mw - + current_drive_variables.p_beam_orbit_loss_mw + + self.data.current_drive.p_beam_orbit_loss_mw + physics_variables.p_fw_alpha_mw - + current_drive_variables.p_beam_shine_through_mw + + self.data.current_drive.p_beam_shine_through_mw ) # Total power deposited in first wall coolant (MW) @@ -904,9 +903,9 @@ def component_thermal_powers(self): self.data.fwbs.p_fw_nuclear_heat_total_mw + self.data.fwbs.p_fw_rad_total_mw + heat_transport_variables.p_fw_coolant_pump_mw - + current_drive_variables.p_beam_orbit_loss_mw + + self.data.current_drive.p_beam_orbit_loss_mw + physics_variables.p_fw_alpha_mw - + current_drive_variables.p_beam_shine_through_mw + + self.data.current_drive.p_beam_shine_through_mw ) # Total power deposited in blanket coolant (MW) @@ -1122,13 +1121,13 @@ def output_plant_thermal_powers(self): self.outfile, "Neutral beam shine-through heat deposited in FW [MW]", "(p_beam_shine_through_mw)", - current_drive_variables.p_beam_shine_through_mw, + self.data.current_drive.p_beam_shine_through_mw, ) po.ovarre( self.outfile, "Neutral beam orbit loss heat deposited in FW [MW]", "(p_beam_orbit_loss_mw)", - current_drive_variables.p_beam_orbit_loss_mw, + self.data.current_drive.p_beam_orbit_loss_mw, ) po.ovarre( diff --git a/process/models/stellarator/heating.py b/process/models/stellarator/heating.py index 4028fefb2..2f181264b 100644 --- a/process/models/stellarator/heating.py +++ b/process/models/stellarator/heating.py @@ -2,8 +2,8 @@ from process.core import process_output as po from process.core.exceptions import ProcessValueError +from process.core.model import DataStructure from process.data_structure import ( - current_drive_variables, heat_transport_variables, physics_variables, stellarator_variables, @@ -12,7 +12,7 @@ logger = logging.getLogger(__name__) -def st_heat(stellarator, f_output: bool): +def st_heat(stellarator, f_output: bool, data: DataStructure): """Routine to calculate the auxiliary heating power in a stellarator @@ -25,69 +25,71 @@ def st_heat(stellarator, f_output: bool): f_output: + data: DataStructure + data structure object """ f_p_beam_injected_ions = None if stellarator_variables.isthtr == 1: - current_drive_variables.p_hcd_ecrh_injected_total_mw = ( - current_drive_variables.p_hcd_primary_extra_heat_mw + data.current_drive.p_hcd_ecrh_injected_total_mw = ( + data.current_drive.p_hcd_primary_extra_heat_mw ) - current_drive_variables.p_hcd_injected_ions_mw = 0 - current_drive_variables.p_hcd_injected_electrons_mw = ( - current_drive_variables.p_hcd_ecrh_injected_total_mw + data.current_drive.p_hcd_injected_ions_mw = 0 + data.current_drive.p_hcd_injected_electrons_mw = ( + data.current_drive.p_hcd_ecrh_injected_total_mw ) - current_drive_variables.eta_hcd_primary_injector_wall_plug = ( - current_drive_variables.eta_ecrh_injector_wall_plug + data.current_drive.eta_hcd_primary_injector_wall_plug = ( + data.current_drive.eta_ecrh_injector_wall_plug ) - current_drive_variables.p_hcd_electric_total_mw = ( - current_drive_variables.p_hcd_injected_ions_mw - + current_drive_variables.p_hcd_injected_electrons_mw - ) / current_drive_variables.eta_hcd_primary_injector_wall_plug + data.current_drive.p_hcd_electric_total_mw = ( + data.current_drive.p_hcd_injected_ions_mw + + data.current_drive.p_hcd_injected_electrons_mw + ) / data.current_drive.eta_hcd_primary_injector_wall_plug elif stellarator_variables.isthtr == 2: - current_drive_variables.p_hcd_lowhyb_injected_total_mw = ( - current_drive_variables.p_hcd_primary_extra_heat_mw + data.current_drive.p_hcd_lowhyb_injected_total_mw = ( + data.current_drive.p_hcd_primary_extra_heat_mw ) - current_drive_variables.p_hcd_injected_ions_mw = 0 - current_drive_variables.p_hcd_injected_electrons_mw = ( - current_drive_variables.p_hcd_lowhyb_injected_total_mw + data.current_drive.p_hcd_injected_ions_mw = 0 + data.current_drive.p_hcd_injected_electrons_mw = ( + data.current_drive.p_hcd_lowhyb_injected_total_mw ) - current_drive_variables.eta_hcd_primary_injector_wall_plug = ( - current_drive_variables.eta_lowhyb_injector_wall_plug + data.current_drive.eta_hcd_primary_injector_wall_plug = ( + data.current_drive.eta_lowhyb_injector_wall_plug ) heat_transport_variables.p_hcd_electric_total_mw = ( - current_drive_variables.p_hcd_injected_ions_mw - + current_drive_variables.p_hcd_injected_electrons_mw - ) / current_drive_variables.eta_hcd_primary_injector_wall_plug + data.current_drive.p_hcd_injected_ions_mw + + data.current_drive.p_hcd_injected_electrons_mw + ) / data.current_drive.eta_hcd_primary_injector_wall_plug elif stellarator_variables.isthtr == 3: ( _effnbss, f_p_beam_injected_ions, - current_drive_variables.f_p_beam_shine_through, + data.current_drive.f_p_beam_shine_through, ) = stellarator.current_drive.culnbi() - current_drive_variables.p_hcd_beam_injected_total_mw = ( - current_drive_variables.p_hcd_primary_extra_heat_mw - * (1 - current_drive_variables.f_p_beam_orbit_loss) + data.current_drive.p_hcd_beam_injected_total_mw = ( + data.current_drive.p_hcd_primary_extra_heat_mw + * (1 - data.current_drive.f_p_beam_orbit_loss) ) - current_drive_variables.p_beam_orbit_loss_mw = ( - current_drive_variables.p_hcd_primary_extra_heat_mw - * current_drive_variables.f_p_beam_orbit_loss + data.current_drive.p_beam_orbit_loss_mw = ( + data.current_drive.p_hcd_primary_extra_heat_mw + * data.current_drive.f_p_beam_orbit_loss ) - current_drive_variables.p_hcd_injected_ions_mw = ( - current_drive_variables.p_hcd_beam_injected_total_mw * f_p_beam_injected_ions + data.current_drive.p_hcd_injected_ions_mw = ( + data.current_drive.p_hcd_beam_injected_total_mw * f_p_beam_injected_ions ) - current_drive_variables.p_hcd_injected_electrons_mw = ( - current_drive_variables.p_hcd_beam_injected_total_mw + data.current_drive.p_hcd_injected_electrons_mw = ( + data.current_drive.p_hcd_beam_injected_total_mw * (1 - f_p_beam_injected_ions) ) - current_drive_variables.eta_hcd_primary_injector_wall_plug = ( - current_drive_variables.eta_beam_injector_wall_plug + data.current_drive.eta_hcd_primary_injector_wall_plug = ( + data.current_drive.eta_beam_injector_wall_plug ) - current_drive_variables.p_hcd_electric_total_mw = ( - current_drive_variables.p_hcd_injected_ions_mw - + current_drive_variables.p_hcd_injected_electrons_mw - ) / current_drive_variables.eta_hcd_primary_injector_wall_plug + data.current_drive.p_hcd_electric_total_mw = ( + data.current_drive.p_hcd_injected_ions_mw + + data.current_drive.p_hcd_injected_electrons_mw + ) / data.current_drive.eta_hcd_primary_injector_wall_plug else: logger.error(f"isthtr {stellarator_variables.isthtr}") logger.error(f"isthtr type {type(stellarator_variables.isthtr)}") @@ -97,45 +99,45 @@ def st_heat(stellarator, f_output: bool): # Total injected power - current_drive_variables.p_hcd_injected_total_mw = ( - current_drive_variables.p_hcd_injected_electrons_mw - + current_drive_variables.p_hcd_injected_ions_mw + data.current_drive.p_hcd_injected_total_mw = ( + data.current_drive.p_hcd_injected_electrons_mw + + data.current_drive.p_hcd_injected_ions_mw ) # Calculate neutral beam current - if abs(current_drive_variables.p_hcd_beam_injected_total_mw) > 1e-8: - current_drive_variables.c_beam_total = ( + if abs(data.current_drive.p_hcd_beam_injected_total_mw) > 1e-8: + data.current_drive.c_beam_total = ( 1e-3 - * (current_drive_variables.p_hcd_beam_injected_total_mw * 1e6) - / current_drive_variables.e_beam_kev + * (data.current_drive.p_hcd_beam_injected_total_mw * 1e6) + / data.current_drive.e_beam_kev ) else: - current_drive_variables.c_beam_total = 0 + data.current_drive.c_beam_total = 0 # Ratio of fusion to input (injection+ohmic) power if ( abs( - current_drive_variables.p_hcd_injected_total_mw - + current_drive_variables.p_beam_orbit_loss_mw + data.current_drive.p_hcd_injected_total_mw + + data.current_drive.p_beam_orbit_loss_mw + physics_variables.p_plasma_ohmic_mw ) < 1e-6 ): - current_drive_variables.big_q_plasma = 1e18 + data.current_drive.big_q_plasma = 1e18 else: - current_drive_variables.big_q_plasma = physics_variables.p_fusion_total_mw / ( - current_drive_variables.p_hcd_injected_total_mw - + current_drive_variables.p_beam_orbit_loss_mw + data.current_drive.big_q_plasma = physics_variables.p_fusion_total_mw / ( + data.current_drive.p_hcd_injected_total_mw + + data.current_drive.p_beam_orbit_loss_mw + physics_variables.p_plasma_ohmic_mw ) if f_output: - output(stellarator, f_p_beam_injected_ions) + output(stellarator, data, f_p_beam_injected_ions) -def output(stellarator, f_p_beam_injected_ions=None): +def output(stellarator, data: DataStructure, f_p_beam_injected_ions=None): po.oheadr(stellarator.outfile, "Auxiliary Heating System") if stellarator_variables.isthtr == 1: @@ -157,27 +159,27 @@ def output(stellarator, f_p_beam_injected_ions=None): stellarator.outfile, "Auxiliary power supplied to plasma (MW)", "(p_hcd_primary_extra_heat_mw)", - current_drive_variables.p_hcd_primary_extra_heat_mw, + data.current_drive.p_hcd_primary_extra_heat_mw, ) po.ovarre( stellarator.outfile, "Fusion gain factor Q", "(big_q_plasma)", - current_drive_variables.big_q_plasma, + data.current_drive.big_q_plasma, ) - if abs(current_drive_variables.p_hcd_beam_injected_total_mw) > 1e-8: + if abs(data.current_drive.p_hcd_beam_injected_total_mw) > 1e-8: po.ovarre( stellarator.outfile, "Neutral beam energy (KEV)", "(enbeam)", - current_drive_variables.enbeam, + data.current_drive.enbeam, ) po.ovarre( stellarator.outfile, "Neutral beam current (A)", "(c_beam_total)", - current_drive_variables.c_beam_total, + data.current_drive.c_beam_total, ) po.ovarre( stellarator.outfile, @@ -189,41 +191,41 @@ def output(stellarator, f_p_beam_injected_ions=None): stellarator.outfile, "Neutral beam shine-through fraction", "(f_p_beam_shine_through)", - current_drive_variables.f_p_beam_shine_through, + data.current_drive.f_p_beam_shine_through, ) po.ovarre( stellarator.outfile, "Neutral beam orbit loss power (MW)", "(p_beam_orbit_loss_mw)", - current_drive_variables.p_beam_orbit_loss_mw, + data.current_drive.p_beam_orbit_loss_mw, ) po.ovarre( stellarator.outfile, "Beam duct shielding thickness (m)", "(dx_beam_shield)", - current_drive_variables.dx_beam_shield, + data.current_drive.dx_beam_shield, ) po.ovarre( stellarator.outfile, "R injection tangent / R-major", "(f_radius_beam_tangency_rmajor)", - current_drive_variables.f_radius_beam_tangency_rmajor, + data.current_drive.f_radius_beam_tangency_rmajor, ) po.ovarre( stellarator.outfile, "Beam centreline tangency radius (m)", "(radius_beam_tangency)", - current_drive_variables.radius_beam_tangency, + data.current_drive.radius_beam_tangency, ) po.ovarre( stellarator.outfile, "Maximum possible tangency radius (m)", "(radius_beam_tangency_max)", - current_drive_variables.radius_beam_tangency_max, + data.current_drive.radius_beam_tangency_max, ) po.ovarre( stellarator.outfile, "Beam decay lengths to centre", "(n_beam_decay_lengths_core)", - current_drive_variables.n_beam_decay_lengths_core, + data.current_drive.n_beam_decay_lengths_core, ) diff --git a/process/models/stellarator/initialization.py b/process/models/stellarator/initialization.py index 2ce5252bc..65d6566a6 100644 --- a/process/models/stellarator/initialization.py +++ b/process/models/stellarator/initialization.py @@ -1,6 +1,5 @@ from process.core.model import DataStructure from process.data_structure import ( - current_drive_variables, numerics, pfcoil_variables, physics_variables, @@ -41,7 +40,7 @@ def st_init(data: DataStructure): # Turn off current drive - current_drive_variables.i_hcd_calculations = 0 + data.current_drive.i_hcd_calculations = 0 # Times for different phases diff --git a/process/models/stellarator/stellarator.py b/process/models/stellarator/stellarator.py index 37ffa13c4..d99f5c9d4 100644 --- a/process/models/stellarator/stellarator.py +++ b/process/models/stellarator/stellarator.py @@ -14,7 +14,6 @@ from process.core.exceptions import ProcessValueError from process.core.model import Model from process.data_structure import ( - current_drive_variables, divertor_variables, global_variables, heat_transport_variables, @@ -134,7 +133,7 @@ def run(self, output: bool = False): self.availability.run(output=True) self.physics.calculate_effective_charge_ionisation_profiles() self.physics.outplas() - st_heat(self, True) + st_heat(self, True, self.data) self.st_phys(True) st_denisty_limits(self, True) @@ -633,7 +632,7 @@ def st_fwbs(self, output: bool): * ( self.data.fwbs.p_fw_nuclear_heat_total_mw + self.data.fwbs.p_fw_rad_total_mw - + current_drive_variables.p_beam_orbit_loss_mw + + self.data.current_drive.p_beam_orbit_loss_mw ) ) heat_transport_variables.p_blkt_coolant_pump_mw = ( @@ -897,7 +896,7 @@ def st_fwbs(self, output: bool): + p_fw_outboard_nuclear_heat_mw + psurffwi + psurffwo - + current_drive_variables.p_beam_orbit_loss_mw + + self.data.current_drive.p_beam_orbit_loss_mw ) ) heat_transport_variables.p_blkt_coolant_pump_mw = ( @@ -2001,7 +2000,7 @@ def st_phys(self, output): # Perform auxiliary power calculations - st_heat(self, False) + st_heat(self, False, self.data) # Calculate fusion power @@ -2026,7 +2025,7 @@ def st_phys(self, output): # Calculate neutral beam slowing down effects # If ignited, then ignore beam fusion effects - if (current_drive_variables.p_hcd_beam_injected_total_mw != 0.0e0) and ( # noqa: RUF069 + if (self.data.current_drive.p_hcd_beam_injected_total_mw != 0.0e0) and ( # noqa: RUF069 physics_variables.i_plasma_ignited == 0 ): ( @@ -2037,14 +2036,14 @@ def st_phys(self, output): physics_variables.beamfus0, physics_variables.betbm0, physics_variables.b_plasma_total, - current_drive_variables.c_beam_total, + self.data.current_drive.c_beam_total, physics_variables.nd_plasma_electrons_vol_avg, physics_variables.nd_plasma_fuel_ions_vol_avg, physics_variables.dlamie, - current_drive_variables.e_beam_kev, + self.data.current_drive.e_beam_kev, physics_variables.f_plasma_fuel_deuterium, physics_variables.f_plasma_fuel_tritium, - current_drive_variables.f_beam_tritium, + self.data.current_drive.f_beam_tritium, physics_variables.temp_plasma_electron_density_weighted_kev, physics_variables.vol_plasma, physics_variables.n_charge_plasma_effective_mass_weighted_vol_avg, @@ -2203,7 +2202,7 @@ def st_phys(self, output): if physics_variables.i_plasma_ignited == 0: # if not ignited add the auxiliary power - powht += current_drive_variables.p_hcd_injected_total_mw + powht += self.data.current_drive.p_hcd_injected_total_mw # Here the implementation sometimes leaves the accessible regime when p_plasma_rad_mw> powht which is unphysical and # is not taken care of by the rad module. We restrict the radiation power here by the heating power: @@ -2265,7 +2264,7 @@ def st_phys(self, output): * physics_variables.p_alpha_total_mw + physics_variables.p_non_alpha_charged_mw + physics_variables.p_plasma_ohmic_mw - + current_drive_variables.p_hcd_injected_total_mw + + self.data.current_drive.p_hcd_injected_total_mw ) # Calculate transport losses and energy confinement time using the @@ -2294,7 +2293,7 @@ def st_phys(self, output): physics_variables.kappa, physics_variables.kappa95, physics_variables.p_non_alpha_charged_mw, - current_drive_variables.p_hcd_injected_total_mw, + self.data.current_drive.p_hcd_injected_total_mw, physics_variables.plasma_current, physics_variables.pden_plasma_core_rad_mw, physics_variables.rmajor, diff --git a/tests/unit/models/blankets/test_ccfe_hcpb.py b/tests/unit/models/blankets/test_ccfe_hcpb.py index c303b4fa0..6df8d4867 100644 --- a/tests/unit/models/blankets/test_ccfe_hcpb.py +++ b/tests/unit/models/blankets/test_ccfe_hcpb.py @@ -3,7 +3,6 @@ import pytest from process.data_structure import ( - current_drive_variables, divertor_variables, global_variables, heat_transport_variables, @@ -882,7 +881,7 @@ def test_powerflow_calc(powerflowcalcparam, monkeypatch, ccfe_hcpb): ) monkeypatch.setattr( - current_drive_variables, + ccfe_hcpb.data.current_drive, "p_beam_orbit_loss_mw", powerflowcalcparam.p_beam_orbit_loss_mw, ) diff --git a/tests/unit/models/physics/test_current_drive.py b/tests/unit/models/physics/test_current_drive.py index cd5f07965..7544feff6 100644 --- a/tests/unit/models/physics/test_current_drive.py +++ b/tests/unit/models/physics/test_current_drive.py @@ -2,125 +2,116 @@ from process.core import constants from process.data_structure import ( - current_drive_variables, heat_transport_variables, physics_variables, ) -from process.models.physics.current_drive import ( - CurrentDrive, - ElectronBernstein, - ElectronCyclotron, - IonCyclotron, - LowerHybrid, - NeutralBeam, -) -from process.models.physics.plasma_profiles import PlasmaProfile @pytest.fixture -def current_drive(): - """Provides CurrentDrive object for testing. +def current_drive(process_models): + """Fixture to get the CurrentDrive instance from process_models :returns current_drive: initialised CurrentDrive object :rtype: process.current_drive.CurrentDrive """ - return CurrentDrive( - PlasmaProfile(), - electron_cyclotron=ElectronCyclotron(plasma_profile=PlasmaProfile()), - electron_bernstein=ElectronBernstein(plasma_profile=PlasmaProfile()), - neutral_beam=NeutralBeam(plasma_profile=PlasmaProfile()), - lower_hybrid=LowerHybrid(plasma_profile=PlasmaProfile()), - ion_cyclotron=IonCyclotron(plasma_profile=PlasmaProfile()), - ) + return process_models.current_drive def test_current_drive_primary_lower_hybrid(current_drive): - current_drive_variables.i_hcd_primary = 1 # Lower Hybrid - current_drive_variables.i_hcd_secondary = 0 - current_drive_variables.i_hcd_calculations = 1 - current_drive_variables.p_hcd_primary_extra_heat_mw = 0.0 - current_drive_variables.eta_cd_hcd_secondary = 0.0 + current_drive.data.current_drive.i_hcd_primary = 1 # Lower Hybrid + current_drive.data.current_drive.i_hcd_secondary = 0 + current_drive.data.current_drive.i_hcd_calculations = 1 + current_drive.data.current_drive.p_hcd_primary_extra_heat_mw = 0.0 + current_drive.data.current_drive.eta_cd_hcd_secondary = 0.0 physics_variables.nd_plasma_electrons_vol_avg = 1e20 physics_variables.temp_plasma_electron_vol_avg_kev = 10 physics_variables.rmajor = 6.2 physics_variables.plasma_current = 15e6 physics_variables.f_c_plasma_auxiliary = 0.2 - current_drive_variables.eta_lowhyb_injector_wall_plug = 0.4 + current_drive.data.current_drive.eta_lowhyb_injector_wall_plug = 0.4 current_drive.current_drive() - assert current_drive_variables.eta_cd_hcd_primary == pytest.approx( + assert current_drive.data.current_drive.eta_cd_hcd_primary == pytest.approx( 0.07812311, rel=1e-6 ) - assert current_drive_variables.eta_cd_norm_hcd_primary == pytest.approx( + assert current_drive.data.current_drive.eta_cd_norm_hcd_primary == pytest.approx( 0.48436326, rel=1e-6 ) - assert current_drive_variables.f_c_plasma_hcd_secondary == pytest.approx( + assert current_drive.data.current_drive.f_c_plasma_hcd_secondary == pytest.approx( 0.0, rel=1e-6 ) - assert current_drive_variables.p_hcd_primary_injected_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_primary_injected_mw == pytest.approx( 38.4009309, rel=1e-6 ) - assert current_drive_variables.c_hcd_primary_driven == pytest.approx( + assert current_drive.data.current_drive.c_hcd_primary_driven == pytest.approx( 3000000.0, rel=1e-6 ) - assert current_drive_variables.f_c_plasma_hcd_primary == pytest.approx(0.2, rel=1e-6) + assert current_drive.data.current_drive.f_c_plasma_hcd_primary == pytest.approx( + 0.2, rel=1e-6 + ) assert heat_transport_variables.p_hcd_primary_electric_mw == pytest.approx( 96.00232726, rel=1e-6 ) assert heat_transport_variables.p_hcd_secondary_electric_mw == pytest.approx( 0.0, rel=1e-6 ) - assert current_drive_variables.p_hcd_injected_total_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_injected_total_mw == pytest.approx( 38.4009309, rel=1e-6 ) - assert current_drive_variables.p_hcd_injected_electrons_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_injected_electrons_mw == pytest.approx( 38.4009309, rel=1e-6 ) def test_current_drive_primary_lower_hybrid_with_heat(current_drive): - current_drive_variables.i_hcd_primary = 1 # Lower Hybrid - current_drive_variables.i_hcd_secondary = 0 - current_drive_variables.i_hcd_calculations = 1 - current_drive_variables.p_hcd_primary_extra_heat_mw = 5.0 # Adding primary heat - current_drive_variables.eta_cd_hcd_secondary = 0.0 + current_drive.data.current_drive.i_hcd_primary = 1 # Lower Hybrid + current_drive.data.current_drive.i_hcd_secondary = 0 + current_drive.data.current_drive.i_hcd_calculations = 1 + current_drive.data.current_drive.p_hcd_primary_extra_heat_mw = ( + 5.0 # Adding primary heat + ) + current_drive.data.current_drive.eta_cd_hcd_secondary = 0.0 physics_variables.nd_plasma_electrons_vol_avg = 1e20 physics_variables.temp_plasma_electron_vol_avg_kev = 10 physics_variables.rmajor = 6.2 physics_variables.plasma_current = 15e6 physics_variables.f_c_plasma_auxiliary = 0.2 - current_drive_variables.eta_lowhyb_injector_wall_plug = 0.4 + current_drive.data.current_drive.eta_lowhyb_injector_wall_plug = 0.4 current_drive.current_drive() - assert current_drive_variables.eta_cd_hcd_primary == pytest.approx( + assert current_drive.data.current_drive.eta_cd_hcd_primary == pytest.approx( 0.07812311, rel=1e-6 ) - assert current_drive_variables.eta_cd_norm_hcd_primary == pytest.approx( + assert current_drive.data.current_drive.eta_cd_norm_hcd_primary == pytest.approx( 0.48436326, rel=1e-6 ) - assert current_drive_variables.f_c_plasma_hcd_secondary == pytest.approx( + assert current_drive.data.current_drive.f_c_plasma_hcd_secondary == pytest.approx( 0.0, rel=1e-6 ) - assert current_drive_variables.p_hcd_primary_injected_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_primary_injected_mw == pytest.approx( 38.4009309, rel=1e-6 ) # Adjusted for extra heat - assert current_drive_variables.c_hcd_primary_driven == pytest.approx( + assert current_drive.data.current_drive.c_hcd_primary_driven == pytest.approx( 3000000.0, rel=1e-6 ) - assert current_drive_variables.f_c_plasma_hcd_primary == pytest.approx(0.2, rel=1e-6) + assert current_drive.data.current_drive.f_c_plasma_hcd_primary == pytest.approx( + 0.2, rel=1e-6 + ) assert heat_transport_variables.p_hcd_primary_electric_mw == pytest.approx( 108.50232725752629, rel=1e-6 ) # Adjusted for extra heat assert heat_transport_variables.p_hcd_secondary_electric_mw == pytest.approx( 0.0, rel=1e-6 ) - assert current_drive_variables.p_hcd_injected_total_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_injected_total_mw == pytest.approx( 43.4009309, rel=1e-6 ) # Adjusted for extra heat - assert current_drive_variables.p_hcd_injected_electrons_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_injected_electrons_mw == pytest.approx( 43.4009309, rel=1e-6 ) - assert current_drive_variables.p_hcd_injected_ions_mw == pytest.approx(0.0, rel=1e-6) + assert current_drive.data.current_drive.p_hcd_injected_ions_mw == pytest.approx( + 0.0, rel=1e-6 + ) def test_sigbeam(current_drive): @@ -130,17 +121,17 @@ def test_sigbeam(current_drive): def test_current_drive_primary_neutral_beam(current_drive): - current_drive_variables.i_hcd_primary = 5 # Neutral Beam - current_drive_variables.i_hcd_secondary = 0 - current_drive_variables.i_hcd_calculations = 1 - current_drive_variables.p_hcd_primary_extra_heat_mw = 0.0 - current_drive_variables.eta_cd_hcd_secondary = 0.0 + current_drive.data.current_drive.i_hcd_primary = 5 # Neutral Beam + current_drive.data.current_drive.i_hcd_secondary = 0 + current_drive.data.current_drive.i_hcd_calculations = 1 + current_drive.data.current_drive.p_hcd_primary_extra_heat_mw = 0.0 + current_drive.data.current_drive.eta_cd_hcd_secondary = 0.0 physics_variables.nd_plasma_electrons_vol_avg = 1e20 physics_variables.temp_plasma_electron_vol_avg_kev = 10 physics_variables.rmajor = 6.2 physics_variables.plasma_current = 15e6 physics_variables.f_c_plasma_auxiliary = 0.2 - current_drive_variables.eta_beam_injector_wall_plug = 0.3 + current_drive.data.current_drive.eta_beam_injector_wall_plug = 0.3 physics_variables.m_beam_amu = 2.0 physics_variables.temp_plasma_electron_density_weighted_kev = 10.0 physics_variables.n_charge_plasma_effective_vol_avg = 2.0 @@ -148,166 +139,174 @@ def test_current_drive_primary_neutral_beam(current_drive): physics_variables.n_charge_plasma_effective_mass_weighted_vol_avg = 0.4 current_drive.current_drive() - assert current_drive_variables.eta_cd_hcd_primary == pytest.approx( + assert current_drive.data.current_drive.eta_cd_hcd_primary == pytest.approx( 0.050571139708731186, rel=1e-6 ) - assert current_drive_variables.eta_cd_norm_hcd_primary == pytest.approx( + assert current_drive.data.current_drive.eta_cd_norm_hcd_primary == pytest.approx( 0.31354106619413336, rel=1e-6 ) - assert current_drive_variables.f_c_plasma_hcd_secondary == pytest.approx( + assert current_drive.data.current_drive.f_c_plasma_hcd_secondary == pytest.approx( 0.0, rel=1e-6 ) - assert current_drive_variables.p_hcd_primary_injected_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_primary_injected_mw == pytest.approx( 59.32237274617019, rel=1e-6 ) - assert current_drive_variables.c_hcd_primary_driven == pytest.approx( + assert current_drive.data.current_drive.c_hcd_primary_driven == pytest.approx( 3000000.0, rel=1e-6 ) - assert current_drive_variables.f_c_plasma_hcd_primary == pytest.approx(0.2, rel=1e-6) + assert current_drive.data.current_drive.f_c_plasma_hcd_primary == pytest.approx( + 0.2, rel=1e-6 + ) assert heat_transport_variables.p_hcd_primary_electric_mw == pytest.approx( 197.74124248723396, rel=1e-6 ) assert heat_transport_variables.p_hcd_secondary_electric_mw == pytest.approx( 0.0, rel=1e-6 ) - assert current_drive_variables.p_hcd_injected_total_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_injected_total_mw == pytest.approx( 59.32237274617019, rel=1e-6 ) def test_current_drive_primary_electron_cyclotron(current_drive): - current_drive_variables.i_hcd_primary = 3 # Electron Cyclotron - current_drive_variables.i_hcd_secondary = 0 - current_drive_variables.i_hcd_calculations = 1 - current_drive_variables.p_hcd_primary_extra_heat_mw = 0.0 - current_drive_variables.eta_cd_hcd_secondary = 0.0 + current_drive.data.current_drive.i_hcd_primary = 3 # Electron Cyclotron + current_drive.data.current_drive.i_hcd_secondary = 0 + current_drive.data.current_drive.i_hcd_calculations = 1 + current_drive.data.current_drive.p_hcd_primary_extra_heat_mw = 0.0 + current_drive.data.current_drive.eta_cd_hcd_secondary = 0.0 physics_variables.nd_plasma_electrons_vol_avg = 1e20 physics_variables.temp_plasma_electron_vol_avg_kev = 10 physics_variables.rmajor = 6.2 physics_variables.plasma_current = 15e6 physics_variables.f_c_plasma_auxiliary = 0.2 - current_drive_variables.eta_ecrh_injector_wall_plug = 0.5 + current_drive.data.current_drive.eta_ecrh_injector_wall_plug = 0.5 physics_variables.dlamee = 1.0 physics_variables.temp_plasma_electron_density_weighted_kev = 10.0 current_drive.current_drive() - assert current_drive_variables.eta_cd_hcd_primary == pytest.approx( + assert current_drive.data.current_drive.eta_cd_hcd_primary == pytest.approx( 0.33870967741935487, rel=1e-6 ) - assert current_drive_variables.eta_cd_norm_hcd_primary == pytest.approx( + assert current_drive.data.current_drive.eta_cd_norm_hcd_primary == pytest.approx( 2.1, rel=1e-6 ) - assert current_drive_variables.f_c_plasma_hcd_secondary == pytest.approx( + assert current_drive.data.current_drive.f_c_plasma_hcd_secondary == pytest.approx( 0.0, rel=1e-6 ) - assert current_drive_variables.p_hcd_primary_injected_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_primary_injected_mw == pytest.approx( 8.857142857142856, rel=1e-6 ) - assert current_drive_variables.c_hcd_primary_driven == pytest.approx( + assert current_drive.data.current_drive.c_hcd_primary_driven == pytest.approx( 3000000.0, rel=1e-6 ) - assert current_drive_variables.f_c_plasma_hcd_primary == pytest.approx(0.2, rel=1e-6) + assert current_drive.data.current_drive.f_c_plasma_hcd_primary == pytest.approx( + 0.2, rel=1e-6 + ) assert heat_transport_variables.p_hcd_primary_electric_mw == pytest.approx( 17.71428571428571, rel=1e-6 ) assert heat_transport_variables.p_hcd_secondary_electric_mw == pytest.approx( 0.0, rel=1e-6 ) - assert current_drive_variables.p_hcd_injected_total_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_injected_total_mw == pytest.approx( 8.857142857142856, rel=1e-6 ) - assert current_drive_variables.p_hcd_injected_electrons_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_injected_electrons_mw == pytest.approx( 8.857142857142856, rel=1e-6 ) def test_current_drive_primary_ion_cyclotron(current_drive): - current_drive_variables.i_hcd_primary = 2 # Ion Cyclotron - current_drive_variables.i_hcd_secondary = 0 - current_drive_variables.i_hcd_calculations = 1 - current_drive_variables.p_hcd_primary_extra_heat_mw = 0.0 - current_drive_variables.eta_cd_hcd_secondary = 0.0 + current_drive.data.current_drive.i_hcd_primary = 2 # Ion Cyclotron + current_drive.data.current_drive.i_hcd_secondary = 0 + current_drive.data.current_drive.i_hcd_calculations = 1 + current_drive.data.current_drive.p_hcd_primary_extra_heat_mw = 0.0 + current_drive.data.current_drive.eta_cd_hcd_secondary = 0.0 physics_variables.nd_plasma_electrons_vol_avg = 1e20 physics_variables.temp_plasma_electron_vol_avg_kev = 10 physics_variables.rmajor = 6.2 physics_variables.plasma_current = 15e6 physics_variables.f_c_plasma_auxiliary = 0.2 - current_drive_variables.eta_icrh_injector_wall_plug = 0.35 + current_drive.data.current_drive.eta_icrh_injector_wall_plug = 0.35 physics_variables.n_charge_plasma_effective_vol_avg = 2.0 physics_variables.temp_plasma_electron_density_weighted_kev = 10.0 current_drive.current_drive() - assert current_drive_variables.eta_cd_hcd_primary == pytest.approx( + assert current_drive.data.current_drive.eta_cd_hcd_primary == pytest.approx( 0.025403225806451612, rel=1e-6 ) - assert current_drive_variables.eta_cd_norm_hcd_primary == pytest.approx( + assert current_drive.data.current_drive.eta_cd_norm_hcd_primary == pytest.approx( 0.1575, rel=1e-6 ) - assert current_drive_variables.f_c_plasma_hcd_secondary == pytest.approx( + assert current_drive.data.current_drive.f_c_plasma_hcd_secondary == pytest.approx( 0.0, rel=1e-6 ) - assert current_drive_variables.p_hcd_primary_injected_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_primary_injected_mw == pytest.approx( 118.0952380952381, rel=1e-6 ) - assert current_drive_variables.c_hcd_primary_driven == pytest.approx( + assert current_drive.data.current_drive.c_hcd_primary_driven == pytest.approx( 3000000.0, rel=1e-6 ) - assert current_drive_variables.f_c_plasma_hcd_primary == pytest.approx(0.2, rel=1e-6) + assert current_drive.data.current_drive.f_c_plasma_hcd_primary == pytest.approx( + 0.2, rel=1e-6 + ) assert heat_transport_variables.p_hcd_primary_electric_mw == pytest.approx( 337.4149659863946, rel=1e-6 ) assert heat_transport_variables.p_hcd_secondary_electric_mw == pytest.approx( 0.0, rel=1e-6 ) - assert current_drive_variables.p_hcd_injected_total_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_injected_total_mw == pytest.approx( 118.0952380952381, rel=1e-6 ) def test_current_drive_primary_electron_bernstein(current_drive): - current_drive_variables.i_hcd_primary = 12 # Electron Bernstein - current_drive_variables.i_hcd_secondary = 0 - current_drive_variables.i_hcd_calculations = 1 - current_drive_variables.p_hcd_primary_extra_heat_mw = 0.0 - current_drive_variables.eta_cd_hcd_secondary = 0.0 + current_drive.data.current_drive.i_hcd_primary = 12 # Electron Bernstein + current_drive.data.current_drive.i_hcd_secondary = 0 + current_drive.data.current_drive.i_hcd_calculations = 1 + current_drive.data.current_drive.p_hcd_primary_extra_heat_mw = 0.0 + current_drive.data.current_drive.eta_cd_hcd_secondary = 0.0 physics_variables.nd_plasma_electrons_vol_avg = 2e20 physics_variables.temp_plasma_electron_vol_avg_kev = 10 physics_variables.rmajor = 6.2 physics_variables.plasma_current = 15e6 physics_variables.f_c_plasma_auxiliary = 0.2 - current_drive_variables.eta_ebw_injector_wall_plug = 0.45 + current_drive.data.current_drive.eta_ebw_injector_wall_plug = 0.45 physics_variables.b_plasma_toroidal_on_axis = 2.0 physics_variables.temp_plasma_electron_density_weighted_kev = 10.0 - current_drive_variables.n_ecrh_harmonic = 2 - current_drive_variables.xi_ebw = 0.7 + current_drive.data.current_drive.n_ecrh_harmonic = 2 + current_drive.data.current_drive.xi_ebw = 0.7 constants.ELECTRON_CHARGE = constants.ELECTRON_CHARGE constants.ELECTRON_MASS = constants.ELECTRON_MASS constants.EPSILON0 = constants.EPSILON0 current_drive.current_drive() - assert current_drive_variables.eta_cd_hcd_primary == pytest.approx( + assert current_drive.data.current_drive.eta_cd_hcd_primary == pytest.approx( 0.011640447389800388, rel=1e-6 ) - assert current_drive_variables.eta_cd_norm_hcd_primary == pytest.approx( + assert current_drive.data.current_drive.eta_cd_norm_hcd_primary == pytest.approx( 0.1443415476335248, rel=1e-6 ) - assert current_drive_variables.f_c_plasma_hcd_secondary == pytest.approx( + assert current_drive.data.current_drive.f_c_plasma_hcd_secondary == pytest.approx( 0.0, rel=1e-6 ) - assert current_drive_variables.p_hcd_primary_injected_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_primary_injected_mw == pytest.approx( 257.72205307406523, rel=1e-6 ) - assert current_drive_variables.c_hcd_primary_driven == pytest.approx( + assert current_drive.data.current_drive.c_hcd_primary_driven == pytest.approx( 3000000.0, rel=1e-6 ) - assert current_drive_variables.f_c_plasma_hcd_primary == pytest.approx(0.2, rel=1e-6) + assert current_drive.data.current_drive.f_c_plasma_hcd_primary == pytest.approx( + 0.2, rel=1e-6 + ) assert heat_transport_variables.p_hcd_primary_electric_mw == pytest.approx( 572.7156734979227, rel=1e-6 ) assert heat_transport_variables.p_hcd_secondary_electric_mw == pytest.approx( 0.0, rel=1e-6 ) - assert current_drive_variables.p_hcd_injected_total_mw == pytest.approx( + assert current_drive.data.current_drive.p_hcd_injected_total_mw == pytest.approx( 257.72205307406523, rel=1e-6 ) @@ -330,16 +329,9 @@ def test_calculate_dimensionless_current_drive_efficiency_simple( temp_plasma_electron_vol_avg_kev, c_hcd_driven, p_hcd_injected, + current_drive, ): - plasma_profile = PlasmaProfile() - cd = CurrentDrive( - plasma_profile=plasma_profile, - electron_cyclotron=ElectronCyclotron(plasma_profile), - ion_cyclotron=IonCyclotron(plasma_profile), - lower_hybrid=LowerHybrid(plasma_profile), - neutral_beam=NeutralBeam(plasma_profile), - electron_bernstein=ElectronBernstein(plasma_profile), - ) + cd = current_drive expected = ( (constants.ELECTRON_CHARGE**3 / constants.EPSILON0**2) * ( diff --git a/tests/unit/models/physics/test_physics.py b/tests/unit/models/physics/test_physics.py index 7432bb23b..fd4df1e64 100644 --- a/tests/unit/models/physics/test_physics.py +++ b/tests/unit/models/physics/test_physics.py @@ -7,27 +7,12 @@ from process.core import constants from process.data_structure import ( - current_drive_variables, impurity_radiation_module, physics_variables, ) -from process.models.physics.bootstrap_current import PlasmaBootstrapCurrent -from process.models.physics.confinement_time import PlasmaConfinementTime -from process.models.physics.current_drive import ( - CurrentDrive, - ElectronBernstein, - ElectronCyclotron, - IonCyclotron, - LowerHybrid, - NeutralBeam, -) -from process.models.physics.density_limit import PlasmaDensityLimit -from process.models.physics.exhaust import PlasmaExhaust from process.models.physics.impurity_radiation import initialise_imprad -from process.models.physics.l_h_transition import PlasmaConfinementTransition from process.models.physics.physics import ( DetailedPhysics, - Physics, PlasmaBeta, PlasmaInductance, calculate_cylindrical_safety_factor, @@ -35,41 +20,17 @@ res_diff_time, rether, ) -from process.models.physics.plasma_current import PlasmaCurrent, PlasmaDiamagneticCurrent -from process.models.physics.plasma_fields import PlasmaFields -from process.models.physics.plasma_geometry import PlasmaGeom from process.models.physics.plasma_profiles import PlasmaProfile @pytest.fixture -def physics(): - """Provides Physics object for testing. +def physics(process_models): + """Fixture to get the Physics instance from process_models. :returns: initialised Physics object :rtype: process.physics.Physics """ - return Physics( - PlasmaProfile(), - CurrentDrive( - PlasmaProfile(), - electron_cyclotron=ElectronCyclotron(plasma_profile=PlasmaProfile()), - ion_cyclotron=IonCyclotron(plasma_profile=PlasmaProfile()), - neutral_beam=NeutralBeam(plasma_profile=PlasmaProfile()), - electron_bernstein=ElectronBernstein(plasma_profile=PlasmaProfile()), - lower_hybrid=LowerHybrid(plasma_profile=PlasmaProfile()), - ), - PlasmaBeta(), - PlasmaInductance(), - PlasmaDensityLimit(), - PlasmaExhaust(), - PlasmaBootstrapCurrent(plasma_profile=PlasmaProfile()), - PlasmaConfinementTime(), - PlasmaConfinementTransition(), - PlasmaCurrent(), - PlasmaFields(), - plasma_dia_current=PlasmaDiamagneticCurrent(), - plasma_geometry=PlasmaGeom(), - ) + return process_models.physics def test_calculate_poloidal_beta(): @@ -1744,7 +1705,9 @@ def test_plasma_composition(plasmacompositionparam, monkeypatch, physics): initialise_imprad() monkeypatch.setattr( - current_drive_variables, "f_beam_tritium", plasmacompositionparam.f_beam_tritium + physics.data.current_drive, + "f_beam_tritium", + plasmacompositionparam.f_beam_tritium, ) monkeypatch.setattr( @@ -3364,7 +3327,7 @@ def test_calculate_confinement_time(confinementtimeparam, monkeypatch, physics): ) -def test_calculate_plasma_masses(): +def test_calculate_plasma_masses(physics): """Test calculate_plasma_masses()""" m_fuel_amu = 2.5 m_ions_total_amu = 3.0 @@ -3380,7 +3343,7 @@ def test_calculate_plasma_masses(): m_plasma_alpha, m_plasma_electron, m_plasma, - ) = Physics.calculate_plasma_masses( + ) = physics.calculate_plasma_masses( m_fuel_amu=m_fuel_amu, m_ions_total_amu=m_ions_total_amu, nd_plasma_ions_total_vol_avg=nd_plasma_ions_total_vol_avg, @@ -3397,11 +3360,11 @@ def test_calculate_plasma_masses(): assert m_plasma == pytest.approx(4.982528145131389e-05, abs=1e-30) -def test_calculate_current_profile_index_wesson(): +def test_calculate_current_profile_index_wesson(physics): """Test calculate_current_profile_index_wesson().""" qstar = 3.5 q0 = 1.5 - result = Physics.calculate_current_profile_index_wesson(qstar, q0) + result = physics.calculate_current_profile_index_wesson(qstar, q0) assert result == pytest.approx(1.33333, abs=0.0001) diff --git a/tests/unit/models/test_buildings.py b/tests/unit/models/test_buildings.py index 77ec526b7..36ec198e5 100644 --- a/tests/unit/models/test_buildings.py +++ b/tests/unit/models/test_buildings.py @@ -3,7 +3,6 @@ import pytest from process.data_structure import ( - current_drive_variables, divertor_variables, pfcoil_variables, physics_variables, @@ -737,7 +736,7 @@ def test_bldgs_sizes(buildings, bldgssizesparam, monkeypatch): buildings.data.buildings, "hot_sepdist", bldgssizesparam.hot_sepdist ) monkeypatch.setattr( - current_drive_variables, "i_hcd_primary", bldgssizesparam.i_hcd_primary + buildings.data.current_drive, "i_hcd_primary", bldgssizesparam.i_hcd_primary ) monkeypatch.setattr(tfcoil_variables, "n_tf_coils", bldgssizesparam.n_tf_coils) monkeypatch.setattr(tfcoil_variables, "i_tf_sup", bldgssizesparam.i_tf_sup) diff --git a/tests/unit/models/test_costs_1990.py b/tests/unit/models/test_costs_1990.py index 1787cfb8a..5ff979ed4 100644 --- a/tests/unit/models/test_costs_1990.py +++ b/tests/unit/models/test_costs_1990.py @@ -7,7 +7,6 @@ from process import data_structure from process.data_structure import ( - current_drive_variables, divertor_variables, heat_transport_variables, ife_variables, @@ -3042,23 +3041,23 @@ def test_acc223(acc223param, monkeypatch, costs): monkeypatch.setattr(costs.data.costs, "fcdfuel", acc223param.fcdfuel) monkeypatch.setattr( - current_drive_variables, + costs.data.current_drive, "p_hcd_lowhyb_injected_total_mw", acc223param.p_hcd_lowhyb_injected_total_mw, ) monkeypatch.setattr( - current_drive_variables, "i_hcd_primary", acc223param.i_hcd_primary + costs.data.current_drive, "i_hcd_primary", acc223param.i_hcd_primary ) monkeypatch.setattr( - current_drive_variables, + costs.data.current_drive, "p_hcd_ecrh_injected_total_mw", acc223param.p_hcd_ecrh_injected_total_mw, ) monkeypatch.setattr( - current_drive_variables, "p_beam_injected_mw", acc223param.p_beam_injected_mw + costs.data.current_drive, "p_beam_injected_mw", acc223param.p_beam_injected_mw ) monkeypatch.setattr(ife_variables, "dcdrv2", acc223param.dcdrv2) diff --git a/tests/unit/models/test_costs_2015.py b/tests/unit/models/test_costs_2015.py index a1dea7611..244c72873 100644 --- a/tests/unit/models/test_costs_2015.py +++ b/tests/unit/models/test_costs_2015.py @@ -6,7 +6,6 @@ import pytest from process.data_structure import ( - current_drive_variables, heat_transport_variables, pf_power_variables, pfcoil_variables, @@ -2265,7 +2264,9 @@ def test_calc_building_costs(calcbuildingcostsparam, monkeypatch, costs2015): :type monkeypatch: _pytest.monkeypatch.monkeypatch """ - monkeypatch.setattr(current_drive_variables, "pwpnb", calcbuildingcostsparam.pwpnb) + monkeypatch.setattr( + costs2015.data.current_drive, "pwpnb", calcbuildingcostsparam.pwpnb + ) monkeypatch.setattr( pfcoil_variables, @@ -15917,7 +15918,7 @@ def test_calc_remaining_subsystems(calcremainingsubsystemsparam, monkeypatch, co """ monkeypatch.setattr( - current_drive_variables, + costs2015.data.current_drive, "p_hcd_injected_total_mw", calcremainingsubsystemsparam.p_hcd_injected_total_mw, ) diff --git a/tests/unit/models/test_dcll.py b/tests/unit/models/test_dcll.py index ad4b83a14..ee79ea546 100644 --- a/tests/unit/models/test_dcll.py +++ b/tests/unit/models/test_dcll.py @@ -3,7 +3,6 @@ import pytest from process.data_structure import ( - current_drive_variables, divertor_variables, physics_variables, ) @@ -164,7 +163,7 @@ def test_dcll_neutronics_and_power(dcllneutronicsandpowerparam, monkeypatch, dcl ) monkeypatch.setattr( - current_drive_variables, + dcll.data.current_drive, "p_beam_orbit_loss_mw", dcllneutronicsandpowerparam.p_beam_orbit_loss_mw, ) diff --git a/tests/unit/models/test_power.py b/tests/unit/models/test_power.py index 245971a97..2a8164f93 100644 --- a/tests/unit/models/test_power.py +++ b/tests/unit/models/test_power.py @@ -4,7 +4,6 @@ import pytest from process.data_structure import ( - current_drive_variables, divertor_variables, heat_transport_variables, numerics, @@ -2507,7 +2506,7 @@ def test_power2(power2param, monkeypatch, power): monkeypatch.setattr(power.data.costs, "ireactor", power2param.ireactor) monkeypatch.setattr( - current_drive_variables, + power.data.current_drive, "p_hcd_injected_total_mw", power2param.p_hcd_injected_total_mw, )