from concurrent.futures import thread
from operator import xor
import numpy as np
import numba
from numba import jit, cuda
from numba.cuda import random
from numba.cuda.random import xoroshiro128p_normal_float32, create_xoroshiro128p_states
import math
import sys
import logging
[docs]
def Ry(thetas):
"""Calculates rotation matrices for the desired fiber orientations
:param thetas: List of angles (with respect to the `y`-axis) for each fiber bundle
:type thetas: int, tuple
:return: Rotation matrices for each fiber bundle.
:rtype: np.ndarray
"""
logging.info('------------------------------')
logging.info(' Rotation Matrices ')
logging.info('------------------------------')
rotation_matricies = np.zeros((len(thetas),3,3))
for i, theta in enumerate(thetas):
theta = np.radians(float(theta))
s, c = np.sin(theta), np.cos(theta)
Ry = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]])
rotation_matricies[i,:,:] = Ry
logging.info(' [[{: .2f}, {: .2f}, {: .2f}],'.format( Ry[0,0],Ry[0,1],Ry[0,2]))
logging.info(' [{: .2f}, {: .2f}, {: .2f}],'.format( Ry[1,0],Ry[1,1],Ry[1,2]))
logging.info(' [{: .2f}, {: .2f}, {: .2f}]]\n'.format( Ry[2,0],Ry[2,1],Ry[2,2]))
return rotation_matricies
[docs]
@cuda.jit(device = True,nopython = False)
def dL2(x,y,v,project_along):
"""Internal linear algebra function for projecting along transformed vectors.
:param x: `x` coordinate
:type x: float
:param y: `x` coordinate
:type y: float
:param v: Vector to project along
:type v: list
:return: Distance
:rtype: float
"""
dist = 0
proj = 0
if project_along:
for i in range(x.shape[0]):
dist += math.pow(x[i]-y[i],2)
proj += ((x[i] - y[i])*v[i])
return math.sqrt(dist - math.pow(proj,2))
else:
for i in range(x.shape[0]):
dist += math.pow(x[i]-y[i],2)
return math.sqrt(dist)
@cuda.jit(device = True, nopython = False)
def cosine_similarity(a, b):
theta = math.acos(dot(a,b))
return theta
@cuda.jit(device = True,nopython = False)
def dot(a, b):
t = 0.
for i in range(a.shape[0]):
t += a[i]*b[i]
return t
@cuda.jit(device = True,nopython = False)
def matmul(A, b):
c = cuda.local.array(shape = A.shape[0], dtype = numba.float32)
for i in range(A.shape[0]):
for j in range(A.shape[1]):
c[i] += A[i,j]*b[j]
return c
@cuda.jit(device = True,nopython = False)
def gamma(a, b, theta, ta, cp):
r"""evaluate the space curve, gamma, that traces the fiber.
:param a: the proposed spin position
:type a: numba.cuda.cudadrv.devicearray.DeviceNDArray
:param b: the fiber's principle orientation (Ry(theta).dot([0., 0., 1.]))
:type b: numba.cuda.cudadrv.devicearray.DeviceNDArray
:param theta: The orientation of the fiber bundle
:type theta: float32
:param ta: memory to write the dynamic fiber center to
:type ta: numba.cuda.cudadrv.devicearray.DeviceNDArray
:param cp: the curvature parameters of the fiber; cp[0] = kappa, cp[1] = L, cp[2] = A, cp[3] = P
:type ta: numba.cuda.cudadrv.devicearray.DeviceNDArray
:return: ta
:rtype: numba.cuda.cudadrv.devicearray.DeviceNDArray
"""
t = dot(a,b)
x = cp[2] * math.sin(math.pi*cp[0] /((1/cp[3])*cp[1])*t)
y = numba.float32(0.0)
z = numba.float32(t)
ta[0] = math.cos(theta)*x + math.sin(theta)*z
ta[1] = y
ta[2] = -math.sin(theta)*x + math.cos(theta)*z
return ta
@cuda.jit(device = True,nopython = False)
def d_gamma__d_t(a, b, theta, ta, cp):
r"""calculate the unit-normal tangent vector to the space space curve, gamma, that traces the fiber.
:param a: the proposed spin position
:type a: numba.cuda.cudadrv.devicearray.DeviceNDArray
:param b: the fiber's principle orientation (Ry(theta).dot([0., 0., 1.]))
:type b: numba.cuda.cudadrv.devicearray.DeviceNDArray
:param theta: The orientation of the fiber bundle
:type theta: float32
:param ta: memory to write the dynamic fiber center to
:type ta: numba.cuda.cudadrv.devicearray.DeviceNDArray
:param cp: the curvature parameters of the fiber; cp[0] = kappa, cp[1] = L, cp[2] = A, cp[3] = P
:type ta: numba.cuda.cudadrv.devicearray.DeviceNDArray
:return: ta
:rtype: numba.cuda.cudadrv.devicearray.DeviceNDArray
"""
t = dot(a,b)
x = cp[2] * (math.pi*cp[0] /((1/cp[3])*cp[1])) * math.cos(math.pi*cp[0] /((1/cp[3])*cp[1])*t)
y = numba.float32(0.0)
z = numba.float32(1.0)
l2_norm = math.sqrt(math.pow(x, 2) + math.pow(y,2) + math.pow(z, 2))
x = x / l2_norm
y = y / l2_norm
z = z / l2_norm
ta[0] = math.cos(theta)*x + math.sin(theta)*z
ta[1] = y
ta[2] = -math.sin(theta)*x + math.cos(theta)*z
return ta