YAC 3.21.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_interp_method_rbf_parallel.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
9#include "tests.h"
12#include "dist_grid_utils.h"
13#include "yac_mpi.h"
14#include "geometry.h"
15
16#include <mpi.h>
17#include <yaxt.h>
18
24char const src_grid_name[] = "src_grid";
25char const tgt_grid_name[] = "tgt_grid";
26
27static void utest_target_main(MPI_Comm target_comm);
28static void utest_source_main(MPI_Comm source_comm);
29
30int main (void) {
31
32 MPI_Init(NULL, NULL);
33
34 xt_initialize(MPI_COMM_WORLD);
35
36 int comm_rank, comm_size;
37 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
38 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
39 MPI_Barrier(MPI_COMM_WORLD);
40
41 if (comm_size != 2) {
42 PUT_ERR("ERROR: wrong number of processes");
43 xt_finalize();
44 MPI_Finalize();
45 return TEST_EXIT_CODE;
46 }
47
48 int tgt_flag = comm_rank < 1;
49
50 MPI_Comm split_comm;
51 MPI_Comm_split(MPI_COMM_WORLD, tgt_flag, 0, &split_comm);
52
53 if (tgt_flag) utest_target_main(split_comm);
54 else utest_source_main(split_comm);
55
56 MPI_Comm_free(&split_comm);
57 xt_finalize();
58 MPI_Finalize();
59
60 return TEST_EXIT_CODE;
61}
62
63static void utest_source_main(MPI_Comm source_comm) {
64
65 // 1 and 5 nearest neighbours per target point with fixed value fallback
66
67 // corner and cell ids for a 7 x 7 grid (x == target point position)
68
69 // 56-----57-----58-----59-----60-----61-----62-----63
70 // | x| x| x| x| x| x| x|
71 // | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
72 // | | | | | | | |
73 // 48-----49-----50-----51-----52-----53-----54-----55
74 // | x| x| x| x| x| x| x|
75 // | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
76 // | | | | | | | |
77 // 40-----41-----42-----43-----44-----45-----46-----47
78 // | x| x| x| x| x| x| x|
79 // | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
80 // | | | | | | | |
81 // 32-----33-----34-----35-----36-----37-----38-----39
82 // | x| x| x| x| x| x| x|
83 // | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
84 // | | | | | | | |
85 // 24-----25-----26-----27-----28-----29-----30-----31
86 // | x| x| x| x| x| x| x|
87 // | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
88 // | | | | | | | |
89 // 16-----17-----18-----19-----20-----21-----22-----23
90 // | x| x| x| x| x| x| x|
91 // | 07 | 08 | 09 | 10 | 11 | 12 | 13 |
92 // | | | | | | | |
93 // 08-----09-----10-----11-----12-----13-----14-----15
94 // | x| x| x| x| x| x| x|
95 // | 00 | 01 | 02 | 03 | 04 | 05 | 06 |
96 // | | | | | | | |
97 // 00-----01-----02-----03-----04-----05-----06-----07
98 //
99 // the grid is distributed among the processes as follows:
100 // (index == process)
101 //
102 // 3---3---3---3---3---3---3---3
103 // | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
104 // 3---3---3---3---3---3---3---3
105 // | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
106 // 3---3---3---1---2---2---3---3
107 // | 1 | 1 | 1 | 2 | 2 | 2 | 2 |
108 // 1---1---1---2---2---2---2---2
109 // | 1 | 1 | 1 | 2 | 2 | 2 | 2 |
110 // 1---1---1---1---2---2---2---2
111 // | 1 | 1 | 1 | 2 | 2 | 2 | 2 |
112 // 1---1---1---0---0---0---2---2
113 // | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
114 // 0---0---0---0---0---0---0---0
115 // | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
116 // 0---0---0---0---0---0---0---0
117 //
118 // the source mask looks as follows (# == masked point)
119 //
120 // +---+---+---+---+---+---+---#
121 // | | | | | | | |
122 // +---+---+---+---+---+---#---+
123 // | | | | | | | |
124 // +---+---+---+---+---#---+---+
125 // | | | | | | | |
126 // +---+---+---+---#---+---+---+
127 // | | | | | | | |
128 // +---+---+---#---+---+---+---+
129 // | | | | | | | |
130 // +---+---#---+---+---+---+---+
131 // | | | | | | | |
132 // +---#---+---+---+---+---+---+
133 // | | | | | | | |
134 // #---+---+---+---+---+---+---+
135
136 int my_source_rank;
137 MPI_Comm_rank(source_comm, &my_source_rank);
138
139 double coordinates_x[] = {-2.0, -1.0, 0.0, 1.0, 2.0};
140 double coordinates_y[] = {-2.0, -1.0, 0.0, 1.0, 2.0};
141 size_t const num_cells[2] = {4,4};
142 size_t local_start[2] = {0,0};
143 size_t local_count[2] = {4,4};
144 int with_halo = 0;
145 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
146 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
147
149 utest_generate_basic_grid_data_reg2d(
151 local_start, local_count, with_halo);
152
153 struct yac_basic_grid * grids[2] =
157
158 struct yac_dist_grid_pair * grid_pair =
159 yac_dist_grid_pair_new(grids[0], grids[1], MPI_COMM_WORLD);
160
161 struct yac_interp_field src_fields[] =
162 {{.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
163 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
165 {.location = YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = SIZE_MAX};
166
167 struct yac_interp_grid * interp_grid =
170
171 struct interp_method * method_stack[2] =
174 .type = YAC_INTERP_NNN_RBF, .n = 9,
176 .max_search_distance = YAC_INTERP_RBF_MAX_SEARCH_DISTANCE_DEFAULT,
177 .data.rbf_scale = YAC_INTERP_RBF_SCALE_DEFAULT}),
178 NULL};
179
180 struct yac_interp_weights * weights =
181 yac_interp_method_do_search(method_stack, interp_grid);
182
183 yac_interp_method_delete(method_stack);
184
185 enum yac_interp_weights_reorder_type reorder_type[2] =
187
188 for (size_t i = 0; i < 2; ++i) {
189 for (size_t collection_size = 1; collection_size < 4;
190 collection_size += 2) {
191
192 struct yac_interpolation * interpolation =
194 weights, reorder_type[i], collection_size,
195 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
196
197 // check generated interpolation
198 {
199 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
200 double ref_src_data[25] = {0,1,2,3,4,
201 1,2,3,4,5,
202 2,3,4,5,6,
203 3,4,5,6,7,
204 4,5,6,7,8};
205
206 for (size_t collection_idx = 0; collection_idx < collection_size;
207 ++collection_idx) {
208 // only one field
209 src_data[collection_idx] = xmalloc(1 * sizeof(**src_data));
210 src_data[collection_idx][0] =
211 xmalloc(grid_data.num_vertices * sizeof(***src_data));
212 for (size_t i = 0; i < grid_data.num_vertices; ++i)
213 src_data[collection_idx][0][i] =
214 ref_src_data[i] + (double)(collection_idx * 9);
215 }
216
217 yac_interpolation_execute(interpolation, src_data, NULL);
218
219 for (size_t collection_idx = 0; collection_idx < collection_size;
220 ++collection_idx) {
221 free(src_data[collection_idx][0]);
222 free(src_data[collection_idx]);
223 }
224 free(src_data);
225 }
226
227 yac_interpolation_delete(interpolation);
228 }
229 }
230
232 yac_interp_grid_delete(interp_grid);
233 yac_dist_grid_pair_delete(grid_pair);
234 yac_basic_grid_delete(grids[1]);
235 yac_basic_grid_delete(grids[0]);
236}
237
238static void utest_target_main(MPI_Comm target_comm) {
239
240 UNUSED(target_comm);
241
242 double coordinates_x[] = {-1.5,-0.5,0.5,1.5};
243 double coordinates_y[] = {-1.5,-0.5,0.5,1.5};
244 double cell_coordinates_x[] = {-1.0,0.0,1.0};
245 double cell_coordinates_y[] = {-1.0,0.0,1.0};
246 yac_coordinate_pointer cell_coordinates = xmalloc(9 * sizeof(*cell_coordinates));
247 size_t const num_cells[2] = {3,3};
248 size_t local_start[2] = {0,0};
249 size_t local_count[2] = {3,3};
250 int with_halo = 0;
251 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
252 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
253 for (size_t i = 0, k = 0; i < num_cells[1]; ++i)
254 for (size_t j = 0; j < num_cells[0]; ++j, ++k)
256 cell_coordinates_x[j], cell_coordinates_y[i], cell_coordinates[k]);
257
259 utest_generate_basic_grid_data_reg2d(
261 local_start, local_count, with_halo);
262
263 struct yac_basic_grid * grids[2] =
267 grids[0], YAC_LOC_CELL, cell_coordinates);
268
269 struct yac_dist_grid_pair * grid_pair =
270 yac_dist_grid_pair_new(grids[0], grids[1], MPI_COMM_WORLD);
271
272 struct yac_interp_field src_fields[] =
273 {{.location = YAC_LOC_CORNER, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
274 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
276 {.location = YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = SIZE_MAX};
277
278 struct yac_interp_grid * interp_grid =
281
282 struct interp_method * method_stack[2] =
285 .type = YAC_INTERP_NNN_RBF, .n = 9,
287 .max_search_distance = YAC_INTERP_RBF_MAX_SEARCH_DISTANCE_DEFAULT,
288 .data.rbf_scale = YAC_INTERP_RBF_SCALE_DEFAULT}),
289 NULL};
290
291 struct yac_interp_weights * weights =
292 yac_interp_method_do_search(method_stack, interp_grid);
293
294 yac_interp_method_delete(method_stack);
295
296 enum yac_interp_weights_reorder_type reorder_type[2] =
298
299 for (size_t i = 0; i < 2; ++i) {
300 for (size_t collection_size = 1; collection_size < 4;
301 collection_size += 2) {
302
303 struct yac_interpolation * interpolation =
305 weights, reorder_type[i], collection_size,
306 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
307
308 // check generated interpolation
309 {
310 double ref_tgt_field[9] = {2,3,4, 3,4,5, 4,5,6};
311
312 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
313 for (size_t collection_idx = 0; collection_idx < collection_size;
314 ++collection_idx) {
315 tgt_data[collection_idx] =
316 xmalloc(grid_data.num_cells * sizeof(**tgt_data));
317 for (size_t j = 0; j < 9; ++j) tgt_data[collection_idx][j] = -1.0;
318 }
319
320 yac_interpolation_execute(interpolation, NULL, tgt_data);
321
322 for (size_t collection_idx = 0; collection_idx < collection_size;
323 ++collection_idx)
324 for (size_t j = 0, offset = collection_idx * 9;
325 j < grid_data.num_cells; ++j)
326 if (fabs((ref_tgt_field[j] + (double)offset) -
327 tgt_data[collection_idx][j]) > 1e-3)
328 PUT_ERR("wrong interpolation result");
329
330 for (size_t collection_idx = 0; collection_idx < collection_size;
331 ++collection_idx)
332 free(tgt_data[collection_idx]);
333 free(tgt_data);
334 }
335
336 yac_interpolation_delete(interpolation);
337 }
338 }
339
341 yac_interp_grid_delete(interp_grid);
342 yac_dist_grid_pair_delete(grid_pair);
343 yac_basic_grid_delete(grids[1]);
344 yac_basic_grid_delete(grids[0]);
345}
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
#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
#define YAC_RAD
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.
Defines the interface of the interpolation method "base class" in YAC.
struct interp_method * yac_interp_method_nnn_new(struct yac_interp_method_nnn_config config)
@ YAC_INTERP_NNN_RBF
radial basis functions
#define YAC_INTERP_RBF_MAX_SEARCH_DISTANCE_DEFAULT
#define YAC_INTERP_RBF_N_MIN_DEFAULT
a value of 0 is interpreted as "use the value of n"
#define YAC_INTERP_RBF_SCALE_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)
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
@ 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
int collection_size
static MPI_Comm split_comm
char const src_grid_name[]
char const tgt_grid_name[]
double coordinates_x[]
size_t num_cells[2]
double cell_coordinates_y[]
double coordinates_y[]
double cell_coordinates_x[]
#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