YAC 3.12.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_interpolation_parallel4.c
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <math.h>
8#include <unistd.h>
9#include <string.h>
10
11#include <mpi.h>
12
13#include "tests.h"
14#include "test_common.h"
15#include "weight_file_common.h"
16#include "dist_grid_utils.h"
17#include "grids/dist_grid.h"
19#include "geometry.h"
23
29#define YAC_RAD (0.01745329251994329576923690768489) // M_PI / 180
30
31// needs to be a multiple of 2
32#define NUM_CELLS_X 128
33#define NUM_CELLS_Y 128
34#define NUM_CELLS_X_2 64
35#define NUM_CELLS_Y_2 64
36
37static void utest_generate_input_weights();
38
39static void utest_generate_ref_weights();
40
41static void utest_submain_src(
42 MPI_Comm comp_comm, enum yac_interp_weights_reorder_type reorder_type);
43
44static void utest_submain_tgt(
45 MPI_Comm comp_comm, enum yac_interp_weights_reorder_type reorder_type);
46
47// link data for input weight file
52
53char const weight_file_in[] =
54 "test_interpolation_parallel4_weight_file_in.nc";
55char const weight_file_out[] =
56 "test_interpolation_parallel4_weight_file_out.nc";
57char const src_grid_name[] = "src_grid";
58char const tgt_grid_name[] = "tgt_grid";
59
60// reference link data for output weight file
62
66
67int const * ref_tgt_address_fixed = NULL;
68double const * ref_fixed_values = NULL;
69int const * ref_num_tgt_per_fixed_value = NULL;
71
72// grid information (is the same for source and target)
73unsigned cyclic[2] = {0,0};
76int with_halo = 1;
77
78int main(int argc, char *argv[]) {
79
80 if (argc != 2) {
81 PUT_ERR("wrong number of arguments\n");
82 return TEST_EXIT_CODE;
83 }
84
85 enum yac_interp_weights_reorder_type reorder_type =
86 (strcmp(argv[1], "src") == 0)?YAC_MAPPING_ON_SRC:YAC_MAPPING_ON_TGT;
87
88 if ((reorder_type != YAC_MAPPING_ON_SRC) && strcmp(argv[1], "tgt")) {
89 PUT_ERR("invalid argument (has to be either \"src\" or \"tgt\")\n");
90 return TEST_EXIT_CODE;
91 }
92
93 MPI_Init(NULL, NULL);
94
95 xt_initialize(MPI_COMM_WORLD);
96
97 utest_generate_input_weights();
98 utest_generate_ref_weights();
99
100 for (unsigned i = 0; i < NUM_CELLS_X + 1; ++i)
101 global_coordinates_x[i] = (double)i * YAC_RAD;
102
103 for (unsigned i = 0; i < NUM_CELLS_Y + 1; ++i)
104 global_coordinates_y[i] = (double)i * YAC_RAD;
105
106 int comm_rank, comm_size;
107 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
108 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
109 MPI_Barrier(MPI_COMM_WORLD);
110
111 if (comm_size != 5) {
112 PUT_ERR("ERROR: wrong number of processes");
113 xt_finalize();
114 MPI_Finalize();
115 return TEST_EXIT_CODE;
116 }
117
118 // split processes into source an target
119
120 int comp_flag = comm_rank < 4;
121
122 MPI_Comm split_comm;
123 MPI_Comm_split(
124 MPI_COMM_WORLD, comp_flag, 0, &split_comm);
125
126 if (comp_flag) utest_submain_src(split_comm, reorder_type);
127 else utest_submain_tgt(split_comm, reorder_type);
128
129 MPI_Comm_free(&split_comm);
130 xt_finalize();
131 MPI_Finalize();
132
133 return TEST_EXIT_CODE;
134}
135
136static void utest_submain_tgt(
137 MPI_Comm comp_comm, enum yac_interp_weights_reorder_type reorder_type) {
138
139 UNUSED(comp_comm);
140
141 size_t local_start[2] = {0,0};
142 size_t local_count[2] = {NUM_CELLS_X, NUM_CELLS_Y};
143
147 local_start, local_count, with_halo);
148
151
152 for (unsigned i = 0; i < NUM_CELLS_X; ++i)
153 cell_coordinates_x[i] = ((double)i + 0.5)*YAC_RAD;
154 for (unsigned i = 0; i < NUM_CELLS_Y; ++i)
155 cell_coordinates_y[i] = ((double)i + 0.5)*YAC_RAD;
156
157 double cell_field_coords[NUM_CELLS_Y][NUM_CELLS_X][3];
158 for (size_t i = 0; i < NUM_CELLS_Y; ++i)
159 for (size_t j = 0; j < NUM_CELLS_X; ++j)
160 LLtoXYZ(
161 cell_coordinates_x[j], cell_coordinates_y[i], cell_field_coords[i][j]);
162
163 struct yac_basic_grid * tgt_grid =
166 tgt_grid, YAC_LOC_CELL, &(cell_field_coords[0][0]), grid_data.num_cells);
167 struct yac_basic_grid * src_grid =
169
170 struct yac_dist_grid_pair * grid_pair =
171 yac_dist_grid_pair_new(tgt_grid, src_grid, MPI_COMM_WORLD);
172
173 { // test interpolation
174
175 struct yac_interp_field src_fields[] =
176 {{.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
177 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
179 {.location = YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = SIZE_MAX};
180
181 struct yac_interp_grid * interp_grid =
184
185 struct interp_method * method_stack[] =
190 NULL};
191
192 struct yac_interp_weights * weights =
193 yac_interp_method_do_search(method_stack, interp_grid);
194
195 yac_interp_method_delete(method_stack);
196
197 struct yac_interpolation * interpolation =
199 weights, reorder_type, 1,
200 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
201
202 //---------------------
203 // do the interpolation
204 //---------------------
205
206 // target_data dimensions [collection_idx]
207 // [local_idx]
208
209 double target_field[NUM_CELLS_X][NUM_CELLS_Y];
210 double * target_field_ = &target_field[0][0];
211 double ** target_data = &target_field_;
212
213 for (unsigned i = 0; i < NUM_CELLS_Y; ++i)
214 for (unsigned j = 0; j < NUM_CELLS_X; ++j)
215 target_field[i][j] = -1;
216
217 yac_interpolation_execute_get(interpolation, target_data);
218
219 //----------------------------
220 // check interpolation results
221 //----------------------------
222
226
227 double ref_target_field[NUM_CELLS_X*NUM_CELLS_Y];
228
229 for (unsigned i = 0; i < NUM_CELLS_X*NUM_CELLS_Y; ++i)
230 ref_target_field[i] = 0;
231
232 for (unsigned i = 0; i < NUM_CELLS_Y; ++i)
233 for (unsigned j = 0; j < NUM_CELLS_X; ++j)
234 for (unsigned k = 0; k < 4; ++k)
235 ref_target_field[ref_tgt_address[i][j][k]] +=
236 ((double)ref_src_address[i][j][k]) * ref_weights[i][j][k];
237
238 for (unsigned i = 0; i < NUM_CELLS_Y; ++i)
239 for (unsigned j = 0; j < NUM_CELLS_X; ++j)
240 if (fabs(target_field[i][j] - ref_target_field[i * NUM_CELLS_X + j]) >
241 1e-10)
242 PUT_ERR("wrong interpolation result\n")
243
244 //--------
245 // cleanup
246 //--------
247
248 yac_interpolation_delete(interpolation);
250 yac_interp_grid_delete(interp_grid);
251 }
252
253 //--------
254 // cleanup
255 //--------
256
257 yac_dist_grid_pair_delete(grid_pair);
258 yac_basic_grid_delete(src_grid);
259 yac_basic_grid_delete(tgt_grid);
260}
261
262static void utest_submain_src(
263 MPI_Comm comp_comm, enum yac_interp_weights_reorder_type reorder_type) {
264
265 int my_rank;
266 MPI_Comm_rank(comp_comm, &my_rank);
267
268 // create a weight file
269 if (my_rank == 0) {
270 enum yac_location src_locations[1] = {YAC_LOC_CORNER};
271 enum yac_location tgt_location = YAC_LOC_CELL;
272 int * tgt_id_fixed = NULL;
273 unsigned num_fixed_tgt = 0;
274 double * fixed_values = NULL;
275 int * num_tgt_per_fixed_value = NULL;
276 unsigned num_fixed_values = 0;
278 &(tgt_address_file[0][0][0]), &(weights_file[0][0][0]),
279 num_links_file, src_locations, 1, (int*)&num_links_file,
280 tgt_id_fixed, num_fixed_tgt, fixed_values,
281 num_tgt_per_fixed_value, num_fixed_values,
282 tgt_location, src_grid_name, tgt_grid_name);
283 }
284
285 size_t local_start[4][2] =
287 size_t local_count[2] = {NUM_CELLS_X_2,NUM_CELLS_Y_2};
288 size_t global_num_cells[2] = {NUM_CELLS_X,NUM_CELLS_Y};
289
293 local_start[my_rank], local_count, with_halo);
294 size_t num_vertices = grid_data.num_vertices;
295
296 struct yac_basic_grid * src_grid =
299 struct yac_basic_grid * tgt_grid =
301
302 struct yac_dist_grid_pair * grid_pair =
303 yac_dist_grid_pair_new(src_grid, tgt_grid, MPI_COMM_WORLD);
304
305 { // test interpolation
306
307 struct yac_interp_field src_fields[] =
308 {{.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
309 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
311 {.location = YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = SIZE_MAX};
312
313 struct yac_interp_grid * interp_grid =
316
317 struct interp_method * method_stack[] =
322 NULL};
323
324 struct yac_interp_weights * weights =
325 yac_interp_method_do_search(method_stack, interp_grid);
326
327 yac_interp_method_delete(method_stack);
328
329 struct yac_interpolation * interpolation =
331 weights, reorder_type, 1,
332 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
333
334 //---------------------
335 // do the interpolation
336 //---------------------
337
338 // source_data dimensions [collection_idx]
339 // [pointset_idx]
340 // [local_idx]
341 double * source_data_field =
342 xmalloc(num_vertices * sizeof(*source_data_field));
343
344 double * source_data_pointset[1] = {source_data_field}; // num_pointset == 1
345 double ** source_data[1] = {source_data_pointset}; // collection_size == 1
346 for (size_t i = 0; i < num_vertices; ++i)
347 source_data_field[i] =
348 (grid_data.core_vertex_mask[i])?
349 ((double)(grid_data.vertex_ids[i])):(-1.0);
350
351 yac_interpolation_execute_put(interpolation, source_data);
352
353 //------------------------------
354 // check the written weight file
355 //------------------------------
356
360
361 if (my_rank == 0) {
362 enum yac_location ref_src_locations[1] = {YAC_LOC_CORNER};
363 enum yac_location ref_tgt_location = YAC_LOC_CELL;
365 &ref_tgt_address[0][0][0], &ref_weights[0][0][0],
366 ref_num_links, ref_src_locations, 1, (int*)&ref_num_links,
369 ref_tgt_location, src_grid_name, tgt_grid_name);
370 }
371
372 //--------
373 // cleanup
374 //--------
375
376 free(source_data_field);
377 yac_interpolation_delete(interpolation);
379 yac_interp_grid_delete(interp_grid);
380 }
381
382 //--------
383 // cleanup
384 //--------
385
386 yac_dist_grid_pair_delete(grid_pair);
387 yac_basic_grid_delete(tgt_grid);
388 yac_basic_grid_delete(src_grid);
389
390 // delete weight file
391 if (my_rank == 0) {
392 unlink(weight_file_in);
393 unlink(weight_file_out);
394 }
395}
396
397static void
398utest_generate_input_weights() {
399
400 for (unsigned i = 0; i < NUM_CELLS_Y_2; ++i) {
401 for (unsigned j = 0; j < NUM_CELLS_X_2; ++j) {
402 src_address_file[i][j][0] =
403 0 + (i + NUM_CELLS_Y_2 / 2) * (NUM_CELLS_X + 1) + (j + NUM_CELLS_X_2 / 2);
404 src_address_file[i][j][1] =
405 1 + (i + NUM_CELLS_Y_2 / 2) * (NUM_CELLS_X + 1) + (j + NUM_CELLS_X_2 / 2);
406 src_address_file[i][j][2] =
407 0 + (i + 1 + NUM_CELLS_Y_2 / 2) * (NUM_CELLS_X + 1) + (j + NUM_CELLS_X_2 / 2);
408 src_address_file[i][j][3] =
409 1 + (i + 1 + NUM_CELLS_Y_2 / 2) * (NUM_CELLS_X + 1) + (j + NUM_CELLS_X_2 / 2);
410 for (unsigned k = 0; k < 4; ++k)
411 tgt_address_file[i][j][k] =
412 (i + NUM_CELLS_Y_2 / 2) * NUM_CELLS_X + (j + NUM_CELLS_X_2 / 2);
413 for (unsigned k = 0; k < 4; ++k)
414 weights_file[i][j][k] = (double)(k + 1) * 0.1;
415 }
416 }
417}
418
419static void
420utest_generate_ref_weights() {
421
422 for (unsigned i = 0, idx = 0; i < NUM_CELLS_Y; ++i) {
423 for (unsigned j = 0; j < NUM_CELLS_X; ++j, ++idx) {
424 ref_src_address[i][j][0] = 0 + i * (NUM_CELLS_X + 1) + j;
425 ref_src_address[i][j][1] = 1 + i * (NUM_CELLS_X + 1) + j;
426 ref_src_address[i][j][2] = 0 + (i + 1) * (NUM_CELLS_X + 1) + j;
427 ref_src_address[i][j][3] = 1 + (i + 1) * (NUM_CELLS_X + 1) + j;
428 for (unsigned k = 0; k < 4; ++k) {
429 ref_tgt_address[i][j][k] = idx;
430 ref_weights[i][j][k] = 0.25;
431 }
432 }
433 }
434 for (unsigned i = 0; i < NUM_CELLS_Y_2; ++i)
435 for (unsigned j = 0; j < NUM_CELLS_X_2; ++j)
436 for (unsigned k = 0; k < 4; ++k)
439 [tgt_address_file[i][j][k]%NUM_CELLS_X][k] = weights_file[i][j][k];
440}
441
struct yac_basic_grid * yac_basic_grid_new(char const *name, struct yac_basic_grid_data grid_data)
Definition basic_grid.c:50
size_t yac_basic_grid_add_coordinates_nocpy(struct yac_basic_grid *grid, enum yac_location location, yac_coordinate_pointer coordinates)
Definition basic_grid.c:208
size_t yac_basic_grid_add_coordinates(struct yac_basic_grid *grid, enum yac_location location, yac_coordinate_pointer coordinates, size_t count)
Definition basic_grid.c:232
struct yac_basic_grid * yac_basic_grid_empty_new(char const *name)
Definition basic_grid.c:63
void yac_basic_grid_delete(struct yac_basic_grid *grid)
Definition basic_grid.c:70
#define UNUSED(x)
Definition core.h:73
void yac_dist_grid_pair_delete(struct yac_dist_grid_pair *grid_pair)
Definition dist_grid.c:2313
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)
Definition dist_grid.c:2061
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)
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)
Definition interp_grid.c:31
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_avg_new(enum yac_interp_avg_weight_type weight_type, int partial_coverage)
@ YAC_INTERP_AVG_ARITHMETIC
struct interp_method * yac_interp_method_file_new(char const *weight_file_name, enum yac_interp_file_on_missing_file on_missing_file, enum yac_interp_file_on_success on_success)
#define YAC_INTERP_FILE_ON_SUCCESS_DEFAULT
#define YAC_INTERP_FILE_ON_MISSING_FILE_DEFAULT
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)
void yac_interp_weights_write_to_file(struct yac_interp_weights *weights, char const *filename, char const *src_grid_name, char const *tgt_grid_name, size_t src_grid_size, size_t tgt_grid_size, enum yac_weight_file_on_existing on_existing)
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
@ YAC_WEIGHT_FILE_ERROR
error when weight file existis already
void yac_interpolation_delete(struct yac_interpolation *interp)
Free an interpolation object and release all resources.
void yac_interpolation_execute_get(struct yac_interpolation *interp, double **tgt_field)
Complete interpolation and write results to the target field (get phase).
void yac_interpolation_execute_put(struct yac_interpolation *interp, double ***src_fields)
Provide source field data and start asynchronous execution of interpolation (put phase).
double const YAC_FRAC_MASK_NO_VALUE
yac_location
Definition location.h:12
@ YAC_LOC_CORNER
Definition location.h:15
@ YAC_LOC_CELL
Definition location.h:14
#define xmalloc(size)
Definition ppm_xfuncs.h:66
enum yac_location location
Definition basic_grid.h:16
struct yac_interp_field tgt_field
Definition interp_grid.c:26
size_t num_src_fields
Definition interp_grid.c:27
struct yac_dist_grid_pair * grid_pair
Definition interp_grid.c:25
struct yac_interp_field src_fields[]
Definition interp_grid.c:28
static MPI_Comm split_comm
double cell_coordinates_y[]
double cell_coordinates_x[]
unsigned ref_num_links
unsigned num_links_file
int tgt_address_file[NUM_CELLS_Y_2][NUM_CELLS_X_2][4]
int const * ref_tgt_address_fixed
int ref_tgt_address[NUM_CELLS_Y][NUM_CELLS_X][4]
unsigned ref_num_fixed_values
char const src_grid_name[]
int ref_src_address[NUM_CELLS_Y][NUM_CELLS_X][4]
char const tgt_grid_name[]
double weights_file[NUM_CELLS_Y_2][NUM_CELLS_X_2][4]
char const weight_file_out[]
#define NUM_CELLS_X
double global_coordinates_y[NUM_CELLS_X+1]
int const * ref_num_tgt_per_fixed_value
#define NUM_CELLS_X_2
double global_coordinates_x[NUM_CELLS_X+1]
double const * ref_fixed_values
unsigned cyclic[2]
int src_address_file[NUM_CELLS_Y_2][NUM_CELLS_X_2][4]
#define NUM_CELLS_Y_2
#define NUM_CELLS_Y
double ref_weights[NUM_CELLS_Y][NUM_CELLS_X][4]
char const weight_file_in[]
#define TEST_EXIT_CODE
Definition tests.h:14
#define PUT_ERR(string)
Definition tests.h:10
static void LLtoXYZ(double lon, double lat, double p_out[])
Definition toy_scrip.c:587
void check_weight_file(char const *file_name, int const *ref_src_address, int const *ref_tgt_address, double const *ref_weights, unsigned ref_num_links, enum yac_location const *ref_src_locations, unsigned ref_num_src_fields, int const *ref_num_links_per_src_field, int const *ref_tgt_address_fixed, double const *ref_fixed_values, int const *ref_num_tgt_per_fixed_value, unsigned ref_num_fixed_values, enum yac_location ref_tgt_location, char const *ref_src_grid_name, char const *ref_tgt_grid_name)
void write_weight_file(char const *file_name, int const *src_id, int const *tgt_id, double const *weights, unsigned num_links, enum yac_location const *src_locations, unsigned num_src_fields, int const *num_links_per_src_field, int *tgt_id_fixed, unsigned num_fixed_tgt, double *fixed_values, int *num_tgt_per_fixed_value, unsigned num_fixed_values, enum yac_location tgt_location, char const *src_grid_name, char const *tgt_grid_name)