diff --git a/qpms/__init__.py b/qpms/__init__.py index a5f1830..1bd8c74 100644 --- a/qpms/__init__.py +++ b/qpms/__init__.py @@ -6,6 +6,7 @@ from .qpms_p import * from .cyquaternions import CQuat, IRot3 from .cybspec import VSWFNorm, BaseSpec from .cytranslations import trans_calculator +from .cymaterials import MaterialInterpolator from .lattices2d import * from .hexpoints import * from .tmatrices import * diff --git a/qpms/cycommon.pxd b/qpms/cycommon.pxd new file mode 100644 index 0000000..e627917 --- /dev/null +++ b/qpms/cycommon.pxd @@ -0,0 +1 @@ +cdef char *make_c_string(pythonstring) diff --git a/qpms/cycommon.pyx b/qpms/cycommon.pyx index 8b0d9d9..83b3a28 100644 --- a/qpms/cycommon.pyx +++ b/qpms/cycommon.pyx @@ -1,5 +1,6 @@ import numpy as np from qpms_cdefs cimport * +from libc.stdlib cimport malloc cimport cython import enum @@ -180,3 +181,23 @@ def uvswfi2tlm(u): ma.append(m) return (ta, la, ma) +cdef char *make_c_string(pythonstring): + ''' + Copies contents of a python string into a char[] + (allocating the memory with malloc()) + ''' + bytestring = pythonstring.encode('UTF-8') + cdef Py_ssize_t n = len(bytestring) + cdef Py_ssize_t i + cdef char *s + s = malloc(n+1) + if not s: + raise MemoryError + #s[:n] = bytestring # This segfaults; why? + for i in range(n): s[i] = bytestring[i] + s[n] = 0 + return s + +def string_c2py(const char* cstring): + return cstring.decode('UTF-8') + diff --git a/qpms/cymaterials.pxd b/qpms/cymaterials.pxd new file mode 100644 index 0000000..c3b90e5 --- /dev/null +++ b/qpms/cymaterials.pxd @@ -0,0 +1,8 @@ +from qpms_cdefs cimport qpms_permittivity_interpolator_t + +cdef class MaterialInterpolator: + cdef qpms_permittivity_interpolator_t *interp + cdef readonly double omegamin + cdef readonly double omegamax + + diff --git a/qpms/cymaterials.pyx b/qpms/cymaterials.pyx new file mode 100644 index 0000000..5c35447 --- /dev/null +++ b/qpms/cymaterials.pyx @@ -0,0 +1,44 @@ +# Cythonized parts of QPMS here +# ----------------------------- + +import numpy as np +import cmath +from qpms_cdefs cimport * +from cybspec cimport * +from cycommon import * +from cycommon cimport make_c_string +cimport cython +import enum +import warnings +import os +from libc.stdlib cimport malloc, free, calloc, abort + + +cdef class MaterialInterpolator: + ''' + Wrapper over the qpms_permittivity_interpolator_t structure. + ''' + + def __cinit__(self, filename, *args, **kwargs): + '''Creates a permittivity interpolator.''' + cdef char *cpath = make_c_string(filename) + self.interp = qpms_permittivity_interpolator_from_yml(cpath, gsl_interp_cspline) + if not self.interp: + raise IOError("Could not load permittivity data from %s" % filename) + self.omegamin = qpms_permittivity_interpolator_omega_min(self.interp) + self.omegamax = qpms_permittivity_interpolator_omega_max(self.interp) + + def __dealloc__(self): + qpms_permittivity_interpolator_free(self.interp) + + def __call__(self, double freq): + '''Returns interpolated permittivity, corresponding to a given angular frequency.''' + if freq < self.omegamin or freq > self.omegamax: + raise ValueError("Input frequency %g is outside the interpolator domain (%g, %g)." + % (freq, self.minomega, self.freqs[self.maxomega])) + return qpms_permittivity_interpolator_eps_at_omega(self.interp, freq) + + property freq_interval: + def __get__(self): + return [self.omegamin, self.omegamax] + diff --git a/qpms/qpms_c.pyx b/qpms/qpms_c.pyx index 0fa88b9..7f37b2d 100644 --- a/qpms/qpms_c.pyx +++ b/qpms/qpms_c.pyx @@ -15,44 +15,13 @@ from cyquaternions cimport * from cybspec cimport * #from cybspec import * from cycommon import * +from cycommon cimport make_c_string cimport cython import enum import warnings import os from libc.stdlib cimport malloc, free, calloc, abort - -cdef class MaterialInterpolator: - ''' - Wrapper over the qpms_permittivity_interpolator_t structure. - ''' - cdef qpms_permittivity_interpolator_t *interp - cdef readonly double omegamin - cdef readonly double omegamax - - def __cinit__(self, filename, *args, **kwargs): - '''Creates a permittivity interpolator.''' - cdef char *cpath = make_c_string(filename) - self.interp = qpms_permittivity_interpolator_from_yml(cpath, gsl_interp_cspline) - if not self.interp: - raise IOError("Could not load permittivity data from %s" % filename) - self.omegamin = qpms_permittivity_interpolator_omega_min(self.interp) - self.omegamax = qpms_permittivity_interpolator_omega_max(self.interp) - - def __dealloc__(self): - qpms_permittivity_interpolator_free(self.interp) - - def __call__(self, double freq): - '''Returns interpolated permittivity, corresponding to a given angular frequency.''' - if freq < self.omegamin or freq > self.omegamax: - raise ValueError("Input frequency %g is outside the interpolator domain (%g, %g)." - % (freq, self.minomega, self.freqs[self.maxomega])) - return qpms_permittivity_interpolator_eps_at_omega(self.interp, freq) - - property freq_interval: - def __get__(self): - return [self.omegamin, self.omegamax] - cdef class TMatrixInterpolator: ''' Wrapper over the qpms_tmatrix_interpolator_t structure. @@ -177,26 +146,6 @@ cdef class CTMatrix: # N.B. there is another type called TMatrix in tmatrices.py tm.spherical_perm_fill(radius, freq, epsilon_int, epsilon_ext) return tm -cdef char *make_c_string(pythonstring): - ''' - Copies contents of a python string into a char[] - (allocating the memory with malloc()) - ''' - bytestring = pythonstring.encode('UTF-8') - cdef Py_ssize_t n = len(bytestring) - cdef Py_ssize_t i - cdef char *s - s = malloc(n+1) - if not s: - raise MemoryError - #s[:n] = bytestring # This segfaults; why? - for i in range(n): s[i] = bytestring[i] - s[n] = 0 - return s - -def string_c2py(const char* cstring): - return cstring.decode('UTF-8') - cdef class PointGroup: cdef readonly qpms_pointgroup_t G diff --git a/setup.py b/setup.py index 0860a46..43a1435 100755 --- a/setup.py +++ b/setup.py @@ -102,6 +102,11 @@ cybspec = Extension('qpms.cybspec', extra_link_args=['qpms/libqpms.a'], libraries=['gsl', 'lapacke', 'blas', 'gslcblas', 'pthread',] ) +cymaterials = Extension('qpms.cymaterials', + sources = ['qpms/cymaterials.pyx'], + extra_link_args=['qpms/libqpms.a'], + libraries=['gsl', 'lapacke', 'blas', 'gslcblas', 'pthread',] + ) cyquaternions = Extension('qpms.cyquaternions', sources = ['qpms/cyquaternions.pyx'], extra_link_args=['amos/libamos.a', 'qpms/libqpms.a'], @@ -130,7 +135,7 @@ setup(name='qpms', #'quaternion','spherical_functions', 'scipy>=0.18.0', 'sympy>=1.2'], #dependency_links=['https://github.com/moble/quaternion/archive/v2.0.tar.gz','https://github.com/moble/spherical_functions/archive/master.zip'], - ext_modules=cythonize([qpms_c, cytranslations, cycommon, cyquaternions, cybspec], include_path=['qpms', 'amos'], gdb_debug=True), + ext_modules=cythonize([qpms_c, cytranslations, cycommon, cyquaternions, cybspec, cymaterials], include_path=['qpms', 'amos'], gdb_debug=True), cmdclass = {'build_ext': build_ext}, zip_safe=False )