NASA Logo
Ocean Color Science Software

ocssw V2022
int_4d.c
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include "l12_proto.h"
4 #include "l2prod.h"
5 #include "l1.h"
6 #include "get_ctht.h"
7 
8 /*
9  file int_4d.c, get index and weights to do a 4-d interpolation
10  Also for now, have the 3-d interp hard coded as int_3d
11 */
12 int32_t int_4d( float *sxax[4], int32_t snax[4], int64_t n_block, float x[4],
13  int64_t ar_off[16], float ar_wt[16], float orig_wt[4] )
14 
15  /*
16  int_4d - get index and weights to do a 4-d interpolation
17 
18  Returns, int32_t status 0 is good 1 - outside range
19 
20  Parameters: (in calling order)
21  Type Name I/O Description
22  ---- ---- --- -----------
23  float *[4] sxax I array of pointers to each
24  dimension axis
25  int32_t [4] snax I size of each axis
26  int64_t n_block I size of all dimensions before
27  the ones here being used
28  float [4] x I value of point on each axis
29  int64_t [16] ar_off O linear offset to each corner pt
30  float [16] ar_wt O weight for each corner pt
31  float [4] orig_wt O the weights from the low point
32 
33  the multi-dim array, sxax has dims [ snax[0],... snax[3] ] with a the
34  combination of the fastest dimensions Based on x's position in each
35  sxax axis, there will be a index in each axis of the start point for
36  the interpolation and also a fraction of the distance to the next
37  point. That is converted into a linear position and multiplied by a
38  to properly index the data for the offset and to a combined weight
39  to apply to all 16 corner points
40 
41  W. Robinson, SAIC, 3 Aug 2023
42 
43 */
44  {
45  int32_t ndim = 4, base_ix[4];
46  int32_t idim, idim0, idim1, idim2, idim3;
47  int32_t int_off0, int_off1, int_off2, int_off3;
48  int64_t base_off, ixoff;
49  float int_wt0, int_wt1, int_wt2, int_wt3;
50  float base, frac_ix[4], delta[4], bounds[2];
51 
52  for( idim = 0; idim < ndim; idim++ )
53  {
54  // check for bounds violation
55  if( sxax[idim][0] < sxax[idim][snax[idim]-1] )
56  {
57  bounds[0] = sxax[idim][0];
58  bounds[1] = sxax[idim][snax[idim]-1];
59  }
60  else
61  {
62  bounds[0] = sxax[idim][snax[idim]-1];
63  bounds[1] = sxax[idim][0];
64  }
65  if( ( x[idim] < bounds[0] ) || ( x[idim] > bounds[1] ) )
66  {
67  //printf( "%s - %d: I: a point is outside table bounds\n", __FILE__,
68  // __LINE__ );
69  return 1;
70  }
71  delta[idim] = sxax[idim][1] - sxax[idim][0];
72  base = ( x[idim] - sxax[idim][0] ) / delta[idim];
73  // *** for Andy's sol zen, it starts at 0.001 so I'll make it 0
74  // to match what he does FOR NOW
75  if( idim == 1 ) {
76  delta[idim] = sxax[idim][2] - sxax[idim][1];
77  base = x[idim] / delta[idim];
78  }
79  base_ix[idim] = (int32_t) base;
80  frac_ix[idim] = fmod( (double)base, 1. );
81  orig_wt[idim] = frac_ix[idim];
82  }
83  // get offset from 0 to base indicies
84  base_off = base_ix[0] + snax[0] *
85  ( base_ix[1] + snax[1] * ( base_ix[2] + snax[2] * base_ix[3] ) );
86  /*
87  * compile the locations of corners and weights here
88  */
89  ixoff = 0;
90  for( idim0 = 0; idim0 < 2; idim0++ )
91  {
92  int_wt0 = ( idim0 == 0 ) ? 1 - frac_ix[0] : frac_ix[0];
93  int_off0 = ( idim0 == 0 ) ? 0 : 1;
94  for( idim1 = 0; idim1 < 2; idim1++ )
95  {
96  int_wt1 = ( idim1 == 0 ) ? 1 - frac_ix[1] : frac_ix[1];
97  int_off1 = int_off0 + ( ( idim1 == 0 ) ? 0 : snax[0] );
98  for( idim2 = 0; idim2 < 2; idim2++ )
99  {
100  int_wt2 = ( idim2 == 0 ) ? 1 - frac_ix[2] : frac_ix[2];
101  int_off2 = int_off1 + ( ( idim2 == 0 ) ? 0 : snax[0] * snax[1] );
102  for( idim3 = 0; idim3 < 2; idim3++ )
103  {
104  int_wt3 = ( idim3 == 0 ) ? 1 - frac_ix[3] : frac_ix[3];
105  int_off3 = int_off2 + ( ( idim3 == 0 ) ?
106  0 : snax[0] * snax[1] * snax[2] );
107 
108  ar_off[ixoff] = n_block * ( base_off + int_off3 );
109  ar_wt[ixoff++] = int_wt3 * int_wt2 * int_wt1 * int_wt0;
110  }
111  }
112  }
113  }
114  return 0;
115  }
116 
117 int32_t iint_3d( int32_t snax[3], double x[3], int64_t ar_off[9],
118  float ar_wt[9], float orig_wt[3] )
119 
120  /*
121  iint_3d - get index and weights to do a 3-d interpolation. this is done
122  assuming that the input x values are in units of each axis with the
123  fractional part as the fraction of the span from 1 grid point to the next
124  (I'm not sure of the universality of this but I think it will reproduce
125  what Andy is getting)
126 
127  Returns, int32_t status 0 is good 1 - outside range
128 
129  Parameters: (in calling order)
130  Type Name I/O Description
131  ---- ---- --- -----------
132  int32_t [3] snax I size of each axis
133  double [3] x I value of point on each axis
134  int64_t [9] ar_off O linear offset to each corner pt
135  float [9] ar_wt O weight for each corner pt
136  float [3] orig_wt O the weights from the low point
137 
138  W. Robinson, SAIC, 22 Aug 2023
139 
140 */
141  {
142  int32_t ndim = 3, base_ix[3];
143  int32_t idim, idim0, idim1, idim2;
144  int32_t int_off0, int_off1, int_off2;
145  int64_t base_off, ixoff;
146  float int_wt0, int_wt1, int_wt2;
147  float base, frac_ix[3], bounds[2];
148 
149  for( idim = 0; idim < ndim; idim++ )
150  {
151  bounds[0] = 0;
152  bounds[1] = snax[idim] - 1;
153  // check for bounds violation
154  if( ( x[idim] < bounds[0] ) || ( x[idim] > bounds[1] ) )
155  {
156  // printf( "%s - %d: E: a point is outside table bounds\n", __FILE__,
157  // __LINE__ );
158  // exit(1);
159  // quick fix is to move point in-bounds
160  if( x[idim] < bounds[0] ) x[idim] = bounds[0];
161  if( x[idim] > bounds[1] ) x[idim] = bounds[1];
162  }
163  // steps are 1, so delta = 1
164  base = x[idim];
165  base_ix[idim] = (int32_t) base;
166  frac_ix[idim] = fmod( (double)base, 1. );
167  orig_wt[idim] = frac_ix[idim];
168  }
169  // get offset from 0 to base indicies
170  base_off = base_ix[0] + snax[0] * ( base_ix[1] + snax[1] * base_ix[2] );
171  /*
172  * compile the locations of corners and weights here
173  */
174  ixoff = 0;
175  for( idim0 = 0; idim0 < 2; idim0++ )
176  {
177  int_wt0 = ( idim0 == 0 ) ? 1 - frac_ix[0] : frac_ix[0];
178  int_off0 = ( ( idim0 == 0 ) || ( base_ix[0] == snax[0] - 1 ) ) ? 0 : 1;
179  for( idim1 = 0; idim1 < 2; idim1++ )
180  {
181  int_wt1 = ( idim1 == 0 ) ? 1 - frac_ix[1] : frac_ix[1];
182  int_off1 = int_off0 +
183  ( ( ( idim1 == 0 ) || ( base_ix[1] == snax[1] - 1 ) ) ? 0 : snax[0] );
184  for( idim2 = 0; idim2 < 2; idim2++ )
185  {
186  int_wt2 = ( idim2 == 0 ) ? 1 - frac_ix[2] : frac_ix[2];
187  int_off2 = int_off1 +
188  ( ( ( idim2 == 0 ) || ( base_ix[2] == snax[2] - 1 ) ) ?
189  0 : snax[0] * snax[1] );
190  ar_off[ixoff] = ( base_off + int_off2 );
191  ar_wt[ixoff++] = int_wt2 * int_wt1 * int_wt0;
192  }
193  }
194  }
195  return 0;
196  }
float32 base
Definition: maplists.h:106
dictionary bounds
const double delta
int32_t iint_3d(int32_t snax[3], double x[3], int64_t ar_off[9], float ar_wt[9], float orig_wt[3])
Definition: int_4d.c:117
int32_t int_4d(float *sxax[4], int32_t snax[4], int64_t n_block, float x[4], int64_t ar_off[16], float ar_wt[16], float orig_wt[4])
Definition: int_4d.c:12