ICON Community Interface 0.4.0
Loading...
Searching...
No Matches
comin_setup.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
16 USE comin_setup_constants, ONLY: wp
38
39 USE iso_c_binding, ONLY: c_int, c_ptr, c_funptr, c_f_procpointer, c_null_char, &
40 & c_associated, c_null_ptr, c_loc, c_char, c_double, c_f_pointer
41 IMPLICIT NONE
42
43 PRIVATE
44
45 PUBLIC :: comin_setup_check
47 PUBLIC :: comin_setup_init
48 PUBLIC :: comin_setup_finalize
50 PUBLIC :: comin_plugin_init
53
55 abstract INTERFACE
56 SUBROUTINE comin_plugin_init_fct(state_ptr, host_version, host_wp) BIND(C)
57 IMPORT c_ptr, c_int, t_comin_setup_version_info
58
59#ifndef __NVCOMPILER
60 TYPE(C_PTR), VALUE, INTENT(IN) :: state_ptr
61#else
62 TYPE(C_PTR), INTENT(IN) :: state_ptr
63#endif
64
65 TYPE(t_comin_setup_version_info), INTENT(IN) :: host_version
66 INTEGER(C_INT), INTENT(IN) :: host_wp
67 END SUBROUTINE comin_plugin_init_fct
68
69 SUBROUTINE comin_primaryconstructor_fct() &
70 & BIND(C)
71 END SUBROUTINE comin_primaryconstructor_fct
72
73 END INTERFACE
74
75 INTEGER(c_int), PARAMETER :: rtld_now = 2 ! (value extracted from the C header file)
76 !
77 ! interface to linux API
78 INTERFACE
79 FUNCTION dlopen_ptr(filename,mode) BIND(c,name="dlopen")
80 ! void *dlopen(const char *filename, int mode);
81 USE iso_c_binding
82 IMPLICIT NONE
83 TYPE(c_ptr) :: dlopen_ptr
84 TYPE(c_ptr), VALUE, INTENT(in) :: filename
85 INTEGER(c_int), VALUE :: mode
86 END FUNCTION dlopen_ptr
87
88 FUNCTION dlsym(handle,name) BIND(c,name="dlsym")
89 ! void *dlsym(void *handle, const char *name);
90 USE iso_c_binding
91 IMPLICIT NONE
92 TYPE(c_funptr) :: dlsym
93 TYPE(c_ptr), VALUE :: handle
94 CHARACTER(c_char), INTENT(in) :: name(*)
95 END FUNCTION dlsym
96
97 ! FUNCTION dlclose(handle) BIND(c,name="dlclose")
98 ! ! int dlclose(void *handle);
99 ! USE iso_c_binding
100 ! IMPLICIT NONE
101 ! INTEGER(c_int) :: dlclose
102 ! TYPE(c_ptr), VALUE :: handle
103 ! END FUNCTION dlclose
104
105 FUNCTION dlerror() RESULT(error) BIND(C,NAME="dlerror")
106 ! char *dlerror(void);
107 USE iso_c_binding
108 TYPE(C_PTR) :: error
109 END FUNCTION dlerror
110
111 END INTERFACE
112
113 ! list type
114 TYPE :: comin_primaryconstructor_ptr
115 PROCEDURE(comin_primaryconstructor_fct), POINTER, NOPASS :: fct_ptr
116 END TYPE comin_primaryconstructor_ptr
117
119 TYPE(c_ptr), ALLOCATABLE :: dl_handles(:)
120
121#include "comin_version.inc"
122
123CONTAINS
124
125 FUNCTION dlopen(filename, mode)
126 CHARACTER(LEN=*), INTENT(in) :: filename
127 INTEGER(c_int), VALUE :: mode
128 !
129 TYPE(c_ptr) :: dlopen
130 CHARACTER(len=1, kind=c_char), TARGET :: c_filename(len(filename)+1)
131 CALL convert_f_string(trim(filename), c_filename)
132 dlopen = dlopen_ptr(c_loc(c_filename), mode)
133 END FUNCTION dlopen
134
137 SUBROUTINE comin_plugin_primaryconstructor(plugin_list)
138
139 TYPE(t_comin_plugin_description), INTENT(IN), TARGET :: plugin_list(:)
140 !
141 INTEGER :: i, last_sep_idx
142 TYPE(c_funptr) :: setup_fct_c, plugin_init_fct_c
143 PROCEDURE(comin_primaryconstructor_fct), BIND(C), POINTER :: setup_fct
144 PROCEDURE(comin_plugin_init_fct), BIND(C), POINTER :: plugin_init_fct
145
146 CALL comin_ftnlist_new(state%comin_callback_list)
147 CALL comin_varmap_new(state%comin_var_list)
148 CALL comin_ftnlist_new(state%comin_var_descr_list)
149 CALL comin_ftnlist_new(state%comin_var_request_list)
150
151 state%num_plugins = SIZE(plugin_list)
152 ALLOCATE(dl_handles(state%num_plugins))
153 ALLOCATE(state%plugin_info(state%num_plugins))
154 DO i=1,state%num_plugins
155
156 IF (trim(plugin_list(i)%plugin_library) .EQ. "") THEN
157 dl_handles(i) = dlopen_ptr(c_null_ptr, rtld_now)
158 ELSE
159 dl_handles(i) = dlopen(plugin_list(i)%plugin_library, rtld_now)
160 END IF
161 IF (.NOT. c_associated(dl_handles(i))) &
162 & CALL comin_plugin_finish("comin_plugin_primaryconstructor", &
163 & "ERROR: Cannot load plugin " // convert_c_string(dlerror()))
164
165 ! We load the symbol comin_plugin_init explicitly from the library
166 plugin_init_fct_c = dlsym(dl_handles(i), "comin_plugin_init"//c_null_char)
167 IF (.NOT. c_associated(plugin_init_fct_c)) &
168 & CALL comin_plugin_finish("comin_plugin_primaryconstructor", &
169 & "Cannot load 'comin_plugin_init' from plugin: " // convert_c_string(dlerror()))
170 CALL c_f_procpointer( plugin_init_fct_c, plugin_init_fct )
171 CALL plugin_init_fct(c_loc(state), comin_setup_get_version(), wp)
172
173 setup_fct_c = dlsym(dl_handles(i), trim(plugin_list(i)%primary_constructor)//c_null_char)
174 IF (.NOT. c_associated(setup_fct_c)) &
175 & CALL comin_plugin_finish("comin_plugin_primaryconstructor", &
176 & "Cannot load primary constructor from plugin: " // convert_c_string(dlerror()))
177
178 CALL c_f_procpointer( setup_fct_c, setup_fct )
179 state%current_plugin => state%plugin_info(i)
180 state%current_plugin%id = i
181 IF (len_trim(plugin_list(i)%name) > 0) THEN
182 state%current_plugin%name = trim(plugin_list(i)%name)
183 ELSE
184 last_sep_idx = scan(plugin_list(i)%plugin_library, "/", .true.)
185 state%current_plugin%name = trim(plugin_list(i)%plugin_library(last_sep_idx+1:)) // &
186 & "(" // trim(plugin_list(i)%primary_constructor) // ")"
187 ENDIF
188 state%current_plugin%options = trim(plugin_list(i)%options)
189 state%current_plugin%comm = trim(plugin_list(i)%comm)
190 state%current_plugin%log_debug = plugin_list(i)%log_debug
191 state%current_plugin%log_info = plugin_list(i)%log_info
192 state%current_plugin%log_warning = plugin_list(i)%log_warning
193 CALL setup_fct()
194 NULLIFY(state%current_plugin)
195
196 END DO
197
198 ! after all primary callbacks are done: finalize callback structure and set flag
200 CALL comin_var_complete()
201 state%l_primary_done = .true.
203
206 SUBROUTINE comin_setup_check(plugin_str, wp_check)
207 CHARACTER(LEN=*), INTENT(IN) :: plugin_str
208 INTEGER, INTENT(IN) :: wp_check
209 !
210
211 IF (.NOT. ASSOCIATED(state%comin_host_finish)) THEN
213 END IF
214
215 ! compare floating point precision
216 IF (wp /= wp_check) THEN
218 ELSE
219 CALL comin_message(" " // plugin_str // ": working precision test successful.", 0)
220 END IF
221 END SUBROUTINE comin_setup_check
222
226 SUBROUTINE comin_current_get_plugin_info(comin_current_plugin)
227 TYPE(t_comin_plugin_info), INTENT(OUT) :: comin_current_plugin
228
229 comin_current_plugin = state%current_plugin
230
231 END SUBROUTINE comin_current_get_plugin_info
232
234 INTEGER(C_INT) FUNCTION comin_current_get_plugin_id() &
235 & BIND(C, NAME="comin_current_get_plugin_id")
236 comin_current_get_plugin_id = int(state%current_plugin%id, c_int)
237 END FUNCTION comin_current_get_plugin_id
238
240 SUBROUTINE comin_current_get_plugin_name(val, len) &
241 & BIND(C, NAME="comin_current_get_plugin_name")
242 TYPE(c_ptr), INTENT(OUT) :: val
243 INTEGER(kind=c_int), INTENT(OUT) :: len
244
245 val = c_loc(state%current_plugin%name)
246 len = len_trim(state%current_plugin%name)
247 END SUBROUTINE comin_current_get_plugin_name
248
250 SUBROUTINE comin_current_get_plugin_options(val, len) &
251 & BIND(C, NAME="comin_current_get_plugin_options")
252 TYPE(c_ptr), INTENT(OUT) :: val
253 INTEGER(kind=c_int), INTENT(OUT) :: len
254
255 val = c_loc(state%current_plugin%options)
256 len = len_trim(state%current_plugin%options)
257 END SUBROUTINE comin_current_get_plugin_options
258
260 SUBROUTINE comin_current_get_plugin_comm(val, len) &
261 & BIND(C, NAME="comin_current_get_plugin_comm")
262 TYPE(c_ptr), INTENT(OUT) :: val
263 INTEGER(kind=c_int), INTENT(OUT) :: len
264
265 val = c_loc(state%current_plugin%comm)
266 len = len_trim(state%current_plugin%comm)
267 END SUBROUTINE comin_current_get_plugin_comm
268
273 SUBROUTINE comin_setup_init(lstdout, output_unit)
274 LOGICAL, INTENT(IN) :: lstdout
275 INTEGER, INTENT(IN), OPTIONAL :: output_unit
276 IF (ASSOCIATED(state)) THEN
277 ! <! cant use comin_message due to circular dependencies
279 END IF
280 ALLOCATE(state)
281 state%lstdout = lstdout
282 IF(PRESENT(output_unit)) THEN
283 state%output_unit = output_unit
284 END IF
285 END SUBROUTINE comin_setup_init
286
290 !
291 ! INTEGER :: i
292 ! INTEGER(c_int) :: ierr_c
293
295
296 ! we don't call dlclose in the finalization because it has no
297 ! advantages, while it would triggers some problems:
298 !
299 ! - NVHPC compilers for GPU try to unload the library again in at
300 ! the end of the program resulting in a segfault. See
301 ! https://gitlab.dkrz.de/icon-comin/comin/-/issues/210
302 !
303 ! - parallel HDF5 registers calls backs at `MPI_COMM_SELF` atexit
304 ! handler, which also results in a segfault as the call gets
305 ! unloaded in dlclose before the handler is called.
306 ! See https://gitlab.dkrz.de/icon-comin/comin/-/issues/214
307 !
308
309 ! DO i=1,SIZE(dl_handles)
310 ! ierr_c = dlclose(dl_handles(i))
311 ! IF (ierr_c /= 0) THEN
312 ! CALL comin_error_set(COMIN_ERROR_SETUP_FINALIZE)
313 ! END IF
314 ! END DO
315 DEALLOCATE(dl_handles, state%plugin_info)
316 END SUBROUTINE comin_setup_finalize
317
319 ! This routine is called by the host to set the plugins state
320 ! explicitly to the state of the host model. It should by loaded by
321 ! the host explicitly from the shared library of the plugin by using
322 ! `dlsym`.
323 SUBROUTINE comin_plugin_init(state_ptr, host_version, host_wp) &
324 BIND(C)
325
326 ! At the moment assuming only NVHPC and GCC (default way)
327 TYPE(c_ptr), VALUE, INTENT(IN) :: state_ptr
328 TYPE(t_comin_setup_version_info), INTENT(IN) :: host_version
329 INTEGER(C_INT), INTENT(IN) :: host_wp
330
331 TYPE(t_comin_state), POINTER :: host_state => null()
332
333 ! we cant rely on calling methods to obtain the version or wp,
334 ! because this might call functions dynamically loaded by the host
335 ! or other plugins. Hence we use the version preprocessor and wp
336 ! constants directly.
337
338 IF( .NOT. comin_setup_version_compatible(host_version, &
339 & t_comin_setup_version_info(comin_version_major, comin_version_minor, comin_version_patch))) THEN
341 END IF
342
343 IF( host_wp /= c_double ) THEN
345 END IF
346
347 CALL c_f_pointer(state_ptr, host_state)
348
349 IF(ASSOCIATED(state) .AND. .NOT. ASSOCIATED(state, host_state)) THEN
350 ! <! cant use comin_message due to circular dependencies
352 END IF
353
354 state => host_state
355 END SUBROUTINE comin_plugin_init
356
360 PROCEDURE(comin_glb2loc_index_lookup_fct) :: fct
361 state%comin_descrdata_fct_glb2loc_cell => fct
362 IF (.NOT. ASSOCIATED(state%comin_descrdata_fct_glb2loc_cell)) THEN
364 END IF
366
374 SUBROUTINE comin_setup_errhandler(error_handler)
375 PROCEDURE(comin_host_errhandler_fct) :: error_handler
376
377 state%comin_host_finish => error_handler
378 IF (.NOT. ASSOCIATED(state%comin_host_finish)) THEN
380 END IF
381 END SUBROUTINE comin_setup_errhandler
382
383END MODULE comin_setup
integer, parameter, public wp
working precision
type(t_comin_setup_version_info) function, public comin_setup_get_version()
Returns version info.
subroutine, public comin_setup_check(plugin_str, wp_check)
Performs basic compatibility checks.
subroutine, public comin_plugin_primaryconstructor(plugin_list)
Execute primary constructors.
subroutine, public comin_descrdata_set_fct_glb2loc_cell(fct)
Sets the "global-to-local" index lookup function.
subroutine, public comin_setup_init(lstdout, output_unit)
Initialize the comin stateThis routine needs to be called by the host before any other comin call.
subroutine, public comin_setup_finalize()
Destructor.
subroutine, public comin_setup_errhandler(error_handler)
Sets the global error handler procedure pointer.
subroutine, public comin_plugin_finish(routine, text)
Wrapper function for callback to ICON's "finish" routine.
subroutine, public comin_current_get_plugin_info(comin_current_plugin)
Returns the structure current_plugin. It can for example be used to access the id of the current plug...
In order to be compatible with ICON, the interface contains OPTIONAL arguments which are probably not...
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.
subroutine, public comin_parallel_free_mpi_comms()
logical function, public comin_setup_version_compatible(setupa, setupb)
subroutine, public comin_plugin_init(state_ptr, host_version, host_wp)
Initialize the plugin state.
type(c_ptr), dimension(:), allocatable dl_handles
list of primary constructors
type(t_comin_state), pointer, public state
subroutine, public comin_var_complete()
Data type, describing the dynamic libraries.
The elements of this derived data type describe a 3rd party plugin.
The elements of this derived data type describe the current community interface.