-
Notifications
You must be signed in to change notification settings - Fork 0
/
upscale.py
95 lines (76 loc) · 3.58 KB
/
upscale.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import boutdata
from boututils.datafile import DataFile
import numpy as np
from scipy.ndimage.interpolation import map_coordinates
from scipy.interpolate import griddata
from vtk import vtkPoints
from vtk.numpy_interface import algorithms as algs
from vtk.numpy_interface import dataset_adapter as dsa
from paraview import numpy_support
def upscale(field, gridfile, upscale_factor=4):
"""Increase the resolution in y of field along the FCI maps from
gridfile.
"""
# Read the FCI maps from the gridfile
with DataFile(gridfile) as grid:
xt_prime = grid.read("forward_xt_prime")
zt_prime = grid.read("forward_zt_prime")
# The field should be the same shape as the grid
if field.shape != xt_prime.shape:
try:
field = field.reshape(xt_prime.T.shape).T
except ValueError:
raise ValueError("Field, {}, must be same shape as grid, {}"
.format(field.shape, xt_prime.shape))
# Get the shape of the grid
nx, ny, nz = xt_prime.shape
index_coords = np.mgrid[0:nx, 0:ny, 0:nz]
# We use the forward maps, so get the y-index of the *next* y-slice
yup_3d = index_coords[1,...] + 1
yup_3d[:,-1,:] = 0
# Index space coordinates of the field line end points
end_points = np.array([xt_prime, yup_3d, zt_prime])
# Interpolation of the field at the end points
field_prime = map_coordinates(field, end_points)
# This is a 4D array where the first dimension is the start/end of
# the field line
field_aligned = np.array([field, field_prime])
# x, z coords at start/end of field line
x_start_end = np.array([index_coords[0,...], xt_prime])
z_start_end = np.array([index_coords[2,...], zt_prime])
# Parametric points along the field line
midpoints = np.linspace(0, 1, upscale_factor, endpoint=False)
# Need to make this 4D as well
new_points = np.tile(midpoints[:,np.newaxis,np.newaxis,np.newaxis], [nx, ny, nz])
# Index space coordinates of our upscaled field
index_4d = np.mgrid[0:upscale_factor,0:nx,0:ny,0:nz]
hires_points = np.array([new_points, index_4d[1,...], index_4d[2,...], index_4d[3,...]])
# Upscale the field
hires_field = map_coordinates(field_aligned, hires_points)
# Linearly interpolate the x, z coordinates of the field lines
hires_x = map_coordinates(x_start_end, hires_points)
hires_z = map_coordinates(z_start_end, hires_points)
def twizzle(array):
"""Transpose and reshape the output of map_coordinates to
be 3D
"""
return array.transpose((1, 2, 0, 3)).reshape((nx, upscale_factor*ny, nz))
# Rearrange arrays to be 3D
hires_field = twizzle(hires_field)
hires_x = twizzle(hires_x)
hires_z = twizzle(hires_z)
# Interpolate from field line sections onto grid
hires_grid_field = np.zeros( (nx, upscale_factor*ny, nz) )
hires_index_coords = np.mgrid[0:nx, 0:ny:1./upscale_factor, 0:nz]
grid_points = (hires_index_coords[0,:,0,:], hires_index_coords[2,:,0,:])
def y_first(array):
"""Put the middle index first
"""
return array.transpose((0, 2, 1))
# The hires data is unstructed only in (x,z), interpolate onto
# (x,z) grid for each y-slice individually
for k, (x_points, z_points, f_slice) in enumerate(zip(y_first(hires_x).T, y_first(hires_z).T, y_first(hires_field).T)):
points = np.column_stack((x_points.flat, z_points.flat))
hires_grid_field[:,k,:] = griddata(points, f_slice.flat, grid_points,
method='linear', fill_value=0.0)
return hires_grid_field