/* This file is part of the OpenLB library * * Copyright (C) 2014 Peter Weisbrod * 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. */ /* phaseSeparation3d.cpp: * In this example the simulation is initialized with a given * density plus a small random number all over the domain. This * condition is unstable and leads to liquid-vapor phase separation. * Boundaries are assumed to be periodic. This example shows the * usage of multiphase flow. */ #include "olb3D.h" #include "olb3D.hh" // use only generic version! #include #include using namespace olb; using namespace olb::descriptors; using namespace olb::graphics; using namespace std; typedef double T; #define DESCRIPTOR ShanChenDynOmegaForcedD3Q19Descriptor // Parameters for the simulation setup const int maxIter = 2000; const int nx = 76; const int ny = 76; const int nz = 76; // Stores geometry information in form of material numbers void prepareGeometry( SuperGeometry3D& superGeometry ) { OstreamManager clout( std::cout,"prepareGeometry" ); clout << "Prepare Geometry ..." << std::endl; // Sets material number for fluid superGeometry.rename( 0,1 ); // 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; } // Set up the geometry of the simulation void prepareLattice( SuperLattice3D& sLattice, Dynamics& bulkDynamics1, SuperGeometry3D& superGeometry ) { // Material=1 -->bulk dynamics sLattice.defineDynamics( superGeometry, 1, &bulkDynamics1 ); // Initial conditions AnalyticalConst3D noise( .01 ); std::vector v( 3,T() ); AnalyticalConst3D zeroVelocity( v ); AnalyticalConst3D oldRho( .125 ); AnalyticalRandom3D random; AnalyticalIdentity3D newRho( random*noise+oldRho ); // Initialize all values of distribution functions to their local equilibrium sLattice.defineRhoU( superGeometry, 1, newRho, zeroVelocity ); sLattice.iniEquilibrium( superGeometry, 1, newRho, zeroVelocity ); // Make the lattice ready for simulation sLattice.initialize(); } // Output to console and files void getResults( SuperLattice3D& sLattice, int iT, SuperGeometry3D& superGeometry, Timer& timer ) { OstreamManager clout( std::cout,"getResults" ); SuperVTMwriter3D vtmWriter( "phaseSeparation3d" ); SuperLatticeVelocity3D velocity( sLattice ); SuperLatticeDensity3D density( sLattice ); vtmWriter.addFunctor( velocity ); vtmWriter.addFunctor( density ); const int vtkIter = 20; const int statIter = 20; if ( iT==0 ) { // Writes the geometry, cuboid no. and rank no. as vti file for visualization SuperLatticeGeometry3D geometry( sLattice, superGeometry ); SuperLatticeCuboid3D cuboid( sLattice ); SuperLatticeRank3D rank( sLattice ); vtmWriter.write( geometry ); vtmWriter.write( cuboid ); vtmWriter.write( rank ); vtmWriter.createMasterFile(); } // Writes the vtk files if ( iT%vtkIter==0 ) { clout << "Writing VTK and JPEG..." << std::endl; vtmWriter.write( iT ); BlockReduction3D2D planeReduction( density, {0, 0, 1} ); // write output as JPEG heatmap::write(planeReduction, iT); } // Writes output on the console if ( iT%statIter==0 ) { // Timer console output timer.update( iT ); timer.printStep(); // Lattice statistics console output sLattice.getStatistics().print( iT,iT ); } } int main( int argc, char *argv[] ) { // === 1st Step: Initialization === olbInit( &argc, &argv ); singleton::directories().setOutputDir( "./tmp/" ); OstreamManager clout( std::cout,"main" ); // display messages from every single mpi process //clout.setMultiOutput(true); const T omega1 = 1.0; const T G = -1.; // === 2rd Step: Prepare Geometry === // Instantiation of a cuboidGeometry with weights #ifdef PARALLEL_MODE_MPI const int noOfCuboids = singleton::mpi().getSize(); #else const int noOfCuboids = 1; #endif CuboidGeometry3D cuboidGeometry( 0, 0, 0, 1, nx, ny, nz, noOfCuboids ); // Periodic boundaries in x- and y- and z-direction cuboidGeometry.setPeriodicity( true, true, true ); // Instantiation of a loadBalancer HeuristicLoadBalancer loadBalancer( cuboidGeometry ); // Instantiation of a superGeometry SuperGeometry3D superGeometry( cuboidGeometry,loadBalancer,2 ); prepareGeometry( superGeometry ); // === 3rd Step: Prepare Lattice === SuperLattice3D sLattice( superGeometry ); ForcedShanChenBGKdynamics bulkDynamics1 ( omega1, instances::getExternalVelocityMomenta() ); std::vector rho0; rho0.push_back( 1 ); rho0.push_back( 1 ); CarnahanStarling interactionPotential( G ); ShanChenForcedSingleComponentGenerator3D coupling( G,rho0,interactionPotential ); sLattice.addLatticeCoupling( coupling, sLattice ); prepareLattice( sLattice, bulkDynamics1, superGeometry ); // === 4th Step: Main Loop === int iT = 0; clout << "starting simulation..." << endl; Timer timer( maxIter, superGeometry.getStatistics().getNvoxel() ); timer.start(); for ( iT = 0; iT < maxIter; ++iT ) { // === 5th Step: Definition of Initial and Boundary Conditions === // in this application no boundary conditions have to be adjusted // === 6th Step: Collide and Stream Execution === sLattice.collideAndStream(); sLattice.communicate(); sLattice.executeCoupling(); // === 7th Step: Computation and Output of the Results === getResults( sLattice, iT, superGeometry, timer ); } timer.stop(); timer.printSummary(); }