22#include " module_base/constants.h"
33
44#include < cmath>
5+ #include < functional>
56#include < numeric>
6- #include < vector >
7+ #include < algorithm >
78
89namespace Grid {
910namespace Partition {
1011
1112const double stratmann_a = 0.64 ;
1213const double stratmann_mod_b = 0.8 ;
1314
15+
1416double w_becke (
1517 int nR0,
16- double * drR,
17- double * dRR,
18+ const double * drR,
19+ const double * dRR,
1820 int nR,
19- int * iR,
21+ const int * iR,
2022 int c
2123) {
22- std::vector<double > P (nR, 1.0 );
24+ double P[nR];
25+ std::fill (P, P + nR, 1.0 );
2326 for (int i = 0 ; i < nR; ++i) {
2427 int I = iR[i];
2528 for (int j = i + 1 ; j < nR; ++j) {
2629 int J = iR[j];
2730 double mu = (drR[I] - drR[J]) / dRR[I*nR0 + J];
2831 double s = s_becke (mu);
2932 P[I] *= s;
30- P[J] *= (1.0 - s); // s_becke (-mu) = 1 - s_becke (mu)
33+ P[J] *= (1.0 - s); // s (-mu) = 1 - s (mu)
3134 }
3235 }
33- return P[c] / std::accumulate (P. begin () , P. end () , 0.0 );
36+ return P[c] / std::accumulate (P, P + nR , 0.0 );
3437}
3538
39+
3640double s_becke (double mu) {
3741 /*
3842 * Becke's iterated polynomials (3rd order)
@@ -51,59 +55,63 @@ double s_becke(double mu) {
5155
5256double w_stratmann (
5357 int nR0,
54- double * drR,
55- double * dRR,
56- double * drR_thr,
57- int nR,
58+ const double * drR,
59+ const double * dRR,
60+ const double * drR_thr,
61+ const int nR,
5862 int * iR,
5963 int c
6064) {
65+ int I = iR[c], J = 0 ;
6166
62- // if r falls within the exclusive zone of the center
63- // whom this grid point belongs to
64- int I = iR[c];
65- if (drR[I] <= drR_thr[I]) {
66- return 1.0 ;
67- }
68-
69- // if r falls within the exclusive zone of a center
70- // other than the one whom this grid point belongs to
71- for (int J = 0 ; J < nR; ++J) {
72- // no need to exclude J == c because it was checked before
73- if (drR[iR[J]] <= drR_thr[iR[J]]) {
74- return 0.0 ;
67+ // If r falls within the exclusive zone of a center, return immediately.
68+ for (int j = 0 ; j < nR; ++j) {
69+ J = iR[j];
70+ if (drR[J] <= drR_thr[J]) {
71+ return static_cast <double >(I == J);
7572 }
7673 }
7774
78- double Pc = 1.0 ;
79- for (int i = 0 ; i < c; ++i) {
80- int J = iR[i];
81- double mu = (drR[I] - drR[J]) / dRR[I*nR0 + J];
82- Pc *= s_stratmann (mu);
83- }
84- for (int i = c + 1 ; i < nR; ++i) {
85- int J = iR[i];
75+ // Even if the grid point does not fall within the exclusive zone of any
76+ // center, the normalized weight could still be 0 or 1, and this can be
77+ // figured out by examining the unnormalized weight alone.
78+
79+ // Move the center to the first position for convenience. Swap back later.
80+ std::swap (iR[0 ], iR[c]);
81+
82+ double P[nR];
83+ for (int j = 1 ; j < nR; ++j) {
84+ J = iR[j];
8685 double mu = (drR[I] - drR[J]) / dRR[I*nR0 + J];
87- Pc * = s_stratmann (mu);
86+ P[j] = s_stratmann (mu);
8887 }
89- if (Pc == 0.0 || Pc == 1.0 ) {
90- return Pc;
88+ P[0 ] = std::accumulate (P + 1 , P + nR, 1.0 , std::multiplies<double >());
89+
90+ if (P[0 ] == 0.0 || P[0 ] == 1.0 ) {
91+ std::swap (iR[0 ], iR[c]);
92+ return P[0 ];
9193 }
9294
93- std::vector<double > P (nR, 1.0 );
94- for (int i = 0 ; i < nR; ++i) {
95- int I = iR[i];
95+ // If it passes all the screening, all unnormalized weights have to be
96+ // calculated in order to get the normalized weight.
97+
98+ std::for_each (P + 1 , P + nR, [](double & s) { s = 1.0 - s; });
99+ for (int i = 1 ; i < nR; ++i) {
100+ I = iR[i];
96101 for (int j = i + 1 ; j < nR; ++j) {
97- int J = iR[j];
102+ J = iR[j];
98103 double mu = (drR[I] - drR[J]) / dRR[I*nR0 + J];
99104 double s = s_stratmann (mu);
100- P[I ] *= s;
101- P[J ] *= (1.0 - s); // s(-mu) = 1 - s(mu)
105+ P[i ] *= s;
106+ P[j ] *= (1.0 - s); // s(-mu) = 1 - s(mu)
102107 }
103108 }
104- return P[c] / std::accumulate (P.begin (), P.end (), 0.0 );
109+
110+ std::swap (iR[0 ], iR[c]);
111+ return P[0 ] / std::accumulate (P, P + nR, 0.0 );
105112}
106113
114+
107115double s_stratmann (double mu) {
108116 /*
109117 * Stratmann's piecewise cell function
@@ -127,57 +135,76 @@ double s_stratmann(double mu) {
127135}
128136
129137
130- double u_stratmann_mod (double y) {
131- using ModuleBase::PI;
132- bool core = y <= stratmann_mod_b;
133- bool edge = !core && y < 1.0 ;
134- return core + edge * 0.5 * (1.0 +
135- std::cos (PI * (y - stratmann_mod_b) / (1.0 - stratmann_mod_b)));
138+ double w_stratmann_mod (
139+ int nR0,
140+ const double * drR,
141+ const double * dRR,
142+ const double * drR_thr,
143+ const double * Rcut,
144+ int nR,
145+ int * iR,
146+ int c
147+ ) {
148+ int I = iR[c], J = 0 ;
149+
150+ // If r falls within the exclusive zone of a center, return immediately.
151+ for (int j = 0 ; j < nR; ++j) {
152+ J = iR[j];
153+ if (drR[J] <= drR_thr[J]) {
154+ return static_cast <double >(I == J);
155+ }
156+ }
157+
158+ // Even if the grid point does not fall within the exclusive zone of any
159+ // center, the normalized weight could still be 0 or 1, and this can be
160+ // figured out by examining the unnormalized weight alone.
161+
162+ // Move the center to the first position for convenience. Swap back later.
163+ std::swap (iR[0 ], iR[c]);
164+
165+ double P[nR];
166+ for (int j = 1 ; j < nR; ++j) {
167+ J = iR[j];
168+ double mu = (drR[I] - drR[J]) / dRR[I*nR0 + J];
169+ P[j] = s_stratmann (mu);
170+ }
171+ P[0 ] = std::accumulate (P + 1 , P + nR, 1.0 , std::multiplies<double >());
172+
173+ if (P[0 ] == 0.0 || P[0 ] == 1.0 ) {
174+ std::swap (iR[0 ], iR[c]);
175+ return P[0 ];
176+ }
177+
178+ // If it passes all the screening, all unnormalized weights have to be
179+ // calculated in order to get the normalized weight.
180+
181+ std::for_each (P + 1 , P + nR, [](double & s) { s = 1.0 - s; });
182+ for (int i = 1 ; i < nR; ++i) {
183+ I = iR[i];
184+ for (int j = i + 1 ; j < nR; ++j) {
185+ J = iR[j];
186+ double mu = (drR[I] - drR[J]) / dRR[I*nR0 + J];
187+ double s = s_stratmann (mu);
188+ P[i] *= s;
189+ P[j] *= (1.0 - s); // s(-mu) = 1 - s(mu)
190+ }
191+ }
192+
193+ std::swap (iR[0 ], iR[c]);
194+ return P[0 ] / std::accumulate (P, P + nR, 0.0 );
136195}
137196
138197
139198double s_stratmann_mod (double mu, double y) {
140- // Modified Stratmann's cell function by Knuth et al.
141- // y = |r-R(J)| / Rcut(J)
142- return 1.0 + u_stratmann_mod (y) * (s_stratmann (mu) - 1.0 );
199+ using ModuleBase::PI;
200+ bool core = y <= stratmann_mod_b;
201+ bool edge = !core && y < 1.0 ;
202+ double u = core + edge * 0.5 * (1.0 +
203+ std::cos (PI * (y - stratmann_mod_b) / (1.0 - stratmann_mod_b)));
204+ return 1.0 + u * (s_stratmann (mu) - 1.0 );
143205}
144206
145207
146- // double weight(
147- // int nRtot,
148- // double* drR,
149- // double* dRR,
150- // int nR,
151- // int* iR,
152- // int c,
153- // CellFuncType type,
154- // double* Rcut
155- // ) {
156- // // unnormalized weight
157- // std::vector<double> P(nR, 1.0);
158- //
159- // // confocal ellipsoidal coordinates
160- // std::vector<double> mu(nR*nR, 0.0);
161- // for (int i = 0; i < nR; ++i) {
162- // int I = iR[i];
163- // for (int j = i + 1; j < nR; ++j) {
164- // int J = iR[j];
165- // mu[I*nR + J] = (drR[I] - drR[J]) / dRR[I*nRtot + J];
166- // mu[J*nR + I] = -mu[I*nR + J];
167- // }
168- // }
169- //
170- // for (int i = 0; i < nR; ++i) {
171- // if (i == c) {
172- // continue;
173- // }
174- // int J = iR[i];
175- // double mu = (drR[I] - drR[J]) / dRR[I*nRtot + J];
176- // P[i] *= s_becke(mu);
177- // }
178- //
179- // return P[c] / std::accumulate(P.begin(), P.end(), 0.0);
180- // }
181208
182209} // end of namespace Partition
183210} // end of namespace Grid
0 commit comments