libMesh
radial_basis_interpolation.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 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 // C++ includes
21 #include <iomanip>
22 
23 // Local includes
24 #include "libmesh/radial_basis_interpolation.h"
25 #include "libmesh/radial_basis_functions.h"
26 #include "libmesh/mesh_tools.h" // BoundingBox
27 #include "libmesh/libmesh_logging.h"
28 #include "libmesh/eigen_core_support.h"
29 
30 #ifdef LIBMESH_HAVE_EIGEN
31 # include "libmesh/ignore_warnings.h"
32 # include <Eigen/Dense>
33 # include "libmesh/restore_warnings.h"
34 #endif
35 
36 
37 namespace libMesh
38 {
39 //--------------------------------------------------------------------------------
40 // RadialBasisInterpolation methods
41 template <unsigned int KDDim, class RBF>
43 {
44  // Call base class clear method
46 }
47 
48 
49 
50 template <unsigned int KDDim, class RBF>
52 {
53  // Call base class methods for prep
56 
57 #ifndef LIBMESH_HAVE_EIGEN
58 
59  libmesh_error_msg("ERROR: this functionality presently requires Eigen!");
60 
61 #else
62  LOG_SCOPE ("prepare_for_use()", "RadialBasisInterpolation<>");
63 
64  // Construct a bounding box for our source points
65  _src_bbox.invalidate();
66 
67  const std::size_t n_src_pts = this->_src_pts.size();
68  const unsigned int n_vars = this->n_field_variables();
69  libmesh_assert_equal_to (this->_src_vals.size(), n_src_pts*this->n_field_variables());
70 
71  {
72  Point
73  &p_min(_src_bbox.min()),
74  &p_max(_src_bbox.max());
75 
76  for (std::size_t p=0; p<n_src_pts; p++)
77  {
78  const Point & p_src(_src_pts[p]);
79 
80  for (unsigned int d=0; d<LIBMESH_DIM; d++)
81  {
82  p_min(d) = std::min(p_min(d), p_src(d));
83  p_max(d) = std::max(p_max(d), p_src(d));
84  }
85  }
86  }
87 
88  libMesh::out << "bounding box is \n"
89  << _src_bbox.min() << '\n'
90  << _src_bbox.max() << std::endl;
91 
92 
93  // Construct the Radial Basis Function, giving it the size of the domain
94  if (_r_override < 0)
95  _r_bbox = (_src_bbox.max() - _src_bbox.min()).norm();
96  else
97  _r_bbox = _r_override;
98 
99  RBF rbf(_r_bbox);
100 
101  libMesh::out << "bounding box is \n"
102  << _src_bbox.min() << '\n'
103  << _src_bbox.max() << '\n'
104  << "r_bbox = " << _r_bbox << '\n'
105  << "rbf(r_bbox/2) = " << rbf(_r_bbox/2) << std::endl;
106 
107 
108  // Construct the projection Matrix
109  typedef Eigen::Matrix<Number, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> DynamicMatrix;
110  //typedef Eigen::Matrix<Number, Eigen::Dynamic, 1, Eigen::ColMajor> DynamicVector;
111 
112  DynamicMatrix A(n_src_pts, n_src_pts), x(n_src_pts,n_vars), b(n_src_pts,n_vars);
113 
114  for (std::size_t i=0; i<n_src_pts; i++)
115  {
116  const Point & x_i (_src_pts[i]);
117 
118  // Diagonal
119  A(i,i) = rbf(0.);
120 
121  for (std::size_t j=i+1; j<n_src_pts; j++)
122  {
123  const Point & x_j (_src_pts[j]);
124 
125  const Real r_ij = (x_j - x_i).norm();
126 
127  A(i,j) = A(j,i) = rbf(r_ij);
128  }
129 
130  // set source data
131  for (unsigned int var=0; var<n_vars; var++)
132  b(i,var) = _src_vals[i*n_vars + var];
133  }
134 
135 
136  // Solve the linear system
137  x = A.ldlt().solve(b);
138  //x = A.fullPivLu().solve(b);
139 
140  // save the weights for each variable
141  _weights.resize (this->_src_vals.size());
142 
143  for (std::size_t i=0; i<n_src_pts; i++)
144  for (unsigned int var=0; var<n_vars; var++)
145  _weights[i*n_vars + var] = x(i,var);
146 
147 #endif
148 
149 }
150 
151 
152 
153 template <unsigned int KDDim, class RBF>
154 void RadialBasisInterpolation<KDDim,RBF>::interpolate_field_data (const std::vector<std::string> & field_names,
155  const std::vector<Point> & tgt_pts,
156  std::vector<Number> & tgt_vals) const
157 {
158  LOG_SCOPE ("interpolate_field_data()", "RadialBasisInterpolation<>");
159 
160  libmesh_experimental();
161 
162  const unsigned int
163  n_vars = this->n_field_variables();
164 
165  const std::size_t
166  n_src_pts = this->_src_pts.size(),
167  n_tgt_pts = tgt_pts.size();
168 
169  libmesh_assert_equal_to (_weights.size(), this->_src_vals.size());
170  libmesh_assert_equal_to (field_names.size(), this->n_field_variables());
171 
172  // If we already have field variables, we assume we are appending.
173  // that means the names and ordering better be identical!
174  if (this->_names.size() != field_names.size())
175  libmesh_error_msg("ERROR: when adding field data to an existing list the \nvariable list must be the same!");
176 
177  for (std::size_t v=0; v<this->_names.size(); v++)
178  if (_names[v] != field_names[v])
179  libmesh_error_msg("ERROR: when adding field data to an existing list the \nvariable list must be the same!");
180 
181 
182  RBF rbf(_r_bbox);
183 
184  tgt_vals.resize (n_tgt_pts*n_vars); std::fill (tgt_vals.begin(), tgt_vals.end(), Number(0.));
185 
186  for (std::size_t tgt=0; tgt<n_tgt_pts; tgt++)
187  {
188  const Point & p (tgt_pts[tgt]);
189 
190  for (std::size_t i=0; i<n_src_pts; i++)
191  {
192  const Point & x_i(_src_pts[i]);
193  const Real
194  r_i = (p - x_i).norm(),
195  phi_i = rbf(r_i);
196 
197  for (unsigned int var=0; var<n_vars; var++)
198  tgt_vals[tgt*n_vars + var] += _weights[i*n_vars + var]*phi_i;
199  }
200  }
201 }
202 
203 
204 
205 // ------------------------------------------------------------
206 // Explicit Instantiations
211 
212 } // namespace libMesh
libMesh::Number
Real Number
Definition: libmesh_common.h:195
libMesh::InverseDistanceInterpolation::clear
virtual void clear() override
Clears all internal data structures and restores to a pristine state.
Definition: meshfree_interpolation.C:176
n_vars
unsigned int n_vars
Definition: adaptivity_ex3.C:116
libMesh::MeshfreeInterpolation::prepare_for_use
virtual void prepare_for_use()
Prepares data structures for use.
Definition: meshfree_interpolation.C:110
libMesh::RadialBasisInterpolation::prepare_for_use
virtual void prepare_for_use() override
Prepares data structures for use.
Definition: radial_basis_interpolation.C:51
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::RadialBasisInterpolation::interpolate_field_data
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.
Definition: radial_basis_interpolation.C:154
libMesh::RadialBasisInterpolation::clear
virtual void clear() override
Clears all internal data structures and restores to a pristine state.
Definition: radial_basis_interpolation.C:42
libMesh::Point
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38
A
static PetscErrorCode Mat * A
Definition: petscdmlibmeshimpl.C:1026
libMesh::InverseDistanceInterpolation::construct_kd_tree
virtual void construct_kd_tree()
Build & initialize the KD tree, if needed.
Definition: meshfree_interpolation.C:154
std::norm
MetaPhysicL::DualNumber< T, D > norm(const MetaPhysicL::DualNumber< T, D > &in)
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::RadialBasisInterpolation
Radial Basis Function interpolation.
Definition: radial_basis_interpolation.h:43
libMesh::out
OStreamProxy out