25#define AREA_TOL_FACTOR (1e-6)
29 size_t * tgt_points,
size_t count,
31 int * interpolation_complete);
34 size_t * tgt_points,
size_t count,
36 int * interpolation_complete);
88 int max_num_vertices_per_cell = 0;
91 max_num_vertices_per_cell)
92 max_num_vertices_per_cell =
94 return max_num_vertices_per_cell;
106 *src_grid_cells =
xmalloc(max_num_src_per_tgt *
sizeof(**src_grid_cells));
108 double (*coordinates_xyz_buffer)[3];
112 int max_num_vertices_per_cell =
117 xmalloc((max_num_src_per_tgt + 1) * (
size_t)max_num_vertices_per_cell *
118 sizeof(*edge_type_buffer));
119 coordinates_xyz_buffer =
120 xmalloc((max_num_src_per_tgt + 1) * (
size_t)max_num_vertices_per_cell *
121 sizeof(*coordinates_xyz_buffer));
124 tgt_grid_cell->
edge_type = edge_type_buffer;
125 tgt_grid_cell->
array_size = max_num_vertices_per_cell;
126 for (
size_t i = 0; i < max_num_src_per_tgt; ++i) {
127 (*src_grid_cells)[i].coordinates_xyz =
128 coordinates_xyz_buffer + (i + 1) * max_num_vertices_per_cell;
129 (*src_grid_cells)[i].edge_type =
130 edge_type_buffer + (i + 1) * max_num_vertices_per_cell;
131 (*src_grid_cells)[i].array_size = max_num_vertices_per_cell;
145 int max_num_vertices_per_cell =
150 xmalloc(2 * (
size_t)max_num_vertices_per_cell *
151 sizeof(*edge_type_buffer));
153 xmalloc(2 * (
size_t)max_num_vertices_per_cell *
154 sizeof(*coordinates_xyz_buffer));
157 tgt_grid_cell->
edge_type = edge_type_buffer;
158 tgt_grid_cell->
array_size = max_num_vertices_per_cell;
161 coordinates_xyz_buffer + max_num_vertices_per_cell;
163 edge_type_buffer + max_num_vertices_per_cell;
164 src_grid_cell->
array_size = max_num_vertices_per_cell;
170 size_t * src_cells,
struct yac_grid_cell tgt_grid_cell_buffer,
172 double * weights,
size_t * num_weights,
int partial_coverage,
174 int enforced_conserv) {
177 tgt_basic_grid_data, tgt_cell, &tgt_grid_cell_buffer);
178 for (
size_t i = 0; i < src_count; ++i)
180 src_basic_grid_data, src_cells[i], src_grid_cell_buffer + i);
182 double * area = weights;
184 src_count, src_grid_cell_buffer, tgt_grid_cell_buffer, area);
186 size_t num_valid_weights = 0;
187 for (
size_t i = 0; i < src_count; ++i) {
190 if (i != num_valid_weights) {
191 area[num_valid_weights] = area[i];
192 src_cells[num_valid_weights] = src_cells[i];
197 *num_weights = num_valid_weights;
198 if (num_valid_weights == 0)
return 0;
203 switch(normalisation) {
205 "invalid normalisation option in conservative remapping")
207 norm_factor = 1.0 / tgt_cell_area;
210 double fracarea = 0.0;
211 for (
size_t i = 0; i < num_valid_weights; ++i) fracarea += area[i];
212 norm_factor = 1.0 / fracarea;
217 if (partial_coverage) {
218 for (
size_t i = 0; i < num_valid_weights; ++i) weights[i] *= norm_factor;
221 double tgt_cell_area_diff = tgt_cell_area;
223 for (
size_t i = 0; i < num_valid_weights; ++i) {
224 double curr_area = area[i];
225 tgt_cell_area_diff -= curr_area;
226 weights[i] = curr_area * norm_factor;
228 int successful = fabs(tgt_cell_area_diff) <= area_tol;
229 if (successful && enforced_conserv)
237 size_t * tgt_points,
size_t count,
239 int * interpolation_complete) {
241 if (*interpolation_complete)
return 0;
252 size_t * src_cells = NULL;
253 size_t * num_src_per_tgt =
xmalloc(count *
sizeof(*num_src_per_tgt));
257 interp_grid, tgt_points, count, &src_cells, num_src_per_tgt);
266 size_t total_num_weights = 0;
267 size_t max_num_src_per_tgt = 0;
268 for (
size_t i = 0; i <
count; ++i) {
269 size_t curr_num_src_per_tgt = num_src_per_tgt[i];
270 if (curr_num_src_per_tgt > max_num_src_per_tgt)
271 max_num_src_per_tgt = curr_num_src_per_tgt;
272 total_num_weights += num_src_per_tgt[i];
278 yac_int * temp_src_global_ids =
279 xmalloc(max_num_src_per_tgt *
sizeof(*temp_src_global_ids));
281 for (
size_t i = 0, offset = 0; i <
count; ++i) {
283 size_t curr_num_src_per_tgt = num_src_per_tgt[i];
284 size_t * curr_src_cells = src_cells + offset;
285 offset += curr_num_src_per_tgt;
287 for (
size_t j = 0; j < curr_num_src_per_tgt; ++j)
288 temp_src_global_ids[j] =
292 temp_src_global_ids, curr_num_src_per_tgt, curr_src_cells);
295 free(temp_src_global_ids);
298 double * w =
xmalloc(total_num_weights *
sizeof(*w));
299 size_t result_count = 0;
300 size_t * failed_tgt =
xmalloc(
count *
sizeof(*failed_tgt));
301 total_num_weights = 0;
311 interp_grid, max_num_src_per_tgt, &tgt_grid_cell, &src_grid_cells);
314 for (
size_t i = 0, offset = 0, result_offset = 0; i < count; ++i) {
316 size_t curr_src_count = num_src_per_tgt[i];
317 size_t curr_tgt_point = tgt_points[i];
322 tgt_basic_grid_data, curr_tgt_point,
323 src_basic_grid_data, curr_src_count, src_cells + offset,
324 tgt_grid_cell, src_grid_cells, w + result_offset, &num_weights,
325 partial_coverage, normalisation, enforced_conserv)) {
327 if (offset != result_offset) {
330 src_cells + result_offset, src_cells + offset,
331 num_weights *
sizeof(*src_cells));
333 tgt_points[result_count] = curr_tgt_point;
334 num_src_per_tgt[result_count] = num_weights;
336 result_offset += num_weights;
337 total_num_weights += num_weights;
339 failed_tgt[i - result_count] = curr_tgt_point;
342 offset += curr_src_count;
348 free(src_grid_cells);
350 if (result_count != count)
351 memcpy(tgt_points + result_count, failed_tgt,
352 (count - result_count) *
sizeof(*tgt_points));
358 interp_grid, tgt_points, result_count),
359 .count = result_count};
362 interp_grid, 0, src_cells, total_num_weights);
366 weights, &tgts, num_src_per_tgt, srcs, w);
371 free(num_src_per_tgt);
422 for (
size_t k = 0; k < 3; ++k)
423 for (
size_t l = 0; l < 3; ++l)
424 M[k][l] = - src_cell_centroid[k] * src_cell_centroid[l];
425 for (
size_t k = 0; k < 3; ++k)
431 for (
size_t i = 0; i <
N; ++i) {
434 for (
size_t j = 0; j < 3; ++j)
buffer[i].
weight[j] = 0.0;
437 for (
size_t n = 0; n <
N; ++n)
438 for (
size_t i = 0; i < 3; ++i)
439 for (
size_t j = 0; j < 3; ++j)
446 void const * a,
void const * b) {
455 double abs_weight_a = fabs(weight_a->
weight);
456 double abs_weight_b = fabs(weight_b->
weight);
457 ret = (abs_weight_a > abs_weight_b) - (abs_weight_a < abs_weight_b);
464 void const * a,
void const * b) {
487 for (
size_t i = 1; i < n_; ++i, ++curr_weight_data) {
495 *prev_weight_data = *curr_weight_data;
503 for (
size_t i = 0; i < n_; ++i) {
505 if (weights[i].
weight == 0.0)
continue;
506 if (i != new_n) weights[new_n] = weights[i];
516 weights[0].weight = super_cell->
norm_area;
522 size_t N = src_cell_gradient->
n;
527 double * overlap_barycenter = super_cell->
barycenter;
529 for (
size_t n = 1; n <=
N; ++n) {
531 (gradient_weights[n].
weight[0] * overlap_barycenter[0] +
532 gradient_weights[n].
weight[1] * overlap_barycenter[1] +
533 gradient_weights[n].
weight[2] * overlap_barycenter[2]) *
535 weights[n].global_id = gradient_weights[n].
global_id;
536 weights[n].local_id = gradient_weights[n].
local_id;
545 double barycenter[3]) {
548 size_t const * vertices =
555 for (
size_t i = 0; i < num_vertices; ++i) {
556 double const * curr_vertex_coordinate =
557 grid_data->vertex_coordinates[vertices[i]];
558 barycenter[0] += curr_vertex_coordinate[0];
559 barycenter[1] += curr_vertex_coordinate[1];
560 barycenter[2] += curr_vertex_coordinate[2];
566 struct yac_interp_grid * interp_grid,
size_t * tgt_points,
size_t count,
568 int * interp_fail_flag,
size_t ** src_cells,
size_t * num_src_cells,
570 int partial_coverage) {
575 "invalid normalisation option in conservative remapping")
577 size_t * num_src_per_tgt =
xmalloc(count *
sizeof(*num_src_per_tgt));
581 interp_grid, tgt_points, count, src_cells, num_src_per_tgt);
584 size_t total_num_overlaps = 0;
585 for (
size_t i = 0; i < count; ++i) total_num_overlaps += num_src_per_tgt[i];
587 *num_src_cells = total_num_overlaps;
590 size_t * num_tgt_per_src =
591 xrealloc(num_src_per_tgt, *num_src_cells *
sizeof(*num_tgt_per_src));
596 size_t * tgt_cells = NULL;
598 interp_grid, *src_cells, *num_src_cells, &tgt_cells, num_tgt_per_src);
600 total_num_overlaps = 0;
601 for (
size_t i = 0; i < *num_src_cells; ++i)
602 total_num_overlaps += num_tgt_per_src[i];
605 xmalloc(total_num_overlaps *
sizeof(*super_cells));
612 for (
size_t i = 0, j = 0; i < *num_src_cells; ++i) {
614 size_t curr_num_overlaps = num_tgt_per_src[i];
615 size_t curr_src_cell = (*src_cells)[i];
619 for (
size_t k = 0; k < curr_num_overlaps; ++k, ++j) {
621 size_t curr_tgt_cell = tgt_cells[j];
631 free(num_tgt_per_src);
635 qsort(super_cells, total_num_overlaps,
sizeof(*super_cells),
647 size_t new_num_super_cells = 0;
649 for (
size_t i = 0, j = 0; i < total_num_overlaps;) {
652 size_t curr_tgt_cell = super_cells[i].
tgt.
local_id;
654 tgt_basic_grid_data, curr_tgt_cell, &tgt_grid_cell);
655 double curr_tgt_cell_coverage = 0.0;
658 for (;(i < total_num_overlaps) &&
659 (super_cells[i].tgt.local_id == curr_tgt_cell); ++i) {
663 src_basic_grid_data, super_cells[i].
src.local_id, &src_grid_cell);
666 double super_cell_area;
667 double barycenter[3];
669 1, &src_grid_cell, tgt_grid_cell, &super_cell_area, &barycenter);
672 if (super_cell_area > 0.0) {
674 super_cells[new_num_super_cells].
src = super_cells[i].
src;
675 super_cells[new_num_super_cells].
tgt = super_cells[i].
tgt;
676 super_cells[new_num_super_cells].
area = super_cell_area;
677 memcpy(super_cells[new_num_super_cells].barycenter, barycenter,
680 ++new_num_super_cells;
682 curr_tgt_cell_coverage += super_cell_area;
689 if (new_num_super_cells != j) {
692 switch (normalisation) {
694 "invalid normalisation option in conservative remapping")
696 norm_factor = 1.0 / curr_tgt_cell_area;
699 norm_factor = 1.0 / curr_tgt_cell_coverage;
703 for (; j < new_num_super_cells; ++j)
704 super_cells[j].norm_area = super_cells[j].area * norm_factor;
709 while ((tgt_idx < count) && (tgt_points[tgt_idx] < curr_tgt_cell))
710 interp_fail_flag[tgt_idx++] = 1;
712 if ((tgt_idx < count) && (tgt_points[tgt_idx] == curr_tgt_cell)) {
716 if (partial_coverage) {
717 interp_fail_flag[tgt_idx] = curr_tgt_cell_coverage < area_tol;
719 interp_fail_flag[tgt_idx] =
720 fabs(curr_tgt_cell_area - curr_tgt_cell_coverage) > area_tol;
726 for (; tgt_idx < count; ++tgt_idx) interp_fail_flag[tgt_idx] = 1;
727 *num_super_cells = new_num_super_cells;
729 xrealloc(super_cells, new_num_super_cells *
sizeof(*super_cells));
737 size_t * src_cells,
int * skip_src_cell,
size_t num_src_cells,
741 xmalloc(num_src_cells *
sizeof(*src_cell_centroids));
745 qsort(super_cells, num_super_cells,
sizeof(*super_cells),
761 for (
size_t i = 0, offset = 0; i < num_src_cells; ++i) {
763 if (skip_src_cell[i])
continue;
765 size_t curr_src_cell = src_cells[i];
768 size_t curr_num_super_cells = offset;
769 while ((offset < num_super_cells) &&
770 (super_cells[offset].
src.local_id == curr_src_cell)) ++offset;
771 curr_num_super_cells = offset - curr_num_super_cells;
773 double src_cell_centroid[3] = {0.0, 0.0, 0.0};
775 if (curr_num_super_cells > 0) {
776 for (
size_t j = 0; j < curr_num_super_cells; ++j) {
778 double super_cell_area = curr_super_cells[j].
area;
779 double * super_cell_barycenter = curr_super_cells[j].
barycenter;
780 src_cell_centroid[0] += super_cell_area * super_cell_barycenter[0];
781 src_cell_centroid[1] += super_cell_area * super_cell_barycenter[1];
782 src_cell_centroid[2] += super_cell_area * super_cell_barycenter[2];
791 src_basic_grid_data, curr_src_cell, &src_grid_cell);
792 for (
size_t j = 0; j < src_grid_cell.
num_corners; ++j) {
800 src_cell_centroids[i][0] = src_cell_centroid[0];
801 src_cell_centroids[i][1] = src_cell_centroid[1];
802 src_cell_centroids[i][2] = src_cell_centroid[2];
808 return src_cell_centroids;
814 size_t num_src_cells,
size_t * src_cell_neighbours) {
817 xmalloc(num_src_cells *
sizeof(*src_cell_gradients));
822 size_t total_num_gradient_weights = 0;
823 size_t max_num_neigh_per_src = 0;
824 for (
size_t i = 0; i < num_src_cells; ++i) {
825 src_cell_gradients[i].
data = NULL;
826 src_cell_gradients[i].
n = 0;
827 size_t curr_num_neigh =
829 total_num_gradient_weights += curr_num_neigh + 1;
830 if (max_num_neigh_per_src < curr_num_neigh)
831 max_num_neigh_per_src = curr_num_neigh;
834 (total_num_gradient_weights > 0)?
835 (
xmalloc(total_num_gradient_weights *
836 sizeof(*weight_vector_data_buffer))):NULL;
837 for (
size_t i = 0; i < total_num_gradient_weights; ++i)
838 for (
size_t j = 0; j < 3; ++j)
839 weight_vector_data_buffer[i].
weight[j] = 0.0;
842 xmalloc((max_num_neigh_per_src + 1) *
sizeof(*orth_buffer));
866 for (
size_t i = 0, offset = 0, weight_vector_data_buffer_offset = 0;
867 i < num_src_cells; ++i) {
869 size_t curr_num_neigh =
871 size_t * curr_neighs = src_cell_neighbours + offset;
872 offset += curr_num_neigh;
874 G_i->
data = weight_vector_data_buffer + weight_vector_data_buffer_offset;
876 if (skip_src_cell[i])
continue;
878 weight_vector_data_buffer_offset += curr_num_neigh + 1;
879 G_i->
n = curr_num_neigh + 1;
883 for (
size_t j = 0; j < curr_num_neigh; ++j) {
884 size_t curr_neigh = curr_neighs[j];
886 if (curr_neigh != SIZE_MAX) {
905 .num_corners = 3, .array_size = 0};
915 for (
size_t j = 0; j < curr_num_neigh; ++j) {
917 size_t neigh_idx[2] = {j + 1, (j+1)%curr_num_neigh+1};
918 size_t neigh_local_ids[2] =
922 if (neigh_local_ids[0] == neigh_local_ids[1])
continue;
924 double neigh_cell_barycenters[2][3];
926 src_basic_grid_data, neigh_local_ids[0], neigh_cell_barycenters[0]);
928 src_basic_grid_data, neigh_local_ids[1], neigh_cell_barycenters[1]);
930 centroid_triangle.
coordinates_xyz[1][0] = neigh_cell_barycenters[0][0];
931 centroid_triangle.
coordinates_xyz[1][1] = neigh_cell_barycenters[0][1];
932 centroid_triangle.
coordinates_xyz[1][2] = neigh_cell_barycenters[0][2];
933 centroid_triangle.
coordinates_xyz[2][0] = neigh_cell_barycenters[1][0];
934 centroid_triangle.
coordinates_xyz[2][1] = neigh_cell_barycenters[1][1];
935 centroid_triangle.
coordinates_xyz[2][2] = neigh_cell_barycenters[1][2];
942 neigh_cell_barycenters[0], neigh_cell_barycenters[1], C_j_x_C_k);
944 double curr_edge_direction =
957 for (
size_t l = 0; l < 3; ++l) C_j_x_C_k[l] *= 0.5;
960 G_i->
data[neigh_idx[0]].
weight[0] += C_j_x_C_k[0];
961 G_i->
data[neigh_idx[0]].
weight[1] += C_j_x_C_k[1];
962 G_i->
data[neigh_idx[0]].
weight[2] += C_j_x_C_k[2];
965 G_i->
data[neigh_idx[1]].
weight[0] += C_j_x_C_k[0];
966 G_i->
data[neigh_idx[1]].
weight[1] += C_j_x_C_k[1];
967 G_i->
data[neigh_idx[1]].
weight[2] += C_j_x_C_k[2];
972 for (
size_t j = 0; j <= curr_num_neigh; ++j)
973 for (
size_t k = 0; k < 3; ++k)
976 double inv_A_C_K = (A_C_k >
YAC_AREA_TOL)?(1.0/A_C_k):0.0;
978 for (
size_t k = 0; k <= curr_num_neigh; ++k)
979 for (
size_t l = 0; l < 3; ++l)
983 src_cell_centroids[i], G_i, orth_buffer);
987 return src_cell_gradients;
991 size_t * tgt_cells,
int * interp_fail_flag,
size_t num_tgt_cells,
993 size_t ** src_per_tgt,
double ** weights,
size_t * num_src_per_tgt) {
995 size_t num_interpolated_tgt = 0;
999 qsort(super_cells, num_super_cells,
sizeof(*super_cells),
1002 size_t max_num_weights_per_tgt = 0;
1003 size_t max_num_total_weights = 0;
1006 for (
size_t i = 0, j = 0; i < num_tgt_cells; ++i) {
1008 if (interp_fail_flag[i])
continue;
1010 size_t curr_tgt_cell = tgt_cells[i];
1011 size_t curr_num_weights = 0;
1014 while ((j < num_super_cells) &&
1015 (super_cells[j].tgt.local_id < curr_tgt_cell)) ++j;
1018 while ((j < num_super_cells) &&
1019 (super_cells[j].tgt.local_id == curr_tgt_cell))
1022 max_num_total_weights += curr_num_weights;
1023 if (max_num_weights_per_tgt < curr_num_weights)
1024 max_num_weights_per_tgt = curr_num_weights;
1025 num_interpolated_tgt++;
1029 xmalloc(max_num_weights_per_tgt *
sizeof(*weight_buffer));
1030 *weights =
xmalloc(max_num_total_weights *
sizeof(**weights));
1031 *src_per_tgt =
xmalloc(max_num_total_weights *
sizeof(**src_per_tgt));
1052 for (
size_t i = 0, j = 0; i < num_interpolated_tgt; ++i) {
1054 size_t curr_tgt_cell = tgt_cells[i];
1057 while ((j < num_super_cells) &&
1058 (super_cells[j].tgt.local_id != curr_tgt_cell)) ++j;
1060 size_t weight_buffer_offset = 0;
1063 while ((j < num_super_cells) &&
1064 (super_cells[j].tgt.local_id == curr_tgt_cell)) {
1066 size_t num_weights =
1068 super_cells + j, weight_buffer + weight_buffer_offset);
1069 weight_buffer_offset += num_weights;
1076 num_src_per_tgt[i] = weight_buffer_offset;
1078 for (
size_t k = 0; k < weight_buffer_offset; ++k, ++w_idx) {
1079 (*weights)[w_idx] = weight_buffer[k].
weight;
1080 (*src_per_tgt)[w_idx] = weight_buffer[k].
local_id;
1083 free(weight_buffer);
1085 return num_interpolated_tgt;
1090 size_t * tgt_points,
size_t count,
1092 int * interpolation_complete) {
1094 if (*interpolation_complete)
return 0;
1108 int * interp_fail_flag =
xmalloc(count *
sizeof(*interp_fail_flag));
1110 size_t num_super_cells = 0;
1111 size_t * src_cells = NULL;
1112 size_t num_src_cells = 0;
1116 interp_grid, tgt_points, count, &super_cells, &num_super_cells,
1117 interp_fail_flag, &src_cells, &num_src_cells,
1120 size_t total_num_src_cell_neighbours = 0;
1123 for (
size_t i = 0; i < num_src_cells; ++i)
1124 total_num_src_cell_neighbours +=
1126 size_t * src_cell_neighbours =
1127 xmalloc(total_num_src_cell_neighbours *
sizeof(*src_cell_neighbours));
1131 interp_grid, src_cells, num_src_cells, src_cell_neighbours);
1135 int * skip_src_cell =
xmalloc(num_src_cells *
sizeof(*skip_src_cell));
1139 if (src_cell_mask != NULL) {
1140 for (
size_t i = 0, offset = 0; i < num_src_cells; ++i) {
1141 size_t curr_src_cell = src_cells[i];
1142 if ((skip_src_cell[i] = !src_cell_mask[curr_src_cell]))
continue;
1143 size_t * curr_neighbours = src_cell_neighbours + offset;
1144 size_t curr_num_neigh =
1146 offset += curr_num_neigh;
1147 for (
size_t j = 0; j < curr_num_neigh; ++j)
1148 if ((curr_neighbours[j] != SIZE_MAX) &&
1149 (!src_cell_mask[curr_neighbours[j]]))
1150 curr_neighbours[j] = SIZE_MAX;
1153 memset(skip_src_cell, 0, num_src_cells *
sizeof(*skip_src_cell));
1159 num_src_cells, super_cells, num_super_cells);
1164 interp_grid, src_cells, src_cell_centroids,
1165 skip_src_cell, num_src_cells, src_cell_neighbours);
1166 free(src_cell_neighbours);
1167 free(src_cell_centroids);
1170 qsort(super_cells, num_super_cells,
sizeof(*super_cells),
1172 for (
size_t i = 0, j = 0; i < num_src_cells; ++i) {
1173 size_t curr_src_cell = src_cells[i];
1178 (j >= num_super_cells) ||
1179 (super_cells[j].
src.local_id >= curr_src_cell),
"internal error");
1180 while ((j < num_super_cells) &&
1181 (super_cells[j].
src.local_id == curr_src_cell)) {
1185 free(skip_src_cell);
1188 size_t * src_per_tgt = NULL;
1190 size_t * num_src_per_tgt =
xmalloc(count *
sizeof(*num_src_per_tgt));
1193 size_t num_interpolated_tgt =
1195 tgt_points, interp_fail_flag, count, super_cells, num_super_cells,
1196 &src_per_tgt, &w, num_src_per_tgt);
1197 if (num_src_cells > 0) free(src_cell_gradients->
data);
1198 free(src_cell_gradients);
1200 free(interp_fail_flag);
1202 size_t total_num_weights = 0;
1203 for (
size_t i = 0; i < num_interpolated_tgt; ++i)
1204 total_num_weights += num_src_per_tgt[i];
1209 interp_grid, tgt_points, num_interpolated_tgt),
1210 .count = num_interpolated_tgt};
1213 interp_grid, 0, src_per_tgt, total_num_weights);
1217 weights, &tgts, num_src_per_tgt, srcs, w);
1222 free(num_src_per_tgt);
1225 return num_interpolated_tgt;
1229 int order,
int enforced_conserv,
int partial_coverage,
1236 "interp_method_conserv only "
1237 "supports enforced_conserv with first order conservative remapping")
1239 (order == 1) || (order == 2),
"invalid order")
1283 copy->
base.
vtable = config_conserv->base.vtable;
1285 copy->
config = config_conserv->config;
1290 void const *a_,
void const *b_) {
1313 yac_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &int_pack_size), comm);
1316 return 4 * (size_t)int_pack_size;
1322 void *
buffer,
int buffer_size,
int *position, MPI_Comm comm) {
1326 &config_conserv->config.order, 1, MPI_INT,
buffer, buffer_size, position,
1330 &config_conserv->config.enforced_conserv, 1, MPI_INT,
buffer, buffer_size,
1331 position, comm), comm);
1334 &config_conserv->config.partial_coverage, 1, MPI_INT,
buffer, buffer_size,
1335 position, comm), comm);
1336 int normalisation = (int)config_conserv->config.normalisation;
1339 &normalisation, 1, MPI_INT,
buffer, buffer_size, position, comm), comm);
1364 ORDER_HAS_DEFAULT = 1,
1365 ORDER_IS_DEFINED = 1,
1366 ENFORCED_CONSERV_HAS_DEFAULT = 1,
1367 ENFORCED_CONSERV_IS_DEFINED = 1,
1368 PARTIAL_COVERAGE_HAS_DEFAULT = 1,
1369 PARTIAL_COVERAGE_IS_DEFINED = 1,
1370 NORMALISATION_HAS_DEFAULT = 1,
1371 NORMALISATION_IS_DEFINED = 1,
1374 int const order_min_value = 1;
1375 int const order_max_value = 2;
1382 order_min_value, order_max_value,
1383 ORDER_HAS_DEFAULT, ORDER_IS_DEFINED);
1385 struct yac_param *param_enforced_conserv =
1387 "enforced_conservation",
1390 ENFORCED_CONSERV_HAS_DEFAULT, ENFORCED_CONSERV_IS_DEFINED);
1392 struct yac_param *param_partial_coverage =
1397 PARTIAL_COVERAGE_HAS_DEFAULT, PARTIAL_COVERAGE_IS_DEFINED);
1400 normalisation_enum_table,
1409 normalisation_enum_table, normalisation_enum_table_size,
1410 NORMALISATION_HAS_DEFAULT, NORMALISATION_IS_DEFINED);
1412 struct yac_param *root_param_array[] = {
1414 param_enforced_conserv,
1415 param_partial_coverage,
1419 ROOT_PARAM_ARRAY_SIZE =
1420 sizeof(root_param_array) /
sizeof(root_param_array[0])
1424 "conservative", root_param_array, ROOT_PARAM_ARRAY_SIZE);
1440 xmalloc(
sizeof(*config_conserv));
1454 void *
buffer,
int buffer_size,
int *position, MPI_Comm comm) {
1456 xmalloc(
sizeof(*config_conserv));
1466 MPI_INT, comm), comm);
1470 MPI_INT, comm), comm);
1474 buffer, buffer_size, position, &normalisation, 1, MPI_INT, comm), comm);
#define YAC_ASSERT(exp, msg)
double yac_grid_cell_area(struct yac_grid_cell cell)
Area calculation of a spherical cell.
Structs and interfaces for area calculations.
static int edge_direction(double *a, double *b)
void yac_correct_weights(size_t nSourceCells, double *weight)
correct interpolation weights
void yac_compute_overlap_info(size_t N, struct yac_grid_cell *source_cell, struct yac_grid_cell target_cell, double *overlap_areas, double(*overlap_barycenters)[3])
calculates partial areas for all overlapping parts of the source cells with arbitrary target cells,...
void yac_compute_overlap_areas(size_t N, struct yac_grid_cell *source_cell, struct yac_grid_cell target_cell, double *partial_areas)
calculates partial areas for all overlapping parts of the source cells with arbitrary target cells,...
void yac_compute_overlap_buf_free()
void yac_const_basic_grid_data_get_grid_cell(struct yac_const_basic_grid_data *grid_data, size_t cell_idx, struct yac_grid_cell *buffer_cell)
int const * const_int_pointer
static void crossproduct_kahan(double const a[], double const b[], double cross[])
static void normalise_vector(double v[])
@ YAC_GREAT_CIRCLE_EDGE
great circle
#define DEF_NAME_TYPE_PAIR(NAME, TYPE)
#define DEF_NAME_TYPE_PAIRS(NAME,...)
void yac_interp_grid_do_cell_search_tgt(struct yac_interp_grid *interp_grid, size_t *src_cells, size_t count, size_t **tgt_cells, size_t *num_tgt_per_src)
const_int_pointer yac_interp_grid_get_src_field_mask(struct yac_interp_grid *interp_grid, size_t src_field_idx)
void yac_interp_grid_get_src_cell_neighbours(struct yac_interp_grid *interp_grid, size_t *src_cells, size_t count, size_t *neighbours)
struct remote_point * yac_interp_grid_get_tgt_remote_points(struct yac_interp_grid *interp_grid, size_t *tgt_points, size_t count)
struct remote_point * yac_interp_grid_get_src_remote_points(struct yac_interp_grid *interp_grid, size_t src_field_idx, size_t *src_points, size_t count)
struct yac_const_basic_grid_data * yac_interp_grid_get_basic_grid_data_tgt(struct yac_interp_grid *interp_grid)
void yac_interp_grid_do_cell_search_src(struct yac_interp_grid *interp_grid, size_t *tgt_cells, size_t count, size_t **src_cells, size_t *num_src_per_tgt)
struct yac_const_basic_grid_data * yac_interp_grid_get_basic_grid_data_src(struct yac_interp_grid *interp_grid)
@ YAC_CONSERVATIVE
Conservative remapping (area/flux conserving)
#define DEF_INTERP_METHOD_CONFIG_COMPARE_TYPE(TYPE)
#define DEF_INTERP_METHOD_CONFIG_TYPE(TYPE)
static void delete_conserv(struct interp_method *method)
static struct yac_param * config_conserv_get_param(struct yac_interp_method_config const *config)
static void get_cell_buffers_(struct yac_interp_grid *interp_grid, struct yac_grid_cell *tgt_grid_cell, struct yac_grid_cell *src_grid_cell)
static size_t config_conserv_get_pack_size(struct yac_interp_method_config const *config, MPI_Comm comm)
struct yac_interp_method_config * yac_interp_method_config_conserv_unpack(void *buffer, int buffer_size, int *position, MPI_Comm comm)
Unpacks a conservative interpolation method configuration from a buffer.
static int config_conserv_compare(void const *a_, void const *b_)
static struct yac_interp_method_config * config_conserv_copy(const struct yac_interp_method_config *config)
static void config_conserv_pack(struct yac_interp_method_config const *config, void *buffer, int buffer_size, int *position, MPI_Comm comm)
static size_t compute_2nd_order_weights(size_t *tgt_cells, int *interp_fail_flag, size_t num_tgt_cells, struct supermesh_cell *super_cells, size_t num_super_cells, size_t **src_per_tgt, double **weights, size_t *num_src_per_tgt)
static struct interp_method * config_conserv_generate(struct yac_interp_method_config const *config)
static size_t do_search_conserv_1st_order(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 yac_coordinate_pointer compute_src_cell_centroids(struct yac_interp_grid *interp_grid, size_t *src_cells, int *skip_src_cell, size_t num_src_cells, struct supermesh_cell *super_cells, size_t num_super_cells)
static void get_cell_buffers(struct yac_interp_grid *interp_grid, size_t max_num_src_per_tgt, struct yac_grid_cell *tgt_grid_cell, struct yac_grid_cell **src_grid_cells)
static void compute_cell_barycenter(struct yac_const_basic_grid_data *grid_data, size_t cell_idx, double barycenter[3])
static void compact_weight_vector_data(struct weight_vector_data *weights, size_t *n)
static struct interp_method_vtable interp_method_conserv_2nd_order_vtable
static enum yac_interpolation_list config_conserv_get_type()
static struct yac_interp_method_config_vtable yac_interp_method_config_vtable_conserv
struct interp_method * yac_interp_method_conserv_new(int order, int enforced_conserv, int partial_coverage, enum yac_interp_method_conserv_normalisation normalisation)
static int get_max_num_vertices_per_cell(struct yac_const_basic_grid_data *basic_grid_data)
static void compute_super_cells(struct yac_interp_grid *interp_grid, size_t *tgt_points, size_t count, struct supermesh_cell **super_cells_, size_t *num_super_cells, int *interp_fail_flag, size_t **src_cells, size_t *num_src_cells, enum yac_interp_method_conserv_normalisation normalisation, int partial_coverage)
static int compare_supermesh_cell_tgt_local_ids(const void *a, const void *b)
static void orthogonalise_weight_vector(double *src_cell_centroid, struct weight_vector_3d *G_i, struct weight_vector_data_3d *buffer)
struct yac_interp_method_config * yac_interp_method_config_default_conserv_new(void)
Creates a conservative interpolation method configuration with default parameters.
static struct interp_method_vtable interp_method_conserv_1st_order_vtable
static void config_conserv_delete(struct yac_interp_method_config *config)
static int compare_supermesh_cell_src_local_ids(const void *a, const void *b)
static size_t do_search_conserv_2nd_order(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 size_t compute_2nd_order_tgt_cell_weights(struct supermesh_cell *super_cell, struct weight_vector_data *weights)
static int compare_weight_vector_data_weight(void const *a, void const *b)
static int compare_weight_vector_data(void const *a, void const *b)
static struct weight_vector_3d * compute_src_cell_gradients(struct yac_interp_grid *interp_grid, size_t *src_cells, yac_coordinate_pointer src_cell_centroids, int *skip_src_cell, size_t num_src_cells, size_t *src_cell_neighbours)
static int compute_1st_order_weights(struct yac_const_basic_grid_data *tgt_basic_grid_data, size_t tgt_cell, struct yac_const_basic_grid_data *src_basic_grid_data, size_t src_count, size_t *src_cells, struct yac_grid_cell tgt_grid_cell_buffer, struct yac_grid_cell *src_grid_cell_buffer, double *weights, size_t *num_weights, int partial_coverage, enum yac_interp_method_conserv_normalisation normalisation, int enforced_conserv)
#define YAC_INTERP_CONSERV_NORMALISATION_DEFAULT
#define YAC_INTERP_CONSERV_ENFORCED_CONSERV_DEFAULT
#define YAC_INTERP_CONSERV_PARTIAL_COVERAGE_DEFAULT
#define YAC_INTERP_CONSERV_ORDER_DEFAULT
yac_interp_method_conserv_normalisation
@ YAC_INTERP_CONSERV_DESTAREA
@ YAC_INTERP_CONSERV_FRACAREA
#define CHECK_TGT_FIELD_LOCATION_CELL(INTERP_GRID)
#define CHECK_SRC_FIELD_COUNT_SINGLE(INTERP_GRID)
#define CHECK_SRC_FIELD_LOCATION_CELL(INTERP_GRID)
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)
struct yac_param * yac_param_bool_new(const char *name, int *value_ptr, int default_value, int has_default, int is_defined)
Create a bool parameter (backed by int)
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.
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.
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)
int * num_vertices_per_cell
enum yac_interp_method_conserv_normalisation normalisation
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 weight_vector_3d * src_cell_gradient
struct supermesh_cell::@25 src
struct supermesh_cell::@25 tgt
struct weight_vector_data_3d * data
const const_int_pointer num_vertices_per_cell
const const_yac_int_pointer ids[3]
enum yac_edge_type * edge_type
double(* coordinates_xyz)[3]
Concrete implementation of yac_interp_method_config for the conservative method.
struct yac_interp_method_config base
base config object, must be first entry
struct yac_interp_method_conserv_config config
method-specific configuration
void(* delete)(struct yac_interp_method_config *config)
struct yac_param * root_param_cache
struct yac_interp_method_config_vtable const * vtable
enum yac_interp_method_conserv_normalisation normalisation
static struct yac_interp_method_config * config
void yac_quicksort_index_yac_int_size_t(yac_int *a, size_t n, size_t *idx)
void yac_quicksort_index_int_size_t(int *a, size_t n, size_t *idx)
static void yac_remove_duplicates_size_t(size_t *array, size_t *n)
void yac_quicksort_index_size_t_int(size_t *a, size_t n, int *idx)
#define YAC_UNREACHABLE_DEFAULT(msg)
#define yac_mpi_call(call, comm)
double(* yac_coordinate_pointer)[3]