YAC 3.7.1
Yet Another Coupler
Loading...
Searching...
No Matches
interp_method_callback.c
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#ifdef HAVE_CONFIG_H
6// Get the definition of the 'restrict' keyword.
7#include "config.h"
8#endif
9
10#include <string.h>
11
13#include "utils_core.h"
14#include "yac_mpi_internal.h"
15#include "ensure_array_size.h"
17
23
24static size_t do_search_callback(struct interp_method * method,
25 struct yac_interp_grid * interp_grid,
26 size_t * tgt_points, size_t count,
27 struct yac_interp_weights * weights,
28 int * interpolation_complete);
29static void delete_callback(struct interp_method * method);
30
31static struct interp_method_vtable
35
42
43static void get_orig_data(
44 struct remote_point const * remote_point,
45 int * owner_rank, size_t * orig_pos) {
46
47 struct remote_point_info const * point_infos = NULL;
48
49 if (remote_point->data.count == 1) {
50 point_infos = &(remote_point->data.data.single);
51 } else {
52 int min_rank = INT_MAX;
53 for (int i = 0; i < remote_point->data.count; ++i) {
54 int curr_rank = remote_point->data.data.multi[i].rank;
55 if (curr_rank < min_rank) {
56 point_infos = remote_point->data.data.multi + i;
57 min_rank = curr_rank;
58 }
59 }
60 }
61
62 YAC_ASSERT(point_infos != NULL, "ERROR(get_orig_data): internal error")
63
64 *owner_rank = point_infos->rank;
65 *orig_pos = point_infos->orig_pos;
66}
67
68static MPI_Datatype yac_get_request_data_mpi_datatype(MPI_Comm comm) {
69
70 struct tgt_request_data dummy;
71 MPI_Datatype tgt_request_data_dt;
72 int array_of_blocklengths[] = {1, 1, 3};
73 const MPI_Aint array_of_displacements[] =
74 {(MPI_Aint)(intptr_t)(const void *)&(dummy.src_orig_pos) -
75 (MPI_Aint)(intptr_t)(const void *)&dummy,
76 (MPI_Aint)(intptr_t)(const void *)&(dummy.src_global_id) -
77 (MPI_Aint)(intptr_t)(const void *)&dummy,
78 (MPI_Aint)(intptr_t)(const void *)&(dummy.tgt_coord[0]) -
79 (MPI_Aint)(intptr_t)(const void *)&dummy};
80 const MPI_Datatype array_of_types[] =
81 {MPI_UINT64_T, yac_int_dt, MPI_DOUBLE};
83 MPI_Type_create_struct(3, array_of_blocklengths, array_of_displacements,
84 array_of_types, &tgt_request_data_dt), comm);
85 return yac_create_resized(tgt_request_data_dt, sizeof(dummy), comm);
86}
87
88// move the target points, which have a valid source cells
89// (invalid src_cell == SIZE_MAX) to the front of the array and count the number
90// of valid results
91static size_t get_valid_results(
92 size_t * src_cells, size_t count, size_t * tgt_points) {
93
94 size_t valid_count = 0;
95 size_t end_pos = count;
96
97 while (valid_count < end_pos) {
98
99 // find next invalid result
100 while ((valid_count < end_pos) && (src_cells[valid_count] != SIZE_MAX))
101 ++valid_count;
102
103 // find valid result from the end of the array
104 do {
105 --end_pos;
106 } while ((valid_count < end_pos) && (src_cells[end_pos] == SIZE_MAX));
107
108 // switch valid result with invalid one
109 if (valid_count < end_pos) {
110 size_t temp_src_cell = src_cells[valid_count];
111 size_t temp_tgt_point = tgt_points[valid_count];
112 src_cells[valid_count] = src_cells[end_pos];
113 tgt_points[valid_count] = tgt_points[end_pos];
114 src_cells[end_pos] = temp_src_cell;
115 tgt_points[end_pos] = temp_tgt_point;
116 ++valid_count;
117 }
118 }
119
120 return valid_count;
121}
122
123static size_t do_search_callback (struct interp_method * method,
124 struct yac_interp_grid * interp_grid,
125 size_t * tgt_points, size_t count,
126 struct yac_interp_weights * weights,
127 int * interpolation_complete) {
128
129 if (*interpolation_complete) return 0;
130
131 char const * routine = "do_search_callback";
132
133 struct interp_method_callback * method_callback =
134 (struct interp_method_callback *)method;
135
136 MPI_Comm comm = yac_interp_grid_get_MPI_Comm(interp_grid);
137 int comm_rank, comm_size;
138 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
139 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
140
141 // get coordinates of target points
142 yac_coordinate_pointer tgt_coords = xmalloc(count * sizeof(*tgt_coords));
144 interp_grid, tgt_points, count, tgt_coords);
145
146 // get matching source cells for all target points
147 size_t * src_cells = xmalloc(count * sizeof(*src_cells));
149 interp_grid, tgt_coords, count, src_cells);
150 free(tgt_coords);
151
152 // move the target points, which have a valid source cells
153 // (invalid src_cell == SIZE_MAX) to the front of the array
154 size_t temp_result_count = get_valid_results(src_cells, count, tgt_points);
155
156 // get all unique source result cells
157 yac_quicksort_index_size_t_size_t(src_cells, temp_result_count, tgt_points);
158 size_t num_unique_src_cells = 0;
159 size_t * src_to_unique_src =
160 xmalloc(temp_result_count * sizeof(*src_to_unique_src));
161 for (size_t i = 0, prev_src_cell = SIZE_MAX; i < temp_result_count; ++i) {
162 size_t curr_src_cell = src_cells[i];
163 if (curr_src_cell != prev_src_cell) {
164 src_cells[num_unique_src_cells++] = curr_src_cell;
165 prev_src_cell = curr_src_cell;
166 }
167 src_to_unique_src[i] = num_unique_src_cells - 1;
168 }
169
170 // get remote point information for all unique source result cell
171 struct remote_point * src_remote_points =
173 interp_grid, YAC_LOC_CELL, src_cells, num_unique_src_cells);
174 free(src_cells);
175
176 // get original owners of all unique source result cells
177 int * orig_src_cell_ranks =
178 xmalloc(num_unique_src_cells * sizeof(*orig_src_cell_ranks));
179 size_t * orig_src_cell_pos =
180 xmalloc(num_unique_src_cells * sizeof(*orig_src_cell_pos));
181 for (size_t i = 0; i < num_unique_src_cells; ++i)
183 src_remote_points + i, orig_src_cell_ranks + i, orig_src_cell_pos + i);
184
185 // set up communication buffers
186 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
188 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
189 // count number of target requests per rank
190 for (size_t i = 0; i < temp_result_count; ++i)
191 sendcounts[orig_src_cell_ranks[src_to_unique_src[i]]]++;
193 1, sendcounts, recvcounts, sdispls, rdispls, comm);
194 size_t request_count = recvcounts[comm_size - 1] + rdispls[comm_size - 1];
195
196 // pack target request data
197 yac_const_coordinate_pointer tgt_field_coords =
199 struct tgt_request_data * request_buffer =
200 xmalloc((temp_result_count + request_count) * sizeof(*request_buffer));
201 struct tgt_request_data * request_send_buffer = request_buffer;
202 struct tgt_request_data * request_recv_buffer =
203 request_buffer + temp_result_count;
204 size_t * new_tgt_points =
205 xmalloc(temp_result_count * sizeof(*new_tgt_points));
206 for (size_t i = 0; i < temp_result_count; ++i) {
207 size_t unique_src_cell_idx = src_to_unique_src[i];
208 size_t pos = sdispls[orig_src_cell_ranks[unique_src_cell_idx] + 1]++;
209 request_send_buffer[pos].src_orig_pos =
210 orig_src_cell_pos[unique_src_cell_idx];
211 request_send_buffer[pos].src_global_id =
212 src_remote_points[unique_src_cell_idx].global_id;
213 memcpy(request_send_buffer[pos].tgt_coord, tgt_field_coords[tgt_points[i]],
214 3 * sizeof(double));
215 new_tgt_points[pos] = tgt_points[i];
216 }
217 free(src_remote_points);
218 free(orig_src_cell_pos);
219 free(src_to_unique_src);
220 free(orig_src_cell_ranks);
221
222 // bring target points into the order in which we will receive the results
223 memcpy(tgt_points, new_tgt_points, temp_result_count * sizeof(*tgt_points));
224 free(new_tgt_points);
225
226 // transfer tgt coords, orig src pos and src id
227 MPI_Datatype request_data_dt = yac_get_request_data_mpi_datatype(comm);
229 request_send_buffer, sendcounts, sdispls,
230 request_recv_buffer, recvcounts, rdispls,
231 sizeof(*request_recv_buffer), request_data_dt, comm, routine, __LINE__);
232 yac_mpi_call(MPI_Type_free(&request_data_dt), comm);
233
235 method_callback->compute_weights_callback;
236 void * user_data = method_callback->user_data;
237 size_t num_src_fields = yac_interp_grid_get_num_src_fields(interp_grid);
238 uint64_t * uint64_t_buffer =
239 xmalloc(num_src_fields * (request_count + temp_result_count) *
240 sizeof(*uint64_t_buffer));
241 uint64_t * temp_num_results_per_src_field_per_tgt = uint64_t_buffer;
242 uint64_t * num_results_per_src_field_per_tgt_uint64 =
243 uint64_t_buffer + num_src_fields * request_count;
244 yac_int * temp_global_ids = NULL;
245 size_t temp_global_ids_array_size = 0;
246 double * temp_w = NULL;
247 size_t temp_w_array_size = 0;
248 size_t temp_weights_count = 0;
249
250 // the weight computation function should be available on
251 // all source
253 (request_count == 0) || (compute_weights != NULL),
254 "ERROR(%s): no callback routine defined on source process", routine)
255
256 // compute weights and store results
257 for (size_t i = 0, k = 0; i < request_count; ++i) {
258
259 // get weights for the current target point from the user
260 int const * curr_global_result_points[num_src_fields];
261 double * curr_result_weights[num_src_fields];
262 size_t curr_result_counts[num_src_fields];
264 (double const *)(request_recv_buffer[i].tgt_coord),
265 (int)(request_recv_buffer[i].src_global_id),
266 (size_t)(request_recv_buffer[i].src_orig_pos),
267 curr_global_result_points, curr_result_weights, curr_result_counts,
268 user_data);
269
270 // copy current results
271 for (size_t j = 0; j < num_src_fields; ++j, ++k) {
272 size_t curr_count = curr_result_counts[j];
273 temp_num_results_per_src_field_per_tgt[k] = (uint64_t)curr_count;
275 temp_global_ids, temp_global_ids_array_size,
276 temp_weights_count + curr_count);
278 temp_w, temp_w_array_size,
279 temp_weights_count + curr_count);
280 for (size_t l = 0; l < curr_count; ++l)
281 temp_global_ids[temp_weights_count + l] =
282 (yac_int)(curr_global_result_points[j][l]);
283 memcpy(temp_w + temp_weights_count, curr_result_weights[j],
284 curr_count * sizeof(*curr_result_weights));
285 temp_weights_count += curr_count;
286 }
287 }
288 free(request_buffer);
289
290 // return number of results per source field per target point
291 for (int i = 0; i < comm_size; ++i) {
292 sendcounts[i] *= num_src_fields;
293 recvcounts[i] *= num_src_fields;
294 sdispls[i] *= num_src_fields;
295 rdispls[i] *= num_src_fields;
296 }
297 yac_alltoallv_uint64_p2p(
298 temp_num_results_per_src_field_per_tgt, recvcounts, rdispls,
299 num_results_per_src_field_per_tgt_uint64, sendcounts, sdispls, comm,
300 routine, __LINE__);
301
302 // set up comm buffers for exchanging of the interpolation results and
303 // count the total number of weights per source field
304 size_t num_weights = 0;
305 size_t * total_num_results_per_src_field =
306 xcalloc(num_src_fields, sizeof(*total_num_results_per_src_field));
307 {
308 uint64_t * curr_num_send_results = temp_num_results_per_src_field_per_tgt;
309 uint64_t * curr_num_recv_results = num_results_per_src_field_per_tgt_uint64;
310 size_t saccu = 0, raccu = 0;
311 for (int i = 0; i < comm_size; ++i) {
312 size_t num_send_results = recvcounts[i] / num_src_fields;
313 size_t num_recv_results = sendcounts[i] / num_src_fields;
314 size_t num_send_weights = 0;
315 size_t num_recv_weights = 0;
316 for (size_t j = 0; j < num_send_results; ++j)
317 for (size_t k = 0; k < num_src_fields; ++k, ++curr_num_send_results)
318 num_send_weights += (size_t)*curr_num_send_results;
319 for (size_t j = 0; j < num_recv_results; ++j) {
320 for (size_t k = 0; k < num_src_fields; ++k, ++curr_num_recv_results) {
321 size_t curr_count = (size_t)*curr_num_recv_results;
322 num_recv_weights += curr_count;
323 total_num_results_per_src_field[k] += curr_count;
324 }
325 }
326 sdispls[i] = saccu;
327 rdispls[i] = raccu;
328 sendcounts[i] = num_send_weights;
329 recvcounts[i] = num_recv_weights;
330 saccu += num_send_weights;
331 raccu += num_recv_weights;
332 num_weights += num_recv_weights;
333 }
334 }
335
336 double * w = xmalloc(num_weights * sizeof(*w));
337 yac_int * global_ids = xmalloc(num_weights * sizeof(*global_ids));
338
339 // return interpolation results
340 yac_alltoallv_dble_p2p(
341 temp_w, sendcounts, sdispls, w, recvcounts, rdispls, comm,
342 routine, __LINE__);
343 yac_alltoallv_yac_int_p2p(
344 temp_global_ids, sendcounts, sdispls,
345 global_ids, recvcounts, rdispls, comm, routine, __LINE__);
346 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
347 free(temp_w);
348 free(temp_global_ids);
349
350 // check which target points have results
351 size_t * interpolated_flag =
352 xmalloc(temp_result_count * sizeof(*interpolated_flag));
353 size_t result_count = 0;
354 for (size_t i = 0, k = 0; i < temp_result_count; ++i) {
355 int flag = 0;
356 for (size_t j = 0; j < num_src_fields; ++j, ++k)
357 flag |= (num_results_per_src_field_per_tgt_uint64[k] > 0);
358 if (flag) {
359 if (result_count != i)
360 memmove(
361 num_results_per_src_field_per_tgt_uint64 + result_count * num_src_fields,
362 num_results_per_src_field_per_tgt_uint64 + i * num_src_fields,
363 num_src_fields * sizeof(*num_results_per_src_field_per_tgt_uint64));
364 interpolated_flag[i] = result_count++;
365 } else {
366 interpolated_flag[i] = SIZE_MAX;
367 }
368 }
369
370 // sort the target points that can be interpolated to the beginning
371 // of the array
373 interpolated_flag, temp_result_count, tgt_points);
374 free(interpolated_flag);
375
376 // sort global result ids into a per tgt per src_field order
377 size_t * global_id_reorder_idx =
378 xmalloc((num_weights + num_src_fields) * sizeof(*global_id_reorder_idx));
379 size_t * src_field_displ = global_id_reorder_idx + num_weights;
380 size_t max_num_results_per_src_field = 0;
381 size_t * num_results_per_src_field_per_tgt =
382 xmalloc(result_count * num_src_fields *
383 sizeof(*num_results_per_src_field_per_tgt));
384 for (size_t i = 0, accu = 0; i < num_src_fields; ++i) {
385 src_field_displ[i] = accu;
386 accu += total_num_results_per_src_field[i];
387 if (max_num_results_per_src_field < total_num_results_per_src_field[i])
388 max_num_results_per_src_field = total_num_results_per_src_field[i];
389 }
390 for (size_t i = 0, k = 0, l = 0; i < result_count; ++i) {
391 for (size_t j = 0; j < num_src_fields; ++j, ++k) {
392 num_results_per_src_field_per_tgt[k] =
393 (size_t)(num_results_per_src_field_per_tgt_uint64[k]);
394 size_t curr_count =
395 (size_t)(num_results_per_src_field_per_tgt_uint64[k]);
396 for (size_t m = 0; m < curr_count; ++m, ++l)
397 global_id_reorder_idx[l] = src_field_displ[j]++;
398 }
399 }
401 global_id_reorder_idx, num_weights, global_ids);
402 free(uint64_t_buffer);
403 free(global_id_reorder_idx);
404
405 // get remote data for all required source points
406 struct remote_point * srcs_per_field[num_src_fields];
407 size_t * result_point_buffer =
408 xmalloc(max_num_results_per_src_field * sizeof(*result_point_buffer));
409 for (size_t i = 0, offset = 0; i < num_src_fields; ++i) {
410 size_t curr_count = total_num_results_per_src_field[i];
412 interp_grid, i, global_ids + offset, curr_count, result_point_buffer);
413 srcs_per_field[i] =
415 interp_grid, i, result_point_buffer, curr_count);
416 offset += curr_count;
417 }
418 free(result_point_buffer);
419 free(global_ids);
420 free(total_num_results_per_src_field);
421
422 struct remote_points tgts = {
423 .data =
425 interp_grid, tgt_points, result_count),
426 .count = result_count};
427
428 // generate weights
430 weights, &tgts, num_results_per_src_field_per_tgt, srcs_per_field, w,
431 num_src_fields);
432
433 free(tgts.data);
434 for (size_t i = 0; i < num_src_fields; ++i) free(srcs_per_field[i]);
435 free(num_results_per_src_field_per_tgt);
436 free(w);
437
438 return result_count;
439}
440
443
444 struct interp_method_callback * method = xmalloc(1 * sizeof(*method));
445
448 method->user_data = user_data;
449
450 return (struct interp_method*)method;
451}
452
453static void delete_callback(struct interp_method * method) {
454 free(method);
455}
456
457typedef void (*func_dummy)(void);
458static struct {
460 void * user_data;
461 char * key;
465
468 void * user_data, char const * key) {
469
471 key != NULL,
472 "ERROR(yac_interp_method_callback_add_compute_weights_callback): "
473 "key is NULL")
474
475 for (size_t i = 0; i < callback_lookup_table_size; ++i) {
476
477 // if the key as already been set
478 if (!strcmp(callback_lookup_table[i].key, key)) {
479
483 "ERROR(interp_method_callback_add_do_search_callback): "
484 "identical key has been set before with different callback "
485 "or user data (key = \"%s\")", key)
486
487 // nothing needs to be added
488 return;
489 }
490 }
491
494
496 xmalloc((strlen(key)+1) * sizeof(*key));
502}
503
513
516 void ** user_data) {
517
519 key != NULL,
520 "ERROR(yac_interp_method_callback_get_compute_weights_callback): "
521 "key is NULL")
522
523 for (size_t i = 0; i < callback_lookup_table_size; ++i) {
524 if (!strcmp(callback_lookup_table[i].key, key)) {
526 *user_data = callback_lookup_table[i].user_data;
527 return;
528 }
529 }
531 *user_data = NULL;
532 return;
533}
#define YAC_ASSERT(exp, msg)
#define ENSURE_ARRAY_SIZE(arrayp, curr_array_size, req_size)
void yac_interp_grid_do_points_search(struct yac_interp_grid *interp_grid, yac_coordinate_pointer search_coords, size_t count, size_t *src_cells)
struct remote_point * yac_interp_grid_get_src_remote_points2(struct yac_interp_grid *interp_grid, enum yac_location location, size_t *src_points, size_t count)
size_t yac_interp_grid_get_num_src_fields(struct yac_interp_grid *interp_grid)
MPI_Comm yac_interp_grid_get_MPI_Comm(struct yac_interp_grid *interp_grid)
struct remote_point * yac_interp_grid_get_tgt_remote_points(struct yac_interp_grid *interp_grid, size_t *tgt_points, size_t count)
struct remote_point * yac_interp_grid_get_src_remote_points(struct yac_interp_grid *interp_grid, size_t src_field_idx, size_t *src_points, size_t count)
void yac_interp_grid_get_tgt_coordinates(struct yac_interp_grid *interp_grid, size_t *tgt_points, size_t count, yac_coordinate_pointer tgt_coordinates)
yac_const_coordinate_pointer yac_interp_grid_get_tgt_field_coords(struct yac_interp_grid *interp_grid)
void yac_interp_grid_src_global_to_local(struct yac_interp_grid *interp_grid, size_t src_field_idx, yac_int *src_global_ids, size_t count, size_t *src_local_ids)
void * user_data
void yac_interp_method_callback_get_compute_weights_callback(char const *key, yac_func_compute_weights *compute_weights_callback, void **user_data)
static MPI_Datatype yac_get_request_data_mpi_datatype(MPI_Comm comm)
static struct @13 * callback_lookup_table
void(* func_dummy)(void)
yac_func_compute_weights callback
static void delete_callback(struct interp_method *method)
char * key
static size_t get_valid_results(size_t *src_cells, size_t count, size_t *tgt_points)
static struct interp_method_vtable interp_method_callback_vtable
static size_t callback_lookup_table_size
struct interp_method * yac_interp_method_callback_new(yac_func_compute_weights compute_weights_callback, void *user_data)
void yac_interp_method_callback_add_compute_weights_callback(yac_func_compute_weights compute_weights_callback, void *user_data, char const *key)
static size_t callback_lookup_table_array_size
static void get_orig_data(struct remote_point const *remote_point, int *owner_rank, size_t *orig_pos)
void yac_interp_method_callback_buf_free()
static size_t do_search_callback(struct interp_method *method, struct yac_interp_grid *interp_grid, size_t *tgt_points, size_t count, struct yac_interp_weights *weights, int *interpolation_complete)
void(* yac_func_compute_weights)(double const tgt_coords[3], int src_cell_id, size_t src_cell_idx, int const **global_results_points, double **result_weights, size_t *result_count, void *user_data)
static void compute_weights(struct tgt_point_search_data *tgt_point_data, size_t num_tgt_points, struct edge_interp_data *edge_data, size_t num_edges, struct triangle_interp_data *triangle_data, size_t num_triangles, struct weight_vector_data **weights, size_t **num_weights_per_tgt, size_t *total_num_weights)
void yac_interp_weights_add_wsum_mf(struct yac_interp_weights *weights, struct remote_points *tgts, size_t *num_src_per_field_per_tgt, struct remote_point **srcs_per_field, double *w, size_t num_src_fields)
@ YAC_LOC_CELL
Definition location.h:14
#define xcalloc(nmemb, size)
Definition ppm_xfuncs.h:64
#define xmalloc(size)
Definition ppm_xfuncs.h:66
struct interp_method_vtable * vtable
yac_func_compute_weights compute_weights_callback
size_t(* do_search)(struct interp_method *method, struct yac_interp_grid *grid, size_t *tgt_points, size_t count, struct yac_interp_weights *weights, int *interpolation_complete)
single location information of a point
union remote_point_infos::@53 data
struct remote_point_info single
struct remote_point_info * multi
information (global id and location) about a point that
yac_int global_id
struct remote_point_infos data
structure containing the information (global id and location)
struct remote_point * data
static void compute_weights_callback(double const tgt_coords[3], int src_cell_id, size_t src_cell_idx, int const **global_results_points, double **result_weights, size_t *result_count, void *user_data)
void yac_quicksort_index_size_t_yac_int(size_t *a, size_t n, yac_int *idx)
void yac_quicksort_index_size_t_size_t(size_t *a, size_t n, size_t *idx)
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:19
void yac_generate_alltoallv_args(int count, size_t const *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls, MPI_Comm comm)
Definition yac_mpi.c:577
void yac_free_comm_buffers(size_t *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls)
Definition yac_mpi.c:633
void yac_get_comm_buffers(int count, size_t **sendcounts, size_t **recvcounts, size_t **sdispls, size_t **rdispls, MPI_Comm comm)
Definition yac_mpi.c:602
MPI_Datatype yac_create_resized(MPI_Datatype dt, size_t new_size, MPI_Comm comm)
Definition yac_mpi.c:556
void yac_alltoallv_p2p(void const *send_buffer, size_t const *sendcounts, size_t const *sdispls, void *recv_buffer, size_t const *recvcounts, size_t const *rdispls, size_t dt_size, MPI_Datatype dt, MPI_Comm comm, char const *caller, int line)
Definition yac_mpi.c:131
#define yac_mpi_call(call, comm)
Xt_int yac_int
Definition yac_types.h:15
double const (* yac_const_coordinate_pointer)[3]
Definition yac_types.h:20
#define yac_int_dt
Definition yac_types.h:16
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:19