From 711dc8e190bdfc7dcb54d005eb88ab62509a6778 Mon Sep 17 00:00:00 2001
From: Michael Kuron <mkuron@icp.uni-stuttgart.de>
Date: Fri, 6 Mar 2020 12:46:29 +0100
Subject: [PATCH] flattened shallow copy of GhostLayerField

---
 src/field/GhostLayerField.h      | 20 +++++++++----
 src/field/GhostLayerField.impl.h | 27 ++++++++++++++++++
 tests/field/FieldTest.cpp        | 49 ++++++++++++++++++++++++++++++++
 3 files changed, 91 insertions(+), 5 deletions(-)

diff --git a/src/field/GhostLayerField.h b/src/field/GhostLayerField.h
index 122e2a465..7ab587975 100644
--- a/src/field/GhostLayerField.h
+++ b/src/field/GhostLayerField.h
@@ -66,6 +66,11 @@ namespace field {
 
       typedef typename Field<T,fSize_>::Ptr                    Ptr;
       typedef typename Field<T,fSize_>::ConstPtr               ConstPtr;
+
+      typedef typename std::conditional<VectorTrait<T>::F_SIZE!=0,
+                                        GhostLayerField<typename VectorTrait<T>::OutputType, VectorTrait<T>::F_SIZE*fSize_>,
+                                        GhostLayerField<T, fSize_>
+                                        >::type FlattenedGhostLayerField;
       //@}
       //****************************************************************************************************************
 
@@ -97,7 +102,7 @@ namespace field {
                  const shared_ptr<FieldAllocator<T> > &alloc = shared_ptr<FieldAllocator<T> >() );
 
 
-      virtual void resize( uint_t xSize, uint_t ySize, uint_t zSize );
+      virtual void resize( uint_t xSize, uint_t ySize, uint_t zSize ) override;
               void resize( uint_t xSize, uint_t ySize, uint_t zSize, uint_t gl );
 
       using Field<T,fSize_>::resize;
@@ -105,6 +110,7 @@ namespace field {
       inline GhostLayerField<T,fSize_> * clone()              const;
       inline GhostLayerField<T,fSize_> * cloneUninitialized() const;
       inline GhostLayerField<T,fSize_> * cloneShallowCopy()   const;
+      inline FlattenedGhostLayerField * flattenedShallowCopy() const;
       //@}
       //****************************************************************************************************************
 
@@ -194,8 +200,8 @@ namespace field {
       /*! \name Slicing */
       //@{
       GhostLayerField<T,fSize_> * getSlicedField( const CellInterval & interval ) const;
-      virtual void slice           ( const CellInterval & interval );
-      virtual void shiftCoordinates( cell_idx_t cx, cell_idx_t cy, cell_idx_t cz );
+      virtual void slice           ( const CellInterval & interval ) override;
+      virtual void shiftCoordinates( cell_idx_t cx, cell_idx_t cy, cell_idx_t cz ) override;
       //@}
       //****************************************************************************************************************
 
@@ -208,12 +214,16 @@ namespace field {
       //** Shallow Copy ************************************************************************************************
       /*! \name Shallow Copy */
       //@{
-      virtual Field<T,fSize_> * cloneShallowCopyInternal()   const;
+      virtual Field<T,fSize_> * cloneShallowCopyInternal()   const override;
+      virtual typename Field<T,fSize_>::FlattenedField * flattenedShallowCopyInternal() const override;
       GhostLayerField(const GhostLayerField<T,fSize_> & other);
+      template <typename T2, uint_t fSize2>
+      GhostLayerField(const GhostLayerField<T2, fSize2> & other);
       //@}
       //****************************************************************************************************************
 
-
+      template <typename T2, uint_t fSize2>
+      friend class GhostLayerField;
    };
 
 } // namespace field
diff --git a/src/field/GhostLayerField.impl.h b/src/field/GhostLayerField.impl.h
index 27c87ce0e..3ccbcb8c3 100644
--- a/src/field/GhostLayerField.impl.h
+++ b/src/field/GhostLayerField.impl.h
@@ -696,6 +696,17 @@ namespace field {
    {
    }
 
+   //*******************************************************************************************************************
+   /*!\brief Private copy constructor, which does a flattened shallow copy
+    *******************************************************************************************************************/
+   template<typename T, uint_t fSize_>
+   template <typename T2, uint_t fSize2>
+   GhostLayerField<T,fSize_>::GhostLayerField(const GhostLayerField<T2,fSize2> & other)
+      : Field<T,fSize_>::Field(other),
+        gl_( other.gl_ )
+   {
+   }
+
    //*******************************************************************************************************************
    /*!\brief See Field::cloneShallowCopyInternal()
     *  Has to be re-implemented because a new GhostLayerField is created
@@ -706,6 +717,16 @@ namespace field {
       return new GhostLayerField<T,fSize_>(*this);
    }
 
+   //*******************************************************************************************************************
+   /*!\brief See Field::flattenedShallowCopyInternal()
+    *  Has to be re-implemented because a new GhostLayerField is created
+    *******************************************************************************************************************/
+   template<typename T, uint_t fSize_>
+   typename Field<T,fSize_>::FlattenedField * GhostLayerField<T,fSize_>::flattenedShallowCopyInternal() const
+   {
+      return new GhostLayerField<T,fSize_>::FlattenedGhostLayerField(*this);
+   }
+
 
    template<typename T, uint_t fSize_>
    GhostLayerField<T,fSize_> * GhostLayerField<T,fSize_>::clone() const
@@ -725,6 +746,12 @@ namespace field {
       return dynamic_cast<GhostLayerField<T,fSize_>* > (Field<T,fSize_>::cloneShallowCopy() );
    }
 
+   template<typename T, uint_t fSize_>
+   typename GhostLayerField<T,fSize_>::FlattenedGhostLayerField * GhostLayerField<T,fSize_>::flattenedShallowCopy() const
+   {
+      return dynamic_cast<GhostLayerField<T,fSize_>::FlattenedGhostLayerField* > (Field<T,fSize_>::flattenedShallowCopy() );
+   }
+
    template<typename T, uint_t fSize_>
    void GhostLayerField<T,fSize_>::slice( const CellInterval & interval )
    {
diff --git a/tests/field/FieldTest.cpp b/tests/field/FieldTest.cpp
index 2f3d5b691..2021554dd 100644
--- a/tests/field/FieldTest.cpp
+++ b/tests/field/FieldTest.cpp
@@ -623,6 +623,53 @@ void flattenTest()
 }
 
 
+template<uint_t fSize>
+void ghostFlattenTest()
+{
+   GhostLayerField<Vector3<uint_t>, fSize> field ( 2,2,1, 1 );
+
+   for( cell_idx_t x = -cell_idx_c(field.nrOfGhostLayers()); x < cell_idx_c(field.xSize()+field.nrOfGhostLayers()); ++x )
+      for( cell_idx_t y = -cell_idx_c(field.nrOfGhostLayers()); y < cell_idx_c(field.ySize()+field.nrOfGhostLayers()); ++y )
+         for( cell_idx_t z = -cell_idx_c(field.nrOfGhostLayers()); z < cell_idx_c(field.zSize()+field.nrOfGhostLayers()); ++z )
+            for( cell_idx_t f = 0; f < cell_idx_c(field.fSize()); ++f )
+               for( uint_t g = 0; g < 3; ++g )
+               {
+                  uint_t val = uint_t(&(field( x,y,z,f )[g]));
+                  field( x,y,z,f )[g] = val;
+               }
+
+   shared_ptr<GhostLayerField<uint_t, 3*fSize>> flattened(field.flattenedShallowCopy());
+
+   GhostLayerField<uint_t, 3*fSize> cmp ( 2,2,1, 1 );
+   WALBERLA_CHECK_EQUAL(cmp.xSize(), flattened->xSize());
+   WALBERLA_CHECK_EQUAL(cmp.ySize(), flattened->ySize());
+   WALBERLA_CHECK_EQUAL(cmp.zSize(), flattened->zSize());
+   WALBERLA_CHECK_EQUAL(cmp.fSize(), flattened->fSize());
+   WALBERLA_CHECK_EQUAL(cmp.xAllocSize(), flattened->xAllocSize());
+   WALBERLA_CHECK_EQUAL(cmp.yAllocSize(), flattened->yAllocSize());
+   WALBERLA_CHECK_EQUAL(cmp.zAllocSize(), flattened->zAllocSize());
+   WALBERLA_CHECK_EQUAL(cmp.fAllocSize(), flattened->fAllocSize());
+   WALBERLA_CHECK_EQUAL(cmp.allocSize(), flattened->allocSize());
+   WALBERLA_CHECK_EQUAL(cmp.xStride(), flattened->xStride());
+   WALBERLA_CHECK_EQUAL(cmp.yStride(), flattened->yStride());
+   WALBERLA_CHECK_EQUAL(cmp.zStride(), flattened->zStride());
+   WALBERLA_CHECK_EQUAL(cmp.fStride(), flattened->fStride());
+   WALBERLA_CHECK_EQUAL(cmp.xOff(), flattened->xOff());
+   WALBERLA_CHECK_EQUAL(cmp.yOff(), flattened->yOff());
+   WALBERLA_CHECK_EQUAL(cmp.zOff(), flattened->zOff());
+   WALBERLA_CHECK_EQUAL(cmp.nrOfGhostLayers(), flattened->nrOfGhostLayers());
+
+   for( cell_idx_t x = -cell_idx_c(field.nrOfGhostLayers()); x < cell_idx_c(field.xSize()+field.nrOfGhostLayers()); ++x )
+      for( cell_idx_t y = -cell_idx_c(field.nrOfGhostLayers()); y < cell_idx_c(field.ySize()+field.nrOfGhostLayers()); ++y )
+         for( cell_idx_t z = -cell_idx_c(field.nrOfGhostLayers()); z < cell_idx_c(field.zSize()+field.nrOfGhostLayers()); ++z )
+            for( cell_idx_t f = 0; f < cell_idx_c(field.fSize()); ++f )
+               for( uint_t g = 0; g < 3; ++g )
+               {
+                  WALBERLA_CHECK_EQUAL(field(x,y,z,f)[g], flattened->get(x,y,z,3*f+cell_idx_c(g)));
+               }
+}
+
+
 int main( int argc, char**argv )
 {
    walberla::Environment walberlaEnv( argc, argv );
@@ -675,6 +722,8 @@ int main( int argc, char**argv )
 
    flattenTest<1>();
    flattenTest<3>();
+   ghostFlattenTest<1>();
+   ghostFlattenTest<3>();
 
 
    //swapableCompareTest();
-- 
GitLab