48static double tri_area(
double const * restrict a,
49 double const * restrict b,
50 double const * restrict c) {
54#if defined __NVCOMPILER && __NVCOMPILER_MAJOR__ == 26 && __NVCOMPILER_MINOR__ \
65 det2_error(b[1], b[2], c[1], c[2], &bc[0], &bc_e[0]);
66 det2_error(b[2], b[0], c[2], c[0], &bc[1], &bc_e[1]);
67 det2_error(b[0], b[1], c[0], c[1], &bc[2], &bc_e[2]);
75 {a[0]*bc[0], a[1]*bc[1], a[2]*bc[2]};
77 {fma(a[0], bc[0], -abc[0]) + a[0] * bc_e[0],
78 fma(a[1], bc[1], -abc[1]) + a[1] * bc_e[1],
79 fma(a[2], bc[2], -abc[2]) + a[2] * bc_e[2]};
81 double triple = 0.0, triple_e = 0.0;
83 accu_eft(abc_e[0], &triple, &triple_e);
84 accu_eft(abc_e[1], &triple, &triple_e);
85 accu_eft(abc_e[2], &triple, &triple_e);
86 accu_eft(abc[0], &triple, &triple_e);
87 accu_eft(abc[1], &triple, &triple_e);
88 accu_eft(abc[2], &triple, &triple_e);
114 return 2.0 * atan2(triple + triple_e, D + D_e);
123 double scale = sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
137 return atan2(a[1] , a[0]);
141 double base_vec[3],
double a[3],
double b[3],
double * middle_lat) {
148 double const tol = 1e-8;
151 fabs(a[2]-b[2]) <=
tol,
"latitude of both corners is not identical")
153 double h = fabs(a[2]);
156 if (h <
tol || fabs(1.0 - h) <
tol)
return 0.0;
169 double pole[3] = {0, 0, copysign(1.0, a[2])};
170 double gc_area = fabs(
tri_area(a, b, pole));
174 double correction =
MAX(lat_area - gc_area, 0.0);
182 middle_lat[0] = a[0]+b[0];
183 middle_lat[1] = a[1]+b[1];
184 middle_lat[2] = a[2];
185 double scale = sqrt(middle_lat[0]*middle_lat[0]+middle_lat[1]*middle_lat[1]);
186 YAC_ASSERT(fabs(scale) >= 1e-18,
"internal error")
187 scale = sqrt(1.0 - a[2]*a[2]) / scale;
188 middle_lat[0] *= scale;
189 middle_lat[1] *= scale;
195 int negative_correction_flag;
198 if (fabs(scalar_base) < 1e-11) {
204 double norm_middle[3];
208 negative_correction_flag = scalar_a <= 0;
215 negative_correction_flag = scalar_middle_lat >= 0;
218 return negative_correction_flag?-correction:correction;
222 double base_vec[3],
double a[3],
double b[3]) {
224 double middle_lat[3];
229 double base_vec[3],
double a[3],
double b[3],
230 double * barycenter,
double sign) {
232 double middle_lat[3];
235 if (correction == 0.0)
return 0.0;
237 double middle_gc[3] = {a[0] + b[0], a[1] + b[1], a[2] + b[2]};
240 double temp_barycenter[3] =
241 {middle_lat[0] + middle_gc[0],
242 middle_lat[1] + middle_gc[1],
243 middle_lat[2] + middle_gc[2]};
246 barycenter[0] += temp_barycenter[0] * correction * sign;
247 barycenter[1] += temp_barycenter[1] * correction * sign;
248 barycenter[2] += temp_barycenter[2] * correction * sign;
250 return correction * sign;
280 if (M < 2)
return 0.0;
284 for (
size_t i = 0; i < M; i++)
289 if (M == 3 && !lat_flag) {
303 for (
size_t i = 1; i < M - 1; ++i) {
316 for (
size_t i = 0, j = M - 1; i < M; j = i++) {
354 double ref[3],
double a[3],
double b[3],
355 double * barycenter,
double sign) {
361 double * corners[3] = {b, ref, a};
362 for (
int i = 0, j = 2; i < 3; j = i++) {
367 sqrt(cross[0]*cross[0] + cross[1]*cross[1] + cross[2]*cross[2]);
372 double angle = asin(sin_angle);
374 double scale = 0.5 * angle / sin_angle * sign;
375 for (
int k = 0; k < 3; ++k) barycenter[k] += cross[k] * scale;
409 struct yac_grid_cell cell,
double * barycenter,
double sign) {
413 if (M < 2)
return 0.0;
417 for (
size_t i = 0; i < M; i++)
422 if (M == 3 && !lat_flag) {
436 for (
size_t i = 1; i < M - 1; ++i) {
452 for (
size_t i = 0, j = M - 1; i < M; j = i++) {
476 return (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]);
#define YAC_ASSERT(exp, msg)
static int compute_norm_vector(double a[], double b[], double norm[])
double yac_grid_cell_area(struct yac_grid_cell cell)
Area calculation of a spherical cell.
static double scalar_product(double a[], double b[])
static double tri_area_info(double ref[3], double a[3], double b[3], double *barycenter, double sign)
static double lat_edge_correction_info(double base_vec[3], double a[3], double b[3], double *barycenter, double sign)
double yac_grid_cell_area_info(struct yac_grid_cell cell, double *barycenter, double sign)
static double XYZtoLon(double a[3])
static double lat_edge_correction_(double base_vec[3], double a[3], double b[3], double *middle_lat)
static double lat_edge_correction(double base_vec[3], double a[3], double b[3])
static double tri_area(double const *restrict a, double const *restrict b, double const *restrict c)
Structs and interfaces for area calculations.
static void det2_error(double a, double b, double c, double d, double *restrict det, double *restrict det_error)
static void crossproduct_kahan(double const a[], double const b[], double cross[])
static void accu_product_eft(double a, double b, double *restrict accu, double *restrict accu_error)
static void normalise_vector(double v[])
static double get_angle(double a_lon, double b_lon)
static void accu_eft(double a, double *restrict accu, double *restrict error)
@ YAC_LAT_CIRCLE_EDGE
latitude circle
enum yac_edge_type * edge_type
double(* coordinates_xyz)[3]