29static char const *
grid_names[2] = {
"src_grid",
"tgt_grid"};
31static double utest_compute_ref_tgt_value(
32 size_t tgt_corner,
int * tgt_global_core_mask,
int * tgt_global_field_mask,
33 int * src_global_core_mask,
int * src_global_field_maske,
int with_src_mask,
35 int partial_coverage);
41 xt_initialize(MPI_COMM_WORLD);
43 int comm_rank, comm_size;
44 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
45 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
46 MPI_Barrier(MPI_COMM_WORLD);
49 PUT_ERR(
"ERROR: wrong number of processes");
57 MPI_COMM_WORLD, comm_rank < 2, 0, &
split_comm);
59 int split_comm_rank, split_comm_size;
89 int is_tgt = split_comm_size == 1;
91 {{0,1,2,3,4,5}, {0.25,0.75,1.25,1.75,2.25,2.75,3.25,3.75,4.25,4.75}};
93 {{-2,-1,0,1,2}, {-1.75,-1.25,-0.75,-0.25,0.25,0.75,1.25,1.75}};
94 double cell_coordiantes_x[5 * 4] =
99 double cell_coordiantes_y[5 * 4] =
100 {-1.5,-1.5,-1.5,-1.5,-1.5,
101 -0.5,-0.5,-0.5,-0.5,-0.5,
103 1.5,1.5,1.5,1.5,1.5};
104 size_t const num_cells[2][2] = {{5,4}, {9,7}};
105 size_t local_start[2][2][2] = {{{0,0},{3,0}}, {{0,0}}};
106 size_t local_count[2][2][2] = {{{3,4},{2,4}}, {{9,7}}};
107 int global_core_mask[2][10*8] =
112 {1,1,1,0,0,0,0,0,0,0,
113 1,1,1,0,0,0,0,0,0,0,
114 1,1,1,1,1,1,0,0,0,0,
115 1,1,1,1,1,1,0,0,0,0,
116 1,1,1,1,1,1,1,1,1,0,
117 1,1,1,1,1,1,1,1,1,0,
118 1,1,1,1,1,1,1,1,1,0,
119 1,1,1,1,1,1,1,1,1,0}};
120 int global_field_mask[2][10*8] =
125 {1,1,1,1,1,1,1,1,1,1,
126 1,1,1,1,1,1,1,1,1,1,
127 1,1,1,1,1,1,1,1,1,1,
128 1,1,1,1,1,1,1,1,1,1,
129 1,1,1,1,1,1,1,1,1,1,
130 1,1,1,1,1,1,1,1,1,1,
131 1,1,1,1,1,1,1,1,1,1,
132 0,0,0,0,0,0,0,0,0,0}};
142 local_start[is_tgt][split_comm_rank],
143 local_count[is_tgt][split_comm_rank],
with_halo);
146 for (
size_t i = 0;
i <
grid_data.num_vertices; ++
i)
148 global_core_mask[is_tgt][
grid_data.vertex_ids[i]];
156 global_core_mask[is_tgt][
grid_data.cell_ids[i]];
163 int field_mask[10*8];
164 double field_coords[10*8][3];
166 for (
size_t i = 0;
i <
grid_data.num_vertices; ++
i)
167 field_mask[i] = global_field_mask[is_tgt][
grid_data.vertex_ids[i]];
172 field_mask[
i] = global_field_mask[is_tgt][
grid_data.cell_ids[
i]];
174 cell_coordiantes_x[
grid_data.cell_ids[i]],
175 cell_coordiantes_y[
grid_data.cell_ids[i]], field_coords[i]);
186 for (
int with_src_mask = 0; with_src_mask < 2; ++with_src_mask) {
187 for (
int with_tgt_mask = 0; with_tgt_mask < 2; ++with_tgt_mask) {
191 .coordinates_idx = 0,
192 .masks_idx = (with_src_mask)?0:SIZE_MAX}};
193 size_t num_src_fields =
sizeof(src_fields) /
sizeof(src_fields[0]);
196 .coordinates_idx = SIZE_MAX,
197 .masks_idx = (with_tgt_mask)?0:SIZE_MAX};
210 ++weight_types_idx) {
211 for (
int partial_coverage = 0; partial_coverage < 2;
212 ++partial_coverage) {
231 double src_field_data[5*4];
235 {-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,
236 -2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,
237 -2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,
238 -2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,
239 -2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,
240 -2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,
241 -2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,
242 -2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,-2.0};
247 src_field[i] = (
double)(
grid_data.cell_ids[
i] + 1);
250 interpolation, &src_fields, &tgt_field);
254 for (
size_t i = 0;
i <
grid_data.num_vertices; ++
i) {
256 double ref_tgt_value =
257 utest_compute_ref_tgt_value(
258 i, global_core_mask[1], global_field_mask[1],
259 global_core_mask[0], global_field_mask[0],
260 with_src_mask, with_tgt_mask,
263 if (fabs(ref_tgt_value - tgt_field[i]) > 1e-3)
264 PUT_ERR(
"wrong interpolation result");
291 int is_tgt = split_comm_size == 1;
293 {{-2,-1,1,2}, {-1.0,0.0,1.0}};
295 {{-2,-1,1,2}, {-1.0,0.0,1.0}};
296 double field_coordiantes_x[2][3*3] =
303 double field_coordiantes_y[2][3*3] =
310 int field_mask[3*3] = {0,1,1, 1,1,1, 1,1,0};
311 size_t const num_cells[2][2] = {{3,3}, {2,2}};
312 size_t local_start[2][2][2] = {{{0,0},{0,1}}, {{0,0}}};
313 size_t local_count[2][2][2] = {{{3,2},{3,2}}, {{2,2}}};
323 local_start[is_tgt][split_comm_rank],
324 local_count[is_tgt][split_comm_rank],
with_halo);
330 double field_coords[3*3][3];
335 int src_field_mask[3*3];
336 for (
size_t i = 0;
i < count; ++
i) {
338 field_coordiantes_x[is_tgt][ids[i]],
339 field_coordiantes_y[is_tgt][ids[i]], field_coords[i]);
340 if (!is_tgt) src_field_mask[
i] = field_mask[ids[
i]];
343 grids[0], field_location[is_tgt], field_coords, count);
346 grids[0], field_location[is_tgt], src_field_mask, count, NULL);
352 for (
int with_src_mask = 0; with_src_mask < 2; ++with_src_mask) {
356 .coordinates_idx = 0,
357 .masks_idx = with_src_mask?0:SIZE_MAX}};
358 size_t num_src_fields =
sizeof(src_fields) /
sizeof(src_fields[0]);
361 .coordinates_idx = 0,
362 .masks_idx = SIZE_MAX};
368 for (
int partial_coverage = 0; partial_coverage < 2; ++partial_coverage) {
385 double src_field_data[3*3];
396 src_field[i] = (
double)(
grid_data.cell_ids[
i] + 1);
399 interpolation, &src_fields, &tgt_field);
403 yac_int tgt_to_src[2][2][9][4] =
404 {{{{0,1,3,4},{0,1,3,4},{1,2,4,5},
405 {0,1,3,4},{4},{1,2,4,5},
406 {3,4,6,7},{3,4,6,7},{4,5,7,8}},
407 {{0,1,3,4},{1,2,4,5},{1,2,4,5},
408 {3,4,6,7},{4},{4,5,7,8},
409 {3,4,6,7},{4,5,7,8},{4,5,7,8}}},
410 {{{1,3,4},{1,3,4},{1,2,4,5},
411 {1,3,4},{4},{1,2,4,5},
412 {3,4,6,7},{3,4,6,7},{4,5,7}},
413 {{1,3,4},{1,2,4,5},{1,2,4,5},
414 {3,4,6,7},{4},{4,5,7},
415 {3,4,6,7},{4,5,7},{4,5,7}}}};
416 int num_src_per_tgt[2][2][2][9] =
417 {{{{4,4,4, 4,1,4, 4,4,4},{4,4,4, 4,1,4, 4,4,4}},
418 {{0,0,4, 0,1,4, 4,4,0},{0,4,4, 4,1,0, 4,0,0}}},
419 {{{4,4,4, 4,1,4, 4,4,4},{4,4,4, 4,1,4, 4,4,4}},
420 {{3,3,4, 3,1,4, 4,4,3},{3,4,4, 4,1,3, 4,3,3}}}};
422 for (
size_t i = 0;
i <
grid_data.num_vertices; ++
i) {
425 double ref_tgt_value[2] = {0.0, 0.0};
429 field_coordiantes_x[1][tgt_id], field_coordiantes_y[1][tgt_id],
432 for (
int j = 0; j < 2; ++j) {
434 double inv_distance_sum = 0.0;
436 num_src_per_tgt[partial_coverage][with_src_mask][j][tgt_id];
439 for (
int k = 0; k < num_src; ++k) {
440 yac_int src_id = tgt_to_src[with_src_mask][j][tgt_id][k];
443 field_coordiantes_x[0][src_id],
444 field_coordiantes_y[0][src_id], src_coord);
447 ref_tgt_value[j] = (double)(src_id + 1);
448 inv_distance_sum = 1.0;
451 double inv_distance =
453 inv_distance_sum += inv_distance;
454 ref_tgt_value[j] += (double)(src_id + 1) * inv_distance;
457 ref_tgt_value[j] /= inv_distance_sum;
459 ref_tgt_value[j] = -1.0;
463 if ((fabs(ref_tgt_value[0] - tgt_field[i]) > 1e-3) &&
464 (fabs(ref_tgt_value[1] - tgt_field[i]) > 1e-3))
465 PUT_ERR(
"wrong interpolation result");
490static double utest_compute_ref_tgt_value(
491 size_t tgt_corner,
int * tgt_global_core_mask,
int * tgt_global_field_mask,
492 int * src_global_core_mask,
int * src_global_field_mask,
int with_src_mask,
494 int partial_coverage) {
497 if (!tgt_global_core_mask[tgt_corner] ||
498 (with_tgt_mask && !tgt_global_field_mask[tgt_corner]))
return -2.0;
501 int source_grid_x_idx = ((int)tgt_corner % 10) / 2;
502 int source_grid_y_idx = ((int)tgt_corner / 10) / 2;
503 int source_cell = source_grid_x_idx + source_grid_y_idx * 5;
506 if (!src_global_core_mask[source_cell])
return -1.0;
509 int is_right_corner = (int)tgt_corner & 1;
510 int is_upper_corner = ((int)tgt_corner / 10) & 1;
512 source_grid_x_idx + is_right_corner +
513 6 * (source_grid_y_idx + is_upper_corner);
517 source_cells[0] = (5 * (source_corner / 6) + source_corner % 6) - 5 - 1;
518 source_cells[1] = (5 * (source_corner / 6) + source_corner % 6) - 5;
519 source_cells[2] = (5 * (source_corner / 6) + source_corner % 6) - 1;
520 source_cells[3] = (5 * (source_corner / 6) + source_corner % 6);
523 if (source_corner <= 5) {
524 source_cells[0] = -1;
525 source_cells[1] = -1;
527 if (source_corner >= 24) {
528 source_cells[2] = -1;
529 source_cells[3] = -1;
531 if ((source_corner % 6) == 0) {
532 source_cells[0] = -1;
533 source_cells[2] = -1;
535 if (((source_corner + 1) % 6) == 0) {
536 source_cells[3] = -1;
537 source_cells[1] = -1;
541 for (
int i = 0;
i < 4; ++
i)
542 if ((source_cells[i] >= 0) &&
543 (!src_global_core_mask[source_cells[
i]]))
544 source_cells[
i] = -1;
548 for (
int i = 0;
i < 4; ++
i) {
549 if ((source_cells[i] >= 0) &&
550 (!src_global_field_mask[source_cells[
i]])) {
551 if (!partial_coverage)
return -1.0;
552 source_cells[
i] = -1;
557 double const ref_distances[2][2] =
558 {{sqrt(0.25*0.25 + 0.25*0.25),
559 sqrt(0.75*0.75 + 0.25*0.25)},
560 {sqrt(0.25*0.25 + 0.75*0.75),
561 sqrt(0.75*0.75 + 0.75*0.75)}};
564 int num_src_cells = 0;
565 for (
int i = 0, k = 0;
i < 2; ++
i) {
566 for (
int j = 0; j < 2; ++j, ++k) {
567 if (source_cells[k] >= 0) {
568 distances[num_src_cells] =
569 ref_distances[
i^is_upper_corner^1][j^is_right_corner^1];
570 source_cells[num_src_cells] = source_cells[k];
576 if (num_src_cells == 0)
return -1.0;
578 double tgt_value = 0.0;
582 double weight = 1.0 / (double)num_src_cells;
583 for (
int i = 0;
i < num_src_cells; ++
i)
584 tgt_value += (
double)(source_cells[
i] + 1) * weight;
588 double inv_distance_sum = 0.0;
589 for (
int i = 0;
i < num_src_cells; ++
i)
590 inv_distance_sum += 1.0 / distances[i];
591 for (
int i = 0;
i < num_src_cells; ++
i)
593 (
double)(source_cells[
i] + 1) / (distances[i] * inv_distance_sum);
struct yac_basic_grid * yac_basic_grid_new(char const *name, struct yac_basic_grid_data grid_data)
size_t yac_basic_grid_add_mask(struct yac_basic_grid *grid, enum yac_location location, int const *mask, size_t count, char const *mask_name)
size_t yac_basic_grid_add_coordinates(struct yac_basic_grid *grid, enum yac_location location, yac_coordinate_pointer coordinates, size_t count)
struct yac_basic_grid * yac_basic_grid_empty_new(char const *name)
void yac_basic_grid_delete(struct yac_basic_grid *grid)
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)
struct yac_basic_grid_data yac_generate_basic_grid_data_reg2d(double const *global_coords_x, double const *global_coords_y, size_t const num_global_cells_[2], size_t const local_start[2], size_t const local_count[2], int with_halo)
static void LLtoXYZ_deg(double lon, double lat, double p_out[])
static double get_vector_angle(double const a[3], double const b[3])
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_ncc_new(enum yac_interp_ncc_weight_type weight_type, int partial_coverage)
yac_interp_ncc_weight_type
@ YAC_INTERP_NCC_DIST
distance weighted average of n source points
@ YAC_INTERP_NCC_AVG
average of n source points
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, int is_source, int is_target)
void yac_interp_weights_delete(struct yac_interp_weights *weights)
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)
Execute interpolation synchronously and write results to the target field.
void yac_interpolation_delete(struct yac_interpolation *interp)
Free an interpolation object and release all resources.
double const YAC_FRAC_MASK_NO_VALUE
enum yac_location location
struct yac_interp_field tgt_field
struct yac_dist_grid_pair * grid_pair
struct yac_interp_field src_fields[]
static MPI_Comm split_comm
static char const * grid_names[2]
enum yac_interp_weights_reorder_type reorder_types[]
enum yac_interp_spmap_weight_type weight_types[]
static double tgt_field_data[MAX_COLLECTION_SIZE][NUM_TGT_POINTS]
struct yac_basic_grid ** grids