aboutsummaryrefslogtreecommitdiff
path: root/src/molecule_posn.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/molecule_posn.c')
-rw-r--r--src/molecule_posn.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/src/molecule_posn.c b/src/molecule_posn.c
new file mode 100644
index 0000000..1eb4eeb
--- /dev/null
+++ b/src/molecule_posn.c
@@ -0,0 +1,238 @@
+ /*@@
+ @file molecule_posn.c
+ @date 23 Oct 2001
+ @author Jonathan Thornburg <jthorn@aei.mpg.de>
+ @desc Worker function to compute molecule positions for interpolator.
+ @enddesc
+ @version $Id$
+ @@*/
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifndef AEILOCALINTERP_STANDALONE_TEST
+ #include "cctk.h"
+#endif
+
+#include "InterpLocalUniform.h"
+
+/* the rcs ID and its dummy function to use it */
+static const char *rcsid = "$Header$";
+#ifndef AEILOCALINTERP_STANDALONE_TEST
+ CCTK_FILEVERSION(AEIThorns_AEILocalInterp_src_molecule_posn_c)
+#endif
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+/*@@
+ @routine AEILocalInterp_molecule_posn
+ @date 23 Oct 2001
+ @author Jonathan Thornburg <jthorn@aei.mpg.de>
+ @desc
+ Given a uniformly-spaced grid, this function computes molecule
+ positions for an interpolation or similar operation:
+ (1) It computes the closest grid point to the input coordinate
+ (2) It does the slightly tricky odd/even computation to decide where
+ to center the molecule
+ (3) It checks for the molecule falling off the edge of the grid,
+ and off-centers it as appropriate.
+
+ For (1), we assume that grid points have floating-point
+ coordinates (we refer to these as "x") which are an arbitrary
+ linear function of the integer grid coordinates (we refer to
+ these as "i"), x = grid_origin + i*grid_delta.
+
+ For (2), suppose we have a data array indexed by [i], from which we
+ wish to select an N-point molecule [i_lo, i_hi] centered as close as
+ possible to the point x . The problem is just how to choose the
+ centering. The following diagram illustrates the issues:
+
+ N i_lo i_hi [i-3] [i-2] [i-1] [i] [i+1] [i+2] [i+3] [i+4]
+ - ---- ---- ----- ----- ----- ----- ----- ----- ----- -----
+ 2 i i+1 *xxxxxx*
+ 3 i-1 i+1 * xxx*xxx *
+ 4 i-1 i+2 * *xxxxxx* *
+ 5 i-2 i+2 * * xxx*xxx * *
+ 6 i-2 i+3 * * *xxxxxx* * *
+ 7 i-3 i+3 * * * xxx*xxx * * *
+ 8 i-3 i+4 * * * *xxxxxx* * * *
+
+ The diagram shows the range of x values relative to the grid,
+ for which we'll choose each centering. Thus if N is even, the
+ centering is based on which grid zone contains x (take the floor
+ of the floating-point i coordinate), while if N is odd, the centering
+ is based on which grid point is closest to x (round the floating-
+ -point i coordinate to the nearest integer).
+
+ It's also convenient to introduce the integer molecule coordinate m;
+ this is the integer grid coordinate i relative to that of the molecule
+ center, i.e. the above diagram has columns labelled with [i+m].
+ @enddesc
+
+ @hdate 27.Jan.2003
+ @hauthor Jonathan Thornburg <jthorn@aei.mpg.de>
+ @hdesc Complete rewrite: now supports
+ @var boundary_off_centering_tolerance_min,
+ @var boundary_off_centering_tolerance_max,
+ @var boundary_extrapolation_tolerance_min,
+ @var boundary_extrapolation_tolerance_max,
+ also change to returning status code,
+ also drop returning @var min_m and @var max_m
+ since they were never used.
+ @endhdesc
+
+ @var grid_origin
+ @vdesc The floating-point coordinate x of the grid point i=0.
+ @vtype fp grid_origin
+ @endvar
+
+ @var grid_delta
+ @vdesc The grid spacing (in the floating-point coordinate x).
+ @vtype fp grid_delta
+ @endvar
+
+ @var grid_i_min
+ @vdesc The minimum integer coordinate i of the grid.
+ @vtype int grid_i_min
+ @endvar
+
+ @var grid_i_max
+ @vdesc The maximum integer coordinate i of the grid.
+ @vtype int grid_i_max
+ @endvar
+
+ @var molecule_size
+ @vdesc The size (number of points) of the molecule.
+ @vtype int molecule_size
+ @endvar
+
+ @var boundary_off_centering_tolerance_min,
+ boundary_off_centering_tolerance_max
+ @vdesc Specifies how many grid spacings the interpolation point
+ may be beyond the default-centering region before being
+ declared "out of range" on the {minimum,maximum} boundaries
+ of the grid respectively.
+ @vtype fp boundary_off_centering_tolerance_min,
+ boundary_off_centering_tolerance_max
+ @endvar
+
+ @var boundary_extrapolation_tolerance_min,
+ boundary_extrapolation_tolerance_max
+ @vdesc Specifies how many grid spacings the interpolation point
+ may be beyond the grid boundary before being declared
+ "out of range" on the {minimum,maximum} boundaries
+ of the grid respectively.
+ @vtype fp boundary_extrapolation_tolerance_min,
+ boundary_extrapolation_tolerance_max
+ @endvar
+
+ @var x
+ @vdesc The floating-point coordinate of the interpolation point.
+ @vtype fp x
+ @endvar
+
+ @var i_center
+ @vdesc A pointer to an value where this function should
+ store the integer coordinate of the molecule center,
+ or NULL to skip storing this
+ @vtype int *i_center
+ @vio pointer to out
+ @endvar
+
+ @var x_rel
+ @vdesc A pointer to where this function should store the
+ interpolation point's x coordinate relative to the
+ molecule center, measured in units of the grid spacing;
+ or NULL to skip storing this.
+ @vtype fp *x_rel
+ @vio pointer to out
+ @endvar
+
+ @returntype int
+ @returndesc
+ This function returns 0 if the interpolation point is "in range",
+ or one of the (negative) error codes defined in "InterpLocalUniform.h"
+ if the interpolation point is "out of range":
+ MOLECULE_POSN_ERROR_X_LT_MIN
+ if x is out-of-range on the min end of the grid
+ (i.e. x < the minimum allowable x)
+ MOLECULE_POSN_ERROR_X_GT_MAX
+ if x is out-of-range on the max end of the grid
+ (i.e. x > the maximum allowable x)
+ MOLECULE_POSN_ERROR_GRID_TINY
+ if the grid is smaller than the molecule
+ @endreturndesc
+ @@*/
+int AEILocalInterp_molecule_posn(fp grid_origin, fp grid_delta,
+ int grid_i_min, int grid_i_max,
+ int molecule_size,
+ fp boundary_off_centering_tolerance_min,
+ fp boundary_off_centering_tolerance_max,
+ fp boundary_extrapolation_tolerance_min,
+ fp boundary_extrapolation_tolerance_max,
+ fp x,
+ int* i_center, fp* x_rel)
+{
+/* molecule radia (inherently positive) in +/- directions */
+const int mr_plus = (molecule_size >> 1);
+const int mr_minus = molecule_size - mr_plus - 1;
+
+/* range of x_rel for which this molecule is centered, cf. diagram in header comment */
+const fp centered_min_x_rel = IS_EVEN(molecule_size) ? 0.0 : -0.5;
+const fp centered_max_x_rel = IS_EVEN(molecule_size) ? 1.0 : +0.5;
+
+/* range of i where we *could* center the molecule, as floating-point numbers */
+const fp fp_centered_min_possible_i = grid_i_min + mr_minus + centered_min_x_rel;
+const fp fp_centered_max_possible_i = grid_i_max - mr_plus + centered_max_x_rel;
+
+/* integer coordinate i of interpolation point, as a floating-point number */
+const fp fp_i = (x - grid_origin) / grid_delta;
+
+/* is the molecule larger than the grid? */
+if (molecule_size > HOW_MANY_IN_RANGE(grid_i_min,grid_i_max))
+ then return MOLECULE_POSN_ERROR_GRID_TINY; /*** ERROR RETURN ***/
+
+/* is interpolation point x beyond the extrapolation tolerance? */
+if (fp_i < (fp)grid_i_min - boundary_extrapolation_tolerance_min)
+ then return MOLECULE_POSN_ERROR_X_LT_MIN; /*** ERROR RETURN ***/
+if (fp_i > (fp)grid_i_max + boundary_extrapolation_tolerance_max)
+ then return MOLECULE_POSN_ERROR_X_GT_MAX; /*** ERROR RETURN ***/
+
+/* is interpolation point x beyond the off-centering tolerance? */
+if (fp_i < fp_centered_min_possible_i - boundary_off_centering_tolerance_min)
+ then return MOLECULE_POSN_ERROR_X_LT_MIN; /*** ERROR RETURN ***/
+if (fp_i > fp_centered_max_possible_i + boundary_off_centering_tolerance_max)
+ then return MOLECULE_POSN_ERROR_X_GT_MAX; /*** ERROR RETURN ***/
+
+/* now choose the actual molecule position/centering: */
+/* first set up a centered molecule */
+ {
+fp fp_i_center = IS_EVEN(molecule_size) /* ... as a floating-point number */
+ ? floor(fp_i)
+ : JT_ROUND(fp_i);
+int int_i_center = (int) fp_i_center; /* ... as an integer */
+
+/* then clamp the molecule at the grid boundaries */
+if (int_i_center - mr_minus < grid_i_min)
+ then {
+ int_i_center = grid_i_min + mr_minus;
+ fp_i_center = (fp) int_i_center;
+ }
+if (int_i_center + mr_plus > grid_i_max)
+ then {
+ int_i_center = grid_i_max - mr_plus;
+ fp_i_center = (fp) int_i_center;
+ }
+
+/* store the results */
+if (i_center != NULL)
+ then *i_center = int_i_center;
+if (x_rel != NULL)
+ then *x_rel = fp_i - fp_i_center;
+
+return 0; /*** NORMAL RETURN ***/
+ }
+}