A test for the parallel Hybrid cubic spherical Bernstein-Bezier interpolation method.
#include <stdlib.h>
#include <string.h>
#include "tests.h"
#include "test_common.h"
#include "dist_grid_utils.h"
#include <mpi.h>
#include <yaxt.h>
#include <netcdf.h>
enum {NUM_REORDER_TYPES = sizeof(reorder_types) / sizeof(reorder_types[0])};
static void compute_field_data_XYZ(
double (*vertices)[3], size_t num_vertices, double * f_v);
static char const * grid_names[2] = {"src_grid", "tgt_grid"};
MPI_Init(NULL, NULL);
xt_initialize(MPI_COMM_WORLD);
int comm_rank, comm_size;
MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
MPI_Barrier(MPI_COMM_WORLD);
if (comm_size != 6) {
PUT_ERR("ERROR: wrong number of processes");
xt_finalize();
MPI_Finalize();
return TEST_EXIT_CODE;
}
MPI_Comm split_comm;
MPI_Comm_split(MPI_COMM_WORLD, comm_rank < 1, 0, &split_comm);
int split_comm_rank, split_comm_size;
MPI_Comm_rank(split_comm, &split_comm_rank);
MPI_Comm_size(split_comm, &split_comm_size);
{
enum {NUM_SRC_DECOMP = 2};
size_t num_points[NUM_SRC_DECOMP][NUM_REORDER_TYPES];
double * tgt_fields[NUM_SRC_DECOMP][NUM_REORDER_TYPES];
int is_tgt = split_comm_size == 1;
for (int case_idx = 0; case_idx < NUM_SRC_DECOMP; ++case_idx) {
double coordinates_x[NUM_SRC_DECOMP][2][10] =
{{{0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0},{-1.0}},
{{0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0},{-1.0}}};
double coordinates_y[NUM_SRC_DECOMP][2][10] =
{{{0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0},{-1.0}},
{{0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0},{-1.0}}};
size_t const num_cells[2][2] = {{7,7}, {9,9}};
size_t local_start[NUM_SRC_DECOMP][2][5][2] =
{{{{0,0},{0,2},{0,3},{4,2},{0,5}}, {{0,0}}},
{{{0,0},{1,0},{3,0},{3,3},{5,0}}, {{0,0}}}};
size_t local_count[NUM_SRC_DECOMP][2][5][2] =
{{{{7,2},{4,1},{4,2},{3,3},{7,2}}, {{9,9}}},
{{{2,7},{2,7},{2,3},{2,4},{2,7}}, {{9,9}}}};
int with_halo = 0;
for (size_t i = 0; i < 10; ++i) {
coordinates_x[case_idx][1][i] = 2.5 + 2.0 * ((double)i / 9.0);
coordinates_y[case_idx][1][i] = 2.5 + 2.0 * ((double)i / 9.0);
}
for (size_t i = 0; i <= num_cells[is_tgt][0]; ++i)
coordinates_x[case_idx][is_tgt][i] *=
YAC_RAD;
for (size_t i = 0; i <= num_cells[is_tgt][1]; ++i)
coordinates_y[case_idx][is_tgt][i] *=
YAC_RAD;
yac_generate_basic_grid_data_reg2d(
coordinates_x[case_idx][is_tgt], coordinates_y[case_idx][is_tgt],
num_cells[is_tgt], local_start[case_idx][is_tgt][split_comm_rank],
local_count[case_idx][is_tgt][split_comm_rank], with_halo);
size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
for (size_t i = 0; i < NUM_REORDER_TYPES; ++i) {
weights, reorder_types[i], 1,
{
double * src_field = NULL;
double ** src_fields = &src_field;
double * tgt_field = NULL;
double * ref_tgt_field = NULL;
if (is_tgt) {
ref_tgt_field =
compute_field_data_XYZ(
for (size_t i = 0; i < 100; ++i) tgt_field[i] = -1;
tgt_fields[case_idx][i] = tgt_field;
} else {
compute_field_data_XYZ(
}
if (is_tgt)
for (size_t i = 0; i < 100; ++i)
if (fabs(1.0 - ref_tgt_field[i] / tgt_field[i]) > 1e-2)
PUT_ERR("wrong interpolation result");
free(ref_tgt_field);
free(src_field);
}
}
}
if (is_tgt) {
for (int case_idx = 0; case_idx < NUM_SRC_DECOMP; ++case_idx) {
for (int reorder_type = 0; reorder_type < NUM_REORDER_TYPES;
++reorder_type) {
PUT_ERR("error in test setup");
if (tgt_fields[0][0][i] != tgt_fields[case_idx][reorder_type][i])
PUT_ERR("interpolation results are not "
"decomposition-independant");
}
}
for (int case_idx = 0; case_idx < NUM_SRC_DECOMP; ++case_idx)
for (int reorder_type = 0; reorder_type < NUM_REORDER_TYPES;
++reorder_type) free(tgt_fields[case_idx][reorder_type]);
}
}
{
int is_tgt = split_comm_size == 1;
double coordinates_x[2][10] = {{0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0},{-1.0}};
double coordinates_y[2][10] = {{0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0},{-1.0}};
size_t const num_cells[2][2] = {{7,7}, {9,9}};
size_t local_start[2][5][2] = {{{0,0},{0,2},{0,3},{4,2},{0,5}}, {{0,0}}};
size_t local_count[2][5][2] = {{{7,2},{4,1},{4,2},{3,3},{7,2}}, {{9,9}}};
int with_halo = 0;
for (size_t i = 0; i < 10; ++i) {
coordinates_x[1][i] = 2.0 + 3.0 * ((double)i / 9.0);
coordinates_y[1][i] = 2.0 + 3.0 * ((double)i / 9.0);
}
for (size_t i = 0; i <= num_cells[is_tgt][0]; ++i)
coordinates_x[is_tgt][i] *=
YAC_RAD;
for (size_t i = 0; i <= num_cells[is_tgt][1]; ++i)
coordinates_y[is_tgt][i] *=
YAC_RAD;
yac_generate_basic_grid_data_reg2d(
coordinates_x[is_tgt], coordinates_y[is_tgt],
num_cells[is_tgt],
local_start[is_tgt][split_comm_rank],
local_count[is_tgt][split_comm_rank], with_halo);
{{.location =
YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
{.location =
YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
for (size_t i = 0; i < NUM_REORDER_TYPES; ++i) {
weights, reorder_types[i], 1,
{
double * src_field = NULL;
double ** src_fields = &src_field;
double * tgt_field = NULL;
double * ref_tgt_field = NULL;
if (is_tgt) {
ref_tgt_field =
compute_field_data_XYZ(
for (size_t i = 0; i < 100; ++i) tgt_field[i] = -1;
} else {
compute_field_data_XYZ(
}
if (is_tgt)
for (size_t i = 0; i < 100; ++i)
if (fabs(1.0 - ref_tgt_field[i] / tgt_field[i]) > 1e-2)
PUT_ERR("wrong interpolation result");
free(ref_tgt_field);
free(tgt_field);
free(src_field);
}
}
}
{
int is_tgt = split_comm_size == 1;
double coordinates_x[2][10] = {{0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0},{-1.0}};
double coordinates_y[2][10] = {{0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0},{-1.0}};
size_t const num_cells[2][2] = {{7,7}, {9,9}};
size_t local_start[2][5][2] = {{{0,0},{0,2},{0,3},{4,2},{0,5}}, {{0,0}}};
size_t local_count[2][5][2] = {{{7,2},{4,1},{4,2},{3,3},{7,2}}, {{9,9}}};
int with_halo = 0;
for (size_t i = 0; i < 10; ++i) {
coordinates_x[1][i] = 2.0 + 3.0 * ((double)i / 9.0);
coordinates_y[1][i] = 2.0 + 3.0 * ((double)i / 9.0);
}
for (size_t i = 0; i <= num_cells[is_tgt][0]; ++i)
coordinates_x[is_tgt][i] *=
YAC_RAD;
for (size_t i = 0; i <= num_cells[is_tgt][1]; ++i)
coordinates_y[is_tgt][i] *=
YAC_RAD;
yac_generate_basic_grid_data_reg2d(
coordinates_x[is_tgt], coordinates_y[is_tgt],
num_cells[is_tgt],
local_start[is_tgt][split_comm_rank],
local_count[is_tgt][split_comm_rank], with_halo);
if (!is_tgt) {
src_point_coordinates =
for (
size_t i = 0; i < grid_data.
num_cells; ++i) {
double * middle_point = src_point_coordinates[i];
for (size_t k = 0; k < 3; ++k) middle_point[k] = 0.0;
size_t * curr_vertices =
for (size_t j = 0; j < curr_num_vertices; ++j) {
double * curr_vertex_coord =
for (size_t k = 0; k < 3; ++k)
middle_point[k] += curr_vertex_coord[k];
}
}
}
if (!is_tgt)
{{.location =
YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = SIZE_MAX}};
size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
{.location =
YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
for (size_t i = 0; i < NUM_REORDER_TYPES; ++i) {
weights, reorder_types[i], 1,
{
double * src_field = NULL;
double ** src_fields = &src_field;
double * tgt_field = NULL;
double * ref_tgt_field = NULL;
if (is_tgt) {
ref_tgt_field =
compute_field_data_XYZ(
for (size_t i = 0; i < 100; ++i) tgt_field[i] = -1;
} else {
compute_field_data_XYZ(
src_point_coordinates, grid_data.
num_cells, src_field);
}
if (is_tgt)
for (size_t i = 0; i < 100; ++i)
if (fabs(1.0 - ref_tgt_field[i] / tgt_field[i]) > 1e-2)
PUT_ERR("wrong interpolation result");
free(ref_tgt_field);
free(tgt_field);
free(src_field);
}
}
}
{
int is_tgt = split_comm_size == 1;
double coordinates_x[2][10] = {{0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0},{-1.0}};
double coordinates_y[2][10] = {{0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0},{-1.0}};
size_t const num_cells[2][2] = {{7,7}, {9,9}};
size_t local_start[2][5][2] = {{{0,0},{0,2},{0,3},{4,2},{0,5}}, {{0,0}}};
size_t local_count[2][5][2] = {{{7,2},{4,1},{4,2},{3,3},{7,2}}, {{9,9}}};
int with_halo = 0;
for (size_t i = 0; i < 10; ++i) {
coordinates_x[1][i] = 4.0 + 4.0 * ((double)i / 9.0);
coordinates_y[1][i] = 4.0 + 4.0 * ((double)i / 9.0);
}
for (size_t i = 0; i <= num_cells[is_tgt][0]; ++i)
coordinates_x[is_tgt][i] *=
YAC_RAD;
for (size_t i = 0; i <= num_cells[is_tgt][1]; ++i)
coordinates_y[is_tgt][i] *=
YAC_RAD;
yac_generate_basic_grid_data_reg2d(
coordinates_x[is_tgt], coordinates_y[is_tgt],
num_cells[is_tgt],
local_start[is_tgt][split_comm_rank],
local_count[is_tgt][split_comm_rank], with_halo);
if (!is_tgt) {
src_point_coordinates =
for (
size_t i = 0; i < grid_data.
num_cells; ++i) {
double * middle_point = src_point_coordinates[i];
for (size_t k = 0; k < 3; ++k) middle_point[k] = 0.0;
size_t * curr_vertices =
for (size_t j = 0; j < curr_num_vertices; ++j) {
double * curr_vertex_coord =
for (size_t k = 0; k < 3; ++k)
middle_point[k] += curr_vertex_coord[k];
}
}
}
if (!is_tgt)
{{.location =
YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = SIZE_MAX}};
size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
{.location =
YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
for (size_t i = 0; i < NUM_REORDER_TYPES; ++i) {
weights, reorder_types[i], 1,
{
double * src_field = NULL;
double ** src_fields = &src_field;
double * tgt_field = NULL;
double * ref_tgt_field = NULL;
if (is_tgt) {
int is_outside_src_grid[] = {
0,0,0,0,0,0,1,1,1,1,
0,0,0,0,0,0,1,1,1,1,
0,0,0,0,0,0,1,1,1,1,
0,0,0,0,0,0,1,1,1,1,
0,0,0,0,0,0,1,1,1,1,
0,0,0,0,0,0,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1};
ref_tgt_field =
compute_field_data_XYZ(
ref_tgt_field[i] = -1.0;
for (size_t i = 0; i < 100; ++i) tgt_field[i] = -2.0;
} else {
compute_field_data_XYZ(
src_point_coordinates, grid_data.
num_cells, src_field);
}
if (is_tgt)
for (size_t i = 0; i < 100; ++i)
if (fabs(1.0 - ref_tgt_field[i] / tgt_field[i]) > 1e-2)
PUT_ERR("wrong interpolation result");
free(ref_tgt_field);
free(tgt_field);
free(src_field);
}
}
}
{
int is_tgt = split_comm_size == 1;
double coordinates_x[2][10] =
{{72.00,72.25,72.50,72.75,73.00,73.25,73.5,73.75},{-1.0}};
double coordinates_y[2][10] =
{{90.0,89.75,89.50,89.25,89.00,88.75,88.50,88.25},{-1.0}};
size_t const num_cells[2][2] = {{7,7}, {9,9}};
size_t local_start[2][5][2] = {{{0,0},{0,2},{0,3},{4,2},{0,5}}, {{0,0}}};
size_t local_count[2][5][2] = {{{7,2},{4,1},{4,2},{3,3},{7,2}}, {{9,9}}};
int with_halo = 0;
for (size_t i = 0; i < 10; ++i) {
coordinates_x[1][i] = 72.50 + 0.90 * ((double)i / 9.0);
coordinates_y[1][i] = 89.06 + 0.90 * ((double)i / 9.0);
}
for (size_t i = 0; i <= num_cells[is_tgt][0]; ++i)
coordinates_x[is_tgt][i] *=
YAC_RAD;
for (size_t i = 0; i <= num_cells[is_tgt][1]; ++i)
coordinates_y[is_tgt][i] *=
YAC_RAD;
yac_generate_basic_grid_data_reg2d(
coordinates_x[is_tgt], coordinates_y[is_tgt],
num_cells[is_tgt],
local_start[is_tgt][split_comm_rank],
local_count[is_tgt][split_comm_rank], with_halo);
if (!is_tgt) {
memcpy(
if (fabs(1.0 - fabs(vertex_coordinates[i][2])) < 1e-9) {
vertex_coordinates[i][0] = 0.0;
vertex_coordinates[i][1] = 0.0;
}
}
}
{{.location =
YAC_LOC_CORNER, .coordinates_idx = 0, .masks_idx = SIZE_MAX}};
size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
{.location =
YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
for (size_t i = 0; i < NUM_REORDER_TYPES; ++i) {
weights, reorder_types[i], 1,
{
double * src_field = NULL;
double ** src_fields = &src_field;
double * tgt_field = NULL;
double * ref_tgt_field = NULL;
if (is_tgt) {
ref_tgt_field =
compute_field_data_XYZ(
for (size_t i = 0; i < 100; ++i) tgt_field[i] = -1;
} else {
compute_field_data_XYZ(
}
if (is_tgt)
for (size_t i = 0; i < 100; ++i)
if (fabs(1.0 - ref_tgt_field[i] / tgt_field[i]) > 1e-2)
PUT_ERR("wrong interpolation result");
free(ref_tgt_field);
free(tgt_field);
free(src_field);
}
}
}
MPI_Comm_free(&split_comm);
xt_finalize();
MPI_Finalize();
return TEST_EXIT_CODE;
}
#if defined __INTEL_COMPILER
#pragma intel optimization_level 0
#elif defined _CRAYC
#pragma _CRI noopt
#endif
static void compute_field_data_XYZ(
double (*vertices)[3], size_t num_vertices, double * f_v) {
for (size_t i = 0; i < num_vertices; ++i) {
double x = vertices[i][0];
double y = vertices[i][1];
double z = vertices[i][2];
f_v[i] = 1.0 + pow(x, 8.0);
f_v[i] += exp(2.0*y*y*y);
f_v[i] += exp(2.0*x*x) + 10.0*x*
y*z;
}
}
struct yac_basic_grid * yac_basic_grid_new(char const *name, struct yac_basic_grid_data grid_data)
size_t yac_basic_grid_add_coordinates_nocpy(struct yac_basic_grid *grid, enum yac_location location, yac_coordinate_pointer coordinates)
struct yac_basic_grid * yac_basic_grid_empty_new(char const *name)
void yac_basic_grid_delete(struct yac_basic_grid *grid)
int main(int argc, char **argv)
void yac_dist_grid_pair_delete(struct yac_dist_grid_pair *grid_pair)
struct yac_dist_grid_pair * yac_dist_grid_pair_new(struct yac_basic_grid *grid_a, struct yac_basic_grid *grid_b, MPI_Comm comm)
static void normalise_vector(double v[])
void yac_interp_grid_delete(struct yac_interp_grid *interp_grid)
struct yac_interp_grid * yac_interp_grid_new(struct yac_dist_grid_pair *grid_pair, char const *src_grid_name, char const *tgt_grid_name, size_t num_src_fields, struct yac_interp_field const *src_fields, struct yac_interp_field const tgt_field)
void yac_interp_method_delete(struct interp_method **method)
struct yac_interp_weights * yac_interp_method_do_search(struct interp_method **method, struct yac_interp_grid *interp_grid)
struct interp_method * yac_interp_method_fixed_new(double value)
struct interp_method * yac_interp_method_hcsbb_new()
void yac_interp_weights_delete(struct yac_interp_weights *weights)
struct yac_interpolation * yac_interp_weights_get_interpolation(struct yac_interp_weights *weights, enum yac_interp_weights_reorder_type reorder, size_t collection_size, double frac_mask_fallback_value, double scaling_factor, double scaling_summand, char const *yaxt_exchanger_name)
yac_interp_weights_reorder_type
@ YAC_MAPPING_ON_TGT
weights will be applied at target processes
@ YAC_MAPPING_ON_SRC
weights will be applied at source processes
void yac_interpolation_execute(struct yac_interpolation *interp, double ***src_fields, double **tgt_field)
void yac_interpolation_delete(struct yac_interpolation *interp)
double const YAC_FRAC_MASK_NO_VALUE
yac_coordinate_pointer vertex_coordinates
size_t * cell_to_vertex_offsets
int * num_vertices_per_cell
enum yac_location location
struct yac_interp_field tgt_field
struct yac_dist_grid_pair * grid_pair
struct yac_interp_field src_fields[]
struct yac_basic_grid ** grids
double(* yac_coordinate_pointer)[3]