MADNESS 0.10.1
key.h
Go to the documentation of this file.
1/*
2 This file is part of MADNESS.
3
4 Copyright (C) 2007,2010 Oak Ridge National Laboratory
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 For more information please contact:
21
22 Robert J. Harrison
23 Oak Ridge National Laboratory
24 One Bethel Valley Road
25 P.O. Box 2008, MS-6367
26
27 email: harrisonrj@ornl.gov
28 tel: 865-241-3937
29 fax: 865-572-0680
30*/
31
32#ifndef MADNESS_MRA_KEY_H__INCLUDED
33#define MADNESS_MRA_KEY_H__INCLUDED
34
35/// \file key.h
36/// \brief Multidimension Key for MRA tree and associated iterators
37
38#include <madness/mra/bc.h>
39#include <madness/mra/power.h>
44
45#include <algorithm>
46#include <climits> // CHAR_BIT
47#include <cstdint>
48#include <optional>
49
50namespace madness {
51
52 // // this has problems when nproc is a large-ish power of 2 such as 256
53 // // and leads to bad data distribution.
54 // static inline unsigned int sdbm(int n, const unsigned char* c, unsigned int sum=0) {
55 // for (int i=0; i<n; ++i) sum = c[i] + (sum << 6) + (sum << 16) - sum;
56 // return sum;
57 // }
58
59 typedef int64_t Translation;
60 typedef int Level;
61
62 template<std::size_t NDIM>
63 class KeyChildIterator;
64
65 /// Key is the index for a node of the 2^NDIM-tree
66
67 /// See KeyChildIterator for facile generation of children,
68 /// and foreach_child(parent,op) for facile application of operators
69 /// to child keys.
70 template<std::size_t NDIM>
71 class Key {
72 public:
73// static const typename Vector<Translation,NDIM>::size_type static_size = Vector<Translation,NDIM>::static_size;
74 static const std::size_t static_size = NDIM;
75
76 private:
77 friend class KeyChildIterator<NDIM> ;
78 Level n = 0;
81
82
83 public:
84
85 /// Default constructor makes an initialized key
86 Key() : n(0), l(0), hashval(0) {}
87
88 /// Constructor with given n, l
90 {
91 MADNESS_ASSERT(n >= 0 && size_t(n) < sizeof(Translation)*CHAR_BIT);
92 rehash();
93 }
94
95 /// Constructor with given n and l=0
96 Key(int n) : n(n), l(0)
97 {
98 MADNESS_ASSERT(n >= 0 && size_t(n) < sizeof(Translation)*CHAR_BIT);
99 rehash();
100 }
101
102 // /// easy constructor ... UGH !!!!!!!!!!!!!!!!!!!!!!
103 // Key(const int n, const int l0, const int l1, const int l2) : n(n) {
104 // MADNESS_ASSERT(NDIM==3);
105 // l=Vector<Translation, NDIM>(0);
106 // l[0]=l0; l[1]=l1; l[2]=l2;
107 // rehash();
108 // }
109
110 /// Returns an invalid key
112 Key<NDIM> result;
113 result.n = -1;
114 result.l = 0;
115 result.rehash();
116 return result;
117 }
118
119 /// Checks if a key is invalid
120 bool is_invalid() const {
121 return n == -1;
122 }
123
124 /// Checks if a key is valid
125 bool is_valid() const {
126 return n != -1;
127 }
128
129 /// Equality test
130 bool operator==(const Key& other) const {
131 if (hashval != other.hashval) return false;
132 if (n != other.n) return false;
133 for (unsigned int i=0; i<NDIM; i++)
134 if (l[i] != other.l[i]) return false;
135 return true; // everything is equal
136 }
137
138 bool operator!=(const Key& other) const {
139 return !(*this == other);
140 }
141
142 /// Comparison operator less than to enable storage in STL map
143 bool operator<(const Key& other) const {
144 if (hashval < other.hashval) return true;
145 if (hashval > other.hashval) return false;
146
147 if (n < other.n) return true;
148 if (n > other.n) return false;
149
150 for (unsigned int i=0; i<NDIM; i++) {
151 if (l[i] < other.l[i]) return true;
152 if (l[i] > other.l[i]) return false;
153 }
154
155 return false; // everything is equal
156 }
157
158 inline hashT
159 hash() const {
160 return hashval;
161 }
162
163 // template<typename Archive>
164 // inline void
165 // serialize(Archive& ar) {
166 // ar & archive::wrap((unsigned char*) this, sizeof(*this));
167 // }
168
169 Level
170 level() const {
171 return n;
172 }
173
175 translation() const {
176 return l;
177 }
178
179 /// const accessor to elements of this->translation()
180 const Translation& operator[](std::size_t d) const {
181 return l[d];
182 }
183
184 uint64_t
185 distsq() const {
186 uint64_t dist = 0;
187 for (std::size_t d = 0; d < NDIM; ++d) {
188 dist += l[d] * l[d];
189 }
190 return dist;
191 }
192
193 // The distance of a displacement in real space.
194 double real_distsq(const madness::Tensor<double>& widths) const {
195 double dist = 0;
196 for (std::size_t d = 0; d < NDIM; ++d) {
197 // Subtract 1 to account for the least distance between points in the boxes.
198 const auto least_displacement_distance = std::max(std::abs(l[d]) - 1, static_cast<Translation>(0));
199 const auto real_width = widths(d) * least_displacement_distance;
200 dist += real_width * real_width;
201 }
202 return dist;
203 }
204
205 /// like distsq() but accounts for periodicity
206 uint64_t distsq_bc(const array_of_bools<NDIM>& is_periodic) const {
207 const Translation twonm1 = (Translation(1) << level()) >> 1;
208
209 uint64_t dsq = 0;
210 for (std::size_t d = 0; d < NDIM; ++d) {
211 Translation la = translation()[d];
212 if (is_periodic[d]) {
213 if (la > twonm1) {
214 la -= twonm1 * 2;
215 MADNESS_ASSERT(la <= twonm1);
216 }
217 if (la < -twonm1) {
218 la += twonm1 * 2;
219 MADNESS_ASSERT(la >= -twonm1);
220 }
221 }
222 dsq += la * la;
223 }
224
225 return dsq;
226 }
227
228 /// like real_distsq() but accounts for periodicity
229 double real_distsq_bc(const array_of_bools<NDIM>& is_periodic, const Tensor<double>& widths) const {
230 const Translation twonm1 = (Translation(1) << level()) >> 1;
231
232 double dsq = 0;
233 for (std::size_t d = 0; d < NDIM; ++d) {
234 Translation la = translation()[d];
235 if (is_periodic[d]) {
236 if (la > twonm1) {
237 la -= twonm1 * 2;
238 MADNESS_ASSERT(la <= twonm1);
239 }
240 if (la < -twonm1) {
241 la += twonm1 * 2;
242 MADNESS_ASSERT(la >= -twonm1);
243 }
244 }
245 // Subtract 1 to account for the least distance between points in the boxes.
246 const auto least_displacement_distance = std::max(std::abs(la) - 1, static_cast<Translation>(0));
247 const auto real_width = widths(d) * least_displacement_distance;
248 dsq += real_width * real_width;
249 }
250
251 return dsq;
252 }
253
254 /// like distsq_bc() but to the nearest lattice image other than the home cell
255
256 /// The rest-of-crystal kernel (OperatorInfo::images_only) at displacement l sums the free-space
257 /// kernel at l + R 2^n over the lattice vectors R != 0 of the periodic axes, so it decays with this
258 /// distance as an ordinary lattice-summed kernel decays with distsq_bc().
259 /// @note saturates: each axis contributes at most distsq_images_axis_max(), since from level 31 on the
260 /// offset to the next-nearest image (~2^n boxes) squared does not fit; real_distsq_images() does not
261 uint64_t distsq_images(const array_of_bools<NDIM>& is_periodic) const {
262 return distsq_images_impl(is_periodic, [](std::size_t, Translation la) -> uint64_t {
263 const uint64_t a = std::min(la < 0 ? uint64_t(0) - uint64_t(la) : uint64_t(la), distsq_images_axis_cap);
264 return a * a;
265 });
266 }
267
268 /// the largest contribution of one axis to distsq_images(); NDIM <= 6 of them sum below 2^63
270
271 /// like real_distsq_bc() but to the nearest lattice image other than the home cell (see distsq_images())
272 double real_distsq_images(const array_of_bools<NDIM>& is_periodic, const Tensor<double>& widths) const {
273 return distsq_images_impl(is_periodic, [&](std::size_t d, Translation la) -> double {
274 // Subtract 1 to account for the least distance between points in the boxes.
275 const auto real_width = widths(d) * std::max(std::abs(la) - 1, static_cast<Translation>(0));
276 return real_width * real_width;
277 });
278 }
279
280 /// like real_distsq_images() but between the centers of the boxes
281
282 /// real_distsq_images() is the least distance between points of the two boxes, which is zero for every
283 /// displacement one box from an image whatever the axis. The center distance is the axis width there, so
284 /// it tells those displacements apart (Displacements::sort_displacements_images breaks ties with it).
285 double real_distsq_images_centers(const array_of_bools<NDIM>& is_periodic, const Tensor<double>& widths) const {
286 return distsq_images_impl(is_periodic, [&](std::size_t d, Translation la) -> double {
287 const double real_width = widths(static_cast<long>(d)) * static_cast<double>(la);
288 return real_width * real_width;
289 });
290 }
291
292 private:
293 static constexpr uint64_t distsq_images_axis_cap = uint64_t(1) << 30; ///< |l| in boxes at which distsq_images() saturates
294
295 /// min over R != 0 of sum_d axis_distsq(d, l_d + R_d 2^n), R_d = 0 along nonperiodic axes. The sum is
296 /// separable, so the minimum takes the nearest image on every axis (as distsq_bc() does) unless that is
297 /// R = 0 on every periodic axis; then exactly one periodic axis moves to its next-nearest image, the
298 /// one that costs least.
299 template <typename F>
300 auto distsq_images_impl(const array_of_bools<NDIM>& is_periodic, F&& axis_distsq) const {
301 using T = decltype(axis_distsq(std::size_t(0), Translation(0)));
302 const Translation twon = Translation(1) << level();
303 const Translation twonm1 = twon >> 1;
304 T dsq = 0;
305 bool wrapped = false;
306 std::optional<T> step; // least cost of moving one periodic axis off R = 0
307 for (std::size_t d = 0; d < NDIM; ++d) {
308 Translation la = translation()[d];
309 if (is_periodic[d]) {
310 // reduce to the nearest image; one step suffices for |l| < 2^n, which is all Displacements
311 // produces, the loop makes the function correct for any l
312 if (la > twonm1) { do la -= twon; while (la > twonm1); wrapped = true; }
313 else if (la < -twonm1) { do la += twon; while (la < -twonm1); wrapped = true; }
314 else {
315 const T s = axis_distsq(d, la > 0 ? la - twon : la + twon) - axis_distsq(d, la);
316 if (!step || s < *step) step = s;
317 }
318 }
319 dsq += axis_distsq(d, la);
320 }
321 if (!wrapped) {
322 MADNESS_CHECK_THROW(step.has_value(), "Key::distsq_images: no axis is periodic, so there are no images");
323 dsq += *step;
324 }
325 return dsq;
326 }
327
328 public:
329 /// like "periodic" distsq() but only selects the prescribed axes
330 template <std::size_t NDIM2>
331 std::enable_if_t<NDIM >= NDIM2, uint64_t>
332 distsq_bc(const array_of_bools<NDIM>& is_periodic, const std::array<std::size_t, NDIM2>& axes) const {
333 const Translation twonm1 = (Translation(1) << level()) >> 1;
334
335 uint64_t dsq = 0;
336 for (std::size_t a = 0; a < NDIM2; ++a) {
337 const auto d = axes[a];
339 Translation la = translation()[d];
340 if (is_periodic[d]) {
341 if (la > twonm1) {
342 la -= twonm1 * 2;
343 MADNESS_ASSERT(la <= twonm1);
344 }
345 if (la < -twonm1) {
346 la += twonm1 * 2;
347 MADNESS_ASSERT(la >= -twonm1);
348 }
349 }
350 dsq += la * la;
351 }
352
353 return dsq;
354 }
355
356 /// Returns the key of the parent
357
358 /// Default is the immediate parent (generation=1). To get
359 /// the grandparent use generation=2, and similarly for
360 /// great-grandparents.
361 ///
362 /// !! If there is no such parent it quietly returns the
363 /// closest match (which may be self if this is the top of the
364 /// tree).
365 Key
366 parent(int generation = 1) const {
368 if (generation > n)
369 generation = n;
370 for (std::size_t i = 0; i < NDIM; ++i)
371 pl[i] = l[i] >> generation;
372 return Key(n - generation, pl);
373 }
374
375
376 bool
377 is_child_of(const Key& key) const {
378 if (this->n < key.n) {
379 return false; // I can't be child of something lower on the tree
380 }
381 else if (this->n == key.n) {
382 return (*this == key); // I am child of myself
383 }
384 else {
385 Level dn = this->n - key.n;
386 Key mama = this->parent(dn);
387 return (mama == key);
388 }
389 }
390
391
392 bool
393 is_parent_of(const Key& key) const {
394 return (key.is_child_of(*this));
395 }
396
397 /// Assuming keys are at the same level, returns true if displaced by no more than 1 in any direction
398
399 /// Assumes key and this are at the same level
400 bool
401 is_neighbor_of(const Key& key, const array_of_bools<NDIM>& bperiodic) const {
402 Translation dist = 0;
403 Translation TWON1 = (Translation(1)<<n) - 1;
404 for (std::size_t i=0; i<NDIM; ++i)
405 {
406 Translation ll = std::abs(l[i] - key.l[i]);
407 if (bperiodic[i] && ll==TWON1) ll=1;
408 dist = std::max(dist, ll);
409 }
410 return (dist <= 1);
411 }
412
413 /// True iff this box is a neighbor of a point in simulation coordinates
414
415 /// Geometrically: this box's closure overlaps the closed box of
416 /// half-width 1 (one box-width at this level) centered on `simpt`.
417 /// Equivalently, the Chebyshev distance from this box to `simpt`
418 /// (measured in box-widths) is at most 1.
419 ///
420 /// This is the point-argument analogue of the key-vs-key overload
421 /// `is_neighbor_of(Key, bperiodic)`; both express "within one
422 /// box-width" adjacency. It supersedes the legacy idiom
423 /// `simpt2key(simpt, n).is_neighbor_of(*this, ...)`, which was
424 /// asymmetric for points lying on box boundaries because
425 /// `simpt2key` truncates to a single key. The new test reports
426 /// face-, edge-, and corner-coincident points as contained in
427 /// *every* box that shares the face/edge/corner — and therefore
428 /// every neighbor of those boxes is correctly flagged too.
429 ///
430 /// @param[in] simpt point in simulation coordinates
431 /// (in [0,1]^NDIM, modulo 1 in periodic dimensions)
432 /// @param[in] bperiodic per-dimension periodic-boundary flags
433 template <typename T>
434 bool
436 const array_of_bools<NDIM>& bperiodic) const {
437 const double twon = std::ldexp(1.0, n); // 2^n
438 const double period = twon; // sim domain has unit length
439 // round-off in d = twon*simpt - l is ~ period * eps; pad by a few
440 // ULPs so points within machine noise of an edge deterministically
441 // count as on it.
442 const double tol = 8.0 * period * std::numeric_limits<double>::epsilon();
443 for (std::size_t i = 0; i < NDIM; ++i) {
444 // signed distance from this box's lower edge, in box-widths
445 double d = twon * static_cast<double>(simpt[i]) - static_cast<double>(l[i]);
446 if (bperiodic[i]) {
447 // fold to the nearest periodic image: d ∈ [-period/2, period/2)
448 d -= period * std::floor((d + 0.5 * period) / period);
449 }
450 if (d < -1.0 - tol || d > 2.0 + tol)
451 return false;
452 }
453 return true;
454 }
455
456 /// given a displacement, generate a neighbor key; ignore boundary conditions and disp's level
457
458 /// @param[in] disp the displacement
459 /// @return a new key
460 Key neighbor(const Key<NDIM>& disp) const {
462 return Key(this->level(),l);
463 }
464
465 /// given a displacement, generate a neighbor key; ignore boundary conditions and disp's level
466
467 /// @param[in] disp the displacement
468 /// @return a new key
471 return Key(this->level(),l);
472 }
473
474
475 /// check if this MultiIndex contains point x, disregarding these two dimensions
476 bool thisKeyContains(const Vector<double,NDIM>& x, const unsigned int& dim0,
477 const unsigned int& dim1) const {
478
479 // it's sufficient if one single dimension is out
480 bool contains=true;
481 const double twotoN = std::pow(2.0,double(n));
482 MADNESS_ASSERT(dim0<NDIM and dim1<NDIM);
483
484 for (unsigned int i=0; i<NDIM; i++ ) {
485
486 // check bounds
487 MADNESS_ASSERT((x[i]>=0.0) and (x[i]<=1.0));
488
489 // leave these two dimensions out
490 if ((i==dim0) or (i==dim1)) continue;
491
492 const int ll=int (x[i]*twotoN);
493 if (not (l[i]==ll)) contains=false;
494 }
495 return contains;
496 }
497
498 /// break key into two low-dimensional keys
499 template<std::size_t LDIM, std::size_t KDIM>
500 void break_apart(Key<LDIM>& key1, Key<KDIM>& key2) const {
501
502 // if LDIM==NDIM the 2nd key will be constructed empty
503 // static_assert((LDIM+KDIM==NDIM) or (LDIM==NDIM));
506 if constexpr((LDIM+KDIM==NDIM) or (LDIM==NDIM)) {
507 for (size_t i=0; i<LDIM; ++i) {
508 l1[i]=l[i];
509 }
510 for (size_t i=LDIM; i<NDIM; ++i) {
511 l2[i-LDIM]=l[i];
512 }
513
514 key1=Key<LDIM>(n,l1);
515 key2=Key<KDIM>(n,l2);
516 } else {
517 MADNESS_EXCEPTION("Key::break_apart: LDIM+KDIM must equal NDIM or LDIM==NDIM",1);
518 }
519 }
520
521 /// extract a new key consisting of first VDIM dimensions of this
522 template<std::size_t VDIM>
524 static_assert(VDIM <= NDIM, "VDIM must be less than or equal to NDIM");
526 for (size_t i = 0; i < VDIM; ++i) t[i] = this->translation()[i];
527 return Key<VDIM>(this->level(),t);
528 }
529
530 /// extract a new key consisting of last VDIM dimensions of this
531 template<std::size_t VDIM>
533 static_assert(VDIM <= NDIM, "VDIM must be less than or equal to NDIM");
535 for (size_t i = 0; i < VDIM; ++i) t[i] = this->translation()[NDIM-VDIM+i];
536 return Key<VDIM>(this->level(),t);
537 }
538
539 /// extract a new key with the Translations indicated in the v array
540 template<std::size_t VDIM>
541 Key<VDIM> extract_key(const std::array<int,VDIM>& v) const {
543 for (size_t i = 0; i < VDIM; ++i) t[i] = this->translation()[v[i]];
544 return Key<VDIM>(this->level(),t);
545 };
546
547 /// extract a new key with the Translations complementary to the ones indicated in the v array
548 template<std::size_t VDIM>
549 Key<NDIM-VDIM> extract_complement_key(const std::array<int,VDIM>& v) const {
550
551 // return the complement of v, e.g. v={0,1}, v_complement={2,3,4} if NDIM==5
552 // v must be contiguous and ascending (i.e. 1,2,3 or 2,3,4)
553 auto v_complement = [](const std::array<int, VDIM>& v) {
554 std::array<int, NDIM - VDIM> result;
555 for (std::size_t i = 0; i < NDIM - VDIM; i++) result[i] = (v.back() + i + 1) % NDIM;
556 return result;
557 };
558 return extract_key(v_complement(v));
559 };
560
561 /// merge with other key (ie concatenate), use level of rhs, not of this
562 template<std::size_t LDIM>
565 if constexpr (NDIM > 0) for (size_t i=0; i<NDIM; ++i) t[i] =this->l[i];
566 if constexpr (LDIM > 0) for (size_t i=0; i<LDIM; ++i) t[NDIM+i]=rhs.translation()[i];
567 return Key<NDIM+LDIM>(rhs.level(),t);
568 }
569
570 /// return if the other key is pointing in the same direction and is farther out
571
572 /// unlike in distsq() the direction is taken into account, and other must be
573 /// longer than this in each dimension
574 /// @param[in] other a key
575 /// @return if other is farther out
576 bool is_farther_out_than(const Key<NDIM>& other) const {
577 for (size_t i=0; i<NDIM; ++i) {
578 if ((other.translation()[i]>0) and (other.translation()[i]>l[i])) return false;
579 if ((other.translation()[i]<0) and (other.translation()[i]<l[i])) return false;
580 }
581 return true;
582 }
583
584
585 /// Recomputes hashval ... presently only done when reading from external storage
586 void
588 //hashval = sdbm(sizeof(n)+sizeof(l), (unsigned char*)(&n));
589 // default hash is still best
590
593 }
594 };
595
596 template<std::size_t NDIM>
597 std::ostream&
598 operator<<(std::ostream& s, const Key<NDIM>& key) {
599 s << "(" << key.level() << "," << key.translation() << ")";
600 return s;
601 }
602
603 /// given a source and a target, return the displacement in translation
604
605 /// @param[in] source the source key
606 /// @param[in] target the target key
607 /// @return disp such that target = source + disp
608 template<size_t NDIM>
610 MADNESS_ASSERT(source.level()==target.level());
611 const Vector<Translation,NDIM> l = target.translation()-source.translation();
612 return Key<NDIM>(source.level(),l);
613 }
614
615
616
617 /// Iterates in lexical order thru all children of a key
618
619 /// Example usage:
620 /// \code
621 /// for (KeyChildIterator<NDIM> it(key); it; ++it) print(it.key());
622 /// \endcode
623 template<std::size_t NDIM>
629
630 public:
632 p(0), finished(true) {
633 }
634
636 parent(parent), child(parent.n + 1, parent.l * 2), p(0),
637 finished(false) {
638 }
639
640 /// Pre-increment of an iterator (i.e., ++it)
643 if (finished)
644 return *this;
645 std::size_t i;
646 for (i = 0; i < NDIM; ++i) {
647 if (p[i] == 0) {
648 ++(p[i]);
649 ++(child.l[i]);
650 for (std::size_t j = 0; j < i; ++j) {
651 --(p[j]);
652 --(child.l[j]);
653 }
654 break;
655 }
656 }
657 finished = (i == NDIM);
658 child.rehash();
659 return *this;
660 }
661
662 /// True if iterator is not at end
663 operator bool() const {
664 return !finished;
665 }
666
667 template<typename Archive>
668 inline void
669 serialize(Archive& ar) {
670 ar & archive::wrap((unsigned char*) this, sizeof(*this));
671 }
672
673 /// Returns the key of the child
674 inline const Key<NDIM>&
675 key() const {
676 return child;
677 }
678 };
679
680 /// Applies op(key) to each child key of parent
681 template<std::size_t NDIM, typename opT>
682 inline void
683 foreach_child(const Key<NDIM>& parent, opT& op) {
685 it(parent); it; ++it)
686 op(it.key());
687 }
688
689 /// Applies member function of obj to each child key of parent
690 template<std::size_t NDIM, typename objT>
691 inline void
692 foreach_child(const Key<NDIM>& parent, objT* obj, void
693 (objT::*memfun)(const Key<NDIM>&)) {
695 it(parent); it; ++it)
696 (obj ->* memfun)(it.key());
697 }
698
699 namespace archive {
700
701 // For efficiency serialize opaque so is just one memcpy, but
702 // when reading from external storage rehash() so that we
703 // can read data even if hash algorithm/function has changed.
704
705 template <class Archive, std::size_t NDIM>
706 struct ArchiveLoadImpl< Archive, Key<NDIM> > {
707 static void load(const Archive& ar, Key<NDIM>& t) {
708 ar & archive::wrap((unsigned char*) &t, sizeof(t));
709 }
710 };
711
712 template <std::size_t NDIM>
714 static void load(const BinaryFstreamInputArchive& ar, Key<NDIM>& t) {
715 ar & archive::wrap((unsigned char*) &t, sizeof(t));
716 t.rehash(); // <<<<<<<<<< This is the point
717 }
718 };
719
720 template <class Archive, std::size_t NDIM>
721 struct ArchiveStoreImpl< Archive, Key<NDIM> > {
722 static void store(const Archive& ar, const Key<NDIM>& t) {
723 ar & archive::wrap((unsigned char*) &t, sizeof(t));
724 }
725 };
726 }
727
728}
729
730#endif // MADNESS_MRA_KEY_H__INCLUDED
731
Provides BoundaryConditions.
Implements an archive wrapping a binary filestream.
simple class for testing the solver
Definition derivatives.cc:60
Iterates in lexical order thru all children of a key.
Definition key.h:624
Vector< Translation, NDIM > p
Definition key.h:627
KeyChildIterator(const Key< NDIM > &parent)
Definition key.h:635
bool finished
Definition key.h:628
const Key< NDIM > & key() const
Returns the key of the child.
Definition key.h:675
KeyChildIterator()
Definition key.h:631
Key< NDIM > child
Definition key.h:626
Key< NDIM > parent
Definition key.h:625
void serialize(Archive &ar)
Definition key.h:669
KeyChildIterator & operator++()
Pre-increment of an iterator (i.e., ++it).
Definition key.h:642
Key is the index for a node of the 2^NDIM-tree.
Definition key.h:71
std::enable_if_t< NDIM >=NDIM2, uint64_t > distsq_bc(const array_of_bools< NDIM > &is_periodic, const std::array< std::size_t, NDIM2 > &axes) const
like "periodic" distsq() but only selects the prescribed axes
Definition key.h:332
double real_distsq_images_centers(const array_of_bools< NDIM > &is_periodic, const Tensor< double > &widths) const
like real_distsq_images() but between the centers of the boxes
Definition key.h:285
Key< VDIM > extract_back() const
extract a new key consisting of last VDIM dimensions of this
Definition key.h:532
Key< NDIM+LDIM > merge_with(const Key< LDIM > &rhs) const
merge with other key (ie concatenate), use level of rhs, not of this
Definition key.h:563
Level level() const
Definition key.h:170
uint64_t distsq_images(const array_of_bools< NDIM > &is_periodic) const
like distsq_bc() but to the nearest lattice image other than the home cell
Definition key.h:261
uint64_t distsq_bc(const array_of_bools< NDIM > &is_periodic) const
like distsq() but accounts for periodicity
Definition key.h:206
bool is_farther_out_than(const Key< NDIM > &other) const
return if the other key is pointing in the same direction and is farther out
Definition key.h:576
Vector< Translation, NDIM > l
Definition key.h:79
double real_distsq(const madness::Tensor< double > &widths) const
Definition key.h:194
Key neighbor(const Vector< Translation, NDIM > &disp) const
given a displacement, generate a neighbor key; ignore boundary conditions and disp's level
Definition key.h:469
Key(int n)
Constructor with given n and l=0.
Definition key.h:96
static constexpr uint64_t distsq_images_axis_max()
the largest contribution of one axis to distsq_images(); NDIM <= 6 of them sum below 2^63
Definition key.h:269
Key(Level n, const Vector< Translation, NDIM > &l)
Constructor with given n, l.
Definition key.h:89
bool is_parent_of(const Key &key) const
Definition key.h:393
double real_distsq_images(const array_of_bools< NDIM > &is_periodic, const Tensor< double > &widths) const
like real_distsq_bc() but to the nearest lattice image other than the home cell (see distsq_images())
Definition key.h:272
bool is_neighbor_of(const Key &key, const array_of_bools< NDIM > &bperiodic) const
Assuming keys are at the same level, returns true if displaced by no more than 1 in any direction.
Definition key.h:401
Key()
Default constructor makes an initialized key.
Definition key.h:86
bool is_valid() const
Checks if a key is valid.
Definition key.h:125
hashT hash() const
Definition key.h:159
bool thisKeyContains(const Vector< double, NDIM > &x, const unsigned int &dim0, const unsigned int &dim1) const
check if this MultiIndex contains point x, disregarding these two dimensions
Definition key.h:476
bool is_invalid() const
Checks if a key is invalid.
Definition key.h:120
bool operator==(const Key &other) const
Equality test.
Definition key.h:130
auto distsq_images_impl(const array_of_bools< NDIM > &is_periodic, F &&axis_distsq) const
Definition key.h:300
const Translation & operator[](std::size_t d) const
const accessor to elements of this->translation()
Definition key.h:180
Level n
Definition key.h:78
static constexpr uint64_t distsq_images_axis_cap
Definition key.h:293
static const std::size_t static_size
Definition key.h:74
bool operator!=(const Key &other) const
Definition key.h:138
Key< NDIM-VDIM > extract_complement_key(const std::array< int, VDIM > &v) const
extract a new key with the Translations complementary to the ones indicated in the v array
Definition key.h:549
Key< VDIM > extract_front() const
extract a new key consisting of first VDIM dimensions of this
Definition key.h:523
double real_distsq_bc(const array_of_bools< NDIM > &is_periodic, const Tensor< double > &widths) const
like real_distsq() but accounts for periodicity
Definition key.h:229
Key< VDIM > extract_key(const std::array< int, VDIM > &v) const
extract a new key with the Translations indicated in the v array
Definition key.h:541
bool is_neighbor_of(const Vector< T, NDIM > &simpt, const array_of_bools< NDIM > &bperiodic) const
True iff this box is a neighbor of a point in simulation coordinates.
Definition key.h:435
hashT hashval
Definition key.h:80
Key parent(int generation=1) const
Returns the key of the parent.
Definition key.h:366
void rehash()
Recomputes hashval ... presently only done when reading from external storage.
Definition key.h:587
const Vector< Translation, NDIM > & translation() const
Definition key.h:175
bool operator<(const Key &other) const
Comparison operator less than to enable storage in STL map.
Definition key.h:143
static Key< NDIM > invalid()
Returns an invalid key.
Definition key.h:111
uint64_t distsq() const
Definition key.h:185
Key neighbor(const Key< NDIM > &disp) const
given a displacement, generate a neighbor key; ignore boundary conditions and disp's level
Definition key.h:460
bool is_child_of(const Key &key) const
Definition key.h:377
void break_apart(Key< LDIM > &key1, Key< KDIM > &key2) const
break key into two low-dimensional keys
Definition key.h:500
A tensor is a multidimensional array.
Definition tensor.h:313
A simple, fixed dimension vector.
Definition vector.h:64
Wraps an archive around a binary filestream for input.
Definition binary_fstream_archive.h:104
syntactic sugar for std::array<bool, N>
Definition array_of_bools.h:19
archive_array< T > wrap(const T *, unsigned int)
Factory function to wrap a dynamically allocated pointer as a typed archive_array.
Definition archive.h:914
static const double v
Definition hatom_sf_dirac.cc:20
Tensor< double > op(const Tensor< double > &x)
Definition kain.cc:508
#define MADNESS_EXCEPTION(msg, value)
Macro for throwing a MADNESS exception.
Definition madness_exception.h:119
#define MADNESS_ASSERT(condition)
Assert a condition that should be free of side-effects since in release builds this might be a no-op.
Definition madness_exception.h:134
#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
Namespace for all elements and tools of MADNESS.
Definition DFConvergence.h:9
std::ostream & operator<<(std::ostream &os, const particle< PDIM > &p)
Definition lowrankfunction.h:452
void hash_combine(hashT &seed, const T &v)
Combine hash values.
Definition worldhash.h:261
int64_t Translation
Definition key.h:59
Key< NDIM > displacement(const Key< NDIM > &source, const Key< NDIM > &target)
given a source and a target, return the displacement in translation
Definition key.h:609
int Level
Definition key.h:60
std::size_t hashT
The hash value type.
Definition worldhash.h:146
void foreach_child(const Key< NDIM > &parent, opT &op)
Applies op(key) to each child key of parent.
Definition key.h:683
madness::hashT hash_value(const std::array< T, N > &a)
Hash std::array with madness hash.
Definition array_addons.h:78
static long abs(long a)
Definition tensor.h:214
static const double d
Definition nonlinschro.cc:121
static const double a
Definition nonlinschro.cc:118
static void load(const Archive &ar, Key< NDIM > &t)
Definition key.h:707
static void load(const BinaryFstreamInputArchive &ar, Key< NDIM > &t)
Definition key.h:714
Default load of an object via serialize(ar, t).
Definition archive.h:667
static void store(const Archive &ar, const Key< NDIM > &t)
Definition key.h:722
Default store of an object via serialize(ar, t).
Definition archive.h:612
Defines and implements most of Tensor.
double dist(const Vector< double, 3 > v1, const Vector< double, 3 > v2)
distance between v1 and v2
Definition test_localizer.cc:38
constexpr std::size_t NDIM
Definition testgconv.cc:54
double source(const coordT &r)
Definition testperiodic.cc:48
Implement the madness:Vector class, an extension of std::array that supports some mathematical operat...
Defines hash functions for use in distributed containers.
FLOAT target(const FLOAT &x)
Definition y.cc:295