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