33#ifndef MADNESS_MRA_DISPLACEMENTS_H__INCLUDED
34#define MADNESS_MRA_DISPLACEMENTS_H__INCLUDED
77 template <std::
size_t NDIM>
80 inline static std::vector< Key<NDIM> >
disp = {};
90 if (
NDIM == 1) bmax = 7;
91 else if (
NDIM == 2) bmax = 5;
92 else if (
NDIM == 3) bmax = 4;
93 else if (
NDIM == 4) bmax = 3;
94 else if (
NDIM == 5) bmax = 3;
95 else if (
NDIM == 6) bmax = 3;
117 return key.translation() < other.
key.translation();
122 std::vector<DispEntry> entries;
123 entries.reserve(
d.size());
124 for (
const auto&
k :
d) {
125 entries.push_back({
k,
k.real_distsq(
w),
k.distsq()});
127 std::sort(entries.begin(), entries.end());
128 for (std::size_t i = 0; i <
d.size(); ++i) {
129 d[i] = entries[i].key;
134 std::vector<DispEntry> entries;
135 entries.reserve(
d.size());
136 for (
const auto&
k :
d) {
137 entries.push_back({
k,
k.real_distsq_bc(paxes,
w),
k.distsq_bc(paxes)});
139 std::sort(entries.begin(), entries.end());
140 for (std::size_t i = 0; i <
d.size(); ++i) {
141 d[i] = entries[i].key;
150 for (std::size_t i=0; i<
NDIM; ++i) num *= (2*bmax + 1);
155 for (
d[0]=-bmax;
d[0]<=bmax; ++
d[0])
158 else if (
NDIM == 2) {
159 for (
d[0]=-bmax;
d[0]<=bmax; ++
d[0])
160 for (
d[1]=-bmax;
d[1]<=bmax; ++
d[1])
163 else if (
NDIM == 3) {
164 for (
d[0]=-bmax;
d[0]<=bmax; ++
d[0])
165 for (
d[1]=-bmax;
d[1]<=bmax; ++
d[1])
166 for (
d[2]=-bmax;
d[2]<=bmax; ++
d[2])
169 else if (
NDIM == 4) {
170 for (
d[0]=-bmax;
d[0]<=bmax; ++
d[0])
171 for (
d[1]=-bmax;
d[1]<=bmax; ++
d[1])
172 for (
d[2]=-bmax;
d[2]<=bmax; ++
d[2])
173 for (
d[3]=-bmax;
d[3]<=bmax; ++
d[3])
176 else if (
NDIM == 5) {
177 for (
d[0]=-bmax;
d[0]<=bmax; ++
d[0])
178 for (
d[1]=-bmax;
d[1]<=bmax; ++
d[1])
179 for (
d[2]=-bmax;
d[2]<=bmax; ++
d[2])
180 for (
d[3]=-bmax;
d[3]<=bmax; ++
d[3])
181 for (
d[4]=-bmax;
d[4]<=bmax; ++
d[4])
185 else if (
NDIM == 6) {
186 for (
d[0]=-bmax;
d[0]<=bmax; ++
d[0])
187 for (
d[1]=-bmax;
d[1]<=bmax; ++
d[1])
188 for (
d[2]=-bmax;
d[2]<=bmax; ++
d[2])
189 for (
d[3]=-bmax;
d[3]<=bmax; ++
d[3])
190 for (
d[4]=-bmax;
d[4]<=bmax; ++
d[4])
191 for (
d[5]=-bmax;
d[5]<=bmax; ++
d[5])
205 if (bmax > (twon-1)) bmax=twon-1;
208 std::vector<Translation> bp(4*bmax+1);
209 std::vector<Translation> bnp(2*bmax+1);
214 if ((lx < 0) && (lx+twon > bmax)) bp[ip++] = lx + twon;
215 if ((lx > 0) && (lx-twon <-bmax)) bp[ip++] = lx - twon;
221 const int nbnp = inp;
228 for(
size_t i=0; i!=
NDIM; ++i) {
233 for (std::size_t i=0; i<
NDIM; ++i) {
266 if constexpr (
NDIM <= 3) {
284 if (kernel_lattice_sum_axes.
any()) {
287 if ((kernel_lattice_sum_axes &&
periodic_axes) != kernel_lattice_sum_axes) {
289 "Displacements<" + std::to_string(
NDIM) +
290 ">::get_disp(level, kernel_lattice_sum_axes): kernel_lattice_sum_axes is set for some axes that were not periodic in the FunctionDefault's boundary conditions active at the time when Displacements were initialized; invoke Displacements<NDIM>::reset_periodic_axes(kernel_lattice_sum_axes) to rebuild the periodic displacements";
326 for (
Level n = 0; n < nmax; ++n)
341 bool changed =
false;
342 for (std::size_t i = 0; !changed && i !=
NDIM; ++i) changed =
widths(i) != width(i);
343 if (!changed)
return;
348 for (
size_t n = 0; n < 64; ++n) {
356 template <std::
size_t N, std::
size_t M>
357 constexpr std::enable_if_t<N>=M, std::array<std::size_t,
N-M>>
iota_array(std::array<std::size_t, M> values_to_skip_sorted) {
358 std::array<std::size_t,
N - M> result;
359 if constexpr (
N != M) {
360 std::size_t nadded = 0;
361 auto value_to_skip_it = values_to_skip_sorted.begin();
362 assert(*value_to_skip_it <
N);
363 auto value_to_skip = *value_to_skip_it;
364 for (std::size_t i = 0; i <
N; ++i) {
365 if (i < value_to_skip) {
366 result[nadded++] = i;
367 }
else if (value_to_skip_it != values_to_skip_sorted.end()) {
369 if (value_to_skip_it != values_to_skip_sorted.end()) {
370 value_to_skip = *value_to_skip_it;
389 template <std::
size_t NDIM>
398 template <
size_t NDIM>
414 std::optional<Reach>
reach = {}
419 for (
size_t i = 0; i <
NDIM; i++) {
422 }
else if (is_infinite_domain[i]) {
428 MADNESS_CHECK_THROW(
reach_->cell_width[i] > 0,
"BoxSurfaceDisplacementValidator: cell widths in StandardDisplacementsReach must be positive");
460 const auto twon = (
static_cast<Translation>(1) << level);
463 const auto map_to_range_twon = [&,
mask = level == 0 ? std::uint64_t(0) : ((~(
static_cast<std::uint64_t
>(0)) << (64-level)) >> (64-level))](std::int64_t x) -> std::int64_t {
464 const std::int64_t x_mapped = x &
mask;
469 const auto out_of_domain = [&](
const Translation& t) ->
bool {
470 return t < 0 || t >= twon;
474 const bool dest_is_in_domain = [&]() {
475 for(
size_t d=0;
d!=
NDIM; ++
d) {
481 if (dest_is_in_domain) {
489 bool among_standard_displacements =
true;
490 for(
size_t d=0;
d!=
NDIM; ++
d) {
491 const auto disp_d = (*displacement)[
d];
499 auto disp_d_eff_abs =
std::abs(disp_d);
502 const std::int64_t disp_d_eff = map_to_range_twon(disp_d);
503 disp_d_eff_abs = std::min(disp_d_eff,
std::abs(disp_d_eff-twon));
507 if (dest[
d].has_value()) {
509 const auto dest_d_in_cell = map_to_range_twon(dest_d);
513 auto t = (*displacement).translation();
514 t[
d] += (dest_d_in_cell - dest_d);
519 if (disp_d_eff_abs > bmax_standard) {
520 among_standard_displacements =
false;
525 if (among_standard_displacements) {
550 template<std::
size_t NDIM>
561 using Box = std::array<std::pair<Translation, Translation>,
NDIM>;
589 mutable std::optional<Displacement>
disp;
640 auto increment_along_dim = [
this](
size_t dim) {
649 for (
size_t i =
NDIM; i > 0; --i) {
650 const size_t cur_dim = i - 1;
654 increment_along_dim(cur_dim);
663 const auto filtered_out = [&,
this]() {
665 const auto& validator = this->parent->
validator_;
669 std::optional<Displacement> nulldisp;
670 result = !(*validator)(
point.level(), point_pattern, nulldisp);
686 bool has_layer =
true;
687 for (
size_t i = 0; i <
NDIM; ++i) {
736 const auto filtered_out = [&]() ->
bool {
741 while (!
done && filtered_out()) {
751 const auto is_fixed_dim = dim ==
fixed_dim;
770 l_dim_min = std::max(
parent->
box_[dim].second -
782 const auto filtered_out = [&,
this]() {
784 const auto& validator = this->parent->
validator_;
788 std::optional<Displacement> nulldisp;
789 result = !(*validator)(
point.level(), point_pattern, nulldisp);
794 if (filtered_out()) {
795 bool have_another_surface_layer;
800 return have_another_surface_layer;
884 if (
a.done &&
b.done)
return true;
885 if (
a.done ||
b.done)
return false;
886 return a.fixed_dim ==
b.fixed_dim &&
922 std::optional<Validator> validator = {})
926 for (
size_t d=0;
d!=
NDIM; ++
d)
928 "BoxSurfaceDisplacementRange: validator and range disagree on which axes are lattice summed");
931 bool has_finite_dimensions =
false;
932 const auto n =
center_.level();
934 for (
size_t d=0;
d!=
NDIM; ++
d) {
938 r = (n == 0) ? (r+1)/2 : (r *
Translation(1) << (n-1));
941 has_finite_dimensions =
true;
947 for (
size_t d=0;
d!=
NDIM; ++
d) {
950 for (
size_t d=0;
d!=
NDIM; ++
d) {
960 : std::pair{
box_[
d].first - t,
box_[
d].second + t};
1076 const auto face_origin_is_center = [
this](
size_t d) {
1083 const auto n =
center_.level();
1086 r = (n == 0) ? (r+1)/2 : (r *
Translation(1) << (n-1));
1088 probing_displacement_vec[face_dimension] = r -
surface_thickness_[face_dimension].value_or(0);
1094 auto& l = probing_displacement_vec[face_dimension];
1095 l = ((l % period) + period) % period;
1096 if (l > period / 2) l -= period;
1101 if (!face_origin_is_center(face_dimension) || n == 0 ||
NDIM == 1)
1122 const auto offset_along = [&](
size_t d) ->
Translation {
1123 const double width = reach.cell_width[
d];
1125 return std::min(std::min(nboxes, bmax) + 1, half_cell);
1128 const auto offset_distance = [&](
size_t d) ->
double {
1129 return reach.cell_width[
d] * (offset_along(
d) - 1);
1135 const auto offset_sort_key = [&](
size_t d) {
1138 size_t offset_dimension =
NDIM;
1139 for (
size_t d=0;
d !=
NDIM; ++
d) {
1140 if (
d == face_dimension)
continue;
1141 if (offset_dimension ==
NDIM || offset_sort_key(
d) < offset_sort_key(offset_dimension))
1142 offset_dimension =
d;
1146 const auto d = offset_dimension;
1151 probing_displacement_vec[
d] =
offset;
1156 const auto sign = right_distance >= left_distance ? +1 : -1;
1157 probing_displacement_vec[
d] = sign *
offset;
double w(double t, double eps)
Definition DKops.h:22
long ndim() const
Returns the number of dimensions in the tensor.
Definition basetensor.h:144
long size() const
Returns the number of elements in the tensor.
Definition basetensor.h:138
Iterator class for lazy generation of surface points.
Definition displacements.h:583
std::optional< Displacement > disp
Memoized displacement from parent->center_ to point, computed by displacement(), reset by advance()
Definition displacements.h:589
Iterator(const BoxSurfaceDisplacementRange *p, Type type)
Constructs an iterator.
Definition displacements.h:831
Type
Definition displacements.h:585
@ End
Definition displacements.h:585
@ Begin
Definition displacements.h:585
size_t fixed_dim
Current fixed dimension (i.e. faces perpendicular to this axis are being iterated over)
Definition displacements.h:590
const std::optional< Displacement > & displacement() const
Definition displacements.h:810
friend bool operator!=(const Iterator &a, const Iterator &b)
Inequality comparison operator.
Definition displacements.h:896
bool done
Flag indicating iteration completion.
Definition displacements.h:599
const Point * pointer
Definition displacements.h:822
pointer operator->() const
Arrow operator for member access.
Definition displacements.h:856
Box unprocessed_bounds
Definition displacements.h:591
Iterator operator++(int)
Post-increment operator.
Definition displacements.h:871
void next_face()
Definition displacements.h:695
std::ptrdiff_t difference_type
Definition displacements.h:821
bool positioned
whether the iterator is positioned on a point that has been (or is about to be) yielded; false until ...
Definition displacements.h:600
std::input_iterator_tag iterator_category
Definition displacements.h:819
const BoxSurfaceDisplacementRange * parent
Pointer to parent surface.
Definition displacements.h:587
bool next_surface_layer()
Definition displacements.h:604
reference operator*() const
Dereferences the iterator.
Definition displacements.h:850
Point value_type
Definition displacements.h:820
void advance_till_valid()
Leave the current point (if positioned on one) and advance to the next point that passes the filter.
Definition displacements.h:731
bool start_face()
Definition displacements.h:685
bool exclude_face(size_t dim)
Definition displacements.h:709
Point point
Current point / box. This is always free to leave the simulation cell.
Definition displacements.h:588
void select_face(size_t from)
Definition displacements.h:723
friend bool operator==(const Iterator &a, const Iterator &b)
Equality comparison operator.
Definition displacements.h:883
Iterator & operator++()
Pre-increment operator.
Definition displacements.h:862
const Point & reference
Definition displacements.h:823
bool reset_along_dim(size_t dim)
Definition displacements.h:750
void advance()
Advances the iterator to the next surface point.
Definition displacements.h:637
Definition displacements.h:551
Box initial_bounds_
bounds of the boxes to be iterated over, before any face is processed: the box plus its surface thick...
Definition displacements.h:570
const Displacement & probing_displacement(size_t face_dimension) const
Definition displacements.h:1017
Key< NDIM > Point
Definition displacements.h:553
const Key< NDIM > & center() const
Definition displacements.h:996
std::array< std::optional< Translation >, NDIM > SurfaceThickness
Definition displacements.h:560
const std::array< std::optional< int64_t >, NDIM > & box_radius() const
Definition displacements.h:1001
const array_of_bools< NDIM > & is_lattice_summed() const
Definition displacements.h:1011
Periodicity is_lattice_summed_
which dimensions are lattice summed?
Definition displacements.h:572
std::array< bool, NDIM > skip_face_
faces excluded from iteration (see skip_face())
Definition displacements.h:575
BoxSurfaceDisplacementRange(const Key< NDIM > ¢er, const std::array< std::optional< std::int64_t >, NDIM > &box_radius, const std::array< std::optional< std::int64_t >, NDIM > &surface_thickness, const array_of_bools< NDIM > &is_lattice_summed, std::optional< Validator > validator={})
Constructs a box with different radii and thicknesses for each dimension.
Definition displacements.h:918
void skip_face(size_t face_dimension)
Definition displacements.h:1037
SurfaceThickness surface_thickness_
surface thickness in each dimension, measured in boxes. Real-space surface size is thus n-dependent.
Definition displacements.h:568
std::array< std::optional< Translation >, NDIM > BoxRadius
Definition displacements.h:559
Displacement compute_probing_displacement(const size_t face_dimension) const
Definition displacements.h:1050
const std::array< std::optional< int64_t >, NDIM > & surface_thickness() const
Definition displacements.h:1006
std::array< std::optional< Displacement >, NDIM > probing_displacements_
for each finite-radius dimension, a displacement to a nearby point on the faces normal to it (the pai...
Definition displacements.h:574
Hollowness hollowness_
does box contain non-surface points along each dimension?
Definition displacements.h:571
auto begin() const
Returns an iterator to the beginning of the surface points.
Definition displacements.h:975
Box box_
box bounds in each dimension.
Definition displacements.h:569
Point center_
Center point of the box.
Definition displacements.h:565
std::optional< Validator > validator_
optional filter; also the source of the reach of the standard displacements, which the probing displa...
Definition displacements.h:573
Key< NDIM > Displacement
Definition displacements.h:555
std::array< bool, NDIM > Hollowness
Definition displacements.h:562
BoxSurfaceDisplacementValidator< NDIM > Validator
Definition displacements.h:556
bool face_skipped(size_t face_dimension) const
Definition displacements.h:1045
auto end() const
Returns an iterator to the end of the surface points.
Definition displacements.h:981
const std::array< std::optional< Displacement >, NDIM > & probing_displacements() const
Definition displacements.h:1026
Vector< std::optional< Translation >, NDIM > PointPattern
Definition displacements.h:554
std::array< std::pair< Translation, Translation >, NDIM > Box
Definition displacements.h:561
BoxRadius box_radius_
halved size of the box in each dimension, in half-SimulationCells.
Definition displacements.h:566
Definition displacements.h:399
array_of_bools< NDIM > is_lattice_summed_
Definition displacements.h:544
std::optional< Reach > reach_
Definition displacements.h:545
Vector< std::optional< Translation >, NDIM > PointPattern
Definition displacements.h:402
Key< NDIM > Displacement
Definition displacements.h:403
std::array< ExtraDomainPolicy, NDIM > domain_policies_
Definition displacements.h:543
Key< NDIM > Point
Definition displacements.h:401
const std::optional< Reach > & reach() const
Definition displacements.h:438
Tensor< double > cell_width_
reach_->cell_width as a Tensor, for Key::real_distsq_bc
Definition displacements.h:546
BoxSurfaceDisplacementValidator(const array_of_bools< NDIM > &is_infinite_domain, const array_of_bools< NDIM > &is_lattice_summed, std::optional< Reach > reach={})
Definition displacements.h:411
bool operator()(const Level level, const PointPattern &dest, std::optional< Displacement > &displacement) const
Apply filter to a displacement ending up at a point or a group of points (point pattern)
Definition displacements.h:454
StandardDisplacementsReach< NDIM > Reach
Definition displacements.h:405
const array_of_bools< NDIM > & is_lattice_summed() const
Definition displacements.h:435
Holds displacements for applying operators to avoid replicating for all operators.
Definition displacements.h:78
static std::array< std::vector< Key< NDIM > >, 64 > disp_periodic
displacements to be used with lattice-summed kernels
Definition displacements.h:82
const std::vector< Key< NDIM > > & get_disp()
return the standard displacements appropriate for operators w/o lattice summation
Definition displacements.h:303
const std::vector< Key< NDIM > > & get_disp(Level n, const array_of_bools< NDIM > &kernel_lattice_sum_axes)
Definition displacements.h:279
static std::vector< Key< NDIM > > disp
standard displacements to be used with standard kernels (range-unrestricted, no lattice sum)
Definition displacements.h:80
static Tensor< double > widths
cell width, used to order displacements from least to most real space distance
Definition displacements.h:83
static void reset_periodic_axes(const array_of_bools< NDIM > &new_periodic_axes)
rebuilds periodic displacements so that they are optimal for the given set of periodic axes
Definition displacements.h:317
static void make_disp(int bmax)
Definition displacements.h:145
static void make_disp_periodic(int bmax, Level n)
Definition displacements.h:201
static int bmax_default()
Definition displacements.h:86
static array_of_bools< NDIM > periodic_axes
along which axes lattice summation is performed?
Definition displacements.h:81
static void set_width(const Tensor< double > &width)
Definition displacements.h:336
static void sort_displacements(std::vector< Key< NDIM > > &d, const Tensor< double > &w)
Definition displacements.h:121
Displacements()
Definition displacements.h:256
static void sort_displacements_periodic(std::vector< Key< NDIM > > &d, const array_of_bools< NDIM > &paxes, const Tensor< double > &w)
Definition displacements.h:133
FunctionDefaults holds default paramaters as static class members.
Definition funcdefaults.h:101
Key is the index for a node of the 2^NDIM-tree.
Definition key.h:70
A tensor is a multidimensional array.
Definition tensor.h:318
float_scalar_type normf() const
Returns the Frobenius norm of the tensor.
Definition tensor.h:1727
A simple, fixed dimension vector.
Definition vector.h:64
syntactic sugar for std::array<bool, N>
Definition array_of_bools.h:19
bool any() const
Definition array_of_bools.h:38
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition derivatives.cc:72
real_function_3d mask
Definition dirac-hatom.cc:27
Provides FunctionDefaults and utilities for coordinate transformation.
#define MADNESS_PRAGMA_CLANG(x)
Definition madness_config.h:200
#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
ExtraDomainPolicy
Definition displacements.h:65
int64_t Translation
Definition key.h:58
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:533
int Level
Definition key.h:59
static double pop(std::vector< double > &v)
Definition SCF.cc:117
constexpr std::array< std::size_t, N-M > iota_array(std::array< std::size_t, M > values_to_skip_sorted)
Definition displacements.h:357
std::string type(const PairType &n)
Definition PNOParameters.h:18
bool same_displacement_shell(double a, double b)
Definition displacements.h:60
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:2233
static long abs(long a)
Definition tensor.h:219
static const double b
Definition nonlinschro.cc:119
static const double d
Definition nonlinschro.cc:121
static const double a
Definition nonlinschro.cc:118
static const long k
Definition rk.cc:44
Definition displacements.h:109
double real_distsq
Definition displacements.h:111
Key< NDIM > key
Definition displacements.h:110
bool operator<(const DispEntry &other) const
Definition displacements.h:114
uint64_t distsq
Definition displacements.h:112
Definition displacements.h:390
std::array< double, NDIM > cell_width
real-space width of the simulation cell along each axis, as used to compute max_distsq
Definition displacements.h:392
double max_distsq
max real distance squared reached by the standard displacements (see Key::real_distsq_bc)
Definition displacements.h:391
Defines and implements most of Tensor.
void e()
Definition test_sig.cc:75
#define N
Definition testconv.cc:37
const double offset
Definition testfuns.cc:143
constexpr std::size_t NDIM
Definition testgconv.cc:54