diff options
Diffstat (limited to 'src/interpolate.c')
-rw-r--r-- | src/interpolate.c | 454 |
1 files changed, 107 insertions, 347 deletions
diff --git a/src/interpolate.c b/src/interpolate.c index 3ae6b3f..151f08c 100644 --- a/src/interpolate.c +++ b/src/interpolate.c @@ -23,128 +23,7 @@ CCTK_REAL interpolate_local(int order, CCTK_REAL x0, CCTK_REAL dx, CCTK_REAL y[], - CCTK_REAL x, - CCTK_INT excised_points[]); - -CCTK_REAL interpolate_eno(CCTK_INT order, CCTK_REAL x0, CCTK_REAL dx, - CCTK_REAL y[], - CCTK_REAL x, - CCTK_INT excised_points[]); - -/* prototypes for private functions defined in this file */ -static CCTK_REAL interpolate_local_order1(CCTK_REAL x0, CCTK_REAL dx, - CCTK_REAL y[], - CCTK_REAL x); -static CCTK_REAL interpolate_local_order2(CCTK_REAL x0, CCTK_REAL dx, - CCTK_REAL y[], - CCTK_REAL x); -static CCTK_REAL interpolate_local_order3(CCTK_REAL x0, CCTK_REAL dx, - CCTK_REAL y[], - CCTK_REAL x); -static CCTK_REAL interpolate_local_order4(CCTK_REAL x0, CCTK_REAL dx, - CCTK_REAL y[], - CCTK_REAL x); -static CCTK_REAL interpolate_local_order5(CCTK_REAL x0, CCTK_REAL dx, - CCTK_REAL y[], - CCTK_REAL x); - -/*****************************************************************************/ - -/* - * This function does local Lagrange polynomial interpolation on a - * uniform grid. That is, given order+1 uniformly spaced data points - * (x0 + i*dx, y[i]) , i = 0...order, it interpolates a degree-(order) - * (Lagrange) polynomial through them and evaluates this polynomial at - * a specified x coordinate. In general the error in this computed - * function value is O(h^(order+1)) . - * - * Except for possible end effects (see end_action (below)), the local - * interpolation is internally centered to improve its conditioning. Even - * so, the interpolation is highly ill-conditioned for small dx and/or - * large order and/or x outside the domain of the data points. - * - * The interpolation formulas were (are) all derived via Maple, see - * "./interpolate.in" and "./interpolate.out". - * - * Arguments: - * order = (in) The order of the local interpolation, i.e. the degree - * of the interpolated polynomial. - * x0 = (in) The x coordinate corresponding to y[0]. - * dx = (in) The x spacing between the data points. - * y[0...order] = (in) The y data array. - * x = (in) The x coordinate for the interpolation. - */ -CCTK_REAL interpolate_local(int order, - CCTK_REAL x0, CCTK_REAL dx, - CCTK_REAL y[], - CCTK_REAL x, - CCTK_INT excised_points[]) -{ - - /* - We assume that the excised region has one of the following 4 forms: - - o o o o o (No excision) - x o o o o (left excision) - o o o o x (right excision) - x o o o x (left and right excision) - - Anything else (e.g., x o x o x) will go horribly wrong. - */ - - int start, end, available_order; - - start = 0; - end = order; - - while ((start < order + 1)&&(excised_points[start])) - { - ++start; - } - while ((end > -1)&&(excised_points[end])) - { - --end; - } - - if (end < start) - { - /* The whole block is excised */ - return y[0]; - } - - /* The possible interpolation order that can be used */ - - available_order = end - start; - - if (available_order == 0) - { - /* There is only one non-excised point */ - return y[start]; - } - - if (dx * start + x0 > x) - { - /* We would have to extrapolate to the left */ - return y[start]; - } - - if (dx * end + x0 < x) - { - /* We would have to extrapolate to the right */ - return y[end]; - } - - switch (available_order) - { - case 1: return interpolate_local_order1(x0 + start * dx, dx, &y[start], x); - case 2: return interpolate_local_order2(x0 + start * dx, dx, &y[start], x); - case 3: return interpolate_local_order3(x0 + start * dx, dx, &y[start], x); - case 4: return interpolate_local_order4(x0 + start * dx, dx, &y[start], x); - case 5: return interpolate_local_order5(x0 + start * dx, dx, &y[start], x); - default: CCTK_WARN(0, "Interpolation order not supported"); - return 0; /* Avoid warning */ - } -} + CCTK_REAL x); /*****************************************************************************/ @@ -156,13 +35,13 @@ static CCTK_REAL interpolate_local_order1(CCTK_REAL x0, CCTK_REAL dx, CCTK_REAL y[], CCTK_REAL x) { -CCTK_REAL c0 = (+1.0/2.0)*y[0] + (+1.0/2.0)*y[1]; -CCTK_REAL c1 = - y[0] + + y[1]; + CCTK_REAL c0 = (+1.0/2.0)*y[0] + (+1.0/2.0)*y[1]; + CCTK_REAL c1 = - y[0] + + y[1]; -CCTK_REAL xc = x0 + 0.5*dx; -CCTK_REAL xr = (x - xc) / dx; + CCTK_REAL xc = x0 + 0.5*dx; + CCTK_REAL xr = (x - xc) / dx; -return( c0 + xr*c1 ); + return c0 + xr * c1; } /*****************************************************************************/ @@ -175,14 +54,14 @@ static CCTK_REAL interpolate_local_order2(CCTK_REAL x0, CCTK_REAL dx, CCTK_REAL y[], CCTK_REAL x) { -CCTK_REAL c0 = y[1]; -CCTK_REAL c1 = (-1.0/2.0)*y[0] + (+1.0/2.0)*y[2]; -CCTK_REAL c2 = (+1.0/2.0)*y[0] - y[1] + (+1.0/2.0)*y[2]; + CCTK_REAL c0 = y[1]; + CCTK_REAL c1 = (-1.0/2.0)*y[0] + (+1.0/2.0)*y[2]; + CCTK_REAL c2 = (+1.0/2.0)*y[0] - y[1] + (+1.0/2.0)*y[2]; -CCTK_REAL xc = x0 + 1.0*dx; -CCTK_REAL xr = (x - xc) / dx; + CCTK_REAL xc = x0 + 1.0*dx; + CCTK_REAL xr = (x - xc) / dx; -return( c0 + xr*(c1 + xr*c2) ); + return c0 + xr*(c1 + xr*c2); } /*****************************************************************************/ @@ -195,19 +74,19 @@ static CCTK_REAL interpolate_local_order3(CCTK_REAL x0, CCTK_REAL dx, CCTK_REAL y[], CCTK_REAL x) { -CCTK_REAL c0 = (-1.0/16.0)*y[0] + (+9.0/16.0)*y[1] - + (+9.0/16.0)*y[2] + (-1.0/16.0)*y[3]; -CCTK_REAL c1 = (+1.0/24.0)*y[0] + (-9.0/ 8.0)*y[1] - + (+9.0/ 8.0)*y[2] + (-1.0/24.0)*y[3]; -CCTK_REAL c2 = (+1.0/ 4.0)*y[0] + (-1.0/ 4.0)*y[1] - + (-1.0/ 4.0)*y[2] + (+1.0/ 4.0)*y[3]; -CCTK_REAL c3 = (-1.0/ 6.0)*y[0] + (+1.0/ 2.0)*y[1] - + (-1.0/ 2.0)*y[2] + ( 1.0/ 6.0)*y[3]; - -CCTK_REAL xc = x0 + 1.5*dx; -CCTK_REAL xr = (x - xc) / dx; - -return( c0 + xr*(c1 + xr*(c2 + xr*c3)) ); + CCTK_REAL c0 = (-1.0/16.0)*y[0] + (+9.0/16.0)*y[1] + + (+9.0/16.0)*y[2] + (-1.0/16.0)*y[3]; + CCTK_REAL c1 = (+1.0/24.0)*y[0] + (-9.0/ 8.0)*y[1] + + (+9.0/ 8.0)*y[2] + (-1.0/24.0)*y[3]; + CCTK_REAL c2 = (+1.0/ 4.0)*y[0] + (-1.0/ 4.0)*y[1] + + (-1.0/ 4.0)*y[2] + (+1.0/ 4.0)*y[3]; + CCTK_REAL c3 = (-1.0/ 6.0)*y[0] + (+1.0/ 2.0)*y[1] + + (-1.0/ 2.0)*y[2] + ( 1.0/ 6.0)*y[3]; + + CCTK_REAL xc = x0 + 1.5*dx; + CCTK_REAL xr = (x - xc) / dx; + + return c0 + xr*(c1 + xr*(c2 + xr*c3)); } /*****************************************************************************/ @@ -220,20 +99,20 @@ static CCTK_REAL interpolate_local_order4(CCTK_REAL x0, CCTK_REAL dx, CCTK_REAL y[], CCTK_REAL x) { -CCTK_REAL c0 = y[2]; -CCTK_REAL c1 = (+1.0/12.0)*y[0] + (-2.0/ 3.0)*y[1] - + (+2.0/ 3.0)*y[3] + (-1.0/12.0)*y[4]; -CCTK_REAL c2 = + (-1.0/24.0)*y[0] + (+2.0/ 3.0)*y[1] + (-5.0/ 4.0)*y[2] - + (+2.0/ 3.0)*y[3] + (-1.0/24.0)*y[4]; -CCTK_REAL c3 = + (-1.0/12.0)*y[0] + (+1.0/ 6.0)*y[1] - + (-1.0/ 6.0)*y[3] + (+1.0/12.0)*y[4]; -CCTK_REAL c4 = + (+1.0/24.0)*y[0] + (-1.0/ 6.0)*y[1] + (+1.0/ 4.0)*y[2] - + (-1.0/ 6.0)*y[3] + (+1.0/24.0)*y[4]; - -CCTK_REAL xc = x0 + 2.0*dx; -CCTK_REAL xr = (x - xc) / dx; - -return( c0 + xr*(c1 + xr*(c2 + xr*(c3 + xr*c4))) ); + CCTK_REAL c0 = y[2]; + CCTK_REAL c1 = (+1.0/12.0)*y[0] + (-2.0/ 3.0)*y[1] + + (+2.0/ 3.0)*y[3] + (-1.0/12.0)*y[4]; + CCTK_REAL c2 = + (-1.0/24.0)*y[0] + (+2.0/ 3.0)*y[1] + (-5.0/ 4.0)*y[2] + + (+2.0/ 3.0)*y[3] + (-1.0/24.0)*y[4]; + CCTK_REAL c3 = + (-1.0/12.0)*y[0] + (+1.0/ 6.0)*y[1] + + (-1.0/ 6.0)*y[3] + (+1.0/12.0)*y[4]; + CCTK_REAL c4 = + (+1.0/24.0)*y[0] + (-1.0/ 6.0)*y[1] + (+1.0/ 4.0)*y[2] + + (-1.0/ 6.0)*y[3] + (+1.0/24.0)*y[4]; + + CCTK_REAL xc = x0 + 2.0*dx; + CCTK_REAL xr = (x - xc) / dx; + + return c0 + xr*(c1 + xr*(c2 + xr*(c3 + xr*c4))); } /*****************************************************************************/ @@ -246,200 +125,81 @@ static CCTK_REAL interpolate_local_order5(CCTK_REAL x0, CCTK_REAL dx, CCTK_REAL y[], CCTK_REAL x) { -CCTK_REAL c0 = (+ 3.0/256.0)*y[0] + (-25.0/256.0)*y[1] - + (+75.0/128.0)*y[2] + (+75.0/128.0)*y[3] - + (-25.0/256.0)*y[4] + (+ 3.0/256.0)*y[5]; -CCTK_REAL c1 = (- 3.0/640.0)*y[0] + (+25.0/384.0)*y[1] - + (-75.0/ 64.0)*y[2] + (+75.0/ 64.0)*y[3] - + (-25.0/384.0)*y[4] + (+ 3.0/640.0)*y[5]; -CCTK_REAL c2 = (- 5.0/ 96.0)*y[0] + (+13.0/ 32.0)*y[1] - + (-17.0/ 48.0)*y[2] + (-17.0/ 48.0)*y[3] - + (+13.0/ 32.0)*y[4] + (- 5.0/ 96.0)*y[5]; -CCTK_REAL c3 = (+ 1.0/ 48.0)*y[0] + (-13.0/ 48.0)*y[1] - + (+17.0/ 24.0)*y[2] + (-17.0/ 24.0)*y[3] - + (+13.0/ 48.0)*y[4] + (- 1.0/ 48.0)*y[5]; -CCTK_REAL c4 = (+ 1.0/ 48.0)*y[0] + (- 1.0/ 16.0)*y[1] - + (+ 1.0/ 24.0)*y[2] + (+ 1.0/ 24.0)*y[3] - + (- 1.0/ 16.0)*y[4] + (+ 1.0/ 48.0)*y[5]; -CCTK_REAL c5 = (- 1.0/120.0)*y[0] + (+ 1.0/ 24.0)*y[1] - + (- 1.0/ 12.0)*y[2] + (+ 1.0/ 12.0)*y[3] - + (- 1.0/ 24.0)*y[4] + (+ 1.0/120.0)*y[5]; - -CCTK_REAL xc = x0 + 2.5*dx; -CCTK_REAL xr = (x - xc) / dx; - -return( c0 + xr*(c1 + xr*(c2 + xr*(c3 + xr*(c4 + xr*c5)))) ); + CCTK_REAL c0 = (+ 3.0/256.0)*y[0] + (-25.0/256.0)*y[1] + + (+75.0/128.0)*y[2] + (+75.0/128.0)*y[3] + + (-25.0/256.0)*y[4] + (+ 3.0/256.0)*y[5]; + CCTK_REAL c1 = (- 3.0/640.0)*y[0] + (+25.0/384.0)*y[1] + + (-75.0/ 64.0)*y[2] + (+75.0/ 64.0)*y[3] + + (-25.0/384.0)*y[4] + (+ 3.0/640.0)*y[5]; + CCTK_REAL c2 = (- 5.0/ 96.0)*y[0] + (+13.0/ 32.0)*y[1] + + (-17.0/ 48.0)*y[2] + (-17.0/ 48.0)*y[3] + + (+13.0/ 32.0)*y[4] + (- 5.0/ 96.0)*y[5]; + CCTK_REAL c3 = (+ 1.0/ 48.0)*y[0] + (-13.0/ 48.0)*y[1] + + (+17.0/ 24.0)*y[2] + (-17.0/ 24.0)*y[3] + + (+13.0/ 48.0)*y[4] + (- 1.0/ 48.0)*y[5]; + CCTK_REAL c4 = (+ 1.0/ 48.0)*y[0] + (- 1.0/ 16.0)*y[1] + + (+ 1.0/ 24.0)*y[2] + (+ 1.0/ 24.0)*y[3] + + (- 1.0/ 16.0)*y[4] + (+ 1.0/ 48.0)*y[5]; + CCTK_REAL c5 = (- 1.0/120.0)*y[0] + (+ 1.0/ 24.0)*y[1] + + (- 1.0/ 12.0)*y[2] + (+ 1.0/ 12.0)*y[3] + + (- 1.0/ 24.0)*y[4] + (+ 1.0/120.0)*y[5]; + + CCTK_REAL xc = x0 + 2.5*dx; + CCTK_REAL xr = (x - xc) / dx; + + return c0 + xr*(c1 + xr*(c2 + xr*(c3 + xr*(c4 + xr*c5)))); } - -/*****************************************************************************/ - -CCTK_REAL interpolate_eno(CCTK_INT order, - CCTK_REAL x0, CCTK_REAL dx, - CCTK_REAL y[], - CCTK_REAL x, - CCTK_INT excised_points[]) +/* + * This function does local Lagrange polynomial interpolation on a + * uniform grid. That is, given order+1 uniformly spaced data points + * (x0 + i*dx, y[i]) , i = 0...order, it interpolates a degree-(order) + * (Lagrange) polynomial through them and evaluates this polynomial at + * a specified x coordinate. In general the error in this computed + * function value is O(h^(order+1)) . + * + * Except for possible end effects (see end_action (below)), the local + * interpolation is internally centered to improve its conditioning. Even + * so, the interpolation is highly ill-conditioned for small dx and/or + * large order and/or x outside the domain of the data points. + * + * The interpolation formulas were (are) all derived via Maple, see + * "./interpolate.in" and "./interpolate.out". + * + * Arguments: + * order = (in) The order of the local interpolation, i.e. the degree + * of the interpolated polynomial. + * x0 = (in) The x coordinate corresponding to y[0]. + * dx = (in) The x spacing between the data points. + * y[0...order] = (in) The y data array. + * x = (in) The x coordinate for the interpolation. + */ +CCTK_REAL interpolate_local(int order, + CCTK_REAL x0, CCTK_REAL dx, + CCTK_REAL y[], + CCTK_REAL x) { -/* CCTK_REAL diff[4]; */ -/* CCTK_INT seed = 0; */ -/* CCTK_INT j,r; */ - -/* CCTK_REAL c0; */ -/* CCTK_REAL c1; */ -/* CCTK_REAL c2; */ - -/* CCTK_REAL xc; */ -/* CCTK_REAL xr; */ - - CCTK_REAL result; - CCTK_REAL undiv_diff [13][6]; - CCTK_INT diff, i, ii, r; - CCTK_REAL fp_i, fp_ii, x_rel; - - /* Find seed index */ -/* while (x > x0 + dx * ((CCTK_REAL)seed+0.5)) seed++; */ - -/* if (seed!=2) { */ - /* Not enough stencil, only perform linear interpolation */ -/* seed = 0; */ -/* while (x > x0 + dx * ((CCTK_REAL)(seed+1))) seed++; */ -/* if (seed==4) seed=3; */ -/* return y[seed] + (y[seed+1]-y[seed])/dx * (x-x0-(CCTK_REAL)seed*dx); */ -/* } */ - - /* Calculate the undivided differences */ -/* for (j=0; j<=3; j++) */ -/* diff[j] = y[j+1] - y[j]; */ - - /* Find the stencil */ -/* if ( fabs(diff[1]) < fabs(diff[2]) ) { */ -/* if ( fabs(diff[1]-diff[0]) < fabs(diff[2]-diff[1]) ) */ -/* r = 0; */ -/* else */ -/* r = 1; */ -/* } else { */ -/* if ( fabs(diff[2]-diff[1]) < fabs(diff[3]-diff[2]) ) */ -/* r = 1; */ -/* else */ -/* r = 2; */ -/* } */ - - /* Interpolate second order */ -/* c0 = y[r+1]; */ -/* c1 = (-1.0/2.0)*y[r] + (+1.0/2.0)*y[r+2]; */ -/* c2 = (+1.0/2.0)*y[r] - y[r+1] + (+1.0/2.0)*y[r+2]; */ - -/* xc = x0 + dx * (CCTK_REAL)(r+1); */ -/* xr = (x - xc) / dx; */ -/* result = ( c0 + xr*(c1 + xr*c2) ); */ - - for (i = 1; i < 2 * order + 2; ++i) - { - undiv_diff[i][0] = y[i-1]; - } - for (i = 0; i < 6; ++i) - { - undiv_diff[0][i] = 1e10; - undiv_diff[2 * order + 2][i] = 1e10; - } - - for (diff = 1; diff < order + 1; ++diff) - { - for (i = 1; i < 2 * order + 2; ++i) - { - undiv_diff[i][diff] = undiv_diff[i][diff-1] - undiv_diff[i-1][diff-1]; - } - undiv_diff[0][diff] = -10 * undiv_diff[1][diff]; - undiv_diff[2 * order + 2][diff]= -10 * undiv_diff[2 * order + 1][diff]; - } + int start, end; - fp_i = (x - x0) / dx; - fp_ii = floor(fp_i); - x_rel = fp_i - fp_ii; - - ii = (CCTK_INT)(fp_ii) + 1; - - if (ii < 1) - { - ii = 1; - x_rel = fp_i - (CCTK_REAL)(ii) + 1.0; - } - else if (ii > 2 * order + 1) - { - ii = 2 * order + 1; - x_rel = fp_i - (CCTK_REAL)(ii) + 1.0; - } + start = 0; + end = order; - r = 0; - for (diff = 1; diff < order + 1; ++diff) - { - if (fabs(undiv_diff[ii-r][diff]) < fabs(undiv_diff[ii-r+1][diff]) ) - { - ++r; - } - - if (ii - r < diff + 1) - { - --r; - } - else if (ii - r + diff > 2 * order + 1) - { - ++r; - } - } - - result = undiv_diff[ii-r][0]; + /* The possible interpolation order that can be used */ - switch (order) - { - case 1: - result += (x_rel + r - 0.0) / 1.0 * undiv_diff[ii-r+1][1]; - break; - case 2: - result += (x_rel + r - 0.0) / 1.0 * (undiv_diff[ii-r+1][1] + - (x_rel + r - 1.0) / 2.0 * (undiv_diff[ii-r+2][2])); - break; - case 3: - result += (x_rel + r - 0.0) / 1.0 * (undiv_diff[ii-r+1][1] + - (x_rel + r - 1.0) / 2.0 * (undiv_diff[ii-r+2][2] + - (x_rel + r - 2.0) / 3.0 * (undiv_diff[ii-r+3][3]))); - break; - case 4: - result += (x_rel + r - 0.0) / 1.0 * (undiv_diff[ii-r+1][1] + - (x_rel + r - 1.0) / 2.0 * (undiv_diff[ii-r+2][2] + - (x_rel + r - 2.0) / 3.0 * (undiv_diff[ii-r+3][3] + - (x_rel + r - 3.0) / 4.0 * (undiv_diff[ii-r+4][4])))); - break; - case 5: - result += (x_rel + r - 0.0) / 1.0 * (undiv_diff[ii-r+1][1] + - (x_rel + r - 1.0) / 2.0 * (undiv_diff[ii-r+2][2] + - (x_rel + r - 2.0) / 3.0 * (undiv_diff[ii-r+3][3] + - (x_rel + r - 3.0) / 4.0 * (undiv_diff[ii-r+4][4] + - (x_rel + r - 4.0) / 5.0 * (undiv_diff[ii-r+5][5]))))); - break; - } + if (x0 > x) + return y[start]; -/* #define CARTOON_ENO_DBG 1 */ -#ifdef CARTOON_ENO_DBG - - printf("Cartoon ENO interpolation.\n" - "Input: order %d x0 %g dx %g x %g.\n", - order, x0, dx, x); - printf("Data is\n"); - for (i = 0; i < 2 * order + 1; ++i) - { - printf(" %g", y[i]); + if (dx * end + x0 < x) + return y[end]; + + switch (order) { + case 1: return interpolate_local_order1(x0, dx, y, x); + case 2: return interpolate_local_order2(x0, dx, y, x); + case 3: return interpolate_local_order3(x0, dx, y, x); + case 4: return interpolate_local_order4(x0, dx, y, x); + case 5: return interpolate_local_order5(x0, dx, y, x); + default: CCTK_WARN(0, "Interpolation order not supported"); + return 0; /* Avoid warning */ } - printf("\nEntries used were\n"); - printf("0: %g 1: %g 2: %g\n", - undiv_diff[ii-r][0], undiv_diff[ii-r+1][1], undiv_diff[ii-r+2][2]); - printf("Parameters are fp_i %g fp_ii %g x_rel %g ii %d r %d\n", - fp_i, fp_ii, x_rel, ii, r); - printf("Result is %g\n", result); - -#endif - - return result; - } |