|
13 | 13 | # limitations under the License. |
14 | 14 | """Common formulas used in neoclassical models.""" |
15 | 15 |
|
16 | | -import jax |
17 | 16 | import jax.numpy as jnp |
18 | 17 | from torax._src import array_typing |
19 | 18 | from torax._src import constants |
20 | 19 | from torax._src import math_utils |
21 | 20 | from torax._src.fvm import cell_variable |
22 | 21 | from torax._src.geometry import geometry as geometry_lib |
23 | 22 | from torax._src.neoclassical.bootstrap_current import base as bootstrap_current_base |
24 | | -from torax._src.physics import collisions |
25 | 23 |
|
26 | 24 |
|
27 | 25 | # pylint: disable=invalid-name |
@@ -133,8 +131,7 @@ def calculate_nu_i_star( |
133 | 131 | ) |
134 | 132 |
|
135 | 133 |
|
136 | | -# Functions to calculate the neoclassical poloidal velocity. |
137 | | -def _calculate_neoclassical_k_neo( |
| 134 | +def calculate_neoclassical_k_neo( |
138 | 135 | nu_star: array_typing.FloatScalar, epsilon: array_typing.FloatScalar |
139 | 136 | ): |
140 | 137 | """Calculates the neoclassical coefficient k_neo. |
@@ -177,94 +174,6 @@ def _calculate_neoclassical_k_neo( |
177 | 174 | # See Sauter (1999) Eq. 17a-17b |
178 | 175 |
|
179 | 176 |
|
180 | | -@jax.jit |
181 | | -def calculate_poloidal_velocity( |
182 | | - T_i: cell_variable.CellVariable, |
183 | | - n_i: array_typing.FloatVectorFace, |
184 | | - q: array_typing.FloatVectorFace, |
185 | | - Z_eff: array_typing.FloatVectorFace, |
186 | | - Z_i: array_typing.FloatVectorFace, |
187 | | - B_tor: array_typing.FloatVectorFace, |
188 | | - B_total_squared: array_typing.FloatVectorFace, |
189 | | - geo: geometry_lib.Geometry, |
190 | | - poloidal_velocity_multiplier: array_typing.FloatScalar = 1.0, |
191 | | -) -> cell_variable.CellVariable: |
192 | | - """Computes the neoclassical ion poloidal velocity profile. |
193 | | -
|
194 | | - Implementing eq.33 from |
195 | | - Y. B. Kim , P. H. Diamond , R. J. Groebner. |
196 | | - "Neoclassical poloidal and toroidal rotation in tokamaks" |
197 | | - Phys. Fluids B 3, 2050–2060 (1991) |
198 | | - https://doi.org/10.1063/1.859671 |
199 | | -
|
200 | | - Eq. 33 can be simplified to the following form in SI units: |
201 | | - v_pol = k_neo * (dT/dr) * (B_tor / <B^2>) / (Z * e) |
202 | | -
|
203 | | - Args: |
204 | | - T_i: Ion temperature as a cell variable [keV]. |
205 | | - n_i: Ion density on the face grid [m^-3]. |
206 | | - q: Safety factor on the face grid. |
207 | | - Z_eff: Effective charge on the face grid. |
208 | | - Z_i: Main ion charge on the face grid. |
209 | | - B_tor: Toroidal magnetic field on the face grid [T]. |
210 | | - B_total_squared: Total magnetic field (toroidal + poloidal) on the face grid |
211 | | - [T]. |
212 | | - geo: Geometry |
213 | | - poloidal_velocity_multiplier: A multiplier to apply to the poloidal |
214 | | - velocity. |
215 | | -
|
216 | | - Returns: |
217 | | - v_pol : Poloidal velocity profile [m/s]. |
218 | | - """ |
219 | | - # Note: all computations are performed on the face grid. |
220 | | - |
221 | | - T_i_face = T_i.face_value() |
222 | | - epsilon = geo.epsilon_face |
223 | | - |
224 | | - # Calculate Neoclassical Coefficient k_i |
225 | | - log_lambda_ii = collisions.calculate_log_lambda_ii( |
226 | | - T_i_face, # pyrefly: ignore[bad-argument-type] |
227 | | - n_i, # pyrefly: ignore[bad-argument-type] |
228 | | - Z_eff, # pyrefly: ignore[bad-argument-type] |
229 | | - ) |
230 | | - nu_i_star = calculate_nu_i_star( |
231 | | - q=q, |
232 | | - geo=geo, |
233 | | - n_i=n_i, |
234 | | - T_i=T_i_face, # pyrefly: ignore[bad-argument-type] |
235 | | - Z_eff=Z_eff, |
236 | | - log_lambda_ii=log_lambda_ii, |
237 | | - ) |
238 | | - k_neo = _calculate_neoclassical_k_neo(nu_i_star, epsilon) |
239 | | - |
240 | | - # Calculate Radial Temperature Gradient (dT/dr) |
241 | | - grad_Ti = ( |
242 | | - T_i.face_grad( |
243 | | - x=geo.r_mid, x_left=geo.r_mid_face[0], x_right=geo.r_mid_face[-1] |
244 | | - ) |
245 | | - * constants.CONSTANTS.keV_to_J |
246 | | - ) # [J/m] |
247 | | - |
248 | | - # Calculate Poloidal Velocity |
249 | | - # v_pol = k_i * (dT/dr) * (B_tor / <B^2>) / (Z * e) |
250 | | - B_total_squared_safe = jnp.maximum(B_total_squared, constants.CONSTANTS.eps) |
251 | | - v_pol = ( |
252 | | - k_neo |
253 | | - * grad_Ti |
254 | | - * (B_tor / B_total_squared_safe) |
255 | | - / (constants.CONSTANTS.q_e * Z_i) |
256 | | - ) |
257 | | - |
258 | | - v_pol = poloidal_velocity_multiplier * v_pol |
259 | | - |
260 | | - return cell_variable.CellVariable( |
261 | | - value=geometry_lib.face_to_cell(v_pol), |
262 | | - face_centers=geo.rho_face_norm, |
263 | | - right_face_constraint=v_pol[-1], |
264 | | - right_face_grad_constraint=None, |
265 | | - ) |
266 | | - |
267 | | - |
268 | 177 | def calculate_analytic_bootstrap_current( |
269 | 178 | *, |
270 | 179 | bootstrap_multiplier: float, |
|
0 commit comments