LifeV
BCDataInterpolator.cpp
Go to the documentation of this file.
1 //@HEADER
2 /*
3  *******************************************************************************
4 
5  Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
6  Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
7 
8  This file is part of LifeV.
9 
10  LifeV is free software; you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  LifeV is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with LifeV. If not, see <http://www.gnu.org/licenses/>.
22 
23  *******************************************************************************
24  */
25 //@HEADER
26 
27 /*!
28  * @file
29  * @brief File containing a class for interpolating boundary functions from scattered data
30  *
31  * @date 09-06-2011
32  * @author Toni Lassila <toni.lassila@epfl.ch>
33  *
34  * @maintainer Toni Lassila <toni.lassila@epfl.ch>
35  */
36 
37 #include <lifev/core/fem/BCDataInterpolator.hpp>
38 
39 
40 #include <boost/shared_array.hpp>
41 #include <boost/bind.hpp>
42 #include <sstream>
43 #include <stdexcept>
44 #include <cstdlib>
45 #include <fstream>
46 #include <iostream>
47 #include <cmath>
48 
49 
50 namespace LifeV
51 {
52 
53 // ===================================================
54 // Constructors & Destructor
55 // ===================================================
58  M_rhs_x(),
59  M_rhs_y(),
60  M_rhs_z(),
61  M_coeffs_x(),
62  M_coeffs_y(),
63  M_coeffs_z(),
64  M_denseSolver(),
69  M_filteringLevel ( 0 ),
71  M_timePeriod ( 0 ),
72  M_timeInterval ( 0 ),
73  M_flagInterpolated ( false ),
74  M_verbose ( false )
75 {
76  M_userDefinedFunction = std::bind ( &BCDataInterpolator::interpolatedDataFunction, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5 );
77 }
78 
80 {
81 }
82 
83 // ===================================================
84 // Operators
85 // ===================================================
86 /*BCDataInterpolator&
87  BCDataInterpolator::operator = (const BCDataInterpolator &BCdi)
88  {
89  if (this != &BCdi)
90  {
91  }
92 
93  return *this;
94  }*/
95 
96 // ===================================================
97 // Methods
98 // ===================================================
100  const Real& x,
101  const Real& y,
102  const Real& z,
103  const ID& component )
104 {
105  BCDataInterpolator_point vectEval;
106 
107  vectEval = interpolateVectorialFunction ( t, x, y, z );
108 
109  switch ( component )
110  {
111  case 0:
112  return vectEval.x;
113  case 1:
114  return vectEval.y;
115  case 2:
116  return vectEval.z;
117  default:
118  std::ostringstream exception;
119  exception << "Invalid component: " << component << std::endl;
120  throw std::invalid_argument ( exception.str() );
121  }
122 }
123 
124 void BCDataInterpolator::showMe ( bool verbose, std::ostream& out ) const
125 {
126  out << " Boundary Conditions Data Interpolator ====>" << std::endl;
127  out << " Data sites:" << std::endl;
128 
129  for (UInt i = 0; i < M_nofControlPoints; i++)
130  {
131  out << "(" << M_dataSites[i].x << ", " << M_dataSites[i].y << ", " << M_dataSites[i].z << ")" << std::endl;
132  }
133 
134  if (verbose)
135  {
136  for (Int t = 0; t < M_timePeriod / M_timeInterval; t++)
137  {
138  out << " Data values (at sites):" << std::endl;
139  for (UInt i = 0; i < M_nofControlPoints; i++)
140  {
141  out << "(" << M_dataValues_timeSamples[indexInTime (i, t)].x << ", " << M_dataValues_timeSamples[indexInTime (i, t)].y << ", " << M_dataValues_timeSamples[indexInTime (i, t)].z << ")" << std::endl;
142  }
143  }
144  }
145 
146  out << " Data values (interpolated):" << std::endl;
147  for (UInt i = 0; i < M_nofControlPoints; i++)
148  {
149  out << "(" << M_dataValues[i].x << ", " << M_dataValues[i].y << ", " << M_dataValues[i].z << ")" << std::endl;
150  }
151 }
152 
153 void BCDataInterpolator::readData ( const std::string& fileName )
154 {
155  std::ifstream fin;
156  UInt RDIM;
157 
158  fin.open ( fileName.c_str() );
159 
160  if ( !fin.fail() )
161  {
162  fin.ignore ( 80, '\n' );
163 
164  fin >> M_nofControlPoints;
165  fin >> RDIM;
166  fin >> M_timeInterval;
167  fin >> M_timePeriod;
168  fin >> M_filteringLevel;
169 
170  if ( ( RDIM != 1 ) && ( RDIM != 3 ) )
171  {
172  std::ostringstream exception;
173  exception << "Interpolated data must be either scalar or a 3-vector: " << std::endl;
174  throw std::invalid_argument ( exception.str() );
175  }
176 
178  {
179  std::ostringstream exception;
180  exception << "Interpolation time interval and/or period are inconsistent." << std::endl;
181  throw std::invalid_argument ( exception.str() );
182  }
183 
184  Int n = static_cast< Int > (floor (M_timePeriod / M_timeInterval) );
185 
186  M_dataSites = boost::shared_array<BCDataInterpolator_point> (new BCDataInterpolator_point[M_nofControlPoints]);
187  M_dataValues = boost::shared_array<BCDataInterpolator_point> (new BCDataInterpolator_point[M_nofControlPoints]);
188  M_dataValues_timeSamples = boost::shared_array<BCDataInterpolator_point> (new BCDataInterpolator_point[M_nofControlPoints * (n + 1)]);
189 
190  fin.ignore ( 80, '\n' );
191  fin.ignore ( 80, '\n' );
192 
193  // Read the data site locations
194  for ( UInt i = 0; i < M_nofControlPoints; i++ )
195  {
196  fin >> M_dataSites[i].x;
197  fin >> M_dataSites[i].y;
198  fin >> M_dataSites[i].z;
199  }
200 
201  fin.ignore ( 80, '\n' );
202  fin.ignore ( 80, '\n' );
203 
204  // Read the data values at time instances
205  for (Int t = 0; t <= n; t++)
206  {
207 
208  for ( UInt i = 0; i < M_nofControlPoints; i++ )
209  {
210  fin >> M_dataValues_timeSamples[indexInTime (i, t)].x;
211  fin >> M_dataValues_timeSamples[indexInTime (i, t)].y;
212  fin >> M_dataValues_timeSamples[indexInTime (i, t)].z;
213  }
214 
215  fin.ignore ( 80, '\n' );
216  fin.ignore ( 80, '\n' );
217  }
218 
219  fin.close();
220 
221  // Form the interpolation matrix now
223  }
224 
225 }
226 
228 {
229  // TODO: Write matrix exporting routine
230 }
231 
232 
233 // ===================================================
234 // Private Methods
235 // ===================================================
237 {
238  Int nofElementsPerRow = ( needSideConstraints() ? M_nofControlPoints + NDIM + 1 : M_nofControlPoints );
239 
240  M_interpolationMatrix.Shape ( static_cast< int > ( nofElementsPerRow ),
241  static_cast< int > ( nofElementsPerRow ) );
242 
243  Real rbfEval;
244 
245  for ( UInt i = 0; i < M_nofControlPoints; i++ )
246  {
247 
248  for ( UInt j = 0; j <= i; j++ )
249  {
250  // Symmetric interpolation matrix [A]_ij = phi(|x_i - x_j|)
251 
252  rbfEval = evaluateRBF ( M_dataSites[i], M_dataSites[j] );
253  M_interpolationMatrix ( static_cast< int > ( i ), static_cast< int > ( j ) ) = static_cast< double > ( rbfEval );
254  M_interpolationMatrix ( static_cast< int > ( j ), static_cast< int > ( i ) ) = static_cast< double > ( rbfEval );
255 
256  }
257 
258  }
259 
260  if ( needSideConstraints() )
261  {
262 
263  // Add global linear polynomial to the interpolation basis
264 
265  for ( UInt i = 0; i < M_nofControlPoints; i++ )
266  {
267 
268  // First order term of the polynomial
269  M_interpolationMatrix ( i, M_nofControlPoints ) = M_dataSites[i].x;
270  M_interpolationMatrix ( i, M_nofControlPoints + 1 ) = M_dataSites[i].y;
271  M_interpolationMatrix ( i, M_nofControlPoints + 2 ) = M_dataSites[i].z;
272 
273  M_interpolationMatrix ( M_nofControlPoints, i ) = M_dataSites[i].x;
274  M_interpolationMatrix ( M_nofControlPoints + 1, i ) = M_dataSites[i].y;
275  M_interpolationMatrix ( M_nofControlPoints + 2, i ) = M_dataSites[i].z;
276 
277  // Constant term of the polynomial
278  M_interpolationMatrix ( i, M_nofControlPoints + 3 ) = 1;
279  M_interpolationMatrix ( M_nofControlPoints + 3, i ) = 1;
280 
281  }
282  }
283 
284  M_denseSolver.SetMatrix ( M_interpolationMatrix );
285  M_flagInterpolated = false;
286 
287 }
288 
290 {
291 
292 #ifdef DEBUG
293  // Check that condition number is "reasonable" (< 1e6), if not print a warning
294  Real reciprocalCond = M_denseSolver.RCOND();
295 
296  if (reciprocalCond < 1e-6)
297  {
298  debugStream ( 5000 ) << "Radial basis interpolation matrix is ill-conditioned.\n";
299  debugStream ( 5000 ) << "Estimated reciprocal of condition number: " << reciprocalCond << "\n";
300  }
301 #endif
302 
303  // Solve the interpolation system for each component using LU-factorization
304 
305  M_denseSolver.SetVectors ( M_coeffs_x, M_rhs_x );
306  M_denseSolver.Solve();
307 
308  M_denseSolver.SetVectors ( M_coeffs_y, M_rhs_y );
309  M_denseSolver.Solve();
310 
311  M_denseSolver.SetVectors ( M_coeffs_z, M_rhs_z );
312  M_denseSolver.Solve();
313 }
314 
316  const Real& x,
317  const Real& y,
318  const Real& z )
319 {
320  BCDataInterpolator_point rbfEval, evalPoint;
321  Real rbfShape;
322 
323  rbfEval.x = 0;
324  rbfEval.y = 0;
325  rbfEval.z = 0;
326  evalPoint.x = x;
327  evalPoint.y = y;
328  evalPoint.z = z;
329 
330  // Data values need to be interpolated in time, if not already done for this t
331  if (M_lastInterpolatedAtTime != t)
332  {
334  }
335 
336  // If not yet solved the interpolation system, do so
337  if ( !M_flagInterpolated )
338  {
340  M_flagInterpolated = true;
341  }
342 
343  // For each data site...
344  for ( UInt i = 0; i < M_nofControlPoints; i++ )
345  {
346 
347  rbfShape = evaluateRBF ( evalPoint, M_dataSites[i] );
348 
349  // Interpolated function value at point (x,y,z)
350  rbfEval.x += M_coeffs_x ( i ) * rbfShape;
351  rbfEval.y += M_coeffs_y ( i ) * rbfShape;
352  rbfEval.z += M_coeffs_z ( i ) * rbfShape;
353 
354  } // ...for each data site
355 
356 
357  if ( needSideConstraints() )
358  {
359  // Add the linear term of the polynomial...
360  rbfEval.x += M_coeffs_x ( M_nofControlPoints ) * evalPoint.x;
361  rbfEval.x += M_coeffs_x ( 1 + M_nofControlPoints ) * evalPoint.y;
362  rbfEval.x += M_coeffs_x ( 2 + M_nofControlPoints ) * evalPoint.z;
363 
364  rbfEval.y += M_coeffs_y ( M_nofControlPoints ) * evalPoint.x;
365  rbfEval.y += M_coeffs_y ( 1 + M_nofControlPoints ) * evalPoint.y;
366  rbfEval.y += M_coeffs_y ( 2 + M_nofControlPoints ) * evalPoint.z;
367 
368  rbfEval.z += M_coeffs_z ( M_nofControlPoints ) * evalPoint.x;
369  rbfEval.z += M_coeffs_z ( 1 + M_nofControlPoints ) * evalPoint.y;
370  rbfEval.z += M_coeffs_z ( 2 + M_nofControlPoints ) * evalPoint.z;
371 
372  // ...and the constant term of the polynomial
373  rbfEval.x += M_coeffs_x ( 3 + M_nofControlPoints );
374  rbfEval.y += M_coeffs_y ( 3 + M_nofControlPoints );
375  rbfEval.z += M_coeffs_z ( 3 + M_nofControlPoints );
376  }
377 
378  return rbfEval;
379 }
380 
382  const BCDataInterpolator_point point2 )
383 {
384  Real r = std::sqrt ( std::pow ( point1.x - point2.x, 2 ) + std::pow ( point1.y - point2.y, 2 ) + std::pow ( point1.z - point2.z, 2 ) );
385 
386  switch ( M_interpolationMethod )
387  {
388 
389  case RBF_ThinPlateSpline:
390  return ( r < 1e-3 ? 0.0 : std::pow ( r, 2 ) * std::log ( r ) );
391 
392  case RBF_MultiQuadric:
393  return std::sqrt ( std::pow ( r, 2 ) + 1 );
394 
395  case RBF_Cubic:
396  return std::pow ( r, 3 );
397 
398  case RBF_Gaussian:
399  return std::exp ( -std::pow ( r, 2 ) );
400 
402  return 1 / std::sqrt (std::pow ( r, 2 ) + 1);
403 
404  default:
405  return 0.0;
406  }
407 }
408 
410 {
411  switch ( M_interpolationMethod )
412  {
413 
414  case RBF_MultiQuadric:
415  case RBF_Gaussian:
417  return false;
418 
419  default:
420  return true;
421  }
422 }
423 
425 {
426  Int nofElementsPerRow = ( needSideConstraints() ? 2 * M_nofControlPoints + NDIM : M_nofControlPoints );
427 
428  M_rhs_x.Size ( static_cast< int > ( nofElementsPerRow ) );
429  M_rhs_y.Size ( static_cast< int > ( nofElementsPerRow ) );
430  M_rhs_z.Size ( static_cast< int > ( nofElementsPerRow ) );
431 
432  M_coeffs_x.Size ( static_cast< int > ( nofElementsPerRow ) );
433  M_coeffs_y.Size ( static_cast< int > ( nofElementsPerRow ) );
434  M_coeffs_z.Size ( static_cast< int > ( nofElementsPerRow ) );
435 
436  for ( UInt i = 0; i < M_nofControlPoints; i++ )
437  {
438  // Form RHS for the values at the RBF sites
439 
440  M_rhs_x ( i ) = M_dataValues[i].x;
441  M_rhs_y ( i ) = M_dataValues[i].y;
442  M_rhs_z ( i ) = M_dataValues[i].z;
443  }
444 
445  M_flagInterpolated = false;
446 }
447 
449 {
450  Int n = static_cast< Int > (floor (0.5 + M_timePeriod / (2 * M_timeInterval) ) ); // 2n time instances per period
451 
452  // Fourier interpolate the values between two time instants
453 
454  for ( UInt i = 0; i < M_nofControlPoints; i++ )
455  {
457 
458  c1.x = 0;
459  c1.y = 0;
460  c1.z = 0;
461  c2.x = 0;
462  c2.y = 0;
463  c2.z = 0;
464 
465  M_dataValues[i].x = 0;
466  M_dataValues[i].y = 0;
467  M_dataValues[i].z = 0;
468 
469  for (Int j = (M_filteringLevel - n); j <= (n - M_filteringLevel); j++)
470  {
471  for (Int k = 0; k <= 2 * n; k++)
472  {
473  Real tk = M_timePeriod / (2 * n + 1) * k;
474  Int index_ik = indexInTime (i, k);
475 
476  c1.x += std::cos (-j * tk * 2 * M_PI / M_timePeriod) * M_dataValues_timeSamples[index_ik].x;
477  c1.y += std::cos (-j * tk * 2 * M_PI / M_timePeriod) * M_dataValues_timeSamples[index_ik].y;
478  c1.z += std::cos (-j * tk * 2 * M_PI / M_timePeriod) * M_dataValues_timeSamples[index_ik].z;
479 
480  c2.x += std::sin (-j * tk * 2 * M_PI / M_timePeriod) * M_dataValues_timeSamples[index_ik].x;
481  c2.y += std::sin (-j * tk * 2 * M_PI / M_timePeriod) * M_dataValues_timeSamples[index_ik].y;
482  c2.z += std::sin (-j * tk * 2 * M_PI / M_timePeriod) * M_dataValues_timeSamples[index_ik].z;
483  }
484 
485  c1.x = c1.x / (2 * n + 1);
486  c1.y = c1.y / (2 * n + 1);
487  c1.z = c1.z / (2 * n + 1);
488  c2.x = c2.x / (2 * n + 1);
489  c2.y = c2.y / (2 * n + 1);
490  c2.z = c2.z / (2 * n + 1);
491 
492  M_dataValues[i].x += c1.x * std::cos (j * t * 2 * M_PI / M_timePeriod) - c2.x * std::sin (j * t * 2 * M_PI / M_timePeriod);
493  M_dataValues[i].y += c1.y * std::cos (j * t * 2 * M_PI / M_timePeriod) - c2.y * std::sin (j * t * 2 * M_PI / M_timePeriod);
494  M_dataValues[i].z += c1.z * std::cos (j * t * 2 * M_PI / M_timePeriod) - c2.z * std::sin (j * t * 2 * M_PI / M_timePeriod);
495  }
496  }
497 
499 
500  // Afterwards must solve again the interpolation weights because RHS changed
501  M_flagInterpolated = false;
503 }
504 
505 } // namespace LifeV
void readData(const std::string &fileName)
Read control points and data from a file.
BCInterpolationMethod M_interpolationMethod
Real interpolatedDataFunction(const Real &t, const Real &x, const Real &y, const Real &z, const ID &component)
Evaluate the interpolated function.
Real evaluateRBF(const BCDataInterpolator_point point1, const BCDataInterpolator_point point2)
void showMe(bool verbose=false, std::ostream &out=std::cout) const
Display the content of the variables.
BCDataInterpolator()
Constructors for an data interpolator.
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
#define M_PI
Definition: winmath.h:20
void interpolateDataValuesInTime(const Real t)
void updateInverseJacobian(const UInt &iQuadPt)
#define NDIM
Definition: LifeV.hpp:265
BCDataInterpolator_point interpolateVectorialFunction(const Real &t, const Real &x, const Real &y, const Real &z)
uint32_type ID
IDs.
Definition: LifeV.hpp:194
virtual ~BCDataInterpolator()
Destructor.
void exportInterpolationMatrix() const
Export the interpolation matrix for debugging purposes.
double Real
Generic real data.
Definition: LifeV.hpp:175
BCDataInterpolator - Class for interpolating boundary functions from scattered data.
Int indexInTime(const Int dataSite, const Int timeInstant) const
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191