GEOS
MultivariableTableFunctionKernels.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 Total, S.A
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
20 #ifndef GEOS_FUNCTIONS_MULTIVARIABLETABLEFUNCTIONKERNELS_HPP_
21 #define GEOS_FUNCTIONS_MULTIVARIABLETABLEFUNCTIONKERNELS_HPP_
22 
23 namespace geos
24 {
25 
26 
27 
43 template< integer NUM_DIMS, integer NUM_OPS >
45 {
46 public:
47 
49  static constexpr integer numDims = NUM_DIMS;
50 
52  static constexpr integer numOps = NUM_OPS;
53 
55  static constexpr integer numVerts = 1 << numDims;
56 
57 
70  arrayView1d< real64 const > const & axisMaximums,
71  arrayView1d< integer const > const & axisPoints,
72  arrayView1d< real64 const > const & axisSteps,
73  arrayView1d< real64 const > const & axisStepInvs,
74  arrayView1d< globalIndex const > const & axisHypercubeMults,
75  arrayView1d< real64 const > const & hypercubeData ):
76  m_axisMinimums ( axisMinimums ),
77  m_axisMaximums ( axisMaximums ),
78  m_axisPoints ( axisPoints ),
79  m_axisSteps ( axisSteps ),
80  m_axisStepInvs ( axisStepInvs ),
81  m_axisHypercubeMults ( axisHypercubeMults ),
82  m_hypercubeData ( hypercubeData )
83  {};
84 
91  template< typename IN_ARRAY, typename OUT_ARRAY >
93  void
94  compute( IN_ARRAY const & coordinates,
95  OUT_ARRAY && values ) const
96  {
97  globalIndex hypercubeIndex = 0;
98  real64 axisLows[numDims];
99  real64 axisMults[numDims];
100 
101  for( int i = 0; i < numDims; ++i )
102  {
103  integer const axisIndex = getAxisIntervalIndexLowMult( coordinates[i],
106  axisLows[i], axisMults[i] );
107  hypercubeIndex += axisIndex * m_axisHypercubeMults[i];
108  }
109 
110  interpolatePoint( coordinates,
111  getHypercubeData( hypercubeIndex ),
112  &axisLows[0],
113  &m_axisStepInvs[0],
114  values );
115  }
116 
124  template< typename IN_ARRAY, typename OUT_ARRAY, typename OUT_2D_ARRAY >
126  void
127  compute( IN_ARRAY const & coordinates,
128  OUT_ARRAY && values,
129  OUT_2D_ARRAY && derivatives ) const
130  {
131  globalIndex hypercubeIndex = 0;
132  real64 axisLows[numDims];
133  real64 axisMults[numDims];
134 
135  for( int i = 0; i < numDims; ++i )
136  {
137  integer const axisIndex = getAxisIntervalIndexLowMult( coordinates[i],
140  axisLows[i], axisMults[i] );
141  hypercubeIndex += axisIndex * m_axisHypercubeMults[i];
142  }
143 
144  interpolatePointWithDerivatives( coordinates,
145  getHypercubeData( hypercubeIndex ),
146  &axisLows[0], &axisMults[0],
147  &m_axisStepInvs[0],
148  values,
149  derivatives );
150 
151  }
152 
153 protected:
154 
162  inline
163  real64 const *
164  getHypercubeData( globalIndex const hypercubeIndex ) const
165  {
166  return &m_hypercubeData[hypercubeIndex * numVerts * numOps];
167  }
168 
183  inline
184  integer
185  getAxisIntervalIndexLowMult( real64 const axisCoordinate,
186  real64 const axisMin,
187  real64 const axisMax,
188  real64 const axisStep,
189  real64 const axisStepInv,
190  integer const axisPoints,
191  real64 & axisLow,
192  real64 & axisMult ) const
193  {
194  integer axisIntervalIndex = integer((axisCoordinate - axisMin) * axisStepInv );
195 
196  // check that axisindex is within interpolation interval: valid axisindex is between 0 and (axisPoints - 2),
197  // since there are axisPoints-1 intervals along the axis
198 
199  if( axisIntervalIndex < 0 )
200  {
201  axisIntervalIndex = 0;
202  if( axisCoordinate < axisMin )
203  {
204  printf( "Interpolation warning: axis coordinate is out of limits (%lf; %lf) with value %lf, extrapolation is applied\n", axisMin, axisMax, axisCoordinate );
205  }
206  }
207  else if( axisIntervalIndex > (axisPoints - 2))
208  {
209  axisIntervalIndex = axisPoints - 2;
210  if( axisCoordinate > axisMax )
211  {
212  printf( "Interpolation warning: axis coordinate is out of limits (%lf; %lf) with value %lf, extrapolation is applied\n", axisMin, axisMax, axisCoordinate );
213  }
214  }
215 
216  axisLow = axisIntervalIndex * axisStep + axisMin;
217  axisMult = (axisCoordinate - axisLow) * axisStepInv;
218  return axisIntervalIndex;
219  }
220 
231  template< typename IN_ARRAY, typename OUT_ARRAY >
233  inline
234  void
235  interpolatePoint( IN_ARRAY const & axisCoordinates,
236  real64 const * const hypercubeData,
237  real64 const * const axisLows,
238  real64 const * const axisStepInvs,
239  OUT_ARRAY && values ) const
240  {
241  integer pwr = numVerts / 2; // distance between high and low values
242  real64 workspace[numVerts][numOps];
243 
244  // copy operator values for all vertices
245  for( integer i = 0; i < numVerts; ++i )
246  {
247  for( integer j = 0; j < numOps; ++j )
248  {
249  workspace[i][j] = hypercubeData[i * numOps + j];
250  }
251  }
252 
253  for( integer i = 0; i < numDims; ++i )
254  {
255 
256  for( integer j = 0; j < pwr; ++j )
257  {
258  for( integer op = 0; op < numOps; ++op )
259  {
260  // update own derivative
261  workspace[j][op] += (axisCoordinates[i] - axisLows[i]) * (workspace[j + pwr][op] - workspace[j][op]) * axisStepInvs[i];
262  }
263  }
264  pwr /= 2;
265  }
266  for( integer op = 0; op < numOps; ++op )
267  {
268  values[op] = workspace[0][op];
269  }
270  }
271 
272 
285  template< typename IN_ARRAY, typename OUT_ARRAY, typename OUT_2D_ARRAY >
287  inline
288  void
289  interpolatePointWithDerivatives( IN_ARRAY const & axisCoordinates,
290  real64 const * const hypercubeData,
291  real64 const * const axisLows,
292  real64 const * const axisMults,
293  real64 const * const axisStepInvs,
294  OUT_ARRAY && values,
295  OUT_2D_ARRAY && derivatives ) const
296  {
297  integer pwr = numVerts / 2; // distance between high and low values
298  real64 workspace[2 * numVerts - 1][numOps];
299 
300  // copy operator values for all vertices
301  for( integer i = 0; i < numVerts; ++i )
302  {
303  for( integer j = 0; j < numOps; ++j )
304  {
305  workspace[i][j] = hypercubeData[i * numOps + j];
306  }
307  }
308 
309  for( integer i = 0; i < numDims; ++i )
310  {
311 
312  for( integer j = 0; j < pwr; ++j )
313  {
314  for( integer op = 0; op < numOps; ++op )
315  {
316  // update own derivative
317  workspace[2 * numVerts - (numVerts >> i) + j][op] = (workspace[j + pwr][op] - workspace[j][op]) * axisStepInvs[i];
318  }
319 
320  // update all dependent derivatives
321  for( integer k = 0; k < i; k++ )
322  {
323  for( integer op = 0; op < numOps; ++op )
324  {
325  workspace[2 * numVerts - (numVerts >> k) + j][op] = workspace[2 * numVerts - (numVerts >> k) + j][op] + axisMults[i] *
326  (workspace[2 * numVerts - (numVerts >> k) + j + pwr][op] -
327  workspace[2 * numVerts - (numVerts >> k) + j][op]);
328  }
329  }
330 
331  for( integer op = 0; op < numOps; ++op )
332  {
333  // interpolate value
334  workspace[j][op] = workspace[j][op] + (axisCoordinates[i] - axisLows[i]) * workspace[2 * numVerts - (numVerts >> i) + j][op];
335  }
336  }
337  pwr /= 2;
338  }
339  for( integer op = 0; op < numOps; ++op )
340  {
341  values[op] = workspace[0][op];
342  for( integer i = 0; i < numDims; ++i )
343  {
344  derivatives[op][i] = workspace[2 * numVerts - (numVerts >> i)][op];
345  }
346  }
347  }
348 
349  // inputs : table discretization data
350 
353 
356 
359 
360  // inputs : service data derived from table discretization data
361 
364 
367 
370 
371  // inputs: operator sample data
372 
375 
376  // inputs: where to interpolate
377 
380 
381  // outputs
382 
385 
388 };
389 
390 } /* namespace geos */
391 
392 #endif /* GEOS_FUNCTIONS_MULTIVARIABLETABLEFUNCTIONKERNELS_HPP_ */
#define GEOS_HOST_DEVICE
Marks a host-device function.
Definition: GeosxMacros.hpp:49
GEOS_HOST_DEVICE void compute(IN_ARRAY const &coordinates, OUT_ARRAY &&values) const
interpolate all operators at a given point
arrayView1d< real64 const > m_axisMinimums
Array [numDims] of axis minimum values.
arrayView1d< real64 const > m_coordinates
Coordinates in numDims-dimensional space where interpolation is requested.
arrayView1d< real64 > m_derivatives
/// Interpolated derivatives
arrayView1d< globalIndex const > m_axisHypercubeMults
Array [numDims] of hypercube index mult factors for each axis.
arrayView1d< real64 const > m_axisStepInvs
Array [numDims] of inversions of axis interval lengths (axes are discretized uniformly)
arrayView1d< real64 const > m_hypercubeData
Main table data stored per hypercube: all values required for interpolation withing give hypercube ar...
MultivariableTableFunctionStaticKernel(arrayView1d< real64 const > const &axisMinimums, arrayView1d< real64 const > const &axisMaximums, arrayView1d< integer const > const &axisPoints, arrayView1d< real64 const > const &axisSteps, arrayView1d< real64 const > const &axisStepInvs, arrayView1d< globalIndex const > const &axisHypercubeMults, arrayView1d< real64 const > const &hypercubeData)
Construct a new Multivariable Table Function Static Kernel object.
GEOS_HOST_DEVICE void interpolatePointWithDerivatives(IN_ARRAY const &axisCoordinates, real64 const *const hypercubeData, real64 const *const axisLows, real64 const *const axisMults, real64 const *const axisStepInvs, OUT_ARRAY &&values, OUT_2D_ARRAY &&derivatives) const
interpolate all operators values and derivatives at a given point The algoritm is based on http://dx....
GEOS_HOST_DEVICE real64 const * getHypercubeData(globalIndex const hypercubeIndex) const
Get pointer to hypercube data.
static constexpr integer numOps
Compile time value for the number of operators (interpolated functions, outputs)
static constexpr integer numVerts
Compile time value for the number of hypercube vertices.
GEOS_HOST_DEVICE void interpolatePoint(IN_ARRAY const &axisCoordinates, real64 const *const hypercubeData, real64 const *const axisLows, real64 const *const axisStepInvs, OUT_ARRAY &&values) const
interpolate all operators values at a given point The algoritm is based on http://dx....
GEOS_HOST_DEVICE integer getAxisIntervalIndexLowMult(real64 const axisCoordinate, real64 const axisMin, real64 const axisMax, real64 const axisStep, real64 const axisStepInv, integer const axisPoints, real64 &axisLow, real64 &axisMult) const
Get the interval index, low and mult values for a given axis coordinate.
arrayView1d< integer const > m_axisPoints
Array [numDims] of axis discretization points.
arrayView1d< real64 const > m_axisMaximums
Array [numDims] of axis maximum values.
GEOS_HOST_DEVICE void compute(IN_ARRAY const &coordinates, OUT_ARRAY &&values, OUT_2D_ARRAY &&derivatives) const
interpolate all operators and compute their derivatives at a given point
arrayView1d< real64 const > m_axisSteps
Array [numDims] of axis interval lengths (axes are discretized uniformly)
static constexpr integer numDims
Compile time value for the number of table dimensions (inputs)
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
Definition: DataTypes.hpp:180
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
Definition: DataTypes.hpp:88
double real64
64-bit floating point type.
Definition: DataTypes.hpp:99
std::int32_t integer
Signed integer type.
Definition: DataTypes.hpp:82