Skip to content

Commit 4f2e453

Browse files
authored
Radial quadrature grid (#5173)
* initial commit * ta3 * add unit test * more tests * minor change
1 parent 954c358 commit 4f2e453

File tree

7 files changed

+315
-40
lines changed

7 files changed

+315
-40
lines changed

source/module_base/grid/delley.cpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
#include "module_base/grid/delley.h"
22

3+
#include <functional>
34
#include <algorithm>
45
#include <cmath>
56
#include <cassert>
67

78
namespace {
89

9-
struct Table {
10+
struct DelleyTable {
1011
const int lmax_;
1112
const int ngrid_;
1213
const int ntype_[6];
1314
const std::vector<double> data_;
1415
};
1516

1617
// Delley's table from the original article
17-
const std::vector<Table> table = {
18+
const std::vector<DelleyTable> delley_table = {
1819
{
1920
17, 110, {1, 1, 0, 3, 1, 0},
2021
{
@@ -209,7 +210,7 @@ const std::vector<Table> table = {
209210
0.63942796347491023, 0.06424549224220589, 0.0009158016174693465,
210211
}
211212
}
212-
}; // end of the definition of "table"
213+
}; // end of the definition of "delley_table"
213214

214215
// size of each group of points with octahedral symmetry
215216
// 6: (1, 0, 0) x sign x permutation (vertices)
@@ -324,15 +325,15 @@ const std::vector<Fill_t> fill = {
324325
},
325326
}; // end of the definition of "fill"
326327

327-
const Table* _find_table(int& lmax) {
328-
// NOTE: this function assumes elements in "Delley::table_" are
328+
const DelleyTable* _find_delley(int& lmax) {
329+
// NOTE: this function assumes elements in "delley_table" are
329330
// arranged such that their members "lmax_" are in ascending order.
330-
auto tab = std::find_if(table.begin(), table.end(),
331-
[lmax](const Table& t) { return t.lmax_ >= lmax; });
332-
return tab == table.end() ? nullptr : (lmax = tab->lmax_, &(*tab));
331+
auto tab = std::find_if(delley_table.begin(), delley_table.end(),
332+
[lmax](const DelleyTable& t) { return t.lmax_ >= lmax; });
333+
return tab == delley_table.end() ? nullptr : (lmax = tab->lmax_, &(*tab));
333334
}
334335

335-
void _get(const Table* tab, double* grid, double* weight) {
336+
void _delley(const DelleyTable* tab, double* grid, double* weight) {
336337
assert(tab);
337338
const double* ptr = &tab->data_[0];
338339
for (int itype = 0; itype < 6; ++itype) {
@@ -348,29 +349,29 @@ void _get(const Table* tab, double* grid, double* weight) {
348349
} // end of anonymous namespace
349350

350351

351-
int Grid::Delley::ngrid(int& lmax) {
352-
auto tab = _find_table(lmax);
352+
int Grid::Angular::ngrid_delley(int& lmax) {
353+
auto tab = _find_delley(lmax);
353354
return tab ? tab->ngrid_ : -1;
354355
}
355356

356357

357-
int Grid::Delley::get(int& lmax, double* grid, double* weight) {
358-
auto tab = _find_table(lmax);
359-
return tab ? _get(tab, grid, weight), 0 : -1;
358+
int Grid::Angular::delley(int& lmax, double* grid, double* weight) {
359+
auto tab = _find_delley(lmax);
360+
return tab ? _delley(tab, grid, weight), 0 : -1;
360361
}
361362

362363

363-
int Grid::Delley::get(
364+
int Grid::Angular::delley(
364365
int& lmax,
365366
std::vector<double>& grid,
366367
std::vector<double>& weight
367368
) {
368-
auto tab = _find_table(lmax);
369+
auto tab = _find_delley(lmax);
369370
if (!tab) {
370371
return -1;
371372
}
372373
grid.resize(3 * tab->ngrid_);
373374
weight.resize(tab->ngrid_);
374-
_get(tab, grid.data(), weight.data());
375+
_delley(tab, grid.data(), weight.data());
375376
return 0;
376377
}

source/module_base/grid/delley.h

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,10 @@
1-
#ifndef GRID_DELLEY_H
2-
#define GRID_DELLEY_H
1+
#ifndef GRID_ANGULAR_DELLEY_H
2+
#define GRID_ANGULAR_DELLEY_H
33

44
#include <vector>
5-
#include <functional>
65

7-
/**
8-
* @brief Delley's grid for quadrature on the unit sphere.
9-
*
10-
* Reference:
11-
* Delley, B. (1996). High order integration schemes on the unit sphere.
12-
* Journal of computational chemistry, 17(9), 1152-1155.
13-
*
14-
*/
156
namespace Grid {
16-
namespace Delley {
7+
namespace Angular {
178

189
/**
1910
* @brief Number of Delley's grid points for a certain order of accuracy.
@@ -27,7 +18,7 @@ namespace Delley {
2718
* lmax will be set to 23.
2819
*
2920
*/
30-
int ngrid(int& lmax);
21+
int ngrid_delley(int& lmax);
3122

3223

3324
/**
@@ -45,13 +36,16 @@ int ngrid(int& lmax);
4536
* ngrid(lmax) elements, respectively. The function will return 0 if
4637
* successful, or -1 if the requested order cannot be fulfilled.
4738
*
39+
* Reference:
40+
* Delley, B. (1996). High order integration schemes on the unit sphere.
41+
* Journal of computational chemistry, 17(9), 1152-1155.
4842
*/
49-
int get(int& lmax, double* grid, double* weight);
43+
int delley(int& lmax, double* grid, double* weight);
5044

5145
// a handy wrapper doing the same as above
52-
int get(int& lmax, std::vector<double>& grid, std::vector<double>& weight);
46+
int delley(int& lmax, std::vector<double>& grid, std::vector<double>& weight);
5347

54-
} // end of namespace Delley
48+
} // end of namespace Angular
5549
} // end of namespace Grid
5650

5751
#endif

source/module_base/grid/radial.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "module_base/grid/radial.h"
2+
3+
#include <cmath>
4+
5+
namespace {
6+
7+
const double pi = std::acos(-1.0);
8+
const double inv_ln2 = 1.0 / std::log(2.0);
9+
10+
} // end of anonymous namespace
11+
12+
13+
namespace Grid {
14+
namespace Radial {
15+
16+
void baker(int nbase, double R, double* r, double* w, int mult) {
17+
int n = (nbase+1) * mult - 1;
18+
double r0 = -R / std::log((2.0 * nbase + 1.0) / ((nbase+1)*(nbase+1)));
19+
for (int i = 1; i <= n; ++i) {
20+
r[i-1] = -r0 * std::log(1.0 - static_cast<double>(i)*i/((n+1)*(n+1)));
21+
w[i-1] = 2.0 * i * r0 * r[i-1] * r[i-1] / ((n+1+i)*(n+1-i));
22+
}
23+
}
24+
25+
26+
void baker(int nbase, double R, std::vector<double>& r,
27+
std::vector<double>& w, int mult) {
28+
int n = (nbase+1) * mult - 1;
29+
r.resize(n);
30+
w.resize(n);
31+
baker(nbase, R, r.data(), w.data(), mult);
32+
}
33+
34+
35+
void murray(int n, double R, double* r, double* w) {
36+
for (int i = 1; i <= n; ++i) {
37+
double x = static_cast<double>(i) / (n + 1);
38+
r[i-1] = std::pow(x / (1.0 - x), 2) * R;
39+
w[i-1] = 2.0 / (n + 1) * std::pow(R, 3) * std::pow(x, 5)
40+
/ std::pow(1.0 - x, 7);
41+
}
42+
}
43+
44+
45+
void treutler_m4(int n, double R, double* r, double* w, double alpha) {
46+
for (int i = 1; i <= n; ++i) {
47+
double x = std::cos(i * pi / (n + 1));
48+
double beta = std::sqrt((1.0 + x) / (1.0 - x));
49+
double gamma = std::log((1.0 - x) / 2.0);
50+
double delta = std::pow(1.0 + x, alpha);
51+
r[i-1] = -R * inv_ln2 * delta * gamma;
52+
w[i-1] = pi / (n + 1) * std::pow(delta * R * inv_ln2, 3)
53+
* gamma * gamma * (beta - alpha / beta * gamma);
54+
}
55+
}
56+
57+
58+
void mura(int n, double R, double* r, double* w) {
59+
for (int i = 1; i <= n; ++i) {
60+
double x = static_cast<double>(i) / (n + 1);
61+
double alpha = 1.0 - x * x * x;
62+
r[i-1] = -R * std::log(alpha);
63+
w[i-1] = 3.0 * R * std::pow(x * r[i-1], 2) / ((n+1) * alpha);
64+
}
65+
}
66+
67+
68+
} // end of namespace Radial
69+
} // end of namespace Grid

source/module_base/grid/radial.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#ifndef GRID_RADIAL_H
2+
#define GRID_RADIAL_H
3+
4+
#include <vector>
5+
6+
namespace Grid {
7+
namespace Radial {
8+
9+
/**
10+
* @brief Radial quadratures.
11+
*
12+
* This namespace contains functions that generate grids and weights
13+
* for numerical integration
14+
*
15+
* / inf 2
16+
* | dr r g(r) ~ \sum_i w[i] g(r[i])
17+
* / 0
18+
*
19+
*/
20+
21+
/**
22+
* Baker, J., Andzelm, J., Scheiner, A., & Delley, B. (1994).
23+
* The effect of grid quality and weight derivatives in
24+
* density functional calculations.
25+
* The Journal of chemical physics, 101(10), 8894-8902.
26+
*
27+
* Zhang, I. Y., Ren, X., Rinke, P., Blum, V., & Scheffler, M. (2013).
28+
* Numeric atom-centered-orbital basis sets with valence-correlation
29+
* consistency from H to Ar.
30+
* New Journal of Physics, 15(12), 123033.
31+
*
32+
* @note nbase is the number of points of the "base" grid, i.e.,
33+
* before applying the "radial multiplier" introduced by Zhang et al.
34+
* The true number of grid points is (nbase+1) * mult - 1.
35+
*/
36+
void baker(int nbase, double R, double* r, double* w, int mult = 1);
37+
void baker(int nbase, double R, std::vector<double>& r,
38+
std::vector<double>& w, int mult = 1);
39+
40+
41+
/**
42+
* Murray, C. W., Handy, N. C., & Laming, G. J. (1993).
43+
* Quadrature schemes for integrals of density functional theory.
44+
* Molecular Physics, 78(4), 997-1014.
45+
*/
46+
void murray(int n, double R, double* r, double* w);
47+
48+
49+
/**
50+
* Treutler, O., & Ahlrichs, R. (1995).
51+
* Efficient molecular numerical integration schemes.
52+
* The Journal of Chemical Physics, 102(1), 346-354.
53+
*
54+
* @note M4 reduces to M3 at alpha = 0.
55+
*/
56+
void treutler_m4(int n, double R, double* r, double* w, double alpha = 0.6);
57+
58+
59+
/**
60+
* Mura, M. E., & Knowles, P. J. (1996).
61+
* Improved radial grids for quadrature in molecular
62+
* density‐functional calculations.
63+
* The Journal of chemical physics, 104(24), 9848-9858.
64+
*/
65+
void mura(int n, double R, double* r, double* w);
66+
67+
} // end of namespace Radial
68+
} // end of namespace Grid
69+
70+
#endif

source/module_base/grid/test/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,8 @@ AddTest(
77
../../ylm.cpp
88
)
99

10+
AddTest(
11+
TARGET test_radial
12+
SOURCES test_radial.cpp
13+
../radial.cpp
14+
)

source/module_base/grid/test/test_delley.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <mpi.h>
88
#endif
99

10-
using namespace Grid;
10+
using namespace Grid::Angular;
1111

1212
// mock the function to prevent unnecessary dependency
1313
namespace ModuleBase {
@@ -47,27 +47,27 @@ void DelleyTest::randgen(int lmax, std::vector<double>& coef) {
4747

4848
TEST_F(DelleyTest, NumGrid) {
4949
int lmax = 5;
50-
int ngrid = Delley::ngrid(lmax);
50+
int ngrid = ngrid_delley(lmax);
5151
EXPECT_EQ(lmax, 17);
5252
EXPECT_EQ(ngrid, 110);
5353

5454
lmax = 17;
55-
ngrid = Delley::ngrid(lmax);
55+
ngrid = ngrid_delley(lmax);
5656
EXPECT_EQ(lmax, 17);
5757
EXPECT_EQ(ngrid, 110);
5858

5959
lmax = 20;
60-
ngrid = Delley::ngrid(lmax);
60+
ngrid = ngrid_delley(lmax);
6161
EXPECT_EQ(lmax, 23);
6262
EXPECT_EQ(ngrid, 194);
6363

6464
lmax = 59;
65-
ngrid = Delley::ngrid(lmax);
65+
ngrid = ngrid_delley(lmax);
6666
EXPECT_EQ(lmax, 59);
6767
EXPECT_EQ(ngrid, 1202);
6868

6969
lmax = 60;
70-
ngrid = Delley::ngrid(lmax);
70+
ngrid = ngrid_delley(lmax);
7171
EXPECT_EQ(lmax, 60);
7272
EXPECT_EQ(ngrid, -1);
7373
}
@@ -91,7 +91,7 @@ TEST_F(DelleyTest, Accuracy) {
9191
std::vector<double> grid, weight, coef;
9292

9393
for (int grid_lmax = 17; grid_lmax < 60; grid_lmax +=6) {
94-
Delley::get(grid_lmax, grid, weight);
94+
delley(grid_lmax, grid, weight);
9595
int func_lmax = grid_lmax / 2;
9696
randgen(func_lmax, coef);
9797

0 commit comments

Comments
 (0)