1 #ifndef teca_cartesian_mesh_util_h
2 #define teca_cartesian_mesh_util_h
6 #include "teca_cartesian_mesh.h"
8 #include "teca_metadata.h"
9 #include "teca_array_attributes.h"
13 #include <type_traits>
19 std::setprecision(std::numeric_limits<T>::digits10 + 1)
36 template <
typename n_t>
39 #define declare_equal_tt(cpp_t, atol, rtol) \
42 struct equal_tt<cpp_t> \
44 static cpp_t absTol() { return atol; } \
45 static cpp_t relTol() { return rtol; } \
48 declare_equal_tt(
float, 10.0f*std::numeric_limits<float>::epsilon(),
49 std::numeric_limits<float>::epsilon())
51 declare_equal_tt(
double, 10.0*std::numeric_limits<
double>::epsilon(),
52 std::numeric_limits<
float>::epsilon())
54 declare_equal_tt(
long double, std::numeric_limits<
double>::epsilon(),
55 std::numeric_limits<
double>::epsilon())
63 typename std::enable_if<std::is_floating_point<T>::value>::type* = 0)
66 T diff = std::abs(a - b);
81 bool equal(T a, T b, T relTol = 0, T absTol = 0,
82 typename std::enable_if<std::is_integral<T>::value>::type* = 0)
94 bool equal(T a, T b, std::string &diagnostic,
96 typename std::enable_if<std::is_floating_point<T>::value>::type* = 0)
99 T diff = std::abs(a - b);
105 bb = (bb > aa) ? bb : aa;
110 T eps = std::numeric_limits<T>::epsilon();
111 std::ostringstream os;
113 <<
" relTol=" <<
max_prec(T) << relTol
114 <<
" absTol=" <<
max_prec(T) << absTol
116 <<
" |a-b|/eps=" <<
max_prec(T) << diff/eps
117 <<
" max(|a|,|b|)*relTol=" <<
max_prec(T) << cc
118 <<
" |a-b|/max(|a|,|b|)=" <<
max_prec(T) << diff/bb
119 <<
" eps(" <<
typeid(a).name() <<
sizeof(T) <<
")="
121 diagnostic = os.str();
129 template <
typename T>
130 bool equal(T a, T b, std::string &diagnostic, T relTol = 0, T absTol = 0,
131 typename std::enable_if<std::is_integral<T>::value>::type* = 0)
138 std::ostringstream os;
139 os <<
typeid(a).name() <<
sizeof(T) <<
" " << a <<
" != " << b;
140 diagnostic = os.str();
160 length_missmatch = 2,
174 double absTol,
double relTol,
int &errorNo,
175 std::string &errorStr);
178 template<
typename data_t>
180 {
static bool eval(
const data_t &l,
const data_t &r) {
return l <= r; } };
183 template<
typename data_t>
185 {
static bool eval(
const data_t &l,
const data_t &r) {
return l >= r; } };
188 template<
typename data_t>
190 {
static bool eval(
const data_t &l,
const data_t &r) {
return l < r; } };
193 template<
typename data_t>
195 {
static bool eval(
const data_t &l,
const data_t &r) {
return l > r; } };
198 template<
typename data_t>
210 static unsigned long get_id(
bool lower,
211 unsigned long m_0,
unsigned long m_1)
220 template<
typename data_t>
232 static unsigned long get_id(
bool lower,
233 unsigned long m_0,
unsigned long m_1)
247 template <
typename data_t,
typename bracket_t = ascend_bracket<data_t>>
248 int index_of(
const data_t *data,
unsigned long l,
unsigned long r,
249 data_t val,
bool lower,
unsigned long &
id)
251 unsigned long m_0 = (r + l)/2;
252 unsigned long m_1 = m_0 + 1;
256 if (
equal(val, data[m_0]))
265 if (bracket_t::comp0_t::eval(val, data[m_0]) &&
266 bracket_t::comp1_t::eval(val, data[m_1]))
269 if (
equal(val, data[m_0]))
272 if (
equal(val, data[m_1]))
275 id = bracket_t::get_id(lower, m_0, m_1);
279 if (bracket_t::comp1_t::eval(val, data[m_0]))
282 return teca_coordinate_util::index_of<data_t, bracket_t>(
283 data, l, m_0, val, lower,
id);
288 return teca_coordinate_util::index_of<data_t, bracket_t>(
289 data, m_1, r, val, lower,
id);
299 template <
typename T>
300 int index_of(
const T *data,
size_t l,
size_t r, T val,
unsigned long &
id)
302 unsigned long m_0 = (r + l)/2;
303 unsigned long m_1 = m_0 + 1;
308 if (
equal(val, data[m_0], T(8)*std::numeric_limits<T>::epsilon()))
317 if (
equal(val, data[m_0], T(8)*std::numeric_limits<T>::epsilon()))
323 if (
equal(val, data[m_1], T(8)*std::numeric_limits<T>::epsilon()))
355 unsigned long *extent);
361 int index_of(
const const_p_teca_cartesian_mesh &mesh, T x, T y, T z,
362 unsigned long &i,
unsigned long &j,
unsigned long &k)
372 const NT *p_xc = std::dynamic_pointer_cast<TT>(xc)->get();
373 const NT *p_yc = std::dynamic_pointer_cast<TT>(yc)->get();
374 const NT *p_zc = std::dynamic_pointer_cast<TT>(zc)->get();
376 unsigned long nx = xc->size();
377 unsigned long ny = yc->size();
378 unsigned long nz = zc->size();
403 bool lower,
bool clamp,
const std::string &calendar,
404 const std::string &units,
const std::string &
date,
405 unsigned long &step);
412 const std::string &units,
const std::string &format, std::string &
date);
421 template <
typename int_t>
423 unsigned long &n_entities, std::vector<unsigned long> &counts,
424 std::vector<unsigned long> &offsets, std::vector<unsigned long> &ids)
430 unsigned long n_m1 = n_rows - 1;
431 for (
unsigned long i = 0; i < n_m1; ++i)
433 ids[i] = n_entities - 1;
434 if (index[i] != index[i+1])
437 ids[n_m1] = n_entities - 1;
440 counts.resize(n_entities);
442 for (
unsigned long i = 0; i < n_entities; ++i)
445 while ((q < n_m1) && (index[q] == index[q+1]))
454 offsets.resize(n_entities);
456 for (
unsigned long i = 1; i < n_entities; ++i)
457 offsets[i] = offsets[i-1] + counts[i-1];
470 template<
typename CT,
typename DT>
472 const CT *p_x,
const CT *p_y,
const CT *p_z,
473 const DT *p_data,
unsigned long ihi,
unsigned long jhi,
474 unsigned long khi,
unsigned long nx,
unsigned long nxy,
491 unsigned long ii = std::min(i + 1, ihi);
492 unsigned long jj = std::min(j + 1, jhi);
493 unsigned long kk = std::min(k + 1, khi);
496 unsigned long p = (cx - p_x[i]) <= (p_x[ii] - cx) ? i : ii;
497 unsigned long q = (cy - p_y[j]) <= (p_y[jj] - cy) ? j : jj;
498 unsigned long r = (cz - p_z[k]) <= (p_z[kk] - cz) ? k : kk;
501 val = p_data[p + nx*q + nxy*r];
517 template<
typename coord_t,
typename data_t>
519 const coord_t *p_y,
const data_t *p_data,
unsigned long ihi,
520 unsigned long jhi,
unsigned long nx, data_t &val)
534 unsigned long ii = std::min(i + 1, ihi);
535 unsigned long jj = std::min(j + 1, jhi);
538 unsigned long p = (cx - p_x[i]) <= (p_x[ii] - cx) ? i : ii;
539 unsigned long q = (cy - p_y[j]) <= (p_y[jj] - cy) ? j : jj;
542 val = p_data[p + nx*q];
557 template<
typename CT,
typename DT>
559 const CT *p_x,
const CT *p_y,
const CT *p_z,
560 const DT *p_data,
unsigned long ihi,
unsigned long jhi,
561 unsigned long khi,
unsigned long nx,
unsigned long nxy,
578 unsigned long ii = std::min(i + 1, ihi);
579 unsigned long jj = std::min(j + 1, jhi);
580 unsigned long kk = std::min(k + 1, khi);
583 CT wx = ii == i ? 0 : (cx - p_x[i])/(p_x[ii] - p_x[i]);
584 CT wy = jj == j ? 0 : (cy - p_y[j])/(p_y[jj] - p_y[j]);
585 CT wz = kk == k ? 0 : (cz - p_z[k])/(p_z[kk] - p_z[k]);
592 val = vx*vy*vz*p_data[ i + j*nx + k*nxy]
593 + wx*vy*vz*p_data[ii + j*nx + k*nxy]
594 + wx*wy*vz*p_data[ii + jj*nx + k*nxy]
595 + vx*wy*vz*p_data[ i + jj*nx + k*nxy]
596 + vx*vy*wz*p_data[ i + j*nx + kk*nxy]
597 + wx*vy*wz*p_data[ii + j*nx + kk*nxy]
598 + wx*wy*wz*p_data[ii + jj*nx + kk*nxy]
599 + vx*wy*wz*p_data[ i + jj*nx + kk*nxy];
616 template<
typename CT,
typename DT>
618 const DT *p_data,
unsigned long ihi,
unsigned long jhi,
619 unsigned long nx, DT &val)
633 unsigned long ii = std::min(i + 1, ihi);
634 unsigned long jj = std::min(j + 1, jhi);
637 CT wx = ii == i ? 0 : (cx - p_x[i])/(p_x[ii] - p_x[i]);
638 CT wy = jj == j ? 0 : (cy - p_y[j])/(p_y[jj] - p_y[j]);
644 val = vx*vy*p_data[ i + j*nx]
645 + wx*vy*p_data[ii + j*nx]
646 + wx*wy*p_data[ii + jj*nx]
647 + vx*wy*p_data[ i + jj*nx];
659 template<
typename CT,
typename DT>
660 int operator()(CT tx, CT ty, CT tz,
const CT *sx,
const CT *sy,
661 const CT *sz,
const DT *sa,
unsigned long ihi,
unsigned long jhi,
662 unsigned long khi,
unsigned long nx,
unsigned long nxy, DT &ta)
665 sx,sy,sz,sa, ihi,jhi,khi, nx,nxy, ta);
669 template<
typename CT,
typename DT>
670 int operator()(CT tx, CT ty,
const CT *sx,
const CT *sy,
671 const DT *sa,
unsigned long ihi,
unsigned long jhi,
672 unsigned long nx, DT &ta)
675 sx,sy,sa, ihi,jhi, nx, ta);
683 template<
typename CT,
typename DT>
684 int operator()(CT tx, CT ty, CT tz,
const CT *sx,
const CT *sy,
685 const CT *sz,
const DT *sa,
unsigned long ihi,
unsigned long jhi,
686 unsigned long khi,
unsigned long nx,
unsigned long nxy, DT &ta)
689 sx,sy,sz,sa, ihi,jhi,khi, nx,nxy, ta);
693 template<
typename CT,
typename DT>
694 int operator()(CT tx, CT ty,
const CT *sx,
const CT *sy,
695 const DT *sa,
unsigned long ihi,
unsigned long jhi,
696 unsigned long nx, DT &ta)
699 sx,sy,sa, ihi,jhi, nx, ta);
707 template <
typename num_t>
712 case teca_array_attributes::invalid_value:
713 TECA_ERROR(
"detected invalid_value in centering")
716 case teca_array_attributes::cell_centering:
718 case teca_array_attributes::x_face_centering:
721 case teca_array_attributes::y_face_centering:
724 case teca_array_attributes::z_face_centering:
727 case teca_array_attributes::x_edge_centering:
731 case teca_array_attributes::y_edge_centering:
735 case teca_array_attributes::z_edge_centering:
739 case teca_array_attributes::point_centering:
744 case teca_array_attributes::no_centering:
747 TECA_ERROR(
"this centering is undefined " << centering)
759 unsigned long *whole_extent,
double *bounds);
769 template <
typename num_t>
772 if ((part[0] >= whole[0]) && (part[0] <= whole[1]) &&
773 (part[1] >= whole[0]) && (part[1] <= whole[1]) &&
774 (part[2] >= whole[2]) && (part[2] <= whole[3]) &&
775 (part[3] >= whole[2]) && (part[3] <= whole[3]) &&
776 (part[4] >= whole[4]) && (part[4] <= whole[5]) &&
777 (part[5] >= whole[4]) && (part[5] <= whole[5]))
786 template <
typename num_t>
787 int covers(
const num_t *whole,
const num_t *part)
789 bool x_ascend = whole[0] <= whole[1];
790 bool y_ascend = whole[2] <= whole[3];
791 bool z_ascend = whole[4] <= whole[5];
793 (part[0] >= whole[0]) && (part[0] <= whole[1]) &&
794 (part[1] >= whole[0]) && (part[1] <= whole[1])) ||
796 (part[0] <= whole[0]) && (part[0] >= whole[1]) &&
797 (part[1] <= whole[0]) && (part[1] >= whole[1]))) &&
799 (part[2] >= whole[2]) && (part[2] <= whole[3]) &&
800 (part[3] >= whole[2]) && (part[3] <= whole[3])) ||
802 (part[2] <= whole[2]) && (part[2] >= whole[3]) &&
803 (part[3] <= whole[2]) && (part[3] >= whole[3]))) &&
805 (part[4] >= whole[4]) && (part[4] <= whole[5]) &&
806 (part[5] >= whole[4]) && (part[5] <= whole[5])) ||
808 (part[4] <= whole[4]) && (part[4] >= whole[5]) &&
809 (part[5] <= whole[4]) && (part[5] >= whole[5]))))
817 template <
typename num_t>
820 if ((((whole[0] <= whole[1]) && (part[0] <= part[1])) ||
821 ((whole[0] >= whole[1]) && (part[0] >= part[1]))) &&
822 (((whole[2] <= whole[3]) && (part[2] <= part[3])) ||
823 ((whole[2] >= whole[3]) && (part[2] >= part[3]))) &&
824 (((whole[4] <= whole[5]) && (part[4] <= part[5])) ||
825 ((whole[4] >= whole[5]) && (part[4] >= part[5]))))
837 unsigned long nz_max,
unsigned long *extent,
bool verbose);
844 unsigned long nz_max,
unsigned long *extent,
bool verbose);
853 const std::string &a_name,
const std::string a_units,
858 const std::string &a_name,
const std::string &a_units,
864 length_missmatch = 2,
867 unsupported_type = 5,
876 int validate(
const std::string &a_descriptor,
877 double a_abs_tol,
double a_rel_tol,
878 std::string &errorStr);
882 std::string m_reference_source;
883 std::string m_reference_name;
884 std::string m_reference_units;
886 std::vector<const_p_teca_variant_array> m_arrays;
887 std::vector<std::string> m_array_sources;
888 std::vector<std::string> m_array_names;
889 std::vector<std::string> m_array_units;
919 bool provides_geometry);
928 bool provides_geometry);
937 bool provides_geometry);
952 double m_absolute_tolerance;
953 double m_relative_tolerance;