From 2e30cf27eb5ad200dbdaced81482ec25ebef82e4 Mon Sep 17 00:00:00 2001
From: Martin Bauer <martin.bauer@fau.de>
Date: Fri, 17 Nov 2017 10:23:11 +0100
Subject: [PATCH] CUDA: exported field copy functions to python

---
 apps/pythonmodule/PythonModule.cpp |  2 +-
 apps/pythonmodule/setup.py         |  2 +-
 src/cuda/python/Exports.h          |  4 +-
 src/cuda/python/Exports.impl.h     | 59 +++++++++++++++++++++++++++---
 4 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/apps/pythonmodule/PythonModule.cpp b/apps/pythonmodule/PythonModule.cpp
index 82fab2e04..991ff455a 100644
--- a/apps/pythonmodule/PythonModule.cpp
+++ b/apps/pythonmodule/PythonModule.cpp
@@ -120,7 +120,7 @@ struct InitObject
       using walberla::cuda::GPUField;
       typedef bmpl::vector<GPUField<double>, GPUField<float>, GPUField<int>, GPUField<uint8_t>, GPUField<uint16_t> > GPUFields;
 
-      pythonManager->addExporterFunction( cuda::exportModuleToPython<GPUFields> );
+      pythonManager->addExporterFunction( cuda::exportModuleToPython<GPUFields, FieldTypes> );
       pythonManager->addBlockDataConversion<GPUFields>();
 #endif
 
diff --git a/apps/pythonmodule/setup.py b/apps/pythonmodule/setup.py
index 146f62380..74532db4f 100644
--- a/apps/pythonmodule/setup.py
+++ b/apps/pythonmodule/setup.py
@@ -62,4 +62,4 @@ if sys.argv[1] == 'build':
           " - to install run 'make pythonModuleInstall'\n"
           " - for development usage: \n"
           "      bash: export PYTHONPATH=%s:$PYTHONPATH \n"
-          "      fish: set -x PYTHONPATH %s $PYTHONPATH \n" % ( walberla_binary_dir,walberla_binary_dir ) )
\ No newline at end of file
+          "      fish: set -x PYTHONPATH %s $PYTHONPATH \n" % (walberla_binary_dir, walberla_binary_dir))
diff --git a/src/cuda/python/Exports.h b/src/cuda/python/Exports.h
index a2990cfc2..5e5b00090 100644
--- a/src/cuda/python/Exports.h
+++ b/src/cuda/python/Exports.h
@@ -24,13 +24,11 @@
 #ifdef WALBERLA_BUILD_WITH_PYTHON
 
 
-#include <string>
-
 namespace walberla {
 namespace cuda {
 
 
-   template<typename GpuFields >
+   template<typename GpuFields, typename CpuFields>
    void exportModuleToPython();
 
 
diff --git a/src/cuda/python/Exports.impl.h b/src/cuda/python/Exports.impl.h
index 1d2e2dc23..69807dbd8 100644
--- a/src/cuda/python/Exports.impl.h
+++ b/src/cuda/python/Exports.impl.h
@@ -26,19 +26,16 @@
 #include "cuda/GPUField.h"
 #include "cuda/communication/GPUPackInfo.h"
 #include "cuda/AddGPUFieldToStorage.h"
-
+#include "cuda/FieldCopy.h"
+#include "cuda/GPUField.h"
 #include "field/communication/UniformMPIDatatypeInfo.h"
-
 #include "field/AddToStorage.h"
 #include "field/python/FieldExport.h"
-
 #include "python_coupling/helper/MplHelpers.h"
 #include "python_coupling/helper/BoostPythonHelpers.h"
 
 #include <boost/type_traits/is_unsigned.hpp>
-
 #include <iostream>
-#include <cuda/communication/GPUPackInfo.h>
 
 namespace walberla {
 namespace cuda {
@@ -315,13 +312,61 @@ namespace internal {
    }
 
 
+   //===================================================================================================================
+   //
+   //  fieldCopy
+   //
+   //===================================================================================================================
+
+   template<typename Field_T>
+   void copyFieldToGpuDispatch(const shared_ptr<StructuredBlockStorage> & bs,
+                               BlockDataID cpuFieldId, BlockDataID gpuFieldId, bool toGpu)
+   {
+      typedef cuda::GPUField<typename Field_T::value_type> GpuField;
+      if(toGpu)
+         cuda::fieldCpy<GpuField, Field_T>(bs, gpuFieldId, cpuFieldId);
+      else
+         cuda::fieldCpy<Field_T, GpuField>(bs, cpuFieldId, gpuFieldId);
+   }
+   FunctionExporterClass( copyFieldToGpuDispatch,
+                          void( const shared_ptr<StructuredBlockStorage> &, BlockDataID, BlockDataID, bool ) );
+
+   template< typename FieldTypes >
+   void transferFields( const shared_ptr<StructuredBlockStorage> & bs,
+                        const std::string & gpuFieldId, const std::string & cpuFieldId, bool toGpu)
+   {
+      if( bs->begin() == bs->end()) {
+         return;
+      };
+
+      auto dstBdId = python_coupling::blockDataIDFromString( *bs, gpuFieldId );
+      auto srcBdId = python_coupling::blockDataIDFromString( *bs, cpuFieldId );
+
+      IBlock * firstBlock =  & ( * bs->begin() );
+      python_coupling::Dispatcher<FieldTypes, Exporter_copyFieldToGpuDispatch> dispatcher( firstBlock );
+      dispatcher( srcBdId )( bs, srcBdId, dstBdId, toGpu );
+   }
+
+   template< typename FieldTypes>
+   void copyFieldToGpu(const shared_ptr<StructuredBlockStorage> & bs,
+                       const std::string & gpuFieldId, const std::string & cpuFieldId)
+   {
+      transferFields<FieldTypes>(bs, gpuFieldId, cpuFieldId, true);
+   }
+
+   template< typename FieldTypes>
+   void copyFieldToCpu(const shared_ptr<StructuredBlockStorage> & bs,
+                       const std::string & gpuFieldId, const std::string & cpuFieldId)
+   {
+      transferFields<FieldTypes>(bs, gpuFieldId, cpuFieldId, false);
+   }
 
 } // namespace internal
 
 
 
 
-template<typename GpuFields >
+template<typename GpuFields, typename CpuFields >
 void exportModuleToPython()
 {
    python_coupling::ModuleScope fieldModule( "cuda" );
@@ -348,6 +393,8 @@ void exportModuleToPython()
    def( "createMPIDatatypeInfo",&internal::createMPIDatatypeInfo<GpuFields>, ( arg("blocks"), arg("blockDataName"), arg("numberOfGhostLayers" ) =0 ) );
    def( "createPackInfo",       &internal::createPackInfo<GpuFields>,        ( arg("blocks"), arg("blockDataName"), arg("numberOfGhostLayers" ) =0 ) );
 
+   def( "copyFieldToGpu", &internal::copyFieldToGpu<CpuFields>, (arg("blocks"), ("gpuFieldId"), ("cpuFieldId")));
+   def( "copyFieldToCpu", &internal::copyFieldToCpu<CpuFields>, (arg("blocks"), ("gpuFieldId"), ("cpuFieldId")));
 }
 
 
-- 
GitLab