YAC 3.13.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_interp_method_conserv_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"
13#include "dist_grid_utils.h"
14#include "yac_mpi.h"
15#include "geometry.h"
16
17#include <mpi.h>
18#include <yaxt.h>
19
20
26char const src_grid_name[] = "src_grid";
27char const tgt_grid_name[] = "tgt_grid";
28
29// conservative remapping with one source and one target process
30static void utest_test1();
31
32// conservative remapping with two source and one target process
33static void utest_test2();
34
35// conservative remapping with three source and two target processes
36static void utest_test3();
37
38// conservative remapping with three source and two target processes
39// this test checks all possible configurations for the conservative
40// remapping
41static void utest_test4();
42
43// conservative remapping with three source and two target processes
44// this test checks how the interpolation method handles the case in which
45// it does not receive any target points because they are masked
46static void utest_test5();
47
48// 2nd order conservative remapping with one source and one target process
49static void utest_test6();
50
51// 2nd order conservative remapping with three sources and one target process
52static void utest_test7();
53
54// 2nd order conservative remapping with three sources and one target process
55static void utest_test8();
56
57// conservative remapping with 4 source and 4 target processes
58// contain partially overlapping cells and non-covered tgt cells
59static void utest_test9();
60
61// target cell do not overlap with any non-masked source cell
62static void utest_test10();
63static void utest_test11();
64
65// 2nd order conservative remapping with three sources and one target process
66static void utest_test12();
67
68// only half of the target cells overlap with source grid
69// (replicates a bug found in the packing of the final results)
70static void utest_test13();
71
72// check a bug found in 2nd order conservative
73static void utest_test14();
74
75int main (void) {
76
77 MPI_Init(NULL, NULL);
78
79 xt_initialize(MPI_COMM_WORLD);
80
81 utest_test1();
82 utest_test2();
83 utest_test3();
84 utest_test4();
85 utest_test5();
86 utest_test6();
87 utest_test7();
88 utest_test8();
89 utest_test9();
90 utest_test10();
91 utest_test11();
92 utest_test12();
93 utest_test13();
94 utest_test14();
95
96 xt_finalize();
97 MPI_Finalize();
98
99 return TEST_EXIT_CODE;
100}
101
102static void utest_test1() {
103
104 int comm_rank, comm_size;
105 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
106 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
107 MPI_Barrier(MPI_COMM_WORLD);
108
109 if (comm_size < 2) {
110 PUT_ERR("ERROR: too few processes");
111 xt_finalize();
112 MPI_Finalize();
113 exit(TEST_EXIT_CODE);
114 }
115
116 int is_active = comm_rank < 2;
117
118 MPI_Comm global_comm;
119 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
120
121 if (!is_active) {
122 MPI_Comm_free(&global_comm);
123 return;
124 }
125
126 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
127 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
128
129 int is_source = comm_rank == 1;
130 int is_target = comm_rank == 0;
131
132 MPI_Comm split_comm;
133 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
134
135 MPI_Comm_rank(split_comm, &comm_rank);
136 MPI_Comm_size(split_comm, &comm_size);
137
138 struct yac_basic_grid * src_grid = NULL;
139 struct yac_basic_grid * tgt_grid = NULL;
140
141 if (is_source) {
142
143 // the global source grid is a 2x2 grid:
144 // 06--10--07--11--08
145 // | | |
146 // 06 02 08 03 09
147 // | | |
148 // 03--05--04--07--05
149 // | | |
150 // 01 00 03 01 04
151 // | | |
152 // 00--00--01--02--02
153
154 double coordinates_x[] = {-1,0,1};
155 double coordinates_y[] = {-1,0,1};
156 size_t const num_cells[2] = {2,2};
157 size_t local_start[1][2] = {{0,0}};
158 size_t local_count[1][2] = {{2,2}};
159 int with_halo = 1;
160 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
161 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
162
163
164 src_grid =
169 local_start[comm_rank], local_count[comm_rank], with_halo));
171
172 if (is_target) {
173
174 double coordinates_x[] = {-0.5,0.5};
175 double coordinates_y[] = {-0.5,0.5};
176 size_t const num_cells[2] = {1,1};
177 size_t local_start[1][2] = {{0,0}};
178 size_t local_count[1][2] = {{1,1}};
179 int with_halo = 1;
180 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
181 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
182
183 tgt_grid =
188 local_start[comm_rank], local_count[comm_rank], with_halo));
190
191 struct yac_dist_grid_pair * grid_pair =
192 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
193
194 struct yac_interp_field src_fields[] =
195 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
196 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
198 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
199
200 struct yac_interp_grid * interp_grid =
203
204 int order = 1;
205 int enforced_conserv = 0;
206 int partial_coverage = 0;
207 enum yac_interp_method_conserv_normalisation normalisation =
209
210 struct interp_method * method_stack[] = {
212 order, enforced_conserv, partial_coverage, normalisation), NULL};
213
214 struct yac_interp_weights * weights =
215 yac_interp_method_do_search(method_stack, interp_grid);
216
217 yac_interp_method_delete(method_stack);
218
219 enum yac_interp_weights_reorder_type reorder_type[2] =
221
222 for (size_t j = 0; j < 2; ++j) {
223 for (size_t collection_size = 1; collection_size < 4;
224 collection_size += 2) {
225
226 struct yac_interpolation * interpolation =
228 weights, reorder_type[j], collection_size,
229 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
230
231 // check generated interpolation
232 if (is_source) {
233 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
234 for (size_t i = 0; i < collection_size; ++i)
235 src_data[i] = xmalloc(1 * sizeof(**src_data));
236
237 struct yac_basic_grid_data * src_grid_data =
238 yac_basic_grid_get_data(src_grid);
239
240 for (size_t collection_idx = 0; collection_idx < collection_size;
241 ++collection_idx) {
242 double * src_field =
243 xmalloc(src_grid_data->num_cells * sizeof(*src_field));
244 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
245 src_field[i] =
246 (src_grid_data->core_cell_mask[i])?
247 (double)(src_grid_data->cell_ids[i] + 1) +
248 (double)(collection_idx * 4):
249 -1.0;
250 src_data[collection_idx][0] = src_field;
251 }
252
253 yac_interpolation_execute_put(interpolation, src_data);
254
255 for (size_t collection_idx = 0; collection_idx < collection_size;
256 ++collection_idx) {
257 free(src_data[collection_idx][0]);
258 free(src_data[collection_idx]);
259 }
260 free(src_data);
261 }
262 if (is_target) {
263 double ref_tgt_field[1] = {2.5};
264
265 struct yac_basic_grid_data * tgt_grid_data =
266 yac_basic_grid_get_data(tgt_grid);
267
268 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
269 for (size_t collection_idx = 0; collection_idx < collection_size;
270 ++collection_idx) {
271 tgt_data[collection_idx] =
272 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
273 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
274 tgt_data[collection_idx][k] = -1;
275 }
276
277 yac_interpolation_execute_get(interpolation, tgt_data);
278
279 for (size_t collection_idx = 0; collection_idx < collection_size;
280 ++collection_idx) {
281 for (size_t j = 0, offset = collection_idx * 4;
282 j < tgt_grid_data->num_cells; ++j) {
283 if (tgt_grid_data->core_cell_mask[j] &&
284 (ref_tgt_field[tgt_grid_data->cell_ids[j]] != -1.0)) {
285 if (fabs((ref_tgt_field[tgt_grid_data->cell_ids[j]] +
286 (double)offset) - tgt_data[collection_idx][j]) > 1e-3)
287 PUT_ERR("wrong interpolation result");
288 } else {
289 if (tgt_data[collection_idx][j] != -1.0)
290 PUT_ERR("wrong interpolation result");
291 }
292 }
293 }
294
295 for (size_t collection_idx = 0; collection_idx < collection_size;
296 ++collection_idx)
297 free(tgt_data[collection_idx]);
298 free(tgt_data);
299 }
300
301 yac_interpolation_delete(interpolation);
302 }
303 }
304
305 yac_basic_grid_delete(src_grid);
306 yac_basic_grid_delete(tgt_grid);
308 yac_interp_grid_delete(interp_grid);
309 yac_dist_grid_pair_delete(grid_pair);
310
311 MPI_Comm_free(&split_comm);
312 MPI_Comm_free(&global_comm);
313}
314
315static void utest_test2() {
316
317 int comm_rank, comm_size;
318 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
319 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
320 MPI_Barrier(MPI_COMM_WORLD);
321
322 if (comm_size < 3) {
323 PUT_ERR("ERROR: too few processes");
324 xt_finalize();
325 MPI_Finalize();
326 exit(TEST_EXIT_CODE);
327 }
328
329 int is_active = comm_rank < 3;
330
331 MPI_Comm global_comm;
332 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
333
334 if (!is_active) {
335 MPI_Comm_free(&global_comm);
336 return;
337 }
338
339 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
340 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
341
342 int is_source = comm_rank >= 1;
343 int is_target = comm_rank < 1;
344
345 MPI_Comm split_comm;
346 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
347
348 MPI_Comm_rank(split_comm, &comm_rank);
349 MPI_Comm_size(split_comm, &comm_size);
350
351 struct yac_basic_grid * src_grid = NULL;
352 struct yac_basic_grid * tgt_grid = NULL;
353
354 if (is_source) {
355
356 // the global source grid is a 2x2 grid:
357 //
358 // 06--10--07--11--08
359 // | | |
360 // 06 02 08 03 09
361 // | | |
362 // 03--05--04--07--05
363 // | | |
364 // 01 00 03 01 04
365 // | | |
366 // 00--00--01--02--02
367
368 double coordinates_x[] = {-1,0,1};
369 double coordinates_y[] = {-1,0,1};
370 size_t const num_cells[2] = {2,2};
371 size_t local_start[2][2] = {{0,0},{1,0}};
372 size_t local_count[2][2] = {{1,2},{1,2}};
373 int with_halo = 1;
374 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
375 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
376
377 src_grid =
382 local_start[comm_rank], local_count[comm_rank], with_halo));
384
385 if (is_target) {
386
387 double coordinates_x[] = {-0.5,0.5};
388 double coordinates_y[] = {-0.5,0.5};
389 size_t const num_cells[2] = {1,1};
390 size_t local_start[1][2] = {{0,0}};
391 size_t local_count[1][2] = {{1,1}};
392 int with_halo = 1;
393 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
394 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
395
396 tgt_grid =
401 local_start[comm_rank], local_count[comm_rank], with_halo));
403
404 struct yac_dist_grid_pair * grid_pair =
405 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
406
407 struct yac_interp_field src_fields[] =
408 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
409 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
411 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
412
413 struct yac_interp_grid * interp_grid =
416
417 int order = 1;
418 int enforced_conserv = 1;
419 int partial_coverage = 0;
420 enum yac_interp_method_conserv_normalisation normalisation =
422
423 struct interp_method * method_stack[] = {
425 order, enforced_conserv, partial_coverage, normalisation), NULL};
426
427 struct yac_interp_weights * weights =
428 yac_interp_method_do_search(method_stack, interp_grid);
429
430 yac_interp_method_delete(method_stack);
431
432 enum yac_interp_weights_reorder_type reorder_type[2] =
434
435 for (size_t j = 0; j < 2; ++j) {
436 for (size_t collection_size = 1; collection_size < 4;
437 collection_size += 2) {
438
439 struct yac_interpolation * interpolation =
441 weights, reorder_type[j], collection_size,
442 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
443
444 // check generated interpolation
445 if (is_source) {
446 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
447 for (size_t i = 0; i < collection_size; ++i)
448 src_data[i] = xmalloc(1 * sizeof(**src_data));
449
450 struct yac_basic_grid_data * src_grid_data =
451 yac_basic_grid_get_data(src_grid);
452
453 for (size_t collection_idx = 0; collection_idx < collection_size;
454 ++collection_idx) {
455 src_data[collection_idx][0] =
456 xmalloc(src_grid_data->num_cells * sizeof(***src_data));
457 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
458 src_data[collection_idx][0][i] =
459 (src_grid_data->core_cell_mask[i])?
460 (double)(src_grid_data->cell_ids[i] + 1) +
461 (double)(collection_idx * 4):
462 -1.0;
463 }
464
465 yac_interpolation_execute_put(interpolation, src_data);
466
467 for (size_t collection_idx = 0; collection_idx < collection_size;
468 ++collection_idx) {
469 free(src_data[collection_idx][0]);
470 free(src_data[collection_idx]);
471 }
472 free(src_data);
473 }
474 if (is_target) {
475 double ref_tgt_field[1] = {2.5};
476
477 struct yac_basic_grid_data * tgt_grid_data =
478 yac_basic_grid_get_data(tgt_grid);
479
480 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
481 for (size_t collection_idx = 0; collection_idx < collection_size;
482 ++collection_idx) {
483 tgt_data[collection_idx] =
484 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
485 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
486 tgt_data[collection_idx][k] = -1;
487 }
488
489 yac_interpolation_execute_get(interpolation, tgt_data);
490
491 for (size_t collection_idx = 0; collection_idx < collection_size;
492 ++collection_idx) {
493 for (size_t j = 0, offset = collection_idx * 4;
494 j < tgt_grid_data->num_cells; ++j) {
495 if (tgt_grid_data->core_cell_mask[j] &&
496 (ref_tgt_field[tgt_grid_data->cell_ids[j]] != -1.0)) {
497 if (fabs((ref_tgt_field[tgt_grid_data->cell_ids[j]] +
498 (double)offset) - tgt_data[collection_idx][j]) > 1e-3)
499 PUT_ERR("wrong interpolation result");
500 } else {
501 if (tgt_data[collection_idx][j] != -1.0)
502 PUT_ERR("wrong interpolation result");
503 }
504 }
505 }
506
507 for (size_t collection_idx = 0; collection_idx < collection_size;
508 ++collection_idx)
509 free(tgt_data[collection_idx]);
510 free(tgt_data);
511 }
512
513 yac_interpolation_delete(interpolation);
514 }
515 }
516
517 yac_basic_grid_delete(src_grid);
518 yac_basic_grid_delete(tgt_grid);
520 yac_interp_grid_delete(interp_grid);
521 yac_dist_grid_pair_delete(grid_pair);
522
523 MPI_Comm_free(&split_comm);
524 MPI_Comm_free(&global_comm);
525}
526
527static void utest_test3() {
528
529 int comm_rank, comm_size;
530 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
531 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
532 MPI_Barrier(MPI_COMM_WORLD);
533
534 if (comm_size < 5) {
535 PUT_ERR("ERROR: too few processes");
536 xt_finalize();
537 MPI_Finalize();
538 exit(TEST_EXIT_CODE);
539 }
540
541 int is_active = comm_rank < 5;
542
543 MPI_Comm global_comm;
544 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
545
546 if (!is_active) {
547 MPI_Comm_free(&global_comm);
548 return;
549 }
550
551 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
552 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
553
554 int is_source = comm_rank >= 2;
555 int is_target = comm_rank < 2;
556
557 MPI_Comm split_comm;
558 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
559
560 MPI_Comm_rank(split_comm, &comm_rank);
561 MPI_Comm_size(split_comm, &comm_size);
562
563 struct yac_basic_grid * src_grid = NULL;
564 struct yac_basic_grid * tgt_grid = NULL;
565
566 if (is_source) {
567
568 // the global source grid is a 3x3 grid:
569 //
570 // 12--21--13--22--14--23--15
571 // | | | |
572 // 15 06 17 07 19 08 20
573 // | | | |
574 // 08--14--09--16--10--18--11
575 // | | | |
576 // 08 03 10 04 12 05 13
577 // | | | |
578 // 04--07--05--09--06--11--07
579 // | | | |
580 // 01 00 03 01 05 02 06
581 // | | | |
582 // 00--00--01--02--02--04--03
583
584 double coordinates_x[] = {-1.5,-0.5,0.5,1.5};
585 double coordinates_y[] = {-1.5,-0.5,0.5,1.5};
586 size_t const num_cells[2] = {3,3};
587 size_t local_start[3][2] = {{0,0},{1,0},{2,0}};
588 size_t local_count[3][2] = {{1,3},{1,3},{1,3}};
589 int with_halo = 1;
590 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
591 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
592
593 src_grid =
598 local_start[comm_rank], local_count[comm_rank], with_halo));
600
601 if (is_target) {
602
603 // the global target grid is a 2x2 grid:
604 //
605 // 06--10--07--11--08
606 // | | |
607 // 06 02 08 03 09
608 // | | |
609 // 03--05--04--07--05
610 // | | |
611 // 01 00 03 01 04
612 // | | |
613 // 00--00--01--02--02
614
615 double coordinates_x[] = {-1,0,1};
616 double coordinates_y[] = {-1,0,1};
617 size_t const num_cells[2] = {2,2};
618 size_t local_start[2][2] = {{0,0},{0,1}};
619 size_t local_count[2][2] = {{2,1},{2,1}};
620 int with_halo = 1;
621 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
622 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
623
624 tgt_grid =
629 local_start[comm_rank], local_count[comm_rank], with_halo));
631
632 struct yac_dist_grid_pair * grid_pair =
633 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
634
635 struct yac_interp_field src_fields[] =
636 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
637 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
639 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
640
641 struct yac_interp_grid * interp_grid =
644
645 int order = 1;
646 int enforced_conserv = 0;
647 int partial_coverage = 0;
648 enum yac_interp_method_conserv_normalisation normalisation =
650
651 struct interp_method * method_stack[] = {
653 order, enforced_conserv, partial_coverage, normalisation), NULL};
654
655 struct yac_interp_weights * weights =
656 yac_interp_method_do_search(method_stack, interp_grid);
657
658 yac_interp_method_delete(method_stack);
659
660 enum yac_interp_weights_reorder_type reorder_type[2] =
662
663 for (size_t j = 0; j < 2; ++j) {
664 for (size_t collection_size = 1; collection_size < 4;
665 collection_size += 2) {
666
667 struct yac_interpolation * interpolation =
669 weights, reorder_type[j], collection_size,
670 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
671
672 // check generated interpolation
673 if (is_source) {
674 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
675 for (size_t i = 0; i < collection_size; ++i)
676 src_data[i] = xmalloc(1 * sizeof(**src_data));
677
678 struct yac_basic_grid_data * src_grid_data =
679 yac_basic_grid_get_data(src_grid);
680
681 for (size_t collection_idx = 0; collection_idx < collection_size;
682 ++collection_idx) {
683 src_data[collection_idx][0] =
684 xmalloc(src_grid_data->num_cells * sizeof(***src_data));
685 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
686 src_data[collection_idx][0][i] =
687 (src_grid_data->core_cell_mask[i])?
688 (double)(src_grid_data->cell_ids[i] + 1) +
689 (double)(collection_idx * 9):
690 -1.0;
691 }
692
693 yac_interpolation_execute_put(interpolation, src_data);
694
695 for (size_t collection_idx = 0; collection_idx < collection_size;
696 ++collection_idx) {
697 free(src_data[collection_idx][0]);
698 free(src_data[collection_idx]);
699 }
700 free(src_data);
701 }
702 if (is_target) {
703 double ref_tgt_field[4] = {3,4,6,7};
704
705 struct yac_basic_grid_data * tgt_grid_data =
706 yac_basic_grid_get_data(tgt_grid);
707
708 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
709 for (size_t collection_idx = 0; collection_idx < collection_size;
710 ++collection_idx) {
711 tgt_data[collection_idx] =
712 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
713 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
714 tgt_data[collection_idx][k] = -1;
715 }
716
717 yac_interpolation_execute_get(interpolation, tgt_data);
718
719 for (size_t collection_idx = 0; collection_idx < collection_size;
720 ++collection_idx) {
721 for (size_t j = 0, offset = collection_idx * 9;
722 j < tgt_grid_data->num_cells; ++j) {
723 if (tgt_grid_data->core_cell_mask[j] &&
724 (ref_tgt_field[tgt_grid_data->cell_ids[j]] != -1.0)) {
725 if (fabs((ref_tgt_field[tgt_grid_data->cell_ids[j]] +
726 (double)offset) - tgt_data[collection_idx][j]) > 1e-3)
727 PUT_ERR("wrong interpolation result");
728 } else {
729 if (tgt_data[collection_idx][j] != -1.0)
730 PUT_ERR("wrong interpolation result");
731 }
732 }
733 }
734
735 for (size_t collection_idx = 0; collection_idx < collection_size;
736 ++collection_idx)
737 free(tgt_data[collection_idx]);
738 free(tgt_data);
739 }
740
741 yac_interpolation_delete(interpolation);
742 }
743 }
744
745 yac_basic_grid_delete(src_grid);
746 yac_basic_grid_delete(tgt_grid);
748 yac_interp_grid_delete(interp_grid);
749 yac_dist_grid_pair_delete(grid_pair);
750
751 MPI_Comm_free(&split_comm);
752 MPI_Comm_free(&global_comm);
753}
754
755static void utest_test4() {
756
757 int comm_rank, comm_size;
758 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
759 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
760 MPI_Barrier(MPI_COMM_WORLD);
761
762 if (comm_size < 8) {
763 PUT_ERR("ERROR: too few processes");
764 xt_finalize();
765 MPI_Finalize();
766 exit(TEST_EXIT_CODE);
767 }
768
769 int is_active = comm_rank < 5;
770
771 MPI_Comm global_comm;
772 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
773
774 if (!is_active) {
775 MPI_Comm_free(&global_comm);
776 return;
777 }
778
779 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
780 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
781
782 int is_source = comm_rank >= 2;
783 int is_target = comm_rank < 2;
784
785 MPI_Comm split_comm;
786 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
787
788 MPI_Comm_rank(split_comm, &comm_rank);
789 MPI_Comm_size(split_comm, &comm_size);
790
791 struct yac_basic_grid * src_grid = NULL;
792 struct yac_basic_grid * tgt_grid = NULL;
793
794 if (is_source) {
795
796 // the global source grid is a 4x4 grid:
797 //
798 // 20--36--21--37--22--38--23--39--24
799 // | | | | |
800 // 28 12 30 13 32 14 34 15 35
801 // | | | | |
802 // 15--27--16--29--17--31--18--33--19
803 // | | | | |
804 // 19 08 21 09 23 10 25 11 26
805 // | | | | |
806 // 10--18--11--20--12--22--13--24--14
807 // | | | | |
808 // 10 04 12 05 14 06 16 07 17
809 // | | | | |
810 // 05--09--06--11--07--13--08--15--09
811 // | | | | |
812 // 01 00 03 01 05 02 07 03 08
813 // | | | | |
814 // 00--00--01--02--02--04--03--06--04
815 //
816 // mask for the source grid (cells with "x" are masked)
817 //
818 // +---+---+---+---+
819 // | x | x | x | |
820 // +---+---+---+---+
821 // | x | x | | |
822 // +---+---+---+---+
823 // | x | | | |
824 // +---+---+---+---+
825 // | | | | |
826 // +---+---+---+---+
827
828 double coordinates_x[] = {0,1,2,3,4};
829 double coordinates_y[] = {0,1,2,3,4};
830 size_t const num_cells[2] = {4,4};
831 size_t local_start[3][2] = {{0,0},{0,1},{0,3}};
832 size_t local_count[3][2] = {{4,1},{4,2},{4,1}};
833 int with_halo = 1;
834 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
835 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
836
837 src_grid =
842 local_start[comm_rank], local_count[comm_rank], with_halo));
844
845 if (is_target) {
846 // the global target grid is a 3x3 grid:
847 //
848 // 12--21--13--22--14--23--15
849 // | | | |
850 // 15 06 17 07 19 08 20
851 // | | | |
852 // 08--14--09--16--10--18--11
853 // | | | |
854 // 08 03 10 04 12 05 13
855 // | | | |
856 // 04--07--05--09--06--11--07
857 // | | | |
858 // 01 00 03 01 05 02 06
859 // | | | |
860 // 00--00--01--02--02--04--03
861
862 double coordinates_x[] = {0.5,1.5,2.5,3.5};
863 double coordinates_y[] = {0.5,1.5,2.5,3.5};
864 size_t const num_cells[2] = {3,3};
865 size_t local_start[2][2] = {{0,0},{0,1}};
866 size_t local_count[2][2] = {{3,1},{3,2}};
867 int with_halo = 1;
868 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
869 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
870
871 tgt_grid =
876 local_start[comm_rank], local_count[comm_rank], with_halo));
878
879 int * src_cell_mask = NULL;
880 if (is_source) {
881 int global_src_mask [] = {1,1,1,1,
882 0,1,1,1,
883 0,0,1,1,
884 0,0,0,1};
885
886 struct yac_basic_grid_data * src_grid_data =
887 yac_basic_grid_get_data(src_grid);
888
889 src_cell_mask = xmalloc(src_grid_data->num_cells * sizeof(*src_cell_mask));
890 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
891 src_cell_mask[i] = global_src_mask[src_grid_data->cell_ids[i]];
892 yac_basic_grid_add_mask_nocpy(src_grid, YAC_LOC_CELL, src_cell_mask, NULL);
893 }
894
895 struct yac_dist_grid_pair * grid_pair =
896 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
897
898 struct yac_interp_field src_fields[] =
899 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = 0}};
900 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
902 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
903
904 struct yac_interp_grid * interp_grid =
907
909 normalisation[2] = {YAC_INTERP_CONSERV_DESTAREA,
911
912 for (int partial_coverage = 0; partial_coverage <= 1; ++partial_coverage) {
913 for (int norm_idx = 0; norm_idx <= 1; ++norm_idx) {
914
915 int order = 1;
916 int enforced_conserv = 0;
917
918 struct interp_method * method_stack[] = {
920 order, enforced_conserv, partial_coverage,
921 normalisation[norm_idx]), NULL};
922
923 struct yac_interp_weights * weights =
924 yac_interp_method_do_search(method_stack, interp_grid);
925
926 yac_interp_method_delete(method_stack);
927
928 enum yac_interp_weights_reorder_type reorder_type[2] =
930
931 for (size_t j = 0; j < 2; ++j) {
932
933 size_t collection_size = 1;
934 struct yac_interpolation * interpolation =
936 weights, reorder_type[j], collection_size,
937 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
938
939 // check generated interpolation
940 if (is_source) {
941 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
942 for (size_t i = 0; i < collection_size; ++i)
943 src_data[i] = xmalloc(1 * sizeof(**src_data));
944
945 struct yac_basic_grid_data * src_grid_data =
946 yac_basic_grid_get_data(src_grid);
947
948 for (size_t collection_idx = 0; collection_idx < collection_size;
949 ++collection_idx) {
950 src_data[collection_idx][0] =
951 xmalloc(src_grid_data->num_cells * sizeof(***src_data));
952 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
953 src_data[collection_idx][0][i] =
954 (src_grid_data->core_cell_mask[i])?
955 (double)(src_grid_data->cell_ids[i]) +
956 (double)(collection_idx * 16):
957 -1.0;
958 }
959
960 yac_interpolation_execute_put(interpolation, src_data);
961
962 for (size_t collection_idx = 0; collection_idx < collection_size;
963 ++collection_idx) {
964 free(src_data[collection_idx][0]);
965 free(src_data[collection_idx]);
966 }
967 free(src_data);
968 }
969 if (is_target) {
970 // [norm_idx][partial_coverage][tgt_idx]
971 double ref_tgt_field[2][2][9] =
972 {{{-1,3.5,4.5,-1,-1,8.5,-1,-1,-1},
973 {1.5,3.5,4.5,1.25,5.25,8.5,-1,2.5,9.0}},
974 {{-1,3.5,4.5,-1,-1,8.5,-1,-1,-1},
975 {2.0,3.5,4.5,5.0,7.0,8.5,-1,10.0,12.0}}};
976
977 struct yac_basic_grid_data * tgt_grid_data =
978 yac_basic_grid_get_data(tgt_grid);
979
980 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
981 for (size_t collection_idx = 0; collection_idx < collection_size;
982 ++collection_idx) {
983 tgt_data[collection_idx] =
984 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
985 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
986 tgt_data[collection_idx][k] = -1;
987 }
988
989 yac_interpolation_execute_get(interpolation, tgt_data);
990
991 for (size_t collection_idx = 0; collection_idx < collection_size;
992 ++collection_idx) {
993 for (size_t j = 0, offset = collection_idx * 16;
994 j < tgt_grid_data->num_cells; ++j) {
995 if (tgt_grid_data->core_cell_mask[j] &&
996 (ref_tgt_field[norm_idx]
997 [partial_coverage]
998 [tgt_grid_data->cell_ids[j]] != -1.0)) {
999 if (fabs((ref_tgt_field[norm_idx]
1000 [partial_coverage]
1001 [tgt_grid_data->cell_ids[j]] +
1002 (double)offset) -
1003 tgt_data[collection_idx][j]) > 1e-3)
1004 PUT_ERR("wrong interpolation result");
1005 } else {
1006 if (tgt_data[collection_idx][j] != -1.0)
1007 PUT_ERR("wrong interpolation result");
1008 }
1009 }
1010 }
1011
1012 for (size_t collection_idx = 0; collection_idx < collection_size;
1013 ++collection_idx)
1014 free(tgt_data[collection_idx]);
1015 free(tgt_data);
1016 }
1017
1018 yac_interpolation_delete(interpolation);
1019 }
1021 }
1022 }
1023
1024 yac_basic_grid_delete(src_grid);
1025 yac_basic_grid_delete(tgt_grid);
1026 yac_interp_grid_delete(interp_grid);
1027 yac_dist_grid_pair_delete(grid_pair);
1028
1029 MPI_Comm_free(&split_comm);
1030 MPI_Comm_free(&global_comm);
1031}
1032
1033static void utest_test5() {
1034
1035 int comm_rank, comm_size;
1036 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
1037 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
1038 MPI_Barrier(MPI_COMM_WORLD);
1039
1040 if (comm_size < 5) {
1041 PUT_ERR("ERROR: too few processes");
1042 xt_finalize();
1043 MPI_Finalize();
1044 exit(TEST_EXIT_CODE);
1045 }
1046
1047 int is_active = comm_rank < 5;
1048
1049 MPI_Comm global_comm;
1050 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
1051
1052 if (!is_active) {
1053 MPI_Comm_free(&global_comm);
1054 return;
1055 }
1056
1057 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
1058 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
1059
1060 int is_source = comm_rank >= 2;
1061 int is_target = comm_rank < 2;
1062
1063 MPI_Comm split_comm;
1064 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
1065
1066 MPI_Comm_rank(split_comm, &comm_rank);
1067 MPI_Comm_size(split_comm, &comm_size);
1068
1069 struct yac_basic_grid * src_grid = NULL;
1070 struct yac_basic_grid * tgt_grid = NULL;
1071
1072 if (is_source) {
1073
1074 // the global source grid is a 4x4 grid:
1075 //
1076 // 20--36--21--37--22--38--23--39--24
1077 // | | | | |
1078 // 28 12 30 13 32 14 34 15 35
1079 // | | | | |
1080 // 15--27--16--29--17--31--18--33--19
1081 // | | | | |
1082 // 19 08 21 09 23 10 25 11 26
1083 // | | | | |
1084 // 10--18--11--20--12--22--13--24--14
1085 // | | | | |
1086 // 10 04 12 05 14 06 16 07 17
1087 // | | | | |
1088 // 05--09--06--11--07--13--08--15--09
1089 // | | | | |
1090 // 01 00 03 01 05 02 07 03 08
1091 // | | | | |
1092 // 00--00--01--02--02--04--03--06--04
1093 //
1094 // mask for the source grid (cells with "x" are masked)
1095 //
1096 // +---+---+---+---+
1097 // | x | x | x | |
1098 // +---+---+---+---+
1099 // | x | x | | |
1100 // +---+---+---+---+
1101 // | x | | | |
1102 // +---+---+---+---+
1103 // | | | | |
1104 // +---+---+---+---+
1105
1106 double coordinates_x[] = {0,1,2,3,4};
1107 double coordinates_y[] = {0,1,2,3,4};
1108 size_t const num_cells[2] = {4,4};
1109 size_t local_start[3][2] = {{0,0},{0,1},{0,3}};
1110 size_t local_count[3][2] = {{4,1},{4,2},{4,1}};
1111 int with_halo = 1;
1112 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
1113 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
1114
1115 src_grid =
1120 local_start[comm_rank], local_count[comm_rank], with_halo));
1122
1123 if (is_target) {
1124 // the global target grid is a 3x3 grid:
1125 //
1126 // 12--21--13--22--14--23--15
1127 // | | | |
1128 // 15 06 17 07 19 08 20
1129 // | | | |
1130 // 08--14--09--16--10--18--11
1131 // | | | |
1132 // 08 03 10 04 12 05 13
1133 // | | | |
1134 // 04--07--05--09--06--11--07
1135 // | | | |
1136 // 01 00 03 01 05 02 06
1137 // | | | |
1138 // 00--00--01--02--02--04--03
1139 //
1140 // target mask:
1141 //
1142 // +---+---+---+
1143 // | x | x | x |
1144 // +---+---+---+
1145 // | x | x | x |
1146 // +---+---+---+
1147 // | | | |
1148 // +---+---+---+
1149
1150 double coordinates_x[] = {0.5,1.5,2.5,3.5};
1151 double coordinates_y[] = {0.5,1.5,2.5,3.5};
1152 size_t const num_cells[2] = {3,3};
1153 size_t local_start[2][2] = {{0,0},{0,1}};
1154 size_t local_count[2][2] = {{3,1},{3,2}};
1155 int with_halo = 1;
1156 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
1157 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
1158
1159 tgt_grid =
1164 local_start[comm_rank], local_count[comm_rank], with_halo));
1166
1167 int * src_cell_mask = NULL, * tgt_cell_mask = NULL;
1168 if (is_source) {
1169 int global_src_mask [] = {1,1,1,1,
1170 0,1,1,1,
1171 0,0,1,1,
1172 0,0,0,1};
1173
1174 struct yac_basic_grid_data * src_grid_data =
1175 yac_basic_grid_get_data(src_grid);
1176
1177 src_cell_mask = xmalloc(src_grid_data->num_cells * sizeof(*src_cell_mask));
1178 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
1179 src_cell_mask[i] = global_src_mask[src_grid_data->cell_ids[i]];
1180 yac_basic_grid_add_mask_nocpy(src_grid, YAC_LOC_CELL, src_cell_mask, NULL);
1181 }
1182 if (is_target) {
1183 int global_tgt_mask [] = {1,1,1,
1184 0,0,0,
1185 0,0,0};
1186 double coordinates_x [] = {1.0,2.0,3.0};
1187 double coordinates_y [] = {1.0,2.0,3.0};
1188
1189 struct yac_basic_grid_data * tgt_grid_data =
1190 yac_basic_grid_get_data(tgt_grid);
1191
1192 tgt_cell_mask = xmalloc(tgt_grid_data->num_cells * sizeof(*tgt_cell_mask));
1193 yac_coordinate_pointer tgt_cell_coords =
1194 xmalloc(tgt_grid_data->num_cells * sizeof(*tgt_cell_coords));
1195 for (size_t i = 0; i < tgt_grid_data->num_cells; ++i) {
1196 tgt_cell_mask[i] = global_tgt_mask[tgt_grid_data->cell_ids[i]];
1198 coordinates_x[tgt_grid_data->cell_ids[i]%3],
1199 coordinates_y[tgt_grid_data->cell_ids[i]/3],
1200 tgt_cell_coords[i]);
1201 }
1203 tgt_grid, YAC_LOC_CELL, tgt_cell_mask, NULL);
1205 tgt_grid, YAC_LOC_CELL, tgt_cell_coords);
1206 }
1207
1208 struct yac_dist_grid_pair * grid_pair =
1209 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
1210
1211 struct yac_interp_field src_fields[] =
1212 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = 0}};
1213 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
1215 {.location = YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = 0};
1216
1217 struct yac_interp_grid * interp_grid =
1220
1222 normalisation[2] = {YAC_INTERP_CONSERV_DESTAREA,
1224
1225 for (int partial_coverage = 0; partial_coverage <= 1; ++partial_coverage) {
1226 for (int norm_idx = 0; norm_idx <= 1; ++norm_idx) {
1227
1228 int order = 1;
1229 int enforced_conserv = 0;
1230
1231 struct interp_method * method_stack[] = {
1233 order, enforced_conserv, partial_coverage,
1234 normalisation[norm_idx]), NULL};
1235
1236 struct yac_interp_weights * weights =
1237 yac_interp_method_do_search(method_stack, interp_grid);
1238
1239 yac_interp_method_delete(method_stack);
1240
1241 enum yac_interp_weights_reorder_type reorder_type[2] =
1243
1244 for (size_t j = 0; j < 2; ++j) {
1245
1246 size_t collection_size = 1;
1247 struct yac_interpolation * interpolation =
1249 weights, reorder_type[j], collection_size,
1250 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
1251
1252 // check generated interpolation
1253 if (is_source) {
1254 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
1255 for (size_t i = 0; i < collection_size; ++i)
1256 src_data[i] = xmalloc(1 * sizeof(**src_data));
1257
1258 struct yac_basic_grid_data * src_grid_data =
1259 yac_basic_grid_get_data(src_grid);
1260
1261 for (size_t collection_idx = 0; collection_idx < collection_size;
1262 ++collection_idx) {
1263 src_data[collection_idx][0] =
1264 xmalloc(src_grid_data->num_cells * sizeof(***src_data));
1265 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
1266 src_data[collection_idx][0][i] =
1267 (src_grid_data->core_cell_mask[i])?
1268 (double)(src_grid_data->cell_ids[i]) +
1269 (double)(collection_idx * 16):
1270 -1.0;
1271 }
1272
1273 yac_interpolation_execute_put(interpolation, src_data);
1274
1275 for (size_t collection_idx = 0; collection_idx < collection_size;
1276 ++collection_idx) {
1277 free(src_data[collection_idx][0]);
1278 free(src_data[collection_idx]);
1279 }
1280 free(src_data);
1281 }
1282 if (is_target) {
1283 // [norm_idx][partial_coverage][tgt_idx]
1284 double ref_tgt_field[2][2][9] =
1285 {{{-1,3.5,4.5,-1,-1,-1,-1,-1,-1},
1286 {1.5,3.5,4.5,-1,-1,-1,-1,-1,-1}},
1287 {{-1,3.5,4.5,-1,-1,-1,-1,-1,-1},
1288 {2.0,3.5,4.5,-1,-1,-1,-1,-1,-1}}};
1289
1290 struct yac_basic_grid_data * tgt_grid_data =
1291 yac_basic_grid_get_data(tgt_grid);
1292
1293 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
1294 for (size_t collection_idx = 0; collection_idx < collection_size;
1295 ++collection_idx) {
1296 tgt_data[collection_idx] =
1297 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
1298 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
1299 tgt_data[collection_idx][k] = -1;
1300 }
1301
1302 yac_interpolation_execute_get(interpolation, tgt_data);
1303
1304 for (size_t collection_idx = 0; collection_idx < collection_size;
1305 ++collection_idx) {
1306 for (size_t j = 0, offset = collection_idx * 16;
1307 j < tgt_grid_data->num_cells; ++j) {
1308 if (tgt_grid_data->core_cell_mask[j] &&
1309 (ref_tgt_field[norm_idx]
1310 [partial_coverage]
1311 [tgt_grid_data->cell_ids[j]] != -1.0)) {
1312 if (fabs((ref_tgt_field[norm_idx]
1313 [partial_coverage]
1314 [tgt_grid_data->cell_ids[j]] +
1315 (double)offset) -
1316 tgt_data[collection_idx][j]) > 1e-3)
1317 PUT_ERR("wrong interpolation result");
1318 } else {
1319 if (tgt_data[collection_idx][j] != -1.0)
1320 PUT_ERR("wrong interpolation result");
1321 }
1322 }
1323 }
1324
1325 for (size_t collection_idx = 0; collection_idx < collection_size;
1326 ++collection_idx)
1327 free(tgt_data[collection_idx]);
1328 free(tgt_data);
1329 }
1330
1331 yac_interpolation_delete(interpolation);
1332 }
1334 }
1335 }
1336
1337 yac_basic_grid_delete(src_grid);
1338 yac_basic_grid_delete(tgt_grid);
1339 yac_interp_grid_delete(interp_grid);
1340 yac_dist_grid_pair_delete(grid_pair);
1341
1342 MPI_Comm_free(&split_comm);
1343 MPI_Comm_free(&global_comm);
1344}
1345
1346static void utest_test6() {
1347
1348 int comm_rank, comm_size;
1349 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
1350 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
1351 MPI_Barrier(MPI_COMM_WORLD);
1352
1353 if (comm_size < 2) {
1354 PUT_ERR("ERROR: too few processes");
1355 xt_finalize();
1356 MPI_Finalize();
1357 exit(TEST_EXIT_CODE);
1358 }
1359
1360 int is_active = comm_rank < 2;
1361
1362 MPI_Comm global_comm;
1363 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
1364
1365 if (!is_active) {
1366 MPI_Comm_free(&global_comm);
1367 return;
1368 }
1369
1370 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
1371 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
1372
1373 int is_source = comm_rank >= 1;
1374 int is_target = comm_rank < 1;
1375
1376 MPI_Comm split_comm;
1377 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
1378
1379 MPI_Comm_rank(split_comm, &comm_rank);
1380 MPI_Comm_size(split_comm, &comm_size);
1381
1382 struct yac_basic_grid * src_grid = NULL;
1383 struct yac_basic_grid * tgt_grid = NULL;
1384
1385 if (is_source) {
1386
1387 // the global source grid is a 3x3 grid:
1388 //
1389 // 12--21--13--22--14--23--15
1390 // | | | |
1391 // 15 06 17 07 19 08 20
1392 // | | | |
1393 // 08--14--09--16--10--18--11
1394 // | | | |
1395 // 08 03 10 04 12 05 13
1396 // | | | |
1397 // 04--07--05--09--06--11--07
1398 // | | | |
1399 // 01 00 03 01 05 02 06
1400 // | | | |
1401 // 00--00--01--02--02--04--03
1402
1403 double coordinates_x[] = {-1.5,-0.5,0.5,1.5};
1404 double coordinates_y[] = {-1.5,-0.5,0.5,1.5};
1405 size_t const num_cells[2] = {3,3};
1406 size_t local_start[1][2] = {{0,0}};
1407 size_t local_count[1][2] = {{3,3}};
1408 int with_halo = 1;
1409 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
1410 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
1411
1412 src_grid =
1417 local_start[comm_rank], local_count[comm_rank], with_halo));
1419
1420 if (is_target) {
1421
1422 // the global target grid is a 2x2 grid:
1423 //
1424 // 06--10--07--11--08
1425 // | | |
1426 // 06 02 08 03 09
1427 // | | |
1428 // 03--05--04--07--05
1429 // | | |
1430 // 01 00 03 01 04
1431 // | | |
1432 // 00--00--01--02--02
1433
1434 double coordinates_x[] = {-0.5,0,0.5};
1435 double coordinates_y[] = {-0.5,0,0.5};
1436 size_t const num_cells[2] = {2,2};
1437 size_t local_start[1][2] = {{0,0}};
1438 size_t local_count[1][2] = {{2,2}};
1439 int with_halo = 1;
1440 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
1441 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
1442
1443 tgt_grid =
1448 local_start[comm_rank], local_count[comm_rank], with_halo));
1450
1451 struct yac_dist_grid_pair * grid_pair =
1452 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
1453
1454 struct yac_interp_field src_fields[] =
1455 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
1456 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
1458 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
1459
1460 struct yac_interp_grid * interp_grid =
1463
1464 int order = 2;
1465 int enforced_conserv = 0;
1466 int partial_coverage = 0;
1467 enum yac_interp_method_conserv_normalisation normalisation =
1469
1470 struct interp_method * method_stack[] = {
1472 order, enforced_conserv, partial_coverage, normalisation), NULL};
1473
1474 struct yac_interp_weights * weights =
1475 yac_interp_method_do_search(method_stack, interp_grid);
1476
1477 yac_interp_method_delete(method_stack);
1478
1479 enum yac_interp_weights_reorder_type reorder_type[2] =
1481
1482#define NUM_TESTS (4)
1483
1484 for (size_t t = 0; t < NUM_TESTS; ++t) {
1485 for (size_t j = 0; j < 2; ++j) {
1486
1487 size_t collection_size = 1;
1488
1489 struct yac_interpolation * interpolation =
1491 weights, reorder_type[j], collection_size,
1492 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
1493
1494 // check generated interpolation
1495 if (is_source) {
1496 double global_field_data[NUM_TESTS][9] = {
1497 {1,1,1, 1,1,1, 1,1,1},
1498 {0,0,0, 1,1,1, 2,2,2},
1499 {0,1,2, 0,1,2, 0,1,2},
1500 {0,1,2, 1,2,3, 2,3,4}};
1501
1502 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
1503 for (size_t i = 0; i < collection_size; ++i)
1504 src_data[i] = xmalloc(1 * sizeof(**src_data));
1505
1506 struct yac_basic_grid_data * src_grid_data =
1507 yac_basic_grid_get_data(src_grid);
1508
1509 for (size_t collection_idx = 0; collection_idx < collection_size;
1510 ++collection_idx) {
1511 double * src_field =
1512 xmalloc(src_grid_data->num_cells * sizeof(*src_field));
1513 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
1514 src_field[i] =
1515 (src_grid_data->core_cell_mask[i])?
1516 global_field_data[t][src_grid_data->cell_ids[i]]:-1.0;
1517 src_data[collection_idx][0] = src_field;
1518 }
1519
1520 yac_interpolation_execute_put(interpolation, src_data);
1521
1522 for (size_t collection_idx = 0; collection_idx < collection_size;
1523 ++collection_idx) {
1524 free(src_data[collection_idx][0]);
1525 free(src_data[collection_idx]);
1526 }
1527 free(src_data);
1528 }
1529 if (is_target) {
1530 double ref_tgt_field[NUM_TESTS][4] = {
1531 {1,1,
1532 1,1},
1533 {0.75,0.75,
1534 1.25,1.25},
1535 {0.75,1.25,
1536 0.75,1.25},
1537 {1.5,2.0,
1538 2.0,2.5}};
1539
1540 struct yac_basic_grid_data * tgt_grid_data =
1541 yac_basic_grid_get_data(tgt_grid);
1542
1543 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
1544 for (size_t collection_idx = 0; collection_idx < collection_size;
1545 ++collection_idx) {
1546 tgt_data[collection_idx] =
1547 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
1548 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
1549 tgt_data[collection_idx][k] = -1;
1550 }
1551
1552 yac_interpolation_execute_get(interpolation, tgt_data);
1553
1554 for (size_t collection_idx = 0; collection_idx < collection_size;
1555 ++collection_idx) {
1556 for (size_t j = 0; j < tgt_grid_data->num_cells; ++j) {
1557 if (tgt_grid_data->core_cell_mask[j] &&
1558 (ref_tgt_field[t][tgt_grid_data->cell_ids[j]] != -1.0)) {
1559 if (fabs((ref_tgt_field[t][tgt_grid_data->cell_ids[j]]) -
1560 tgt_data[collection_idx][j]) > 1e-3)
1561 PUT_ERR("wrong interpolation result");
1562 } else {
1563 if (tgt_data[collection_idx][j] != -1.0)
1564 PUT_ERR("wrong interpolation result");
1565 }
1566 }
1567 }
1568
1569 for (size_t collection_idx = 0; collection_idx < collection_size;
1570 ++collection_idx)
1571 free(tgt_data[collection_idx]);
1572 free(tgt_data);
1573 }
1574
1575 yac_interpolation_delete(interpolation);
1576 }
1577 }
1578#undef NUM_TESTS
1579
1580 yac_basic_grid_delete(src_grid);
1581 yac_basic_grid_delete(tgt_grid);
1583 yac_interp_grid_delete(interp_grid);
1584 yac_dist_grid_pair_delete(grid_pair);
1585
1586 MPI_Comm_free(&split_comm);
1587 MPI_Comm_free(&global_comm);
1588}
1589
1590static void utest_test7() {
1591
1592 int comm_rank, comm_size;
1593 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
1594 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
1595 MPI_Barrier(MPI_COMM_WORLD);
1596
1597 if (comm_size < 4) {
1598 PUT_ERR("ERROR: too few processes");
1599 xt_finalize();
1600 MPI_Finalize();
1601 exit(TEST_EXIT_CODE);
1602 }
1603
1604 int is_active = comm_rank < 4;
1605
1606 MPI_Comm global_comm;
1607 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
1608
1609 if (!is_active) {
1610 MPI_Comm_free(&global_comm);
1611 return;
1612 }
1613
1614 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
1615 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
1616
1617 int is_source = comm_rank >= 1;
1618 int is_target = comm_rank < 1;
1619
1620 MPI_Comm split_comm;
1621 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
1622
1623 MPI_Comm_rank(split_comm, &comm_rank);
1624 MPI_Comm_size(split_comm, &comm_size);
1625
1626 struct yac_basic_grid * src_grid = NULL;
1627 struct yac_basic_grid * tgt_grid = NULL;
1628
1629 if (is_source) {
1630
1631 // the global source grid is a 3x3 grid:
1632 //
1633 // 12--21--13--22--14--23--15
1634 // | | | |
1635 // 15 06 17 07 19 08 20
1636 // | | | |
1637 // 08--14--09--16--10--18--11
1638 // | | | |
1639 // 08 03 10 04 12 05 13
1640 // | | | |
1641 // 04--07--05--09--06--11--07
1642 // | | | |
1643 // 01 00 03 01 05 02 06
1644 // | | | |
1645 // 00--00--01--02--02--04--03
1646
1647 double coordinates_x[] = {-1.5,-0.5,0.5,1.5};
1648 double coordinates_y[] = {-1.5,-0.5,0.5,1.5};
1649 size_t const num_cells[2] = {3,3};
1650 size_t local_start[3][2] = {{0,0},{0,1},{0,2}};
1651 size_t local_count[3][2] = {{3,1},{3,1},{3,1}};
1652 int with_halo = 1;
1653 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
1654 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
1655
1656 src_grid =
1661 local_start[comm_rank], local_count[comm_rank], with_halo));
1663
1664 if (is_target) {
1665
1666 // the global target grid is a 2x2 grid:
1667 //
1668 // 06--10--07--11--08
1669 // | | |
1670 // 06 02 08 03 09
1671 // | | |
1672 // 03--05--04--07--05
1673 // | | |
1674 // 01 00 03 01 04
1675 // | | |
1676 // 00--00--01--02--02
1677
1678 double coordinates_x[] = {-0.5,0,0.5};
1679 double coordinates_y[] = {-0.5,0,0.5};
1680 size_t const num_cells[2] = {2,2};
1681 size_t local_start[1][2] = {{0,0}};
1682 size_t local_count[1][2] = {{2,2}};
1683 int with_halo = 1;
1684 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
1685 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
1686
1687 tgt_grid =
1692 local_start[comm_rank], local_count[comm_rank], with_halo));
1694
1695 struct yac_dist_grid_pair * grid_pair =
1696 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
1697
1698 struct yac_interp_field src_fields[] =
1699 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
1700 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
1702 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
1703
1704 struct yac_interp_grid * interp_grid =
1707
1708 int order = 2;
1709 int enforced_conserv = 0;
1710 int partial_coverage = 0;
1711 enum yac_interp_method_conserv_normalisation normalisation =
1713
1714 struct interp_method * method_stack[] = {
1716 order, enforced_conserv, partial_coverage, normalisation), NULL};
1717
1718 struct yac_interp_weights * weights =
1719 yac_interp_method_do_search(method_stack, interp_grid);
1720
1721 yac_interp_method_delete(method_stack);
1722
1723 enum yac_interp_weights_reorder_type reorder_type[2] =
1725
1726#define NUM_TESTS (4)
1727
1728 for (size_t t = 0; t < NUM_TESTS; ++t) {
1729 for (size_t j = 0; j < 2; ++j) {
1730
1731 size_t collection_size = 1;
1732
1733 struct yac_interpolation * interpolation =
1735 weights, reorder_type[j], collection_size,
1736 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
1737
1738 // check generated interpolation
1739 if (is_source) {
1740 double global_field_data[NUM_TESTS][9] = {
1741 {1,1,1, 1,1,1, 1,1,1},
1742 {0,0,0, 1,1,1, 2,2,2},
1743 {0,1,2, 0,1,2, 0,1,2},
1744 {0,1,2, 1,2,3, 2,3,4}};
1745 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
1746 for (size_t i = 0; i < collection_size; ++i)
1747 src_data[i] = xmalloc(1 * sizeof(**src_data));
1748
1749 struct yac_basic_grid_data * src_grid_data =
1750 yac_basic_grid_get_data(src_grid);
1751
1752 for (size_t collection_idx = 0; collection_idx < collection_size;
1753 ++collection_idx) {
1754 src_data[collection_idx][0] =
1755 xmalloc(src_grid_data->num_cells * sizeof(***src_data));
1756 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
1757 src_data[collection_idx][0][i] =
1758 (src_grid_data->core_cell_mask[i])?
1759 global_field_data[t][src_grid_data->cell_ids[i]]:-1.0;
1760 }
1761
1762 yac_interpolation_execute_put(interpolation, src_data);
1763
1764 for (size_t collection_idx = 0; collection_idx < collection_size;
1765 ++collection_idx) {
1766 free(src_data[collection_idx][0]);
1767 free(src_data[collection_idx]);
1768 }
1769 free(src_data);
1770 }
1771 if (is_target) {
1772 double ref_tgt_field[NUM_TESTS][4] = {
1773 {1,1,
1774 1,1},
1775 {0.75,0.75,
1776 1.25,1.25},
1777 {0.75,1.25,
1778 0.75,1.25},
1779 {1.5,2.0,
1780 2.0,2.5}};
1781
1782 struct yac_basic_grid_data * tgt_grid_data =
1783 yac_basic_grid_get_data(tgt_grid);
1784
1785 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
1786 for (size_t collection_idx = 0; collection_idx < collection_size;
1787 ++collection_idx) {
1788 tgt_data[collection_idx] =
1789 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
1790 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
1791 tgt_data[collection_idx][k] = -1;
1792 }
1793
1794 yac_interpolation_execute_get(interpolation, tgt_data);
1795
1796 for (size_t collection_idx = 0; collection_idx < collection_size;
1797 ++collection_idx) {
1798 for (size_t j = 0; j < tgt_grid_data->num_cells; ++j) {
1799 if (tgt_grid_data->core_cell_mask[j] &&
1800 (ref_tgt_field[t][tgt_grid_data->cell_ids[j]] != -1.0)) {
1801 if (fabs((ref_tgt_field[t][tgt_grid_data->cell_ids[j]]) -
1802 tgt_data[collection_idx][j]) > 1e-3)
1803 PUT_ERR("wrong interpolation result");
1804 } else {
1805 if (tgt_data[collection_idx][j] != -1.0)
1806 PUT_ERR("wrong interpolation result");
1807 }
1808 }
1809 }
1810
1811 for (size_t collection_idx = 0; collection_idx < collection_size;
1812 ++collection_idx)
1813 free(tgt_data[collection_idx]);
1814 free(tgt_data);
1815 }
1816
1817 yac_interpolation_delete(interpolation);
1818 }
1819 }
1820#undef NUM_TESTS
1821
1822 yac_basic_grid_delete(src_grid);
1823 yac_basic_grid_delete(tgt_grid);
1825 yac_interp_grid_delete(interp_grid);
1826 yac_dist_grid_pair_delete(grid_pair);
1827
1828 MPI_Comm_free(&split_comm);
1829 MPI_Comm_free(&global_comm);
1830}
1831
1832static void utest_test8() {
1833
1834 int comm_rank, comm_size;
1835 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
1836 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
1837 MPI_Barrier(MPI_COMM_WORLD);
1838
1839 if (comm_size < 4) {
1840 PUT_ERR("ERROR: too few processes");
1841 xt_finalize();
1842 MPI_Finalize();
1843 exit(TEST_EXIT_CODE);
1844 }
1845
1846 int is_active = comm_rank < 4;
1847
1848 MPI_Comm global_comm;
1849 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
1850
1851 if (!is_active) {
1852 MPI_Comm_free(&global_comm);
1853 return;
1854 }
1855
1856 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
1857 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
1858
1859 int is_source = comm_rank >= 1;
1860 int is_target = comm_rank < 1;
1861
1862 MPI_Comm split_comm;
1863 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
1864
1865 MPI_Comm_rank(split_comm, &comm_rank);
1866 MPI_Comm_size(split_comm, &comm_size);
1867
1868 struct yac_basic_grid * src_grid = NULL;
1869 struct yac_basic_grid * tgt_grid = NULL;
1870
1871 if (is_source) {
1872
1873 // the global source grid is a 5x5 grid:
1874 //
1875 // 30--55--31--56--32--57--33-58--34-59--35
1876 // | | | | | |
1877 // 45 20 47 21 49 22 51 23 53 24 54
1878 // | | | | | |
1879 // 24--44--25--46--26--48--27-50--28-52--29
1880 // | | | | | |
1881 // 34 15 36 16 38 17 40 18 42 19 43
1882 // | | | | | |
1883 // 18--33--19--35--20--37--21-39--22-41--23
1884 // | | | | | |
1885 // 23 10 25 11 27 12 29 13 31 14 32
1886 // | | | | | |
1887 // 12--22--13--24--14--26--15-28--16-30--17
1888 // | | | | | |
1889 // 12 05 14 06 16 07 18 08 20 09 21
1890 // | | | | | |
1891 // 06--11--07--13--08--15--09-17--10-19--11
1892 // | | | | | |
1893 // 01 00 03 01 05 02 07 03 09 04 10
1894 // | | | | | |
1895 // 00--00--01--02--02--04--03-06--04-08--05
1896
1897 double coordinates_x[] = {-2.5,-1.5,-0.5,0.5,1.5,2.5};
1898 double coordinates_y[] = {-2.5,-1.5,-0.5,0.5,1.5,2.5};
1899 size_t const num_cells[2] = {5,5};
1900 size_t local_start[3][2] = {{0,0},{0,2},{3,2}};
1901 size_t local_count[3][2] = {{5,2},{3,3},{2,3}};
1902 int with_halo = 1;
1903 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
1904 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
1905
1906 src_grid =
1911 local_start[comm_rank], local_count[comm_rank], with_halo));
1913
1914 if (is_target) {
1915
1916 // the global target grid is a 5x5 grid and is slightly shifted to the
1917 // source grid
1918
1919 double coordinates_x[] = {-2,-1,0,1,2,3};
1920 double coordinates_y[] = {-3,-2,-1,0,1,2};
1921 size_t const num_cells[2] = {5,5};
1922 size_t local_start[1][2] = {{0,0}};
1923 size_t local_count[1][2] = {{5,5}};
1924 int with_halo = 1;
1925 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
1926 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
1927
1928 tgt_grid =
1933 local_start[comm_rank], local_count[comm_rank], with_halo));
1935
1936 struct yac_dist_grid_pair * grid_pair =
1937 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
1938
1939 struct yac_interp_field src_fields[] =
1940 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
1941 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
1943 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
1944
1945 struct yac_interp_grid * interp_grid =
1948
1949 int order = 2;
1950 int enforced_conserv = 0;
1951 int partial_coverage = 1;
1952 enum yac_interp_method_conserv_normalisation normalisation =
1954
1955 struct interp_method * method_stack[] = {
1957 order, enforced_conserv, partial_coverage, normalisation), NULL};
1958
1959 struct yac_interp_weights * weights =
1960 yac_interp_method_do_search(method_stack, interp_grid);
1961
1962 yac_interp_method_delete(method_stack);
1963
1964 enum yac_interp_weights_reorder_type reorder_type[2] =
1966
1967#define NUM_TESTS (4)
1968
1969 for (size_t t = 0; t < NUM_TESTS; ++t) {
1970 for (size_t j = 0; j < 2; ++j) {
1971
1972 size_t collection_size = 1;
1973
1974 struct yac_interpolation * interpolation =
1976 weights, reorder_type[j], collection_size,
1977 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
1978
1979 double global_src_field_data[NUM_TESTS][25] =
1980 {{1,1,1,1,1,
1981 1,1,1,1,1,
1982 1,1,1,1,1,
1983 1,1,1,1,1,
1984 1,1,1,1,1},
1985 {0.00,0.25,0.50,0.75,1.00,
1986 0.00,0.25,0.50,0.75,1.00,
1987 0.00,0.25,0.50,0.75,1.00,
1988 0.00,0.25,0.50,0.75,1.00,
1989 0.00,0.25,0.50,0.75,1.00},
1990 {0.00,0.00,0.00,0.00,0.00,
1991 0.25,0.25,0.25,0.25,0.25,
1992 0.50,0.50,0.50,0.50,0.50,
1993 0.75,0.75,0.75,0.75,0.75,
1994 1.00,1.00,1.00,1.00,1.00},
1995 {0.00,0.25,0.50,0.75,1.00,
1996 0.25,0.50,0.75,1.00,1.25,
1997 0.50,0.75,1.00,1.25,1.50,
1998 0.75,1.00,1.25,1.50,1.75,
1999 1.00,1.25,1.50,1.75,2.00}};
2000
2001 size_t src_neighs[25][4] =
2002 {{0,1,5,0},{1,2,6,0},{2,3,7,1},{3,4,8,2},{4,4,9,3},
2003 {0,6,10,5},{1,7,11,5},{2,8,12,6},{3,9,13,7},{4,9,14,8},
2004 {5,11,15,10},{6,12,16,10},{7,13,17,11},{8,14,18,12},{9,14,19,13},
2005 {10,16,20,15},{11,17,21,15},{12,18,22,16},{13,19,23,17},{14,19,24,18},
2006 {15,21,20,20},{16,22,21,20},{17,23,22,21},{18,24,23,22},{19,24,24,23}};
2007 double src_gradient_weights_signs[4][4] =
2008 {{-1.0,1.0,1.0,-1.0},{-1.0,-1.0,1.0,1.0},
2009 {1.0,1.0,-1.0,-1.0},{1.0,-1.0,-1.0,1.0}};
2010 double src_gradient_weights[25][4] =
2011 {{0.25,0,0.25,0},{0.25,0.125,0.25,0.125},{0.25,0.125,0.25,0.125},
2012 {0.25,0.125,0.25,0.125},{0.25,0.25,0.25,0.25},
2013 {0.125,0,0.125,0},{0.125,0.125,0.125,0.125},{0.125,0.125,0.125,0.125},
2014 {0.125,0.125,0.125,0.125},{0.125,0.25,0.125,0.25},
2015 {0.125,0,0.125,0},{0.125,0.125,0.125,0.125},{0.125,0.125,0.125,0.125},
2016 {0.125,0.125,0.125,0.125},{0.125,0.25,0.125,0.25},
2017 {0.125,0,0.125,0},{0.125,0.125,0.125,0.125},{0.125,0.125,0.125,0.125},
2018 {0.125,0.125,0.125,0.125},{0.125,0.25,0.125,0.25},
2019 {0,0,0,0},{0,0.125,0,0.125},{0,0.125,0,0.125},
2020 {0,0.125,0,0.125},{0,0.25,0,0.25}};
2021 size_t tgt_to_src[25][4] =
2022 {{SIZE_MAX,SIZE_MAX,0,1}, {SIZE_MAX,SIZE_MAX,1,2},
2023 {SIZE_MAX,SIZE_MAX,2,3},{SIZE_MAX,SIZE_MAX,3,4},
2024 {SIZE_MAX,SIZE_MAX,4,SIZE_MAX},
2025 {0,1,5,6},{1,2,6,7},{2,3,7,8},{3,4,8,9},{4,SIZE_MAX,9,SIZE_MAX},
2026 {5,6,10,11},{6,7,11,12},{7,8,12,13},{8,9,13,14},
2027 {9,SIZE_MAX,14,SIZE_MAX},
2028 {10,11,15,16},{11,12,16,17},{12,13,17,18},{13,14,18,19},
2029 {14,SIZE_MAX,19,SIZE_MAX},
2030 {15,16,20,21},{16,17,21,22},{17,18,22,23},{18,19,23,24},
2031 {19,SIZE_MAX,24,SIZE_MAX}};
2032
2033 // check generated interpolation
2034 if (is_source) {
2035 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
2036 for (size_t i = 0; i < collection_size; ++i)
2037 src_data[i] = xmalloc(1 * sizeof(**src_data));
2038
2039 struct yac_basic_grid_data * src_grid_data =
2040 yac_basic_grid_get_data(src_grid);
2041
2042 for (size_t collection_idx = 0; collection_idx < collection_size;
2043 ++collection_idx) {
2044 src_data[collection_idx][0] =
2045 xmalloc(src_grid_data->num_cells * sizeof(***src_data));
2046 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
2047 src_data[collection_idx][0][i] =
2048 (src_grid_data->core_cell_mask[i])?
2049 global_src_field_data[t][src_grid_data->cell_ids[i]]:-1.0;
2050 }
2051
2052 yac_interpolation_execute_put(interpolation, src_data);
2053
2054 for (size_t collection_idx = 0; collection_idx < collection_size;
2055 ++collection_idx) {
2056 free(src_data[collection_idx][0]);
2057 free(src_data[collection_idx]);
2058 }
2059 free(src_data);
2060 }
2061 if (is_target) {
2062
2063 double ref_tgt_field[25];
2064
2065 for (size_t i = 0; i < 25; ++i) {
2066 double tgt_field_value = 0.0;
2067 for (size_t j = 0; j < 4; ++j) {
2068 size_t src_global_id = tgt_to_src[i][j];
2069 if (src_global_id != SIZE_MAX) {
2070 tgt_field_value +=
2071 global_src_field_data[t][src_global_id];
2072 for (size_t k = 0; k < 4; ++k)
2073 tgt_field_value +=
2074 global_src_field_data[t][src_neighs[src_global_id][k]] *
2075 src_gradient_weights_signs[j][k] *
2076 src_gradient_weights[src_global_id][k];
2077 }
2078 }
2079 ref_tgt_field[i] = tgt_field_value / 4.0;
2080 }
2081
2082 struct yac_basic_grid_data * tgt_grid_data =
2083 yac_basic_grid_get_data(tgt_grid);
2084
2085 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
2086 for (size_t collection_idx = 0; collection_idx < collection_size;
2087 ++collection_idx) {
2088 tgt_data[collection_idx] =
2089 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
2090 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
2091 tgt_data[collection_idx][k] = -1;
2092 }
2093
2094 yac_interpolation_execute_get(interpolation, tgt_data);
2095
2096 for (size_t collection_idx = 0; collection_idx < collection_size;
2097 ++collection_idx) {
2098 for (size_t j = 0; j < tgt_grid_data->num_cells; ++j) {
2099 if (tgt_grid_data->core_cell_mask[j]) {
2100 if (fabs((ref_tgt_field[tgt_grid_data->cell_ids[j]]) -
2101 tgt_data[collection_idx][j]) > 1e-3)
2102 PUT_ERR("wrong interpolation result");
2103 } else {
2104 if (tgt_data[collection_idx][j] != -1.0)
2105 PUT_ERR("wrong interpolation result");
2106 }
2107 }
2108 }
2109
2110 for (size_t collection_idx = 0; collection_idx < collection_size;
2111 ++collection_idx)
2112 free(tgt_data[collection_idx]);
2113 free(tgt_data);
2114 }
2115
2116 yac_interpolation_delete(interpolation);
2117 }
2118 }
2119#undef NUM_TESTS
2120
2121 yac_basic_grid_delete(src_grid);
2122 yac_basic_grid_delete(tgt_grid);
2124 yac_interp_grid_delete(interp_grid);
2125 yac_dist_grid_pair_delete(grid_pair);
2126
2127 MPI_Comm_free(&split_comm);
2128 MPI_Comm_free(&global_comm);
2129}
2130
2131static void utest_test9() {
2132
2133 int comm_rank, comm_size;
2134 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
2135 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
2136 MPI_Barrier(MPI_COMM_WORLD);
2137
2138 if (comm_size < 8) {
2139 PUT_ERR("ERROR: too few processes");
2140 xt_finalize();
2141 MPI_Finalize();
2142 exit(TEST_EXIT_CODE);
2143 }
2144
2145 int is_active = comm_rank < 8;
2146
2147 MPI_Comm global_comm;
2148 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
2149
2150 if (!is_active) {
2151 MPI_Comm_free(&global_comm);
2152 return;
2153 }
2154
2155 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
2156 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
2157
2158 int is_source = comm_rank >= 4;
2159 int is_target = comm_rank < 4;
2160
2161 MPI_Comm split_comm;
2162 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
2163
2164 MPI_Comm_rank(split_comm, &comm_rank);
2165 MPI_Comm_size(split_comm, &comm_size);
2166
2167 struct yac_basic_grid * src_grid = NULL;
2168 struct yac_basic_grid * tgt_grid = NULL;
2169
2170 if (is_source) {
2171
2172 // corner and cell ids for a 6 x 5 grid
2173 //
2174 // 35-----36-----37-----38-----39-----40-----41
2175 // | | | | | | |
2176 // | 24 | 25 | 26 | 27 | 28 | 29 |
2177 // | | | | | | |
2178 // 28-----29-----30-----31-----32-----33-----34
2179 // | | | | | | |
2180 // | 18 | 19 | 20 | 21 | 22 | 23 |
2181 // | | | | | | |
2182 // 21-----22-----23-----24-----25-----26-----27
2183 // | | | | | | |
2184 // | 12 | 13 | 14 | 15 | 16 | 17 |
2185 // | | | | | | |
2186 // 14-----15-----16-----17-----18-----19-----20
2187 // | | | | | | |
2188 // | 06 | 07 | 08 | 09 | 10 | 11 |
2189 // | | | | | | |
2190 // 07-----08-----09-----10-----11-----12-----13
2191 // | | | | | | |
2192 // | 00 | 01 | 02 | 03 | 04 | 05 |
2193 // | | | | | | |
2194 // 00-----01-----02-----03-----04-----05-----06
2195 //
2196 // the grid is distributed among the processes as follows:
2197 // (index == process)
2198 //
2199 // +---+---+---+---+---+---+
2200 // | 2 | 2 | 2 | 3 | 3 | 3 |
2201 // +---+---+---+---+---+---+
2202 // | 2 | 2 | 2 | 3 | 3 | 3 |
2203 // +---+---+---+---+---+---+
2204 // | 2 | 2 | 2 | 3 | 3 | 3 |
2205 // +---+---+---+---+---+---+
2206 // | 0 | 0 | 0 | 1 | 1 | 1 |
2207 // +---+---+---+---+---+---+
2208 // | 0 | 0 | 0 | 1 | 1 | 1 |
2209 // +---+---+---+---+---+---+
2210
2211 double coordinates_x[] = {-3,-2,-1,0,1,2,3};
2212 double coordinates_y[] = {-3,-2,-1,0,1,2};
2213 size_t const num_cells[2] = {6,5};
2214 size_t local_start[4][2] = {{0,0},{3,0},{0,2},{3,2}};
2215 size_t local_count[4][2] = {{3,2},{3,2},{3,3},{3,3}};
2216 int with_halo = 1;
2217 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
2218 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
2219
2220 src_grid =
2225 local_start[comm_rank], local_count[comm_rank], with_halo));
2227
2228 if (is_target) {
2229 // corner and cell ids for a 5 x 6 grid
2230 //
2231 // 36-----37-----38-----39-----40-----41
2232 // | | | | | |
2233 // | 25 | 26 | 27 | 28 | 29 |
2234 // | | | | | |
2235 // 30-----31-----32-----33-----34-----35
2236 // | | | | | |
2237 // | 20 | 21 | 22 | 23 | 24 |
2238 // | | | | | |
2239 // 24-----25-----26-----27-----28-----29
2240 // | | | | | |
2241 // | 15 | 16 | 17 | 18 | 19 |
2242 // | | | | | |
2243 // 18-----19-----20-----21-----22-----23
2244 // | | | | | |
2245 // | 10 | 11 | 12 | 13 | 14 |
2246 // | | | | | |
2247 // 12-----13-----14-----15-----16-----17
2248 // | | | | | |
2249 // | 05 | 06 | 07 | 08 | 09 |
2250 // | | | | | |
2251 // 06-----07-----08-----09-----10-----11
2252 // | | | | | |
2253 // | 00 | 01 | 02 | 03 | 04 |
2254 // | | | | | |
2255 // 00-----01-----02-----03-----04-----05
2256 //
2257 // the grid is distributed among the processes as follows:
2258 // (index == process)
2259 //
2260 // +---+---+---+---+---+
2261 // | 2 | 2 | 3 | 3 | 3 |
2262 // +---+---+---+---+---+
2263 // | 2 | 2 | 3 | 3 | 3 |
2264 // +---+---+---+---+---+
2265 // | 2 | 2 | 3 | 3 | 3 |
2266 // +---+---+---+---+---+
2267 // | 0 | 0 | 0 | 1 | 1 |
2268 // +---+---+---+---+---+
2269 // | 0 | 0 | 0 | 1 | 1 |
2270 // +---+---+---+---+---+
2271 // | 0 | 0 | 0 | 1 | 1 |
2272 // +---+---+---+---+---+
2273
2274 double coordinates_x[] = {-2.5,-1.5,-0.5,0.5,1.5,2.5};
2275 double coordinates_y[] = {-2.5,-1.5,-0.5,0.5,1.5,2.5,3.5};
2276 size_t const num_cells[2] = {5,6};
2277 size_t local_start[4][2] = {{0,0},{3,0},{0,3},{2,3}};
2278 size_t local_count[4][2] = {{3,2},{3,2},{3,3},{3,3}};
2279 int with_halo = 1;
2280 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
2281 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
2282
2283 tgt_grid =
2287 local_start[comm_rank], local_count[comm_rank], with_halo));
2289
2290 struct yac_dist_grid_pair * grid_pair =
2291 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
2292
2293 struct yac_interp_field src_fields[] =
2294 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
2295 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
2297 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
2298
2299 struct yac_interp_grid * interp_grid =
2302
2303 int order = 1;
2304 int enforced_conserv = 0;
2305 int partial_coverage = 0;
2306 enum yac_interp_method_conserv_normalisation normalisation =
2308
2309 struct interp_method * method_stack[] = {
2311 order, enforced_conserv, partial_coverage, normalisation), NULL};
2312
2313 struct yac_interp_weights * weights =
2314 yac_interp_method_do_search(method_stack, interp_grid);
2315
2316 yac_interp_method_delete(method_stack);
2317
2318 enum yac_interp_weights_reorder_type reorder_type[2] =
2320
2321 for (size_t j = 0; j < 2; ++j) {
2322 for (size_t collection_size = 1; collection_size < 4;
2323 collection_size += 2) {
2324
2325 struct yac_interpolation * interpolation =
2327 weights, reorder_type[j], collection_size,
2328 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
2329
2330 // check generated interpolation
2331 if (is_source) {
2332 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
2333 for (size_t i = 0; i < collection_size; ++i)
2334 src_data[i] = xmalloc(1 * sizeof(**src_data));
2335
2336 struct yac_basic_grid_data * src_grid_data =
2337 yac_basic_grid_get_data(src_grid);
2338
2339 for (size_t collection_idx = 0; collection_idx < collection_size;
2340 ++collection_idx) {
2341 src_data[collection_idx][0] =
2342 xmalloc(src_grid_data->num_cells * sizeof(***src_data));
2343 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
2344 src_data[collection_idx][0][i] =
2345 (src_grid_data->core_cell_mask[i])?
2346 (double)(src_grid_data->cell_ids[i]) +
2347 (double)(collection_idx * 30):
2348 -1.0;
2349 }
2350
2351 yac_interpolation_execute_put(interpolation, src_data);
2352
2353 for (size_t collection_idx = 0; collection_idx < collection_size;
2354 ++collection_idx) {
2355 free(src_data[collection_idx][0]);
2356 free(src_data[collection_idx]);
2357 }
2358 free(src_data);
2359 }
2360 if (is_target) {
2361 double ref_tgt_field[30] = {
2362 (0+1+6+7)/4.0,(1+2+7+8)/4.0,(2+3+8+9)/4.0,
2363 (3+4+9+10)/4.0,(4+5+10+11)/4.0,
2364 (6+7+12+13)/4.0,(7+8+13+14)/4.0,(8+9+14+15)/4.0,
2365 (9+10+15+16)/4.0,(10+11+16+17)/4.0,
2366 (12+13+18+19)/4.0,(13+14+19+20)/4.0,(14+15+20+21)/4.0,
2367 (15+16+21+22)/4.0,(16+17+22+23)/4.0,
2368 (18+19+24+25)/4.0,(19+20+25+26)/4.0,(20+21+26+27)/4.0,
2369 (21+22+27+28)/4.0,(22+23+28+29)/4.0,
2370 -1,-1,-1,-1,-1,
2371 -1,-1,-1,-1,-1,};
2372
2373 struct yac_basic_grid_data * tgt_grid_data =
2374 yac_basic_grid_get_data(tgt_grid);
2375
2376 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
2377 for (size_t collection_idx = 0; collection_idx < collection_size;
2378 ++collection_idx) {
2379 tgt_data[collection_idx] =
2380 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
2381 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
2382 tgt_data[collection_idx][k] = -1;
2383 }
2384
2385 yac_interpolation_execute_get(interpolation, tgt_data);
2386
2387 for (size_t collection_idx = 0; collection_idx < collection_size;
2388 ++collection_idx) {
2389 for (size_t j = 0, offset = collection_idx * 30;
2390 j < tgt_grid_data->num_cells; ++j) {
2391 if (tgt_grid_data->core_cell_mask[j] &&
2392 (ref_tgt_field[tgt_grid_data->cell_ids[j]] != -1.0)) {
2393 if (fabs((ref_tgt_field[tgt_grid_data->cell_ids[j]] +
2394 (double)offset) - tgt_data[collection_idx][j]) > 1e-3)
2395 PUT_ERR("wrong interpolation result");
2396 } else {
2397 if (tgt_data[collection_idx][j] != -1.0)
2398 PUT_ERR("wrong interpolation result");
2399 }
2400 }
2401 }
2402
2403 for (size_t collection_idx = 0; collection_idx < collection_size;
2404 ++collection_idx)
2405 free(tgt_data[collection_idx]);
2406 free(tgt_data);
2407 }
2408
2409 yac_interpolation_delete(interpolation);
2410 }
2411 }
2412
2413 yac_basic_grid_delete(src_grid);
2414 yac_basic_grid_delete(tgt_grid);
2416 yac_interp_grid_delete(interp_grid);
2417 yac_dist_grid_pair_delete(grid_pair);
2418
2419 MPI_Comm_free(&split_comm);
2420 MPI_Comm_free(&global_comm);
2421}
2422
2423static void utest_test10() {
2424
2425 int comm_rank, comm_size;
2426 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
2427 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
2428 MPI_Barrier(MPI_COMM_WORLD);
2429
2430 if (comm_size < 2) {
2431 PUT_ERR("ERROR: too few processes");
2432 xt_finalize();
2433 MPI_Finalize();
2434 exit(TEST_EXIT_CODE);
2435 }
2436
2437 int is_active = comm_rank < 2;
2438
2439 MPI_Comm global_comm;
2440 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
2441
2442 if (!is_active) {
2443 MPI_Comm_free(&global_comm);
2444 return;
2445 }
2446
2447 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
2448 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
2449
2450 int is_source = comm_rank == 1;
2451 int is_target = comm_rank == 0;
2452
2453 MPI_Comm split_comm;
2454 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
2455
2456 MPI_Comm_rank(split_comm, &comm_rank);
2457 MPI_Comm_size(split_comm, &comm_size);
2458
2459 struct yac_basic_grid * src_grid = NULL;
2460 struct yac_basic_grid * tgt_grid = NULL;
2461
2462 if (is_source) {
2463
2464 // the global source grid is a 3x3 grid:
2465 //
2466 // 12--21--13--22--14--23--15
2467 // | | | |
2468 // 15 06 17 07 19 08 20
2469 // | | | |
2470 // 08--14--09--16--10--18--11
2471 // | | | |
2472 // 08 03 10 04 12 05 13
2473 // | | | |
2474 // 04--07--05--09--06--11--07
2475 // | | | |
2476 // 01 00 03 01 05 02 06
2477 // | | | |
2478 // 00--00--01--02--02--04--03
2479
2480 double coordinates_x[] = {0.0,1.0,2.0,3.0};
2481 double coordinates_y[] = {0.0,1.0,2.0,3.0};
2482 size_t const num_cells[2] = {3,3};
2483 size_t local_start[1][2] = {{0,0}};
2484 size_t local_count[1][2] = {{3,3}};
2485 int cell_mask[] = {0,0,0, 0,0,0, 0,0,1};
2486 int with_halo = 1;
2487 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
2488 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
2489
2490 src_grid =
2495 local_start[comm_rank], local_count[comm_rank], with_halo));
2496 yac_basic_grid_add_mask(src_grid, YAC_LOC_CELL, cell_mask, 9, NULL);
2498
2499 if (is_target) {
2500
2501 double coordinates_x[] = {0.0,0.5,1.0};
2502 double coordinates_y[] = {0.0,0.5,1.0};
2503 size_t const num_cells[2] = {2,2};
2504 size_t local_start[1][2] = {{0,0}};
2505 size_t local_count[1][2] = {{2,2}};
2506 int with_halo = 1;
2507 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
2508 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
2509
2510 tgt_grid =
2515 local_start[comm_rank], local_count[comm_rank], with_halo));
2517
2518 struct yac_dist_grid_pair * grid_pair =
2519 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
2520
2521 struct yac_interp_field src_fields[] =
2522 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = 0}};
2523 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
2525 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
2526
2527 struct yac_interp_grid * interp_grid =
2530
2531 for (int config = 0; config < (1 << 4); ++config) {
2532
2533 int order = ((config >> 0) & 1) + 1;
2534 int enforced_conserv = (config >> 1) & 1;
2535 int partial_coverage = (config >> 2) & 1;
2536 enum yac_interp_method_conserv_normalisation normalisation =
2537 (enum yac_interp_method_conserv_normalisation)((config >> 3) & 1);
2538
2539 if ((order == 2) && (enforced_conserv == 1)) continue;
2540
2541 struct interp_method * method_stack[] = {
2543 order, enforced_conserv, partial_coverage, normalisation),
2544 yac_interp_method_fixed_new(-2.0), NULL};
2545
2546 struct yac_interp_weights * weights =
2547 yac_interp_method_do_search(method_stack, interp_grid);
2548
2549 yac_interp_method_delete(method_stack);
2550
2551 enum yac_interp_weights_reorder_type reorder_type[2] =
2553
2554 for (size_t j = 0; j < 2; ++j) {
2555 for (size_t collection_size = 1; collection_size < 4;
2556 collection_size += 2) {
2557
2558 struct yac_interpolation * interpolation =
2560 weights, reorder_type[j], collection_size,
2561 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
2562
2563 // check generated interpolation
2564 if (is_source) {
2565 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
2566 for (size_t i = 0; i < collection_size; ++i)
2567 src_data[i] = xmalloc(1 * sizeof(**src_data));
2568
2569 struct yac_basic_grid_data * src_grid_data =
2570 yac_basic_grid_get_data(src_grid);
2571
2572 for (size_t collection_idx = 0; collection_idx < collection_size;
2573 ++collection_idx) {
2574 double * src_field =
2575 xmalloc(src_grid_data->num_cells * sizeof(*src_field));
2576 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
2577 src_field[i] =
2578 (src_grid_data->core_cell_mask[i])?
2579 (double)(src_grid_data->cell_ids[i] + 1) +
2580 (double)(collection_idx * 4):
2581 -1.0;
2582 src_data[collection_idx][0] = src_field;
2583 }
2584
2585 yac_interpolation_execute_put(interpolation, src_data);
2586
2587 for (size_t collection_idx = 0; collection_idx < collection_size;
2588 ++collection_idx) {
2589 free(src_data[collection_idx][0]);
2590 free(src_data[collection_idx]);
2591 }
2592 free(src_data);
2593 }
2594 if (is_target) {
2595 double ref_tgt_field[4] = {-2.0, -2.0, -2.0, -2.0};
2596
2597 struct yac_basic_grid_data * tgt_grid_data =
2598 yac_basic_grid_get_data(tgt_grid);
2599
2600 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
2601 for (size_t collection_idx = 0; collection_idx < collection_size;
2602 ++collection_idx) {
2603 tgt_data[collection_idx] =
2604 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
2605 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
2606 tgt_data[collection_idx][k] = -1;
2607 }
2608
2609 yac_interpolation_execute_get(interpolation, tgt_data);
2610
2611 for (size_t collection_idx = 0; collection_idx < collection_size;
2612 ++collection_idx) {
2613 for (size_t j = 0; j < tgt_grid_data->num_cells; ++j) {
2614 if (tgt_grid_data->core_cell_mask[j] &&
2615 (ref_tgt_field[tgt_grid_data->cell_ids[j]] != -1.0)) {
2616 if (fabs(ref_tgt_field[tgt_grid_data->cell_ids[j]] -
2617 tgt_data[collection_idx][j]) > 1e-3)
2618 PUT_ERR("wrong interpolation result");
2619 } else {
2620 if (tgt_data[collection_idx][j] != -1.0)
2621 PUT_ERR("wrong interpolation result");
2622 }
2623 }
2624 }
2625
2626 for (size_t collection_idx = 0; collection_idx < collection_size;
2627 ++collection_idx)
2628 free(tgt_data[collection_idx]);
2629 free(tgt_data);
2630 }
2631
2632 yac_interpolation_delete(interpolation);
2633 }
2634 }
2635
2637 }
2638 yac_basic_grid_delete(src_grid);
2639 yac_basic_grid_delete(tgt_grid);
2640 yac_interp_grid_delete(interp_grid);
2641 yac_dist_grid_pair_delete(grid_pair);
2642
2643 MPI_Comm_free(&split_comm);
2644 MPI_Comm_free(&global_comm);
2645}
2646
2647static void utest_test11() {
2648
2649 int comm_rank, comm_size;
2650 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
2651 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
2652 MPI_Barrier(MPI_COMM_WORLD);
2653
2654 if (comm_size < 2) {
2655 PUT_ERR("ERROR: too few processes");
2656 xt_finalize();
2657 MPI_Finalize();
2658 exit(TEST_EXIT_CODE);
2659 }
2660
2661 int is_active = comm_rank < 2;
2662
2663 MPI_Comm global_comm;
2664 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
2665
2666 if (!is_active) {
2667 MPI_Comm_free(&global_comm);
2668 return;
2669 }
2670
2671 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
2672 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
2673
2674 int is_source = comm_rank == 1;
2675 int is_target = comm_rank == 0;
2676
2677 MPI_Comm split_comm;
2678 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
2679
2680 MPI_Comm_rank(split_comm, &comm_rank);
2681 MPI_Comm_size(split_comm, &comm_size);
2682
2683 struct yac_basic_grid * src_grid = NULL;
2684 struct yac_basic_grid * tgt_grid = NULL;
2685
2686 if (is_source) {
2687
2688 // the global source grid is a 3x3 grid:
2689 //
2690 // 12--21--13--22--14--23--15
2691 // | | | |
2692 // 15 06 17 07 19 08 20
2693 // | | | |
2694 // 08--14--09--16--10--18--11
2695 // | | | |
2696 // 08 03 10 04 12 05 13
2697 // | | | |
2698 // 04--07--05--09--06--11--07
2699 // | | | |
2700 // 01 00 03 01 05 02 06
2701 // | | | |
2702 // 00--00--01--02--02--04--03
2703
2704 double coordinates_x[] = {-1.5,-0.5,0.5,1.5};
2705 double coordinates_y[] = {-1.5,-0.5,0.5,1.5};
2706 size_t const num_cells[2] = {3,3};
2707 size_t local_start[1][2] = {{0,0}};
2708 size_t local_count[1][2] = {{3,3}};
2709 int cell_mask[] = {1,1,1, 1,0,1, 1,1,1};
2710 int with_halo = 1;
2711 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
2712 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
2713
2714 src_grid =
2719 local_start[comm_rank], local_count[comm_rank], with_halo));
2720 yac_basic_grid_add_mask(src_grid, YAC_LOC_CELL, cell_mask, 9, NULL);
2722
2723 if (is_target) {
2724
2725 double coordinates_x[] = {-0.49,0.49};
2726 double coordinates_y[] = {-0.49,0.49};
2727 size_t const num_cells[2] = {1,1};
2728 size_t local_start[1][2] = {{0,0}};
2729 size_t local_count[1][2] = {{1,1}};
2730 int with_halo = 1;
2731 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
2732 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
2733
2734 tgt_grid =
2739 local_start[comm_rank], local_count[comm_rank], with_halo));
2741
2742 struct yac_dist_grid_pair * grid_pair =
2743 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
2744
2745 struct yac_interp_field src_fields[] =
2746 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = 0}};
2747 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
2749 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
2750
2751 struct yac_interp_grid * interp_grid =
2754
2755 for (int config = 0; config < (1 << 4); ++config) {
2756
2757 int order = ((config >> 0) & 1) + 1;
2758 int enforced_conserv = (config >> 1) & 1;
2759 int partial_coverage = (config >> 2) & 1;
2760 enum yac_interp_method_conserv_normalisation normalisation =
2761 (enum yac_interp_method_conserv_normalisation)((config >> 3) & 1);
2762
2763 if ((order == 2) && (enforced_conserv == 1)) continue;
2764
2765 struct interp_method * method_stack[] = {
2767 order, enforced_conserv, partial_coverage, normalisation),
2768 yac_interp_method_fixed_new(-2.0), NULL};
2769
2770 struct yac_interp_weights * weights =
2771 yac_interp_method_do_search(method_stack, interp_grid);
2772
2773 yac_interp_method_delete(method_stack);
2774
2775 enum yac_interp_weights_reorder_type reorder_type[2] =
2777
2778 for (size_t j = 0; j < 2; ++j) {
2779 for (size_t collection_size = 1; collection_size < 4;
2780 collection_size += 2) {
2781
2782 struct yac_interpolation * interpolation =
2784 weights, reorder_type[j], collection_size,
2785 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
2786
2787 // check generated interpolation
2788 if (is_source) {
2789 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
2790 for (size_t i = 0; i < collection_size; ++i)
2791 src_data[i] = xmalloc(1 * sizeof(**src_data));
2792
2793 struct yac_basic_grid_data * src_grid_data =
2794 yac_basic_grid_get_data(src_grid);
2795
2796 for (size_t collection_idx = 0; collection_idx < collection_size;
2797 ++collection_idx) {
2798 double * src_field =
2799 xmalloc(src_grid_data->num_cells * sizeof(*src_field));
2800 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
2801 src_field[i] =
2802 (src_grid_data->core_cell_mask[i])?
2803 (double)(src_grid_data->cell_ids[i] + 1) +
2804 (double)(collection_idx * 4):
2805 -1.0;
2806 src_data[collection_idx][0] = src_field;
2807 }
2808
2809 yac_interpolation_execute_put(interpolation, src_data);
2810
2811 for (size_t collection_idx = 0; collection_idx < collection_size;
2812 ++collection_idx) {
2813 free(src_data[collection_idx][0]);
2814 free(src_data[collection_idx]);
2815 }
2816 free(src_data);
2817 }
2818 if (is_target) {
2819 double ref_tgt_field[1] = {-2.0};
2820
2821 struct yac_basic_grid_data * tgt_grid_data =
2822 yac_basic_grid_get_data(tgt_grid);
2823
2824 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
2825 for (size_t collection_idx = 0; collection_idx < collection_size;
2826 ++collection_idx) {
2827 tgt_data[collection_idx] =
2828 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
2829 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
2830 tgt_data[collection_idx][k] = -1;
2831 }
2832
2833 yac_interpolation_execute_get(interpolation, tgt_data);
2834
2835 for (size_t collection_idx = 0; collection_idx < collection_size;
2836 ++collection_idx) {
2837 for (size_t j = 0; j < tgt_grid_data->num_cells; ++j) {
2838 if (tgt_grid_data->core_cell_mask[j] &&
2839 (ref_tgt_field[tgt_grid_data->cell_ids[j]] != -2.0)) {
2840 if (fabs(ref_tgt_field[tgt_grid_data->cell_ids[j]] -
2841 tgt_data[collection_idx][j]) > 1e-3)
2842 PUT_ERR("wrong interpolation result");
2843 } else {
2844 if (tgt_data[collection_idx][j] != -2.0)
2845 PUT_ERR("wrong interpolation result");
2846 }
2847 }
2848 }
2849
2850 for (size_t collection_idx = 0; collection_idx < collection_size;
2851 ++collection_idx)
2852 free(tgt_data[collection_idx]);
2853 free(tgt_data);
2854 }
2855
2856 yac_interpolation_delete(interpolation);
2857 }
2858 }
2859
2861 }
2862 yac_basic_grid_delete(src_grid);
2863 yac_basic_grid_delete(tgt_grid);
2864 yac_interp_grid_delete(interp_grid);
2865 yac_dist_grid_pair_delete(grid_pair);
2866
2867 MPI_Comm_free(&split_comm);
2868 MPI_Comm_free(&global_comm);
2869}
2870
2871static void utest_test12() {
2872
2873 int comm_rank, comm_size;
2874 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
2875 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
2876 MPI_Barrier(MPI_COMM_WORLD);
2877
2878 if (comm_size < 4) {
2879 PUT_ERR("ERROR: too few processes");
2880 xt_finalize();
2881 MPI_Finalize();
2882 exit(TEST_EXIT_CODE);
2883 }
2884
2885 int is_active = comm_rank < 4;
2886
2887 MPI_Comm global_comm;
2888 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
2889
2890 if (!is_active) {
2891 MPI_Comm_free(&global_comm);
2892 return;
2893 }
2894
2895 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
2896 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
2897
2898 int is_source = comm_rank >= 1;
2899 int is_target = comm_rank < 1;
2900
2901 MPI_Comm split_comm;
2902 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
2903
2904 MPI_Comm_rank(split_comm, &comm_rank);
2905 MPI_Comm_size(split_comm, &comm_size);
2906
2907 struct yac_basic_grid * src_grid = NULL;
2908 struct yac_basic_grid * tgt_grid = NULL;
2909
2910 if (is_source) {
2911
2912 // the global source grid is a 3x3 grid:
2913 //
2914 // 12--21--13--22--14--23--15
2915 // | | | |
2916 // 15 06 17 07 19 08 20
2917 // | | | |
2918 // 08--14--09--16--10--18--11
2919 // | | | |
2920 // 08 03 10 04 12 05 13
2921 // | | | |
2922 // 04--07--05--09--06--11--07
2923 // | | | |
2924 // 01 00 03 01 05 02 06
2925 // | | | |
2926 // 00--00--01--02--02--04--03
2927
2928 double coordinates_x[] = {-1.0,0.0,1.5,2.0};
2929 double coordinates_y[] = {-1.0,0.0,1.5,2.0};
2930 size_t const num_cells[2] = {3,3};
2931 size_t local_start[3][2] = {{0,0},{0,1},{0,2}};
2932 size_t local_count[3][2] = {{3,1},{3,1},{3,1}};
2933 int with_halo = 1;
2934 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
2935 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
2936
2937 src_grid =
2942 local_start[comm_rank], local_count[comm_rank], with_halo));
2944
2945 if (is_target) {
2946
2947 // the global target grid is a 4x4 grid:
2948 //
2949 // 20--36--21--37--22--38--23--39--24
2950 // | | | | |
2951 // 28 12 30 13 32 14 34 15 35
2952 // | | | | |
2953 // 15--27--16--29--17--31--18--33--19
2954 // | | | | |
2955 // 19 08 21 09 23 10 25 11 26
2956 // | | | | |
2957 // 10--18--11--20--12--22--13--24--14
2958 // | | | | |
2959 // 10 04 12 05 14 06 16 07 17
2960 // | | | | |
2961 // 05--09--06--11--07--13--08--15--09
2962 // | | | | |
2963 // 01 00 03 01 05 02 07 03 08
2964 // | | | | |
2965 // 00--00--01--02--02--04--03--06--04
2966
2967 double coordinates_x[] = {-3.0,-2.0,-1.0,1.0,1.5};
2968 double coordinates_y[] = {-3.0,-2.0,-1.0,1.0,1.5};
2969 size_t const num_cells[2] = {4,4};
2970 size_t local_start[1][2] = {{0,0}};
2971 size_t local_count[1][2] = {{4,4}};
2972 int with_halo = 1;
2973 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
2974 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
2975
2976 tgt_grid =
2981 local_start[comm_rank], local_count[comm_rank], with_halo));
2983
2984 if (is_source) {
2985 int global_src_mask [] = {1,1,1,
2986 1,0,1,
2987 1,1,1};
2988
2989 struct yac_basic_grid_data * src_grid_data =
2990 yac_basic_grid_get_data(src_grid);
2991
2992 int * src_cell_mask =
2993 xmalloc(src_grid_data->num_cells * sizeof(*src_cell_mask));
2994 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
2995 src_cell_mask[i] = global_src_mask[src_grid_data->cell_ids[i]];
2997 src_grid, YAC_LOC_CELL, src_cell_mask, NULL);
2998 }
2999
3000 if (is_target) {
3001 int global_tgt_mask [] = {0,0,1,1,
3002 0,1,1,1,
3003 1,1,1,1,
3004 1,1,1,0};
3005 double coordinates_x[] = {-2.5,-1.75,-0.75,0.25};
3006 double coordinates_y[] = {-2.5,-1.75,-0.75,0.25};
3007
3008 struct yac_basic_grid_data * tgt_grid_data =
3009 yac_basic_grid_get_data(tgt_grid);
3010
3011 int * tgt_cell_mask =
3012 xmalloc(tgt_grid_data->num_cells * sizeof(*tgt_cell_mask));
3013 yac_coordinate_pointer tgt_cell_coords =
3014 xmalloc(tgt_grid_data->num_cells * sizeof(*tgt_cell_coords));
3015 for (size_t i = 0; i < tgt_grid_data->num_cells; ++i) {
3016 tgt_cell_mask[i] = global_tgt_mask[tgt_grid_data->cell_ids[i]];
3018 coordinates_x[tgt_grid_data->cell_ids[i]%4],
3019 coordinates_y[tgt_grid_data->cell_ids[i]/4],
3020 tgt_cell_coords[i]);
3021 }
3023 tgt_grid, YAC_LOC_CELL, tgt_cell_mask, NULL);
3025 tgt_grid, YAC_LOC_CELL, tgt_cell_coords);
3026 }
3027
3028 struct yac_dist_grid_pair * grid_pair =
3029 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
3030
3031 struct yac_interp_field src_fields[] =
3032 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = 0}};
3033 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
3035 {.location = YAC_LOC_CELL, .coordinates_idx = 0, .masks_idx = 0};
3036
3037 struct yac_interp_grid * interp_grid =
3040
3041 int order = 2;
3042 int enforced_conserv = 0;
3043 int partial_coverage = 1;
3044 enum yac_interp_method_conserv_normalisation normalisation =
3046
3047 struct interp_method * method_stack[] = {
3049 order, enforced_conserv, partial_coverage, normalisation),
3050 yac_interp_method_fixed_new(-2.0), NULL};
3051
3052 struct yac_interp_weights * weights =
3053 yac_interp_method_do_search(method_stack, interp_grid);
3054
3055 yac_interp_method_delete(method_stack);
3056
3057 enum yac_interp_weights_reorder_type reorder_type[2] =
3059
3060#define NUM_TESTS (4)
3061
3062 for (size_t t = 0; t < NUM_TESTS; ++t) {
3063 for (size_t j = 0; j < 2; ++j) {
3064
3065 size_t collection_size = 1;
3066
3067 struct yac_interpolation * interpolation =
3069 weights, reorder_type[j], collection_size,
3070 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
3071
3072 // check generated interpolation
3073 if (is_source) {
3074 double global_field_data[NUM_TESTS][9] = {
3075 {1,1,1, 1,1,1, 1,1,1},
3076 {0,0,0, 1,1,1, 2,2,2},
3077 {0,1,2, 0,1,2, 0,1,2},
3078 {0,1,2, 1,2,3, 2,3,4}};
3079 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
3080 for (size_t i = 0; i < collection_size; ++i)
3081 src_data[i] = xmalloc(1 * sizeof(**src_data));
3082
3083 struct yac_basic_grid_data * src_grid_data =
3084 yac_basic_grid_get_data(src_grid);
3085
3086 for (size_t collection_idx = 0; collection_idx < collection_size;
3087 ++collection_idx) {
3088 src_data[collection_idx][0] =
3089 xmalloc(src_grid_data->num_cells * sizeof(***src_data));
3090 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
3091 src_data[collection_idx][0][i] =
3092 (src_grid_data->core_cell_mask[i])?
3093 global_field_data[t][src_grid_data->cell_ids[i]]:-1.0;
3094 }
3095
3096 yac_interpolation_execute_put(interpolation, src_data);
3097
3098 for (size_t collection_idx = 0; collection_idx < collection_size;
3099 ++collection_idx) {
3100 free(src_data[collection_idx][0]);
3101 free(src_data[collection_idx]);
3102 }
3103 free(src_data);
3104 }
3105 if (is_target) {
3106 double ref_tgt_field[NUM_TESTS][16] = {
3107 {-1.0,-1.0,-2.0,-2.0,
3108 -1.0,-2.0,-2.0,-2.0,
3109 -2.0,-2.0,1.0,1.0,
3110 -2.0,-2.0,1.0,-1.0},
3111 {-1.0,-1.0,-2.0,-2.0,
3112 -1.0,-2.0,-2.0,-2.0,
3113 -2.0,-2.0,(0.0+0.0+1.0)/3.0,0.0,
3114 -2.0,-2.0,1.0,-1.0},
3115 {-1.0,-1.0,-2.0,-2.0,
3116 -1.0,-2.0,-2.0,-2.0,
3117 -2.0,-2.0,(0.0+1.0+0.0)/3.0,1.0,
3118 -2.0,-2.0,0.0,-1.0},
3119 {-1.0,-1.0,-2.0,-2.0,
3120 -1.0,-2.0,-2.0,-2.0,
3121 -2.0,-2.0,(0.0+1.0+1.0)/3.0,1.0,
3122 -2.0,-2.0,1.0,-1.0}};
3123
3124 struct yac_basic_grid_data * tgt_grid_data =
3125 yac_basic_grid_get_data(tgt_grid);
3126
3127 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
3128 for (size_t collection_idx = 0; collection_idx < collection_size;
3129 ++collection_idx) {
3130 tgt_data[collection_idx] =
3131 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
3132 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
3133 tgt_data[collection_idx][k] = -1;
3134 }
3135
3136 yac_interpolation_execute_get(interpolation, tgt_data);
3137
3138 for (size_t collection_idx = 0; collection_idx < collection_size;
3139 ++collection_idx) {
3140 for (size_t j = 0; j < tgt_grid_data->num_cells; ++j) {
3141 if (tgt_grid_data->core_cell_mask[j] &&
3142 (ref_tgt_field[t][tgt_grid_data->cell_ids[j]] != -1.0)) {
3143 if (fabs((ref_tgt_field[t][tgt_grid_data->cell_ids[j]]) -
3144 tgt_data[collection_idx][j]) > 1e-3)
3145 PUT_ERR("wrong interpolation result");
3146 } else {
3147 if (tgt_data[collection_idx][j] != -1.0)
3148 PUT_ERR("wrong interpolation result");
3149 }
3150 }
3151 }
3152
3153 for (size_t collection_idx = 0; collection_idx < collection_size;
3154 ++collection_idx)
3155 free(tgt_data[collection_idx]);
3156 free(tgt_data);
3157 }
3158
3159 yac_interpolation_delete(interpolation);
3160 }
3161 }
3162#undef NUM_TESTS
3163
3164 yac_basic_grid_delete(src_grid);
3165 yac_basic_grid_delete(tgt_grid);
3167 yac_interp_grid_delete(interp_grid);
3168 yac_dist_grid_pair_delete(grid_pair);
3169
3170 MPI_Comm_free(&split_comm);
3171 MPI_Comm_free(&global_comm);
3172}
3173
3174static void utest_test13() {
3175
3176 int comm_rank, comm_size;
3177 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
3178 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
3179 MPI_Barrier(MPI_COMM_WORLD);
3180
3181 if (comm_size < 2) {
3182 PUT_ERR("ERROR: too few processes");
3183 xt_finalize();
3184 MPI_Finalize();
3185 exit(TEST_EXIT_CODE);
3186 }
3187
3188 int is_active = comm_rank < 2;
3189
3190 MPI_Comm global_comm;
3191 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
3192
3193 if (!is_active) {
3194 MPI_Comm_free(&global_comm);
3195 return;
3196 }
3197
3198 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
3199 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
3200
3201 int is_source = comm_rank >= 1;
3202 int is_target = comm_rank < 1;
3203
3204 MPI_Comm split_comm;
3205 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
3206
3207 MPI_Comm_rank(split_comm, &comm_rank);
3208 MPI_Comm_size(split_comm, &comm_size);
3209
3210 struct yac_basic_grid * src_grid = NULL;
3211 struct yac_basic_grid * tgt_grid = NULL;
3212
3213 if (is_source) {
3214
3215 // the global source grid is a 1x1 grid:
3216 //
3217 // 02--03--03
3218 // | |
3219 // 01 00 02
3220 // | |
3221 // 00--00--01
3222
3223 double coordinates_x[] = {-0.1,0.1};
3224 double coordinates_y[] = {-0.1,0.1};
3225 size_t const num_cells[2] = {1,1};
3226 size_t local_start[1][2] = {{0,0}};
3227 size_t local_count[1][2] = {{1,1}};
3228 int with_halo = 1;
3229 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
3230 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
3231
3232 src_grid =
3237 local_start[comm_rank], local_count[comm_rank], with_halo));
3239
3240 if (is_target) {
3241
3242 // the global target grid:
3243 //
3244 // 10--18--11--19--12--20--13--21--14
3245 // | | | | |
3246 // 10 04 12 05 14 06 16 07 17
3247 // | | | | |
3248 // 05--09--06--11--07--13--08--15--09
3249 // | | | | |
3250 // 01 00 03 01 05 02 07 03 08
3251 // | | | | |
3252 // 00--00--01--02--02--04--03--06--04
3253
3254 enum {NBR_VERTICES = 15, NBR_CELLS = 8, NUM_VERTICES_PER_CELL = 4};
3255 int num_vertices_per_cell[NBR_CELLS] = {NUM_VERTICES_PER_CELL,
3256 NUM_VERTICES_PER_CELL,
3257 NUM_VERTICES_PER_CELL,
3258 NUM_VERTICES_PER_CELL,
3259 NUM_VERTICES_PER_CELL,
3260 NUM_VERTICES_PER_CELL,
3261 NUM_VERTICES_PER_CELL,
3262 NUM_VERTICES_PER_CELL};
3263 double coordinates_x[NBR_VERTICES] = {-3,-2,0,2,3, -3,-2,0,2,3, -3,-2,0,2,3};
3264 double coordinates_y[NBR_VERTICES] = {-1,-1,-1,-1,-1, 0,0,0,0,0, 1,1,1,1,1};
3265 int cell_to_vertex[NBR_CELLS][NUM_VERTICES_PER_CELL] =
3266 {{0,1,6,5}, {1,2,7,6}, {2,3,8,7}, {3,4,9,8},
3267 {5,6,11,10}, {6,7,12,11}, {7,8,13,12}, {8,9,14,13}};
3268
3269 struct yac_basic_grid_data tgt_grid_data =
3273 tgt_grid_data.cell_ids =
3274 xmalloc(NBR_CELLS * sizeof(*tgt_grid_data.cell_ids));
3275 for (size_t i = 0; i < NBR_CELLS; ++i)
3276 tgt_grid_data.cell_ids[i] = (yac_int)i;
3277 tgt_grid =
3278 yac_basic_grid_new(tgt_grid_name, tgt_grid_data);
3280
3281 struct yac_dist_grid_pair * grid_pair =
3282 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
3283
3284 struct yac_interp_field src_fields[] =
3285 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
3286 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
3288 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
3289
3290 struct yac_interp_grid * interp_grid =
3293
3294 int order = 1;
3295 int enforced_conserv = 0;
3296 int partial_coverage = 1;
3297 enum yac_interp_method_conserv_normalisation normalisation =
3299
3300 struct interp_method * method_stack[] = {
3302 order, enforced_conserv, partial_coverage, normalisation), NULL};
3303
3304 struct yac_interp_weights * weights =
3305 yac_interp_method_do_search(method_stack, interp_grid);
3306
3307 yac_interp_method_delete(method_stack);
3308
3309 size_t collection_size = 1;
3310 struct yac_interpolation * interpolation =
3313 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
3314
3315 // check generated interpolation
3316 if (is_source) {
3317 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
3318 for (size_t i = 0; i < collection_size; ++i)
3319 src_data[i] = xmalloc(1 * sizeof(**src_data));
3320
3321 struct yac_basic_grid_data * src_grid_data =
3322 yac_basic_grid_get_data(src_grid);
3323
3324 for (size_t collection_idx = 0; collection_idx < collection_size;
3325 ++collection_idx) {
3326 src_data[collection_idx][0] =
3327 xmalloc(src_grid_data->num_cells * sizeof(***src_data));
3328 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
3329 src_data[collection_idx][0][i] =
3330 (src_grid_data->core_cell_mask[i])?
3331 (double)(src_grid_data->cell_ids[i] + 1) +
3332 (double)(collection_idx * 9):
3333 -1.0;
3334 }
3335
3336 yac_interpolation_execute_put(interpolation, src_data);
3337
3338 for (size_t collection_idx = 0; collection_idx < collection_size;
3339 ++collection_idx) {
3340 free(src_data[collection_idx][0]);
3341 free(src_data[collection_idx]);
3342 }
3343 free(src_data);
3344 }
3345 if (is_target) {
3346 double ref_tgt_field[8] = {-1,1,1,-1,-1,1,1,-1};
3347
3348 struct yac_basic_grid_data * tgt_grid_data =
3349 yac_basic_grid_get_data(tgt_grid);
3350
3351 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
3352 for (size_t collection_idx = 0; collection_idx < collection_size;
3353 ++collection_idx) {
3354 tgt_data[collection_idx] =
3355 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
3356 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
3357 tgt_data[collection_idx][k] = -1;
3358 }
3359
3360 yac_interpolation_execute_get(interpolation, tgt_data);
3361
3362 for (size_t collection_idx = 0; collection_idx < collection_size;
3363 ++collection_idx) {
3364 for (size_t j = 0, offset = collection_idx * 9;
3365 j < tgt_grid_data->num_cells; ++j) {
3366 if (((tgt_grid_data->core_cell_mask == NULL) ||
3367 tgt_grid_data->core_cell_mask[j]) &&
3368 (ref_tgt_field[tgt_grid_data->cell_ids[j]] != -1.0)) {
3369 if (fabs((ref_tgt_field[tgt_grid_data->cell_ids[j]] +
3370 (double)offset) - tgt_data[collection_idx][j]) > 1e-3)
3371 PUT_ERR("wrong interpolation result");
3372 } else {
3373 if (tgt_data[collection_idx][j] != -1.0)
3374 PUT_ERR("wrong interpolation result");
3375 }
3376 }
3377 }
3378
3379 for (size_t collection_idx = 0; collection_idx < collection_size;
3380 ++collection_idx)
3381 free(tgt_data[collection_idx]);
3382 free(tgt_data);
3383 }
3384
3385 yac_interpolation_delete(interpolation);
3386
3387 yac_basic_grid_delete(src_grid);
3388 yac_basic_grid_delete(tgt_grid);
3390 yac_interp_grid_delete(interp_grid);
3391 yac_dist_grid_pair_delete(grid_pair);
3392
3393 MPI_Comm_free(&split_comm);
3394 MPI_Comm_free(&global_comm);
3395}
3396
3397static void utest_test14() {
3398
3399 int comm_rank, comm_size;
3400 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
3401 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
3402 MPI_Barrier(MPI_COMM_WORLD);
3403
3404 if (comm_size < 2) {
3405 PUT_ERR("ERROR: too few processes");
3406 xt_finalize();
3407 MPI_Finalize();
3408 exit(TEST_EXIT_CODE);
3409 }
3410
3411 int is_active = comm_rank < 2;
3412
3413 MPI_Comm global_comm;
3414 MPI_Comm_split(MPI_COMM_WORLD, is_active, 0, &global_comm);
3415
3416 if (!is_active) {
3417 MPI_Comm_free(&global_comm);
3418 return;
3419 }
3420
3421 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
3422 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
3423
3424 int is_source = comm_rank >= 1;
3425 int is_target = comm_rank < 1;
3426
3427 MPI_Comm split_comm;
3428 MPI_Comm_split(global_comm, is_target, 0, &split_comm);
3429
3430 MPI_Comm_rank(split_comm, &comm_rank);
3431 MPI_Comm_size(split_comm, &comm_size);
3432
3433 struct yac_basic_grid * src_grid = NULL;
3434 struct yac_basic_grid * tgt_grid = NULL;
3435
3436 if (is_source) {
3437
3438 // the global source grid is a 3x3 grid:
3439 //
3440 // 12--21--13--22--14--23--15
3441 // | | | |
3442 // 15 06 17 07 19 08 20
3443 // | | | |
3444 // 08--14--09--16--10--18--11
3445 // | | | |
3446 // 08 03 10 04 12 05 13
3447 // | | | |
3448 // 04--07--05--09--06--11--07
3449 // | | | |
3450 // 01 00 03 01 05 02 06
3451 // | | | |
3452 // 00--00--01--02--02--04--03
3453 //
3454 // mask for the source grid (cells with "x" are masked)
3455 //
3456 // +---+---+---+
3457 // | x | | x |
3458 // +---+---+---+
3459 // | | | |
3460 // +---+---+---+
3461 // | | | |
3462 // +---+---+---+
3463
3464 double coordinates_x[] = {-1.5,-0.5,0.5,1.5};
3465 double coordinates_y[] = {-1.5,-0.5,0.5,1.5};
3466 size_t const num_cells[2] = {3,3};
3467 size_t local_start[1][2] = {{0,0}};
3468 size_t local_count[1][2] = {{3,3}};
3469 int with_halo = 1;
3470 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
3471 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
3472
3473 int cell_core_mask[] = {1,1,1,
3474 1,1,1,
3475 1,0,1};
3479 local_start[comm_rank], local_count[comm_rank], with_halo);
3480 for (size_t i = 0; i < grid_data.num_cells; ++i)
3481 grid_data.core_cell_mask[i] =
3482 grid_data.core_cell_mask[i] &&
3483 cell_core_mask[grid_data.cell_ids[i]];
3484 src_grid =
3487
3488 if (is_target) {
3489
3490 // the global target grid is a 2x2 grid:
3491 //
3492 // 06--10--07--11--08
3493 // | | |
3494 // 06 02 08 03 09
3495 // | | |
3496 // 03--05--04--07--05
3497 // | | |
3498 // 01 00 03 01 04
3499 // | | |
3500 // 00--00--01--02--02
3501
3502 double coordinates_x[] = {-2,0,2};
3503 double coordinates_y[] = {-2,0,2};
3504 size_t const num_cells[2] = {2,2};
3505 size_t local_start[1][2] = {{0,0}};
3506 size_t local_count[1][2] = {{2,2}};
3507 int with_halo = 1;
3508 for (size_t i = 0; i <= num_cells[0]; ++i) coordinates_x[i] *= YAC_RAD;
3509 for (size_t i = 0; i <= num_cells[1]; ++i) coordinates_y[i] *= YAC_RAD;
3510
3511 tgt_grid =
3516 local_start[comm_rank], local_count[comm_rank], with_halo));
3518
3519 struct yac_dist_grid_pair * grid_pair =
3520 yac_dist_grid_pair_new(src_grid, tgt_grid, global_comm);
3521
3522 struct yac_interp_field src_fields[] =
3523 {{.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX}};
3524 size_t num_src_fields = sizeof(src_fields) / sizeof(src_fields[0]);
3526 {.location = YAC_LOC_CELL, .coordinates_idx = SIZE_MAX, .masks_idx = SIZE_MAX};
3527
3528 struct yac_interp_grid * interp_grid =
3531
3532 int order = 2;
3533 int enforced_conserv = 0;
3534 int partial_coverage = 1;
3535 enum yac_interp_method_conserv_normalisation normalisation =
3537
3538 struct interp_method * method_stack[] = {
3540 order, enforced_conserv, partial_coverage, normalisation), NULL};
3541
3542 struct yac_interp_weights * weights =
3543 yac_interp_method_do_search(method_stack, interp_grid);
3544
3545 yac_interp_method_delete(method_stack);
3546
3547 size_t collection_size = 1;
3548 struct yac_interpolation * interpolation =
3551 YAC_FRAC_MASK_NO_VALUE, 1.0, 0.0, NULL, 1, 1);
3552
3553 // check generated interpolation
3554 if (is_source) {
3555 double *** src_data = xmalloc(collection_size * sizeof(*src_data));
3556 for (size_t i = 0; i < collection_size; ++i)
3557 src_data[i] = xmalloc(1 * sizeof(**src_data));
3558
3559 struct yac_basic_grid_data * src_grid_data =
3560 yac_basic_grid_get_data(src_grid);
3561
3562 for (size_t collection_idx = 0; collection_idx < collection_size;
3563 ++collection_idx) {
3564 src_data[collection_idx][0] =
3565 xmalloc(src_grid_data->num_cells * sizeof(***src_data));
3566 for (size_t i = 0; i < src_grid_data->num_cells; ++i)
3567 src_data[collection_idx][0][i] =
3568 (src_grid_data->core_cell_mask[i])?
3569 (1.0 + (double)(collection_idx * 4)):-1.0;
3570 }
3571
3572 yac_interpolation_execute_put(interpolation, src_data);
3573
3574 for (size_t collection_idx = 0; collection_idx < collection_size;
3575 ++collection_idx) {
3576 free(src_data[collection_idx][0]);
3577 free(src_data[collection_idx]);
3578 }
3579 free(src_data);
3580 }
3581 if (is_target) {
3582 double ref_tgt_field[4] = {1,1,1,1};
3583
3584 struct yac_basic_grid_data * tgt_grid_data =
3585 yac_basic_grid_get_data(tgt_grid);
3586
3587 double ** tgt_data = xmalloc(collection_size * sizeof(*tgt_data));
3588 for (size_t collection_idx = 0; collection_idx < collection_size;
3589 ++collection_idx) {
3590 tgt_data[collection_idx] =
3591 xmalloc(tgt_grid_data->num_cells * sizeof(**tgt_data));
3592 for (size_t k = 0; k < tgt_grid_data->num_cells; ++k)
3593 tgt_data[collection_idx][k] = -1;
3594 }
3595
3596 yac_interpolation_execute_get(interpolation, tgt_data);
3597
3598 for (size_t collection_idx = 0; collection_idx < collection_size;
3599 ++collection_idx) {
3600 for (size_t j = 0, offset = collection_idx * 4;
3601 j < tgt_grid_data->num_cells; ++j) {
3602 if (tgt_grid_data->core_cell_mask[j] &&
3603 (ref_tgt_field[tgt_grid_data->cell_ids[j]] != -1.0)) {
3604 if (fabs((ref_tgt_field[tgt_grid_data->cell_ids[j]] +
3605 (double)offset) - tgt_data[collection_idx][j]) > 1e-3)
3606 PUT_ERR("wrong interpolation result");
3607 } else {
3608 if (tgt_data[collection_idx][j] != -1.0)
3609 PUT_ERR("wrong interpolation result");
3610 }
3611 }
3612 }
3613
3614 for (size_t collection_idx = 0; collection_idx < collection_size;
3615 ++collection_idx)
3616 free(tgt_data[collection_idx]);
3617 free(tgt_data);
3618 }
3619
3620 yac_interpolation_delete(interpolation);
3621
3622 yac_basic_grid_delete(src_grid);
3623 yac_basic_grid_delete(tgt_grid);
3625 yac_interp_grid_delete(interp_grid);
3626 yac_dist_grid_pair_delete(grid_pair);
3627
3628 MPI_Comm_free(&split_comm);
3629 MPI_Comm_free(&global_comm);
3630}
struct yac_basic_grid * yac_basic_grid_new(char const *name, struct yac_basic_grid_data grid_data)
Definition basic_grid.c:53
struct yac_basic_grid_data * yac_basic_grid_get_data(struct yac_basic_grid *grid)
Definition basic_grid.c:140
size_t yac_basic_grid_add_mask(struct yac_basic_grid *grid, enum yac_location location, int const *mask, size_t count, char const *mask_name)
Definition basic_grid.c:287
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:211
struct yac_basic_grid * yac_basic_grid_empty_new(char const *name)
Definition basic_grid.c:66
void yac_basic_grid_delete(struct yac_basic_grid *grid)
Definition basic_grid.c:73
size_t yac_basic_grid_add_mask_nocpy(struct yac_basic_grid *grid, enum yac_location location, int const *mask, char const *mask_name)
Definition basic_grid.c:261
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_deg(size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell, double *x_vertices, double *y_vertices, int *cell_to_vertex)
void yac_dist_grid_pair_delete(struct yac_dist_grid_pair *grid_pair)
Definition dist_grid.c:2315
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:2063
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)
#define NBR_CELLS
#define NBR_VERTICES
#define YAC_RAD
static void LLtoXYZ_deg(double lon, double lat, double p_out[])
Definition geometry.h:269
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:30
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_conserv_new(int order, int enforced_conserv, int partial_coverage, enum yac_interp_method_conserv_normalisation normalisation)
yac_interp_method_conserv_normalisation
@ YAC_INTERP_CONSERV_DESTAREA
@ YAC_INTERP_CONSERV_FRACAREA
struct interp_method * yac_interp_method_fixed_new(double value)
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_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_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:25
size_t num_src_fields
Definition interp_grid.c:26
struct yac_dist_grid_pair * grid_pair
Definition interp_grid.c:24
struct yac_interp_field src_fields[]
Definition interp_grid.c:27
int * cell_to_vertex
int * cell_mask
int collection_size
char const src_grid_name[]
char const tgt_grid_name[]
#define NUM_TESTS
static MPI_Comm split_comm
double coordinates_x[]
size_t num_cells[2]
double coordinates_y[]
#define TEST_EXIT_CODE
Definition tests.h:14
#define PUT_ERR(string)
Definition tests.h:10
int * cell_core_mask
YAC_INT yac_int
Definition yac_types.h:15
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:21