YAC 3.18.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_dummy_coupling9.F90
Go to the documentation of this file.
1! Copyright (c) 2024 The YAC Authors
2!
3! SPDX-License-Identifier: BSD-3-Clause
4
8
9#include "test_macros.inc"
10
11#define NOP(x) associate( x => x ); end associate
12
13PROGRAM main
14
15 USE utest
16 USE yac
17 USE mpi
18
19 IMPLICIT NONE
20
21 INTEGER :: global_rank, global_size
22 LOGICAL :: is_target, is_empty_source
23
24 CHARACTER (LEN=*), PARAMETER :: src_comp_name = 'source_comp'
25 CHARACTER (LEN=*), PARAMETER :: tgt_comp_name = 'target_comp'
26 CHARACTER (LEN=*), PARAMETER :: src_grid_name = 'source_grid'
27 CHARACTER (LEN=*), PARAMETER :: tgt_grid_name = 'target_grid'
28 CHARACTER (LEN=*), PARAMETER :: even_mask_name = 'even_mask'
29 CHARACTER (LEN=*), PARAMETER :: odd_mask_name = 'odd_mask'
30 TYPE(yac_string) :: mask_type_str(3)
31 TYPE(yac_string) :: with_str(2)
32 TYPE(yac_string) :: from_file_str(2)
33
34 INTEGER, PARAMETER :: collection_size = 3
35 INTEGER, PARAMETER :: num_pointsets = 1
36 INTEGER, PARAMETER :: num_points = 9
37
38 INTEGER :: config_from_file, with_field_mask
39 INTEGER :: source_mask_type, target_mask_type
40
41 INTEGER :: instance_id
42 INTEGER :: comp_id, grid_id, point_id, field_ids(3,3,2,2)
43 INTEGER :: default_mask_id, dummy_mask_id
44
45 INTEGER :: interp_stack_config
46 CHARACTER(LEN=YAC_MAX_CHARLEN) :: field_name
47 TYPE(yac_string) :: src_mask_names(1)
48 CHARACTER(LEN=YAC_MAX_CHARLEN) :: tgt_mask_name
49
50 DOUBLE PRECISION :: send_field(num_points, num_pointsets, collection_size)
51 DOUBLE PRECISION, TARGET :: recv_field(num_points, collection_size)
52 TYPE(yac_dble_ptr) :: recv_field_ptr(collection_size)
53
54 LOGICAL :: check_recv_field
55
56 INTEGER :: i, j, k, t, info, ierror
57
58 INTEGER, PARAMETER :: max_opt_arg_len = 1024
59 CHARACTER(max_opt_arg_len) :: config_dir
60 INTEGER :: arg_len
61 TYPE(yac_dble_ptr) :: buffer_ptr(num_pointsets, collection_size)
62 DOUBLE PRECISION, ALLOCATABLE, TARGET :: buffer(:)
63
64 DOUBLE PRECISION, PARAMETER :: yac_rad = 0.017453292519943295769d0 ! M_PI / 180
65
66 ALLOCATE(buffer(0))
67
68 mask_type_str(1)%string = "even"
69 mask_type_str(2)%string = "odd"
70 mask_type_str(3)%string = "none"
71 with_str(1)%string = "without"
72 with_str(2)%string = "with"
73 from_file_str(1)%string = "manual"
74 from_file_str(2)%string = "yaml"
75
76 ! ===================================================================
77
78 CALL start_test('dummy_coupling9')
79
80 CALL mpi_init(ierror)
81
82 CALL test(command_argument_count() == 1)
83 CALL get_command_argument(1, config_dir, arg_len)
84
85 CALL mpi_comm_rank(mpi_comm_world, global_rank, ierror)
86 CALL mpi_comm_size(mpi_comm_world, global_size, ierror)
87
88 IF (global_size /= 3) THEN
89 WRITE ( * , * ) "Wrong number of processes (should be 3)"
90 CALL error_exit
91 ENDIF
92
93 is_target = global_rank == 1
94 is_empty_source = global_rank == 2
95
96 IF (is_target) THEN
97 CALL yac_finit ()
98 ELSE
99 CALL yac_finit(instance_id)
100 END IF
102 IF (is_target) THEN
103 CALL yac_fread_config_yaml(trim(config_dir) // "coupling_test9.yaml")
104 ELSE
106 instance_id, trim(config_dir) // "coupling_test9.yaml")
107 END IF
108
109 ! define local component
110 IF (is_target) THEN
111 CALL yac_fdef_comp( tgt_comp_name, comp_id)
112 ELSE
113 CALL yac_fdef_comp( instance_id, src_comp_name, comp_id)
114 END IF
115
116 ! define grid (both components use an identical grids)
117 IF (is_empty_source) THEN
118 ! The empty source process defines an empty grid
119 CALL yac_fdef_grid(src_grid_name, &
120 0, 0, 0, [INTEGER :: ], [REAL :: ], &
121 [REAL :: ], [INTEGER :: ], grid_id)
122 ! define points at the vertices of the grid
123 CALL yac_fdef_points( &
124 grid_id, 0, yac_location_corner, &
125 [real :: ], [real :: ], point_id)
126
127 ! define masks for vertices
128 CALL yac_fdef_mask( &
129 grid_id, 0, yac_location_corner, &
130 [INTEGER :: ], default_mask_id)
131 CALL yac_fdef_mask_named( &
132 grid_id, 0, yac_location_corner, &
133 [INTEGER :: ], even_mask_name, dummy_mask_id)
134 CALL yac_fdef_mask_named( &
135 grid_id, 0, yac_location_corner, &
136 [LOGICAL :: ], odd_mask_name, dummy_mask_id)
137 ELSE
138 CALL yac_fdef_grid( &
139 merge(tgt_grid_name, src_grid_name, is_target), &
140 (/3,3/), (/0,0/), (/0.0,1.0,2.0/) * yac_rad, &
141 (/0.0,1.0,2.0/) * yac_rad, grid_id)
142 ! define points at the vertices of the grid
143 CALL yac_fdef_points( &
144 grid_id, (/3,3/), yac_location_corner, &
145 (/0.0,1.0,2.0/) * yac_rad, (/0.0,1.0,2.0/) * yac_rad, point_id)
146
147 ! define masks for vertices
148 CALL yac_fdef_mask( &
149 grid_id, 3 * 3, yac_location_corner, &
150 (/1,0,0, 0,0,0, 0,0,0/), default_mask_id)
151 CALL yac_fdef_mask_named( &
152 grid_id, 3 * 3, yac_location_corner, &
153 (/0,1,0, 1,0,1, 0,1,0/), even_mask_name, dummy_mask_id)
154 CALL yac_fdef_mask_named( &
155 grid_id, 3 * 3, yac_location_corner, &
156 (/.true.,.false.,.true., .false.,.true.,.false., .true.,.false.,.true./), &
157 odd_mask_name, dummy_mask_id)
158 ENDIF
159
160 ! define field
161 DO config_from_file = 1, 2
162 DO with_field_mask = 1, 2
163 DO source_mask_type = 1, 3
164 DO target_mask_type = 1, 3
165 WRITE (field_name, "('src2tgt_',A,'_',A,'_field_mask_',A,'_src_mask_',A,'_tgt_mask')") &
166 trim(from_file_str(config_from_file)%string), &
167 trim(with_str(with_field_mask)%string), &
168 trim(mask_type_str(source_mask_type)%string), &
169 trim(mask_type_str(target_mask_type)%string)
170 IF (with_field_mask == 1) THEN
171 CALL yac_fdef_field( &
172 field_name, comp_id, (/point_id/), num_pointsets, &
173 collection_size, "1", yac_time_unit_second, &
174 field_ids(target_mask_type, source_mask_type, &
175 with_field_mask, config_from_file))
176 ELSE
177 CALL yac_fdef_field_mask( &
178 field_name, comp_id, (/point_id/), (/default_mask_id/), &
179 num_pointsets, collection_size, "1", yac_time_unit_second, &
180 field_ids(target_mask_type, source_mask_type, &
181 with_field_mask, config_from_file))
182 END IF
183 END DO
184 END DO
185 END DO
186 END DO
187
188 ! define manual couples
189 CALL yac_fget_interp_stack_config(interp_stack_config)
191 interp_stack_config, yac_nnn_avg, 1, 0.0d0, 0.0d0)
192 DO with_field_mask = 1, 2
193 DO source_mask_type = 1, 3
194 IF (source_mask_type == 1) THEN
195 src_mask_names(1)%string = even_mask_name
196 ELSE IF (source_mask_type == 2) THEN
197 src_mask_names(1)%string = odd_mask_name
198 END IF
199 DO target_mask_type = 1, 3
200 IF (target_mask_type == 1) THEN
201 tgt_mask_name = even_mask_name
202 ELSE IF (target_mask_type == 2) THEN
203 tgt_mask_name = odd_mask_name
204 END IF
205 WRITE (field_name, "('src2tgt_manual_',A,'_field_mask_',A,'_src_mask_',A,'_tgt_mask')") &
206 trim(with_str(with_field_mask)%string), &
207 trim(mask_type_str(source_mask_type)%string), &
208 trim(mask_type_str(target_mask_type)%string)
209 IF (source_mask_type /= 3) THEN
210 IF (target_mask_type /= 3) THEN
211 IF (is_target) THEN
212 CALL yac_fdef_couple ( &
213 src_comp_name, src_grid_name, field_name, &
214 tgt_comp_name, tgt_grid_name, field_name, &
216 interp_stack_config, 0, 0, &
217 src_mask_names = src_mask_names, &
218 tgt_mask_name = tgt_mask_name )
219 ELSE
220 CALL yac_fdef_couple (instance_id, &
221 src_comp_name, src_grid_name, field_name, &
222 tgt_comp_name, tgt_grid_name, field_name, &
224 interp_stack_config, 0, 0, &
225 src_mask_names = src_mask_names, &
226 tgt_mask_name = tgt_mask_name )
227 END IF
228 ELSE
229 IF (is_target) THEN
230 CALL yac_fdef_couple ( &
231 src_comp_name, src_grid_name, field_name, &
232 tgt_comp_name, tgt_grid_name, field_name, &
234 interp_stack_config, 0, 0, &
235 src_mask_names = src_mask_names)
236 ELSE
237 CALL yac_fdef_couple (instance_id, &
238 src_comp_name, src_grid_name, field_name, &
239 tgt_comp_name, tgt_grid_name, field_name, &
241 interp_stack_config, 0, 0, &
242 src_mask_names = src_mask_names)
243 END IF
244 END IF
245 ELSE
246 IF (target_mask_type /= 3) THEN
247 IF (is_target) THEN
248 CALL yac_fdef_couple ( &
249 src_comp_name, src_grid_name, field_name, &
250 tgt_comp_name, tgt_grid_name, field_name, &
252 interp_stack_config, 0, 0, &
253 tgt_mask_name = tgt_mask_name )
254 ELSE
255 CALL yac_fdef_couple (instance_id, &
256 src_comp_name, src_grid_name, field_name, &
257 tgt_comp_name, tgt_grid_name, field_name, &
259 interp_stack_config, 0, 0, &
260 tgt_mask_name = tgt_mask_name )
261 END IF
262 ELSE
263 IF (is_target) THEN
264 CALL yac_fdef_couple ( &
265 src_comp_name, src_grid_name, field_name, &
266 tgt_comp_name, tgt_grid_name, field_name, &
268 interp_stack_config, 0, 0)
269 ELSE
270 CALL yac_fdef_couple (instance_id, &
271 src_comp_name, src_grid_name, field_name, &
272 tgt_comp_name, tgt_grid_name, field_name, &
274 interp_stack_config, 0, 0)
275 END IF
276 END IF
277 END IF
278 END DO
279 END DO
280 END DO
281 CALL yac_ffree_interp_stack_config(interp_stack_config)
282
283 IF (is_target) THEN
284 CALL yac_fenddef()
285 ELSE
286 CALL yac_fenddef(instance_id)
287 END IF
288
289 send_field = &
290 reshape( &
291 (/ 1, 2, 3, 4, 5, 6, 7, 8, 9, &
292 11,12,13,14,15,16,17,18,19, &
293 21,22,23,24,25,26,27,28,29/), &
294 (/num_points, num_pointsets, collection_size/))
295
296 DO j = 1, collection_size
297 recv_field_ptr(j)%p => recv_field(:,j)
298 END DO
299
300 ! initalize buffer_ptr with empty pointers (only used for empty_source)
301 DO i=1,num_pointsets
302 DO j=1,collection_size
303 buffer_ptr(i,j)%p => buffer
304 END DO
305 END DO
306
307 ! do time steps
308 DO t = 1, 4
309
310 IF (.NOT. is_target) THEN
311
312 DO config_from_file = 1, 2
313 DO with_field_mask = 1, 2
314 DO source_mask_type = 1, 3
315 DO target_mask_type = 1, 3
316 IF(is_empty_source)THEN
317 CALL yac_fput( &
318 field_ids(target_mask_type, source_mask_type, &
319 with_field_mask, config_from_file), &
320 num_pointsets, collection_size, &
321 buffer_ptr, info, ierror)
322 ELSE
323 CALL yac_fput( &
324 field_ids(target_mask_type, source_mask_type, &
325 with_field_mask, config_from_file), &
326 num_points, num_pointsets, collection_size, &
327 send_field, info, ierror)
328 ENDIF
329 CALL yac_fwait( &
330 field_ids(target_mask_type, source_mask_type, &
331 with_field_mask, config_from_file))
332 CALL test(ierror == 0)
333 CALL test(info == yac_action_coupling)
334
335 END DO
336 END DO
337 END DO
338 END DO
339
340 ELSE
341
342 DO config_from_file = 1, 2
343 DO with_field_mask = 1, 2
344 DO source_mask_type = 1, 3
345 DO target_mask_type = 1, 3
346
347 ! initialise recv_field
348 recv_field = -1
349
350 IF (iand(t, 1) == 1) THEN
351 CALL yac_fget( &
352 field_ids(target_mask_type, source_mask_type, &
353 with_field_mask, config_from_file), &
354 num_points, collection_size, &
355 recv_field, info, ierror)
356 ELSE
357 CALL yac_fget_async( &
358 field_ids(target_mask_type, source_mask_type, &
359 with_field_mask, config_from_file), &
360 collection_size, recv_field_ptr, info, ierror)
361 CALL yac_fwait( &
362 field_ids(target_mask_type, source_mask_type, &
363 with_field_mask, config_from_file))
364 END IF
365 CALL test(ierror == 0)
366 CALL test(info == yac_action_coupling)
367
368 DO j = 1, collection_size
369 DO k = 1, num_points
370 check_recv_field = &
371 check_tgt( &
372 recv_field(k,j), k, j, with_field_mask == 2, &
373 target_mask_type, source_mask_type)
374 CALL test(.NOT. check_recv_field)
375 END DO
376 END DO
377 END DO
378 END DO
379 END DO
380 END DO
381
382 END IF
383
384 END DO
385
386 IF (is_target) THEN
387 CALL yac_ffinalize()
388 ELSE
389 CALL yac_ffinalize(instance_id)
390 END IF
391
392 CALL mpi_finalize(ierror)
393
394 CALL stop_test
395 CALL exit_tests
396
397! ----------------------------------------------------------
398
399CONTAINS
400
401 SUBROUTINE error_exit ()
402
403 USE mpi, ONLY : mpi_abort, mpi_comm_world
404 USE utest
405
406 INTEGER :: ierror
407
408 CALL test ( .false. )
409 CALL stop_test
410 CALL exit_tests
411 CALL mpi_abort ( mpi_comm_world, 999, ierror )
412
413 END SUBROUTINE error_exit
414
415 FUNCTION check_src_even_mask(value, idx, collection_idx, with_field_mask)
416 DOUBLE PRECISION, INTENT(IN) :: value
417 INTEGER, INTENT(IN) :: idx
418 INTEGER, INTENT(IN) :: collection_idx
419 LOGICAL, INTENT(IN) :: with_field_mask
420 LOGICAL :: check_src_even_mask
421
422 nop(idx)
423 nop(collection_idx)
424 nop(with_field_mask)
425 check_src_even_mask = (value < 0.0) .OR. (iand(int(value), 1) /= 0)
426 END FUNCTION
427
428 FUNCTION check_src_odd_mask(value, idx, collection_idx, with_field_mask)
429 DOUBLE PRECISION, INTENT(IN) :: value
430 INTEGER, INTENT(IN) :: idx
431 INTEGER, INTENT(IN) :: collection_idx
432 LOGICAL, INTENT(IN) :: with_field_mask
433 LOGICAL :: check_src_odd_mask
434
435 nop(idx)
436 nop(collection_idx)
437 nop(with_field_mask)
438 check_src_odd_mask = (value < 0.0) .OR. (iand(int(value), 1) /= 1)
439 END FUNCTION
440
441 FUNCTION check_src_no_mask(value, idx, collection_idx, with_field_mask)
442 DOUBLE PRECISION, INTENT(IN) :: value
443 INTEGER, INTENT(IN) :: idx
444 INTEGER, INTENT(IN) :: collection_idx
445 LOGICAL, INTENT(IN) :: with_field_mask
446 LOGICAL :: check_src_no_mask
447
448 check_src_no_mask = &
449 merge( &
450 int(value) /= 1 + 10 * (collection_idx - 1), &
451 int(value) /= idx + 10 * (collection_idx - 1), with_field_mask)
452 END FUNCTION
453
454 FUNCTION check_tgt_even_mask( &
455 value, idx, with_field_mask, check_src)
456 DOUBLE PRECISION, INTENT(IN) :: value
457 INTEGER, INTENT(IN) :: idx
458 LOGICAL, INTENT(IN) :: with_field_mask
459 LOGICAL :: check_src
460 LOGICAL :: check_tgt_even_mask
461
462 nop(with_field_mask)
463 check_tgt_even_mask = merge(check_src, value /= -1.0d0, iand(idx, 1) == 0)
464 END FUNCTION
465
466 FUNCTION check_tgt_odd_mask( &
467 value, idx, with_field_mask, check_src)
468 DOUBLE PRECISION, INTENT(IN) :: value
469 INTEGER, INTENT(IN) :: idx
470 LOGICAL, INTENT(IN) :: with_field_mask
471 LOGICAL :: check_src
472 LOGICAL :: check_tgt_odd_mask
473
474 nop(with_field_mask)
475 check_tgt_odd_mask = merge(check_src, value /= -1.0d0, iand(idx, 1) == 1)
476 END FUNCTION
477
478 FUNCTION check_tgt_no_mask( &
479 value, idx, with_field_mask, check_src)
480 DOUBLE PRECISION, INTENT(IN) :: value
481 INTEGER, INTENT(IN) :: idx
482 LOGICAL, INTENT(IN) :: with_field_mask
483 LOGICAL :: check_src
484 LOGICAL :: check_tgt_no_mask
485
486 check_tgt_no_mask = &
487 merge(value /= -1.0d0, check_src, with_field_mask .AND. (idx /= 1))
488 END FUNCTION
489
490 FUNCTION check_src( &
491 value, idx, collection_idx, with_field_mask, source_mask_type)
492 DOUBLE PRECISION, INTENT(IN) :: value
493 INTEGER, INTENT(IN) :: idx
494 INTEGER, INTENT(IN) :: collection_idx
495 LOGICAL, INTENT(IN) :: with_field_mask
496 INTEGER :: source_mask_type
497 LOGICAL :: check_src
498
499 SELECT CASE (source_mask_type)
500 CASE (1)
501 check_src = &
502 check_src_even_mask( &
503 value, idx, collection_idx, with_field_mask)
504 CASE (2)
505 check_src = &
506 check_src_odd_mask( &
507 value, idx, collection_idx, with_field_mask)
508 CASE (3)
509 check_src = &
510 check_src_no_mask( &
511 value, idx, collection_idx, with_field_mask)
512 CASE DEFAULT
513 check_src = .true.
514 END SELECT
515 END FUNCTION
516
517 FUNCTION check_tgt( &
518 value, idx, collection_idx, with_field_mask, &
519 target_mask_type, source_mask_type)
520 DOUBLE PRECISION, INTENT(IN) :: value
521 INTEGER, INTENT(IN) :: idx
522 INTEGER, INTENT(IN) :: collection_idx
523 LOGICAL, INTENT(IN) :: with_field_mask
524 INTEGER :: target_mask_type
525 INTEGER :: source_mask_type
526 LOGICAL :: check_tgt
527
528 SELECT CASE (target_mask_type)
529 CASE (1)
530 check_tgt = &
531 check_tgt_even_mask( &
532 value, idx, with_field_mask, &
533 check_src( &
534 value, idx, collection_idx, with_field_mask, &
535 source_mask_type))
536 CASE (2)
537 check_tgt = &
538 check_tgt_odd_mask( &
539 value, idx, with_field_mask, &
540 check_src( &
541 value, idx, collection_idx, with_field_mask, &
542 source_mask_type))
543 CASE (3)
544 check_tgt = &
545 check_tgt_no_mask( &
546 value, idx, with_field_mask, &
547 check_src( &
548 value, idx, collection_idx, with_field_mask, &
549 source_mask_type))
550 CASE DEFAULT
551 check_tgt = .true.
552 END SELECT
553 END FUNCTION
554
555END PROGRAM main
Fortran interface for definition of a couple.
Fortran interface for the definition of coupling fields using explicit masks.
Fortran interface for the definition of coupling fields using default masks.
Fortran interface for the definition of grids.
Fortran interface for the definition of masks.
Fortran interface for the definition of points.
Fortran interface for invoking the end of the definition phase.
Fortran interface for the coupler termination.
Fortran interface for asynchronous receiving coupling fields.
Fortran interfaces for the definition of an interpolation stack.
Fortran interface for receiving coupling fields.
Fortran interface for sending coupling fields.
Fortran interface for the reading of configuration files.
Fortran interface for testing fields for active communicaitons.
static void merge(char *base_a, size_t num_a, int a_ascending, char *base_b, size_t num_b, int b_ascending, size_t size, int(*compar)(const void *, const void *), char *target)
Definition mergesort.c:56
Definition utest.F90:5
subroutine, public start_test(name)
Definition utest.F90:20
subroutine, public stop_test()
Definition utest.F90:27
subroutine, public exit_tests()
Definition utest.F90:81
@ yac_location_corner
@ yac_time_unit_second
@ yac_action_coupling
data exchange
@ yac_nnn_avg
@ yac_proleptic_gregorian
@ yac_reduction_time_none
subroutine error_exit()