libMesh
Loading...
Searching...
No Matches
radial_basis_interpolation.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18
19
20// Local includes
21#include "libmesh/radial_basis_interpolation.h"
22
23#include "libmesh/eigen_core_support.h"
24#include "libmesh/int_range.h"
25#include "libmesh/libmesh_logging.h"
26#include "libmesh/mesh_tools.h" // BoundingBox
27#include "libmesh/radial_basis_functions.h"
28
29#ifdef LIBMESH_HAVE_EIGEN
30# include "libmesh/ignore_warnings.h"
31# include <Eigen/Dense>
32# include "libmesh/restore_warnings.h"
33#endif
34
35// C++ includes
36#include <iomanip>
37
38
39namespace libMesh
40{
41//--------------------------------------------------------------------------------
42// RadialBasisInterpolation methods
43template <unsigned int KDDim, class RBF>
45{
46 // Call base class clear method
48}
49
50
51
52template <unsigned int KDDim, class RBF>
54{
55 // Call base class methods for prep
58
59#ifndef LIBMESH_HAVE_EIGEN
60
61 libmesh_error_msg("ERROR: this functionality presently requires Eigen!");
62
63#else
64 LOG_SCOPE ("prepare_for_use()", "RadialBasisInterpolation<>");
65
66 // Construct a bounding box for our source points
67 _src_bbox.invalidate();
68
69 const std::size_t n_src_pts = this->_src_pts.size();
70 const unsigned int n_vars = this->n_field_variables();
71 libmesh_assert_equal_to (this->_src_vals.size(), n_src_pts*this->n_field_variables());
72
73 {
74 LOG_SCOPE ("prepare_for_use():bbox", "RadialBasisInterpolation<>");
75
76 Point
77 &p_min(_src_bbox.min()),
78 &p_max(_src_bbox.max());
79
80 for (std::size_t p=0; p<n_src_pts; p++)
81 {
82 const Point & p_src(_src_pts[p]);
83
84 for (unsigned int d=0; d<LIBMESH_DIM; d++)
85 {
86 p_min(d) = std::min(p_min(d), p_src(d));
87 p_max(d) = std::max(p_max(d), p_src(d));
88 }
89 }
90 }
91
92 // Debugging code
93 // libMesh::out << "bounding box is \n"
94 // << _src_bbox.min() << '\n'
95 // << _src_bbox.max() << std::endl;
96
97
98 // Construct the Radial Basis Function, giving it the size of the domain
99 if (_r_override < 0)
100 _r_bbox = (_src_bbox.max() - _src_bbox.min()).norm();
101 else
102 _r_bbox = _r_override;
103
104 RBF rbf(_r_bbox);
105
106 // libMesh::out << "bounding box is \n"
107 // << _src_bbox.min() << '\n'
108 // << _src_bbox.max() << '\n'
109 // << "r_bbox = " << _r_bbox << '\n'
110 // << "rbf(r_bbox/2) = " << rbf(_r_bbox/2) << std::endl;
111
112
113 // Construct the projection Matrix
114 typedef Eigen::Matrix<Number, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> DynamicMatrix;
115 //typedef Eigen::Matrix<Number, Eigen::Dynamic, 1, Eigen::ColMajor> DynamicVector;
116
117 DynamicMatrix A(n_src_pts, n_src_pts), x(n_src_pts,n_vars), b(n_src_pts,n_vars);
118
119 {
120 LOG_SCOPE ("prepare_for_use():mat", "RadialBasisInterpolation<>");
121
122 for (std::size_t i=0; i<n_src_pts; i++)
123 {
124 const Point & x_i (_src_pts[i]);
125
126 // Diagonal
127 A(i,i) = rbf(0.);
128
129 for (std::size_t j=i+1; j<n_src_pts; j++)
130 {
131 const Point & x_j (_src_pts[j]);
132
133 const Real r_ij = (x_j - x_i).norm();
134
135 A(i,j) = A(j,i) = rbf(r_ij);
136 }
137
138 // set source data
139 for (unsigned int var=0; var<n_vars; var++)
140 b(i,var) = _src_vals[i*n_vars + var];
141 }
142 }
143
144
145 {
146 LOG_SCOPE ("prepare_for_use():solve", "RadialBasisInterpolation<>");
147
148 // Solve the linear system
149 x = A.ldlt().solve(b);
150 //x = A.fullPivLu().solve(b);
151 }
152
153 // save the weights for each variable
154 _weights.resize (this->_src_vals.size());
155
156 for (std::size_t i=0; i<n_src_pts; i++)
157 for (unsigned int var=0; var<n_vars; var++)
158 _weights[i*n_vars + var] = x(i,var);
159
160#endif
161
162}
163
164
165
166template <unsigned int KDDim, class RBF>
167void RadialBasisInterpolation<KDDim,RBF>::interpolate_field_data (const std::vector<std::string> & field_names,
168 const std::vector<Point> & tgt_pts,
169 std::vector<Number> & tgt_vals) const
170{
171 LOG_SCOPE ("interpolate_field_data()", "RadialBasisInterpolation<>");
172
173 libmesh_experimental();
174
175 const unsigned int
176 n_vars = this->n_field_variables();
177
178 const std::size_t
179 n_src_pts = this->_src_pts.size(),
180 n_tgt_pts = tgt_pts.size();
181
182 libmesh_assert_equal_to (_weights.size(), this->_src_vals.size());
183 libmesh_assert_equal_to (field_names.size(), this->n_field_variables());
184
185 // If we already have field variables, we assume we are appending.
186 // that means the names and ordering better be identical!
187 libmesh_error_msg_if(this->_names.size() != field_names.size(),
188 "ERROR: when adding field data to an existing list the \nvariable list must be the same!");
189
190 for (auto v : index_range(this->_names))
191 libmesh_error_msg_if(_names[v] != field_names[v],
192 "ERROR: when adding field data to an existing list the \nvariable list must be the same!");
193
194
195 RBF rbf(_r_bbox);
196
197 tgt_vals.resize (n_tgt_pts*n_vars); std::fill (tgt_vals.begin(), tgt_vals.end(), Number(0.));
198
199 for (std::size_t tgt=0; tgt<n_tgt_pts; tgt++)
200 {
201 const Point & p (tgt_pts[tgt]);
202
203 for (std::size_t i=0; i<n_src_pts; i++)
204 {
205 const Point & x_i(_src_pts[i]);
206 const Real
207 r_i = (p - x_i).norm(),
208 phi_i = rbf(r_i);
209
210 for (unsigned int var=0; var<n_vars; var++)
211 tgt_vals[tgt*n_vars + var] += _weights[i*n_vars + var]*phi_i;
212 }
213 }
214}
215
216
217
218// ------------------------------------------------------------
219// Explicit Instantiations
220template class LIBMESH_EXPORT RadialBasisInterpolation<3, WendlandRBF<3,0>>;
221template class LIBMESH_EXPORT RadialBasisInterpolation<3, WendlandRBF<3,2>>;
222template class LIBMESH_EXPORT RadialBasisInterpolation<3, WendlandRBF<3,4>>;
223template class LIBMESH_EXPORT RadialBasisInterpolation<3, WendlandRBF<3,8>>;
224
225} // namespace libMesh
unsigned int n_vars
virtual void construct_kd_tree()
Build & initialize the KD tree, if needed.
virtual void clear() override
Clears all internal data structures and restores to a pristine state.
virtual void prepare_for_use()
Prepares data structures for use.
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
Radial Basis Function interpolation.
virtual void clear() override
Clears all internal data structures and restores to a pristine state.
virtual void interpolate_field_data(const std::vector< std::string > &field_names, const std::vector< Point > &tgt_pts, std::vector< Number > &tgt_vals) const override
Interpolate source data at target points.
virtual void prepare_for_use() override
Prepares data structures for use.
static const Real b
The libMesh namespace provides an interface to certain functionality in the library.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition int_range.h:153
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real