based on GMLS_Manifold.cpp
GMLS Example with Device Views
This tutorial sets up a batch of GMLS problems, solves the minimization problems, and applies the coefficients produced to data.
Parse Command Line Arguments
int main (
int argc,
char* args[]) {
#ifdef COMPADRE_USE_MPI
MPI_Init(&argc, &args);
#endif
Kokkos::initialize(argc, args);
{
int main(int argc, char **argv)
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....
std::string constraint_name
Setting Up The Point Cloud
Kokkos::View<double**, Kokkos::DefaultExecutionSpace> source_coords_device("source coordinates",
1.25*N_pts_on_sphere, 3);
Kokkos::View<double**>::HostMirror source_coords = Kokkos::create_mirror_view(source_coords_device);
double r = 1.0;
int number_source_coords;
{
int N_count = 0;
double a = 4*
PI*r*r/N_pts_on_sphere;
double d = std::sqrt(a);
int M_theta = std::round(
PI/d);
double d_theta =
PI/M_theta;
double d_phi = a/d_theta;
for (int i=0; i<M_theta; ++i) {
double theta =
PI*(i + 0.5)/M_theta;
int M_phi = std::ceil(2*
PI*std::sin(theta)/d_phi);
for (int j=0; j<M_phi; ++j) {
double phi = 2*
PI*j/M_phi;
source_coords(N_count, 0) = theta;
source_coords(N_count, 1) = phi;
N_count++;
}
}
for (int i=0; i<N_count; ++i) {
double theta = source_coords(i,0);
double phi = source_coords(i,1);
source_coords(i,0) = r*std::sin(theta)*std::cos(phi);
source_coords(i,1) = r*std::sin(theta)*std::sin(phi);
source_coords(i,2) = r*cos(theta);
}
number_source_coords = N_count;
}
Kokkos::resize(source_coords, number_source_coords, 3);
Kokkos::resize(source_coords_device, number_source_coords, 3);
Kokkos::View<double**, Kokkos::DefaultExecutionSpace> target_coords_device ("target coordinates",
number_target_coords, 3);
Kokkos::View<double**>::HostMirror target_coords = Kokkos::create_mirror_view(target_coords_device);
{
bool enough_pts_found = false;
int N_count = 0;
double a = 4.0*
PI*r*r/((double)(1.0*number_target_coords));
double d = std::sqrt(a);
int M_theta = std::round(
PI/d);
double d_theta =
PI/((double)M_theta);
double d_phi = a/d_theta;
for (int i=0; i<M_theta; ++i) {
double theta =
PI*(i + 0.5)/M_theta;
int M_phi = std::ceil(2*
PI*std::sin(theta)/d_phi);
for (int j=0; j<M_phi; ++j) {
double phi = 2*
PI*j/M_phi;
target_coords(N_count, 0) = theta;
target_coords(N_count, 1) = phi;
N_count++;
if (N_count == number_target_coords) {
enough_pts_found = true;
break;
}
}
if (enough_pts_found) break;
}
for (int i=0; i<N_count; ++i) {
double theta = target_coords(i,0);
double phi = target_coords(i,1);
target_coords(i,0) = r*std::sin(theta)*std::cos(phi);
target_coords(i,1) = r*std::sin(theta)*std::sin(phi);
target_coords(i,2) = r*cos(theta);
}
}
Performing Neighbor Search
double epsilon_multiplier = 1.9;
Kokkos::View<int*> neighbor_lists_device("neighbor lists",
0);
Kokkos::View<int*>::HostMirror neighbor_lists = Kokkos::create_mirror_view(neighbor_lists_device);
Kokkos::View<int*> number_of_neighbors_list_device("number of neighbor lists",
number_target_coords);
Kokkos::View<int*>::HostMirror number_of_neighbors_list = Kokkos::create_mirror_view(number_of_neighbors_list_device);
Kokkos::View<double*, Kokkos::DefaultExecutionSpace> epsilon_device("h supports", number_target_coords);
Kokkos::View<double*>::HostMirror epsilon = Kokkos::create_mirror_view(epsilon_device);
size_t storage_size = point_cloud_search.generateCRNeighborListsFromKNNSearch(true , target_coords, neighbor_lists,
number_of_neighbors_list, epsilon, min_neighbors, epsilon_multiplier);
Kokkos::resize(neighbor_lists_device, storage_size);
neighbor_lists = Kokkos::create_mirror_view(neighbor_lists_device);
point_cloud_search.generateCRNeighborListsFromKNNSearch(false , target_coords, neighbor_lists,
number_of_neighbors_list, epsilon, min_neighbors, epsilon_multiplier);
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...
Creating The Data
Kokkos::deep_copy(source_coords_device, source_coords);
Kokkos::deep_copy(target_coords_device, target_coords);
Kokkos::fence();
Kokkos::View<double*, Kokkos::DefaultExecutionSpace> sampling_data_device("samples of true solution",
source_coords_device.extent(0));
Kokkos::View<double*, Kokkos::DefaultExecutionSpace> ones_data_device("samples of ones",
source_coords_device.extent(0));
Kokkos::deep_copy(ones_data_device, 1.0);
Kokkos::View<double**, Kokkos::DefaultExecutionSpace> sampling_vector_data_device("samples of vector true solution",
source_coords_device.extent(0), 3);
Kokkos::parallel_for("Sampling Manufactured Solutions", Kokkos::RangePolicy<Kokkos::DefaultExecutionSpace>
(0,source_coords.extent(0)), KOKKOS_LAMBDA(const int i) {
double xval = source_coords_device(i,0);
double yval = (dimension>1) ? source_coords_device(i,1) : 0;
double zval = (dimension>2) ? source_coords_device(i,2) : 0;
for (int j=0; j<3; ++j) {
double gradient[3] = {0,0,0};
sampling_vector_data_device(i,j) = gradient[j];
}
});
KOKKOS_INLINE_FUNCTION double sphere_harmonic54(double x, double y, double z)
KOKKOS_INLINE_FUNCTION void gradient_sphereHarmonic54_ambient(double *gradient, double x, double y, double z)
Setting Up The GMLS Object
Kokkos::deep_copy(neighbor_lists_device, neighbor_lists);
Kokkos::deep_copy(number_of_neighbors_list_device, number_of_neighbors_list);
Kokkos::deep_copy(epsilon_device, epsilon);
GMLS my_GMLS_scalar(order, dimension,
solver_name.c_str(), problem_name.c_str(), constraint_name.c_str(),
order );
my_GMLS_scalar.setProblemData(neighbor_lists_device, number_of_neighbors_list_device, source_coords_device, target_coords_device, epsilon_device);
my_GMLS_scalar.setReferenceOutwardNormalDirection(target_coords_device, true );
std::vector<TargetOperation> lro_scalar(4);
my_GMLS_scalar.addTargets(lro_scalar);
my_GMLS_scalar.setCurvatureWeightingParameter(2);
my_GMLS_scalar.setWeightingParameter(2);
my_GMLS_scalar.generateAlphas();
Kokkos::Profiling::pushRegion("Full Polynomial Basis GMLS Solution");
order, dimension,
solver_name.c_str(), problem_name.c_str(), constraint_name.c_str(),
order );
my_GMLS_vector.setProblemData(neighbor_lists_device, number_of_neighbors_list_device, source_coords_device, target_coords_device, epsilon_device);
std::vector<TargetOperation> lro_vector(2);
my_GMLS_vector.addTargets(lro_vector);
my_GMLS_vector.setCurvatureWeightingParameter(2);
my_GMLS_vector.setWeightingParameter(2);
my_GMLS_vector.generateAlphas();
Kokkos::Profiling::popRegion();
Kokkos::Profiling::pushRegion("Scalar Polynomial Basis Repeated to Form a Vector GMLS Solution");
order, dimension,
solver_name.c_str(), problem_name.c_str(), constraint_name.c_str(),
order );
my_GMLS_vector_of_scalar_clones.setProblemData(neighbor_lists_device, number_of_neighbors_list_device, source_coords_device, target_coords_device, epsilon_device);
std::vector<TargetOperation> lro_vector_of_scalar_clones(2);
my_GMLS_vector_of_scalar_clones.addTargets(lro_vector_of_scalar_clones);
my_GMLS_vector_of_scalar_clones.setCurvatureWeightingParameter(2);
my_GMLS_vector_of_scalar_clones.setWeightingParameter(2);
my_GMLS_vector_of_scalar_clones.generateAlphas();
Kokkos::Profiling::popRegion();
@ 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...
constexpr SamplingFunctional ManifoldVectorPointSample
Point evaluations of the entire vector source function (but on a manifold, so it includes a transform...
@ LaplacianOfScalarPointEvaluation
Point evaluation of the laplacian of a scalar (could be on a manifold or not)
@ GradientOfScalarPointEvaluation
Point evaluation of the gradient of a scalar.
@ GaussianCurvaturePointEvaluation
Point evaluation of Gaussian curvature.
@ DivergenceOfVectorPointEvaluation
Point evaluation of the divergence of a vector (results in a scalar)
@ VectorPointEvaluation
Point evaluation of a vector (reconstructs entire vector at once, requiring a ReconstructionSpace hav...
@ ScalarPointEvaluation
Point evaluation of a scalar.
Apply GMLS Alphas To Data
Evaluator scalar_gmls_evaluator(&my_GMLS_scalar);
Evaluator vector_gmls_evaluator(&my_GMLS_vector);
Evaluator vector_gmls_evaluator_of_scalar_clones(&my_GMLS_vector_of_scalar_clones);
auto output_value = scalar_gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double*, Kokkos::HostSpace>
auto output_laplacian = scalar_gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double*, Kokkos::HostSpace>
auto output_gradient = scalar_gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double**, Kokkos::HostSpace>
auto output_gc = scalar_gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double*, Kokkos::HostSpace>
auto output_vector = vector_gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double**, Kokkos::HostSpace>
auto output_divergence = vector_gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double*, Kokkos::HostSpace>
auto output_vector_of_scalar_clones =
vector_gmls_evaluator_of_scalar_clones.applyAlphasToDataAllComponentsAllTargetSites<double**,
auto output_divergence_of_scalar_clones =
vector_gmls_evaluator_of_scalar_clones.applyAlphasToDataAllComponentsAllTargetSites<double*,
Check That Solutions Are Correct
double tangent_bundle_error = 0;
double tangent_bundle_norm = 0;
double values_error = 0;
double values_norm = 0;
double laplacian_error = 0;
double laplacian_norm = 0;
double gradient_ambient_error = 0;
double gradient_ambient_norm = 0;
double gc_error = 0;
double gc_norm = 0;
double vector_ambient_error = 0;
double vector_ambient_norm = 0;
double divergence_ambient_error = 0;
double divergence_ambient_norm = 0;
double vector_of_scalar_clones_ambient_error = 0;
double vector_of_scalar_clones_ambient_norm = 0;
double divergence_of_scalar_clones_ambient_error = 0;
double divergence_of_scalar_clones_ambient_norm = 0;
for (int i=0; i<number_target_coords; i++) {
double GMLS_value = output_value(i);
double GMLS_gc = output_gc(i);
double GMLS_Laplacian = output_laplacian(i);
double xval = target_coords(i,0);
double yval = (dimension>1) ? target_coords(i,1) : 0;
double zval = (dimension>2) ? target_coords(i,2) : 0;
double coord[3] = {xval, yval, zval};
for (unsigned int j=0; j<static_cast<unsigned int>(dimension-1); ++j) {
double tangent_inner_prod = 0;
for (int k=0; k<dimension; ++k) {
tangent_inner_prod += coord[k] * my_GMLS_scalar.getTangentBundle(i, j, k);
}
tangent_bundle_error += tangent_inner_prod * tangent_inner_prod;
}
double normal_inner_prod = 0;
for (int k=0; k<dimension; ++k) {
normal_inner_prod += coord[k] * my_GMLS_scalar.getTangentBundle(i, dimension-1, k);
}
double normal_error_to_sum = (normal_inner_prod > 0) ? normal_inner_prod - 1 : normal_inner_prod + 1;
tangent_bundle_error += normal_error_to_sum * normal_error_to_sum;
tangent_bundle_norm += 1;
double actual_Gradient_ambient[3] = {0,0,0};
values_error += (GMLS_value - actual_value)*(GMLS_value - actual_value);
values_norm += actual_value*actual_value;
laplacian_error += (GMLS_Laplacian - actual_Laplacian)*(GMLS_Laplacian - actual_Laplacian);
laplacian_norm += actual_Laplacian*actual_Laplacian;
double actual_gc = 1.0;
gc_error += (GMLS_gc - actual_gc)*(GMLS_gc - actual_gc);
gc_norm += actual_gc*actual_gc;
for (int j=0; j<dimension; ++j) {
gradient_ambient_error += (output_gradient(i,j) - actual_Gradient_ambient[j])*(output_gradient(i,j) - actual_Gradient_ambient[j]);
gradient_ambient_norm += actual_Gradient_ambient[j]*actual_Gradient_ambient[j];
}
for (int j=0; j<dimension; ++j) {
vector_ambient_error += (output_vector(i,j) - actual_Gradient_ambient[j])*(output_vector(i,j) - actual_Gradient_ambient[j]);
vector_ambient_norm += actual_Gradient_ambient[j]*actual_Gradient_ambient[j];
}
divergence_ambient_error += (output_divergence(i) - actual_Laplacian)*(output_divergence(i) - actual_Laplacian);
divergence_ambient_norm += actual_Laplacian*actual_Laplacian;
for (int j=0; j<dimension; ++j) {
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]);
vector_of_scalar_clones_ambient_norm += actual_Gradient_ambient[j]*actual_Gradient_ambient[j];
}
divergence_of_scalar_clones_ambient_error += (output_divergence_of_scalar_clones(i) - actual_Laplacian)*(output_divergence_of_scalar_clones(i) - actual_Laplacian);
divergence_of_scalar_clones_ambient_norm += actual_Laplacian*actual_Laplacian;
}
tangent_bundle_error /= number_target_coords;
tangent_bundle_error = std::sqrt(tangent_bundle_error);
tangent_bundle_norm /= number_target_coords;
tangent_bundle_norm = std::sqrt(tangent_bundle_norm);
values_error /= number_target_coords;
values_error = std::sqrt(values_error);
values_norm /= number_target_coords;
values_norm = std::sqrt(values_norm);
laplacian_error /= number_target_coords;
laplacian_error = std::sqrt(laplacian_error);
laplacian_norm /= number_target_coords;
laplacian_norm = std::sqrt(laplacian_norm);
gradient_ambient_error /= number_target_coords;
gradient_ambient_error = std::sqrt(gradient_ambient_error);
gradient_ambient_norm /= number_target_coords;
gradient_ambient_norm = std::sqrt(gradient_ambient_norm);
gc_error /= number_target_coords;
gc_error = std::sqrt(gc_error);
gc_norm /= number_target_coords;
gc_norm = std::sqrt(gc_norm);
vector_ambient_error /= number_target_coords;
vector_ambient_error = std::sqrt(vector_ambient_error);
vector_ambient_norm /= number_target_coords;
vector_ambient_norm = std::sqrt(vector_ambient_norm);
divergence_ambient_error /= number_target_coords;
divergence_ambient_error = std::sqrt(divergence_ambient_error);
divergence_ambient_norm /= number_target_coords;
divergence_ambient_norm = std::sqrt(divergence_ambient_norm);
vector_of_scalar_clones_ambient_error /= number_target_coords;
vector_of_scalar_clones_ambient_error = std::sqrt(vector_of_scalar_clones_ambient_error);
vector_of_scalar_clones_ambient_norm /= number_target_coords;
vector_of_scalar_clones_ambient_norm = std::sqrt(vector_of_scalar_clones_ambient_norm);
divergence_of_scalar_clones_ambient_error /= number_target_coords;
divergence_of_scalar_clones_ambient_error = std::sqrt(divergence_of_scalar_clones_ambient_error);
divergence_of_scalar_clones_ambient_norm /= number_target_coords;
divergence_of_scalar_clones_ambient_norm = std::sqrt(divergence_of_scalar_clones_ambient_norm);
printf("Tangent Bundle Error: %g\n", tangent_bundle_error / tangent_bundle_norm);
printf("Point Value Error: %g\n", values_error / values_norm);
printf("Laplace-Beltrami Error: %g\n", laplacian_error / laplacian_norm);
printf("Gaussian Curvature Error: %g\n", gc_error / gc_norm);
printf("Surface Gradient (Ambient) Error: %g\n", gradient_ambient_error / gradient_ambient_norm);
printf("Surface Vector (VectorBasis) Error: %g\n", vector_ambient_error / vector_ambient_norm);
printf("Surface Divergence (VectorBasis) Error: %g\n", divergence_ambient_error / divergence_ambient_norm);
printf("Surface Vector (ScalarClones) Error: %g\n",
vector_of_scalar_clones_ambient_error / vector_of_scalar_clones_ambient_norm);
printf("Surface Divergence (ScalarClones) Error: %g\n",
divergence_of_scalar_clones_ambient_error / divergence_of_scalar_clones_ambient_norm);
KOKKOS_INLINE_FUNCTION double laplace_beltrami_sphere_harmonic54(double x, double y, double z)
Finalize Program
}
Kokkos::finalize();
#ifdef COMPADRE_USE_MPI
MPI_Finalize();
#endif
return 0;
}
GMLS Tutorial