SIRIUS 7.5.0
Electronic structure library and applications
k_point_set.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2016 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 k_point_set.hpp
21 *
22 * \brief Contains declaration and partial implementation of sirius::K_point_set class.
23 */
24
25#ifndef __K_POINT_SET_HPP__
26#define __K_POINT_SET_HPP__
27
28#include "k_point.hpp"
29#include "dft/smearing.hpp"
30
31namespace sirius {
32
33enum class sync_band_t
34{
35 energy,
36 occupancy
37};
38
39/// Set of k-points.
41{
42 private:
43 /// Context of a simulation.
45
46 /// List of k-points.
47 std::vector<std::unique_ptr<K_point<double>>> kpoints_;
48
49#if defined(SIRIUS_USE_FP32)
50 /// List of k-points in fp32 type, most calculation and assertion in this class only rely on fp64 type kpoints_
51 std::vector<std::unique_ptr<K_point<float>>> kpoints_float_;
52#endif
53
54 /// Split index of k-points.
56
57 /// Fermi energy which is searched in find_band_occupancies().
58 double energy_fermi_{0};
59
60 /// Band gap found by find_band_occupancies().
61 double band_gap_{0};
62
63 /// Copy constuctor is not allowed.
64 K_point_set(K_point_set& src) = delete;
65
66 /// Create regular grid of k-points.
67 void create_k_mesh(r3::vector<int> k_grid__, r3::vector<int> k_shift__, int use_symmetry__);
68
69 bool initialized_{false};
70
71 /// Return sum of valence eigen-values store in Kpoint<T>.
72 template <typename T>
73 double valence_eval_sum() const;
74
75 /// Return entropy contribution from smearing store in Kpoint<T>.
76 template <typename T>
77 double entropy_sum() const;
78 public:
79 /// Create empty k-point set.
81 : ctx_(ctx__)
82 {
83 }
84
85 /// Create a regular mesh of k-points.
86 K_point_set(Simulation_context& ctx__, r3::vector<int> k_grid__, r3::vector<int> k_shift__, int use_symmetry__)
87 : ctx_(ctx__)
88 {
89 create_k_mesh(k_grid__, k_shift__, use_symmetry__);
90 }
91
92 /// Create k-point set from a list of vectors.
93 K_point_set(Simulation_context& ctx__, std::vector<std::array<double, 3>> vec__)
94 : ctx_(ctx__)
95 {
96 for (auto& v : vec__) {
97 add_kpoint(&v[0], 1.0);
98 }
99 initialize();
100 }
101
102 /// Create k-point set from a list of vectors.
103 K_point_set(Simulation_context& ctx__, std::initializer_list<std::array<double, 3>> vec__)
104 : K_point_set(ctx__, std::vector<std::array<double, 3>>(vec__.begin(), vec__.end()))
105 {
106 }
107
108 /// Initialize the k-point set
109 void initialize(std::vector<int> const& counts = {});
110
111 /// Sync band energies or occupancies between all MPI ranks.
112 template <typename T, sync_band_t what>
113 void sync_band();
114
115 /// Find Fermi energy and band occupation numbers.
116 template <typename T>
118
119 /// Print basic info to the standard output.
120 void print_info();
121
122 /// Save k-point set to HDF5 file.
123 void save(std::string const& name__) const;
124
125 void load();
126
127 /// Return sum of valence eigen-values.
128 double valence_eval_sum() const;
129
130 /// Return entropy contribution from smearing.
131 double entropy_sum() const;
132
133 inline auto const& spl_num_kpoints() const
134 {
135 return spl_num_kpoints_;
136 }
137
138 inline auto const& comm() const
139 {
140 return ctx_.comm_k();
141 }
142
143 /// Update k-points after moving atoms or changing the lattice vectors.
144 void update()
145 {
146 /* update k-points */
147 for (auto it : spl_num_kpoints_) {
148 kpoints_[it.i]->update();
149#if defined(SIRIUS_USE_FP32)
150 kpoints_float_[it.i]->update();
151#endif
152 }
153 }
154
155 /// Get a list of band energies for a given k-point index.
156 template <typename T>
157 auto get_band_energies(int ik__, int ispn__) const
158 {
159 std::vector<double> bnd_e(ctx_.num_bands());
160 for (int j = 0; j < ctx_.num_bands(); j++) {
161 bnd_e[j] = (*this).get<T>(ik__)->band_energy(j, ispn__);
162 }
163 return bnd_e;
164 }
165
166 /// Return maximum number of G+k vectors among all k-points.
167 int max_num_gkvec() const
168 {
169 int max_num_gkvec{0};
170 for (auto it : spl_num_kpoints_) {
171 max_num_gkvec = std::max(max_num_gkvec, kpoints_[it.i]->num_gkvec());
172 }
173 comm().allreduce<int, mpi::op_t::max>(&max_num_gkvec, 1);
174 return max_num_gkvec;
175 }
176
177 /// Add k-point to the set.
178 void add_kpoint(r3::vector<double> vk__, double weight__)
179 {
180 kpoints_.push_back(std::unique_ptr<K_point<double>>(new K_point<double>(ctx_, vk__, weight__)));
181#ifdef SIRIUS_USE_FP32
182 kpoints_float_.push_back(std::unique_ptr<K_point<float>>(new K_point<float>(ctx_, vk__, weight__)));
183#endif
184 }
185
186 /// Add multiple k-points to the set.
187 void add_kpoints(sddk::mdarray<double, 2> const& kpoints__, double const* weights__)
188 {
189 for (int ik = 0; ik < (int)kpoints__.size(1); ik++) {
190 add_kpoint(&kpoints__(0, ik), weights__[ik]);
191 }
192 }
193
194 template <typename T>
195 inline K_point<T>* get(int ik__) const;
196
197 template <typename T>
198 inline K_point<T>* get(int ik__)
199 {
200 return const_cast<K_point<T>*>(static_cast<K_point_set const&>(*this).get<T>(ik__));
201 }
202
203 /// Return total number of k-points.
204 inline int num_kpoints() const
205 {
206 return static_cast<int>(kpoints_.size());
207 }
208
209 inline auto spl_num_kpoints(kp_index_t::local ikloc__) const
210 {
211 return spl_num_kpoints_.global_index(ikloc__);
212 }
213
214 inline double energy_fermi() const
215 {
216 return energy_fermi_;
217 }
218
219 inline void set_energy_fermi(double energy_fermi__)
220 {
221 this->energy_fermi_ = energy_fermi__;
222 }
223
224 inline double band_gap() const
225 {
226 return band_gap_;
227 }
228
229 /// Find index of k-point.
231 {
232 for (int ik = 0; ik < num_kpoints(); ik++) {
233 if ((kpoints_[ik]->vk() - vk__).length() < 1e-12) {
234 return ik;
235 }
236 }
237 return -1;
238 }
239
240 inline auto& ctx()
241 {
242 return ctx_;
243 }
244
245 const auto& unit_cell()
246 {
247 return ctx_.unit_cell();
248 }
249
250 /// Send G+k vectors of k-point jk to a given rank.
251 /** Other ranks receive an empty Gvec placeholder */
252 inline fft::Gvec get_gkvec(kp_index_t::global jk__, int rank__)
253 {
254 /* rank in the k-point communicator */
255 int my_rank = comm().rank();
256
257 /* rank that stores jk */
258 int jrank = spl_num_kpoints().location(jk__).ib;
259
260 /* need this to pass communicator */
261 fft::Gvec gkvec(ctx_.comm_band());
262
263 fft::Gvec const* gvptr{nullptr};
264 /* if this rank stores the k-point, then send it */
265 if (my_rank == jrank) {
266 gvptr = &kpoints_[jk__].get()->gkvec();
267 } else {
268 gvptr = &gkvec;
269 }
270 return send_recv(comm(), *gvptr, jrank, rank__);
271 }
272};
273
274template<>
275inline K_point<double>* K_point_set::get<double>(int ik__) const
276{
277 RTE_ASSERT(ik__ >= 0 && ik__ < (int)kpoints_.size());
278 return kpoints_[ik__].get();
279}
280
281template<>
282inline K_point<float>* K_point_set::get<float>(int ik__) const
283{
284#if defined(SIRIUS_USE_FP32)
285 RTE_ASSERT(ik__ >= 0 && ik__ < (int)kpoints_float_.size());
286 return kpoints_float_[ik__].get();
287#else
288 RTE_THROW("not compiled with FP32 support");
289 return nullptr; // make compiler happy
290#endif
291}
292
293}; // namespace sirius
294
295#endif // __K_POINT_SET_H__
Set of k-points.
Definition: k_point_set.hpp:41
int num_kpoints() const
Return total number of k-points.
double entropy_sum() const
Return entropy contribution from smearing store in Kpoint<T>.
double energy_fermi_
Fermi energy which is searched in find_band_occupancies().
Definition: k_point_set.hpp:58
int find_kpoint(r3::vector< double > vk__)
Find index of k-point.
K_point_set(Simulation_context &ctx__, std::initializer_list< std::array< double, 3 > > vec__)
Create k-point set from a list of vectors.
fft::Gvec get_gkvec(kp_index_t::global jk__, int rank__)
Send G+k vectors of k-point jk to a given rank.
void add_kpoint(r3::vector< double > vk__, double weight__)
Add k-point to the set.
std::vector< std::unique_ptr< K_point< double > > > kpoints_
List of k-points.
Definition: k_point_set.hpp:47
K_point_set(Simulation_context &ctx__, r3::vector< int > k_grid__, r3::vector< int > k_shift__, int use_symmetry__)
Create a regular mesh of k-points.
Definition: k_point_set.hpp:86
void initialize(std::vector< int > const &counts={})
Initialize the k-point set.
K_point_set(Simulation_context &ctx__)
Create empty k-point set.
Definition: k_point_set.hpp:80
K_point_set(K_point_set &src)=delete
Copy constuctor is not allowed.
Simulation_context & ctx_
Context of a simulation.
Definition: k_point_set.hpp:44
double valence_eval_sum() const
Return sum of valence eigen-values store in Kpoint<T>.
void add_kpoints(sddk::mdarray< double, 2 > const &kpoints__, double const *weights__)
Add multiple k-points to the set.
void sync_band()
Sync band energies or occupancies between all MPI ranks.
Definition: k_point_set.cpp:30
K_point_set(Simulation_context &ctx__, std::vector< std::array< double, 3 > > vec__)
Create k-point set from a list of vectors.
Definition: k_point_set.hpp:93
void print_info()
Print basic info to the standard output.
int max_num_gkvec() const
Return maximum number of G+k vectors among all k-points.
void find_band_occupancies()
Find Fermi energy and band occupation numbers.
void create_k_mesh(r3::vector< int > k_grid__, r3::vector< int > k_shift__, int use_symmetry__)
Create regular grid of k-points.
Definition: k_point_set.cpp:90
void update()
Update k-points after moving atoms or changing the lattice vectors.
double band_gap_
Band gap found by find_band_occupancies().
Definition: k_point_set.hpp:61
void save(std::string const &name__) const
Save k-point set to HDF5 file.
splindex_chunk< kp_index_t > spl_num_kpoints_
Split index of k-points.
Definition: k_point_set.hpp:55
auto get_band_energies(int ik__, int ispn__) const
Get a list of band energies for a given k-point index.
Simulation context is a set of parameters and objects describing a single simulation.
auto const & comm_band() const
Band parallelization communicator.
auto const & comm_k() const
Communicator between k-points.
int num_bands(int num_bands__)
Set the number of bands.
A set of G-vectors for FFTs and G+k basis functions.
Definition: gvec.hpp:130
Simple implementation of 3d vector.
Definition: r3.hpp:45
size_t size() const
Return total size (number of elements) of the array.
Definition: memory.hpp:1207
Externally defined block distribution.
Definition: splindex.hpp:444
Contains definition of sirius::K_point class.
Namespace of the SIRIUS library.
Definition: sirius.f90:5
Smearing functions used in finding the band occupancies.