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 TotalEnergies
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 #if !defined(__CUDA_ARCH__) && !defined(__HIP_DEVICE_COMPILE__)
205  printf( "Interpolation warning: axis coordinate is out of limits (%lf; %lf) with value %lf, extrapolation is applied\n", axisMin, axisMax, axisCoordinate );
206 #endif
207  }
208  }
209  else if( axisIntervalIndex > (axisPoints - 2))
210  {
211  axisIntervalIndex = axisPoints - 2;
212  if( axisCoordinate > axisMax )
213  {
214 #if !defined(__CUDA_ARCH__) && !defined(__HIP_DEVICE_COMPILE__)
215  printf( "Interpolation warning: axis coordinate is out of limits (%lf; %lf) with value %lf, extrapolation is applied\n", axisMin, axisMax, axisCoordinate );
216 #endif
217  }
218  }
219 
220  axisLow = axisIntervalIndex * axisStep + axisMin;
221  axisMult = (axisCoordinate - axisLow) * axisStepInv;
222  return axisIntervalIndex;
223  }
224 
235  template< typename IN_ARRAY, typename OUT_ARRAY >
237  inline
238  void
239  interpolatePoint( IN_ARRAY const & axisCoordinates,
240  real64 const * const hypercubeData,
241  real64 const * const axisLows,
242  real64 const * const axisStepInvs,
243  OUT_ARRAY && values ) const
244  {
245  integer pwr = numVerts / 2; // distance between high and low values
246  real64 workspace[numVerts][numOps];
247 
248  // copy operator values for all vertices
249  for( integer i = 0; i < numVerts; ++i )
250  {
251  for( integer j = 0; j < numOps; ++j )
252  {
253  workspace[i][j] = hypercubeData[i * numOps + j];
254  }
255  }
256 
257  for( integer i = 0; i < numDims; ++i )
258  {
259 
260  for( integer j = 0; j < pwr; ++j )
261  {
262  for( integer op = 0; op < numOps; ++op )
263  {
264  // update own derivative
265  workspace[j][op] += (axisCoordinates[i] - axisLows[i]) * (workspace[j + pwr][op] - workspace[j][op]) * axisStepInvs[i];
266  }
267  }
268  pwr /= 2;
269  }
270  for( integer op = 0; op < numOps; ++op )
271  {
272  values[op] = workspace[0][op];
273  }
274  }
275 
276 
289  template< typename IN_ARRAY, typename OUT_ARRAY, typename OUT_2D_ARRAY >
291  inline
292  void
293  interpolatePointWithDerivatives( IN_ARRAY const & axisCoordinates,
294  real64 const * const hypercubeData,
295  real64 const * const axisLows,
296  real64 const * const axisMults,
297  real64 const * const axisStepInvs,
298  OUT_ARRAY && values,
299  OUT_2D_ARRAY && derivatives ) const
300  {
301  integer pwr = numVerts / 2; // distance between high and low values
302  real64 workspace[2 * numVerts - 1][numOps];
303 
304  // copy operator values for all vertices
305  for( integer i = 0; i < numVerts; ++i )
306  {
307  for( integer j = 0; j < numOps; ++j )
308  {
309  workspace[i][j] = hypercubeData[i * numOps + j];
310  }
311  }
312 
313  for( integer i = 0; i < numDims; ++i )
314  {
315 
316  for( integer j = 0; j < pwr; ++j )
317  {
318  for( integer op = 0; op < numOps; ++op )
319  {
320  // update own derivative
321  workspace[2 * numVerts - (numVerts >> i) + j][op] = (workspace[j + pwr][op] - workspace[j][op]) * axisStepInvs[i];
322  }
323 
324  // update all dependent derivatives
325  for( integer k = 0; k < i; k++ )
326  {
327  for( integer op = 0; op < numOps; ++op )
328  {
329  workspace[2 * numVerts - (numVerts >> k) + j][op] = workspace[2 * numVerts - (numVerts >> k) + j][op] + axisMults[i] *
330  (workspace[2 * numVerts - (numVerts >> k) + j + pwr][op] -
331  workspace[2 * numVerts - (numVerts >> k) + j][op]);
332  }
333  }
334 
335  for( integer op = 0; op < numOps; ++op )
336  {
337  // interpolate value
338  workspace[j][op] = workspace[j][op] + (axisCoordinates[i] - axisLows[i]) * workspace[2 * numVerts - (numVerts >> i) + j][op];
339  }
340  }
341  pwr /= 2;
342  }
343  for( integer op = 0; op < numOps; ++op )
344  {
345  values[op] = workspace[0][op];
346  for( integer i = 0; i < numDims; ++i )
347  {
348  derivatives[op][i] = workspace[2 * numVerts - (numVerts >> i)][op];
349  }
350  }
351  }
352 
353  // inputs : table discretization data
354 
357 
360 
363 
364  // inputs : service data derived from table discretization data
365 
368 
371 
374 
375  // inputs: operator sample data
376 
379 
380  // inputs: where to interpolate
381 
384 };
385 
386 } /* namespace geos */
387 
388 #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< 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:179
GEOS_GLOBALINDEX_TYPE globalIndex
Global index type (for indexing objects across MPI partitions).
Definition: DataTypes.hpp:87
double real64
64-bit floating point type.
Definition: DataTypes.hpp:98
int integer
Signed integer type.
Definition: DataTypes.hpp:81