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