lattices.py using now the c module

Former-commit-id: 52cecb23a8757726bcac796417ebade8242d687a
This commit is contained in:
Marek Nečada 2017-04-27 13:12:52 +03:00
parent 796c7d7289
commit e2a2100b57
4 changed files with 116 additions and 6 deletions

View File

@ -6,7 +6,7 @@ nx = np.newaxis
import time import time
import scipy import scipy
import sys import sys
from qpms_c import get_mn_y # TODO be explicit about what is imported from qpms_c import get_mn_y, trans_calculator # TODO be explicit about what is imported
from .qpms_p import cart2sph, nelem2lMax, Ã, B̃ # TODO be explicit about what is imported from .qpms_p import cart2sph, nelem2lMax, Ã, B̃ # TODO be explicit about what is imported
def _time_b(active = True, name = None, step = None): def _time_b(active = True, name = None, step = None):
@ -83,6 +83,7 @@ class Scattering(object):
self.N = positions.shape[0] self.N = positions.shape[0]
self.k_0 = k_0 self.k_0 = k_0
self.lMax = lMax if lMax else nelem2lMax(TMatrices.shape[-1]) self.lMax = lMax if lMax else nelem2lMax(TMatrices.shape[-1])
self.tc = trans_calculator(lMax)
nelem = lMax * (lMax + 2) #! nelem = lMax * (lMax + 2) #!
self.nelem = nelem #! self.nelem = nelem #!
self.prepared = False self.prepared = False
@ -91,7 +92,7 @@ class Scattering(object):
def prepare(self, keep_interaction_matrix = False, verbose=False): def prepare(self, keep_interaction_matrix = False, verbose=False):
btime = _time_b(verbose) btime = _time_b(verbose)
if not self.prepared: if not self.prepared:
if not self.interaction_matrix: if self.interaction_matrix is None:
self.build_interaction_matrix(verbose=verbose) self.build_interaction_matrix(verbose=verbose)
self.lupiv = scipy.linalg.lu_factor(self.interaction_matrix,overwrite_a = not keep_interaction_matrix) self.lupiv = scipy.linalg.lu_factor(self.interaction_matrix,overwrite_a = not keep_interaction_matrix)
if not keep_interaction_matrix: if not keep_interaction_matrix:
@ -106,6 +107,7 @@ class Scattering(object):
nelem = len(my) nelem = len(my)
leftmatrix = np.zeros((N,2,nelem,N,2,nelem), dtype=complex) leftmatrix = np.zeros((N,2,nelem,N,2,nelem), dtype=complex)
sbtime = _time_b(verbose, step = 'Calculating interparticle translation coefficients') sbtime = _time_b(verbose, step = 'Calculating interparticle translation coefficients')
"""
for i in range(N): for i in range(N):
for j in range(N): for j in range(N):
for yi in range(nelem): for yi in range(nelem):
@ -118,6 +120,20 @@ class Scattering(object):
leftmatrix[j,1,yj,i,1,yi] = a leftmatrix[j,1,yj,i,1,yi] = a
leftmatrix[j,0,yj,i,1,yi] = b leftmatrix[j,0,yj,i,1,yi] = b
leftmatrix[j,1,yj,i,0,yi] = b leftmatrix[j,1,yj,i,0,yi] = b
"""
kdji = cart2sph(self.positions[:,nx,:] - self.positions[nx,:,:])
kdji[:,:,0] *= self.k_0
# get_AB array structure: [j,yj,i,yi]
a, b = self.tc.get_AB(my[nx,:,nx,nx],ny[nx,:,nx,nx],my[nx,nx,nx,:],ny[nx,nx,nx,:],
(kdji[:,:,0])[:,nx,:,nx], (kdji[:,:,1])[:,nx,:,nx], (kdji[:,:,2])[:,nx,:,nx],
False,self.J_scat)
mask = np.broadcast_to(np.eye(N,dtype=bool)[:,nx,:,nx],(N,nelem,N,nelem))
a[mask] = 0 # no self-translations
b[mask] = 0
leftmatrix[:,0,:,:,0,:] = a
leftmatrix[:,1,:,:,1,:] = a
leftmatrix[:,0,:,:,1,:] = b
leftmatrix[:,1,:,:,0,:] = b
_time_e(sbtime, verbose, step = 'Calculating interparticle translation coefficients') _time_e(sbtime, verbose, step = 'Calculating interparticle translation coefficients')
# at this point, leftmatrix is the translation matrix # at this point, leftmatrix is the translation matrix
n2id = np.identity(2*nelem) n2id = np.identity(2*nelem)
@ -199,6 +215,7 @@ class Scattering_2D_zsym(Scattering):
self.my, self.ny = get_mn_y(self.lMax) self.my, self.ny = get_mn_y(self.lMax)
self.TE_NMz = (self.my + self.ny) % 2 self.TE_NMz = (self.my + self.ny) % 2
self.TM_NMz = 1 - self.TE_NMz self.TM_NMz = 1 - self.TE_NMz
self.tc = trans_calculator(lMax)
# TODO možnost zadávat T-matice rovnou ve zhuštěné podobě # TODO možnost zadávat T-matice rovnou ve zhuštěné podobě
TMatrices_TE = TMatrices[...,self.TE_NMz[:,nx],self.TE_yz[:,nx],self.TE_NMz[nx,:],self.TE_yz[nx,:]] TMatrices_TE = TMatrices[...,self.TE_NMz[:,nx],self.TE_yz[:,nx],self.TE_NMz[nx,:],self.TE_yz[nx,:]]
TMatrices_TM = TMatrices[...,self.TM_NMz[:,nx],self.TM_yz[:,nx],self.TM_NMz[nx,:],self.TM_yz[nx,:]] TMatrices_TM = TMatrices[...,self.TM_NMz[:,nx],self.TM_yz[:,nx],self.TM_NMz[nx,:],self.TM_yz[nx,:]]
@ -216,13 +233,13 @@ class Scattering_2D_zsym(Scattering):
btime = _time_b(verbose) btime = _time_b(verbose)
if (TE_or_TM == 0): #TE if (TE_or_TM == 0): #TE
if not self.prepared_TE: if not self.prepared_TE:
if not self.interaction_matrix_TE: if self.interaction_matrix_TE is None:
self.build_interaction_matrix(0, verbose) self.build_interaction_matrix(0, verbose)
self.lupiv_TE = scipy.linalg.lu_factor(self.interaction_matrix_TE, overwrite_a = not keep_interaction_matrix) self.lupiv_TE = scipy.linalg.lu_factor(self.interaction_matrix_TE, overwrite_a = not keep_interaction_matrix)
self.prepared_TE = True self.prepared_TE = True
if (TE_or_TM == 1): #TM if (TE_or_TM == 1): #TM
if not self.prepared_TM: if not self.prepared_TM:
if not self.interaction_matrix_TM: if self.interaction_matrix_TM is None:
self.build_interaction_matrix(1, verbose) self.build_interaction_matrix(1, verbose)
self.lupiv_TM = scipy.linalg.lu_factor(self.interaction_matrix_TM, overwrite_a = not keep_interaction_matrix) self.lupiv_TM = scipy.linalg.lu_factor(self.interaction_matrix_TM, overwrite_a = not keep_interaction_matrix)
self.prepared_TM = True self.prepared_TM = True
@ -249,9 +266,29 @@ class Scattering_2D_zsym(Scattering):
EoMl = (1,) EoMl = (1,)
elif (TE_or_TM is None): elif (TE_or_TM is None):
EoMl = (0,1) EoMl = (0,1)
sbtime = _time_b(verbose, step = 'Calculating interparticle translation coefficients')
kdji = cart2sph(self.positions[:,nx,:] - self.positions[nx,:,:])
kdji[:,:,0] *= self.k_0
# get_AB array structure: [j,yj,i,yi]
# FIXME I could save some memory by calculating only half of these coefficients
a, b = self.tc.get_AB(my[nx,:,nx,nx],ny[nx,:,nx,nx],my[nx,nx,nx,:],ny[nx,nx,nx,:],
(kdji[:,:,0])[:,nx,:,nx], (kdji[:,:,1])[:,nx,:,nx], (kdji[:,:,2])[:,nx,:,nx],
False,self.J_scat)
mask = np.broadcast_to(np.eye(N,dtype=bool)[:,nx,:,nx],(N,nelem,N,nelem))
a[mask] = 0 # no self-translations
b[mask] = 0
print(np.isnan(np.min(a)))
_time_e(sbtime, verbose, step = 'Calculating interparticle translation coefficients')
for EoM in EoMl: for EoM in EoMl:
leftmatrix = np.zeros((N,nelem,N,nelem), dtype=complex) leftmatrix = np.zeros((N,nelem,N,nelem), dtype=complex)
sbtime = _time_b(verbose, step = 'Calculating interparticle translation coefficients, T%s part' % ('M' if EoM else 'E')) y = np.arange(nelem)
yi = y[nx,nx,nx,:]
yj = y[nx,:,nx,nx]
mask = np.broadcast_to((((yi - yj) % 2) == 0),(N,nelem,N,nelem))
leftmatrix[mask] = a[mask]
mask = np.broadcast_to((((yi - yj) % 2) != 0),(N,nelem,N,nelem))
leftmatrix[mask] = b[mask]
""" # we use to calculate the AB coefficients here
for i in range(N): for i in range(N):
for j in range(i): for j in range(i):
for yi in range(nelem): for yi in range(nelem):
@ -264,6 +301,7 @@ class Scattering_2D_zsym(Scattering):
leftmatrix[j,yj,i,yi] = tr leftmatrix[j,yj,i,yi] = tr
leftmatrix[i,yi,j,yj] = tr if (0 == (my[yj]+my[yi]) % 2) else -tr leftmatrix[i,yi,j,yj] = tr if (0 == (my[yj]+my[yi]) % 2) else -tr
_time_e(sbtime, verbose, step = 'Calculating interparticle translation coefficients, T%s part' % ('M' if EoM else 'E')) _time_e(sbtime, verbose, step = 'Calculating interparticle translation coefficients, T%s part' % ('M' if EoM else 'E'))
"""
for j in range(N): for j in range(N):
leftmatrix[j] = - np.tensordot(self.TMatrices_TM[j] if EoM else self.TMatrices_TE[j],leftmatrix[j], leftmatrix[j] = - np.tensordot(self.TMatrices_TM[j] if EoM else self.TMatrices_TE[j],leftmatrix[j],
axes = ([-1],[0])) axes = ([-1],[0]))
@ -273,6 +311,8 @@ class Scattering_2D_zsym(Scattering):
self.interaction_matrix_TE = leftmatrix self.interaction_matrix_TE = leftmatrix
if EoM == 1: if EoM == 1:
self.interaction_matrix_TM = leftmatrix self.interaction_matrix_TM = leftmatrix
a = None
b = None
_time_e(btime, verbose) _time_e(btime, verbose)
def scatter_partial(self, TE_or_TM, pq_0, verbose = False): def scatter_partial(self, TE_or_TM, pq_0, verbose = False):

View File

@ -5,6 +5,8 @@ import numpy as np
cimport numpy as np cimport numpy as np
cimport cython cimport cython
from cython.parallel cimport parallel, prange from cython.parallel cimport parallel, prange
#cimport openmp
#openmp.omp_set_dynamic(1)
## Auxillary function for retrieving the "meshgrid-like" indices; inc. nmax ## Auxillary function for retrieving the "meshgrid-like" indices; inc. nmax
@cython.boundscheck(False) @cython.boundscheck(False)
@ -371,10 +373,65 @@ cdef void trans_calculator_loop_E_C_DD_iiiidddii_As_lllldddbl_DD(char **args, np
# FIXME ERROR HANDLING!!! requires correct import and different data passed (see scipy's generated ufuncs) # FIXME ERROR HANDLING!!! requires correct import and different data passed (see scipy's generated ufuncs)
# sf_error.check_fpe(func_name) # sf_error.check_fpe(func_name)
@cython.boundscheck(False)
@cython.wraparound(False)
cdef void trans_calculator_parallel_loop_E_C_DD_iiiidddii_As_lllldddbl_DD(char **args, np.npy_intp *dims, np.npy_intp *steps, void *data) nogil:
# E stands for error value (int), C for qpms_trans_calculator*
cdef np.npy_intp i, n = dims[0]
cdef void *func = (<trans_calculator_get_X_data_t*>data)[0].cmethod
#cdef complex double (*func)(qpms_trans_calculator*, double complex *, double complex *, int, int, int, int, double, double, double, int, int) nogil = (<trans_calculator_get_X_data_t*>data)[0].cmethod
cdef qpms_trans_calculator* c = (<trans_calculator_get_X_data_t*>data)[0].c
#cdef char *func_name= <char*>(<void**>data)[1] # i am not using this, nor have I saved func_name to data
cdef char *ip0
cdef char *ip1
cdef char *ip2
cdef char *ip3
cdef char *ip4
cdef char *ip5
cdef char *ip6
cdef char *ip7
cdef char *ip8
cdef char *op0
cdef char *op1
cdef int errval
for i in prange(n): # iterating over dimensions
ip0 = args[0] + i * steps[0]
ip1 = args[1] + i * steps[1]
ip2 = args[2] + i * steps[2]
ip3 = args[3] + i * steps[3]
ip4 = args[4] + i * steps[4]
ip5 = args[5] + i * steps[5]
ip6 = args[6] + i * steps[6]
ip7 = args[7] + i * steps[7]
ip8 = args[8] + i * steps[8]
op0 = args[9] + i * steps[9]
op1 = args[10] + i * steps[10]
#errval = func(
errval = (<int(*)(qpms_trans_calculator*, double complex *, double complex *, int, int, int, int, double, double, double, int, int) nogil>func)(
c,
<cdouble *> op0,
<cdouble *> op1,
<int>(<np.npy_long*>ip0)[0],
<int>(<np.npy_long*>ip1)[0],
<int>(<np.npy_long*>ip2)[0],
<int>(<np.npy_long*>ip3)[0],
<double>(<np.npy_double*>ip4)[0],
<double>(<np.npy_double*>ip5)[0],
<double>(<np.npy_double*>ip6)[0],
<int>(<np.npy_bool*>ip7)[0],
<int>(<np.npy_long*>ip8)[0],
)
# TODO if (errval != 0): ...
# FIXME ERROR HANDLING!!! requires correct import and different data passed (see scipy's generated ufuncs)
# sf_error.check_fpe(func_name)
cdef np.PyUFuncGenericFunction trans_calculator_get_X_loop_funcs[1] cdef np.PyUFuncGenericFunction trans_calculator_get_X_loop_funcs[1]
trans_calculator_get_X_loop_funcs[0] = trans_calculator_loop_D_Ciiiidddii_As_D_lllldddbl trans_calculator_get_X_loop_funcs[0] = trans_calculator_loop_D_Ciiiidddii_As_D_lllldddbl
cdef np.PyUFuncGenericFunction trans_calculator_get_AB_loop_funcs[1] cdef np.PyUFuncGenericFunction trans_calculator_get_AB_loop_funcs[1]
#trans_calculator_get_AB_loop_funcs[0] = trans_calculator_parallel_loop_E_C_DD_iiiidddii_As_lllldddbl_DD
trans_calculator_get_AB_loop_funcs[0] = trans_calculator_loop_E_C_DD_iiiidddii_As_lllldddbl_DD trans_calculator_get_AB_loop_funcs[0] = trans_calculator_loop_E_C_DD_iiiidddii_As_lllldddbl_DD
cdef void *trans_calculator_get_AB_elementwise_funcs[1] cdef void *trans_calculator_get_AB_elementwise_funcs[1]
trans_calculator_get_AB_elementwise_funcs[0] = <void *>qpms_trans_calculator_get_AB_p_ext trans_calculator_get_AB_elementwise_funcs[0] = <void *>qpms_trans_calculator_get_AB_p_ext

View File

@ -419,6 +419,10 @@ complex double qpms_trans_calculator_get_A_buf(const qpms_trans_calculator *c,
bool r_ge_d, qpms_bessel_t J, bool r_ge_d, qpms_bessel_t J,
complex double *bessel_buf, double *legendre_buf) { complex double *bessel_buf, double *legendre_buf) {
if (r_ge_d) J = QPMS_BESSEL_REGULAR; if (r_ge_d) J = QPMS_BESSEL_REGULAR;
if (0 == kdlj.r && J != QPMS_BESSEL_REGULAR)
// TODO warn?
return NAN+I*NAN;
switch(c->normalization) { switch(c->normalization) {
case QPMS_NORMALIZATION_TAYLOR: case QPMS_NORMALIZATION_TAYLOR:
{ {
@ -451,6 +455,9 @@ complex double qpms_trans_calculator_get_B_buf(const qpms_trans_calculator *c,
bool r_ge_d, qpms_bessel_t J, bool r_ge_d, qpms_bessel_t J,
complex double *bessel_buf, double *legendre_buf) { complex double *bessel_buf, double *legendre_buf) {
if (r_ge_d) J = QPMS_BESSEL_REGULAR; if (r_ge_d) J = QPMS_BESSEL_REGULAR;
if (0 == kdlj.r && J != QPMS_BESSEL_REGULAR)
// TODO warn?
return NAN+I*NAN;
switch(c->normalization) { switch(c->normalization) {
case QPMS_NORMALIZATION_TAYLOR: case QPMS_NORMALIZATION_TAYLOR:
{ {
@ -486,6 +493,12 @@ int qpms_trans_calculator_get_AB_buf_p(const qpms_trans_calculator *c,
bool r_ge_d, qpms_bessel_t J, bool r_ge_d, qpms_bessel_t J,
complex double *bessel_buf, double *legendre_buf) { complex double *bessel_buf, double *legendre_buf) {
if (r_ge_d) J = QPMS_BESSEL_REGULAR; if (r_ge_d) J = QPMS_BESSEL_REGULAR;
if (0 == kdlj.r && J != QPMS_BESSEL_REGULAR) {
*Adest = NAN+I*NAN;
*Bdest = NAN+I*NAN;
// TODO warn? different return value?
return 0;
}
switch(c->normalization) { switch(c->normalization) {
case QPMS_NORMALIZATION_TAYLOR: case QPMS_NORMALIZATION_TAYLOR:
{ {

View File

@ -23,7 +23,7 @@ qpms_c = Extension('qpms_c',
extra_compile_args=['-std=c99','-ggdb','-O3', extra_compile_args=['-std=c99','-ggdb','-O3',
'-DDISABLE_NDEBUG', # uncomment to enable assertions in the modules '-DDISABLE_NDEBUG', # uncomment to enable assertions in the modules
], ],
libraries=['gsl', 'blas'], libraries=['gsl', 'blas', 'omp'],
runtime_library_dirs=os.environ['LD_LIBRARY_PATH'].split(':') runtime_library_dirs=os.environ['LD_LIBRARY_PATH'].split(':')
) )