YAC 3.12.0
Yet Another Coupler
Loading...
Searching...
No Matches
point_selection.c
Go to the documentation of this file.
1// Copyright (c) 2025 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include "string.h"
6
7#include "point_selection.h"
8#include "utils_core.h"
9#include "yac_mpi_internal.h"
10#include "geometry.h"
11
14 union {
15 struct {
16 double center_lon;
17 double center_lat;
18 double inc_angle;
21};
22
24 double center_lon, double center_lat, double inc_angle) {
25
27 (center_lat >= - M_PI_2) && (center_lat <= M_PI_2),
28 "ERROR(yac_point_selection_bnd_circle_new): "
29 "invalid latitude for bounding circle center (%lf) "
30 "(has to be in the range of [-M_PI_2;M_PI_2])", center_lat);
32 (inc_angle >= 0.0) && (inc_angle < M_PI),
33 "ERROR(yac_point_selection_bnd_circle_new): "
34 "invalid angle for bounding circle (%lf) "
35 "(has to be in the range of [0;M_PI[)", inc_angle);
36
37 struct yac_point_selection * point_select =
38 xmalloc(1 * sizeof(*point_select));
39
41 point_select->data.bnd_circle.center_lon = center_lon;
42 point_select->data.bnd_circle.center_lat = center_lat;
43 point_select->data.bnd_circle.inc_angle = inc_angle;
44
45 return point_select;
46}
47
49 struct yac_point_selection const * point_select) {
50
52 yac_point_selection_get_type(point_select);
53
54 struct yac_point_selection * point_select_copy;
55 switch (type) {
57 "ERROR(yac_point_selection_copy): invalid point selection type");
59 point_select_copy = NULL;
60 break;
62 point_select_copy =
64 point_select->data.bnd_circle.center_lon,
65 point_select->data.bnd_circle.center_lat,
66 point_select->data.bnd_circle.inc_angle);
67 break;
68 }
69
70 return point_select_copy;
71}
72
74 free(point_select);
75}
76
78 struct yac_point_selection const * point_select, MPI_Comm comm) {
79
80 int int_pack_size;
81 yac_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &int_pack_size), comm);
82
84 yac_point_selection_get_type(point_select);
85
86 size_t pack_size = int_pack_size; // type
87
88 switch (type) {
90 "ERROR(yac_point_selection_get_pack_size): invalid point selection type");
92 break;
94 int dble_pack_size;
96 MPI_Pack_size(1, MPI_DOUBLE, comm, &dble_pack_size), comm);
97 pack_size += dble_pack_size + // center_lon
98 dble_pack_size + // center_lat
99 dble_pack_size; // inc_angle
100 };
101 }
102
103 return pack_size;
104}
105
107 struct yac_point_selection const * point_select,
108 void * buffer, int buffer_size, int * position, MPI_Comm comm) {
109
110 int int_pack_size;
111 yac_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &int_pack_size), comm);
112
113 int type = (int)yac_point_selection_get_type(point_select);
114
116 MPI_Pack(&type, 1, MPI_INT, buffer, buffer_size, position, comm), comm);
117
118 switch (type) {
120 "ERROR(yac_point_selection_pack): invalid point selection type");
122 break;
125 MPI_Pack(
126 &(point_select->data.bnd_circle.center_lon), 1, MPI_DOUBLE,
127 buffer, buffer_size, position, comm), comm);
129 MPI_Pack(
130 &(point_select->data.bnd_circle.center_lat), 1, MPI_DOUBLE,
131 buffer, buffer_size, position, comm), comm);
133 MPI_Pack(
134 &(point_select->data.bnd_circle.inc_angle), 1, MPI_DOUBLE,
135 buffer, buffer_size, position, comm), comm);
136 }
137 }
138}
139
141 void const * buffer, int buffer_size, int * position, MPI_Comm comm) {
142
143 int type;
145 MPI_Unpack(
146 buffer, buffer_size, position, &type, 1, MPI_INT, comm), comm);
147
148 struct yac_point_selection * point_select;
149
150 switch (type) {
152 "ERROR(yac_point_selection_unpack): invalid point selection type");
154 point_select = NULL;
155 break;
159 MPI_Unpack(
160 buffer, buffer_size, position, &center_lon, 1,
161 MPI_DOUBLE, comm), comm);
163 MPI_Unpack(
164 buffer, buffer_size, position, &center_lat, 1,
165 MPI_DOUBLE, comm), comm);
167 MPI_Unpack(
168 buffer, buffer_size, position, &inc_angle, 1,
169 MPI_DOUBLE, comm), comm);
170 point_select =
172 break;
173 }
174 }
175
176 return point_select;
177}
178
180 struct yac_point_selection const * a, struct yac_point_selection const * b) {
181
184
185 int ret = (type_a > type_b) - (type_a < type_b);
186
187 if (!ret) {
188
189 switch (type_a) {
191 "ERROR(yac_point_selection_compare): invalid point selection type");
193 ret = 0;
194 break;
196 ret =
199 if (ret) break;
200 ret =
203 if (ret) break;
204 ret =
207 break;
208 }
209 }
210 }
211 return ret;
212}
213
214// Sorts the provided arrays based on a flag-array (containing the
215// values "0" and "!= 0"). After the sort, all array elements whose associated
216// flag value is "0" are the front of the array.
217//
218// This sort is:
219// * not stable
220// * has a time complexity of O(n)
221static void flag_sort(
222 size_t * array_size_t, yac_coordinate_pointer array_coord,
223 int * flag, size_t false_count/*, size_t true_count*/) {
224
225 // The number of "true" elements in the 0...false_count-1 range of the
226 // array is identical to the number of "false" elements in the
227 // false_count...false_count+true_count-1. We just have to find matching
228 // pairs and swap them.
229 for (size_t i = 0, j = false_count; i < false_count; ++i) {
230 // if there is a wrongfully placed "true" element
231 if (flag[i]) {
232 // find a wrongfully place "false" element
233 for (; flag[j]; ++j);
234 // swap elements
235 double temp_coord[3];
236 memcpy(temp_coord, array_coord[i], sizeof(temp_coord));
237 memcpy(array_coord[i], array_coord[j], sizeof(temp_coord));
238 memcpy(array_coord[j], temp_coord, sizeof(temp_coord));
239 size_t temp_size_t = array_size_t[i];
240 array_size_t[i] = array_size_t[j];
241 array_size_t[j] = temp_size_t;
242 // set to next element in "true" list
243 ++j;
244 }
245 }
246}
247
249 struct yac_point_selection const * point_select,
250 yac_coordinate_pointer point_coords, size_t * point_indices,
251 size_t num_points, size_t * num_selected_points) {
252
254 yac_point_selection_get_type(point_select);
255
256 switch (type) {
258 "ERROR(yac_point_selection_apply): invalid point selection type");
260 *num_selected_points = 0;
261 break;
263
264 // generate bounding bounding circle
265 struct bounding_circle bnd_circle = {.sq_crd = DBL_MAX};
266 LLtoXYZ(
267 point_select->data.bnd_circle.center_lon,
268 point_select->data.bnd_circle.center_lat,
269 bnd_circle.base_vector);
270 double sin_inc_angle, cos_inc_angle;
272 point_select->data.bnd_circle.inc_angle,
273 &sin_inc_angle, &cos_inc_angle);
274 bnd_circle.inc_angle = sin_cos_angle_new(sin_inc_angle, cos_inc_angle);
275
276 int * match_flag = xmalloc(num_points * sizeof(*match_flag));
277
278 // determine matching points and count them
279 size_t match_count = 0;
280 for (size_t i = 0; i < num_points; ++i) {
281
282 int point_in_bounding_circle =
284 (double*)(point_coords[i]), &bnd_circle);
285 match_flag[i] = point_in_bounding_circle;
286 if (point_in_bounding_circle) ++match_count;
287 }
288
289 // sort selected points to the end of the list
290 flag_sort(
291 point_indices, point_coords, match_flag, num_points - match_count);
292 free(match_flag);
293
294 *num_selected_points = match_count;
295 break;
296 }
297 }
298}
299
301 struct yac_point_selection const * point_select) {
302
303 return
304 (point_select != NULL)?point_select->type:YAC_POINT_SELECTION_TYPE_EMPTY;
305}
306
308 struct yac_point_selection const * point_selection,
309 double * center_lon, double * center_lat, double * inc_angle) {
310
312 yac_point_selection_get_type(point_selection) ==
314 "ERROR(yac_point_selection_bnd_circle_get_config): "
315 "invalid point selection type");
316
317 *center_lon = point_selection->data.bnd_circle.center_lon;
318 *center_lat = point_selection->data.bnd_circle.center_lat;
319 *inc_angle = point_selection->data.bnd_circle.inc_angle;
320}
#define YAC_ASSERT(exp, msg)
static void compute_sin_cos(double angle, double *sin_value, double *cos_value)
Definition geometry.h:220
static int yac_point_in_bounding_circle_vec(double point_vector[3], struct bounding_circle *bnd_circle)
Definition geometry.h:197
static struct sin_cos_angle sin_cos_angle_new(double sin, double cos)
Definition geometry.h:351
enum callback_type type
int yac_point_selection_compare(struct yac_point_selection const *a, struct yac_point_selection const *b)
struct yac_point_selection * yac_point_selection_bnd_circle_new(double center_lon, double center_lat, double inc_angle)
struct yac_point_selection * yac_point_selection_unpack(void const *buffer, int buffer_size, int *position, MPI_Comm comm)
struct yac_point_selection * yac_point_selection_copy(struct yac_point_selection const *point_select)
void yac_point_selection_apply(struct yac_point_selection const *point_select, yac_coordinate_pointer point_coords, size_t *point_indices, size_t num_points, size_t *num_selected_points)
void yac_point_selection_pack(struct yac_point_selection const *point_select, void *buffer, int buffer_size, int *position, MPI_Comm comm)
size_t yac_point_selection_get_pack_size(struct yac_point_selection const *point_select, MPI_Comm comm)
void yac_point_selection_delete(struct yac_point_selection *point_select)
void yac_point_selection_bnd_circle_get_config(struct yac_point_selection const *point_selection, double *center_lon, double *center_lat, double *inc_angle)
enum yac_point_selection_type yac_point_selection_get_type(struct yac_point_selection const *point_select)
static void flag_sort(size_t *array_size_t, yac_coordinate_pointer array_coord, int *flag, size_t false_count)
yac_point_selection_type
@ YAC_POINT_SELECTION_TYPE_BND_CIRCLE
@ YAC_POINT_SELECTION_TYPE_EMPTY
#define xmalloc(size)
Definition ppm_xfuncs.h:66
struct sin_cos_angle inc_angle
angle between the middle point and the boundary of the spherical cap
Definition geometry.h:53
double base_vector[3]
Definition geometry.h:51
double sq_crd
Definition geometry.h:56
union yac_point_selection::@56 data
struct yac_point_selection::@56::@57 bnd_circle
enum yac_point_selection_type type
double * buffer
static void LLtoXYZ(double lon, double lat, double p_out[])
Definition toy_scrip.c:587
static size_t num_points
Definition yac.c:159
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:19
#define YAC_UNREACHABLE_DEFAULT(msg)
Definition yac_assert.h:34
#define yac_mpi_call(call, comm)
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:19