Object-oriented Scientific Computing Library: Version 0.910
Two-dimensional Interpolation

Successive use of smart_interp is implemented in twod_intp, which is useful for interpolating data presented on a two-dimensional grid (though the spacings between grid points need not be equal). An example demonstrating the use of twod_intp is given in ex_twod_intp_sect. Also, one can compute contour lines from data represented on a grid using the contour class.

If data is arranged without a grid, then planar_intp can be used. At present, the only way to compute contour lines on data which is not defined on a grid is to use planar_intp to recast the data on a grid and then use contour afterwards.

Higher-dimensional interpolation is possible with tensor_grid.

Two-dimensional interpolation

/* Example: ex_twod_intp.cpp
   -------------------------------------------------------------------
   A simple example for two-dimensional interpolation using
   the twod_intp class.
*/

#include <o2scl/twod_intp.h>
#include <o2scl/test_mgr.h>

using namespace std;
using namespace o2scl;

// A function for filling the data and comparing results
double f(double x, double y) {
  return pow(sin(0.1*x+0.3*y),2.0);
}

int main(void) {
  int i,j;

  test_mgr t;
  t.set_output_level(1);

  // Create the sample data

  ovector x(3), y(3);
  omatrix data(3,3);

  cout.setf(ios::scientific);

  // Set the grid
  x[0]=0.0;
  x[1]=1.0;
  x[2]=2.0;
  y[0]=3.0;
  y[1]=2.0;
  y[2]=1.0;

  // Set and print out the data
  cout << endl;
  cout << "Data: " << endl;
  cout << "          x  | ";
  for(i=0;i<3;i++) cout << x[i] << " ";
  cout << endl;
  cout << " y           |" << endl;
  cout << "-------------|-";
  for(i=0;i<3;i++) cout << "-------------";
  cout << endl;
  for(i=0;i<3;i++) {
    cout << y[i] << " | ";
    for(j=0;j<3;j++) {
      data[i][j]=f(x[j],y[i]);
      cout << data[i][j] << " ";
    }
    cout << endl;
  }
  cout << endl;

  // Perform the interpolation

  cout << "x            y            Calc.        Exact" << endl;

  twod_intp ti;

  // Interpolation, x-first
  double tol=0.05;
  double tol2=0.4;

  ti.set_data(3,3,x,y,data,true);

  double x0, y0, x1, y1;

  x0=0.5; y0=1.5;
  cout << x0 << " " << y0 << " "
       << ti.interp(x0,y0) << " " << f(x0,y0) << endl;

  x0=0.99; y0=1.99;
  cout << x0 << " " << y0 << " "
       << ti.interp(x0,y0) << " " << f(x0,y0) << endl;

  x0=1.0; y0=2.0;
  cout << x0 << " " << y0 << " "
       << ti.interp(x0,y0) << " " << f(x0,y0) << endl;

  cout << endl;

  // Interpolation, y-first

  ti.set_data(3,3,x,y,data,false);

  x0=0.5; y0=1.5;
  cout << x0 << " " << y0 << " "
       << ti.interp(x0,y0) << " " << f(x0,y0) << endl;

  x0=0.99; y0=1.99;
  cout << x0 << " " << y0 << " "
       << ti.interp(x0,y0) << " " << f(x0,y0) << endl;

  x0=1.0; y0=2.0;
  cout << x0 << " " << y0 << " "
       << ti.interp(x0,y0) << " " << f(x0,y0) << endl;

  cout << endl;

  t.report();
  return 0;
}
// End of example

This example creates a sample 3 by 3 grid of data with the function $ \left[ \sin \left( x/10 + 3 y/10 \right) \right]^2 $ and performs some interpolations and compares them with the exact result.

Data: 
          x  | 0.000000e+00 1.000000e+00 2.000000e+00 
 y           |
-------------|----------------------------------------
3.000000e+00 | 6.136010e-01 7.080734e-01 7.942506e-01 
2.000000e+00 | 3.188211e-01 4.150164e-01 5.145998e-01 
1.000000e+00 | 8.733219e-02 1.516466e-01 2.298488e-01 

x            y            Calc.        Exact
5.000000e-01 1.500000e+00 2.380255e-01 2.298488e-01
9.900000e-01 1.990000e+00 4.112589e-01 4.110774e-01
1.000000e+00 2.000000e+00 4.150164e-01 4.150164e-01

5.000000e-01 1.500000e+00 2.380255e-01 2.298488e-01
9.900000e-01 1.990000e+00 4.112589e-01 4.110774e-01
1.000000e+00 2.000000e+00 4.150164e-01 4.150164e-01

Contour lines

This example generates contour lines of the function

\[ z = f(x,y) = 15 \exp \left[ - \frac{1}{20^2}\left( x-20 \right)^2 - \frac{1}{5^2}\left(y-5\right)^2\right] + 40 \exp \left[ - \frac{1}{500}\left( x-70 \right)^2 - \frac{1}{2^2}\left(y-2\right)^2\right] \]

/* Example: ex_contour.cpp
   -------------------------------------------------------------------
   Example for generating contour lines
*/

#include <iostream>
#include <o2scl/test_mgr.h>
#include <o2scl/contour.h>
#include <o2scl/ovector_tlate.h>

using namespace std;
using namespace o2scl;

// A function defining the three-dimensional surface
// for which we want to compute contour levels
double fun(double x, double y) {
  return 15.0*exp(-pow(x-20.0,2.0)/400.0-pow(y-5.0,2.0)/25.0)
    +40.0*exp(-pow(x-70.0,2.0)/500.0-pow(y-2.0,2.0)/4.0);
}

// A function for outputting the data to cout
int print_data(int nx, int ny, ovector_base &x, ovector_base &y,
               omatrix_base &data);

// A function for printing the contour information to a file
int file_out(vector<contour_line> &conts, vector<contour_line> &conts2);

int main(void) {
  test_mgr t;
  t.set_output_level(1);

  cout.setf(ios::scientific);

  contour co;

  // Initialize the data

  ovector x(12), y(10);
  omatrix data(10,12);
  for(size_t i=0;i<10;i++) {
    y[i]=((double)i);
  }
  for(size_t i=0;i<12;i++) {
    x[i]=((double)i)*((double)i);
  }
  
  for(size_t j=0;j<12;j++) {
    for(size_t k=0;k<10;k++) {
      data[k][j]=fun(x[j],y[k]);
    }
  }
  co.set_data(12,10,x,y,data);
  
  // Print out the data

  print_data(12,10,x,y,data);

  // Set the contour levels

  ovector levels(7);
  levels[0]=5.0;
  levels[1]=10.0;
  levels[2]=0.002;
  levels[3]=20.0;
  levels[4]=0.2;
  levels[5]=30.0;
  levels[6]=2.0;
  
  co.set_levels(7,levels);

  // Compute the contours

  vector<contour_line> conts;
  co.calc_contours(conts);

  // Print the contours to the screen and test to make sure
  // that they match the requested level

  size_t nc=conts.size();
  for(size_t i=0;i<nc;i++) {
    cout << "Contour " << i << " at level " << conts[i].level << ":" << endl;
    size_t cs=conts[i].x.size();
    for(size_t j=0;j<cs;j++) {
      cout << "(" << conts[i].x[j] << ", " << conts[i].y[j] << ") " 
           << fun(conts[i].x[j],conts[i].y[j]) << endl;
      t.test_rel(fun(conts[i].x[j],conts[i].y[j]),conts[i].level,
                 1.0,"curve");
    }
    cout << endl;
  }

  // Refine the data using cubic spline interpolation

  def_interp_mgr<ovector_const_view,cspline_interp> dim1;
  def_interp_mgr<ovector_const_subvector,cspline_interp> dim2;
  co.regrid_data(5,5,dim1,dim2);

  // Recompute the contours

  vector<contour_line> conts2;
  co.calc_contours(conts2);

  // Output the contour information to a file for the documentation
  file_out(conts,conts2);
  
  t.report();

  return 0;
}
// End of example

The figure below shows contour lines in the region $ x\in(0,120), y\in(0,9) $. The data grid is represented by plus signs, and the associated generated contours. The figure clearly shows the obvious peaks at $ (20,5) $ and $ (70,2) $ .

ex_contour_plot1.png
Contour example plot

The contour class can also use interpolation to attempt to refine the data grid. The new contours after a refinement of a factor of 5 is given in the figure below.

ex_contour_plot2.png
Contour example plot
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.