14#ifndef PECLET_CORE_AMR_BARNES_HUT_HPP
15#define PECLET_CORE_AMR_BARNES_HUT_HPP
17#ifdef PECLET_CORE_HAVE_MORTON
31template <
int Dim = 3,
unsigned Bits = (Dim == 2 ? 32u : (Dim == 3 ? 21u : 16u))>
54 std::vector<int>
cnt(
static_cast<std::size_t
>(octree_.
numLeaves()), 0);
55 for (std::size_t p = 0; p < pos_.size(); ++p)
56 ++
cnt[
static_cast<std::size_t
>(leafOf(p))];
57 std::vector<Code>
split;
59 if (
cnt[
static_cast<std::size_t
>(
i)] > 1 && octree_.
level(
i) > 0)
65 [&](
Code c,
unsigned) {
return std::binary_search(
split.begin(),
split.end(),
c); });
70 leafStart_.assign(
static_cast<std::size_t
>(
nleaf) + 1, 0);
71 std::vector<Index>
ofLeaf(pos_.size());
72 for (std::size_t p = 0; p < pos_.size(); ++p) {
75 ++leafStart_[
static_cast<std::size_t
>(
li) + 1];
78 leafStart_[
static_cast<std::size_t
>(
i) + 1] += leafStart_[
static_cast<std::size_t
>(
i)];
79 leafParts_.assign(pos_.size(), 0);
80 std::vector<Index>
cur(leafStart_.begin(), leafStart_.end() - 1);
81 for (std::size_t p = 0; p < pos_.size(); ++p) {
83 leafParts_[
static_cast<std::size_t
>(
cur[
static_cast<std::size_t
>(
li)]++)] =
84 static_cast<Index>(p);
88 agg_.assign(lmax_ + 1, {});
89 for (std::size_t p = 0; p < pos_.size(); ++p) {
93 for (
unsigned L =
Ll;
L <= lmax_; ++
L) {
94 Code anc = M::from_code(
lo).ancestor(
L).code();
95 Agg&
a = agg_[
L][
anc];
97 for (
int d = 0; d < Dim; ++d)
98 a.com[d] += mass_[p] * pos_[p][d];
111 std::vector<Vec<Dim>>
a(pos_.size());
112 for (std::size_t p = 0; p < pos_.size(); ++p)
120 for (std::size_t
q = 0;
q < pos_.size(); ++
q)
122 addPair(pos_[
static_cast<std::size_t
>(
pi)], pos_[
q], mass_[
q],
a);
131 std::array<double, Dim> com{};
134 std::array<Index, Dim> makeBrick()
const {
135 std::array<Index, Dim> b{};
136 for (
int d = 0; d < Dim; ++d)
141 std::array<Coord, Dim> fineCoord(std::size_t p)
const {
142 std::array<Coord, Dim>
c{};
143 for (
int d = 0; d < Dim; ++d) {
144 long v =
static_cast<long>(std::floor((pos_[p][d] - geo_.origin[d]) / geo_.h0));
147 if (
v >=
static_cast<long>(fineExt_))
148 v =
static_cast<long>(fineExt_) - 1;
153 Index leafOf(std::size_t p)
const {
return octree_.
find(M::encode(fineCoord(p)).code()); }
158 for (
int d = 0; d < Dim; ++d) {
159 dir[d] =
y[d] - x[d];
160 r2 += dir[d] * dir[d];
162 double inv = 1.0 / (
r2 * std::sqrt(
r2));
163 for (
int d = 0; d < Dim; ++d)
164 a[d] += m * dir[d] *
inv;
167 bool isLeafNode(
unsigned L,
Code code,
Index&
li)
const {
173 auto it = agg_[
L].find(code);
174 if (
it == agg_[
L].end())
176 const Agg& g =
it->second;
179 if (isLeafNode(
L, code,
li)) {
180 for (
Index k = leafStart_[
static_cast<std::size_t
>(
li)];
182 Index q = leafParts_[
static_cast<std::size_t
>(k)];
184 addPair(pos_[
static_cast<std::size_t
>(
pi)], pos_[
static_cast<std::size_t
>(
q)],
185 mass_[
static_cast<std::size_t
>(
q)],
a);
191 const Vec<Dim>& x = pos_[
static_cast<std::size_t
>(
pi)];
194 for (
int d = 0; d < Dim; ++d) {
195 com[d] = g.com[d] / g.m;
196 double dd = com[d] - x[d];
199 const double width = geo_.h0 *
static_cast<double>(
Index(1) <<
L);
201 addPair(x, com, g.m,
a);
209 std::vector<Vec<Dim>> pos_;
210 std::vector<double> mass_;
215 double soft2_ = 1
e-6;
216 std::vector<Index> leafStart_;
217 std::vector<Index> leafParts_;
218 std::vector<std::map<Code, Agg>> agg_;
const Octree & octree() const
Vec< Dim > accelerationDirect(Index pi) const
Direct O(N^2) reference acceleration on particle pi (for validation).
void build(const std::vector< Vec< Dim > > &pos, const std::vector< double > &mass, const AmrGeometry< Dim > &geo, unsigned lmax, double theta, double soft=1e-3)
Build the tree from particle positions (+ masses) inside the world box described by geo (origin + h0;...
BlockOctree< Dim, Bits > Octree
Vec< Dim > acceleration(Index pi) const
Approximate acceleration on particle pi.
std::vector< Vec< Dim > > accelerations() const
typename Octree::Coord Coord
typename Octree::Code Code
morton::Morton< Dim, Bits > M
void init(IVec< Dim > brick, unsigned lmax, IVec< Dim > globalOrigin=IVec< Dim >{})
typename M::coord_type Coord
Index refineIf(Pred &&pred)
Split every leaf for which pred(code, level) is true (and level > 0) into its 2^Dim children one leve...
unsigned level(Index i) const
Index find(Code p) const
Leaf containing Morton code p, or -1. Host wrapper over amrLocate.
static constexpr unsigned octants
typename M::code_type Code
Kokkos::View< T *, MemSpace > View
1D device array.
std::int64_t Index
Signed index type for grids and particles (supersedes block_decomposer's long int IndxT).