#ifndef _GRID3D_H_ #define _GRID3D_H_ #include #include #include /// written by Christoph Federrath, Sep 2010 /// based on a 2D class written by Philipp Girichidis class GRID3D { public: double * field; bool * is_set; private: long dimx, dimy, dimz, ntot; double xl, xh, yl, yh, zl, zh; double Lx, Ly, Lz; double minval, maxval; double cell_dx, cell_dy, cell_dz; static const bool Debug = false; ////////////////////////////////////////////////////////////// // CONSTRUCTOR & SET GLOBAL PROPERTIES ////////////////////////////////////////////////////////////// public: GRID3D() { field = 0; is_set = 0; minval = 0.0; maxval = 0.0; dimx = 0; dimy = 0; dimz = 0; ntot = 0; if (Debug) std::cout<<"GRID3D: default constructor called."< xhigh !! swapping these values !!" << std::endl; double temp = xlow; xlow = xhigh; xhigh = temp; } if(yhigh-ylow <= 0.0) { std::cout << " ylow > yhigh !! swapping these values !!" << std::endl; double temp = ylow; ylow = yhigh; yhigh = temp; } if(zhigh-zlow <= 0.0) { std::cout << " zlow > zhigh !! swapping these values !!" << std::endl; double temp = zlow; zlow = zhigh; zhigh = temp; } xl = xlow; xh = xhigh; yl = ylow; yh = yhigh; zl = zlow; zh = zhigh; Lx = xh-xl; Ly = yh-yl; Lz = zh-zl; cell_dx = (xhigh-xlow)/(double)dimx; cell_dy = (yhigh-ylow)/(double)dimy; cell_dz = (zhigh-zlow)/(double)dimz; } ////////////////////////////////////////////////////////////// // GLOBAL OBJECT INFORMATION ////////////////////////////////////////////////////////////// public: inline int get_dimx() { return dimx; } public: inline int get_dimy() { return dimy; } public: inline int get_dimz() { return dimz; } public: inline long get_ntot() { return ntot; } public: inline double get_xmin() { return xl; } public: inline double get_xmax() { return xh; } public: inline double get_ymin() { return yl; } public: inline double get_ymax() { return yh; } public: inline double get_zmin() { return zl; } public: inline double get_zmax() { return zh; } public: inline double get_dx() { return cell_dx; } public: inline double get_dy() { return cell_dy; } public: inline double get_dz() { return cell_dz; } public: inline double get_Lx() { return Lx; } public: inline double get_Ly() { return Ly; } public: inline double get_Lz() { return Lz; } public: inline double get_dV() { return cell_dx*cell_dy*cell_dz; } public: inline void print_bnds(std::ostream & out = std::cout) { out << " grid bounds" << " [" << xl << ":" << xh << "]" << " [" << yl << ":" << yh << "]" << " [" << zl << ":" << zh << "]" << std::endl; } public: inline void print_minmax(std::ostream & out = std::cout) { double MIN, MAX; minmax(MIN, MAX); out << " min value : " << minval << std::endl; out << " max value : " << maxval << std::endl; } public: inline void print_sum(std::ostream & out = std::cout) { double val = sum(); out << " sum : " << val << std::endl; } public: inline void print_sum_vw(std::ostream & out = std::cout) { double val_vw = sum_vw(); out << " sum_vw : " << val_vw << std::endl; } public: double first_set() { // find first data point that is set and use it as starting point for min and max long counter = 0; while(counter < ntot) { if (is_set[counter]) return field[counter]; counter++; } // no field is set so far!! std::cout << " NO DATA POINT IS SET IN YOUR FIELD, ABORT!!" << std::endl; exit(1); return 0.0; } public: double min() { double MIN = first_set(); for (long n=0; n MAX)) MAX = field[n]; maxval = MAX; return maxval; } public: void minmax(double &tmin, double &tmax) { tmin = first_set(); tmax = tmin; for (long n=0; n tmax)) tmax = field[n]; } minval = tmin; maxval = tmax; } public: double sum() { double ret = 0.; for (long n=0; n=0) && (ix=0) && (iy=0) && (iz= 0) ix = (int)(xmxl/Lx*(double)dimx); else ix = (int)(xmxl/Lx*(double)dimx)-1; if (ymyl >= 0) iy = (int)(ymyl/Ly*(double)dimy); else iy = (int)(ymyl/Ly*(double)dimy)-1; if (zmzl >= 0) iz = (int)(zmzl/Lz*(double)dimz); else iz = (int)(zmzl/Lz*(double)dimz)-1; } private: inline long index(int ix, int iy, int iz) { return iz*dimx*dimy + iy*dimx + ix; } private: inline double cell_center_x(int i) { return xl + ((double)i + 0.5)*cell_dx; } private: inline double cell_center_y(int i) { return yl + ((double)i + 0.5)*cell_dy; } private: inline double cell_center_z(int i) { return zl + ((double)i + 0.5)*cell_dz; } private: inline double get_cell_xlow(int ix) { return xl + ((double)ix)*cell_dx; } private: inline double get_cell_xhigh(int ix) { return xl + ((double)(ix+1))*cell_dx; } private: inline double get_cell_ylow(int iy) { return yl + ((double)iy)*cell_dy; } private: inline double get_cell_yhigh(int iy) { return yl + ((double)(iy+1))*cell_dy; } private: inline double get_cell_zlow(int iz) { return zl + ((double)iz)*cell_dz; } private: inline double get_cell_zhigh(int iz) { return zl + ((double)(iz+1))*cell_dz; } private: inline void cell_corner_x(int i, double &xlow, double &xhigh) { xlow = xl + ((double)i)*cell_dx; xhigh = xl + ((double)(i+1))*cell_dx; } private: inline void cell_corner_y(int i, double &ylow, double &yhigh) { ylow = yl + ((double)i)*cell_dy; yhigh = yl + ((double)(i+1))*cell_dy; } private: inline void cell_corner_z(int i, double &zlow, double &zhigh) { zlow = zl + ((double)i)*cell_dz; zhigh = zl + ((double)(i+1))*cell_dz; } private: inline void cell_corners(int ix, int iy, int iz, double &xlow, double &xhigh, double &ylow, double &yhigh, double &zlow, double &zhigh) { xlow = xl + ((double)ix)*cell_dx; xhigh = xl + ((double)(ix+1))*cell_dx; ylow = yl + ((double)iy)*cell_dy; yhigh = yl + ((double)(iy+1))*cell_dy; zlow = zl + ((double)iz)*cell_dz; zhigh = zl + ((double)(iz+1))*cell_dz; } /// this subroutine adds cell-centered data values given at (x,y,z) to the appropriate cell of the GRID3D /// taking into account all overlapping fractions of the original data /// This routine does not use interpolation (it is thus conserving the integral over all datavalues) public: inline void add_coord_fields(double x, double y, double z, double dx, double dy, double dz, double val) { // get cell at the center x,y double xlow = x-0.5*dx; double xhigh = x+0.5*dx; double ylow = y-0.5*dy; double yhigh = y+0.5*dy; double zlow = z-0.5*dz; double zhigh = z+0.5*dz; double cell_vol = cell_dx*cell_dy*cell_dz; double data_vol = dx*dy*dz; int ix0, ix1, iy0, iy1, iz0, iz1; get_bins(xlow, ylow, zlow, ix0, iy0, iz0); get_bins(xhigh, yhigh, zhigh, ix1, iy1, iz1); // check whether data cell fits entirely in grid cell // equal to ix0==ix1 and iy0==iy1 and iz0==iz1 if((ix0==ix1) && (iy0==iy1) && (iz0==iz1)) { if (Debug) std::cout << "data cell fits entirely in grid cell" << std::endl; add(ix0, iy0, iz0, val/cell_vol); } else { // get specific value for one cell // N_cells for dx*dy*dz = dx*dy*dz/(cell_dx*cell_dy*cell_dz) double spec_val = val/data_vol; // data cell occupies more than one cell in x direction if((ix0!=ix1) && (iy0==iy1) && (iz0==iz1)) { if (Debug) std::cout << "data cell occupies more than one cell in x direction" << std::endl; double frac; // left cell frac = (get_cell_xhigh(ix0)-xlow)*dy*dz/cell_vol; add(ix0,iy0,iz0,frac*spec_val); // middle cells for(int xx=ix0+1; xx= 0) && (ix < dimx) && (iy >= 0) && (iy < dimy) && (iz >= 0) && (iz < dimz)) { long n = index(ix,iy,iz); field[n] += val; is_set[n] = true; } } ////////////////////////////////////////////////////////////// // MANIPULATE ENTIRE FIELD ////////////////////////////////////////////////////////////// public: inline void clear() { for (long n=0; n