26static void utest_compute_reference_result(
28 double const * src_coordinates_x,
double const * src_coordinates_y,
29 int const * src_global_mask,
size_t const src_size_x,
size_t const src_size_y,
30 double const * tgt_coordinates_x,
double const * tgt_coordinates_y,
31 size_t const tgt_size_x,
size_t const tgt_size_y,
32 double * ref_tgt_results);
40 xt_initialize(MPI_COMM_WORLD);
42 int comm_rank, comm_size;
43 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
44 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
45 MPI_Barrier(MPI_COMM_WORLD);
48 PUT_ERR(
"ERROR: wrong number of processes");
138 size_t const local_start[
NUM_PROCS][2] = {{0,0},{0,2},{3,2},{0,5}, {0,0}};
139 size_t const local_count[
NUM_PROCS][2] = {{7,2},{3,3},{4,3},{7,2}, {7,7}};
155 int const is_tgt = comm_rank == TGT_RANK;
158 utest_generate_basic_grid_data_reg2d(
160 local_start[comm_rank], local_count[comm_rank],
with_halo);
178 int * src_corner_mask =
180 for (
size_t i = 0; i <
grid_data.num_vertices; ++i)
182 ((
int*)(&(src_global_corner_mask[0][0])))[
grid_data.vertex_ids[i]];
192 size_t num_src_fields =
sizeof(src_fields) /
sizeof(src_fields[0]);
194 {.location =
YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = SIZE_MAX};
208 .search_distance = {.fixed = 1.3 *
YAC_RAD}},
217 .search_distance = {.fixed = 1.3 *
YAC_RAD}},
226 .search_distance = {.fixed = 1.3 *
YAC_RAD}},
235 .search_distance = {.fixed = 0.4 *
YAC_RAD}},
244 .search_distance = {.fixed = 0.4 *
YAC_RAD}},
253 .search_distance = {.scale = 1.0}},
262 .search_distance = {.scale = 2.0}},
271 .search_distance = {.fixed = 1.3 *
YAC_RAD}},
280 .search_distance = {.fixed = 1.3 *
YAC_RAD}},
289 .search_distance = {.fixed = 1.3 *
YAC_RAD}},
294 enum {NUM_DNN_CONFIGS =
sizeof(dnn_configs)/
sizeof(dnn_configs[0])};
296 for (
size_t i = 0; i < NUM_DNN_CONFIGS; ++i) {
303 utest_compute_reference_result(
305 (
int const *)(&(src_global_corner_mask[0][0])),
330 double *** src_data = NULL;
331 double ** tgt_data = NULL;
335 tgt_data[COLLECTION_IDX] =
337 for (
size_t k = 0; k <
grid_data.num_cells; ++k) {
338 tgt_data[COLLECTION_IDX][k] = -999.0;
346 src_data[COLLECTION_IDX] =
xmalloc(1 *
sizeof(**src_data));
347 src_data[COLLECTION_IDX][0] =
349 for (
size_t k = 0; k <
grid_data.num_vertices; ++k) {
350 src_data[COLLECTION_IDX][0][k] =
362 for (
size_t k = 0; k <
grid_data.num_cells; ++k) {
364 if (fabs(tgt_data[COLLECTION_IDX][k] - ref_tgt_results[k]) > 1e-6) {
373 free(tgt_data[COLLECTION_IDX]);
378 free(src_data[COLLECTION_IDX][0]);
379 free(src_data[COLLECTION_IDX]);
428static void utest_determine_src_points(
429 double const * src_coordinates_x,
double const * src_coordinates_y,
430 size_t const src_size_x,
size_t const src_size_y,
431 double const * tgt_coordinates_x,
double const * tgt_coordinates_y,
432 size_t const tgt_size_x,
size_t const tgt_size_y,
433 double const inc_angle,
int const * src_mask,
434 size_t * num_src_points,
size_t ** src_points) {
438 src_size_x * src_size_y * tgt_size_x * tgt_size_y *
sizeof(**src_points));
439 size_t total_num_src_points = 0;
441 for (
size_t tgt_y = 0, tgt_point_idx = 0; tgt_y < tgt_size_y; ++tgt_y) {
443 for (
size_t tgt_x = 0; tgt_x < tgt_size_x; ++tgt_x, ++tgt_point_idx) {
447 LLtoXYZ(tgt_coordinates_x[tgt_x], tgt_coordinates_y[tgt_y], tgt_coord);
449 size_t curr_num_src = 0;
452 for (
size_t src_y = 0, src_point_idx = 0; src_y < src_size_y; ++src_y) {
453 for (
size_t src_x = 0; src_x < src_size_x; ++src_x, ++src_point_idx) {
458 src_coordinates_x[src_x], src_coordinates_y[src_y], src_coord);
464 if (angle <= inc_angle && src_mask[src_point_idx]) {
465 (*src_points)[total_num_src_points] = src_point_idx;
466 ++total_num_src_points;
472 num_src_points[tgt_point_idx] = curr_num_src;
477 xrealloc(*src_points, total_num_src_points *
sizeof(**src_points));
480static double utest_compute_avg_result(
481 size_t const n,
size_t const * src_indices,
size_t const tgt_index,
482 double const * src_coordinates_x,
double const * src_coordinates_y,
483 size_t const src_size_x,
484 double const * tgt_coordinates_x,
double const * tgt_coordinates_y,
485 size_t const tgt_size_x) {
488 UNUSED(src_coordinates_x);
489 UNUSED(src_coordinates_y);
491 UNUSED(tgt_coordinates_x);
492 UNUSED(tgt_coordinates_y);
496 for (
size_t i = 0;
i <
n; ++
i) {
497 sum += (double)(src_indices[i]);
499 return sum / (double)n;
502static double utest_compute_dist_result(
503 size_t const n,
size_t const * src_indices,
size_t const tgt_index,
504 double const * src_coordinates_x,
double const * src_coordinates_y,
505 size_t const src_size_x,
506 double const * tgt_coordinates_x,
double const * tgt_coordinates_y,
507 size_t const tgt_size_x) {
511 tgt_coordinates_x[tgt_index%tgt_size_x],
512 tgt_coordinates_y[tgt_index/tgt_size_x], tgt_coord);
515 double weights_sum = 0.0;
517 for (
size_t i = 0;
i <
n; ++
i) {
520 LLtoXYZ(src_coordinates_x[src_indices[i]%src_size_x],
521 src_coordinates_y[src_indices[i]/src_size_x], src_coord);
524 result += weight * (double)src_indices[i];
525 weights_sum += weight;
527 return result / weights_sum;
530static double utest_compute_gauss_result(
531 size_t const n,
size_t const * src_indices,
size_t const tgt_index,
532 double const * src_coordinates_x,
double const * src_coordinates_y,
533 size_t const src_size_x,
534 double const * tgt_coordinates_x,
double const * tgt_coordinates_y,
535 size_t const tgt_size_x) {
539 return (
double)src_indices[0];
544 for (
size_t i = 0;
i <
n; ++
i) {
545 LLtoXYZ(src_coordinates_x[src_indices[i]%src_size_x],
546 src_coordinates_y[src_indices[i]/src_size_x], src_coords[i]);
550 double src_distances_sum = 0.0;
551 for (
size_t i = 0;
i <
n; ++
i)
552 for (
size_t j = 0; j <
n; ++j)
555 size_t src_distance_count =
n *
n -
n;
558 double src_distance_mean = src_distances_sum / (double)src_distance_count;
559 double src_distance_mean_sq = src_distance_mean * src_distance_mean;
563 LLtoXYZ(tgt_coordinates_x[tgt_index%tgt_size_x],
564 tgt_coordinates_y[tgt_index/tgt_size_x], tgt_coord);
566 for (
size_t i = 0;
i <
n; ++
i) {
569 exp(-1.0 * (tgt_distance * tgt_distance) /
574 double weights_sum = 0.0;
575 for (
size_t i = 0;
i <
n; ++
i) weights_sum += weights[i];
576 for (
size_t i = 0;
i <
n; ++
i) weights[i] /= weights_sum;
580 for (
size_t i = 0;
i <
n; ++
i) {
581 result +=
weights[
i] * (double)src_indices[i];
587static void utest_inverse(
double * A,
size_t n);
589static double utest_compute_rbf_result(
590 size_t const n,
size_t const * src_indices,
size_t const tgt_index,
591 double const * src_coordinates_x,
double const * src_coordinates_y,
592 size_t const src_size_x,
593 double const * tgt_coordinates_x,
double const * tgt_coordinates_y,
594 size_t const tgt_size_x) {
597 for (
size_t i = 0;
i <
n; ++
i) {
598 LLtoXYZ(src_coordinates_x[src_indices[i]%src_size_x],
599 src_coordinates_y[src_indices[i]/src_size_x], src_coords[i]);
606 for (
size_t i = 0;
i <
n; ++
i) A[i][i] = 0.0;
607 for (
size_t i = 0;
i <
n - 1; ++
i) {
608 for (
size_t j = i + 1; j <
n; ++j) {
617 double scale_d = 1.0;
619 scale_d = ((double)((n - 1) *
n)) / (2.0 * sum_d);
622 double sq_scale_d = scale_d * scale_d;
625 for (
size_t i = 0;
i <
n; ++
i) {
626 for (
size_t j = 0; j <
n; ++j) {
628 A[
i][j] = exp(-1.0 * d * d * sq_scale_d);
633 utest_inverse(&A[0][0], n);
637 LLtoXYZ(tgt_coordinates_x[tgt_index%tgt_size_x],
638 tgt_coordinates_y[tgt_index/tgt_size_x], tgt_coord);
641 for (
size_t i = 0;
i <
n; ++
i) {
643 a[
i] = exp(-1.0 * d * d * sq_scale_d);
648 for (
size_t i = 0;
i <
n; ++
i) {
650 for (
size_t j = 0; j <
n; ++j) weights[i] += A[i][j] * a[j];
655 for (
size_t i = 0;
i <
n; ++
i) {
656 result +=
weights[
i] * (double)src_indices[i];
662static void utest_inverse(
double * A,
size_t n) {
666#ifdef YAC_LAPACK_NO_DSYTR
667 lapack_int ipiv[
n+1];
670 for (
size_t i = 0;
i <
n+1; ++
i) ipiv[i] = 0;
671 for (
size_t i = 0;
i <
n*
n; ++
i) work[i] = 0;
675 LAPACK_COL_MAJOR, (lapack_int) n, (lapack_int) n,
676 A, (lapack_int) n, ipiv),
"internal ERROR: dgetrf")
679 !LAPACKE_dgetri_work(
680 LAPACK_COL_MAJOR, (lapack_int) n, A, (lapack_int) n,
681 ipiv, work, (lapack_int) (n * n)), "internal ERROR: dgetri")
687 !LAPACKE_dsytrf_work(
688 LAPACK_COL_MAJOR,
'L', (lapack_int) n , A,
689 (lapack_int) n, ipiv, work, (lapack_int) n),
"internal ERROR: dsytrf")
692 !LAPACKE_dsytri_work(
693 LAPACK_COL_MAJOR, 'L', (lapack_int) n , A,
694 (lapack_int) n, ipiv, work), "internal ERROR: dsytri")
696 for (
size_t i = 0; i < n; ++i)
697 for (
size_t j = i + 1; j < n; ++j)
702static void utest_compute_reference_result(
704 double const * src_coordinates_x,
double const * src_coordinates_y,
705 int const * src_global_mask,
size_t const src_size_x,
size_t const src_size_y,
706 double const * tgt_coordinates_x,
double const * tgt_coordinates_y,
707 size_t const tgt_size_x,
size_t const tgt_size_y,
708 double * ref_tgt_results) {
711 double search_distance;
713 switch (dnn_config.search_distance->
type) {
725 sqrt(cell_area / M_PI);
733 size_t num_src_per_tgt[tgt_size_x * tgt_size_y];
734 utest_determine_src_points(
735 src_coordinates_x, src_coordinates_y, src_size_x, src_size_y,
736 tgt_coordinates_x, tgt_coordinates_y, tgt_size_x, tgt_size_y,
737 search_distance, src_global_mask, num_src_per_tgt, &src_points);
741 double (*compute_result)(
742 size_t const,
size_t const *,
size_t const,
743 double const *,
double const *,
size_t const,
744 double const *,
double const *,
size_t const) = NULL;
745 switch (dnn_config.
type) {
748 compute_result = utest_compute_avg_result;
751 compute_result = utest_compute_dist_result;
754 compute_result = utest_compute_gauss_result;
757 compute_result = utest_compute_rbf_result;
766 size_t src_offset = 0;
767 for (
size_t k = 0; k < tgt_size_x * tgt_size_y; ++k) {
769 if (num_src_per_tgt[k] >= n_min) {
770 size_t * curr_src_points = &
src_points[src_offset];
773 num_src_per_tgt[k], curr_src_points, k,
774 src_coordinates_x, src_coordinates_y, src_size_x,
775 tgt_coordinates_x, tgt_coordinates_y, tgt_size_x);
780 src_offset += num_src_per_tgt[k];
#define YAC_ASSERT(exp, msg)
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)
size_t yac_basic_grid_add_mask_nocpy(struct yac_basic_grid *grid, enum yac_location location, int const *mask, char const *mask_name)
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 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)
Delete an interpolation stack and free its resources (but not the pointer array).
struct yac_interp_weights * yac_interp_method_do_search(struct interp_method **method, struct yac_interp_grid *interp_grid)
Perform weight computation using given interpolation stack and grid.
Defines the interface of the interpolation method "base class" in YAC.
struct interp_method * yac_interp_method_dnn_new(struct yac_interp_method_dnn_config config)
@ YAC_INTERP_DNN_WEIGHT_AVG
average of source points within search distance
@ YAC_INTERP_DNN_WEIGHT_DIST
distance weighted average of source points
@ YAC_INTERP_DNN_WEIGHT_GAUSS
Gauss weighted average of source points.
@ YAC_INTERP_DNN_WEIGHT_RBF
radial basis function weighted average
#define YAC_INTERP_DNN_RBF_SCALE_DEFAULT
#define YAC_INTERP_DNN_GAUSS_SCALE_DEFAULT
#define YAC_INTERP_DNN_N_MIN_DEFAULT
@ YAC_INTERP_DNN_SEARCH_DISTANCE_FIXED
use a fixed search distance (in radians)
@ YAC_INTERP_DNN_SEARCH_DISTANCE_CELL_AREA
struct interp_method * yac_interp_method_fixed_new(double value)
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
#define xrealloc(ptr, size)
enum yac_location location
struct yac_interp_field tgt_field
struct yac_dist_grid_pair * grid_pair
struct yac_interp_field src_fields[]
union yac_interp_method_dnn_config_search_distance::@28 search_distance
enum yac_interp_dnn_weight_type type
weighting type
struct yac_interp_method_dnn_config_search_distance * search_distance
char const src_grid_name[]
char const tgt_grid_name[]
static double const fixed_value
double cell_coordinates_y[]
double cell_coordinates_x[]
static void LLtoXYZ(double lon, double lat, double p_out[])
#define YAC_UNREACHABLE_DEFAULT(msg)
double(* yac_coordinate_pointer)[3]