13#ifndef PECLET_AMR_BARNES_HUT_HPP
14#define PECLET_AMR_BARNES_HUT_HPP
25#include "peclet/core/common/types.hpp"
29template <
int Dim = 3,
unsigned Bits = (Dim == 2 ? 32u : (Dim == 3 ? 21u : 16u))>
52 std::vector<int>
cnt(
static_cast<std::size_t
>(octree_.
numLeaves()), 0);
53 for (std::size_t
p = 0;
p < pos_.size(); ++
p)
54 ++
cnt[
static_cast<std::size_t
>(leafOf(
p))];
55 std::vector<Code>
split;
57 if (
cnt[
static_cast<std::size_t
>(
i)] > 1 && octree_.
level(
i) > 0)
63 [&](
Code c,
unsigned) {
return std::binary_search(
split.begin(),
split.end(),
c); });
68 leafStart_.assign(
static_cast<std::size_t
>(
nleaf) + 1, 0);
69 std::vector<Index>
ofLeaf(pos_.size());
70 for (std::size_t
p = 0;
p < pos_.size(); ++
p) {
73 ++leafStart_[
static_cast<std::size_t
>(
li) + 1];
76 leafStart_[
static_cast<std::size_t
>(
i) + 1] += leafStart_[
static_cast<std::size_t
>(
i)];
77 leafParts_.assign(pos_.size(), 0);
78 std::vector<Index>
cur(leafStart_.begin(), leafStart_.end() - 1);
79 for (std::size_t
p = 0;
p < pos_.size(); ++
p) {
81 leafParts_[
static_cast<std::size_t
>(
cur[
static_cast<std::size_t
>(
li)]++)] =
86 agg_.assign(lmax_ + 1, {});
87 for (std::size_t
p = 0;
p < pos_.size(); ++
p) {
91 for (
unsigned L =
Ll;
L <= lmax_; ++
L) {
92 Code anc = M::from_code(
lo).ancestor(
L).code();
93 Agg&
a = agg_[
L][
anc];
95 for (
int d = 0; d < Dim; ++d)
96 a.com[d] += mass_[
p] * pos_[
p][d];
109 std::vector<Vec<Dim>>
a(pos_.size());
110 for (std::size_t
p = 0;
p < pos_.size(); ++
p)
118 for (std::size_t
q = 0;
q < pos_.size(); ++
q)
120 addPair(pos_[
static_cast<std::size_t
>(
pi)], pos_[
q], mass_[
q],
a);
129 std::array<double, Dim> com{};
132 std::array<Index, Dim> makeBrick()
const {
133 std::array<Index, Dim> b{};
134 for (
int d = 0; d < Dim; ++d)
139 std::array<Coord, Dim> fineCoord(std::size_t
p)
const {
140 std::array<Coord, Dim>
c{};
141 for (
int d = 0; d < Dim; ++d) {
142 long v =
static_cast<long>(std::floor((pos_[
p][d] - geo_.origin[d]) / geo_.h0[d]));
145 if (
v >=
static_cast<long>(fineExt_))
146 v =
static_cast<long>(fineExt_) - 1;
151 Index leafOf(std::size_t
p)
const {
return octree_.
find(M::encode(fineCoord(
p)).code()); }
156 for (
int d = 0; d < Dim; ++d) {
157 dir[d] =
y[d] - x[d];
158 r2 += dir[d] * dir[d];
160 double inv = 1.0 / (
r2 * std::sqrt(
r2));
161 for (
int d = 0; d < Dim; ++d)
162 a[d] += m * dir[d] *
inv;
165 bool isLeafNode(
unsigned L,
Code code,
Index&
li)
const {
171 auto it = agg_[
L].find(code);
174 const Agg& g =
it->second;
177 if (isLeafNode(
L, code,
li)) {
178 for (
Index k = leafStart_[
static_cast<std::size_t
>(
li)];
180 Index q = leafParts_[
static_cast<std::size_t
>(k)];
182 addPair(pos_[
static_cast<std::size_t
>(
pi)], pos_[
static_cast<std::size_t
>(
q)],
183 mass_[
static_cast<std::size_t
>(
q)],
a);
189 const Vec<Dim>& x = pos_[
static_cast<std::size_t
>(
pi)];
192 for (
int d = 0; d < Dim; ++d) {
193 com[d] = g.com[d] / g.m;
194 double dd = com[d] - x[d];
199 const double width = geo_.hMax() *
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_;
Vec< Dim > accelerationDirect(Index pi) const
Direct O(N^2) reference acceleration on particle pi (for validation).
BlockOctree< Dim, Bits > Octree
const Octree & octree() const
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;...
typename Octree::Coord Coord
std::vector< Vec< Dim > > accelerations() const
Vec< Dim > acceleration(Index pi) const
Approximate acceleration on particle pi.
typename Octree::Code Code
Index refineIf(Pred &&pred)
Split every leaf for which pred(code, level) is true (and level > 0) into its 2^Dim children one leve...
morton::Morton< Dim, Bits > M
unsigned level(Index i) const
Index find(Code p) const
Leaf containing Morton code p, or -1. Host wrapper over amrLocate.
void init(IVec< Dim > brick, unsigned lmax, IVec< Dim > globalOrigin=IVec< Dim >{})
typename M::coord_type Coord
typename M::code_type Code
static constexpr unsigned octants
std::vector< std::array< double, Dim > > transferFieldGradients(const BlockOctree< Dim, Bits > &oldT, const std::vector< double > &oldF)
Per-old-leaf minmod prolongation gradients (per fine-coordinate unit) — transferField's stencil,...
World-space placement of a block-local octree: fine coordinate (0,..,0) sits at origin,...