YetAnotherCoupler 3.5.2
Loading...
Searching...
No Matches
grid_unstruct.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#include <string.h>
6
7#include "basic_grid_data.h"
8#include "geometry.h"
9#include "utils_common.h"
10
11struct temp_edge {
12 size_t vertex[2];
14};
15
16static int compare_temp_edges(void const * a, void const * b) {
17
18 struct temp_edge const * edge_a = (struct temp_edge const *)a;
19 struct temp_edge const * edge_b = (struct temp_edge const *)b;
20
21 if (edge_a->vertex[0] != edge_b->vertex[0])
22 return (edge_a->vertex[0] > edge_b->vertex[0])?1:-1;
23 return (edge_a->vertex[1] > edge_b->vertex[1]) -
24 (edge_a->vertex[1] < edge_b->vertex[1]);
25}
26
28 size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges,
29 int *num_vertices_per_cell_,
30 double *x_vertices, double *y_vertices, yac_size_t_2_pointer edge_to_vertex,
31 size_t *cell_to_vertex, size_t *cell_to_edge,
32 void (*LLtoXYZ_ptr)(double, double, double[])) {
33
34 // convert 2D coordinates to 3D
36 xmalloc(nbr_vertices * sizeof(*vertex_coordinates));
37 for (size_t i = 0; i < nbr_vertices; ++i)
38 LLtoXYZ_ptr(
39 x_vertices[i], y_vertices[i], &(vertex_coordinates[i][0]));
40
41 // make an internal copy of num_vertices_per_cell
43 xmalloc(nbr_cells * sizeof(*num_vertices_per_cell));
44 memcpy(num_vertices_per_cell, num_vertices_per_cell_,
45 nbr_cells * sizeof(*num_vertices_per_cell));
46
47 // generate cell_to_vertex_offsets
48 size_t total_num_cell_corners = 0;
49 size_t * cell_to_vertex_offsets =
50 xmalloc(nbr_cells * sizeof(*cell_to_vertex_offsets));
51 for (size_t i = 0; i < nbr_cells; ++i) {
52 cell_to_vertex_offsets[i] = total_num_cell_corners;
53 total_num_cell_corners += (size_t)(num_vertices_per_cell[i]);
54 }
55
56 // generate num_cells_per_vertex
58 xcalloc(nbr_vertices, sizeof(*num_cells_per_vertex));
59 for (size_t i = 0; i < total_num_cell_corners; ++i)
61
62 // generate vertex_to_cell
63 size_t * vertex_to_cell =
64 xmalloc(total_num_cell_corners * sizeof(*vertex_to_cell));
65 size_t * vertex_to_cell_offsets =
66 xmalloc((nbr_vertices + 1) * sizeof(*vertex_to_cell_offsets));
68 for (size_t i = 0, accu = 0; i < nbr_vertices; ++i) {
69 vertex_to_cell_offsets[i+1] = accu;
70 accu += num_cells_per_vertex[i];
71 }
72 for (size_t i = 0, k = 0; i < nbr_cells; ++i) {
73 size_t curr_num_vertices = num_vertices_per_cell[i];
74 for (size_t j = 0; j < curr_num_vertices; ++j, ++k)
76 }
77
78 enum yac_edge_type * edge_type = xmalloc(nbr_edges * sizeof(*edge_type));
79 for (size_t i = 0; i < nbr_edges; ++i) edge_type[i] = YAC_GREAT_CIRCLE_EDGE;
80
81 struct yac_basic_grid_data grid;
83 grid.cell_ids = NULL;
84 grid.vertex_ids = NULL;
85 grid.edge_ids = NULL;
86 grid.num_cells = nbr_cells;
87 grid.num_vertices = nbr_vertices;
88 grid.num_edges = nbr_edges;
89 grid.core_cell_mask = NULL;
90 grid.core_vertex_mask = NULL;
91 grid.core_edge_mask = NULL;
101 grid.edge_type = edge_type;
102 grid.num_total_cells = nbr_cells;
103 grid.num_total_vertices = nbr_vertices;
104 grid.num_total_edges = nbr_edges;
105 return grid;
106}
107
109 size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges,
110 int *num_edges_per_cell, double *x_vertices, double *y_vertices,
111 int *cell_to_edge_, int *edge_to_vertex_,
112 void (*LLtoXYZ_ptr)(double, double, double[])) {
113
114 // compute the sum of num_edges_per_cell
115 size_t total_num_cell_edges = 0;
116 for (size_t i = 0; i < nbr_cells; ++i)
117 total_num_cell_edges += (size_t)(num_edges_per_cell[i]);
118
119 // check consistency of cell_to_edge and convert to size_t
120 size_t * cell_to_edge =
121 xmalloc(total_num_cell_edges * sizeof(*cell_to_edge));
122 for (size_t i = 0; i < total_num_cell_edges; ++i) {
123 YAC_ASSERT_F(cell_to_edge_[i] >= 0,
124 "ERROR(yac_generate_basic_grid_data_unstruct_edge_): "
125 "Index %zu in cell_to_edge (%d) is negative.",
126 i, cell_to_edge_[i])
127 YAC_ASSERT_F((size_t)(cell_to_edge_[i]) < nbr_edges,
128 "ERROR(yac_generate_basic_grid_data_unstruct_edge_): "
129 "Index %zu in cell_to_edge (%d) is not smaller than nbr_edges (%zu).",
130 i, cell_to_edge_[i], nbr_edges)
131 cell_to_edge[i] = (size_t)(cell_to_edge_[i]);
132 }
133
134 // check consistency of edge_to_vertex and convert to size_t
136 xmalloc(nbr_edges * sizeof(*edge_to_vertex));
137 for (size_t i = 0; i < 2 * nbr_edges; ++i) {
138 YAC_ASSERT_F(edge_to_vertex_[i] >= 0,
139 "ERROR(yac_generate_basic_grid_data_unstruct_edge_): "
140 "Index %zu in edge_to_vertex (%d) is negative.",
141 i, edge_to_vertex_[i])
142 YAC_ASSERT_F((size_t)(edge_to_vertex_[i]) < nbr_vertices,
143 "ERROR(yac_generate_basic_grid_data_unstruct_edge_): "
144 "Index %zu in edge_to_vertex (%d) is not smaller than nbr_vertices (%zu).",
145 i, edge_to_vertex_[i], nbr_edges)
146 ((size_t*)edge_to_vertex)[i] = (size_t)(edge_to_vertex_[i]);
147 }
148
149 // generate cell_to_vertex
150 size_t * cell_to_vertex =
151 xmalloc(total_num_cell_edges * sizeof(*cell_to_vertex));
152 for (size_t i = 0, k = 0; i < nbr_cells; ++i) {
153 size_t curr_num_vertices = (size_t)(num_edges_per_cell[i]);
154 if (curr_num_vertices == 0) continue;
155 size_t first_vertex = edge_to_vertex[cell_to_edge[k]][0];
156 size_t prev_vertex;
157 size_t curr_vertex = first_vertex;
158 for (size_t j = 0; j < curr_num_vertices; ++j, ++k) {
159 cell_to_vertex[k] = curr_vertex;
160 size_t * curr_edge_vertices = edge_to_vertex[cell_to_edge[k]];
161 prev_vertex = curr_vertex;
162 curr_vertex = curr_edge_vertices[curr_edge_vertices[0] == prev_vertex];
164 (curr_edge_vertices[0] == prev_vertex) ||
165 (curr_edge_vertices[1] == prev_vertex),
166 "ERROR(yac_generate_basic_grid_data_unstruct_edge_): "
167 "inconsistent definition of cell_to_edge or edge_to_vertex")
168 }
170 first_vertex == curr_vertex,
171 "ERROR(yac_generate_basic_grid_data_unstruct_edge_): "
172 "inconsistent definition of cell_to_edge or edge_to_vertex")
173 }
174
175 return
177 nbr_vertices, nbr_cells, nbr_edges, num_edges_per_cell,
178 x_vertices, y_vertices, edge_to_vertex, cell_to_vertex, cell_to_edge,
179 LLtoXYZ_ptr);
180}
181
183 size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell,
184 double *x_vertices, double *y_vertices, int *cell_to_vertex_,
185 void (*LLtoXYZ_ptr)(double, double, double[])) {
186
187 // compute the sum of num_vertices_per_cell
188 size_t total_num_cell_corners = 0;
189 for (size_t i = 0; i < nbr_cells; ++i)
190 total_num_cell_corners += (size_t)(num_vertices_per_cell[i]);
191
192 // check consistency of cell_to_vertex and convert to size_t
193 size_t * cell_to_vertex =
194 xmalloc(total_num_cell_corners * sizeof(*cell_to_vertex));
195 for (size_t i = 0; i < total_num_cell_corners; ++i) {
196 YAC_ASSERT_F(cell_to_vertex_[i] >= 0,
197 "ERROR(yac_generate_basic_grid_data_unstruct_): "
198 "Index %zu in cell_to_vertex (%d) is negative.",
199 i, cell_to_vertex_[i])
200 YAC_ASSERT_F((size_t)(cell_to_vertex_[i]) < nbr_vertices,
201 "ERROR(yac_generate_basic_grid_data_unstruct_): "
202 "Index %zu in cell_to_vertex (%d) is not smaller than nbr_vertices (%zu).",
203 i, cell_to_vertex_[i], nbr_vertices)
204 cell_to_vertex[i] = (size_t)(cell_to_vertex_[i]);
205 }
206
207 // generate temporary array containing edge information
208 struct temp_edge * temp_edges =
209 xmalloc(total_num_cell_corners * sizeof(*temp_edges));
210 for (size_t i = 0, offset = 0, k = 0; i < nbr_cells; ++i) {
211 size_t * curr_cell_to_vertex = cell_to_vertex + offset;
212 size_t curr_num_edges = num_vertices_per_cell[i];
213 offset += curr_num_edges;
214 for (size_t j = 0; j < curr_num_edges; ++j, ++k) {
215 int order =
216 curr_cell_to_vertex[j] > curr_cell_to_vertex[(j+1)%curr_num_edges];
217 temp_edges[k].vertex[order] = curr_cell_to_vertex[j];
218 temp_edges[k].vertex[order^1] = curr_cell_to_vertex[(j+1)%curr_num_edges];
219 temp_edges[k].cell_to_edge_idx = k;
220 }
221 }
222 qsort(temp_edges, total_num_cell_corners,
223 sizeof(*temp_edges), compare_temp_edges);
224
225 // generate cell_to_edge and edge_to_vertex; count total number of edges
226 size_t * cell_to_edge =
227 xmalloc(total_num_cell_corners * sizeof(*cell_to_edge));
228 size_t nbr_edges = 0;
229 yac_size_t_2_pointer edge_to_vertex = (yac_size_t_2_pointer)temp_edges;
230 for (size_t i = 0, prev_indices[2] = {SIZE_MAX, SIZE_MAX};
231 i < total_num_cell_corners; ++i) {
232
233 size_t curr_cell_to_edge_idx = temp_edges[i].cell_to_edge_idx;
234 if ((prev_indices[0] != temp_edges[i].vertex[0]) ||
235 (prev_indices[1] != temp_edges[i].vertex[1])) {
236
237 prev_indices[0] = temp_edges[i].vertex[0];
238 prev_indices[1] = temp_edges[i].vertex[1];
239 edge_to_vertex[nbr_edges][0] = prev_indices[0];
240 edge_to_vertex[nbr_edges][1] = prev_indices[1];
241 ++nbr_edges;
242 }
243
244 cell_to_edge[curr_cell_to_edge_idx] = nbr_edges - 1;
245 }
246 edge_to_vertex =
247 xrealloc(edge_to_vertex, nbr_edges * sizeof(*edge_to_vertex));
248
249 return
251 nbr_vertices, nbr_cells, nbr_edges, num_vertices_per_cell,
252 x_vertices, y_vertices, edge_to_vertex, cell_to_vertex, cell_to_edge,
253 LLtoXYZ_ptr);
254}
255
257 size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell_,
258 double *x_vertices, double *y_vertices, int *cell_to_vertex_) {
259
260 return
262 nbr_vertices, nbr_cells, num_vertices_per_cell_,
263 x_vertices, y_vertices, cell_to_vertex_, LLtoXYZ);
264}
265
267 size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell_,
268 double *x_vertices, double *y_vertices, int *cell_to_vertex_) {
269
270 return
272 nbr_vertices, nbr_cells, num_vertices_per_cell_,
273 x_vertices, y_vertices, cell_to_vertex_, LLtoXYZ_deg);
274}
275
277 size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges,
278 int *num_edges_per_cell, double *x_vertices, double *y_vertices,
279 int *cell_to_edge, int *edge_to_vertex) {
280
281 return
283 nbr_vertices, nbr_cells, nbr_edges, num_edges_per_cell,
284 x_vertices, y_vertices, cell_to_edge, edge_to_vertex, LLtoXYZ);
285}
286
288 size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges,
289 int *num_edges_per_cell, double *x_vertices, double *y_vertices,
290 int *cell_to_edge, int *edge_to_vertex) {
291
292 return
294 nbr_vertices, nbr_cells, nbr_edges, num_edges_per_cell,
295 x_vertices, y_vertices, cell_to_edge, edge_to_vertex, LLtoXYZ_deg);
296}
297
299 struct yac_basic_grid_data grid_data,
300 double *x_vertices, double *y_vertices,
301 double (*get_angle_ptr)(double, double),
302 double angle_tol, double pole_y_vertex) {
303
304 for (size_t i = 0; i < grid_data.num_edges; ++i) {
305 int is_lon_edge =
306 (fabs(
307 get_angle_ptr(
308 x_vertices[grid_data.edge_to_vertex[i][0]],
309 x_vertices[grid_data.edge_to_vertex[i][1]])) < angle_tol) ||
310 ((fabs(fabs(y_vertices[grid_data.edge_to_vertex[i][0]]) -
311 pole_y_vertex) < angle_tol) ^
312 (fabs(fabs(y_vertices[grid_data.edge_to_vertex[i][1]]) -
313 pole_y_vertex) < angle_tol));
314 int is_lat_edge =
315 fabs(y_vertices[grid_data.edge_to_vertex[i][0]] -
316 y_vertices[grid_data.edge_to_vertex[i][1]]) < angle_tol;
318 is_lon_edge || is_lat_edge,
319 "ERROR(yac_generate_basic_grid_data_unstruct_ll): "
320 "edge is neither lon nor lat ((%lf,%lf),(%lf,%lf))",
321 x_vertices[grid_data.edge_to_vertex[i][0]],
322 y_vertices[grid_data.edge_to_vertex[i][0]],
323 x_vertices[grid_data.edge_to_vertex[i][1]],
324 y_vertices[grid_data.edge_to_vertex[i][1]]);
325 grid_data.edge_type[i] = (is_lon_edge)?YAC_LON_CIRCLE_EDGE:YAC_LAT_CIRCLE_EDGE;
326 }
327}
328
330 size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell_,
331 double *x_vertices, double *y_vertices, int *cell_to_vertex_,
332 void (*LLtoXYZ_ptr)(double, double, double[]),
333 double (*get_angle_ptr)(double, double),
334 double angle_tol, double pole_y_vertex) {
335
336 struct yac_basic_grid_data grid_data =
338 nbr_vertices, nbr_cells, num_vertices_per_cell_,
339 x_vertices, y_vertices, cell_to_vertex_, LLtoXYZ_ptr);
340
342 grid_data, x_vertices, y_vertices, get_angle_ptr, angle_tol, pole_y_vertex);
343
344 return grid_data;
345}
346
348 size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell_,
349 double *x_vertices, double *y_vertices, int *cell_to_vertex_) {
350
351 return
353 nbr_vertices, nbr_cells, num_vertices_per_cell_,
354 x_vertices, y_vertices, cell_to_vertex_, LLtoXYZ,
355 get_angle, yac_angle_tol, M_PI_2);
356}
357
359 size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell_,
360 double *x_vertices, double *y_vertices, int *cell_to_vertex_) {
361
362 return
364 nbr_vertices, nbr_cells, num_vertices_per_cell_,
365 x_vertices, y_vertices, cell_to_vertex_, LLtoXYZ_deg,
366 get_angle_deg, yac_angle_tol / M_PI * 180.0, 90.0);
367}
368
369static struct yac_basic_grid_data
371 size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges,
372 int *num_edges_per_cell, double *x_vertices, double *y_vertices,
373 int *cell_to_edge, int *edge_to_vertex,
374 void (*LLtoXYZ_ptr)(double, double, double[]),
375 double (*get_angle_ptr)(double, double),
376 double angle_tol, double pole_y_vertex) {
377
378 struct yac_basic_grid_data grid_data =
380 nbr_vertices, nbr_cells, nbr_edges, num_edges_per_cell,
381 x_vertices, y_vertices, cell_to_edge, edge_to_vertex, LLtoXYZ_ptr);
382
384 grid_data, x_vertices, y_vertices, get_angle_ptr, angle_tol, pole_y_vertex);
385
386 return grid_data;
387}
388
390 size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges,
391 int *num_edges_per_cell, double *x_vertices, double *y_vertices,
392 int *cell_to_edge, int *edge_to_vertex) {
393
394 return
396 nbr_vertices, nbr_cells, nbr_edges, num_edges_per_cell,
397 x_vertices, y_vertices, cell_to_edge, edge_to_vertex, LLtoXYZ,
398 get_angle, yac_angle_tol, M_PI_2);
399}
400
402 size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges,
403 int *num_edges_per_cell, double *x_vertices, double *y_vertices,
404 int *cell_to_edge, int *edge_to_vertex) {
405
406 return
408 nbr_vertices, nbr_cells, nbr_edges, num_edges_per_cell,
409 x_vertices, y_vertices, cell_to_edge, edge_to_vertex, LLtoXYZ_deg,
410 get_angle_deg, yac_angle_tol / M_PI * 180.0, 90.0);
411}
static void LLtoXYZ_deg(double lon, double lat, double p_out[])
Definition geometry.h:304
#define yac_angle_tol
Definition geometry.h:34
static double get_angle(double a_lon, double b_lon)
Definition geometry.h:127
static void LLtoXYZ(double lon, double lat, double p_out[])
Definition geometry.h:287
static double get_angle_deg(double a_lon, double b_lon)
Definition geometry.h:143
yac_edge_type
Definition grid_cell.h:12
@ YAC_GREAT_CIRCLE_EDGE
great circle
Definition grid_cell.h:13
@ YAC_LAT_CIRCLE_EDGE
latitude circle
Definition grid_cell.h:14
@ YAC_LON_CIRCLE_EDGE
longitude circle
Definition grid_cell.h:15
static struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_(size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell, double *x_vertices, double *y_vertices, int *cell_to_vertex_, void(*LLtoXYZ_ptr)(double, double, double[]))
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_edge(size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge, int *edge_to_vertex)
static struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_ll_(size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell_, double *x_vertices, double *y_vertices, int *cell_to_vertex_, void(*LLtoXYZ_ptr)(double, double, double[]), double(*get_angle_ptr)(double, double), double angle_tol, double pole_y_vertex)
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_edge_deg(size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge, int *edge_to_vertex)
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_deg(size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell_, double *x_vertices, double *y_vertices, int *cell_to_vertex_)
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_ll_deg(size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell_, double *x_vertices, double *y_vertices, int *cell_to_vertex_)
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_edge_ll(size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge, int *edge_to_vertex)
static void set_ll_edge_type(struct yac_basic_grid_data grid_data, double *x_vertices, double *y_vertices, double(*get_angle_ptr)(double, double), double angle_tol, double pole_y_vertex)
static struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_edge_ll_(size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge, int *edge_to_vertex, void(*LLtoXYZ_ptr)(double, double, double[]), double(*get_angle_ptr)(double, double), double angle_tol, double pole_y_vertex)
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_edge_ll_deg(size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge, int *edge_to_vertex)
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct(size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell_, double *x_vertices, double *y_vertices, int *cell_to_vertex_)
static struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_base(size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_vertices_per_cell_, double *x_vertices, double *y_vertices, yac_size_t_2_pointer edge_to_vertex, size_t *cell_to_vertex, size_t *cell_to_edge, void(*LLtoXYZ_ptr)(double, double, double[]))
static struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_edge_(size_t nbr_vertices, size_t nbr_cells, size_t nbr_edges, int *num_edges_per_cell, double *x_vertices, double *y_vertices, int *cell_to_edge_, int *edge_to_vertex_, void(*LLtoXYZ_ptr)(double, double, double[]))
static int compare_temp_edges(void const *a, void const *b)
struct yac_basic_grid_data yac_generate_basic_grid_data_unstruct_ll(size_t nbr_vertices, size_t nbr_cells, int *num_vertices_per_cell_, double *x_vertices, double *y_vertices, int *cell_to_vertex_)
#define xrealloc(ptr, size)
Definition ppm_xfuncs.h:67
#define xcalloc(nmemb, size)
Definition ppm_xfuncs.h:64
#define xmalloc(size)
Definition ppm_xfuncs.h:66
size_t vertex[2]
size_t cell_to_edge_idx
yac_coordinate_pointer vertex_coordinates
size_t * vertex_to_cell_offsets
yac_size_t_2_pointer edge_to_vertex
enum yac_edge_type * edge_type
size_t * cell_to_vertex_offsets
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:19
#define YAC_ASSERT(exp, msg)
Definition yac_assert.h:16
size_t(* yac_size_t_2_pointer)[2]
Definition yac_types.h:23
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:19