Commit ce57b567 authored by Tobias WEBER's avatar Tobias WEBER
Browse files
parent 5425851e
...@@ -8,6 +8,7 @@ Neutrons ...@@ -8,6 +8,7 @@ Neutrons
* (Shirane 2002), G. Shirane et al., "Neutron Scattering with a Triple-Axis Spectrometer", 2002, ISBN: 978-0521411264. * (Shirane 2002), G. Shirane et al., "Neutron Scattering with a Triple-Axis Spectrometer", 2002, ISBN: 978-0521411264.
* (Squires 2012), G. L. Squires, "Thermal Neutron Scattering", 2012, ISBN: 9781139107808. * (Squires 2012), G. L. Squires, "Thermal Neutron Scattering", 2012, ISBN: 9781139107808.
* (ILL Neutron Data Booklet), ISBN: 0-9704143-7-4, 2003, https://www.ill.eu/about-the-ill/documentation/
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include "../helper/flags.h" #include "../helper/flags.h"
#include "../helper/exception.h" #include "../helper/exception.h"
//#include "quat.h"
#include "linalg.h" #include "linalg.h"
#include "linalg2.h" #include "linalg2.h"
#include "stat.h" #include "stat.h"
...@@ -37,6 +36,7 @@ public: ...@@ -37,6 +36,7 @@ public:
using t_vec = ublas::vector<T>; using t_vec = ublas::vector<T>;
using t_mat = ublas::matrix<T>; using t_mat = ublas::matrix<T>;
protected: protected:
bool m_bValid = 0; bool m_bValid = 0;
t_vec m_vecX0; t_vec m_vecX0;
...@@ -44,6 +44,7 @@ protected: ...@@ -44,6 +44,7 @@ protected:
t_vec m_vecNorm; t_vec m_vecNorm;
T m_d; T m_d;
public: public:
/** /**
* plane from a point and a normal * plane from a point and a normal
...@@ -258,21 +259,27 @@ public: ...@@ -258,21 +259,27 @@ public:
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<typename T> class Line template<typename T> class Line
{ {
public: public:
using t_vec = ublas::vector<T>; using t_vec = ublas::vector<T>;
using t_mat = ublas::matrix<T>; using t_mat = ublas::matrix<T>;
protected: protected:
t_vec m_vecX0; t_vec m_vecX0;
t_vec m_vecDir; t_vec m_vecDir;
public: public:
Line() {} Line() {}
Line(const t_vec& vec0, const t_vec& dir) Line(const t_vec& vec0, const t_vec& dir)
: m_vecX0(vec0), m_vecDir(dir) : m_vecX0(vec0), m_vecDir(dir)
{} {}
...@@ -291,6 +298,25 @@ public: ...@@ -291,6 +298,25 @@ public:
const t_vec& GetDir() const { return m_vecDir; } const t_vec& GetDir() const { return m_vecDir; }
/**
* distance to a point
*/
T GetDist(const t_vec& vecPt) const
{
const t_vec& vecX0 = GetX0();
t_vec vecDir = GetDir() / veclen(GetDir());
// shift everything so that line goes through the origin
t_vec vecPtShift = vecPt - vecX0;
// project point on direction vector
t_vec vecClosestPt = inner(vecPtShift, vecDir) * vecDir;
// distance between point and projected point
return veclen(vecClosestPt - vecPtShift);
}
/** /**
* distance to line l1 * distance to line l1
*/ */
...@@ -299,14 +325,14 @@ public: ...@@ -299,14 +325,14 @@ public:
const Line<T>& l0 = *this; const Line<T>& l0 = *this;
// vector normal to both directions defining the distance line // vector normal to both directions defining the distance line
t_vec vecNorm = cross_3(l0.GetDir(), l1.GetDir()); t_vec vecNorm = cross_3<t_vec>(l0.GetDir(), l1.GetDir());
T tlenNorm = veclen(vecNorm); T tlenNorm = veclen(vecNorm);
t_vec vec01 = l1.GetX0() - l0.GetX0(); t_vec vec01 = l1.GetX0() - l0.GetX0();
// if the lines are parallel, any point (e.g. the X0s) can be used // if the lines are parallel, any point (e.g. the x0s) can be used
if(float_equal(tlenNorm, T(0))) if(float_equal(tlenNorm, T(0)))
return veclen(vec01); return GetDist(l1.GetX0());
// project x0_1 - x0_0 onto vecNorm // project x0_1 - x0_0 onto vecNorm
T tdot = std::abs(inner(vec01, vecNorm)); T tdot = std::abs(inner(vec01, vecNorm));
...@@ -314,26 +340,6 @@ public: ...@@ -314,26 +340,6 @@ public:
} }
/**
* distance to a point
*/
T GetDist(const t_vec& vecPt) const
{
const t_vec& vecX0 = GetX0();
const t_vec& vecDir = GetDir();
T tlenDir = veclen(vecDir);
// area of parallelogram spanned by vecDir and vecPt-vecX0
// == ||vecDir||*||vecPt-vecX0||*sin(th)
T tArea = veclen(cross_3(vecDir, vecPt-vecX0));
// length of perpendicular line from vecPt, also by sine theorem
// == ||vecPt-vecX0||*sin(th)
return tArea / tlenDir;
}
bool IsParallel(const Line<T>& line, T eps = tl::get_epsilon<T>()) const bool IsParallel(const Line<T>& line, T eps = tl::get_epsilon<T>()) const
{ {
return vec_is_collinear<t_vec>(GetDir(), line.GetDir(), eps); return vec_is_collinear<t_vec>(GetDir(), line.GetDir(), eps);
...@@ -420,7 +426,7 @@ public: ...@@ -420,7 +426,7 @@ public:
const t_vec xp2 = plane.GetX0() + plane.GetDir1(); const t_vec xp2 = plane.GetX0() + plane.GetDir1();
t_mat matDenom(N+1,N+1); t_mat matDenom(N+1,N+1);
matDenom(0,0) = 1; matDenom(0,1) = 1; matDenom(0,2) = 1; matDenom(0,3) = 0; matDenom(0,0) = 1; matDenom(0,1) = 1; matDenom(0,2) = 1; matDenom(0,3) = 0;
matDenom(1,0) = xp0[0]; matDenom(1,1) = xp1[0]; matDenom(1,2) = xp2[0]; matDenom(1,3) = dirl[0]; matDenom(1,0) = xp0[0]; matDenom(1,1) = xp1[0]; matDenom(1,2) = xp2[0]; matDenom(1,3) = dirl[0];
matDenom(2,0) = xp0[1]; matDenom(2,1) = xp1[1]; matDenom(2,2) = xp2[1]; matDenom(2,3) = dirl[1]; matDenom(2,0) = xp0[1]; matDenom(2,1) = xp1[1]; matDenom(2,2) = xp2[1]; matDenom(2,3) = dirl[1];
matDenom(3,0) = xp0[2]; matDenom(3,1) = xp1[2]; matDenom(3,2) = xp2[2]; matDenom(3,3) = dirl[2]; matDenom(3,0) = xp0[2]; matDenom(3,1) = xp1[2]; matDenom(3,2) = xp2[2]; matDenom(3,3) = dirl[2];
...@@ -430,7 +436,7 @@ public: ...@@ -430,7 +436,7 @@ public:
return false; return false;
t_mat matNum(N+1,N+1); t_mat matNum(N+1,N+1);
matNum(0,0) = 1; matNum(0,1) = 1; matNum(0,2) = 1; matNum(0,3) = 1; matNum(0,0) = 1; matNum(0,1) = 1; matNum(0,2) = 1; matNum(0,3) = 1;
matNum(1,0) = xp0[0]; matNum(1,1) = xp1[0]; matNum(1,2) = xp2[0]; matNum(1,3) = posl[0]; matNum(1,0) = xp0[0]; matNum(1,1) = xp1[0]; matNum(1,2) = xp2[0]; matNum(1,3) = posl[0];
matNum(2,0) = xp0[1]; matNum(2,1) = xp1[1]; matNum(2,2) = xp2[1]; matNum(2,3) = posl[1]; matNum(2,0) = xp0[1]; matNum(2,1) = xp1[1]; matNum(2,2) = xp2[1]; matNum(2,3) = posl[1];
matNum(3,0) = xp0[2]; matNum(3,1) = xp1[2]; matNum(3,2) = xp2[2]; matNum(3,3) = posl[2]; matNum(3,0) = xp0[2]; matNum(3,1) = xp1[2]; matNum(3,2) = xp2[2]; matNum(3,3) = posl[2];
...@@ -448,19 +454,27 @@ public: ...@@ -448,19 +454,27 @@ public:
* *
* pos0 + t0*dir0 = pos1 + t1*dir1 * pos0 + t0*dir0 = pos1 + t1*dir1
* pos0 - pos1 = t1*dir1 - t0*dir0 * pos0 - pos1 = t1*dir1 - t0*dir0
* exact: b = Mx -> M^(-1)*b = x * pos0 - pos1 = (-dir0 dir1) * (t0 t1)^t
* approx: M^t b = M^t M x -> (M^t M)^(-1) * M^t b = x * exact solution for the t params: (-dir0 dir1)^(-1) * (pos0 - pos1) = (t0 t1)^t
*
* generally:
* exact: b = M t -> M^(-1)*b = t
* approx.: M^t b = M^t M t -> (M^t M)^(-1) * M^t b = t
*/ */
bool intersect(const Line<T>& line, T& t, T eps = tl::get_epsilon<T>()) const bool intersect(const Line<T>& line1, T& t0, T eps = tl::get_epsilon<T>(), T *pt1=nullptr) const
{ {
if(IsParallel(line, eps)) if(IsParallel(line1, eps))
{
t0 = 0;
if(pt1) *pt1 = 0;
return false; return false;
}
const t_vec& pos0 = this->GetX0(); const t_vec& pos0 = this->GetX0();
const t_vec& pos1 = line.GetX0(); const t_vec& pos1 = line1.GetX0();
const t_vec& dir0 = this->GetDir(); const t_vec& dir0 = this->GetDir();
const t_vec& dir1 = line.GetDir(); const t_vec& dir1 = line1.GetDir();
const t_vec pos = pos0-pos1; const t_vec pos = pos0-pos1;
t_mat M = column_matrix({-dir0, dir1}); t_mat M = column_matrix({-dir0, dir1});
...@@ -473,9 +487,17 @@ public: ...@@ -473,9 +487,17 @@ public:
t_vec Mtb = prod_mv(Mt, pos); t_vec Mtb = prod_mv(Mt, pos);
t_vec params = prod_mv(MtMinv, Mtb); t_vec params = prod_mv(MtMinv, Mtb);
t = params[0];
return true; // get parameters
t0 = params[0];
T t1 = params[1];
if(pt1) *pt1 = t1;
// get closest points between the two lines
t_vec vecInters0 = (*this)(t0);
t_vec vecInters1 = line1(t1);
return veclen(vecInters1-vecInters0) <= eps;
} }
...@@ -501,6 +523,7 @@ public: ...@@ -501,6 +523,7 @@ public:
return true; return true;
} }
/** /**
* middle perpendicular plane (in 3d) * middle perpendicular plane (in 3d)
*/ */
...@@ -586,9 +609,6 @@ bool intersect_line_poly(const Line<T>& line, ...@@ -586,9 +609,6 @@ bool intersect_line_poly(const Line<T>& line,
// is intersection point within polygon? // is intersection point within polygon?
const t_vec vecFaceCentre = mean_value(vertPoly); const t_vec vecFaceCentre = mean_value(vertPoly);
//std::ostringstream ostr;
//ostr << "intersect: " << vecIntersect << ", face centre: " << vecFaceCentre << "\n";
for(std::size_t iVert = 0; iVert < vertPoly.size(); ++iVert) for(std::size_t iVert = 0; iVert < vertPoly.size(); ++iVert)
{ {
std::size_t iNextVert = iVert < (vertPoly.size()-1) ? iVert+1 : 0; std::size_t iNextVert = iVert < (vertPoly.size()-1) ? iVert+1 : 0;
...@@ -604,9 +624,6 @@ bool intersect_line_poly(const Line<T>& line, ...@@ -604,9 +624,6 @@ bool intersect_line_poly(const Line<T>& line,
if(planeEdge.GetDist(vecIntersect) < -eps) if(planeEdge.GetDist(vecIntersect) < -eps)
return false; return false;
//ostr << "Face " << iVert << ": " << vecEdgeCentre << ", " << vecNorm << ", "
// << planeEdge.GetDist(vecIntersect) << "\n";
} }
return true; return true;
...@@ -740,7 +757,6 @@ t_vec get_face_normal(const t_cont<t_vec>& vecVerts, t_vec vecCentre, ...@@ -740,7 +757,6 @@ t_vec get_face_normal(const t_cont<t_vec>& vecVerts, t_vec vecCentre,
if(inner(vecNorm, vecCentreToFace) < T(0)) if(inner(vecNorm, vecCentreToFace) < T(0))
vecNorm = -vecNorm; vecNorm = -vecNorm;
//tl::log_debug("vec = ", vecCentreToFace, ",\tnorm = ", vecNorm);
return vecNorm; return vecNorm;
} }
...@@ -799,7 +815,7 @@ t_cont<t_cont<t_vec>> verts_to_polyhedron( ...@@ -799,7 +815,7 @@ t_cont<t_cont<t_vec>> verts_to_polyhedron(
t_cont<t_vec>& vecPoly = vecPolys[iPlane]; t_cont<t_vec>& vecPoly = vecPolys[iPlane];
// plane already in set? // plane already in set?
if(plane.IsOnPlane(vert0, T(10)*eps) && if(plane.IsOnPlane(vert0, T(10)*eps) &&
plane.IsOnPlane(vert1, T(10)*eps) && plane.IsOnPlane(vert1, T(10)*eps) &&
plane.IsOnPlane(vert2, T(10)*eps)) plane.IsOnPlane(vert2, T(10)*eps))
{ {
...@@ -864,6 +880,7 @@ public: ...@@ -864,6 +880,7 @@ public:
using t_vec = ublas::vector<T>; using t_vec = ublas::vector<T>;
using t_mat = ublas::matrix<T>; using t_mat = ublas::matrix<T>;
protected: protected:
// x^T Q x + r x + s = 0 // x^T Q x + r x + s = 0
t_mat m_Q = zero_m<t_mat>(3,3); t_mat m_Q = zero_m<t_mat>(3,3);
...@@ -873,26 +890,36 @@ protected: ...@@ -873,26 +890,36 @@ protected:
t_vec m_vecOffs = zero_v<t_vec>(3); t_vec m_vecOffs = zero_v<t_vec>(3);
bool m_bQSymm = 1; bool m_bQSymm = 1;
protected: protected:
void CheckSymm() void CheckSymm()
{ {
m_bQSymm = is_symmetric(m_Q, std::cbrt(get_epsilon<T>())); m_bQSymm = is_symmetric(m_Q, std::cbrt(get_epsilon<T>()));
} }
public: public:
Quadric() {} Quadric() {}
Quadric(std::size_t iDim) Quadric(std::size_t iDim)
: m_Q(zero_m<t_mat>(iDim,iDim)), m_r(zero_v<t_vec>(iDim)) : m_Q(zero_m<t_mat>(iDim,iDim)), m_r(zero_v<t_vec>(iDim))
{ CheckSymm(); } { CheckSymm(); }
Quadric(const t_mat& Q) : m_Q(Q) Quadric(const t_mat& Q) : m_Q(Q)
{ CheckSymm(); } { CheckSymm(); }
Quadric(const t_mat& Q, const t_vec& r, T s) Quadric(const t_mat& Q, const t_vec& r, T s)
: m_Q(Q), m_r(r), m_s(s) : m_Q(Q), m_r(r), m_s(s)
{ CheckSymm(); } { CheckSymm(); }
~Quadric() {} ~Quadric() {}
void SetDim(std::size_t iDim) { m_Q.resize(iDim, iDim, 1); } void SetDim(std::size_t iDim) { m_Q.resize(iDim, iDim, 1); }
const Quadric<T>& operator=(const Quadric<T>& quad) const Quadric<T>& operator=(const Quadric<T>& quad)
{ {
this->m_Q = quad.m_Q; this->m_Q = quad.m_Q;
...@@ -904,6 +931,7 @@ public: ...@@ -904,6 +931,7 @@ public:
return *this; return *this;
} }
Quadric<T>& operator=(Quadric<T>&& quad) Quadric<T>& operator=(Quadric<T>&& quad)
{ {
this->m_Q = std::move(quad.m_Q); this->m_Q = std::move(quad.m_Q);
...@@ -915,20 +943,25 @@ public: ...@@ -915,20 +943,25 @@ public:
return *this; return *this;
} }
Quadric(const Quadric<T>& quad) { *this = quad; } Quadric(const Quadric<T>& quad) { *this = quad; }
Quadric(Quadric<T>&& quad) { *this = quad; } Quadric(Quadric<T>&& quad) { *this = quad; }
void SetOffset(const t_vec& vec) { m_vecOffs = vec; } void SetOffset(const t_vec& vec) { m_vecOffs = vec; }
const t_vec& GetOffset() const { return m_vecOffs; } const t_vec& GetOffset() const { return m_vecOffs; }
const t_mat& GetQ() const { return m_Q; } const t_mat& GetQ() const { return m_Q; }
const t_vec& GetR() const { return m_r; } const t_vec& GetR() const { return m_r; }
T GetS() const { return m_s; } T GetS() const { return m_s; }
void SetQ(const t_mat& Q) { m_Q = Q; CheckSymm(); } void SetQ(const t_mat& Q) { m_Q = Q; CheckSymm(); }
void SetR(const t_vec& r) { m_r = r; } void SetR(const t_vec& r) { m_r = r; }
void SetS(T s) { m_s = s; } void SetS(T s) { m_s = s; }
T operator()(const t_vec& _x) const T operator()(const t_vec& _x) const
{ {
t_vec x = _x-m_vecOffs; t_vec x = _x-m_vecOffs;
...@@ -940,6 +973,7 @@ public: ...@@ -940,6 +973,7 @@ public:
return dQ + dR + m_s; return dQ + dR + m_s;
} }
/** /**
* remove column and row iIdx * remove column and row iIdx
*/ */
...@@ -950,6 +984,7 @@ public: ...@@ -950,6 +984,7 @@ public:
m_vecOffs = remove_elem(m_vecOffs, iIdx); m_vecOffs = remove_elem(m_vecOffs, iIdx);
} }
void transform(const t_mat& S) void transform(const t_mat& S)
{ {
m_Q = tl::transform<t_mat>(m_Q, S, 1); m_Q = tl::transform<t_mat>(m_Q, S, 1);
......
...@@ -43,7 +43,6 @@ T ferromag(const t_cont<t_vec>& vecNeighbours, const t_cont<std::complex<T>>& ve ...@@ -43,7 +43,6 @@ T ferromag(const t_cont<t_vec>& vecNeighbours, const t_cont<std::complex<T>>& ve
return T(2)*tS*(J0 - J).real(); return T(2)*tS*(J0 - J).real();
} }
template<class t_vec = ublas::vector<double>, template<class t_vec = ublas::vector<double>,
typename T = typename t_vec::value_type, typename T = typename t_vec::value_type,
typename t_cont = std::initializer_list<std::tuple<t_vec, std::complex<T>>>> typename t_cont = std::initializer_list<std::tuple<t_vec, std::complex<T>>>>
...@@ -56,10 +55,9 @@ T ferromag(const t_cont& lstNeighbours, const ublas::vector<T>& vecq, T tS) ...@@ -56,10 +55,9 @@ T ferromag(const t_cont& lstNeighbours, const ublas::vector<T>& vecq, T tS)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** /**
* Magnetic form factors * Magnetic form factors
* @desc see: ILL Neutron Data Booklet sec. 2.5-1 (p. 60) * @desc see: (ILL Neutron Data Booklet), sec. 2.5-1 (p. 60)
* @desc also see: https://www.ill.eu/sites/ccsl/ffacts/ * @desc also see: https://www.ill.eu/sites/ccsl/ffacts/
*/ */
template<class T=double, template<class...> class t_vec=std::initializer_list> template<class T=double, template<class...> class t_vec=std::initializer_list>
...@@ -75,7 +73,6 @@ T j0_avg(T Q, const t_vec<T>& A, const t_vec<T>& a) ...@@ -75,7 +73,6 @@ T j0_avg(T Q, const t_vec<T>& A, const t_vec<T>& a)
return tl::formfact<T, std::vector>(Q, vecA, vecB, c); return tl::formfact<T, std::vector>(Q, vecA, vecB, c);
} }
template<class T=double, template<class...> class t_vec=std::initializer_list> template<class T=double, template<class...> class t_vec=std::initializer_list>
T j2_avg(T Q, const t_vec<T>& A, const t_vec<T>& a) T j2_avg(T Q, const t_vec<T>& A, const t_vec<T>& a)
{ {
...@@ -83,7 +80,6 @@ T j2_avg(T Q, const t_vec<T>& A, const t_vec<T>& a) ...@@ -83,7 +80,6 @@ T j2_avg(T Q, const t_vec<T>& A, const t_vec<T>& a)
return j0_avg<T, t_vec>(Q, A, a) * s * s; return j0_avg<T, t_vec>(Q, A, a) * s * s;
} }
template<class T=double, template<class...> class t_vec=std::initializer_list> template<class T=double, template<class...> class t_vec=std::initializer_list>
T mag_formfact(T Q, T L, T S, T mag_formfact(T Q, T L, T S,
const t_vec<T>& A0, const t_vec<T>& a0, const t_vec<T>& A0, const t_vec<T>& a0,
...@@ -92,7 +88,6 @@ T mag_formfact(T Q, T L, T S, ...@@ -92,7 +88,6 @@ T mag_formfact(T Q, T L, T S,
return (L+T(2)*S) * j0_avg<T, t_vec>(Q, A0, a0) * L * j2_avg<T, t_vec>(Q, A2, a2); return (L+T(2)*S) * j0_avg<T, t_vec>(Q, A0, a0) * L * j2_avg<T, t_vec>(Q, A2, a2);
} }
/** /**
* form factor for transition metals (d orbitals, weak LS, spin-only) * form factor for transition metals (d orbitals, weak LS, spin-only)
* @desc see: (Squires 2012), p. 138 * @desc see: (Squires 2012), p. 138
...@@ -109,7 +104,6 @@ std::tuple<T,T,T> mag_formfact_d(T Q, T g, ...@@ -109,7 +104,6 @@ std::tuple<T,T,T> mag_formfact_d(T Q, T g,
return std::tuple<T,T,T>(j0, j2, j0 + (T(1)-T(2)/g)*j2); return std::tuple<T,T,T>(j0, j2, j0 + (T(1)-T(2)/g)*j2);
} }
/** /**
* form factor for rare earths (f orbitals, strong LS, jj) * form factor for rare earths (f orbitals, strong LS, jj)
* @desc see: (Squires 2012), p. 139 * @desc see: (Squires 2012), p. 139
......
...@@ -45,8 +45,8 @@ template<typename T=double> T get_E2KSQ() ...@@ -45,8 +45,8 @@ template<typename T=double> T get_E2KSQ()
template<class T=double> T t_E2KSQ = T(1)/t_KSQ2E<T>; template<class T=double> T t_E2KSQ = T(1)/t_KSQ2E<T>;
#endif #endif
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
...@@ -59,7 +59,6 @@ t_momentum<Sys,Y> lam2p(const t_length<Sys,Y>& lam) ...@@ -59,7 +59,6 @@ t_momentum<Sys,Y> lam2p(const t_length<Sys,Y>& lam)
return get_h<Y>() / lam; return get_h<Y>() / lam;
} }
template<class Sys, class Y> template<class Sys, class Y>
t_length<Sys,Y> p2lam(const t_momentum<Sys,Y>& p) t_length<Sys,Y> p2lam(const t_momentum<Sys,Y>& p)
{ {
...@@ -74,35 +73,30 @@ t_length<Sys,Y> k2lam(const t_wavenumber<Sys,Y>& k) ...@@ -74,35 +73,30 @@ t_length<Sys,Y> k2lam(const t_wavenumber<Sys,Y>& k)
return Y(2.)*get_pi<Y>() / k; return Y(2.)*get_pi<Y>() / k;
} }
template<class Sys, class Y> template<class Sys, class Y>
t_wavenumber<Sys,Y> lam2k(const t_length<Sys,Y>& lam) t_wavenumber<Sys,Y> lam2k(const t_length<Sys,Y>& lam)
{ {
return Y(2.)*get_pi<Y>() / lam; return Y(2.)*get_pi<Y>() / lam;
} }
template<class Sys, class Y> template<class Sys, class Y>
t_momentum<Sys,Y> k2p(const t_wavenumber<Sys,Y>& k)