SIRIUS 7.5.0
Electronic structure library and applications
periodic_function.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2019 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 periodic_function.hpp
21 *
22 * \brief Contains declaration and partial implementation of sirius::Periodic_function class.
23 */
24
25#ifndef __PERIODIC_FUNCTION_HPP__
26#define __PERIODIC_FUNCTION_HPP__
27
29#include "spheric_function.hpp"
30#include "spheric_function_set.hpp"
32#include "core/profiler.hpp"
33
34namespace sirius {
35
36/// Representation of the periodical function on the muffin-tin geometry.
37/** Inside each muffin-tin the spherical expansion is used:
38 * \f[
39 * f({\bf r}) = \sum_{\ell m} f_{\ell m}(r) Y_{\ell m}(\hat {\bf r})
40 * \f]
41 * or
42 * \f[
43 * f({\bf r}) = \sum_{\ell m} f_{\ell m}(r) R_{\ell m}(\hat {\bf r})
44 * \f]
45 * In the interstitial region function is stored on the real-space grid or as a Fourier series:
46 * \f[
47 * f({\bf r}) = \sum_{{\bf G}} f({\bf G}) e^{i{\bf G}{\bf r}}
48 * \f]
49 */
50template <typename T>
52{
53 private:
54
55 /// Simulation contex.
57
58 /// Alias to unit cell.
60
61 mpi::Communicator const& comm_;
62
63 /// Regular space grid component of the periodic function.
65
66 /// Muffin-tin part of the periodic function.
68
69 /// Alias to G-vectors.
71
72 /* forbid copy constructor */
73 Periodic_function(const Periodic_function<T>& src) = delete;
74
75 /* forbid assignment operator */
76 Periodic_function<T>& operator=(const Periodic_function<T>& src) = delete;
77
78 public:
79 /// Constructor for real-space FFT grid only (PP-PW case).
81 : ctx_(ctx__)
82 , unit_cell_(ctx__.unit_cell())
83 , comm_(ctx__.comm())
84 , rg_component_(ctx__.spfft<real_type<T>>(), ctx__.gvec_fft_sptr(), rg_ptr__)
85 , gvec_(ctx__.gvec())
86 {
87 }
88
89 /// Constructor for interstitial and muffin-tin parts (FP-LAPW case).
90 Periodic_function(Simulation_context const& ctx__, std::function<lmax_t(int)> lmax__,
91 splindex_block<atom_index_t> const* spl_atoms__ = nullptr,
92 smooth_periodic_function_ptr_t<T> const* rg_ptr__ = nullptr,
93 spheric_function_set_ptr_t<T> const* mt_ptr__ = nullptr)
94 : ctx_(ctx__)
95 , unit_cell_(ctx__.unit_cell())
96 , comm_(ctx__.comm())
97 , rg_component_(ctx__.spfft<real_type<T>>(), ctx__.gvec_fft_sptr(), rg_ptr__)
98 , mt_component_("MT component of Periodic_function", ctx__.unit_cell(), lmax__, spl_atoms__, mt_ptr__)
99 , gvec_(ctx__.gvec())
100 {
101 }
102
103 /// Zero the function.
104 void zero()
105 {
106 mt_component_.zero();
107 rg_component_.zero();
108 }
109
110 /// Add the function
112 {
113 PROFILE("sirius::Periodic_function::add");
114 /* add regular-grid part */
115 this->rg_component_ += g__.rg();
116 /* add muffin-tin part */
117 if (ctx_.full_potential()) {
118 this->mt_component_ += g__.mt();
119 }
120 return *this;
121 }
122
123 Periodic_function<T>& operator*=(T alpha__)
124 {
125 PROFILE("sirius::Periodic_function::add");
126 /* add regular-grid part */
127 this->rg_component_ *= alpha__;
128 /* add muffin-tin part */
129 if (ctx_.full_potential()) {
130 for (int ialoc = 0; ialoc < unit_cell_.spl_num_atoms().local_size(); ialoc++) {
131 this->f_mt_local_(ialoc) *= alpha__;
132 }
133 }
134 return *this;
135 }
136
137
138 /// Return total integral, interstitial contribution and muffin-tin contributions.
139 inline std::tuple<T, T, std::vector<T>>
140 integrate() const
141 {
142 PROFILE("sirius::Periodic_function::integrate");
143
144 T it_val = 0;
145
146 if (!ctx_.full_potential()) {
147 //#pragma omp parallel for schedule(static) reduction(+:it_val)
148 for (int irloc = 0; irloc < this->rg().spfft().local_slice_size(); irloc++) {
149 it_val += this->rg().value(irloc);
150 }
151 } else {
152 //#pragma omp parallel for schedule(static) reduction(+:it_val)
153 for (int irloc = 0; irloc < this->rg().spfft().local_slice_size(); irloc++) {
154 it_val += this->rg().value(irloc) * ctx_.theta(irloc);
155 }
156 }
157 it_val *= (unit_cell_.omega() / fft::spfft_grid_size(this->rg().spfft()));
158 mpi::Communicator(this->rg().spfft().communicator()).allreduce(&it_val, 1);
159 T total = it_val;
160
161 std::vector<T> mt_val;
162 if (ctx_.full_potential()) {
163 mt_val = std::vector<T>(unit_cell_.num_atoms(), 0);
164
165 for (auto it : unit_cell_.spl_num_atoms()) {
166 mt_val[it.i] = mt_component_[it.i].component(0).integrate(2) * fourpi * y00;
167 }
168
169 comm_.allreduce(&mt_val[0], unit_cell_.num_atoms());
170 for (int ia = 0; ia < unit_cell_.num_atoms(); ia++) {
171 total += mt_val[ia];
172 }
173 }
174
175 return std::make_tuple(total, it_val, mt_val);
176 }
177
178 /** \todo write and read distributed functions */
179 void hdf5_write(std::string file_name__, std::string path__) const
180 {
181 auto v = this->rg().gather_f_pw();
182 if (ctx_.comm().rank() == 0) {
183 HDF5_tree fout(file_name__, hdf5_access_t::read_write);
184 fout[path__].write("f_pw", reinterpret_cast<T*>(v.data()), static_cast<int>(v.size() * 2));
185 if (ctx_.full_potential()) {
186 for (int ia = 0; ia < unit_cell_.num_atoms(); ia++) {
187 fout[path__].write("f_mt_" + std::to_string(ia), mt_component_[ia].at(sddk::memory_t::host),
188 mt_component_[ia].size());
189 }
190 }
191 }
192 }
193
194 void hdf5_read(std::string file_name__, std::string path__, sddk::mdarray<int, 2> const& gvec__)
195 {
196 HDF5_tree h5f(file_name__, hdf5_access_t::read_only);
197
198 /* read the PW coeffs. */
199 std::vector<std::complex<T>> v(gvec_.num_gvec());
200 h5f[path__].read("f_pw", reinterpret_cast<T*>(v.data()), static_cast<int>(v.size() * 2));
201
203 for (int ig = 0; ig < gvec_.num_gvec(); ig++) {
204 r3::vector<int> G(&gvec__(0, ig));
205 /* locl index in a new (current) layout */
206 auto igloc = gvec_.index_by_gvec(G) - gvec_.offset();
207 /* only one rank will store the G-vector index ig */
208 if (igloc >= 0 && igloc < gvec_.count()) {
209 igmap[igloc] = ig;
210 }
211 }
212 for (int igloc = 0; igloc < gvec_.count(); igloc++) {
213 this->rg().f_pw_local(igloc) = v[igmap[igloc]];
214 }
215
216 if (ctx_.full_potential()) {
217 for (int ia = 0; ia < unit_cell_.num_atoms(); ia++) {
218 h5f[path__].read("f_mt_" + std::to_string(ia), mt_component_[ia].at(sddk::memory_t::host),
219 mt_component_[ia].size());
220 }
221 }
222 }
223
224 T value_rg(r3::vector<T> const& vc) const
225 {
226 T p{0};
227 for (int igloc = 0; igloc < gvec_.count(); igloc++) {
228 auto vgc = gvec_.gvec_cart<index_domain_t::local>(igloc);
229 p += std::real(this->rg().f_pw_local(igloc) * std::exp(std::complex<T>(0.0, dot(vc, vgc))));
230 }
231 gvec_.comm().allreduce(&p, 1);
232 return p;
233 }
234
235 T value(r3::vector<T> const& vc)
236 {
237 int ja{-1}, jr{-1};
238 T dr{0}, tp[2];
239
240 if (unit_cell_.is_point_in_mt(vc, ja, jr, dr, tp)) {
241 auto& frlm = mt_component_[ja];
242 int lmax = sf::lmax(frlm.angular_domain_size());
243 std::vector<T> rlm(frlm.angular_domain_size());
244 sf::spherical_harmonics(lmax, tp[0], tp[1], &rlm[0]);
245 T p{0};
246 for (int lm = 0; lm < frlm.angular_domain_size(); lm++) {
247 T d = (frlm(lm, jr + 1) - frlm(lm, jr)) / unit_cell_.atom(ja).type().radial_grid().dx(jr);
248
249 p += rlm[lm] * (frlm(lm, jr) + d * dr);
250 }
251 return p;
252 } else {
253 return value_rg(vc);
254 }
255 }
256
257 inline auto const& ctx() const
258 {
259 return ctx_;
260 }
261
262 /// Return reference to regular space grid component.
263 auto& rg()
264 {
265 return rg_component_;
266 }
267
268 /// Return const reference to regular space grid component.
269 auto const& rg() const
270 {
271 return rg_component_;
272 }
273
274 /// Return reference to spherical functions component.
275 auto& mt()
276 {
277 return mt_component_;
278 }
279
280 /// Return const reference to spherical functions component.
281 auto const& mt() const
282 {
283 return mt_component_;
284 }
285};
286
287template <typename T>
288inline T inner(Periodic_function<T> const& f__, Periodic_function<T> const& g__)
289{
290 PROFILE("sirius::inner");
291 if (f__.ctx().full_potential()) {
292 auto result = sirius::inner_local(f__.rg(), g__.rg(),
293 [&](int ir) { return f__.ctx().theta(ir); });
294 f__.ctx().comm_fft().allreduce(&result, 1);
295 result += inner(f__.mt(), g__.mt());
296 return result;
297 } else {
298 return inner(f__.rg(), g__.rg());
299 }
300}
301
302/// Copy values of the function to the external location.
303template <typename T>
304inline void copy(Periodic_function<T> const& src__, periodic_function_ptr_t<T> dest__)
305{
306 copy(src__.rg(), dest__.rg);
307 if (src__.ctx().full_potential()) {
308 copy(src__.mt(), dest__.mt);
309 }
310}
311
312/// Copy the values of the function from the external location.
313template <typename T>
314inline void copy(periodic_function_ptr_t<T> const src__, Periodic_function<T>& dest__ )
315{
316 copy(src__.rg, dest__.rg());
317 if (dest__.ctx().full_potential()) {
318 copy(src__.mt, dest__.mt());
319 }
320}
321
322} // namespace sirius
323
324#endif // __PERIODIC_FUNCTION_HPP__
Atom_type const & type() const
Return const reference to corresponding atom type object.
Definition: atom.hpp:318
Interface to the HDF5 library.
Definition: hdf5_tree.hpp:86
void write(const std::string &name, T const *data, std::vector< int > const &dims)
Write a multidimensional array.
Definition: hdf5_tree.hpp:301
Representation of the periodical function on the muffin-tin geometry.
Smooth_periodic_function< T > rg_component_
Regular space grid component of the periodic function.
auto const & mt() const
Return const reference to spherical functions component.
Simulation_context const & ctx_
Simulation contex.
auto & mt()
Return reference to spherical functions component.
auto & rg()
Return reference to regular space grid component.
std::tuple< T, T, std::vector< T > > integrate() const
Return total integral, interstitial contribution and muffin-tin contributions.
Spheric_function_set< T, atom_index_t > mt_component_
Muffin-tin part of the periodic function.
Periodic_function< T > & operator+=(Periodic_function< T > const &g__)
Add the function.
void zero()
Zero the function.
Unit_cell const & unit_cell_
Alias to unit cell.
fft::Gvec const & gvec_
Alias to G-vectors.
Periodic_function(Simulation_context const &ctx__, std::function< lmax_t(int)> lmax__, splindex_block< atom_index_t > const *spl_atoms__=nullptr, smooth_periodic_function_ptr_t< T > const *rg_ptr__=nullptr, spheric_function_set_ptr_t< T > const *mt_ptr__=nullptr)
Constructor for interstitial and muffin-tin parts (FP-LAPW case).
auto const & rg() const
Return const reference to regular space grid component.
void hdf5_write(std::string file_name__, std::string path__) const
Periodic_function(Simulation_context const &ctx__, smooth_periodic_function_ptr_t< T > const *rg_ptr__=nullptr)
Constructor for real-space FFT grid only (PP-PW case).
T dx(const int i) const
Return .
Simulation context is a set of parameters and objects describing a single simulation.
double theta(int ir__) const
Return the value of the step function for the grid point ir.
mpi::Communicator const & comm() const
Total communicator of the simulation.
Representation of a smooth (Fourier-transformable) periodic function.
Representation of a unit cell.
Definition: unit_cell.hpp:43
double omega() const
Unit cell volume.
Definition: unit_cell.hpp:275
Atom const & atom(int id__) const
Return const atom instance by id.
Definition: unit_cell.hpp:344
int num_atoms() const
Number of atoms in the unit cell.
Definition: unit_cell.hpp:338
A set of G-vectors for FFTs and G+k basis functions.
Definition: gvec.hpp:130
int num_gvec() const
Return the total number of G-vectors within the cutoff.
Definition: gvec.hpp:478
int offset() const
Offset (in the global index) of G-vectors for a fine-grained distribution for a current MPI rank.
Definition: gvec.hpp:520
int count() const
Number of G-vectors for a fine-grained distribution for the current MPI rank.
Definition: gvec.hpp:506
int index_by_gvec(r3::vector< int > const &G__) const
Return a global G-vector index in the range [0, num_gvec) by the G-vector.
Definition: gvec.cpp:518
r3::vector< double > gvec_cart(int ig__) const
Return G vector in Cartesian coordinates.
Definition: gvec.hpp:574
MPI communicator wrapper.
void allreduce(T *buffer__, int count__) const
Perform the in-place (the output buffer is used as the input buffer) all-to-all reduction.
int rank() const
Rank of MPI process inside communicator.
Simple implementation of 3d vector.
Definition: r3.hpp:45
size_t spfft_grid_size(T const &spfft__)
Total size of the SpFFT transformation grid.
Definition: fft.hpp:221
int lmax(int lmmax__)
Get maximum orbital quantum number by the maximum lm index.
Definition: specfunc.hpp:56
int lm(int l, int m)
Get composite lm index by angular index l and azimuthal index m.
Definition: specfunc.hpp:50
void spherical_harmonics(int lmax, double theta, double phi, std::complex< double > *ylm)
Optimized implementation of complex spherical harmonics.
Definition: specfunc.hpp:298
std::enable_if_t< std::is_same< T, real_type< F > >::value, void > inner(::spla::Context &spla_ctx__, sddk::memory_t mem__, spin_range spins__, W const &wf_i__, band_range br_i__, Wave_functions< T > const &wf_j__, band_range br_j__, la::dmatrix< F > &result__, int irow0__, int jcol0__)
Compute inner product between the two sets of wave-functions.
Namespace of the SIRIUS library.
Definition: sirius.f90:5
T inner_local(Smooth_periodic_function< T > const &f__, Smooth_periodic_function< T > const &g__, F &&theta__)
Compute local contribution to inner product <f|g>
const double y00
First spherical harmonic .
Definition: constants.hpp:51
const double fourpi
Definition: constants.hpp:48
A time-based profiler.
Contains definition and implementation of Simulation_context class.
Contains declaration and implementation of sirius::Smooth_periodic_function and sirius::Smooth_period...
Contains declaration and implementation of sirius::Spheric_function and sirius::Spheric_function_grad...
Describe external pointers to periodic function.
Definition: typedefs.hpp:256