Compadre  1.6.0
GMLS_Manifold_Multiple_Evaluation_Sites.cpp
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 #include <iostream>
10 #include <string>
11 #include <vector>
12 #include <map>
13 #include <stdlib.h>
14 #include <cstdio>
15 #include <random>
16 
17 #include <Compadre_Config.h>
18 #include <Compadre_GMLS.hpp>
19 #include <Compadre_Evaluator.hpp>
21 
22 #include "GMLS_Manifold.hpp"
23 #include "CommandLineProcessor.hpp"
24 
25 #ifdef COMPADRE_USE_MPI
26 #include <mpi.h>
27 #endif
28 
29 #include <Kokkos_Timer.hpp>
30 #include <Kokkos_Core.hpp>
31 
32 using namespace Compadre;
33 //! [Ambient to Local Back To Ambient Helper Function]
34 void AmbientLocalAmbient(XYZ& u, double* T_data, double* P_data) {
35  // reconstructions with vector output on a manifold are defined
36  // in their local chart (2D). Next, they are mapped to 3D using
37  // the tangent vector calculated at the target site.
38  //
39  // We are interested in a mapping using the tangent vector at
40  // additional evaluation site instead, so we map back to the
41  // local chart using the tangent vector defined at the target
42  // site (T), then mapping from the local chart to ambient space
43  // using the tangent vector calculated at the extra site (P).
44 
45 
46  host_scratch_matrix_right_type T(T_data, 3, 3);
47  host_scratch_matrix_right_type P(P_data, 3, 3);
48 
49  // first get back to local chart
50  double local_vec[3] = {0,0};
51  for (int j=0; j<3; ++j) {
52  local_vec[0] += T(0,j) * u[j];
53  local_vec[1] += T(1,j) * u[j];
54  }
55  // second go to ambient space using tangent for first neighbor
56  for (int j=0; j<3; ++j) u[j] = 0;
57  for (int j=0; j<3; ++j) {
58  u[j] += P(0, j) * local_vec[0];
59  u[j] += P(1, j) * local_vec[1];
60  }
61 
62 }
63 
64 //! [Ambient to Local Back To Ambient Helper Function]
65 
66 // called from command line
67 int main (int argc, char* args[]) {
68 
69 // initializes MPI (if available) with command line arguments given
70 #ifdef COMPADRE_USE_MPI
71 MPI_Init(&argc, &args);
72 #endif
73 
74 // initializes Kokkos with command line arguments given
75 Kokkos::initialize(argc, args);
76 
77 // code block to reduce scope for all Kokkos View allocations
78 // otherwise, Views may be deallocating when we call Kokkos::finalize() later
79 {
80 
81  CommandLineProcessor clp(argc, args);
82  auto order = clp.order;
83  auto dimension = clp.dimension;
84  auto number_target_coords = clp.number_target_coords;
85  auto constraint_name = clp.constraint_name;
86  auto solver_name = clp.solver_name;
87  auto problem_name = clp.problem_name;
88  int N_pts_on_sphere = (clp.number_source_coords>=0) ? clp.number_source_coords : 1000;
89 
90  // minimum neighbors for unisolvency is the same as the size of the polynomial basis
91  // dimension has one subtracted because it is a D-1 manifold represented in D dimensions
92  const int min_neighbors = Compadre::GMLS::getNP(order, dimension-1);
93 
94  //! [Parse Command Line Arguments]
95  Kokkos::Timer timer;
96  Kokkos::Profiling::pushRegion("Setup Point Data");
97  //! [Setting Up The Point Cloud]
98 
99 
100  // coordinates of source sites, bigger than needed then resized later
101  Kokkos::View<double**, Kokkos::DefaultExecutionSpace> source_coords_device("source coordinates",
102  1.25*N_pts_on_sphere, 3);
103  Kokkos::View<double**>::HostMirror source_coords = Kokkos::create_mirror_view(source_coords_device);
104 
105  double r = 1.0;
106 
107  // set number of source coordinates from what was calculated
108  int number_source_coords;
109 
110  {
111  // fill source coordinates from surface of a sphere with quasiuniform points
112  // algorithm described at https://www.cmu.edu/biolphys/deserno/pdf/sphere_equi.pdf
113  int N_count = 0;
114  double a = 4*PI*r*r/N_pts_on_sphere;
115  double d = std::sqrt(a);
116  int M_theta = std::round(PI/d);
117  double d_theta = PI/M_theta;
118  double d_phi = a/d_theta;
119  for (int i=0; i<M_theta; ++i) {
120  double theta = PI*(i + 0.5)/M_theta;
121  int M_phi = std::round(2*PI*std::sin(theta)/d_phi);
122  for (int j=0; j<M_phi; ++j) {
123  double phi = 2*PI*j/M_phi;
124  source_coords(N_count, 0) = theta;
125  source_coords(N_count, 1) = phi;
126  N_count++;
127  }
128  }
129 
130  for (int i=0; i<N_count; ++i) {
131  double theta = source_coords(i,0);
132  double phi = source_coords(i,1);
133  source_coords(i,0) = r*std::sin(theta)*std::cos(phi);
134  source_coords(i,1) = r*std::sin(theta)*std::sin(phi);
135  source_coords(i,2) = r*cos(theta);
136  //printf("%f %f %f\n", source_coords(i,0), source_coords(i,1), source_coords(i,2));
137  }
138  number_source_coords = N_count;
139  }
140 
141  // resize source_coords to the size actually needed
142  Kokkos::resize(source_coords, number_source_coords, 3);
143  Kokkos::resize(source_coords_device, number_source_coords, 3);
144 
145  // coordinates of target sites
146  Kokkos::View<double**, Kokkos::DefaultExecutionSpace> target_coords_device ("target coordinates",
147  number_target_coords, 3);
148  Kokkos::View<double**>::HostMirror target_coords = Kokkos::create_mirror_view(target_coords_device);
149 
150  {
151  bool enough_pts_found = false;
152  // fill target coordinates from surface of a sphere with quasiuniform points
153  // stop when enough points are found
154  int N_count = 0;
155  double a = 4.0*PI*r*r/((double)(5.0*number_target_coords)); // 5.0 is in case number_target_coords is set to something very small (like 1)
156  double d = std::sqrt(a);
157  int M_theta = std::round(PI/d);
158  double d_theta = PI/((double)M_theta);
159  double d_phi = a/d_theta;
160  for (int i=0; i<M_theta; ++i) {
161  double theta = PI*(i + 0.5)/M_theta;
162  int M_phi = std::round(2*PI*std::sin(theta)/d_phi);
163  for (int j=0; j<M_phi; ++j) {
164  double phi = 2*PI*j/M_phi;
165  target_coords(N_count, 0) = theta;
166  target_coords(N_count, 1) = phi;
167  N_count++;
168  if (N_count == number_target_coords) {
169  enough_pts_found = true;
170  break;
171  }
172  }
173  if (enough_pts_found) break;
174  }
175 
176  for (int i=0; i<N_count; ++i) {
177  double theta = target_coords(i,0);
178  double phi = target_coords(i,1);
179  target_coords(i,0) = r*std::sin(theta)*std::cos(phi);
180  target_coords(i,1) = r*std::sin(theta)*std::sin(phi);
181  target_coords(i,2) = r*cos(theta);
182  //printf("%f %f %f\n", target_coords(i,0), target_coords(i,1), target_coords(i,2));
183  }
184  }
185 
186 
187  //! [Setting Up The Point Cloud]
188 
189  Kokkos::Profiling::popRegion();
190  Kokkos::fence();
191  Kokkos::Profiling::pushRegion("Creating Data");
192 
193  //! [Creating The Data]
194 
195 
196  // source coordinates need copied to device before using to construct sampling data
197  Kokkos::deep_copy(source_coords_device, source_coords);
198 
199  // target coordinates copied next, because it is a convenient time to send them to device
200  Kokkos::deep_copy(target_coords_device, target_coords);
201 
202  // ensure that source coordinates are sent to device before evaluating sampling data based on them
203  Kokkos::fence();
204 
205 
206  // need Kokkos View storing true solution (for samples)
207  Kokkos::View<double*, Kokkos::DefaultExecutionSpace> sampling_data_device("samples of true solution",
208  source_coords_device.extent(0));
209  Kokkos::View<double*, Kokkos::DefaultExecutionSpace> ones_data_device("samples of ones",
210  source_coords_device.extent(0));
211  Kokkos::deep_copy(ones_data_device, 1.0);
212 
213  // need Kokkos View storing true vector solution (for samples)
214  Kokkos::View<double**, Kokkos::DefaultExecutionSpace> sampling_vector_data_device("samples of vector true solution",
215  source_coords_device.extent(0), 3);
216 
217  Kokkos::parallel_for("Sampling Manufactured Solutions", Kokkos::RangePolicy<Kokkos::DefaultExecutionSpace>
218  (0,source_coords.extent(0)), KOKKOS_LAMBDA(const int i) {
219 
220  // coordinates of source site i
221  double xval = source_coords_device(i,0);
222  double yval = (dimension>1) ? source_coords_device(i,1) : 0;
223  double zval = (dimension>2) ? source_coords_device(i,2) : 0;
224 
225  // data for targets with scalar input
226  sampling_data_device(i) = sphere_harmonic54(xval, yval, zval);
227 
228  for (int j=0; j<3; ++j) {
229  double gradient[3] = {0,0,0};
230  gradient_sphereHarmonic54_ambient(gradient, xval, yval, zval);
231  sampling_vector_data_device(i,j) = gradient[j];
232  }
233  });
234 
235 
236  //! [Creating The Data]
237 
238  Kokkos::Profiling::popRegion();
239  Kokkos::Profiling::pushRegion("Neighbor Search");
240 
241  //! [Performing Neighbor Search]
242 
243 
244  // Point cloud construction for neighbor search
245  // CreatePointCloudSearch constructs an object of type PointCloudSearch, but deduces the templates for you
246  auto point_cloud_search(CreatePointCloudSearch(source_coords, dimension));
247 
248  // each row is a neighbor list for a target site, with the first column of each row containing
249  // the number of neighbors for that rows corresponding target site
250  double epsilon_multiplier = 1.7;
251  int estimated_upper_bound_number_neighbors =
252  point_cloud_search.getEstimatedNumberNeighborsUpperBound(min_neighbors, dimension, epsilon_multiplier);
253 
254  Kokkos::View<int**, Kokkos::DefaultExecutionSpace> neighbor_lists_device("neighbor lists",
255  number_target_coords, estimated_upper_bound_number_neighbors); // first column is # of neighbors
256  Kokkos::View<int**>::HostMirror neighbor_lists = Kokkos::create_mirror_view(neighbor_lists_device);
257 
258  // each target site has a window size
259  Kokkos::View<double*, Kokkos::DefaultExecutionSpace> epsilon_device("h supports", number_target_coords);
260  Kokkos::View<double*>::HostMirror epsilon = Kokkos::create_mirror_view(epsilon_device);
261 
262  // query the point cloud to generate the neighbor lists using a kdtree to produce the n nearest neighbor
263  // to each target site, adding (epsilon_multiplier-1)*100% to whatever the distance away the further neighbor used is from
264  // each target to the view for epsilon
265  point_cloud_search.generate2DNeighborListsFromKNNSearch(false /*not dry run*/, target_coords, neighbor_lists,
266  epsilon, min_neighbors, epsilon_multiplier);
267 
268  //! [Performing Neighbor Search]
269 
270  Kokkos::Profiling::popRegion();
271  Kokkos::fence(); // let call to build neighbor lists complete before copying back to device
272  timer.reset();
273 
274  //! [Setting Up The GMLS Object]
275 
276 
277  // Copy data back to device (they were filled on the host)
278  // We could have filled Kokkos Views with memory space on the host
279  // and used these instead, and then the copying of data to the device
280  // would be performed in the GMLS class
281  Kokkos::deep_copy(neighbor_lists_device, neighbor_lists);
282  Kokkos::deep_copy(epsilon_device, epsilon);
283 
284  // initialize an instance of the GMLS class for problems with a scalar basis and
285  // traditional point sampling as the sampling functional
286  GMLS my_GMLS_scalar(order, dimension,
287  solver_name.c_str(), problem_name.c_str(), constraint_name.c_str(),
288  order /*manifold order*/);
289 
290  // pass in neighbor lists, source coordinates, target coordinates, and window sizes
291  //
292  // neighbor lists have the format:
293  // dimensions: (# number of target sites) X (# maximum number of neighbors for any given target + 1)
294  // the first column contains the number of neighbors for that rows corresponding target index
295  //
296  // source coordinates have the format:
297  // dimensions: (# number of source sites) X (dimension)
298  // entries in the neighbor lists (integers) correspond to rows of this 2D array
299  //
300  // target coordinates have the format:
301  // dimensions: (# number of target sites) X (dimension)
302  // # of target sites is same as # of rows of neighbor lists
303  //
304  my_GMLS_scalar.setProblemData(neighbor_lists_device, source_coords_device, target_coords_device, epsilon_device);
305 
306  // set up additional sites to evaluate target operators
307  // these sites will be the neighbors of the target site
308  my_GMLS_scalar.setAdditionalEvaluationSitesData(neighbor_lists_device, source_coords_device);
309 
310  // set a reference outward normal direction, causing a surface orientation after
311  // the GMLS instance computes an approximate tangent bundle
312  // on a sphere, the ambient coordinates are the outward normal direction
313  my_GMLS_scalar.setReferenceOutwardNormalDirection(target_coords_device, true /* use to orient surface */);
314 
315  // create a vector of target operations
316  std::vector<TargetOperation> lro_scalar(3);
317  lro_scalar[0] = ScalarPointEvaluation;
318  lro_scalar[1] = GaussianCurvaturePointEvaluation;
319  lro_scalar[2] = CurlOfVectorPointEvaluation;
320 
321  // and then pass them to the GMLS class
322  my_GMLS_scalar.addTargets(lro_scalar);
323 
324  // sets the weighting kernel function from WeightingFunctionType for curvature
326 
327  // power to use in the weighting kernel function for curvature coefficients
328  my_GMLS_scalar.setCurvatureWeightingParameter(2);
329 
330  // sets the weighting kernel function from WeightingFunctionType
332 
333  // power to use in that weighting kernel function
334  my_GMLS_scalar.setWeightingParameter(2);
335 
336  // generate the alphas that to be combined with data for each target operation requested in lro
337  my_GMLS_scalar.generateAlphas();
338 
339  Kokkos::Profiling::pushRegion("Full Polynomial Basis GMLS Solution");
340  // initialize another instance of the GMLS class for problems with a vector basis on a manifold and point
341  // evaluation of that vector as the sampling functional
342  // VectorTaylorPolynomial indicates that the basis will be a polynomial with as many components as the
343  // dimension of the manifold. This differs from another possibility, which follows this class.
345  order, dimension,
346  solver_name.c_str(), problem_name.c_str(), constraint_name.c_str(),
347  order /*manifold order*/);
348 
349  my_GMLS_vector.setProblemData(neighbor_lists_device, source_coords_device, target_coords_device, epsilon_device);
350  my_GMLS_vector.setAdditionalEvaluationSitesData(neighbor_lists_device, source_coords_device);
351  std::vector<TargetOperation> lro_vector(2);
352  lro_vector[0] = VectorPointEvaluation;
353  //lro_vector[1] = DivergenceOfVectorPointEvaluation;
354  my_GMLS_vector.addTargets(lro_vector);
356  my_GMLS_vector.setCurvatureWeightingParameter(2);
358  my_GMLS_vector.setWeightingParameter(2);
359  my_GMLS_vector.generateAlphas();
360  Kokkos::Profiling::popRegion();
361 
362  Kokkos::Profiling::pushRegion("Scalar Polynomial Basis Repeated to Form a Vector GMLS Solution");
363  // initialize another instance of the GMLS class for problems with a vector basis on a manifold and point
364  // evaluation of that vector as the sampling functional
365  // VectorOfScalarClonesTaylorPolynomial indicates a scalar polynomial will be solved for, since
366  // each component of the reconstructed vector are independent. This results in solving a smaller system
367  // for each GMLS problem, and is the suggested way to do vector reconstructions when sampling functionals
368  // acting on the basis would not create non-zero offdiagonal blocks.
369  //
370  // As an example, consider a 2D manifold in 3D ambient space. The GMLS problem is posed in the local chart,
371  // meaning that the problem being solved looks like
372  //
373  // [P_0 0 | where P_0 has dimension #number of neighbors for a target X #dimension of a scalar basis
374  // | 0 P_1]
375  //
376  // P_1 is similarly shaped, and for sampling functional that is a point evaluation, P_0 and P_1 are
377  // identical and their degrees of freedom in this system are disjoint, allowing us to solve for the
378  // degrees of freedom for either block independently. Additionally, the will produce the exact
379  // same polynomial coefficients for the point sampling functional, therefore it makes sense to use
380  // VectorOfScalarClonesTaylorPolynomial.
381  //
382  // In the print-out for this program, we include the timings and errors on this and VectorTaylorPolynomial
383  // in order to demonstrate that they produce exactly the same answer, but that one is much more efficient.
384  //
386  order, dimension,
387  solver_name.c_str(), problem_name.c_str(), constraint_name.c_str(),
388  order /*manifold order*/);
389 
390  my_GMLS_vector_of_scalar_clones.setProblemData(neighbor_lists_device, source_coords_device, target_coords_device, epsilon_device);
391  my_GMLS_vector_of_scalar_clones.setAdditionalEvaluationSitesData(neighbor_lists_device, source_coords_device);
392  std::vector<TargetOperation> lro_vector_of_scalar_clones(2);
393  lro_vector_of_scalar_clones[0] = VectorPointEvaluation;
394  //lro_vector_of_scalar_clones[1] = DivergenceOfVectorPointEvaluation;
395  my_GMLS_vector_of_scalar_clones.addTargets(lro_vector_of_scalar_clones);
396  my_GMLS_vector_of_scalar_clones.setCurvatureWeightingType(WeightingFunctionType::Power);
397  my_GMLS_vector_of_scalar_clones.setCurvatureWeightingParameter(2);
398  my_GMLS_vector_of_scalar_clones.setWeightingType(WeightingFunctionType::Power);
399  my_GMLS_vector_of_scalar_clones.setWeightingParameter(2);
400  my_GMLS_vector_of_scalar_clones.generateAlphas();
401  Kokkos::Profiling::popRegion();
402 
403 
404  //! [Setting Up The GMLS Object]
405 
406  double instantiation_time = timer.seconds();
407  std::cout << "Took " << instantiation_time << "s to complete alphas generation." << std::endl;
408  Kokkos::fence(); // let generateAlphas finish up before using alphas
409  Kokkos::Profiling::pushRegion("Apply Alphas to Data");
410 
411  //! [Apply GMLS Alphas To Data]
412 
413 
414  // it is important to note that if you expect to use the data as a 1D view, then you should use double*
415  // however, if you know that the target operation will result in a 2D view (vector or matrix output),
416  // then you should template with double** as this is something that can not be infered from the input data
417  // or the target operator at compile time. Additionally, a template argument is required indicating either
418  // Kokkos::HostSpace or Kokkos::DefaultExecutionSpace::memory_space()
419 
420  // The Evaluator class takes care of handling input data views as well as the output data views.
421  // It uses information from the GMLS class to determine how many components are in the input
422  // as well as output for any choice of target functionals and then performs the contactions
423  // on the data using the alpha coefficients generated by the GMLS class, all on the device.
424  Evaluator scalar_gmls_evaluator(&my_GMLS_scalar);
425  Evaluator vector_gmls_evaluator(&my_GMLS_vector);
426  Evaluator vector_gmls_evaluator_of_scalar_clones(&my_GMLS_vector_of_scalar_clones);
427 
428  auto output_value = scalar_gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double*, Kokkos::HostSpace>
429  (sampling_data_device, ScalarPointEvaluation, PointSample,
430  true /*scalar_as_vector_if_needed*/, 1 /*evaluation site index*/);
431 
432  auto output_gaussian_curvature = scalar_gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double*, Kokkos::HostSpace>
433  (ones_data_device, GaussianCurvaturePointEvaluation, PointSample,
434  true /*scalar_as_vector_if_needed*/, 1 /*evaluation site index*/);
435 
436  auto output_curl = scalar_gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double**, Kokkos::HostSpace>
437  (sampling_data_device, CurlOfVectorPointEvaluation, PointSample,
438  true /*scalar_as_vector_if_needed*/, 1 /*evaluation site index*/);
439 
440  //auto output_laplacian = scalar_gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double*, Kokkos::HostSpace>
441  // (sampling_data_device, LaplacianOfScalarPointEvaluation, PointSample,
442  // true /*scalar_as_vector_if_needed*/, 1 /*evaluation site index*/);
443 
444  //auto output_gradient = scalar_gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double**, Kokkos::HostSpace>
445  // (sampling_data_device, GradientOfScalarPointEvaluation, PointSample,
446  // true /*scalar_as_vector_if_needed*/, 1 /*evaluation site index*/);
447 
448  auto output_vector = vector_gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double**, Kokkos::HostSpace>
449  (sampling_vector_data_device, VectorPointEvaluation, VaryingManifoldVectorPointSample,
450  true /*scalar_as_vector_if_needed*/, 1 /*evaluation site index*/);
451 
452  //auto output_divergence = vector_gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double*, Kokkos::HostSpace>
453  // (sampling_vector_data_device, DivergenceOfVectorPointEvaluation, ManifoldVectorPointSample,
454  // true /*scalar_as_vector_if_needed*/, 1 /*evaluation site index*/);
455 
456  auto output_vector_of_scalar_clones =
457  vector_gmls_evaluator_of_scalar_clones.applyAlphasToDataAllComponentsAllTargetSites<double**,
458  Kokkos::HostSpace>(sampling_vector_data_device, VectorPointEvaluation, VaryingManifoldVectorPointSample,
459  true /*scalar_as_vector_if_needed*/, 1 /*evaluation site index*/);
460 
461  //auto output_divergence_of_scalar_clones =
462  // vector_gmls_evaluator_of_scalar_clones.applyAlphasToDataAllComponentsAllTargetSites<double*,
463  // Kokkos::HostSpace>(sampling_vector_data_device, DivergenceOfVectorPointEvaluation, ManifoldVectorPointSample,
464  // true /*scalar_as_vector_if_needed*/, 1 /*evaluation site index*/);
465 
466 
467  // Kokkos::fence(); // let application of alphas to data finish before using results
468  //
469  //// move gradient data to device so that it can be transformed into velocity
470  //auto output_gradient_device_mirror = Kokkos::create_mirror(Kokkos::DefaultExecutionSpace::memory_space(), output_gradient);
471  //Kokkos::deep_copy(output_gradient_device_mirror, output_gradient);
472  //Kokkos::parallel_for("Create Velocity From Surface Gradient", Kokkos::RangePolicy<Kokkos::DefaultExecutionSpace>
473  // (0,target_coords.extent(0)), KOKKOS_LAMBDA(const int i) {
474  //
475  // // coordinates of target site i
476  // double xval = target_coords_device(i,0);
477  // double yval = (dimension>1) ? target_coords_device(i,1) : 0;
478  // double zval = (dimension>2) ? target_coords_device(i,2) : 0;
479 
480  // double gradx = output_gradient_device_mirror(i,0);
481  // double grady = output_gradient_device_mirror(i,1);
482  // double gradz = output_gradient_device_mirror(i,2);
483  //
484  // // overwrites gradient with velocity
485  // output_gradient_device_mirror(i,0) = (grady*zval - yval*gradz);
486  // output_gradient_device_mirror(i,1) = (-(gradx*zval - xval*gradz));
487  // output_gradient_device_mirror(i,2) = (gradx*yval - xval*grady);
488  //
489  //});
490  //Kokkos::deep_copy(output_gradient, output_gradient_device_mirror);
491 
492 
493  //! [Apply GMLS Alphas To Data]
494 
495  Kokkos::fence(); // let application of alphas to data finish before using results
496  Kokkos::Profiling::popRegion();
497  // times the Comparison in Kokkos
498  Kokkos::Profiling::pushRegion("Comparison");
499 
500  //! [Check That Solutions Are Correct]
501 
502  double tangent_bundle_error = 0;
503  double tangent_bundle_norm = 0;
504  double values_error = 0;
505  double values_norm = 0;
506  double gc_error = 0;
507  double gc_norm = 0;
508  double curl_ambient_error = 0;
509  double curl_ambient_norm = 0;
510  //double laplacian_error = 0;
511  //double laplacian_norm = 0;
512  //double gradient_ambient_error = 0;
513  //double gradient_ambient_norm = 0;
514  double vector_ambient_error = 0;
515  double vector_ambient_norm = 0;
516  //double divergence_ambient_error = 0;
517  //double divergence_ambient_norm = 0;
518  double vector_of_scalar_clones_ambient_error = 0;
519  double vector_of_scalar_clones_ambient_norm = 0;
520  //double divergence_of_scalar_clones_ambient_error = 0;
521  //double divergence_of_scalar_clones_ambient_norm = 0;
522 
523  // tangent vectors for each source coordinate are stored here
524  auto d_prestencil_weights = my_GMLS_vector_of_scalar_clones.getPrestencilWeights();
525  auto prestencil_weights = Kokkos::create_mirror_view(d_prestencil_weights);
526  Kokkos::deep_copy(prestencil_weights, d_prestencil_weights);
527 
528  // tangent vector at target sites are stored here
529  auto d_tangent_directions = *(my_GMLS_vector_of_scalar_clones.getTangentDirections());
530  auto tangent_directions = Kokkos::create_mirror_view(d_tangent_directions);
531  Kokkos::deep_copy(tangent_directions, d_tangent_directions);
532 
533  // loop through the target sites
534  for (int i=0; i<number_target_coords; i++) {
535 
537  (tangent_directions.data() + TO_GLOBAL(i)*TO_GLOBAL(3)*TO_GLOBAL(3), 3, 3);
538  XYZ u;
539 
540 
541  // load value from output
542  double GMLS_value = output_value(i);
543  //printf("GMLS val: %f, %d\n", GMLS_value, i);
544 
545  double GMLS_gc = output_gaussian_curvature(i);
546  //printf("GMLS gc: %f, %d\n", GMLS_gc, i);
547 
548  // // load laplacian from output
549  // double GMLS_Laplacian = output_laplacian(i);
550 
551  // target site i's coordinate
552  //double xval = target_coords(i,0);
553  //double yval = (dimension>1) ? target_coords(i,1) : 0;
554  //double zval = (dimension>2) ? target_coords(i,2) : 0;
555  double xval = source_coords(neighbor_lists(i,1),0);
556  double yval = (dimension>1) ? source_coords(neighbor_lists(i,1),1) : 0;
557  double zval = (dimension>2) ? source_coords(neighbor_lists(i,1),2) : 0;
558  double coord[3] = {xval, yval, zval};
559 
560  // get tangent vector and see if orthgonal to coordinate (it should be on a sphere)
561  for (int j=0; j<dimension-1; ++j) {
562  double tangent_inner_prod = 0;
563  for (int k=0; k<std::min(dimension,3); ++k) {
564  tangent_inner_prod += coord[k] * prestencil_weights(0, i, 0 /* local neighbor index */, j, k);
565  }
566  tangent_bundle_error += tangent_inner_prod * tangent_inner_prod;
567  }
568  double normal_inner_prod = 0;
569  for (int k=0; k<dimension; ++k) {
570  normal_inner_prod += coord[k] * my_GMLS_scalar.getTangentBundle(i, dimension-1, k);
571  }
572  // inner product could be plus or minus 1 (depends on tangent direction ordering)
573  double normal_error_to_sum = (normal_inner_prod > 0) ? normal_inner_prod - 1 : normal_inner_prod + 1;
574  tangent_bundle_error += normal_error_to_sum * normal_error_to_sum;
575  tangent_bundle_norm += 1;
576 
577  // evaluation of various exact solutions
578  double actual_value = sphere_harmonic54(xval, yval, zval);
579  double actual_gc = 1.0; // Gaussian curvature is constant
580  // double actual_Laplacian = laplace_beltrami_sphere_harmonic54(xval, yval, zval);
581  double actual_Gradient_ambient[3] = {0,0,0}; // initialized for 3, but only filled up to dimension
582  gradient_sphereHarmonic54_ambient(actual_Gradient_ambient, xval, yval, zval);
583  // //velocity_sphereHarmonic54_ambient(actual_Gradient_ambient, xval, yval, zval);
584  double actual_Curl_ambient[3] = {0,0,0};
585  curl_sphere_harmonic54(actual_Curl_ambient, xval, yval, zval);
586 
587  values_error += (GMLS_value - actual_value)*(GMLS_value - actual_value);
588  values_norm += actual_value*actual_value;
589 
590  gc_error += (GMLS_gc - actual_gc)*(GMLS_gc - actual_gc);
591  gc_norm += 1;
592 
593  for (int j=0; j<dimension; ++j) u[j] = output_curl(i,j);
594  AmbientLocalAmbient(u, T.data(), &prestencil_weights(0, i, 0 /* local neighbor index */, 0, 0));
595  for (int j=0; j<dimension; ++j) output_curl(i,j) = u[j];
596 
597  for (int j=0; j<dimension; ++j) {
598  curl_ambient_error += (output_curl(i,j) - actual_Curl_ambient[j])*(output_curl(i,j) - actual_Curl_ambient[j]);
599  curl_ambient_norm += actual_Curl_ambient[j]*actual_Curl_ambient[j];
600  }
601 
602  // laplacian_error += (GMLS_Laplacian - actual_Laplacian)*(GMLS_Laplacian - actual_Laplacian);
603  // laplacian_norm += actual_Laplacian*actual_Laplacian;
604 
605  // for (int j=0; j<dimension; ++j) {
606  // gradient_ambient_error += (output_gradient(i,j) - actual_Gradient_ambient[j])*(output_gradient(i,j) - actual_Gradient_ambient[j]);
607  // gradient_ambient_norm += actual_Gradient_ambient[j]*actual_Gradient_ambient[j];
608  // }
609 
610  for (int j=0; j<dimension; ++j) u[j] = output_vector(i,j);
611  AmbientLocalAmbient(u, T.data(), &prestencil_weights(0, i, 0 /* local neighbor index */, 0, 0));
612  for (int j=0; j<dimension; ++j) output_vector(i,j) = u[j];
613 
614  for (int j=0; j<dimension; ++j) {
615  vector_ambient_error += (output_vector(i,j) - actual_Gradient_ambient[j])*(output_vector(i,j) - actual_Gradient_ambient[j]);
616  vector_ambient_norm += actual_Gradient_ambient[j]*actual_Gradient_ambient[j];
617  }
618 
619  // divergence_ambient_error += (output_divergence(i) - actual_Laplacian)*(output_divergence(i) - actual_Laplacian);
620  // divergence_ambient_norm += actual_Laplacian*actual_Laplacian;
621 
622 
623  for (int j=0; j<dimension; ++j) u[j] = output_vector_of_scalar_clones(i,j);
624  AmbientLocalAmbient(u, T.data(), &prestencil_weights(0, i, 0 /* local neighbor index */, 0, 0));
625  for (int j=0; j<dimension; ++j) output_vector_of_scalar_clones(i,j) = u[j];
626  //// first get back to local chart
627  //double local_vec[3] = {0,0};
628  //for (int j=0; j<dimension; ++j) {
629  // local_vec[0] += T(0,j) * output_vector_of_scalar_clones(i,j);
630  // local_vec[1] += T(1,j) * output_vector_of_scalar_clones(i,j);
631  //}
632  //// second go to ambient space using tangent for first neighbor
633  //for (int j=0; j<dimension; ++j) output_vector_of_scalar_clones(i,j) = 0;
634  //for (int j=0; j<dimension; ++j) {
635  // output_vector_of_scalar_clones(i,j) += prestencil_weights(0, i, 0 /* local neighbor index */, 0, j) * local_vec[0];
636  // output_vector_of_scalar_clones(i,j) += prestencil_weights(0, i, 0 /* local neighbor index */, 1, j) * local_vec[1];
637  //}
638 
639 
640  for (int j=0; j<dimension; ++j) {
641  vector_of_scalar_clones_ambient_error += (output_vector_of_scalar_clones(i,j) - actual_Gradient_ambient[j])*(output_vector_of_scalar_clones(i,j) - actual_Gradient_ambient[j]);
642  vector_of_scalar_clones_ambient_norm += actual_Gradient_ambient[j]*actual_Gradient_ambient[j];
643  }
644 
645  // divergence_of_scalar_clones_ambient_error += (output_divergence_of_scalar_clones(i) - actual_Laplacian)*(output_divergence_of_scalar_clones(i) - actual_Laplacian);
646  // divergence_of_scalar_clones_ambient_norm += actual_Laplacian*actual_Laplacian;
647 
648  }
649 
650  tangent_bundle_error /= number_target_coords;
651  tangent_bundle_error = std::sqrt(tangent_bundle_error);
652  tangent_bundle_norm /= number_target_coords;
653  tangent_bundle_norm = std::sqrt(tangent_bundle_norm);
654 
655  values_error /= number_target_coords;
656  values_error = std::sqrt(values_error);
657  values_norm /= number_target_coords;
658  values_norm = std::sqrt(values_norm);
659 
660  gc_error /= number_target_coords;
661  gc_error = std::sqrt(gc_error);
662  gc_norm /= number_target_coords;
663  gc_norm = std::sqrt(gc_norm);
664 
665  curl_ambient_error /= number_target_coords;
666  curl_ambient_error = std::sqrt(curl_ambient_error);
667  curl_ambient_norm /= number_target_coords;
668  curl_ambient_norm = std::sqrt(curl_ambient_norm);
669 
670  //laplacian_error /= number_target_coords;
671  //laplacian_error = std::sqrt(laplacian_error);
672  //laplacian_norm /= number_target_coords;
673  //laplacian_norm = std::sqrt(laplacian_norm);
674 
675  //gradient_ambient_error /= number_target_coords;
676  //gradient_ambient_error = std::sqrt(gradient_ambient_error);
677  //gradient_ambient_norm /= number_target_coords;
678  //gradient_ambient_norm = std::sqrt(gradient_ambient_norm);
679 
680  vector_ambient_error /= number_target_coords;
681  vector_ambient_error = std::sqrt(vector_ambient_error);
682  vector_ambient_norm /= number_target_coords;
683  vector_ambient_norm = std::sqrt(vector_ambient_norm);
684 
685  //divergence_ambient_error /= number_target_coords;
686  //divergence_ambient_error = std::sqrt(divergence_ambient_error);
687  //divergence_ambient_norm /= number_target_coords;
688  //divergence_ambient_norm = std::sqrt(divergence_ambient_norm);
689 
690  vector_of_scalar_clones_ambient_error /= number_target_coords;
691  vector_of_scalar_clones_ambient_error = std::sqrt(vector_of_scalar_clones_ambient_error);
692  vector_of_scalar_clones_ambient_norm /= number_target_coords;
693  vector_of_scalar_clones_ambient_norm = std::sqrt(vector_of_scalar_clones_ambient_norm);
694 
695  //divergence_of_scalar_clones_ambient_error /= number_target_coords;
696  //divergence_of_scalar_clones_ambient_error = std::sqrt(divergence_of_scalar_clones_ambient_error);
697  //divergence_of_scalar_clones_ambient_norm /= number_target_coords;
698  //divergence_of_scalar_clones_ambient_norm = std::sqrt(divergence_of_scalar_clones_ambient_norm);
699 
700  printf("Tangent Bundle Error: %g\n", tangent_bundle_error / tangent_bundle_norm);
701  printf("Point Value Error: %g\n", values_error / values_norm);
702  printf("Gaussian Curvature Error: %g\n", gc_error / gc_norm);
703  printf("Surface Curl (Ambient) Error: %g\n", curl_ambient_error / curl_ambient_norm);
704  //printf("Laplace-Beltrami Error: %g\n", laplacian_error / laplacian_norm);
705  //printf("Surface Gradient (Ambient) Error: %g\n", gradient_ambient_error / gradient_ambient_norm);
706  printf("Surface Vector (VectorBasis) Error: %g\n", vector_ambient_error / vector_ambient_norm);
707  //printf("Surface Divergence (VectorBasis) Error: %g\n", divergence_ambient_error / divergence_ambient_norm);
708  printf("Surface Vector (ScalarClones) Error: %g\n",
709  vector_of_scalar_clones_ambient_error / vector_of_scalar_clones_ambient_norm);
710  //printf("Surface Divergence (ScalarClones) Error: %g\n",
711  // divergence_of_scalar_clones_ambient_error / divergence_of_scalar_clones_ambient_norm);
712  //! [Check That Solutions Are Correct]
713  // popRegion hidden from tutorial
714  // stop timing comparison loop
715  Kokkos::Profiling::popRegion();
716  //! [Finalize Program]
717 
718 
719 } // end of code block to reduce scope, causing Kokkos View de-allocations
720 // otherwise, Views may be deallocating when we call Kokkos::finalize() later
721 
722 // finalize Kokkos and MPI (if available)
723 Kokkos::finalize();
724 #ifdef COMPADRE_USE_MPI
725 MPI_Finalize();
726 #endif
727 
728 return 0;
729 
730 } // main
731 
732 
733 //! [Finalize Program]
#define TO_GLOBAL(variable)
Kokkos::View< double **, layout_right, host_execution_space, Kokkos::MemoryTraits< Kokkos::Unmanaged > > host_scratch_matrix_right_type
KOKKOS_INLINE_FUNCTION double sphere_harmonic54(double x, double y, double z)
#define PI
KOKKOS_INLINE_FUNCTION void gradient_sphereHarmonic54_ambient(double *gradient, double x, double y, double z)
KOKKOS_INLINE_FUNCTION void curl_sphere_harmonic54(double *curl, double x, double y, double z)
void AmbientLocalAmbient(XYZ &u, double *T_data, double *P_data)
[Ambient to Local Back To Ambient Helper Function]
int main(int argc, char *args[])
[Ambient to Local Back To Ambient Helper Function]
Lightweight Evaluator Helper This class is a lightweight wrapper for extracting and applying all rele...
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)
Generalized Moving Least Squares (GMLS)
void addTargets(TargetOperation lro)
Adds a target to the vector of target functional to be applied to the reconstruction.
void setReferenceOutwardNormalDirection(view_type outward_normal_directions, bool use_to_orient_surface=true)
(OPTIONAL) Sets outward normal direction.
void setCurvatureWeightingParameter(int wp, int index=0)
Parameter for weighting kernel for curvature index = 0 sets p paramater for weighting kernel index = ...
void setAdditionalEvaluationSitesData(view_type_1 additional_evaluation_indices, view_type_2 additional_evaluation_coordinates)
(OPTIONAL) Sets additional evaluation sites for each target site
void setWeightingParameter(int wp, int index=0)
Parameter for weighting kernel for GMLS problem index = 0 sets p paramater for weighting kernel index...
void generateAlphas(const int number_of_batches=1, const bool keep_coefficients=false, const bool clear_cache=true)
Meant to calculate target operations and apply the evaluations to the previously constructed polynomi...
void setProblemData(view_type_1 neighbor_lists, view_type_2 source_coordinates, view_type_3 target_coordinates, view_type_4 epsilons)
Sets basic problem data (neighbor lists, source coordinates, and target coordinates)
void setWeightingType(const std::string &wt)
Type for weighting kernel for GMLS problem.
static KOKKOS_INLINE_FUNCTION int getNP(const int m, const int dimension=3, const ReconstructionSpace r_space=ReconstructionSpace::ScalarTaylorPolynomial)
Returns size of the basis for a given polynomial order and dimension General to dimension 1....
decltype(_T) * getTangentDirections()
Get a view (device) of all tangent direction bundles.
void setCurvatureWeightingType(const std::string &wt)
Type for weighting kernel for curvature.
double getTangentBundle(const int target_index, const int direction, const int component) const
Get component of tangent or normal directions for manifold problems.
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...
constexpr SamplingFunctional VaryingManifoldVectorPointSample
For integrating polynomial dotted with normal over an edge.
constexpr SamplingFunctional PointSample
Available sampling functionals.
PointCloudSearch< view_type > CreatePointCloudSearch(view_type src_view, const local_index_type dimensions=-1, const local_index_type max_leaf=-1)
CreatePointCloudSearch allows for the construction of an object of type PointCloudSearch with templat...
@ VectorTaylorPolynomial
Vector polynomial basis having # of components _dimensions, or (_dimensions-1) in the case of manifol...
@ VectorOfScalarClonesTaylorPolynomial
Scalar basis reused as many times as there are components in the vector resulting in a much cheaper p...
@ CurlOfVectorPointEvaluation
Point evaluation of the curl of a vector (results in a vector)
@ GaussianCurvaturePointEvaluation
Point evaluation of Gaussian curvature.
@ VectorPointEvaluation
Point evaluation of a vector (reconstructs entire vector at once, requiring a ReconstructionSpace hav...
@ ScalarPointEvaluation
Point evaluation of a scalar.