YAC 3.21.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_area.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 <stdlib.h>
6#include <stdio.h>
7#include <math.h>
8#include "test_common.h"
9#include "clipping.h"
10#include "area.h"
11#include "tests.h"
12#include "geometry.h"
13
19#define YAC_EARTH_RADIUS (6371.2290)
20
21static int utest_compare_area(double a, double b);
22static void utest_area(struct yac_grid_cell cell, double ref_area,
23 double (*area_func)(struct yac_grid_cell));
24
25int main (void) {
26
27 enum yac_edge_type gc_edges[] =
31 enum yac_edge_type lat_edges[4] =
33
34 double area;
35
36 puts ("----- calculating area -----\n");
37
38 {
39 /* set the test data over the Equator
40
41 0.0 (lon)
42 0.5 (lat)
43 / \
44 / \
45 -0.5 / \ 0.5
46 0.0 \ / 0.0
47 \ /
48 \ /
49 0.0
50 -0.5
51 */
52
53 struct yac_grid_cell Quad =
54 utest_generate_cell_deg((double[4]){0.5, 0.0, -0.5, 0.0},
55 (double[4]){0.0, 0.5, 0.0, -0.5}, gc_edges, 4);
56
57 area = yac_grid_cell_area ( Quad );
58 printf ( "grid cell area of quad over Equator is %f sqr km\n",
60 yac_free_grid_cell(&Quad);
61 }
62
63 {
64 /* Triangle, half of the above Quad */
65
66 struct yac_grid_cell Tri =
67 utest_generate_cell_deg((double[3]){0.5, 0.0, -0.5},
68 (double[3]){0.0, 0.5, 0.0}, gc_edges, 3);
69
70 area = yac_grid_cell_area ( Tri );
71 printf ( "grid cell area of triangle over Equator is %f sqr km\n",
74 }
75
76 {
77 /* set the test data over the Equator
78
79 -0.5 0.5 (lon)
80 0.5 ----------- 0.5 (lat)
81 | |
82 | |
83 | |
84 | |
85 | |
86 -0.5 ----------- 0.5
87 -0.5 -0.5
88
89 */
90
91 struct yac_grid_cell Quad =
92 utest_generate_cell_deg((double[4]){-0.5, 0.5, 0.5, -0.5},
93 (double[4]){-0.5, -0.5, 0.5, 0.5}, gc_edges, 4);
94
95 area = yac_grid_cell_area ( Quad );
96 printf ( "grid cell area of quad over Equator is %f sqr km\n",
98 yac_free_grid_cell(&Quad);
99 }
100
101 {
102 /* Half of the above Quad */
103
104 struct yac_grid_cell Tri =
105 utest_generate_cell_deg((double[3]){-0.5, 0.5, 0.5},
106 (double[3]){-0.5, -0.5, 0.5}, gc_edges, 3);
107
108 area = yac_grid_cell_area ( Tri );
109 printf ( "grid cell area of triangle over Equator is %f sqr km\n",
111
112 yac_free_grid_cell(&Tri);
113 }
114
115 {
116
117 struct yac_grid_cell Tri =
118 utest_generate_cell_deg((double[3]){150.0, 180.0, 180.0},
119 (double[3]){-60.0, -60.0, -90.0}, gc_edges, 3);
120
121 area = yac_grid_cell_area ( Tri );
122 printf ( "grid cell area of triangle over South Pole is %f sqr km\n",
124
125 yac_free_grid_cell(&Tri);
126 }
127
128 {
129 /* set the test data over the North Pole
130
131 90.0 0.0 (lon)
132 89.5 ----------- 89.5 (lat)
133 | |
134 | |
135 | x |
136 | |
137 | |
138 180.0 ----------- 270.0
139 89.5 89.5
140
141 */
142
143 struct yac_grid_cell Quad =
144 utest_generate_cell_deg((double[4]){0.0, 90.0, -180.0, -90.0},
145 (double[4]){89.5, 89.5, 89.5, 89.5}, gc_edges, 4);
146
147 area = yac_grid_cell_area ( Quad );
148 printf ( "grid cell area of quad over North Pole is %f sqr km\n",
150
151 yac_free_grid_cell(&Quad);
152 }
153
154 {
155 struct yac_grid_cell Quad =
156 utest_generate_cell_deg((double[4]){-180.0, -150.0, -150.0, -180.0},
157 (double[4]){60.0, 60.0, 90.0, 90.0}, gc_edges, 4);
158
159 area = yac_grid_cell_area ( Quad );
160 printf ( "grid cell area of quad near North Pole is %f sqr km\n",
162
163 yac_free_grid_cell(&Quad);
164 }
165
166 {
167 struct yac_grid_cell Quad =
168 utest_generate_cell_deg((double[4]){-180.0, -150.0, -150.0, -180.0},
169 (double[4]){-90.0, -90.0, -60.0, -60.0}, gc_edges, 4);
170
171 area = yac_grid_cell_area ( Quad );
172 printf ( "grid cell area of quad near South Pole is %f sqr km \n",
174
175 yac_free_grid_cell(&Quad);
176 }
177
178 {
179 struct yac_grid_cell Quin =
180 utest_generate_cell_deg((double[5]){-180.0, -150.0, 0.0, -150.0, -180.0},
181 (double[5]){60.0, 60.0, 90.0, 90.0, 90.0}, gc_edges, 5);
182
183 area = yac_grid_cell_area ( Quin );
184 printf ( "grid cell area of quin near North Pole is %f sqr km\n",
186
187 yac_free_grid_cell(&Quin);
188 }
189
190 {
191 /* Triangle that contains an edge of length zero */
192
193 struct yac_grid_cell Tri =
194 utest_generate_cell_deg((double[3]){-0.5, 0.5, -0.5},
195 (double[3]){-0.5, -0.5, -0.5}, gc_edges, 3);
196
197 area = yac_grid_cell_area ( Tri );
198 printf ( "grid cell area of triangle over Equator is %f sqr km\n",
200
201 if ((area < 0.0) || (area > 1e-9))
202 PUT_ERR("ERROR in yac_grid_cell_area for zero size triangle");
203
204 yac_free_grid_cell(&Tri);
205 }
206
207 {
208 struct yac_grid_cell Quad =
209 utest_generate_cell_deg((double[4]){0, 1, 1, 0},
210 (double[4]){0, 0, 1, 1}, gc_edges, 4);
211 struct yac_grid_cell Tri =
212 utest_generate_cell_deg((double[3]){1, 1, 1},
213 (double[3]){0, 0, 1}, gc_edges, 3);
214
215 double base_area = yac_grid_cell_area(Quad);
216
217 yac_free_grid_cell(&Quad);
218 yac_free_grid_cell(&Tri);
219
220 /* A dx of 1e-8 deg corresponds to a dx of ~1 mm on the Earth surface */
221
222 double dx[] = {1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1,
223 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9};
224
225 for (size_t i = 0; i < sizeof(dx) / sizeof(dx[0]); ++i) {
226
227
228 struct yac_grid_cell Quad =
229 utest_generate_cell_deg((double[4]){0, 1.0-dx[i], 1, 0},
230 (double[4]){0, 0, 1, 1}, gc_edges, 4);
231 struct yac_grid_cell Tri =
232 utest_generate_cell_deg((double[3]){1.0-dx[i], 1, 1},
233 (double[3]){0, 0, 1}, gc_edges, 3);
234
235 double partial_area = yac_grid_cell_area(Quad);
236 partial_area += yac_grid_cell_area(Tri);
237
238 yac_free_grid_cell(&Quad);
239 yac_free_grid_cell(&Tri);
240
241 if (utest_compare_area(base_area, partial_area))
242 PUT_ERR("yac_grid_cell_area computed wrong area\n");
243
244 printf ("accuracy check for (base_area - partial_area) %8.1e sqr km for dx %.1e\n",
245 base_area - partial_area, dx[i]);
246 }
247 }
248
249 {
250 struct yac_grid_cell Tri =
251 utest_generate_cell_deg(
252 (double[3]){0.09817477/YAC_RAD, 0.09817477/YAC_RAD, 0.098174496/YAC_RAD},
253 (double[3]){0.353325247/YAC_RAD, 0.353335501/YAC_RAD, 0.353335609/YAC_RAD},
254 gc_edges, 3);
255
256 area = yac_grid_cell_area(Tri);
257
258 if (area < 0)
259 PUT_ERR("grid cell computed wrong area\n");
260
261 printf ("grid cell accuracy check of very small area %.2e sqr km\n",
263
264 yac_free_grid_cell(&Tri);
265 }
266
267 { // cell with two edges (one great circle and one circle of latitude)
268
269 for (int y = -90; y <= 90; y += 5) {
270
271 struct yac_grid_cell cell =
272 utest_generate_cell_deg((double[2]){0.0, 20.0},
273 (double[2]){(double)y, (double)y},
274 (enum yac_edge_type[]){
276
277 // compute reference area
278 double ref_area;
279
280 {
281 double coordinates_x[3] = {0.0, 20.0, 0.0};
282 double coordinates_y[3] = {(double)y, (double)y, 0};
283
284 if ((y == -90) || (y == 90) || (y == 0)) {
285
286 ref_area = 0.0;
287
288 } else {
289
290 if (y < 0) {
291 ref_area = (coordinates_x[1]*YAC_RAD - coordinates_x[0]*YAC_RAD) *
292 (1 - cos(M_PI_2 + coordinates_y[0]*YAC_RAD));
293 coordinates_y[2] = -90.0;
294 } else {
295 ref_area = (coordinates_x[1]*YAC_RAD - coordinates_x[0]*YAC_RAD) *
296 (1 - cos(M_PI_2 - coordinates_y[0]*YAC_RAD));
297 coordinates_y[2] = 90.0;
298 }
299
300 struct yac_grid_cell tmp_cell =
301 utest_generate_cell_deg(coordinates_x, coordinates_y, gc_edges, 3);
302 // ref_area *= YAC_EARTH_RADIUS * YAC_EARTH_RADIUS;
303 ref_area -= yac_grid_cell_area(tmp_cell);
304
305 yac_free_grid_cell(&tmp_cell);
306 }
307 }
308
309 utest_area(cell, ref_area, yac_grid_cell_area);
310
311 yac_free_grid_cell(&cell);
312 }
313 }
314
315 { // cell with lon lat edges and one edge on the equator
316
317 double ref_area = sin(0.5 * YAC_RAD) * (0.5 * YAC_RAD);
318 // ref_area *= YAC_EARTH_RADIUS * YAC_EARTH_RADIUS;
319
320 double coordinates_x[2][4] = {{-0.5, 0.0, 0.0, -0.5},
321 { 0.0, 0.5, 0.5, 0.0}};
322 double coordinates_y[2][4] = {{-0.5, -0.5, 0.0, 0.0},
323 { 0.0, 0.0, 0.5, 0.5}};
324
325 for (int x = 0; x < 2; ++x) {
326 for (int y = 0; y < 2; ++y) {
327 struct yac_grid_cell cell =
328 utest_generate_cell_deg(coordinates_x[x], coordinates_y[y], lat_edges, 4);
329
330 utest_area(cell, ref_area, yac_grid_cell_area);
331
332 yac_free_grid_cell(&cell);
333 }
334 }
335 }
336
337 { // cell with lon lat edges (both lat edges on the different side of the
338 // equator)
339 double ref_area = (2.0 * sin(0.5 * YAC_RAD)) * (1.0 * YAC_RAD);
340 // ref_area *= YAC_EARTH_RADIUS * YAC_EARTH_RADIUS;
341
342 struct yac_grid_cell cell =
343 utest_generate_cell_deg((double[4]){-0.5, 0.5, 0.5, -0.5},
344 (double[4]){-0.5, -0.5, 0.5, 0.5}, lat_edges, 4);
345
346 utest_area(cell, ref_area, yac_grid_cell_area);
347
348 yac_free_grid_cell(&cell);
349 }
350
351 { // cell with lon lat edges (both lat edges on the same side of the equator)
352 double ref_area = sin(1.0 * YAC_RAD);
353 ref_area -= sin(0.5 * YAC_RAD);
354 ref_area *= 1.0 * YAC_RAD;
355 // ref_area *= YAC_EARTH_RADIUS * YAC_EARTH_RADIUS;
356
357 for (int i = 0; i < 2; ++i) {
358
359 double coordinates_x[4] = {-0.5, 0.5, 0.5, -0.5};
360 double coordinates_y[2][4] = {{ 0.5, 0.5, 1.0, 1.0},
361 {-0.5,-0.5,-1.0, -1.0}};
362 enum yac_edge_type edge_types[4] =
364
365 struct yac_grid_cell cell =
366 utest_generate_cell_deg(coordinates_x, coordinates_y[i], edge_types, 4);
367
368 utest_area(cell, ref_area, yac_grid_cell_area);
369
370 yac_free_grid_cell(&cell);
371 }
372 }
373
374 { // concave cell
375
376 double intersections[2][3];
377
378 if (!utest_intersect(YAC_GREAT_CIRCLE_EDGE, 20.0, 59.0, 0.0, 80.0,
379 YAC_LAT_CIRCLE_EDGE, 0.0, 60.0, 20.0, 60.0,
380 intersections[0]))
381 return EXIT_FAILURE;
382 if (!utest_intersect(YAC_GREAT_CIRCLE_EDGE, 20.0, 59.0, -20.0, 59.0,
383 YAC_LAT_CIRCLE_EDGE, 0.0, 60.0, 20.0, 60.0,
384 intersections[1]))
385 return EXIT_FAILURE;
386
387 double intersections_lon[2], intersections_lat[2];
388 XYZtoLL(intersections[0], &(intersections_lon[0]), &(intersections_lat[0]));
389 XYZtoLL(intersections[1], &(intersections_lon[1]), &(intersections_lat[1]));
390
391 // this cell is convex
392 struct yac_grid_cell partial_ref_cell =
393 utest_generate_cell_deg(
394 (double[]){20.0, intersections_lon[0]/YAC_RAD,
395 intersections_lon[1]/YAC_RAD},
396 (double[]){59.0, 60.0, 60.0},
398
399 double partial_area = yac_grid_cell_area(partial_ref_cell);
400
401 double ref_area = 2.0 * partial_area;
402
403 struct yac_grid_cell cells[2] =
404 {utest_generate_cell_deg(
405 (double[]){20.0,
406 intersections_lon[0]/YAC_RAD,
407 intersections_lon[1]/YAC_RAD,
408 -intersections_lon[1]/YAC_RAD,
409 -intersections_lon[0]/YAC_RAD, -20.0},
410 (double[]){59.0, 60.0, 60.0, 60.0, 60.0, 59.0},
411 (enum yac_edge_type[]){
414 utest_generate_cell_deg(
415 (double[]){20.0,
416 intersections_lon[0]/YAC_RAD,
417 -intersections_lon[0]/YAC_RAD,
418 -20.0,
419 -intersections_lon[1]/YAC_RAD,
420 intersections_lon[1]/YAC_RAD},
421 (double[]){59.0, 60.0, 60.0, 59.0, 60.0, 60.0},
422 (enum yac_edge_type[]){
425
426 for (int i = 0; i < 2; ++i) {
427 utest_area(cells[i], ref_area, yac_grid_cell_area);
428 }
429 yac_free_grid_cell(&(cells[0]));
430 yac_free_grid_cell(&(cells[1]));
431 yac_free_grid_cell(&partial_ref_cell);
432 }
433
434 { // case extracted from ICON example, which requires a high accuracy in the
435 // area computation
436 struct yac_grid_cell cells[] = {
437 utest_generate_cell_deg((double[]){-151.1489316535362661,
438 -151.7087167856307133,
439 -150.6174180645230933},
440 (double[]){ 10.6333746562670566,
441 11.5836995038666437,
442 11.6243355661022782}, gc_edges, 3),
443 utest_generate_cell_deg((double[]){-152.8132296086113513,
444 -153.8786613849353557,
445 -151.6929566531634066},
446 (double[]){ 13.4512385235805798,
447 11.4650630285209161,
448 11.5568484830228009}, gc_edges, 3),
449 utest_generate_cell_deg((double[]){-152.8132296086113513,
450 -151.6929566531634066,
451 -150.6265735326831532},
452 (double[]){ 13.4512385235805798,
453 11.5568484830228009,
454 13.5446528932721275}, gc_edges, 3),
455 utest_generate_cell_deg((double[]){-153.8786613849353557,
456 -151.6929566531634066,
457 -152.7627337461449031},
458 (double[]){ 11.4650630285209161,
459 11.5568484830228009,
460 9.5827293336264265}, gc_edges, 3),
461 utest_generate_cell_deg((double[]){-151.6929566531634066,
462 -152.7627337461449031,
463 -150.5840076321059371},
464 (double[]){ 11.5568484830228009,
465 9.5827293336264265,
466 9.6520960946755832}, gc_edges, 3),
467 utest_generate_cell_deg((double[]){-151.6929566531634066,
468 -150.6265735326831532,
469 -149.5139953075027108},
470 (double[]){ 11.5568484830228009,
471 13.5446528932721275,
472 11.6284420125700851}, gc_edges, 3),
473 utest_generate_cell_deg((double[]){-151.6929566531634066,
474 -149.5139953075027108,
475 -150.5840076321059371},
476 (double[]){ 11.5568484830228009,
477 11.6284420125700851,
478 9.6520960946755832}, gc_edges, 3)};
479 size_t num_cells = sizeof(cells) / sizeof(cells[0]);
480
481 struct yac_grid_cell overlap_cells[sizeof(cells) / sizeof(cells[0]) - 1];
482 for (size_t i = 0; i < num_cells-1; ++i)
483 yac_init_grid_cell(&overlap_cells[i]);
484
485 yac_cell_clipping(num_cells - 1, &cells[1], cells[0], &overlap_cells[0]);
486
487 double tgt_area = yac_grid_cell_area(cells[0]);
488 double area_tol = tgt_area * 1e-8;
489 double diff_area = tgt_area;
490
491 for (size_t i = 0; i < num_cells-1; ++i)
492 diff_area -= yac_grid_cell_area(overlap_cells[i]);
493
494 if (fabs(diff_area) > area_tol)
495 PUT_ERR("yac_grid_cell_area is too inaccurate");
496
497 for (size_t i = 0; i < num_cells; ++i)
498 yac_free_grid_cell(&cells[i]);
499 for (size_t i = 0; i < num_cells-1; ++i)
500 yac_free_grid_cell(&overlap_cells[i]);
501 }
502
503 {
504 double ref_area = 0.0;
505 double ref_barycenter[3] = {0.0, 0.0, 0.0};
506
507 {
508 struct yac_grid_cell ref_cell =
509 utest_generate_cell_deg(
510 (double[]){0.0,1.0,1.0, 0.0},
511 (double[]){0.0,0.0,1.0, 1.0}, gc_edges, 4);
512 ref_area = yac_grid_cell_area_info(ref_cell, ref_barycenter, 1.0);
513 yac_free_grid_cell(&ref_cell);
514 normalise_vector(ref_barycenter);
515 }
516
517 enum {NUM_CORNERS = 6};
518 double coordinates_x[NUM_CORNERS] = {0.0, 1.0, 1.0, 0.0, 1.0, 0.0};
519 double coordinates_y[NUM_CORNERS] = {0.0, 0.0, 1.0, 0.0, 1.0, 1.0};
520
521 for (size_t i = 0; i < NUM_CORNERS; ++i) {
522
523 double temp_coordinates_x[NUM_CORNERS];
524 double temp_coordinates_y[NUM_CORNERS];
525
526 for (size_t j = 0; j < NUM_CORNERS; ++j) {
527 temp_coordinates_x[(i+j)%NUM_CORNERS] = coordinates_x[j];
528 temp_coordinates_y[(i+j)%NUM_CORNERS] = coordinates_y[j];
529 }
530 double area = 0.0, barycenter[3] = {0.0, 0.0, 0.0};
531 struct yac_grid_cell cell =
532 utest_generate_cell_deg(
533 temp_coordinates_x, temp_coordinates_y, gc_edges, NUM_CORNERS);
534 area = yac_grid_cell_area_info(cell, barycenter, 1.0);
535 yac_free_grid_cell(&cell);
536
537 normalise_vector(barycenter);
538 if (fabs(area - ref_area) > YAC_AREA_TOL)
539 PUT_ERR("ERROR in yac_grid_cell_area_info (area)");
540
541 if (get_vector_angle(barycenter, ref_barycenter) > yac_angle_tol)
542 PUT_ERR("ERROR in yac_grid_cell_area_info (barycenter)");
543
544 // check for NANs
545 if ((barycenter[0] != barycenter[0]) ||
546 (barycenter[1] != barycenter[1]) ||
547 (barycenter[2] != barycenter[2]))
548 PUT_ERR("ERROR in yac_grid_cell_area_info (barycenter NAN)");
549 }
550 }
551
552 { // check influence of lat circle edges on computation of the barycenter
553 // of a cell
554
555 for (int pole = -1; pole <= 1; pole += 2) {
556 for (int cell_order_a = 0; cell_order_a < 2; ++cell_order_a) {
557 for (int cell_order_b = 0; cell_order_b < 2; ++cell_order_b) {
558
559 enum yac_edge_type ll_edges[3] =
561 double lon[2][3] = {{0.0,0.0,20.0}, {20.0, 20.0, 0.0}};
562 struct yac_grid_cell gc_triangle =
563 utest_generate_cell_deg(
564 lon[cell_order_a],
565 (double[]){copysign(88.0,(double)pole),
566 copysign(90.0,(double)pole),
567 copysign(88.0,(double)pole)}, gc_edges, 3);
568 struct yac_grid_cell ll_triangle =
569 utest_generate_cell_deg(
570 lon[cell_order_b],
571 (double[]){copysign(88.0,(double)pole),
572 copysign(90.0,(double)pole),
573 copysign(88.0,(double)pole)}, ll_edges, 3);
574
575 double gc_barycenter[3] = {0.0, 0.0, 0.0};
576 double gc_area =
577 yac_grid_cell_area_info(gc_triangle, gc_barycenter, 1.0);
578 double ll_barycenter[3] = {0.0, 0.0, 0.0};
579 double ll_area =
580 yac_grid_cell_area_info(ll_triangle, ll_barycenter, 1.0);
581
582 if (gc_area < 0.0) {
583 gc_area = -gc_area;
584 gc_barycenter[0] = -gc_barycenter[0];
585 gc_barycenter[1] = -gc_barycenter[1];
586 gc_barycenter[2] = -gc_barycenter[2];
587 }
588 normalise_vector(gc_barycenter);
589
590 if (ll_area < 0.0) {
591 ll_area = -ll_area;
592 ll_barycenter[0] = -ll_barycenter[0];
593 ll_barycenter[1] = -ll_barycenter[1];
594 ll_barycenter[2] = -ll_barycenter[2];
595 }
596 normalise_vector(ll_barycenter);
597
598 // the triangle with the lat circle edge should be bigger
599 if ((ll_area - gc_area) < YAC_AREA_TOL)
600 PUT_ERR("ERROR in yac_grid_cell_area_info (area)");
601
602 // the barycenter of the triangle with the gc edges should be closer
603 // to the pole
604 if (((gc_barycenter[2] - ll_barycenter[2]) * (double)pole) < 1e-9)
605 PUT_ERR("ERROR in yac_grid_cell_area_info (barycenter)");
606 }
607 }
608 }
609 }
610
611 return TEST_EXIT_CODE;
612}
613
614static void utest_area(struct yac_grid_cell cell, double ref_area,
615 double (*area_func)(struct yac_grid_cell)) {
616
617 double mem_dummy_[128][3];
618 enum yac_edge_type edge_dummy[128];
619 struct yac_grid_cell test_cell = {.coordinates_xyz = mem_dummy_,
620 .edge_type = edge_dummy,
621 .num_corners = cell.num_corners};
622
623 for (int order = -1; order <= 1; order += 2) {
624 for (int start = 0; start < (int)(cell.num_corners); ++start) {
625
626 for (int i = 0; i < (int)(cell.num_corners); ++i) {
627 int j = ((int)(cell.num_corners)+start+i*order)%(int)(cell.num_corners);
628 test_cell.coordinates_xyz[i][0] = cell.coordinates_xyz[j][0];
629 test_cell.coordinates_xyz[i][1] = cell.coordinates_xyz[j][1];
630 test_cell.coordinates_xyz[i][2] = cell.coordinates_xyz[j][2];
631 j = ((int)(cell.num_corners) + j - (order < 0))%(int)(cell.num_corners);
632 test_cell.edge_type[i] = cell.edge_type[j];
633 }
634
635 double area = area_func(test_cell);
636
637 if (utest_compare_area(area, ref_area)) PUT_ERR("ERROR: wrong area\n");
638 }
639 }
640}
641
642static int utest_compare_area(double a, double b) {
643
644 double diff = fabs(a - b);
645 double tol = MAX(MIN(a,b)*1e-6, YAC_AREA_TOL);
646
647 if (diff < tol) return 0;
648 else return (a > b) - (a < b);
649}
double yac_grid_cell_area(struct yac_grid_cell cell)
Area calculation of a spherical cell.
Definition area.c:276
double yac_grid_cell_area_info(struct yac_grid_cell cell, double *barycenter, double sign)
Definition area.c:408
Structs and interfaces for area calculations.
#define YAC_AREA_TOL
Definition area.h:18
static double const tol
void yac_cell_clipping(size_t N, struct yac_grid_cell *source_cell, struct yac_grid_cell target_cell, struct yac_grid_cell *overlap_buffer)
cell clipping to get the cells describing the intersections
Definition clipping.c:1125
#define YAC_RAD
#define yac_angle_tol
Definition geometry.h:26
static void normalise_vector(double v[])
Definition geometry.h:754
static double get_vector_angle(double const a[3], double const b[3])
Definition geometry.h:472
void yac_init_grid_cell(struct yac_grid_cell *cell)
Definition grid_cell.c:14
void yac_free_grid_cell(struct yac_grid_cell *cell)
Definition grid_cell.c:44
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
size_t num_corners
Definition grid_cell.h:21
enum yac_edge_type * edge_type
Definition grid_cell.h:20
double(* coordinates_xyz)[3]
Definition grid_cell.h:19
#define YAC_EARTH_RADIUS
Definition test_area.c:19
static enum yac_edge_type gc_edges[]
double coordinates_x[]
size_t num_cells[2]
double coordinates_y[]
#define TEST_EXIT_CODE
Definition tests.h:15
#define PUT_ERR(string)
Definition tests.h:10
#define MIN(a, b)
Definition toy_common.h:29
static void XYZtoLL(double const p_in[], double *lon, double *lat)
Definition toy_common.h:23
#define MAX(a, b)