Source code for RCAIDE.Framework.Core.Utilities

 
# RCAIDE/Core/Utilities.py
# 
# 
# Created:  Jul 2023, M. Clarke

# ----------------------------------------------------------------------------------------------------------------------
#  IMPORT
# ----------------------------------------------------------------------------------------------------------------------

# Package imports 
import numpy as np

# ----------------------------------------------------------------------------------------------------------------------
#  interp2d
# ----------------------------------------------------------------------------------------------------------------------
 
[docs] def interp2d(x,y,xp,yp,zp,fill_value= None): """ Bilinear interpolation on a grid. ``CartesianGrid`` is much faster if the data lies on a regular grid. Args: x, y: 1D arrays of point at which to interpolate. Any out-of-bounds coordinates will be clamped to lie in-bounds. xp, yp: 1D arrays of points specifying grid points where function values are provided. zp: 2D array of function values. For a function `f(x, y)` this must satisfy `zp[i, j] = f(xp[i], yp[j])` Returns: 1D array `z` satisfying `z[i] = f(x[i], y[i])`. """ ix = np.clip(np.searchsorted(xp, x, side="right"), 1, len(xp) - 1) iy = np.clip(np.searchsorted(yp, y, side="right"), 1, len(yp) - 1) # Using Wikipedia's notation (https://en.wikipedia.org/wiki/Bilinear_interpolation) z_11 = zp[ix - 1, iy - 1] z_21 = zp[ix, iy - 1] z_12 = zp[ix - 1, iy] z_22 = zp[ix, iy] z_xy1 = (xp[ix] - x) / (xp[ix] - xp[ix - 1]) * z_11 + (x - xp[ix - 1]) / ( xp[ix] - xp[ix - 1] ) * z_21 z_xy2 = (xp[ix] - x) / (xp[ix] - xp[ix - 1]) * z_12 + (x - xp[ix - 1]) / ( xp[ix] - xp[ix - 1] ) * z_22 z = (yp[iy] - y) / (yp[iy] - yp[iy - 1]) * z_xy1 + (y - yp[iy - 1]) / ( yp[iy] - yp[iy - 1] ) * z_xy2 if fill_value is not None: oob = np.logical_or( x < xp[0], np.logical_or(x > xp[-1], np.logical_or(y < yp[0], y > yp[-1])) ) z = np.where(oob, fill_value, z) return z
# ---------------------------------------------------------------------------------------------------------------------- # orientation_product # ----------------------------------------------------------------------------------------------------------------------
[docs] def orientation_product(T,Bb): """Computes the product of a tensor and a vector. Assumptions: None Source: N/A Inputs: T [-] 3-dimensional array with rotation matrix patterned along dimension zero Bb [-] 3-dimensional vector Outputs: C [-] transformed vector Properties Used: N/A """ assert T.ndim == 3 if Bb.ndim == 3: C = np.einsum('aij,ajk->aik', T, Bb ) elif Bb.ndim == 2: C = np.einsum('aij,aj->ai', T, Bb ) else: raise Exception('bad B rank') return C
# ---------------------------------------------------------------------------------------------------------------------- # orientation_transpose # ----------------------------------------------------------------------------------------------------------------------
[docs] def orientation_transpose(T): """Computes the transpose of a tensor. Assumptions: None Source: N/A Inputs: T [-] 3-dimensional array with rotation matrix patterned along dimension zero Outputs: Tt [-] transformed tensor Properties Used: N/A """ assert T.ndim == 3 Tt = np.swapaxes(T,1,2) return Tt
# ---------------------------------------------------------------------------------------------------------------------- # angles_to_dcms # ----------------------------------------------------------------------------------------------------------------------
[docs] def angles_to_dcms(rotations,sequence=(2,1,0)): """Builds an euler angle rotation matrix Assumptions: N/A Source: N/A Inputs: rotations [radians] [r1s r2s r3s], column array of rotations sequence [-] (2,1,0) (default), (2,1,2), etc.. a combination of three column indices Outputs: transform [-] 3-dimensional array with direction cosine matrices patterned along dimension zero Properties Used: N/A """ # transform map Ts = { 0:T0, 1:T1, 2:T2 } # a bunch of eyes transform = new_tensor(rotations[:,0]) # build the tranform for dim in sequence[::-1]: angs = rotations[:,dim] transform = orientation_product( transform, Ts[dim](angs) ) # done! return transform
# ---------------------------------------------------------------------------------------------------------------------- # T0 # ----------------------------------------------------------------------------------------------------------------------
[docs] def T0(a): """Rotation matrix about first axis Assumptions: N/A Source: N/A Inputs: a [radians] angle of rotation Outputs: T [-] rotation matrix Properties Used: N/A """ # T = np.array([[1, 0, 0], # [0, cos,sin], # [0,-sin,cos]]) cos = np.cos(a) sin = np.sin(a) T = new_tensor(a) T[:,1,1] = cos T[:,1,2] = sin T[:,2,1] = -sin T[:,2,2] = cos return T
# ---------------------------------------------------------------------------------------------------------------------- # T1 # ----------------------------------------------------------------------------------------------------------------------
[docs] def T1(a): """Rotation matrix about second axis Assumptions: N/A Source: N/A Inputs: a [radians] angle of rotation Outputs: T [-] rotation matrix Properties Used: N/A """ # T = np.array([[cos,0,-sin], # [0 ,1, 0], # [sin,0, cos]]) cos = np.cos(a) sin = np.sin(a) T = new_tensor(a) T[:,0,0] = cos T[:,0,2] = -sin T[:,2,0] = sin T[:,2,2] = cos return T
# ---------------------------------------------------------------------------------------------------------------------- # T2 # ----------------------------------------------------------------------------------------------------------------------
[docs] def T2(a): """Rotation matrix about third axis Assumptions: N/A Source: N/A Inputs: a [radians] angle of rotation Outputs: T [-] rotation matrix Properties Used: N/A """ # T = np.array([[cos ,sin,0], # [-sin,cos,0], # [0 ,0 ,1]]) cos = np.cos(a) sin = np.sin(a) T = new_tensor(a) T[:,0,0] = cos T[:,0,1] = sin T[:,1,0] = -sin T[:,1,1] = cos return T
# ---------------------------------------------------------------------------------------------------------------------- # new_tensor # ----------------------------------------------------------------------------------------------------------------------
[docs] def new_tensor(a): """Initializes the required tensor. Able to handle imaginary values. Assumptions: N/A Source: N/A Inputs: a [radians] angle of rotation Outputs: T [-] 3-dimensional array with identity matrix patterned along dimension zero Properties Used: N/A """ assert a.ndim == 1 n_a = len(a) T = np.eye(3) if a.dtype is np.dtype('complex'): T = T + 0j T = np.resize(T,[n_a,3,3]) return T