/***********************************************************************
* GNU Lesser General Public License
*
* This file is part of the GFDL Flexible Modeling System (FMS).
*
* FMS is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* FMS is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FMS. If not, see .
**********************************************************************/
#include
#include
#include
#include "mosaic_util.h"
#include "interp.h"
#include "create_xgrid.h"
/*********************************************************************
void cublic_spline_sp(size1, size2, grid1, grid2, data1, data2)
Calculate a shape preserving cubic spline. Monotonicity is ensured over each subinterval
unlike classic cubic spline interpolation.
It will be used to interpolation data in 1-D space.
INPUT Arguments:
grid1: grid for input data grid.
grid2: grid for output data grid.
size1: size of input grid.
size2: size of output grid.
data1: input data associated with grid1.
OUTPUT ARGUMENTS:
data2: output data associated with grid2. (OUTPUT)
*********************************************************************/
void cubic_spline_sp(int size1, int size2, const double *grid1, const double *grid2, const double *data1,
double *data2 )
{
double *delta=NULL, *d=NULL, *dh=NULL, *b=NULL, *c = NULL;
double s, w1, w2, p;
int i, k, n, klo, khi, kmax;
for(i=1; i grid1[size1-1]) error_handler("cubic_spline_sp: grid2 lies outside grid1");
}
if(size1 < 2) error_handler("cubic_spline_sp: the size of input grid should be at least 2");
if(size1 == 2) { /* when size1 is 2, it just reduced to a linear interpolation */
p = (data1[1]-data1[0])/(grid1[1]-grid1[0]);
for(i=0; i< size2; i++) data2[i] = p*(grid2[i] - grid1[0]) + data1[0];
return;
}
delta = (double *)malloc((size1-1)*sizeof(double));
dh = (double *)malloc((size1-1)*sizeof(double));
d = (double *)malloc(size1*sizeof(double));
for(k=0;k 0.0 ) {
w1 = 2.0*dh[k] + dh[k-1];
w2 = dh[k] + 2.0*dh[k-1];
d[k] = (w1+w2)/(w1/delta[k-1]+w2/delta[k]);
}
else {
d[k] = 0.0;
}
}
/*
End slopes
*/
kmax = size1-1;
d[0] = ((2.0*dh[0] + dh[1])*delta[0] - dh[0]*delta[1])/(dh[0]+dh[1]);
if ( d[0]*delta[0] < 0.0 ) {
d[0] = 0.0;
}
else {
if ( delta[0]*delta[1] < 0.0 && fabs(d[0]) > fabs(3.0*delta[0])) {
d[0]=3.0*delta[0];
}
}
d[kmax] = ((2.0*dh[kmax-1] + dh[kmax-2])*delta[kmax-1] - dh[kmax-1]*delta[kmax-2])/(dh[kmax-1]+dh[kmax-2]);
if ( d[kmax]*delta[kmax-1] < 0.0 ) {
d[kmax] = 0.0;
}
else {
if ( delta[kmax-1]*delta[kmax-2] < 0.0 && fabs(d[kmax]) > fabs(3.0*delta[kmax-1])) {
d[kmax]=3.0*delta[kmax-1];
}
}
/* Precalculate coefficients */
b = (double *)malloc((size1-1)*sizeof(double));
c = (double *)malloc((size1-1)*sizeof(double));
for (k=0; k grid1[size1-1]) error_handler("cubic_spline: grid2 lies outside grid1");
}
if(size1 < 2) error_handler("cubic_spline: the size of input grid should be at least 2");
if(size1 == 2) { /* when size1 is 2, it just reduced to a linear interpolation */
p = (data1[1]-data1[0])/(grid1[1]-grid1[0]);
for(i=0; i< size2; i++) data2[i] = p*(grid2[i] - grid1[0]) + data1[0];
return;
}
y2 = (double *)malloc(size1*sizeof(double));
u = (double *)malloc(size1*sizeof(double));
if (yp1 >.99e30) {
y2[0]=0.;
u[0]=0.;
}
else {
y2[0]=-0.5;
u[0]=(3./(grid1[1]-grid1[0]))*((data1[1]-data1[0])/(grid1[1]-grid1[0])-yp1);
}
for(i=1; i .99e30) {
qn=0.;
un=0.;
}
else {
qn=0.5;
un=(3./(grid1[size1-1]-grid1[size1-2]))*(ypn-(data1[size1-1]-data1[size1-2])/(grid1[size1-1]-grid1[size1-2]));
}
y2[size1-1]=(un-qn*u[size1-2])/(qn*y2[size1-2]+1.);
for(k=size1-2; k>=0; k--) y2[k] = y2[k]*y2[k+1]+u[k];
/* interpolate data onto grid2 */
for(k=0; k grid2[0] ) error_handler("interp.c: grid2 lies outside grid1");
if (grid1[nk1-1] < grid2[nk2-1] ) error_handler("interp.c: grid2 lies outside grid1");
for(k=0; k