17 using Cell = FChebCell<double, Order>;
18 using ParticleContainer = FP2PParticleContainerIndexed<double>;
19 using Leaf = FSimpleLeaf<double, ParticleContainer>;
20 using Octree = FOctree<double, Cell, ParticleContainer, Leaf>;
21 using InterpolatedKernel = FChebSymKernel<double, Cell, ParticleContainer, fmm_rbf_kernel, Order>;
22 using Fmm = FFmmAlgorithmThread<Octree, Cell, ParticleContainer, InterpolatedKernel, Leaf>;
24 static constexpr int FmmAlgorithmScheduleChunkSize = 1;
29 auto a_bbox = bbox.transform(
model.rbf().anisotropy());
30 auto width = 1.01 * a_bbox.size().maxCoeff();
34 auto center = a_bbox.center();
36 interpolated_kernel_ = std::make_unique<InterpolatedKernel>(
37 tree_height, width, FPoint<double>(center.data()), &rbf_kernel_);
39 tree_ = std::make_unique<Octree>(tree_height, std::max(1, tree_height - 4), width,
40 FPoint<double>(center.data()));
42 fmm_ = std::make_unique<Fmm>(tree_.get(), interpolated_kernel_.get(),
43 int{FmmAlgorithmScheduleChunkSize});
46 valuesd evaluate()
const {
51 auto self_potential = model_.rbf().evaluate_isotropic(geometry::vector3d::Zero());
52 return potentials() + weights_ * self_potential;
56 n_points_ = points.rows();
59 tree_->forEachLeaf([](Leaf* leaf) {
60 auto& particles = *leaf->getSrc();
65 auto a = model_.rbf().anisotropy();
66 for (index_t idx = 0; idx < n_points_; idx++) {
68 tree_->insert(FPoint<double>(ap.data()), idx, 0.0);
72 update_potential_ptrs();
75 void set_weights(
const Eigen::Ref<const valuesd>& weights) {
76 RSMESH_ASSERT(weights.rows() == n_points_);
79 for (index_t idx = 0; idx < n_points_; idx++) {
80 *weight_ptrs_.at(idx) = weights(idx);
87 valuesd potentials()
const {
88 valuesd phi = valuesd::Zero(n_points_);
90 for (index_t i = 0; i < n_points_; i++) {
91 phi(i) = *potential_ptrs_.at(i);
97 void reset_tree()
const {
98 tree_->forEachCell([](Cell* cell) { cell->resetToInitialState(); });
100 tree_->forEachLeaf([](Leaf* leaf) {
101 auto& particles = *leaf->getTargets();
102 particles.resetForcesAndPotential();
106 void update_potential_ptrs() {
107 potential_ptrs_.resize(n_points_);
108 tree_->forEachLeaf([&](Leaf* leaf) {
109 const auto& particles = *leaf->getTargets();
111 const auto& indices = particles.getIndexes();
112 const double* potentials = particles.getPotentials();
114 auto n_particles =
static_cast<index_t
>(particles.getNbParticles());
115 for (index_t i = 0; i < n_particles; i++) {
116 auto idx =
static_cast<index_t
>(indices[i]);
118 potential_ptrs_.at(idx) = &potentials[i];
123 void update_weight_ptrs() {
124 weight_ptrs_.resize(n_points_);
125 tree_->forEachLeaf([&](Leaf* leaf) {
126 auto& particles = *leaf->getSrc();
128 const auto& indices = particles.getIndexes();
129 double* weights = particles.getPhysicalValues();
131 auto n_particles =
static_cast<index_t
>(particles.getNbParticles());
132 for (index_t i = 0; i < n_particles; i++) {
133 auto idx =
static_cast<index_t
>(indices[i]);
135 weight_ptrs_.at(idx) = &weights[i];
146 std::unique_ptr<Fmm> fmm_;
147 std::unique_ptr<InterpolatedKernel> interpolated_kernel_;
148 std::unique_ptr<Octree> tree_;
150 std::vector<const double*> potential_ptrs_;
151 std::vector<double*> weight_ptrs_;