/* This file is part of the OpenLB library * * Copyright (C) 2006, 2007 Jonas Latt * E-mail contact: info@openlb.net * The most recent release of OpenLB can be downloaded at * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ /** \file * Set of functions commonly used in LB computations * -- header file */ #ifndef UTIL_H #define UTIL_H #include #include #include #include "dynamics/descriptorFunction.h" // patch due to ploblems with older compilers namespace std { template std::string to_string(const T &n) { std::ostringstream s; s << n; return s.str(); } } namespace olb { namespace util { template T norm(const std::vector& a); template inline int sign(T val) { return (0 < val) - (val < 0); } template inline bool aligned_to_x(const std::vector& vec) { return (vec[0]!=0 and vec[1]==0 and vec[2]==0); } template inline bool aligned_to_y(const std::vector& vec) { return (vec[0]==0 and vec[1]!=0 and vec[2]==0); } template inline bool aligned_to_z(const std::vector& vec) { return (vec[0]==0 and vec[1]==0 and vec[2]!=0); } template inline bool aligned_to_grid(const std::vector& vec) { return (aligned_to_x(vec) or aligned_to_y(vec) or aligned_to_z(vec)); } inline bool intersect ( int x0, int x1, int y0, int y1, int x0_, int x1_, int y0_, int y1_, int& newX0, int& newX1, int& newY0, int& newY1 ) { newX0 = std::max(x0,x0_); newY0 = std::max(y0,y0_); newX1 = std::min(x1,x1_); newY1 = std::min(y1,y1_); return newX1>=newX0 && newY1>=newY0; } inline bool intersect ( int x0, int x1, int y0, int y1, int z0, int z1, int x0_, int x1_, int y0_, int y1_, int z0_, int z1_, int& newX0, int& newX1, int& newY0, int& newY1, int& newZ0, int& newZ1 ) { newX0 = std::max(x0,x0_); newY0 = std::max(y0,y0_); newZ0 = std::max(z0,z0_); newX1 = std::min(x1,x1_); newY1 = std::min(y1,y1_); newZ1 = std::min(z1,z1_); return newX1>=newX0 && newY1>=newY0 && newZ1>=newZ0; } inline bool contained(int x, int y, int x0, int x1, int y0, int y1) { return x>=x0 && x<=x1 && y>=y0 && y<=y1; } inline bool contained(int x, int y, int z, int x0, int x1, int y0, int y1, int z0, int z1) { return x>=x0 && x<=x1 && y>=y0 && y<=y1 && z>=z0 && z<=z1; } template T sqr(T arg) { return arg*arg; } /// Compute norm square of a d-dimensional vector template T normSqr(const T u[D]) { T uSqr = T(); for (unsigned iD=0; iD < D; ++iD) { uSqr += u[iD]*u[iD]; } return uSqr; } /// Compute norm square of a d-dimensional vector template T normSqr(const Vector& u) { T uSqr = T(); for (unsigned iD=0; iD < D; ++iD) { uSqr += u[iD]*u[iD]; } return uSqr; } template T scalarProduct(const T u1[d], const T u2[d]) { T prod = T(); for (int iD=0; iD T scalarProduct(const std::vector& u1, const std::vector& u2) { T prod = T(); if (u1.size() == u2.size()) { for (int iD=0; iD struct TensorVal { static const int n = (DESCRIPTORBASE::d*(DESCRIPTORBASE::d+1))/2; ///< result stored in n }; /// Compute the opposite of a given direction template inline int opposite(int iPop) { return descriptors::opposite(iPop); } template class SubIndex { private: SubIndex() { for (int iVel=0; iVel(iVel,index)==value) { indices.push_back(iVel); } } } std::vector indices; template friend std::vector const& subIndex(); }; template std::vector const& subIndex() { static SubIndex subIndexSingleton; return subIndexSingleton.indices; } template int findVelocity(const int v[DESCRIPTORBASE::d]) { for (int iPop=0; iPop(iPop,iD) != v[iD]) { fit = false; break; } } if (fit) { return iPop; } } return DESCRIPTORBASE::q; } /** * finds distributions incoming into the wall * but we want the ones outgoing from the wall, * therefore we have to take the opposite ones. */ template class SubIndexOutgoing { private: SubIndexOutgoing() // finds the indexes outgoing from the walls { indices = util::subIndex(); for (unsigned iPop = 0; iPop < indices.size(); ++iPop) { indices[iPop] = util::opposite(indices[iPop]); } } std::vector indices; template friend std::vector const& subIndexOutgoing(); }; template std::vector const& subIndexOutgoing() { static SubIndexOutgoing subIndexOutgoingSingleton; return subIndexOutgoingSingleton.indices; } ///finds all the remaining indexes of a lattice given some other indexes template std::vector remainingIndexes(const std::vector &indices) { std::vector remaining; for (int iPop = 0; iPop < DESCRIPTORBASE::q; ++iPop) { bool found = false; for (unsigned jPop = 0; jPop < indices.size(); ++jPop) { if (indices[jPop] == iPop) { found = true; } } if (!found) { remaining.push_back(iPop); } } return remaining; } template class SubIndexOutgoing3DonEdges { private: SubIndexOutgoing3DonEdges() { int normalX,normalY,normalZ; typedef DESCRIPTORBASE L; switch (plane) { case 0: { normalX=0; if (normal1==1) { normalY= 1; } else { normalY=-1; } if (normal2==1) { normalZ= 1; } else { normalZ=-1; } } case 1: { normalY=0; if (normal1==1) { normalX= 1; } else { normalX=-1; } if (normal2==1) { normalZ= 1; } else { normalZ=-1; } } case 2: { normalZ=0; if (normal1==1) { normalX= 1; } else { normalX=-1; } if (normal2==1) { normalY= 1; } else { normalY=-1; } } } // add zero velocity //knownIndexes.push_back(0); // compute scalar product with boundary normal for all other velocities for (int iP=1; iP(iP,0)*normalX + descriptors::c(iP,1)*normalY + descriptors::c(iP,2)*normalZ<0) { indices.push_back(iP); } } } std::vector indices; template friend std::vector const& subIndexOutgoing3DonEdges(); }; template std::vector const& subIndexOutgoing3DonEdges() { static SubIndexOutgoing3DonEdges subIndexOutgoing3DonEdgesSingleton; return subIndexOutgoing3DonEdgesSingleton.indices; } // For 2D Corners template class SubIndexOutgoing2DonCorners { private: SubIndexOutgoing2DonCorners() { typedef DESCRIPTORBASE L; // add zero velocity //knownIndexes.push_back(0); // compute scalar product with boundary normal for all other velocities for (int iPop=1; iPop(iPop,0)*normalX + descriptors::c(iPop,1)*normalY<0) { indices.push_back(iPop); } } } std::vector indices; template friend std::vector const& subIndexOutgoing2DonCorners(); }; template std::vector const& subIndexOutgoing2DonCorners() { static SubIndexOutgoing2DonCorners subIndexOutgoing2DonCornersSingleton; return subIndexOutgoing2DonCornersSingleton.indices; } // For 3D Corners template class SubIndexOutgoing3DonCorners { private: SubIndexOutgoing3DonCorners() { typedef DESCRIPTORBASE L; // add zero velocity //knownIndexes.push_back(0); // compute scalar product with boundary normal for all other velocities for (int iP=1; iP(iP,0)*normalX + descriptors::c(iP,1)*normalY + descriptors::c(iP,2)*normalZ<0) { indices.push_back(iP); } } } std::vector indices; template friend std::vector const& subIndexOutgoing3DonCorners(); }; template std::vector const& subIndexOutgoing3DonCorners() { static SubIndexOutgoing3DonCorners subIndexOutgoing3DonCornersSingleton; return subIndexOutgoing3DonCornersSingleton.indices; } /// Util Function for Wall Model of Malaspinas /// get link with smallest angle to a vector template int get_nearest_link(const std::vector& vec) { T max=-1; int max_index = 0; for (int iQ=1; iQ c_i(DESCRIPTOR::c[iQ], DESCRIPTOR::c[iQ]+3); T tmp = util::scalarProduct(c_i, vec)/util::norm(c_i); if (tmp > max) { max = tmp; max_index = iQ; } } return max_index; } namespace tensorIndices2D { enum { xx=0, xy=1, yy=2 }; } namespace tensorIndices3D { enum { xx=0, xy=1, xz=2, yy=3, yz=4, zz=5 }; } /// compute lattice density from lattice pressure template T densityFromPressure( T latticePressure ) { // rho = p / c_s^2 + 1 return latticePressure * descriptors::invCs2() + 1.0; } /// compute lattice pressure from lattice density template T pressureFromDensity( T latticeDensity ) { // p = (rho - 1) * c_s^2 return (latticeDensity - 1.0) / descriptors::invCs2(); } } // namespace util } // namespace olb #endif