YAC 3.18.0
Yet Another Coupler
Loading...
Searching...
No Matches
interp_method_creep.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 <limits.h>
11#include <string.h>
12
15#include "parameter/param_int.h"
18#include "yac_mpi_internal.h"
19#include "ensure_array_size.h"
20#include "yac_mpi_common.h"
21
22static size_t do_search_creep(struct interp_method * method,
23 struct yac_interp_grid * interp_grid,
24 size_t * tgt_points, size_t count,
25 struct yac_interp_weights * weights,
26 int * interpolation_complete);
27static void delete_creep(struct interp_method * method);
28
29static struct interp_method_vtable
33
39
41 int rank; // rank of the owner of the stencil
42 uint64_t idx; // index of the stencil that is supposed to be used
43 double weight; // weight of the stencil
44};
45
47 yac_int global_id; // global id of target point for which
48 // the stencil was originally generated
49 size_t count; // number of contributing stencils
50 union {
51 struct stencil_info single,
54};
55
57 struct result_stencil * stencils; // result stencils
58 size_t count; // number of result stencils
60};
61
63 size_t local_id; // local id of target points that is supposed to
64 // be interpolated by the stencil
65 yac_int global_id; // global id of target points that is supposed to
66 // be interpolated by the stencil
67 size_t idx;
69};
70
72 yac_int global_id; // global id of requested point
73 int rank; // rank of process which requested
75};
76
77struct comm_stuff {
78 int rank, size;
80 MPI_Datatype stencil_info_dt;
81 MPI_Comm comm;
82};
83
84static MPI_Datatype yac_get_stencil_info_mpi_datatype(MPI_Comm comm) {
85
86 struct stencil_info dummy;
87 MPI_Datatype stencil_info_dt;
88 int array_of_blocklengths[] = {1, 1, 1};
89 const MPI_Aint array_of_displacements[] =
90 {(MPI_Aint)(intptr_t)(const void *)&(dummy.rank) -
91 (MPI_Aint)(intptr_t)(const void *)&dummy,
92 (MPI_Aint)(intptr_t)(const void *)&(dummy.idx) -
93 (MPI_Aint)(intptr_t)(const void *)&dummy,
94 (MPI_Aint)(intptr_t)(const void *)&(dummy.weight) -
95 (MPI_Aint)(intptr_t)(const void *)&dummy};
96 const MPI_Datatype array_of_types[] =
97 {MPI_INT, MPI_UINT64_T, MPI_DOUBLE};
99 MPI_Type_create_struct(3, array_of_blocklengths, array_of_displacements,
100 array_of_types, &stencil_info_dt), comm);
101 return yac_create_resized(stencil_info_dt, sizeof(dummy), comm);
102}
103
105 void * results, size_t result_count, size_t result_size,
106 struct result_stencil*(*get_stencil)(void*), size_t * pack_order,
107 int * pack_sizes, MPI_Datatype stencil_info_dt, MPI_Comm comm) {
108
109 int pack_size_global_id, pack_size_count;
110 yac_mpi_call(MPI_Pack_size(1, yac_int_dt, comm, &pack_size_global_id), comm);
111 yac_mpi_call(MPI_Pack_size(1, MPI_UINT64_T, comm, &pack_size_count), comm);
112
113 for (size_t i = 0; i < result_count; ++i) {
114
115 struct result_stencil * stencil =
116 (*get_stencil)(
117 (void*)((unsigned char*)results + pack_order[i] * result_size));
118 size_t curr_count = stencil->count;
119 int pack_size_stencils;
121 MPI_Pack_size(
122 (int)curr_count, stencil_info_dt, comm, &pack_size_stencils), comm);
123 pack_sizes[i] = pack_size_global_id +
124 pack_size_count +
125 pack_size_stencils;
126 }
127}
128
130 struct result_stencil * stencil, void * buffer, int buffer_size,
131 int * position, MPI_Datatype stencil_info_dt, MPI_Comm comm) {
132
133 // global_id
135 MPI_Pack(&(stencil->global_id), 1, yac_int_dt,
136 buffer, buffer_size, position, comm), comm);
137
138 // count
139 uint64_t count_uint64_t = (uint64_t)(stencil->count);
141 MPI_Pack(&count_uint64_t, 1, MPI_UINT64_T,
142 buffer, buffer_size, position, comm), comm);
143
144 // stencils
145 struct stencil_info * stencils =
146 (count_uint64_t == 1)?(&(stencil->data.single)):(stencil->data.multi);
148 MPI_Pack(stencils, (int)count_uint64_t, stencil_info_dt,
149 buffer, buffer_size, position, comm), comm);
150}
151
153 void * results, size_t result_count, size_t result_size,
154 struct result_stencil*(*get_stencil)(void*), size_t * pack_order,
155 void ** pack_data, int * pack_sizes, MPI_Datatype stencil_info_dt,
156 MPI_Comm comm) {
157
159 results, result_count, result_size, get_stencil, pack_order,
160 pack_sizes, stencil_info_dt, comm);
161
162 size_t temp_total_pack_size = 0;
163 for (size_t i = 0; i < result_count; ++i)
164 temp_total_pack_size += (size_t)(pack_sizes[i]);
165
167 temp_total_pack_size <= INT_MAX,
168 "ERROR(pack_result_stencils): pack size exceeds INT_MAX")
169
170 void * pack_data_ = xmalloc(temp_total_pack_size);
171 size_t total_pack_size = 0;
172
173 for (size_t i = 0; i < result_count; ++i) {
174
175 struct result_stencil * curr_stencil =
176 (*get_stencil)(
177 (void*)((unsigned char*)results + pack_order[i] * result_size));
178
179 int position = 0;
180 void * buffer = (void*)((char*)pack_data_ + total_pack_size);
181 int buffer_size = (int)(temp_total_pack_size - total_pack_size);
182
183 // stencil
185 curr_stencil, buffer, buffer_size, &position, stencil_info_dt, comm);
186
187 pack_sizes[i] = position;
188 total_pack_size += (size_t)position;
189 }
190
191 *pack_data = pack_data_;
192}
193
195 struct result_stencil * stencil, void * buffer, int buffer_size,
196 int * position, MPI_Datatype stencil_info_dt, MPI_Comm comm,
197 struct stencil_info ** stencil_info_buffer,
198 size_t * stencil_info_buffer_array_size,
199 size_t * stencil_info_buffer_size) {
200
201 // global_id
203 MPI_Unpack(buffer, buffer_size, position,
204 &(stencil->global_id), 1, yac_int_dt, comm), comm);
205
206 // count
207 uint64_t count_uint64_t;
209 MPI_Unpack(buffer, buffer_size, position,
210 &count_uint64_t, 1, MPI_UINT64_T, comm), comm);
211 size_t count = ((stencil->count = (size_t)count_uint64_t));
212
213 // stencils
214 struct stencil_info * stencils;
215 if (count_uint64_t == 1) {
216 stencils = &(stencil->data.single);
217 } else {
219 *stencil_info_buffer, *stencil_info_buffer_array_size,
220 *stencil_info_buffer_size + count);
221 stencils =
222 ((stencil->data.multi =
223 *stencil_info_buffer + *stencil_info_buffer_size));
224 *stencil_info_buffer_size += count;
225 }
227 MPI_Unpack(buffer, buffer_size, position,
228 stencils, (int)count, stencil_info_dt, comm), comm);
229}
230
232 size_t count, void * packed_data, size_t packed_data_size,
233 MPI_Datatype stencil_info_dt, MPI_Comm comm) {
234
235 struct stencil_info * stencil_info_buffer = NULL;
236 size_t stencil_info_buffer_array_size = 0;
237 size_t stencil_info_buffer_size = 0;
238
240 xmalloc(count * sizeof(*result_stencils));
241
242 for (size_t i = 0, offset = 0; i < count; ++i) {
243
244 int position = 0;
245 void * curr_buffer = (void*)((char*)packed_data + offset);
246 int buffer_size = (int)(packed_data_size - offset);
247 struct result_stencil * curr_stencil = result_stencils + i;
248
250 curr_stencil, curr_buffer, buffer_size, &position, stencil_info_dt, comm,
251 &stencil_info_buffer, &stencil_info_buffer_array_size,
252 &stencil_info_buffer_size);
253 offset += (size_t)position;
254 }
255
256 struct result_stencils * results =
257 xmalloc(sizeof(*results) +
258 stencil_info_buffer_size * sizeof(results->stencil_info_buffer[0]));
259 results->stencils = result_stencils;
260 results->count = count;
261 memcpy(&(results->stencil_info_buffer[0]), stencil_info_buffer,
262 stencil_info_buffer_size * sizeof(*stencil_info_buffer));
264 for (size_t i = 0, offset = 0; i < count; ++i) {
265 size_t curr_count = result_stencils[i].count;
266 if (curr_count > 1) {
267 result_stencils[i].data.multi = &(results->stencil_info_buffer[offset]);
268 offset += curr_count;
269 }
270 }
271
272 return results;
273}
274
276 void * results, size_t result_count, size_t result_size,
277 struct result_stencil*(*result_get_stencil)(void*), size_t * pack_order,
278 int * ranks, struct comm_stuff comm) {
279
280 char const * routine = "exchange_interp_results";
281
282 // mark and count local results
283 size_t local_count = 0;
284 for (size_t i = 0; i < result_count; ++i) {
285 if (ranks[i] == comm.rank) {
286 ranks[i] = INT_MAX;
287 ++local_count;
288 }
289 }
290 size_t send_count = result_count - local_count;
291
292 // sort results by rank (local results go to the end of the array)
293 yac_quicksort_index_int_size_t(ranks, result_count, pack_order);
294
295 // pack the result stencils that need to be send to other processes
296 void * send_buffer;
297 int * pack_sizes = xmalloc(send_count * sizeof(*pack_sizes));
299 results, send_count, result_size,
300 result_get_stencil, pack_order, &send_buffer, pack_sizes,
301 comm.stencil_info_dt, comm.comm);
302
303 // set up comm buffers
304 size_t * num_results_per_rank =
305 xmalloc((size_t)comm.size * sizeof(*num_results_per_rank));
306 memset(comm.sendcounts, 0,
307 (size_t)comm.size * sizeof(*comm.sendcounts));
308 size_t j = 0;
309 for (int rank = 0; rank < comm.size; ++rank) {
310 size_t curr_num_results = 0;
311 size_t curr_sendcount = 0;
312 while ((j < send_count) && (ranks[j] == rank)) {
313 curr_sendcount += (size_t)(pack_sizes[j++]);
314 curr_num_results++;
315 }
316 num_results_per_rank[rank] = curr_num_results;
318 curr_sendcount <= INT_MAX, "ERROR(%s): pack size to big", routine)
319 comm.sendcounts[rank] = curr_sendcount;
320 }
321 free(pack_sizes);
323 1, comm.sendcounts, comm.recvcounts,
324 comm.sdispls, comm.rdispls, comm.comm);
326 MPI_Alltoall(MPI_IN_PLACE, 1, YAC_MPI_SIZE_T,
327 num_results_per_rank, 1, YAC_MPI_SIZE_T, comm.comm),
328 comm.comm);
329 size_t recv_count = 0;
330 for (int i = 0; i < comm.size; ++i)
331 recv_count += num_results_per_rank[i];
332 free(num_results_per_rank);
333
334 size_t recv_size = comm.recvcounts[comm.size - 1] +
335 comm.rdispls[comm.size - 1];
336 void * recv_buffer = xmalloc(recv_size);
337
338 // exchange result stencils
339 yac_alltoallv_packed_p2p(
340 send_buffer, comm.sendcounts, comm.sdispls+1,
341 recv_buffer, comm.recvcounts, comm.rdispls, comm.comm,
342 routine, __LINE__);
343 free(send_buffer);
344
345 // unpack stencils
348 recv_count, recv_buffer, recv_size, comm.stencil_info_dt, comm.comm);
349 free(recv_buffer);
350
351 result_stencils->count += local_count;
353 xrealloc(
355 (recv_count + local_count) * sizeof(*(result_stencils->stencils)));
356
357 // add the local result stenils
358 struct result_stencil * local_stencils =
359 result_stencils->stencils + recv_count;
360 pack_order += send_count;
361 for (size_t i = 0; i < local_count; ++i)
362 local_stencils[i] =
363 *(*result_get_stencil)(
364 (void*)((unsigned char*)results + pack_order[i] * result_size));
365
366 return result_stencils;
367}
368
370 void * interp_result) {
371
372 return &(((struct interp_result*)interp_result)->stencil);
373}
374
376 struct yac_interp_grid * interp_grid, struct comm_stuff comm,
377 struct interp_result * interp_results, size_t result_count) {
378
379 // get the the newly interpolated target points
380 size_t * tgt_points = xmalloc(result_count * sizeof(*tgt_points));
381 for (size_t i = 0; i < result_count; ++i)
382 tgt_points[i] = interp_results[i].local_id;
383
384 // get the distributed owners for all targets
385 int * tgt_points_dist_owner =
386 xmalloc(result_count * sizeof(*tgt_points_dist_owner));
388 interp_grid, tgt_points, result_count, tgt_points_dist_owner);
389 size_t * pack_order = tgt_points;
390 for (size_t i = 0; i < result_count; ++i) pack_order[i] = i;
391
392 struct result_stencils * relocated_results =
394 interp_results, result_count, sizeof(*interp_results),
395 interp_result_get_stencil, pack_order, tgt_points_dist_owner,
396 comm);
397 free(pack_order);
398 free(tgt_points_dist_owner);
399
400 return relocated_results;
401}
402
404 struct yac_interp_grid * interp_grid, struct comm_stuff comm,
405 struct yac_interp_weights * interp_weights,
406 struct interp_result ** interp_results, size_t * result_count) {
407
408 // get list of all already interpolated target points
409 size_t num_interpolated_tgt =
411 yac_int * interpolated_tgts_global_ids =
412 yac_interp_weights_get_interp_tgt(interp_weights);
413 size_t * interpolated_tgts_local_ids =
414 xmalloc(num_interpolated_tgt * sizeof(*interpolated_tgts_local_ids));
416 interp_grid, interpolated_tgts_global_ids, num_interpolated_tgt,
417 interpolated_tgts_local_ids);
418
419 // initialise initial interpolation results
420 struct interp_result * initial_interp_results =
421 (num_interpolated_tgt > 0)?
422 xmalloc(num_interpolated_tgt * sizeof(*initial_interp_results)):NULL;
423 for (size_t i = 0; i < num_interpolated_tgt; ++i) {
424 initial_interp_results[i].local_id = interpolated_tgts_local_ids[i];
425 initial_interp_results[i].global_id = interpolated_tgts_global_ids[i];
426 initial_interp_results[i].idx = SIZE_MAX;
427 initial_interp_results[i].stencil.global_id =
428 interpolated_tgts_global_ids[i];
429 initial_interp_results[i].stencil.count = 1;
430 initial_interp_results[i].stencil.data.single.rank = comm.rank;
431 initial_interp_results[i].stencil.data.single.idx = (uint64_t)i;
432 initial_interp_results[i].stencil.data.single.weight = 1.0;
433 }
434 free(interpolated_tgts_local_ids);
435 free(interpolated_tgts_global_ids);
436
437 *interp_results = initial_interp_results;
438 *result_count = num_interpolated_tgt;
439}
440
442 const void * a, const void * b) {
443
444 int ret = (((const struct interp_result *)a)->stencil.count >
445 ((const struct interp_result *)b)->stencil.count) -
446 (((const struct interp_result *)a)->stencil.count <
447 ((const struct interp_result *)b)->stencil.count);
448
449 if (ret) return ret;
450
451 return (((const struct interp_result *)a)->global_id >
452 ((const struct interp_result *)b)->global_id) -
453 (((const struct interp_result *)a)->global_id <
454 ((const struct interp_result *)b)->global_id);
455}
456
458 const void * a, const void * b) {
459
460 return (((const struct interp_result *)a)->local_id >
461 ((const struct interp_result *)b)->local_id) -
462 (((const struct interp_result *)a)->local_id <
463 ((const struct interp_result *)b)->local_id);
464}
465
466static int compare_interp_result_global_id(const void * a, const void * b) {
467
468 return (((const struct interp_result *)a)->global_id >
469 ((const struct interp_result *)b)->global_id) -
470 (((const struct interp_result *)a)->global_id <
471 ((const struct interp_result *)b)->global_id);
472}
473
475 const void * a, const void * b) {
476
477 return (((const struct tgt_request *)a)->stencil.count >
478 ((const struct tgt_request *)b)->stencil.count) -
479 (((const struct tgt_request *)a)->stencil.count <
480 ((const struct tgt_request *)b)->stencil.count);
481}
482
484 const void * a, const void * b) {
485
486 return (((const struct tgt_request *)a)->global_id >
487 ((const struct tgt_request *)b)->global_id) -
488 (((const struct tgt_request *)a)->global_id <
489 ((const struct tgt_request *)b)->global_id);
490}
491
493 const void * a, const void * b) {
494
495 return (((const struct result_stencil *)a)->global_id >
496 ((const struct result_stencil *)b)->global_id) -
497 (((const struct result_stencil *)a)->global_id <
498 ((const struct result_stencil *)b)->global_id);
499}
500
501static inline int compare_yac_int(const void * a, const void * b) {
502
503 return ((*(const yac_int *)a) >
504 (*(const yac_int *)b)) -
505 ((*(const yac_int *)a) <
506 (*(const yac_int *)b));
507}
508
510 struct yac_interp_grid * interp_grid,
511 struct interp_result * interp_results, size_t result_count,
512 struct remote_points * interp_tgt_remote_points,
513 size_t ** num_stencils_per_tgt_, size_t ** stencil_indices_,
514 int ** stencil_ranks_, double ** w_) {
515
516 // sort interpolation results by target local id
517 qsort(interp_results, result_count, sizeof(*interp_results),
519
520 size_t total_num_stencils = 0;
521 size_t * interpolated_tgts_local_ids =
522 xmalloc(result_count * sizeof(*interpolated_tgts_local_ids));
523 for (size_t i = 0; i < result_count; ++i) {
524 interpolated_tgts_local_ids[i] = interp_results[i].local_id;
525 total_num_stencils += interp_results[i].stencil.count;
526 }
527 interp_tgt_remote_points->data =
529 interp_grid, interpolated_tgts_local_ids, result_count);
530 interp_tgt_remote_points->count = result_count;
531 free(interpolated_tgts_local_ids);
532
533 size_t * num_stencils_per_tgt =
534 xmalloc(result_count * sizeof(*num_stencils_per_tgt));
535 size_t * stencil_indices =
536 xmalloc(total_num_stencils * sizeof(*stencil_indices));
537 int * stencil_ranks =
538 xmalloc(total_num_stencils * sizeof(*stencil_ranks));
539 double * w = xmalloc(total_num_stencils * sizeof(*w));
540
541 for (size_t i = 0, j = 0; i < result_count; ++i) {
542
543 size_t curr_count = interp_results[i].stencil.count;
544
545 num_stencils_per_tgt[i] = curr_count;
546
547 if (curr_count == 1) {
548 stencil_indices[j] = interp_results[i].stencil.data.single.idx;
549 stencil_ranks[j] = interp_results[i].stencil.data.single.rank;
550 w[j] = interp_results[i].stencil.data.single.weight;
551 ++j;
552 } else {
553 for (size_t k = 0; k < curr_count; ++k, ++j) {
554 stencil_indices[j] = interp_results[i].stencil.data.multi[k].idx;
555 stencil_ranks[j] = interp_results[i].stencil.data.multi[k].rank;
556 w[j] = interp_results[i].stencil.data.multi[k].weight;
557 }
558 }
559 }
560
561 *num_stencils_per_tgt_ = num_stencils_per_tgt;
562 *stencil_indices_ = stencil_indices;
563 *stencil_ranks_ = stencil_ranks;
564 *w_ = w;
565}
566
568 void * tgt_request) {
569
570 return &(((struct tgt_request*)tgt_request)->stencil);
571}
572
574 struct comm_stuff comm, struct tgt_request * neigh_requests,
575 size_t * request_count_, struct result_stencils * interp_stencils) {
576
577 size_t request_count = *request_count_;
578 size_t match_count = 0;
579
580 struct result_stencil * stencils = interp_stencils->stencils;
581 size_t stencil_count = interp_stencils->count;
582
583 // match current result points with neighbour requests
584 qsort(
585 stencils, stencil_count, sizeof(*stencils),
587 for (size_t i = 0, j = 0; i < stencil_count; ++i) {
588 yac_int curr_global_id = stencils[i].global_id;
589
590 while ((j < request_count) &&
591 (neigh_requests[j].global_id < curr_global_id)) ++j;
592 while ((j < request_count) &&
593 (neigh_requests[j].global_id == curr_global_id)) {
594
595 ++match_count;
596 neigh_requests[j].stencil = stencils[i];
597 ++j;
598 }
599 }
600
601 // sort neighbour request by stencil count
602 // (open requests have a stencil count of 0)
603 qsort(neigh_requests, request_count, sizeof(*neigh_requests),
605
606 request_count -= match_count;
607 *request_count_ = request_count;
608 struct tgt_request * neigh_request_matches = neigh_requests + request_count;
609
610 // sort open neighbour requests by global id
611 qsort(neigh_requests, request_count, sizeof(*neigh_requests),
613
614 size_t * pack_order = xmalloc(match_count * sizeof(*pack_order));
615 int * origin_rank = xmalloc(match_count * sizeof(*origin_rank));
616 for (size_t i = 0; i < match_count; ++i) {
617 pack_order[i] = i;
618 origin_rank[i] = neigh_request_matches[i].rank;
619 }
620
621 struct result_stencils * relocated_results =
623 neigh_request_matches, match_count, sizeof(*neigh_request_matches),
624 tgt_request_get_stencil, pack_order, origin_rank, comm);
625 free(origin_rank);
626 free(pack_order);
627
628 return relocated_results;
629}
630
632 struct yac_interp_grid * interp_grid, size_t * tgt_local_ids,
633 yac_int * tgt_global_ids, size_t count,
634 size_t ** neigh_local_ids_, yac_int ** neigh_to_tgt_global_id_,
635 size_t * total_num_neighbours_) {
636
637 // get neighbour cells for all target cells
638 size_t total_num_neighbours = 0;
639 struct yac_const_basic_grid_data * tgt_basic_grid_data =
641 for (size_t i = 0; i < count; ++i)
642 total_num_neighbours +=
643 tgt_basic_grid_data->num_vertices_per_cell[tgt_local_ids[i]];
644 size_t * neigh_local_ids =
645 xmalloc(total_num_neighbours * sizeof(*neigh_local_ids));
647 interp_grid, tgt_local_ids, count, neigh_local_ids);
648
649 // generate mapping between neighbour global ids and target points
650 yac_int * neigh_to_tgt_global_id =
651 xmalloc(total_num_neighbours * sizeof(*neigh_to_tgt_global_id));
652 for (size_t i = 0, j = 0; i < count; ++i) {
653 int curr_num_neigh =
654 tgt_basic_grid_data->num_vertices_per_cell[tgt_local_ids[i]];
655 yac_int curr_tgt_global_id = tgt_global_ids[i];
656 for (int k = 0; k < curr_num_neigh; ++k, ++j)
657 neigh_to_tgt_global_id[j] = curr_tgt_global_id;
658 }
659
660 *neigh_local_ids_ = neigh_local_ids;
661 *neigh_to_tgt_global_id_ = neigh_to_tgt_global_id;
662 *total_num_neighbours_ = total_num_neighbours;
663}
664
666 struct yac_interp_grid * interp_grid, size_t * tgt_local_ids,
667 yac_int * tgt_global_ids, size_t count,
668 size_t ** neigh_local_ids_, yac_int ** neigh_to_tgt_global_id_,
669 size_t * total_num_neighbours_) {
670
671 int * num_neighs_per_vertex = xmalloc(count * sizeof(*num_neighs_per_vertex));
672 size_t * neigh_vertices;
673
675 interp_grid, tgt_local_ids, count,
676 &neigh_vertices, num_neighs_per_vertex);
677
678 size_t total_num_neighbours = 0;
679 for (size_t i = 0; i < count; ++i)
680 total_num_neighbours += (size_t)(num_neighs_per_vertex[i]);
681
682 // generate mapping between neighbour global ids and target points
683 yac_int * neigh_to_tgt_global_id =
684 xmalloc(total_num_neighbours * sizeof(*neigh_to_tgt_global_id));
685 for (size_t i = 0, j = 0; i < count; ++i) {
686 int curr_num_neigh = num_neighs_per_vertex[i];
687 yac_int curr_tgt_global_id = tgt_global_ids[i];
688 for (int k = 0; k < curr_num_neigh; ++k, ++j)
689 neigh_to_tgt_global_id[j] = curr_tgt_global_id;
690 }
691 free(num_neighs_per_vertex);
692
693 *neigh_local_ids_ = neigh_vertices;
694 *neigh_to_tgt_global_id_ = neigh_to_tgt_global_id;
695 *total_num_neighbours_ = total_num_neighbours;
696}
697
698// extracts basic information about the neighbours of the target points
700 struct yac_interp_grid * interp_grid,
701 size_t * tgt_local_ids, yac_int * tgt_global_ids, size_t count,
702 size_t ** neigh_local_ids_, yac_int ** neigh_global_ids_,
703 yac_int ** neigh_to_tgt_global_id_, size_t * total_num_neighbours_) {
704
705 // get basic neighbour information
706 size_t * neigh_local_ids;
707 yac_int * neigh_to_tgt_global_id;
708 size_t total_num_neighbours;
709 enum yac_location tgt_field_location =
712 (tgt_field_location == YAC_LOC_CELL) ||
713 (tgt_field_location == YAC_LOC_CORNER),
714 "ERROR(get_tgt_neigh_info): unsupported target field location")
715 if (tgt_field_location == YAC_LOC_CELL)
717 interp_grid, tgt_local_ids, tgt_global_ids, count,
718 &neigh_local_ids, &neigh_to_tgt_global_id, &total_num_neighbours);
719 else
721 interp_grid, tgt_local_ids, tgt_global_ids, count,
722 &neigh_local_ids, &neigh_to_tgt_global_id, &total_num_neighbours);
723
724 // remove invalid neighbour indices
726 neigh_local_ids, total_num_neighbours, neigh_to_tgt_global_id);
727 while((total_num_neighbours > 0) &&
728 (neigh_local_ids[total_num_neighbours-1] == SIZE_MAX))
729 --total_num_neighbours;
730
731 // get global ids for all neighbours
732 yac_int * neigh_global_ids =
733 xmalloc(total_num_neighbours * sizeof(*neigh_global_ids));
735 interp_grid, neigh_local_ids, total_num_neighbours, neigh_global_ids);
736
737 *neigh_local_ids_ =
738 xrealloc(neigh_local_ids, total_num_neighbours * sizeof(*neigh_local_ids));
739 *neigh_global_ids_ = neigh_global_ids;
740 *neigh_to_tgt_global_id_ =
741 xrealloc(neigh_to_tgt_global_id,
742 total_num_neighbours * sizeof(*neigh_to_tgt_global_id));
743 *total_num_neighbours_ = total_num_neighbours;
744}
745
746// sends request for target points neighbours to the respective
747// distributed owners
749 struct yac_interp_grid * interp_grid, struct comm_stuff comm,
750 size_t * neigh_local_ids, yac_int * neigh_global_ids,
751 size_t num_neighbours, struct tgt_request ** neigh_requests_,
752 size_t * request_count_) {
753
754 // get the distributed owner of the neighbour target points
755 int * neigh_dist_owner =
756 xmalloc(num_neighbours * sizeof(*neigh_dist_owner));
758 interp_grid, neigh_local_ids, num_neighbours,
759 neigh_dist_owner);
760
761 yac_int * send_neigh_global_ids =
762 xmalloc(num_neighbours * sizeof(*send_neigh_global_ids));
763 memcpy(send_neigh_global_ids, neigh_global_ids,
764 num_neighbours * sizeof(*send_neigh_global_ids));
765
766 // sort send buffer by rank
768 neigh_dist_owner, num_neighbours, send_neigh_global_ids);
769
770 // remove duplicated global ids
771 size_t to = 0, new_to = 0, from = 0, new_from = 0;
772 for (int rank = 0; rank < comm.size; ++rank) {
773 while ((new_from < num_neighbours) &&
774 (neigh_dist_owner[new_from] == rank)) new_from++;
775 size_t curr_count = new_from - from;
776 qsort(send_neigh_global_ids + from, curr_count,
777 sizeof(*send_neigh_global_ids), compare_yac_int);
778 yac_int prev_global_id =
779 (curr_count > 0)?(send_neigh_global_ids[from]-1):0;
780 for (; from < new_from; ++from) {
781 yac_int curr_global_id = send_neigh_global_ids[from];
782 if (prev_global_id != curr_global_id) {
783 send_neigh_global_ids[new_to++] = curr_global_id;
784 prev_global_id = curr_global_id;
785 }
786 }
787 curr_count = new_to - to;
788 to = new_to;
789 comm.sendcounts[rank] = curr_count;
790 }
791 free(neigh_dist_owner);
792
793 // send request for all neighbours
795 1, comm.sendcounts, comm.recvcounts, comm.sdispls, comm.rdispls, comm.comm);
796 size_t request_count = comm.recvcounts[comm.size-1] +
797 comm.rdispls[comm.size-1];
798 yac_int * recv_neigh_global_ids =
799 xmalloc(request_count * sizeof(*recv_neigh_global_ids));
800 yac_alltoallv_yac_int_p2p(
801 send_neigh_global_ids, comm.sendcounts, comm.sdispls+1,
802 recv_neigh_global_ids, comm.recvcounts, comm.rdispls, comm.comm,
803 "send_neigh_request", __LINE__);
804 struct tgt_request * neigh_requests =
805 xmalloc(request_count * sizeof(*neigh_requests));
806 for (int i = 0, k = 0; i < comm.size; ++i) {
807 for (size_t j = 0; j < comm.recvcounts[i]; ++j, ++k) {
808 neigh_requests[k].global_id = recv_neigh_global_ids[k];
809 neigh_requests[k].rank = i;
810 neigh_requests[k].stencil.count = 0;
811 }
812 }
813 qsort(neigh_requests, request_count, sizeof(*neigh_requests),
815 free(send_neigh_global_ids);
816 free(recv_neigh_global_ids);
817
818 *neigh_requests_ = neigh_requests;
819 *request_count_ = request_count;
820}
821
823 size_t * tgt_local_ids, yac_int * tgt_global_ids, size_t count) {
824
825 struct interp_result * interp_results =
826 xmalloc(count * sizeof(*interp_results));
827 for (size_t i = 0; i < count; ++i) {
828 interp_results[i].local_id = tgt_local_ids[i];
829 interp_results[i].global_id = tgt_global_ids[i];
830 interp_results[i].idx = i;
831 interp_results[i].stencil.count = 0;
832 }
833 qsort(interp_results, count, sizeof(*interp_results),
835 return interp_results;
836}
837
839 const void * a, const void * b) {
840
841 int ret = ((struct stencil_info *)a)->rank -
842 ((struct stencil_info *)b)->rank;
843 if (ret) return ret;
844
845 return (((struct stencil_info *)a)->idx >
846 ((struct stencil_info *)b)->idx) -
847 (((struct stencil_info *)a)->idx <
848 ((struct stencil_info *)b)->idx);
849}
850
852 struct result_stencil * neigh_stencils, size_t * stencil_indices,
853 size_t count, yac_int global_id, double weight) {
854
855 size_t stencil_info_count = 0;
856
857 for (size_t i = 0; i < count; ++i)
858 stencil_info_count += neigh_stencils[stencil_indices[i]].count;
859
860 struct result_stencil stencil;
861
862 struct stencil_info * stencil_infos;
863 if (stencil_info_count > 1) {
864 stencil_infos =
865 ((stencil.data.multi =
866 xmalloc(stencil_info_count * sizeof(*stencil_infos))));
867 } else {
868 stencil_infos = &(stencil.data.single);
869 }
870
871 stencil.global_id = global_id;
872 for (size_t i = 0, j = 0; i < count; ++i) {
873 struct result_stencil * curr_stencil =
874 neigh_stencils + stencil_indices[i];
875 size_t curr_stencil_info_count = curr_stencil->count;
876 struct stencil_info * curr_stencil_infos =
877 (curr_stencil_info_count == 1)?
878 (&(curr_stencil->data.single)):(curr_stencil->data.multi);
879 memcpy(stencil_infos + j, curr_stencil_infos,
880 curr_stencil_info_count * sizeof(*stencil_infos));
881 for (size_t k = 0; k < curr_stencil_info_count; ++k, ++j)
882 stencil_infos[j].weight *= weight;
883 }
884
885 // in case we have multiple stencil infos, there may be duplicated
886 // entries from different source
887 // here we remove these duplicated entries
888 if (stencil_info_count > 1) {
889
890 // sort the stencils
891 qsort(stencil_infos, stencil_info_count, sizeof(*stencil_infos),
893
894 // remote duplicated stencils
895 struct stencil_info * prev_stencil_info = stencil_infos,
896 * curr_stencil_info = stencil_infos + 1;
897 size_t new_stencil_info_count = 1;
898 for (size_t i = 1; i < stencil_info_count; ++i, ++curr_stencil_info) {
900 curr_stencil_info, prev_stencil_info)) {
901 if (new_stencil_info_count != i)
902 stencil_infos[new_stencil_info_count] =
903 *curr_stencil_info;
904 ++new_stencil_info_count;
905 prev_stencil_info = curr_stencil_info;
906 } else {
907 stencil_infos[new_stencil_info_count-1].weight +=
908 curr_stencil_info->weight;
909 }
910 }
911 if (new_stencil_info_count != stencil_info_count) {
912 stencil_info_count = new_stencil_info_count;
913 if (new_stencil_info_count == 1) {
914 stencil.data.single = *stencil_infos;
915 free(stencil_infos);
916 } else {
917 stencil.data.multi =
918 xrealloc(
919 stencil_infos, stencil_info_count * sizeof(*stencil_infos));
920 }
921 }
922 }
923 stencil.count = stencil_info_count;
924
925 return stencil;
926}
927
929 struct result_stencils * neigh_answer,
930 yac_int * neigh_global_ids, yac_int * neigh_to_tgt_global_id,
931 size_t * stencil_indices, size_t * num_neighbours_,
932 struct interp_result * interp_results, size_t * num_open_tgt_) {
933
934 size_t num_neighbours = *num_neighbours_;
935 size_t num_open_tgt = *num_open_tgt_;
936
937 struct result_stencil * neigh_stencils = neigh_answer->stencils;
938 size_t answer_count = neigh_answer->count;
939
940 // match received neigh request answers with tgt neighbours
941 // (remove duplicated results)
942 qsort(
943 neigh_stencils, answer_count, sizeof(*neigh_stencils),
945 size_t match_count = 0;
946 for (size_t i = 0, j = 0; i < answer_count; ++i) {
947 yac_int curr_global_id = neigh_stencils[i].global_id;
948
949 while ((j < num_neighbours) &&
950 (neigh_global_ids[j] < curr_global_id)) ++j;
951
952 while ((j < num_neighbours) &&
953 (neigh_global_ids[j] == curr_global_id)) {
954 neigh_global_ids[j] = YAC_INT_MAX;
955 stencil_indices[j] = i;
956 ++match_count;
957 ++j;
958 }
959 }
960
961 // move fullfilled neighbour requests to the end of the array
963 neigh_global_ids, num_neighbours, neigh_to_tgt_global_id, stencil_indices);
964 num_neighbours -= match_count;
965 *num_neighbours_ = num_neighbours;
966
967 neigh_to_tgt_global_id += num_neighbours;
968 stencil_indices += num_neighbours;
969
970 // sort matches by target global ids
972 neigh_to_tgt_global_id, match_count, stencil_indices);
973
974 // set stencils for target matches
975 for (size_t i = 0, k = 0; i < match_count;) {
976
977 size_t prev_i = i;
978
979 // count the number of stencils for the current target
980 yac_int curr_tgt_global_id = neigh_to_tgt_global_id[i++];
981 while ((i < match_count) &&
982 (neigh_to_tgt_global_id[i] == curr_tgt_global_id)) ++i;
983 size_t curr_stencil_count = i - prev_i;
984
985 while ((k < num_open_tgt) &&
986 (interp_results[k].global_id < curr_tgt_global_id)) ++k;
987
988 while ((k < num_open_tgt) &&
989 (interp_results[k].global_id == curr_tgt_global_id)) {
990
991 interp_results[k].stencil =
993 neigh_stencils, stencil_indices + prev_i, curr_stencil_count,
994 curr_tgt_global_id, 1.0 / (double)curr_stencil_count);
995 ++k;
996 }
997 }
998
999 // move successfully interpolated target points to the end of
1000 // the array
1001 qsort(interp_results, num_open_tgt, sizeof(*interp_results),
1003 size_t new_num_open_tgt = 0;
1004 while ((new_num_open_tgt < num_open_tgt) &&
1005 (interp_results[new_num_open_tgt].stencil.count == 0))
1006 new_num_open_tgt++;
1007 *num_open_tgt_ = new_num_open_tgt;
1008 return num_open_tgt - new_num_open_tgt;
1009}
1010
1012 struct yac_interp_grid * interp_grid) {
1013
1014 struct comm_stuff comm;
1015
1016 comm.comm = yac_interp_grid_get_MPI_Comm(interp_grid);
1018 1, &comm.sendcounts, &comm.recvcounts, &comm.sdispls, &comm.rdispls,
1019 comm.comm);
1020 yac_mpi_call(MPI_Comm_rank(comm.comm, &comm.rank), comm.comm);
1021 yac_mpi_call(MPI_Comm_size(comm.comm, &comm.size), comm.comm);
1022 comm.stencil_info_dt = yac_get_stencil_info_mpi_datatype(comm.comm);
1023
1024 return comm;
1025}
1026
1027static void free_comm_stuff(struct comm_stuff comm) {
1028
1030 comm.sendcounts, comm.recvcounts, comm.sdispls, comm.rdispls);
1031 yac_mpi_call(MPI_Type_free(&comm.stencil_info_dt), comm.comm);
1032}
1033
1034// the local process is the distributed owner for all target points
1035// passed to this routine
1037 struct yac_interp_grid * interp_grid, int const max_creep_distance,
1038 size_t * tgt_points, yac_int * tgt_global_ids, size_t count,
1039 int * interp_flag, struct yac_interp_weights * weights) {
1040
1041 struct comm_stuff comm = init_comm_stuff(interp_grid);
1042
1043 // get information about the neighbours of the target points
1044 size_t * neigh_local_ids;
1045 yac_int * neigh_global_ids;
1046 yac_int * neigh_to_tgt_global_id;
1047 size_t total_num_neighbours;
1049 interp_grid, tgt_points, tgt_global_ids, count,
1050 &neigh_local_ids, &neigh_global_ids, &neigh_to_tgt_global_id,
1051 &total_num_neighbours);
1052 size_t * stencil_indices =
1053 xmalloc(total_num_neighbours * sizeof(*stencil_indices));
1054
1055 // send request for target points neighbours to the respective
1056 // distributed owners
1057 struct tgt_request * neigh_requests;
1058 size_t request_count;
1060 interp_grid, comm, neigh_local_ids, neigh_global_ids, total_num_neighbours,
1061 &neigh_requests, &request_count);
1062 free(neigh_local_ids);
1063
1064 // sort global ids of target point neighbours
1066 neigh_global_ids, total_num_neighbours, neigh_to_tgt_global_id);
1067
1068 // initialise interpolation results
1069 size_t num_open_tgt = count;
1070 struct interp_result * interp_results =
1071 init_interp_results(tgt_points, tgt_global_ids, count);
1072
1073 // get already existing results and relocate them to their respective
1074 // distributed owners
1075 struct interp_result * initial_interp_results;
1076 size_t result_count;
1078 interp_grid, comm, weights, &initial_interp_results, &result_count);
1079
1080 for (int creep_distance = 0;
1081 creep_distance < max_creep_distance; ++creep_distance) {
1082
1083 // check whether there are initial results on any process
1084 int result_flag = result_count > 0;
1086 MPI_Allreduce(
1087 MPI_IN_PLACE, &result_flag, 1, MPI_INT, MPI_MAX, comm.comm), comm.comm);
1088 if (result_flag == 0) break;
1089
1090 // relocate interpolation results to distributed owners of associated
1091 // target points
1092 struct result_stencils * interp_stencils =
1094 interp_grid, comm,
1095 (creep_distance == 0)?
1096 initial_interp_results:(interp_results + num_open_tgt),
1097 result_count);
1098 if (creep_distance == 0) free(initial_interp_results);
1099
1100 // match interpolation results with distributed neighbour requests and
1101 // inform origins of requests about matches
1102 struct result_stencils * neigh_matches =
1104 comm, neigh_requests, &request_count, interp_stencils);
1105
1106 // match received neigh request answers with tgts
1107 result_count =
1109 neigh_matches, neigh_global_ids, neigh_to_tgt_global_id,
1110 stencil_indices, &total_num_neighbours, interp_results,
1111 &num_open_tgt);
1112 free(interp_stencils->stencils);
1113 free(interp_stencils);
1114 free(neigh_matches->stencils);
1115 free(neigh_matches);
1116 } // creep_distance < max_creep_distance
1117
1118 free(neigh_requests);
1119 free(stencil_indices);
1120 free(neigh_global_ids);
1121 free(neigh_to_tgt_global_id);
1122
1123 for (size_t i = 0; i < count; ++i)
1124 interp_flag[interp_results[i].idx] =
1125 interp_results[i].stencil.count > 0;
1126
1127 // copy stencils
1128 struct remote_points interp_tgt_remote_points;
1129 size_t * num_stencils_per_tgt;
1130 int * stencil_ranks;
1131 double * w;
1133 interp_grid, interp_results + num_open_tgt, count - num_open_tgt,
1134 &interp_tgt_remote_points, &num_stencils_per_tgt, &stencil_indices,
1135 &stencil_ranks, &w);
1137 weights, &interp_tgt_remote_points, num_stencils_per_tgt,
1138 stencil_indices, stencil_ranks, w);
1139 free(interp_tgt_remote_points.data);
1140 free(w);
1141 free(num_stencils_per_tgt);
1142 free(stencil_ranks);
1143 free(stencil_indices);
1144 for (size_t i = num_open_tgt; i < count; ++i)
1145 if (interp_results[i].stencil.count > 1)
1146 free(interp_results[i].stencil.data.multi);
1147 free(interp_results);
1148
1149 free_comm_stuff(comm);
1150}
1151
1152static size_t do_search_creep (struct interp_method * method,
1153 struct yac_interp_grid * interp_grid,
1154 size_t * tgt_points, size_t count,
1155 struct yac_interp_weights * weights,
1156 int * interpolation_complete) {
1157
1158 if (*interpolation_complete) return 0;
1159
1160 char const * routine = "do_search_creep";
1161
1162 struct interp_method_creep * creep_method =
1163 (struct interp_method_creep *)method;
1164
1165 int const max_creep_distance = creep_method->max_creep_distance;
1166
1167 if (max_creep_distance == 0) return 0;
1168
1172 "ERROR(%s): unsupported target field location "
1173 "(has to be YAC_LOC_CELL or YAC_LOC_CORNER)", routine)
1174
1175 MPI_Comm comm = yac_interp_grid_get_MPI_Comm(interp_grid);
1176 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
1178 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
1179 int comm_rank, comm_size;
1180 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
1181 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
1182
1183 // get the distributed owners for all tgts
1184 int * tgt_points_dist_owner =
1185 xmalloc(count * sizeof(*tgt_points_dist_owner));
1187 interp_grid, tgt_points, count, tgt_points_dist_owner);
1188 yac_int * tgt_points_global_ids =
1189 xmalloc(count * sizeof(*tgt_points_global_ids));
1191 interp_grid, tgt_points, count, tgt_points_global_ids);
1192
1193 // determine which of these points are local
1194 size_t local_count = 0;
1195 for (size_t i = 0; i < count; ++i) {
1196 if (tgt_points_dist_owner[i] == comm_rank) {
1197 local_count++;
1198 tgt_points_dist_owner[i] = INT_MAX;
1199 }
1200 }
1201 size_t send_count = count - local_count;
1202
1203 // sort target points (remote points to the start of the array)
1205 tgt_points_dist_owner, count, tgt_points, tgt_points_global_ids);
1206
1207 // relocate tgt_points to distributed owners
1208 for (size_t i = 0; i < send_count; ++i)
1209 sendcounts[tgt_points_dist_owner[i]]++;
1211 1, sendcounts, recvcounts, sdispls, rdispls, comm);
1212 size_t recv_count = recvcounts[comm_size-1] + rdispls[comm_size-1];
1213 yac_int * global_ids_buffer =
1214 xrealloc(
1215 tgt_points_global_ids,
1216 (send_count + local_count + recv_count) * sizeof(*global_ids_buffer));
1217 yac_int * send_global_ids = global_ids_buffer;
1218 yac_int * recv_global_ids = global_ids_buffer + send_count;
1219 yac_alltoallv_yac_int_p2p(
1220 send_global_ids, sendcounts, sdispls+1,
1221 recv_global_ids + local_count, recvcounts, rdispls, comm,
1222 routine, __LINE__);
1223
1224 // get local ids for received global ids
1225 size_t * temp_tgt_points =
1226 xmalloc((local_count + recv_count) * sizeof(*temp_tgt_points));
1227 memcpy(temp_tgt_points, tgt_points + send_count,
1228 local_count * sizeof(*tgt_points));
1230 interp_grid, recv_global_ids + local_count, recv_count,
1231 temp_tgt_points + local_count);
1232
1233 // do the interpolation for the redistributed target points
1234 int * interp_flag_buffer =
1235 xmalloc((send_count + local_count + recv_count) *
1236 sizeof(*interp_flag_buffer));
1237 int * temp_interp_flag = interp_flag_buffer + send_count;
1238 int * interp_flag = interp_flag_buffer;
1239 memset(temp_interp_flag, 0, (local_count + recv_count) * sizeof(*temp_interp_flag));
1241 interp_grid, max_creep_distance, temp_tgt_points, global_ids_buffer + send_count,
1242 local_count + recv_count, temp_interp_flag, weights);
1243 free(global_ids_buffer);
1244 free(temp_tgt_points);
1245
1246 // relocate interp_flag
1247 yac_alltoallv_int_p2p(
1248 temp_interp_flag + local_count, recvcounts, rdispls,
1249 interp_flag, sendcounts, sdispls+1, comm, routine, __LINE__);
1250
1251 // count number of points that can be interpolated and reorder
1252 // tgt_points accordingly (interpolated first)
1253 size_t num_interpolated_tgt = 0;
1254 for (size_t i = 0; i < count; ++i) {
1255 if (interp_flag[i]) {
1256 interp_flag[i] = 0;
1257 ++num_interpolated_tgt;
1258 } else {
1259 interp_flag[i] = 1;
1260 }
1261 }
1262 yac_quicksort_index_int_size_t(interp_flag, count, tgt_points);
1263 free(interp_flag_buffer);
1264 free(tgt_points_dist_owner);
1265
1266 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
1267
1268 return num_interpolated_tgt;
1269}
1270
1271struct interp_method * yac_interp_method_creep_new(int creep_distance) {
1272
1273 struct interp_method_creep * method_creep =
1274 xmalloc(1 * sizeof(*method_creep));
1275
1276 method_creep->vtable = &interp_method_creep_vtable;
1277 method_creep->max_creep_distance =
1278 (creep_distance >= 0)?creep_distance:INT_MAX;
1279
1280 return (struct interp_method*)method_creep;
1281}
1282
1283static void delete_creep(struct interp_method * method) {
1284 free(method);
1285}
1286
1287// --- Modular config struct and vtable for CHECK method ---
1288
1304
1307 free(config);
1308}
1309
1311 const struct yac_interp_method_config *config) {
1313 struct yac_interp_method_config_creep *copy =
1314 xmalloc(sizeof(*copy));
1315 copy->vtable = config_creep->vtable;
1316 copy->config = config_creep->config;
1317 return (struct yac_interp_method_config *)copy;
1318}
1319
1321 void const *a_, void const *b_) {
1323 // Compare creep fill interpolation parameter:
1324 // creep_distance: number of iterations for extrapolation
1325 CHECK_INT(config.creep_distance);
1326 return 0;
1327}
1328
1329// Returns the MPI pack size for a creep config
1331 struct yac_interp_method_config const *config, MPI_Comm comm) {
1332 UNUSED(config);
1333 int int_pack_size;
1334 yac_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &int_pack_size), comm);
1335 return (size_t)int_pack_size;
1336}
1337
1338// Packs a creep config into a buffer
1340 struct yac_interp_method_config const *config,
1341 void *buffer, int buffer_size, int *position, MPI_Comm comm) {
1344 MPI_Pack(
1345 &config_creep->config.creep_distance, 1, MPI_INT, buffer, buffer_size,
1346 position, comm), comm);
1347}
1348
1349// Gets interpolation method typed_config_hcsbb_get_type
1351 return YAC_CREEP;
1352}
1353
1355 struct yac_interp_method_config const *config) {
1356 const struct yac_interp_method_config_creep *config_creep =
1357 (const struct yac_interp_method_config_creep *)config;
1359}
1360
1362 struct yac_interp_method_config const *config) {
1363 struct yac_interp_method_config_creep *config_creep =
1365
1366 enum {
1367 CREEP_DISTANCE_HAS_DEFAULT = 1,
1368 CREEP_DISTANCE_IS_DEFINED = 1,
1369 };
1370
1371 int const creep_distance_min = -1;
1372 int const creep_distance_max = INT_MAX;
1373
1374 struct yac_param *creep_distance_param =
1376 "creep_distance",
1377 &config_creep->config.creep_distance,
1379 creep_distance_min, creep_distance_max,
1380 CREEP_DISTANCE_HAS_DEFAULT,
1381 CREEP_DISTANCE_IS_DEFINED);
1382
1383 struct yac_param *root_param_array[] = {
1384 creep_distance_param
1385 };
1386 enum {
1387 ROOT_PARAM_ARRAY_SIZE =
1388 sizeof(root_param_array) / sizeof(root_param_array[0])
1389 };
1390
1391 return yac_param_struct_new(
1392 "creep", root_param_array, ROOT_PARAM_ARRAY_SIZE);
1393}
1394
1397 .copy = config_creep_copy,
1398 .compare = config_creep_compare,
1399 .get_pack_size = config_creep_get_pack_size,
1400 .pack = config_creep_pack,
1401 .get_type = config_creep_get_type,
1402 .generate = config_creep_generate,
1403 .get_param = config_creep_get_param
1404};
1405
1407 struct yac_interp_method_config_creep *config_creep =
1408 xmalloc(sizeof(*config_creep));
1410 config_creep->config = (struct yac_interp_method_creep_config){
1412 };
1413 return (struct yac_interp_method_config *)config_creep;
1414}
1415
1416// Unpacks a creep config from a buffer
1418 void *buffer, int buffer_size, int *position, MPI_Comm comm) {
1419 struct yac_interp_method_config_creep *creep_config =
1420 xmalloc(sizeof(*creep_config));
1423 MPI_Unpack(
1424 buffer, buffer_size, position, &creep_config->config.creep_distance, 1,
1425 MPI_INT, comm), comm);
1426 // set vtable pointer here if needed
1427 return (struct yac_interp_method_config *)creep_config;
1428}
#define YAC_ASSERT(exp, msg)
#define UNUSED(x)
Definition core.h:72
#define ENSURE_ARRAY_SIZE(arrayp, curr_array_size, req_size)
void yac_interp_grid_get_tgt_cell_neighbours(struct yac_interp_grid *interp_grid, size_t *tgt_cells, size_t count, size_t *neighbours)
enum yac_location yac_interp_grid_get_tgt_field_location(struct yac_interp_grid *interp_grid)
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)
void yac_interp_grid_determine_dist_tgt_owners(struct yac_interp_grid *interp_grid, size_t *tgt_indices, size_t count, int *owners)
void yac_interp_grid_get_tgt_vertex_neighbours(struct yac_interp_grid *interp_grid, size_t *vertices, size_t count, size_t **neigh_vertices, int *num_neighs_per_vertex)
struct yac_const_basic_grid_data * yac_interp_grid_get_basic_grid_data_tgt(struct yac_interp_grid *interp_grid)
void yac_interp_grid_tgt_global_to_local(struct yac_interp_grid *interp_grid, yac_int *tgt_global_ids, size_t count, size_t *tgt_local_ids)
yac_interpolation_list
@ YAC_CREEP
Creep-fill interpolation.
#define DEF_INTERP_METHOD_CONFIG_COMPARE_TYPE(TYPE)
#define DEF_INTERP_METHOD_CONFIG_TYPE(TYPE)
static void do_search_creep_2(struct yac_interp_grid *interp_grid, int const max_creep_distance, size_t *tgt_points, yac_int *tgt_global_ids, size_t count, int *interp_flag, struct yac_interp_weights *weights)
static int compare_tgt_request_global_id(const void *a, const void *b)
static void pack_result_stencil(struct result_stencil *stencil, void *buffer, int buffer_size, int *position, MPI_Datatype stencil_info_dt, MPI_Comm comm)
static struct result_stencils * unpack_result_stencils(size_t count, void *packed_data, size_t packed_data_size, MPI_Datatype stencil_info_dt, MPI_Comm comm)
static int compare_interp_result_stencil_local_id(const void *a, const void *b)
static int compare_stencil_info(const void *a, const void *b)
static MPI_Datatype yac_get_stencil_info_mpi_datatype(MPI_Comm comm)
static struct result_stencil * tgt_request_get_stencil(void *tgt_request)
static struct result_stencils * update_neigh_requests(struct comm_stuff comm, struct tgt_request *neigh_requests, size_t *request_count_, struct result_stencils *interp_stencils)
static int config_creep_compare(void const *a_, void const *b_)
static struct result_stencil * interp_result_get_stencil(void *interp_result)
static size_t config_creep_get_pack_size(struct yac_interp_method_config const *config, MPI_Comm comm)
static struct yac_param * config_creep_get_param(struct yac_interp_method_config const *config)
static void get_tgt_neigh_info_vertex(struct yac_interp_grid *interp_grid, size_t *tgt_local_ids, yac_int *tgt_global_ids, size_t count, size_t **neigh_local_ids_, yac_int **neigh_to_tgt_global_id_, size_t *total_num_neighbours_)
static struct result_stencils * exchange_interp_results(void *results, size_t result_count, size_t result_size, struct result_stencil *(*result_get_stencil)(void *), size_t *pack_order, int *ranks, struct comm_stuff comm)
static struct yac_interp_method_config_vtable yac_interp_method_config_vtable_creep
static void config_creep_pack(struct yac_interp_method_config const *config, void *buffer, int buffer_size, int *position, MPI_Comm comm)
static void free_comm_stuff(struct comm_stuff comm)
static struct yac_interp_method_config * config_creep_copy(const struct yac_interp_method_config *config)
static struct comm_stuff init_comm_stuff(struct yac_interp_grid *interp_grid)
static int compare_result_stencil_global_id(const void *a, const void *b)
static int compare_interp_result_stencil(const void *a, const void *b)
static void get_tgt_neigh_info(struct yac_interp_grid *interp_grid, size_t *tgt_local_ids, yac_int *tgt_global_ids, size_t count, size_t **neigh_local_ids_, yac_int **neigh_global_ids_, yac_int **neigh_to_tgt_global_id_, size_t *total_num_neighbours_)
static void get_initial_results(struct yac_interp_grid *interp_grid, struct comm_stuff comm, struct yac_interp_weights *interp_weights, struct interp_result **interp_results, size_t *result_count)
static void extract_interp_info(struct yac_interp_grid *interp_grid, struct interp_result *interp_results, size_t result_count, struct remote_points *interp_tgt_remote_points, size_t **num_stencils_per_tgt_, size_t **stencil_indices_, int **stencil_ranks_, double **w_)
struct interp_method * yac_interp_method_creep_new(int creep_distance)
static struct result_stencil copy_result_stencil_multi(struct result_stencil *neigh_stencils, size_t *stencil_indices, size_t count, yac_int global_id, double weight)
static void pack_result_stencils(void *results, size_t result_count, size_t result_size, struct result_stencil *(*get_stencil)(void *), size_t *pack_order, void **pack_data, int *pack_sizes, MPI_Datatype stencil_info_dt, MPI_Comm comm)
static size_t do_search_creep(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 get_tgt_neigh_info_cell(struct yac_interp_grid *interp_grid, size_t *tgt_local_ids, yac_int *tgt_global_ids, size_t count, size_t **neigh_local_ids_, yac_int **neigh_to_tgt_global_id_, size_t *total_num_neighbours_)
static struct interp_method * config_creep_generate(struct yac_interp_method_config const *config)
static struct interp_result * init_interp_results(size_t *tgt_local_ids, yac_int *tgt_global_ids, size_t count)
static int compare_yac_int(const void *a, const void *b)
static size_t match_neigh_answers_with_tgts(struct result_stencils *neigh_answer, yac_int *neigh_global_ids, yac_int *neigh_to_tgt_global_id, size_t *stencil_indices, size_t *num_neighbours_, struct interp_result *interp_results, size_t *num_open_tgt_)
struct yac_interp_method_config * yac_interp_method_config_creep_unpack(void *buffer, int buffer_size, int *position, MPI_Comm comm)
Unpacks a creep interpolation method configuration from a buffer.
static void unpack_result_stencil(struct result_stencil *stencil, void *buffer, int buffer_size, int *position, MPI_Datatype stencil_info_dt, MPI_Comm comm, struct stencil_info **stencil_info_buffer, size_t *stencil_info_buffer_array_size, size_t *stencil_info_buffer_size)
static enum yac_interpolation_list config_creep_get_type()
static void config_creep_delete(struct yac_interp_method_config *config)
static void get_result_stencil_pack_sizes(void *results, size_t result_count, size_t result_size, struct result_stencil *(*get_stencil)(void *), size_t *pack_order, int *pack_sizes, MPI_Datatype stencil_info_dt, MPI_Comm comm)
static struct interp_method_vtable interp_method_creep_vtable
static void send_neigh_request(struct yac_interp_grid *interp_grid, struct comm_stuff comm, size_t *neigh_local_ids, yac_int *neigh_global_ids, size_t num_neighbours, struct tgt_request **neigh_requests_, size_t *request_count_)
static void delete_creep(struct interp_method *method)
static struct result_stencils * relocate_interp_results(struct yac_interp_grid *interp_grid, struct comm_stuff comm, struct interp_result *interp_results, size_t result_count)
static int compare_tgt_request_stencil_count(const void *a, const void *b)
static int compare_interp_result_global_id(const void *a, const void *b)
struct yac_interp_method_config * yac_interp_method_config_default_creep_new(void)
Creates a creep-fill interpolation method configuration with default parameters.
#define YAC_INTERP_CREEP_DISTANCE_DEFAULT
void yac_interp_weights_wcopy_weights(struct yac_interp_weights *weights, struct remote_points *tgts, size_t *num_stencils_per_tgt, size_t *stencil_indices, int *stencil_ranks, double *w)
yac_int * yac_interp_weights_get_interp_tgt(struct yac_interp_weights *weights)
size_t yac_interp_weights_get_interp_count(struct yac_interp_weights *weights)
yac_location
Definition location.h:12
@ YAC_LOC_CORNER
Definition location.h:15
@ YAC_LOC_CELL
Definition location.h:14
struct yac_param * yac_param_int_new(const char *name, int *value_ptr, int default_value, int value_min, int value_max, int has_default, int is_defined)
Create an int parameter.
Definition param_int.c:157
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 xrealloc(ptr, size)
Definition ppm_xfuncs.h:67
#define xmalloc(size)
Definition ppm_xfuncs.h:66
MPI_Datatype stencil_info_dt
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)
struct result_stencil stencil
structure containing the information (global id and location)
struct remote_point * data
union result_stencil::@26 data
struct stencil_info single * multi
struct stencil_info stencil_info_buffer[]
struct result_stencil * stencils
struct result_stencil stencil
const const_int_pointer num_vertices_per_cell
Concrete implementation of yac_interp_method_config for the creep method.
struct yac_interp_method_config_vtable const * vtable
‍vtable pointer, must be first entry
struct yac_interp_method_creep_config config
‍method-specific configuration
void(* delete)(struct yac_interp_method_config *config)
static struct yac_interp_method_config * config
double * buffer
double * send_buffer
double * recv_buffer
void yac_quicksort_index_yac_int_size_t(yac_int *a, size_t n, size_t *idx)
void yac_quicksort_index_int_yac_int(int *a, size_t n, yac_int *idx)
void yac_quicksort_index_yac_int_yac_int_size_t(yac_int *a, size_t n, yac_int *b, size_t *c)
void yac_quicksort_index_size_t_yac_int(size_t *a, size_t n, yac_int *idx)
void yac_quicksort_index_int_size_t(int *a, size_t n, size_t *idx)
void yac_quicksort_index_yac_int_yac_int(yac_int *a, size_t n, yac_int *idx)
void yac_quicksort_index_int_size_t_yac_int(int *a, size_t n, size_t *b, yac_int *c)
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:30
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:578
void yac_free_comm_buffers(size_t *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls)
Definition yac_mpi.c:634
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:603
MPI_Datatype yac_create_resized(MPI_Datatype dt, size_t new_size, MPI_Comm comm)
Definition yac_mpi.c:557
#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