YAC 3.21.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#include <yaxt.h>
13
14#include "tests.h"
15#include "test_common.h"
16#include "weight_file_common.h"
17#include "dist_grid_utils.h"
18#include "grids/dist_grid.h"
20#include "geometry.h"
24
30#define YAC_RAD (0.01745329251994329576923690768489) // M_PI / 180
31
32// needs to be a multiple of 2
33#define NUM_CELLS_X 128
34#define NUM_CELLS_Y 128
35#define NUM_CELLS_X_2 64
36#define NUM_CELLS_Y_2 64
37
38static void utest_generate_input_weights();
39
40static void utest_generate_ref_weights();
41
42static void utest_submain_src(
43 MPI_Comm comp_comm, enum yac_interp_weights_reorder_type reorder_type);
44
45static void utest_submain_tgt(
46 MPI_Comm comp_comm, enum yac_interp_weights_reorder_type reorder_type);
47
48// link data for input weight file
53
54char const weight_file_in[] =
55 "test_interpolation_parallel4_weight_file_in.nc";
56char const weight_file_out[] =
57 "test_interpolation_parallel4_weight_file_out.nc";
58char const src_grid_name[] = "src_grid";
59char const tgt_grid_name[] = "tgt_grid";
60
61// reference link data for output weight file
63
67
68int const * ref_tgt_address_fixed = NULL;
69double const * ref_fixed_values = NULL;
70int const * ref_num_tgt_per_fixed_value = NULL;
72
73// grid information (is the same for source and target)
74unsigned cyclic[2] = {0,0};
77int with_halo = 1;
78
79int main(int argc, char *argv[]) {
80
81 if (argc != 2) {
82 PUT_ERR("wrong number of arguments\n");
83 return TEST_EXIT_CODE;
84 }
85
86 enum yac_interp_weights_reorder_type reorder_type =
87 (strcmp(argv[1], "src") == 0)?YAC_MAPPING_ON_SRC:YAC_MAPPING_ON_TGT;
88
89 if ((reorder_type != YAC_MAPPING_ON_SRC) && strcmp(argv[1], "tgt")) {
90 PUT_ERR("invalid argument (has to be either \"src\" or \"tgt\")\n");
91 return TEST_EXIT_CODE;
92 }
93
94 MPI_Init(NULL, NULL);
95
96 xt_initialize(MPI_COMM_WORLD);
97
98 utest_generate_input_weights();
99 utest_generate_ref_weights();
100
101 for (unsigned i = 0; i < NUM_CELLS_X + 1; ++i)
102 global_coordinates_x[i] = (double)i * YAC_RAD;
103
104 for (unsigned i = 0; i < NUM_CELLS_Y + 1; ++i)
105 global_coordinates_y[i] = (double)i * YAC_RAD;
106
107 int comm_rank, comm_size;
108 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
109 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
110 MPI_Barrier(MPI_COMM_WORLD);
111
112 if (comm_size != 5) {
113 PUT_ERR("ERROR: wrong number of processes");
114 xt_finalize();
115 MPI_Finalize();
116 return TEST_EXIT_CODE;
117 }
118
119 // split processes into source an target
120
121 int comp_flag = comm_rank < 4;
122
123 MPI_Comm split_comm;
124 MPI_Comm_split(
125 MPI_COMM_WORLD, comp_flag, 0, &split_comm);
126
127 if (comp_flag) utest_submain_src(split_comm, reorder_type);
128 else utest_submain_tgt(split_comm, reorder_type);
129
130 MPI_Comm_free(&split_comm);
131 xt_finalize();
132 MPI_Finalize();
133
134 return TEST_EXIT_CODE;
135}
136
137static void utest_submain_tgt(
138 MPI_Comm comp_comm, enum yac_interp_weights_reorder_type reorder_type) {
139
140 UNUSED(comp_comm);
141
142 size_t local_start[2] = {0,0};
143 size_t local_count[2] = {NUM_CELLS_X, NUM_CELLS_Y};
144
146 utest_generate_basic_grid_data_reg2d(
148 local_start, local_count, with_halo);
149
152
153 for (unsigned i = 0; i < NUM_CELLS_X; ++i)
154 cell_coordinates_x[i] = ((double)i + 0.5)*YAC_RAD;
155 for (unsigned i = 0; i < NUM_CELLS_Y; ++i)
156 cell_coordinates_y[i] = ((double)i + 0.5)*YAC_RAD;
157
158 double cell_field_coords[NUM_CELLS_Y][NUM_CELLS_X][3];
159 for (size_t i = 0; i < NUM_CELLS_Y; ++i)
160 for (size_t j = 0; j < NUM_CELLS_X; ++j)
161 LLtoXYZ(
162 cell_coordinates_x[j], cell_coordinates_y[i], cell_field_coords[i][j]);
163
164 struct yac_basic_grid * tgt_grid =
167 tgt_grid, YAC_LOC_CELL, &(cell_field_coords[0][0]), grid_data.num_cells);
168 struct yac_basic_grid * src_grid =
170
171 struct yac_dist_grid_pair * grid_pair =
172 yac_dist_grid_pair_new(tgt_grid, src_grid, MPI_COMM_WORLD);
173
174 { // test interpolation
175
176 struct yac_interp_field src_fields[] =
177 {{.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
178 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
180 {.location = YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = SIZE_MAX};
181
182 struct yac_interp_grid * interp_grid =
185
186 struct interp_method * method_stack[] =
191 NULL};
192
193 struct yac_interp_weights * weights =
194 yac_interp_method_do_search(method_stack, interp_grid);
195
196 yac_interp_method_delete(method_stack);
197
198 struct yac_interpolation * interpolation =
200 weights, reorder_type, 1,
201 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
202
203 //---------------------
204 // do the interpolation
205 //---------------------
206
207 // target_data dimensions [collection_idx]
208 // [local_idx]
209
210 double target_field[NUM_CELLS_X][NUM_CELLS_Y];
211 double * target_field_ = &target_field[0][0];
212 double ** target_data = &target_field_;
213
214 for (unsigned i = 0; i < NUM_CELLS_Y; ++i)
215 for (unsigned j = 0; j < NUM_CELLS_X; ++j)
216 target_field[i][j] = -1;
217
218 yac_interpolation_execute_get(interpolation, target_data);
219
220 //----------------------------
221 // check interpolation results
222 //----------------------------
223
227
228 double ref_target_field[NUM_CELLS_X*NUM_CELLS_Y];
229
230 for (unsigned i = 0; i < NUM_CELLS_X*NUM_CELLS_Y; ++i)
231 ref_target_field[i] = 0;
232
233 for (unsigned i = 0; i < NUM_CELLS_Y; ++i)
234 for (unsigned j = 0; j < NUM_CELLS_X; ++j)
235 for (unsigned k = 0; k < 4; ++k)
236 ref_target_field[ref_tgt_address[i][j][k]] +=
237 ((double)ref_src_address[i][j][k]) * ref_weights[i][j][k];
238
239 for (unsigned i = 0; i < NUM_CELLS_Y; ++i)
240 for (unsigned j = 0; j < NUM_CELLS_X; ++j)
241 if (fabs(target_field[i][j] - ref_target_field[i * NUM_CELLS_X + j]) >
242 1e-10)
243 PUT_ERR("wrong interpolation result\n")
244
245 //--------
246 // cleanup
247 //--------
248
249 yac_interpolation_delete(interpolation);
251 yac_interp_grid_delete(interp_grid);
252 }
253
254 //--------
255 // cleanup
256 //--------
257
258 yac_dist_grid_pair_delete(grid_pair);
259 yac_basic_grid_delete(src_grid);
260 yac_basic_grid_delete(tgt_grid);
261}
262
263static void utest_submain_src(
264 MPI_Comm comp_comm, enum yac_interp_weights_reorder_type reorder_type) {
265
266 int my_rank;
267 MPI_Comm_rank(comp_comm, &my_rank);
268
269 // create a weight file
270 if (my_rank == 0) {
271 enum yac_location src_locations[1] = {YAC_LOC_CORNER};
272 enum yac_location tgt_location = YAC_LOC_CELL;
273 int * tgt_id_fixed = NULL;
274 unsigned num_fixed_tgt = 0;
275 double * fixed_values = NULL;
276 int * num_tgt_per_fixed_value = NULL;
277 unsigned num_fixed_values = 0;
278 utest_write_weight_file(weight_file_in, &(src_address_file[0][0][0]),
279 &(tgt_address_file[0][0][0]), &(weights_file[0][0][0]),
280 num_links_file, src_locations, 1, (int*)&num_links_file,
281 tgt_id_fixed, num_fixed_tgt, fixed_values,
282 num_tgt_per_fixed_value, num_fixed_values,
283 tgt_location, src_grid_name, tgt_grid_name);
284 }
285
286 size_t local_start[4][2] =
288 size_t local_count[2] = {NUM_CELLS_X_2,NUM_CELLS_Y_2};
289 size_t global_num_cells[2] = {NUM_CELLS_X,NUM_CELLS_Y};
290
292 utest_generate_basic_grid_data_reg2d(
294 local_start[my_rank], local_count, with_halo);
295 size_t num_vertices = grid_data.num_vertices;
296
297 struct yac_basic_grid * src_grid =
300 struct yac_basic_grid * tgt_grid =
302
303 struct yac_dist_grid_pair * grid_pair =
304 yac_dist_grid_pair_new(src_grid, tgt_grid, MPI_COMM_WORLD);
305
306 { // test interpolation
307
308 struct yac_interp_field src_fields[] =
309 {{.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
310 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
312 {.location = YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = SIZE_MAX};
313
314 struct yac_interp_grid * interp_grid =
317
318 struct interp_method * method_stack[] =
323 NULL};
324
325 struct yac_interp_weights * weights =
326 yac_interp_method_do_search(method_stack, interp_grid);
327
328 yac_interp_method_delete(method_stack);
329
330 struct yac_interpolation * interpolation =
332 weights, reorder_type, 1,
333 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
334
335 //---------------------
336 // do the interpolation
337 //---------------------
338
339 // source_data dimensions [collection_idx]
340 // [pointset_idx]
341 // [local_idx]
342 double * source_data_field =
343 xmalloc(num_vertices * sizeof(*source_data_field));
344
345 double * source_data_pointset[1] = {source_data_field}; // num_pointset == 1
346 double ** source_data[1] = {source_data_pointset}; // collection_size == 1
347 for (size_t i = 0; i < num_vertices; ++i)
348 source_data_field[i] =
349 (grid_data.core_vertex_mask[i])?
350 ((double)(grid_data.vertex_ids[i])):(-1.0);
351
352 yac_interpolation_execute_put(interpolation, source_data);
353
354 //------------------------------
355 // check the written weight file
356 //------------------------------
357
361
362 if (my_rank == 0) {
363 enum yac_location ref_src_locations[1] = {YAC_LOC_CORNER};
364 enum yac_location ref_tgt_location = YAC_LOC_CELL;
365 utest_check_weight_file(weight_file_out, &ref_src_address[0][0][0],
366 &ref_tgt_address[0][0][0], &ref_weights[0][0][0],
367 ref_num_links, ref_src_locations, 1, (int*)&ref_num_links,
370 ref_tgt_location, src_grid_name, tgt_grid_name);
371 }
372
373 //--------
374 // cleanup
375 //--------
376
377 free(source_data_field);
378 yac_interpolation_delete(interpolation);
380 yac_interp_grid_delete(interp_grid);
381 }
382
383 //--------
384 // cleanup
385 //--------
386
387 yac_dist_grid_pair_delete(grid_pair);
388 yac_basic_grid_delete(tgt_grid);
389 yac_basic_grid_delete(src_grid);
390
391 // delete weight file
392 if (my_rank == 0) {
393 unlink(weight_file_in);
394 unlink(weight_file_out);
395 }
396}
397
398static void
399utest_generate_input_weights() {
400
401 for (unsigned i = 0; i < NUM_CELLS_Y_2; ++i) {
402 for (unsigned j = 0; j < NUM_CELLS_X_2; ++j) {
403 src_address_file[i][j][0] =
404 0 + (i + NUM_CELLS_Y_2 / 2) * (NUM_CELLS_X + 1) + (j + NUM_CELLS_X_2 / 2);
405 src_address_file[i][j][1] =
406 1 + (i + NUM_CELLS_Y_2 / 2) * (NUM_CELLS_X + 1) + (j + NUM_CELLS_X_2 / 2);
407 src_address_file[i][j][2] =
408 0 + (i + 1 + NUM_CELLS_Y_2 / 2) * (NUM_CELLS_X + 1) + (j + NUM_CELLS_X_2 / 2);
409 src_address_file[i][j][3] =
410 1 + (i + 1 + NUM_CELLS_Y_2 / 2) * (NUM_CELLS_X + 1) + (j + NUM_CELLS_X_2 / 2);
411 for (unsigned k = 0; k < 4; ++k)
412 tgt_address_file[i][j][k] =
413 (i + NUM_CELLS_Y_2 / 2) * NUM_CELLS_X + (j + NUM_CELLS_X_2 / 2);
414 for (unsigned k = 0; k < 4; ++k)
415 weights_file[i][j][k] = (double)(k + 1) * 0.1;
416 }
417 }
418}
419
420static void
421utest_generate_ref_weights() {
422
423 for (unsigned i = 0, idx = 0; i < NUM_CELLS_Y; ++i) {
424 for (unsigned j = 0; j < NUM_CELLS_X; ++j, ++idx) {
425 ref_src_address[i][j][0] = 0 + i * (NUM_CELLS_X + 1) + j;
426 ref_src_address[i][j][1] = 1 + i * (NUM_CELLS_X + 1) + j;
427 ref_src_address[i][j][2] = 0 + (i + 1) * (NUM_CELLS_X + 1) + j;
428 ref_src_address[i][j][3] = 1 + (i + 1) * (NUM_CELLS_X + 1) + j;
429 for (unsigned k = 0; k < 4; ++k) {
430 ref_tgt_address[i][j][k] = idx;
431 ref_weights[i][j][k] = 0.25;
432 }
433 }
434 }
435 for (unsigned i = 0; i < NUM_CELLS_Y_2; ++i)
436 for (unsigned j = 0; j < NUM_CELLS_X_2; ++j)
437 for (unsigned k = 0; k < 4; ++k)
440 [tgt_address_file[i][j][k]%NUM_CELLS_X][k] = weights_file[i][j][k];
441}
442
struct yac_basic_grid * yac_basic_grid_new(char const *name, struct yac_basic_grid_data grid_data)
Definition basic_grid.c:57
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:202
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:222
struct yac_basic_grid * yac_basic_grid_empty_new(char const *name)
Definition basic_grid.c:70
void yac_basic_grid_delete(struct yac_basic_grid *grid)
Definition basic_grid.c:77
#define UNUSED(x)
Definition core.h:72
void yac_dist_grid_pair_delete(struct yac_dist_grid_pair *grid_pair)
Definition dist_grid.c:2377
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:2089
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)
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.
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:15
#define PUT_ERR(string)
Definition tests.h:10
static void LLtoXYZ(double lon, double lat, double p_out[])
Definition toy_scrip.c:587