Compadre 1.7.0
Loading...
Searching...
No Matches
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>
21
22#include "GMLS_Manifold.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
32using namespace Compadre;
33//! [Ambient to Local Back To Ambient Helper Function]
34void 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
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
67int main (int argc, char* args[]) {
68
69// initializes MPI (if available) with command line arguments given
70#ifdef COMPADRE_USE_MPI
71MPI_Init(&argc, &args);
72#endif
73
74// initializes Kokkos with command line arguments given
75Kokkos::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**>::host_mirror_type 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**>::host_mirror_type 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**>::host_mirror_type 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*>::host_mirror_type 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
325 my_GMLS_scalar.setCurvatureWeightingType(WeightingFunctionType::Power);
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
331 my_GMLS_scalar.setWeightingType(WeightingFunctionType::Power);
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.
344 GMLS my_GMLS_vector(ReconstructionSpace::VectorTaylorPolynomial, VaryingManifoldVectorPointSample,
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);
355 my_GMLS_vector.setCurvatureWeightingType(WeightingFunctionType::Power);
356 my_GMLS_vector.setCurvatureWeightingParameter(2);
357 my_GMLS_vector.setWeightingType(WeightingFunctionType::Power);
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 //
385 GMLS my_GMLS_vector_of_scalar_clones(ReconstructionSpace::VectorOfScalarClonesTaylorPolynomial, VaryingManifoldVectorPointSample,
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>
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)
723Kokkos::finalize();
724#ifdef COMPADRE_USE_MPI
725MPI_Finalize();
726#endif
727
728return 0;
729
730} // main
731
732
733//! [Finalize Program]
#define TO_GLOBAL(variable)
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...
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...
constexpr SamplingFunctional VaryingManifoldVectorPointSample
For integrating polynomial dotted with normal over an edge.
constexpr SamplingFunctional PointSample
Available sampling functionals.
Kokkos::View< double **, layout_right, host_execution_space, Kokkos::MemoryTraits< Kokkos::Unmanaged > > host_unmanaged_matrix_right_type
@ 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.