Skip to content

Commit c4730de

Browse files
jcitrinTorax team
authored andcommitted
Refactor as preparation for multiple options of ion_cyclotron_source models.
Build base infrastructure in new ion_cyclotron_source subpackage, and set up dedicated toric_nn model. PiperOrigin-RevId: 906551698
1 parent cc46db9 commit c4730de

9 files changed

Lines changed: 773 additions & 599 deletions

File tree

torax/_src/imas_tools/input/core_sources.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414
"""Useful functions to load IMAS core_sources IDSs."""
15+
1516
from collections.abc import Mapping, Sequence
1617
import dataclasses
1718
from typing import Any, NamedTuple, Self
@@ -26,12 +27,12 @@
2627
from torax._src.sources import electron_cyclotron_source
2728
from torax._src.sources import fusion_heat_source
2829
from torax._src.sources import gas_puff_source
29-
from torax._src.sources import ion_cyclotron_source
3030
from torax._src.sources import ohmic_heat_source
3131
from torax._src.sources import pellet_source
3232
from torax._src.sources import qei_source
3333
from torax._src.sources import source as source_module
3434
from torax._src.sources.impurity_radiation_heat_sink import impurity_radiation_heat_sink
35+
from torax._src.sources.ion_cyclotron_source import base as ion_cyclotron_source
3536

3637

3738
class _SourceMappingEntry(NamedTuple):
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2026 DeepMind Technologies Limited
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Ion-cyclotron resonance heating (ICRH) source models."""
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Copyright 2026 DeepMind Technologies Limited
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""Base infrastructure for ion-cyclotron resonance heating (ICRH) sources."""
15+
16+
from collections.abc import Sequence
17+
import dataclasses
18+
from typing import Annotated, ClassVar
19+
20+
from jax import numpy as jnp
21+
from torax._src.fvm import cell_variable
22+
from torax._src.geometry import geometry
23+
from torax._src.physics import fast_ion as fast_ion_lib
24+
from torax._src.sources import base as source_base
25+
from torax._src.sources import runtime_params as source_runtime_params_lib
26+
from torax._src.sources import source
27+
from torax._src.torax_pydantic import torax_pydantic
28+
29+
# pylint: disable=invalid-name
30+
31+
# Default value for the model function to be used for the ion cyclotron
32+
# source. This is also used as an identifier for the model function in
33+
# the default source config for Pydantic to "discriminate" against.
34+
DEFAULT_MODEL_FUNCTION_NAME: str = 'toric_nn'
35+
36+
37+
def build_fast_ions(
38+
source_name: str,
39+
geo: geometry.Geometry,
40+
fast_ions: Sequence[fast_ion_lib.FastIon] = (),
41+
) -> tuple[fast_ion_lib.FastIon, ...]:
42+
"""Builds a complete FastIon tuple for all supported species.
43+
44+
Takes a list of computed FastIon objects (for a subset of species) and
45+
produces a full tuple covering all species in
46+
``fast_ion_lib.FAST_ION_SPECIES``.
47+
Species not present in the input list are filled with zero density and
48+
temperature.
49+
50+
Args:
51+
source_name: The name of the source.
52+
geo: Geometry.
53+
fast_ions: Computed FastIon objects for a subset of species.
54+
55+
Returns:
56+
Tuple of FastIon objects, one per species in
57+
``fast_ion_lib.FAST_ION_SPECIES``, in order.
58+
"""
59+
computed = {fi.species: fi for fi in fast_ions}
60+
zeros = jnp.zeros_like(geo.rho)
61+
result = []
62+
for species in fast_ion_lib.FAST_ION_SPECIES:
63+
if species in computed:
64+
result.append(computed[species])
65+
else:
66+
result.append(
67+
fast_ion_lib.FastIon(
68+
species=species,
69+
source=source_name,
70+
n=cell_variable.CellVariable(
71+
value=zeros,
72+
face_centers=geo.rho_face_norm,
73+
right_face_grad_constraint=None,
74+
right_face_constraint=jnp.zeros(()),
75+
),
76+
T=cell_variable.CellVariable(
77+
value=zeros,
78+
face_centers=geo.rho_face_norm,
79+
right_face_grad_constraint=None,
80+
right_face_constraint=jnp.zeros(()),
81+
),
82+
)
83+
)
84+
return tuple(result)
85+
86+
87+
@dataclasses.dataclass(kw_only=True, frozen=True, eq=False)
88+
class IonCyclotronSource(source.Source):
89+
"""Ion cyclotron source."""
90+
91+
SOURCE_NAME: ClassVar[str] = 'icrh'
92+
AFFECTED_CORE_PROFILES: ClassVar[tuple[source.AffectedCoreProfile, ...]] = (
93+
source.AffectedCoreProfile.TEMP_ION,
94+
source.AffectedCoreProfile.TEMP_EL,
95+
source.AffectedCoreProfile.FAST_IONS,
96+
)
97+
98+
@classmethod
99+
def zero_fast_ions(
100+
cls,
101+
geo: geometry.Geometry,
102+
) -> tuple[fast_ion_lib.FastIon, ...]:
103+
return build_fast_ions(source_name=cls.SOURCE_NAME, geo=geo)
104+
105+
106+
class IonCyclotronSourceConfig(source_base.SourceModelBase):
107+
"""Base configuration for IonCyclotronSource.
108+
109+
This base class contains fields common to all ICRH model implementations.
110+
Subclasses implement the specific model logic,and must override `model_name`
111+
with a `Literal` to serve as discriminator.
112+
113+
Attributes:
114+
model_name: Discriminator field for Pydantic. Subclasses must override with
115+
a `Literal` value.
116+
P_total: Total heating power [W].
117+
absorption_fraction: Fraction of absorbed power.
118+
mode: Defines how the source values are computed.
119+
minority_species: Optional symbol of the minority species (e.g., 'He3').
120+
When specified, the minority concentration is extracted from
121+
plasma_composition. The species can be either a main ion or an impurity.
122+
"""
123+
124+
model_name: Annotated[str, torax_pydantic.JAX_STATIC] = ''
125+
# TODO(b/434175938): Remove default source amplitudes in V2.
126+
P_total: torax_pydantic.TimeVaryingScalar = torax_pydantic.ValidatedDefault(
127+
10e6
128+
)
129+
absorption_fraction: torax_pydantic.PositiveTimeVaryingScalar = (
130+
torax_pydantic.ValidatedDefault(1.0)
131+
)
132+
mode: Annotated[source_runtime_params_lib.Mode, torax_pydantic.JAX_STATIC] = (
133+
source_runtime_params_lib.Mode.MODEL_BASED
134+
)
135+
# TODO(b/434175938): Make minority_species a required field in V2.
136+
minority_species: Annotated[str | None, torax_pydantic.JAX_STATIC] = None
137+
138+
def build_source(self) -> IonCyclotronSource:
139+
return IonCyclotronSource(model_func=self.model_func)

0 commit comments

Comments
 (0)