MADNESS 0.10.1
exchangeoperator.h
Go to the documentation of this file.
1#ifndef SRC_APPS_CHEM_EXCHANGEOPERATOR_H_
2#define SRC_APPS_CHEM_EXCHANGEOPERATOR_H_
3
4#include<madness.h>
8
9namespace madness {
10
11// forward declaration
12class SCF;
13class Nemo;
14
15
16template<typename T, std::size_t NDIM>
19 typedef std::vector<functionT> vecfuncT;
20
21 static inline std::atomic<long> apply_timer;
22 static inline std::atomic<long> mul2_timer;
23 static inline std::atomic<long> mul1_timer; ///< timing
24 static inline double elapsed_time;
25
26 static void reset_timer() {
27 mul1_timer = 0l;
28 mul2_timer = 0l;
29 apply_timer = 0l;
30 elapsed_time = 0.0;
31 }
32
33public:
34 nlohmann::json gather_timings(World& world) const {
35 double t1 = double(mul1_timer) * 0.001;
36 double t2 = double(apply_timer) * 0.001;
37 double t3 = double(mul2_timer) * 0.001;
38 world.gop.sum(t1);
39 world.gop.sum(t2);
40 world.gop.sum(t3);
41 nlohmann::json j;
42 j["multiply1"] = t1;
43 j["apply"] = t2;
44 j["multiply2"] = t3;
45 j["total"] = elapsed_time;
46 return j;
47 }
48
49 void print_timer(World& world) const {
50 auto timings= gather_timings(world);
51 if (world.rank() == 0) {
52 printf(" cpu time spent in multiply1 %8.2fs\n", timings["multiply1"].template get<double>());
53 printf(" cpu time spent in apply %8.2fs\n", timings["apply"].template get<double>());
54 printf(" cpu time spent in multiply2 %8.2fs\n", timings["multiply2"].template get<double>());
55 printf(" total wall time %8.2fs\n", timings["total"].template get<double>());
56 }
57 }
58
59
62 MacroTaskInfo macro_task_info = MacroTaskInfo::preset("default");
63
64 /// default ctor
65 ExchangeImpl(World& world, const double lo, const double thresh) : world(world), lo(lo), thresh(thresh) {}
66
67 /// ctor with a conventional calculation
68 ExchangeImpl(World& world, const SCF *calc, const int ispin) ;
69
70 /// ctor with a nemo calculation
71 ExchangeImpl(World& world, const Nemo *nemo, const int ispin);
72
73 /// set the bra and ket orbital spaces, and the occupation
74
75 /// @param[in] bra bra space, must be provided as complex conjugate
76 /// @param[in] ket ket space
77 void set_bra_and_ket(const vecfuncT& bra, const vecfuncT& ket) {
78 mo_bra = copy(world, bra);
79 mo_ket = copy(world, ket);
80 }
81
82 std::string info() const {return "K";}
83
84 static auto set_poisson(World& world, const double lo, const double econv = FunctionDefaults<3>::get_thresh()) {
85 return std::shared_ptr<real_convolution_3d>(CoulombOperatorPtr(world, lo, econv));
86 }
87
88 /// apply the exchange operator on a vector of functions
89
90 /// note that only one spin is used (either alpha or beta orbitals)
91 /// @param[in] vket the orbitals |i> that the operator is applied on
92 /// @return a vector of orbitals K| i>
93 vecfuncT operator()(const vecfuncT& vket) const;
94
95 bool is_symmetric() const { return symmetric_; }
96
97 ExchangeImpl& set_taskq(std::shared_ptr<MacroTaskQ> taskq1) {
98 this->taskq=taskq1;
99 return *this;
100 }
101
103 symmetric_ = flag;
104 return *this;
105 }
106
108 macro_task_info = info;
109 return *this;
110 }
111
112 ExchangeImpl& set_macro_task_info(const std::vector<std::string>& info) {
113 macro_task_info.from_vector_of_strings(info);
114 if (world.rank() == 0 && printdebug()) {
115 print("set macrotaskinfo to");
116 print(macro_task_info);
117 }
118 return *this;
119 }
120
122 algorithm_ = alg;
123 return *this;
124 }
125
126 ExchangeImpl& set_printlevel(const long& level) {
127 printlevel=level;
128 return *this;
129 }
130
131 std::shared_ptr<MacroTaskQ> get_taskq() const {return taskq;}
132
133 World& get_world() const {return world;}
134
135 nlohmann::json get_statistics() const {return statistics;}
136
137 /// return some statistics about the current settings
138 nlohmann::json gather_statistics() const {
139 nlohmann::json j;
140 j["symmetric"] = symmetric_;
141 j["lo"] = lo;
142 j["thresh"] = thresh;
143 j["mul_tol"] = mul_tol;
144 j["printlevel"] = printlevel;
145 j["algorithm"] = to_string(algorithm_);
146 j["macro_task_info"] = macro_task_info.to_json();
147 auto timings = gather_timings(world);
148 j.update(timings);
149 return j;
150 }
151
152private:
153
154 /// exchange using macrotasks, i.e. apply K on a function in individual worlds
155 vecfuncT K_macrotask_efficient(const vecfuncT& vket, const double mul_tol = 0.0) const;
156
157 /// exchange using macrotasks, i.e. apply K on a function in individual worlds row-wise
158 vecfuncT K_macrotask_efficient_row(const vecfuncT& vket, const double mul_tol = 0.0) const;
159
160 /// computing the full square of the double sum (over vket and the K orbitals)
161 vecfuncT K_small_memory(const vecfuncT& vket, const double mul_tol = 0.0) const;
162
163 /// computing the upper triangle of the double sum (over vket and the K orbitals)
164 vecfuncT K_large_memory(const vecfuncT& vket, const double mul_tol = 0.0) const;
165
166 /// computing the upper triangle of the double sum (over vket and the K orbitals)
167 static vecfuncT compute_K_tile(World& world, const vecfuncT& mo_bra, const vecfuncT& mo_ket,
168 const vecfuncT& vket, std::shared_ptr<real_convolution_3d> poisson,
169 const bool symmetric, const double mul_tol = 0.0);
170
171 inline bool printdebug() const {return printlevel >= 10; }
172 inline bool printprogress() const {return (printlevel>=4) and (not (printdebug()));}
173 inline bool printtimings() const {return printlevel>=3;}
174 inline bool printtimings_detail() const {return printlevel>=4;}
175
177 std::shared_ptr<MacroTaskQ> taskq;
178 bool symmetric_ = false; /// is the exchange matrix symmetric? K phi_i = \sum_k \phi_k \int \phi_k \phi_i
179 vecfuncT mo_bra, mo_ket; ///< MOs for bra and ket
180 double lo = 1.e-4;
182 long printlevel = 0;
184
185 mutable nlohmann::json statistics; ///< statistics of the Cloud (timings, memory) and of the parameters of this run
186
188
190 double lo = 1.e-4;
191 double mul_tol = 1.e-7;
192 bool symmetric = false;
193
194 /// custom partitioning for the exchange operator in exchangeoperator.h
195
196 /// arguments are: result[i] += sum_k vket[k] \int 1/r vbra[k] f[i]
197 /// with f and vbra being batched, result and vket being passed on as a whole
199 public:
200 MacroTaskPartitionerExchange(const bool symmetric) : symmetric(symmetric) {
201 max_batch_size=30;
202 }
203
204 bool symmetric = false;
205
206 partitionT do_partitioning(const std::size_t& vsize1, const std::size_t& vsize2,
207 const std::string policy) const override {
208
209 partitionT partition1 = do_1d_partition(vsize1, policy);
210 partitionT partition2 = do_1d_partition(vsize2, policy);
211 partitionT result;
212 for (auto i = partition1.begin(); i != partition1.end(); ++i) {
213 if (symmetric) {
214 for (auto j = i; j != partition1.end(); ++j) {
215 Batch batch(i->first.input[0], j->first.input[0], _);
216 double priority=compute_priority(batch);
217 result.push_back(std::make_pair(batch,priority));
218 }
219 } else {
220 for (auto j = partition2.begin(); j != partition2.end(); ++j) {
221 Batch batch(i->first.input[0], j->first.input[0], _);
222 double priority=compute_priority(batch);
223 result.push_back(std::make_pair(batch,priority));
224 }
225 }
226 }
227 return result;
228 }
229
230 /// compute the priority of this task for non-dumb scheduling
231
232 /// \return the priority as double number (no limits)
233 double compute_priority(const Batch& batch) const override {
234 MADNESS_CHECK(batch.input.size() == 2); // must be quadratic batches
235 long nrow = batch.input[0].size();
236 long ncol = batch.input[1].size();
237 return double(nrow * ncol);
238 }
239 };
240
241 public:
242 MacroTaskExchangeSimple(const long nresult, const double lo, const double mul_tol, const bool symmetric)
243 : nresult(nresult), lo(lo), mul_tol(mul_tol), symmetric(symmetric) {
244 partitioner.reset(new MacroTaskPartitionerExchange(symmetric));
245 }
246
247
248 // you need to define the exact argument(s) of operator() as tuple
249 typedef std::tuple<const std::vector<Function<T, NDIM>>&,
250 const std::vector<Function<T, NDIM>>&,
251 const std::vector<Function<T, NDIM>>&> argtupleT;
252
253 using resultT = std::vector<Function<T, NDIM>>;
254
255 // you need to define an empty constructor for the result
256 // resultT must implement operator+=(const resultT&)
257 resultT allocator(World& world, const argtupleT& argtuple) const {
258 std::size_t n = std::get<0>(argtuple).size();
259 resultT result = zero_functions_compressed<T, NDIM>(world, n);
260 return result;
261 }
262
263 std::vector<Function<T, NDIM>>
264 operator()(const std::vector<Function<T, NDIM>>& vf_batch, // will be batched (column)
265 const std::vector<Function<T, NDIM>>& bra_batch, // will be batched (row)
266 const std::vector<Function<T, NDIM>>& vket) { // will not be batched
267
268 World& world = vf_batch.front().world();
269 resultT Kf = zero_functions_compressed<T, NDIM>(world, nresult);
270
271 bool diagonal_block = batch.input[0] == batch.input[1];
272 auto& bra_range = batch.input[1]; // corresponds to vbra
273 auto& vf_range = batch.input[0]; // corresponds to vf_batch
274
275 if (vf_range.is_full_size()) vf_range.end = vf_batch.size();
276 if (bra_range.is_full_size()) bra_range.end = bra_batch.size();
277
278 MADNESS_CHECK(vf_range.end <= nresult);
279 if (symmetric) MADNESS_CHECK(bra_range.end <= nresult);
280
281 if (symmetric and diagonal_block) {
282 auto ket_batch = bra_range.copy_batch(vket);
283 vecfuncT resultcolumn = compute_diagonal_batch_in_symmetric_matrix(world, ket_batch, bra_batch,
284 vf_batch);
285
286 for (int i = vf_range.begin; i < vf_range.end; ++i){
287 Kf[i] += resultcolumn[i - vf_range.begin];}
288
289 } else if (symmetric and not diagonal_block) {
290 auto[resultcolumn, resultrow]=compute_offdiagonal_batch_in_symmetric_matrix(world, vket, bra_batch,
291 vf_batch);
292
293 for (int i = bra_range.begin; i < bra_range.end; ++i){
294 Kf[i] += resultcolumn[i - bra_range.begin];}
295 for (int i = vf_range.begin; i < vf_range.end; ++i){
296 Kf[i] += resultrow[i - vf_range.begin];}
297 } else {
298 auto ket_batch = bra_range.copy_batch(vket);
299 vecfuncT resultcolumn = compute_batch_in_asymmetric_matrix(world, ket_batch, bra_batch, vf_batch);
300 for (int i = vf_range.begin; i < vf_range.end; ++i)
301 Kf[i] += resultcolumn[i - vf_range.begin];
302 }
303 return Kf;
304 }
305
306 /// compute a batch of the exchange matrix, with identical ranges, exploiting the matrix symmetry
307
308 /// \param subworld the world we're computing in
309 /// \param cloud where to store the results
310 /// \param bra_batch the bra batch of orbitals (including the nuclear correlation factor square)
311 /// \param ket_batch the ket batch of orbitals, i.e. the orbitals to premultiply with
312 /// \param vf_batch the argument of the exchange operator
314 const vecfuncT& ket_batch, // is batched
315 const vecfuncT& bra_batch, // is batched
316 const vecfuncT& vf_batch // is batched
317 ) const {
318 double mul_tol = 0.0;
319 double symmetric = true;
320 auto poisson = Exchange<double, 3>::ExchangeImpl::set_poisson(subworld, lo);
321 return Exchange<T, NDIM>::ExchangeImpl::compute_K_tile(subworld, bra_batch, ket_batch, vf_batch, poisson, symmetric,
322 mul_tol);
323 }
324
325 /// compute a batch of the exchange matrix, with non-identical ranges
326
327 /// \param subworld the world we're computing in
328 /// \param cloud where to store the results
329 /// \param bra_batch the bra batch of orbitals (including the nuclear correlation factor square)
330 /// \param ket_batch the ket batch of orbitals, i.e. the orbitals to premultiply with
331 /// \param vf_batch the argument of the exchange operator
333 const vecfuncT& ket_batch,
334 const vecfuncT& bra_batch,
335 const vecfuncT& vf_batch) const {
336 double mul_tol = 0.0;
337 double symmetric = false;
338 auto poisson = Exchange<double, 3>::ExchangeImpl::set_poisson(subworld, lo);
339 return Exchange<T, NDIM>::ExchangeImpl::compute_K_tile(subworld, bra_batch, ket_batch, vf_batch, poisson, symmetric,
340 mul_tol);
341 }
342
343 /// compute a batch of the exchange matrix, with non-identical ranges
344
345 /// \param subworld the world we're computing in
346 /// \param cloud where to store the results
347 /// \param bra_batch the bra batch of orbitals (including the nuclear correlation factor square)
348 /// \param ket_batch the ket batch of orbitals, i.e. the orbitals to premultiply with
349 /// \param vf_batch the argument of the exchange operator
350 std::pair<vecfuncT, vecfuncT> compute_offdiagonal_batch_in_symmetric_matrix(World& subworld,
351 const vecfuncT& ket, // not batched
352 const vecfuncT& bra_batch, // batched
353 const vecfuncT& vf_batch) const; // batched
354
355 };
356
358
360 double lo = 1.e-4;
361 double mul_tol = 1.e-7;
362 bool symmetric = false;
364
365 /// custom partitioning for the exchange operator in exchangeoperator.h
367 public:
369 max_batch_size=1;
370 }
371 };
372
373 public:
374 MacroTaskExchangeRow(const long nresult, const double lo, const double mul_tol, const Algorithm algorithm)
375 : nresult(nresult), lo(lo), mul_tol(mul_tol), algorithm_(algorithm) {
376 partitioner.reset(new MacroTaskPartitionerRow());
377 name="MacroTaskExchangeRow";
378 }
379
380 // you need to define the exact argument(s) of operator() as tuple
381 typedef std::tuple<const std::vector<Function<T, NDIM>>&,
382 const std::vector<Function<T, NDIM>>&,
383 const std::vector<Function<T, NDIM>>&> argtupleT;
384
385 using resultT = std::vector<Function<T, NDIM>>;
386
387 // you need to define an empty constructor for the result
388 // resultT must implement operator+=(const resultT&)
389 resultT allocator(World& world, const argtupleT& argtuple) const {
390 std::size_t n = std::get<0>(argtuple).size();
391 resultT result = zero_functions_compressed<T, NDIM>(world, n);
392 return result;
393 }
394
395 /// compute exchange row-wise for a fixed orbital phi_i of vket
396
397 /// create 2 worlds: one fetches the function coefficients from the universe, the other
398 /// does the computation, then swap. The result is copied back to the universe
399 std::vector<Function<T, NDIM>>
400 operator()(const std::vector<Function<T, NDIM>>& vket,
401 const std::vector<Function<T, NDIM>>& mo_bra,
402 const std::vector<Function<T, NDIM>>& mo_ket) {
403 std::vector<Function<T,NDIM>> result;
404 if (algorithm_==fetch_compute) {
405 result=row_fetch_compute(vket,mo_bra,mo_ket);
406 } else if (algorithm_==multiworld_efficient_row) {
407 result=row(vket,mo_bra,mo_ket);
408 } else {
409 MADNESS_EXCEPTION("unknown algorithm in Exchange::MacroTaskExchangeRow::operator()",1);
410 }
411 return result;
412 }
413
414 std::vector<Function<T,NDIM>>
415 row(const std::vector<Function<T, NDIM>>& vket,
416 const std::vector<Function<T, NDIM>>& mo_bra,
417 const std::vector<Function<T, NDIM>>& mo_ket) {
418
419 double cpu0, cpu1;
420 World& world = vket.front().world();
421 mul_tol = 0.0;
422
423 resultT Kf = zero_functions_compressed<T, NDIM>(world, 1);
424 vecfuncT psif = zero_functions_compressed<T,NDIM>(world, mo_bra.size());
426
427 // !! NO !! vket is batched, starts at batch.input[0].begin
428 // auto& i = batch.input[0].begin;
429 long i=0;
430 MADNESS_CHECK_THROW(vket.size()==1,"out-of-bounds error in Exchange::MacroTaskExchangeRow::operator()");
431 size_t min_tile = 10;
432 size_t ntile = std::min(mo_bra.size(), min_tile);
433
434 for (size_t ilo=0; ilo<mo_bra.size(); ilo+=ntile){
435 cpu0 = cpu_time();
436 size_t iend = std::min(ilo+ntile,mo_bra.size());
437 vecfuncT tmp_mo_bra(mo_bra.begin()+ilo,mo_bra.begin()+iend);
438 auto tmp_psif = mul_sparse(world, vket[i], tmp_mo_bra, mul_tol);
439 truncate(world, tmp_psif);
440 cpu1 = cpu_time();
441 mul1_timer += long((cpu1 - cpu0) * 1000l);
442
443 cpu0 = cpu_time();
444 tmp_psif = apply(world, *poisson.get(), tmp_psif);
445 truncate(world, tmp_psif);
446 cpu1 = cpu_time();
447 apply_timer += long((cpu1 - cpu0) * 1000l);
448
449 cpu0 = cpu_time();
450 vecfuncT tmp_mo_ket(mo_ket.begin()+ilo,mo_ket.begin()+iend);
451 auto tmp_Kf = dot(world, tmp_mo_ket, tmp_psif);
452 cpu1 = cpu_time();
453 mul2_timer += long((cpu1 - cpu0) * 1000l);
454
455 Kf[0] += tmp_Kf;
456 truncate(world, Kf);
457 }
458
459 return Kf;
460 }
461
462 std::vector<Function<T,NDIM>>
463 row_fetch_compute(const std::vector<Function<T, NDIM>>& vket,
464 const std::vector<Function<T, NDIM>>& mo_bra,
465 const std::vector<Function<T, NDIM>>& mo_ket) {
466
468 double total_execution_time=0.0;
469 double total_fetch_time=0.0;
470 double total_fetch_spawn_time=0.0;
471
472 resultT Kf = zero_functions_compressed<T, NDIM>(*subworld_ptr, 1);
473 {
474 // create the two worlds that will be used for fetching and computing
475 // std::shared_ptr<World> executing_world(subworld_ptr);
476 double cpu0=cpu_time();
477 SafeMPI::Intracomm comm = subworld_ptr->mpi.comm();
478 std::shared_ptr<World> fetching_world(new World(comm.Clone()));
479 std::shared_ptr<World> executing_world(new World(comm.Clone()));
480 double cpu1=cpu_time();
481 print("time to create two worlds:",cpu1-cpu0,"seconds");
482 print("executing_world.id()",executing_world->id(),"fetching_world.id()",fetching_world->id(),"in MacroTaskExchangeRow");
483
484 {
485 auto poisson1 = Exchange<double, 3>::ExchangeImpl::set_poisson(*executing_world, lo);
486 auto poisson2 = Exchange<double, 3>::ExchangeImpl::set_poisson(*fetching_world, lo);
487
488 functionT phi1=copy(*executing_world,vket[0]);
489 functionT phi2=copy(*fetching_world,vket[0]);
490
491 // !! NO !! vket is batched, starts at batch.input[0].begin
492 // auto& i = batch.input[0].begin;
493 MADNESS_CHECK_THROW(vket.size()==1,"out-of-bounds error in Exchange::MacroTaskExchangeRow::operator()");
494 size_t min_tile = 10;
495 size_t ntile = std::min(mo_bra.size(), min_tile);
496
497 struct Tile {
498 size_t ilo;
499 size_t iend;
500 };
501
502
503 // copy the data from the universe bra and ket to subworld bra and ket
504 // returns a pair of vectors in the subworld which are still awaiting the function coefficients
505 auto fetch_data = [&](World& world, const Tile& tile) {
506 MADNESS_CHECK_THROW(mo_bra.size()==mo_ket.size(),
507 "bra and ket size mismatch in Exchange::MacroTaskExchangeRow::execute()");
508
509 std::size_t sz=tile.iend-tile.ilo;
510 vecfuncT subworld_bra(sz);
511 vecfuncT subworld_ket;
512 for (size_t i=tile.ilo; i<tile.iend; ++i) {
513 auto f=copy(world,mo_bra[i],false);
514 subworld_bra[i-tile.ilo]=f;
515 subworld_ket.push_back(copy(world, mo_ket[i],false));
516 }
517 return std::make_pair(subworld_bra,subworld_ket);
518 };
519
520 // apply the exchange operator on phi for a a tile of mo_bra and mo_ket
521 auto execute = [&](World& world, auto poisson, const functionT& phi, const vecfuncT& mo_bra, const vecfuncT& mo_ket) {
522 MADNESS_CHECK_THROW(mo_bra.size()==mo_ket.size(),
523 "bra and ket size mismatch in Exchange::MacroTaskExchangeRow::execute()");
524
525 auto world_id=world.id();
526 auto phi_id=phi.world().id();
527 auto bra_id=mo_bra.front().world().id();
528 auto ket_id=mo_ket.front().world().id();
529 std::string msg="world mismatch in Exchange::MacroTaskExchangeRow::execute(): ";
530 msg+="world.id()="+std::to_string(world_id)+", ";
531 msg+="phi.world().id()="+std::to_string(phi_id)+", ";
532 msg+="bra.world().id()="+std::to_string(bra_id)+", ";
533 msg+="ket.world().id()="+std::to_string(ket_id);
534 if (not (world_id==phi_id && world_id==bra_id && world_id==ket_id)) {
535 print(msg);
536 }
537 MADNESS_CHECK_THROW(world_id==phi_id && world_id==bra_id && world_id==ket_id,msg.c_str());
538
539 double cpu0 = cpu_time();
540 auto tmp_psif = mul_sparse(world, phi, mo_bra, mul_tol);
541 truncate(world, tmp_psif);
542 double cpu1 = cpu_time();
543 mul1_timer += long((cpu1 - cpu0) * 1000l);
544
545 cpu0 = cpu_time();
546 tmp_psif = apply(world, *poisson.get(), tmp_psif);
547 truncate(world, tmp_psif);
548 cpu1 = cpu_time();
549 apply_timer += long((cpu1 - cpu0) * 1000l);
550
551 cpu0 = cpu_time();
552 auto tmp_Kf = dot(world, mo_ket, tmp_psif);
553 cpu1 = cpu_time();
554 mul2_timer += long((cpu1 - cpu0) * 1000l);
555
556 return tmp_Kf.truncate();
557
558 };
559
560 std::vector<Tile> tiles;
561 for (size_t ilo=0; ilo<mo_bra.size(); ilo+=ntile) {
562 tiles.push_back(Tile{ilo,std::min(ilo+ntile,mo_bra.size())});
563 }
564
565 vecfuncT tmp_mo_bra1,tmp_mo_ket1;
566 vecfuncT tmp_mo_bra2,tmp_mo_ket2;
567
568 for (size_t itile=0; itile<tiles.size(); ++itile) {
569 Tile& tile = tiles[itile];
570
571 if (itile==0) {
572 double t0=cpu_time();
573 print("fetching tile",tile.ilo,"into world",executing_world->id());
574 std::tie(tmp_mo_bra1,tmp_mo_ket1)=fetch_data(*executing_world,tiles[itile]);
575 fetching_world->gop.set_forbid_fence(false);
576 double t2=cpu_time();
577 executing_world->gop.fence();
578 double t1=cpu_time();
579 total_fetch_time += (t1 - t0);
580 total_fetch_spawn_time += (t2 - t0);
581 }
582
583 double t0=cpu_time();
584 fetching_world->gop.set_forbid_fence(true);
585 if (itile<tiles.size()-1) {
586 // fetch data into fetching_world while computing in executing_world
587 print("fetching tile",tiles[itile+1].ilo,"into world",fetching_world->id()," at time ",wall_time());
588 std::tie(tmp_mo_bra2,tmp_mo_ket2)=fetch_data(*fetching_world,tiles[itile+1]);
589 }
590 fetching_world->gop.set_forbid_fence(false);
591 double t2=cpu_time();
592 // uncomment the next line to enforce that fetching is finished before executing
593 // fetching_world->gop.fence();
594 double t1=cpu_time();
595 total_fetch_time += (t1 - t0);
596 total_fetch_spawn_time += (t2 - t0);
597
598 print("executing tile",tile.ilo,"in world",executing_world->id());
599 double dpu0=cpu_time();
600 Kf[0]+=execute(*executing_world,poisson1,phi1,tmp_mo_bra1,tmp_mo_ket1);
601 double dpu1=cpu_time();
602 print("time to execute tile",tile.ilo,"in world",executing_world->id(),dpu1-dpu0,"seconds");
603 total_execution_time += dpu1-dpu0;
604
605 fetching_world->gop.fence();
606
607 // change roles of the two worlds
608 std::swap(poisson1,poisson2);
609 std::swap(phi1,phi2);
610 std::swap(tmp_mo_bra2,tmp_mo_bra1);
611 std::swap(tmp_mo_ket2,tmp_mo_ket1);
612 std::swap(executing_world,fetching_world);
613 }
614 } // objects living in the two worlds must be destroyed before the worlds are freed
615
616 // deferred destruction of WorldObjects happens here
617 fetching_world->gop.fence();
618 executing_world->gop.fence();
619 double cpu2=cpu_time();
620 print("overall time: ",cpu2-cpu0,"seconds");
621 print("total execution time:",total_execution_time,"seconds");
622 print("total fetch time:",total_fetch_time,"seconds");
623 print("total fetch spawn time:",total_fetch_spawn_time,"seconds");
624 } // worlds are destroyed here
625
626 return Kf;
627 }
628 };
629};
630
631} /* namespace madness */
632
633#endif /* SRC_APPS_CHEM_EXCHANGEOPERATOR_H_ */
Operators for the molecular HF and DFT code.
Wrapper around MPI_Comm. Has a shallow copy constructor; use Create(Get_group()) for deep copy.
Definition safempi.h:497
Intracomm Clone() const
Definition safempi.h:696
a batch consists of a 2D-input batch and a 1D-output batch: K-batch <- (I-batch, J-batch)
Definition macrotaskpartitioner.h:124
std::vector< Batch_1D > input
Definition macrotaskpartitioner.h:127
custom partitioning for the exchange operator in exchangeoperator.h
Definition exchangeoperator.h:366
resultT allocator(World &world, const argtupleT &argtuple) const
Definition exchangeoperator.h:389
std::vector< Function< T, NDIM > > row_fetch_compute(const std::vector< Function< T, NDIM > > &vket, const std::vector< Function< T, NDIM > > &mo_bra, const std::vector< Function< T, NDIM > > &mo_ket)
Definition exchangeoperator.h:463
std::vector< Function< T, NDIM > > operator()(const std::vector< Function< T, NDIM > > &vket, const std::vector< Function< T, NDIM > > &mo_bra, const std::vector< Function< T, NDIM > > &mo_ket)
compute exchange row-wise for a fixed orbital phi_i of vket
Definition exchangeoperator.h:400
long nresult
Definition exchangeoperator.h:359
std::tuple< const std::vector< Function< T, NDIM > > &, const std::vector< Function< T, NDIM > > &, const std::vector< Function< T, NDIM > > & > argtupleT
Definition exchangeoperator.h:383
std::vector< Function< T, NDIM > > row(const std::vector< Function< T, NDIM > > &vket, const std::vector< Function< T, NDIM > > &mo_bra, const std::vector< Function< T, NDIM > > &mo_ket)
Definition exchangeoperator.h:415
std::vector< Function< T, NDIM > > resultT
Definition exchangeoperator.h:385
Algorithm algorithm_
Definition exchangeoperator.h:363
MacroTaskExchangeRow(const long nresult, const double lo, const double mul_tol, const Algorithm algorithm)
Definition exchangeoperator.h:374
custom partitioning for the exchange operator in exchangeoperator.h
Definition exchangeoperator.h:198
double compute_priority(const Batch &batch) const override
compute the priority of this task for non-dumb scheduling
Definition exchangeoperator.h:233
MacroTaskPartitionerExchange(const bool symmetric)
Definition exchangeoperator.h:200
partitionT do_partitioning(const std::size_t &vsize1, const std::size_t &vsize2, const std::string policy) const override
override this if you want your own partitioning
Definition exchangeoperator.h:206
vecfuncT compute_diagonal_batch_in_symmetric_matrix(World &subworld, const vecfuncT &ket_batch, const vecfuncT &bra_batch, const vecfuncT &vf_batch) const
compute a batch of the exchange matrix, with identical ranges, exploiting the matrix symmetry
Definition exchangeoperator.h:313
MacroTaskExchangeSimple(const long nresult, const double lo, const double mul_tol, const bool symmetric)
Definition exchangeoperator.h:242
long nresult
Definition exchangeoperator.h:189
std::vector< Function< T, NDIM > > resultT
Definition exchangeoperator.h:253
vecfuncT compute_batch_in_asymmetric_matrix(World &subworld, const vecfuncT &ket_batch, const vecfuncT &bra_batch, const vecfuncT &vf_batch) const
compute a batch of the exchange matrix, with non-identical ranges
Definition exchangeoperator.h:332
std::vector< Function< T, NDIM > > operator()(const std::vector< Function< T, NDIM > > &vf_batch, const std::vector< Function< T, NDIM > > &bra_batch, const std::vector< Function< T, NDIM > > &vket)
Definition exchangeoperator.h:264
std::tuple< const std::vector< Function< T, NDIM > > &, const std::vector< Function< T, NDIM > > &, const std::vector< Function< T, NDIM > > & > argtupleT
Definition exchangeoperator.h:251
resultT allocator(World &world, const argtupleT &argtuple) const
Definition exchangeoperator.h:257
Definition exchangeoperator.h:17
static std::atomic< long > mul1_timer
timing
Definition exchangeoperator.h:23
Exchange< T, NDIM >::ExchangeAlgorithm Algorithm
Definition exchangeoperator.h:60
bool printtimings() const
Definition exchangeoperator.h:173
ExchangeImpl & symmetric(const bool flag)
Definition exchangeoperator.h:102
ExchangeImpl & set_printlevel(const long &level)
Definition exchangeoperator.h:126
nlohmann::json statistics
statistics of the Cloud (timings, memory) and of the parameters of this run
Definition exchangeoperator.h:185
static double elapsed_time
Definition exchangeoperator.h:24
void print_timer(World &world) const
Definition exchangeoperator.h:49
World & get_world() const
Definition exchangeoperator.h:133
ExchangeImpl & set_macro_task_info(const std::vector< std::string > &info)
Definition exchangeoperator.h:112
nlohmann::json get_statistics() const
Definition exchangeoperator.h:135
ExchangeImpl & set_macro_task_info(const MacroTaskInfo &info)
Definition exchangeoperator.h:107
static void reset_timer()
Definition exchangeoperator.h:26
vecfuncT mo_bra
is the exchange matrix symmetric? K phi_i = \sum_k \phi_k \int \phi_k \phi_i
Definition exchangeoperator.h:179
World & world
Definition exchangeoperator.h:176
std::shared_ptr< MacroTaskQ > taskq
Definition exchangeoperator.h:177
Function< T, NDIM > functionT
Definition exchangeoperator.h:18
nlohmann::json gather_statistics() const
return some statistics about the current settings
Definition exchangeoperator.h:138
bool is_symmetric() const
Definition exchangeoperator.h:95
ExchangeImpl & set_taskq(std::shared_ptr< MacroTaskQ > taskq1)
Definition exchangeoperator.h:97
std::vector< functionT > vecfuncT
Definition exchangeoperator.h:19
ExchangeImpl & set_algorithm(const Algorithm &alg)
Definition exchangeoperator.h:121
bool printprogress() const
Definition exchangeoperator.h:172
static std::atomic< long > apply_timer
Definition exchangeoperator.h:21
ExchangeImpl(World &world, const double lo, const double thresh)
default ctor
Definition exchangeoperator.h:65
std::string info() const
Definition exchangeoperator.h:82
nlohmann::json gather_timings(World &world) const
Definition exchangeoperator.h:34
bool printtimings_detail() const
Definition exchangeoperator.h:174
bool printdebug() const
Definition exchangeoperator.h:171
std::shared_ptr< MacroTaskQ > get_taskq() const
Definition exchangeoperator.h:131
static auto set_poisson(World &world, const double lo, const double econv=FunctionDefaults< 3 >::get_thresh())
Definition exchangeoperator.h:84
static std::atomic< long > mul2_timer
Definition exchangeoperator.h:22
void set_bra_and_ket(const vecfuncT &bra, const vecfuncT &ket)
set the bra and ket orbital spaces, and the occupation
Definition exchangeoperator.h:77
Definition SCFOperators.h:105
static std::string to_string(const ExchangeAlgorithm alg)
Definition SCFOperators.h:144
ExchangeAlgorithm
Definition SCFOperators.h:117
@ multiworld_efficient_row
Definition SCFOperators.h:118
Function< T, NDIM > operator()(const Function< T, NDIM > &ket) const
Definition SCFOperators.h:198
std::vector< functionT > vecfuncT
Definition SCFOperators.h:111
std::string info() const
print some information about this operator
Definition SCFOperators.h:173
FunctionDefaults holds default paramaters as static class members.
Definition funcdefaults.h:100
static const double & get_thresh()
Returns the default threshold.
Definition funcdefaults.h:177
A multiresolution adaptive numerical function.
Definition mra.h:139
Definition macrotaskq.h:1287
partition one (two) vectors into 1D (2D) batches.
Definition macrotaskpartitioner.h:182
std::list< std::pair< Batch, double > > partitionT
Definition macrotaskpartitioner.h:186
The Nemo class.
Definition nemo.h:327
nlohmann::json statistics
Definition SCFOperators.h:64
std::shared_ptr< MacroTaskQ > taskq
Definition SCFOperators.h:71
Definition SCF.h:190
void sum(T *buf, size_t nelem)
Inplace global sum while still processing AM & tasks.
Definition worldgop.h:890
A parallel world class.
Definition world.h:132
ProcessID rank() const
Returns the process rank in this World (same as MPI_Comm_rank()).
Definition world.h:320
ProcessID size() const
Returns the number of processes in this World (same as MPI_Comm_size()).
Definition world.h:330
unsigned long id() const
Definition world.h:315
WorldGopInterface & gop
Global operations.
Definition world.h:207
Declares the Cloud class for storing data and transfering them between worlds.
double(* f)(const coord_3d &)
Definition derivatives.cc:54
static double lo
Definition dirac-hatom.cc:23
std::vector< Spinor > truncate(std::vector< Spinor > arg)
Definition dirac-hatom.cc:503
Fcwf apply(World &world, real_convolution_3d &op, const Fcwf &psi)
Definition fcwf.cc:281
Fcwf copy(Fcwf psi)
Definition fcwf.cc:338
Declares the macrotaskq and MacroTaskBase classes.
General header file for using MADNESS.
#define MADNESS_CHECK(condition)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition madness_exception.h:182
#define MADNESS_EXCEPTION(msg, value)
Macro for throwing a MADNESS exception.
Definition madness_exception.h:119
#define MADNESS_CHECK_THROW(condition, msg)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition madness_exception.h:207
void print(const tensorT &t)
Definition mcpfit.cc:140
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
Function< TENSOR_RESULT_TYPE(L, R), NDIM > mul_sparse(const Function< L, NDIM > &left, const Function< R, NDIM > &right, double tol, bool fence=true)
Sparse multiplication — left and right must be reconstructed and if tol!=0 have tree of norms already...
Definition mra.h:1911
void print(const T &t, const Ts &... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition print.h:226
Function< TENSOR_RESULT_TYPE(T, R), NDIM > dot(World &world, const std::vector< Function< T, NDIM > > &a, const std::vector< Function< R, NDIM > > &b, bool fence=true)
Multiplies and sums two vectors of functions r = \sum_i a[i] * b[i].
Definition vmra.h:1590
double wall_time()
Returns the wall time in seconds relative to an arbitrary origin.
Definition timers.cc:48
static SeparatedConvolution< double, 3 > * CoulombOperatorPtr(World &world, double lo, double eps, const std::array< LatticeRange, 3 > &lattice_ranges=FunctionDefaults< 3 >::get_bc().lattice_range(), int k=FunctionDefaults< 3 >::get_k())
Factory function generating separated kernel for convolution with 1/r in 3D.
Definition operator.h:1776
static XNonlinearSolver< std::vector< Function< T, NDIM > >, T, vector_function_allocator< T, NDIM > > nonlinear_vector_solver(World &world, const long nvec)
Definition nonlinsol.h:371
std::string name(const FuncType &type, const int ex=-1)
Definition ccpairfunction.h:28
Function< T, NDIM > copy(const Function< T, NDIM > &f, const std::shared_ptr< WorldDCPmapInterface< Key< NDIM > > > &pmap, bool fence=true)
Create a new copy of the function with different distribution and optional fence.
Definition mra.h:2172
static const double thresh
Definition rk.cc:45
Definition macrotaskq.h:280
static MacroTaskInfo preset(const std::string name)
Definition macrotaskq.h:313
nlohmann::json to_json() const
Definition macrotaskq.h:447
void from_vector_of_strings(const std::vector< std::string > &vec)
set policy from a vector of strings, assuming the order is storage policy, cloud distribution policy,...
Definition macrotaskq.h:373
class to temporarily redirect output to cout
Definition print.h:277
double cpu_time()
Definition test_list.cc:43
constexpr std::size_t NDIM
Definition testgconv.cc:54