1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
8 //
9 // File created by: Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
10 //////////////////////////////////////////////////////////////////////////////////////
11
12 #undef NDEBUG
13
14 #include "catch.hpp"
15
16 #include "Configuration.h"
17
18 #include "OhmmsData/Libxml2Doc.h"
19 #include "OhmmsApp/ProjectData.h"
20 #include "hdf/hdf_archive.h"
21 #include "Utilities/RandomGenerator.h"
22 #include "Utilities/TimerManager.h"
23
24 #undef APP_ABORT
25 #define APP_ABORT(x) \
26 { \
27 std::cout << x << std::endl; \
28 throw; \
29 }
30
31 #include <string>
32 #include <vector>
33 #include <complex>
34 #include <iomanip>
35
36 #include "AFQMC/Utilities/test_utils.hpp"
37 //#include "AFQMC/Utilities/myTimer.h"
38 #include "Utilities/Timer.h"
39 #include "AFQMC/Hamiltonians/HamiltonianFactory.h"
40 #include "AFQMC/Hamiltonians/Hamiltonian.hpp"
41 #include "AFQMC/Wavefunctions/WavefunctionFactory.h"
42 #include "AFQMC/Wavefunctions/Wavefunction.hpp"
43 #include "AFQMC/Propagators/PropagatorFactory.h"
44 #include "AFQMC/Propagators/Propagator.hpp"
45 #include "AFQMC/Walkers/WalkerSet.hpp"
46 #include "AFQMC/Memory/buffer_managers.h"
47
48 #include "AFQMC/Matrix/csr_matrix_construct.hpp"
49 #include "AFQMC/Numerics/ma_blas.hpp"
50
51 using std::cerr;
52 using std::complex;
53 using std::cout;
54 using std::endl;
55 using std::ifstream;
56 using std::setprecision;
57 using std::string;
58
59 extern std::string UTEST_HAMIL, UTEST_WFN;
60
61 namespace qmcplusplus
62 {
63 using namespace afqmc;
64
propg_fac_shared(boost::mpi3::communicator & world)65 void propg_fac_shared(boost::mpi3::communicator& world)
66 {
67 if (check_hamil_wfn_for_utest("propg_fac_shared", UTEST_WFN, UTEST_HAMIL))
68 {
69 timer_manager.set_timer_threshold(timer_level_coarse);
70 setup_timers(AFQMCTimers, AFQMCTimerNames, timer_level_coarse);
71
72 // Global Task Group
73 afqmc::GlobalTaskGroup gTG(world);
74
75 int NMO, NAEA, NAEB;
76 std::tie(NMO, NAEA, NAEB) = read_info_from_hdf(UTEST_HAMIL);
77 WALKER_TYPES type = afqmc::getWalkerType(UTEST_WFN);
78 int NPOL = (type == NONCOLLINEAR) ? 2 : 1;
79
80 std::map<std::string, AFQMCInfo> InfoMap;
81 InfoMap.insert(std::pair<std::string, AFQMCInfo>("info0", AFQMCInfo{"info0", NMO, NAEA, NAEB}));
82 HamiltonianFactory HamFac(InfoMap);
83 std::string hamil_xml = "<Hamiltonian name=\"ham0\" info=\"info0\"> \
84 <parameter name=\"filetype\">hdf5</parameter> \
85 <parameter name=\"filename\">" +
86 UTEST_HAMIL + "</parameter> \
87 <parameter name=\"cutoff_decomposition\">1e-5</parameter> \
88 </Hamiltonian> \
89 ";
90 const char* ham_xml_block = hamil_xml.c_str();
91 Libxml2Document doc;
92 bool okay = doc.parseFromString(ham_xml_block);
93 REQUIRE(okay);
94 std::string ham_name("ham0");
95 HamFac.push(ham_name, doc.getRoot());
96 Hamiltonian& ham = HamFac.getHamiltonian(gTG, ham_name);
97
98 auto TG = TaskGroup_(gTG, std::string("WfnTG"), 1, gTG.getTotalCores());
99 int nwalk = 11; // choose prime number to force non-trivial splits in shared routines
100 RandomGenerator_t rng;
101
102 const char* wlk_xml_block_closed = "<WalkerSet name=\"wset0\"> \
103 <parameter name=\"walker_type\">closed</parameter> \
104 </WalkerSet> \
105 ";
106 const char* wlk_xml_block_coll = "<WalkerSet name=\"wset0\"> \
107 <parameter name=\"walker_type\">collinear</parameter> \
108 </WalkerSet> \
109 ";
110 const char* wlk_xml_block_noncol = "<WalkerSet name=\"wset0\"> \
111 <parameter name=\"walker_type\">noncollinear</parameter> \
112 </WalkerSet> \
113 ";
114 const char* wlk_xml_block =
115 ((type == CLOSED) ? (wlk_xml_block_closed) : (type == COLLINEAR ? wlk_xml_block_coll : wlk_xml_block_noncol));
116 Libxml2Document doc3;
117 okay = doc3.parseFromString(wlk_xml_block);
118 REQUIRE(okay);
119
120 // Create unique restart filename to avoid issues with running tests in parallel
121 // through ctest.
122 std::string restart_file = create_test_hdf(UTEST_WFN, UTEST_HAMIL);
123 app_log() << " propg_fac_shared destroy restart_file " << restart_file << "\n";
124 if (!remove_file(restart_file)) APP_ABORT("failed to remove restart_file");
125 std::string wfn_xml = "<Wavefunction name=\"wfn0\" info=\"info0\"> \
126 <parameter name=\"filetype\">ascii</parameter> \
127 <parameter name=\"filename\">" +
128 UTEST_WFN + "</parameter> \
129 <parameter name=\"cutoff\">1e-6</parameter> \
130 <parameter name=\"dense_trial\">yes</parameter> \
131 <parameter name=\"restart_file\">" +
132 restart_file + "</parameter> \
133 </Wavefunction> \
134 ";
135 const char* wfn_xml_block = wfn_xml.c_str();
136 Libxml2Document doc2;
137 okay = doc2.parseFromString(wfn_xml_block);
138 REQUIRE(okay);
139 std::string wfn_name("wfn0");
140 WavefunctionFactory WfnFac(InfoMap);
141 WfnFac.push(wfn_name, doc2.getRoot());
142 Wavefunction& wfn = WfnFac.getWavefunction(TG, TG, wfn_name, type, &ham, 1e-6, nwalk);
143
144 WalkerSet wset(TG, doc3.getRoot(), InfoMap["info0"], &rng);
145 auto initial_guess = WfnFac.getInitialGuess(wfn_name);
146 REQUIRE(initial_guess.size(0) == 2);
147 REQUIRE(initial_guess.size(1) == NPOL * NMO);
148 REQUIRE(initial_guess.size(2) == NAEA);
149 wset.resize(nwalk, initial_guess[0], initial_guess[0]);
150 // initial_guess[1](XXX.extension(0),{0,NAEB}));
151
152 const char* propg_xml_block = "<Propagator name=\"prop0\"> \
153 </Propagator> \
154 ";
155 Libxml2Document doc4;
156 okay = doc4.parseFromString(propg_xml_block);
157 REQUIRE(okay);
158 std::string prop_name("prop0");
159 PropagatorFactory PropgFac(InfoMap);
160 PropgFac.push(prop_name, doc4.getRoot());
161 Propagator& prop = PropgFac.getPropagator(TG, prop_name, wfn, &rng);
162
163 std::cout << setprecision(12);
164 wfn.Energy(wset);
165 {
166 ComplexType eav = 0, ov = 0;
167 for (auto it = wset.begin(); it != wset.end(); ++it)
168 {
169 eav += *it->weight() * (it->energy());
170 ov += *it->weight();
171 }
172 app_log() << " Initial Energy: " << (eav / ov).real() << std::endl;
173 }
174 double tot_time = 0;
175 RealType dt = 0.01;
176 RealType Eshift = std::abs(ComplexType(*wset[0].overlap()));
177 for (int i = 0; i < 4; i++)
178 {
179 prop.Propagate(2, wset, Eshift, dt, 1);
180 wfn.Energy(wset);
181 ComplexType eav = 0, ov = 0;
182 for (auto it = wset.begin(); it != wset.end(); ++it)
183 {
184 eav += *it->weight() * (it->energy());
185 ov += *it->weight();
186 }
187 tot_time += 2 * dt;
188 app_log() << " -- " << i << " " << tot_time << " " << (eav / ov).real() << std::endl;
189 wfn.Orthogonalize(wset, true);
190 }
191 for (int i = 0; i < 4; i++)
192 {
193 prop.Propagate(4, wset, Eshift, dt, 1);
194 wfn.Energy(wset);
195 ComplexType eav = 0, ov = 0;
196 for (auto it = wset.begin(); it != wset.end(); ++it)
197 {
198 eav += *it->weight() * (it->energy());
199 ov += *it->weight();
200 }
201 tot_time += 4 * dt;
202 app_log() << " -- " << i << " " << tot_time << " " << (eav / ov).real() << std::endl;
203 wfn.Orthogonalize(wset, true);
204 }
205
206 for (int i = 0; i < 4; i++)
207 {
208 prop.Propagate(4, wset, Eshift, dt, 2);
209 wfn.Energy(wset);
210 ComplexType eav = 0, ov = 0;
211 for (auto it = wset.begin(); it != wset.end(); ++it)
212 {
213 eav += *it->weight() * (it->energy());
214 ov += *it->weight();
215 }
216 tot_time += 4 * dt;
217 app_log() << " -- " << i << " " << tot_time << " " << (eav / ov).real() << std::endl;
218 wfn.Orthogonalize(wset, true);
219 }
220 for (int i = 0; i < 4; i++)
221 {
222 prop.Propagate(5, wset, Eshift, 2 * dt, 2);
223 wfn.Energy(wset);
224 ComplexType eav = 0, ov = 0;
225 for (auto it = wset.begin(); it != wset.end(); ++it)
226 {
227 eav += *it->weight() * (it->energy());
228 ov += *it->weight();
229 }
230 tot_time += 5 * 2 * dt;
231 app_log() << " -- " << i << " " << tot_time << " " << (eav / ov).real() << std::endl;
232 wfn.Orthogonalize(wset, true);
233 }
234
235 timer_manager.print(nullptr);
236 }
237 }
238
propg_fac_distributed(boost::mpi3::communicator & world,int ngrp)239 void propg_fac_distributed(boost::mpi3::communicator& world, int ngrp)
240 {
241 if (check_hamil_wfn_for_utest("propg_fac_distributed", UTEST_WFN, UTEST_HAMIL))
242 {
243 timer_manager.set_timer_threshold(timer_level_coarse);
244 setup_timers(AFQMCTimers, AFQMCTimerNames, timer_level_coarse);
245
246 // Global Task Group
247 afqmc::GlobalTaskGroup gTG(world);
248
249 int NMO, NAEA, NAEB;
250 std::tie(NMO, NAEA, NAEB) = read_info_from_hdf(UTEST_HAMIL);
251 WALKER_TYPES type = afqmc::getWalkerType(UTEST_WFN);
252 int NPOL = (type == NONCOLLINEAR) ? 2 : 1;
253
254 std::map<std::string, AFQMCInfo> InfoMap;
255 InfoMap.insert(std::pair<std::string, AFQMCInfo>("info0", AFQMCInfo{"info0", NMO, NAEA, NAEB}));
256 HamiltonianFactory HamFac(InfoMap);
257 std::string hamil_xml = "<Hamiltonian name=\"ham0\" info=\"info0\"> \
258 <parameter name=\"filetype\">hdf5</parameter> \
259 <parameter name=\"filename\">" +
260 UTEST_HAMIL + "</parameter> \
261 <parameter name=\"cutoff_decomposition\">1e-5</parameter> \
262 </Hamiltonian> \
263 ";
264 const char* ham_xml_block = hamil_xml.c_str();
265 Libxml2Document doc;
266 bool okay = doc.parseFromString(ham_xml_block);
267 REQUIRE(okay);
268 std::string ham_name("ham0");
269 HamFac.push(ham_name, doc.getRoot());
270 Hamiltonian& ham = HamFac.getHamiltonian(gTG, ham_name);
271
272 auto TG = TaskGroup_(gTG, std::string("WfnTG"), 1, gTG.getTotalCores());
273 auto TGprop = TaskGroup_(gTG, std::string("WfnTG"), ngrp, gTG.getTotalCores());
274 //int nwalk = 4; // choose prime number to force non-trivial splits in shared routines
275 int nwalk = 11; // choose prime number to force non-trivial splits in shared routines
276 RandomGenerator_t rng;
277 qmcplusplus::Timer Time;
278
279 const char* wlk_xml_block_closed = "<WalkerSet name=\"wset0\"> \
280 <parameter name=\"walker_type\">closed</parameter> \
281 </WalkerSet> \
282 ";
283 const char* wlk_xml_block_coll = "<WalkerSet name=\"wset0\"> \
284 <parameter name=\"walker_type\">collinear</parameter> \
285 </WalkerSet> \
286 ";
287 const char* wlk_xml_block_noncol = "<WalkerSet name=\"wset0\"> \
288 <parameter name=\"walker_type\">noncollinear</parameter> \
289 </WalkerSet> \
290 ";
291 const char* wlk_xml_block =
292 ((type == CLOSED) ? (wlk_xml_block_closed) : (type == COLLINEAR ? wlk_xml_block_coll : wlk_xml_block_noncol));
293 Libxml2Document doc3;
294 okay = doc3.parseFromString(wlk_xml_block);
295 REQUIRE(okay);
296
297 std::string restart_file = create_test_hdf(UTEST_WFN, UTEST_HAMIL);
298 app_log() << " propg_fac_distributed destroy restart_file " << restart_file << "\n";
299 if (!remove_file(restart_file)) APP_ABORT("failed to remove restart_file");
300 std::string wfn_xml = "<Wavefunction name=\"wfn0\" info=\"info0\"> \
301 <parameter name=\"filetype\">ascii</parameter> \
302 <parameter name=\"filename\">" +
303 UTEST_WFN + "</parameter> \
304 <parameter name=\"cutoff\">1e-6</parameter> \
305 <parameter name=\"restart_file\">" +
306 restart_file + "</parameter> \
307 </Wavefunction> \
308 ";
309 const char* wfn_xml_block = wfn_xml.c_str();
310 Libxml2Document doc2;
311 okay = doc2.parseFromString(wfn_xml_block);
312 REQUIRE(okay);
313 std::string wfn_name("wfn0");
314 WavefunctionFactory WfnFac(InfoMap);
315 WfnFac.push(wfn_name, doc2.getRoot());
316 Wavefunction& wfn = WfnFac.getWavefunction(TGprop, TGprop, wfn_name, type, &ham, 1e-6, nwalk);
317
318 WalkerSet wset(TG, doc3.getRoot(), InfoMap["info0"], &rng);
319 auto initial_guess = WfnFac.getInitialGuess(wfn_name);
320 REQUIRE(initial_guess.size(0) == 2);
321 REQUIRE(initial_guess.size(1) == NPOL * NMO);
322 REQUIRE(initial_guess.size(2) == NAEA);
323 wset.resize(nwalk, initial_guess[0], initial_guess[0]);
324
325 const char* propg_xml_block0 = "<Propagator name=\"prop0\"> \
326 <parameter name=\"nnodes\">";
327 const char* propg_xml_block1 = "</parameter> \
328 </Propagator> \
329 ";
330 std::string str_ = std::string("<Propagator name=\"prop0\"> <parameter name=\"nnodes\">") +
331 std::to_string(gTG.getTotalNodes()) + std::string("</parameter> </Propagator>");
332 Libxml2Document doc4;
333 okay = doc4.parseFromString(str_.c_str());
334 REQUIRE(okay);
335 std::string prop_name("prop0");
336 PropagatorFactory PropgFac(InfoMap);
337 PropgFac.push(prop_name, doc4.getRoot());
338 Propagator& prop = PropgFac.getPropagator(TGprop, prop_name, wfn, &rng);
339 wfn.Energy(wset);
340 {
341 ComplexType eav = 0, ov = 0;
342 for (auto it = wset.begin(); it != wset.end(); ++it)
343 {
344 eav += *it->weight() * (it->energy());
345 ov += *it->weight();
346 }
347 app_log() << " Initial Energy: " << (eav / ov).real() << std::endl;
348 }
349 double tot_time = 0, t1;
350 RealType dt = 0.01;
351 RealType Eshift = std::abs(ComplexType(*wset[0].overlap()));
352 Time.restart();
353 for (int i = 0; i < 4; i++)
354 {
355 prop.Propagate(2, wset, Eshift, dt, 1);
356 wfn.Energy(wset);
357 ComplexType eav = 0, ov = 0;
358 for (auto it = wset.begin(); it != wset.end(); ++it)
359 {
360 eav += *it->weight() * (it->energy());
361 ov += *it->weight();
362 }
363 tot_time += 2 * dt;
364 wfn.Orthogonalize(wset, true);
365 t1 = Time.elapsed();
366 app_log() << " -- " << i << " " << tot_time << " " << (eav / ov).real() << " Time: " << t1 << std::endl;
367 }
368 for (int i = 0; i < 4; i++)
369 {
370 prop.Propagate(4, wset, Eshift, dt, 1);
371 wfn.Energy(wset);
372 ComplexType eav = 0, ov = 0;
373 for (auto it = wset.begin(); it != wset.end(); ++it)
374 {
375 eav += *it->weight() * (it->energy());
376 ov += *it->weight();
377 }
378 tot_time += 4 * dt;
379 wfn.Orthogonalize(wset, true);
380 t1 = Time.elapsed();
381 app_log() << " -- " << i << " " << tot_time << " " << (eav / ov).real() << " Time: " << t1 << std::endl;
382 }
383
384 for (int i = 0; i < 4; i++)
385 {
386 prop.Propagate(4, wset, Eshift, dt, 2);
387 wfn.Energy(wset);
388 ComplexType eav = 0, ov = 0;
389 for (auto it = wset.begin(); it != wset.end(); ++it)
390 {
391 eav += *it->weight() * (it->energy());
392 ov += *it->weight();
393 }
394 tot_time += 4 * dt;
395 wfn.Orthogonalize(wset, true);
396 t1 = Time.elapsed();
397 app_log() << " -- " << i << " " << tot_time << " " << (eav / ov).real() << " Time: " << t1 << std::endl;
398 }
399 for (int i = 0; i < 4; i++)
400 {
401 prop.Propagate(5, wset, Eshift, 2 * dt, 2);
402 wfn.Energy(wset);
403 ComplexType eav = 0, ov = 0;
404 for (auto it = wset.begin(); it != wset.end(); ++it)
405 {
406 eav += *it->weight() * (it->energy());
407 ov += *it->weight();
408 }
409 tot_time += 5 * 2 * dt;
410 wfn.Orthogonalize(wset, true);
411 t1 = Time.elapsed();
412 app_log() << " -- " << i << " " << tot_time << " " << (eav / ov).real() << " Time: " << t1 << std::endl;
413 }
414
415 timer_manager.print(nullptr);
416 }
417 }
418
419 TEST_CASE("propg_fac_shared", "[propagator_factory]")
420 {
421 auto world = boost::mpi3::environment::get_world_instance();
422 if (not world.root())
423 infoLog.pause();
424 auto node = world.split_shared(world.rank());
425
426 #if defined(ENABLE_CUDA) || defined(ENABLE_HIP)
427 arch::INIT(node);
428 #endif
429 setup_memory_managers(node, 10uL * 1024uL * 1024uL);
430
431 propg_fac_shared(world);
432 release_memory_managers();
433 }
434
435 TEST_CASE("propg_fac_distributed", "[propagator_factory]")
436 {
437 auto world = boost::mpi3::environment::get_world_instance();
438 if (not world.root())
439 infoLog.pause();
440 auto node = world.split_shared(world.rank());
441
442 #if defined(ENABLE_CUDA) || defined(ENABLE_HIP)
443 int ngrp(world.size());
444 arch::INIT(node);
445 #else
446 int ngrp(world.size() / node.size());
447 #endif
448 setup_memory_managers(node, 10uL * 1024uL * 1024uL);
449
450 propg_fac_distributed(world, ngrp);
451 release_memory_managers();
452 }
453
454 } // namespace qmcplusplus
455