From d41eac2f5cee24d1a15e25d52aced7edd31016cf Mon Sep 17 00:00:00 2001
From: Christoph Rettinger <christoph.rettinger@fau.de>
Date: Tue, 25 Feb 2020 17:35:56 +0100
Subject: [PATCH] Added initialization kernel for hydrodynamic force for
 averaging

---
 .../ForcesOnSphereNearPlane.cpp               |  6 +++
 .../ObliqueWetCollision.cpp                   |  9 +++-
 .../SettlingSphereInBox.cpp                   | 12 +++--
 .../SphereMovingWithPrescribedVelocity.cpp    | 12 +++--
 .../SphereWallCollision.cpp                   |  9 +++-
 ...ydrodynamicForceTorqueForAveragingKernel.h | 54 +++++++++++++++++++
 .../SettlingSphere.cpp                        | 12 +++--
 7 files changed, 101 insertions(+), 13 deletions(-)
 create mode 100644 src/lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h

diff --git a/apps/benchmarks/FluidParticleCoupling/ForcesOnSphereNearPlane.cpp b/apps/benchmarks/FluidParticleCoupling/ForcesOnSphereNearPlane.cpp
index 77524bf2d..93da4ad7e 100644
--- a/apps/benchmarks/FluidParticleCoupling/ForcesOnSphereNearPlane.cpp
+++ b/apps/benchmarks/FluidParticleCoupling/ForcesOnSphereNearPlane.cpp
@@ -55,6 +55,7 @@
 #include "lbm_mesapd_coupling/utility/ParticleSelector.h"
 #include "lbm_mesapd_coupling/DataTypes.h"
 #include "lbm_mesapd_coupling/utility/AverageHydrodynamicForceTorqueKernel.h"
+#include "lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h"
 #include "lbm_mesapd_coupling/utility/ResetHydrodynamicForceTorqueKernel.h"
 #include "lbm_mesapd_coupling/utility/OmegaBulkAdaption.h"
 
@@ -714,6 +715,11 @@ int main( int argc, char **argv )
       timeloop.singleStep( timeloopTiming );
 
       // average force
+      if( timestep == 0 )
+      {
+         lbm_mesapd_coupling::InitializeHydrodynamicForceTorqueForAveragingKernel initializeHydrodynamicForceTorqueForAveragingKernel;
+         ps->forEachParticle(false, mesa_pd::kernel::SelectAll(), *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor );
+      }
       ps->forEachParticle(false, mesa_pd::kernel::SelectAll(), *accessor, averageHydrodynamicForceTorque, *accessor );
 
       // evaluation
diff --git a/apps/benchmarks/FluidParticleCoupling/ObliqueWetCollision.cpp b/apps/benchmarks/FluidParticleCoupling/ObliqueWetCollision.cpp
index 12ef798b2..0e1aa9653 100644
--- a/apps/benchmarks/FluidParticleCoupling/ObliqueWetCollision.cpp
+++ b/apps/benchmarks/FluidParticleCoupling/ObliqueWetCollision.cpp
@@ -65,6 +65,7 @@
 #include "lbm_mesapd_coupling/DataTypes.h"
 #include "lbm_mesapd_coupling/utility/AverageHydrodynamicForceTorqueKernel.h"
 #include "lbm_mesapd_coupling/utility/AddHydrodynamicInteractionKernel.h"
+#include "lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h"
 #include "lbm_mesapd_coupling/utility/ResetHydrodynamicForceTorqueKernel.h"
 #include "lbm_mesapd_coupling/utility/LubricationCorrectionKernel.h"
 #include "lbm_mesapd_coupling/utility/OmegaBulkAdaption.h"
@@ -1057,9 +1058,13 @@ int main( int argc, char **argv )
       // perform a single simulation step -> this contains LBM and setting of the hydrodynamic interactions
       timeloop.singleStep( timeloopTiming );
 
-
-      if( averageForceTorqueOverTwoTimeSteps && i!= 0)
+      if( averageForceTorqueOverTwoTimeSteps )
       {
+         if( i == 0 )
+         {
+            lbm_mesapd_coupling::InitializeHydrodynamicForceTorqueForAveragingKernel initializeHydrodynamicForceTorqueForAveragingKernel;
+            ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor );
+         }
          ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, averageHydrodynamicForceTorque, *accessor );
       }
 
diff --git a/apps/benchmarks/FluidParticleCoupling/SettlingSphereInBox.cpp b/apps/benchmarks/FluidParticleCoupling/SettlingSphereInBox.cpp
index b8a2b2c19..d0d186c16 100644
--- a/apps/benchmarks/FluidParticleCoupling/SettlingSphereInBox.cpp
+++ b/apps/benchmarks/FluidParticleCoupling/SettlingSphereInBox.cpp
@@ -58,6 +58,7 @@
 #include "lbm_mesapd_coupling/DataTypes.h"
 #include "lbm_mesapd_coupling/utility/AverageHydrodynamicForceTorqueKernel.h"
 #include "lbm_mesapd_coupling/utility/AddHydrodynamicInteractionKernel.h"
+#include "lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h"
 #include "lbm_mesapd_coupling/utility/ResetHydrodynamicForceTorqueKernel.h"
 #include "lbm_mesapd_coupling/utility/LubricationCorrectionKernel.h"
 #include "lbm_mesapd_coupling/utility/OmegaBulkAdaption.h"
@@ -372,7 +373,7 @@ int main( int argc, char **argv )
 
    //numerical parameters
    uint_t numberOfCellsInHorizontalDirection = uint_t(135);
-   bool averageForceTorqueOverTwoTimSteps = true;
+   bool averageForceTorqueOverTwoTimeSteps = true;
    bool conserveMomentum = false;
    uint_t numRPDSubCycles = uint_t(1);
    bool useVelocityVerlet = true;
@@ -393,7 +394,7 @@ int main( int argc, char **argv )
       if( std::strcmp( argv[i], "--fluidType" )            == 0 ) { fluidType = uint_c( std::atof( argv[++i] ) ); continue; }
       if( std::strcmp( argv[i], "--numRPDSubCycles" )      == 0 ) { numRPDSubCycles = uint_c( std::atof( argv[++i] ) ); continue; }
       if( std::strcmp( argv[i], "--resolution" )           == 0 ) { numberOfCellsInHorizontalDirection = uint_c( std::atof( argv[++i] ) ); continue; }
-      if( std::strcmp( argv[i], "--noForceAveraging" )     == 0 ) { averageForceTorqueOverTwoTimSteps = false; continue; }
+      if( std::strcmp( argv[i], "--noForceAveraging" )     == 0 ) { averageForceTorqueOverTwoTimeSteps = false; continue; }
       if( std::strcmp( argv[i], "--conserveMomentum" )     == 0 ) { conserveMomentum = true; continue; }
       if( std::strcmp( argv[i], "--baseFolder" )           == 0 ) { baseFolder = argv[++i]; continue; }
       if( std::strcmp( argv[i], "--useEulerIntegrator" )   == 0 ) { useVelocityVerlet = false; continue; }
@@ -811,8 +812,13 @@ int main( int argc, char **argv )
 
       timeloopTiming["RPD"].start();
 
-      if( averageForceTorqueOverTwoTimSteps && i!= 0)
+      if( averageForceTorqueOverTwoTimeSteps )
       {
+         if( i == 0 )
+         {
+            lbm_mesapd_coupling::InitializeHydrodynamicForceTorqueForAveragingKernel initializeHydrodynamicForceTorqueForAveragingKernel;
+            ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor );
+         }
          ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, averageHydrodynamicForceTorque, *accessor );
       }
 
diff --git a/apps/benchmarks/FluidParticleCoupling/SphereMovingWithPrescribedVelocity.cpp b/apps/benchmarks/FluidParticleCoupling/SphereMovingWithPrescribedVelocity.cpp
index 644a887df..eac6530d0 100644
--- a/apps/benchmarks/FluidParticleCoupling/SphereMovingWithPrescribedVelocity.cpp
+++ b/apps/benchmarks/FluidParticleCoupling/SphereMovingWithPrescribedVelocity.cpp
@@ -63,6 +63,7 @@
 #include "lbm_mesapd_coupling/DataTypes.h"
 #include "lbm_mesapd_coupling/utility/AverageHydrodynamicForceTorqueKernel.h"
 #include "lbm_mesapd_coupling/utility/AddHydrodynamicInteractionKernel.h"
+#include "lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h"
 #include "lbm_mesapd_coupling/utility/ResetHydrodynamicForceTorqueKernel.h"
 #include "lbm_mesapd_coupling/utility/OmegaBulkAdaption.h"
 
@@ -393,7 +394,7 @@ int main( int argc, char **argv )
    bool vtkOutputAtEnd = true;
 
    //numerical parameters
-   bool averageForceTorqueOverTwoTimSteps = true;
+   bool averageForceTorqueOverTwoTimeSteps = true;
    bool conserveMomentum = false;
    uint_t numRPDSubCycles = uint_t(1);
    std::string reconstructorType = "Grad"; // Eq, EAN, Ext, Grad
@@ -424,7 +425,7 @@ int main( int argc, char **argv )
       if( std::strcmp( argv[i], "--logDensity" )           == 0 ) { logDensity = true; continue; }
       if( std::strcmp( argv[i], "--vtkIOFreq" )            == 0 ) { vtkIOFreq = uint_c( std::atof( argv[++i] ) ); continue; }
       if( std::strcmp( argv[i], "--numRPDSubCycles" )      == 0 ) { numRPDSubCycles = uint_c( std::atof( argv[++i] ) ); continue; }
-      if( std::strcmp( argv[i], "--noForceAveraging" )     == 0 ) { averageForceTorqueOverTwoTimSteps = false; continue; }
+      if( std::strcmp( argv[i], "--noForceAveraging" )     == 0 ) { averageForceTorqueOverTwoTimeSteps = false; continue; }
       if( std::strcmp( argv[i], "--conserveMomentum" )     == 0 ) { conserveMomentum = true; continue; }
       if( std::strcmp( argv[i], "--baseFolder" )           == 0 ) { baseFolder = argv[++i]; continue; }
       if( std::strcmp( argv[i], "--reconstructorType" )    == 0 ) { reconstructorType = argv[++i]; continue; }
@@ -768,8 +769,13 @@ int main( int argc, char **argv )
 
       timeloopTiming["RPD"].start();
 
-      if( averageForceTorqueOverTwoTimSteps && i!= 0)
+      if( averageForceTorqueOverTwoTimeSteps )
       {
+         if( i == 0 )
+         {
+            lbm_mesapd_coupling::InitializeHydrodynamicForceTorqueForAveragingKernel initializeHydrodynamicForceTorqueForAveragingKernel;
+            ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor );
+         }
          ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, averageHydrodynamicForceTorque, *accessor );
       }
 
diff --git a/apps/benchmarks/FluidParticleCoupling/SphereWallCollision.cpp b/apps/benchmarks/FluidParticleCoupling/SphereWallCollision.cpp
index 0890c4ef4..594cfd432 100644
--- a/apps/benchmarks/FluidParticleCoupling/SphereWallCollision.cpp
+++ b/apps/benchmarks/FluidParticleCoupling/SphereWallCollision.cpp
@@ -68,6 +68,7 @@
 #include "lbm_mesapd_coupling/utility/ResetHydrodynamicForceTorqueKernel.h"
 #include "lbm_mesapd_coupling/utility/LubricationCorrectionKernel.h"
 #include "lbm_mesapd_coupling/utility/OmegaBulkAdaption.h"
+#include "lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h"
 
 #include "mesa_pd/collision_detection/AnalyticContactDetection.h"
 #include "mesa_pd/data/ParticleAccessorWithShape.h"
@@ -1183,9 +1184,13 @@ int main( int argc, char **argv )
       // perform a single simulation step -> this contains LBM and setting of the hydrodynamic interactions
       timeloop.singleStep( timeloopTiming );
 
-
-      if( averageForceTorqueOverTwoTimeSteps && i!= 0)
+      if( averageForceTorqueOverTwoTimeSteps )
       {
+         if( i == 0 )
+         {
+            lbm_mesapd_coupling::InitializeHydrodynamicForceTorqueForAveragingKernel initializeHydrodynamicForceTorqueForAveragingKernel;
+            ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor );
+         }
          ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, averageHydrodynamicForceTorque, *accessor );
       }
 
diff --git a/src/lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h b/src/lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h
new file mode 100644
index 000000000..07feb955e
--- /dev/null
+++ b/src/lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h
@@ -0,0 +1,54 @@
+//======================================================================================================================
+//
+//  This file is part of waLBerla. waLBerla 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 3 of 
+//  the License, or (at your option) any later version.
+//  
+//  waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file InitializeHydrodynamicForceTorqueForAveragingKernel.h
+//! \ingroup lbm_mesapd_coupling
+//! \author Christoph Rettinger <christoph.rettinger@fau.de>
+//
+//======================================================================================================================
+
+#pragma once
+
+#include "mesa_pd/data/IAccessor.h"
+
+namespace walberla {
+namespace lbm_mesapd_coupling {
+
+/*
+ * Kernel that initializes the old hydrodynamic force/torque property of a particle with the currently set one.
+ * This should be used when starting the simulation (from anew or from checkpoint) and after load balancing.
+ * Only then, the following averaging kernel (AverageHydrodynamicForceTorqueKernel) applies the correct amount of force.
+ *
+ * Should usually be carried out on local and ghost particles.
+ */
+class InitializeHydrodynamicForceTorqueForAveragingKernel
+{
+
+public:
+
+   InitializeHydrodynamicForceTorqueForAveragingKernel( ) = default;
+
+   template< typename ParticleAccessor_T >
+   void operator()(const size_t idx, ParticleAccessor_T& ac) const
+   {
+      static_assert(std::is_base_of<mesa_pd::data::IAccessor, ParticleAccessor_T>::value, "Provide a valid accessor as template");
+      
+      ac.setOldHydrodynamicForce( idx, ac.getHydrodynamicForce(idx) );
+      ac.setOldHydrodynamicTorque( idx, ac.getHydrodynamicTorque(idx) );
+   }
+};
+
+} // namespace lbm_mesapd_coupling
+} // namespace walberla
diff --git a/tests/lbm_mesapd_coupling/momentum_exchange_method/SettlingSphere.cpp b/tests/lbm_mesapd_coupling/momentum_exchange_method/SettlingSphere.cpp
index ef8db99fa..b3db22610 100644
--- a/tests/lbm_mesapd_coupling/momentum_exchange_method/SettlingSphere.cpp
+++ b/tests/lbm_mesapd_coupling/momentum_exchange_method/SettlingSphere.cpp
@@ -55,6 +55,7 @@
 #include "lbm_mesapd_coupling/momentum_exchange_method/reconstruction/PdfReconstructionManager.h"
 #include "lbm_mesapd_coupling/utility/AddForceOnParticlesKernel.h"
 #include "lbm_mesapd_coupling/utility/ParticleSelector.h"
+#include "lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h"
 #include "lbm_mesapd_coupling/utility/AverageHydrodynamicForceTorqueKernel.h"
 #include "lbm_mesapd_coupling/utility/AddHydrodynamicInteractionKernel.h"
 #include "lbm_mesapd_coupling/utility/ResetHydrodynamicForceTorqueKernel.h"
@@ -361,7 +362,7 @@ int main( int argc, char **argv )
 
    //numerical parameters
    uint_t numberOfCellsInHorizontalDirection = uint_t(135);
-   bool averageForceTorqueOverTwoTimSteps = true;
+   bool averageForceTorqueOverTwoTimeSteps = true;
    bool conserveMomentum = false;
    uint_t numRPDSubCycles = uint_t(1);
    bool useVelocityVerlet = false;
@@ -377,7 +378,7 @@ int main( int argc, char **argv )
       if( std::strcmp( argv[i], "--fluidType" )           == 0 ) { fluidType = uint_c( std::atof( argv[++i] ) ); continue; }
       if( std::strcmp( argv[i], "--numRPDSubCycles" )     == 0 ) { numRPDSubCycles = uint_c( std::atof( argv[++i] ) ); continue; }
       if( std::strcmp( argv[i], "--resolution" )          == 0 ) { numberOfCellsInHorizontalDirection = uint_c( std::atof( argv[++i] ) ); continue; }
-      if( std::strcmp( argv[i], "--noForceAveraging" )    == 0 ) { averageForceTorqueOverTwoTimSteps = false; continue; }
+      if( std::strcmp( argv[i], "--noForceAveraging" )    == 0 ) { averageForceTorqueOverTwoTimeSteps = false; continue; }
       if( std::strcmp( argv[i], "--baseFolder" )          == 0 ) { baseFolder = argv[++i]; continue; }
       if( std::strcmp( argv[i], "--useVV" )               == 0 ) { useVelocityVerlet = true; continue; }
       if( std::strcmp( argv[i], "--useEANReconstructor" ) == 0 ) { useEANReconstructor = true; continue; }
@@ -742,8 +743,13 @@ int main( int argc, char **argv )
 
       timeloopTiming["RPD"].start();
 
-      if( averageForceTorqueOverTwoTimSteps && i!= 0)
+      if( averageForceTorqueOverTwoTimeSteps )
       {
+         if( i == 0 )
+         {
+            lbm_mesapd_coupling::InitializeHydrodynamicForceTorqueForAveragingKernel initializeHydrodynamicForceTorqueForAveragingKernel;
+            ps->forEachParticle(useOpenMP, sphereSelector, *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor );
+         }
          ps->forEachParticle(useOpenMP, sphereSelector, *accessor, averageHydrodynamicForceTorque, *accessor );
       }
 
-- 
GitLab