Source code for torx.vector.vector_operations_m
"""Functions to operator on vectors."""
import numpy as np
import xarray as xr
from torx.autodoc_decorators_m import autodoc_function
[docs]
@autodoc_function
def vector_magnitude(input_array: xr.DataArray):
"""Return the vector magnitude."""
return np.sqrt(vector_dot(input_array, input_array))
[docs]
@autodoc_function
def poloidal_vector_magnitude(input_array: xr.DataArray):
"""Return the vector magnitude of the poloidal component."""
return vector_magnitude(input_array.sel(vector=["eR", "eZ"]))
[docs]
@autodoc_function
def vector_dot(input_a: xr.DataArray, input_b: xr.DataArray):
"""Return the dot product of two vectors."""
assert ("vector" in input_a.dims) and ("vector" in input_b.dims)
assert input_a.vector.size == input_b.vector.size
dims = list(input_a.dims)
dims.remove("vector")
a_attrs = input_a.attrs.copy()
b_attrs = input_b.attrs.copy()
# Handle arbitrary vector length
result = input_a.isel(vector=0) * input_b.isel(vector=0)
for i in np.arange(1, input_a.vector.size):
result += input_a.isel(vector = i) * input_b.isel(vector = i)
if "norm" in a_attrs and "norm" in b_attrs:
result.attrs["norm"] = a_attrs["norm"] * b_attrs["norm"]
return result.transpose(*dims).drop_vars("vector")
[docs]
@autodoc_function
def vector_cross(input_a, input_b):
"""
Return the cross product of two vectors.
vec(a) cross vec(b) = mag(a) mag(b) sin(theta) vec(n)
where theta is the angle between vec(a) and vec(b) and
where vec(n) is a unit vector perpendicular to both vec(a) and vec(b)
The sign of vec(b) is given by right-hand-rule (i.e. if 'a' is index
finger, 'b' is middle finger, 'n' is thumb, or alternatively if 'a'
is thumb, 'b' is index finger, 'n' is middle finger).
"""
dask_gufunc_kwargs_dict = dict(output_sizes=dict(vector=3))
return xr.apply_ufunc(
np.cross,
input_a,
input_b,
input_core_dims=[["vector"], ["vector"]],
output_core_dims=[["vector"]],
dask="parallelized",
output_dtypes=[input_a.dtype],
dask_gufunc_kwargs=dask_gufunc_kwargs_dict
)
[docs]
@autodoc_function
def unit_vector(input_array: xr.DataArray):
"""Return the unit vector in the direction of the input array."""
return input_array / vector_magnitude(input_array)
[docs]
@autodoc_function
def scalar_projection(input_a: xr.DataArray, input_b: xr.DataArray):
"""
Return the magnitude of input_a which is parallel to input_b.
See https://en.wikipedia.org/wiki/Vector_projection for notation.
scalar_projection is 'a_1'.
"""
return vector_dot(input_a, unit_vector(input_b))
[docs]
@autodoc_function
def vector_projection(input_a: xr.DataArray, input_b: xr.DataArray):
"""
Return a projected vector.
The result is the orthogonal projection of input_a onto a
straight line parallel to input_b. It is parallel to input_b.
See https://en.wikipedia.org/wiki/Vector_projection for notation.
vector_rejection is 'vec(a)_1'.
"""
return scalar_projection(input_a, input_b) * unit_vector(input_b)
[docs]
@autodoc_function
def vector_rejection(input_a: xr.DataArray, input_b: xr.DataArray):
"""
Return a rejected vector.
The result is the projection of input_a onto a straight
line orthogonal to input_b.
See https://en.wikipedia.org/wiki/Vector_projection for notation.
vector_rejection is 'vec(a)_2'.
"""
return input_a - vector_projection(input_a, input_b)