20 using Cell = FTypedChebCell<double, Order>;
21 using ParticleContainer = FP2PParticleContainerIndexed<double>;
22 using Leaf = FTypedLeaf<double, ParticleContainer>;
23 using Octree = FOctree<double, Cell, ParticleContainer, Leaf>;
24 using InterpolatedKernel = FChebSymKernel<double, Cell, ParticleContainer, fmm_rbf_kernel, Order>;
25 using Fmm = FFmmAlgorithmThreadTsm<Octree, Cell, ParticleContainer, InterpolatedKernel, Leaf>;
27 static constexpr int FmmAlgorithmScheduleChunkSize = 1;
31 auto a_bbox = bbox.transform(
model.rbf().anisotropy());
32 auto width = 1.01 * a_bbox.size().maxCoeff();
36 auto center = a_bbox.center();
38 interpolated_kernel_ = std::make_unique<InterpolatedKernel>(
39 tree_height, width, FPoint<double>(center.data()), &rbf_kernel_);
41 tree_ = std::make_unique<Octree>(tree_height, std::max(1, tree_height - 4), width,
42 FPoint<double>(center.data()));
44 fmm_ = std::make_unique<Fmm>(tree_.get(), interpolated_kernel_.get(),
45 int{FmmAlgorithmScheduleChunkSize});
48 [[nodiscard]] valuesd evaluate()
const {
49 tree_->forEachLeaf([](Leaf* leaf) {
50 auto& particles = *leaf->getTargets();
51 particles.resetForcesAndPotential();
54 fmm_->execute(FFmmM2L | FFmmL2L | FFmmL2P | FFmmP2P);
60 n_fld_points_ = points.rows();
63 tree_->forEachLeaf([](Leaf* leaf) {
64 auto& particles = *leaf->getTargets();
69 auto a = model_.rbf().anisotropy();
70 for (index_t idx = 0; idx < n_fld_points_; idx++) {
72 tree_->insert(FPoint<double>(ap.data()), FParticleType::FParticleTypeTarget, idx, 0.0);
75 fmm_->updateTargetCells();
77 update_potential_ptrs();
81 n_src_points_ = points.rows();
84 tree_->forEachLeaf([&](Leaf* leaf) {
85 auto& particles = *leaf->getSrc();
90 auto a = model_.rbf().anisotropy();
91 for (index_t idx = 0; idx < n_src_points_; idx++) {
93 tree_->insert(FPoint<double>(ap.data()), FParticleType::FParticleTypeSource, idx, 0.0);
100 const Eigen::Ref<const valuesd>& weights) {
101 RSMESH_ASSERT(weights.rows() == points.rows());
103 n_src_points_ = points.rows();
106 tree_->forEachLeaf([&](Leaf* leaf) {
107 auto& particles = *leaf->getSrc();
112 auto a = model_.rbf().anisotropy();
113 for (index_t idx = 0; idx < n_src_points_; idx++) {
115 tree_->insert(FPoint<double>(ap.data()), FParticleType::FParticleTypeSource, idx,
119 tree_->forEachCell([&](Cell* cell) { cell->resetToInitialState(); });
121 fmm_->execute(FFmmP2M | FFmmM2M);
123 weight_ptrs_.clear();
126 void set_weights(
const Eigen::Ref<const valuesd>& weights) {
127 RSMESH_ASSERT(weights.rows() == n_src_points_);
129 if (n_src_points_ == 0) {
133 if (weight_ptrs_.empty()) {
134 update_weight_ptrs();
137 for (index_t idx = 0; idx < n_src_points_; idx++) {
138 *weight_ptrs_.at(idx) = weights(idx);
141 tree_->forEachCell([](Cell* cell) { cell->resetToInitialState(); });
143 fmm_->execute(FFmmP2M | FFmmM2M);
147 [[nodiscard]] valuesd potentials()
const {
148 valuesd phi = valuesd::Zero(n_fld_points_);
150 for (index_t i = 0; i < n_fld_points_; i++) {
151 phi(i) = *potential_ptrs_.at(i);
157 void update_potential_ptrs() {
158 potential_ptrs_.resize(n_fld_points_);
159 tree_->forEachLeaf([&](Leaf* leaf) {
160 const auto& particles = *leaf->getTargets();
162 const auto& indices = particles.getIndexes();
163 const double* potentials = particles.getPotentials();
165 auto n_particles =
static_cast<index_t
>(particles.getNbParticles());
166 for (index_t i = 0; i < n_particles; i++) {
167 auto idx =
static_cast<index_t
>(indices[i]);
169 potential_ptrs_.at(idx) = &potentials[i];
174 void update_weight_ptrs() {
175 weight_ptrs_.resize(n_src_points_);
176 tree_->forEachLeaf([&](Leaf* leaf) {
177 auto& particles = *leaf->getSrc();
179 const auto& indices = particles.getIndexes();
180 double* weights = particles.getPhysicalValues();
182 auto n_particles =
static_cast<index_t
>(particles.getNbParticles());
183 for (index_t i = 0; i < n_particles; i++) {
184 auto idx =
static_cast<index_t
>(indices[i]);
186 weight_ptrs_.at(idx) = &weights[i];
194 index_t n_src_points_{};
195 index_t n_fld_points_{};
197 std::unique_ptr<Fmm> fmm_;
198 std::unique_ptr<InterpolatedKernel> interpolated_kernel_;
199 std::unique_ptr<Octree> tree_;
201 std::vector<const double*> potential_ptrs_;
202 std::vector<double*> weight_ptrs_;