/* This file is part of the OpenLB library
*
* Copyright (C) 2013, 2015 Gilles Zahnd, 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 LATTICE_FRAME_CHANGE_F_3D_HH
#define LATTICE_FRAME_CHANGE_F_3D_HH
#include
#include "latticeFrameChangeF3D.h"
#include "functors/analytical/frameChangeF2D.h"
#include "core/superLattice3D.h"
#include "dynamics/lbHelpers.h" // for computation of lattice rho and velocity
#include "utilities/vectorHelpers.h" // for normalize
#include "geometry/superGeometry3D.h"
namespace olb {
template
RotatingForceField3D::RotatingForceField3D
(SuperLattice3D& sLattice_, SuperGeometry3D& superGeometry_,
const UnitConverter& converter_, std::vector axisPoint_,
std::vector axisDirection_, T w_, bool centrifugeForceOn_,
bool coriolisForceOn_)
: SuperLatticeF3D(sLattice_,3), sg(superGeometry_),
converter(converter_), axisPoint(axisPoint_), axisDirection(axisDirection_),
w(w_), centrifugeForceOn(centrifugeForceOn_), coriolisForceOn(coriolisForceOn_),
velocity(sLattice_,converter_), rho(sLattice_)
{
this->getName() = "rotatingForce";
}
template
bool RotatingForceField3D::operator()(T output[], const int x[])
{
std::vector F_centri(3,0);
std::vector F_coriolis(3,0);
if ( this->_sLattice.getLoadBalancer().rank(x[0]) == singleton::mpi().getRank() ) {
// local coords are given, fetch local cell and compute value(s)
std::vector physR(3,T());
this->sg.getCuboidGeometry().getPhysR(&(physR[0]),&(x[0]));
T scalar = (physR[0]-axisPoint[0])*axisDirection[0]
+(physR[1]-axisPoint[1])*axisDirection[1]
+(physR[2]-axisPoint[2])*axisDirection[2];
if (centrifugeForceOn) {
F_centri[0] = w*w*(physR[0]-axisPoint[0]-scalar*axisDirection[0]);
F_centri[1] = w*w*(physR[1]-axisPoint[1]-scalar*axisDirection[1]);
F_centri[2] = w*w*(physR[2]-axisPoint[2]-scalar*axisDirection[2]);
}
if (coriolisForceOn) {
T _vel[3];
(velocity)(_vel,x);
F_coriolis[0] = -2*w*(axisDirection[1]*_vel[2]-axisDirection[2]*_vel[1]);
F_coriolis[1] = -2*w*(axisDirection[2]*_vel[0]-axisDirection[0]*_vel[2]);
F_coriolis[2] = -2*w*(axisDirection[0]*_vel[1]-axisDirection[1]*_vel[0]);
}
// return latticeForce
output[0] = (F_coriolis[0]+F_centri[0]) * converter.getConversionFactorTime() / converter.getConversionFactorVelocity();
output[1] = (F_coriolis[1]+F_centri[1]) * converter.getConversionFactorTime() / converter.getConversionFactorVelocity();
output[2] = (F_coriolis[2]+F_centri[2]) * converter.getConversionFactorTime() / converter.getConversionFactorVelocity();
}
return true;
}
template
HarmonicOscillatingRotatingForceField3D::HarmonicOscillatingRotatingForceField3D
(SuperLattice3D& sLattice_, SuperGeometry3D& superGeometry_,
const UnitConverter& converter_, std::vector axisPoint_,
std::vector axisDirection_, T amplitude_, T frequency_)
: SuperLatticeF3D(sLattice_,3), sg(superGeometry_),
converter(converter_), axisPoint(axisPoint_), axisDirection(axisDirection_),
amplitude(amplitude_), resonanceFrequency(2.*4.*std::atan(1.0)*frequency_), w(0.0), dwdt(0.0),
velocity(sLattice_,converter_)
{
this->getName() = "harmonicOscillatingrotatingForce";
}
template
void HarmonicOscillatingRotatingForceField3D::updateTimeStep(int iT) {
w = resonanceFrequency * amplitude * cos(resonanceFrequency*converter.getPhysTime(iT));
dwdt = -resonanceFrequency * resonanceFrequency * amplitude * sin(resonanceFrequency*converter.getPhysTime(iT));
}
template
bool HarmonicOscillatingRotatingForceField3D::operator()(T output[], const int x[])
{
std::vector F_centri(3,0);
std::vector F_coriolis(3,0);
std::vector F_euler(3,0);
if ( this->_sLattice.getLoadBalancer().rank(x[0]) == singleton::mpi().getRank() ) {
// local coords are given, fetch local cell and compute value(s)
std::vector physR(3,T());
this->sg.getCuboidGeometry().getPhysR(&(physR[0]),&(x[0]));
T scalar = (physR[0]-axisPoint[0])*axisDirection[0]
+(physR[1]-axisPoint[1])*axisDirection[1]
+(physR[2]-axisPoint[2])*axisDirection[2];
T r[3];
r[0] = physR[0]-axisPoint[0]-scalar*axisDirection[0];
r[1] = physR[1]-axisPoint[1]-scalar*axisDirection[1];
r[2] = physR[2]-axisPoint[2]-scalar*axisDirection[2];
F_centri[0] = w*w*(r[0]);
F_centri[1] = w*w*(r[1]);
F_centri[2] = w*w*(r[2]);
T _vel[3];
(velocity)(_vel,x);
F_coriolis[0] = -2*w*(axisDirection[1]*_vel[2]-axisDirection[2]*_vel[1]);
F_coriolis[1] = -2*w*(axisDirection[2]*_vel[0]-axisDirection[0]*_vel[2]);
F_coriolis[2] = -2*w*(axisDirection[0]*_vel[1]-axisDirection[1]*_vel[0]);
F_euler[0] = -dwdt*(axisDirection[1]*r[2]-axisDirection[2]*r[1]);
F_euler[1] = -dwdt*(axisDirection[2]*r[0]-axisDirection[0]*r[2]);
F_euler[2] = -dwdt*(axisDirection[0]*r[1]-axisDirection[1]*r[0]);
// return latticeForce
output[0] = (F_coriolis[0]+F_centri[0]+F_euler[0]) * converter.getConversionFactorTime() / converter.getConversionFactorVelocity();
output[1] = (F_coriolis[1]+F_centri[1]+F_euler[1]) * converter.getConversionFactorTime() / converter.getConversionFactorVelocity();
output[2] = (F_coriolis[2]+F_centri[2]+F_euler[2]) * converter.getConversionFactorTime() / converter.getConversionFactorVelocity();
}
return true;
}
} // end namespace olb
#endif