LCOV - code coverage report
Current view: top level - src/solution_transfer - radial_basis_interpolation.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 58 62 93.5 %
Date: 2025-08-19 19:27:09 Functions: 3 16 18.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 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             : 
      39             : namespace libMesh
      40             : {
      41             : //--------------------------------------------------------------------------------
      42             : // RadialBasisInterpolation methods
      43             : template <unsigned int KDDim, class RBF>
      44           0 : void RadialBasisInterpolation<KDDim,RBF>::clear()
      45             : {
      46             :   // Call base class clear method
      47           0 :   InverseDistanceInterpolation<KDDim>::clear();
      48           0 : }
      49             : 
      50             : 
      51             : 
      52             : template <unsigned int KDDim, class RBF>
      53         142 : void RadialBasisInterpolation<KDDim,RBF>::prepare_for_use()
      54             : {
      55             :   // Call base class methods for prep
      56         142 :   InverseDistanceInterpolation<KDDim>::prepare_for_use();
      57         142 :   InverseDistanceInterpolation<KDDim>::construct_kd_tree();
      58             : 
      59             : #ifndef LIBMESH_HAVE_EIGEN
      60             : 
      61             :   libmesh_error_msg("ERROR: this functionality presently requires Eigen!");
      62             : 
      63             : #else
      64           8 :   LOG_SCOPE ("prepare_for_use()", "RadialBasisInterpolation<>");
      65             : 
      66             :   // Construct a bounding box for our source points
      67           4 :   _src_bbox.invalidate();
      68             : 
      69         146 :   const std::size_t  n_src_pts = this->_src_pts.size();
      70         142 :   const unsigned int n_vars    = this->n_field_variables();
      71           4 :   libmesh_assert_equal_to (this->_src_vals.size(), n_src_pts*this->n_field_variables());
      72             : 
      73             :   {
      74           8 :     LOG_SCOPE ("prepare_for_use():bbox", "RadialBasisInterpolation<>");
      75             : 
      76             :     Point
      77           4 :       &p_min(_src_bbox.min()),
      78           4 :       &p_max(_src_bbox.max());
      79             : 
      80      238063 :     for (std::size_t p=0; p<n_src_pts; p++)
      81             :       {
      82       13404 :         const Point & p_src(_src_pts[p]);
      83             : 
      84      951684 :         for (unsigned int d=0; d<LIBMESH_DIM; d++)
      85             :           {
      86      713763 :             p_min(d) = std::min(p_min(d), p_src(d));
      87      713763 :             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         142 :   if (_r_override < 0)
     100         142 :     _r_bbox = (_src_bbox.max() - _src_bbox.min()).norm();
     101             :   else
     102           0 :     _r_bbox = _r_override;
     103             : 
     104         142 :   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         146 :   DynamicMatrix A(n_src_pts, n_src_pts), x(n_src_pts,n_vars), b(n_src_pts,n_vars);
     118             : 
     119             :   {
     120           8 :   LOG_SCOPE ("prepare_for_use():mat", "RadialBasisInterpolation<>");
     121             : 
     122      238063 :   for (std::size_t i=0; i<n_src_pts; i++)
     123             :     {
     124       13404 :       const Point & x_i (_src_pts[i]);
     125             : 
     126             :       // Diagonal
     127      237921 :       A(i,i) = rbf(0.);
     128             : 
     129   375673496 :       for (std::size_t j=i+1; j<n_src_pts; j++)
     130             :         {
     131    21151300 :           const Point & x_j (_src_pts[j]);
     132             : 
     133   364859925 :           const Real r_ij = (x_j - x_i).norm();
     134             : 
     135   396586875 :           A(i,j) = A(j,i) = rbf(r_ij);
     136             :         }
     137             : 
     138             :       // set source data
     139      482942 :       for (unsigned int var=0; var<n_vars; var++)
     140      258825 :         b(i,var) = _src_vals[i*n_vars + var];
     141             :     }
     142             :   }
     143             : 
     144             : 
     145             :   {
     146           4 :     LOG_SCOPE ("prepare_for_use():solve", "RadialBasisInterpolation<>");
     147             : 
     148             :     // Solve the linear system
     149         142 :     x = A.ldlt().solve(b);
     150             :     //x = A.fullPivLu().solve(b);
     151             :   }
     152             : 
     153             :   // save  the weights for each variable
     154         146 :   _weights.resize (this->_src_vals.size());
     155             : 
     156      238063 :   for (std::size_t i=0; i<n_src_pts; i++)
     157      482942 :     for (unsigned int var=0; var<n_vars; var++)
     158      258825 :       _weights[i*n_vars + var] = x(i,var);
     159             : 
     160             : #endif
     161             : 
     162         142 : }
     163             : 
     164             : 
     165             : 
     166             : template <unsigned int KDDim, class RBF>
     167       36922 : void 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        5900 :   LOG_SCOPE ("interpolate_field_data()", "RadialBasisInterpolation<>");
     172             : 
     173             :   libmesh_experimental();
     174             : 
     175             :   const unsigned int
     176        2950 :     n_vars    = this->n_field_variables();
     177             : 
     178             :   const std::size_t
     179        5900 :     n_src_pts = this->_src_pts.size(),
     180        5900 :     n_tgt_pts = tgt_pts.size();
     181             : 
     182        2950 :   libmesh_assert_equal_to (_weights.size(),    this->_src_vals.size());
     183        2950 :   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       39872 :   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       73915 :   for (auto v : index_range(this->_names))
     191       36993 :     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       36922 :   RBF rbf(_r_bbox);
     196             : 
     197       36922 :   tgt_vals.resize (n_tgt_pts*n_vars); /**/ std::fill (tgt_vals.begin(), tgt_vals.end(), Number(0.));
     198             : 
     199       80873 :   for (std::size_t tgt=0; tgt<n_tgt_pts; tgt++)
     200             :     {
     201        6296 :       const Point & p (tgt_pts[tgt]);
     202             : 
     203   120556552 :       for (std::size_t i=0; i<n_src_pts; i++)
     204             :         {
     205    19207896 :           const Point & x_i(_src_pts[i]);
     206             :           const Real
     207   110908653 :             r_i   = (p - x_i).norm(),
     208     9603948 :             phi_i = rbf(r_i);
     209             : 
     210   241735202 :           for (unsigned int var=0; var<n_vars; var++)
     211   140470497 :             tgt_vals[tgt*n_vars + var] += _weights[i*n_vars + var]*phi_i;
     212             :         }
     213             :     }
     214       36922 : }
     215             : 
     216             : 
     217             : 
     218             : // ------------------------------------------------------------
     219             : // Explicit Instantiations
     220             : template class LIBMESH_EXPORT RadialBasisInterpolation<3, WendlandRBF<3,0>>;
     221             : template class LIBMESH_EXPORT RadialBasisInterpolation<3, WendlandRBF<3,2>>;
     222             : template class LIBMESH_EXPORT RadialBasisInterpolation<3, WendlandRBF<3,4>>;
     223             : template class LIBMESH_EXPORT RadialBasisInterpolation<3, WendlandRBF<3,8>>;
     224             : 
     225             : } // namespace libMesh

Generated by: LCOV version 1.14