Compadre  1.5.9
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Compadre_Evaluator.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Compadre: COMpatible PArticle Discretization and REmap Toolkit
4 //
5 // Copyright 2018 NTESS and the Compadre contributors.
6 // SPDX-License-Identifier: BSD-2-Clause
7 // *****************************************************************************
8 // @HEADER
9 #ifndef _COMPADRE_EVALUATOR_HPP_
10 #define _COMPADRE_EVALUATOR_HPP_
11 
12 #include "Compadre_Typedefs.hpp"
13 #include "Compadre_GMLS.hpp"
15 
16 namespace Compadre {
17 
18 //! Creates 1D subviews of data from a 2D view, generally constructed with CreateNDSliceOnDeviceView
19 template<typename T, typename T2, typename T3=void>
20 struct SubviewND {
21 
25 
26  SubviewND(T data_in, T2 data_original_view, bool scalar_as_vector_if_needed) {
27  _data_in = data_in;
28  _data_original_view = data_original_view;
29  _scalar_as_vector_if_needed = scalar_as_vector_if_needed;
30  }
31 
32  auto get1DView(const int column_num) -> decltype(Kokkos::subview(_data_in, Kokkos::ALL, column_num)) {
34  compadre_assert_debug(((size_t)column_num<_data_in.extent(1))
35  && "Subview asked for column > second dimension of input data.");
36  }
37  if ((size_t)column_num<_data_in.extent(1))
38  return Kokkos::subview(_data_in, Kokkos::ALL, column_num);
39  else // scalar treated as a vector (being reused for each component of the vector input that was expected)
40  return Kokkos::subview(_data_in, Kokkos::ALL, 0);
41  }
42 
43  auto get2DView(const int column_num, const int block_size) -> decltype(Kokkos::subview(_data_in, Kokkos::ALL,
44  Kokkos::make_pair(column_num*block_size, (column_num+1)*block_size))) {
46  compadre_assert_debug(((size_t)((column_num+1)*block_size-1)<_data_in.extent(1))
47  && "Subview asked for column > second dimension of input data.");
48  }
49  if ((size_t)((column_num+1)*block_size-1)<_data_in.extent(1)) {
50  return Kokkos::subview(_data_in, Kokkos::ALL, Kokkos::make_pair(column_num*block_size, (column_num+1)*block_size));
51  } else {
52  compadre_assert_debug(((size_t)(block_size-1)<_data_in.extent(1)) && "Subview asked for column > second dimension of input data.");
53  return Kokkos::subview(_data_in, Kokkos::ALL, Kokkos::make_pair(0,block_size));
54  }
55  }
56 
58  Kokkos::deep_copy(_data_original_view, _data_in);
59  Kokkos::fence();
60  return _data_original_view;
61  }
62 
63 };
64 
65 //! Creates 1D subviews of data from a 1D view, generally constructed with CreateNDSliceOnDeviceView
66 template<typename T, typename T2>
67 struct SubviewND<T, T2, enable_if_t<(T::rank<2)> >
68 {
69 
70  T _data_in;
73 
74  SubviewND(T data_in, T2 data_original_view, bool scalar_as_vector_if_needed) {
75  _data_in = data_in;
76  _data_original_view = data_original_view;
77  _scalar_as_vector_if_needed = scalar_as_vector_if_needed;
78  }
79 
80  auto get1DView(const int column_num) -> decltype(Kokkos::subview(_data_in, Kokkos::ALL)) {
81  // TODO: There is a valid use case for violating this assert, so in the future we may want
82  // to add other logic to the evaluator function calling this so that it knows to do nothing with
83  // this data.
85  compadre_assert_debug((column_num==0) && "Subview asked for column column_num!=0, but _data_in is rank 1.");
86  }
87  return Kokkos::subview(_data_in, Kokkos::ALL);
88  }
89 
90  auto get2DView(const int column_num, const int block_size) -> decltype(Kokkos::subview(_data_in, Kokkos::ALL)) {
91  compadre_assert_release((block_size==1) && "2D subview requested not compatible with one column.");
92  return Kokkos::subview(_data_in, Kokkos::ALL);
93  }
94 
96  Kokkos::deep_copy(_data_original_view, _data_in);
97  Kokkos::fence();
98  return _data_original_view;
99  }
100 
101 };
102 
103 //! Copies data_in to the device, and then allows for access to 1D columns of data on device.
104 //! Handles either 2D or 1D views as input, and they can be on the host or the device.
105 template <typename T>
106 auto CreateNDSliceOnDeviceView(T sampling_input_data_host_or_device, bool scalar_as_vector_if_needed) -> SubviewND<decltype(Kokkos::create_mirror_view(
107  device_memory_space(), sampling_input_data_host_or_device)), T> {
108 
109  // makes view on the device (does nothing if already on the device)
110  auto sampling_input_data_device = Kokkos::create_mirror_view(
111  device_memory_space(), sampling_input_data_host_or_device);
112  Kokkos::deep_copy(sampling_input_data_device, sampling_input_data_host_or_device);
113  Kokkos::fence();
114 
115  return SubviewND<decltype(sampling_input_data_device),T>(sampling_input_data_device,
116  sampling_input_data_host_or_device, scalar_as_vector_if_needed);
117 }
118 
119 //! \brief Lightweight Evaluator Helper
120 //! This class is a lightweight wrapper for extracting and applying all relevant data from a GMLS class
121 //! in order to transform data into a form that can be acted on by the GMLS operator, apply the action of
122 //! the GMLS operator, and then transform data again (only if on a manifold)
123 class Evaluator {
124 
125 private:
126 
128 
129 
130 public:
131 
132  Evaluator(GMLS *gmls) : _gmls(gmls) {
133  Kokkos::fence();
134  };
135 
137 
138  //! Dot product of alphas with sampling data, FOR A SINGLE target_index, where sampling data is in a 1D/2D Kokkos View
139  //!
140  //! This function is to be used when the alpha values have already been calculated and stored for use
141  //!
142  //! Only supports one output component / input component at a time. The user will need to loop over the output
143  //! components in order to fill a vector target or matrix target.
144  //!
145  //! Assumptions on input data:
146  //! \param sampling_input_data [in] - 1D/2D Kokkos View (no restriction on memory space)
147  //! \param column_of_input [in] - Column of sampling_input_data to use for this input component
148  //! \param lro [in] - Target operation from the TargetOperation enum
149  //! \param target_index [in] - Target # user wants to reconstruct target functional at, corresponds to row number of neighbor_lists
150  //! \param output_component_axis_1 [in] - Row for a rank 2 tensor or rank 1 tensor, 0 for a scalar output
151  //! \param output_component_axis_2 [in] - Columns for a rank 2 tensor, 0 for rank less than 2 output tensor
152  //! \param input_component_axis_1 [in] - Row for a rank 2 tensor or rank 1 tensor, 0 for a scalar input
153  //! \param input_component_axis_2 [in] - Columns for a rank 2 tensor, 0 for rank less than 2 input tensor
154  //! \param scalar_as_vector_if_needed [in] - If a 1D view is given, where a 2D view is expected (scalar values given where a vector was expected), then the scalar will be repeated for as many components as the vector has
155  template <typename view_type_data>
156  double applyAlphasToDataSingleComponentSingleTargetSite(view_type_data sampling_input_data, const int column_of_input, TargetOperation lro, const int target_index, const int evaluation_site_local_index, const int output_component_axis_1, const int output_component_axis_2, const int input_component_axis_1, const int input_component_axis_2, bool scalar_as_vector_if_needed = true) const {
157 
158  double value = 0;
159 
160  const int alpha_input_output_component_index = _gmls->_h_ss.getAlphaColumnOffset(lro, output_component_axis_1,
161  output_component_axis_2, input_component_axis_1, input_component_axis_2, evaluation_site_local_index);
162 
163  auto sampling_subview_maker = CreateNDSliceOnDeviceView(sampling_input_data, scalar_as_vector_if_needed);
164 
165 
166  // gather needed information for evaluation
167  auto nla = *(_gmls->getNeighborLists());
168  auto alphas = _gmls->getSolutionSetDevice()->getAlphas();
169  auto sampling_data_device = sampling_subview_maker.get1DView(column_of_input);
170 
171  auto alpha_index = _gmls->_h_ss.getAlphaIndex(target_index, alpha_input_output_component_index);
172  // loop through neighbor list for this target_index
173  // grabbing data from that entry of data
174  Kokkos::parallel_reduce("applyAlphasToData::Device",
175  Kokkos::RangePolicy<device_execution_space>(0,nla.getNumberOfNeighborsHost(target_index)),
176  KOKKOS_LAMBDA(const int i, double& t_value) {
177 
178  t_value += sampling_data_device(nla.getNeighborDevice(target_index, i))
179  *alphas(alpha_index + i);
180 
181  }, value );
182  Kokkos::fence();
183 
184  return value;
185  }
186 
187  //! Dot product of alphas with sampling data where sampling data is in a 1D/2D Kokkos View and output view is also
188  //! a 1D/2D Kokkos View, however THE SAMPLING DATA and OUTPUT VIEW MUST BE ON THE DEVICE!
189  //!
190  //! This function is to be used when the alpha values have already been calculated and stored for use.
191  //!
192  //! Only supports one output component / input component at a time. The user will need to loop over the output
193  //! components in order to fill a vector target or matrix target.
194  //!
195  //! Assumptions on input data:
196  //! \param output_data_single_column [out] - 1D Kokkos View (memory space must be device_memory_space())
197  //! \param sampling_data_single_column [in] - 1D Kokkos View (memory space must match output_data_single_column)
198  //! \param lro [in] - Target operation from the TargetOperation enum
199  //! \param sro [in] - Sampling functional from the SamplingFunctional enum
200  //! \param evaluation_site_local_index [in] - local column index of site from additional evaluation sites list or 0 for the target site
201  //! \param output_component_axis_1 [in] - Row for a rank 2 tensor or rank 1 tensor, 0 for a scalar output
202  //! \param output_component_axis_2 [in] - Columns for a rank 2 tensor, 0 for rank less than 2 output tensor
203  //! \param input_component_axis_1 [in] - Row for a rank 2 tensor or rank 1 tensor, 0 for a scalar input
204  //! \param input_component_axis_2 [in] - Columns for a rank 2 tensor, 0 for rank less than 2 input tensor
205  //! \param pre_transform_local_index [in] - For manifold problems, this is the local coordinate direction that sampling data may need to be transformed to before the application of GMLS
206  //! \param pre_transform_global_index [in] - For manifold problems, this is the global coordinate direction that sampling data can be represented in
207  //! \param post_transform_local_index [in] - For manifold problems, this is the local coordinate direction that vector output target functionals from GMLS will output into
208  //! \param post_transform_global_index [in] - For manifold problems, this is the global coordinate direction that the target functional output from GMLS will be transformed into
209  //! \param transform_output_ambient [in] - Whether or not a 1D output from GMLS is on the manifold and needs to be mapped to ambient space
210  //! \param vary_on_target [in] - Whether the sampling functional has a tensor to act on sampling data that varies with each target site
211  //! \param vary_on_neighbor [in] - Whether the sampling functional has a tensor to act on sampling data that varies with each neighbor site in addition to varying wit each target site
212  template <typename view_type_data_out, typename view_type_data_in>
213  void applyAlphasToDataSingleComponentAllTargetSitesWithPreAndPostTransform(view_type_data_out output_data_single_column, view_type_data_in sampling_data_single_column, TargetOperation lro, const SamplingFunctional sro, const int evaluation_site_local_index, const int output_component_axis_1, const int output_component_axis_2, const int input_component_axis_1, const int input_component_axis_2, const int pre_transform_local_index = -1, const int pre_transform_global_index = -1, const int post_transform_local_index = -1, const int post_transform_global_index = -1, bool vary_on_target = false, bool vary_on_neighbor = false) const {
214 
215  const int alpha_input_output_component_index = _gmls->_h_ss.getAlphaColumnOffset(lro, output_component_axis_1,
216  output_component_axis_2, input_component_axis_1, input_component_axis_2, evaluation_site_local_index);
217  const int alpha_input_output_component_index2 = alpha_input_output_component_index;
218 
219  // gather needed information for evaluation
220  auto nla = *(_gmls->getNeighborLists());
221  auto solution_set = *(_gmls->getSolutionSetDevice());
222  compadre_assert_release(solution_set._contains_valid_alphas &&
223  "application of alphas called before generateAlphas() was called.");
224  auto prestencil_weights = _gmls->getPrestencilWeights();
225 
226  const int num_targets = nla.getNumberOfTargets();
227 
228  // make sure input and output views have same memory space
229  compadre_assert_debug((std::is_same<typename view_type_data_out::memory_space, typename view_type_data_in::memory_space>::value) &&
230  "output_data_single_column view and input_data_single_column view have difference memory spaces.");
231 
232  bool weight_with_pre_T = (pre_transform_local_index>=0 && pre_transform_global_index>=0) ? true : false;
233  bool target_plus_neighbor_staggered_schema = sro.use_target_site_weights;
234 
235  // loops over target indices
236  Kokkos::parallel_for(team_policy(num_targets, Kokkos::AUTO),
237  KOKKOS_LAMBDA(const member_type& teamMember) {
238 
239  const int target_index = teamMember.league_rank();
240  teamMember.team_barrier();
241 
242 
243  const double previous_value = output_data_single_column(target_index);
244 
245  // loops over neighbors of target_index
246  auto alpha_index = solution_set.getAlphaIndex(target_index, alpha_input_output_component_index);
247  double gmls_value = 0;
248  Kokkos::parallel_reduce(Kokkos::TeamThreadRange(teamMember, nla.getNumberOfNeighborsDevice(target_index)), [&](const int i, double& t_value) {
249  const double neighbor_varying_pre_T = (weight_with_pre_T && vary_on_neighbor) ?
250  prestencil_weights(0, target_index, i, pre_transform_local_index, pre_transform_global_index)
251  : 1.0;
252 
253  t_value += neighbor_varying_pre_T * sampling_data_single_column(nla.getNeighborDevice(target_index, i))
254  *solution_set._alphas(alpha_index + i);
255 
256  }, gmls_value );
257 
258  // data contract for sampling functional
259  double pre_T = 1.0;
260  if (weight_with_pre_T) {
261  if (!vary_on_neighbor && vary_on_target) {
262  pre_T = prestencil_weights(0, target_index, 0, pre_transform_local_index,
263  pre_transform_global_index);
264  } else if (!vary_on_target) { // doesn't vary on target or neighbor
265  pre_T = prestencil_weights(0, 0, 0, pre_transform_local_index,
266  pre_transform_global_index);
267  }
268  }
269 
270  double staggered_value_from_targets = 0;
271  double pre_T_staggered = 1.0;
272  auto alpha_index2 = solution_set.getAlphaIndex(target_index, alpha_input_output_component_index2);
273  // loops over target_index for each neighbor for staggered approaches
274  if (target_plus_neighbor_staggered_schema) {
275  Kokkos::parallel_reduce(Kokkos::TeamThreadRange(teamMember, nla.getNumberOfNeighborsDevice(target_index)), [&](const int i, double& t_value) {
276  const double neighbor_varying_pre_T_staggered = (weight_with_pre_T && vary_on_neighbor) ?
277  prestencil_weights(1, target_index, i, pre_transform_local_index, pre_transform_global_index)
278  : 1.0;
279 
280  t_value += neighbor_varying_pre_T_staggered * sampling_data_single_column(nla.getNeighborDevice(target_index, 0))
281  *solution_set._alphas(alpha_index2 + i);
282 
283  }, staggered_value_from_targets );
284 
285  // for staggered approaches that transform source data for the target and neighbors
286  if (weight_with_pre_T) {
287  if (!vary_on_neighbor && vary_on_target) {
288  pre_T_staggered = prestencil_weights(1, target_index, 0, pre_transform_local_index,
289  pre_transform_global_index);
290  } else if (!vary_on_target) { // doesn't vary on target or neighbor
291  pre_T_staggered = prestencil_weights(1, 0, 0, pre_transform_local_index,
292  pre_transform_global_index);
293  }
294  }
295  }
296 
297  double added_value = pre_T*gmls_value + pre_T_staggered*staggered_value_from_targets;
298  Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
299  output_data_single_column(target_index) = previous_value + added_value;
300  });
301  });
302  Kokkos::fence();
303  }
304 
305  //! Postprocessing for manifolds. Maps local chart vector solutions to ambient space.
306  //! THE SAMPLING DATA and OUTPUT VIEW MUST BE ON THE DEVICE!
307  //!
308  //! Only supports one output component / input component at a time. The user will need to loop over the output
309  //! components in order to transform a vector target.
310  //!
311  //! Assumptions on input data:
312  //! \param output_data_single_column [out] - 1D Kokkos View (memory space must be device_memory_space())
313  //! \param sampling_data_single_column [in] - 1D Kokkos View (memory space must match output_data_single_column)
314  //! \param local_dim_index [in] - For manifold problems, this is the local coordinate direction that sampling data may need to be transformed to before the application of GMLS
315  //! \param global_dim_index [in] - For manifold problems, this is the global coordinate direction that sampling data can be represented in
316  template <typename view_type_data_out, typename view_type_data_in>
317  void applyLocalChartToAmbientSpaceTransform(view_type_data_out output_data_single_column, view_type_data_in sampling_data_single_column, const int local_dim_index, const int global_dim_index) const {
318 
319  // Does T transpose times a vector
320  auto global_dimensions = _gmls->getGlobalDimensions();
321 
322  // gather needed information for evaluation
323  auto nla = *(_gmls->getNeighborLists());
324  const int num_targets = nla.getNumberOfTargets();
325 
326  auto tangent_directions = *(_gmls->getTangentDirections());
327 
328  // make sure input and output views have same memory space
329  compadre_assert_debug((std::is_same<typename view_type_data_out::memory_space, typename view_type_data_in::memory_space>::value) &&
330  "output_data_single_column view and input_data_single_column view have difference memory spaces.");
331 
332  // loops over target indices
333  Kokkos::parallel_for(team_policy(num_targets, Kokkos::AUTO),
334  KOKKOS_LAMBDA(const member_type& teamMember) {
335 
336  const int target_index = teamMember.league_rank();
337 
339  (tangent_directions.data() + TO_GLOBAL(target_index)*TO_GLOBAL(global_dimensions)*TO_GLOBAL(global_dimensions),
340  global_dimensions, global_dimensions);
341  teamMember.team_barrier();
342 
343 
344  const double previous_value = output_data_single_column(target_index);
345 
346  double added_value = T(local_dim_index, global_dim_index)*sampling_data_single_column(target_index);
347  Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
348  output_data_single_column(target_index) = previous_value + added_value;
349  });
350  });
351  Kokkos::fence();
352  }
353 
354  //! Transformation of data under GMLS (allocates memory for output)
355  //!
356  //! This function is the go-to function to be used when the alpha values have already been calculated and stored for use. The sampling functional provided instructs how a data transformation tensor is to be used on source data before it is provided to the GMLS operator. Once the sampling functional (if applicable) and the GMLS operator have been applied, this function also handles mapping the local vector back to the ambient space if working on a manifold problem and a target functional who has rank 1 output.
357  //!
358  //! Produces a Kokkos View as output with a Kokkos memory_space provided as a template tag by the caller.
359  //! The data type (double* or double**) must also be specified as a template type if one wish to get a 1D
360  //! Kokkos View back that can be indexed into with only one ordinal.
361  //!
362  //! Assumptions on input data:
363  //! \param sampling_data [in] - 1D or 2D Kokkos View that has the layout #targets * columns of data. Memory space for data can be host or device.
364  //! \param lro [in] - Target operation from the TargetOperation enum
365  //! \param sro_in [in] - Sampling functional from the SamplingFunctional enum
366  //! \param scalar_as_vector_if_needed [in] - If a 1D view is given, where a 2D view is expected (scalar values given where a vector was expected), then the scalar will be repeated for as many components as the vector has
367  //! \param evaluation_site_local_index [in] - 0 corresponds to evaluating at the target site itself, while a number larger than 0 indicates evaluation at a site other than the target, and specified by calling setAdditionalEvaluationSitesData on the GMLS class
368  template <typename output_data_type = double**, typename output_memory_space, typename view_type_input_data, typename output_array_layout = typename view_type_input_data::array_layout>
369  Kokkos::View<output_data_type, output_array_layout, output_memory_space> // shares layout of input by default
370  applyAlphasToDataAllComponentsAllTargetSites(view_type_input_data sampling_data, TargetOperation lro, const SamplingFunctional sro_in = PointSample, bool scalar_as_vector_if_needed = true, const int evaluation_site_local_index = 0) const {
371  // gather needed information for evaluation
372  auto nla = *(_gmls->getNeighborLists());
373 
374  // determines the number of columns needed for output after action of the target functional
375  auto local_dimensions = _gmls->getLocalDimensions();
376  auto global_dimensions = _gmls->getGlobalDimensions();
377  int output_dimensions = getOutputDimensionOfOperation(lro, local_dimensions);
378  auto problem_type = _gmls->getProblemType();
379 
380  typedef Kokkos::View<output_data_type, output_array_layout, output_memory_space> output_view_type;
381  // create view on whatever memory space the user specified with their template argument when calling this function
382  output_view_type target_output = createView<output_view_type>("output of target operation",
383  nla.getNumberOfTargets(), output_dimensions);
384 
385  output_view_type ambient_target_output;
386  bool transform_gmls_output_to_ambient = (problem_type==MANIFOLD && getTargetOutputTensorRank(lro)==1);
387  if (transform_gmls_output_to_ambient) {
388  ambient_target_output = createView<output_view_type>("output of transform to ambient space",
389  nla.getNumberOfTargets(), global_dimensions);
390  }
391 
392  applyAlphasToDataAllComponentsAllTargetSites(target_output, ambient_target_output, sampling_data, lro, sro_in, scalar_as_vector_if_needed, evaluation_site_local_index);
393 
394  if (transform_gmls_output_to_ambient) {
395  return ambient_target_output;
396  } else {
397  return target_output;
398  }
399 
400  }
401 
402  //! Transformation of data under GMLS (does not allocate memory for output)
403  //!
404  //! If space for the output result is already allocated, this function will populate the output result view (and possibly ambient target output). The sampling functional provided instructs how a data transformation tensor is to be used on source data before it is provided to the GMLS operator. Once the sampling functional (if applicable) and the GMLS operator have been applied, this function also handles mapping the local vector back to the ambient space if working on a manifold problem and a target functional who has rank 1 output.
405  //!
406  //! Fills a Kokkos View of output.
407  //!
408  //! Assumptions on input data:
409  //! \param target_output [in] - 1D or 2D Kokkos View that has the resulting #targets * need output columns. Memory space for data can be host or device.
410  //! \param ambient_target_output [in] - Same view type as target_output, but dimensions should be #targets * global_dimension if this is being filled (if not being filled, then this can be an empty view)
411  //! \param sampling_data [in] - 1D or 2D Kokkos View that has the layout #targets * columns of data. Memory space for data can be host or device.
412  //! \param lro [in] - Target operation from the TargetOperation enum
413  //! \param sro_in [in] - Sampling functional from the SamplingFunctional enum
414  //! \param scalar_as_vector_if_needed [in] - If a 1D view is given, where a 2D view is expected (scalar values given where a vector was expected), then the scalar will be repeated for as many components as the vector has
415  //! \param evaluation_site_local_index [in] - 0 corresponds to evaluating at the target site itself, while a number larger than 0 indicates evaluation at a site other than the target, and specified by calling setAdditionalEvaluationSitesData on the GMLS class
416  template <typename view_type_output_data, typename view_type_input_data, typename output_array_layout = typename view_type_input_data::array_layout>
417  void applyAlphasToDataAllComponentsAllTargetSites(view_type_output_data target_output, view_type_output_data ambient_target_output, view_type_input_data sampling_data, TargetOperation lro, const SamplingFunctional sro_in = PointSample, bool scalar_as_vector_if_needed = true, const int evaluation_site_local_index = 0) const {
418 
419 
420  // output can be device or host
421  // input can be device or host
422  // move everything to device and calculate there, then move back to host if necessary
423 
424 
425  auto problem_type = _gmls->getProblemType();
426  auto global_dimensions = _gmls->getGlobalDimensions();
427  auto local_dimensions = _gmls->getLocalDimensions();
428  int output_dimension1_of_operator = (getTargetOutputTensorRank(lro)<2) ? getOutputDimensionOfOperation(lro, local_dimensions) : std::sqrt(getOutputDimensionOfOperation(lro, local_dimensions));
429  int output_dimension2_of_operator = (getTargetOutputTensorRank(lro)<2) ? 1 : std::sqrt(getOutputDimensionOfOperation(lro, local_dimensions));
430 
431  // gather needed information for evaluation
432  auto nla = *(_gmls->getNeighborLists());
433 
434  // determines the number of columns needed for output after action of the target functional
435  int output_dimensions = getOutputDimensionOfOperation(lro, local_dimensions);
436 
437  // special case for VectorPointSample, because if it is on a manifold it includes data transform to local charts
438  auto sro = (problem_type==MANIFOLD && sro_in==VectorPointSample) ? ManifoldVectorPointSample : sro_in;
439  int input_dimension_of_operator = getInputDimensionOfOperation(lro, _gmls->_data_sampling_functional, local_dimensions);
440 
441  compadre_assert_debug(target_output.extent(0)==(size_t)nla.getNumberOfTargets()
442  && "First dimension of target_output is incorrect size.\n");
443  compadre_assert_debug(target_output.extent(1)==(size_t)output_dimensions
444  && "Second dimension of target_output is incorrect size.\n");
445 
446  // make sure input and output columns make sense under the target operation
447  compadre_assert_debug(((output_dimensions==1 && view_type_output_data::rank==1) || view_type_output_data::rank!=1) &&
448  "Output view is requested as rank 1, but the target requires a rank larger than 1. Try double** as template argument.");
449 
450  // we need to specialize a template on the rank of the output view type and the input view type
451  auto sampling_subview_maker = CreateNDSliceOnDeviceView(sampling_data, scalar_as_vector_if_needed);
452  auto output_subview_maker = CreateNDSliceOnDeviceView(target_output, false); // output will always be the correct dimension
453 
454  // figure out preprocessing and postprocessing
455  auto prestencil_weights = _gmls->getPrestencilWeights();
456 
457  // all loop logic based on transforming data under a sampling functional
458  // into something that is valid input for GMLS
459  bool vary_on_target = false, vary_on_neighbor = false;
460  auto sro_style = sro.transform_type;
461  bool loop_global_dimensions = sro.input_rank>0 && sro_style!=Identity;
462 
464  && "SamplingFunctional requested for Evaluator does not match GMLS data sampling functional or is not of type 'Identity'.");
465 
466  if (sro.transform_type == Identity || sro.transform_type == SameForAll) {
467  vary_on_target = false;
468  vary_on_neighbor = false;
469  } else if (sro.transform_type == DifferentEachTarget) {
470  vary_on_target = true;
471  vary_on_neighbor = false;
472  } else if (sro.transform_type == DifferentEachNeighbor) {
473  vary_on_target = true;
474  vary_on_neighbor = true;
475  }
476 
477 
478  // only written for up to rank 1 to rank 2 (in / out)
479  // loop over components of output of the target operation
480  for (int axes1=0; axes1<output_dimension1_of_operator; ++axes1) {
481  const int output_component_axis_1 = axes1;
482  for (int axes2=0; axes2<output_dimension2_of_operator; ++axes2) {
483  const int output_component_axis_2 = axes2;
484  // loop over components of input of the target operation
485  for (int j=0; j<input_dimension_of_operator; ++j) {
486  const int input_component_axis_1 = j;
487  const int input_component_axis_2 = 0;
488 
489  if (loop_global_dimensions) {
490  for (int k=0; k<global_dimensions; ++k) { // loop for handling sampling functional
492  output_subview_maker.get1DView(axes1*output_dimension2_of_operator+axes2),
493  sampling_subview_maker.get1DView(k), lro, sro,
494  evaluation_site_local_index, output_component_axis_1, output_component_axis_2, input_component_axis_1,
495  input_component_axis_2, j, k, -1, -1,
496  vary_on_target, vary_on_neighbor);
497  }
498  } else if (sro_style != Identity) {
500  output_subview_maker.get1DView(axes1*output_dimension2_of_operator+axes2),
501  sampling_subview_maker.get1DView(j), lro, sro,
502  evaluation_site_local_index, output_component_axis_1, output_component_axis_2, input_component_axis_1,
503  input_component_axis_2, 0, 0, -1, -1,
504  vary_on_target, vary_on_neighbor);
505  } else { // standard
507  output_subview_maker.get1DView(axes1*output_dimension2_of_operator+axes2),
508  sampling_subview_maker.get1DView(j), lro, sro,
509  evaluation_site_local_index, output_component_axis_1, output_component_axis_2, input_component_axis_1,
510  input_component_axis_2);
511  }
512  }
513  }
514  }
515 
516  bool transform_gmls_output_to_ambient = (problem_type==MANIFOLD && getTargetOutputTensorRank(lro)==1);
517  if (transform_gmls_output_to_ambient) {
518  Kokkos::fence();
519 
520  compadre_assert_debug(ambient_target_output.extent(0)==(size_t)nla.getNumberOfTargets()
521  && "First dimension of target_output is incorrect size.\n");
522  compadre_assert_debug(ambient_target_output.extent(1)==(size_t)global_dimensions
523  && "Second dimension of target_output is incorrect size.\n");
524  auto transformed_output_subview_maker = CreateNDSliceOnDeviceView(ambient_target_output, false);
525  // output will always be the correct dimension
526  for (int i=0; i<global_dimensions; ++i) {
527  for (int j=0; j<output_dimensions; ++j) {
529  transformed_output_subview_maker.get1DView(i), output_subview_maker.get1DView(j), j, i);
530  }
531  }
532  // copy back to whatever memory space the user requester through templating from the device
533  Kokkos::deep_copy(ambient_target_output, transformed_output_subview_maker.copyToAndReturnOriginalView());
534  }
535 
536  // copy back to whatever memory space the user requester through templating from the device
537  Kokkos::deep_copy(target_output, output_subview_maker.copyToAndReturnOriginalView());
538  }
539 
540 
541  //! Dot product of data with full polynomial coefficient basis where sampling data is in a 1D/2D Kokkos View and output view is also
542  //! a 1D/2D Kokkos View, however THE SAMPLING DATA and OUTPUT VIEW MUST BE ON THE DEVICE!
543  //!
544  //! This function is to be used when the polynomial coefficient basis has already been calculated and stored for use.
545  //!
546  //! Only supports one output component / input component at a time. The user will need to loop over the output
547  //! components in order to fill a vector target or matrix target.
548  //!
549  //! Assumptions on input data:
550  //! \param output_data_block_column [out] - 2D Kokkos View (memory space must be device_memory_space())
551  //! \param sampling_data_single_column [in] - 1D Kokkos View (memory space must match output_data_single_column)
552  //! \param sro [in] - Sampling functional from the SamplingFunctional enum
553  //! \param target_index [in] - Target # user wants to reconstruct target functional at, corresponds to row number of neighbor_lists
554  //! \param output_component_axis_1 [in] - Row for a rank 2 tensor or rank 1 tensor, 0 for a scalar output
555  //! \param output_component_axis_2 [in] - Columns for a rank 2 tensor, 0 for rank less than 2 output tensor
556  //! \param input_component_axis_1 [in] - Row for a rank 2 tensor or rank 1 tensor, 0 for a scalar input
557  //! \param input_component_axis_2 [in] - Columns for a rank 2 tensor, 0 for rank less than 2 input tensor
558  //! \param pre_transform_local_index [in] - For manifold problems, this is the local coordinate direction that sampling data may need to be transformed to before the application of GMLS
559  //! \param pre_transform_global_index [in] - For manifold problems, this is the global coordinate direction that sampling data can be represented in
560  //! \param post_transform_local_index [in] - For manifold problems, this is the local coordinate direction that vector output target functionals from GMLS will output into
561  //! \param post_transform_global_index [in] - For manifold problems, this is the global coordinate direction that the target functional output from GMLS will be transformed into
562  //! \param vary_on_target [in] - Whether the sampling functional has a tensor to act on sampling data that varies with each target site
563  //! \param vary_on_neighbor [in] - Whether the sampling functional has a tensor to act on sampling data that varies with each neighbor site in addition to varying wit each target site
564  template <typename view_type_data_out, typename view_type_data_in>
565  void applyFullPolynomialCoefficientsBasisToDataSingleComponent(view_type_data_out output_data_block_column, view_type_data_in sampling_data_single_column, const SamplingFunctional sro, const int output_component_axis_1, const int output_component_axis_2, const int input_component_axis_1, const int input_component_axis_2, const int pre_transform_local_index = -1, const int pre_transform_global_index = -1, const int post_transform_local_index = -1, const int post_transform_global_index = -1, bool vary_on_target = false, bool vary_on_neighbor = false) const {
566 
567  auto nla = *(_gmls->getNeighborLists());
568 
569  auto coefficient_matrix_dims = _gmls->getPolynomialCoefficientsDomainRangeSize();
570  auto coefficient_memory_layout_dims = _gmls->getPolynomialCoefficientsMemorySize();
571  auto coefficient_memory_layout_dims_device =
572  Kokkos::create_mirror_view_and_copy(device_memory_space(), coefficient_memory_layout_dims);
573 
574  auto global_dimensions = _gmls->getGlobalDimensions();
575 
576  // gather needed information for evaluation
577  auto coeffs = _gmls->getFullPolynomialCoefficientsBasis();
578  auto tangent_directions = *(_gmls->getTangentDirections());
579  auto prestencil_weights = _gmls->getPrestencilWeights();
580 
581  const int num_targets = nla.getNumberOfTargets();
582 
583  // make sure input and output views have same memory space
584  compadre_assert_debug((std::is_same<typename view_type_data_out::memory_space, typename view_type_data_in::memory_space>::value) &&
585  "output_data_block_column view and input_data_single_column view have difference memory spaces.");
586 
587  bool weight_with_pre_T = (pre_transform_local_index>=0 && pre_transform_global_index>=0) ? true : false;
588  bool target_plus_neighbor_staggered_schema = sro.use_target_site_weights;
589 
590  // loops over target indices
591  for (int j=0; j<coefficient_matrix_dims(0); ++j) {
592  Kokkos::parallel_for(team_policy(num_targets, Kokkos::AUTO),
593  KOKKOS_LAMBDA(const member_type& teamMember) {
594 
595  const int target_index = teamMember.league_rank();
596 
597  scratch_matrix_right_type T (tangent_directions.data()
598  + TO_GLOBAL(target_index)*TO_GLOBAL(global_dimensions)*TO_GLOBAL(global_dimensions),
599  global_dimensions, global_dimensions);
600 
602  Coeffs = scratch_matrix_right_type(coeffs.data()
603  + TO_GLOBAL(target_index)*TO_GLOBAL(coefficient_memory_layout_dims_device(0))
604  *TO_GLOBAL(coefficient_memory_layout_dims_device(1)),
605  coefficient_memory_layout_dims_device(0), coefficient_memory_layout_dims_device(1));
606 
607  teamMember.team_barrier();
608 
609 
610  const double previous_value = output_data_block_column(target_index, j);
611 
612  // loops over neighbors of target_index
613  double gmls_value = 0;
614  Kokkos::parallel_reduce(Kokkos::TeamThreadRange(teamMember, nla.getNumberOfNeighborsDevice(target_index)), [&](const int i, double& t_value) {
615  const double neighbor_varying_pre_T = (weight_with_pre_T && vary_on_neighbor) ?
616  prestencil_weights(0, target_index, i, pre_transform_local_index, pre_transform_global_index)
617  : 1.0;
618 
619  t_value += neighbor_varying_pre_T * sampling_data_single_column(nla.getNeighborDevice(target_index, i))
620  *Coeffs(j, i+input_component_axis_1*nla.getNumberOfNeighborsDevice(target_index));
621 
622  }, gmls_value );
623 
624  // data contract for sampling functional
625  double pre_T = 1.0;
626  if (weight_with_pre_T) {
627  if (!vary_on_neighbor && vary_on_target) {
628  pre_T = prestencil_weights(0, target_index, 0, pre_transform_local_index,
629  pre_transform_global_index);
630  } else if (!vary_on_target) { // doesn't vary on target or neighbor
631  pre_T = prestencil_weights(0, 0, 0, pre_transform_local_index,
632  pre_transform_global_index);
633  }
634  }
635 
636  double staggered_value_from_targets = 0;
637  double pre_T_staggered = 1.0;
638  // loops over target_index for each neighbor for staggered approaches
639  if (target_plus_neighbor_staggered_schema) {
640  Kokkos::parallel_reduce(Kokkos::TeamThreadRange(teamMember, nla.getNumberOfNeighborsDevice(target_index)), [&](const int i, double& t_value) {
641  const double neighbor_varying_pre_T_staggered = (weight_with_pre_T && vary_on_neighbor) ?
642  prestencil_weights(1, target_index, i, pre_transform_local_index, pre_transform_global_index)
643  : 1.0;
644 
645  t_value += neighbor_varying_pre_T_staggered * sampling_data_single_column(nla.getNeighborDevice(target_index, 0))
646  *Coeffs(j, i+input_component_axis_1*nla.getNumberOfNeighborsDevice(target_index));
647 
648  }, staggered_value_from_targets );
649 
650  // for staggered approaches that transform source data for the target and neighbors
651  if (weight_with_pre_T) {
652  if (!vary_on_neighbor && vary_on_target) {
653  pre_T_staggered = prestencil_weights(1, target_index, 0, pre_transform_local_index,
654  pre_transform_global_index);
655  } else if (!vary_on_target) { // doesn't vary on target or neighbor
656  pre_T_staggered = prestencil_weights(1, 0, 0, pre_transform_local_index,
657  pre_transform_global_index);
658  }
659  }
660  }
661 
662  double added_value = (pre_T*gmls_value + pre_T_staggered*staggered_value_from_targets);
663  Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
664  output_data_block_column(target_index, j) = previous_value + added_value;
665  });
666  });
667  Kokkos::fence();
668  }
669  }
670 
671  //! Generation of polynomial reconstruction coefficients by applying to data in GMLS (allocates memory for output)
672  //!
673  //! Polynomial reconstruction coefficients exist for each target, but there are coefficients for each neighbor (a basis for all potentional input data). This function uses a particular choice of data to contract over this basis and return the polynomial reconstructions coefficients specific to this data.
674  //!
675  //! Produces a Kokkos View as output with a Kokkos memory_space provided as a template tag by the caller.
676  //! The data type (double* or double**) must also be specified as a template type if one wish to get a 1D
677  //! Kokkos View back that can be indexed into with only one ordinal.
678  //!
679  //! Assumptions on input data:
680  //! \param sampling_data [in] - 1D or 2D Kokkos View that has the layout #targets * columns of data. Memory space for data can be host or device.
681  //! \param sro [in] - Sampling functional from the SamplingFunctional enum
682  //! \param scalar_as_vector_if_needed [in] - If a 1D view is given, where a 2D view is expected (scalar values given where a vector was expected), then the scalar will be repeated for as many components as the vector has
683  template <typename output_data_type = double**, typename output_memory_space, typename view_type_input_data, typename output_array_layout = typename view_type_input_data::array_layout>
684  Kokkos::View<output_data_type, output_array_layout, output_memory_space> // shares layout of input by default
685  applyFullPolynomialCoefficientsBasisToDataAllComponents(view_type_input_data sampling_data, bool scalar_as_vector_if_needed = true) const {
686 
687  auto local_dimensions = _gmls->getLocalDimensions();
688  auto output_dimension_of_reconstruction_space = calculateBasisMultiplier(_gmls->getReconstructionSpace(), local_dimensions);
689  auto coefficient_matrix_dims = _gmls->getPolynomialCoefficientsDomainRangeSize();
690 
691  // gather needed information for evaluation
692  auto nla = *(_gmls->getNeighborLists());
693 
694  // determines the number of columns needed for output
695  int output_dimensions = output_dimension_of_reconstruction_space;
696 
697  typedef Kokkos::View<output_data_type, output_array_layout, output_memory_space> output_view_type;
698  // create view on whatever memory space the user specified with their template argument when calling this function
699  output_view_type coefficient_output("output coefficients", nla.getNumberOfTargets(),
700  output_dimensions*_gmls->getPolynomialCoefficientsSize() /* number of coefficients */);
701 
702  applyFullPolynomialCoefficientsBasisToDataAllComponents(coefficient_output, sampling_data, scalar_as_vector_if_needed);
703 
704  return coefficient_output;
705 
706  }
707 
708  //! Generation of polynomial reconstruction coefficients by applying to data in GMLS (does not allocate memory for output)
709  //!
710  //! Polynomial reconstruction coefficients exist for each target, but there are coefficients for each neighbor (a basis for all potentional input data). This function uses a particular choice of data to contract over this basis and return the polynomial reconstructions coefficients specific to this data.
711  //!
712  //! Produces a Kokkos View as output with a Kokkos memory_space provided as a template tag by the caller.
713  //! The data type (double* or double**) must also be specified as a template type if one wish to get a 1D
714  //! Kokkos View back that can be indexed into with only one ordinal.
715  //!
716  //! Assumptions on input data:
717  //! \param coefficient_output [in] - 1D or 2D Kokkos View that has the layout #targets * #coefficients. Memory space for data can be host or device.
718  //! \param sampling_data [in] - 1D or 2D Kokkos View that has the layout #targets * columns of data. Memory space for data can be host or device.
719  //! \param sro [in] - Sampling functional from the SamplingFunctional enum
720  //! \param scalar_as_vector_if_needed [in] - If a 1D view is given, where a 2D view is expected (scalar values given where a vector was expected), then the scalar will be repeated for as many components as the vector has
721  template <typename view_type_coefficient_output, typename view_type_input_data>
722  void applyFullPolynomialCoefficientsBasisToDataAllComponents(view_type_coefficient_output coefficient_output,
723  view_type_input_data sampling_data, bool scalar_as_vector_if_needed = true) const {
724 
725  // output can be device or host
726  // input can be device or host
727  // move everything to device and calculate there, then move back to host if necessary
728 
729  auto global_dimensions = _gmls->getGlobalDimensions();
730  auto local_dimensions = _gmls->getLocalDimensions();
731  auto output_dimension_of_reconstruction_space = calculateBasisMultiplier(_gmls->getReconstructionSpace(), local_dimensions);
732  auto input_dimension_of_reconstruction_space = calculateSamplingMultiplier(_gmls->getReconstructionSpace(), _gmls->getPolynomialSamplingFunctional(), local_dimensions);
733  auto coefficient_matrix_dims = _gmls->getPolynomialCoefficientsDomainRangeSize();
734 
735  // gather needed information for evaluation
736  auto nla = *(_gmls->getNeighborLists());
737 
739 
740  compadre_assert_debug(coefficient_output.extent(0)==(size_t)nla.getNumberOfTargets()
741  && "First dimension of coefficient_output is incorrect size.\n");
742  // determines the number of columns needed for output
744  coefficient_output.extent(1)==(size_t)output_dimension_of_reconstruction_space*_gmls->getPolynomialCoefficientsSize()
745  /* number of coefficients */ && "Second dimension of coefficient_output is incorrect size.\n");
746 
747  // make sure input and output columns make sense under the target operation
748  compadre_assert_debug(((output_dimension_of_reconstruction_space==1 && view_type_coefficient_output::rank==1) || view_type_coefficient_output::rank!=1) &&
749  "Output view is requested as rank 1, but the target requires a rank larger than 1. Try double** as template argument.");
750 
751  // we need to specialize a template on the rank of the output view type and the input view type
752  auto sampling_subview_maker = CreateNDSliceOnDeviceView(sampling_data, scalar_as_vector_if_needed);
753  auto output_subview_maker = CreateNDSliceOnDeviceView(coefficient_output, false); // output will always be the correct dimension
754 
755  // figure out preprocessing and postprocessing
756  auto prestencil_weights = _gmls->getPrestencilWeights();
757 
758  // all loop logic based on transforming data under a sampling functional
759  // into something that is valid input for GMLS
760  bool vary_on_target = false, vary_on_neighbor = false;
761  auto sro_style = sro.transform_type;
762  bool loop_global_dimensions = sro.input_rank>0 && sro_style!=Identity;
763 
764 
765  if (sro.transform_type == Identity || sro.transform_type == SameForAll) {
766  vary_on_target = false;
767  vary_on_neighbor = false;
768  } else if (sro.transform_type == DifferentEachTarget) {
769  vary_on_target = true;
770  vary_on_neighbor = false;
771  } else if (sro.transform_type == DifferentEachNeighbor) {
772  vary_on_target = true;
773  vary_on_neighbor = true;
774  }
775 
776  // written for up to rank 1 to rank 0 (in / out)
777  // loop over components of output of the target operation
778  for (int i=0; i<output_dimension_of_reconstruction_space; ++i) {
779  const int output_component_axis_1 = i;
780  const int output_component_axis_2 = 0;
781  // loop over components of input of the target operation
782  for (int j=0; j<input_dimension_of_reconstruction_space; ++j) {
783  const int input_component_axis_1 = j;
784  const int input_component_axis_2 = 0;
785 
786  if (loop_global_dimensions) {
787  for (int k=0; k<global_dimensions; ++k) { // loop for handling sampling functional
789  output_subview_maker.get2DView(i,_gmls->getPolynomialCoefficientsSize()),
790  sampling_subview_maker.get1DView(k), sro,
791  output_component_axis_1, output_component_axis_2, input_component_axis_1,
792  input_component_axis_2, j, k, -1, -1,
793  vary_on_target, vary_on_neighbor);
794  }
795  } else if (sro_style != Identity) {
797  output_subview_maker.get2DView(i,_gmls->getPolynomialCoefficientsSize()),
798  sampling_subview_maker.get1DView(j), sro,
799  output_component_axis_1, output_component_axis_2, input_component_axis_1,
800  input_component_axis_2, 0, 0, -1, -1,
801  vary_on_target, vary_on_neighbor);
802  } else { // standard
804  output_subview_maker.get2DView(i,_gmls->getPolynomialCoefficientsSize()),
805  sampling_subview_maker.get1DView(j), sro,
806  output_component_axis_1, output_component_axis_2, input_component_axis_1,
807  input_component_axis_2);
808  }
809  }
810  }
811 
812  // copy back to whatever memory space the user requester through templating from the device
813  Kokkos::deep_copy(coefficient_output, output_subview_maker.copyToAndReturnOriginalView());
814  }
815 
816 }; // Evaluator
817 
818 } // Compadre
819 
820 #endif
SamplingFunctional getDataSamplingFunctional() const
Get the data sampling functional specified at instantiation (often the same as the polynomial samplin...
Each neighbor for each target all apply the same transform.
ReconstructionSpace getReconstructionSpace() const
Get the reconstruction space specified at instantiation.
SolutionSet< host_memory_space > _h_ss
Solution Set (contains all alpha values from solution and alpha layout methods)
Lightweight Evaluator Helper This class is a lightweight wrapper for extracting and applying all rele...
constexpr SamplingFunctional ManifoldVectorPointSample
Point evaluations of the entire vector source function (but on a manifold, so it includes a transform...
decltype(_prestencil_weights) getPrestencilWeights() const
Get a view (device) of all rank 2 preprocessing tensors This is a rank 5 tensor that is able to provi...
team_policy::member_type member_type
KOKKOS_INLINE_FUNCTION int calculateSamplingMultiplier(const ReconstructionSpace rs, const SamplingFunctional sro, const int local_dimensions)
Calculate sampling_multiplier.
void applyAlphasToDataSingleComponentAllTargetSitesWithPreAndPostTransform(view_type_data_out output_data_single_column, view_type_data_in sampling_data_single_column, TargetOperation lro, const SamplingFunctional sro, const int evaluation_site_local_index, const int output_component_axis_1, const int output_component_axis_2, const int input_component_axis_1, const int input_component_axis_2, const int pre_transform_local_index=-1, const int pre_transform_global_index=-1, const int post_transform_local_index=-1, const int post_transform_global_index=-1, bool vary_on_target=false, bool vary_on_neighbor=false) const
Dot product of alphas with sampling data where sampling data is in a 1D/2D Kokkos View and output vie...
decltype(_d_ss)* getSolutionSetDevice(bool alpha_validity_check=true)
Get solution set on device.
bool use_target_site_weights
Whether or not the SamplingTensor acts on the target site as well as the neighbors.
ProblemType getProblemType() const
Get problem type.
Kokkos::View< output_data_type, output_array_layout, output_memory_space > applyFullPolynomialCoefficientsBasisToDataAllComponents(view_type_input_data sampling_data, bool scalar_as_vector_if_needed=true) const
Generation of polynomial reconstruction coefficients by applying to data in GMLS (allocates memory fo...
KOKKOS_INLINE_FUNCTION global_index_type getAlphaIndex(const int target_index, const int alpha_column_offset) const
Gives index into alphas given two axes, which when incremented by the neighbor number transforms acce...
double applyAlphasToDataSingleComponentSingleTargetSite(view_type_data sampling_input_data, const int column_of_input, TargetOperation lro, const int target_index, const int evaluation_site_local_index, const int output_component_axis_1, const int output_component_axis_2, const int input_component_axis_1, const int input_component_axis_2, bool scalar_as_vector_if_needed=true) const
Dot product of alphas with sampling data, FOR A SINGLE target_index, where sampling data is in a 1D/2...
Kokkos::TeamPolicy< device_execution_space > team_policy
void applyAlphasToDataAllComponentsAllTargetSites(view_type_output_data target_output, view_type_output_data ambient_target_output, view_type_input_data sampling_data, TargetOperation lro, const SamplingFunctional sro_in=PointSample, bool scalar_as_vector_if_needed=true, const int evaluation_site_local_index=0) const
Transformation of data under GMLS (does not allocate memory for output)
neighbor_lists_type * getNeighborLists() const
Get neighbor list accessor.
void applyLocalChartToAmbientSpaceTransform(view_type_data_out output_data_single_column, view_type_data_in sampling_data_single_column, const int local_dim_index, const int global_dim_index) const
Postprocessing for manifolds.
TargetOperation
Available target functionals.
Each target applies a different transform for each neighbor.
Solve GMLS problem on a manifold (will use QR or SVD to solve the resultant GMLS problem dependent on...
#define TO_GLOBAL(variable)
device_execution_space::memory_space device_memory_space
int input_rank
Rank of sampling functional input for each SamplingFunctional.
void applyFullPolynomialCoefficientsBasisToDataAllComponents(view_type_coefficient_output coefficient_output, view_type_input_data sampling_data, bool scalar_as_vector_if_needed=true) const
Generation of polynomial reconstruction coefficients by applying to data in GMLS (does not allocate m...
int getPolynomialCoefficientsSize() const
Returns size of the basis used in instance&#39;s polynomial reconstruction.
typename std::enable_if< B, T >::type enable_if_t
KOKKOS_INLINE_FUNCTION int getAlphaColumnOffset(TargetOperation lro, const int output_component_axis_1, const int output_component_axis_2, const int input_component_axis_1, const int input_component_axis_2, const int evaluation_site_local_index=0) const
Retrieves the offset for an operator based on input and output component, generic to row (but still m...
auto get1DView(const int column_num) -> decltype(Kokkos::subview(_data_in, Kokkos::ALL, column_num))
Kokkos::View< double **, layout_right, Kokkos::MemoryTraits< Kokkos::Unmanaged > > scratch_matrix_right_type
SubviewND(T data_in, T2 data_original_view, bool scalar_as_vector_if_needed)
int getLocalDimensions() const
Local dimension of the GMLS problem (less than global dimension if on a manifold), set only at class instantiation.
auto CreateNDSliceOnDeviceView(T sampling_input_data_host_or_device, bool scalar_as_vector_if_needed) -> SubviewND< decltype(Kokkos::create_mirror_view(device_memory_space(), sampling_input_data_host_or_device)), T >
Copies data_in to the device, and then allows for access to 1D columns of data on device...
decltype(_RHS) getFullPolynomialCoefficientsBasis() const
Get a view (device) of all polynomial coefficients basis.
SamplingFunctional _data_sampling_functional
generally the same as _polynomial_sampling_functional, but can differ if specified at ...
int getGlobalDimensions() const
Dimension of the GMLS problem&#39;s point data (spatial description of points in ambient space)...
Generalized Moving Least Squares (GMLS)
decltype(_T)* getTangentDirections()
Get a view (device) of all tangent direction bundles.
No action performed on data before GMLS target operation.
KOKKOS_INLINE_FUNCTION int getTargetOutputTensorRank(const int &index)
Rank of target functional output for each TargetOperation Rank of target functional input for each Ta...
int transform_type
Describes the SamplingFunction relationship to targets, neighbors.
Kokkos::View< output_data_type, output_array_layout, output_memory_space > applyAlphasToDataAllComponentsAllTargetSites(view_type_input_data sampling_data, TargetOperation lro, const SamplingFunctional sro_in=PointSample, bool scalar_as_vector_if_needed=true, const int evaluation_site_local_index=0) const
Transformation of data under GMLS (allocates memory for output)
auto get2DView(const int column_num, const int block_size) -> decltype(Kokkos::subview(_data_in, Kokkos::ALL, Kokkos::make_pair(column_num *block_size,(column_num+1)*block_size)))
constexpr SamplingFunctional PointSample
Available sampling functionals.
host_managed_local_index_type getPolynomialCoefficientsDomainRangeSize() const
Returns (size of the basis used in instance&#39;s polynomial reconstruction) x (data input dimension) ...
struct SubviewND< T, T2, enable_if_t<(T::rank< 2)> >{T _data_in;T2 _data_original_view;bool _scalar_as_vector_if_needed;SubviewND(T data_in, T2 data_original_view, bool scalar_as_vector_if_needed){_data_in=data_in;_data_original_view=data_original_view;_scalar_as_vector_if_needed=scalar_as_vector_if_needed;}auto get1DView(const int column_num) -> decltype(Kokkos::subview(_data_in, Kokkos::ALL))
Creates 1D subviews of data from a 1D view, generally constructed with CreateNDSliceOnDeviceView.
KOKKOS_INLINE_FUNCTION int getInputDimensionOfOperation(TargetOperation lro, SamplingFunctional sro, const int local_dimensions)
Dimensions ^ input rank for target operation (always in local chart if on a manifold, never ambient space)
Each target applies a different data transform, but the same to each neighbor.
#define compadre_assert_debug(condition)
compadre_assert_debug is used for assertions that are checked in loops, as these significantly impact...
void applyFullPolynomialCoefficientsBasisToDataSingleComponent(view_type_data_out output_data_block_column, view_type_data_in sampling_data_single_column, const SamplingFunctional sro, const int output_component_axis_1, const int output_component_axis_2, const int input_component_axis_1, const int input_component_axis_2, const int pre_transform_local_index=-1, const int pre_transform_global_index=-1, const int post_transform_local_index=-1, const int post_transform_global_index=-1, bool vary_on_target=false, bool vary_on_neighbor=false) const
Dot product of data with full polynomial coefficient basis where sampling data is in a 1D/2D Kokkos V...
SamplingFunctional getPolynomialSamplingFunctional() const
Get the polynomial sampling functional specified at instantiation.
KOKKOS_INLINE_FUNCTION int getOutputDimensionOfOperation(TargetOperation lro, const int local_dimensions)
Dimensions ^ output rank for target operation.
#define compadre_assert_release(condition)
compadre_assert_release is used for assertions that should always be checked, but generally are not e...
Creates 1D subviews of data from a 2D view, generally constructed with CreateNDSliceOnDeviceView.
host_managed_local_index_type getPolynomialCoefficientsMemorySize() const
Returns 2D array size in memory on which coefficients are stored.
constexpr SamplingFunctional VectorPointSample
Point evaluations of the entire vector source function.
KOKKOS_INLINE_FUNCTION int calculateBasisMultiplier(const ReconstructionSpace rs, const int local_dimensions)
Calculate basis_multiplier.