From d9c623a7cdc7f7cd82e63de6cad4dccdf9138497 Mon Sep 17 00:00:00 2001 From: Christoph Rettinger <christoph.rettinger@fau.de> Date: Tue, 7 Nov 2017 08:16:55 +0100 Subject: [PATCH] pe_coupling: Adapted MSHS benchmark with new functionality and cleaned up --- .../MotionSingleHeavySphere.cpp | 194 ++++-------------- 1 file changed, 41 insertions(+), 153 deletions(-) diff --git a/apps/benchmarks/MotionSingleHeavySphere/MotionSingleHeavySphere.cpp b/apps/benchmarks/MotionSingleHeavySphere/MotionSingleHeavySphere.cpp index 29aba5b38..b037a5cbf 100644 --- a/apps/benchmarks/MotionSingleHeavySphere/MotionSingleHeavySphere.cpp +++ b/apps/benchmarks/MotionSingleHeavySphere/MotionSingleHeavySphere.cpp @@ -237,13 +237,14 @@ BoundaryHandling_T * MyBoundaryHandling::operator()( IBlock * const block, const return handling; } - -class ForceEval +/* + * Functionality for continuous logging of sphere properties during initial (resting) simulation + */ +class RestingSphereForceEvaluator { public: - ForceEval( SweepTimeloop* timeloop, - const shared_ptr< StructuredBlockStorage > & blocks, const ConstBlockDataID & bodyStorageID, - uint_t averageFrequency, const std::string & basefolder ) : + RestingSphereForceEvaluator( SweepTimeloop* timeloop, const shared_ptr< StructuredBlockStorage > & blocks, + const ConstBlockDataID & bodyStorageID, uint_t averageFrequency, const std::string & basefolder ) : timeloop_( timeloop ), blocks_( blocks ), bodyStorageID_( bodyStorageID ), averageFrequency_( averageFrequency ) { // initially write header in file @@ -325,15 +326,17 @@ private: }; -class SphereEval +/* + * Functionality for continuous logging of sphere properties during moving simulation + */ +class MovingSpherePropertyEvaluator { public: - SphereEval( SweepTimeloop* timeloop, - const shared_ptr< StructuredBlockStorage > & blocks, const ConstBlockDataID & bodyStorageID, - const std::string & basefolder, - const Vector3<real_t> & u_infty, const real_t Galileo, const real_t GalileoSim, - const real_t gravity, const real_t viscosity, const real_t diameter, const real_t densityRatio, - const uint_t numLBMSubCycles ) : + MovingSpherePropertyEvaluator( SweepTimeloop* timeloop, const shared_ptr< StructuredBlockStorage > & blocks, + const ConstBlockDataID & bodyStorageID, const std::string & basefolder, + const Vector3<real_t> & u_infty, const real_t Galileo, const real_t GalileoSim, + const real_t gravity, const real_t viscosity, const real_t diameter, + const real_t densityRatio, const uint_t numLBMSubCycles ) : timeloop_( timeloop ), blocks_( blocks ), bodyStorageID_( bodyStorageID ), u_infty_( u_infty ), gravity_( gravity ), viscosity_( viscosity ), diameter_( diameter ), densityRatio_( densityRatio ), numLBMSubCycles_( numLBMSubCycles ) @@ -494,95 +497,9 @@ private: }; -class ResetForce -{ - public: - ResetForce( const shared_ptr< StructuredBlockStorage > & blocks, const BlockDataID & bodyStorageID ) - : blocks_( blocks ), bodyStorageID_( bodyStorageID ) { } - - void operator()() - { - - for( auto blockIt = blocks_->begin(); blockIt != blocks_->end(); ++blockIt ) - { - for( auto bodyIt = pe::BodyIterator::begin< pe::Sphere >( *blockIt, bodyStorageID_); bodyIt != pe::BodyIterator::end<pe::Sphere>(); ++bodyIt ) - { - bodyIt->resetForceAndTorque(); - } - } - } - private: - const shared_ptr< StructuredBlockStorage > blocks_; - const BlockDataID bodyStorageID_; -}; - -class GravitationalForce -{ - public: - GravitationalForce( const shared_ptr< StructuredBlockStorage > & blocks, const BlockDataID & bodyStorageID, - real_t force ) - : blocks_( blocks ), bodyStorageID_( bodyStorageID ), force_( force ) { } - - void operator()() - { - - for( auto blockIt = blocks_->begin(); blockIt != blocks_->end(); ++blockIt ) - { - for( auto bodyIt = pe::LocalBodyIterator::begin< pe::Sphere >( *blockIt, bodyStorageID_); bodyIt != pe::LocalBodyIterator::end<pe::Sphere>(); ++bodyIt ) - { - bodyIt->addForce ( real_t(0), real_t(0), force_ ); - } - } - } - private: - const shared_ptr< StructuredBlockStorage > blocks_; - const BlockDataID bodyStorageID_; - const real_t force_; -}; - - - /* - * When using N LBM steps and one (larger) pe step in a single simulation step, the force applied on the pe bodies in each LBM sep has to be scaled - * by a factor of 1/N before running the pe simulation. This corresponds to an averaging of the force and torque over the N LBM steps and is said to - * damp oscillations. Usually, N = 2. - * See Ladd - "Numerical simulations of particulate suspensions via a discretized Boltzmann equation. Part 1. Theoretical foundation", 1994, p. 302 - */ -class AverageForce -{ - public: - AverageForce( const shared_ptr< StructuredBlockStorage > & blocks, const BlockDataID & bodyStorageID, - const uint_t lbmSubCycles ) - : blocks_( blocks ), bodyStorageID_( bodyStorageID ), invLbmSubCycles_( real_t(1) / real_c( lbmSubCycles ) ) { } - - void operator()() - { - Vector3<real_t> force( real_t(0) ); - Vector3<real_t> torque( real_t(0) ); - - for( auto blockIt = blocks_->begin(); blockIt != blocks_->end(); ++blockIt ) - { - for( auto bodyIt = pe::BodyIterator::begin( *blockIt, bodyStorageID_); bodyIt != pe::BodyIterator::end(); ++bodyIt ) - { - force = invLbmSubCycles_ * bodyIt->getForce(); - torque = invLbmSubCycles_ * bodyIt->getTorque(); - - bodyIt->resetForceAndTorque(); - - bodyIt->setForce ( force ); - bodyIt->setTorque( torque ); - } - } - } - private: - const shared_ptr< StructuredBlockStorage > blocks_; - const BlockDataID bodyStorageID_; - real_t invLbmSubCycles_; -}; - - -/* - * Result evaluation + * Result evaluation for the written VTK files + * * input: vel (fluid velocity), u_p (particle velocity), u_infty (inflow velocity) * * needed data: @@ -598,45 +515,37 @@ class AverageForce * vel_r_perp = vel_r * e_p_perp * vel_r_Hz_perp = vel_r * e_p_Hz_perp */ -class LogVTKInfo +class VTKInfoLogger { public: - LogVTKInfo( SweepTimeloop* timeloop, - const shared_ptr< StructuredBlockStorage > & blocks, const ConstBlockDataID & bodyStorageID, - const std::string & baseFolder, - const Vector3<real_t> u_infty, const real_t gravity, - const real_t diameter, const real_t densityRatio ) : + VTKInfoLogger( SweepTimeloop* timeloop, const shared_ptr< StructuredBlockStorage > & blocks, + const ConstBlockDataID & bodyStorageID, const std::string & baseFolder, + const Vector3<real_t> u_infty ) : timeloop_( timeloop ), blocks_( blocks ), bodyStorageID_( bodyStorageID ), baseFolder_( baseFolder ), u_infty_( u_infty ) - { - u_p_r_sqr_mag_ = real_t(0); - u_ref_ = std::sqrt( std::fabs(densityRatio - real_t(1)) * gravity * diameter ); - } + { } void operator()() { - Vector3<real_t> transVel( real_t(0) ); + Vector3<real_t> u_p( real_t(0) ); for( auto blockIt = blocks_->begin(); blockIt != blocks_->end(); ++blockIt ) { for( auto bodyIt = pe::LocalBodyIterator::begin<pe::Sphere>(*blockIt, bodyStorageID_ ); bodyIt != pe::LocalBodyIterator::end<pe::Sphere>(); ++bodyIt ) { - transVel = bodyIt->getLinearVel(); + u_p = bodyIt->getLinearVel(); } } WALBERLA_MPI_SECTION() { - mpi::allReduceInplace( transVel[0], mpi::SUM ); - mpi::allReduceInplace( transVel[1], mpi::SUM ); - mpi::allReduceInplace( transVel[2], mpi::SUM ); + mpi::allReduceInplace( u_p[0], mpi::SUM ); + mpi::allReduceInplace( u_p[1], mpi::SUM ); + mpi::allReduceInplace( u_p[2], mpi::SUM ); } - // store particle velocity - u_p_ = transVel; - - Vector3<real_t> u_p_r = u_p_ - u_infty_; - u_p_r_sqr_mag_ = u_p_r.sqrLength(); + Vector3<real_t> u_p_r = u_p - u_infty_; + real_t u_p_r_sqr_mag = u_p_r.sqrLength(); real_t u_p_H = std::sqrt( u_p_r[0] * u_p_r[0] + u_p_r[1] * u_p_r[1]); @@ -660,8 +569,8 @@ public: file.open( filename.c_str() ); file.precision(8); - file << "u_p = " << u_p_ << "\n"; - file << "u_p_r_2 = " << u_p_r_sqr_mag_ << "\n\n"; + file << "u_p = " << u_p << "\n"; + file << "u_p_r_2 = " << u_p_r_sqr_mag << "\n\n"; file << "e_{pH} = " << e_p_H << "\n"; file << "e_{pparallel} = " << e_p_parallel << "\n"; @@ -670,22 +579,6 @@ public: file.close(); } - - } - - Vector3<real_t> getParticleVel() const - { - return u_p_; - } - - real_t getURef() const - { - return u_ref_; - } - - real_t getUPRSqrMag() const - { - return u_p_r_sqr_mag_; } private: @@ -698,10 +591,6 @@ private: std::string baseFolder_; Vector3<real_t> u_infty_; - Vector3< real_t > u_p_; - real_t u_p_r_sqr_mag_; - real_t u_ref_; - }; class PDFFieldCopy @@ -869,7 +758,7 @@ int main( int argc, char **argv ) /////////////////////////// const int numProcs = MPIManager::instance()->numProcesses(); - if( numProcs < 16 ) WALBERLA_ABORT("At least 16 MPI ranks have to be used due to horizontal periodicity requirements!"); + WALBERLA_CHECK(numProcs % 16 != 0, "An integer multiple of 16 MPI ranks has to be used due to horizontal periodicity and domain decomposition requirements!"); uint_t XBlocks, YBlocks, ZBlocks; if( numProcs >= 192 ) @@ -1130,11 +1019,11 @@ int main( int argc, char **argv ) } // evaluate the drag force acting on the sphere... - shared_ptr< ForceEval > forceEval = walberla::make_shared< ForceEval >( &timeloopInit, blocks, bodyStorageID, averageFrequency, basefolder ); - timeloopInit.addFuncAfterTimeStep( SharedFunctor< ForceEval >( forceEval ), "Evaluating drag force" ); + shared_ptr< RestingSphereForceEvaluator > forceEval = walberla::make_shared< RestingSphereForceEvaluator >( &timeloopInit, blocks, bodyStorageID, averageFrequency, basefolder ); + timeloopInit.addFuncAfterTimeStep( SharedFunctor< RestingSphereForceEvaluator >( forceEval ), "Evaluating drag force" ); // ...then reset the force - timeloopInit.addFuncAfterTimeStep( ResetForce( blocks, bodyStorageID ), "Resetting force on body"); + timeloopInit.addFuncAfterTimeStep( pe_coupling::ForceTorqueOnBodiesResetter( blocks, bodyStorageID ), "Resetting force on body"); if( vtkIOInit ) { @@ -1300,8 +1189,7 @@ int main( int argc, char **argv ) } if( numLBMSubCycles != uint_t(1) ) - timeloop.addFuncAfterTimeStep( AverageForce( blocks, bodyStorageID, numLBMSubCycles ), "Force averaging for several LBM steps" ); - + timeloop.addFuncAfterTimeStep( pe_coupling::ForceTorqueOnBodiesScaler( blocks, bodyStorageID, real_t(1) / real_c(numLBMSubCycles) ), "Force averaging for several LBM steps" ); }else{ @@ -1341,15 +1229,16 @@ int main( int argc, char **argv ) } if( numLBMSubCycles != uint_t(1) ) - timeloop.addFuncAfterTimeStep( AverageForce( blocks, bodyStorageID, numLBMSubCycles ), "Force averaging for several LBM steps" ); + timeloop.addFuncAfterTimeStep( pe_coupling::ForceTorqueOnBodiesScaler( blocks, bodyStorageID, real_t(1) / real_c(numLBMSubCycles) ), "Force averaging for several LBM steps" ); } // add gravity - timeloop.addFuncAfterTimeStep( GravitationalForce( blocks, bodyStorageID, - gravity * ( densityRatio - real_t(1) ) * diameter * diameter * diameter * math::PI / real_t(6) ), "Add gravitational force" ); + Vector3<real_t> extForcesOnSphere( real_t(0), real_t(0), - gravity * ( densityRatio - real_t(1) ) * diameter * diameter * diameter * math::PI / real_t(6)); + timeloop.addFuncAfterTimeStep( pe_coupling::ForceOnBodiesAdder( blocks, bodyStorageID, extForcesOnSphere ), "Add external forces (gravity and buoyancy)" ); // evaluate the sphere properties - timeloop.addFuncAfterTimeStep( SphereEval( &timeloop, blocks, bodyStorageID, basefolder, uInfty, Galileo, GalileoSim, gravity, viscosity, diameter, densityRatio, numLBMSubCycles ), "Evaluate sphere"); + timeloop.addFuncAfterTimeStep( MovingSpherePropertyEvaluator( &timeloop, blocks, bodyStorageID, basefolder, uInfty, Galileo, GalileoSim, gravity, viscosity, diameter, densityRatio, numLBMSubCycles ), "Evaluate sphere"); // advance pe rigid body simulation timeloop.addFuncAfterTimeStep( pe_coupling::TimeStep( blocks, bodyStorageID, cr, syncCall, real_c(numLBMSubCycles), numPeSubCycles ), "pe Time Step" ); @@ -1363,8 +1252,7 @@ int main( int argc, char **argv ) pdfFieldVTK->addBeforeFunction( pdfGhostLayerSync ); // function to output plane infos for vtk output - shared_ptr< LogVTKInfo > logVTKInfo = walberla::make_shared< LogVTKInfo >( &timeloop, blocks, bodyStorageID, basefolder, uInfty, gravity, diameter, densityRatio ); - pdfFieldVTK->addBeforeFunction( SharedFunctor< LogVTKInfo >( logVTKInfo ) ); + pdfFieldVTK->addBeforeFunction(VTKInfoLogger( &timeloop, blocks, bodyStorageID, basefolder, uInfty )); // create folder for log_vtk files to not pollute the basefolder boost::filesystem::path tpath2( basefolder+"/log_vtk" ); -- GitLab