Compadre 1.6.4
Loading...
Searching...
No Matches
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
16namespace Compadre {
17
18//! Creates 1D subviews of data from a 2D view, generally constructed with CreateNDSliceOnDeviceView
19template<typename T, typename T2, typename T3=void>
20struct 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();
61 }
62
63};
64
65//! Creates 1D subviews of data from a 1D view, generally constructed with CreateNDSliceOnDeviceView
66template<typename T, typename T2>
67struct SubviewND<T, T2, enable_if_t<(T::rank<2)> >
68{
69
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();
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.
105template <typename T>
106auto 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)
124
125private:
126
128
129
130public:
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
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
#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)
#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...
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.
team_policy::member_type member_type
KOKKOS_INLINE_FUNCTION int calculateBasisMultiplier(const ReconstructionSpace rs, const int local_dimensions)
Calculate basis_multiplier.
KOKKOS_INLINE_FUNCTION int calculateSamplingMultiplier(const ReconstructionSpace rs, const SamplingFunctional sro, const int local_dimensions)
Calculate sampling_multiplier.
@ MANIFOLD
Solve GMLS problem on a manifold (will use QR or SVD to solve the resultant GMLS problem dependent on...
Kokkos::TeamPolicy< device_execution_space > team_policy
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.
typename std::enable_if< B, T >::type enable_if_t
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,...
@ 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.
TargetOperation
Available target functionals.
device_execution_space::memory_space device_memory_space
Kokkos::View< double **, layout_right, Kokkos::MemoryTraits< Kokkos::Unmanaged > > scratch_matrix_right_type
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))