// CELL BOUNDS //------------------------------------------------------------------------- std::pair<Vector, Vector> UniformGrid::cellBounds(Index elem) const { auto n = cellCoordinates(elem, m_numDivisions); Vector min(m_min[0]+n[0]*m_dist[0], m_min[1]+n[1]*m_dist[1], m_min[2]+n[2]*m_dist[2]); Vector max = min + Vector(m_dist[0], m_dist[1], m_dist[2]); return std::make_pair(min, max); }
Scalar RectilinearGrid::exitDistance(Index elem, const Vector &point, const Vector &dir) const { if (elem == InvalidIndex) return false; Vector raydir(dir.normalized()); std::array<Index,3> n = cellCoordinates(elem, m_numDivisions); assert(n[0] < m_numDivisions[0]); assert(n[1] < m_numDivisions[1]); assert(n[2] < m_numDivisions[2]); Scalar exitDist = -1; Scalar t0[3], t1[3]; for (int c=0; c<3; ++c) { Scalar x0 = m_coords[c][n[c]], x1 = m_coords[c][n[c]+1]; t0[c] = (x0-point[c])/raydir[c]; t1[c] = (x1-point[c])/raydir[c]; } for (int c=0; c<3; ++c) { if (t0[c] > 0) { if (exitDist<0 || exitDist>t0[c]) exitDist = t0[c]; } if (t1[c] > 0) { if (exitDist<0 || exitDist>t1[c]) exitDist = t1[c]; } } return exitDist; }
// INSIDE CHECK //------------------------------------------------------------------------- bool RectilinearGrid::inside(Index elem, const Vector &point) const { if (elem == InvalidIndex) return false; std::array<Index,3> n = cellCoordinates(elem, m_numDivisions); assert(n[0] < m_numDivisions[0]); assert(n[1] < m_numDivisions[1]); assert(n[2] < m_numDivisions[2]); for (int c=0; c<3; ++c) { Scalar x0 = m_coords[c][n[c]], x1 = m_coords[c][n[c]+1]; if (point[c] < x0) return false; if (point[c] > x1) return false; } return true; }
std::vector<Index> StructuredGridBase::getNeighborElements(Index elem) const { std::vector<Index> elems; if (elem == InvalidIndex) return elems; const Index dims[3] = { getNumDivisions(0), getNumDivisions(1), getNumDivisions(2) }; const auto coords = cellCoordinates(elem, dims); for (int d=0; d<3; ++d) { auto c = coords; if (coords[d] >= 1) { c[d] = coords[d]-1; elems.push_back(cellIndex(c[0], c[1], c[2], dims)); } if (coords[d] < dims[d]-2) { c[d] = coords[d]+1; elems.push_back(cellIndex(c[0], c[1], c[2], dims)); } } return elems; }
// IS GHOST CELL CHECK //------------------------------------------------------------------------- bool StructuredGridBase::isGhostCell(Index elem) const { if (elem == InvalidIndex) return false; Index dims[3]; std::array<Index,3> cellCoords; for (int c=0; c<3; ++c) { dims[c] = getNumDivisions(c); } cellCoords = cellCoordinates(elem, dims); for (int c=0; c<3; ++c) { if (cellCoords[c] < getNumGhostLayers(c, Bottom) || cellCoords[c]+getNumGhostLayers(c, Top)+1 >= dims[c]) { return true; } } return false; }
// INSIDE CHECK //------------------------------------------------------------------------- bool UniformGrid::inside(Index elem, const Vector &point) const { if (elem == InvalidIndex) return false; for (int c=0; c<3; ++c) { if (point[c] < m_min[c]) return false; if (point[c] > m_max[c]) return false; } std::array<Index,3> n = cellCoordinates(elem, m_numDivisions); for (int c=0; c<3; ++c) { Scalar x = m_min[c]+n[c]*m_dist[c]; if (point[c] < x) return false; if (point[c] > x+m_dist[c]) return false; } return true; }
// GET INTERPOLATOR //------------------------------------------------------------------------- GridInterface::Interpolator RectilinearGrid::getInterpolator(Index elem, const Vector &point, DataBase::Mapping mapping, GridInterface::InterpolationMode mode) const { vassert(inside(elem, point)); #ifdef INTERPOL_DEBUG if (!inside(elem, point)) { return Interpolator(); } #endif if (mapping == DataBase::Element) { std::vector<Scalar> weights(1, 1.); std::vector<Index> indices(1, elem); return Interpolator(weights, indices); } std::array<Index,3> n = cellCoordinates(elem, m_numDivisions); std::array<Index,8> cl = cellVertices(elem, m_numDivisions); Vector corner0(m_coords[0][n[0]], m_coords[1][n[1]], m_coords[2][n[2]]); Vector corner1(m_coords[0][n[0]+1], m_coords[1][n[1]+1], m_coords[2][n[2]+1]); const Vector diff = point-corner0; const Vector size = corner1-corner0; const Index nvert = 8; std::vector<Index> indices((mode==Linear || mode==Mean) ? nvert : 1); std::vector<Scalar> weights((mode==Linear || mode==Mean) ? nvert : 1); if (mode == Mean) { const Scalar w = Scalar(1)/nvert; for (Index i=0; i<nvert; ++i) { indices[i] = cl[i]; weights[i] = w; } } else if (mode == Linear) { vassert(nvert == 8); for (Index i=0; i<nvert; ++i) { indices[i] = cl[i]; } Vector ss = diff; for (int c=0; c<3; ++c) { ss[c] /= size[c]; } weights[0] = (1-ss[0])*(1-ss[1])*(1-ss[2]); weights[1] = ss[0]*(1-ss[1])*(1-ss[2]); weights[2] = ss[0]*ss[1]*(1-ss[2]); weights[3] = (1-ss[0])*ss[1]*(1-ss[2]); weights[4] = (1-ss[0])*(1-ss[1])*ss[2]; weights[5] = ss[0]*(1-ss[1])*ss[2]; weights[6] = ss[0]*ss[1]*ss[2]; weights[7] = (1-ss[0])*ss[1]*ss[2]; } else { weights[0] = 1; if (mode == First) { indices[0] = cl[0]; } else if(mode == Nearest) { Vector ss = diff; int nearest=0; for (int c=0; c<3; ++c) { nearest <<= 1; ss[c] /= size[c]; if (ss[c] < 0.5) nearest |= 1; } indices[0] = cl[nearest]; } } return Interpolator(weights, indices); }
// CELL BOUNDS //------------------------------------------------------------------------- std::pair<Vector, Vector> RectilinearGrid::cellBounds(Index elem) const { auto n = cellCoordinates(elem, m_numDivisions); Vector min(m_coords[0][n[0]], m_coords[1][n[1]], m_coords[2][n[2]]); Vector max(m_coords[0][n[0]+1], m_coords[1][n[1]+1], m_coords[2][n[2]+1]); return std::make_pair(min, max); }