ABACUS develop
Atomic-orbital Based Ab-initio Computation at UStc
Loading...
Searching...
No Matches
lr_util.hpp
Go to the documentation of this file.
1#pragma once
2#include <cstddef>
3#include "lr_util.h"
4#include <algorithm>
8namespace LR_Util
9{
11
12 template <typename TCell>
13 int cal_nelec(const TCell& ucell) {
14 int nelec = 0;
15 for (int it = 0; it < ucell.ntype; ++it) {
16 nelec += ucell.atoms[it].ncpp.zv * ucell.atoms[it].na;
17}
18 return nelec;
19 }
20
23 template<typename T, typename... Args>
24 std::unique_ptr<T> make_unique(Args &&... args)
25 {
26 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
27 }
28
29 //====== newers and deleters========
34 template <typename T>
35 void _allocate_2order_nested_ptr(T**& p2, size_t size1, size_t size2)
36 {
37 p2 = new T * [size1];
38 for (size_t i = 0; i < size1; ++i)
39 {
40 p2[i] = new T[size2];
41 }
42 };
43
48 template <typename T>
49 void _deallocate_2order_nested_ptr(T** p2, size_t size)
50 {
51 if (p2 != nullptr)
52 {
53 for (size_t i = 0; i < size; ++i)
54 {
55 if (p2[i] != nullptr) { delete[] p2[i]; }
56 }
57 delete[] p2;
58 }
59 };
60
61 inline double get_conj(const double& x)
62 {
63 return x;
64 }
65 inline std::complex<double> get_conj(const std::complex<double>& x)
66 {
67 return std::conj(x);
68 }
69 template <typename T>
70 void matsym(const T* in, const int n, T* out)
71 {
72 for (int i = 0; i < n; ++i) {
73 out[i * n + i] = 0.5 * in[i * n + i] + 0.5 * get_conj(in[i * n + i]);
74}
75 for (int i = 0;i < n;++i) {
76 for (int j = i + 1;j < n;++j)
77 {
78 out[i * n + j] = 0.5 * (in[i * n + j] + get_conj(in[j * n + i]));
79 out[j * n + i] = get_conj(out[i * n + j]);
80 }
81}
82 }
83 template <typename T>
84 void matsym(T* inout, const int n)
85 {
86 for (int i = 0; i < n; ++i) {
87 inout[i * n + i] = 0.5 * (inout[i * n + i] + get_conj(inout[i * n + i]));
88}
89 for (int i = 0;i < n;++i) {
90 for (int j = i + 1;j < n;++j)
91 {
92 inout[i * n + j] = 0.5 * (inout[i * n + j] + get_conj(inout[j * n + i]));
93 inout[j * n + i] = get_conj(inout[i * n + j]);
94 }
95}
96 }
97
99 template<typename T>
100 psi::Psi<T> get_psi_spin(const psi::Psi<T>& psi_in, const int& is, const int& nk)
101 {
102 return psi::Psi<T>(&psi_in(is * nk, 0, 0),
103 nk,
104 psi_in.get_nbands(),
105 psi_in.get_nbasis(),
106 true);
107 }
108
110 template<typename T, typename Device>
111 psi::Psi<T, Device> k1_to_bfirst_wrapper(const psi::Psi<T, Device>& psi_kfirst, int nk_in, int nbasis_in)
112 {
113 assert(psi_kfirst.get_nk() == 1);
114 assert(nk_in * nbasis_in == psi_kfirst.get_nbasis());
115
116 int ib_now = psi_kfirst.get_current_b();
117 psi_kfirst.fix_b(0); // for get_pointer() to get the head pointer
118 psi::Psi<T, Device> psi_bfirst(psi_kfirst.get_pointer(),
119 nk_in,
120 psi_kfirst.get_nbands(),
121 nbasis_in,
122 nbasis_in,
123 false);
124 psi_kfirst.fix_b(ib_now);
125 return psi_bfirst;
126 }
127
129 template<typename T, typename Device>
131 {
132 int ib_now = psi_bfirst.get_current_b();
133 int ik_now = psi_bfirst.get_current_k();
134
135 psi_bfirst.fix_kb(0, 0); // for get_pointer() to get the head pointer
136 psi::Psi<T, Device> psi_kfirst(psi_bfirst.get_pointer(),
137 1,
138 psi_bfirst.get_nbands(),
139 psi_bfirst.get_nk() * psi_bfirst.get_nbasis(),
140 psi_bfirst.get_nk() * psi_bfirst.get_nbasis(),
141 true);
142 psi_bfirst.fix_kb(ik_now, ib_now);
143 return psi_kfirst;
144 }
145
146#ifdef __MPI
147 template <typename T>
148 void gather_2d_to_full(const Parallel_2D& pv, const T* submat, T* fullmat, bool col_first, int global_nrow, int global_ncol)
149 {
150 ModuleBase::TITLE("LR_Util", "gather_2d_to_full");
151 auto get_mpi_datatype = []() -> MPI_Datatype {
152 if (std::is_same<T, int>::value) { return MPI_INT; }
153 if (std::is_same<T, float>::value) { return MPI_FLOAT; }
154 else if (std::is_same<T, double>::value) { return MPI_DOUBLE; }
155 if (std::is_same<T, std::complex<float>>::value) { return MPI_COMPLEX; }
156 else if (std::is_same<T, std::complex<double>>::value) { return MPI_DOUBLE_COMPLEX; }
157 else { throw std::runtime_error("gather_2d_to_full: unsupported type"); }
158 };
159
160 // zeros
161 for (int i = 0;i < global_nrow * global_ncol;++i) { fullmat[i] = 0.0;
162}
163 //copy
164 for (int i = 0;i < pv.get_row_size();++i) {
165 for (int j = 0;j < pv.get_col_size();++j) {
166 if (col_first) {
167 fullmat[pv.local2global_row(i) * global_ncol + pv.local2global_col(j)] = submat[i * pv.get_col_size() + j];
168 } else {
169 fullmat[pv.local2global_col(j) * global_nrow + pv.local2global_row(i)] = submat[j * pv.get_row_size() + i];
170}
171}
172}
173
174 //reduce to root
175 MPI_Allreduce(MPI_IN_PLACE, fullmat, global_nrow * global_ncol, get_mpi_datatype(), MPI_SUM, pv.comm());
176 };
177#endif
178
179}
This class packs the basic information of 2D-block-cyclic parallel distribution of an arbitrary matri...
Definition parallel_2d.h:12
int local2global_col(const int ilc) const
get the global index of a local index (col)
Definition parallel_2d.h:63
MPI_Comm comm() const
Definition parallel_2d.cpp:36
int get_row_size() const
number of local rows
Definition parallel_2d.h:21
int local2global_row(const int ilr) const
get the global index of a local index (row)
Definition parallel_2d.h:57
int get_col_size() const
number of local columns
Definition parallel_2d.h:27
Definition psi.h:37
const int & get_nbands() const
Definition psi.cpp:342
int get_current_b() const
Definition psi.cpp:468
const int & get_nk() const
Definition psi.cpp:336
void fix_kb(const int ik, const int ib) const
Definition psi.cpp:419
const int & get_nbasis() const
Definition psi.cpp:348
int get_current_k() const
Definition psi.cpp:462
T * get_pointer() const
Definition psi.cpp:272
void fix_b(const int ib) const
Definition psi.cpp:395
#define T
Definition exp.cpp:237
Definition lr_util.cpp:6
psi::Psi< T > get_psi_spin(const psi::Psi< T > &psi_in, const int &is, const int &nk)
get the Psi wrapper of the selected spin from the Psi object
Definition lr_util.hpp:100
int cal_nelec(const TCell &ucell)
=====================PHYSICS====================
Definition lr_util.hpp:13
std::unique_ptr< T > make_unique(Args &&... args)
Definition lr_util.hpp:24
void matsym(const T *in, const int n, T *out)
Definition lr_util.hpp:70
void gather_2d_to_full(const Parallel_2D &pv, const T *submat, T *fullmat, bool col_first, int global_nrow, int global_ncol)
gather 2d matrix to full matrix the defination of row and col is consistent with setup_2d_division
Definition lr_util.hpp:148
double get_conj(const double &x)
Definition lr_util.hpp:61
psi::Psi< T, Device > bfirst_to_k1_wrapper(const psi::Psi< T, Device > &psi_bfirst)
psi(nb, nk, nbasis) -> psi(nk=1, nbands=nb, nk * nbasis) without memory copy
Definition lr_util.hpp:130
psi::Psi< T, Device > k1_to_bfirst_wrapper(const psi::Psi< T, Device > &psi_kfirst, int nk_in, int nbasis_in)
psi(nk=1, nbands=nb, nk * nbasis) -> psi(nb, nk, nbasis) without memory copy
Definition lr_util.hpp:111
void _allocate_2order_nested_ptr(T **&p2, size_t size1, size_t size2)
new 2d pointer
Definition lr_util.hpp:35
void _deallocate_2order_nested_ptr(T **p2, size_t size)
=================ALGORITHM====================
Definition lr_util.hpp:49
void TITLE(const std::string &class_name, const std::string &function_name, const bool disable)
Definition tool_title.cpp:18