based on GMLS_Device.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
auto kp = KokkosParser(argc, args, true);
bool all_passed = true;
{
int number_of_batches = 1;
if (argc >= 8) {
int arg8toi = atoi(args[7]);
if (arg8toi > 0) {
number_of_batches = arg8toi;
}
}
bool keep_coefficients = number_of_batches==1;
int constraint_type = 0;
if (argc >= 7) {
int arg7toi = atoi(args[6]);
if (arg7toi > 0) {
constraint_type = arg7toi;
}
}
int problem_type = 0;
if (argc >= 6) {
int arg6toi = atoi(args[5]);
if (arg6toi > 0) {
problem_type = arg6toi;
}
}
int solver_type = 1;
if (argc >= 5) {
int arg5toi = atoi(args[4]);
if (arg5toi >= 0) {
solver_type = arg5toi;
}
}
int dimension = 3;
if (argc >= 4) {
int arg4toi = atoi(args[3]);
if (arg4toi > 0) {
dimension = arg4toi;
}
}
int number_target_coords = 200;
if (argc >= 3) {
int arg3toi = atoi(args[2]);
if (arg3toi > 0) {
number_target_coords = arg3toi;
}
}
int order = 3;
if (argc >= 2) {
int arg2toi = atoi(args[1]);
if (arg2toi > 0) {
order = arg2toi;
}
}
const double failure_tolerance = 1e-9;
const double laplacian_failure_tolerance = 1e-9;
Setting Up The Point Cloud
double h_spacing = 0.05;
int n_neg1_to_1 = 2*(1/h_spacing) + 1;
const int number_source_coords = std::pow(n_neg1_to_1, dimension);
Kokkos::View<double**, Kokkos::DefaultExecutionSpace> source_coords_device("source coordinates",
number_source_coords, 3);
Kokkos::View<double**>::HostMirror source_coords = Kokkos::create_mirror_view(source_coords_device);
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);
int source_index = 0;
double this_coord[3] = {0,0,0};
for (int i=-n_neg1_to_1/2; i<n_neg1_to_1/2+1; ++i) {
this_coord[0] = i*h_spacing;
for (int j=-n_neg1_to_1/2; j<n_neg1_to_1/2+1; ++j) {
this_coord[1] = j*h_spacing;
for (int k=-n_neg1_to_1/2; k<n_neg1_to_1/2+1; ++k) {
this_coord[2] = k*h_spacing;
if (dimension==3) {
source_coords(source_index,0) = this_coord[0];
source_coords(source_index,1) = this_coord[1];
source_coords(source_index,2) = this_coord[2];
source_index++;
}
}
if (dimension==2) {
source_coords(source_index,0) = this_coord[0];
source_coords(source_index,1) = this_coord[1];
source_coords(source_index,2) = 0;
source_index++;
}
}
if (dimension==1) {
source_coords(source_index,0) = this_coord[0];
source_coords(source_index,1) = 0;
source_coords(source_index,2) = 0;
source_index++;
}
}
for(int i=0; i<number_target_coords; i++){
double rand_dir[3] = {0,0,0};
for (int j=0; j<dimension; ++j) {
rand_dir[j] = ((double)rand() / (double) RAND_MAX) - 0.5;
}
for (int j=0; j<dimension; ++j) {
target_coords(i,j) = rand_dir[j];
}
}
Performing Neighbor Search
double epsilon_multiplier = 1.5;
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);
Creating The Data
Kokkos::deep_copy(source_coords_device, source_coords);
Kokkos::deep_copy(target_coords_device, target_coords);
Kokkos::View<double*, Kokkos::DefaultExecutionSpace> sampling_data_device("samples of true solution",
source_coords_device.extent(0));
Kokkos::View<double**, Kokkos::DefaultExecutionSpace> gradient_sampling_data_device("samples of true gradient",
source_coords_device.extent(0), dimension);
Kokkos::View<double**, Kokkos::DefaultExecutionSpace> divergence_sampling_data_device
("samples of true solution for divergence test", source_coords_device.extent(0), dimension);
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;
sampling_data_device(i) =
trueSolution(xval, yval, zval, order, dimension);
double true_grad[3] = {0,0,0};
for (int j=0; j<dimension; ++j) {
gradient_sampling_data_device(i,j) = true_grad[j];
}
});
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);
std::string solver_name;
if (solver_type == 0) {
solver_name = "SVD";
} else if (solver_type == 1) {
solver_name = "QR";
} else if (solver_type == 2) {
solver_name = "LU";
}
std::string problem_name;
if (problem_type == 0) {
problem_name = "STANDARD";
} else if (problem_type == 1) {
problem_name = "MANIFOLD";
}
std::string constraint_name;
if (constraint_type == 0) {
constraint_name = "NO_CONSTRAINT";
} else if (constraint_type == 1) {
constraint_name = "NEUMANN_GRAD_SCALAR";
}
order, dimension,
solver_name.c_str(), problem_name.c_str(), constraint_name.c_str(),
2 );
my_GMLS.setProblemData(neighbor_lists_device, number_of_neighbors_list_device, source_coords_device, target_coords_device, epsilon_device);
std::vector<TargetOperation> lro(5);
my_GMLS.addTargets(lro);
my_GMLS.setWeightingPower(2);
my_GMLS.generateAlphas(number_of_batches, keep_coefficients );
Apply GMLS Alphas To Data
Evaluator gmls_evaluator(&my_GMLS);
auto output_value = gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double*, Kokkos::HostSpace>
auto output_laplacian = gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double*, Kokkos::HostSpace>
auto output_gradient = gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double**, Kokkos::HostSpace>
auto output_divergence = gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double*, Kokkos::HostSpace>
auto output_curl = gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double**, Kokkos::HostSpace>
decltype(output_curl) scalar_coefficients;
if (number_of_batches==1)
scalar_coefficients =
gmls_evaluator.applyFullPolynomialCoefficientsBasisToDataAllComponents<double**, Kokkos::HostSpace>
(sampling_data_device);
Check That Solutions Are Correct
for (int i=0; i<number_target_coords; i++) {
double GMLS_value = output_value(i);
double GMLS_Laplacian = output_laplacian(i);
double GMLS_GradX = (number_of_batches==1) ? scalar_coefficients(i,1)*1./epsilon(i) : output_gradient(i,0);
double GMLS_GradY = (dimension>1) ? output_gradient(i,1) : 0;
double GMLS_GradZ = (dimension>2) ? output_gradient(i,2) : 0;
double GMLS_Divergence = output_divergence(i);
double GMLS_CurlX = (dimension>1) ? output_curl(i,0) : 0;
double GMLS_CurlY = (dimension>1) ? output_curl(i,1) : 0;
double GMLS_CurlZ = (dimension>2) ? output_curl(i,2) : 0;
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 actual_value =
trueSolution(xval, yval, zval, order, dimension);
double actual_Laplacian =
trueLaplacian(xval, yval, zval, order, dimension);
double actual_Gradient[3] = {0,0,0};
trueGradient(actual_Gradient, xval, yval, zval, order, dimension);
double actual_Divergence;
actual_Divergence =
trueLaplacian(xval, yval, zval, order, dimension);
double actual_Curl[3] = {0,0,0};
if (dimension>1) {
if (dimension>2) {
}
}
if(GMLS_value!=GMLS_value || std::abs(actual_value - GMLS_value) > failure_tolerance) {
all_passed = false;
std::cout << i << " Failed Actual by: " << std::abs(actual_value - GMLS_value) << std::endl;
}
if(std::abs(actual_Laplacian - GMLS_Laplacian) > laplacian_failure_tolerance) {
all_passed = false;
std::cout << i <<" Failed Laplacian by: " << std::abs(actual_Laplacian - GMLS_Laplacian) << std::endl;
}
if(std::abs(actual_Gradient[0] - GMLS_GradX) > failure_tolerance) {
all_passed = false;
std::cout << i << " Failed GradX by: " << std::abs(actual_Gradient[0] - GMLS_GradX) << std::endl;
if (dimension>1) {
if(std::abs(actual_Gradient[1] - GMLS_GradY) > failure_tolerance) {
all_passed = false;
std::cout << i << " Failed GradY by: " << std::abs(actual_Gradient[1] - GMLS_GradY) << std::endl;
}
}
if (dimension>2) {
if(std::abs(actual_Gradient[2] - GMLS_GradZ) > failure_tolerance) {
all_passed = false;
std::cout << i << " Failed GradZ by: " << std::abs(actual_Gradient[2] - GMLS_GradZ) << std::endl;
}
}
}
if(std::abs(actual_Divergence - GMLS_Divergence) > failure_tolerance) {
all_passed = false;
std::cout << i << " Failed Divergence by: " << std::abs(actual_Divergence - GMLS_Divergence) << std::endl;
}
if (order > 2) {
double tmp_diff = 0;
if (dimension>1)
tmp_diff += std::abs(actual_Curl[0] - GMLS_CurlX) + std::abs(actual_Curl[1] - GMLS_CurlY);
if (dimension>2)
tmp_diff += std::abs(actual_Curl[2] - GMLS_CurlZ);
if(std::abs(tmp_diff) > failure_tolerance) {
all_passed = false;
std::cout << i << " Failed Curl by: " << std::abs(tmp_diff) << std::endl;
}
}
}
Finalize Program
}
kp.finalize();
#ifdef COMPADRE_USE_MPI
MPI_Finalize();
#endif
if(all_passed) {
fprintf(stdout, "Passed test \n");
return 0;
} else {
fprintf(stdout, "Failed test \n");
return -1;
}
}
Tutorial