SIRIUS 7.5.0
Electronic structure library and applications
xc_functional.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 xc_functional.hpp
21 *
22 * \brief Contains implementation of sirius::XC_functional class.
23 */
24
25#ifndef __XC_FUNCTIONAL_HPP__
26#define __XC_FUNCTIONAL_HPP__
27
28#include <xc.h>
29#include <string.h>
30#include "core/r3/r3.hpp"
31#include "xc_functional_base.hpp"
32#include "core/fft/fft.hpp"
33#if defined(SIRIUS_USE_VDWXC)
34#include <vdwxc.h>
35#if SIRIUS_HAVE_VDWXC_MPI
36#include <vdwxc_mpi.h>
37#endif
38#endif
39
40namespace sirius {
41
42/// Interface class to Libxc.
44{
45 private:
46 // I can not use a generic void pointer because xc_func_type is a structure
47 // while wdv_functional_ is a pointer over structure.
48#if defined(SIRIUS_USE_VDWXC)
49 vdwxc_data handler_vdw_{nullptr};
50 bool vdw_functional_{false};
51#endif
52 /* forbid copy constructor */
53 XC_functional(const XC_functional& src) = delete;
54
55 /* forbid assignment operator */
56 XC_functional& operator=(const XC_functional& src) = delete;
57
58 public:
59
60 /* we need the context because libvdwxc asks for lattice vectors and fft parameters */
61 XC_functional(spfft::Transform const& fft__, r3::matrix<double> const& lattice_vectors__,
62 const std::string libxc_name__, int num_spins__)
63 : XC_functional_base(libxc_name__, num_spins__)
64 {
65
66#if defined(SIRIUS_USE_VDWXC)
67 /* return immediately if the functional_base class is initialized */
68 if (this->libxc_initialized_) {
69 return;
70 }
71
72 /* test if have van der walls functionals types */
73
74 bool test = (libxc_name_ == "XC_FUNC_VDWDF");
75 test = test || (libxc_name_ == "XC_FUNC_VDWDF2");
76 test = test || (libxc_name_ == "XC_FUNC_VDWDFCX");
77
78 int func_ = -1;
79
80 if (libxc_name__ == "XC_FUNC_VDWDF") {
81 func_ = FUNC_VDWDF;
82 }
83
84 if (libxc_name__ == "XC_FUNC_VDWDF2") {
85 func_ = FUNC_VDWDF2;
86 }
87
88 if (libxc_name__ == "XC_FUNC_VDWDFCX") {
89 func_ = FUNC_VDWDFCX;
90 }
91
92 if (test) {
93 if (num_spins__ == 1) {
94 // non magnetic case
95 handler_vdw_ = vdwxc_new(func_);
96 } else {
97 // magnetic case
98 handler_vdw_ = vdwxc_new_spin(func_);
99 }
100
101 if (!handler_vdw_) {
102 std::stringstream s;
103 s << "VDW functional lib could not be initialized";
104 RTE_THROW(s);
105 }
106
107 double v1[3] = { lattice_vectors__(0, 0), lattice_vectors__(1, 0), lattice_vectors__(2, 0) };
108 double v2[3] = { lattice_vectors__(0, 1), lattice_vectors__(1, 1), lattice_vectors__(2, 1) };
109 double v3[3] = { lattice_vectors__(0, 2), lattice_vectors__(1, 2), lattice_vectors__(2, 2) };
110 vdwxc_set_unit_cell(handler_vdw_,
111 fft__.dim_x(),
112 fft__.dim_y(),
113 fft__.dim_z(),
114 v1[0], v1[1], v1[2],
115 v2[0], v2[1], v2[2],
116 v3[0], v3[1], v3[2]);
117 if (mpi::Communicator(fft__.communicator()).size() == 1) {
118 vdwxc_init_serial(handler_vdw_);
119 } else {
120#if SIRIUS_HAVE_VDWXC_MPI
121 vdwxc_init_mpi(handler_vdw_, fft__.communicator());
122#else
123 vdwxc_init_serial(handler_vdw_);
124#endif
125 }
126 vdw_functional_ = true;
127 return;
128 } else {
129 /* it means that the functional does not exist either in vdw or xc libraries */
130 std::stringstream s;
131 s << "XC functional " << libxc_name__ << " is unknown";
132 RTE_THROW(s);
133 }
134#else
135 if (this->libxc_initialized_) {
136 return;
137 } else {
138 /* it means that the functional does not exist either in vdw or xc libraries */
139 std::stringstream s;
140 s << "XC functional " << libxc_name__ << " is unknown";
141 RTE_THROW(s);
142 }
143#endif /* SIRIUS_USE_VDWXC */
144 }
145
147 :XC_functional_base(std::move(src__))
148 {
149#if defined(SIRIUS_USE_VDWXC)
150 this->handler_vdw_ = src__.handler_vdw_;
151 this->vdw_functional_ = src__.vdw_functional_;
152 src__.vdw_functional_ = false;
153#endif
154 }
155
157 {
158#if defined(SIRIUS_USE_VDWXC)
159 if (this->vdw_functional_) {
160 vdwxc_finalize(&this->handler_vdw_);
161 this->vdw_functional_ = false;
162 return;
163 }
164#endif
165 }
166
167 const std::string refs() const
168 {
169#if defined(SIRIUS_USE_VDWXC)
170 std::stringstream s;
171 if (vdw_functional_) {
172 s << "==============================================================================\n";
173 s << " \n";
174 s << "Warning : these functionals should be used in combination with GGA functionals\n";
175 s << " \n";
176 s << "==============================================================================\n";
177 s << "\n";
178 s << "A. H. Larsen, M. Kuisma, J. Löfgren, Y. Pouillon, P. Erhart, and P. Hyldgaard, ";
179 s << "Modelling Simul. Mater. Sci. Eng. 25, 065004 (2017) (10.1088/1361-651X/aa7320)\n";
180 return s.str();
181 }
182#endif
183 return XC_functional_base::refs();
184 }
185
186 int family() const
187 {
188#if defined(SIRIUS_USE_VDWXC)
189 if (this->vdw_functional_ == true) {
190 return XC_FAMILY_UNKNOWN;
191 }
192#endif
193 return XC_functional_base::family();
194 }
195
196 bool is_vdw() const
197 {
198#if defined(SIRIUS_USE_VDWXC)
199 return this->vdw_functional_;
200#else
201 return false;
202#endif
203 }
204
205 void vdw_update_unit_cell(spfft::Transform const& fft__, r3::matrix<double> const& lattice_vectors__)
206 {
207 #ifdef SIRIUS_USE_VDWXC
208 if(is_vdw()) {
209 double v1[3] = {lattice_vectors__(0, 0), lattice_vectors__(1, 0), lattice_vectors__(2, 0)};
210 double v2[3] = {lattice_vectors__(0, 1), lattice_vectors__(1, 1), lattice_vectors__(2, 1)};
211 double v3[3] = {lattice_vectors__(0, 2), lattice_vectors__(1, 2), lattice_vectors__(2, 2)};
212
213 vdwxc_set_unit_cell(handler_vdw_, fft__.dim_x(), fft__.dim_y(), fft__.dim_z(), v1[0], v1[1], v1[2], v2[0],
214 v2[1], v2[2], v3[0], v3[1], v3[2]);
215 }
216 #endif
217 }
218
219 int kind() const
220 {
221
222#if defined(SIRIUS_USE_VDWXC)
223 if (this->vdw_functional_ == true) {
224 return -1;
225 }
226#endif
227 return XC_functional_base::kind();
228 }
229
230#if defined(SIRIUS_USE_VDWXC)
231 /// get van der walls contribution for the exchange term
232 void get_vdw(double* rho,
233 double* sigma,
234 double* vrho,
235 double* vsigma,
236 double* energy__)
237 {
238 if (!is_vdw()) {
239 RTE_THROW("Error wrong vdw XC");
240 }
241 energy__[0] = vdwxc_calculate(handler_vdw_, rho, sigma, vrho, vsigma);
242 }
243
244 /// get van der walls contribution to the exchange term magnetic case
245 void get_vdw(double *rho_up, double *rho_down,
246 double *sigma_up, double *sigma_down,
247 double *vrho_up, double *vrho_down,
248 double *vsigma_up, double *vsigma_down,
249 double *energy__)
250 {
251 if (!is_vdw()) {
252 RTE_THROW("Error wrong XC");
253 }
254
255 energy__[0] = vdwxc_calculate_spin(handler_vdw_, rho_up, rho_down,
256 sigma_up , sigma_down,
257 vrho_up, vrho_down,
258 vsigma_up, vsigma_down);
259 }
260#endif
261};
262
263}
264
265#endif // __XC_FUNCTIONAL_H__
Interface class to Libxc.
Interface class to Libxc.
MPI communicator wrapper.
int size() const
Size of the communicator (number of ranks).
Contains helper functions for the interface with SpFFT library.
Namespace of the SIRIUS library.
Definition: sirius.f90:5
Simple classes and functions to work with vectors and matrices of the R^3 space.