1 #ifndef teca_cartesian_mesh_util_h
2 #define teca_cartesian_mesh_util_h
6 #include "teca_config.h"
7 #include "teca_cartesian_mesh.h"
10 #include "teca_metadata.h"
11 #include "teca_array_attributes.h"
15 #include <type_traits>
19 #if defined(TECA_HAS_CUDA)
20 #define TECA_TARGET __host__ __device__
27 std::setprecision(std::numeric_limits<T>::digits10 + 1)
44 template <
typename n_t>
47 #define declare_equal_tt(cpp_t, atol, rtol) \
50 struct equal_tt<cpp_t> \
52 TECA_TARGET static cpp_t absTol() { return atol; } \
53 TECA_TARGET static cpp_t relTol() { return rtol; } \
56 declare_equal_tt(
float, 10.0f*std::numeric_limits<float>::epsilon(),
57 std::numeric_limits<float>::epsilon())
59 declare_equal_tt(
double, 10.0*std::numeric_limits<
double>::epsilon(),
60 std::numeric_limits<
float>::epsilon())
62 declare_equal_tt(
long double, std::numeric_limits<
double>::epsilon(),
63 std::numeric_limits<
double>::epsilon())
72 typename std::enable_if<std::is_floating_point<T>::value>::type* = 0)
75 T diff = std::abs(a - b);
91 bool equal(T a, T b, T relTol = 0, T absTol = 0,
92 typename std::enable_if<std::is_integral<T>::value>::type* = 0)
103 template <
typename T>
104 bool equal(T a, T b, std::string &diagnostic,
106 typename std::enable_if<std::is_floating_point<T>::value>::type* = 0)
109 T diff = std::abs(a - b);
115 bb = (bb > aa) ? bb : aa;
120 T eps = std::numeric_limits<T>::epsilon();
121 std::ostringstream os;
123 <<
" relTol=" <<
max_prec(T) << relTol
124 <<
" absTol=" <<
max_prec(T) << absTol
126 <<
" |a-b|/eps=" <<
max_prec(T) << diff/eps
127 <<
" max(|a|,|b|)*relTol=" <<
max_prec(T) << cc
128 <<
" |a-b|/max(|a|,|b|)=" <<
max_prec(T) << diff/bb
129 <<
" eps(" <<
typeid(a).name() <<
sizeof(T) <<
")="
131 diagnostic = os.str();
139 template <
typename T>
140 bool equal(T a, T b, std::string &diagnostic, T relTol = 0, T absTol = 0,
141 typename std::enable_if<std::is_integral<T>::value>::type* = 0)
148 std::ostringstream os;
149 os <<
typeid(a).name() <<
sizeof(T) <<
" " << a <<
" != " << b;
150 diagnostic = os.str();
170 length_missmatch = 2,
185 double absTol,
double relTol,
int &errorNo,
186 std::string &errorStr);
189 template<
typename data_t>
191 {
static bool eval(
const data_t &l,
const data_t &r) {
return l <= r; } };
194 template<
typename data_t>
196 {
static bool eval(
const data_t &l,
const data_t &r) {
return l >= r; } };
199 template<
typename data_t>
201 {
static bool eval(
const data_t &l,
const data_t &r) {
return l < r; } };
204 template<
typename data_t>
206 {
static bool eval(
const data_t &l,
const data_t &r) {
return l > r; } };
209 template<
typename data_t>
221 static unsigned long get_id(
bool lower,
222 unsigned long m_0,
unsigned long m_1)
231 template<
typename data_t>
243 static unsigned long get_id(
bool lower,
244 unsigned long m_0,
unsigned long m_1)
258 template <
typename data_t,
typename bracket_t = ascend_bracket<data_t>>
260 int index_of(
const data_t *data,
unsigned long l,
unsigned long r,
261 data_t val,
bool lower,
unsigned long &
id)
263 unsigned long m_0 = (r + l)/2;
264 unsigned long m_1 = m_0 + 1;
268 if (
equal(val, data[m_0]))
277 if (bracket_t::comp0_t::eval(val, data[m_0]) &&
278 bracket_t::comp1_t::eval(val, data[m_1]))
281 if (
equal(val, data[m_0]))
284 if (
equal(val, data[m_1]))
287 id = bracket_t::get_id(lower, m_0, m_1);
291 if (bracket_t::comp1_t::eval(val, data[m_0]))
294 return teca_coordinate_util::index_of<data_t, bracket_t>(
295 data, l, m_0, val, lower,
id);
300 return teca_coordinate_util::index_of<data_t, bracket_t>(
301 data, m_1, r, val, lower,
id);
311 template <
typename T>
313 int index_of(
const T *data,
size_t l,
size_t r, T val,
unsigned long &
id)
315 unsigned long m_0 = (r + l)/2;
316 unsigned long m_1 = m_0 + 1;
321 if (
equal(val, data[m_0], T(8)*std::numeric_limits<T>::epsilon()))
330 if (
equal(val, data[m_0], T(8)*std::numeric_limits<T>::epsilon()))
336 if (
equal(val, data[m_1], T(8)*std::numeric_limits<T>::epsilon()))
371 unsigned long *extent);
378 int index_of(
const const_p_teca_cartesian_mesh &mesh, T x, T y, T z,
379 unsigned long &i,
unsigned long &j,
unsigned long &k)
389 auto p_xc = std::dynamic_pointer_cast<TT>(xc)->get_cpu_accessible();
390 auto p_yc = std::dynamic_pointer_cast<TT>(yc)->get_cpu_accessible();
391 auto p_zc = std::dynamic_pointer_cast<TT>(zc)->get_cpu_accessible();
393 unsigned long nx = xc->size();
394 unsigned long ny = yc->size();
395 unsigned long nz = zc->size();
421 bool lower,
bool clamp,
const std::string &calendar,
422 const std::string &units,
const std::string &
date,
423 unsigned long &step);
431 const std::string &units,
const std::string &format, std::string &
date);
440 template <
typename int_t>
443 unsigned long &n_entities, std::vector<unsigned long> &counts,
444 std::vector<unsigned long> &offsets, std::vector<unsigned long> &ids)
450 unsigned long n_m1 = n_rows - 1;
451 for (
unsigned long i = 0; i < n_m1; ++i)
453 ids[i] = n_entities - 1;
454 if (index[i] != index[i+1])
457 ids[n_m1] = n_entities - 1;
460 counts.resize(n_entities);
462 for (
unsigned long i = 0; i < n_entities; ++i)
465 while ((q < n_m1) && (index[q] == index[q+1]))
474 offsets.resize(n_entities);
476 for (
unsigned long i = 1; i < n_entities; ++i)
477 offsets[i] = offsets[i-1] + counts[i-1];
490 template<
typename CT,
typename DT>
493 const CT *p_x,
const CT *p_y,
const CT *p_z,
494 const DT *p_data,
unsigned long ihi,
unsigned long jhi,
495 unsigned long khi,
unsigned long nx,
unsigned long nxy,
512 unsigned long ii = std::min(i + 1, ihi);
513 unsigned long jj = std::min(j + 1, jhi);
514 unsigned long kk = std::min(k + 1, khi);
517 unsigned long p = (cx - p_x[i]) <= (p_x[ii] - cx) ? i : ii;
518 unsigned long q = (cy - p_y[j]) <= (p_y[jj] - cy) ? j : jj;
519 unsigned long r = (cz - p_z[k]) <= (p_z[kk] - cz) ? k : kk;
522 val = p_data[p + nx*q + nxy*r];
538 template<
typename coord_t,
typename data_t>
541 const coord_t *p_y,
const data_t *p_data,
unsigned long ihi,
542 unsigned long jhi,
unsigned long nx, data_t &val)
556 unsigned long ii = std::min(i + 1, ihi);
557 unsigned long jj = std::min(j + 1, jhi);
560 unsigned long p = (cx - p_x[i]) <= (p_x[ii] - cx) ? i : ii;
561 unsigned long q = (cy - p_y[j]) <= (p_y[jj] - cy) ? j : jj;
564 val = p_data[p + nx*q];
579 template<
typename CT,
typename DT>
582 const CT *p_x,
const CT *p_y,
const CT *p_z,
583 const DT *p_data,
unsigned long ihi,
unsigned long jhi,
584 unsigned long khi,
unsigned long nx,
unsigned long nxy,
601 unsigned long ii = std::min(i + 1, ihi);
602 unsigned long jj = std::min(j + 1, jhi);
603 unsigned long kk = std::min(k + 1, khi);
606 CT wx = ii == i ? 0 : (cx - p_x[i])/(p_x[ii] - p_x[i]);
607 CT wy = jj == j ? 0 : (cy - p_y[j])/(p_y[jj] - p_y[j]);
608 CT wz = kk == k ? 0 : (cz - p_z[k])/(p_z[kk] - p_z[k]);
615 val = vx*vy*vz*p_data[ i + j*nx + k*nxy]
616 + wx*vy*vz*p_data[ii + j*nx + k*nxy]
617 + wx*wy*vz*p_data[ii + jj*nx + k*nxy]
618 + vx*wy*vz*p_data[ i + jj*nx + k*nxy]
619 + vx*vy*wz*p_data[ i + j*nx + kk*nxy]
620 + wx*vy*wz*p_data[ii + j*nx + kk*nxy]
621 + wx*wy*wz*p_data[ii + jj*nx + kk*nxy]
622 + vx*wy*wz*p_data[ i + jj*nx + kk*nxy];
639 template<
typename CT,
typename DT>
642 const DT *p_data,
unsigned long ihi,
unsigned long jhi,
643 unsigned long nx, DT &val)
657 unsigned long ii = std::min(i + 1, ihi);
658 unsigned long jj = std::min(j + 1, jhi);
661 CT wx = ii == i ? 0 : (cx - p_x[i])/(p_x[ii] - p_x[i]);
662 CT wy = jj == j ? 0 : (cy - p_y[j])/(p_y[jj] - p_y[j]);
668 val = vx*vy*p_data[ i + j*nx]
669 + wx*vy*p_data[ii + j*nx]
670 + wx*wy*p_data[ii + jj*nx]
671 + vx*wy*p_data[ i + jj*nx];
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 CT,
typename DT>
708 int operator()(CT tx, CT ty, CT tz,
const CT *sx,
const CT *sy,
709 const CT *sz,
const DT *sa,
unsigned long ihi,
unsigned long jhi,
710 unsigned long khi,
unsigned long nx,
unsigned long nxy, DT &ta)
713 sx,sy,sz,sa, ihi,jhi,khi, nx,nxy, ta);
717 template<
typename CT,
typename DT>
718 int operator()(CT tx, CT ty,
const CT *sx,
const CT *sy,
719 const DT *sa,
unsigned long ihi,
unsigned long jhi,
720 unsigned long nx, DT &ta)
723 sx,sy,sa, ihi,jhi, nx, ta);
732 template <
typename num_t>
738 case teca_array_attributes::invalid_value:
739 TECA_ERROR(
"detected invalid_value in centering")
742 case teca_array_attributes::cell_centering:
744 case teca_array_attributes::x_face_centering:
747 case teca_array_attributes::y_face_centering:
750 case teca_array_attributes::z_face_centering:
753 case teca_array_attributes::x_edge_centering:
757 case teca_array_attributes::y_edge_centering:
761 case teca_array_attributes::z_edge_centering:
765 case teca_array_attributes::point_centering:
770 case teca_array_attributes::no_centering:
773 TECA_ERROR(
"this centering is undefined " << centering)
786 unsigned long *whole_extent,
double *bounds);
797 template <
typename num_t>
801 if ((part[0] >= whole[0]) && (part[0] <= whole[1]) &&
802 (part[1] >= whole[0]) && (part[1] <= whole[1]) &&
803 (part[2] >= whole[2]) && (part[2] <= whole[3]) &&
804 (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]))
815 template <
typename num_t>
817 int covers(
const num_t *whole,
const num_t *part)
819 bool x_ascend = whole[0] <= whole[1];
820 bool y_ascend = whole[2] <= whole[3];
821 bool z_ascend = whole[4] <= whole[5];
823 (part[0] >= whole[0]) && (part[0] <= whole[1]) &&
824 (part[1] >= whole[0]) && (part[1] <= whole[1])) ||
826 (part[0] <= whole[0]) && (part[0] >= whole[1]) &&
827 (part[1] <= whole[0]) && (part[1] >= whole[1]))) &&
829 (part[2] >= whole[2]) && (part[2] <= whole[3]) &&
830 (part[3] >= whole[2]) && (part[3] <= whole[3])) ||
832 (part[2] <= whole[2]) && (part[2] >= whole[3]) &&
833 (part[3] <= whole[2]) && (part[3] >= whole[3]))) &&
835 (part[4] >= whole[4]) && (part[4] <= whole[5]) &&
836 (part[5] >= whole[4]) && (part[5] <= whole[5])) ||
838 (part[4] <= whole[4]) && (part[4] >= whole[5]) &&
839 (part[5] <= whole[4]) && (part[5] >= whole[5]))))
847 template <
typename num_t>
851 if ((((whole[0] <= whole[1]) && (part[0] <= part[1])) ||
852 ((whole[0] >= whole[1]) && (part[0] >= part[1]))) &&
853 (((whole[2] <= whole[3]) && (part[2] <= part[3])) ||
854 ((whole[2] >= whole[3]) && (part[2] >= part[3]))) &&
855 (((whole[4] <= whole[5]) && (part[4] <= part[5])) ||
856 ((whole[4] >= whole[5]) && (part[4] >= part[5]))))
869 unsigned long nz_max,
unsigned long *extent,
bool verbose);
877 unsigned long nz_max,
unsigned long *extent,
bool verbose);
885 void set_reference_array(
const std::string &a_source,
886 const std::string &a_name,
const std::string a_units,
890 void append_array(
const std::string &a_source,
891 const std::string &a_name,
const std::string &a_units,
897 length_missmatch = 2,
900 unsupported_type = 5,
909 int validate(
const std::string &a_descriptor,
910 double a_abs_tol,
double a_rel_tol,
911 std::string &errorStr);
915 std::string m_reference_source;
916 std::string m_reference_name;
917 std::string m_reference_units;
919 std::vector<const_p_teca_variant_array> m_arrays;
920 std::vector<std::string> m_array_sources;
921 std::vector<std::string> m_array_names;
922 std::vector<std::string> m_array_units;
941 int add_time_axis(
const std::string &source,
950 int add_x_coordinate_axis(
const std::string &source,
952 bool provides_geometry);
959 int add_y_coordinate_axis(
const std::string &source,
961 bool provides_geometry);
968 int add_z_coordinate_axis(
const std::string &source,
970 bool provides_geometry);
976 int validate_spatial_coordinate_axes(std::string &errorStr);
982 int validate_time_axis(std::string &errorStr);
985 double m_absolute_tolerance;
986 double m_relative_tolerance;