YAC 3.7.1
Yet Another Coupler
Loading...
Searching...
No Matches
interp_method_nnn.c
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#ifdef HAVE_CONFIG_H
6// Get the definition of the 'restrict' keyword.
7#include "config.h"
8#endif
9
10#include <string.h>
11
13#include "interp_method_nnn.h"
15#include "yac_mpi_internal.h"
16
17static size_t do_search_nnn(struct interp_method * method,
18 struct yac_interp_grid * interp_grid,
19 size_t * tgt_points, size_t count,
20 struct yac_interp_weights * weights,
21 int * interpolation_complete);
22static size_t do_search_1nn(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 size_t do_search_zero(struct interp_method * method,
28 struct yac_interp_grid * interp_grid,
29 size_t * tgt_points, size_t count,
30 struct yac_interp_weights * weights,
31 int * interpolation_complete);
32static void delete_nnn(struct interp_method * method);
33
34static struct interp_method_vtable
44
46
49 double[3], yac_coordinate_pointer, size_t const, double *, double const);
50 size_t n;
52 double scale;
53};
54
56
59 struct yac_interp_weights * weights, struct remote_points * tgts,
60 struct remote_point * srcs);
62};
63
68
70 double tgt_coord[3], yac_coordinate_pointer src_coords, size_t const n,
71 double * weights, double const dummy) {
72
73 UNUSED(tgt_coord);
74 UNUSED(src_coords);
75 UNUSED(dummy);
76
77 double weight = 1.0 / (double)n;
78 for (size_t i = 0; i < n; ++i) weights[i] = weight;
79}
80
82 double tgt_coord[3], yac_coordinate_pointer src_coords, size_t const n,
83 double * weights, double const dummy) {
84
85 UNUSED(dummy);
86
87 for (size_t i = 0; i < n; ++i) {
88
89 double distance = get_vector_angle(tgt_coord, (double*)(src_coords[i]));
90
91 // if the target and source point are nearly identical
92 if (distance < yac_angle_tol) {
93 for (size_t j = 0; j < n; ++j) weights[j] = 0.0;
94 weights[i] = 1.0;
95 return;
96 }
97
98 weights[i] = 1.0 / distance;
99 }
100
101 // compute scaling factor for the weights
102 double inv_distance_sum = 0.0;
103 for (size_t i = 0; i < n; ++i) inv_distance_sum += weights[i];
104 double scale = 1.0 / inv_distance_sum;
105
106 for (size_t i = 0; i < n; ++i) weights[i] *= scale;
107}
108
110 double tgt_coord[3], yac_coordinate_pointer src_coords, size_t const n,
111 double * weights, double const gauss_scale) {
112
113 for (size_t i = 0; i < n; ++i) {
114
115 double distance = get_vector_angle(tgt_coord, src_coords[i]);
116
117 weights[i] = distance * distance;
118 }
119
120 // a) compute sum of source point distances
121 double src_distances_sum = 0.0;
122 double src_distances_count = 0.5 * (double)(n * n - n);
123 for (size_t i = 0; i < n-1; ++i)
124 for (size_t j = i + 1; j < n; ++j)
125 src_distances_sum += get_vector_angle(src_coords[i], src_coords[j]);
126
128 (n == 1) || (src_distances_sum > yac_angle_tol),
129 "ERROR(compute_weights_gauss): "
130 "all %zu source points for target point (%.3lf; %.3lf; %.3lf) "
131 "are nearly identical (%.3lf; %.3lf; %.3lf)",
132 n, tgt_coord[0], tgt_coord[1], tgt_coord[2],
133 src_coords[0][0], src_coords[0][1], src_coords[0][2]);
134
135 // b) C = -1 / (c * d_mean^2)
136 double src_distances_mean = src_distances_sum / src_distances_count;
137 double scale = -1.0 / (gauss_scale * src_distances_mean * src_distances_mean);
138
139 // c) calculate weights
140 // w_i = e^(-d_i^2/(c*s^2))
141 // w_i = e^(C * d_i^2)
142 double weights_sum = 0.0;
143 for (size_t i = 0; i < n; ++i) {
144 weights[i] = exp(scale * weights[i]);
145 weights_sum += weights[i];
146 }
147
148 // If the sum of the weights is very low, which can happen in case
149 // the target point is very far away from the group of source points.
150 if (fabs(weights_sum) < 1e-9) {
151
152 // Due to limited accuracy the exact contribution of each source
153 // point cannot be computed. Therefore, the normalisation would
154 // generate NaN's. Hence we fall back to inverse distance weighted
155 // averge for this target point.
157 tgt_coord, src_coords, n, weights, gauss_scale);
158 return;
159 }
160
161 // d) scale weights such that SUM(w_i) == 1
162 for (size_t i = 0; i < n; ++i) weights[i] /= weights_sum;
163}
164
165static void inverse(double * A, size_t n) {
166
167// LAPACKE_dsytrf_work and LAPACKE_dsytri might not be available (see yac_lapack_interface.h).
168#ifdef YAC_LAPACK_NO_DSYTR
169 lapack_int ipiv[n+1];
170 double work[n*n];
171
172 for (size_t i = 0; i < n+1; ++i) ipiv[i] = 0;
173 for (size_t i = 0; i < n*n; ++i) work[i] = 0;
174
176 !LAPACKE_dgetrf(
177 LAPACK_COL_MAJOR, (lapack_int) n, (lapack_int) n,
178 A, (lapack_int) n, ipiv), "internal ERROR: dgetrf")
179
181 !LAPACKE_dgetri_work(
182 LAPACK_COL_MAJOR, (lapack_int) n, A, (lapack_int) n,
183 ipiv, work, (lapack_int) (n * n)), "internal ERROR: dgetri")
184#else
185 lapack_int ipiv[n];
186 double work[n];
187
189 !LAPACKE_dsytrf_work(
190 LAPACK_COL_MAJOR, 'L', (lapack_int) n , A,
191 (lapack_int) n, ipiv, work, (lapack_int) n), "internal ERROR: dsytrf")
192
194 !LAPACKE_dsytri_work(
195 LAPACK_COL_MAJOR, 'L', (lapack_int) n , A,
196 (lapack_int) n, ipiv, work), "internal ERROR: dsytri")
197
198 for (size_t i = 0; i < n; ++i)
199 for (size_t j = i + 1; j < n; ++j)
200 A[j*n+i] = A[i*n+j];
201#endif
202}
203
205 double tgt_coord[3], yac_coordinate_pointer src_coords, size_t const n,
206 double * weights, double const rbf_scale) {
207
208 double A[n][n];
209 double a[n];
210
211 double sum_d = 0.0, scale_d = 1.0;
212
213 // compute distance matrix for all found source points
214 for (size_t i = 0; i < n; ++i) A[i][i] = 0.0;
215 for (size_t i = 0; i < n - 1; ++i) {
216 for (size_t j = i + 1; j < n; ++j) {
217 double d = get_vector_angle(src_coords[i], src_coords[j]);
218 A[i][j] = d;
219 A[j][i] = d;
220 sum_d += d;
221 }
222 }
223
224 // compute and apply scale factor for distance matrix
225 if (sum_d > 0.0)
226 scale_d = ((double)((n - 1) * n)) / (2.0 * sum_d);
227 scale_d /= rbf_scale;
228
229 double sq_scale_d = scale_d * scale_d;
230
231 // compute matrix A[n][n]
232 // with A = rbf(A)
233 // rbf(a) => Radial basis function
234 for (size_t i = 0; i < n; ++i) {
235 for (size_t j = 0; j < n; ++j) {
236 double d = A[i][j];
237 // gauß rbf kernel
238 A[i][j] = exp(-1.0 * d * d * sq_scale_d);
239 }
240 }
241
242 // compute inverse of A
243 inverse(&A[0][0], n);
244
245 // compute a[NUM_NEIGH]
246 // with a_i = rbf(d(x_i, y))
247 // x => vector containing the coordinates of the
248 // n nearest neighbours of the current
249 // target point
250 // y => coordinates of target point
251 // d(a, b) => great circle distance between point a and b
252 // rbf(a) => Radial basis function
253 for (size_t i = 0; i < n; ++i) {
254 double d = get_vector_angle(tgt_coord, src_coords[i]);
255 // gauß rbf kernel
256 a[i] = exp(-1.0 * d * d * sq_scale_d);
257 }
258
259 // compute weights
260 // with w_i = SUM(A_inv[i][j]*a[j]) // j = 0..n-1
261 for (size_t i = 0; i < n; ++i) {
262 weights[i] = 0.0;
263 for (size_t j = 0; j < n; ++j) weights[i] += A[i][j] * a[j];
264 }
265}
266
267static size_t do_search_nnn (struct interp_method * method,
268 struct yac_interp_grid * interp_grid,
269 size_t * tgt_points, size_t count,
270 struct yac_interp_weights * weights,
271 int * interpolation_complete) {
272
273 if (*interpolation_complete) return 0;
274
275 struct interp_method_nnn * method_nnn = (struct interp_method_nnn *)method;
276
278 yac_interp_grid_get_num_src_fields(interp_grid) == 1,
279 "ERROR(do_search_nnn): invalid number of source fields")
280
281 // get coordinates of target points
282 yac_coordinate_pointer tgt_coords = xmalloc(count * sizeof(*tgt_coords));
284 interp_grid, tgt_points, count, tgt_coords);
285
286 size_t n = method_nnn->n;
287
288 size_t * size_t_buffer = xmalloc((2 * n + 1) * count * sizeof(*size_t_buffer));
289 size_t * src_points = size_t_buffer;
290 size_t * src_points_reorder = size_t_buffer + n * count;
291 size_t * reorder_idx = size_t_buffer + 2 * n * count;
292 int * fail_flag = xmalloc(count * sizeof(*fail_flag));
293
294 // search for the n nearest source points
296 interp_grid, tgt_coords, count, n, src_points,
297 method_nnn->max_search_distance);
298
299 size_t result_count = 0;
300
301 // check for which cells the search was successful
302 for (size_t i = 0, k = 0; i < count; ++i) {
303 int flag = 0;
304 for (size_t j = 0; j < n; ++j, ++k) flag |= src_points[k] == SIZE_MAX;
305 result_count += !(size_t)(fail_flag[i] = flag);
306 reorder_idx[i] = i;
307 }
308
309 // sort target points, for which the search was successful to the beginning of
310 // the array
311 for (size_t i = 0; i < count; ++i) reorder_idx[i] = i;
312 yac_quicksort_index_int_size_t(fail_flag, count, reorder_idx);
313 free(fail_flag);
314
315 void (*compute_weights)(
316 double[3], yac_coordinate_pointer, size_t, double *, double const) =
317 method_nnn->compute_weights;
318 double scale = method_nnn->scale;
319 double * w = xmalloc(n * result_count * sizeof(*w));
320 size_t * num_weights_per_tgt =
321 xmalloc(result_count * sizeof(*num_weights_per_tgt));
322 yac_coordinate_pointer src_coord_buffer = xmalloc(n * sizeof(*src_coord_buffer));
323 yac_const_coordinate_pointer src_field_coordinates =
325
326 // compute the weights
327 for (size_t i = 0; i < result_count; ++i) {
328 size_t curr_reorder_idx = reorder_idx[i];
329 for (size_t j = 0; j < n; ++j) {
330 size_t curr_src_point = src_points[curr_reorder_idx * n + j];
331 memcpy(src_coord_buffer[j], src_field_coordinates[curr_src_point],
332 3 * sizeof(double));
333 src_points_reorder[i * n + j] = curr_src_point;
334 }
335
337 tgt_coords[curr_reorder_idx], src_coord_buffer, n, w + i * n, scale);
338 num_weights_per_tgt[i] = n;
339 }
340
341 // move the non-interpolated target points to the end
342 for (size_t i = 0; i < count; ++i) src_points[reorder_idx[i]] = i;
343 yac_quicksort_index_size_t_size_t(src_points, count, tgt_points);
344
345 free(src_coord_buffer);
346 free(tgt_coords);
347
348 struct remote_point * srcs =
350 interp_grid, 0, src_points_reorder, result_count * n);
351
352 struct remote_points tgts = {
353 .data =
355 interp_grid, tgt_points, result_count),
356 .count = result_count};
357
358 // store weights
360 weights, &tgts, num_weights_per_tgt, srcs, w);
361
362 free(size_t_buffer);
363 free(tgts.data);
364 free(srcs);
365 free(w);
366 free(num_weights_per_tgt);
367
368 return result_count;
369}
370
371static size_t do_search_1nn(struct interp_method * method,
372 struct yac_interp_grid * interp_grid,
373 size_t * tgt_points, size_t count,
374 struct yac_interp_weights * weights,
375 int * interpolation_complete) {
376
377 if (*interpolation_complete) return 0;
378
380 yac_interp_grid_get_num_src_fields(interp_grid) == 1,
381 "ERROR(do_search_1nn): invalid number of source fields")
382
383 // get coordinates of target points
384 yac_coordinate_pointer tgt_coords = xmalloc(count * sizeof(*tgt_coords));
386 interp_grid, tgt_points, count, tgt_coords);
387
388 size_t * src_points = xmalloc(count * sizeof(*src_points));
389
390 // search for the nearest source points
392 interp_grid, tgt_coords, count, 1, src_points,
393 ((struct interp_method_1nn *)method)->max_search_distance);
394
395 // move the non-interpolated target points to the end
396 // (source points == SIZE_MAX if no source point was found)
397 yac_quicksort_index_size_t_size_t(src_points, count, tgt_points);
398 free(tgt_coords);
399
400 // count the number of target points for which we found a source point
401 size_t result_count = 0;
402 for (; (result_count < count) && (src_points[result_count] != SIZE_MAX);
403 ++result_count);
404
405 struct remote_point * srcs =
407 interp_grid, 0, src_points, result_count);
408
409 struct remote_points tgts = {
410 .data =
412 interp_grid, tgt_points, result_count),
413 .count = result_count};
414
415 // store weights
416 ((struct interp_method_1nn *)method)->interp_weights_add(
417 weights, &tgts, srcs);
418
419 free(src_points);
420 free(tgts.data);
421 free(srcs);
422
423 return result_count;
424}
425
427 struct yac_interp_weights * weights, struct remote_points * tgts,
428 struct remote_point src) {
429
430 size_t * num_src_per_tgt = xmalloc(tgts->count * sizeof(*num_src_per_tgt));
431 double * w = xmalloc(tgts->count * sizeof(*w));
432 struct remote_point * srcs = xmalloc(tgts->count * sizeof(*srcs));
433
434 for (size_t i = 0; i < tgts->count; ++i) {
435 num_src_per_tgt[i] = 1;
436 w[i] = 0.0;
437 srcs[i] = src;
438 }
439
440 yac_interp_weights_add_wsum(weights, tgts, num_src_per_tgt, srcs, w);
441
442 free(srcs);
443 free(w);
444 free(num_src_per_tgt);
445}
446
447static size_t do_search_zero(struct interp_method * method,
448 struct yac_interp_grid * interp_grid,
449 size_t * tgt_points, size_t count,
450 struct yac_interp_weights * weights,
451 int * interpolation_complete) {
452
453 if (*interpolation_complete) return 0;
454
456 yac_interp_grid_get_num_src_fields(interp_grid) == 1,
457 "ERROR(do_search_zero): invalid number of source fields")
458
459 UNUSED(method);
460
461 // get global ids of all valid local source points
462 size_t * src_points, src_count;
463 yac_interp_grid_get_src_points(interp_grid, 0, &src_points, &src_count);
464 yac_int * src_global_ids = xmalloc(src_count * sizeof(*src_global_ids));
465 if (src_count > 0)
467 interp_grid, src_points, src_count, 0, src_global_ids);
468 free(src_points);
469
470 // determine smallest global id of all unmasked source points in the
471 // local data
472 yac_int min_src_global_id = XT_INT_MAX;
473 for (size_t i = 0; i < src_count; ++i)
474 if (src_global_ids[i] < min_src_global_id)
475 min_src_global_id = src_global_ids[i];
476 free(src_global_ids);
477
478 // determine smallest global id of all unmasked source points in the
479 // global data
480 MPI_Comm comm = yac_interp_grid_get_MPI_Comm(interp_grid);
482 MPI_Allreduce(
483 MPI_IN_PLACE, &min_src_global_id, 1, yac_int_dt, MPI_MIN, comm), comm);
485 min_src_global_id != XT_INT_MAX,
486 "ERROR(do_search_zero): unable to find unmasked source points");
487
488 // get the local id of the source point with the smallest global ids
489 // (add it to the local data if it does not yet exist there)
490 size_t min_src_local_id;
492 interp_grid, 0, &min_src_global_id, 1, &min_src_local_id);
493
494 struct remote_point * src =
496 interp_grid, 0, &min_src_local_id, 1);
497
498 struct remote_points tgts = {
499 .data =
501 interp_grid, tgt_points, count),
502 .count = count};
503
504 // store weights
505 interp_weights_add_zero(weights, &tgts, *src);
506
507 free(tgts.data);
508 free(src);
509
510 return count;
511}
512
514
516 (config.max_search_distance >= 0.0) &&
517 (config.max_search_distance <= M_PI),
518 "ERROR(yac_interp_method_nnn_new): "
519 "unsupported value for max_search_distance (%lf), has to be in [0.0,PI]",
520 config.max_search_distance)
521
522 if (config.type == YAC_INTERP_NNN_ZERO) {
523
525 config.n == 1,
526 "ERROR(yac_interp_method_nnn_new): n != 1 does not make sense for zero")
528 config.max_search_distance == 0.0, "ERROR(yac_interp_method_nnn_new): "
529 "max_search_distance != 0.0 does not make sense for zero")
530
531 struct interp_method_zero * method = xmalloc(1 * sizeof(*method));
533 return (struct interp_method*)method;
534 }
535
536 double max_search_distance =
537 (config.max_search_distance == 0.0)?M_PI:config.max_search_distance;
538
539 if (config.n == 1) {
540
541 struct interp_method_1nn * method = xmalloc(1 * sizeof(*method));
545 return (struct interp_method*)method;
546 }
547
548 struct interp_method_nnn * method = xmalloc(1 * sizeof(*method));
549
551
553 method->n = config.n;
554
556 (config.type == YAC_INTERP_NNN_AVG) ||
557 (config.type == YAC_INTERP_NNN_DIST) ||
558 (config.type == YAC_INTERP_NNN_GAUSS) ||
559 (config.type == YAC_INTERP_NNN_RBF),
560 "ERROR(yac_interp_method_nnn_new): invalid NNN type")
561
562 switch (config.type) {
563 case(YAC_INTERP_NNN_AVG):
565 config.n >= 1,
566 "ERROR(yac_interp_method_nnn_new): n needs to be at least 1 for "
567 "distance weighted average")
568 method->scale = 0.0;
570 break;
573 config.n >= 2,
574 "ERROR(yac_interp_method_nnn_new): n needs to be at least 2 for "
575 "distance weighted average")
576 method->scale = 0.0;
578 break;
581 config.n >= 2,
582 "ERROR(yac_interp_method_nnn_new): n needs to be at least 2 for gauss")
583 method->scale = config.data.gauss_scale;
585 break;
586 default:
587 case(YAC_INTERP_NNN_RBF):
589 config.n >= 2,
590 "ERROR(yac_interp_method_nnn_new): n needs to be at least 2 for RBF")
591 method->scale = config.data.rbf_scale;
593 break;
594 };
595
596 return (struct interp_method*)method;
597}
598
599static void delete_nnn(struct interp_method * method) {
600 free(method);
601}
#define YAC_ASSERT(exp, msg)
#define UNUSED(x)
Definition core.h:73
#define yac_angle_tol
Definition geometry.h:26
static double get_vector_angle(double const a[3], double const b[3])
Definition geometry.h:329
size_t yac_interp_grid_get_num_src_fields(struct yac_interp_grid *interp_grid)
MPI_Comm yac_interp_grid_get_MPI_Comm(struct yac_interp_grid *interp_grid)
struct remote_point * yac_interp_grid_get_tgt_remote_points(struct yac_interp_grid *interp_grid, size_t *tgt_points, size_t count)
void yac_interp_grid_get_src_points(struct yac_interp_grid *interp_grid, size_t src_field_idx, size_t **src_indices, size_t *count)
Definition interp_grid.c:87
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_do_nnn_search_src(struct yac_interp_grid *interp_grid, yac_coordinate_pointer search_coords, size_t count, size_t n, size_t *src_points, double max_search_distance)
yac_const_coordinate_pointer yac_interp_grid_get_src_field_coords(struct yac_interp_grid *interp_grid, size_t src_field_idx)
void yac_interp_grid_get_tgt_coordinates(struct yac_interp_grid *interp_grid, size_t *tgt_points, size_t count, yac_coordinate_pointer tgt_coordinates)
void yac_interp_grid_get_src_global_ids(struct yac_interp_grid *interp_grid, size_t *src_points, size_t count, size_t src_field_idx, yac_int *src_global_ids)
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)
static void compute_weights(struct tgt_point_search_data *tgt_point_data, size_t num_tgt_points, struct edge_interp_data *edge_data, size_t num_edges, struct triangle_interp_data *triangle_data, size_t num_triangles, struct weight_vector_data **weights, size_t **num_weights_per_tgt, size_t *total_num_weights)
static void compute_weights_gauss(double tgt_coord[3], yac_coordinate_pointer src_coords, size_t const n, double *weights, double const gauss_scale)
static size_t do_search_nnn(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 compute_weights_rbf(double tgt_coord[3], yac_coordinate_pointer src_coords, size_t const n, double *weights, double const rbf_scale)
static void delete_nnn(struct interp_method *method)
static size_t do_search_1nn(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 struct interp_method_vtable interp_method_1nn_vtable
static void compute_weights_dist(double tgt_coord[3], yac_coordinate_pointer src_coords, size_t const n, double *weights, double const dummy)
static void interp_weights_add_zero(struct yac_interp_weights *weights, struct remote_points *tgts, struct remote_point src)
static struct interp_method_vtable interp_method_zero_vtable
static void inverse(double *A, size_t n)
static size_t do_search_zero(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 struct interp_method_vtable interp_method_nnn_vtable
struct interp_method * yac_interp_method_nnn_new(struct yac_nnn_config config)
static void compute_weights_avg(double tgt_coord[3], yac_coordinate_pointer src_coords, size_t const n, double *weights, double const dummy)
@ YAC_INTERP_NNN_GAUSS
distance with Gauss weights of n source points
@ YAC_INTERP_NNN_RBF
radial basis functions
@ YAC_INTERP_NNN_AVG
average of n source points
@ YAC_INTERP_NNN_DIST
distance weighted average of n source points
@ YAC_INTERP_NNN_ZERO
all weights are set to zero
void yac_interp_weights_add_wsum(struct yac_interp_weights *weights, struct remote_points *tgts, size_t *num_src_per_tgt, struct remote_point *srcs, double *w)
void yac_interp_weights_add_direct(struct yac_interp_weights *weights, struct remote_points *tgts, struct remote_point *srcs)
Definition __init__.py:1
#define xmalloc(size)
Definition ppm_xfuncs.h:66
void(* interp_weights_add)(struct yac_interp_weights *weights, struct remote_points *tgts, struct remote_point *srcs)
struct interp_method_vtable * vtable
void(* compute_weights)(double[3], yac_coordinate_pointer, size_t const, double *, double const)
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 interp_method_vtable * vtable
information (global id and location) about a point that
structure containing the information (global id and location)
struct remote_point * data
union yac_nnn_config::@28 data
enum yac_interp_nnn_weight_type type
void yac_quicksort_index_int_size_t(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)
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:19
#define yac_mpi_call(call, comm)
Xt_int yac_int
Definition yac_types.h:15
double const (* yac_const_coordinate_pointer)[3]
Definition yac_types.h:20
#define yac_int_dt
Definition yac_types.h:16
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:19