From 9a77a582e90ecd192472129737431a37cdc91b48 Mon Sep 17 00:00:00 2001
From: Pietro Incardona <incardon@mpi-cbg.de>
Date: Tue, 20 Oct 2015 00:33:42 +0200
Subject: [PATCH] Copy decomposition for grid

---
 src/Decomposition/CartDecomposition.hpp | 20 +++++++-
 src/Grid/grid_dist_id.hpp               | 32 ++++++------
 src/Grid/grid_dist_id_unit_test.hpp     | 65 +++++++++++++++++++++++++
 src/Grid/grid_dist_key.hpp              | 18 +++++++
 4 files changed, 119 insertions(+), 16 deletions(-)

diff --git a/src/Decomposition/CartDecomposition.hpp b/src/Decomposition/CartDecomposition.hpp
index ad48a26e..216c15e7 100644
--- a/src/Decomposition/CartDecomposition.hpp
+++ b/src/Decomposition/CartDecomposition.hpp
@@ -334,15 +334,33 @@ private:
 	// Receive counter
 	size_t recv_cnt;
 
+	// reference counter of the object in case is shared between object
+
+	long int ref_cnt;
+
 public:
 
+	//! Increment the reference counter
+	void incRef()
+	{ref_cnt++;}
+
+	//! Decrement the reference counter
+	void decRef()
+	{ref_cnt--;}
+
+	//! Return the reference counter
+	long int ref()
+	{
+		return ref_cnt;
+	}
+
 	/*! \brief Cartesian decomposition constructor
 	 *
      * \param v_cl Virtual cluster, used internally to handle or pipeline communication
 	 *
 	 */
 	CartDecomposition(Vcluster & v_cl)
-	:nn_prcs<dim,T>(v_cl),v_cl(v_cl)
+	:nn_prcs<dim,T>(v_cl),v_cl(v_cl),ref_cnt(0)
 	{
 		// Reset the box to zero
 		bbox.zero();
diff --git a/src/Grid/grid_dist_id.hpp b/src/Grid/grid_dist_id.hpp
index 5854c665..8bc10131 100644
--- a/src/Grid/grid_dist_id.hpp
+++ b/src/Grid/grid_dist_id.hpp
@@ -54,7 +54,7 @@ class grid_dist_id
 	Vcluster_object_array<device_grid> loc_grid;
 
 	//! Space Decomposition
-	Decomposition dec;
+	Decomposition & dec;
 
 	//! Extension of each grid: Domain and ghost + domain
 	openfpm::vector<GBoxes<device_grid::dims>> gdb_ext;
@@ -350,9 +350,12 @@ class grid_dist_id
 public:
 
 	//! constructor
-	grid_dist_id(Vcluster v_cl, Decomposition & dec, const size_t (& g_sz)[dim], const Box<dim,St> & domain, const Ghost<dim,T> & ghost)
-	:domain(domain),ghost(ghost),loc_grid(NULL),v_cl(v_cl),dec(dec)
+	grid_dist_id(Decomposition & dec, const size_t (& g_sz)[dim], const Box<dim,St> & domain, const Ghost<dim,St> & ghost)
+	:domain(domain),ghost(ghost),dec(dec),v_cl(*global_v_cluster)
 	{
+		// Increment the reference counter of the decomposition
+		dec.incRef();
+
 		check_size(g_sz);
 
 		// For a 5x5 grid you have 4x4 Cell
@@ -363,27 +366,18 @@ public:
 		cd_sm.setDimensions(domain,c_g,0);
 
 		// fill the global size of the grid
-		for (int i = 0 ; i < dim ; i++)	{this->g_sz[i] = g_sz[i];}
+		for (size_t i = 0 ; i < dim ; i++)	{this->g_sz[i] = g_sz[i];}
 
 		// Get the number of processor and calculate the number of sub-domain
 		// for decomposition
 		size_t n_proc = v_cl.getProcessingUnits();
 		size_t n_sub = n_proc * SUB_UNIT_FACTOR;
 
-		// Calculate the maximum number (before merging) of sub-domain on
-		// each dimension
-		size_t div[dim];
-		for (int i = 0 ; i < dim ; i++)
-		{div[i] = openfpm::math::round_big_2(pow(n_sub,1.0/dim));}
-
-		// Create the sub-domains
-		dec.setParameters(div);
-
 		// Create local grid
 		Create();
 
 		// Calculate ghost boxes
-		dec.calculateGhostBoxes(ghost);
+		dec.calculateGhostBoxes();
 	}
 
 	/*! \brief Constrcuctor
@@ -394,8 +388,11 @@ public:
 	 *
 	 */
 	grid_dist_id(const size_t (& g_sz)[dim],const Box<dim,St> & domain, const Ghost<dim,St> & g)
-	:domain(domain),ghost(g),dec(Decomposition(*global_v_cluster)),v_cl(*global_v_cluster)
+	:domain(domain),ghost(g),dec(*new Decomposition(*global_v_cluster)),v_cl(*global_v_cluster)
 	{
+		// Increment the reference counter of the decomposition
+		dec.incRef();
+
 		// check that the grid has valid size
 		check_size(g_sz);
 
@@ -541,6 +538,11 @@ public:
 	//! Destructor
 	~grid_dist_id()
 	{
+		dec.decRef();
+
+		// if we reach the 0, destroy the object
+		if (dec.ref() == 0)
+			delete &dec;
 	}
 
 	/*! \brief Get the Virtual Cluster machine
diff --git a/src/Grid/grid_dist_id_unit_test.hpp b/src/Grid/grid_dist_id_unit_test.hpp
index fc4cbf3d..d5fe3841 100644
--- a/src/Grid/grid_dist_id_unit_test.hpp
+++ b/src/Grid/grid_dist_id_unit_test.hpp
@@ -612,6 +612,70 @@ void Test3D_complex(const Box<3,float> & domain, long int k)
 	}
 }
 
+// Test duplicated topology
+
+void Test3D_dup(const Box<3,float> & domain, long int k)
+{
+	typedef Point_test<float> p;
+
+	long int big_step = k / 30;
+	big_step = (big_step == 0)?1:big_step;
+	long int small_step = 1;
+
+	Vcluster & v_cl = *global_v_cluster;
+
+	if ( v_cl.getProcessingUnits() > 32 )
+		return;
+
+	print_test( "Testing 3D duplicate topology complex k<=",k);
+
+	// 3D test
+	for ( ; k >= 2 ; k-= (k > 2*big_step)?big_step:small_step )
+	{
+		BOOST_TEST_CHECKPOINT( "Testing 3D copy decomposition grid k=" << k );
+
+		// grid size
+		size_t sz[3];
+		sz[0] = k;
+		sz[1] = k;
+		sz[2] = k;
+
+		// factor
+		float factor = pow(global_v_cluster->getProcessingUnits()/2.0f,1.0f/3.0f);
+
+		// Ghost
+		Ghost<3,float> g(0.01 / factor);
+
+		//! [Construct two grid with the same topology]
+
+		// Distributed grid with id decomposition
+		grid_dist_id<3, float, Point_test<float>, CartDecomposition<3,float>> g_dist1(sz,domain,g);
+
+		// another grid with the same decomposition
+		grid_dist_id<3, float, Point_test<float>, CartDecomposition<3,float>> g_dist2(g_dist1.getDecomposition(),sz,domain,g);
+
+		//! [Construct two grid with the same topology]
+
+		auto dom_g1 = g_dist1.getDomainIterator();
+		auto dom_g2 = g_dist2.getDomainIterator();
+
+		bool check = true;
+
+		while (dom_g1.isNext())
+		{
+			auto key1 = dom_g1.get();
+			auto key2 = dom_g2.get();
+
+			check &= (key1 == key2)?true:false;
+
+			++dom_g1;
+			++dom_g2;
+		}
+
+		BOOST_REQUIRE_EQUAL(check,true);
+	}
+}
+
 BOOST_AUTO_TEST_CASE( grid_dist_id_iterator_test_use)
 {
 	// Domain
@@ -632,6 +696,7 @@ BOOST_AUTO_TEST_CASE( grid_dist_id_iterator_test_use)
 	k = std::pow(k, 1/3.);
 	Test3D(domain3,k);
 	Test3D_complex(domain3,k);
+	Test3D_dup(domain3,k);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/Grid/grid_dist_key.hpp b/src/Grid/grid_dist_key.hpp
index 9550a694..e62d3b0f 100644
--- a/src/Grid/grid_dist_key.hpp
+++ b/src/Grid/grid_dist_key.hpp
@@ -40,6 +40,24 @@ public:
 		return key;
 	}
 
+	/* \brief Check if two key are the same
+	 *
+	 * \param key_t key to check
+	 *
+	 * \return true if the two key are equal
+	 *
+	 */
+
+	inline bool operator==(const grid_dist_key_dx<dim> & key_t)
+	{
+		if (g_c != key_t.g_c)
+			return false;
+
+		// Check the two key index by index
+
+		return getKey() == key_t.getKey();
+	}
+
 	/*! \brief Create a new key moving the old one
 	 *
 	 * \param i dimension id
-- 
GitLab