/* This file is part of the OpenLB library * * Copyright (C) 2016 Thomas Henn, Cyril Masquelier, Jan Marquardt, Mathias J. Krause * 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. */ #ifndef INDICATOR_F_2D_HH #define INDICATOR_F_2D_HH #include #include "indicatorF2D.h" #include "utilities/vectorHelpers.h" #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #define M_PI2 1.57079632679489661923 namespace olb { // Warning : the cuboid is only defined parallel to the plans x=0 and y=0 !!! // For other cuboids, please use the parallelepiped version template IndicatorF2DfromIndicatorF3D::IndicatorF2DfromIndicatorF3D(IndicatorF3D& indicator3D) : _indicator3D(indicator3D) { this->_myMin[0] = _indicator3D.getMin()[0]; this->_myMin[1] = _indicator3D.getMin()[1]; this->_myMax[0] = _indicator3D.getMax()[0]; this->_myMax[1] = _indicator3D.getMax()[1]; } template bool IndicatorF2DfromIndicatorF3D::operator()(bool output[], const S input[]) { S input3D[3]; input3D[0] = input[0]; input3D[1] = input[1]; input3D[2] = (_indicator3D.getMax()[2] - _indicator3D.getMin()[2]) * 0.5 + _indicator3D.getMin()[2]; _indicator3D(output, input3D); return true; } // Warning : the cuboid is only defined parallel to the plans x=0 and y=0 !!! // For other cuboids, please use the parallelepiped version template IndicatorCuboid2D::IndicatorCuboid2D(Vector extend, Vector origin, S theta) : _theta(theta) { this->_myMin = origin; this->_myMax = origin + extend; _center = origin + S(.5)*extend; _xLength = extend[0]; _yLength = extend[1]; } template IndicatorCuboid2D::IndicatorCuboid2D(S xLength, S yLength, Vector center, S theta ) : _center(center), _xLength(xLength), _yLength(yLength), _theta(-theta) { this->_myMin = {_center[0] - _xLength/2., _center[1] - _yLength/2.}; this->_myMax = {_center[0] + _xLength/2., _center[1] + _yLength/2.}; } // returns true if x is inside the cuboid template bool IndicatorCuboid2D::operator()(bool output[], const S input[]) { S x, y; if ( !util::nearZero(_theta) ) { x = _center[0] + (input[0] - _center[0])*std::cos(_theta) - (input[1] - _center[1])*std::sin(_theta); y = _center[1] + (input[0] - _center[0])*std::sin(_theta) + (input[1] - _center[1])*std::cos(_theta); } else { x = input[0]; y = input[1]; } output[0] = ( (fabs(_center[0] - x) < _xLength/2. || util::approxEqual(fabs(_center[0] - x),_xLength/2.) ) && (fabs(_center[1] - y) < _yLength/2. || util::approxEqual(fabs(_center[1] - y), _yLength/2.) ) ); return true; } // creator function template IndicatorCuboid2D* createIndicatorCuboid2D(XMLreader const& params, bool verbose) { OstreamManager clout(std::cout,"createIndicatorCuboid2D"); params.setWarningsOn(verbose); Vector center; S xLength; S yLength; std::stringstream xmlCenter( params.getAttribute("center") ); xmlCenter >> center[0] >> center[1]; std::stringstream xmlRadius( params.getAttribute("length") ); xmlRadius >> xLength >> yLength; return new IndicatorCuboid2D(xLength, yLength, center); } template IndicatorCircle2D::IndicatorCircle2D(Vector center, S radius) : _center(center), _radius2(radius*radius) { this->_myMin = _center - radius; this->_myMax = _center + radius; } // returns true if x is inside the circle template bool IndicatorCircle2D::operator()(bool output[], const S input[]) { output[0] = ( std::pow(_center[0] - input[0],2) + std::pow(_center[1] - input[1], 2) <= _radius2 ); return output[0]; } template bool IndicatorCircle2D::distance(S& distance, const Vector& origin, const Vector& direction, int iC) { S a = direction[0]*direction[0] + direction[1]*direction[1]; // returns 0 if point is at the boundary of the sphere if ( util::approxEqual(a,_radius2) ) { distance = S(0); return true; } // norm of direction a = sqrt(a); S b = 2.*((origin[0] - _center[0])*direction[0] + (origin[1] - _center[1])*direction[1])/a; S c = -_radius2 + (origin[0] - _center[0])*(origin[0] - _center[0]) + (origin[1] - _center[1])*(origin[1] - _center[1]); // discriminant S d = b*b - 4.*c; if (d < 0) { return false; } S x1 = (- b + sqrt(d)) *0.5; S x2 = (- b - sqrt(d)) *0.5; // case if origin is inside the sphere if ((x1<0.) || (x2<0.)) { if (x1>0.) { distance = x1; return true; } if (x2>0.) { distance = x2; return true; } } // case if origin is ouside the sphere else { distance = std::min(x1,x2); return true; } return false; } template bool IndicatorCircle2D::normal(Vector& normal, const Vector& origin, const Vector& direction, int iC) { S dist; if (!(distance(dist, origin, direction, iC)) ) { return false; } Vector intresection(origin + dist*direction); normal = intresection - _center; return true; } template IndicatorCircle2D* createIndicatorCircle2D(XMLreader const& params, bool verbose) { OstreamManager clout(std::cout,"createIndicatorCircle2D"); params.setWarningsOn(verbose); Vector center; S radius = 1; std::stringstream xmlCenter( params.getAttribute("center") ); xmlCenter >> center[0] >> center[1]; std::stringstream xmlRadius( params.getAttribute("radius") ); xmlRadius >> radius; return new IndicatorCircle2D(center, radius); } template IndicatorLayer2D::IndicatorLayer2D(IndicatorF2D& indicatorF, S layerSize) : _indicatorF(indicatorF), _layerSize(layerSize) { this->_myMin = indicatorF.getMin() - layerSize; this->_myMax = indicatorF.getMax() + layerSize; OLB_ASSERT( (this->_myMax[0]-this->_myMin[0]) <= std::numeric_limits::epsilon() ,"Indicator reduced to zero-set in x direction"); OLB_ASSERT( (this->_myMax[1]-this->_myMin[1]) <= std::numeric_limits::epsilon() ,"Indicator reduced to zero-set in y direction"); _isPositive = std::signbit(layerSize); } // returns true if x is inside the layer template bool IndicatorLayer2D::operator()(bool output[], const S input[]) { output[0] = !_isPositive; S r[2]; for (int iX =- 1; iX < 2; ++iX) { for (int iY =- 1; iY < 2; ++iY) { r[0] = input[0] + iX*_layerSize; r[1] = input[1] + iY*_layerSize; _indicatorF(output,r); if (output[0] == !_isPositive) { return true; } } } return true; } } // namespace olb #endif