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 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,
|
||||
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
|
||||
<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
|
||||
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):
|
||||
cdef qpms_quat4d_t p
|
||||
|
@ -727,3 +727,54 @@ cdef class cquat:
|
|||
return 0
|
||||
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)
|
||||
cdouble qpms_wignerD_elem(qpms_quat_t q, qpms_l_t l,
|
||||
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":
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include "qpms_types.h"
|
||||
|
||||
#include "tiny_inlines.h"
|
||||
|
||||
/// Quaternion type.
|
||||
/**
|
||||
* Internaly represented as a pair of complex numbers,
|
||||
|
@ -20,6 +22,12 @@ typedef struct qpms_quat4d_t {
|
|||
double c1, ci, cj, ck;
|
||||
} 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.
|
||||
// TODO is this really correct?
|
||||
// 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,
|
||||
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
|
||||
|
|
|
@ -42,6 +42,7 @@ setup(name='qpms',
|
|||
install_requires=['cython>=0.21','quaternion','spherical_functions',
|
||||
#'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'],
|
||||
ext_modules=cythonize([qpms_c], include_path=['qpms']),
|
||||
cmdclass = {'build_ext': build_ext},
|
||||
|
|
Loading…
Reference in New Issue