KIDS  ver-0.0.1
KIDS : Kernel Integrated Dynamics Simulator
Loading...
Searching...
No Matches
Kernel_Elec_Utils.h
Go to the documentation of this file.
1
12#ifndef Kernel_Elec_Utils_H
13#define Kernel_Elec_Utils_H
14
15#include "kids/Kernel.h"
16#include "kids/Kernel_Elec.h"
17#include "kids/Kernel_Random.h"
18#include "kids/linalg.h"
19#include "kids/vars_list.h"
20
21namespace PROJECT_NS {
22
23DEFINE_POLICY(SQCPolicy,
24 SQR, // square window
25 TRI, // triangle window
26 SPX, // simplex window
27 BIG // simplex window
28);
29
31 public:
33 static inline double gamma_wigner(int fdim) { return (sqrt(fdim + 1.0e0) - 1) / fdim; }
34
35 static inline double gamma_opt(int fdim) {
36 double sum = 0.0e0;
37 for (int i = 0; i < fdim; ++i) sum += 1.0e0 / (i + 1);
38 return ((fdim - sum) / (sum - 1.0e0)) / fdim;
39 }
41
42 static int max_choose(kids_complex* rho) {
43 int imax = 0;
44 kids_real vmax = 0.0f;
45 for (int i = 0, ii = 0; i < Dimension::F; ++i, ii += Dimension::Fadd1) {
46 if (std::real(rho[ii]) > vmax) {
47 vmax = std::real(rho[ii]);
48 imax = i;
49 }
50 }
51 return imax;
52 }
53
54 static int pop_choose(kids_complex* rho) {
55 kids_real rand_tmp;
56 kids_real sum = 0.0f;
58 for (int i = 0, ii = 0; i < Dimension::F; ++i, ii += Dimension::Fadd1) {
59 sum += std::min({std::max({std::real(rho[ii]), 0.0e0}), 1.0e0});
60 if (rand_tmp < sum) return i;
61 }
62 return 0;
63 }
64
65 static int pop_neg_choose(kids_complex* rho) {
66 kids_real rand_tmp;
67 kids_real sum = 0.0f;
68 for (int i = 0, ii = 0; i < Dimension::F; ++i, ii += Dimension::Fadd1) sum += std::abs(rho[ii]);
70 rand_tmp *= sum;
71 sum = 0.0e0;
72 for (int i = 0, ii = 0; i < Dimension::F; ++i, ii += Dimension::Fadd1) {
73 sum += std::abs(rho[ii]);
74 if (rand_tmp < sum) return i;
75 }
76 return 0;
77 }
78
79 static int hopping_choose(kids_complex* rho, kids_complex* H, int from, kids_real dt) {
80 int to = from;
81 kids_real rand_tmp, sumprob = 0.0f;
82 kids_real rhoii = std::real(rho[from * Dimension::Fadd1]);
84
85 for (int n = 0; n < Dimension::F; ++n) {
86 kids_real prob =
87 (n == from) ? 0.0f
88 : -2.0f * std::imag(rho[n * Dimension::F + from] * H[from * Dimension::F + n]) / rhoii * dt;
89 prob = (prob > 1.0f) ? 1.0f : ((prob < 0.0f) ? 0.0f : prob); // hopping cut-off
90 sumprob += prob;
91 if (rand_tmp < sumprob) {
92 to = n;
93 break;
94 }
95 }
96 return to;
97 }
98
99 static void hopping_direction(kids_real* direction, kids_real* dE, int from, int to) {
100 if (to == from) return;
101 for (int i = 0; i < Dimension::N; ++i) { direction[i] = dE[i * Dimension::FF + from * Dimension::F + to]; }
102 }
103
104 static void hopping_direction(kids_real* direction, kids_real* E, kids_real* dE, kids_complex* rho, int from,
105 int to) {
106 if (to == from) return;
107
108 for (int i = 0; i < Dimension::N; ++i) {
109 direction[i] = 0.0f;
110 for (int k = 0; k < Dimension::F; ++k)
111 if (k != from)
112 direction[i] +=
113 std::real(rho[from * Dimension::F + k] * dE[i * Dimension::FF + k * Dimension::F + from]) /
114 (E[from] - E[k]);
115 for (int k = 0; k < Dimension::F; ++k)
116 if (k != to)
117 direction[i] -=
118 std::real(rho[to * Dimension::F + k] * dE[i * Dimension::FF + k * Dimension::F + to]) /
119 (E[to] - E[k]);
120 }
121 }
122
123 static int hopping_impulse(kids_real* direction, kids_real* np, kids_real* nm, kids_real* E, //
124 int from, int to, bool reflect) {
125 if (to == from) return from;
126
127 // solve x: Ef + P**2 / (2*M) = Et + (P + direction*x)**2 / (2*M)
128 kids_real coeffa = 0.0f, coeffb = 0.0f, coeffc = E[to] - E[from];
129 for (int i = 0; i < Dimension::N; ++i) {
130 coeffa += 0.5f * direction[i] * direction[i] / nm[i];
131 coeffb += np[i] / nm[i] * direction[i];
132 }
133 coeffb /= coeffa, coeffc /= coeffa; // normalization for safety
134
135 kids_real coeffd = coeffb * coeffb - 4 * coeffc;
136 if (coeffd > 0) {
137 kids_real x1 = 0.5f * (-coeffb + sqrt(coeffd)), x2 = 0.5f * (-coeffb - sqrt(coeffd));
138 kids_real xx = (std::abs(x1) < std::abs(x2)) ? x1 : x2;
139 for (int i = 0; i < Dimension::N; ++i) np[i] += xx * direction[i];
140 return to;
141 } else if (reflect) { // 2008Algorithm
142 kids_real xx = -coeffb;
143 for (int i = 0; i < Dimension::N; ++i) np[i] += xx * direction[i];
144 return from;
145 } else { // 1990Algorithm, do nothing
146 return from;
147 }
148 return from;
149 }
150
154 static int c_sphere(kids_complex* c, int fdim) {
155 Kernel_Random::rand_gaussian(reinterpret_cast<double*>(c), 2 * fdim);
156 double l = std::sqrt(std::real(ARRAY_INNER_TRANS1(c, c, fdim)));
157 for (int i = 0; i < fdim; ++i) c[i] /= l;
158 return 0;
159 }
160
161 static int c_focus(kids_complex* c, double xi, double gamma, int occ, int fdim) {
162 for (int i = 0; i < fdim; ++i) c[i] = ((i == occ ? 1.0e0 : 0.0e0) + gamma) / xi;
163 double randu;
164 for (int i = 0; i < fdim; ++i) {
166 randu *= phys::math::twopi;
167 c[i] = std::sqrt(std::abs(c[i])) * (cos(randu) + phys::math::im * sin(randu));
168 }
169 return 0;
170 };
171
172 static int rho_focus(kids_complex* rho, int iocc, double gamma_ou, double gamma_uu, int fdim, bool rand_act,
173 bool pure_phase, bool cont_phase) {
174 double randu = 1.0e0;
175 if (pure_phase) {
176 for (int j = 0; j < fdim; ++j) {
177 if (j == iocc) {
178 rho[iocc * fdim + j] = 1.0e0;
179 continue;
180 }
182 randu = (cont_phase) ? phys::math::twopi * randu : phys::math::halfpi * (int(randu / 0.25f) + 1);
183 rho[iocc * fdim + j] = cos(randu) + phys::math::im * sin(randu);
184 rho[j * fdim + iocc] = std::conj(rho[iocc * fdim + j]);
185 }
186 for (int i = 0, ij = 0; i < fdim; ++i) {
187 for (int j = 0; j < fdim; ++j, ++ij) {
188 if (i == iocc || j == iocc) continue;
189 rho[ij] = rho[iocc * fdim + j] / rho[iocc * fdim + i];
190 }
191 }
192 } else {
193 for (int i = 0; i < fdim; ++i) {
194 for (int j = i + 1; j < fdim; ++j) {
196 randu = (cont_phase) ? phys::math::twopi * randu : phys::math::halfpi * (int(randu / 0.25f) + 1);
197 rho[i * fdim + j] = cos(randu) + phys::math::im * sin(randu);
198 rho[j * fdim + i] = std::conj(rho[i * fdim + j]);
199 }
200 }
201 }
203 double occrand = (rand_act) ? int(randu * fdim) : iocc;
204 for (int i = 0, ij = 0; i < fdim; ++i) {
205 for (int j = 0; j < fdim; ++j, ++ij) {
206 if (i == j) {
207 rho[ij] = (i == occrand) ? phys::math::iu : phys::math::iz;
208 } else if (i == occrand || j == occrand) {
209 rho[ij] *= gamma_ou;
210 } else {
211 rho[ij] *= gamma_uu;
212 }
213 }
214 }
215 return 0;
216 }
217
218 static int c_window(kids_complex* c, int iocc, int type, int fdim) {
219 switch (type) {
220 case SQCPolicy::TRI: {
221 kids_real tmp2[2];
223 while (tmp2[0] + tmp2[1] > 1.0f) Kernel_Random::rand_uniform(tmp2, 2);
224 c[iocc] = tmp2[0];
225 tmp2[1] = 1.0f - std::real(c[iocc]);
226 for (int i = 0; i < fdim; ++i) {
227 if (i != iocc) {
229 c[i] = tmp2[0] * tmp2[1];
230 }
231 }
232 c[iocc] += 1.0e0;
233 break;
234 }
235 case SQCPolicy::SPX: {
237 for (int i = 0; i < Dimension::F; ++i) c[i] = std::abs(c[i] * c[i]);
238 c[iocc] += 1.0e0;
239 break;
240 }
241 case SQCPolicy::BIG: {
244 for (int i = 0; i < Dimension::F; ++i) c[i] = std::abs(cadd1[i] * cadd1[i]);
245 c[iocc] += 1.0e0;
246 delete[] cadd1;
247 break;
248 }
249 case SQCPolicy::SQR: {
250 const kids_real gm0 = gamma_wigner(2.0f);
251 for (int i = 0; i < fdim; ++i) {
252 kids_real randu;
254 c[i] = 2.0 * gm0 * randu;
255 }
256 c[iocc] += 1.0e0;
257 break;
258 }
259 }
260 for (int i = 0; i < fdim; ++i) {
261 kids_real randu;
263 randu *= phys::math::twopi;
264 c[i] = sqrt(c[i]);
265 c[i] *= (cos(randu) + phys::math::im * sin(randu));
266 }
267 return 0;
268 };
269
270 static int ker_binning(kids_complex* ker, kids_complex* rho, int sqc_type) {
271 const kids_real gm0 = gamma_wigner(2.0f), gm1 = 1 + gm0, gmh = 0.5f + gm0;
272
273 // set all elements to 1
274 for (int i = 0; i < Dimension::FF; ++i) ker[i] = rho[i] / std::abs(rho[i]);
275
276 // for ker[ij], loop k-index to find if ker[ij] should be set to 0
277 for (int i = 0, ij = 0; i < Dimension::F; ++i) {
278 for (int j = 0; j < Dimension::F; ++j, ++ij) {
279 for (int k = 0, kk = 0; k < Dimension::F; ++k, kk += Dimension::Fadd1) {
280 double vk = std::abs(rho[kk]);
281 bool Outlier = false;
282 switch (sqc_type) {
283 case SQCPolicy::TRI:
284 case SQCPolicy::SPX:
285 case SQCPolicy::BIG:
286 Outlier = (i == j) ? ((k != i && vk > 1) || (k == i && vk < 1))
287 : ((k != i && k != j && vk > 1) || ((k == i || k == j) && vk < 0.5f));
288
289 if (i != j) Outlier = false;
290 break;
291 case SQCPolicy::SQR: // @bug?
292 Outlier = (i == j) ? ((k != i && std::abs(vk - gm0) < gm0) ||
293 (k == i && std::abs(vk - gm1) < gm0))
294 : ((k != i && std::abs(vk - gm0) > gm0) || //
295 (k == i && std::abs(vk - gmh) > gm0) || //
296 (k == j && std::abs(vk - gmh) > gm0));
297 break;
298 }
299 if (Outlier) {
300 ker[ij] = phys::math::iz;
301 break;
302 }
303 }
304 }
305 }
306 return 0;
307 };
308};
309
310}; // namespace PROJECT_NS
311
312#endif // Kernel_Elec_Utils_H
this file provide Kernel class
initialization kernels for electonic DOFs
#define DEFINE_POLICY(Policy,...)
Definition Policy.h:83
static int rand_uniform(kids_real *res_arr, int N=1, kids_real sigma=1.0)
static int rand_gaussian(kids_real *res_arr, int N=1, kids_real sigma=1.0, kids_real mu=0.0)
static int hopping_choose(kids_complex *rho, kids_complex *H, int from, kids_real dt)
static void hopping_direction(kids_real *direction, kids_real *E, kids_real *dE, kids_complex *rho, int from, int to)
static double gamma_wigner(int fdim)
static int pop_neg_choose(kids_complex *rho)
static int rho_focus(kids_complex *rho, int iocc, double gamma_ou, double gamma_uu, int fdim, bool rand_act, bool pure_phase, bool cont_phase)
static int hopping_impulse(kids_real *direction, kids_real *np, kids_real *nm, kids_real *E, int from, int to, bool reflect)
static int pop_choose(kids_complex *rho)
static int c_window(kids_complex *c, int iocc, int type, int fdim)
static double gamma_opt(int fdim)
static int c_focus(kids_complex *c, double xi, double gamma, int occ, int fdim)
static void hopping_direction(kids_real *direction, kids_real *dE, int from, int to)
static int max_choose(kids_complex *rho)
static int c_sphere(kids_complex *c, int fdim)
sampling mapping variables from uniform sphere distribution (i.e.
static int ker_binning(kids_complex *ker, kids_complex *rho, int sqc_type)
Provide linalg APIs.
std::size_t N
Number of nuclear degrees of freedom.
Definition vars_list.cpp:10
std::size_t F
Number of electronic degrees of freedom.
Definition vars_list.cpp:11
std::size_t Fadd1
F plus 1 (F + 1).
Definition vars_list.cpp:24
std::size_t FF
Product of F and F (F * F).
Definition vars_list.cpp:21
< http://warp.povusers.org/FunctionParser/fparser.html
Definition Context.h:39
kids_real ARRAY_INNER_TRANS1(kids_real *B, kids_real *C, size_t N1)
Compute the inner product of the transpose of B with C for real matrices.
Definition linalg.cpp:400
double kids_real
Alias for real number type.
Definition Types.h:59
std::complex< double > kids_complex
Alias for complex number type.
Definition Types.h:60
constexpr real_precision halfpi
Definition phys.h:32
constexpr std::complex< real_precision > iu(1.0L, 0.0L)
constexpr std::complex< real_precision > im(0.0L, 1.0L)
Imaginary Unit.
constexpr real_precision twopi
Definition phys.h:31
constexpr std::complex< real_precision > iz(0.0L, 0.0L)
declaration of variables used in the program.