/* Lattice Boltzmann sample, written in C++, using the OpenLB
* library
*
* Copyright (C) 2014 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.
*/
/* cavity3d.cpp:
* This example illustrates a flow in a cuboid, lid-driven cavity.
* This version is for parallel use. A version for sequential use
* is also available.
*/
#include "olb3D.h"
#ifndef OLB_PRECOMPILED // Unless precompiled version is used,
#include "olb3D.hh" // include full template code
#endif
#include
#include
#include
using namespace olb;
using namespace olb::descriptors;
using namespace olb::graphics;
using namespace olb::util;
using namespace std;
typedef double T;
#define DESCRIPTOR D3Q19<>
const int N = 30; // resolution of the model
//const int M = 1; // time discretization refinement
const T maxT = (T) 100.; // max. simulation time in s, SI unit
const T interval = 1.0; // Time intervall in seconds for convergence check
const T epsilon = 1e-3; // Residuum for convergence check
void prepareGeometry( UnitConverter const& converter, IndicatorF3D& indicator, SuperGeometry3D& superGeometry ) {
OstreamManager clout( std::cout,"prepareGeometry" );
clout << "Prepare Geometry ..." << std::endl;
// Sets material number for fluid and boundary
superGeometry.rename( 0,2,indicator );
superGeometry.rename( 2,1,1,1,1 );
T eps = converter.getConversionFactorLength();
Vector origin( -eps, converter.getCharPhysLength() - eps, -eps );
Vector extend( converter.getCharPhysLength() + 2*eps, 2*eps, converter.getCharPhysLength() + 2*eps );
IndicatorCuboid3D lid( extend,origin );
superGeometry.rename( 2,3,1,lid );
// Removes all not needed boundary voxels outside the surface
superGeometry.clean();
// Removes all not needed boundary voxels inside the surface
superGeometry.innerClean();
superGeometry.checkForErrors();
superGeometry.print();
clout << "Prepare Geometry ... OK" << std::endl;
}
void prepareLattice( UnitConverter const& converter,
SuperLattice3D& lattice,
Dynamics& bulkDynamics,
sOnLatticeBoundaryCondition3D& bc,
SuperGeometry3D& superGeometry ) {
OstreamManager clout( std::cout,"prepareLattice" );
clout << "Prepare Lattice ..." << std::endl;
const T omega = converter.getLatticeRelaxationFrequency();
// Material=0 -->do nothing
lattice.defineDynamics( superGeometry, 0, &instances::getNoDynamics() );
// Material=1 -->bulk dynamics
lattice.defineDynamics( superGeometry, 1, &bulkDynamics );
// Material=2,3 -->bulk dynamics, velocity boundary
lattice.defineDynamics( superGeometry, 2, &bulkDynamics );
lattice.defineDynamics( superGeometry, 3, &bulkDynamics );
bc.addVelocityBoundary( superGeometry, 2, omega );
bc.addVelocityBoundary( superGeometry, 3, omega );
clout << "Prepare Lattice ... OK" << std::endl;
}
void setBoundaryValues( UnitConverter const& converter,
SuperLattice3D& lattice, SuperGeometry3D& superGeometry, int iT ) {
OstreamManager clout( std::cout,"setBoundaryValues" );
if ( iT==0 ) {
AnalyticalConst3D rhoF( T( 1 ) );
AnalyticalConst3D uF( T( 0 ), T( 0 ), T( 0 ) );
auto bulkIndicator = superGeometry.getMaterialIndicator({1, 2, 3});
lattice.iniEquilibrium( bulkIndicator, rhoF, uF );
lattice.defineRhoU( bulkIndicator, rhoF, uF );
clout << converter.getCharLatticeVelocity() << std::endl;
AnalyticalConst3D uTop( converter.getCharLatticeVelocity(), T( 0 ), T( 0 ) );
lattice.defineU( superGeometry,3,uTop );
// Make the lattice ready for simulation
lattice.initialize();
}
}
void getResults( SuperLattice3D& sLattice,
UnitConverter const& converter, SuperGeometry3D& superGeometry,
int iT, Timer& timer, bool converged ) {
OstreamManager clout( std::cout,"getResults" );
SuperVTMwriter3D vtmWriter( "cavity3d" );
const T logT = ( T )1.;
const T vtkSave = ( T )1.;
const T imSave = ( T )5.;
if ( iT==0 ) {
SuperLatticeGeometry3D geometry( sLattice, superGeometry );
SuperLatticeCuboid3D cuboid( sLattice );
SuperLatticeRank3D rank( sLattice );
vtmWriter.write( geometry );
vtmWriter.write( cuboid );
vtmWriter.write( rank );
vtmWriter.createMasterFile();
}
// Get statistics
if ( (iT%converter.getLatticeTime( logT )==0 && iT>0) || converged ) {
timer.update( iT );
timer.printStep( 2 );
sLattice.getStatistics().print( iT,converter.getPhysTime( iT ) );
}
// Writes the VTK
if ( (iT%converter.getLatticeTime( vtkSave )==0 && iT>0) || converged ) {
SuperLatticePhysVelocity3D velocity( sLattice, converter );
SuperLatticePhysPressure3D pressure( sLattice, converter );
vtmWriter.addFunctor( velocity );
vtmWriter.addFunctor( pressure );
vtmWriter.write( iT );
}
// Writes the JPEG files
if ( (iT%converter.getLatticeTime( imSave )==0 && iT>0) || converged ) {
SuperLatticePhysVelocity3D velocity( sLattice, converter );
// define vector which span the plane
Vector u( 1,0,0 );
Vector v( 0,1,0 );
T tmp = T( converter.getCharPhysLength() / 2. );
T origin[3] = {tmp,tmp,tmp};
SuperEuklidNorm3D normVel( velocity );
BlockReduction3D2D planeReduction( normVel, origin, u, v, 600 );
// write a heatmap
heatmap::plotParam plotParam;
plotParam.maxValue = 1.;
plotParam.name = "velocity";
heatmap::write(planeReduction, iT, plotParam);
}
}
int main( int argc, char **argv ) {
// === 1st Step: Initialization ===
olbInit( &argc, &argv );
singleton::directories().setOutputDir( "./tmp/" );
OstreamManager clout( std::cout,"main" );
UnitConverterFromResolutionAndRelaxationTime const converter(
int {N}, // resolution: number of voxels per charPhysL
(T) 0.509, // latticeRelaxationTime: relaxation time, have to be greater than 0.5!
(T) 1.0, // charPhysLength: reference length of simulation geometry
(T) 1.0, // charPhysVelocity: maximal/highest expected velocity during simulation in __m / s__
(T) 0.001, // physViscosity: physical kinematic viscosity in __m^2 / s__
(T) 1.0 // physDensity: physical density in __kg / m^3__
);
// Prints the converter log as console output
converter.print();
// Writes the converter log in a file
converter.write("cavity3d");
// === 2nd Step: Prepare Geometry ===
// Instantiation of a unit cube by an indicator
Vector origin( T( 0 ) );
Vector extend( converter.getCharPhysLength() );
IndicatorCuboid3D cube( extend,origin );
// Instantiation of a cuboid geometry with weights
int noCuboids = singleton::mpi().getSize();
if ( noCuboids < 7 ) {
noCuboids = 7;
}
CuboidGeometry3D cuboidGeometry( cube, converter.getConversionFactorLength(), noCuboids );
// Instantiation of a load balancer
HeuristicLoadBalancer loadBalancer( cuboidGeometry );
// Instantiation of a super geometry
SuperGeometry3D superGeometry( cuboidGeometry, loadBalancer, 2 );
prepareGeometry( converter, cube, superGeometry );
// === 3rd Step: Prepare Lattice ===
SuperLattice3D sLattice( superGeometry );
ConstRhoBGKdynamics bulkDynamics (
converter.getLatticeRelaxationFrequency(), instances::getBulkMomenta() );
sOnLatticeBoundaryCondition3D sBoundaryCondition( sLattice );
createInterpBoundaryCondition3D >( sBoundaryCondition );
prepareLattice( converter, sLattice, bulkDynamics, sBoundaryCondition, superGeometry );
// === 4th Step: Main Loop with Timer ===
util::ValueTracer converge( converter.getLatticeTime(interval), epsilon );
Timer timer( converter.getLatticeTime( maxT ), std::pow(converter.getResolution(),3) );
timer.start();
for ( int iT = 0; iT <= converter.getLatticeTime( maxT ); ++iT ) {
if ( converge.hasConverged() ) {
clout << "Simulation converged." << endl;
getResults( sLattice, converter, superGeometry, iT, timer, converge.hasConverged() );
break;
}
// === 5th Step: Definition of Initial and Boundary Conditions ===
setBoundaryValues( converter, sLattice, superGeometry, iT );
// === 6th Step: Collide and Stream Execution ===
sLattice.collideAndStream();
// === 7th Step: Computation and Output of the Results ===
getResults( sLattice, converter, superGeometry, iT, timer, converge.hasConverged() );
converge.takeValue( sLattice.getStatistics().getAverageEnergy(), true );
}
timer.stop();
timer.printSummary();
}