Quaternion + determinant representation of improper rotations.
Former-commit-id: fbc101d997ae85565584a3f0ea9c583360fbabec
This commit is contained in:
parent
ee73a8f029
commit
efaf3211e4
|
@ -8,7 +8,7 @@ Installation
|
||||||
The package depends on numpy, scipy, cython and GSL (>= 2.0).
|
The package depends on numpy, scipy, cython and GSL (>= 2.0).
|
||||||
The first three can be obtained by pip. If you have a recent enough OS,
|
The first three can be obtained by pip. If you have a recent enough OS,
|
||||||
you can get GSL easily from the repositories; on Debian and derivatives,
|
you can get GSL easily from the repositories; on Debian and derivatives,
|
||||||
just run `apt-get install libgsl-dev` under root. Alternatively,
|
just run ``apt-get install libgsl-dev`` under root. Alternatively,
|
||||||
you can `get the source
|
you can `get the source
|
||||||
<https://www.gnu.org/software/gsl/>`_ get the source and compile it yourself.
|
<https://www.gnu.org/software/gsl/>`_ get the source and compile it yourself.
|
||||||
|
|
||||||
|
|
|
@ -629,7 +629,7 @@ cdef class cquat:
|
||||||
Wrapper of the qpms_quat_t object, with the functionality
|
Wrapper of the qpms_quat_t object, with the functionality
|
||||||
to evaluate Wigner D-matrix elements.
|
to evaluate Wigner D-matrix elements.
|
||||||
'''
|
'''
|
||||||
cdef qpms_quat_t q
|
cdef readonly qpms_quat_t q
|
||||||
|
|
||||||
def __cinit__(self, double w, double x, double y, double z):
|
def __cinit__(self, double w, double x, double y, double z):
|
||||||
cdef qpms_quat4d_t p
|
cdef qpms_quat4d_t p
|
||||||
|
@ -727,3 +727,54 @@ cdef class cquat:
|
||||||
return 0
|
return 0
|
||||||
return qpms_wignerD_elem(self.q, l, mp, m)
|
return qpms_wignerD_elem(self.q, l, mp, m)
|
||||||
|
|
||||||
|
cdef class irot3:
|
||||||
|
'''
|
||||||
|
Wrapper over the C type qpms_irot3_t.
|
||||||
|
'''
|
||||||
|
cdef qpms_irot3_t qd
|
||||||
|
|
||||||
|
def __cinit__(self, cquat q, short det): # TODO implement a constructor with no arguments
|
||||||
|
if (det != 1 and det != -1):
|
||||||
|
raise ValueError("Improper rotation determinant has to be 1 or -1")
|
||||||
|
self.qd.rot = q.normalise().q
|
||||||
|
self.qd.det = det
|
||||||
|
|
||||||
|
property rot:
|
||||||
|
'''
|
||||||
|
The proper rotation part of the irot3 type.
|
||||||
|
'''
|
||||||
|
def __get__(self):
|
||||||
|
res = cquat(0,0,0,0)
|
||||||
|
res.q = self.qd.rot
|
||||||
|
return res
|
||||||
|
def __set__(self, cquat r):
|
||||||
|
# TODO check for non-zeroness and throw an exception if norm is zero
|
||||||
|
self.qd.rot = r.normalise().q
|
||||||
|
|
||||||
|
property det:
|
||||||
|
'''
|
||||||
|
The determinant of the improper rotation.
|
||||||
|
'''
|
||||||
|
def __get__(self):
|
||||||
|
return self.qd.det
|
||||||
|
def __set__(self, d):
|
||||||
|
d = int(d)
|
||||||
|
if (d != 1 and d != -1):
|
||||||
|
raise ValueError("Improper rotation determinant has to be 1 or -1")
|
||||||
|
self.qd.det = d
|
||||||
|
|
||||||
|
def __repr__(self): # TODO make this look like a quaternion with i,j,k
|
||||||
|
return '(' + repr(self.rot) + ', ' + repr(self.det) + ')'
|
||||||
|
|
||||||
|
def __mul__(irot3 self, irot3 other):
|
||||||
|
res = irot3(cquat(1,0,0,0), 1)
|
||||||
|
res.qd = qpms_irot3_mult(self.qd, other.qd)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def __pow__(irot3 self, int n, _):
|
||||||
|
res = irot3(cquat(1,0,0,0), 1)
|
||||||
|
res.qd = qpms_irot3_pow(self.qd, n)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,11 @@ cdef extern from "wigner.h":
|
||||||
qpms_quat_t qpms_quat_pow(qpms_quat_t q, double exponent)
|
qpms_quat_t qpms_quat_pow(qpms_quat_t q, double exponent)
|
||||||
cdouble qpms_wignerD_elem(qpms_quat_t q, qpms_l_t l,
|
cdouble qpms_wignerD_elem(qpms_quat_t q, qpms_l_t l,
|
||||||
qpms_m_t mp, qpms_m_t m)
|
qpms_m_t mp, qpms_m_t m)
|
||||||
|
struct qpms_irot3_t:
|
||||||
|
qpms_quat_t rot
|
||||||
|
short det
|
||||||
|
qpms_irot3_t qpms_irot3_mult(qpms_irot3_t p, qpms_irot3_t q)
|
||||||
|
qpms_irot3_t qpms_irot3_pow(qpms_irot3_t p, int n)
|
||||||
|
|
||||||
|
|
||||||
#cdef extern from "numpy/arrayobject.h":
|
#cdef extern from "numpy/arrayobject.h":
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "qpms_types.h"
|
#include "qpms_types.h"
|
||||||
|
|
||||||
|
#include "tiny_inlines.h"
|
||||||
|
|
||||||
/// Quaternion type.
|
/// Quaternion type.
|
||||||
/**
|
/**
|
||||||
* Internaly represented as a pair of complex numbers,
|
* Internaly represented as a pair of complex numbers,
|
||||||
|
@ -20,6 +22,12 @@ typedef struct qpms_quat4d_t {
|
||||||
double c1, ci, cj, ck;
|
double c1, ci, cj, ck;
|
||||||
} qpms_quat4d_t;
|
} qpms_quat4d_t;
|
||||||
|
|
||||||
|
/// 3D improper rotations represented as a quaternion and a sign of the determinant.
|
||||||
|
typedef struct qpms_irot3_t {
|
||||||
|
qpms_quat_t rot; ///< Quaternion representing the rotation part.
|
||||||
|
short det; ///< Determinant of the transformation (valid values are 1 (rotation) or -1 (improper rotation)
|
||||||
|
} qpms_irot3_t;
|
||||||
|
|
||||||
/// Conversion from the 4*double to the 2*complex quaternion.
|
/// Conversion from the 4*double to the 2*complex quaternion.
|
||||||
// TODO is this really correct?
|
// TODO is this really correct?
|
||||||
// I.e. do the axis from moble's text match this convention?
|
// I.e. do the axis from moble's text match this convention?
|
||||||
|
@ -134,4 +142,29 @@ static inline qpms_quat_t qpms_quat_pow(const qpms_quat_t q, const double expone
|
||||||
complex double qpms_wignerD_elem(qpms_quat_t q, qpms_l_t l,
|
complex double qpms_wignerD_elem(qpms_quat_t q, qpms_l_t l,
|
||||||
qpms_m_t mp, qpms_m_t m);
|
qpms_m_t mp, qpms_m_t m);
|
||||||
|
|
||||||
|
static inline int qpms_irot3_checkdet(const qpms_irot3_t p) {
|
||||||
|
if (p.det != 1 && p.det != -1) abort();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Improper rotation multiplication.
|
||||||
|
static inline qpms_irot3_t qpms_irot3_mult(const qpms_irot3_t p, const qpms_irot3_t q) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
qpms_irot3_checkdet(p);
|
||||||
|
qpms_irot3_checkdet(q);
|
||||||
|
#endif
|
||||||
|
const qpms_irot3_t r = {qpms_quat_normalise(qpms_quat_mult(p.rot, q.rot)), p.det*q.det};
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Improper rotation power \f$ p^n \f$.
|
||||||
|
static inline qpms_irot3_t qpms_irot3_pow(const qpms_irot3_t p, int n) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
qpms_irot3_checkdet(p);
|
||||||
|
#endif
|
||||||
|
const qpms_irot3_t r = {qpms_quat_normalise(qpms_quat_pow(p.rot, n)),
|
||||||
|
p.det == -1 ? min1pow(n) : 1};
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
#endif //QPMS_WIGNER_H
|
#endif //QPMS_WIGNER_H
|
||||||
|
|
|
@ -42,6 +42,7 @@ setup(name='qpms',
|
||||||
install_requires=['cython>=0.21','quaternion','spherical_functions',
|
install_requires=['cython>=0.21','quaternion','spherical_functions',
|
||||||
#'py_gmm' # no longer needed
|
#'py_gmm' # no longer needed
|
||||||
],
|
],
|
||||||
|
# TODO implement https://stackoverflow.com/questions/17366784/setuptools-unable-to-use-link-from-dependency-links and update README.md accordingly
|
||||||
dependency_links=['https://github.com/texnokrates/py_gmm','https://github.com/moble/quaternion','https://github.com/moble/spherical_functions'],
|
dependency_links=['https://github.com/texnokrates/py_gmm','https://github.com/moble/quaternion','https://github.com/moble/spherical_functions'],
|
||||||
ext_modules=cythonize([qpms_c], include_path=['qpms']),
|
ext_modules=cythonize([qpms_c], include_path=['qpms']),
|
||||||
cmdclass = {'build_ext': build_ext},
|
cmdclass = {'build_ext': build_ext},
|
||||||
|
|
Loading…
Reference in New Issue