SIRIUS 7.5.0
Electronic structure library and applications
testing.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2022 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 testing.hpp
21 *
22 * \brief Common functions for the tests and unit tests.
23 */
24
25#ifndef __TESTING_HPP__
26#define __TESTING_HPP__
27
28#include <string>
29#include <iostream>
30#include <vector>
31#include <cmath>
32#include "core/la/linalg.hpp"
33#include "core/la/dmatrix.hpp"
35#include "core/r3/r3.hpp"
36#include "core/cmd_args.hpp"
37#include "core/profiler.hpp"
39
40namespace sirius {
41
42template <typename F>
43inline int call_test(std::string label__, F&& f__)
44{
45 int err{0};
46 std::string msg;
47 try {
48 err = f__();
49 }
50 catch (std::exception const& e) {
51 err = 1;
52 msg = e.what();
53 }
54 catch (...) {
55 err = 1;
56 msg = "unknown exception";
57 }
58 if (err) {
59 std::cout << label__ << " : Failed" << std::endl;
60 if (msg.size()) {
61 std::cout << "exception occured:" << std::endl;
62 std::cout << msg << std::endl;
63 }
64 } else {
65 std::cout << label__ << " : OK" << std::endl;
66 }
67 return err;
68}
69
70template <typename F>
71inline int call_test(std::string label__, F&& f__, cmd_args const& args__)
72{
73 printf("running %-30s : ", label__.c_str());
74 int result = f__(args__);
75 if (result) {
76 printf("\x1b[31m" "Failed" "\x1b[0m" "\n");
77 } else {
78 printf("\x1b[32m" "OK" "\x1b[0m" "\n");
79 }
80 return result;
81}
82
83class Measurement: public std::vector<double>
84{
85 public:
86
87 double average() const
88 {
89 double d = 0;
90 for (size_t i = 0; i < this->size(); i++) {
91 d += (*this)[i];
92 }
93 d /= static_cast<double>(this->size());
94 return d;
95 }
96
97 double sigma() const
98 {
99 double avg = average();
100 double variance = 0;
101 for (size_t i = 0; i < this->size(); i++) {
102 variance += std::pow((*this)[i] - avg, 2);
103 }
104 variance /= static_cast<double>(this->size());
105 return std::sqrt(variance);
106 }
107};
108
109template <typename T>
110inline auto
111random_symmetric(int N__, int bs__, la::BLACS_grid const& blacs_grid__)
112{
113 PROFILE("random_symmetric");
114
115 la::dmatrix<T> A(N__, N__, blacs_grid__, bs__, bs__);
116 la::dmatrix<T> B(N__, N__, blacs_grid__, bs__, bs__);
117 for (int j = 0; j < A.num_cols_local(); j++) {
118 for (int i = 0; i < A.num_rows_local(); i++) {
119 A(i, j) = random<T>();
120 }
121 }
122
123#ifdef SIRIUS_SCALAPACK
124 la::wrap(la::lib_t::scalapack).tranc(N__, N__, A, 0, 0, B, 0, 0);
125#else
126 for (int i = 0; i < N__; i++) {
127 for (int j = 0; j < N__; j++) {
128 B(i, j) = conj(A(j, i));
129 }
130 }
131#endif
132
133 for (int j = 0; j < A.num_cols_local(); j++) {
134 for (int i = 0; i < A.num_rows_local(); i++) {
135 A(i, j) = 0.5 * (A(i, j) + B(i, j));
136 }
137 }
138
139 for (int i = 0; i < N__; i++) {
140 A.set(i, i, 50.0);
141 }
142
143 return A;
144}
145
146template <typename T>
147inline auto
148random_positive_definite(int N__, int bs__ = 16, la::BLACS_grid const *blacs_grid__ = nullptr)
149{
150 PROFILE("random_positive_definite");
151
152 double p = 1.0 / N__;
153 auto A = (blacs_grid__) ? la::dmatrix<T>(N__, N__, *blacs_grid__, bs__, bs__) : la::dmatrix<T>(N__, N__);
154 auto B = (blacs_grid__) ? la::dmatrix<T>(N__, N__, *blacs_grid__, bs__, bs__) : la::dmatrix<T>(N__, N__);
155 for (int j = 0; j < A.num_cols_local(); j++) {
156 for (int i = 0; i < A.num_rows_local(); i++) {
157 A(i, j) = p * random<T>();
158 }
159 }
160
161 if (blacs_grid__) {
162#ifdef SIRIUS_SCALAPACK
163 la::wrap(la::lib_t::scalapack).gemm('C', 'N', N__, N__, N__, &la::constant<T>::one(), A, 0, 0, A, 0, 0,
164 &la::constant<T>::zero(), B, 0, 0);
165#else
166 RTE_THROW("not compiled with scalapack");
167#endif
168 } else {
169 la::wrap(la::lib_t::blas).gemm('C', 'N', N__, N__, N__, &la::constant<T>::one(), &A(0, 0), A.ld(),
170 &A(0, 0), A.ld(), &la::constant<T>::zero(), &B(0, 0), B.ld());
171 }
172
173 for (int i = 0; i < N__; i++) {
174 B.set(i, i, 50.0);
175 }
176
177 return B;
178}
179
180inline auto
181create_simulation_context(nlohmann::json const& conf__, r3::matrix<double> L__, int num_atoms__,
182std::vector<r3::vector<double>> coord__, bool add_vloc__, bool add_dion__)
183{
184 auto ctx = std::make_unique<sirius::Simulation_context>(conf__);
185
186 ctx->unit_cell().set_lattice_vectors(L__);
187 if (num_atoms__) {
188 auto& atype = ctx->unit_cell().add_atom_type("Cu");
189
190 if (ctx->cfg().parameters().electronic_structure_method() == "full_potential_lapwlo") {
191
192 } else {
193 /* set pseudo charge */
194 atype.zn(11);
195 /* set radial grid */
196 atype.set_radial_grid(radial_grid_t::lin_exp, 1000, 0.0, 100.0, 6);
197 /* cutoff at ~1 a.u. */
198 int icut = atype.radial_grid().index_of(1.0);
199 double rcut = atype.radial_grid(icut);
200 /* create beta radial function */
201 std::vector<double> beta(icut + 1);
202 std::vector<double> beta1(icut + 1);
203 for (int l = 0; l <= 2; l++) {
204 for (int i = 0; i <= icut; i++) {
205 double x = atype.radial_grid(i);
206 beta[i] = confined_polynomial(x, rcut, l, l + 1, 0);
207 beta1[i] = confined_polynomial(x, rcut, l, l + 2, 0);
208 }
209 /* add radial function for l */
210 atype.add_beta_radial_function(angular_momentum(l), beta);
211 atype.add_beta_radial_function(angular_momentum(l), beta1);
212 }
213
214 std::vector<double> ps_wf(atype.radial_grid().num_points());
215 for (int l = 0; l <= 2; l++) {
216 for (int i = 0; i < atype.radial_grid().num_points(); i++) {
217 double x = atype.radial_grid(i);
218 ps_wf[i] = std::exp(-x) * std::pow(x, l);
219 }
220 /* add radial function for l */
221 atype.add_ps_atomic_wf(3, angular_momentum(l), ps_wf);
222 }
223
224 /* set local part of potential */
225 std::vector<double> vloc(atype.radial_grid().num_points(), 0);
226 if (add_vloc__) {
227 for (int i = 0; i < atype.radial_grid().num_points(); i++) {
228 double x = atype.radial_grid(i);
229 vloc[i] = -atype.zn() / (std::exp(-x * (x + 1)) + x);
230 }
231 }
232 atype.local_potential(vloc);
233 /* set Dion matrix */
234 int nbf = atype.num_beta_radial_functions();
235 sddk::matrix<double> dion(nbf, nbf);
236 dion.zero();
237 if (add_dion__) {
238 for (int i = 0; i < nbf; i++) {
239 dion(i, i) = -10.0;
240 }
241 }
242 atype.d_mtrx_ion(dion);
243 /* set atomic density */
244 std::vector<double> arho(atype.radial_grid().num_points());
245 for (int i = 0; i < atype.radial_grid().num_points(); i++) {
246 double x = atype.radial_grid(i);
247 arho[i] = 2 * atype.zn() * std::exp(-x * x) * x;
248 }
249 atype.ps_total_charge_density(arho);
250 }
251
252 for (auto v: coord__) {
253 ctx->unit_cell().add_atom("Cu", v, {0, 0, 1});
254 }
255 }
256 ctx->initialize();
257 return ctx;
258}
259
260template <typename T>
261inline void
262randomize(wf::Wave_functions<T>& wf__)
263{
264 for (int i = 0; i < wf__.num_wf().get(); i++) {
265 for (int s = 0; s < wf__.num_sc().get(); s++) {
266 auto ptr = wf__.at(sddk::memory_t::host, 0, wf::spin_index(s), wf::band_index(i));
267 for (int j = 0; j < wf__.ld(); j++) {
268 ptr[j] = random<std::complex<double>>();
269 }
270 }
271 }
272}
273
274}
275
276#endif
BLACS grid wrapper.
Definition: blacs_grid.hpp:43
Distributed matrix.
Definition: dmatrix.hpp:56
Contains definition and implementation of cmd_args class.
Contains definition and implementation of distributed matrix class.
Linear algebra interface.
@ scalapack
CPU ScaLAPACK.
Namespace of the SIRIUS library.
Definition: sirius.f90:5
auto conj(double x__)
Return complex conjugate of a number. For a real value this is the number itself.
Definition: math_tools.hpp:165
A time-based profiler.
Simple classes and functions to work with vectors and matrices of the R^3 space.
Contains definition and implementation of Simulation_context class.
Contains declaration and implementation of Wave_functions class.