24 #include "libmesh/point.h"
25 #include "libmesh/meshfree_interpolation.h"
26 #include "libmesh/libmesh_logging.h"
27 #include "libmesh/parallel.h"
28 #include "libmesh/parallel_algebra.h"
29 #include "libmesh/auto_ptr.h"
38 os <<
"MeshfreeInterpolation"
39 <<
"\n n_source_points()=" <<
_src_pts.size()
45 os <<
" variables = ";
73 const std::vector<Point> & pts,
74 const std::vector<Number> & vals)
76 libmesh_experimental();
77 libmesh_assert_equal_to (field_names.size()*pts.size(), vals.size());
83 if (
_names.size() != field_names.size())
84 libmesh_error_msg(
"ERROR: when adding field data to an existing list the \nvariable list must be the same!");
86 for (std::size_t v=0; v<
_names.size(); v++)
87 if (
_names[v] != field_names[v])
88 libmesh_error_msg(
"ERROR: when adding field data to an existing list the \nvariable list must be the same!");
104 libmesh_assert_equal_to (
_src_vals.size(),
131 #ifndef LIBMESH_HAVE_MPI
139 parallel_object_only();
141 LOG_SCOPE (
"gather_remote_data()",
"MeshfreeInterpolation");
146 #endif // LIBMESH_HAVE_MPI
153 template <
unsigned int KDDim>
156 #ifdef LIBMESH_HAVE_NANOFLANN
158 LOG_SCOPE (
"construct_kd_tree()",
"InverseDistanceInterpolation<>");
161 if (_kd_tree.get() ==
nullptr)
162 _kd_tree = libmesh_make_unique<kd_tree_t>
165 nanoflann::KDTreeSingleIndexAdaptorParams(10 ));
169 _kd_tree->buildIndex();
175 template <
unsigned int KDDim>
178 #ifdef LIBMESH_HAVE_NANOFLANN
181 _kd_tree.reset (
nullptr);
190 template <
unsigned int KDDim>
192 const std::vector<Point> & tgt_pts,
193 std::vector<Number> & tgt_vals)
const
195 libmesh_experimental();
198 #ifdef LIBMESH_HAVE_NANOFLANN
199 if (_kd_tree.get() ==
nullptr)
203 LOG_SCOPE (
"interpolate_field_data()",
"InverseDistanceInterpolation<>");
205 libmesh_assert_equal_to (field_names.size(), this->n_field_variables());
209 if (_names.size() != field_names.size())
210 libmesh_error_msg(
"ERROR: when adding field data to an existing list the \nvariable list must be the same!");
212 for (std::size_t v=0; v<_names.size(); v++)
213 if (_names[v] != field_names[v])
214 libmesh_error_msg(
"ERROR: when adding field data to an existing list the \nvariable list must be the same!");
216 tgt_vals.resize (tgt_pts.size()*this->n_field_variables());
218 #ifdef LIBMESH_HAVE_NANOFLANN
220 std::vector<Number>::iterator out_it = tgt_vals.begin();
222 const size_t num_results = std::min((
size_t) _n_interp_pts, _src_pts.size());
224 std::vector<size_t> ret_index(num_results);
225 std::vector<Real> ret_dist_sqr(num_results);
227 for (
const auto & tgt : tgt_pts)
229 const Real query_pt[] = { tgt(0), tgt(1), tgt(2) };
231 _kd_tree->knnSearch(query_pt, num_results, ret_index.data(), ret_dist_sqr.data());
233 this->interpolate (tgt, ret_index, ret_dist_sqr, out_it);
249 libmesh_error_msg(
"ERROR: This functionality requires the library to be configured with nanoflann support!");
254 template <
unsigned int KDDim>
256 const std::vector<size_t> & src_indices,
257 const std::vector<Real> & src_dist_sqr,
258 std::vector<Number>::iterator & out_it)
const
263 if (!src_dist_sqr.empty())
265 Real min_dist = src_dist_sqr.front();
267 for (
auto i : src_dist_sqr)
270 libmesh_error_msg(i <<
" was less than min_dist = " << min_dist);
278 libmesh_assert_equal_to (src_dist_sqr.size(), src_indices.size());
282 const unsigned int n_fv = this->n_field_variables();
283 _vals.resize(n_fv); std::fill (_vals.begin(), _vals.end(),
Number(0.));
285 Real tot_weight = 0.;
287 std::vector<Real>::const_iterator src_dist_sqr_it=src_dist_sqr.begin();
288 std::vector<size_t>::const_iterator src_idx_it=src_indices.begin();
291 while ((src_dist_sqr_it != src_dist_sqr.end()) &&
292 (src_idx_it != src_indices.end()))
294 libmesh_assert_greater_equal (*src_dist_sqr_it, 0.);
297 dist_sq = std::max(*src_dist_sqr_it, std::numeric_limits<Real>::epsilon()),
302 const std::size_t src_idx = *src_idx_it;
305 for (
unsigned int v=0; v<n_fv; v++)
307 libmesh_assert_less (src_idx*n_fv+v, _src_vals.size());
308 _vals[v] += _src_vals[src_idx*n_fv+v]*
weight;
316 for (
unsigned int v=0; v<n_fv; v++, ++out_it)
318 _vals[v] /= tot_weight;