YAC 3.20.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#include <limits.h>
7
8#include "point_selection.h"
14#include "utils_core.h"
15#include "yac_mpi_internal.h"
16#include "geometry.h"
17
20 union {
21 struct {
22 double center_lon;
23 double center_lat;
24 double inc_angle;
27};
28
30 double center_lon, double center_lat, double inc_angle) {
31
33 (center_lat >= - M_PI_2) && (center_lat <= M_PI_2),
34 "invalid latitude for bounding circle center (%lf) "
35 "(has to be in the range of [-M_PI_2;M_PI_2])", center_lat);
37 (inc_angle >= 0.0) && (inc_angle < M_PI),
38 "invalid angle for bounding circle (%lf) "
39 "(has to be in the range of [0;M_PI[)", inc_angle);
40
41 struct yac_point_selection * point_select =
42 xmalloc(1 * sizeof(*point_select));
43
45 point_select->data.bnd_circle.center_lon = center_lon;
46 point_select->data.bnd_circle.center_lat = center_lat;
47 point_select->data.bnd_circle.inc_angle = inc_angle;
48
49 return point_select;
50}
51
53 struct yac_point_selection const * point_select) {
54
56 yac_point_selection_get_type(point_select);
57
58 struct yac_point_selection * point_select_copy;
59 switch (type) {
60 YAC_UNREACHABLE_DEFAULT("invalid point selection type");
62 point_select_copy = NULL;
63 break;
65 point_select_copy =
67 point_select->data.bnd_circle.center_lon,
68 point_select->data.bnd_circle.center_lat,
69 point_select->data.bnd_circle.inc_angle);
70 break;
71 }
72
73 return point_select_copy;
74}
75
77 free(point_select);
78}
79
81 struct yac_point_selection const * point_select, MPI_Comm comm) {
82
83 int int_pack_size;
84 yac_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &int_pack_size), comm);
85
87 yac_point_selection_get_type(point_select);
88
89 size_t pack_size = int_pack_size; // type
90
91 switch (type) {
92 YAC_UNREACHABLE_DEFAULT("invalid point selection type");
94 break;
96 int dble_pack_size;
98 MPI_Pack_size(1, MPI_DOUBLE, comm, &dble_pack_size), comm);
99 pack_size += dble_pack_size + // center_lon
100 dble_pack_size + // center_lat
101 dble_pack_size; // inc_angle
102 };
103 }
104
105 return pack_size;
106}
107
109 struct yac_point_selection const * point_select,
110 void * buffer, int buffer_size, int * position, MPI_Comm comm) {
111
112 int int_pack_size;
113 yac_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &int_pack_size), comm);
114
115 int type = (int)yac_point_selection_get_type(point_select);
116
118 MPI_Pack(&type, 1, MPI_INT, buffer, buffer_size, position, comm), comm);
119
120 switch (type) {
121 YAC_UNREACHABLE_DEFAULT("invalid point selection type");
123 break;
126 MPI_Pack(
127 &(point_select->data.bnd_circle.center_lon), 1, MPI_DOUBLE,
128 buffer, buffer_size, position, comm), comm);
130 MPI_Pack(
131 &(point_select->data.bnd_circle.center_lat), 1, MPI_DOUBLE,
132 buffer, buffer_size, position, comm), comm);
134 MPI_Pack(
135 &(point_select->data.bnd_circle.inc_angle), 1, MPI_DOUBLE,
136 buffer, buffer_size, position, comm), comm);
137 }
138 }
139}
140
142 void const * buffer, int buffer_size, int * position, MPI_Comm comm) {
143
144 int type;
146 MPI_Unpack(
147 buffer, buffer_size, position, &type, 1, MPI_INT, comm), comm);
148
149 struct yac_point_selection * point_select;
150
151 switch (type) {
152 YAC_UNREACHABLE_DEFAULT("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) {
190 YAC_UNREACHABLE_DEFAULT("invalid point selection type");
192 ret = 0;
193 break;
195 ret =
198 if (ret) break;
199 ret =
202 if (ret) break;
203 ret =
206 break;
207 }
208 }
209 }
210 return ret;
211}
212
213// Sorts the provided arrays based on a flag-array (containing the
214// values "0" and "!= 0"). After the sort, all array elements whose associated
215// flag value is "0" are the front of the array.
216//
217// This sort is:
218// * not stable
219// * has a time complexity of O(n)
220static void flag_sort(
221 size_t * array_size_t, yac_coordinate_pointer array_coord,
222 int * flag, size_t false_count/*, size_t true_count*/) {
223
224 // The number of "true" elements in the 0...false_count-1 range of the
225 // array is identical to the number of "false" elements in the
226 // false_count...false_count+true_count-1. We just have to find matching
227 // pairs and swap them.
228 for (size_t i = 0, j = false_count; i < false_count; ++i) {
229 // if there is a wrongfully placed "true" element
230 if (flag[i]) {
231 // find a wrongfully place "false" element
232 for (; flag[j]; ++j);
233 // swap elements
234 double temp_coord[3];
235 memcpy(temp_coord, array_coord[i], sizeof(temp_coord));
236 memcpy(array_coord[i], array_coord[j], sizeof(temp_coord));
237 memcpy(array_coord[j], temp_coord, sizeof(temp_coord));
238 size_t temp_size_t = array_size_t[i];
239 array_size_t[i] = array_size_t[j];
240 array_size_t[j] = temp_size_t;
241 // set to next element in "true" list
242 ++j;
243 }
244 }
245}
246
248 struct yac_point_selection const * point_select,
249 yac_coordinate_pointer point_coords, size_t * point_indices,
250 size_t num_points, size_t * num_selected_points) {
251
253 yac_point_selection_get_type(point_select);
254
255 switch (type) {
256 YAC_UNREACHABLE_DEFAULT("invalid point selection type");
258 *num_selected_points = 0;
259 break;
261
262 // generate bounding bounding circle
263 struct bounding_circle bnd_circle = {.sq_crd = DBL_MAX};
264 LLtoXYZ(
265 point_select->data.bnd_circle.center_lon,
266 point_select->data.bnd_circle.center_lat,
267 bnd_circle.base_vector);
268 double sin_inc_angle, cos_inc_angle;
270 point_select->data.bnd_circle.inc_angle,
271 &sin_inc_angle, &cos_inc_angle);
272 bnd_circle.inc_angle = sin_cos_angle_new(sin_inc_angle, cos_inc_angle);
273
274 int * match_flag = xmalloc(num_points * sizeof(*match_flag));
275
276 // determine matching points and count them
277 size_t match_count = 0;
278 for (size_t i = 0; i < num_points; ++i) {
279
280 int point_in_bounding_circle =
282 (double*)(point_coords[i]), &bnd_circle);
283 match_flag[i] = point_in_bounding_circle;
284 if (point_in_bounding_circle) ++match_count;
285 }
286
287 // sort selected points to the end of the list
288 flag_sort(
289 point_indices, point_coords, match_flag, num_points - match_count);
290 free(match_flag);
291
292 *num_selected_points = match_count;
293 break;
294 }
295 }
296}
297
299 struct yac_point_selection const * point_select) {
300
301 return
302 (point_select != NULL)?point_select->type:YAC_POINT_SELECTION_TYPE_EMPTY;
303}
304
306 struct yac_point_selection const * point_selection,
307 double * center_lon, double * center_lat, double * inc_angle) {
308
310 yac_point_selection_get_type(point_selection) ==
311 YAC_POINT_SELECTION_TYPE_BND_CIRCLE, "invalid point selection type");
312
313 *center_lon = point_selection->data.bnd_circle.center_lon;
314 *center_lat = point_selection->data.bnd_circle.center_lat;
315 *inc_angle = point_selection->data.bnd_circle.inc_angle;
316}
317
319 struct yac_point_selection * point_selection) {
320
322 yac_point_selection_get_type(point_selection);
323
324 struct yac_param * param = NULL;
325
326 switch (type) {
327 YAC_UNREACHABLE_DEFAULT("invalid point selection type");
329 break;
331
332 enum {
333 CENTER_LON_HAS_DEFAULT = 0,
334 CENTER_LAT_HAS_DEFAULT = 0,
335 INC_ANGLE_HAS_DEFAULT = 0,
336 };
337 int const is_defined = point_selection != NULL;
338 double const center_lon_min = - 4.0 * M_PI;
339 double const center_lon_max = 4.0 * M_PI;
340 double const center_lat_min = -M_PI_2;
341 double const center_lat_max = M_PI_2;
342 double const inc_angle_min = 0.0;
343 double const inc_angle_max = M_PI - 0.00000001;
344
345 struct yac_param * center_lon_param =
347 "lon", &(point_selection->data.bnd_circle.center_lon),
348 center_lon_min, center_lon_min, center_lon_max,
349 CENTER_LON_HAS_DEFAULT, is_defined);
350 struct yac_param * center_lat_param =
352 "lat", &(point_selection->data.bnd_circle.center_lat),
353 center_lat_min, center_lat_min, center_lat_max,
354 CENTER_LAT_HAS_DEFAULT, is_defined);
355
356 struct yac_param * center_sub_params[] = {
357 center_lon_param,
358 center_lat_param,
359 };
360 struct yac_param * center_param =
362 "center", center_sub_params,
363 sizeof(center_sub_params) / sizeof(center_sub_params[0]));
364
365 struct yac_param * inc_angle_param =
367 "radius", &(point_selection->data.bnd_circle.inc_angle),
368 inc_angle_min, inc_angle_min, inc_angle_max,
369 INC_ANGLE_HAS_DEFAULT, is_defined);
370
371 struct yac_param * bnd_circle_sub_params[] = {
372 center_param,
373 inc_angle_param,
374 };
375 param =
377 "bounding_circle", bnd_circle_sub_params,
378 sizeof(bnd_circle_sub_params) / sizeof(bnd_circle_sub_params[0]));
379 break;
380 }
381 }
382 return param;
383}
384
386 char const * name, void ** obj,
387 struct yac_param ** param, int * is_default) {
388
389 YAC_ASSERT(obj, "obj is NULL");
390 YAC_ASSERT(param, "param is NULL");
391 YAC_ASSERT(is_default, "is_default is NULL");
392
393 *param = NULL;
394 *is_default = 0;
395
396 struct yac_point_selection ** point_selection_ptr =
397 (struct yac_point_selection **)obj;
398
400 (*point_selection_ptr == NULL), "point_selection pointer is not NULL");
401
403 type_table,
406
407 int type =
408 (name == NULL) ?
410 yac_name_type_pair_get_type(type_table, type_table_size, name);
411
413 type != INT_MAX, "invalid point selection type \"%s\"", name);
414
415 struct yac_point_selection * point_selection = NULL;
416
417 switch (type) {
418 YAC_UNREACHABLE_DEFAULT("invalid point selection type");
420
421 double const center_lon_default = 0.0;
422 double const center_lat_default = 0.0;
423 double const inc_angle_default = 0.0;
424
425 point_selection =
427 center_lon_default, center_lat_default, inc_angle_default);
428
429 break;
430 }
431 }
432
433 *point_selection_ptr = point_selection;
434 *param = point_selection_build_param(point_selection);
436
437 return 0;
438}
439
441 char const * param_name, struct yac_point_selection ** point_selection) {
442
443 YAC_ASSERT(param_name != NULL, "param_name is NULL");
444 YAC_ASSERT(param_name[0] != '\0', "param_name is empty");
445 YAC_ASSERT(point_selection, "point_selection is NULL");
446
447 return
450 (void **)point_selection, point_selection_build_param(*point_selection),
451 (*point_selection == NULL));
452}
#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:474
int yac_name_type_pair_get_type(struct yac_name_type_pair const *pairs, size_t count, char const *name)
Definition utils_core.c:23
#define DEF_NAME_TYPE_PAIR(NAME, TYPE)
#define DEF_NAME_TYPE_PAIRS(NAME,...)
enum callback_type type
struct yac_param * yac_param_angle_new(const char *name, double *value_ptr, double default_value, double value_min, double value_max, int has_default, int is_defined)
Create an angle parameter (stored in radians)
struct yac_param * yac_param_distance_new(const char *name, double *value_ptr, double default_value, double value_min, double value_max, int has_default, int is_defined)
Create a distance parameter (stored in radians)
#define YAC_PARAM_ASSERT(COND,...)
struct yac_param * yac_param_oneof_new(const char *name, yac_param_oneof_factory_ptr default_factory, void **value_ptr, struct yac_param *subparam, int subparam_is_default)
Create a new one-of struct parameter with a given name and a default_factory.
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.
struct yac_param * yac_point_selection_get_param(char const *param_name, struct yac_point_selection **point_selection)
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)
static int point_selection_get_param_factory(char const *name, void **obj, struct yac_param **param, int *is_default)
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)
static struct yac_param * point_selection_build_param(struct yac_point_selection *point_selection)
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
enum yac_point_selection_type type
struct yac_point_selection::@50::@51 bnd_circle
union yac_point_selection::@50 data
double * buffer
char const * name
Definition toy_scrip.c:114
static void LLtoXYZ(double lon, double lat, double p_out[])
Definition toy_scrip.c:587
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:39
#define YAC_UNREACHABLE_DEFAULT(msg)
Definition yac_assert.h:56
#define yac_mpi_call(call, comm)
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:21