/* 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 SMOOTH_INDICATOR_F_2D_HH #define SMOOTH_INDICATOR_F_2D_HH #include #include "smoothIndicatorF2D.h" #include "functors/lattice/reductionF3D.h" #include "utilities/vectorHelpers.h" #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #define M_PI2 1.57079632679489661923 namespace olb { template SmoothIndicatorCuboid2D::SmoothIndicatorCuboid2D(Vector center, S xLength, S yLength, S epsilon, S theta, S density, Vector vel) : _xLength(xLength),_yLength(yLength) { this->_pos = center; this->_circumRadius = .5*(std::sqrt(std::pow(_xLength, 2)+std::pow(_yLength, 2))) + 0.5*epsilon; this->_myMin = { center[0] - this->getCircumRadius(), center[1] - this->getCircumRadius() }; this->_myMax = { center[0] + this->getCircumRadius(), center[1] + this->getCircumRadius() }; this->_epsilon = epsilon; this->_theta = theta * M_PI/180.; T mass = xLength*yLength*density; T mofi = 1./12.*mass*(xLength*xLength+yLength*yLength); this->init(theta, vel, mass, mofi); } template bool SmoothIndicatorCuboid2D::operator()(T output[], const S input[]) { T xDist = input[0] - this->getPos()[0]; T yDist = input[1] - this->getPos()[1]; // counter-clockwise rotation by _theta=-theta around center T x = this->getPos()[0] + xDist*this->getRotationMatrix()[0] + yDist*this->getRotationMatrix()[2]; T y = this->getPos()[1] + xDist*this->getRotationMatrix()[1] + yDist*this->getRotationMatrix()[3]; xDist = fabs(x-this->getPos()[0]) - 0.5*(_xLength-this->getEpsilon()); yDist = fabs(y-this->getPos()[1]) - 0.5*(_yLength-this->getEpsilon()); if ( xDist <= 0 && yDist <= 0) { output[0] = 1.; return true; } if ( xDist >= this->getEpsilon() || yDist >= this->getEpsilon() ) { output[0] = 0.; return false; } // treating edges and corners as "rounded" if ( (xDist < this->getEpsilon() && xDist > 0) && (yDist < this->getEpsilon() && yDist > 0) ) { output[0] = T( (std::pow(cos(M_PI2*xDist/this->getEpsilon()), 2) * std::pow(cos(M_PI2*yDist/this->getEpsilon()), 2)) ); return true; } if ( xDist < this->getEpsilon() && xDist > 0 ) { output[0] = T( std::pow(cos(M_PI2*xDist/this->getEpsilon()), 2)); return true; } if ( yDist < this->getEpsilon() && yDist > 0 ) { output[0] = T( std::pow(cos(M_PI2*yDist/this->getEpsilon()), 2)); return true; } output[0] = 0.; return false; } template SmoothIndicatorCircle2D::SmoothIndicatorCircle2D(Vector center, S radius, S epsilon, S density, Vector vel) : _radius(radius) { this->_pos = center; this->_circumRadius = radius + 0.5*epsilon; this->_myMin = {center[0] - this->getCircumRadius(), center[1] - this->getCircumRadius()}; this->_myMax = {center[0] + this->getCircumRadius(), center[1] + this->getCircumRadius()}; this->_epsilon = epsilon; T mass = M_PI*radius*radius*density; T mofi = 0.5 * mass * radius * radius; this->init(0., vel, mass, mofi); } // returns true if x is inside the sphere template bool SmoothIndicatorCircle2D::operator()(T output[], const S input[]) { double distToCenter2 = std::pow(this->getPos()[0]-input[0], 2) + std::pow(this->getPos()[1]-input[1], 2); if ( distToCenter2 >= std::pow(this->_radius + 0.5*this->getEpsilon(), 2)) { output[0] = 0.; return false; } else if ( distToCenter2 <= std::pow(this->_radius - 0.5*this->getEpsilon(), 2)) { output[0] = 1.; return true; } else { // d is between 0 and _epsilon double d = std::sqrt(distToCenter2) - this->_radius + 0.5*this->getEpsilon(); output[0] = T(std::pow(cos(M_PI2*d/this->getEpsilon()), 2)); return true; } return false; } template SmoothIndicatorTriangle2D::SmoothIndicatorTriangle2D(Vector center, S radius, S epsilon, S theta, S density, Vector vel) { this->_pos = center; this->_circumRadius = radius + 0.5*epsilon; this->_myMin = {center[0] - this->getCircumRadius(), center[1] - this->getCircumRadius()}; this->_myMax = {center[0] + this->getCircumRadius(), center[1] + this->getCircumRadius()}; this->_epsilon = epsilon; this->_theta = theta * M_PI/180.; T smallRad = radius * .5; //sin(30) T halfEdge = radius * std::sqrt(3)/2.; // cos(30) T altitude = 1.5*radius; T base = std::sqrt(3)*radius; _PointA[0] = 0.; _PointA[1] = radius; _PointB[0] = - halfEdge; _PointB[1] = - smallRad; _PointC[0] = halfEdge; _PointC[1] = - smallRad; T invEps = 1./this->getEpsilon(); _ab = _PointB - _PointA; _ab.normalize(invEps); _ab_d = _ab[1]*_PointA[0] - _ab[0]*_PointA[1]; _bc = _PointC - _PointB; _bc.normalize(invEps); _bc_d = _bc[1]*_PointB[0] - _bc[0]*_PointB[1]; _ca = _PointA - _PointC; _ca.normalize(invEps); _ca_d = _ca[1]*_PointC[0] - _ca[0]*_PointC[1]; T mass = density*0.5*base*altitude; T mofi = mass*((altitude*altitude/18.)+(base*base/24.)); this->init(theta, vel, mass, mofi); } template bool SmoothIndicatorTriangle2D::operator()(T output[], const S input[]) { T xDist = input[0] - this->getPos()[0]; T yDist = input[1] - this->getPos()[1]; T x = xDist*this->getRotationMatrix()[0] + yDist*this->getRotationMatrix()[2]; T y = xDist*this->getRotationMatrix()[1] + yDist*this->getRotationMatrix()[3]; unsigned short area = 0; T dist_a = _bc[1]*x-_bc[0]*y - _bc_d; T dist_b = _ca[1]*x-_ca[0]*y - _ca_d; T dist_c = _ab[1]*x-_ab[0]*y - _ab_d; if (dist_c < 0) { area = (area | 100); } if (dist_a < 0) { area = (area | 10); } if (dist_b < 0) { area = (area | 1); } if (area == 111) { output[0] = 1.; return true; } if (area == 110 && dist_b < 1) { output[0] = T(std::pow(cos(M_PI2*dist_b), 2)); return true; } if (area == 101 && dist_a < 1) { output[0] = T(std::pow(cos(M_PI2*dist_a), 2)); return true; } if (area == 11 && dist_c < 1) { output[0] = T(std::pow(cos(M_PI2*dist_c), 2)); return true; } if (area == 1 && dist_a < 1 && dist_c < 1) { output[0] = T(std::pow(cos(M_PI2*dist_a), 2)*std::pow(cos(M_PI2*dist_c), 2)); return true; } if (area == 10 && dist_b < 1 && dist_c < 1) { output[0] = T(std::pow(cos(M_PI2*dist_b), 2)*std::pow(cos(M_PI2*dist_c), 2)); return true; } if (area == 100 && dist_b < 1 && dist_a < 1) { output[0] = T(std::pow(cos(M_PI2*dist_b), 2)*std::pow(cos(M_PI2*dist_a), 2)); return true; } output[0] = 0.; return false; } } // namespace olb #endif