ICON Community Interface 0.4.0
Loading...
Searching...
No Matches
comin_callback.F90
Go to the documentation of this file.
1
3!
4! @authors 08/2021 :: ICON Community Interface <comin@icon-model.org>
5!
6! SPDX-License-Identifier: BSD-3-Clause
7!
8! See LICENSES for license information.
9! Where software is supplied by third parties, it is indicated in the
10! headers of the routines.
11!
13
14 USE iso_c_binding, ONLY: c_int, c_char, c_ptr, c_loc, c_f_pointer
15 USE comin_setup_constants, ONLY: ep_destructor, &
16 & domain_undefined, comin_flag_device, comin_flag_write, comin_flag_read, &
17 & comin_flag_sync_halo, comin_zaxis_2d, comin_zaxis_3d
18 USE comin_state, ONLY: state
30
31 IMPLICIT NONE
32
33 PRIVATE
34
37
38#include "comin_global.inc"
39
40CONTAINS
41
46 SUBROUTINE comin_callback_register(entry_point_id, fct_ptr) &
47 & BIND(C)
48 INTEGER(kind=C_INT), INTENT(IN), VALUE :: entry_point_id
49 PROCEDURE(comin_callback_routine) :: fct_ptr
50 !
51 CHARACTER(LEN=:), ALLOCATABLE :: ep_name
52 TYPE(t_comin_callback_element), POINTER :: item
53
55 IF (state%l_primary_done) THEN
57 RETURN
58 ENDIF
59
60 ALLOCATE(item)
61 item = t_comin_callback_element(entry_point_id = entry_point_id, &
62 & plugin_info = state%current_plugin, &
63 & comin_callback = fct_ptr)
64 CALL comin_ftnlist_push_back(state%comin_callback_list, c_loc(item))
65
66 CALL comin_callback_get_ep_name(entry_point_id, ep_name)
67 CALL comin_message(" registration for '"//ep_name//"' (ep: "//&
68 &int2string(entry_point_id,'(i0)')//") associated for 3rd party plugin "//&
69 &trim(state%current_plugin%name)//" successful.", 12)
70 END SUBROUTINE comin_callback_register
71
73 ! local
74 INTEGER :: ep_loc, tp_loc
75 CHARACTER(LEN=:), ALLOCATABLE :: ep_name
76 INTEGER :: status
77 TYPE(c_ptr) :: it, cptr
78 TYPE(t_comin_callback_element), POINTER :: var_list_element
79
81 CALL comin_message(" Complete primary constructors", 0)
82
84 ALLOCATE(state%comin_callback_context(1:ep_destructor,1:state%num_plugins), stat=status)
85 IF (status /= 0) THEN
87 END IF
88 ALLOCATE(state%comin_callback_order(1:ep_destructor,1:state%num_plugins), stat=status)
89 IF (status /= 0) THEN
91 END IF
92 state%comin_callback_order = 0
94 CALL comin_ftnlist_iterator_begin(state%comin_callback_list, it)
95 DO WHILE (.not. comin_ftnlist_is_end(state%comin_callback_list,it))
96 CALL comin_ftnlist_iterator_value(it, cptr)
97 CALL c_f_pointer(cptr, var_list_element)
98
99 ep_loc = var_list_element%entry_point_id
100 tp_loc = var_list_element%plugin_info%id
101
102 associate(callback_context => state%comin_callback_context(ep_loc, tp_loc))
103 IF (.NOT. ASSOCIATED(callback_context%vl)) THEN
104 ALLOCATE(callback_context%vl)
105 ELSE
107 CALL comin_message(" WARNING:: Overwrite callback for plugin '"//&
108 &state%current_plugin%name//"' at entry point '"//ep_name//"' (ep: "//&
109 &int2string(ep_loc,'(i0)')//")", 0)
110 END IF
111 callback_context%vl = t_comin_callback_element( &
112 & entry_point_id = ep_loc, &
113 & plugin_info = var_list_element%plugin_info, &
114 & comin_callback = var_list_element%comin_callback)
115 state%comin_callback_order(ep_loc, tp_loc) = tp_loc
116 END associate
118 END DO
121 call comin_ftnlist_iterator_begin(state%comin_callback_list, it)
122 do while (.not. comin_ftnlist_is_end(state%comin_callback_list,it))
123 call comin_ftnlist_iterator_value(it, cptr)
124 call c_f_pointer(cptr, var_list_element)
125 deallocate(var_list_element)
127 end do
129 call comin_ftnlist_delete(state%comin_callback_list)
130
132 ! Note: re-ordering based on namelist settings will be implemented
133 ! in a later version of ComIn
134 ! current default: order as at registration
135
136 ! Note:
137 ! the adapter library checks for duplicates and exclusiveness of requested
138 ! variables and potentially aborts directly in comin_var_request_add
139 ! therefore no further check before secondary constructor required
140
141 END SUBROUTINE comin_callback_complete
142
145 RECURSIVE SUBROUTINE comin_callback_context_call(entry_point_id, domain_id, lacc)
146 INTEGER, INTENT(IN) :: entry_point_id
147 INTEGER, INTENT(IN) :: domain_id
148 LOGICAL, INTENT(IN) :: lacc
149 TYPE(t_comin_callback_element), POINTER :: cl
150 !PROCEDURE(comin_callback_routine), POINTER :: comin_callback_context
151 INTEGER :: thirdpi, loci
152 LOGICAL :: lcallbacks_exist
153 CHARACTER(LEN=:), ALLOCATABLE :: ep_name
154
155 ! We cant call callbacks before the primary constructors are done
156 ! and comin_callback_complete was called. (e.g. EP_FINISH)
157 if(.NOT. state%l_primary_done) RETURN
158
159 CALL comin_callback_get_ep_name(entry_point_id, ep_name)
160 CALL comin_message(" CONTEXT " // ep_name, 12)
161
163 lcallbacks_exist = SIZE(state%comin_callback_order,2) > 0
164 IF (lcallbacks_exist) lcallbacks_exist = (sum(state%comin_callback_order(entry_point_id,:)) /= 0)
165
166 IF (lcallbacks_exist) THEN
167 DO thirdpi=1,state%num_plugins
168 loci = state%comin_callback_order(entry_point_id, thirdpi)
169 NULLIFY(cl)
170 IF (loci > 0) cl => state%comin_callback_context(entry_point_id,loci)%vl
171 IF (ASSOCIATED(cl)) THEN
172 CALL comin_message(" current ep '"//ep_name//"' (ep: "//&
173 &int2string(cl%entry_point_id,'(i0)')//") for library: "//cl%plugin_info%name, 0)
174 ! undefine domain id for the call of the ComIn destructor
175 IF (entry_point_id == ep_destructor) state%current_domain_id = domain_undefined
176 IF (.NOT. lacc) CALL check_var_no_device(entry_point_id, thirdpi)
177 IF (lacc) CALL sync_vars_for_device(entry_point_id, thirdpi, comin_flag_read)
178 CALL sync_vars_for_halo_region(entry_point_id, thirdpi, comin_flag_read)
179 ! set current plugin
180 state%current_plugin => cl%plugin_info
181 ! set current entry point
182 state%current_ep = entry_point_id
183 ! set current domain id
184 state%current_domain_id = domain_id
185 CALL cl%comin_callback
186 NULLIFY(state%current_plugin)
187 CALL sync_vars_for_halo_region(entry_point_id, thirdpi, comin_flag_write)
188 IF (lacc) CALL sync_vars_for_device(entry_point_id, thirdpi, comin_flag_write)
189 ELSE
190 CALL comin_message(" entry point '"//ep_name//"' (ep: "//&
191 &int2string(entry_point_id,'(i0)')//") not associated", 12)
192 END IF
193 ENDDO
194 ELSE
195 CALL comin_message(" no calls associated with entry point '"//&
196 &ep_name//"' (ep: "//int2string(entry_point_id,'(i0)')//").", 12)
197 END IF
198 DEALLOCATE(ep_name)
199 END SUBROUTINE comin_callback_context_call
200
201 SUBROUTINE sync_vars_for_device(ep, plugin_id, rw_flag)
202 INTEGER, INTENT(IN) :: ep
203 INTEGER, INTENT(IN) :: plugin_id
204 INTEGER, INTENT(IN) :: rw_flag
205 ! locals
206 TYPE(c_ptr) :: it, cptr
207 TYPE(t_comin_var_context_item), POINTER :: item
208
209 CALL comin_ftnlist_iterator_begin(state%comin_var_list_context(ep , plugin_id)%var_list, it)
210 DO WHILE (.not. comin_ftnlist_is_end(state%comin_var_list_context(ep , plugin_id)%var_list,it))
211
212 CALL comin_ftnlist_iterator_value(it, cptr)
213 CALL c_f_pointer(cptr, item)
214
215 IF (iand(item%access_flag, comin_flag_device) == 0 .AND. &
216 & iand(item%access_flag, rw_flag) /= 0) THEN
217 CALL state%sync_device_mem(comin_var_ptr_init(item%var_item), rw_flag == comin_flag_write)
218 END IF
219 CALL comin_ftnlist_iterator_next(it)
220 END DO
221 CALL comin_ftnlist_iterator_delete(it)
222 END SUBROUTINE sync_vars_for_device
223
224 SUBROUTINE check_var_no_device(ep, plugin_id)
225 INTEGER, INTENT(IN) :: ep
226 INTEGER, INTENT(IN) :: plugin_id
227 ! locals
228 TYPE(c_ptr) :: it, cptr
229 TYPE(t_comin_var_context_item), POINTER :: item
230 CHARACTER(LEN=:), ALLOCATABLE :: ep_name
231
232 CALL comin_callback_get_ep_name(ep, ep_name)
233
234 CALL comin_ftnlist_iterator_begin(state%comin_var_list_context(ep , plugin_id)%var_list, it)
235 DO WHILE (.not. comin_ftnlist_is_end(state%comin_var_list_context(ep , plugin_id)%var_list,it))
236 CALL comin_ftnlist_iterator_value(it, cptr)
237 CALL c_f_pointer(cptr, item)
238
239 IF (iand(item%access_flag, comin_flag_device) /= 0) THEN
240 CALL comin_message("WARNING: Device access at a non-ported entrypoint (" // &
241 & ep_name // &
242 & ") requested.", 1)
243 END IF
244 CALL comin_ftnlist_iterator_next(it)
245 END DO
246 CALL comin_ftnlist_iterator_delete(it)
247 END SUBROUTINE check_var_no_device
248
249 SUBROUTINE sync_vars_for_halo_region(ep, plugin_id, rw_flag)
250 INTEGER, INTENT(IN) :: ep
251 INTEGER, INTENT(IN) :: plugin_id
252 INTEGER, INTENT(IN) :: rw_flag
253 !locals
254 INTEGER :: halo_sync_mode
255 TYPE(c_ptr) :: it, cptr
256 TYPE(t_comin_var_context_item), POINTER :: item
257 CALL comin_ftnlist_iterator_begin(state%comin_var_list_context(ep , plugin_id)%var_list, it)
258 DO WHILE (.not. comin_ftnlist_is_end(state%comin_var_list_context(ep , plugin_id)%var_list,it))
259 CALL comin_ftnlist_iterator_value(it, cptr)
260 CALL c_f_pointer(cptr, item)
261 IF (iand(item%access_flag, comin_flag_sync_halo) /= 0 .AND. &
262 & iand(item%access_flag, rw_flag) /= 0) THEN
263 CALL determine_halo_sync_mode(item, halo_sync_mode)
264 CALL state%sync_halo(comin_var_ptr_init(item%var_item), halo_sync_mode)
265 END IF
266 CALL comin_ftnlist_iterator_next(it)
267 END DO
268 CALL comin_ftnlist_iterator_delete(it)
269 END SUBROUTINE sync_vars_for_halo_region
270
271 SUBROUTINE determine_halo_sync_mode(item, halo_sync_mode)
272 TYPE(t_comin_var_context_item), POINTER, INTENT(IN) :: item
273 INTEGER, INTENT(OUT) :: halo_sync_mode
274 !locals
275 CHARACTER(LEN=20) :: metadata_key
276 INTEGER :: val
277 metadata_key = 'zaxis_id'
278 CALL item%var_item%metadata%get(metadata_key, val)
279 IF (val == comin_zaxis_2d) THEN
280 halo_sync_mode = comin_zaxis_2d
281 ELSE IF (val == comin_zaxis_3d) THEN
282 halo_sync_mode = comin_zaxis_3d
283 ELSE
284 CALL comin_error_set(comin_error_var_sync_halo_not_supported_zaxis); RETURN
285 END IF
286 END SUBROUTINE determine_halo_sync_mode
287 ! returns integer n as a string (needed in printing messages)
288 FUNCTION int2string(n, opt_fmt)
289 CHARACTER(:), ALLOCATABLE :: int2string ! result
290 CHARACTER(len=128) :: res
291 INTEGER, INTENT(in) :: n
292 CHARACTER(len=*), INTENT(in), OPTIONAL :: opt_fmt
293 !
294 CHARACTER(len=128) :: fmt
295
296 IF (PRESENT(opt_fmt)) THEN
297 fmt = opt_fmt
298 ELSE
299 fmt = '(i0)'
300 END IF
301 WRITE(res,fmt) n
302 res = adjustl(res)
303 int2string = trim(res)
304 END FUNCTION int2string
305
308 SUBROUTINE comin_callback_get_ep_name( iep, out_ep_name )
309 INTEGER, INTENT(IN) :: iep
310 CHARACTER(LEN=:), ALLOCATABLE, INTENT(OUT) :: out_ep_name
311
312 IF ((iep < 0) .OR. (iep > ep_destructor)) THEN
313 out_ep_name = "UNKNOWN"
314 CALL comin_error_set(comin_error_callback_ep_id_unknown); RETURN
315 ELSE
316 out_ep_name = trim(ep_name(iep))
317 END IF
318 END SUBROUTINE comin_callback_get_ep_name
319
322 !
323 SUBROUTINE comin_callback_get_ep_name_c( iep, out_ep_name) &
324 & BIND(C, name="comin_callback_get_ep_name")
325 INTEGER(c_int), VALUE, INTENT(IN) :: iep
326 CHARACTER(len=1, kind=c_char),DIMENSION(COMIN_MAX_LEN_EP_NAME+1) :: out_ep_name
327 !
328 CHARACTER(LEN=:), ALLOCATABLE :: ep_name
329
330 CALL comin_callback_get_ep_name(iep, ep_name)
331 CALL convert_f_string(ep_name, out_ep_name)
332 END SUBROUTINE comin_callback_get_ep_name_c
333
334END MODULE comin_callback
integer, parameter, public domain_undefined
id of current domain, two states possible if not in domain loop
character(len=comin_max_len_ep_name), dimension(ep_destructor), parameter, public ep_name
Entry point names (character strings)
recursive subroutine, public comin_callback_context_call(entry_point_id, domain_id, lacc)
Routine to find callback routine associated with current entry point.
subroutine, public comin_callback_register(entry_point_id, fct_ptr)
Routine to register new callbacks during primary constructor.
subroutine, public comin_callback_get_ep_name(iep, out_ep_name)
returns entry point name (character string) corresponding to iep.
subroutine, public convert_f_string(string, arr)
Convert Fortran string into C-style character array.
subroutine, public comin_callback_complete()
subroutine, public comin_error_set(errcode)
subroutine, public comin_message(message, lvl)
Prints a message on rank 0 if the global verbosity level larger than lvl.
type(t_comin_state), pointer, public state
type(t_comin_var_handle) function comin_var_ptr_init(var_item)
information about each entry point/callback