12 const bool cal_stress,
23 const int npol = this->ucell->get_npol();
24 std::vector<double> stress_tmp(6, 0);
33 std::vector<double> stress_local(6, 0);
35 #pragma omp for schedule(dynamic)
36 for (
int iat0 = 0; iat0 < this->ucell->nat; iat0++)
39 auto tau0 = ucell->get_tau(iat0);
42 ucell->iat2iait(iat0, &I0, &T0);
46 this->gridD->Find_atom(*ucell, tau0, T0, I0, &adjs);
48 std::vector<bool> is_adj(adjs.
adj_num + 1,
false);
49 for (
int ad = 0; ad < adjs.
adj_num + 1; ++ad)
51 const int T1 = adjs.
ntype[ad];
52 const int I1 = adjs.
natom[ad];
53 const int iat1 = ucell->itia2iat(T1, I1);
59 if (this->ucell->cal_dtau(iat0, iat1, R_index1).norm() * this->ucell->lat0
60 < orb_cutoff_[T1] + this->ucell->infoNL.Beta[T0].get_rcut_max())
67 std::vector<std::unordered_map<int, std::vector<double>>> nlm_iat0(adjs.
adj_num + 1);
68 for (
int ad = 0; ad < adjs.
adj_num + 1; ++ad)
70 const int T1 = adjs.
ntype[ad];
71 const int I1 = adjs.
natom[ad];
72 const int iat1 = ucell->itia2iat(T1, I1);
74 const Atom* atom1 = &ucell->atoms[T1];
79 all_indexes.insert(all_indexes.end(), col_indexes.begin(), col_indexes.end());
80 std::sort(all_indexes.begin(), all_indexes.end());
81 all_indexes.erase(std::unique(all_indexes.begin(), all_indexes.end()), all_indexes.end());
82 for (
int iw1l = 0; iw1l < all_indexes.size(); iw1l += npol)
84 const int iw1 = all_indexes[iw1l] / npol;
85 std::vector<std::vector<double>> nlm;
93 intor_->snap(T1, qn1.L, qn1.N, qn1.M, T0, dtau * this->ucell->lat0,
true , nlm);
95 const int length = nlm[0].size();
96 std::vector<double> nlm_target(length * 4);
98 for(
int index =0;index < length; index++)
100 for (
int n = 0; n < 4; n++)
102 nlm_target[index + n * length] = nlm[n][index];
105 nlm_iat0[ad].insert({all_indexes[iw1l], nlm_target});
110 for (
int ad1 = 0; ad1 < adjs.
adj_num + 1; ++ad1)
112 const int T1 = adjs.
ntype[ad1];
113 const int I1 = adjs.
natom[ad1];
114 const int iat1 = ucell->itia2iat(T1, I1);
115 double* force_tmp1 = (cal_force) ? &force_local(iat1, 0) :
nullptr;
116 double* force_tmp2 = (cal_force) ? &force_local(iat0, 0) :
nullptr;
119 for (
int ad2 = 0; ad2 < adjs.
adj_num + 1; ++ad2)
121 const int T2 = adjs.
ntype[ad2];
122 const int I2 = adjs.
natom[ad2];
123 const int iat2 = ucell->itia2iat(T2, I2);
127 R_index2[1] - R_index1[1],
128 R_index2[2] - R_index1[2]);
132 if(row_size == 0 || col_size == 0)
141 this->cal_force_IJR(iat1,
154 this->cal_stress_IJR(iat1,
163 stress_local.data());
173 force += force_local;
177 for(
int i = 0;
i < 6;
i++)
179 stress_tmp[
i] += stress_local[
i];
192 for (
int i = 0;
i < force.
nr * force.
nc;
i++)
205 const double weight = this->ucell->lat0 / this->ucell->omega;
206 for (
int i = 0;
i < 6;
i++)
208 stress.
c[
i] = stress_tmp[
i] * weight;
210 stress.
c[8] = stress.
c[5];
211 stress.
c[7] = stress.
c[4];
212 stress.
c[6] = stress.
c[2];
213 stress.
c[5] = stress.
c[4];
214 stress.
c[4] = stress.
c[3];
215 stress.
c[3] = stress.
c[1];
226 const std::unordered_map<
int, std::vector<double>>& nlm1_all,
227 const std::unordered_map<
int, std::vector<double>>& nlm2_all,
235 const int npol = this->ucell->get_npol();
242 std::vector<int> step_trace;
245 const std::complex<double>* tmp_d =
nullptr;
246 const std::complex<double>* dm_pointer = dmR_pointer->get_pointer();
247 for (
int iw1l = 0; iw1l < row_indexes.size(); iw1l += npol)
249 const std::vector<double>& nlm1 = nlm1_all.find(row_indexes[iw1l])->second;
250 const int length = nlm1.size() / 4;
251 for (
int iw2l = 0; iw2l < col_indexes.size(); iw2l += npol)
253 const std::vector<double>& nlm2 = nlm2_all.find(col_indexes[iw2l])->second;
255 assert(nlm1.size() == nlm2.size());
258 for (
int is = 0; is < 4; ++is)
260 for (
int no = 0;
no < this->ucell->atoms[T0].ncpp.non_zero_count_soc[is];
no++)
262 const int p1 = this->ucell->atoms[T0].ncpp.index1_soc[is][
no];
263 const int p2 = this->ucell->atoms[T0].ncpp.index2_soc[is][
no];
264 this->ucell->atoms[T0].ncpp.get_d(is, p1, p2, tmp_d);
265 nlm_tmp[is*3] += nlm1[p1 + length] * nlm2[p2] * (*tmp_d);
266 nlm_tmp[is*3+1] += nlm1[p1 + length * 2] * nlm2[p2] * (*tmp_d);
267 nlm_tmp[is*3+2] += nlm1[p1 + length * 3] * nlm2[p2] * (*tmp_d);
271 for(
int i = 0;
i < 3;
i++)
273 double tmp = (dm_pointer[step_trace[0]] * nlm_tmp[
i]
274 + dm_pointer[step_trace[1]] * nlm_tmp[
i+3]
275 + dm_pointer[step_trace[2]] * nlm_tmp[
i+6]
276 + dm_pointer[step_trace[3]] * nlm_tmp[
i+9]).real();
282 dm_pointer += (npol - 1) * col_indexes.size();
291 const std::unordered_map<
int, std::vector<double>>& nlm1_all,
292 const std::unordered_map<
int, std::vector<double>>& nlm2_all,
301 const int npol = this->ucell->get_npol();
302 const int npol2 = npol * npol;
309 std::vector<int> step_trace;
312 const std::complex<double>* tmp_d =
nullptr;
313 const std::complex<double>* dm_pointer = dmR_pointer->get_pointer();
314 for (
int iw1l = 0; iw1l < row_indexes.size(); iw1l += npol)
316 const std::vector<double>& nlm1 = nlm1_all.find(row_indexes[iw1l])->second;
317 const int length = nlm1.size() / npol2;
318 for (
int iw2l = 0; iw2l < col_indexes.size(); iw2l += npol)
320 const std::vector<double>& nlm2 = nlm2_all.find(col_indexes[iw2l])->second;
322 assert(nlm1.size() == nlm2.size());
325 for (
int is = 0; is < 4; ++is)
327 for (
int no = 0;
no < this->ucell->atoms[T0].ncpp.non_zero_count_soc[is];
no++)
329 const int p1 = this->ucell->atoms[T0].ncpp.index1_soc[is][
no];
330 const int p2 = this->ucell->atoms[T0].ncpp.index2_soc[is][
no];
331 this->ucell->atoms[T0].ncpp.get_d(is, p1, p2, tmp_d);
332 nlm_tmp[is*6] += (nlm1[p1 + length] * dis1.
x * nlm2[p2] + nlm1[p1] * nlm2[p2 + length] * dis2.
x) * (*tmp_d);
333 nlm_tmp[is*6+1] += (nlm1[p1 + length] * dis1.
y * nlm2[p2] + nlm1[p1] * nlm2[p2 + length] * dis2.
y) * (*tmp_d);
334 nlm_tmp[is*6+2] += (nlm1[p1 + length] * dis1.
z * nlm2[p2] + nlm1[p1] * nlm2[p2 + length] * dis2.
z) * (*tmp_d);
335 nlm_tmp[is*6+3] += (nlm1[p1 + length * 2] * dis1.
y * nlm2[p2] + nlm1[p1] * nlm2[p2 + length * 2] * dis2.
y) * (*tmp_d);
336 nlm_tmp[is*6+4] += (nlm1[p1 + length * 2] * dis1.
z * nlm2[p2] + nlm1[p1] * nlm2[p2 + length * 2] * dis2.
z) * (*tmp_d);
337 nlm_tmp[is*6+5] += (nlm1[p1 + length * 3] * dis1.
z * nlm2[p2] + nlm1[p1] * nlm2[p2 + length * 3] * dis2.
z) * (*tmp_d);
341 for(
int i = 0;
i < 6;
i++)
343 stress[
i] += (dm_pointer[step_trace[0]] * nlm_tmp[
i]
344 + dm_pointer[step_trace[1]] * nlm_tmp[
i+6]
345 + dm_pointer[step_trace[2]] * nlm_tmp[
i+12]
346 + dm_pointer[step_trace[3]] * nlm_tmp[
i+18]).real();
350 dm_pointer += (npol - 1) * col_indexes.size();
359 const std::unordered_map<
int, std::vector<double>>& nlm1_all,
360 const std::unordered_map<
int, std::vector<double>>& nlm2_all,
371 const double* tmp_d =
nullptr;
372 const double* dm_pointer = dmR_pointer->
get_pointer();
373 for (
int iw1l = 0; iw1l < row_indexes.size(); iw1l++)
375 const std::vector<double>& nlm1 = nlm1_all.find(row_indexes[iw1l])->second;
376 const int length = nlm1.size() / 4;
377 for (
int iw2l = 0; iw2l < col_indexes.size(); iw2l++)
379 const std::vector<double>& nlm2 = nlm2_all.find(col_indexes[iw2l])->second;
381 assert(nlm1.size() == nlm2.size());
383 std::vector<double> nlm_tmp(3, 0.0);
384 for (
int no = 0;
no < this->ucell->atoms[T0].ncpp.non_zero_count_soc[0];
no++)
386 const int p1 = this->ucell->atoms[T0].ncpp.index1_soc[0][
no];
387 const int p2 = this->ucell->atoms[T0].ncpp.index2_soc[0][
no];
388 this->ucell->atoms[T0].ncpp.get_d(0, p1, p2, tmp_d);
389 nlm_tmp[0] += nlm1[p1 + length] * nlm2[p2] * (*tmp_d);
390 nlm_tmp[1] += nlm1[p1 + length * 2] * nlm2[p2] * (*tmp_d);
391 nlm_tmp[2] += nlm1[p1 + length * 3] * nlm2[p2] * (*tmp_d);
394 for(
int i = 0;
i < 3;
i++)
396 force1[
i] += dm_pointer[0] * nlm_tmp[
i];
397 force2[
i] -= dm_pointer[0] * nlm_tmp[
i];
409 const std::unordered_map<
int, std::vector<double>>& nlm1_all,
410 const std::unordered_map<
int, std::vector<double>>& nlm2_all,
422 const double* tmp_d =
nullptr;
423 const double* dm_pointer = dmR_pointer->
get_pointer();
424 for (
int iw1l = 0; iw1l < row_indexes.size(); iw1l++)
426 const std::vector<double>& nlm1 = nlm1_all.find(row_indexes[iw1l])->second;
427 const int length = nlm1.size() / 4;
428 for (
int iw2l = 0; iw2l < col_indexes.size(); iw2l++)
430 const std::vector<double>& nlm2 = nlm2_all.find(col_indexes[iw2l])->second;
432 assert(nlm1.size() == nlm2.size());
434 std::vector<double> nlm_tmp(6, 0.0);
435 for (
int no = 0;
no < this->ucell->atoms[T0].ncpp.non_zero_count_soc[0];
no++)
437 const int p1 = this->ucell->atoms[T0].ncpp.index1_soc[0][
no];
438 const int p2 = this->ucell->atoms[T0].ncpp.index2_soc[0][
no];
439 this->ucell->atoms[T0].ncpp.get_d(0, p1, p2, tmp_d);
440 nlm_tmp[0] += (nlm1[p1 + length] * dis1.
x * nlm2[p2] + nlm1[p1] * nlm2[p2 + length] * dis2.
x) * (*tmp_d);
441 nlm_tmp[1] += (nlm1[p1 + length] * dis1.
y * nlm2[p2] + nlm1[p1] * nlm2[p2 + length] * dis2.
y) * (*tmp_d);
442 nlm_tmp[2] += (nlm1[p1 + length] * dis1.
z * nlm2[p2] + nlm1[p1] * nlm2[p2 + length] * dis2.
z) * (*tmp_d);
443 nlm_tmp[3] += (nlm1[p1 + length * 2] * dis1.
y * nlm2[p2] + nlm1[p1] * nlm2[p2 + length * 2] * dis2.
y) * (*tmp_d);
444 nlm_tmp[4] += (nlm1[p1 + length * 2] * dis1.
z * nlm2[p2] + nlm1[p1] * nlm2[p2 + length * 2] * dis2.
z) * (*tmp_d);
445 nlm_tmp[5] += (nlm1[p1 + length * 3] * dis1.
z * nlm2[p2] + nlm1[p1] * nlm2[p2 + length * 3] * dis2.
z) * (*tmp_d);
448 for(
int i = 0;
i < 6;
i++)
450 stress[
i] += dm_pointer[0] * nlm_tmp[
i];
BaseMatrix< T > * find_matrix(int i, int j, int rx, int ry, int rz)
find BaseMatrix with atom index atom_i and atom_j and R index (rx, ry, rz) This interface can be used...
Definition hcontainer.cpp:286
void setup_step_trace(int npol, int col_size, std::vector< int > &step_trace)
Setup step_trace array for handling npol (spin polarization)
Definition operator_force_stress_utils.h:20