diff --git a/process/current_drive.py b/process/current_drive.py index 3c7cb4f7fe..7540e79e09 100644 --- a/process/current_drive.py +++ b/process/current_drive.py @@ -1479,6 +1479,27 @@ def cudriv(self) -> None: / 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( + 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, + ) + + if current_drive_variables.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( + 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 + * 1.0e6, + ) + # =========================================================== # Calculate the wall plug power for the secondary heating method @@ -1911,6 +1932,52 @@ def cudriv(self) -> None: ) ) + def calculate_dimensionless_current_drive_efficiency( + self, + nd_plasma_electrons_vol_avg: float, + rmajor: float, + temp_plasma_electron_vol_avg_kev: float, + c_hcd_driven: float, + p_hcd_injected: float, + ) -> float: + """ + Calculate the dimensionless current drive efficiency, ζ. + + This function computes the dimensionless current drive efficiency + based on the average electron density, major radius, and electron temperature. + + :param nd_plasma_electrons_vol_avg: Volume averaged electron density in m^-3. + :type nd_plasma_electrons_vol_avg: float + :param rmajor: Major radius of the plasma in meters. + :type rmajor: float + :param temp_plasma_electron_vol_avg_kev: Volume averaged electron temperature in keV. + :type temp_plasma_electron_vol_avg_kev: float + :param c_hcd_driven: Current driven by the heating and current drive system. + :type c_hcd_driven: float + :param p_hcd_injected: Power injected by the heating and current drive system. + :type p_hcd_injected: float + :return: The calculated dimensionless current drive efficiency. + :rtype: float + + :references: + - E. Poli et al., “Electron-cyclotron-current-drive efficiency in DEMO plasmas,” + Nuclear Fusion, vol. 53, no. 1, pp. 013011-013011, Dec. 2012, + doi: https://doi.org/10.1088/0029-5515/53/1/013011. + ‌ + - T. C. Luce et al., “Generation of Localized Noninductive Current by Electron Cyclotron Waves on the DIII-D Tokamak,” + Physical Review Letters, vol. 83, no. 22, pp. 4550-4553, Nov. 1999, + doi: https://doi.org/10.1103/physrevlett.83.4550. + """ + + return ( + (constants.ELECTRON_CHARGE**3 / constants.EPSILON0**2) + * ( + (nd_plasma_electrons_vol_avg * rmajor) + / (temp_plasma_electron_vol_avg_kev * constants.KILOELECTRON_VOLT) + ) + * (c_hcd_driven / p_hcd_injected) + ) + def output_current_drive(self): """ Output the current drive information to the output file. @@ -1990,6 +2057,13 @@ def output_current_drive(self): current_drive_variables.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, + "OP ", + ) if current_drive_variables.i_hcd_primary == 10: po.ovarre( self.outfile, @@ -2211,6 +2285,13 @@ def output_current_drive(self): current_drive_variables.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, + "OP ", + ) if current_drive_variables.i_hcd_secondary == 10: po.ovarre( self.outfile, diff --git a/process/data_structure/current_drive_variables.py b/process/data_structure/current_drive_variables.py index 8c6fc0b70a..e7c3718978 100644 --- a/process/data_structure/current_drive_variables.py +++ b/process/data_structure/current_drive_variables.py @@ -216,10 +216,16 @@ 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))""" @@ -424,7 +430,9 @@ def init_current_drive_variables(): global f_radius_beam_tangency_rmajor global f_beam_tritium global eta_cd_norm_hcd_primary + global eta_cd_dimensionless_hcd_primary global eta_cd_norm_hcd_secondary + global eta_cd_dimensionless_hcd_secondary global eta_cd_norm_ecrh global xi_ebw global i_hcd_primary @@ -497,6 +505,7 @@ def init_current_drive_variables(): 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 @@ -521,6 +530,7 @@ def init_current_drive_variables(): 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 diff --git a/process/io/plot_proc.py b/process/io/plot_proc.py index 1e0d2c7258..eb2f4a3036 100644 --- a/process/io/plot_proc.py +++ b/process/io/plot_proc.py @@ -2587,13 +2587,13 @@ def plot_main_plasma_information( f"$\\mathbf{{Primary \\ system: {primary_heating}}}$ \n" f"Current driving power {mfile_data.data['p_hcd_primary_injected_mw'].get_scan(scan):.4f} MW\n" f"Extra heat power: {mfile_data.data['p_hcd_primary_extra_heat_mw'].get_scan(scan):.4f} MW\n" - f"$\\gamma_{{\\text{{CD,prim}}}}$: {mfile_data.data['eta_cd_hcd_primary'].get_scan(scan):.4f} A/W\n" + f"$\\gamma_{{\\text{{CD,prim}}}}$: {mfile_data.data['eta_cd_hcd_primary'].get_scan(scan):.4f} A/W | $\\langle\\zeta_{{\\text{{CD,prim}}}}\\rangle$: {mfile_data.data['eta_cd_dimensionless_hcd_primary'].get_scan(scan):.4f} \n" f"$\\eta_{{\\text{{CD,prim}}}}$: {mfile_data.data['eta_cd_norm_hcd_primary'].get_scan(scan):.4f} $\\times 10^{{20}} \\mathrm{{A}} / \\mathrm{{Wm}}^2$\n" f"Current driven by primary: {mfile_data.data['c_hcd_primary_driven'].get_scan(scan) / 1e6:.3f} MA\n\n" f"$\\mathbf{{Secondary \\ system: {secondary_heating}}}$ \n" f"Current driving power {mfile_data.data['p_hcd_secondary_injected_mw'].get_scan(scan):.4f} MW\n" f"Extra heat power: {mfile_data.data['p_hcd_secondary_extra_heat_mw'].get_scan(scan):.4f} MW\n" - f"$\\gamma_{{\\text{{CD,sec}}}}$: {mfile_data.data['eta_cd_hcd_secondary'].get_scan(scan):.4f} A/W\n" + f"$\\gamma_{{\\text{{CD,sec}}}}$: {mfile_data.data['eta_cd_hcd_secondary'].get_scan(scan):.4f} A/W | $\\langle\\zeta_{{\\text{{CD,sec}}}}\\rangle$: {mfile_data.data['eta_cd_dimensionless_hcd_secondary'].get_scan(scan):.4f} \n" f"$\\eta_{{\\text{{CD,sec}}}}$: {mfile_data.data['eta_cd_norm_hcd_secondary'].get_scan(scan):.4f} $\\times 10^{{20}} \\mathrm{{A}} / \\mathrm{{Wm}}^2$\n" f"Current driven by secondary: {mfile_data.data['c_hcd_secondary_driven'].get_scan(scan) / 1e6:.3f} MA\n" ) diff --git a/tests/unit/test_current_drive.py b/tests/unit/test_current_drive.py index f18e27ed82..762f52276f 100644 --- a/tests/unit/test_current_drive.py +++ b/tests/unit/test_current_drive.py @@ -322,3 +322,43 @@ def test_cudriv_primary_electron_bernstein(current_drive): assert current_drive_variables.p_hcd_injected_total_mw == pytest.approx( 257.72205307406523, rel=1e-6 ) + + +@pytest.mark.parametrize( + "nd_plasma_electrons_vol_avg, rmajor, temp_plasma_electron_vol_avg_kev, c_hcd_driven, p_hcd_injected", + [ + (1e20, 1.0, 1.0, 1.0, 1.0), + ], +) +def test_calculate_dimensionless_current_drive_efficiency_simple( + nd_plasma_electrons_vol_avg, + rmajor, + temp_plasma_electron_vol_avg_kev, + c_hcd_driven, + p_hcd_injected, +): + 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), + ) + expected = ( + (constants.ELECTRON_CHARGE**3 / constants.EPSILON0**2) + * ( + (nd_plasma_electrons_vol_avg * rmajor) + / (temp_plasma_electron_vol_avg_kev * constants.KILOELECTRON_VOLT) + ) + * (c_hcd_driven / p_hcd_injected) + ) + result = cd.calculate_dimensionless_current_drive_efficiency( + nd_plasma_electrons_vol_avg, + rmajor, + temp_plasma_electron_vol_avg_kev, + c_hcd_driven, + p_hcd_injected, + ) + assert result == pytest.approx(expected, rel=1e-12)