YAC 3.21.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_fortran_api.F90
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 "test_macros.inc"
6
11
12#define NOP(x) associate( x => x ); end associate
13
14PROGRAM main
15
16 use, INTRINSIC :: iso_c_binding
17 USE utest
18 USE yac_core
19 USE mpi
20
21 IMPLICIT NONE
22
23 INTERFACE
24
25 SUBROUTINE utest_c_free ( ptr ) bind ( c, name='free' )
26
27 use, INTRINSIC :: iso_c_binding, only : c_ptr
28
29 TYPE ( c_ptr ), INTENT(IN), VALUE :: ptr
30
31 END SUBROUTINE utest_c_free
32
33 END INTERFACE
34
35 INTEGER :: ierror
36
37 REAL(kind=c_double), PARAMETER :: &
38 yac_rad = 0.017453292519943295769_c_double ! M_PI / 180
39
40 TYPE(c_ptr) :: basic_grid_empty
41 TYPE(c_ptr) :: basic_grid_reg_2d
42 TYPE(c_ptr) :: basic_grid_reg_2d_deg
43 TYPE(c_ptr) :: basic_grid_curve_2d
44 TYPE(c_ptr) :: basic_grid_curve_2d_deg
45 TYPE(c_ptr) :: basic_grid_unstruct
46 TYPE(c_ptr) :: basic_grid_unstruct_deg
47 TYPE(c_ptr) :: basic_grid_unstruct_ll
48 TYPE(c_ptr) :: basic_grid_unstruct_ll_deg
49 TYPE(c_ptr) :: basic_grid_unstruct_edge
50 TYPE(c_ptr) :: basic_grid_unstruct_edge_deg
51 TYPE(c_ptr) :: basic_grid_unstruct_edge_ll
52 TYPE(c_ptr) :: basic_grid_unstruct_edge_ll_deg
53 TYPE(c_ptr) :: basic_grid_cloud
54 TYPE(c_ptr) :: basic_grid_cloud_deg
55 TYPE(c_ptr) :: basic_grid_reg_2d_rot
56 TYPE(c_ptr) :: basic_grid_reg_2d_rot_deg
57 INTEGER(kind=c_size_t) :: num_cells
58 INTEGER(kind=c_size_t) :: num_corners
59 INTEGER(kind=c_size_t) :: num_edges
60 REAL(kind=c_double), ALLOCATABLE :: cell_areas(:)
61
62 REAL(kind=c_double) :: &
63 cell_coords(3) = (/1.0_c_double, 0.0_c_double, 0.0_c_double/)
64 INTEGER(kind=c_int) :: cell_mask(1) = (/1_c_int/)
65 INTEGER(kind=c_size_t) :: cell_coord_idx, cell_coord_ll_idx
66 INTEGER(kind=c_size_t) :: cell_mask_idx, cell_mask_ll_idx
67
68 TYPE(c_ptr) :: grid_pair
69 TYPE(c_ptr) :: interp_grid
70 TYPE(c_ptr) :: interp_stack_config
71 TYPE(c_ptr) :: interp_stack_config_cpy
72
73 ! data types required to generate extended spmap configuration
74 TYPE(c_ptr) :: scale_config
75 TYPE(c_ptr) :: spmap_config
76 TYPE(c_ptr) :: src_point_selection
77 TYPE(c_ptr) :: source_cell_area_config, target_cell_area_config
78 TYPE(c_ptr) :: overwrite_spmap_config
79 TYPE(c_ptr) :: overwrite_config
80 TYPE(c_ptr), TARGET :: overwrite_configs(2)
81
82 INTEGER(kind=c_int) :: compare_value, test_value
83 LOGICAL :: ltest_value
84
85 INTEGER, TARGET :: do_search_call_count
86 INTEGER, TARGET :: constructor_call_count
87 TYPE(c_ptr) :: interp_method
88 TYPE(c_ptr) :: interp_weights
89 TYPE(c_ptr) :: collection_selection
90 TYPE(c_ptr) :: interpolation_gen_config
91 TYPE(c_ptr) :: interpolation_gen_config_copy
92 TYPE(c_ptr) :: interpolation
93 TYPE(c_ptr) :: interpolation_frac
94 TYPE(c_ptr) :: interpolation_ext
95
96 REAL(kind=c_double), TARGET :: src_cell_data(1)
97 TYPE(c_ptr), TARGET :: src_field_(1)
98 TYPE(c_ptr), TARGET :: src_field_collection(1)
99 REAL(kind=c_double), TARGET :: src_frac_mask(1)
100 TYPE(c_ptr), TARGET :: src_frac_mask_(1)
101 TYPE(c_ptr), TARGET :: src_frac_mask_collection(1)
102 REAL(kind=c_double), TARGET :: tgt_cell_data(1)
103 TYPE(c_ptr), TARGET :: tgt_field_collection(1)
104
105 INTEGER(kind=c_int) :: has_mismatched_coordinates
106
107 INTERFACE
108 SUBROUTINE utest_c_unlink ( path ) bind ( c, name='unlink' )
109 use, INTRINSIC :: iso_c_binding, only : c_char
110 CHARACTER(KIND=c_char), DIMENSION(*) :: path
111 END SUBROUTINE utest_c_unlink
112 END INTERFACE
113
114 ! counters/results filled in by the instrumentation callbacks below,
115 ! passed to yac_instrument_set_callbacks_c as user_data
116 TYPE, BIND(C) :: instr_test_ctx_t
117 INTEGER(kind=c_int) :: create_calls
118 INTEGER(kind=c_int) :: start_calls
119 INTEGER(kind=c_int) :: stop_calls
120 INTEGER(kind=c_int) :: destroy_calls
121 INTEGER(kind=c_int) :: last_start_depth
122 INTEGER(kind=c_int) :: last_stop_depth
123 INTEGER(kind=c_int) :: bad_handle_count
124 END TYPE instr_test_ctx_t
125
126 TYPE(instr_test_ctx_t), TARGET :: instr_ctx
127 CHARACTER(len=:), ALLOCATABLE :: instr_name
128 INTEGER(kind=c_int) :: instr_start_calls_global
129
130 ! ===================================================================
131
132 CALL utest_start_test('fortran_api')
133
134 CALL yac_mpi_init_c()
135 CALL yac_yaxt_init_c(mpi_comm_world)
136
137 CALL test(yac_mpi_is_initialised_c() /= 0_c_int)
138
139 ! --- region instrumentation: name lookup + callback registration ---
140
141 instr_name = &
143 CALL test(instr_name == "target field computation (SpMV)")
144
145 instr_ctx%create_calls = 0_c_int
146 instr_ctx%start_calls = 0_c_int
147 instr_ctx%stop_calls = 0_c_int
148 instr_ctx%destroy_calls = 0_c_int
149 instr_ctx%last_start_depth = -1_c_int
150 instr_ctx%last_stop_depth = -1_c_int
151 instr_ctx%bad_handle_count = 0_c_int
152
153 ! registered before any grid/interpolation setup below, so every
154 ! subsequent interpolation execution is instrumented
156 c_funloc(utest_instrument_create_cb), &
157 c_funloc(utest_instrument_start_cb), &
158 c_funloc(utest_instrument_stop_cb), &
159 c_funloc(utest_instrument_destroy_cb), &
160 c_loc(instr_ctx))
161
162 ! empty grids
163 basic_grid_empty = &
164 yac_basic_grid_empty_new_c("empty_grid" // c_null_char)
165 num_cells = &
167 basic_grid_empty, int(yac_loc_cell, c_int))
168 CALL test(num_cells == 0_c_int)
169
170 ! regular 2d grid (rad coords)
171 basic_grid_reg_2d = &
173 "reg_2d_grid" // c_null_char, &
174 (/2_c_size_t, 2_c_size_t/), (/0_c_int, 0_c_int/), &
175 (/-0.1_c_double, 0.1_c_double/), (/-0.1_c_double, 0.1_c_double/))
176 num_corners = &
178 basic_grid_reg_2d, int(yac_loc_corner, c_int))
179 CALL test(num_corners == 4_c_int)
180
181 ALLOCATE( &
182 cell_areas( &
183 int( &
185 basic_grid_reg_2d, int(yac_loc_cell, c_int)))))
186 cell_areas(:) = -1.0_c_double
187 CALL yac_basic_grid_compute_cell_areas_c(basic_grid_reg_2d, cell_areas)
188 CALL test(all(cell_areas(:) /= -1.0_c_double))
189 DEALLOCATE(cell_areas)
190
191 ! regular 2d grid (deg coords)
192 basic_grid_reg_2d_deg = &
194 "reg_2d_grid_deg" // c_null_char, &
195 (/2_c_size_t, 2_c_size_t/), (/0_c_int, 0_c_int/), &
196 (/-0.1_c_double, 0.1_c_double/), (/-0.1_c_double, 0.1_c_double/))
197 num_corners = &
199 basic_grid_reg_2d_deg, int(yac_loc_corner, c_int))
200 CALL test(num_corners == 4_c_int)
201
202 ! curvilinear 2d grid (rad coords)
203 basic_grid_curve_2d = &
205 "curve_2d_grid" // c_null_char, &
206 (/2_c_size_t, 2_c_size_t/), (/0_c_int, 0_c_int/), &
207 (/-0.1_c_double, 0.1_c_double, -0.1_c_double, 0.1_c_double/), &
208 (/-0.1_c_double, -0.1_c_double, 0.1_c_double, 0.1_c_double/))
209 num_edges = &
211 basic_grid_curve_2d, int(yac_loc_edge, c_int))
212 CALL test(num_edges == 4_c_int)
213
214 ! curvilinear 2d grid (deg coords)
215 basic_grid_curve_2d_deg = &
217 "curve_2d_grid_deg" // c_null_char, &
218 (/2_c_size_t, 2_c_size_t/), (/0_c_int, 0_c_int/), &
219 (/-0.1_c_double, 0.1_c_double, -0.1_c_double, 0.1_c_double/), &
220 (/-0.1_c_double, -0.1_c_double, 0.1_c_double, 0.1_c_double/))
221 num_edges = &
223 basic_grid_curve_2d_deg, int(yac_loc_edge, c_int))
224 CALL test(num_edges == 4_c_int)
225
226 ! unstructured grid (rad coords)
227 basic_grid_unstruct = &
229 "unstruct_grid" // c_null_char, &
230 4_c_size_t, 1_c_size_t, (/4_c_int/), &
231 (/-0.1_c_double, 0.1_c_double, 0.1_c_double, -0.1_c_double/), &
232 (/-0.1_c_double, -0.1_c_double, 0.1_c_double, 0.1_c_double/), &
233 (/0_c_int, 1_c_int, 2_c_int, 3_c_int/))
234 num_edges = &
236 basic_grid_unstruct, int(yac_loc_edge, c_int))
237 CALL test(num_edges == 4_c_int)
238
239 ! unstructured grid (deg coords)
240 basic_grid_unstruct_deg = &
242 "unstruct_grid_deg" // c_null_char, &
243 4_c_size_t, 1_c_size_t, (/4_c_int/), &
244 (/-0.1_c_double, 0.1_c_double, 0.1_c_double, -0.1_c_double/), &
245 (/-0.1_c_double, -0.1_c_double, 0.1_c_double, 0.1_c_double/), &
246 (/0_c_int, 1_c_int, 2_c_int, 3_c_int/))
247 num_edges = &
249 basic_grid_unstruct_deg, int(yac_loc_edge, c_int))
250 CALL test(num_edges == 4_c_int)
251
252 ! unstructured grid (rad coords)
253 basic_grid_unstruct_ll = &
255 "unstruct_grid_ll" // c_null_char, &
256 4_c_size_t, 1_c_size_t, (/4_c_int/), &
257 (/-0.1_c_double, 0.1_c_double, 0.1_c_double, -0.1_c_double/), &
258 (/-0.1_c_double, -0.1_c_double, 0.1_c_double, 0.1_c_double/), &
259 (/0_c_int, 1_c_int, 2_c_int, 3_c_int/))
260 num_edges = &
262 basic_grid_unstruct_ll, int(yac_loc_edge, c_int))
263 CALL test(num_edges == 4_c_int)
264
265 ! unstructured grid (deg coords)
266 basic_grid_unstruct_ll_deg = &
268 "unstruct_grid_ll_deg" // c_null_char, &
269 4_c_size_t, 1_c_size_t, (/4_c_int/), &
270 (/-0.1_c_double, 0.1_c_double, 0.1_c_double, -0.1_c_double/), &
271 (/-0.1_c_double, -0.1_c_double, 0.1_c_double, 0.1_c_double/), &
272 (/0_c_int, 1_c_int, 2_c_int, 3_c_int/))
273 num_edges = &
275 basic_grid_unstruct_ll_deg, int(yac_loc_edge, c_int))
276 CALL test(num_edges == 4_c_int)
277
278 ! unstructured grid (rad coords)
279 basic_grid_unstruct_edge = &
281 "unstruct_edge_grid" // c_null_char, &
282 4_c_size_t, 1_c_size_t, 4_c_size_t, (/4_c_int/), &
283 (/-0.1_c_double, 0.1_c_double, 0.1_c_double, -0.1_c_double/), &
284 (/-0.1_c_double, -0.1_c_double, 0.1_c_double, 0.1_c_double/), &
285 (/0_c_int, 1_c_int, 2_c_int, 3_c_int/), &
286 (/0_c_int, 1_c_int, 1_c_int, 2_c_int, &
287 2_c_int, 3_c_int, 3_c_int, 0_c_int/))
288 num_edges = &
290 basic_grid_unstruct_edge, int(yac_loc_edge, c_int))
291 CALL test(num_edges == 4_c_int)
292
293 ! unstructured grid (deg coords)
294 basic_grid_unstruct_edge_deg = &
296 "unstruct_grid_edge_deg" // c_null_char, &
297 4_c_size_t, 1_c_size_t, 4_c_size_t, (/4_c_int/), &
298 (/-0.1_c_double, 0.1_c_double, 0.1_c_double, -0.1_c_double/), &
299 (/-0.1_c_double, -0.1_c_double, 0.1_c_double, 0.1_c_double/), &
300 (/0_c_int, 1_c_int, 2_c_int, 3_c_int/), &
301 (/0_c_int, 1_c_int, 1_c_int, 2_c_int, &
302 2_c_int, 3_c_int, 3_c_int, 0_c_int/))
303 num_edges = &
305 basic_grid_unstruct_edge_deg, int(yac_loc_edge, c_int))
306 CALL test(num_edges == 4_c_int)
307
308 ! unstructured grid (rad coords)
309 basic_grid_unstruct_edge_ll = &
311 "unstruct_grid_edge_ll" // c_null_char, &
312 4_c_size_t, 1_c_size_t, 4_c_size_t, (/4_c_int/), &
313 (/-0.1_c_double, 0.1_c_double, 0.1_c_double, -0.1_c_double/), &
314 (/-0.1_c_double, -0.1_c_double, 0.1_c_double, 0.1_c_double/), &
315 (/0_c_int, 1_c_int, 2_c_int, 3_c_int/), &
316 (/0_c_int, 1_c_int, 1_c_int, 2_c_int, &
317 2_c_int, 3_c_int, 3_c_int, 0_c_int/))
318 num_edges = &
320 basic_grid_unstruct_edge_ll, int(yac_loc_edge, c_int))
321 CALL test(num_edges == 4_c_int)
322
323 ! unstructured grid (deg coords)
324 basic_grid_unstruct_edge_ll_deg = &
326 "unstruct_grid_edge_ll_deg" // c_null_char, &
327 4_c_size_t, 1_c_size_t, 4_c_size_t, (/4_c_int/), &
328 (/-0.1_c_double, 0.1_c_double, 0.1_c_double, -0.1_c_double/), &
329 (/-0.1_c_double, -0.1_c_double, 0.1_c_double, 0.1_c_double/), &
330 (/0_c_int, 1_c_int, 2_c_int, 3_c_int/), &
331 (/0_c_int, 1_c_int, 1_c_int, 2_c_int, &
332 2_c_int, 3_c_int, 3_c_int, 0_c_int/))
333 num_edges = &
335 basic_grid_unstruct_edge_ll_deg, int(yac_loc_edge, c_int))
336 CALL test(num_edges == 4_c_int)
337
338 ! cloud grid (rad coords)
339 basic_grid_cloud = &
341 "cloud_grid" // c_null_char, 4_c_size_t, &
342 (/-0.1_c_double, 0.1_c_double, 0.1_c_double, -0.1_c_double/), &
343 (/-0.1_c_double, -0.1_c_double, 0.1_c_double, 0.1_c_double/))
344 num_cells = &
346 basic_grid_cloud, int(yac_loc_cell, c_int))
347 num_corners = &
349 basic_grid_cloud, int(yac_loc_corner, c_int))
350 num_edges = &
352 basic_grid_cloud, int(yac_loc_edge, c_int))
353 CALL test(num_cells == 0_c_int)
354 CALL test(num_corners == 4_c_int)
355 CALL test(num_edges == 0_c_int)
356
357 ! cloud grid (deg coords)
358 basic_grid_cloud_deg = &
360 "cloud_grid" // c_null_char, 4_c_size_t, &
361 (/-0.1_c_double, 0.1_c_double, 0.1_c_double, -0.1_c_double/), &
362 (/-0.1_c_double, -0.1_c_double, 0.1_c_double, 0.1_c_double/))
363 num_cells = &
365 basic_grid_cloud_deg, int(yac_loc_cell, c_int))
366 num_corners = &
368 basic_grid_cloud_deg, int(yac_loc_corner, c_int))
369 num_edges = &
371 basic_grid_cloud_deg, int(yac_loc_edge, c_int))
372 CALL test(num_cells == 0_c_int)
373 CALL test(num_corners == 4_c_int)
374 CALL test(num_edges == 0_c_int)
375
376 ! rotated regular 2d grid (rad coords)
377 basic_grid_reg_2d_rot = &
379 "reg_2d_grid_deg" // c_null_char, &
380 (/2_c_size_t, 2_c_size_t/), (/0_c_int, 0_c_int/), &
381 (/-0.5_c_double, 0.5_c_double/) * yac_rad, &
382 (/-0.5_c_double, 0.5_c_double/) * yac_rad, &
383 180.0_c_double * yac_rad, 45.0_c_double * yac_rad)
384 num_corners = &
386 basic_grid_reg_2d_rot, int(yac_loc_corner, c_int))
387 CALL test(num_corners == 4_c_int)
388
389 ! rotated regular 2d grid (deg coords)
390 basic_grid_reg_2d_rot_deg = &
392 "reg_2d_grid_deg" // c_null_char, &
393 (/2_c_size_t, 2_c_size_t/), (/0_c_int, 0_c_int/), &
394 (/-0.5_c_double, 0.5_c_double/), &
395 (/-0.5_c_double, 0.5_c_double/), &
396 180.0_c_double, 45.0_c_double)
397 num_corners = &
399 basic_grid_reg_2d_rot_deg, int(yac_loc_corner, c_int))
400 CALL test(num_corners == 4_c_int)
401
402 ! adding field coordinates and masks
403 cell_coord_idx = &
405 basic_grid_unstruct, yac_loc_cell, cell_coords, 1_c_size_t)
406 cell_coord_ll_idx = &
408 basic_grid_unstruct_ll, yac_loc_cell, cell_coords, 1_c_size_t)
409 cell_mask_idx = &
411 basic_grid_unstruct, yac_loc_cell, cell_mask, 1_c_size_t, &
412 "cell_mask" // c_null_char)
413 cell_mask_ll_idx = &
415 basic_grid_unstruct_ll, yac_loc_cell, cell_mask, 1_c_size_t, &
416 "cell_mask_ll" // c_null_char)
417
418 has_mismatched_coordinates = &
420 basic_grid_unstruct, is_fatal=0_c_int)
421 CALL test(has_mismatched_coordinates == 0_c_int)
422
423 ! distributed grid
424 grid_pair = &
426 basic_grid_unstruct, basic_grid_unstruct_ll, mpi_comm_world)
427
428 ! interpolation grid
429 interp_grid = &
431 grid_pair, "unstruct_grid" // c_null_char, &
432 "unstruct_grid_ll" // c_null_char, &
433 1_c_size_t, (/yac_loc_cell/), (/cell_coord_idx/), (/cell_mask_idx/), &
434 yac_loc_cell, cell_coord_ll_idx, cell_mask_ll_idx)
435
436 ! interpolation check
438 c_funloc(utest_constructor_callback), c_loc(constructor_call_count), &
439 "constructor_callback" // c_null_char)
441 c_funloc(utest_do_search_callback), c_loc(do_search_call_count), &
442 "do_search_callback" // c_null_char)
443
444 ! setup structures for extended spmap configuration
445 source_cell_area_config = &
448 target_cell_area_config = &
450 "area.nc", "cell_areas", yac_interp_spmap_min_global_id_default_f)
451 scale_config = &
454 source_cell_area_config, target_cell_area_config)
455 src_point_selection = &
457 0.0_c_double, 0.0_c_double, 0.1_c_double)
458 spmap_config = &
463 scale_config)
464 overwrite_spmap_config = &
466 0.1_c_double, &
469 scale_config)
470 overwrite_config = &
472 src_point_selection, overwrite_spmap_config)
473 overwrite_configs = (/overwrite_config, c_null_ptr/)
474
475 ! interpolation stack configuration
476 constructor_call_count = 0
477 do_search_call_count = 0
478 interp_stack_config = yac_interp_stack_config_new_c()
480 interp_stack_config, "constructor_callback" // c_null_char, &
481 "do_search_callback" // c_null_char)
483 interp_stack_config, yac_interp_nnn_weighted_default_f, &
486 interp_stack_config_cpy = &
487 yac_interp_stack_config_copy_c(interp_stack_config)
489 interp_stack_config, yac_interp_avg_weight_type_default_f, &
492 interp_stack_config, yac_interp_ncc_weight_type_default_f, &
495 interp_stack_config, yac_interp_dnn_weight_type_default_f, &
499 interp_stack_config, yac_interp_nnn_weighted_default_f, &
503 interp_stack_config, yac_interp_rbf_n_default_f, &
507 interp_stack_config, yac_interp_conserv_order_default_f, &
512 interp_stack_config, yac_interp_spmap_spread_distance_default_f, &
522 interp_stack_config, yac_interp_spmap_config_default_f, &
525 interp_stack_config, spmap_config, c_loc(overwrite_configs(1)))
526 CALL yac_interp_stack_config_add_hcsbb_c(interp_stack_config)
528 interp_stack_config, "test_fortran_api_weights.nc" // c_null_char, &
532 interp_stack_config, -1.0_c_double)
534 interp_stack_config, yac_interp_creep_distance_default_f)
536 interp_stack_config, yac_interp_check_constructor_key_default_f, &
538
539 ! clean up data structures for extended spmap configuration
540 CALL yac_spmap_overwrite_config_delete_c(overwrite_config)
541 CALL yac_interp_spmap_config_delete_c(overwrite_spmap_config)
542 CALL yac_point_selection_delete_c(src_point_selection)
543 CALL yac_interp_spmap_config_delete_c(spmap_config)
544 CALL yac_spmap_scale_config_delete_c(scale_config);
545 CALL yac_spmap_cell_area_config_delete_c(target_cell_area_config)
546 CALL yac_spmap_cell_area_config_delete_c(source_cell_area_config)
547
548 compare_value = &
550 interp_stack_config, interp_stack_config_cpy)
551 CALL test(compare_value /= 0_c_int)
552
553 ! interpolation method stack
554 CALL test(constructor_call_count == 0)
555 interp_method = &
556 yac_interp_stack_config_generate_c(interp_stack_config_cpy)
557 CALL test(constructor_call_count == 1)
558
559 ! interpolation method
560 CALL test(do_search_call_count == 0)
561 interp_weights = &
564 interp_weights, "test_fortran_api_weights.nc" // c_null_char, &
565 "unstruct_grid" // c_null_char, "unstruct_grid_ll" // c_null_char, &
566 0_c_size_t, 0_c_size_t, int(yac_weight_file_overwrite, c_int))
567 CALL test(do_search_call_count == 1)
568
569 ! interpolation
570 interpolation = &
572 interp_weights, yac_mapping_on_src, 1_c_size_t, &
574 1.0_c_double, 0.0_c_double, c_null_char, 1_c_int, 1_c_int)
575 interpolation_frac = &
577 interp_weights, yac_mapping_on_src, 1_c_size_t, &
578 0.0_c_double, 1.0_c_double, 0.0_c_double, c_null_char, 1_c_int, 1_c_int)
579 ltest_value = &
582 CALL test(ltest_value)
583
584 ! collection selection (without explicit indices)
585 collection_selection = &
587 CALL yac_collection_selection_delete_c(collection_selection)
588
589 ! collection selection (with explicit indices)
590 collection_selection = &
591 yac_collection_selection_new_c(1_c_size_t, (/0_c_size_t/))
592
593 ! interpolation generation configuration
594 interpolation_gen_config = yac_interpolation_gen_config_new_c()
596 interpolation_gen_config, yac_mapping_on_tgt)
598 interpolation_gen_config, 1_c_size_t)
600 interpolation_gen_config, collection_selection)
602 interpolation_gen_config, 1.0_c_double)
604 interpolation_gen_config, 2.0_c_double)
606 interpolation_gen_config, 2.0_c_double)
608 interpolation_gen_config, "" // c_null_char)
609 interpolation_gen_config_copy = &
610 yac_interpolation_gen_config_copy_c(interpolation_gen_config)
611
612 ! interpolation with extended configuration
613 interpolation_ext = &
615 interp_weights, interpolation_gen_config, 1_c_int, 1_c_int)
616
617 src_field_(1) = c_loc(src_cell_data(1))
618 src_field_collection(1) = c_loc(src_field_(1))
619 src_frac_mask_(1) = c_loc(src_frac_mask)
620 src_frac_mask_collection(1) = c_loc(src_frac_mask_(1))
621 tgt_field_collection(1) = c_loc(tgt_cell_data(1))
622 src_cell_data(1) = 1.0_c_double
623 src_frac_mask(1) = 0.0_c_double
624
625 tgt_cell_data(1) = -1.0_c_double
627 interpolation, c_loc(src_field_collection), c_loc(tgt_field_collection))
628 CALL test(tgt_cell_data(1) == src_cell_data(1))
629
630 tgt_cell_data(1) = -1.0_c_double
632 interpolation_frac, c_loc(src_field_collection), &
633 c_loc(src_frac_mask_collection), c_loc(tgt_field_collection))
634 CALL test(tgt_cell_data(1) == 0.0_c_double)
635
636 tgt_cell_data(1) = -1.0_c_double
637 test_value = yac_interpolation_execute_put_test_c(interpolation)
638 CALL test(test_value == 1_c_int)
640 interpolation, c_loc(src_field_collection))
642 interpolation, c_loc(tgt_field_collection))
643 CALL test(tgt_cell_data(1) == src_cell_data(1))
644
645 tgt_cell_data(1) = -1.0_c_double
647 interpolation_frac, c_loc(tgt_field_collection))
648 test_value = yac_interpolation_execute_get_test_c(interpolation_frac)
649 CALL test(test_value == 0_c_int)
650 CALL mpi_barrier(mpi_comm_world, ierror)
652 interpolation_frac, c_loc(src_field_collection), &
653 c_loc(src_frac_mask_collection))
654 CALL yac_interpolation_execute_wait_c(interpolation_frac)
655 CALL test(tgt_cell_data(1) == 0.0_c_double)
656 tgt_cell_data(1) = -1.0_c_double
657
658 ! cleanup
659 CALL yac_interpolation_delete_c(interpolation_ext)
660 CALL yac_interpolation_delete_c(interpolation_frac)
661 CALL yac_interpolation_delete_c(interpolation)
662 CALL yac_interpolation_gen_config_delete_c(interpolation_gen_config)
663 CALL yac_interpolation_gen_config_delete_c(interpolation_gen_config_copy)
664 CALL yac_collection_selection_delete_c(collection_selection)
665 CALL utest_c_unlink("test_fortran_api_weights.nc" // c_null_char)
666 CALL yac_interp_weights_delete_c(interp_weights)
668 CALL utest_c_free(interp_method)
669 CALL yac_interp_stack_config_delete_c(interp_stack_config_cpy)
670 CALL yac_interp_stack_config_delete_c(interp_stack_config)
672 CALL yac_interp_grid_delete_c(interp_grid)
673 CALL yac_dist_grid_pair_delete_c(grid_pair)
674 CALL yac_basic_grid_delete_c(basic_grid_reg_2d_rot_deg)
675 CALL yac_basic_grid_delete_c(basic_grid_reg_2d_rot)
676 CALL yac_basic_grid_delete_c(basic_grid_cloud_deg)
677 CALL yac_basic_grid_delete_c(basic_grid_cloud)
678 CALL yac_basic_grid_delete_c(basic_grid_unstruct_edge_ll_deg)
679 CALL yac_basic_grid_delete_c(basic_grid_unstruct_edge_ll)
680 CALL yac_basic_grid_delete_c(basic_grid_unstruct_edge_deg)
681 CALL yac_basic_grid_delete_c(basic_grid_unstruct_edge)
682 CALL yac_basic_grid_delete_c(basic_grid_unstruct_ll_deg)
683 CALL yac_basic_grid_delete_c(basic_grid_unstruct_ll)
684 CALL yac_basic_grid_delete_c(basic_grid_unstruct_deg)
685 CALL yac_basic_grid_delete_c(basic_grid_unstruct)
686 CALL yac_basic_grid_delete_c(basic_grid_curve_2d_deg)
687 CALL yac_basic_grid_delete_c(basic_grid_curve_2d)
688 CALL yac_basic_grid_delete_c(basic_grid_reg_2d_deg)
689 CALL yac_basic_grid_delete_c(basic_grid_reg_2d)
690 CALL yac_basic_grid_delete_c(basic_grid_empty)
691
692 ! --- Test user-oriented interpolation method config parameter API ---
693
694 ! Test convenience set/get int (nnn.n)
695 block
696 TYPE(c_ptr) :: method_config
697 INTEGER(kind=c_int) :: n_val
698
699 method_config = &
701 "nnn" // c_null_char)
703 method_config, "n" // c_null_char, 7_c_int)
705 method_config, "n" // c_null_char)
706 CALL test(n_val == 7_c_int)
707 CALL yac_interp_method_config_delete_c(method_config)
708 END block
709
710 ! Test convenience set/get dble (nnn.max_search_distance)
711 block
712 TYPE(c_ptr) :: method_config
713 REAL(kind=c_double) :: d_val
714
715 method_config = &
717 "nnn" // c_null_char)
719 method_config, "max_search_distance" // c_null_char, 0.5_c_double)
721 method_config, "max_search_distance" // c_null_char)
722 CALL test(d_val == 0.5_c_double)
723 CALL yac_interp_method_config_delete_c(method_config)
724 END block
725
726 ! Test convenience set/get str (nnn.weighted)
727 block
728 TYPE(c_ptr) :: method_config
729 CHARACTER(kind=c_char, len=64) :: str_buf
730
731 method_config = &
732 yac_interp_method_config_default_from_name_new_c( &
733 "nnn" // c_null_char)
734 CALL yac_interp_method_config_set_param_str_c( &
735 method_config, "weighted" // c_null_char, &
736 "gauss_weighted" // c_null_char)
737 CALL yac_interp_method_config_get_param_str_c( &
738 method_config, "weighted" // c_null_char, &
739 str_buf, int(len(str_buf), c_int))
740 CALL test(str_buf(1:14) == "gauss_weighted")
741 CALL yac_interp_method_config_delete_c(method_config)
742 END block
743
744 ! Test convenience with dot-separated path (dnn.search_distance.fixed)
745 block
746 TYPE(c_ptr) :: method_config
747 REAL(kind=c_double) :: d_val
748
749 method_config = &
750 yac_interp_method_config_default_from_name_new_c( &
751 "dnn" // c_null_char)
752 CALL yac_interp_method_config_set_param_dble_c( &
753 method_config, "search_distance.fixed" // c_null_char, &
754 1.0_c_double * yac_rad)
755 d_val = yac_interp_method_config_get_param_dble_c( &
756 method_config, "search_distance.fixed" // c_null_char)
757 CALL test(d_val == 1.0_c_double * yac_rad)
758 CALL yac_interp_method_config_delete_c(method_config)
759 END block
760
761 ! Test add to interp stack via generic yac_interp_stack_config_add_c
762 block
763 TYPE(c_ptr) :: method_config, stack
764
765 method_config = &
766 yac_interp_method_config_default_from_name_new_c( &
767 "nnn" // c_null_char)
768 CALL yac_interp_method_config_set_param_int_c( &
769 method_config, "n" // c_null_char, 3_c_int)
770 stack = yac_interp_stack_config_new_c()
771 CALL yac_interp_stack_config_add_c(stack, method_config)
772 CALL yac_interp_stack_config_delete_c(stack)
773 END block
774
775 ! Test list parameter: spmap overwrite list (get_list_size, append, index path)
776 block
777 TYPE(c_ptr) :: method_config
778 INTEGER(kind=c_size_t) :: list_sz, idx0, idx1
779 REAL(kind=c_double) :: sd0, sd1
780
781 method_config = &
782 yac_interp_method_config_default_from_name_new_c( &
783 "spmap" // c_null_char)
784
785 ! Initially empty
786 list_sz = yac_interp_method_config_get_list_size_c( &
787 method_config, "overwrite" // c_null_char)
788 CALL test(list_sz == 0_c_size_t)
789
790 ! Append first element
791 idx0 = yac_interp_method_config_append_list_element_c( &
792 method_config, "overwrite" // c_null_char)
793 CALL test(idx0 == 0_c_size_t)
794
795 ! Set spread_distance of element 0 via index path "overwrite.0.spread_distance"
796 CALL yac_interp_method_config_set_param_dble_c( &
797 method_config, "overwrite.0.spread_distance" // c_null_char, 0.05_c_double)
798 sd0 = yac_interp_method_config_get_param_dble_c( &
799 method_config, "overwrite.0.spread_distance" // c_null_char)
800 CALL test(sd0 == 0.05_c_double)
801
802 ! Append second element
803 idx1 = yac_interp_method_config_append_list_element_c( &
804 method_config, "overwrite" // c_null_char)
805 CALL test(idx1 == 1_c_size_t)
806
807 CALL yac_interp_method_config_set_param_dble_c( &
808 method_config, "overwrite.1.spread_distance" // c_null_char, 0.10_c_double)
809 sd1 = yac_interp_method_config_get_param_dble_c( &
810 method_config, "overwrite.1.spread_distance" // c_null_char)
811 CALL test(sd1 == 0.10_c_double)
812
813 ! First element must remain unchanged
814 sd0 = yac_interp_method_config_get_param_dble_c( &
815 method_config, "overwrite.0.spread_distance" // c_null_char)
816 CALL test(sd0 == 0.05_c_double)
817
818 CALL yac_interp_method_config_delete_c(method_config)
819 END block
820
821 ! --- region instrumentation: verify the callbacks registered above
822 ! actually fired during the interpolation executions further up, and
823 ! that clearing callbacks destroys every resolved region's handle ---
824 !
825 ! Per-rank call counts depend on the domain decomposition (a rank may end
826 ! up with no local interpolation work at all), so only invariants that
827 ! must hold regardless of whether this particular rank did any work are
828 ! checked per-rank; whether instrumentation fired *somewhere* is checked
829 ! via a global reduction across all ranks.
830
831 CALL test(instr_ctx%start_calls == instr_ctx%stop_calls)
832 CALL test(instr_ctx%bad_handle_count == 0_c_int)
833 CALL test(instr_ctx%destroy_calls == 0_c_int)
834 IF (instr_ctx%start_calls > 0_c_int) &
835 CALL test(instr_ctx%last_start_depth >= 0_c_int)
836 IF (instr_ctx%stop_calls > 0_c_int) &
837 CALL test(instr_ctx%last_stop_depth >= 0_c_int)
838
839 CALL mpi_allreduce( &
840 instr_ctx%start_calls, instr_start_calls_global, 1, mpi_integer, &
841 mpi_sum, mpi_comm_world, ierror)
842 CALL test(instr_start_calls_global > 0)
843
844 CALL yac_instrument_clear_callbacks_c()
845
846 CALL test(instr_ctx%destroy_calls == instr_ctx%create_calls)
847
848 CALL yac_mpi_cleanup_c()
849 CALL yac_mpi_finalize_c()
850
851 CALL utest_stop_test
852 CALL utest_exit_tests
853
854CONTAINS
855
856 SUBROUTINE utest_constructor_callback(user_data) BIND(C)
857
858 TYPE(c_ptr), value :: user_data
859
860 INTEGER, POINTER :: constructor_call_count
861
862 CALL c_f_pointer(user_data, constructor_call_count)
863
864 constructor_call_count = constructor_call_count + 1
865
866 END SUBROUTINE utest_constructor_callback
867
868 SUBROUTINE utest_do_search_callback( &
869 global_ids, coordinates_xyz, count, user_data) BIND(C)
870
871 TYPE(c_ptr), value :: global_ids
872 TYPE(c_ptr), value :: coordinates_xyz
873 INTEGER(kind=c_size_t), value :: count
874 TYPE(c_ptr), value :: user_data
875
876 INTEGER, POINTER :: do_search_call_count
877
878 nop(global_ids)
879 nop(coordinates_xyz)
880 nop(count)
881
882 CALL c_f_pointer(user_data, do_search_call_count)
883
884 do_search_call_count = do_search_call_count + 1
885
886 END SUBROUTINE
887
888 FUNCTION utest_instrument_create_cb(id, user_data) BIND(C) RESULT(handle)
889
890 INTEGER(kind=c_int), VALUE :: id
891 TYPE(c_ptr), VALUE :: user_data
892 TYPE(c_ptr) :: handle
893
894 TYPE(instr_test_ctx_t), POINTER :: ctx
895
896 nop(id)
897
898 CALL c_f_pointer(user_data, ctx)
899 ctx%create_calls = ctx%create_calls + 1
900
901 ! use user_data itself as the dummy region handle: it is a fixed,
902 ! known address, so the start/stop/destroy callbacks can verify they
903 ! receive the same handle back without host-associating a separate
904 ! variable (which would force gfortran to emit a stack trampoline
905 ! for this callback)
906 handle = user_data
907
908 END FUNCTION utest_instrument_create_cb
909
910 SUBROUTINE utest_instrument_start_cb( &
911 id, region_handle, depth, user_data) BIND(C)
912
913 INTEGER(kind=c_int), VALUE :: id
914 TYPE(c_ptr), VALUE :: region_handle
915 INTEGER(kind=c_int), VALUE :: depth
916 TYPE(c_ptr), VALUE :: user_data
917
918 TYPE(instr_test_ctx_t), POINTER :: ctx
919
920 nop(id)
921
922 CALL c_f_pointer(user_data, ctx)
923 ctx%start_calls = ctx%start_calls + 1
924 ctx%last_start_depth = depth
925 IF (.NOT. c_associated(region_handle, user_data)) &
926 ctx%bad_handle_count = ctx%bad_handle_count + 1
927
928 END SUBROUTINE utest_instrument_start_cb
929
930 SUBROUTINE utest_instrument_stop_cb( &
931 id, region_handle, depth, user_data) BIND(C)
932
933 INTEGER(kind=c_int), VALUE :: id
934 TYPE(c_ptr), VALUE :: region_handle
935 INTEGER(kind=c_int), VALUE :: depth
936 TYPE(c_ptr), VALUE :: user_data
937
938 TYPE(instr_test_ctx_t), POINTER :: ctx
939
940 nop(id)
941
942 CALL c_f_pointer(user_data, ctx)
943 ctx%stop_calls = ctx%stop_calls + 1
944 ctx%last_stop_depth = depth
945 IF (.NOT. c_associated(region_handle, user_data)) &
946 ctx%bad_handle_count = ctx%bad_handle_count + 1
947
948 END SUBROUTINE utest_instrument_stop_cb
949
950 SUBROUTINE utest_instrument_destroy_cb(id, region_handle, user_data) BIND(C)
951
952 INTEGER(kind=c_int), VALUE :: id
953 TYPE(c_ptr), VALUE :: region_handle
954 TYPE(c_ptr), VALUE :: user_data
955
956 TYPE(instr_test_ctx_t), POINTER :: ctx
957
958 nop(id)
959
960 CALL c_f_pointer(user_data, ctx)
961 ctx%destroy_calls = ctx%destroy_calls + 1
962 IF (.NOT. c_associated(region_handle, user_data)) &
963 ctx%bad_handle_count = ctx%bad_handle_count + 1
964
965 END SUBROUTINE utest_instrument_destroy_cb
966
967END PROGRAM main
Definition utest.F90:5
integer(kind=c_int), parameter yac_interp_ncc_partial_coverage_default_f
Definition yac_core.F90:162
character(kind=c_char, len= *), parameter yac_interp_spmap_varname_default_f
Definition yac_core.F90:203
integer(kind=c_int), parameter yac_interp_dnn_weight_type_default_f
Definition yac_core.F90:183
integer(kind=c_int), parameter yac_interp_dnn_search_distance_type_default_f
Definition yac_core.F90:184
type(c_ptr) function yac_collection_selection_new_c(collection_size, selection_indices)
@ yac_loc_cell
Definition yac_core.F90:32
@ yac_loc_edge
Definition yac_core.F90:34
@ yac_loc_corner
Definition yac_core.F90:33
integer(kind=c_int), parameter yac_interp_nnn_weighted_default_f
Definition yac_core.F90:177
integer(kind=c_int), parameter yac_interp_avg_partial_coverage_default_f
Definition yac_core.F90:158
@ yac_instr_compute_tgt_field
Definition yac_core.F90:131
real(kind=c_double), parameter yac_interp_nnn_max_search_distance_default_f
Definition yac_core.F90:179
@ yac_weight_file_overwrite
Definition yac_core.F90:44
integer(kind=c_int), parameter yac_interp_conserv_normalisation_default_f
Definition yac_core.F90:168
integer(kind=c_int), parameter yac_interp_avg_weight_type_default_f
Definition yac_core.F90:157
integer(kind=c_size_t), parameter yac_interp_rbf_n_default_f
Definition yac_core.F90:191
integer(kind=c_int), parameter yac_interp_file_on_missing_file_default_f
Definition yac_core.F90:213
real(kind=c_double), parameter yac_interp_dnn_scale_default_f
Definition yac_core.F90:186
real(kind=c_double), parameter yac_interp_rbf_scale_default_f
Definition yac_core.F90:193
integer(kind=c_int), parameter yac_interp_spmap_min_global_id_default_f
Definition yac_core.F90:204
integer(kind=c_int), parameter yac_interp_ncc_weight_type_default_f
Definition yac_core.F90:161
@ yac_mapping_on_src
Definition yac_core.F90:221
@ yac_mapping_on_tgt
Definition yac_core.F90:222
type(c_ptr), parameter yac_interp_spmap_overwrite_default_f
Definition yac_core.F90:206
integer(kind=c_int), parameter yac_interp_spmap_weighted_default_f
Definition yac_core.F90:199
integer(kind=c_int), parameter yac_interp_conserv_order_default_f
Definition yac_core.F90:165
character(kind=c_char, len= *), parameter yac_interp_spmap_filename_default_f
Definition yac_core.F90:202
real(kind=c_double), parameter yac_interp_spmap_spread_distance_default_f
Definition yac_core.F90:197
character(len=:) function, allocatable yac_instrument_region_name_c(id)
real(kind=c_double), parameter yac_interp_nnn_gauss_scale_default_f
Definition yac_core.F90:180
character(kind=c_char, len= *), parameter yac_interp_check_constructor_key_default_f
Definition yac_core.F90:209
integer(kind=c_int), parameter yac_interp_file_on_success_default_f
Definition yac_core.F90:214
integer(kind=c_int), parameter yac_interp_conserv_partial_coverage_default_f
Definition yac_core.F90:167
real(kind=c_double), parameter yac_interp_spmap_sphere_radius_default_f
Definition yac_core.F90:201
integer(kind=c_int), parameter yac_interp_conserv_enforced_conserv_default_f
Definition yac_core.F90:166
integer(kind=c_size_t), parameter yac_interp_nnn_n_default_f
Definition yac_core.F90:178
real(kind=c_double), parameter yac_interp_rbf_max_search_distance_default_f
Definition yac_core.F90:192
real(kind=c_double), parameter yac_interp_dnn_search_distance_default_f
Definition yac_core.F90:185
type(c_ptr), parameter yac_interp_spmap_config_default_f
Definition yac_core.F90:205
real(kind=c_double), parameter yac_interp_spmap_max_search_distance_default_f
Definition yac_core.F90:198
integer(kind=c_int), parameter yac_interp_creep_distance_default_f
Definition yac_core.F90:171
character(kind=c_char, len= *), parameter yac_interp_check_do_search_key_default_f
Definition yac_core.F90:210
integer(kind=c_int), parameter yac_interp_spmap_scale_type_default_f
Definition yac_core.F90:200