33#include <initializer_list>
44class vector :
public std::array<T, 3>
62 assert(v__.size() == 3);
63 for (
int x : {0, 1, 2}) {
64 (*this)[x] = v__.begin()[x];
68 vector& operator=(std::initializer_list<T> v__)
70 assert(v__.size() == 3);
71 for (
int x : {0, 1, 2}) {
72 (*this)[x] = v__.begin()[x];
80 assert(v__.size() == 3);
81 for (
int x : {0, 1, 2}) {
86 vector& operator=(std::vector<T>
const& v__)
88 assert(v__.size() == 3);
89 for (
int x : {0, 1, 2}) {
98 for (
int x : {0, 1, 2}) {
99 (*this)[x] = ptr__[x];
106 for (
int x : {0, 1, 2}) {
114 for (
int x : {0, 1, 2}) {
115 (*this)[x] = vec__[x];
122 return std::abs((*
this)[0]) + std::abs((*
this)[1]) + std::abs((*
this)[2]);
128 return std::sqrt(this->
length2());
134 return static_cast<double>(std::pow((*
this)[0], 2) + std::pow((*
this)[1], 2) + std::pow((*
this)[2], 2));
139 for (
int x : {0, 1, 2}) {
145 inline vector<T>& operator-=(vector<T>
const& b)
147 for (
int x : {0, 1, 2}) {
155template <
typename T,
typename U>
156inline vector<
decltype(T{} + U{})>
157operator+(vector<T>
const& a, vector<U>
const& b)
159 vector<
decltype(T{} + U{})> c;
160 for (
int x : {0, 1, 2}) {
166template <
typename T,
typename U>
167inline vector<
decltype(T{} - U{})>
168operator-(vector<T>
const& a, vector<U>
const& b)
170 vector<
decltype(T{} - U{})> c;
171 for (
int x : {0, 1, 2}) {
177template <
typename T,
typename U>
178inline std::enable_if_t<std::is_scalar<U>::value, vector<
decltype(T{} * U{})>>
179operator*(vector<T>
const& vec, U p)
181 vector<
decltype(T{} * U{})> a;
182 for (
int x : {0, 1, 2}) {
188template <
typename T,
typename U>
189inline std::enable_if_t<std::is_scalar<U>::value, vector<
decltype(T{} * U{})>>
190operator*(U p, vector<T>
const& vec)
195template <
typename T,
typename U>
196inline std::enable_if_t<std::is_scalar<U>::value, vector<
decltype(T{} * U{})>>
197operator/(vector<T>
const& vec, U p)
199 vector<
decltype(T{} * U{})> a;
200 for (
int x : {0, 1, 2}) {
206template <
typename T,
typename U>
207inline auto dot(vector<T>
const a, vector<U>
const b) ->
decltype(T{} * U{})
209 return (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]);
213inline auto cross(vector<T>
const a, vector<T>
const b)
216 res[0] = a[1] * b[2] - a[2] * b[1];
217 res[1] = a[2] * b[0] - a[0] * b[2];
218 res[2] = a[0] * b[1] - a[1] * b[0];
223std::ostream& operator<<(std::ostream& out, r3::vector<T>
const& v)
225 out <<
"{" << v[0] <<
", " << v[1] <<
", " << v[2] <<
"}";
238 template <
typename U>
250 for (
int i = 0; i < 3; i++) {
251 for (
int j = 0; j < 3; j++) {
252 mtrx_[i][j] = mtrx__[i][j];
258 matrix(std::vector<std::vector<T>> src__)
260 for (
int i = 0; i < 3; i++) {
261 for (
int j = 0; j < 3; j++) {
262 mtrx_[i][j] = src__[i][j];
267 matrix(std::array<std::array<T, 3>, 3> src__)
269 for (
int i = 0; i < 3; i++) {
270 for (
int j = 0; j < 3; j++) {
271 mtrx_[i][j] = src__[i][j];
277 template <
typename U>
280 for (
int i = 0; i < 3; i++) {
281 for (
int j = 0; j < 3; j++) {
288 matrix(std::initializer_list<std::initializer_list<T>> mtrx__)
290 for (
int i : {0, 1, 2}) {
291 for (
int j : {0, 1, 2}) {
292 mtrx_[i][j] = mtrx__.begin()[i].begin()[j];
301 for (
int i = 0; i < 3; i++) {
302 for (
int j = 0; j < 3; j++) {
303 this->mtrx_[i][j] = rhs.
mtrx_[i][j];
310 inline T& operator()(
const int i,
const int j)
315 inline T
const& operator()(
const int i,
const int j)
const
321 template <
typename U>
324 matrix<
decltype(T{} + U{})> a;
325 for (
int i = 0; i < 3; i++) {
326 for (
int j = 0; j < 3; j++) {
327 a(i, j) = (*this)(i, j) + b(i, j);
334 template <
typename U>
337 for (
int i = 0; i < 3; i++) {
338 for (
int j = 0; j < 3; j++) {
339 (*this)(i, j) += b(i, j);
346 template <
typename U>
349 for (
int i = 0; i < 3; i++) {
350 for (
int j = 0; j < 3; j++) {
372template <
typename T,
typename U>
373inline std::enable_if_t<std::is_scalar<U>::value,
matrix<
decltype(T{} * U{})>>
operator*(matrix<T>
const& a__, U p__)
375 matrix<
decltype(T{} * U{})> c;
376 for (
int i = 0; i < 3; i++) {
377 for (
int j = 0; j < 3; j++) {
378 c(i, j) = a__(i, j) * p__;
384template <
typename T,
typename U>
385inline std::enable_if_t<std::is_scalar<U>::value, matrix<
decltype(T{} * U{})>>
operator*(U p__, matrix<T>
const& a__)
390inline bool operator==(matrix<int>
const& a__, matrix<int>
const& b__)
392 for (
int i = 0; i < 3; i++) {
393 for (
int j = 0; j < 3; j++) {
394 if (a__(i, j) != b__(i, j)) {
403template <
typename T,
typename U>
406 matrix<
decltype(T{} * U{})> c;
407 for (
int i = 0; i < 3; i++) {
408 for (
int j = 0; j < 3; j++) {
409 for (
int k = 0; k < 3; k++) {
410 c(i, j) += a__(i, k) * b__(k, j);
418template <
typename T,
typename U>
421 vector<
decltype(T{} * U{})> a;
422 for (
int i = 0; i < 3; i++) {
423 for (
int j = 0; j < 3; j++) {
424 a[i] += m__(i, j) * b__[j];
431template <
typename T,
typename U>
434 vector<
decltype(T{} * U{})> a;
435 for (
int i = 0; i < 3; i++) {
436 for (
int j = 0; j < 3; j++) {
437 a[i] += b__[j] * m__(j, i);
448 for (
int i = 0; i < 3; i++) {
449 for (
int j = 0; j < 3; j++) {
450 mtrx(i, j) = src(j, i);
461 mtrx(0, 0) = (src(1, 1) * src(2, 2) - src(1, 2) * src(2, 1));
462 mtrx(0, 1) = (src(0, 2) * src(2, 1) - src(0, 1) * src(2, 2));
463 mtrx(0, 2) = (src(0, 1) * src(1, 2) - src(0, 2) * src(1, 1));
464 mtrx(1, 0) = (src(1, 2) * src(2, 0) - src(1, 0) * src(2, 2));
465 mtrx(1, 1) = (src(0, 0) * src(2, 2) - src(0, 2) * src(2, 0));
466 mtrx(1, 2) = (src(0, 2) * src(1, 0) - src(0, 0) * src(1, 2));
467 mtrx(2, 0) = (src(1, 0) * src(2, 1) - src(1, 1) * src(2, 0));
468 mtrx(2, 1) = (src(0, 1) * src(2, 0) - src(0, 0) * src(2, 1));
469 mtrx(2, 2) = (src(0, 0) * src(1, 1) - src(0, 1) * src(1, 0));
478 if (std::abs(t1) != 1) {
479 throw std::runtime_error(
"integer matrix can't be inverted");
481 return inverse_aux(src) * t1;
490 if (std::abs(t1) < 1e-10) {
491 throw std::runtime_error(
"matrix is degenerate");
494 return inverse_aux(src) * (1.0 / t1);
498inline std::ostream& operator<<(std::ostream& out,
matrix<T> const& v)
501 for (
int i = 0; i < 3; i++) {
503 for (
int j = 0; j < 3; j++) {
525 const double eps{1e-9};
530 for (
int i = 0; i < 3; i++) {
531 v.second[i] = (int)floor(v.first[i]);
532 v.first[i] -= v.second[i];
533 if (v.first[i] < -eps || v.first[i] > 1.0 + eps) {
535 s <<
"wrong fractional coordinates" << std::endl
536 << v.first[0] <<
" " << v.first[1] <<
" " << v.first[2];
537 throw std::runtime_error(s.str());
539 if (v.first[i] < 0) {
542 if (v.first[i] >= (1 - eps)) {
546 if (v.first[i] < 0 || v.first[i] >= 1) {
548 s <<
"wrong fractional coordinates" << std::endl
549 << v.first[0] <<
" " << v.first[1] <<
" " << v.first[2];
550 throw std::runtime_error(s.str());
553 for (
int x : {0, 1, 2}) {
554 if (std::abs(coord__[x] - (v.first[x] + v.second[x])) > eps) {
556 s <<
"wrong coordinate reduction" << std::endl
557 <<
" original coord: " << coord__ << std::endl
558 <<
" reduced coord: " << v.first << std::endl
559 <<
" T: " << v.second;
560 throw std::runtime_error(s.str());
574 vector<double> a0(lattice_vectors__(0, 0), lattice_vectors__(1, 0), lattice_vectors__(2, 0));
575 vector<double> a1(lattice_vectors__(0, 1), lattice_vectors__(1, 1), lattice_vectors__(2, 1));
576 vector<double> a2(lattice_vectors__(0, 2), lattice_vectors__(1, 2), lattice_vectors__(2, 2));
578 double det = std::abs(lattice_vectors__.
det());
582 limits[0] =
static_cast<int>(2 * radius__ * cross(a1, a2).length() / det) + 1;
583 limits[1] =
static_cast<int>(2 * radius__ * cross(a0, a2).length() / det) + 1;
584 limits[2] =
static_cast<int>(2 * radius__ * cross(a0, a1).length() / det) + 1;
594 const double eps{1e-12};
596 const double twopi = 6.2831853071795864769;
604 vs[1] = std::acos(vc[2] / vs[0]);
606 if (std::abs(vc[0]) > eps || std::abs(vc[1]) > eps) {
607 vs[2] = std::atan2(vc[1], vc[0]);
Handling of a 3x3 matrix of numerical data types.
matrix< T > & operator=(matrix< T > const &rhs)
Assignment operator.
auto & operator*=(U p)
Multiply matrix by a scalar number.
T det() const
Return determinant of a matrix.
auto operator+(matrix< U > const &b) const
Sum of two matrices.
matrix(matrix< U > const &src__)
Copy constructor.
T mtrx_[3][3]
Store matrix as mtrx[i][j].
matrix(std::initializer_list< std::initializer_list< T > > mtrx__)
Construct matrix form std::initializer_list.
auto & operator+=(matrix< U > const &b)
+= operator
matrix()
Construct a zero matrix.
matrix(std::vector< std::vector< T > > src__)
Construct matrix from std::vector.
matrix(T mtrx__[3][3])
Construct matrix form plain 3x3 array.
Simple implementation of 3d vector.
T l1norm() const
Return L1 norm of the vector.
vector()
Create zero vector.
vector(std::initializer_list< T > v__)
Create from std::initializer_list.
double length() const
Return vector length (L2 norm).
vector(std::array< T, 3 > v__)
Create from array.
vector(vector< T > const &vec__)
Copy constructor.
vector(T x, T y, T z)
Create arbitrary vector.
double length2() const
Return square length of the vector.
vector(std::vector< T > const &v__)
Create from std::vector.
vector(T const *ptr__)
Create from raw pointer.
void zero(T *ptr__, size_t n__)
Zero the device memory.
auto dot(vector< U > const &b__, matrix< T > const &m__)
Vector-matrix multiplication.
auto transpose(matrix< T > src)
Return transpose of the matrix.
auto find_translations(double radius__, matrix< double > const &lattice_vectors__)
Find supercell that circumscribes the sphere with a given radius.
auto inverse(matrix< int > src)
Return inverse of the integer matrix.
auto spherical_coordinates(vector< double > vc)
Transform Cartesian coordinates [x,y,z] to spherical coordinates [r,theta,phi].
auto reduce_coordinates(vector< double > coord__)
Reduce the coordinates to the first unit cell.
Namespace of the SIRIUS library.