ComIn 0.5.1
ICON Community Interface
Loading...
Searching...
No Matches
yaxt_nest_fortran_plugin.F90
Go to the documentation of this file.
1! --------------------------------------------------------------------
2!> Example plugin for the ICON Community Interface (ComIn)
3! using the YAXT library to set up child/parent communication and
4! get the owner PE of cells...
5!
6! @authors 07/2025 :: ICON Community Interface <comin@icon-model.org>
7!
8! --------------------------------------------------------------------
10
12 , comin_var_get &
14 , t_comin_var_handle &
15 , comin_descrdata_get_domain &
16 , t_comin_descrdata_domain &
17 , comin_descrdata_get_global &
18 , t_comin_descrdata_global &
19 , t_comin_setup_version_info &
21 , ep_secondary_constructor &
22 , ep_destructor &
23 , ep_atm_integrate_end &
24 , comin_flag_read &
25 , comin_flag_write &
26 , comin_zaxis_2d &
27 , comin_parallel_get_host_mpi_rank &
29 , comin_parallel_get_plugin_mpi_comm &
31 , t_comin_plugin_info &
32 , comin_current_get_plugin_info &
35 , comin_metadata_set &
37 , comin_error_check, comin_print_info &
38 , comin_print_debug
39 USE yaxt, ONLY: xt_redist
40
41 IMPLICIT NONE
42
43 CHARACTER(LEN=*), PARAMETER :: pluginname = "yaxt_nest_fortran_plugin"
44
45 !> working precision (will be compared to ComIn's and ICON's)
46 INTEGER, PARAMETER :: wp = selected_real_kind(12, 307)
47 TYPE(t_comin_setup_version_info) :: version
48
49 TYPE(t_comin_var_handle), ALLOCATABLE :: temp(:) ! temperature
50 TYPE(t_comin_var_handle), ALLOCATABLE :: temp_diag(:) ! temperature
51 INTEGER :: rank
52 INTEGER :: n_dom, nproma
53
54 !> access descriptive data structures
55 TYPE(t_comin_descrdata_global) :: p_global
56 TYPE(t_comin_descrdata_domain), ALLOCATABLE :: p_patch(:)
57
58 !> yaxt related variables
59 TYPE(xt_redist), ALLOCATABLE :: yaxt_redist(:)
60
61 CHARACTER(LEN=120) :: text
62
63CONTAINS
64
65 ! --------------------------------------------------------------------
66 ! ComIn primary constructor.
67 ! --------------------------------------------------------------------
68 SUBROUTINE comin_main() BIND(C)
69
70 USE yaxt, ONLY: xt_initialize, xt_idxlist, xt_idxlist_delete &
71 , xt_xmap, xt_xmap_delete, xt_idxstripes_new, xt_idxvec_new &
72 , xt_stripe, xt_idxempty_new, xt_xmap_dist_dir_new &
73 , xt_redist_p2p_new, xt_initialized, xi => xt_int_kind
74 USE mpi, ONLY: mpi_double_precision
75
76 CHARACTER(LEN=*), PARAMETER :: substr = 'comin_main (yaxt_nest_fortran_plugin)'
77 TYPE(t_comin_plugin_info) :: this_plugin
78 TYPE(t_comin_var_descriptor) :: temp_d
79 INTEGER :: p_all_comm ! communicator of all ICON tasks
80 TYPE(xt_idxlist) :: src_idxlist, tgt_idxlist
81 TYPE(xt_xmap) :: xmap
82 INTEGER, POINTER :: child_id(:)
83 INTEGER :: ii, ic, cid
84 INTEGER, DIMENSION(:), ALLOCATABLE :: src_indices, parent_indices, tgt_indices
85
86 !> get the rank of the current process and say hello to the world
87 rank = comin_parallel_get_host_mpi_rank()
88 CALL comin_print_info("setup")
89
90 !> check, if the ComIn library version is compatible
92 IF (version%version_no_major > 1) THEN
93 CALL comin_plugin_finish(substr, "incompatible ComIn library version!")
94 END IF
95
96 !> check plugin id
97 CALL comin_current_get_plugin_info(this_plugin)
98 WRITE (text, '(a,a,a,i4)') " plugin " &
99 , trim(this_plugin%name), " has id: ", this_plugin%id
100 CALL comin_print_info(text)
101
102 !> add requests for additional ICON variables
103 ! not applicable for this example
104
105 !> register callbacks
106 CALL comin_callback_register(ep_secondary_constructor &
108 CALL comin_callback_register(ep_atm_integrate_end &
110 CALL comin_callback_register(ep_destructor &
112
113 !> get descriptive data structures
114 p_global = comin_descrdata_get_global()
115 nproma = p_global%get_nproma()
116 n_dom = p_global%get_n_dom()
117 IF (n_dom == 1) THEN
118 CALL comin_plugin_finish(substr, "only applicable for nested domain setups")
119 END IF
120 ALLOCATE (p_patch(n_dom))
121 DO ii = 1, n_dom
122 p_patch(ii) = comin_descrdata_get_domain(ii)
123 END DO
124
125 !> setup yaxt
126 p_all_comm = comin_parallel_get_plugin_mpi_comm()
127 IF (.NOT. xt_initialized()) THEN
128 CALL comin_print_info("Initialize yaxt...")
129 CALL xt_initialize(p_all_comm)
130 END IF
131
132 !> construct yaxt variables ...
133 ALLOCATE (yaxt_redist(n_dom))
134 DO ii = 1, n_dom
135 child_id => p_patch(ii)%get_child_id()
136 DO ic = 1, p_patch(ii)%get_n_childdom()
137 cid = child_id(ic)
138 ALLOCATE (src_indices(count(p_patch(ii)%cells%get_decomp_domain() == 0)))
139 ALLOCATE (parent_indices(SIZE(p_patch(cid)%cells%get_parent_glb_idx())))
140 ALLOCATE (tgt_indices(count(p_patch(cid)%cells%get_decomp_domain() >= 0)))
141 ! assign values to source indices: if reshaped array of child_id for this
142 ! parent equals the current child id (cid): use global index, else: -1
143 src_indices = merge(p_patch(ii)%cells%get_glb_index(), -1_xi &
144 & , reshape(p_patch(ii)%cells%get_child_id() &
145 & , (/ p_patch(ii)%cells%get_ncells()/)) == cid)
146 ! compute 1D global parent index for each cell
147 parent_indices = idx_1d(reshape(p_patch(cid)%cells%get_parent_glb_idx() &
148 & , (/SIZE(p_patch(cid)%cells%get_parent_glb_idx())/)) &
149 & , reshape(p_patch(cid)%cells%get_parent_glb_blk() &
150 & , (/SIZE(p_patch(cid)%cells%get_parent_glb_blk())/)))
151 ! restrict target indices to the cells owned by the task
152 tgt_indices = pack(parent_indices &
153 & , reshape(p_patch(cid)%cells%get_decomp_domain() &
154 & , (/SIZE(p_patch(cid)%cells%get_decomp_domain())/)) >= 0)
155
156 src_idxlist = xt_idxvec_new(src_indices, SIZE(src_indices, 1))
157 tgt_idxlist = xt_idxvec_new(tgt_indices, SIZE(tgt_indices, 1))
158
159 ! ... create exchange map ...
160 xmap = xt_xmap_dist_dir_new(src_idxlist, tgt_idxlist, p_all_comm)
161
162 ! ... create redistribution instance for DP ...
163 yaxt_redist(cid) = xt_redist_p2p_new(xmap, mpi_double_precision)
164
165 ! ... clean up
166 CALL xt_xmap_delete(xmap)
167 CALL xt_idxlist_delete(src_idxlist)
168 CALL xt_idxlist_delete(tgt_idxlist)
169 DEALLOCATE (src_indices, parent_indices, tgt_indices)
170 END DO
171
172 temp_d = t_comin_var_descriptor(id=ii, name="temp_yaxt_diag")
173 CALL comin_var_request_add(temp_d, .true.)
174 CALL comin_metadata_set(temp_d, "zaxis_id", comin_zaxis_2d)
175 CALL comin_metadata_set(temp_d, "tracer", .false.)
176 CALL comin_metadata_set(temp_d, "restart", .false.)
177 CALL comin_metadata_set(temp_d, "units", "K")
178 END DO
179
180 END SUBROUTINE comin_main
181
182 ! --------------------------------------------------------------------
183 ! ComIn secondary constructor.
184 ! --------------------------------------------------------------------
185 SUBROUTINE yaxt_nest_fortran_constructor() BIND(C)
186
187 USE yaxt, ONLY: xt_idxlist, xt_idxlist_delete &
188 , xt_xmap, xt_xmap_delete &
189 , xt_redist
190
191 INTEGER :: ii, pid
192
193 CALL comin_print_info("secondary constructor")
194
195 ALLOCATE (temp(n_dom), temp_diag(n_dom))
196 DO ii = 1, n_dom
197 CALL comin_print_info("request temperature")
198 CALL comin_var_get([ep_atm_integrate_end], &
199 & t_comin_var_descriptor(name='temp', id=ii), comin_flag_read, temp(ii))
200 CALL comin_print_info("request diagnostic temperature")
201 pid = p_patch(ii)%get_parent_id()
202 IF (pid <= 0) cycle
203 CALL comin_var_get([ep_atm_integrate_end], &
204 & t_comin_var_descriptor(name='temp_yaxt_diag', id=ii), comin_flag_write, temp_diag(ii))
205 END DO
206 END SUBROUTINE yaxt_nest_fortran_constructor
207
208 ! --------------------------------------------------------------------
209 ! ComIn callback function.
210 ! --------------------------------------------------------------------
211 SUBROUTINE yaxt_nest_fortran_exchange() BIND(C)
212
213 USE yaxt, ONLY: xt_redist_s_exchange1
214 USE iso_c_binding, ONLY: c_loc
215
216 INTEGER :: domain_id, pid
217 REAL(kind=wp), DIMENSION(:,:), POINTER :: src
218 REAL(kind=wp), DIMENSION(:, :, :), POINTER :: temp3d, tgt
219
220 CALL comin_print_info("callback before output")
221
222 domain_id = comin_current_get_domain_id()
223 IF (domain_id == comin_domain_outside_loop) THEN
224 CALL comin_print_debug("currently not in domain loop")
225 RETURN
226 ELSE
227 WRITE (text, '(a,a,i0)') "currently on domain ", domain_id
228 CALL comin_print_debug(text)
229 END IF
230
231 pid = p_patch(domain_id)%get_parent_id()
232 IF (pid <= 0) RETURN
233
234 CALL temp_diag(domain_id)%to_3d(tgt)
235 tgt = 0._wp
236
237 CALL temp(pid)%to_3d(temp3d)
238 ALLOCATE (src(p_global%get_nproma(), p_patch(pid)%cells%get_nblks()))
239 ! select the near surface temperature as source variable field
240 src(:,:) = temp3d(:,p_patch(pid)%get_nlev(),:)
241
242 !> exchange parent to child
243 CALL xt_redist_s_exchange1(yaxt_redist(domain_id), c_loc(src), c_loc(tgt))
244 ! find the min/max temperatures, filter out 0 values
245 WRITE(text, '(a,2(1x,f7.3))') ': min/max temperature src' &
246 , minval(pack(src, src > 0._wp)), maxval(pack(src, src > 0._wp))
247 CALL comin_print_info(text)
248 WRITE(text, '(a,2(1x,f7.3))') ': min/max temperature tgt' &
249 , minval(pack(tgt, tgt > 0._wp)), maxval(pack(tgt, tgt > 0._wp))
250 CALL comin_print_info(text)
251 DEALLOCATE(src)
252
253 END SUBROUTINE yaxt_nest_fortran_exchange
254
255 ! --------------------------------------------------------------------
256 ! ComIn callback function.
257 ! --------------------------------------------------------------------
258 SUBROUTINE yaxt_nest_fortran_destructor() BIND(C)
259
260 USE yaxt, ONLY: xt_finalize, xt_redist_delete
261
262 INTEGER :: ii, pid
263
264 CALL comin_print_info("destructor")
265
266 !> free yaxt related memory
267 DO ii = 1, n_dom
268 pid = p_patch(ii)%get_parent_id()
269 IF (pid <= 0) cycle
270 CALL xt_redist_delete(yaxt_redist(ii))
271 END DO
272 DEALLOCATE (temp, temp_diag, p_patch)
273
274 !> finalize yaxt
275 CALL xt_finalize()
276
277 END SUBROUTINE yaxt_nest_fortran_destructor
278
279 ELEMENTAL INTEGER FUNCTION idx_1d(jl, jb)
280 INTEGER, INTENT(IN) :: jl, jb
281 IF (jb <= 0) THEN
282 idx_1d = 0 ! This covers the special case nproma==1,jb=0,jl=1
283 ! All other cases are invalid and get also a 0 returned
284 ELSE
285 idx_1d = sign((jb - 1)*nproma + abs(jl), jl)
286 END IF
287 END FUNCTION idx_1d
288
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()
void comin_var_request_add(t_comin_var_descriptor var_desc, bool lmodexclusive)
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)
type(t_comin_var_handle), dimension(:), allocatable temp_diag
character(len= *), parameter pluginname
type(t_comin_descrdata_domain), dimension(:), allocatable p_patch
integer, parameter wp
working precision (will be compared to ComIn's and ICON's)
elemental integer function idx_1d(jl, jb)
type(t_comin_descrdata_global) p_global
access descriptive data structures
type(t_comin_setup_version_info) version
type(t_comin_var_handle), dimension(:), allocatable temp
void comin_main()