ComIn 0.5.1
ICON Community Interface
Loading...
Searching...
No Matches
simple_c_plugin.c
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 FORTRAN, see the subdirectory
8 "simple".
9
10 @authors 11/2023 :: ICON Community Interface <comin@icon-model.org>
11
12 SPDX-License-Identifier: BSD-3-Clause
13
14 Please see the file LICENSE in the root of the source tree for this code.
15 Where software is supplied by third parties, it is indicated in the
16 headers of the routines.
17*/
18
19#include <comin.h>
20#include <stdbool.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25static int compare_keys(const void *a, const void *b) {
26 return strcmp(*(const char **)a, *(const char **)b);
27}
28
29static int compare_descrs(const void *a, const void *b) {
30 const t_comin_var_descriptor *const da = a;
31 const t_comin_var_descriptor *const db = b;
32
33 int d = strcmp(da->name, db->name);
34 if (d != 0)
35 return d;
36
37 return da->id - db->id;
38}
39
40// points to the pointer to the buffer (buffer swapping)
42
44 unsigned int major, minor, patch;
45 comin_setup_get_version(&major, &minor, &patch);
46 comin_print_info_f("ComIn v%u.%u.%u simple_c_constructor called!", major,
47 minor, patch);
48
49 // Print out known variables. The variable descriptors are read into a list
50 // and sorted in order to be independent of the underlying container's
51 // iteration order.
52 size_t num_descrs = 0, size_descrs = 8;
53 t_comin_var_descriptor *descrs = malloc(size_descrs * sizeof(*descrs));
54 for (void *it = comin_var_get_descr_list_head(); it != NULL;
56 if (num_descrs == size_descrs) {
57 size_descrs *= 2;
58 descrs = realloc(descrs, size_descrs * sizeof(*descrs));
59 }
60
61 comin_var_get_descr_list_var_desc(it, &descrs[num_descrs++]);
62 }
63
64 qsort(descrs, num_descrs, sizeof(*descrs), compare_descrs);
65
66 for (size_t i = 0; i < num_descrs; ++i) {
67 comin_print_info_f("found variable: %s on domain id %d", descrs[i].name,
68 descrs[i].id);
69 }
70 free(descrs);
71
72 // test explicit free'ing of a var descriptor list iterator:
73 {
74 t_comin_var_descr_list_iterator *descr_it = comin_var_get_descr_list_head();
75 descr_it = comin_var_get_descr_list_next(descr_it);
77 }
78
79 t_comin_var_descriptor pres_d = {.name = "pres", .id = 1};
80 t_comin_entry_point before_output = EP_ATM_WRITE_OUTPUT_BEFORE;
81 pres = comin_var_get(1, &before_output, pres_d, COMIN_FLAG_READ);
82 if (pres == NULL) {
83 comin_plugin_finish("simple_c_plugin", "Internal error!");
84 }
85
86 t_comin_var_descriptor var_d = {.name = "simple_c_var", .id = 1};
87 simple_c_var = comin_var_get(1, &before_output, var_d, COMIN_FLAG_WRITE);
88 if (simple_c_var == NULL) {
89 comin_plugin_finish("simple_c_plugin", "Internal error!");
90 }
91
92 t_comin_var_descriptor tracer_d = {.name = "simple_c_tracer", .id = 1};
94 comin_var_get(1, &before_output, tracer_d, COMIN_FLAG_WRITE);
95 if (simple_c_tracer == NULL) {
96 comin_plugin_finish("simple_c_plugin", "Internal error!");
97 }
98
99 comin_print_info("Metadata:");
100
101 // Sort keys to be independent of the underlying container's iteration order.
102 const char *metadata_keys[32] = {};
103 size_t n_keys = 0;
104
107 for (; !comin_metadata_iterator_compare(it, end_it);
109 if (n_keys >= sizeof(metadata_keys) / sizeof(metadata_keys[0])) {
110 comin_plugin_finish("simple_c_plugin",
111 "Too many metadata items. "
112 "Increase key array size and recompile.");
113 }
114
115 metadata_keys[n_keys++] = comin_metadata_iterator_get_key(it);
116 }
119
120 qsort(metadata_keys, n_keys, sizeof(metadata_keys[0]), compare_keys);
121
122 // iterator over the metadata:
123 for (size_t i = 0; i < n_keys; ++i) {
124 const char *const key = metadata_keys[i];
125 // query the data type of a metadata value (important
126 // because there are, for example, integer, decimal, or logical metadata).
127 int type = comin_metadata_get_typeid(pres_d, key);
128 comin_print_info_f("%s type:%i", key, type);
129 if (type == COMIN_METADATA_TYPEID_INT) {
130 int val = comin_metadata_get_int(pres_d, key);
131 comin_print_info_f(" value: %i", val);
132 }
133 }
134
135 // test "dim_semantics" auxiliary function, used for
136 // interpretation of array dimensions:
137 int dim_semantics[5];
138 comin_var_get_dim_semantics(pres, dim_semantics);
139 if (dim_semantics[0] != COMIN_DIM_SEMANTICS_NPROMA) {
140 comin_plugin_finish("simple_c_plugin", "Internal error!");
141 }
142 if (dim_semantics[1] != COMIN_DIM_SEMANTICS_LEVEL) {
143 comin_plugin_finish("simple_c_plugin", "Internal error!");
144 }
145 if (dim_semantics[2] != COMIN_DIM_SEMANTICS_BLOCK) {
146 comin_plugin_finish("simple_c_plugin", "Internal error!");
147 }
148}
149
151 comin_print_info("simple_c_diagfct called!");
152
153 comin_print_info_f("currently on domain %i", comin_current_get_domain_id());
154
155 if (comin_current_get_domain_id() != COMIN_DOMAIN_OUTSIDE_LOOP) {
157 "simple_c_plugin",
158 "simple_c_diagfct called unexpectedly inside domain loop.");
159 }
160
161 const int jg = 1; // Do diagnostic for domain 1.
162
163 const int start_prog_cells = comin_descrdata_get_global_grf_bdywidth_c() + 1;
164 const int end_prog_cells = comin_descrdata_get_global_min_rlcell_int();
165
166 int start_block_f, end_block_f;
167 comin_descrdata_get_cell_block_limits(jg, start_prog_cells, end_prog_cells,
168 &start_block_f, &end_block_f);
169
170 int pres_shape[5];
171 comin_var_get_shape(pres, pres_shape);
172
173 const int nproma =
174 pres_shape[0]; // Equal to comin_descrdata_get_global_nproma()
175 const int nlev =
176 pres_shape[1]; // Equal to comin_descrdata_get_domain_nlev(jg)
177
178 // Convenience cast to 3d array (actually pointer to array of 2d arrays).
179 typedef double(*double_3d)[nlev][nproma];
180 double_3d simple_c_var_data =
181 (double_3d)comin_var_get_ptr_double(simple_c_var);
182 double_3d pres_data = (double_3d)comin_var_get_ptr_double(pres);
183
184 for (int blk = start_block_f - 1; blk <= end_block_f - 1; ++blk) {
185 int start_cell_f, end_cell_f;
186 comin_descrdata_get_cell_indices(jg, blk + 1, start_block_f, end_block_f,
187 &start_cell_f, &end_cell_f,
188 start_prog_cells, end_prog_cells);
189
190 for (int lev = 0; lev < nlev; ++lev) {
191 for (int i = start_cell_f - 1; i <= end_cell_f - 1; ++i) {
192 simple_c_var_data[blk][lev][i] = pres_data[blk][lev][i] + 42.;
193 }
194 }
195 }
196
197 int tracer_shape[5];
198 comin_var_get_shape(simple_c_tracer, tracer_shape);
199
200 // Both tracers and pres are full-level 3d variables. They must have the same
201 // dimensions.
202 if (0 != memcmp(tracer_shape, pres_shape, sizeof(pres_shape))) {
203 comin_plugin_finish("simple_c_plugin",
204 "simple_c_tracer and pres must have same shape.");
205 }
206
207 double_3d simple_c_tracer_data =
208 (double_3d)comin_var_get_ptr_double(simple_c_tracer);
209
210 for (int blk = start_block_f - 1; blk <= end_block_f - 1; ++blk) {
211 int start_cell_f, end_cell_f;
212 comin_descrdata_get_cell_indices(jg, blk + 1, start_block_f, end_block_f,
213 &start_cell_f, &end_cell_f,
214 start_prog_cells, end_prog_cells);
215
216 for (int lev = 0; lev < nlev; ++lev) {
217 for (int i = start_cell_f - 1; i <= end_cell_f - 1; ++i) {
218 simple_c_tracer_data[blk][lev][i] = 1337. / (lev + 1);
219 }
220 }
221 }
222}
223
224void simple_c_destructor() { comin_print_info("simple_c_destructor called!"); }
225
227 const char *plugin_name = comin_current_get_plugin_name();
228
229 int plugin_id = comin_current_get_plugin_id();
230 comin_print_info_f("plugin %s has id %d", plugin_name, plugin_id);
231 t_comin_var_descriptor simple_var_d = {.name = "simple_c_var", .id = 1};
232 comin_var_request_add(simple_var_d, true);
233
234 comin_metadata_set_integer(simple_var_d, "zaxis_id", COMIN_ZAXIS_3D);
235 comin_metadata_set_logical(simple_var_d, "restart", false);
236 comin_metadata_set_logical(simple_var_d, "tracer", false);
237 comin_metadata_set_integer(simple_var_d, "tracer_vlimit", 0);
238 comin_metadata_set_integer(simple_var_d, "tracer_hlimit", 0);
239
240 t_comin_var_descriptor simple_tracer_d = {.name = "simple_c_tracer",
241 .id = -1};
242 comin_var_request_add(simple_tracer_d, false);
243 comin_metadata_set_integer(simple_tracer_d, "zaxis_id", COMIN_ZAXIS_3D);
244 comin_metadata_set_logical(simple_tracer_d, "restart", false);
245 comin_metadata_set_logical(simple_tracer_d, "tracer", true);
246 comin_metadata_set_integer(simple_tracer_d, "tracer_vlimit", 0);
247 comin_metadata_set_integer(simple_tracer_d, "tracer_hlimit", 0);
248
249 comin_callback_register(EP_SECONDARY_CONSTRUCTOR, &simple_c_constructor);
250 comin_callback_register(EP_ATM_WRITE_OUTPUT_BEFORE, &simple_c_diagfct);
252
253 const char *ep_name = comin_callback_get_ep_name(EP_DESTRUCTOR);
254 if (strncmp(ep_name, "EP_DESTRUCTOR", (size_t)13)) {
255 comin_plugin_finish_f("simple_c: comin_main",
256 "Expected EP_DESTRUCTOR; got |%s|", ep_name);
257 }
258 // TODO: Access descriptive data structures
259
260 /* access to comin descriptive global data (exemplary)*/
262 comin_print_info_f("n_dom: %d", n_dom);
264 comin_print_info_f("max_dom: %d", max_dom);
266 comin_print_info_f("nproma: %d", nproma);
267 int min_rlcell_int = comin_descrdata_get_global_min_rlcell_int();
268 comin_print_info_f("min_rlcell_int: %d", min_rlcell_int);
269}
C interface for the ICON Community Interface.
void comin_plugin_finish_f(const char *routine, const char *fmt,...)
void comin_print_info_f(const char *fmt,...)
const char * comin_callback_get_ep_name(t_comin_entry_point iep)
void comin_plugin_finish(const char *routine, const char *text)
int comin_metadata_get_int(t_comin_var_descriptor descriptor, const char *key)
t_comin_metadata_iterator * comin_metadata_get_iterator_end(t_comin_var_descriptor var_descriptor)
void comin_metadata_iterator_next(t_comin_metadata_iterator *it)
t_comin_metadata_typeid comin_metadata_get_typeid(t_comin_var_descriptor var_descriptor, const char *key)
const char * comin_metadata_iterator_get_key(t_comin_metadata_iterator *it)
void comin_metadata_iterator_delete(t_comin_metadata_iterator *it)
t_comin_metadata_iterator * comin_metadata_get_iterator_begin(t_comin_var_descriptor var_descriptor)
bool comin_metadata_iterator_compare(t_comin_metadata_iterator *it1, t_comin_metadata_iterator *it2)
const char * comin_current_get_plugin_name()
void comin_setup_get_version(unsigned int *major, unsigned int *minor, unsigned int *patch)
int comin_current_get_plugin_id()
int comin_current_get_domain_id()
void comin_var_request_add(t_comin_var_descriptor var_desc, bool lmodexclusive)
void comin_var_descr_list_iterator_delete(t_comin_var_descr_list_iterator **it)
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)
char name[COMIN_MAX_LEN_VAR_NAME+1]
Definition comin.h:37
int comin_descrdata_get_global_nproma()
Loop chunk length.
int comin_descrdata_get_global_n_dom()
Number of logical domains.
int comin_descrdata_get_global_max_dom()
Maximum number of model domains.
int comin_descrdata_get_global_min_rlcell_int()
Cell row ordering (block index): halo cells have a negative numbering ranging between min_rlcell and ...
int comin_descrdata_get_global_grf_bdywidth_c()
Cell row ordering (block index): width of lateral boundary region, not including the nudging zone.
void comin_callback_register(t_comin_entry_point entry_point, t_comin_callback_function fct_ptr)
static int compare_descrs(const void *a, const void *b)
void simple_c_constructor()
void * simple_c_tracer
static int compare_keys(const void *a, const void *b)
void simple_c_diagfct()
void simple_c_destructor()
void * pres
void * simple_c_var
void comin_main()
const int jg