/* This file is part of the OpenLB library
*
* Copyright (C) 2014-2015 Mathias J. Krause, Marie-Luise Maier
* 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 ANALYTICAL_FRAME_CHANGE_F_2D_HH
#define ANALYTICAL_FRAME_CHANGE_F_2D_HH
#include
#include
#include
#include "frameChangeF2D.h"
#include "frameChangeF3D.h"
#include "functors/genericF.h"
#include "analyticalF.h"
#include "functors/lattice/superBaseF2D.h"
#include "geometry/superGeometry2D.h"
#include "functors/lattice/superLatticeLocalF2D.h"
#include "core/superLattice2D.h"
#include "dynamics/lbHelpers.h" // for computation of lattice rho and velocity
#include "utilities/vectorHelpers.h" // for normalize
using namespace olb::util;
namespace olb {
template
PowerLaw2D::PowerLaw2D(std::vector axisPoint, std::vector axisDirection, T maxVelocity, T radius, T exponent) : AnalyticalF2D(2)
{
this->getName() = "PowerLaw2D";
_axisPoint.resize(2);
_axisDirection.resize(2);
for (int i = 0; i < 2; ++i) {
_axisDirection[i] = axisDirection[i];
_axisPoint[i] = axisPoint[i];
}
_maxVelocity = maxVelocity;
_radius = radius;
_exponent = exponent;
}
template
PowerLaw2D::PowerLaw2D(SuperGeometry2D& superGeometry, int material, T maxVelocity, T distance2Wall, T exponent) : AnalyticalF2D(2)
{
this->getName() = "PowerLaw2D";
_axisPoint.resize(2);
_axisDirection.resize(2);
_axisPoint = superGeometry.getStatistics().getCenterPhysR(material);
std::vector discreteNormal = superGeometry.getStatistics().computeDiscreteNormal(material);
for (int i = 0; i < 2; ++i) {
_axisDirection[i] = discreteNormal[i];
}
_radius = T(distance2Wall);
for (int iD = 0; iD < 2; iD++) {
_radius += (superGeometry.getStatistics().getPhysRadius(material)[iD]);
}
_maxVelocity = maxVelocity;
_exponent = exponent;
}
template
bool PowerLaw2D::operator()(T output[], const T x[])
{
T d = fabs(_axisDirection[1]*(x[0] - _axisPoint[0]) - _axisDirection[0]*(x[1] - _axisPoint[1]));
output[0] = _maxVelocity*_axisDirection[0]*(1. - pow(d/_radius,_exponent));
output[1] = _maxVelocity*_axisDirection[1]*(1. - pow(d/_radius,_exponent));
if ( 1. - pow(d/_radius,_exponent) < 0.) {
output[0] = T();
output[1] = T();
}
return true;
}
template
Poiseuille2D::Poiseuille2D(std::vector axisPoint, std::vector axisDirection, T maxVelocity, T radius) : PowerLaw2D(axisPoint, axisDirection, maxVelocity, radius, 2)
{
this->getName() = "Poiseuille2D";
}
template
Poiseuille2D::Poiseuille2D(SuperGeometry2D& superGeometry, int material, T maxVelocity, T distance2Wall) : PowerLaw2D(superGeometry, material, maxVelocity, distance2Wall, 2)
{
this->getName() = "Poiseuille2D";
}
template
PoiseuilleStrainRate2D::PoiseuilleStrainRate2D(UnitConverter const& converter, T ly)
: AnalyticalF2D(4), _lengthY(ly), _maxVelocity(converter.getCharPhysVelocity())
{
this->getName() = "PoiseuilleStrainRate2D";
}
template
bool PoiseuilleStrainRate2D::operator()(T output[], const S input[])
{
T y = input[1];
T DuDx = T();
T DuDy = (T) _maxVelocity*(-2.*(y-(_lengthY/2.))/((_lengthY/2.)*(_lengthY/2.)));
T DvDx = T();
T DvDy = T();
output[0] = (DuDx + DuDx)/2.;
output[1] = (DuDy + DvDx)/2.;
output[2] = (DvDx + DuDy)/2.;
output[3] = (DvDy + DvDy)/2.;
return true;
};
template
AnalyticalPorousVelocity2D::AnalyticalPorousVelocity2D(std::vector axisDirection_, T K_, T mu_, T gradP_, T radius_, T eps_)
: AnalyticalF2D(2), axisDirection(axisDirection_), K(K_), mu(mu_), gradP(gradP_),radius(radius_), eps(eps_)
{
this->getName() = "AnalyticalPorousVelocity2D";
};
template
T AnalyticalPorousVelocity2D::getPeakVelocity()
{
T uMax = K / mu*gradP*(1. - 1./(cosh((sqrt(1./K))*radius)));
return uMax/eps;
};
template
bool AnalyticalPorousVelocity2D::operator()(T output[], const T input[])
{
output[0] = K / mu*gradP*(1. - (cosh((sqrt(1./K))*(input[1] - radius)))/(cosh((sqrt(1./K))*radius)));
output[1] = K / mu*gradP*(1. - (cosh((sqrt(1./K))*(input[0] - radius)))/(cosh((sqrt(1./K))*radius)));
output[0] *= axisDirection[0]/eps;
output[1] *= axisDirection[1]/eps;
return true;
};
////////// Polar & Cartesian ///////////////
// constructor to obtain Cartesian coordinates of polar coordinates,
// with _polarOrigin, in x-y-plane
template
PolarToCartesian2D::PolarToCartesian2D(std::vector polarOrigin)
: AnalyticalF2D(2),
_polarOrigin(polarOrigin)
{
this->getName() = "const";
}
// operator returns Cartesian coordinates of polar coordinates,
// input is x[0] = radius , x[1] = phi
template
bool PolarToCartesian2D::operator()(T output[], const S x[])
{
output[0] = x[0]*cos(x[1]) + _polarOrigin[0];
output[1] = x[0]*sin(x[1]) + _polarOrigin[1];
return true;
}
// constructor to obtain polar coordinates of Cartesian coordinates
template
CartesianToPolar2D::CartesianToPolar2D(T cartesianOriginX,
T cartesianOriginY, T cartesianOriginZ,
T axisDirectionX, T axisDirectionY, T axisDirectionZ,
T orientationX, T orientationY, T orientationZ)
: AnalyticalF2D(2)
{
_cartesianOrigin.push_back(cartesianOriginX);
_cartesianOrigin.push_back(cartesianOriginY);
_cartesianOrigin.push_back(cartesianOriginZ);
_axisDirection.push_back(axisDirectionX);
_axisDirection.push_back(axisDirectionY);
_axisDirection.push_back(axisDirectionZ);
_orientation.push_back(orientationX);
_orientation.push_back(orientationY);
_orientation.push_back(orientationZ);
}
template
CartesianToPolar2D::CartesianToPolar2D(std::vector cartesianOrigin,
std::vector axisDirection,
std::vector orientation)
: AnalyticalF2D(2),
_cartesianOrigin(cartesianOrigin),
_axisDirection(axisDirection),
_orientation(orientation)
{
this->getName() = "const";
}
// operator returns polar coordinates, output[0] = radius(>= 0),
// output[1] = phi in [0, 2Pi)
template
bool CartesianToPolar2D::operator()(T output[], const S x[])
{
//Vector x_rot(x[this->getSourceDim()]); //// CAUSES ERROR
int dim = this->getSourceDim();
//std::cout<<"Source dim return: "< x_rot;
for (int i = 0; i < dim; ++i) {
x_rot[i] = x[i];
}
Vector e3(T(), T(), 1);
Vector axisDirection(_axisDirection);
Vector normal = crossProduct3D(axisDirection, e3);
Vector normalAxisDir(axisDirection);
normalAxisDir.normalize();
// if axis has to be rotated
if (!( util::nearZero(normalAxisDir[0]) && util::nearZero(normalAxisDir[1]) && util::nearZero(normalAxisDir[2]-1) ) ) {
if ( !util::nearZero(util::norm(_orientation)) ) {
normal = _orientation;
}
// normal is orientation direction
AngleBetweenVectors3D angle(fromVector3(e3), fromVector3(normal));
T tmp[3] = {_axisDirection[0],_axisDirection[1],_axisDirection[2]};
T alpha[1] = {};
angle(alpha, tmp);
// cross is rotation axis
//Vector cross = crossProduct3D(e3, axisDirection);
// rotation with angle alpha to rotAxisDir
RotationRoundAxis3D rotRAxis(_cartesianOrigin, fromVector3(normal), -alpha[0]);
T x_tmp[3] = {};
x_tmp[0] = x[0];
x_tmp[1] = x[1];
x_tmp[2] = x[2];
T tmp2[3] = {};
rotRAxis(tmp2,x_tmp);
x_rot[0] = tmp2[0];
x_rot[1] = tmp2[1];
x_rot[2] = tmp2[2];
}
// calculates r, phi related to cartesianAxisDirection and their origin
Vector difference;
difference[0] = x_rot[0] - _cartesianOrigin[0];
difference[1] = x_rot[1] - _cartesianOrigin[1];
T distance = T();
for (int i = 0; i < 2; ++i) {
distance += difference[i]*difference[i];
}
distance = sqrt(distance);
T phi[1] = {};
if (distance > T()) {
Vector e1(T(1), T(), T());
AngleBetweenVectors3D angle(fromVector3(e1), fromVector3(e3));
T x_help[3] = {difference[0],difference[1],0.};
angle(phi, x_help);
}
output[0] = distance;
output[1] = phi[0];
return true;
}
} // end namespace olb
#endif