SIRIUS 7.5.0
Electronic structure library and applications
fft3d_grid.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2018 Anton Kozhevnikov, Thomas Schulthess
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
5// the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8// following disclaimer.
9// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
10// and the following disclaimer in the documentation and/or other materials provided with the distribution.
11//
12// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
13// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
15// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
18// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
20/** \file fft3d_grid.hpp
21 *
22 * \brief Contains declaration and implementation of sddk::FFT3D_grid class.
23 */
24
25#include <array>
26#include <cassert>
27#include "core/r3/r3.hpp"
28
29#ifndef __FFT3D_GRID_HPP__
30#define __FFT3D_GRID_HPP__
31
32namespace sirius {
33
34namespace fft {
35
36/// Helper class to create FFT grids of given sizes and compute indices in space- and frequency domains.
37class Grid : public std::array<int, 3>
38{
39 private:
40 /// Reciprocal space range.
41 std::array<std::pair<int, int>, 3> grid_limits_;
42
43 /// Find smallest optimal grid size starting from n.
44 int find_grid_size(int n)
45 {
46 while (true) {
47 int m = n;
48 for (int k = 2; k <= 5; k++) {
49 while (m % k == 0) {
50 m /= k;
51 }
52 }
53 if (m == 1) {
54 return n;
55 } else {
56 n++;
57 }
58 }
59 }
60
61 /// Find grid sizes and limits for all three dimensions.
62 void find_grid_size(std::array<int, 3> initial_dims__)
63 {
64 for (int i = 0; i < 3; i++) {
65 (*this)[i] = find_grid_size(initial_dims__[i]);
66
67 grid_limits_[i].second = (*this)[i] / 2;
68 grid_limits_[i].first = grid_limits_[i].second - (*this)[i] + 1;
69 }
70
71 for (int x = 0; x < (*this)[0]; x++) {
72 if (coord_by_freq<0>(freq_by_coord<0>(x)) != x) {
73 throw std::runtime_error("fft::Grid::find_grid_size(): wrong mapping of x-coordinates");
74 }
75 }
76 for (int x = 0; x < (*this)[1]; x++) {
77 if (coord_by_freq<1>(freq_by_coord<1>(x)) != x) {
78 throw std::runtime_error("fft::Grid::find_grid_size(): wrong mapping of y-coordinates");
79 }
80 }
81 for (int x = 0; x < (*this)[2]; x++) {
82 if (coord_by_freq<2>(freq_by_coord<2>(x)) != x) {
83 throw std::runtime_error("ffr::Grid::find_grid_size(): wrong mapping of z-coordinates");
84 }
85 }
86 }
87
88 public:
89
90 /// Default constructor.
92 {
93 }
94
95 /// Create FFT grid with initial dimensions.
96 Grid(std::array<int, 3> initial_dims__)
97 {
98 find_grid_size(initial_dims__);
99 }
100
101 /// Limits of a given dimension.
102 inline const std::pair<int, int>& limits(int idim__) const
103 {
104 assert(idim__ >= 0 && idim__ < 3);
105 return grid_limits_[idim__];
106 }
107
108 /// Total size of the FFT grid.
109 inline int num_points() const
110 {
111 return (*this)[0] * (*this)[1] * (*this)[2];
112 }
113
114 /// Get coordinate in range [0, N_d) by the frequency index.
115 template <int d>
116 inline int coord_by_freq(int i__) const
117 {
118 if (i__ < 0) {
119 i__ += (*this)[d];
120 }
121 return i__;
122 }
123
124 /// Return {x, y, z} coordinates by frequency indices.
125 inline std::array<int, 3> coord_by_freq(int i0__, int i1__, int i2__) const
126 {
127 return {coord_by_freq<0>(i0__), coord_by_freq<1>(i1__), coord_by_freq<2>(i2__)};
128 }
129
130 /// Get frequency by coordinate.
131 template <int d>
132 inline int freq_by_coord(int x__) const
133 {
134 if (x__ > grid_limits_[d].second) {
135 x__ -= (*this)[d];
136 }
137 return x__;
138 }
139
140 /// Return 3d vector of frequencies corresponding to {x, y, z} position in the FFT buffer.
141 inline std::array<int, 3> freq_by_coord(int x__, int y__, int z__) const
142 {
143 return {freq_by_coord<0>(x__), freq_by_coord<1>(y__), freq_by_coord<2>(z__)};
144 }
145
146 /// Linear index inside FFT buffer by grid coordinates.
147 inline int index_by_coord(int x__, int y__, int z__) const
148 {
149 return (x__ + (*this)[0] * (y__ + z__ * (*this)[1]));
150 }
151
152 /// Return linear index of a plane-wave harmonic with fractional coordinates (i0, i1, i2) inside FFT buffer.
153 inline int index_by_freq(int i0__, int i1__, int i2__) const
154 {
155 auto coord = coord_by_freq(i0__, i1__, i2__);
156 return index_by_coord(coord[0], coord[1], coord[2]);
157 }
158};
159
160/// Get the minimum grid that circumscribes the cutoff sphere.
161inline auto get_min_grid(double cutoff__, r3::matrix<double> M__)
162{
163 return Grid(r3::find_translations(cutoff__, M__) + r3::vector<int>({2, 2, 2}));
164}
165
166} // namespace fft
167
168} // namespace sirius
169
170#endif // __FFT3D_GRID_HPP__
Helper class to create FFT grids of given sizes and compute indices in space- and frequency domains.
Definition: fft3d_grid.hpp:38
std::array< int, 3 > freq_by_coord(int x__, int y__, int z__) const
Return 3d vector of frequencies corresponding to {x, y, z} position in the FFT buffer.
Definition: fft3d_grid.hpp:141
int coord_by_freq(int i__) const
Get coordinate in range [0, N_d) by the frequency index.
Definition: fft3d_grid.hpp:116
int index_by_coord(int x__, int y__, int z__) const
Linear index inside FFT buffer by grid coordinates.
Definition: fft3d_grid.hpp:147
std::array< int, 3 > coord_by_freq(int i0__, int i1__, int i2__) const
Return {x, y, z} coordinates by frequency indices.
Definition: fft3d_grid.hpp:125
void find_grid_size(std::array< int, 3 > initial_dims__)
Find grid sizes and limits for all three dimensions.
Definition: fft3d_grid.hpp:62
int num_points() const
Total size of the FFT grid.
Definition: fft3d_grid.hpp:109
const std::pair< int, int > & limits(int idim__) const
Limits of a given dimension.
Definition: fft3d_grid.hpp:102
std::array< std::pair< int, int >, 3 > grid_limits_
Reciprocal space range.
Definition: fft3d_grid.hpp:41
int freq_by_coord(int x__) const
Get frequency by coordinate.
Definition: fft3d_grid.hpp:132
int index_by_freq(int i0__, int i1__, int i2__) const
Return linear index of a plane-wave harmonic with fractional coordinates (i0, i1, i2) inside FFT buff...
Definition: fft3d_grid.hpp:153
Grid(std::array< int, 3 > initial_dims__)
Create FFT grid with initial dimensions.
Definition: fft3d_grid.hpp:96
Grid()
Default constructor.
Definition: fft3d_grid.hpp:91
int find_grid_size(int n)
Find smallest optimal grid size starting from n.
Definition: fft3d_grid.hpp:44
Simple implementation of 3d vector.
Definition: r3.hpp:45
auto get_min_grid(double cutoff__, r3::matrix< double > M__)
Get the minimum grid that circumscribes the cutoff sphere.
Definition: fft3d_grid.hpp:161
auto find_translations(double radius__, matrix< double > const &lattice_vectors__)
Find supercell that circumscribes the sphere with a given radius.
Definition: r3.hpp:572
Namespace of the SIRIUS library.
Definition: sirius.f90:5
Simple classes and functions to work with vectors and matrices of the R^3 space.