5#ifndef INTERPOLATION_UTILS_H
6#define INTERPOLATION_UTILS_H
123#define NO_SCALING(RESULT) (RESULT)
125#define MULT(RESULT) ((RESULT) * scale_factor)
127#define ADD(RESULT) ((RESULT) + scale_summand)
129#define MULT_ADD(RESULT) ((RESULT) * scale_factor + scale_summand)
135#define FRAC_MASK_TOL (1e-12)
172#define COMPUTE_FIELD_STENCIL_FRAC_WGT(TGT_POS, WEIGHT, SCALE) \
174 for (size_t l = 0; l < collection_size; ++l) { \
175 double const * restrict * curr_local_field_data = \
176 src_fields?src_fields[l]:NULL; \
177 double const * restrict * curr_local_frac_mask_data = \
178 src_frac_masks?src_frac_masks[l]:NULL; \
179 double const * restrict curr_remote_field_data = \
180 remote_src_fields[l * num_src_fields]; \
181 double const * restrict curr_remote_frac_mask_data = \
182 remote_src_frac_masks[l * num_src_fields]; \
183 double * restrict curr_tgt_field = tgt_field[l]; \
187 for (size_t i = 0; i < tgt_count; ++i) { \
188 double result = 0.0; \
189 double frac_weight_sum = 0.0; \
190 double weight_sum = 0.0; \
191 size_t const k_bound = prefix_num_src_per_tgt[i+1]; \
192 for (size_t k = prefix_num_src_per_tgt[i]; k < k_bound; ++k) { \
193 double const * restrict frac_mask_data; \
194 double const * restrict src_field_data; \
195 if (src_field_idx[k] == SIZE_MAX) { \
196 frac_mask_data = curr_remote_frac_mask_data; \
197 src_field_data = curr_remote_field_data; \
200 curr_local_frac_mask_data[src_field_idx[k]]; \
201 src_field_data = curr_local_field_data[src_field_idx[k]]; \
203 result += src_field_data[src_idx[k]] * (WEIGHT); \
204 frac_weight_sum += frac_mask_data[src_idx[k]] * (WEIGHT); \
205 weight_sum += (WEIGHT); \
207 curr_tgt_field[(TGT_POS)] = \
208 (fabs(frac_weight_sum) > FRAC_MASK_TOL)? \
209 (SCALE(result / frac_weight_sum * weight_sum)): \
210 frac_mask_fallback_value; \
240#define COMPUTE_FIELD_STENCIL_FRAC_NOWGT(TGT_POS, SCALE) \
242 for (size_t l = 0; l < collection_size; ++l) { \
243 double const * restrict * curr_local_field_data = \
244 src_fields?src_fields[l]:NULL; \
245 double const * restrict * curr_local_frac_mask_data = \
246 src_frac_masks?src_frac_masks[l]:NULL; \
247 double const * restrict curr_remote_field_data = \
248 remote_src_fields[l * num_src_fields]; \
249 double const * restrict curr_remote_frac_mask_data = \
250 remote_src_frac_masks[l * num_src_fields]; \
251 double * restrict curr_tgt_field = tgt_field[l]; \
255 for (size_t i = 0; i < tgt_count; ++i) { \
256 double result = 0.0; \
257 double frac_weight_sum = 0.0; \
258 size_t const k_start = prefix_num_src_per_tgt[i]; \
259 size_t const k_bound = prefix_num_src_per_tgt[i+1]; \
260 for (size_t k = k_start; k < k_bound; ++k) { \
261 double const * restrict frac_mask_data; \
262 double const * restrict src_field_data; \
263 if (src_field_idx[k] == SIZE_MAX) { \
264 frac_mask_data = curr_remote_frac_mask_data; \
265 src_field_data = curr_remote_field_data; \
268 curr_local_frac_mask_data[src_field_idx[k]]; \
269 src_field_data = curr_local_field_data[src_field_idx[k]]; \
271 result += src_field_data[src_idx[k]]; \
272 frac_weight_sum += frac_mask_data[src_idx[k]]; \
274 double const weight_sum = (double)(k_bound - k_start); \
275 curr_tgt_field[(TGT_POS)] = \
276 (fabs(frac_weight_sum) > FRAC_MASK_TOL)? \
277 (SCALE(result / frac_weight_sum * weight_sum)): \
278 frac_mask_fallback_value; \
301#define COMPUTE_FIELD_STENCIL_NOFRAC_(TGT_POS, WEIGHT, SCALE) \
303 for (size_t l = 0; l < collection_size; ++l) { \
304 double const * restrict * curr_local_field_data = \
305 src_fields?src_fields[l]:NULL; \
306 double const * restrict curr_remote_field_data = \
307 remote_src_fields[l * num_src_fields]; \
308 double * restrict curr_tgt_field = tgt_field[l]; \
312 for (size_t i = 0; i < tgt_count; ++i) { \
313 double result = 0.0; \
314 size_t const k_bound = prefix_num_src_per_tgt[i+1]; \
315 for (size_t k = prefix_num_src_per_tgt[i]; k < k_bound; ++k) { \
316 double const * restrict src_field_data; \
317 if (src_field_idx[k] == SIZE_MAX) { \
318 src_field_data = curr_remote_field_data; \
320 src_field_data = curr_local_field_data[src_field_idx[k]]; \
322 result += src_field_data[src_idx[k]] * (WEIGHT); \
324 curr_tgt_field[(TGT_POS)] = SCALE(result); \
350#define COMPUTE_FIELD_DIRECT_FRAC(SCALE) \
352 for (size_t i = 0; i < collection_size; ++i) { \
353 for (size_t j = 0; j < num_src_fields; ++j) { \
354 memcpy(tgt_field[i * num_src_fields + j], \
355 src_fields[i][j], tgt_buffer_sizes[j]); \
356 size_t const tgt_count = \
357 tgt_buffer_sizes[j] / sizeof(***src_fields); \
361 for (size_t k = 0; k < tgt_count; ++k) { \
362 if (fabs(src_frac_masks[i][j][k]) > FRAC_MASK_TOL) \
363 tgt_field[i * num_src_fields + j][k] = \
365 tgt_field[i * num_src_fields + j][k] / \
366 src_frac_masks[i][j][k]); \
368 tgt_field[i * num_src_fields + j][k] = \
369 frac_mask_fallback_value; \
388#define COMPUTE_FIELD_DIRECT_NOFRAC(SCALE) \
390 for (size_t i = 0; i < collection_size; ++i) { \
391 for (size_t j = 0; j < num_src_fields; ++j) { \
392 memcpy(tgt_field[i * num_src_fields + j], \
393 src_fields[i][j], tgt_buffer_sizes[j]); \
394 size_t const tgt_count = \
395 tgt_buffer_sizes[j] / sizeof(***src_fields); \
399 for (size_t k = 0; k < tgt_count; ++k) \
400 tgt_field[i * num_src_fields + j][k] = \
401 SCALE(tgt_field[i * num_src_fields + j][k]); \
417#define COMPUTE_FIELD_STENCIL_FRAC(SCALE) \
419 if (weights != NULL) { \
420 if (tgt_pos != NULL) \
421 COMPUTE_FIELD_STENCIL_FRAC_WGT(tgt_pos[i], weights[k], SCALE) \
423 COMPUTE_FIELD_STENCIL_FRAC_WGT(i, weights[k], SCALE) \
425 if (tgt_pos != NULL) \
426 COMPUTE_FIELD_STENCIL_FRAC_NOWGT(tgt_pos[i], SCALE) \
428 COMPUTE_FIELD_STENCIL_FRAC_NOWGT(i, SCALE) \
438#define COMPUTE_FIELD_STENCIL_NOFRAC(SCALE) \
440 if (weights != NULL) { \
441 if (tgt_pos != NULL) \
442 COMPUTE_FIELD_STENCIL_NOFRAC_(tgt_pos[i], weights[k], SCALE) \
444 COMPUTE_FIELD_STENCIL_NOFRAC_(i, weights[k], SCALE) \
446 if (tgt_pos != NULL) \
447 COMPUTE_FIELD_STENCIL_NOFRAC_(tgt_pos[i], 1.0, SCALE) \
449 COMPUTE_FIELD_STENCIL_NOFRAC_(i, 1.0, SCALE) \
461#define COMPUTE_FIELD(COMPUTE_FIELD_FRAC, COMPUTE_FIELD_NOFRAC) \
463 if (YAC_FRAC_MASK_VALUE_IS_VALID(frac_mask_fallback_value)) { \
464 if (scale_factor == 1.0) { \
465 if (scale_summand == 0.0) COMPUTE_FIELD_FRAC(NO_SCALING) \
466 else COMPUTE_FIELD_FRAC(ADD) \
468 if (scale_summand == 0.0) COMPUTE_FIELD_FRAC(MULT) \
469 else COMPUTE_FIELD_FRAC(MULT_ADD) \
472 if (scale_factor == 1.0) { \
473 if (scale_summand == 0.0) COMPUTE_FIELD_NOFRAC(NO_SCALING) \
474 else COMPUTE_FIELD_NOFRAC(ADD) \
476 if (scale_summand == 0.0) COMPUTE_FIELD_NOFRAC(MULT) \
477 else COMPUTE_FIELD_NOFRAC(MULT_ADD) \
583 double const * restrict ** src_fields,
584 double const * restrict ** src_frac_masks,
585 double const * restrict * remote_src_fields,
586 double const * restrict * remote_src_frac_masks,
587 double * restrict * tgt_field,
588 size_t const * restrict tgt_pos,
589 size_t tgt_count,
size_t const * restrict prefix_num_src_per_tgt,
590 double const * restrict weights,
591 size_t const * restrict src_field_idx,
592 size_t const * restrict src_idx,
594 double frac_mask_fallback_value,
595 double scale_factor,
double scale_summand) {
600 if (tgt_count != 0) {
658 double const * restrict ** src_fields,
659 double const * restrict ** src_frac_masks,
660 double * restrict * tgt_field,
661 size_t * restrict tgt_buffer_sizes,
663 double frac_mask_fallback_value,
664 double scale_factor,
double scale_summand) {
676#undef COMPUTE_FIELD_STENCIL_FRAC
677#undef COMPUTE_FIELD_STENCIL_NOFRAC
678#undef COMPUTE_FIELD_STENCIL_FRAC_WGT
679#undef COMPUTE_FIELD_STENCIL_FRAC_NOWGT
680#undef COMPUTE_FIELD_STENCIL_NOFRAC_
681#undef COMPUTE_FIELD_DIRECT_NOFRAC
682#undef COMPUTE_FIELD_DIRECT_FRAC
699#define CHECK_WITH_FRAC_MASK() \
702 YAC_FRAC_MASK_VALUE_IS_VALID(frac_mask_fallback_value), \
703 "with_frac_mask does not match value provided to constructor\n" \
704 "(frac_mask_fallback_value = %lf with_frac_mask = %d " \
705 "with_frac_mask(constructor) %d)", frac_mask_fallback_value, \
706 frac_mask_fallback_value != YAC_FRAC_MASK_NO_VALUE, with_frac_mask)
712#define YAC_INTERP_GRID_ASSERT_F(INTERP_GRID, EXP, FMT, ...) \
714 (EXP), FMT "(source grid: %s; target grid: %s)", \
716 yac_interp_grid_get_src_grid_name(INTERP_GRID), \
717 yac_interp_grid_get_tgt_grid_name(INTERP_GRID))
719#define YAC_INTERP_GRID_ASSERT(INTERP_GRID, EXP, MSG) \
720 YAC_INTERP_GRID_ASSERT_F(INTERP_GRID, EXP, MSG "%s", "")
722#define YAC_INTERP_GRID_FIELD_ASSERT_F(INTERP_GRID, EXP, FMT, ...) \
725 "(source grid: %s; source field location: %s; " \
726 "target grid: %s; target field location: %s)", \
728 yac_interp_grid_get_src_grid_name(INTERP_GRID), \
729 yac_loc2str(yac_interp_grid_get_src_field_location(INTERP_GRID, 0)), \
730 yac_interp_grid_get_tgt_grid_name(INTERP_GRID), \
731 yac_loc2str(yac_interp_grid_get_tgt_field_location(INTERP_GRID)))
733#define YAC_INTERP_GRID_FIELD_ASSERT(INTERP_GRID, EXP, MSG) \
734 YAC_INTERP_GRID_FIELD_ASSERT_F(INTERP_GRID, EXP, MSG "%s", "")
741#define CHECK_INTERP_GRID_HAS_SRC_FIELDS(INTERP_GRID) \
742 YAC_INTERP_GRID_ASSERT( \
743 INTERP_GRID, yac_interp_grid_get_num_src_fields(INTERP_GRID) != 0, \
744 "Number of source fields is 0.")
746#define CHECK_INTERP_GRID_SRC_FIELD_IDX_VALID(INTERP_GRID, SRC_FIELD_IDX) \
747 CHECK_INTERP_GRID_HAS_SRC_FIELDS(INTERP_GRID) \
748 YAC_INTERP_GRID_ASSERT_F( \
749 INTERP_GRID, (SRC_FIELD_IDX) < yac_interp_grid_get_num_src_fields(INTERP_GRID), \
750 "invalid src_field_idx. Got %zu, expected < %zu", \
751 (size_t)(SRC_FIELD_IDX), yac_interp_grid_get_num_src_fields(INTERP_GRID))
753#define CHECK_INTERP_GRID_SRC_FIELD_LOCATION_CORNER_CELL_EDGE(INTERP_GRID, LOCATION) \
754 CHECK_INTERP_GRID_HAS_SRC_FIELDS(INTERP_GRID) \
755 YAC_INTERP_GRID_FIELD_ASSERT( \
757 ((LOCATION) == YAC_LOC_CORNER) || \
758 ((LOCATION) == YAC_LOC_CELL) || \
759 ((LOCATION) == YAC_LOC_EDGE), \
760 "Expected source fields defined as CORNER, CELL, or EDGE")
762#define CHECK_INTERP_GRID_NUM_SRC_FIELDS_SINGLE(INTERP_GRID) \
763 CHECK_INTERP_GRID_HAS_SRC_FIELDS(INTERP_GRID) \
764 YAC_INTERP_GRID_FIELD_ASSERT_F( \
766 yac_interp_grid_get_num_src_fields(INTERP_GRID) == 1, \
767 "Invalid number of source fields. Got %zu, expected 1.", \
768 yac_interp_grid_get_num_src_fields(INTERP_GRID))
770#define CHECK_INTERP_GRID_SRC_FIELD_IS_CELL(INTERP_GRID, SRC_FIELD_IDX) \
771 CHECK_INTERP_GRID_SRC_FIELD_IDX_VALID(INTERP_GRID, SRC_FIELD_IDX) \
772 YAC_INTERP_GRID_FIELD_ASSERT( \
774 yac_interp_grid_get_src_field_location(INTERP_GRID, SRC_FIELD_IDX) == YAC_LOC_CELL, \
775 "Expected source fields defined as CELL")
777#define CHECK_INTERP_GRID_TGT_FIELD_IS_CELL(INTERP_GRID) \
778 YAC_INTERP_GRID_FIELD_ASSERT( \
780 yac_interp_grid_get_tgt_field_location(INTERP_GRID) == YAC_LOC_CELL, \
781 "Expected target fields defined as CELL")
#define COMPUTE_FIELD(COMPUTE_FIELD_FRAC, COMPUTE_FIELD_NOFRAC)
#define COMPUTE_FIELD_STENCIL_NOFRAC(SCALE)
#define COMPUTE_FIELD_DIRECT_FRAC(SCALE)
#define COMPUTE_FIELD_DIRECT_NOFRAC(SCALE)
#define COMPUTE_FIELD_STENCIL_FRAC(SCALE)
#define YAC_INSTRUMENT_START(ID)
Enter an instrumented region.
#define YAC_INSTRUMENT_STOP(ID)
Exit an instrumented region entered with YAC_INSTRUMENT_START(ID).
struct Xt_redist_ * Xt_redist
Defines internal basic interpolation definitions.
struct yac_interpolation_buffer yac_interpolation_buffer_copy(struct yac_interpolation_buffer buffer, size_t num_fields, size_t collection_size)
static void compute_tgt_field_stencil(double const *restrict **src_fields, double const *restrict **src_frac_masks, double const *restrict *remote_src_fields, double const *restrict *remote_src_frac_masks, double *restrict *tgt_field, size_t const *restrict tgt_pos, size_t tgt_count, size_t const *restrict prefix_num_src_per_tgt, double const *restrict weights, size_t const *restrict src_field_idx, size_t const *restrict src_idx, size_t num_src_fields, size_t collection_size, double frac_mask_fallback_value, double scale_factor, double scale_summand)
Compute target field values using stencil-based summation of source data (sparse-matrix-vector multip...
struct yac_interpolation_buffer yac_interpolation_buffer_init_2(Xt_redist *redists, size_t *min_buffer_sizes, size_t num_fields, size_t collection_size, enum yac_interpolation_buffer_type type)
void yac_interpolation_buffer_free(struct yac_interpolation_buffer *buffer)
static void compute_tgt_field_direct(double const *restrict **src_fields, double const *restrict **src_frac_masks, double *restrict *tgt_field, size_t *restrict tgt_buffer_sizes, size_t num_src_fields, size_t collection_size, double frac_mask_fallback_value, double scale_factor, double scale_summand)
Copy source field values to target buffers, optionally applying fractional masking and scaling.
yac_interpolation_buffer_type
struct yac_interpolation_buffer yac_interpolation_buffer_init(Xt_redist *redists, size_t num_fields, size_t collection_size, enum yac_interpolation_buffer_type type)
add versions of standard API functions not returning on error