YAC 3.12.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_interpolation_parallel5.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"
18#include "geometry.h"
24
30#define YAC_RAD (0.01745329251994329576923690768489) // M_PI / 180
31
32int main(int argc, char *argv[]) {
33
34 if (argc != 2) {
35 PUT_ERR("wrong number of arguments\n");
36 return TEST_EXIT_CODE;
37 }
38
39 enum yac_interp_weights_reorder_type reorder_type =
40 (strcmp(argv[1], "src") == 0)?YAC_MAPPING_ON_SRC:YAC_MAPPING_ON_TGT;
41
42 if ((reorder_type != YAC_MAPPING_ON_SRC) && strcmp(argv[1], "tgt")) {
43 PUT_ERR("invalid argument (has to be either \"src\" or \"tgt\")\n");
44 return TEST_EXIT_CODE;
45 }
46
47 MPI_Init(NULL, NULL);
48
49 xt_initialize(MPI_COMM_WORLD);
50
51 int comm_rank, comm_size;
52 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
53 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
54 MPI_Barrier(MPI_COMM_WORLD);
55
56 if (comm_size != 3) {
57 PUT_ERR("ERROR: wrong number of processes");
58 xt_finalize();
59 MPI_Finalize();
60 return TEST_EXIT_CODE;
61 }
62
63 unsigned is_source = comm_rank > 0;
64 unsigned is_target = comm_rank < 2;
65
66 /*
67 * The source grid is distributed among 2 processes.
68 *
69 * The global source grid has 5x4 cells:
70 *
71 * 24--44--25--45--26--46--27--47--28--48--29
72 * | | | | | |
73 * 34 15 36 16 38 17 40 18 42 19 43
74 * | | | | | |
75 * 18--33--19--35--20--37--21--39--22--41--23
76 * | | | | | |
77 * 23 10 25 11 27 12 29 13 31 14 32
78 * | | | | | |
79 * 12--22--13--24--14--26--15--28--16--30--17
80 * | | | | | |
81 * 12 05 14 06 16 07 18 08 20 09 21
82 * | | | | | |
83 * 06--11--07--13--08--15--09--17--10--19--11
84 * | | | | | |
85 * 01 00 03 01 05 02 07 03 09 04 10
86 * | | | | | |
87 * 00--01--01--02--02--04--03--06--04--08--05
88 */
89 /*
90 * The target grid is distributed among 2 processes
91 *
92 * The global target grid has 6x3 cells:
93 *
94 * 21--39--22--40--23--41--24--42--25--43--26--44--27
95 * | | | | | | |
96 * 27 12 29 13 31 14 33 15 35 16 37 17 38
97 * | | | | | | |
98 * 14--26--15--28--16--30--17--32--18--34--19--36--20
99 * | | | | | | |
100 * 14 06 16 07 18 08 20 09 22 10 24 11 25
101 * | | | | | | |
102 * 07--13--08--15--09--17--10--19--11--21--12--23--13
103 * | | | | | | |
104 * 01 00 03 01 05 02 07 03 09 04 11 05 12
105 * | | | | | | |
106 * 00--00--01--02--02--04--03--06--04--08--05--10--06
107 */
108
109 char const source_grid_name[] = "source_grid";
110 char const target_grid_name[] = "target_grid";
111
112 double src_coordinates_x[] = {0,1,2,3,4,5};
113 double src_coordinates_y[] = {0,1,2,3,4};
114 size_t src_global_num_cells[] = {5,4};
115 int src_with_halo = 1;
116 size_t src_local_start[2][2] = {{0,0}, {0,2}};
117 size_t src_local_count[2] = {5,2};
118
119 for (size_t i = 0; i <= src_global_num_cells[0]; ++i)
120 src_coordinates_x[i] *= YAC_RAD;
121 for (size_t i = 0; i <= src_global_num_cells[1]; ++i)
122 src_coordinates_y[i] *= YAC_RAD;
123
124 struct yac_basic_grid * src_grid =
125 (is_source)?
127 source_grid_name,
129 src_coordinates_x, src_coordinates_y, src_global_num_cells,
130 src_local_start[comm_rank-1], src_local_count, src_with_halo)):
131 yac_basic_grid_empty_new(source_grid_name);
132
133 double tgt_coordinates_x[] = {0.7,1.7,2.7,3.7,4.7,5.7,6.7};
134 double tgt_coordinates_y[] = {0.7,1.7,2.7,3.7};
135 size_t tgt_global_num_cells[] = {6,3};
136 int tgt_with_halo = 1;
137 size_t tgt_local_start[2][2] = {{3,0}, {0,0}};
138 size_t tgt_local_count[2] = {3,3};
139
140 for (size_t i = 0; i <= tgt_global_num_cells[0]; ++i)
141 tgt_coordinates_x[i] *= YAC_RAD;
142 for (size_t i = 0; i <= tgt_global_num_cells[1]; ++i)
143 tgt_coordinates_y[i] *= YAC_RAD;
144
145 struct yac_basic_grid * tgt_grid =
146 (is_target)?
148 target_grid_name,
150 tgt_coordinates_x, tgt_coordinates_y, tgt_global_num_cells,
151 tgt_local_start[comm_rank], tgt_local_count, tgt_with_halo)):
152 yac_basic_grid_empty_new(target_grid_name);
153
154 struct yac_dist_grid_pair * grid_pair =
155 yac_dist_grid_pair_new(src_grid, tgt_grid, MPI_COMM_WORLD);
156
157 { // test interpolation
158
159 struct yac_interp_field src_fields[] =
160 {{.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
161 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
162 struct yac_interp_field tgt_field =
163 {.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
164
165 struct yac_interp_grid * interp_grid =
166 yac_interp_grid_new(grid_pair, source_grid_name, target_grid_name,
168
169 // generate a weight file in which all weights are one
170 char const * sum_weight_file_name =
171 "test_interpolation_parallel5_weight_file.nc";
172 if (comm_rank == 0) {
173 int src_indices[4*5*4] =
174 {0,1,6,7, 1,2,7,8, 2,3,8,9, 3,4,9,10, 4,5,10,11,
175 6,7,12,13, 7,8,13,14, 8,9,14,15, 9,10,15,16, 10,11,16,17,
176 12,13,18,19, 13,14,19,20, 14,15,20,21, 15,16,21,22, 16,17,22,23,
177 18,19,24,25, 19,20,25,26, 20,21,26,27, 21,22,27,28, 22,23,28,29};
178 int tgt_indices[4*5*4] =
179 {0,0,0,0, 1,1,1,1, 2,2,2,2, 3,3,3,3, 4,4,4,4,
180 7,7,7,7, 8,8,8,8, 9,9,9,9, 10,10,10,10, 11,11,11,11,
181 14,14,14,14, 15,15,15,15, 16,16,16,16, 17,17,17,17, 18,18,18,18,
182 21,21,21,21, 22,22,22,22, 23,23,23,23, 24,24,24,24, 25,25,25,25};
183 double weights[4*5*4];
184 for (size_t i = 0; i < 4*5*4; ++i) weights[i] = 1.0;
185 size_t num_links = 4*5*4;
186 enum yac_location src_locations[1] = {YAC_LOC_CORNER};
187 enum yac_location tgt_location = YAC_LOC_CORNER;
188 unsigned num_src_fields = 1;
189 int num_links_per_field[1] = {num_links};
190 int * tgt_id_fixed = NULL;
191 size_t num_fixed_tgt = 0;
192 double * fixed_values = NULL;
193 int * num_tgt_per_fixed_value = NULL;
194 size_t num_fixed_values = 0;
195
197 sum_weight_file_name, src_indices, tgt_indices, weights, num_links,
198 src_locations, num_src_fields, num_links_per_field, tgt_id_fixed,
199 num_fixed_tgt, fixed_values, num_tgt_per_fixed_value,
200 num_fixed_values, tgt_location,
201 source_grid_name, target_grid_name);
202 }
203 MPI_Barrier(MPI_COMM_WORLD);
204
205 size_t const num_method_stacks = 3;
206 struct interp_method * method_stacks[3][3] =
209 NULL},
211 (struct yac_nnn_config){
212 .type = YAC_INTERP_NNN_AVG, .n = 1,
213 .max_search_distance =
216 NULL},
218 sum_weight_file_name, YAC_INTERP_FILE_ON_MISSING_FILE_DEFAULT,
221 NULL}};
222
223 for (size_t method_stack_index = 0;
224 method_stack_index < num_method_stacks; ++method_stack_index) {
225
226 struct yac_interp_weights * weights =
228 method_stacks[method_stack_index], interp_grid);
229
230 yac_interp_method_delete(method_stacks[method_stack_index]);
231
232 struct yac_interpolation * interpolation =
234 weights, reorder_type, 1,
235 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
236
237 char const weight_file_out[] =
238 "test_interpolation_parallel5_weight_file_out.nc";
240 weights, weight_file_out, source_grid_name, target_grid_name, 0, 0,
242
243 //---------------------
244 // do the interpolation
245 //---------------------
246
247 struct yac_basic_grid_data * src_grid_data =
248 is_source?yac_basic_grid_get_data(src_grid):NULL;
249 double * source_data_field =
250 is_source?
251 xmalloc(src_grid_data->num_vertices * sizeof(*source_data_field)):NULL;
252 double * source_data_pointset[1] = {source_data_field}; // num_pointset == 1
253 double ** source_data[1] = {source_data_pointset}; // collection_size == 1
254
255 struct yac_basic_grid_data * tgt_grid_data =
256 is_target?yac_basic_grid_get_data(tgt_grid):NULL;
257 double * target_data_field =
258 is_target?
259 xmalloc(tgt_grid_data->num_vertices * sizeof(*target_data_field)):NULL;
260 double * target_data[1] = {target_data_field}; // collection_size == 1
261
262 if (is_source) {
263
264 // source_data dimensions [collection_idx]
265 // [pointset_idx]
266 // [local_idx]
267 for (size_t i = 0; i < src_grid_data->num_vertices; ++i)
268 source_data_field[i] =
269 (src_grid_data->core_vertex_mask[i])?
270 ((double)(src_grid_data->vertex_ids[i])):(-1.0);
271 }
272
273 for (int use_put_get = 0; use_put_get < 2; ++use_put_get) {
274
275 if (is_target) {
276
277 // target_data dimensions [collection_idx]
278 // [local_idx]
279 for (size_t i = 0; i < tgt_grid_data->num_vertices; ++i)
280 target_data_field[i] = -1.0;
281 }
282
283 if (use_put_get) {
284 if (is_source)
285 yac_interpolation_execute_put(interpolation, source_data);
286 if (is_target)
287 yac_interpolation_execute_get(interpolation, target_data);
288 } else {
289 yac_interpolation_execute(interpolation, source_data, target_data);
290 }
291
292 if (is_target) {
293
294 //----------------------------
295 // check interpolation results
296 //----------------------------
297
298 double ref_target_data[3][4*7] =
299 {{3.5,4.5,5.5,6.5,7.5,1337,1337,
300 9.5,10.5,11.5,12.5,13.5,1337,1337,
301 15.5,16.5,17.5,18.5,19.5,1337,1337,
302 21.5,22.5,23.5,24.5,25.5,1337,1337},
303 {7,8,9,10,11,11,11,
304 13,14,15,16,17,17,17,
305 19,20,21,22,23,23,23,
306 25,26,27,28,29,29,29},
307 {14,18,22,26,30,1337,1337,
308 38,42,46,50,54,1337,1337,
309 62,66,70,74,78,1337,1337,
310 86,90,94,98,102,1337,1337}};
311
312 for (size_t i = 0; i < tgt_grid_data->num_vertices; ++i) {
313 if (tgt_grid_data->core_vertex_mask[i]) {
315 target_data[0][i],
316 ref_target_data
317 [method_stack_index][tgt_grid_data->vertex_ids[i]]))
318 PUT_ERR("error in interpolated data on target side\n");
319 } else {
320 if (target_data[0][i] != -1.0)
321 PUT_ERR("error in interpolated data on target side\n");
322 }
323 }
324 }
325 }
326
327 if (is_target) free(target_data_field);
328 if (is_source) free(source_data_field);
329
330 //--------
331 // cleanup
332 //--------
333
334 if (is_source || is_target) yac_interpolation_delete(interpolation);
336
337 if (comm_rank == 0) unlink(weight_file_out);
338 }
339
340 if (comm_rank == 0) unlink(sum_weight_file_name);
341
342 yac_interp_grid_delete(interp_grid);
343 }
344
345 //--------
346 // cleanup
347 //--------
348
349 yac_dist_grid_pair_delete(grid_pair);
350 yac_basic_grid_delete(src_grid);
351 yac_basic_grid_delete(tgt_grid);
352
353 xt_finalize();
354 MPI_Finalize();
355
356 return TEST_EXIT_CODE;
357}
358
struct yac_basic_grid * yac_basic_grid_new(char const *name, struct yac_basic_grid_data grid_data)
Definition basic_grid.c:50
struct yac_basic_grid_data * yac_basic_grid_get_data(struct yac_basic_grid *grid)
Definition basic_grid.c:137
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
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 interp_method * yac_interp_method_fixed_new(double value)
struct interp_method * yac_interp_method_nnn_new(struct yac_nnn_config config)
@ YAC_INTERP_NNN_AVG
average of n source points
#define YAC_INTERP_NNN_MAX_SEARCH_DISTANCE_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_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.
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
#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
int double_are_unequal(double a, double b)
char const weight_file_out[]
#define TEST_EXIT_CODE
Definition tests.h:14
#define PUT_ERR(string)
Definition tests.h:10
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)