ABACUS develop
Atomic-orbital Based Ab-initio Computation at UStc
Loading...
Searching...
No Matches
pulay_fs_temp.hpp
Go to the documentation of this file.
1#pragma once
2#include <omp.h>
3#include "pulay_fs.h"
4#include "source_base/timer.h"
6#ifdef _OPENMP
7#include <omp.h>
8#endif
9
10
11namespace PulayForceStress
12{
13 // common kernel
14 template <typename TK, typename TR, typename Tfunc>
15 inline void cal_pulay_fs(
19 const UnitCell& ucell,
20 const Parallel_Orbitals& pv,
21 const double** dHSx,
22 const double** dHSxy,
23 const double* dtau,
24 const bool& isforce,
25 const bool& isstress,
26 Record_adj* ra,
27 const double& factor_force,
28 const double& factor_stress,
29 Tfunc& stress_func)
30 {
31 ModuleBase::TITLE("Force_LCAO", "cal_pulay_fs_center2");
32 ModuleBase::timer::tick("Force_LCAO", "cal_pulay_fs_center2");
33
34 const int nspin_DMR = (PARAM.inp.nspin == 2) ? 2 : 1;
35 int total_irr = 0;
36#ifdef _OPENMP
37#pragma omp parallel
38 {
39 int num_threads = omp_get_num_threads();
40 ModuleBase::matrix local_s(3, 3);
41 int local_total_irr = 0;
42#else
43 ModuleBase::matrix& local_s = s;
44 int& local_total_irr = total_irr;
45#endif
46
47#ifdef _OPENMP
48#pragma omp for schedule(dynamic)
49#endif
50 for (int iat = 0; iat < ucell.nat; iat++)
51 {
52 const int T1 = ucell.iat2it[iat];
53 Atom* atom1 = &ucell.atoms[T1];
54 const int I1 = ucell.iat2ia[iat];
55 // get iat1
56 int iat1 = ucell.itia2iat(T1, I1);
57 double* f_iat;
58 if (isforce) { f_iat = &f(iat, 0); }
59#ifdef _OPENMP
60 // using local stack to avoid false sharing in multi-threaded case
61 double f_tmp[3] = { 0.0, 0.0, 0.0 };
62 if (num_threads > 1) { f_iat = f_tmp; }
63#endif
64 int irr = pv.nlocstart[iat];
65 const int start1 = ucell.itiaiw2iwt(T1, I1, 0);
66 for (int cb = 0; cb < ra->na_each[iat]; ++cb)
67 {
68 const int T2 = ra->info[iat][cb][3];
69 const int I2 = ra->info[iat][cb][4];
70 const int start2 = ucell.itiaiw2iwt(T2, I2, 0);
71 Atom* atom2 = &ucell.atoms[T2];
72 // get iat2
73 int iat2 = ucell.itia2iat(T2, I2);
74 double Rx = ra->info[iat][cb][0];
75 double Ry = ra->info[iat][cb][1];
76 double Rz = ra->info[iat][cb][2];
77 // get BaseMatrix
78 if (pv.get_row_size(iat1) <= 0 || pv.get_col_size(iat2) <= 0) { continue; }
79 std::vector<hamilt::BaseMatrix<double>*> tmp_matrix;
80 for (int is = 0; is < nspin_DMR; ++is)
81 {
82 tmp_matrix.push_back(dm.get_DMR_pointer(is + 1)->find_matrix(iat1, iat2, Rx, Ry, Rz));
83 }
84 for (int mu = 0; mu < pv.get_row_size(iat1); ++mu)
85 {
86 for (int nu = 0; nu < pv.get_col_size(iat2); ++nu)
87 {
88 // the DMR should not be summed over spin, do the summation here
89 double dm2d1 = 0.0;
90 for (int is = 0; is < nspin_DMR; ++is) { dm2d1 += tmp_matrix[is]->get_value(mu, nu); }
91 double dm2d2 = 2.0 * dm2d1;
92 if (isforce)
93 {
94 const double dm2d2_f = dm2d2 * factor_force;
95 for (int i = 0; i < 3; ++i) { f_iat[i] += dm2d2_f * dHSx[i][irr]; }
96 }
97 if (isstress)
98 {
99 const double dm2d1_s = dm2d1 * factor_stress;
100 stress_func(local_s, dm2d1_s, dHSx, dHSxy, dtau, irr);
101 }
102 ++local_total_irr;
103 ++irr;
104 }
105 }
106 }
107#ifdef _OPENMP
108 if (isforce && num_threads > 1) { for (int i = 0; i < 3; ++i) { f(iat, i) += f_iat[i]; } }
109#endif
110 } // end iat
111#ifdef _OPENMP
112#pragma omp critical(cal_foverlap_k_reduce)
113 {
114 total_irr += local_total_irr;
115 if (isstress)
116 {
117 for (int i = 0; i < 3; ++i) { for (int j = i; j < 3; ++j) { s(i, j) += local_s(i, j); } }
118 }
119 }
120 }
121#endif
122
123 if (total_irr != pv.nnr)
124 {
125 ModuleBase::GlobalFunc::OUT(GlobalV::ofs_running, "wrong irr", total_irr);
127 ModuleBase::WARNING_QUIT("Force_LCAO::cal_pulay_fs_center2", "irr!=pv.nnr");
128 }
129
130 if (isstress) { StressTools::stress_fill(ucell.lat0, ucell.omega, s); }
131
132 ModuleBase::timer::tick("Force_LCAO", "cal_pulay_fs_center2");
133 }
134}
Definition atom_spec.h:7
Definition matrix.h:19
static void tick(const std::string &class_name_in, const std::string &name_in)
Use twice at a time: the first time, set start_flag to false; the second time, calculate the time dur...
Definition timer.cpp:66
Definition parallel_orbitals.h:9
int get_col_size() const
dimension getters for 2D-block-cyclic division of Hamiltonian matrix get_col_size() : total number of...
Definition parallel_orbitals.h:76
int get_row_size() const
Definition parallel_orbitals.h:77
int * nlocstart
Definition parallel_orbitals.h:34
int nnr
Definition parallel_orbitals.h:32
const Input_para & inp
Definition parameter.h:26
Definition record_adj.h:12
int *** info
Definition record_adj.h:54
int * na_each
Definition record_adj.h:34
Definition unitcell.h:17
int *& iat2it
Definition unitcell.h:49
Tiait itiaiw2iwt(const Tiait &it, const Tiait &ia, const Tiait &iw) const
Definition unitcell.h:70
Atom * atoms
Definition unitcell.h:19
double & lat0
Definition unitcell.h:30
ModuleBase::IntArray & itia2iat
Definition unitcell.h:53
int & nat
Definition unitcell.h:48
double & omega
Definition unitcell.h:34
int *& iat2ia
Definition unitcell.h:50
Definition density_matrix.h:36
hamilt::HContainer< TR > * get_DMR_pointer(const int ispin) const
get pointer of DMR
Definition density_matrix_io.cpp:186
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:261
std::ofstream ofs_running
Definition global_variable.cpp:38
void OUT(std::ofstream &ofs, const std::string &name)
Definition global_function.cpp:51
void WARNING_QUIT(const std::string &, const std::string &)
Combine the functions of WARNING and QUIT.
Definition test_delley.cpp:14
void TITLE(const std::string &class_name, const std::string &function_name, const bool disable)
Definition tool_title.cpp:18
Definition pulay_fs.h:13
void cal_pulay_fs(ModuleBase::matrix &f, ModuleBase::matrix &s, const elecstate::DensityMatrix< TK, TR > &dm, const UnitCell &ucell, const Parallel_Orbitals &pv, const double *(&dHSx)[3], const double *(&dHSxy)[6], const bool &isforce, const bool &isstress, Record_adj *ra=nullptr, const double &factor_force=1.0, const double &factor_stress=1.0)
for 2-center-integration terms, provided force and stress derivatives
void stress_fill(const double &lat0_, const double &omega_, ModuleBase::matrix &stress_matrix)
Definition stress_tools.cpp:4
Parameter PARAM
Definition parameter.cpp:3
int nspin
LDA ; LSDA ; non-linear spin.
Definition input_parameter.h:85