ComIn 0.5.1
ICON Community Interface
Loading...
Searching...
No Matches
simple_fortran_plugin.F90
Go to the documentation of this file.
1! --------------------------------------------------------------------
2!> Example plugin for the ICON Community Interface (ComIn)
3! with basic (not MPI-parallel) callbacks and accessing variables and
4! descriptive data structures.
5!
6! Note that in order to demonstrate ComIn's language interoperability,
7! a similary plugin has been implemented in C, see the subdirectory
8! "simple_c".
9!
10!
11! @authors 01/2023 :: ICON Community INTERFACE <comin@icon-model.org>
12!
13! SPDX-License-Identifier: BSD-3-Clause
14!
15! Please see the file LICENSE in the root of the source tree for this code.
16! Where software is supplied by third parties, it is indicated in the
17! headers of the routines.
18! --------------------------------------------------------------------
20 USE mpi
21 USE iso_c_binding, ONLY : c_int, c_ptr, c_f_pointer, c_associated, c_sizeof, c_loc, &
22 & c_funloc, c_size_t
24 & comin_var_get, comin_parallel_get_host_mpi_comm, &
25 & t_comin_var_descriptor, t_comin_var_handle, &
27 & comin_descrdata_get_domain, t_comin_descrdata_domain, &
28 & comin_descrdata_get_global, t_comin_descrdata_global, &
29 & comin_descrdata_get_cell_block_limits, &
30 & comin_descrdata_get_cell_indices, &
31 & comin_descrdata_get_simulation_interval, &
32 & t_comin_descrdata_simulation_interval, &
33 & t_comin_setup_version_info, comin_setup_get_version, &
34 & ep_secondary_constructor, ep_destructor, &
35 & ep_atm_physics_before, ep_atm_write_output_before, &
36 & comin_flag_read, comin_flag_write, comin_zaxis_2d, &
37 & comin_parallel_get_host_mpi_rank, comin_current_get_domain_id, &
39 & t_comin_plugin_info, comin_current_get_plugin_info, &
40 & comin_plugin_finish, comin_metadata_set, &
42 & comin_descrdata_get_timesteplength, comin_hgrid_unstructured_edge,&
45 & comin_error_check, comin_print_info, &
46 & comin_dim_semantics_nproma, comin_dim_semantics_level, &
47 & comin_dim_semantics_block, comin_dim_semantics_unused, &
48 & comin_var_datatype_double
49
50 IMPLICIT NONE
51
52 CHARACTER(LEN=*), PARAMETER :: pluginname = "simple_fortran_plugin"
53
54 !> working precision
55 INTEGER, PARAMETER :: wp = selected_real_kind(12,307)
56 TYPE(t_comin_setup_version_info) :: version
57
58 TYPE(t_comin_var_handle) :: pres, vn, simple_fortran_var, simple_fortran_tracer
59 INTEGER :: rank
60
61 !> access descriptive data structures
62 TYPE(t_comin_descrdata_global) :: p_global
63 TYPE(t_comin_descrdata_simulation_interval) :: p_simulation_interval
64
65 TYPE(t_comin_var_handle), ALLOCATABLE :: qv(:)
66
67 CHARACTER(LEN=200) :: text
68
69 INTERFACE
70 SUBROUTINE qsort(arr, nmemb, size, pred) BIND(C)
71 use, INTRINSIC :: iso_c_binding, only: c_ptr, c_size_t, c_funptr
72 TYPE(c_ptr), VALUE, INTENT(IN) :: arr
73 INTEGER(c_size_t), VALUE, INTENT(IN) :: nmemb, size
74 TYPE(c_funptr), VALUE, INTENT(IN) :: pred
75 END SUBROUTINE
76 END INTERFACE
77
78CONTAINS
79
80 ! --------------------------------------------------------------------
81 ! ComIn primary constructor.
82 ! --------------------------------------------------------------------
83 SUBROUTINE comin_main() BIND(C)
84 !
85 TYPE(t_comin_plugin_info) :: this_plugin
86 TYPE(t_comin_var_descriptor) :: simple_fortran_d, simple_fortran_tracer_d
87 REAL(wp) :: dtime_1, dtime_2
88
89 rank = comin_parallel_get_host_mpi_rank()
90 CALL comin_print_info("setup")
91
93 IF (version%version_no_major > 1) THEN
94 CALL comin_plugin_finish("comin_main (simple_fortran_plugin)", "incompatible version!")
95 END IF
96
97 !> check plugin id
98 CALL comin_current_get_plugin_info(this_plugin)
99 WRITE (text,'(a,i4)') " plugin id: ", this_plugin%id
100 CALL comin_print_info(text)
101
102 !> add requests for additional ICON variables
103
104 ! request host model to add variable simple_fortran_var
105 simple_fortran_d = t_comin_var_descriptor(id = 1, name = "simple_fortran_var")
106 CALL comin_var_request_add(simple_fortran_d, .false.)
107 CALL comin_metadata_set(simple_fortran_d, "tracer", .false.)
108 CALL comin_metadata_set(simple_fortran_d, "restart", .false.)
109
110 ! request host model to add tracer simple_fortran_tracer
111 simple_fortran_tracer_d = t_comin_var_descriptor( id = -1, name = "simple_fortran_tracer" )
112 CALL comin_var_request_add(simple_fortran_tracer_d, .false.)
113 CALL comin_metadata_set(simple_fortran_tracer_d, "tracer", .true.)
114 CALL comin_metadata_set(simple_fortran_tracer_d, "restart", .false.)
115
116 ! register callbacks
117 CALL comin_callback_register(ep_secondary_constructor, simple_fortran_constructor)
118 CALL comin_callback_register(ep_atm_write_output_before, simple_fortran_diagfct)
120
121 ! get descriptive data structures
122 p_global = comin_descrdata_get_global()
123 p_simulation_interval = comin_descrdata_get_simulation_interval()
124
126 IF(p_global%get_n_dom() > 1) THEN
128 ELSE
129 dtime_2 = 0
130 ENDIF
131 WRITE(text,"(A,F5.0,F5.0)") " timesteplength from comin_descrdata_get_timesteplength", dtime_1, dtime_2
132 CALL comin_print_info(text)
133 END SUBROUTINE comin_main
134
135 ! --------------------------------------------------------------------
136 ! ComIn secondary constructor.
137 ! --------------------------------------------------------------------
138 SUBROUTINE simple_fortran_constructor() BIND(C)
139 TYPE(t_comin_var_descriptor) :: var_desc
140 INTEGER :: jg, hgrid_id, datatype
141 LOGICAL :: tracer, multi_timelevel
142 REAL(WP), POINTER :: tracer_slice(:,:,:)
143 TYPE(c_ptr) :: it
144
145 TYPE(t_comin_var_descriptor), TARGET, ALLOCATABLE :: descrs(:), temp(:)
146 INTEGER(c_size_t) :: descrs_len, descrs_size
147 INTEGER(c_size_t) :: i
148
149 CALL comin_print_info("third party callback: secondary constructor.")
150 CALL comin_print_info("third party callback: iterate over variable list:")
151
152 descrs_len = 0_c_size_t
153 descrs_size = 8_c_size_t
154 ALLOCATE(descrs(descrs_size))
155
157 DO WHILE (c_associated(it))
158 IF (descrs_len == descrs_size) THEN
159 descrs_size = descrs_size * 2
160 ALLOCATE(temp(descrs_size))
161 temp(1:descrs_len) = descrs(1:descrs_len)
162 CALL move_alloc(temp, descrs)
163 END IF
164
165 descrs_len = descrs_len + 1
166
167 CALL comin_var_get_descr_list_var_desc(it, descrs(descrs_len))
169 END DO
170
171 CALL qsort(c_loc(descrs(1)), descrs_len, storage_size(descrs, c_size_t) / 8, c_funloc(compare_descr))
172
173 DO i = 1, descrs_len
174 WRITE (text,*) "Variable found: ", trim(descrs(i)%name), &
175 "(", descrs(i)%id, ")"
176 CALL comin_print_info(text)
177 END DO
178
179 WRITE (text,*) " ", pluginname, " - register some variables in some context"
180 CALL comin_print_info(text)
181 var_desc = t_comin_var_descriptor('pres', 1)
182 CALL comin_var_get([ep_atm_write_output_before], &
183 & var_desc, comin_flag_read, pres)
184 IF (.NOT. pres%valid()) &
185 & CALL comin_plugin_finish("simple_fortran_constructor", "Internal error!")
186
187 IF (any(pres%dim_semantics() /= [comin_dim_semantics_nproma, &
188 & comin_dim_semantics_level, &
189 & comin_dim_semantics_block, &
190 & comin_dim_semantics_unused, &
191 & comin_dim_semantics_unused ])) &
192 & CALL comin_plugin_finish("simple_fortran_constructor", "Dimension check failed!")
193
194 var_desc = t_comin_var_descriptor('vn', 1)
195 CALL comin_var_get([ep_atm_write_output_before], &
196 & var_desc, comin_flag_read, vn)
197 IF (.NOT. vn%valid()) &
198 & CALL comin_plugin_finish("simple_fortran_constructor vn", "Internal error!")
199
200 CALL comin_metadata_get(var_desc, "hgrid_id", hgrid_id)
201 IF (hgrid_id/=comin_hgrid_unstructured_edge) &
202 & CALL comin_plugin_finish("comin_var_get_metadata_hgrid", "Internal error!")
203 CALL comin_metadata_get(var_desc, "multi_timelevel", multi_timelevel)
204
205 ALLOCATE(qv(p_global%get_n_dom()))
206 DO jg =1, p_global%get_n_dom()
207 CALL comin_var_get([ep_atm_write_output_before], &
208 & t_comin_var_descriptor(name='qv', id=jg), &
209 & comin_flag_read, qv(jg))
210 CALL comin_metadata_get(t_comin_var_descriptor(name='qv', id=jg), &
211 & "datatype", datatype)
212 IF (datatype/=comin_var_datatype_double) &
213 & CALL comin_plugin_finish("simple_fortran_constructor", "Internal error!")
214 IF (.NOT. qv(jg)%valid()) &
215 & CALL comin_plugin_finish("simple_fortran_constructor", "Internal error!")
216
217 IF (any(qv(jg)%dim_semantics() /= [ comin_dim_semantics_nproma, &
218 & comin_dim_semantics_level, &
219 & comin_dim_semantics_block, &
220 & comin_dim_semantics_unused, &
221 & comin_dim_semantics_unused ] )) &
222 & CALL comin_plugin_finish("simple_fortran_constructor", "Dimension check failed!")
223 END DO
224
225 CALL comin_var_get([ep_atm_write_output_before], &
226 & t_comin_var_descriptor(name="simple_fortran_var", id=1), &
227 & comin_flag_write, simple_fortran_var)
228 IF (.NOT. simple_fortran_var%valid()) &
229 & CALL comin_plugin_finish("simple_fortran_constructor", "Internal error!")
230
231 CALL comin_metadata_get(t_comin_var_descriptor(name="simple_fortran_var", id=1), &
232 & "tracer", tracer)
233
234 CALL comin_var_get([ep_atm_write_output_before], &
235 & t_comin_var_descriptor(name="simple_fortran_tracer", id=1), &
236 & comin_flag_write, simple_fortran_tracer)
237 IF (.NOT. simple_fortran_tracer%valid()) &
238 & CALL comin_plugin_finish("simple_fortran_constructor", "Internal error!")
239
240 ! access the "simple_fortran_tracer" via a 3D array pointer:
241 CALL simple_fortran_tracer%to_3d(tracer_slice)
242 tracer_slice(1,9,1) = 1.0
243 END SUBROUTINE simple_fortran_constructor
244
245 ! --------------------------------------------------------------------
246 ! ComIn callback function.
247 ! --------------------------------------------------------------------
248 SUBROUTINE simple_fortran_diagfct() BIND(C)
249 INTEGER :: ierr, domain_id, jg, comm, root, &
250 & jb, jbs, jbe, jcs, jce, &
251 & rl_start, rl_end
252 REAL(wp) :: block_max, local_max, global_max
253 REAL(wp), POINTER, DIMENSION(:,:,:,:,:) :: simple_fortran_ptr, &
254 & pres_ptr, qv_ptr
255
256 CALL comin_print_info("third party callback: before output.")
257
258 domain_id = comin_current_get_domain_id()
259 comm = comin_parallel_get_host_mpi_comm()
260
261 IF (domain_id == comin_domain_outside_loop) THEN
262 CALL comin_print_info("currently not in domain loop")
263 ELSE
264 WRITE(text,'(a,i0)') " currently on domain ", domain_id
265 CALL comin_print_info(text)
266 END IF
267
268 CALL simple_fortran_var%get_ptr(simple_fortran_ptr)
269 CALL pres%get_ptr(pres_ptr)
270 simple_fortran_ptr = pres_ptr + 42
271
272 ! Start and end levels of prognostic cells.
273 rl_start = p_global%get_grf_bdywidth_c() + 1
274 rl_end = p_global%get_min_rlcell_int()
275
276 DO jg =1, p_global%get_n_dom()
277 CALL qv(jg)%get_ptr(qv_ptr)
278
279 CALL comin_descrdata_get_cell_block_limits(jg, rl_start, rl_end, jbs, jbe)
280 DO jb = jbs, jbe
281 CALL comin_descrdata_get_cell_indices(jg, jb, jbs, jbe, jcs, jce, rl_start, rl_end)
282
283 block_max = maxval(qv_ptr(jcs:jce,:,jb,1,1))
284
285 IF (jb == jbs) THEN
286 local_max = block_max
287 ELSE
288 local_max = max(local_max, block_max)
289 END IF
290 END DO
291
292 root = 0
293 CALL mpi_reduce(local_max, global_max, 1, mpi_double_precision, mpi_max, root, comm, ierr)
294 WRITE(text,"(A,I8,A,F8.6)") "domain ", jg, ": global max = ", global_max
295 CALL comin_print_info(text)
296 END DO
297 END SUBROUTINE simple_fortran_diagfct
298
299 ! --------------------------------------------------------------------
300 ! ComIn callback function.
301 ! --------------------------------------------------------------------
302 SUBROUTINE simple_fortran_destructor() BIND(C)
303 CALL comin_print_info("third party callback: destructor.")
304 END SUBROUTINE simple_fortran_destructor
305
306 INTEGER(c_int) FUNCTION compare_descr(a, b) BIND(C)
307 TYPE(c_ptr), VALUE, INTENT(IN) :: a, b
308 TYPE(t_comin_var_descriptor), POINTER :: pa, pb
309
310 CALL c_f_pointer(a, pa)
311 CALL c_f_pointer(b, pb)
312
313 IF (pa%name /= pb%name) THEN
314 compare_descr = merge(-1, 1, pa%name < pb%name)
315 ELSE
316 compare_descr = pa%id - pb%id
317 END IF
318 END FUNCTION compare_descr
319END MODULE simple_fortran_plugin
const char * comin_callback_get_ep_name(t_comin_entry_point iep)
void comin_plugin_finish(const char *routine, const char *text)
void comin_error_check()
const T * comin_metadata_get(t_comin_var_descriptor descriptor, const char *key)
void comin_setup_get_version(unsigned int *major, unsigned int *minor, unsigned int *patch)
int comin_current_get_domain_id()
double comin_descrdata_get_timesteplength(int jg)
void comin_var_request_add(t_comin_var_descriptor var_desc, bool lmodexclusive)
void comin_var_get_descr_list_var_desc(t_comin_var_descr_list_iterator *current, t_comin_var_descriptor *var_desc)
t_comin_var_descr_list_iterator * comin_var_get_descr_list_head()
t_comin_var_descr_list_iterator * comin_var_get_descr_list_next(t_comin_var_descr_list_iterator *current)
integer, parameter, public comin_domain_outside_loop
Return value of comin_current_get_domain_id if there is currently no domain loop.
void comin_callback_register(t_comin_entry_point entry_point, t_comin_callback_function fct_ptr)
Example plugin for the ICON Community Interface (ComIn)
character(len= *), parameter pluginname
type(t_comin_descrdata_simulation_interval) p_simulation_interval
integer, parameter wp
working precision
integer(c_int) function compare_descr(a, b)
type(t_comin_descrdata_global) p_global
access descriptive data structures
type(t_comin_var_handle) simple_fortran_tracer
type(t_comin_var_handle) vn
type(t_comin_setup_version_info) version
type(t_comin_var_handle) simple_fortran_var
type(t_comin_var_handle), dimension(:), allocatable qv
void comin_main()