1 //////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source
3 // License. See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by:
8 // Miguel A. Morales, moralessilva2@llnl.gov
9 // Lawrence Livermore National Laboratory
10 //
11 // File created by:
12 // Miguel A. Morales, moralessilva2@llnl.gov
13 // Lawrence Livermore National Laboratory
14 ////////////////////////////////////////////////////////////////////////////////
15
16 #ifndef QMCPLUSPLUS_AFQMC_SPARSETENSORIO_HPP
17 #define QMCPLUSPLUS_AFQMC_SPARSETENSORIO_HPP
18
19 #include <fstream>
20
21 #include "hdf/hdf_multi.h"
22 #include "hdf/hdf_archive.h"
23
24 #include "AFQMC/config.h"
25 #include "AFQMC/Matrix/csr_hdf5_readers.hpp"
26
27 #include "AFQMC/HamiltonianOperations/SparseTensor.hpp"
28 #include "AFQMC/Hamiltonians/rotateHamiltonian.hpp"
29
30 namespace qmcplusplus
31 {
32 namespace afqmc
33 {
34 template<typename T1, typename T2>
loadSparseTensor(hdf_archive & dump,WALKER_TYPES type,int NMO,int NAEA,int NAEB,std::vector<PsiT_Matrix> & PsiT,TaskGroup_ & TGprop,TaskGroup_ & TGwfn,RealType cutvn,RealType cutv2)35 SparseTensor<T1, T2> loadSparseTensor(hdf_archive& dump,
36 WALKER_TYPES type,
37 int NMO,
38 int NAEA,
39 int NAEB,
40 std::vector<PsiT_Matrix>& PsiT,
41 TaskGroup_& TGprop,
42 TaskGroup_& TGwfn,
43 RealType cutvn,
44 RealType cutv2)
45 {
46 #if defined(MIXED_PRECISION)
47 using SpT1 = typename to_single_precision<T1>::value_type;
48 using SpT2 = typename to_single_precision<T2>::value_type;
49 #else
50 using SpT1 = T1;
51 using SpT2 = T2;
52 #endif
53
54 // NEEDS TO BE FIXED FOR SP CASE
55 using T1_shm_csr_matrix = ma::sparse::csr_matrix<SpT1, int, std::size_t, shared_allocator<SpT1>, ma::sparse::is_root>;
56 using T2_shm_csr_matrix = ma::sparse::csr_matrix<SpT2, int, std::size_t, shared_allocator<SpT2>, ma::sparse::is_root>;
57
58 std::vector<int> dims(10);
59 int ndet = (type == COLLINEAR ? PsiT.size() / 2 : PsiT.size());
60 ValueType E0;
61 int global_ncvecs = 0;
62 int V2_nrows, V2_ncols, Spvn_nrows, Spvn_ncols;
63
64 // read from HDF
65 if (!dump.push("HamiltonianOperations", false))
66 {
67 app_error() << " Error in loadSparseTensor: Group HamiltonianOperations not found. \n";
68 APP_ABORT("");
69 }
70 if (!dump.push("SparseTensor", false))
71 {
72 app_error() << " Error in loadSparseTensor: Group SparseTensor not found. \n";
73 APP_ABORT("");
74 }
75 if (TGwfn.Global().root())
76 {
77 if (!dump.readEntry(dims, "dims"))
78 {
79 app_error() << " Error in loadSparseTensor: Problems reading dataset. \n";
80 APP_ABORT("");
81 }
82 if (dims[0] != NMO)
83 {
84 app_error() << " Error in loadSparseTensor: Inconsistent data in file: NMO. \n";
85 APP_ABORT("");
86 }
87 if (dims[1] != NAEA)
88 {
89 app_error() << " Error in loadSparseTensor: Inconsistent data in file: NAEA. \n";
90 APP_ABORT("");
91 }
92 if (dims[2] != NAEB)
93 {
94 app_error() << " Error in loadSparseTensor: Inconsistent data in file: NAEB. \n";
95 APP_ABORT("");
96 }
97 if (dims[3] != ndet)
98 {
99 app_error() << " Error in loadSparseTensor: Inconsistent data in file: ndet. \n";
100 APP_ABORT("");
101 }
102 if (type == CLOSED && dims[4] != 1)
103 {
104 app_error() << " Error in loadSparseTensor: Inconsistent data in file: walker_type. \n";
105 APP_ABORT("");
106 }
107 if (type == COLLINEAR && dims[4] != 2)
108 {
109 app_error() << " Error in loadSparseTensor: Inconsistent data in file: walker_type. \n";
110 APP_ABORT("");
111 }
112 if (type == NONCOLLINEAR && dims[4] != 3)
113 {
114 app_error() << " Error in loadSparseTensor: Inconsistent data in file: walker_type. \n";
115 APP_ABORT("");
116 }
117 std::vector<ValueType> et;
118 if (!dump.readEntry(et, "E0"))
119 {
120 app_error() << " Error in loadSparseTensor: Problems reading dataset. \n";
121 APP_ABORT("");
122 }
123 E0 = et[0];
124 }
125 TGwfn.Global().broadcast_n(dims.data(), 9);
126 TGwfn.Global().broadcast_value(E0);
127 V2_nrows = dims[5];
128 V2_ncols = dims[6];
129 Spvn_nrows = dims[7];
130 Spvn_ncols = dims[8];
131
132 // read 1-body hamiltonian and exchange potential (v0)
133 boost::multi::array<ComplexType, 2> H1({NMO, NMO});
134 boost::multi::array<ComplexType, 2> v0({NMO, NMO});
135 if (TGwfn.Global().root())
136 {
137 boost::multi::array<ValueType, 2> H1_({NMO, NMO});
138 if (!dump.readEntry(H1_, "H1"))
139 {
140 app_error() << " Error in loadSparseTensor: Problems reading dataset. \n";
141 APP_ABORT("");
142 }
143 copy_n_cast(H1_.origin(), NMO * NMO, to_address(H1.origin()));
144 if (!dump.readEntry(v0, "v0"))
145 {
146 app_error() << " Error in loadSparseTensor: Problems reading dataset. \n";
147 APP_ABORT("");
148 }
149 }
150 TGwfn.Global().broadcast_n(H1.origin(), H1.num_elements());
151 TGwfn.Global().broadcast_n(v0.origin(), v0.num_elements());
152
153 // read half-rotated exchange matrix
154 std::vector<T1_shm_csr_matrix> V2;
155 V2.reserve(ndet);
156 for (int i = 0; i < ndet; i++)
157 {
158 if (!dump.push(std::string("HalfRotatedHijkl_") + std::to_string(i), false))
159 {
160 app_error() << " Error in loadSparseTensor: Group HalfRotatedHijkl_" << i << " not found. \n";
161 APP_ABORT("");
162 }
163 V2.emplace_back(
164 csr_hdf5::unstructured_distributed_CSR_from_HDF<T1_shm_csr_matrix>(dump, TGwfn, V2_nrows, V2_ncols, cutv2));
165 dump.pop();
166 }
167
168 // read Cholesky matrix
169 if (!dump.push(std::string("SparseCholeskyMatrix"), false))
170 {
171 app_error() << " Error in loadSparseTensor: Group SparseCholeskyMatrix not found. \n";
172 APP_ABORT("");
173 }
174 SpVType_shm_csr_matrix Spvn(
175 csr_hdf5::column_distributed_CSR_from_HDF<SpVType_shm_csr_matrix>(dump, TGprop, Spvn_nrows, Spvn_ncols, cutv2));
176 dump.pop();
177 // leave hdf_archive in group it started from
178 dump.pop();
179 dump.pop();
180
181 // rotated 1 body hamiltonians
182 std::vector<boost::multi::array<ComplexType, 1>> hij;
183 hij.reserve(ndet);
184 int skp = ((type == COLLINEAR) ? 1 : 0);
185 for (int n = 0, nd = 0; n < ndet; ++n, nd += (skp + 1))
186 {
187 check_wavefunction_consistency(type, &PsiT[nd], &PsiT[nd + skp], NMO, NAEA, NAEB);
188 hij.emplace_back(rotateHij(type, &PsiT[nd], &PsiT[nd + skp], H1));
189 }
190
191 // setup views
192 using matrix_view = typename T1_shm_csr_matrix::template matrix_view<int>;
193 std::vector<matrix_view> V2view;
194 V2view.reserve(ndet);
195 for (auto& v : V2)
196 V2view.emplace_back(csr::shm::local_balanced_partition(v, TGwfn));
197
198 auto Spvnview(csr::shm::local_balanced_partition(Spvn, TGprop));
199
200 if (ndet == 1)
201 {
202 std::vector<T2_shm_csr_matrix> SpvnT;
203 // MAM: chech that T2 is SpComplexType
204 //std::vector<SpCType_shm_csr_matrix> SpvnT;
205 using matrix_view = typename T2_shm_csr_matrix::template matrix_view<int>;
206 std::vector<matrix_view> SpvnTview;
207 #if defined(MIXED_PRECISION)
208 auto PsiTsp(csr::shm::CSRvector_to_single_precision<PsiT_Matrix_t<SPComplexType>>(PsiT));
209 #else
210 auto& PsiTsp(PsiT);
211 #endif
212 SpvnT.emplace_back(
213 sparse_rotate::halfRotateCholeskyMatrixForBias<T2>(type, TGprop, &PsiTsp[0],
214 ((type == COLLINEAR) ? (&PsiTsp[1]) : (&PsiTsp[0])), Spvn,
215 cutv2));
216 SpvnTview.emplace_back(csr::shm::local_balanced_partition(SpvnT[0], TGprop));
217
218 return SparseTensor<T1, T2>(TGwfn.TG_local(), type, std::move(H1), std::move(hij), std::move(V2), std::move(V2view),
219 std::move(Spvn), std::move(Spvnview), std::move(v0), std::move(SpvnT),
220 std::move(SpvnTview), E0, Spvn_ncols);
221 }
222 else
223 {
224 // problem here!!!!!
225 // don't know how to tell if this is NOMSD or PHMSD!!!
226 // whether to rotate or not! That's the question!
227 std::vector<T2_shm_csr_matrix> SpvnT;
228 //std::vector<SpVType_shm_csr_matrix> SpvnT;
229 using matrix_view = typename T2_shm_csr_matrix::template matrix_view<int>;
230 std::vector<matrix_view> SpvnTview;
231 SpvnT.emplace_back(csr::shm::transpose<T2_shm_csr_matrix>(Spvn));
232 SpvnTview.emplace_back(csr::shm::local_balanced_partition(SpvnT[0], TGprop));
233
234 return SparseTensor<T1, T2>(TGwfn.TG_local(), type, std::move(H1), std::move(hij), std::move(V2), std::move(V2view),
235 std::move(Spvn), std::move(Spvnview), std::move(v0), std::move(SpvnT),
236 std::move(SpvnTview), E0, global_ncvecs);
237 }
238 }
239
240 // single writer right now
241 template<class shm_mat1, class shm_mat2>
writeSparseTensor(hdf_archive & dump,WALKER_TYPES type,int NMO,int NAEA,int NAEB,TaskGroup_ & TGprop,TaskGroup_ & TGwfn,boost::multi::array<ValueType,2> & H1,std::vector<shm_mat1> const & v2,shm_mat2 const & Spvn,boost::multi::array<ComplexType,2> & v0,ValueType E0,int gncv,int code)242 inline void writeSparseTensor(hdf_archive& dump,
243 WALKER_TYPES type,
244 int NMO,
245 int NAEA,
246 int NAEB,
247 TaskGroup_& TGprop,
248 TaskGroup_& TGwfn,
249 boost::multi::array<ValueType, 2>& H1,
250 std::vector<shm_mat1> const& v2,
251 shm_mat2 const& Spvn,
252 boost::multi::array<ComplexType, 2>& v0,
253 ValueType E0,
254 int gncv,
255 int code)
256 {
257 assert(v2.size() > 0);
258 if (TGwfn.Global().root())
259 {
260 dump.push("HamiltonianOperations");
261 dump.push("SparseTensor");
262 std::vector<int>
263 dims{NMO, NAEA, NAEB, int(v2.size()), type, int(v2[0].size(0)), int(v2[0].size(1)), int(Spvn.size(0)), gncv};
264 dump.write(dims, "dims");
265 std::vector<int> dm{code};
266 dump.write(dm, "type");
267 std::vector<ValueType> et{E0};
268 dump.write(et, "E0");
269 dump.write(H1, "H1");
270 dump.write(v0, "v0");
271 }
272
273 for (int i = 0; i < v2.size(); i++)
274 {
275 if (TGwfn.Global().root())
276 dump.push(std::string("HalfRotatedHijkl_") + std::to_string(i));
277 csr_hdf5::write_distributed_CSR_to_HDF(v2[i], dump, TGwfn);
278 if (TGwfn.Global().root())
279 dump.pop();
280 }
281
282 if (TGprop.Global().root())
283 dump.push("SparseCholeskyMatrix");
284 csr_hdf5::write_distributed_CSR_to_HDF(Spvn, dump, TGprop);
285
286 if (TGwfn.Global().root())
287 {
288 dump.pop();
289 dump.pop();
290 dump.pop();
291 }
292 TGwfn.Global().barrier();
293 }
294
295 } // namespace afqmc
296 } // namespace qmcplusplus
297
298 #endif
299