#ifndef TRIPLETS_DATA_H_ #define TRIPLETS_DATA_H_ /** @file data.h data structures for triplets */ #include #include #include "layout-ptr.h" #include "vec.h" using namespace std; /** radius of a single tube */ #define TUBE_RADIUS 0.5f /** distance between tube centers */ #define TUBE_CENTER_DIST 1.01f #define TUBE_INV_CENTER_DIST 0.990099f /** data for skewlet binning */ //#define SKEWLET_BIN_HEIGHT (TUBE_CENTER_DIST * sqrtf(1.0f / 3.0f) + 0.5f) #define SKEWLET_BIN_HEIGHT 1.083123772f //#define SKEWLET_BIN_CENTER_DIST (2.0f * SKEWLET_BIN_HEIGHT) #define SKEWLET_BIN_CENTER_DIST (2.166247544f) //#define SKEWLET_BIN_INV_CENTER_DIST (1.0f / SKEWLET_BIN_CENTER_DIST) #define SKEWLET_BIN_INV_CENTER_DIST (0.461627759f) //#define SKEWLET_BIN_RADIUS (SKEWLET_BIN_HEIGHT * sqrtf(2.0f)) #define SKEWLET_BIN_RADIUS 1.531768328f /** drift time */ //#define DRIFT_TIME 245.0f #define DRIFT_TIME 245.0f /** drift time with epsilon */ #define DRIFT_TIME_PEPS 250.0f //#define DRIFT_TIME_PEPS 1000.0f /** total number of sector-layers */ #define NSECTOR_LAYERS (26 * 6) /** number of skewed rows */ #define NSKEWED_ROWS 8 /** inclusive start of skewed rows */ #define SKEWED_ROW_START 8 /** (exclusive) end of skewed rows */ #define SKEWED_ROW_END 16 /** (maximum) number of skewlet bins for a single skewed sector-layer */ #define NSL_SKEWLET_BINS 16 /** a single tube in the detector array */ template struct Tube_flex { typedef float layfield_t; typedef laygroup_t group_t; typedef Tube_flex Tube; hostdevice__ Tube_flex() {} Tube_flex(int id, fvec3 pos, fvec3 dir, float half_length, int row, int sector) : id(id), pos(pos), dir(dir), half_length(half_length), row(row), sector(sector), pivot_range_id(-1), skewed_range_id(-1) {} hostdevice__ operator Tube() const { Tube tube; tube.pos = (fvec3)pos; tube.dir = (fvec3)dir; tube.id = id; tube.row = row; tube.sector = sector; tube.pivot_range_id = pivot_range_id; tube.skewed_range_id = skewed_range_id; tube.half_length = half_length; return tube; } hostdevice__ Tube operator=(const Tube &tube) { pos = tube.pos; dir = tube.dir; id = tube.id; row = tube.row; sector = tube.sector; pivot_range_id = tube.pivot_range_id; skewed_range_id = tube.skewed_range_id; half_length = tube.half_length; return (Tube)*this; } /** tube position */ vec3_flex pos; /** tube direction (.z != 1 for skewed tubes) */ vec3_flex dir; /** the id of the tube, corresponds to position in the array */ union {signed short id; group_t dummy0;}; union { struct { /** tube row (numbered as per Panda experiment) */ signed char row; /** tube sector (numbered as per Panda experiment) */ signed char sector; /** the id of the pivot range to which the tube belongs, or -1 if none */ signed char pivot_range_id; /** the id of the skewed range to which the tube belongs, or -1 if it not skewed */ signed char skewed_range_id; }; group_t dummy1; }; /** tube's half-length */ union {float half_length; group_t dummy2; }; /** checks whether the tube is skewed */ hostdevice__ bool is_skewed(void) const { return dir.z != 1.0f; } /** gets the "position at z = 35", for non-skewed tubes this is just the position itself */ hostdevice__ fvec3 skewed_pos(void) const; /** checks whether this tube has another tube as neighbor */ hostdevice__ bool has_neighbor(const Tube &tube2) const; /** gets the minimum point of the tube */ hostdevice__ fvec3 min_pos(void) const { return (fvec3)pos - (fvec3)dir * half_length; } /** gets the maximum point of the tube */ hostdevice__ fvec3 max_pos(void) const { return (fvec3)pos + (fvec3)dir * half_length; } }; // struct Tube_flex typedef Tube_flex Tube; template struct layflex_t { typedef Tube_flex flex_t; }; /** reads the tubes from the file; tube0 is also filled in @param path the file to read @param [out] the length of the tube array, tube 0 included @returns the array of tubes allocated in pinned memory */ Tube *read_tubes(const char *path, int *n); /** gets distance between tubes taking skewed tubes into account */ inline hostdevice__ float tube_dist3d(const Tube &t1, const Tube &t2); /** a single hit, now with flexible layout */ template struct Hit_flex { typedef float layfield_t; typedef laygroup_t group_t; /** Hit type, for struct-internal use only */ typedef Hit_flex Hit; /** the time of the hit, whatever units of time used */ union {float t; group_t dummy0; }; /** the tube hit */ union {int tube_id; group_t dummy1; }; /** initializaing constructor */ Hit_flex(float t, int tube_id) : t(t), tube_id(tube_id) {} /** conversion to id layout */ hostdevice__ operator Hit() { return Hit(t, tube_id); } /** assignment to any layout */ hostdevice__ Hit operator=(const Hit &h) { t = h.t; tube_id = h.tube_id; return h; } }; // struct Hit_flex typedef Hit_flex Hit; // additional info for layout magic to work template struct layflex_t { typedef Hit_flex flex_t; }; /** a functor to compare hits (based on time only); this is not usable to compare hits for equality, as tube id is not taken into account */ struct hit_is_less { inline hostdevice__ bool operator()(const Hit &h0, const Hit &h1) const { return h0.t < h1.t; } }; /** reads the hits from the file @param path the file to read @param [in,out] n the length of the hit array at the output; if a value greater than -1 is specified on input, it is treated as the maximum number of hits to be read; less hits can actually be read if the file is smaller @returns the hit array allocated in pinned memory */ Hit *read_hits(const char *path, int *n); /** the range of integer values, [start, end) */ struct range { /* hostdevice__ range(int start = 0, int end = 0) : start(start), end(end) { }*/ static inline hostdevice__ range from(int start = 0, int end = 0) { range r; r.start = start; r.end = end; return r; } /** gets the empty range */ static inline hostdevice__ range empty(void) { return range::from(0, 0); } /** length of the range */ inline hostdevice__ int len(void) const { return end - start; } /** last element of the range; defined only for non-empty ranges */ inline hostdevice__ int last(void) const { return end - 1; } /** = start, just a counterpart of last */ inline hostdevice__ int first(void) const { return start; } /** checks whether the range is empty */ inline hostdevice__ bool is_empty(void) const { return start >= end; } /** add/subtract a value to both components of a range */ inline hostdevice__ range &operator+=(int shift) { start += shift; end += shift; return *this; } inline hostdevice__ range &operator-=(int shift) { start -= shift; end -= shift; return *this; } /** start of the range (inclusive) */ int start; /** end of the range (non-inclusive) */ int end; }; // struct range /** gets the next straight row (for the specified straight row) */ hostdevice__ inline int next_straight_row(int irow) { int next_row = irow + 1; if(next_row >= SKEWED_ROW_START && next_row < SKEWED_ROW_END) next_row = SKEWED_ROW_END; return next_row; } // next_straight_row /** adjusts straight row index (to account for missing skewed rows) */ hostdevice__ inline int straight_row_index(int irow) { int index = irow; if(irow >= SKEWED_ROW_END) index -= NSKEWED_ROWS; return index; } // straight_row_index #endif