@@ -135,9 +135,18 @@ class PostProcessedOutputs:
135135 rho_q_3_1_second: Second outermost rho_norm value that intercepts the q=3/1
136136 plane. If no intercept is found, set to -inf.
137137 I_bootstrap: Total bootstrap current [A].
138- j_external: Total current density from psi sources which are external to the
139- plasma (aka not bootstrap) [A m^-2]
140- j_ohmic: Ohmic current density [A/m^2]
138+ j_parallel_external: Parallel current density from external psi sources
139+ (i.e., excluding bootstrap) [A m^-2]
140+ j_parallel_ohmic: Parallel ohmic current density [Am^-2]
141+ j_toroidal_total: Total toroidal current density [Am^-2]
142+ j_toroidal_bootstrap: Toroidal bootstrap current density [Am^-2]
143+ j_toroidal_ohmic: Toroidal ohmic current density [Am^-2]
144+ j_toroidal_external: Toroidal current density from external psi sources
145+ (i.e., excluding bootstrap) [A m^-2]
146+ j_toroidal_generic: Toroidal current density from generic current source
147+ [Am^-2]
148+ j_toroidal_ecrh: Toroidal current density from electron cyclotron heating
149+ and current source [Am^-2]
141150 S_gas_puff: Integrated gas puff source [s^-1]
142151 S_pellet: Integrated pellet source [s^-1]
143152 S_generic_particle: Integrated generic particle source [s^-1]
@@ -217,8 +226,14 @@ class PostProcessedOutputs:
217226 rho_q_3_1_first : array_typing .FloatScalar
218227 rho_q_3_1_second : array_typing .FloatScalar
219228 I_bootstrap : array_typing .FloatScalar
220- j_external : array_typing .FloatVector
221- j_ohmic : array_typing .FloatVector
229+ j_parallel_external : array_typing .FloatVector
230+ j_parallel_ohmic : array_typing .FloatVector
231+ j_toroidal_total : array_typing .FloatVector
232+ j_toroidal_bootstrap : array_typing .FloatVector
233+ j_toroidal_ohmic : array_typing .FloatVector
234+ j_toroidal_external : array_typing .FloatVector
235+ j_toroidal_generic : array_typing .FloatVector
236+ j_toroidal_ecrh : array_typing .FloatVector
222237 S_gas_puff : array_typing .FloatScalar
223238 S_pellet : array_typing .FloatScalar
224239 S_generic_particle : array_typing .FloatScalar
@@ -315,8 +330,14 @@ def zeros(cls, geo: geometry.Geometry) -> typing_extensions.Self:
315330 rho_q_2_1_second = jnp .array (0.0 , dtype = jax_utils .get_dtype ()),
316331 rho_q_3_1_second = jnp .array (0.0 , dtype = jax_utils .get_dtype ()),
317332 I_bootstrap = jnp .array (0.0 , dtype = jax_utils .get_dtype ()),
318- j_external = jnp .zeros (geo .rho_face .shape ),
319- j_ohmic = jnp .zeros (geo .rho_face .shape ),
333+ j_parallel_external = jnp .zeros (geo .rho_face .shape ),
334+ j_parallel_ohmic = jnp .zeros (geo .rho_face .shape ),
335+ j_toroidal_total = jnp .zeros (geo .rho_face .shape ),
336+ j_toroidal_bootstrap = jnp .zeros (geo .rho_face .shape ),
337+ j_toroidal_ohmic = jnp .zeros (geo .rho_face .shape ),
338+ j_toroidal_external = jnp .zeros (geo .rho_face .shape ),
339+ j_toroidal_generic = jnp .zeros (geo .rho_face .shape ),
340+ j_toroidal_ecrh = jnp .zeros (geo .rho_face .shape ),
320341 S_gas_puff = jnp .array (0.0 , dtype = jax_utils .get_dtype ()),
321342 S_pellet = jnp .array (0.0 , dtype = jax_utils .get_dtype ()),
322343 S_generic_particle = jnp .array (0.0 , dtype = jax_utils .get_dtype ()),
@@ -360,8 +381,8 @@ def check_for_errors(self):
360381 'icrh' ,
361382]
362383CURRENT_SOURCE_TRANSFORMATIONS = {
363- 'generic_current' : 'I_aux_generic ' ,
364- 'ecrh' : 'I_ecrh ' ,
384+ 'generic_current' : 'aux_generic ' ,
385+ 'ecrh' : 'ecrh ' ,
365386}
366387PARTICLE_SOURCE_TRANSFORMATIONS = {
367388 'gas_puff' : 'S_gas_puff' ,
@@ -385,6 +406,20 @@ def _get_integrated_source_value(
385406 return jnp .array (0.0 , dtype = jax_utils .get_dtype ())
386407
387408
409+ def _get_source_toroidal_current_value (
410+ source_profiles_dict : dict [str , array_typing .FloatVector ],
411+ internal_source_name : str ,
412+ geo : geometry .Geometry ,
413+ ) -> jax .Array :
414+ """Integrates a source profile if it exists, otherwise returns 0.0."""
415+ if internal_source_name in source_profiles_dict :
416+ return psi_calculations .j_parallel_to_j_tor (
417+ source_profiles_dict [internal_source_name ], geo
418+ )
419+ else :
420+ return jnp .array (0.0 , dtype = jax_utils .get_dtype ())
421+
422+
388423def _calculate_integrated_sources (
389424 geo : geometry .Geometry ,
390425 core_profiles : state .CoreProfiles ,
@@ -491,7 +526,7 @@ def _calculate_integrated_sources(
491526 integrated ['P_external_injected' ] += integrated [f'{ value } ' ]
492527
493528 for key , value in CURRENT_SOURCE_TRANSFORMATIONS .items ():
494- integrated [f'{ value } ' ] = _get_integrated_source_value (
529+ integrated [f'I_ { value } ' ] = _get_integrated_source_value (
495530 core_sources .psi , key , geo , math_utils .area_integration
496531 )
497532
@@ -703,11 +738,36 @@ def make_post_processed_outputs(
703738 sim_state .core_sources .bootstrap_current .j_bootstrap , sim_state .geometry
704739 )
705740
706- j_external = sum (sim_state .core_sources .psi .values ())
707- psi_current = (
708- j_external + sim_state .core_sources .bootstrap_current .j_bootstrap
741+ # Parallel current densities
742+ # Core sources psi are all <j.B>/B0
743+ j_parallel_external = sum (sim_state .core_sources .psi .values ())
744+ j_parallel_ohmic = (
745+ sim_state .core_profiles .j_total # TODO: check whether j_total is parallel or toroidal
746+ - j_parallel_external
747+ - sim_state .core_sources .bootstrap_current .j_bootstrap # parallel by default
748+ )
749+
750+ # Toroidal current densities
751+ # TODO: check whether j_total is parallel or toroidal
752+ j_toroidal_total = psi_calculations .j_parallel_to_j_tor (
753+ sim_state .core_profiles .j_total , sim_state .geometry
754+ )
755+ j_toroidal_bootstrap = psi_calculations .j_parallel_to_j_tor (
756+ sim_state .core_sources .bootstrap_current .j_bootstrap , sim_state .geometry
757+ )
758+ j_toroidal_ohmic = psi_calculations .j_parallel_to_j_tor (
759+ j_parallel_ohmic , sim_state .geometry
760+ )
761+ j_toroidal_external = psi_calculations .j_parallel_to_j_tor (
762+ j_parallel_external , sim_state .geometry
709763 )
710- j_ohmic = sim_state .core_profiles .j_total - psi_current
764+ j_toroidal_sources = {}
765+ for internal_name , external_name in CURRENT_SOURCE_TRANSFORMATIONS .items ():
766+ j_toroidal_sources [f'j_toroidal_{ external_name } ' ] = (
767+ _get_source_toroidal_current_value (
768+ core_sources .psi , internal_name , sim_state .geometry
769+ )
770+ )
711771
712772 beta_tor , beta_pol , beta_N = formulas .calculate_betas (
713773 sim_state .core_profiles , sim_state .geometry
@@ -757,8 +817,13 @@ def make_post_processed_outputs(
757817 rho_q_2_1_second = safety_factor_fit_outputs .rho_q_2_1_second ,
758818 rho_q_3_1_second = safety_factor_fit_outputs .rho_q_3_1_second ,
759819 I_bootstrap = I_bootstrap ,
760- j_external = j_external ,
761- j_ohmic = j_ohmic ,
820+ j_parallel_external = j_parallel_external ,
821+ j_parallel_ohmic = j_parallel_ohmic ,
822+ j_toroidal_total = j_toroidal_total ,
823+ j_toroidal_bootstrap = j_toroidal_bootstrap ,
824+ j_toroidal_ohmic = j_toroidal_ohmic ,
825+ j_toroidal_external = j_toroidal_external ,
826+ ** j_toroidal_sources ,
762827 beta_tor = beta_tor ,
763828 beta_pol = beta_pol ,
764829 beta_N = beta_N ,
0 commit comments