Coverage for tcvx21/grillix_post/observables/parallel_gradient_m.py: 100%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import xarray as xr
2import numpy as np
3from pathlib import Path
4from tcvx21.grillix_post.components import FieldlineTracer
5from tcvx21.grillix_post.lineouts import Lineout
6xr.set_options(keep_attrs=True)
9def initialise_lineout_for_parallel_gradient(lineout, grid, equi, norm, npol, stored_trace: Path=None):
10 """
11 Traces to find the forward and reverse lineouts for a given lineout
13 Expensive! Needs to be done once per lineout that you want to take gradients with
14 """
15 fieldline_tracer = FieldlineTracer(equi)
17 try:
18 print(f"Attempting to read stored trace from {stored_trace}")
19 ds = xr.open_dataset(stored_trace)
20 assert np.allclose(ds['lineout_x'], lineout.r_points)
21 assert np.allclose(ds['lineout_y'], lineout.z_points)
22 except (FileNotFoundError, ValueError):
23 forward_trace, reverse_trace = \
24 fieldline_tracer.find_neighbouring_points(lineout.r_points, lineout.z_points,
25 n_toroidal_planes=int(npol))
27 ds = xr.Dataset(data_vars=dict(
28 forward_x=('points', forward_trace[:, 0]),
29 forward_y=('points', forward_trace[:, 1]),
30 forward_l=('points', forward_trace[:, 2]),
31 reverse_x=('points', reverse_trace[:, 0]),
32 reverse_y=('points', reverse_trace[:, 1]),
33 reverse_l=('points', reverse_trace[:, 2]),
34 lineout_x=('points', lineout.r_points),
35 lineout_y=('points', lineout.z_points),
36 ))
38 if stored_trace is not None:
39 if stored_trace.exists(): stored_trace.unlink()
40 ds.to_netcdf(stored_trace)
42 lineout.forward_lineout = Lineout(ds['forward_x'], ds['forward_y'])
43 lineout.forward_lineout.setup_interpolation_matrix(grid, use_source_points=True)
44 lineout.reverse_lineout = Lineout(ds['reverse_x'], ds['reverse_y'])
45 lineout.reverse_lineout.setup_interpolation_matrix(grid, use_source_points=True)
47 lineout.forward_distance = xr.DataArray(ds['forward_l'],
48 dims='interp_points').assign_attrs(norm=norm.R0)
49 lineout.reverse_distance = xr.DataArray(ds['reverse_l'],
50 dims='interp_points').assign_attrs(norm=norm.R0)
53def compute_parallel_gradient(lineout, field):
54 """
55 Computes the parallel gradient via centred differences
57 Note that you should multiply this by the penalisation direction function to get the direction 'towards the
58 wall'. This isn't quite the same as projecting onto the wall normal, but for computing the parallel
59 heat flux this is actually more helpful
60 """
62 assert hasattr(lineout, 'forward_lineout') and hasattr(lineout, 'reverse_lineout'), \
63 f"Have to call initialise_lineout_for_parallel_gradient on lineout before trying to compute_parallel_gradient"
65 parallel_gradients = [compute_gradient_on_plane(lineout, field, plane)
66 for plane in range(field.sizes['phi'])]
68 return xr.concat(parallel_gradients, dim='phi')
71def compute_gradient_on_plane(lineout, field, plane):
72 """Computes the parallel gradient on a single plane"""
74 forward_value = lineout.forward_lineout.interpolate(field.isel(phi=np.mod(plane+1, field.sizes['phi'])))
75 reverse_value = lineout.forward_lineout.interpolate(field.isel(phi=np.mod(plane-1, field.sizes['phi'])))
77 two_plane_distance = (lineout.forward_distance - lineout.reverse_distance)
79 centred_difference = forward_value - reverse_value
80 return (centred_difference/two_plane_distance).\
81 assign_coords(phi=plane).\
82 assign_attrs(norm=field.norm/two_plane_distance.norm)