/*********************************************************************** * 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