ComIn 0.5.1
ICON Community Interface
Loading...
Searching...
No Matches
comin_callback.cpp
Go to the documentation of this file.
1// @file comin_callback.cpp
2// @brief Callback list based on std::vector
3//
4// @authors 10/2025 :: 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
12#include "comin.h"
13#include "comin_logging.hpp"
14#include "comin_state.hpp"
15#include "comin_variable.hpp"
16#include <algorithm>
17#include <array>
18#include <string_view>
19#include <vector>
20
21extern "C" {
22
33 void comin_callback_register(t_comin_entry_point entry_point,
34 t_comin_callback_function fct_ptr) {
35
36 // adjust for C/C++ 0-based indexing.
37 const int entry_point_slot = static_cast<int>(entry_point) - 1;
38
39 auto& callback_list = comin::state.comin_callback_list_context;
40
41 t_comin_callback_item item;
42 item.plugin_id = comin_current_get_plugin_id();
43 item.entrypoint_id = entry_point;
44 item.fct = fct_ptr;
45
46 // callbacks cannot be registered after primary constructor
48 comin_error_set(COMIN_ERROR_CALLBACK_REGISTER_OUTSIDE_PRIMARYCONSTRUCTOR);
49 return;
50 }
51
52 // first check if the entry point ID and the plugin ID are
53 // already present in the array:
54 auto& ep_callback_list = callback_list[entry_point_slot];
55 const bool is_present =
56 std::any_of(ep_callback_list.cbegin(), ep_callback_list.cend(),
57 [&](const t_comin_callback_item& existing_item) {
58 return existing_item.plugin_id == item.plugin_id;
59 });
60 if (is_present) {
61 const char* ep_name = comin_callback_get_ep_name(entry_point);
62 comin::logging::message(12, "WARNING: Callback for plugin ID ",
63 item.plugin_id,
64 " already registered at entry point '", ep_name,
65 "' (ep: ", entry_point, ")!");
66 return;
67 }
68
69 ep_callback_list.push_back(item);
70
71 {
72 const char* plugin_name = comin_current_get_plugin_name();
73 const char* ep_name = comin_callback_get_ep_name(entry_point);
74 comin::logging::message(
75 0, " registration for '", ep_name, "' (ep: ", entry_point,
76 ") associated for 3rd party plugin ", plugin_name, " successful.");
77 }
78 }
79
80 // Thin wrapper because the integer type underlying a C enum is implementation
81 // defined before C23.
82 void comin_callback_register_f(int entry_point_ftn,
83 t_comin_callback_function fct_ptr) {
84 comin_callback_register(static_cast<t_comin_entry_point>(entry_point_ftn),
85 fct_ptr);
86 }
87
88 // Routine to find callback routine associated with current entry point
89 void comin_callback_context_call(int entry_point_id, int domain_id,
90 bool lacc) {
91
92 const t_comin_entry_point entry_point =
93 static_cast<t_comin_entry_point>(entry_point_id);
94
95 // We can't call callbacks before the primary constructors are done
97 return;
98 }
99
100 const char* ep_name = comin_callback_get_ep_name(entry_point);
101 comin::logging::message(12, " CONTEXT ", ep_name);
102
103 using comin::state;
104 auto& callback_list = state.comin_callback_list_context;
105
106 auto& ep_callback_list = callback_list[entry_point - 1];
107
108 if (ep_callback_list.empty()) {
109 comin::logging::message(12, " no calls associated with entry point '",
110 ep_name, "' (ep: ", entry_point, ").");
111 return;
112 }
113
114 // call callback functions in the order they were registered
115 for (const auto& cl : ep_callback_list) {
116
117 // set current plugin
118 comin_current_set_plugin_id(cl.plugin_id);
119
120 const char* plugin_name = comin_current_get_plugin_name();
121 comin::logging::message(0, " current ep '", ep_name,
122 "' (ep: ", cl.entrypoint_id,
123 ") for library: ", plugin_name);
124
125 if (lacc) {
126 comin_sync_vars_for_device(entry_point, cl.plugin_id, COMIN_FLAG_READ);
127 } else {
128 comin_check_var_no_device(entry_point, cl.plugin_id);
129 }
130
131 comin_sync_vars_for_halo_region(entry_point, cl.plugin_id,
132 COMIN_FLAG_READ);
133
134 // set current entry point
135 state.current_ep = entry_point;
136
137 // set current domain id
138 state.current_domain_id = domain_id;
139 // undefine domain id for the call of the ComIn destructor
140 if (entry_point == EP_DESTRUCTOR)
141 state.current_domain_id = DOMAIN_UNDEFINED;
142
143 // call the callback function
144 cl.fct();
145
146 // reset current plugin
148
149 comin_sync_vars_for_halo_region(entry_point, cl.plugin_id,
150 COMIN_FLAG_WRITE);
151 if (lacc) {
152 comin_sync_vars_for_device(entry_point, cl.plugin_id, COMIN_FLAG_WRITE);
153 }
154 }
155 }
156
157 const char* comin_ep_names[] = {"EP_SECONDARY_CONSTRUCTOR",
158 "EP_ATM_YAC_DEFCOMP_BEFORE",
159 "EP_ATM_YAC_DEFCOMP_AFTER",
160 "EP_ATM_YAC_SYNCDEF_BEFORE",
161 "EP_ATM_YAC_SYNCDEF_AFTER",
162 "EP_ATM_YAC_ENDDEF_BEFORE",
163 "EP_ATM_YAC_ENDDEF_AFTER",
164 "EP_ATM_INIT_FINALIZE",
165 "EP_ATM_TIMELOOP_BEFORE",
166 "EP_ATM_TIMELOOP_START",
167 "EP_ATM_TIMELOOP_END",
168 "EP_ATM_TIMELOOP_AFTER",
169 "EP_ATM_INTEGRATE_BEFORE",
170 "EP_ATM_INTEGRATE_START",
171 "EP_ATM_INTEGRATE_END",
172 "EP_ATM_INTEGRATE_AFTER",
173 "EP_ATM_WRITE_OUTPUT_BEFORE",
174 "EP_ATM_WRITE_OUTPUT_AFTER",
175 "EP_ATM_CHECKPOINT_BEFORE",
176 "EP_ATM_CHECKPOINT_AFTER",
177 "EP_ATM_ADVECTION_BEFORE",
178 "EP_ATM_ADVECTION_AFTER",
179 "EP_ATM_PHYSICS_BEFORE",
180 "EP_ATM_PHYSICS_AFTER",
181 "EP_ATM_NUDGING_BEFORE",
182 "EP_ATM_NUDGING_AFTER",
183 "EP_ATM_SURFACE_BEFORE",
184 "EP_ATM_SURFACE_AFTER",
185 "EP_ATM_TURBULENCE_BEFORE",
186 "EP_ATM_TURBULENCE_AFTER",
187 "EP_ATM_MICROPHYSICS_BEFORE",
188 "EP_ATM_MICROPHYSICS_AFTER",
189 "EP_ATM_CONVECTION_BEFORE",
190 "EP_ATM_CONVECTION_AFTER",
191 "EP_ATM_RADIATION_BEFORE",
192 "EP_ATM_RADIATION_AFTER",
193 "EP_ATM_RADHEAT_BEFORE",
194 "EP_ATM_RADHEAT_AFTER",
195 "EP_ATM_GWDRAG_BEFORE",
196 "EP_ATM_GWDRAG_AFTER",
197 "EP_FINISH",
198 "EP_DESTRUCTOR"};
199
200 const char* comin_callback_get_ep_name(t_comin_entry_point iep) {
201 if (iep < 1 || iep > (sizeof(comin_ep_names) / sizeof(comin_ep_names[0]))) {
202 comin_error_set(COMIN_ERROR_CALLBACK_EP_ID_UNKNOWN);
203 return nullptr;
204 }
205 return comin_ep_names[iep - 1];
206 }
207
208} // extern "C"
C interface for the ICON Community Interface.
void comin_callback_register_f(int entry_point_ftn, t_comin_callback_function fct_ptr)
const char * comin_ep_names[]
void comin_callback_context_call(int entry_point_id, int domain_id, bool lacc)
const char * comin_callback_get_ep_name(t_comin_entry_point iep)
void comin_error_set(t_comin_error_code error_code)
const char * comin_current_get_plugin_name()
bool comin_state_is_primary_done()
int comin_current_get_plugin_id()
void comin_current_set_plugin_id(int plugin_id)
void comin_check_var_no_device(t_comin_entry_point ep, int plugin_id)
void comin_sync_vars_for_device(t_comin_entry_point ep, int plugin_id, int rw_flag)
void comin_sync_vars_for_halo_region(t_comin_entry_point ep, int plugin_id, int rw_flag)
void comin_callback_register(t_comin_entry_point entry_point, t_comin_callback_function fct_ptr)