YAC 3.21.0
Yet Another Coupler
Loading...
Searching...
No Matches
interp_method_file.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#include <limits.h>
6#include <string.h>
7
11#include "parameter/param_str.h"
15#include "instrument_internal.h"
16#include "yac_mpi_internal.h"
17#include "io_utils.h"
18#include "yac_mpi_common.h"
19
20#ifdef YAC_NETCDF_ENABLED
21#include <netcdf.h>
22#endif
23
24static size_t do_search_file(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_file(struct interp_method * method);
30
31static struct interp_method_vtable
35
43
44struct link_data {
45 union {
47 size_t local_id;
48 } src, tgt;
49 double weight;
51};
52
53struct fixed_data {
54 double value;
55 struct {
57 } * tgt;
58 size_t num_tgt;
59};
60
62 double value;
63 struct {
65 } tgt;
66};
67
69 enum {
70 LINK = 0,
71 FIXED = 1,
74 union {
75 struct {
76 struct link_data * links;
77 size_t count;
79 struct {
80 double value;
83 struct {
85 size_t local_id;
86 } tgt;
87 int owner;
89};
90
91static void read_weight_file(
92 char const * weight_file_name, MPI_Comm comm,
93 char const * src_grid_name, char const * tgt_grid_name,
94 enum yac_location * src_locations, enum yac_location tgt_location,
95 size_t num_src_fields,
96 struct link_data ** links, size_t * num_links,
97 struct fixed_data ** fixed, size_t * num_fixed) {
98
99#ifndef YAC_NETCDF_ENABLED
100
102 UNUSED(comm);
105 UNUSED(src_locations);
106 UNUSED(tgt_location);
107 UNUSED(num_src_fields);
108 UNUSED(links);
109 UNUSED(num_links);
110 UNUSED(fixed);
111 UNUSED(num_fixed);
112
113 die("ERROR(read_weight_file): YAC is built without the NetCDF support");
114#else
115
116 *links = NULL;
117 *num_links = 0;
118 *fixed = NULL;
119 *num_fixed = 0;
120
121 int rank;
122 yac_mpi_call(MPI_Comm_rank(comm, &rank), comm);
123
124 // determine ranks that do input
125 int local_is_io;
126 int * io_ranks;
127 int num_io_ranks;
128 yac_get_io_ranks(comm, &local_is_io, &io_ranks, &num_io_ranks);
129
130 int io_idx = INT_MAX;
131 if (local_is_io)
132 for (int i = 0; (i < num_io_ranks) && (io_idx == INT_MAX); ++i)
133 if (io_ranks[i] == rank) io_idx = i;
134 free(io_ranks);
135
136 // if the local process does not have to read anything from the file
137 if (!local_is_io) return;
138
139 // open weight file on io processes
140 int ncid;
141 yac_nc_open(weight_file_name, NC_NOWRITE, &ncid);
142
143 //\todo use parallel netcdf if available
144
145 int dimid, var_id;
146
147 // global attributes
148 size_t version_len;
149 char * version;
150 YAC_HANDLE_ERROR(nc_inq_attlen(ncid, NC_GLOBAL, "version", &version_len));
151 version = xmalloc(version_len + 1);
152 version[version_len] = '\0';
153 YAC_HANDLE_ERROR(nc_get_att_text(ncid, NC_GLOBAL, "version", version));
155 (strlen(YAC_WEIGHT_FILE_VERSION_STRING) == version_len) &&
156 !strncmp(version, YAC_WEIGHT_FILE_VERSION_STRING, version_len),
157 "version string from weight file (\"%s\") does not match "
158 "with YAC version \"%s\"", version, YAC_WEIGHT_FILE_VERSION_STRING)
159 free(version);
160
161 size_t grid_name_len;
162 char * grid_name;
163 YAC_HANDLE_ERROR(nc_inq_attlen(ncid, NC_GLOBAL, "src_grid_name", &grid_name_len));
164 grid_name = xmalloc(grid_name_len + 1);
165 grid_name[grid_name_len] = '\0';
166 YAC_HANDLE_ERROR(nc_get_att_text(ncid, NC_GLOBAL, "src_grid_name", grid_name));
168 (strlen(src_grid_name) == grid_name_len) &&
169 !strncmp(src_grid_name, grid_name, grid_name_len),
170 "source grid name from weight file (\"%s\") "
171 "does not match with the one provided through the interface (\"%s\")",
172 grid_name, src_grid_name)
173
174 free(grid_name);
175
176 YAC_HANDLE_ERROR(nc_inq_attlen(ncid, NC_GLOBAL, "dst_grid_name", &grid_name_len));
177 grid_name = xmalloc(grid_name_len + 1);
178 grid_name[grid_name_len] = '\0';
179 YAC_HANDLE_ERROR(nc_get_att_text(ncid, NC_GLOBAL, "dst_grid_name", grid_name));
181 (strlen(tgt_grid_name) == grid_name_len) &&
182 !strncmp(tgt_grid_name, grid_name, grid_name_len),
183 "target grid name from weight file (\"%s\") "
184 "does not match with the one provided through the interface (\"%s\")",
185 grid_name, tgt_grid_name)
186
187 free(grid_name);
188
189 //---------------
190 // read link data
191 //---------------
192
193 size_t str_link_len;
194 char * str_link;
195 var_id = NC_GLOBAL;
196 YAC_HANDLE_ERROR(nc_inq_attlen(ncid, var_id, "contains_links", &str_link_len));
197 str_link = xmalloc(str_link_len + 1);
198 str_link[str_link_len] = '\0';
199 YAC_HANDLE_ERROR(nc_get_att_text(ncid, var_id, "contains_links", str_link));
200
201 int contains_links = (strlen("TRUE") == str_link_len) &&
202 !strncmp("TRUE", str_link, str_link_len);
204 contains_links ||
205 ((strlen("FALSE") == str_link_len) &&
206 !strncmp("FALSE", str_link, str_link_len)),
207 "invalid global attribute contains_links")
208 free(str_link);
209
210 size_t num_wgts = 0;
211 if (contains_links) {
212 yac_nc_inq_dimid(ncid, "num_wgts", &dimid);
213 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &num_wgts));
214 YAC_ASSERT(num_wgts == 1, "YAC only supports num_wgts == 1")
215 }
216
217 // get number of links from file
218
219 size_t num_links_in_file = 0;
220 if (contains_links) {
221 yac_nc_inq_dimid(ncid, "num_links", &dimid);
222 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &num_links_in_file));
223 YAC_ASSERT(num_links_in_file != 0, "no links defined")
224 }
225
226 // get number of source fields
227 size_t tmp_num_src_fields = 0;
228 if (contains_links) {
229 yac_nc_inq_dimid(ncid, "num_src_fields", &dimid);
230 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &tmp_num_src_fields));
231 YAC_ASSERT(tmp_num_src_fields != 0, "no source fields in file")
233 tmp_num_src_fields == num_src_fields,
234 "number of source fields in file (%zu) does not "
235 "match with the number provided through the interface (%zu)",
236 tmp_num_src_fields, num_src_fields)
237 }
238
239 // get max location string length from file
240 size_t max_loc_str_len;
241 yac_nc_inq_dimid(ncid, "max_loc_str_len", &dimid);
242 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &max_loc_str_len));
244 max_loc_str_len == YAC_MAX_LOC_STR_LEN,
245 "wrong max location string length in weight file")
246
247 // get source locations
248 enum yac_location * tmp_src_locations =
249 xmalloc(num_src_fields * sizeof(*tmp_src_locations));
250 yac_nc_inq_varid(ncid, "src_locations", &var_id);
251
252 for (size_t i = 0; i < num_src_fields; ++i) {
253
254 char loc_str[YAC_MAX_LOC_STR_LEN];
255
256 size_t str_start[2] = {i, 0};
257 size_t str_count[2] = {1, YAC_MAX_LOC_STR_LEN};
258
260 nc_get_vara_text(ncid, var_id, str_start, str_count, loc_str));
261
262 tmp_src_locations[i] = yac_str2loc(loc_str);
263
265 tmp_src_locations[i] == src_locations[i],
266 "source locations in file does not match with "
267 "the locations provided through the interface\n"
268 "location index: %d\n"
269 "location in weight file: %s\n"
270 "location from interface: %s",
271 (int)i, loc_str, yac_loc2str(src_locations[i]))
272 }
273
274 free(tmp_src_locations);
275
276 // get target location
277 yac_nc_inq_varid(ncid, "dst_location", &var_id);
278 {
279 char loc_str[YAC_MAX_LOC_STR_LEN];
280 YAC_HANDLE_ERROR(nc_get_var_text(ncid, var_id, loc_str));
282 tgt_location == yac_str2loc(loc_str),
283 "target locations in file does not match with "
284 "the locations provided through the interface")
285 }
286
287 if (contains_links) {
288
289 // get number of links per source field
290 unsigned * num_links_per_src_field =
291 xmalloc(num_src_fields * sizeof(*num_links_per_src_field));
292 yac_nc_inq_varid(ncid, "num_links_per_src_field", &var_id);
293 YAC_HANDLE_ERROR(nc_get_var_uint(ncid, var_id, num_links_per_src_field));
294
295 size_t offset =
296 (size_t)(((long long)io_idx * (long long)num_links_in_file) /
297 (long long)num_io_ranks);
298 size_t count =
299 (size_t)((((long long)io_idx + 1) * (long long)num_links_in_file) /
300 (long long)num_io_ranks) - offset;
301
302 *num_links = count;
303
304 *links = xmalloc(count * sizeof(**links));
305
306 if (count > 0) {
307 size_t src_field_idx = 0, src_field_start_offset = 0;
308 while ((src_field_idx < num_src_fields) &&
309 (src_field_start_offset +
310 (size_t)num_links_per_src_field[src_field_idx] <
311 offset)) {
312
313 src_field_start_offset += (size_t)num_links_per_src_field[src_field_idx];
314 ++src_field_idx;
315 };
317 src_field_idx < num_src_fields, "problem in num_links_per_src_field")
318 size_t src_field_offset = offset - src_field_start_offset;
319 for (size_t k = 0; (src_field_idx < num_src_fields) && (k < count);
320 src_field_offset = 0, ++src_field_idx) {
321
322 for (; (src_field_offset <
323 (size_t)num_links_per_src_field[src_field_idx]) &&
324 (k < count); ++src_field_offset, ++k) {
325 (*links)[k].src_field_idx = src_field_idx;
326 }
327 }
328 }
329 free(num_links_per_src_field);
330
331 // get links
332 int * address = xmalloc(count * sizeof(*address));
333 yac_nc_inq_varid(ncid, "src_address", &var_id);
334 YAC_HANDLE_ERROR(nc_get_vara_int(ncid, var_id, &offset, &count, address));
335 for (size_t i = 0; i < count; ++i)
336 (*links)[i].src.global_id = (yac_int)(address[i] - 1);
337
338 yac_nc_inq_varid(ncid, "dst_address", &var_id);
339 YAC_HANDLE_ERROR(nc_get_vara_int(ncid, var_id, &offset, &count, address));
340 for (size_t i = 0; i < count; ++i)
341 (*links)[i].tgt.global_id = (yac_int)(address[i] - 1);
342 free(address);
343
344 double * weights = xmalloc(count * sizeof(*weights));
345
346 yac_nc_inq_varid(ncid, "remap_matrix", &var_id);
347 size_t offsets[2] = {offset, 0};
348 size_t counts[2] = {count, 1};
349 YAC_HANDLE_ERROR(nc_get_vara_double(ncid, var_id, offsets, counts, weights));
350 for (size_t i = 0; i < count; ++i)
351 (*links)[i].weight = weights[i];
352
353 free(weights);
354 }
355
356 //----------------
357 // read fixed data
358 //----------------
359
360 // global attributes
361 size_t str_fixed_len;
362 char * str_fixed;
363 var_id = NC_GLOBAL;
365 nc_inq_attlen(ncid, var_id, "contains_fixed_dst", &str_fixed_len));
366 str_fixed = xmalloc(str_fixed_len + 1);
367 str_fixed[str_fixed_len] = '\0';
368 YAC_HANDLE_ERROR(nc_get_att_text(ncid, var_id, "contains_fixed_dst", str_fixed));
369
370 int contains_fixed = (strlen("TRUE") == str_fixed_len) &&
371 !strncmp("TRUE", str_fixed, str_fixed_len);
372
374 contains_fixed ||
375 ((strlen("FALSE") == str_fixed_len) &&
376 !strncmp("FALSE", str_fixed, str_fixed_len)),
377 "invalid global attribute contains_fixed_dst")
378 free(str_fixed);
379
380 if (contains_fixed) {
381
382 // get number of fixed values
383 size_t num_fixed_values;
384 yac_nc_inq_dimid(ncid, "num_fixed_values", &dimid);
385 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &num_fixed_values));
386
387 // get number of fixed target points
388 size_t num_fixed_tgt;
389 yac_nc_inq_dimid(ncid, "num_fixed_dst", &dimid);
390 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &num_fixed_tgt));
391
392 size_t offset =
393 (size_t)(((long long)io_idx * (long long)num_fixed_tgt) /
394 (long long)num_io_ranks);
395 size_t count =
396 (size_t)((((long long)io_idx + 1) * (long long)num_fixed_tgt) /
397 (long long)num_io_ranks) - offset;
398
399 *fixed = xmalloc(num_fixed_values * sizeof(**fixed));
400 *num_fixed = num_fixed_values;
401
402 double * fixed_values = xmalloc(num_fixed_values * sizeof(*fixed_values));
403 int * num_tgt_indices_per_fixed_value =
404 xmalloc(num_fixed_values * sizeof(*num_tgt_indices_per_fixed_value));
405 int * global_tgt_indices = xmalloc(count * sizeof(*global_tgt_indices));
406
407 // get number of fixed target points per fixed value
408 yac_nc_inq_varid(ncid, "num_dst_per_fixed_value", &var_id);
409 YAC_HANDLE_ERROR(nc_get_var_int(ncid, var_id, num_tgt_indices_per_fixed_value));
410
411 // read data
412 yac_nc_inq_varid(ncid, "fixed_values", &var_id);
413 YAC_HANDLE_ERROR(nc_get_var_double(ncid, var_id, fixed_values));
414
415 yac_nc_inq_varid(ncid, "dst_address_fixed", &var_id);
417 nc_get_vara_int(ncid, var_id, &offset, &count, global_tgt_indices));
418
419 if (count > 0) {
420 void * tgt_global_id_buffer = xmalloc(count * sizeof(*((*fixed)->tgt)));
421 size_t fixed_value_idx = 0, fixed_value_start_offset = 0;
422 while ((fixed_value_idx < num_fixed_values) &&
423 (fixed_value_start_offset +
424 (size_t)num_tgt_indices_per_fixed_value[fixed_value_idx] <
425 offset)) {
426
427 fixed_value_start_offset +=
428 (size_t)num_tgt_indices_per_fixed_value[fixed_value_idx];
429 (*fixed)[fixed_value_idx].value = fixed_values[fixed_value_idx];
430 (*fixed)[fixed_value_idx].num_tgt = 0;
431 (*fixed)[fixed_value_idx].tgt = tgt_global_id_buffer;
432 ++fixed_value_idx;
433 };
435 fixed_value_idx < num_fixed_values,
436 "problem in num_tgt_indices_per_fixed_value")
437 size_t fixed_value_offset = offset - fixed_value_start_offset;
438 for (size_t k = 0; (fixed_value_idx < num_fixed_values) && (k < count);
439 fixed_value_offset = 0, ++fixed_value_idx) {
440
441 size_t curr_tgt_count =
442 MIN((size_t)num_tgt_indices_per_fixed_value[fixed_value_idx] -
443 fixed_value_offset, count - k);
444
445 (*fixed)[fixed_value_idx].value = fixed_values[fixed_value_idx];
446 (*fixed)[fixed_value_idx].num_tgt = curr_tgt_count;
447 (*fixed)[fixed_value_idx].tgt =
448 (void*)(((unsigned char *)tgt_global_id_buffer) +
449 k * sizeof(*((*fixed)->tgt)));
450
451 for (size_t i = 0; i < curr_tgt_count; ++fixed_value_offset, ++k, ++i)
452 (*fixed)[fixed_value_idx].tgt[i].global_id =
453 (yac_int)(global_tgt_indices[k] - 1);
454 }
455 for (; fixed_value_idx < num_fixed_values; ++fixed_value_idx) {
456 (*fixed)[fixed_value_idx].value = fixed_values[fixed_value_idx];
457 (*fixed)[fixed_value_idx].num_tgt = 0;
458 (*fixed)[fixed_value_idx].tgt = NULL;
459 }
460 }
461 free(fixed_values);
462 free(global_tgt_indices);
463 free(num_tgt_indices_per_fixed_value);
464 }
465
466 // close file
467 YAC_HANDLE_ERROR(nc_close(ncid));
468#endif
469}
470
471static inline int
472compute_bucket(yac_int value, int comm_size) {
473 return (int)(value / 128) % comm_size;
474}
475
476static int get_tgt_pack_size(MPI_Comm comm) {
477
478 int tgt_pack_size;
479 yac_mpi_call(MPI_Pack_size(1, yac_int_dt, comm, &tgt_pack_size), comm);
480 return tgt_pack_size;
481}
482
483static int get_link_pack_size(MPI_Comm comm) {
484
485 int global_id_pack_size;
486 int weight_pack_size;
487 int src_field_idx_pack_size;
488
490 MPI_Pack_size(1, yac_int_dt, comm, &global_id_pack_size), comm);
492 MPI_Pack_size(1, MPI_DOUBLE, comm, &weight_pack_size), comm);
494 MPI_Pack_size(1, MPI_UINT64_T, comm, &src_field_idx_pack_size), comm);
495
496 return 2 * global_id_pack_size + weight_pack_size +
497 src_field_idx_pack_size;
498}
499
500static int get_fixed_pack_size(MPI_Comm comm) {
501
502 int value_pack_size;
503 int global_id_pack_size;
504 int count_pack_size;
505
507 MPI_Pack_size(1, MPI_DOUBLE, comm, &value_pack_size), comm);
509 MPI_Pack_size(1, yac_int_dt, comm, &global_id_pack_size), comm);
511 MPI_Pack_size(1, MPI_UINT64_T, comm, &count_pack_size), comm);
512
513 return value_pack_size + global_id_pack_size + count_pack_size;
514}
515
516static void pack_tgt(
517 yac_int global_tgt_id, void * buffer, int buffer_size, MPI_Comm comm) {
518
519 int position = 0;
521 MPI_Pack(&global_tgt_id, 1, yac_int_dt, buffer,
522 buffer_size, &position, comm), comm);
523}
524
525static void pack_link(
526 struct link_data * link, void * buffer, int buffer_size, MPI_Comm comm) {
527
528 int position = 0;
530 MPI_Pack(&(link->src.global_id), 1, yac_int_dt, buffer,
531 buffer_size, &position, comm), comm);
533 MPI_Pack(&(link->tgt.global_id), 1, yac_int_dt, buffer,
534 buffer_size, &position, comm), comm);
536 MPI_Pack(&(link->weight), 1, MPI_DOUBLE, buffer,
537 buffer_size, &position, comm), comm);
538 uint64_t temp_src_field_idx = (uint64_t)(link->src_field_idx);
540 MPI_Pack(&temp_src_field_idx, 1, MPI_UINT64_T, buffer,
541 buffer_size, &position, comm), comm);
542
543}
544
545static void pack_fixed(
546 double fixed_value, yac_int global_tgt_id,
547 void * buffer, int buffer_size, MPI_Comm comm) {
548
549 int position = 0;
551 MPI_Pack(&fixed_value, 1, MPI_DOUBLE, buffer,
552 buffer_size, &position, comm), comm);
554 MPI_Pack(&global_tgt_id, 1, yac_int_dt, buffer,
555 buffer_size, &position, comm), comm);
556}
557
558static void unpack_tgt(
559 void * buffer, int buffer_size, yac_int * global_tgt_id, MPI_Comm comm) {
560
561 int position = 0;
563 MPI_Unpack(buffer, buffer_size, &position, global_tgt_id, 1,
564 yac_int_dt, comm), comm);
565}
566
567static void unpack_link(
568 void * buffer, int buffer_size, struct link_data * link, MPI_Comm comm) {
569
570 int position = 0;
572 MPI_Unpack(buffer, buffer_size, &position, &(link->src.global_id), 1,
573 yac_int_dt, comm), comm);
575 MPI_Unpack(buffer, buffer_size, &position, &(link->tgt.global_id), 1,
576 yac_int_dt, comm), comm);
578 MPI_Unpack(buffer, buffer_size, &position, &(link->weight), 1,
579 MPI_DOUBLE, comm), comm);
580 uint64_t temp_src_field_idx;
582 MPI_Unpack(buffer, buffer_size, &position, &temp_src_field_idx, 1,
583 MPI_UINT64_T, comm), comm);
584 link->src_field_idx = (size_t)temp_src_field_idx;
585}
586
587static void unpack_fixed(
588 void * buffer, int buffer_size, struct temp_fixed_data * fixed,
589 MPI_Comm comm) {
590
591 int position = 0;
593 MPI_Unpack(buffer, buffer_size, &position, &(fixed->value), 1,
594 MPI_DOUBLE, comm), comm);
596 MPI_Unpack(buffer, buffer_size, &position, &(fixed->tgt.global_id), 1,
597 yac_int_dt, comm), comm);
598}
599
600static int compare_temp_result_tgt (void const * a, void const * b) {
601
602 struct temp_result const * result_a = (struct temp_result const *)a;
603 struct temp_result const * result_b = (struct temp_result const *)b;
604
605 return (result_a->tgt.global_id > result_b->tgt.global_id) -
606 (result_a->tgt.global_id < result_b->tgt.global_id);
607}
608
609static int compare_link_data_tgt (void const * a, void const * b) {
610
611 struct link_data const * link_a = (struct link_data const *)a;
612 struct link_data const * link_b = (struct link_data const *)b;
613
614 return (link_a->tgt.global_id > link_b->tgt.global_id) -
615 (link_a->tgt.global_id < link_b->tgt.global_id);
616}
617
618static int compare_temp_result_type (void const * a, void const * b) {
619
620 struct temp_result const * result_a = (struct temp_result const *)a;
621 struct temp_result const * result_b = (struct temp_result const *)b;
622
623 return (result_a->type > result_b->type) - (result_a->type < result_b->type);
624}
625
626static int compare_temp_result_fixed (void const * a, void const * b) {
627
628 struct temp_result const * result_a = (struct temp_result const *)a;
629 struct temp_result const * result_b = (struct temp_result const *)b;
630
631 return (result_a->data.fixed.value > result_b->data.fixed.value) -
632 (result_a->data.fixed.value < result_b->data.fixed.value);
633}
634
635static int compare_temp_result_reorder_idx (void const * a, void const * b) {
636
637 struct temp_result const * result_a = (struct temp_result const *)a;
638 struct temp_result const * result_b = (struct temp_result const *)b;
639
640 return (result_a->reorder_idx > result_b->reorder_idx) -
641 (result_a->reorder_idx < result_b->reorder_idx);
642}
643
644static int compare_temp_fixed_data_tgt (void const * a, void const * b) {
645
646 struct temp_fixed_data const * fixed_a = (struct temp_fixed_data const *)a;
647 struct temp_fixed_data const * fixed_b = (struct temp_fixed_data const *)b;
648
649 return (fixed_a->tgt.global_id > fixed_b->tgt.global_id) -
650 (fixed_a->tgt.global_id < fixed_b->tgt.global_id);
651}
652
654 struct temp_result * result, MPI_Comm comm) {
655
656 int type_pack_size;
657 int data_pack_size;
658 int owner_pack_size;
659
661 MPI_Pack_size(1, MPI_INT, comm, &type_pack_size), comm);
663 (result->type == LINK) ||
664 (result->type == FIXED) ||
665 (result->type == NO_INTERP), "invalid result type")
666 switch(result->type) {
667 case(LINK): {
668 int count_pack_size;
669 int links_pack_size;
671 MPI_Pack_size(1, MPI_UINT64_T, comm, &count_pack_size), comm);
672 links_pack_size =
673 (int)(result->data.link.count) * get_link_pack_size(comm);
674 data_pack_size = links_pack_size + count_pack_size;
675 break;
676 }
677 case(FIXED): {
678 int fixed_value_pack_size;
680 MPI_Pack_size(1, MPI_DOUBLE, comm, &fixed_value_pack_size), comm);
681 data_pack_size = fixed_value_pack_size;
682 break;
683 }
684 default:
685 case(NO_INTERP): {
686 data_pack_size = 0;
687 break;
688 }
689 };
690 int tgt_global_id_pack_size;
692 MPI_Pack_size(1, yac_int_dt, comm, &tgt_global_id_pack_size), comm);
694 MPI_Pack_size(1, MPI_INT, comm, &owner_pack_size), comm);
695
696 return type_pack_size + data_pack_size + tgt_global_id_pack_size +
697 owner_pack_size;
698}
699
701 struct temp_result * result, void * buffer, int buffer_size, MPI_Comm comm) {
702
703 int position = 0;
704 int temp_type = (int)(result->type);
706 MPI_Pack(&temp_type, 1, MPI_INT, buffer,
707 buffer_size, &position, comm), comm);
709 (result->type == LINK) ||
710 (result->type == FIXED) ||
711 (result->type == NO_INTERP), "invalid result type")
712 switch(result->type) {
713 case(LINK): {
714 uint64_t temp_count = (uint64_t)(result->data.link.count);
716 MPI_Pack(&temp_count, 1, MPI_UINT64_T, buffer,
717 buffer_size, &position, comm), comm);
718 for (uint64_t i = 0; i < temp_count; ++i) {
720 MPI_Pack(&(result->data.link.links[i].src.global_id), 1,
721 yac_int_dt, buffer, buffer_size, &position, comm), comm);
723 MPI_Pack(&(result->data.link.links[i].tgt.global_id), 1,
724 yac_int_dt, buffer, buffer_size, &position, comm), comm);
726 MPI_Pack(&(result->data.link.links[i].weight), 1,
727 MPI_DOUBLE, buffer, buffer_size, &position, comm), comm);
728 uint64_t temp_src_field_idx =
729 (uint64_t)result->data.link.links[i].src_field_idx;
731 MPI_Pack(&temp_src_field_idx, 1, MPI_UINT64_T,
732 buffer, buffer_size, &position, comm), comm);
733 }
734 break;
735 }
736 case(FIXED): {
738 MPI_Pack(&(result->data.fixed.value), 1,
739 MPI_DOUBLE, buffer, buffer_size, &position, comm), comm);
740 break;
741 }
742 default:
743 case(NO_INTERP): {
744 break;
745 }
746 };
748 MPI_Pack(&(result->tgt.global_id), 1,
749 yac_int_dt, buffer, buffer_size, &position, comm), comm);
751 MPI_Pack(&(result->owner), 1, MPI_INT,
752 buffer, buffer_size, &position, comm), comm);
753}
754
756 void * buffer, int buffer_size, struct temp_result * result,
757 MPI_Comm comm) {
758
759 int position = 0;
760
761 int temp_type;
763 MPI_Unpack(buffer, buffer_size, &position, &temp_type, 1,
764 MPI_INT, comm), comm);
766 (temp_type == LINK) || (temp_type == FIXED) || (temp_type == NO_INTERP),
767 "invalid result type")
768 switch (temp_type) {
769 case(LINK): {
770 result->type = LINK;
771 uint64_t temp_count;
773 MPI_Unpack(buffer, buffer_size, &position, &temp_count, 1,
774 MPI_UINT64_T, comm), comm);
775 result->data.link.count = (size_t)temp_count;
776 result->data.link.links =
777 xmalloc((size_t)temp_count * sizeof(*(result->data.link.links)));
778 for (uint64_t i = 0; i < temp_count; ++i) {
779
781 MPI_Unpack(buffer, buffer_size, &position,
782 &(result->data.link.links[i].src.global_id), 1,
783 yac_int_dt, comm), comm);
785 MPI_Unpack(buffer, buffer_size, &position,
786 &(result->data.link.links[i].tgt.global_id), 1,
787 yac_int_dt, comm), comm);
789 MPI_Unpack(buffer, buffer_size, &position,
790 &(result->data.link.links[i].weight), 1,
791 MPI_DOUBLE, comm), comm);
792 uint64_t temp_src_field_idx;
794 MPI_Unpack(buffer, buffer_size, &position, &temp_src_field_idx, 1,
795 MPI_UINT64_T, comm), comm);
796 result->data.link.links[i].src_field_idx = (size_t)temp_src_field_idx;
797 }
798 break;
799 }
800 case (FIXED): {
801 result->type = FIXED;
803 MPI_Unpack(buffer, buffer_size, &position,
804 &(result->data.fixed.value), 1, MPI_DOUBLE, comm), comm);
805 break;
806 }
807 default:
808 case (NO_INTERP): {
809 result->type = NO_INTERP;
810 break;
811 }
812 };
814 MPI_Unpack(buffer, buffer_size, &position,
815 &(result->tgt.global_id), 1, yac_int_dt, comm), comm);
817 MPI_Unpack(buffer, buffer_size, &position,
818 &(result->owner), 1, MPI_INT, comm), comm);
819}
820
822 struct yac_interp_grid * interp_grid, size_t * tgt_points, size_t tgt_count,
823 size_t * num_interpolated_points,
824 struct link_data ** links, size_t * num_links,
825 struct fixed_data ** fixed, size_t * num_fixed) {
826
827 MPI_Comm comm = yac_interp_grid_get_MPI_Comm(interp_grid);
828
829 int comm_size;
830 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
831
832 // get global ids of target points that have to be interpolated
833 yac_int * tgt_global_ids = xmalloc(tgt_count * sizeof(*tgt_global_ids));
835 interp_grid, tgt_points, tgt_count, tgt_global_ids);
836
837 yac_quicksort_index_yac_int_size_t(tgt_global_ids, tgt_count, tgt_points);
838
839 int tgt_pack_size = get_tgt_pack_size(comm),
840 link_pack_size = get_link_pack_size(comm),
841 fixed_pack_size = get_fixed_pack_size(comm);
842
843 size_t * size_t_buffer =
844 xmalloc(4 * (size_t)comm_size * sizeof(*size_t_buffer));
845 size_t * total_sendcounts = size_t_buffer + 0 * comm_size;
846 size_t * total_recvcounts = size_t_buffer + 1 * comm_size;
847 size_t * total_sdispls = size_t_buffer + 2 * comm_size;
848 size_t * total_rdispls = size_t_buffer + 3 * comm_size;
849 size_t * sendcounts, * recvcounts, * sdispls, *rdispls;
851 3, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
852
853 for (size_t i = 0; i < tgt_count; ++i)
854 sendcounts[3 * compute_bucket(tgt_global_ids[i], comm_size) + 0]++;
855 for (size_t i = 0; i < *num_links; ++i)
856 sendcounts[3 * compute_bucket((*links)[i].tgt.global_id, comm_size) + 1]++;
857 for (size_t i = 0; i < *num_fixed; ++i)
858 for (size_t j = 0; j < (*fixed)[i].num_tgt; ++j)
859 sendcounts[
860 3 * compute_bucket((*fixed)[i].tgt[j].global_id, comm_size) + 2]++;
861
862 // exchange sendcounts
863 yac_mpi_call(MPI_Alltoall(sendcounts, 3, YAC_MPI_SIZE_T,
864 recvcounts, 3, YAC_MPI_SIZE_T, comm), comm);
865
866 size_t saccu = 0, raccu = 0;
867 for (int i = 0; i < comm_size; ++i) {
868 total_sdispls[i] = saccu;
869 sdispls[3*i+0] = saccu;
870 sdispls[3*i+1] =
871 (saccu +
872 (total_sendcounts[i] =
873 sendcounts[3*i+0] * (size_t)tgt_pack_size));
874 sdispls[3*i+2] =
875 (saccu +
876 (total_sendcounts[i] +=
877 sendcounts[3*i+1] * (size_t)link_pack_size));
878 total_sendcounts[i] +=
879 sendcounts[3*i+2] * (size_t)fixed_pack_size;
880 total_rdispls[i] = raccu;
881 rdispls[3*i+0] = raccu;
882 rdispls[3*i+1] =
883 (raccu +
884 (total_recvcounts[i] =
885 recvcounts[3*i+0] * (size_t)tgt_pack_size));
886 rdispls[3*i+2] =
887 (raccu +
888 (total_recvcounts[i] +=
889 recvcounts[3*i+1] * (size_t)link_pack_size));
890 total_recvcounts[i] +=
891 recvcounts[3*i+2] * (size_t)fixed_pack_size;
892 saccu += total_sendcounts[i];
893 raccu += total_recvcounts[i];
894 }
895
896 size_t send_size = total_sendcounts[comm_size - 1] +
897 total_sdispls[comm_size - 1];
898 size_t recv_size = total_recvcounts[comm_size - 1] +
899 total_rdispls[comm_size - 1];
900
901 void * pack_buffer = xmalloc(send_size + recv_size);
902 void * send_pack_buffer = pack_buffer;
903 void * recv_pack_buffer = (void*)((unsigned char *)pack_buffer + send_size);
904
905 // pack data
906 for (size_t i = 0; i < tgt_count; ++i) {
907 yac_int curr_global_id = tgt_global_ids[i];
908 int rank = compute_bucket(curr_global_id, comm_size);
909 pack_tgt(
910 curr_global_id,
911 (void*)((unsigned char*)send_pack_buffer + sdispls[3*rank+0]),
912 tgt_pack_size, comm);
913 sdispls[3*rank+0] += (size_t)tgt_pack_size;
914 }
915 for (size_t i = 0; i < *num_links; ++i) {
916 struct link_data * curr_link = (*links) + i;
917 int rank = compute_bucket(curr_link->tgt.global_id, comm_size);
918 pack_link(
919 curr_link,
920 (void*)((unsigned char*)send_pack_buffer + sdispls[3*rank+1]),
921 link_pack_size, comm);
922 sdispls[3*rank+1] += (size_t)link_pack_size;
923 }
924 for (size_t i = 0; i < *num_fixed; ++i) {
925 double curr_fixed_value = (*fixed)[i].value;
926 size_t curr_num_tgt = (*fixed)[i].num_tgt;
927 for (size_t j = 0; j < curr_num_tgt; ++j) {
928 yac_int curr_global_id = (*fixed)[i].tgt[j].global_id;
929 int rank = compute_bucket(curr_global_id, comm_size);
931 curr_fixed_value, curr_global_id,
932 (void*)((unsigned char*)send_pack_buffer + sdispls[3*rank+2]),
933 fixed_pack_size, comm);
934 sdispls[3*rank+2] += (size_t)fixed_pack_size;
935 }
936 }
937
938 // exchange data
939 yac_alltoallv_packed_p2p(
940 send_pack_buffer, total_sendcounts, total_sdispls,
941 recv_pack_buffer, total_recvcounts, total_rdispls, comm,
942 __func__, __LINE__);
943
944 size_t recv_tgt_count = 0, recv_link_count = 0, recv_fixed_count = 0;
945 for (int i = 0; i < comm_size; ++i) {
946 recv_tgt_count += recvcounts[3*i+0];
947 recv_link_count += recvcounts[3*i+1];
948 recv_fixed_count += recvcounts[3*i+2];
949 }
950 struct link_data * recv_links =
951 xrealloc(*links, recv_link_count * sizeof(*recv_links));
952 struct temp_fixed_data * recv_fixed =
953 xmalloc(recv_fixed_count * sizeof(*recv_fixed));
954 struct temp_result * result_buffer =
955 xmalloc((recv_tgt_count + tgt_count) * sizeof(*result_buffer));
956 struct temp_result * send_results = result_buffer;
957 struct temp_result * recv_results = result_buffer + recv_tgt_count;
958
959 // unpack data
960 recv_tgt_count = 0, recv_link_count = 0, recv_fixed_count = 0;
961 size_t unpack_offset = 0;
962 for (int i = 0; i < comm_size; ++i) {
963 size_t curr_num_tgt = recvcounts[3 * i + 0];
964 size_t curr_num_links = recvcounts[3 * i + 1];
965 size_t curr_num_fixed = recvcounts[3 * i + 2];
966 for (size_t j = 0; j < curr_num_tgt; ++j, ++recv_tgt_count) {
968 (void*)((unsigned char *)recv_pack_buffer + unpack_offset),
969 tgt_pack_size, &(send_results[recv_tgt_count].tgt.global_id),
970 comm);
971 unpack_offset += (size_t)tgt_pack_size;
972 send_results[recv_tgt_count].owner = i;
973 send_results[recv_tgt_count].reorder_idx = recv_tgt_count;
974 }
975 for (size_t j = 0; j < curr_num_links; ++j, ++recv_link_count) {
977 (void*)((unsigned char *)recv_pack_buffer + unpack_offset),
978 link_pack_size, recv_links + recv_link_count, comm);
979 unpack_offset += (size_t)link_pack_size;
980 }
981 for (size_t j = 0; j < curr_num_fixed; ++j, ++recv_fixed_count) {
983 (void*)((unsigned char *)recv_pack_buffer + unpack_offset),
984 fixed_pack_size, recv_fixed + recv_fixed_count, comm);
985 unpack_offset += (size_t)fixed_pack_size;
986 }
987 }
988
989 // sort received target point inforation by global target id
990 qsort(
991 send_results, recv_tgt_count, sizeof(*send_results),
993
994 // sort links by global target ids
995 qsort(
996 recv_links, recv_link_count, sizeof(*recv_links), compare_link_data_tgt);
997
998 // sort fixed data by global target ids
999 qsort(
1000 recv_fixed, recv_fixed_count, sizeof(*recv_fixed),
1002
1003 // match target points with linked and fixed data from the weight file
1004 for (size_t tgt_idx = 0, link_idx = 0, fixed_idx = 0;
1005 tgt_idx < recv_tgt_count; ++tgt_idx) {
1006
1007 yac_int curr_tgt = send_results[tgt_idx].tgt.global_id;
1008
1009 while ((link_idx < recv_link_count) &&
1010 (recv_links[link_idx].tgt.global_id < curr_tgt)) ++link_idx;
1011 while ((fixed_idx < recv_fixed_count) &&
1012 (recv_fixed[fixed_idx].tgt.global_id < curr_tgt)) ++fixed_idx;
1013
1014 YAC_ASSERT(
1015 (link_idx >= recv_link_count) ||
1016 (recv_links[link_idx].tgt.global_id != curr_tgt) ||
1017 (fixed_idx >= recv_fixed_count) ||
1018 (recv_fixed[fixed_idx].tgt.global_id != curr_tgt),
1019 "inconsistent data in weight file;"
1020 "link and fixed data available for a target point")
1021 if ((link_idx < recv_link_count) &&
1022 (recv_links[link_idx].tgt.global_id == curr_tgt)) {
1023
1024 size_t temp_link_idx = link_idx;
1025 while ((temp_link_idx < recv_link_count) &&
1026 (recv_links[temp_link_idx].tgt.global_id == curr_tgt))
1027 ++temp_link_idx;
1028 send_results[tgt_idx].type = LINK;
1029 send_results[tgt_idx].data.link.links = recv_links + link_idx;
1030 send_results[tgt_idx].data.link.count = temp_link_idx - link_idx;
1031
1032 } else if ((fixed_idx < recv_fixed_count) &&
1033 (recv_fixed[fixed_idx].tgt.global_id == curr_tgt)) {
1034
1035 send_results[tgt_idx].type = FIXED;
1036 send_results[tgt_idx].data.fixed.value = recv_fixed[fixed_idx].value;
1037
1038 } else {
1039 send_results[tgt_idx].type = NO_INTERP;
1040 }
1041 }
1042 free(recv_fixed);
1043
1044 // sort received target point inforatiom into origional receive order
1045 qsort(
1046 send_results, recv_tgt_count, sizeof(*send_results),
1048
1049 int * pack_size_buffer =
1050 xmalloc((recv_tgt_count + tgt_count) * sizeof(*pack_size_buffer));
1051 int * send_pack_sizes = pack_size_buffer;
1052 int * recv_pack_sizes = pack_size_buffer + recv_tgt_count;
1053 for (size_t i = 0; i < recv_tgt_count; ++i)
1054 send_pack_sizes[i] = get_temp_result_pack_size(send_results + i, comm);
1055
1056 saccu = 0, raccu = 0;
1057 for (int i = 0; i < comm_size; ++i) {
1058 sdispls[i] = saccu;
1059 rdispls[i] = raccu;
1060 int sendcount = recvcounts[3*i];
1061 int recvcount = sendcounts[3*i];
1062 saccu += (sendcounts[i] = sendcount);
1063 raccu += (recvcounts[i] = recvcount);
1064 }
1065
1066 yac_alltoallv_int_p2p(
1067 send_pack_sizes, sendcounts, sdispls,
1068 recv_pack_sizes, recvcounts, rdispls, comm, __func__, __LINE__);
1069
1070 saccu = 0, raccu = 0;
1071 for (int i = 0, k = 0, l = 0; i < comm_size; ++i) {
1072 size_t sendcount = sendcounts[i];
1073 size_t recvcount = recvcounts[i];
1074 sendcounts[i] = 0;
1075 recvcounts[i] = 0;
1076 for (size_t j = 0; j < sendcount; ++j, ++k)
1077 sendcounts[i] += send_pack_sizes[k];
1078 for (size_t j = 0; j < recvcount; ++j, ++l)
1079 recvcounts[i] += recv_pack_sizes[l];
1080 sdispls[i] = saccu;
1081 rdispls[i] = raccu;
1082 saccu += sendcounts[i];
1083 raccu += recvcounts[i];
1084 }
1085 size_t total_send_pack_size =
1086 sdispls[comm_size-1] + sendcounts[comm_size-1];
1087 size_t total_recv_pack_size =
1088 rdispls[comm_size-1] + recvcounts[comm_size-1];
1089
1090 pack_buffer =
1091 xrealloc(pack_buffer, total_send_pack_size + total_recv_pack_size);
1092 send_pack_buffer = pack_buffer;
1093 recv_pack_buffer =
1094 (void*)((unsigned char*)pack_buffer + total_send_pack_size);
1095
1096 for (size_t i = 0, offset = 0; i < recv_tgt_count; ++i) {
1098 send_results + i, (void*)((unsigned char*)send_pack_buffer + offset),
1099 send_pack_sizes[i], comm);
1100 offset += (size_t)(send_pack_sizes[i]);
1101 }
1102
1103 // redistribute link and fixed data to processes requiring this data for
1104 // their local target points
1106 send_pack_buffer, sendcounts, sdispls,
1107 recv_pack_buffer, recvcounts, rdispls,
1108 1, MPI_PACKED, comm, __func__, __LINE__);
1109
1110 // unpack results
1111 for (size_t i = 0, offset = 0; i < tgt_count; ++i) {
1113 (void*)((unsigned char*)recv_pack_buffer + offset),
1114 recv_pack_sizes[i], recv_results + i, comm);
1115 offset += (size_t)(recv_pack_sizes[i]);
1116 }
1117 free(pack_size_buffer);
1118
1119 // sort received results by global target id
1120 qsort(
1121 recv_results, tgt_count, sizeof(*recv_results),
1123
1124 for (size_t i = 0; i < tgt_count; ++i)
1125 recv_results[i].tgt.local_id = tgt_points[i];
1126
1127 // sort received results by type
1128 qsort(
1129 recv_results, tgt_count, sizeof(*recv_results),
1131
1132 size_t new_num_links = 0;
1133 size_t new_total_num_links = 0;
1134 size_t new_num_fixed = 0;
1135 {
1136 size_t i = 0;
1137 while ((i < tgt_count) && (recv_results[i].type == LINK))
1138 new_total_num_links += recv_results[i++].data.link.count;
1139 new_num_links = i;
1140 while ((i < tgt_count) && (recv_results[i].type == FIXED)) ++i;
1141 new_num_fixed = i - new_num_links;
1142 }
1143
1144 // extract links from results
1145 *links = xrealloc(recv_links, new_total_num_links * sizeof(**links));
1146 for (size_t i = 0, offset = 0; i < new_num_links;
1147 offset += recv_results[i++].data.link.count)
1148 memcpy(*links + offset, recv_results[i].data.link.links,
1149 recv_results[i].data.link.count * sizeof(**links));
1150 *num_links = new_total_num_links;
1151
1152 // extract fixed data from results
1153 if (new_num_fixed > 0) {
1154 recv_results += new_num_links;
1155 qsort(
1156 recv_results, new_num_fixed, sizeof(*recv_results),
1158 // initialise to anything that does not match the first fixed value
1159 double curr_fixed_value =
1160 (recv_results[0].data.fixed.value == 1337.0)?(-1337.0):(1337.0);
1161 size_t num_fixed_values = 0;
1162 void * tgt_global_id_buffer =
1163 xrealloc((*num_fixed > 0)?(*fixed)->tgt:NULL,
1164 new_num_fixed * sizeof(*((*fixed)->tgt)));
1165 struct fixed_data * curr_fixed = NULL;
1166 for (size_t i = 0, offset = 0; i < new_num_fixed; ++i) {
1167 // use memcmp for handling NaNs
1168 if (memcmp(
1169 &recv_results[i].data.fixed.value, &curr_fixed_value,
1170 sizeof(curr_fixed_value))) {
1171 curr_fixed_value = recv_results[i].data.fixed.value;
1172 *fixed = xrealloc(*fixed, (num_fixed_values + 1) * sizeof(**fixed));
1173 curr_fixed = *fixed + num_fixed_values;
1174 ++num_fixed_values;
1175 curr_fixed->value = curr_fixed_value;
1176 curr_fixed->tgt = (void*)(((unsigned char *)tgt_global_id_buffer) +
1177 offset * sizeof(*((*fixed)->tgt)));
1178 curr_fixed->num_tgt = 0;
1179 }
1180 curr_fixed->tgt[curr_fixed->num_tgt++].global_id =
1181 recv_results[i].tgt.global_id;
1182 }
1183 *num_fixed = num_fixed_values;
1184 recv_results -= new_num_links;
1185
1186 } else {
1187 if (*num_fixed > 0) free((*fixed)->tgt);
1188 free(*fixed);
1189 *fixed = NULL;
1190 *num_fixed = 0;
1191 }
1192
1193 for (size_t i = 0; i < tgt_count; ++i)
1194 tgt_points[i] = recv_results[i].tgt.local_id;
1195 *num_interpolated_points = new_num_links + new_num_fixed;
1196
1197 for (size_t i = 0; i < new_num_links; ++i)
1198 free(recv_results[i].data.link.links);
1199 free(result_buffer);
1200 free(pack_buffer);
1201 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
1202 free(size_t_buffer);
1203 free(tgt_global_ids);
1204}
1205
1206static int compare_link_data_field_idx_src(void const *a, void const *b) {
1207
1208 struct link_data const * link_a = (struct link_data*)a;
1209 struct link_data const * link_b = (struct link_data*)b;
1210
1211 int ret = (link_a->src_field_idx > link_b->src_field_idx) -
1212 (link_a->src_field_idx < link_b->src_field_idx);
1213
1214 if (ret) return ret;
1215
1216 else return (link_a->src.global_id > link_b->src.global_id) -
1217 (link_a->src.global_id < link_b->src.global_id);
1218}
1219
1220// sort links by tgt local id and src ids (SIZE_MAX first; remaining by ascending src ids)
1221static int compare_link_data_tgt_src_mask(void const *a, void const *b) {
1222
1223 struct link_data const * link_a = (struct link_data*)a;
1224 struct link_data const * link_b = (struct link_data*)b;
1225
1226 int ret = (link_a->tgt.local_id > link_b->tgt.local_id) -
1227 (link_a->tgt.local_id < link_b->tgt.local_id);
1228
1229 if (ret) return ret;
1230
1231 if (link_a->src.local_id == SIZE_MAX) return -1;
1232 if (link_b->src.local_id == SIZE_MAX) return 1;
1233
1234 return (link_a->src.local_id > link_b->src.local_id) -
1235 (link_a->src.local_id < link_b->src.local_id);
1236}
1237
1238// sort links by tgt local id, source field index, and src local id
1239static int compare_link_data_tgt_src_field_src_id(void const *a, void const *b) {
1240
1241 struct link_data const * link_a = (struct link_data*)a;
1242 struct link_data const * link_b = (struct link_data*)b;
1243
1244 int ret = (link_a->tgt.local_id > link_b->tgt.local_id) -
1245 (link_a->tgt.local_id < link_b->tgt.local_id);
1246
1247 if (ret) return ret;
1248
1249 ret = (link_a->src_field_idx > link_b->src_field_idx) -
1250 (link_a->src_field_idx < link_b->src_field_idx);
1251
1252 if (ret) return ret;
1253
1254 if (link_a->src.local_id == SIZE_MAX) return -1;
1255 if (link_b->src.local_id == SIZE_MAX) return 1;
1256
1257 return (link_a->src.local_id > link_b->src.local_id) -
1258 (link_a->src.local_id < link_b->src.local_id);
1259}
1260
1261
1262static size_t do_search_file(struct interp_method * method,
1263 struct yac_interp_grid * interp_grid,
1264 size_t * tgt_points, size_t count,
1265 struct yac_interp_weights * weights,
1266 int * interpolation_complete) {
1267
1268 if (*interpolation_complete) return 0;
1269
1270 YAC_INSTRUMENT_START(YAC_INSTR_INTERP_SEARCH_FILE);
1271
1272 struct interp_method_file * method_file =
1273 (struct interp_method_file*)(method);
1274
1275 MPI_Comm comm = yac_interp_grid_get_MPI_Comm(interp_grid);
1276 int comm_rank;
1277 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
1278
1279 // determine root io rank
1280 int local_is_io;
1281 int * io_ranks;
1282 int num_io_ranks;
1283 yac_get_io_ranks(comm, &local_is_io, &io_ranks, &num_io_ranks);
1284 int root_io_rank = io_ranks[0];
1285 free(io_ranks);
1286
1290 "unsupported value for on_missing_file %d "
1291 "(has to be either YAC_INTERP_FILE_MISSING_ERROR(%d) or "
1292 "YAC_INTERP_FILE_MISSING_CONT (%d))",
1295
1296 // determine if a file with the same name already exists
1297 int file_exists =
1298 (comm_rank == root_io_rank) &&
1299 yac_file_exists(method_file->weight_file_name);
1301 MPI_Allreduce(
1302 MPI_IN_PLACE, &file_exists, 1, MPI_INT, MPI_MAX, comm), comm);
1303
1304 // it is enough if one process calls abort, otherwise we would have a lot of
1305 // output
1306 if ((comm_rank == root_io_rank) && !file_exists &&
1308 char const msg_fmt[] =
1309 "ERROR(do_search_file): weight file \"%s\" does not exist";
1310 char msg[strlen(msg_fmt) + strlen(method_file->weight_file_name)];
1311 sprintf(msg, msg_fmt, method_file->weight_file_name);
1312 yac_abort(comm, msg, __FILE__, __LINE__);
1313 }
1314
1315 // if there is no weight file continue normally
1316 // (in case of error, another process will have called abort)
1317 if (!file_exists) {
1318 YAC_INSTRUMENT_STOP(YAC_INSTR_INTERP_SEARCH_FILE);
1319 return 0;
1320 }
1321
1322 size_t num_src_fields = yac_interp_grid_get_num_src_fields(interp_grid);
1323 enum yac_location * src_locations =
1324 xmalloc(num_src_fields * sizeof(*src_locations));
1325 for (size_t i = 0; i < num_src_fields; ++i)
1326 src_locations[i] = yac_interp_grid_get_src_field_location(interp_grid, i);
1327 enum yac_location tgt_location =
1329
1330 struct link_data * links = NULL;
1331 size_t num_links = 0;
1332 struct fixed_data * fixed = NULL;
1333 size_t num_fixed = 0;
1334
1335 // read data from file
1337 method_file->weight_file_name, comm,
1340 src_locations, tgt_location, num_src_fields,
1341 &links, &num_links, &fixed, &num_fixed);
1342
1343 free(src_locations);
1344
1345 // relocates links and fixed to the processes, which require them to
1346 // interpolate their local target points
1347 // (the tgt_points first contain the link-tgt_points, then the fixed-tgt_points,
1348 // and followed the non-interpolated tgt_points)
1349 size_t num_interpolated_points;
1351 interp_grid, tgt_points, count, &num_interpolated_points,
1352 &links, &num_links, &fixed, &num_fixed);
1353
1354 size_t * tgt_points_reorder_idx =
1355 xmalloc(num_interpolated_points * sizeof(*tgt_points_reorder_idx));
1356 for (size_t i = 0; i < num_interpolated_points; ++i)
1357 tgt_points_reorder_idx[i] = i;
1358
1359 size_t num_fixed_tgt = 0;
1360 if (num_fixed) {
1361 for (size_t i = 0; i < num_fixed; ++i) num_fixed_tgt += fixed[i].num_tgt;
1362
1363 size_t tgt_points_offset = num_interpolated_points - num_fixed_tgt;
1364
1365 for (size_t i = 0; i < num_fixed; ++i) {
1366
1367 struct remote_points tgts = {
1368 .data =
1370 interp_grid, tgt_points + tgt_points_offset, fixed[i].num_tgt),
1371 .count = fixed[i].num_tgt};
1372
1373 yac_interp_weights_add_fixed(weights, &tgts, fixed[i].value);
1374 free(tgts.data);
1375 tgt_points_offset += fixed[i].num_tgt;
1376 }
1377 free(fixed->tgt);
1378 }
1379 free(fixed);
1380
1381 size_t num_link_tgt = 0;
1382 if (num_links > 0) {
1383
1384 // set local target ids for all links
1385 for (size_t link_idx = 0, tgt_idx = 0; link_idx < num_links; tgt_idx++) {
1386
1387 yac_int curr_global_id = links[link_idx].tgt.global_id;
1388 size_t curr_local_id = tgt_points[tgt_idx];
1389
1390 while ((link_idx < num_links) &&
1391 (links[link_idx].tgt.global_id == curr_global_id)) {
1392 links[link_idx].tgt.local_id = curr_local_id;
1393 link_idx++;
1394 }
1395 }
1396
1397 // sort links by field idx and src id
1398 qsort(links, num_links, sizeof(*links), compare_link_data_field_idx_src);
1399
1400 // determine number of source fields
1401 size_t num_src_fields = links[num_links-1].src_field_idx + 1;
1402
1403 {
1404 int int_num_src_fields = (int)num_src_fields;
1405 MPI_Comm comm = yac_interp_grid_get_MPI_Comm(interp_grid);
1407 MPI_Allreduce(MPI_IN_PLACE, &int_num_src_fields, 1, MPI_INT, MPI_MAX,
1408 comm), comm);
1409 num_src_fields = (size_t)int_num_src_fields;
1410 }
1411
1412 yac_int * src_global_ids = xmalloc(num_links * sizeof(*src_global_ids));
1413 size_t * src_local_ids = xmalloc(num_links * sizeof(*src_local_ids));
1414 size_t src_field_prefix_sum[num_src_fields];
1415
1416 // check the mask of the source points and get the local ids for the
1417 // remaining ones
1418 for (size_t src_field_idx = 0, link_idx = 0, offset = 0;
1419 src_field_idx < num_src_fields; ++src_field_idx) {
1420
1421 size_t curr_num_links = 0;
1422 while ((link_idx < num_links) &&
1423 (links[link_idx].src_field_idx == src_field_idx)) {
1424
1425 // get global source ids
1426 src_global_ids[offset + curr_num_links] =
1427 links[link_idx].src.global_id;
1428 ++curr_num_links;
1429 ++link_idx;
1430 }
1431
1432 // get local ids for all source points
1434 interp_grid, src_field_idx, src_global_ids + offset, curr_num_links,
1435 src_local_ids + offset);
1436
1437 // get the mask after the call to yac_interp_grid_src_global_to_local
1438 const_int_pointer src_mask =
1439 yac_interp_grid_get_src_field_mask(interp_grid, src_field_idx);
1440
1441 // check source masks and mask src ids of marked links with SIZE_MAX
1442 link_idx -= curr_num_links;
1443 if (src_mask != NULL) {
1444 for (size_t i = 0; i < curr_num_links; ++i, ++link_idx)
1445 links[link_idx].src.local_id =
1446 (src_mask[src_local_ids[link_idx]])?
1447 src_local_ids[link_idx]:SIZE_MAX;
1448 } else {
1449 for (size_t i = 0; i < curr_num_links; ++i, ++link_idx)
1450 links[link_idx].src.local_id = src_local_ids[link_idx];
1451 }
1452
1453 src_field_prefix_sum[src_field_idx] = offset;
1454 offset += curr_num_links;
1455 }
1456
1457 // sort links by tgt local id and src ids (SIZE_MAX first; remaining by ascending src ids)
1458 qsort(links, num_links, sizeof(*links), compare_link_data_tgt_src_mask);
1459
1460 // pack links (remove links with targets that have at least one masked source point)
1461 size_t new_num_links = 0;
1462 int contains_masked_tgt = 0;
1463 num_link_tgt = num_interpolated_points - num_fixed_tgt;
1464 size_t * tgt_local_ids = xmalloc(num_link_tgt * sizeof(*tgt_local_ids));
1465 size_t * num_src_per_field_per_tgt =
1466 xcalloc(num_link_tgt * num_src_fields, sizeof(*num_src_per_field_per_tgt));
1467 size_t num_links_per_src_field[num_src_fields];
1468 memset(num_links_per_src_field, 0, sizeof(num_links_per_src_field));
1469 num_link_tgt = 0;
1470 for (size_t link_idx = 0, tgt_idx = 0; link_idx < num_links; ++tgt_idx) {
1471
1472 size_t curr_tgt_local_id = links[link_idx].tgt.local_id;
1473 int is_masked = links[link_idx].src.local_id == SIZE_MAX;
1474 tgt_points[tgt_idx] = curr_tgt_local_id;
1475
1476 // if the current target point has a masked source point
1477 if (is_masked) {
1478
1479 while ((link_idx < num_links) &&
1480 (links[link_idx].tgt.local_id == curr_tgt_local_id)) ++link_idx;
1481 contains_masked_tgt = 1;
1482 tgt_points_reorder_idx[tgt_idx] += num_interpolated_points;
1483
1484 // if there already have been target points with masked source points
1485 } else {
1486 size_t * curr_num_src_per_field_per_tgt =
1487 num_src_per_field_per_tgt + num_link_tgt * num_src_fields;
1488 if (contains_masked_tgt) {
1489 while ((link_idx < num_links) &&
1490 (links[link_idx].tgt.local_id == curr_tgt_local_id)) {
1491 size_t curr_src_field_idx = links[link_idx].src_field_idx;
1492 src_local_ids[
1493 src_field_prefix_sum[curr_src_field_idx] +
1494 num_links_per_src_field[curr_src_field_idx] +
1495 curr_num_src_per_field_per_tgt[curr_src_field_idx]++] =
1496 links[link_idx].src.local_id;
1497 links[new_num_links++] = links[link_idx++];
1498 }
1499 } else {
1500
1501 while ((link_idx < num_links) &&
1502 (links[link_idx].tgt.local_id == curr_tgt_local_id)) {
1503 size_t curr_src_field_idx = links[link_idx].src_field_idx;
1504 src_local_ids[
1505 src_field_prefix_sum[curr_src_field_idx] +
1506 num_links_per_src_field[curr_src_field_idx] +
1507 curr_num_src_per_field_per_tgt[curr_src_field_idx]++] =
1508 links[link_idx].src.local_id;
1509 ++link_idx, ++new_num_links;
1510 }
1511 }
1512 for (size_t i = 0; i < num_src_fields; ++i) {
1513 num_links_per_src_field[i] += curr_num_src_per_field_per_tgt[i];
1514 }
1515 tgt_local_ids[num_link_tgt++] = curr_tgt_local_id;
1516 }
1517 }
1518 num_links = new_num_links;
1519 tgt_local_ids =
1520 xrealloc(tgt_local_ids, num_link_tgt * sizeof(*tgt_local_ids));
1521 num_src_per_field_per_tgt =
1522 xrealloc(
1523 num_src_per_field_per_tgt,
1524 num_link_tgt * num_src_fields * sizeof(*num_src_per_field_per_tgt));
1525
1526 // get the remote points for all required source points
1527 struct remote_point * srcs_per_field[num_src_fields];
1528 for (size_t src_field_idx = 0; src_field_idx < num_src_fields; ++src_field_idx)
1529 srcs_per_field[src_field_idx] =
1531 interp_grid, src_field_idx, src_local_ids + src_field_prefix_sum[src_field_idx],
1532 num_links_per_src_field[src_field_idx]);
1533 free(src_local_ids);
1534
1535 // sort links by tgt local id, source field index, and src local id
1536 qsort(links, num_links, sizeof(*links), compare_link_data_tgt_src_field_src_id);
1537
1538 // gather weights
1539 double * w = xmalloc(num_links * sizeof(*w));
1540 for (size_t link_idx = 0; link_idx < num_links; ++link_idx)
1541 w[link_idx] = links[link_idx].weight;
1542
1543 struct remote_points tgts = {
1544 .data =
1546 interp_grid, tgt_local_ids, num_link_tgt),
1547 .count = num_link_tgt};
1548 free(tgt_local_ids);
1549
1551 weights, &tgts, num_src_per_field_per_tgt, srcs_per_field, w, num_src_fields);
1552
1553 free(tgts.data);
1554 for (size_t i = 0; i < num_src_fields; ++i) free(srcs_per_field[i]);
1555 free(num_src_per_field_per_tgt);
1556 free(w);
1557 free(src_global_ids);
1558
1559 } else {
1560 int num_src_fields = 0;
1561 MPI_Comm comm = yac_interp_grid_get_MPI_Comm(interp_grid);
1563 MPI_Allreduce(MPI_IN_PLACE, &num_src_fields, 1, MPI_INT, MPI_MAX,
1564 comm), comm);
1565 // get local ids for all source points
1566 // (since this routine is collective for all processes, we have to call
1567 // this here if the local process received no links)
1568 for (int i = 0; i < num_src_fields; ++i)
1569 yac_interp_grid_src_global_to_local(interp_grid, 0, NULL, 0, NULL);
1570 }
1571 free(links);
1572
1574 tgt_points_reorder_idx, num_interpolated_points, tgt_points);
1575 free(tgt_points_reorder_idx);
1576
1577
1579 (method_file->on_success == YAC_INTERP_FILE_SUCCESS_STOP) ||
1580 (method_file->on_success == YAC_INTERP_FILE_SUCCESS_CONT),
1581 "unsupported value for on_success %d "
1582 "(has to be either YAC_INTERP_FILE_SUCCESS_STOP(%d) or "
1583 "YAC_INTERP_FILE_SUCCESS_CONT (%d))",
1584 (int)(method_file->on_success), YAC_INTERP_FILE_SUCCESS_STOP,
1586
1587 *interpolation_complete =
1589
1590 YAC_INSTRUMENT_STOP(YAC_INSTR_INTERP_SEARCH_FILE);
1591
1592 return num_fixed_tgt + num_link_tgt;
1593}
1594
1596 char const * weight_file_name,
1597 enum yac_interp_file_on_missing_file on_missing_file,
1598 enum yac_interp_file_on_success on_success) {
1599
1600 struct interp_method_file * method = xmalloc(1 * sizeof(*method));
1601
1602 YAC_ASSERT(
1603 weight_file_name, "weight_file_name cannot be NULL");
1604
1608 method->on_success = on_success;
1609
1610 return (struct interp_method*)method;
1611}
1612
1613static void delete_file(struct interp_method * method) {
1614
1615 struct interp_method_file * method_file =
1616 (struct interp_method_file *)method;
1617 free((void*)(method_file->weight_file_name));
1618 free(method_file);
1619}
1620
1621// --- Modular config struct and vtable for FILE method ---
1622
1637
1640 struct yac_interp_method_config_file *config_file =
1642 free(config_file->config.filename);
1643 free(config);
1644}
1645
1647 const struct yac_interp_method_config *config) {
1649 struct yac_interp_method_config_file *copy = xmalloc(sizeof(*copy));
1650 copy->base.vtable = config_file->base.vtable;
1651 copy->base.root_param_cache = NULL;
1652 copy->config = config_file->config;
1653 copy->config.filename = config_file->config.filename
1654 ? xstrdup(config_file->config.filename) : NULL;
1655 return (struct yac_interp_method_config *)copy;
1656}
1657
1659 void const *a_, void const *b_) {
1661 // Compare user file interpolation options:
1662 // 1. on_missing_file: behavior if file is missing (error/continue)
1663 CHECK_ENUM(config.on_missing_file);
1664 // 2. on_success: behavior if file is successfully read (stop/continue)
1665 CHECK_ENUM(config.on_success);
1666 // 3. filename: path to the weight file (lexical comparison)
1667 CHECK_STRING(config.filename);
1668 return 0;
1669}
1670
1671// Gets interpolation method typed_config_hcsbb_get_type
1675
1677 struct yac_interp_method_config const *config) {
1678 const struct yac_interp_method_config_file *config_file =
1679 (const struct yac_interp_method_config_file *)config;
1681 config_file->config.filename,
1682 config_file->config.on_missing_file,
1683 config_file->config.on_success);
1684}
1685
1687 struct yac_interp_method_config const *config) {
1688 struct yac_interp_method_config_file *config_file =
1690
1691 enum {
1692 FILENAME_HAS_DEFAULT = 0,
1693 FILENAME_ALLOW_NULL = 0,
1694 FILENAME_ALLOW_EMPTY = 0,
1695 ON_MISSING_FILE_HAS_DEFAULT = 1,
1696 ON_MISSING_FILE_IS_DEFINED = 1,
1697 ON_SUCCESS_HAS_DEFAULT = 1,
1698 ON_SUCCESS_IS_DEFINED = 1
1699 };
1700
1701 struct yac_param *filename_param =
1703 "filename",
1704 &config_file->config.filename,
1706 FILENAME_ALLOW_NULL, FILENAME_ALLOW_EMPTY,
1707 YAC_MAX_FILE_NAME_LENGTH, FILENAME_HAS_DEFAULT,
1708 config_file->config.filename != NULL);
1709
1711 on_missing_file_enum_table,
1715
1716 struct yac_param *on_missing_file_param =
1718 "on_missing_file",
1719 (int *)&config_file->config.on_missing_file,
1721 on_missing_file_enum_table, on_missing_file_enum_table_size,
1722 ON_MISSING_FILE_HAS_DEFAULT, ON_MISSING_FILE_IS_DEFINED);
1723
1725 on_success_enum_table,
1729
1730 struct yac_param *on_success_param =
1732 "on_success",
1733 (int *)&config_file->config.on_success,
1735 on_success_enum_table, on_success_enum_table_size,
1736 ON_SUCCESS_HAS_DEFAULT, ON_SUCCESS_IS_DEFINED);
1737
1738 struct yac_param *root_param_array[] = {
1739 filename_param,
1740 on_missing_file_param,
1741 on_success_param
1742 };
1743 enum {
1744 ROOT_PARAM_ARRAY_SIZE =
1745 sizeof(root_param_array) / sizeof(root_param_array[0])
1746 };
1747
1748 return yac_param_struct_new(
1749 "file", root_param_array, ROOT_PARAM_ARRAY_SIZE);
1750}
1751
1754 .copy = config_file_copy,
1755 .compare = config_file_compare,
1756 .get_type = config_file_get_type,
1757 .generate = config_file_generate,
1758 .get_param = config_file_get_param
1759};
1760
1762 struct yac_interp_method_config_file *config_file =
1763 xmalloc(sizeof(*config_file));
1765 config_file->base.root_param_cache = NULL;
1766 config_file->config = (struct yac_interp_method_file_config){
1768 .on_missing_file = YAC_INTERP_FILE_ON_MISSING_FILE_DEFAULT,
1770 };
1771 return (struct yac_interp_method_config *)config_file;
1772}
#define YAC_ASSERT(exp, msg)
#define UNUSED(x)
Definition core.h:72
int const * const_int_pointer
#define DEF_NAME_TYPE_PAIR(NAME, TYPE)
#define DEF_NAME_TYPE_PAIRS(NAME,...)
#define YAC_INSTRUMENT_START(ID)
Enter an instrumented region.
#define YAC_INSTRUMENT_STOP(ID)
Exit an instrumented region entered with YAC_INSTRUMENT_START(ID).
enum yac_location yac_interp_grid_get_tgt_field_location(struct yac_interp_grid *interp_grid)
size_t yac_interp_grid_get_num_src_fields(struct yac_interp_grid *interp_grid)
const_int_pointer yac_interp_grid_get_src_field_mask(struct yac_interp_grid *interp_grid, size_t src_field_idx)
char const * yac_interp_grid_get_src_grid_name(struct yac_interp_grid *interp_grid)
Definition interp_grid.c:77
char const * yac_interp_grid_get_tgt_grid_name(struct yac_interp_grid *interp_grid)
Definition interp_grid.c:82
void yac_interp_grid_get_tgt_global_ids(struct yac_interp_grid *interp_grid, size_t *tgt_points, size_t count, yac_int *tgt_global_ids)
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)
enum yac_location yac_interp_grid_get_src_field_location(struct yac_interp_grid *interp_grid, size_t src_field_idx)
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_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)
yac_interpolation_list
@ YAC_USER_FILE
User-supplied weights from file.
#define YAC_MAX_FILE_NAME_LENGTH
Maximum length for file names (used in user file interpolation)
enum callback_type type
struct @23::@24 value
#define DEF_INTERP_METHOD_CONFIG_COMPARE_TYPE(TYPE)
#define DEF_INTERP_METHOD_CONFIG_TYPE(TYPE)
static int config_file_compare(void const *a_, void const *b_)
static int compare_temp_result_fixed(void const *a, void const *b)
static int compare_link_data_tgt(void const *a, void const *b)
static int compare_link_data_tgt_src_mask(void const *a, void const *b)
static int compare_link_data_field_idx_src(void const *a, void const *b)
static int get_fixed_pack_size(MPI_Comm comm)
static int compute_bucket(yac_int value, int comm_size)
static struct yac_param * config_file_get_param(struct yac_interp_method_config const *config)
static int compare_temp_result_tgt(void const *a, void const *b)
static int get_link_pack_size(MPI_Comm comm)
static struct yac_interp_method_config * config_file_copy(const struct yac_interp_method_config *config)
static enum yac_interpolation_list config_file_get_type()
struct yac_interp_method_config * yac_interp_method_config_default_file_new(void)
Creates a file-based interpolation method configuration with default parameters.
static void pack_tgt(yac_int global_tgt_id, void *buffer, int buffer_size, MPI_Comm comm)
static void pack_temp_result(struct temp_result *result, void *buffer, int buffer_size, MPI_Comm comm)
static void redist_weight_file_data(struct yac_interp_grid *interp_grid, size_t *tgt_points, size_t tgt_count, size_t *num_interpolated_points, struct link_data **links, size_t *num_links, struct fixed_data **fixed, size_t *num_fixed)
static size_t do_search_file(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)
static void unpack_temp_result(void *buffer, int buffer_size, struct temp_result *result, MPI_Comm comm)
static void unpack_fixed(void *buffer, int buffer_size, struct temp_fixed_data *fixed, MPI_Comm comm)
static void pack_link(struct link_data *link, void *buffer, int buffer_size, MPI_Comm comm)
static int compare_temp_result_reorder_idx(void const *a, void const *b)
static void pack_fixed(double fixed_value, yac_int global_tgt_id, void *buffer, int buffer_size, MPI_Comm comm)
static struct yac_interp_method_config_vtable yac_interp_method_config_vtable_file
static struct interp_method_vtable interp_method_file_vtable
static void unpack_link(void *buffer, int buffer_size, struct link_data *link, MPI_Comm comm)
static void config_file_delete(struct yac_interp_method_config *config)
static struct interp_method * config_file_generate(struct yac_interp_method_config const *config)
static int get_temp_result_pack_size(struct temp_result *result, MPI_Comm comm)
static int compare_temp_result_type(void const *a, void const *b)
static void delete_file(struct interp_method *method)
static int compare_temp_fixed_data_tgt(void const *a, void const *b)
struct interp_method * yac_interp_method_file_new(char const *weight_file_name, enum yac_interp_file_on_missing_file on_missing_file, enum yac_interp_file_on_success on_success)
static int get_tgt_pack_size(MPI_Comm comm)
static void unpack_tgt(void *buffer, int buffer_size, yac_int *global_tgt_id, MPI_Comm comm)
static void read_weight_file(char const *weight_file_name, MPI_Comm comm, char const *src_grid_name, char const *tgt_grid_name, enum yac_location *src_locations, enum yac_location tgt_location, size_t num_src_fields, struct link_data **links, size_t *num_links, struct fixed_data **fixed, size_t *num_fixed)
static int compare_link_data_tgt_src_field_src_id(void const *a, void const *b)
#define YAC_INTERP_FILE_ON_SUCCESS_DEFAULT
#define YAC_INTERP_FILE_WEIGHT_FILE_NAME_DEFAULT
yac_interp_file_on_missing_file
@ YAC_INTERP_FILE_MISSING_CONT
continue on missing file
@ YAC_INTERP_FILE_MISSING_ERROR
abort on missing file
#define YAC_WEIGHT_FILE_VERSION_STRING
yac_interp_file_on_success
@ YAC_INTERP_FILE_SUCCESS_CONT
@ YAC_INTERP_FILE_SUCCESS_STOP
#define YAC_INTERP_FILE_ON_MISSING_FILE_DEFAULT
#define CHECK_STRING(STR)
void yac_interp_weights_add_fixed(struct yac_interp_weights *weights, struct remote_points *tgts, double fixed_value)
@ FIXED
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)
void yac_get_io_ranks(MPI_Comm comm, int *local_is_io_, int **io_ranks_, int *num_io_ranks_)
Definition io_utils.c:271
void yac_nc_inq_varid(int ncid, char const *name, int *varidp)
Definition io_utils.c:369
int yac_file_exists(const char *filename)
Check whether a file exists.
Definition io_utils.c:394
void yac_nc_open(const char *path, int omode, int *ncidp)
Definition io_utils.c:311
void yac_nc_inq_dimid(int ncid, char const *name, int *dimidp)
Definition io_utils.c:344
enum yac_location yac_str2loc(char const *location_str)
Definition location.c:22
char const * yac_loc2str(enum yac_location location)
Definition location.c:33
yac_location
Definition location.h:12
#define YAC_MAX_LOC_STR_LEN
Definition location.h:10
Definition __init__.py:1
struct yac_param * yac_param_enum_new(const char *name, int *value_ptr, int default_value, struct yac_name_type_pair const *enum_table, size_t enum_table_size, int has_default, int is_defined)
Create a new enum parameter for configuration.
Definition param_enum.c:148
struct yac_param * yac_param_str_new(const char *name, char **value_ptr, const char *default_value, int allow_NULL, int allow_empty, size_t max_str_len, int has_default, int is_defined)
Create a string parameter.
Definition param_str.c:176
struct yac_param * yac_param_struct_new(const char *name, struct yac_param **subparams, size_t subparam_count)
Create a new struct parameter with a given name and subparameters.
#define xstrdup(s)
Definition ppm_xfuncs.h:84
#define xrealloc(ptr, size)
Definition ppm_xfuncs.h:67
#define xcalloc(nmemb, size)
Definition ppm_xfuncs.h:64
#define xmalloc(size)
Definition ppm_xfuncs.h:66
struct fixed_data::@30 * tgt
char const * weight_file_name
enum yac_interp_file_on_missing_file on_missing_file
enum yac_interp_file_on_success on_success
struct interp_method_vtable * vtable
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)
information (global id and location) about a point that
structure containing the information (global id and location)
struct remote_point * data
struct temp_fixed_data::@31 tgt
struct temp_result::@33::@35 link
union temp_result::@33 data
struct temp_result::@34 tgt
struct temp_result::@33::@36 fixed
enum temp_result::@32 type
struct link_data * links
Concrete implementation of yac_interp_method_config for the file method.
struct yac_interp_method_config base
‍base config object, must be first entry
struct yac_interp_method_file_config config
‍method-specific configuration
void(* delete)(struct yac_interp_method_config *config)
struct yac_interp_method_config_vtable const * vtable
enum yac_interp_file_on_success on_success
enum yac_interp_file_on_missing_file on_missing_file
@ error
Definition test_cxc.c:17
double * data
char const * weight_file_name
static struct yac_interp_method_config * config
char const src_grid_name[]
char const tgt_grid_name[]
static double const fixed_value
#define MIN(a, b)
Definition toy_common.h:29
double * buffer
#define YAC_HANDLE_ERROR(exp)
Definition toy_output.c:13
void yac_quicksort_index_yac_int_size_t(yac_int *a, size_t n, size_t *idx)
void yac_quicksort_index_size_t_size_t(size_t *a, size_t n, size_t *idx)
void yac_abort(MPI_Comm comm, const char *msg, const char *source, int line) __attribute__((noreturn))
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:39
#define die(msg)
Definition yac_assert.h:14
void yac_free_comm_buffers(size_t *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls)
Definition yac_mpi.c:639
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:608
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:129
#define yac_mpi_call(call, comm)
#define YAC_MPI_SIZE_T
YAC_INT yac_int
Definition yac_types.h:15
#define yac_int_dt
Definition yac_types.h:18