YAC 3.21.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_interpolation_parallel3.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 "grids/dist_grid.h"
18#include "dist_grid_utils.h"
19#include "geometry.h"
23
29#define YAC_RAD (0.01745329251994329576923690768489) // M_PI / 180
30
31static void
32utest_generate_ref_weights();
33
34static void utest_submain_src(
35 MPI_Comm comp_comm, enum yac_interp_weights_reorder_type reorder_type);
36
37static void utest_submain_tgt(
38 MPI_Comm comp_comm, enum yac_interp_weights_reorder_type reorder_type);
39
40// link data for input weight file
41unsigned const num_links_file = 48;
43 9,10,16,17, 10,11,17,18, 15,16,22,23, 16,17,23,24, 17,18,24,25, 18,19,25,26,
44 22,23,29,30, 23,24,30,31, 24,25,31,32, 25,26,32,33, 30,31,37,38, 31,32,38,39};
46 8,8,8,8, 9,9,9,9, 13,13,13,13, 14,14,14,14, 15,15,15,15, 16,16,16,16,
47 19,19,19,19, 20,20,20,20, 21,21,21,21, 22,22,22,22, 26,26,26,26, 27,27,27,27};
48double weights_file[48] = {
49 0.1,0.2,0.3,0.4, 0.1,0.2,0.3,0.4, 0.1,0.2,0.3,0.4, 0.1,0.2,0.3,0.4,
50 0.1,0.2,0.3,0.4, 0.1,0.2,0.3,0.4, 0.1,0.2,0.3,0.4, 0.1,0.2,0.3,0.4,
51 0.1,0.2,0.3,0.4, 0.1,0.2,0.3,0.4, 0.1,0.2,0.3,0.4, 0.1,0.2,0.3,0.4};
52char const weight_file_in[] =
53 "test_interpolation_parallel3_weight_file_in.nc";
54char const weight_file_out[] =
55 "test_interpolation_parallel3_weight_file_out.nc";
56char const src_grid_name[] = "src_grid";
57char const tgt_grid_name[] = "tgt_grid";
58
59// reference link data for output weight file
60unsigned ref_num_links = 4 * 36;
61
62int ref_src_address[4 * 36];
63int ref_tgt_address[4 * 36];
64double ref_weights[4 * 36];
65
66int const * ref_tgt_address_fixed = NULL;
67double const * ref_fixed_values = NULL;
68int const * ref_num_tgt_per_fixed_value = NULL;
70
71/*
72 * The grid is distributed among 4 processes
73 *
74 * The global grid has 6x6 cells:
75 *
76 * 42--79--43--81--44--83--45--85--46--87--47--89--48
77 * | | | | | | |
78 * 66 30 68 31 70 32 72 33 74 34 76 35 78
79 * | | | | | | |
80 * 35--65--36--67--37--69--38--71--39--73--40--75--41
81 * | | | | | | |
82 * 53 24 55 25 57 26 59 27 61 28 63 29 64
83 * | | | | | | |
84 * 28--52--29--54--30--56--31--58--32--60--33--62--34
85 * | | | | | | |
86 * 40 18 42 19 44 20 46 21 48 22 50 23 51
87 * | | | | | | |
88 * 21--39--22--41--23--43--24--45--25--47--26--49--27
89 * | | | | | | |
90 * 27 12 29 13 31 14 33 15 35 16 37 17 38
91 * | | | | | | |
92 * 14--26--15--28--16--30--17--32--18--34--19--36--20
93 * | | | | | | |
94 * 14 06 16 07 18 08 20 09 22 10 24 11 25
95 * | | | | | | |
96 * 07--13--08--15--09--17--10--19--11--21--12--23--13
97 * | | | | | | |
98 * 01 00 03 01 05 02 07 03 09 04 11 05 12
99 * | | | | | | |
100 * 00--00--01--02--02--04--03--06--04--08--05--10--06
101 */
102
103// grid information (is the same for source and target)
104size_t num_cells[2] = {6,6};
105double coordinates_x[] = {0,1,2,3,4,5,6};
106double coordinates_y[] = {0,1,2,3,4,5,6};
107double cell_coordinates_x[] = {0.5,1.5,2.5,3.5,4.5,5.5};
108double cell_coordinates_y[] = {0.5,1.5,2.5,3.5,4.5,5.5};
109double cell_coords[36][3];
110int with_halo = 1;
111
112int main(int argc, char *argv[]) {
113
114 if (argc != 2) {
115 PUT_ERR("wrong number of arguments\n");
116 return TEST_EXIT_CODE;
117 }
118
119 enum yac_interp_weights_reorder_type reorder_type =
120 (strcmp(argv[1], "src") == 0)?YAC_MAPPING_ON_SRC:YAC_MAPPING_ON_TGT;
121
122 if ((reorder_type != YAC_MAPPING_ON_SRC) && strcmp(argv[1], "tgt")) {
123 PUT_ERR("invalid argument (has to be either \"src\" or \"tgt\")\n");
124 return TEST_EXIT_CODE;
125 }
126
127 MPI_Init(NULL, NULL);
128
129 xt_initialize(MPI_COMM_WORLD);
130
131 int comm_rank, comm_size;
132 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
133 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
134 MPI_Barrier(MPI_COMM_WORLD);
135
136 if (comm_size != 8) {
137 PUT_ERR("ERROR: wrong number of processes");
138 xt_finalize();
139 MPI_Finalize();
140 return TEST_EXIT_CODE;
141 }
142
143 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
144 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
145 for (size_t i = 0; i < 6; ++i)
146 for (size_t j = 0; j < 6; ++j)
149
150 utest_generate_ref_weights();
151
152 // split processes into source an target
153
154 int comp_flag = comm_rank < 4;
155
156 MPI_Comm split_comm;
157 MPI_Comm_split(
158 MPI_COMM_WORLD, comp_flag, 0, &split_comm);
159
160 if (comp_flag) utest_submain_src(split_comm, reorder_type);
161 else utest_submain_tgt(split_comm, reorder_type);
162
163 MPI_Comm_free(&split_comm);
164 xt_finalize();
165 MPI_Finalize();
166
167 return TEST_EXIT_CODE;
168}
169
170static void utest_submain_tgt(
171 MPI_Comm comp_comm, enum yac_interp_weights_reorder_type reorder_type) {
172
173 int my_rank;
174 MPI_Comm_rank(comp_comm, &my_rank);
175
176 size_t local_start[4][2] = {{0,0},{3,0},{0,3},{3,3}};
177 size_t local_count[4][2] = {{3,3},{3,3},{3,3},{3,3}};
178
180 utest_generate_basic_grid_data_reg2d(
182 local_start[my_rank], local_count[my_rank], with_halo);
183 size_t num_cells = grid_data.num_cells;
184
185 yac_coordinate_pointer cell_field_coords =
186 xmalloc(num_cells * sizeof(*cell_field_coords));
187 for (size_t i = 0; i < num_cells; ++i)
188 memcpy(cell_field_coords[i], cell_coords[grid_data.cell_ids[i]],
189 3 * sizeof(double));
190
191 struct yac_basic_grid * tgt_grid =
194 tgt_grid, YAC_LOC_CELL, cell_field_coords);
195 struct yac_basic_grid * src_grid =
197
198 struct yac_dist_grid_pair * grid_pair =
199 yac_dist_grid_pair_new(tgt_grid, src_grid, MPI_COMM_WORLD);
200
201 { // test interpolation
202
203 struct yac_interp_field src_fields[] =
204 {{.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
205 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
207 {.location = YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = SIZE_MAX};
208
209 struct yac_interp_grid * interp_grid =
212
213 struct interp_method * method_stack[] =
218 NULL};
219
220 struct yac_interp_weights * weights =
221 yac_interp_method_do_search(method_stack, interp_grid);
222
223 yac_interp_method_delete(method_stack);
224
225 struct yac_interpolation * interpolation =
227 weights, reorder_type, 1,
228 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
229
230 //---------------------
231 // do the interpolation
232 //---------------------
233
234 // target_data dimensions [collection_idx]
235 // [local_idx]
236 double * target_data_field =
237 xmalloc(num_cells * sizeof(*target_data_field));
238 double * target_data[1] = {target_data_field}; // collection_size == 1
239 for (size_t i = 0; i < num_cells; ++i) target_data_field[i] = -1.0;
240
241 yac_interpolation_execute_get(interpolation, target_data);
242
243 //----------------------------
244 // check interpolation results
245 //----------------------------
246
250
251 double ref_global_target_data[6*6];
252
253 for (size_t i = 0; i < 6*6; ++i) {
254 ref_global_target_data[i] = 0;
255 for (size_t j = 0; j < 4; ++j)
256 ref_global_target_data[i] +=
257 ref_weights[4 * i + j] * (double)ref_src_address[4 * i + j];
258 }
259
260 for (size_t i = 0; i < num_cells; ++i) {
261 if (grid_data.core_cell_mask[i]) {
262 if (fabs(
263 target_data[0][i] -
264 ref_global_target_data[grid_data.cell_ids[i]]) > 1e-10)
265 PUT_ERR("error in interpolated data on target side\n");
266 } else {
267 if (target_data[0][i] != -1.0)
268 PUT_ERR("error in interpolated data on target side\n");
269 }
270 }
271
272 //--------
273 // cleanup
274 //--------
275
276 free(target_data_field);
277 yac_interpolation_delete(interpolation);
279 yac_interp_grid_delete(interp_grid);
280 }
281
282 //--------
283 // cleanup
284 //--------
285
286 yac_dist_grid_pair_delete(grid_pair);
287 yac_basic_grid_delete(src_grid);
288 yac_basic_grid_delete(tgt_grid);
289}
290
291static void utest_submain_src(
292 MPI_Comm comp_comm, enum yac_interp_weights_reorder_type reorder_type) {
293
294 int my_rank;
295 MPI_Comm_rank(comp_comm, &my_rank);
296
297 // create a weight file
298 if (my_rank == 0) {
299 enum yac_location src_locations[1] = {YAC_LOC_CORNER};
300 enum yac_location tgt_location = YAC_LOC_CELL;
301 int * tgt_id_fixed = NULL;
302 unsigned num_fixed_tgt = 0;
303 double * fixed_values = NULL;
304 int * num_tgt_per_fixed_value = NULL;
305 unsigned num_fixed_values = 0;
306 utest_write_weight_file(weight_file_in, src_address_file, tgt_address_file,
307 weights_file, num_links_file, src_locations,
308 1, (int*)&num_links_file, tgt_id_fixed, num_fixed_tgt,
309 fixed_values, num_tgt_per_fixed_value, num_fixed_values,
310 tgt_location, src_grid_name, tgt_grid_name);
311 }
312
313 size_t local_start[4][2] = {{0,0},{1,0},{3,0},{5,0}};
314 size_t local_count[4][2] = {{1,6},{2,6},{2,6},{1,6}};
315
317 utest_generate_basic_grid_data_reg2d(
319 local_start[my_rank], local_count[my_rank], with_halo);
320 size_t num_vertices = grid_data.num_vertices;
321
322 struct yac_basic_grid * src_grid =
325 struct yac_basic_grid * tgt_grid =
327
328 struct yac_dist_grid_pair * grid_pair =
329 yac_dist_grid_pair_new(src_grid, tgt_grid, MPI_COMM_WORLD);
330
331 { // test interpolation
332
333 struct yac_interp_field src_fields[] =
334 {{.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
335 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
337 {.location = YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = SIZE_MAX};
338
339 struct yac_interp_grid * interp_grid =
342
343 struct interp_method * method_stack[] =
348 NULL};
349
350 struct yac_interp_weights * weights =
351 yac_interp_method_do_search(method_stack, interp_grid);
352
353 yac_interp_method_delete(method_stack);
354
355 struct yac_interpolation * interpolation =
357 weights, reorder_type, 1,
358 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
359
360 //---------------------
361 // do the interpolation
362 //---------------------
363
364 // source_data dimensions [collection_idx]
365 // [pointset_idx]
366 // [local_idx]
367 double * source_data_field =
368 xmalloc(num_vertices * sizeof(*source_data_field));
369 double * source_data_pointset[1] = {source_data_field}; // num_pointset == 1
370 double ** source_data[1] = {source_data_pointset}; // collection_size == 1
371 for (size_t i = 0; i < num_vertices; ++i)
372 source_data_field[i] =
373 (grid_data.core_vertex_mask[i])?
374 ((double)(grid_data.vertex_ids[i])):(-1.0);
375
376 yac_interpolation_execute_put(interpolation, source_data);
377
378
379 //------------------------------
380 // check the written weight file
381 //------------------------------
382
386
387 if (my_rank == 0) {
388 enum yac_location ref_src_locations[1] = {YAC_LOC_CORNER};
389 enum yac_location ref_tgt_location = YAC_LOC_CELL;
390 utest_check_weight_file(weight_file_out, ref_src_address, ref_tgt_address,
391 ref_weights, ref_num_links, ref_src_locations,
394 ref_num_fixed_values, ref_tgt_location,
396 }
397
398 //--------
399 // cleanup
400 //--------
401
402 free(source_data_field);
403 yac_interpolation_delete(interpolation);
405 yac_interp_grid_delete(interp_grid);
406 }
407
408 //--------
409 // cleanup
410 //--------
411
412 yac_dist_grid_pair_delete(grid_pair);
413 yac_basic_grid_delete(tgt_grid);
414 yac_basic_grid_delete(src_grid);
415
416 // delete weight file
417 if (my_rank == 0) {
418 unlink(weight_file_in);
419 unlink(weight_file_out);
420 }
421}
422
423static void
424utest_generate_ref_weights() {
425
426 for (unsigned i = 0; i < 6; ++i) {
427 for (unsigned j = 0; j < 6; ++j) {
428 ref_src_address[4 * (i * 6 + j) + 0] = 0 + i * 7 + j;
429 ref_src_address[4 * (i * 6 + j) + 1] = 1 + i * 7 + j;
430 ref_src_address[4 * (i * 6 + j) + 2] = 7 + i * 7 + j;
431 ref_src_address[4 * (i * 6 + j) + 3] = 8 + i * 7 + j;
432 }
433 }
434 for (unsigned i = 0; i < ref_num_links; ++i) ref_tgt_address[i] = i / 4;
435 for (unsigned i = 0; i < ref_num_links; ++i) ref_weights[i] = 0.25;
436 for (unsigned i = 0; i < num_links_file; ++i)
437 ref_weights[tgt_address_file[i] * 4 + (i & 3)] = weights_file[i];
438}
439
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
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
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
static void LLtoXYZ_deg(double lon, double lat, double p_out[])
Definition geometry.h:278
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 coordinates_x[]
unsigned ref_num_links
int const * ref_tgt_address_fixed
unsigned ref_num_fixed_values
unsigned const num_links_file
int ref_src_address[4 *36]
char const src_grid_name[]
char const tgt_grid_name[]
size_t num_cells[2]
char const weight_file_out[]
int src_address_file[48]
double cell_coordinates_y[]
double coordinates_y[]
double ref_weights[4 *36]
int const * ref_num_tgt_per_fixed_value
double const * ref_fixed_values
int ref_tgt_address[4 *36]
double cell_coords[36][3]
double weights_file[48]
int tgt_address_file[48]
double cell_coordinates_x[]
char const weight_file_in[]
#define TEST_EXIT_CODE
Definition tests.h:15
#define PUT_ERR(string)
Definition tests.h:10
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:21