From 4c930ad2b729b654c1a3b23ce45ff67edf97077c Mon Sep 17 00:00:00 2001
From: Pietro Incardona <incardon@mpi-cbg.de>
Date: Sun, 22 Mar 2020 09:41:37 +0100
Subject: [PATCH] Latest modules

---
 CMakeLists.txt                                |  2 +
 openfpm_data                                  |  2 +-
 src/Amr/grid_dist_amr.hpp                     | 28 ++++++-
 src/Amr/tests/amr_base_gpu_unit_tests.cu      | 75 ++++++++++++++++--
 src/CMakeLists.txt                            |  5 ++
 .../Iterators/grid_dist_id_iterator_dec.hpp   | 26 +++++++
 src/Grid/grid_dist_id.hpp                     | 78 ++++++++++++++++++-
 src/Grid/grid_dist_key.hpp                    | 10 +++
 src/Vector/vector_dist.hpp                    |  2 +-
 9 files changed, 214 insertions(+), 14 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 99ad9c12a..3d1492fb5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,8 @@
 cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
 project(openfpm_pdata LANGUAGES C CXX)
 
+cmake_policy(SET CMP0074 OLD)
+
 enable_testing()
 
 list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake_modules/)
diff --git a/openfpm_data b/openfpm_data
index 0083a00b0..ad46a9fef 160000
--- a/openfpm_data
+++ b/openfpm_data
@@ -1 +1 @@
-Subproject commit 0083a00b0bf82127a828c52ff3c1e922c18e19cf
+Subproject commit ad46a9fef9242807d928e64a441d550808b32412
diff --git a/src/Amr/grid_dist_amr.hpp b/src/Amr/grid_dist_amr.hpp
index ce1d0eb39..9d6c791fd 100644
--- a/src/Amr/grid_dist_amr.hpp
+++ b/src/Amr/grid_dist_amr.hpp
@@ -729,10 +729,11 @@ public:
 				gd_array.get(lvl).construct_link_dw(gd_array.get(lvl+1),mv_off.get(lvl));
 			}
 			else if (lvl == gd_array.size() - 1)
-			{gd_array.get(lvl).construct_link_up(gd_array.get(lvl-1));}
+			{gd_array.get(lvl).construct_link_up(gd_array.get(lvl-1),mv_off.get(lvl));}
 			else
 			{
 				gd_array.get(lvl).construct_link_dw(gd_array.get(lvl+1),mv_off.get(lvl));
+				gd_array.get(lvl).construct_link_up(gd_array.get(lvl-1),mv_off.get(lvl));
 			}
 		}
 	}
@@ -875,6 +876,31 @@ public:
 		key.setLvl(lvl+1);
 	}
 
+	/*! \brief Move down (to finer level) the key
+	 *
+	 * \param i level
+	 * \param key of grid at level i
+	 *
+	 */
+	template<typename bg_key>
+	void moveLvlDw(int i, grid_dist_key_dx<dim,bg_key> & key)
+	{
+#ifdef SE_CLASS1
+
+		if (i >= this->getNLvl() - 1)
+		{std::cerr << __FILE__ << ":" << __LINE__ << " error: we are already at the last level, we cannot go one level down" << std::endl;}
+
+#endif
+
+		auto & key_ref = key.getKeyRef();
+		size_t lvl = i;
+
+		for (size_t j = 0 ; j < dim ; j++)
+		{
+			key_ref.set_d(j,(key_ref.get(j) << 1) + mv_off.get(i).get(key.getSub()).dw.get(j) );
+		}
+	}
+
 	/*! \brief From a distributed key it return a AMR key that contain also the grid level
 	 *
 	 * \param lvl level
diff --git a/src/Amr/tests/amr_base_gpu_unit_tests.cu b/src/Amr/tests/amr_base_gpu_unit_tests.cu
index b22454719..b58d5457b 100644
--- a/src/Amr/tests/amr_base_gpu_unit_tests.cu
+++ b/src/Amr/tests/amr_base_gpu_unit_tests.cu
@@ -340,7 +340,6 @@ BOOST_AUTO_TEST_CASE( grid_dist_id_amr_gpu_link_test_more_dense )
 	auto it = amr_g.getGridIterator(0,start,stop);
 	auto it2 = amr_g.getGridIterator(1,start_lvl_dw,stop_lvl_dw);
 	auto it3 = amr_g.getGridIterator(2,start_lvl_dw2,stop_lvl_dw2);
-//	it.setGPUInsertBuffer(4);
 
 	auto & lvl_0 = amr_g.getDistGrid(0);
 	auto & lvl_1 = amr_g.getDistGrid(1);
@@ -391,6 +390,18 @@ BOOST_AUTO_TEST_CASE( grid_dist_id_amr_gpu_link_test_more_dense )
 
 	// For each local grid
 
+	size_t tot_dw_offs_12 = 0;
+	size_t tot_dw_lk_12 = 0;
+
+	size_t tot_dw_offs_23 = 0;
+	size_t tot_dw_lk_23 = 0;
+
+	size_t tot_up_offs_12 = 0;
+	size_t tot_up_lk_12 = 0;
+
+	size_t tot_up_offs_23 = 0;
+	size_t tot_up_lk_23 = 0;
+
 	for (int i = 0 ; i < lvl_zero_d.getN_loc_grid() ; i++)
 	{
 
@@ -402,8 +413,14 @@ BOOST_AUTO_TEST_CASE( grid_dist_id_amr_gpu_link_test_more_dense )
 		auto & offs_dw_link = lvl_zero.getDownLinksOffsets();
 		auto & dw_links = lvl_zero.getDownLinks();
 
-		BOOST_REQUIRE_EQUAL(offs_dw_link.size(),(i+1)*56);
-		BOOST_REQUIRE_EQUAL(dw_links.size(),(i+1)*56*4);
+		auto & offs_up_link = lvl_one.getUpLinksOffsets();
+		auto & up_links = lvl_one.getUpLinks();
+
+		tot_dw_offs_12 += offs_dw_link.size();
+		tot_dw_lk_12 += dw_links.size();
+
+		tot_up_offs_12 += offs_up_link.size();
+		tot_up_lk_12 += up_links.size();
 
 		auto & indexL0 = lvl_zero.private_get_blockMap().getIndexBuffer();
 		auto & indexL1 = lvl_one.private_get_blockMap().getIndexBuffer();
@@ -414,26 +431,70 @@ BOOST_AUTO_TEST_CASE( grid_dist_id_amr_gpu_link_test_more_dense )
 		auto & dataL2 = lvl_two.private_get_blockMap().getDataBuffer();
 
 		dw_links.template deviceToHost<0,1>();
+		up_links.template deviceToHost<0,1>();
 
 		for (int i = 0 ; i < dw_links.size(); i++)
 		{
-			BOOST_REQUIRE_EQUAL(dataL1.template get<0>(dw_links.template get<0>(0))[dw_links.template get<1>(0)],2);
+			BOOST_REQUIRE_EQUAL(dataL1.template get<0>(dw_links.template get<0>(i))[dw_links.template get<1>(i)],2);
+		}
+
+		for (int i = 0 ; i < up_links.size(); i++)
+		{
+			BOOST_REQUIRE_EQUAL(dataL0.template get<0>(up_links.template get<0>(i))[up_links.template get<1>(i)],1);
 		}
 
 		auto & offs_dw_link_1 = lvl_one.getDownLinksOffsets();
 		auto & dw_links_1 = lvl_one.getDownLinks();
 
-		BOOST_REQUIRE_EQUAL(offs_dw_link_1.size(),116);
-		BOOST_REQUIRE_EQUAL(dw_links_1.size(),116*4);
+		auto & offs_up_link_1 = lvl_two.getUpLinksOffsets();
+		auto & up_links_1 = lvl_two.getUpLinks();
+
+		tot_dw_offs_23 += offs_dw_link_1.size();
+		tot_dw_lk_23 += dw_links_1.size();
+
+		tot_up_offs_23 += offs_up_link_1.size();
+		tot_up_lk_23 += up_links_1.size();
 
 		dw_links_1.template deviceToHost<0,1>();
+		up_links_1.template deviceToHost<0,1>();
 
 		for (int i = 0 ; i < dw_links_1.size(); i++)
 		{
-			BOOST_REQUIRE_EQUAL(dataL2.template get<0>(dw_links_1.template get<0>(0))[dw_links_1.template get<1>(0)],3);
+			BOOST_REQUIRE_EQUAL(dataL2.template get<0>(dw_links_1.template get<0>(i))[dw_links_1.template get<1>(i)],3);
+		}
+
+		for (int i = 0 ; i < up_links_1.size(); i++)
+		{
+			BOOST_REQUIRE_EQUAL(dataL1.template get<0>(up_links_1.template get<0>(i))[up_links_1.template get<1>(i)],2);
 		}
 	}
 
+	v_cl.sum(tot_dw_offs_12);
+	v_cl.sum(tot_dw_lk_12);
+
+	v_cl.sum(tot_dw_offs_23);
+	v_cl.sum(tot_dw_lk_23);
+
+	v_cl.sum(tot_up_offs_12);
+	v_cl.sum(tot_up_lk_12);
+
+	v_cl.sum(tot_up_offs_23);
+	v_cl.sum(tot_up_lk_23);
+
+	v_cl.execute();
+
+	BOOST_REQUIRE_EQUAL(tot_dw_offs_12,56);
+	BOOST_REQUIRE_EQUAL(tot_dw_lk_12,56*4);
+
+	BOOST_REQUIRE_EQUAL(tot_dw_offs_23,116);
+	BOOST_REQUIRE_EQUAL(tot_dw_lk_23,116*4);
+
+	BOOST_REQUIRE_EQUAL(tot_up_offs_12,116);
+	BOOST_REQUIRE_EQUAL(tot_up_lk_12,116);
+
+	BOOST_REQUIRE_EQUAL(tot_up_offs_23,236);
+	BOOST_REQUIRE_EQUAL(tot_up_lk_23,236);
+
 	/////////////////////////////////////////////////////////////
 }
 
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f7a2c3857..995632ec8 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -165,6 +165,11 @@ install(FILES Grid/grid_dist_id.hpp
 	      Grid/staggered_dist_grid_copy.hpp
 	      DESTINATION openfpm_pdata/include/Grid/ )
 
+install(FILES Amr/grid_dist_amr_key_iterator.hpp 
+	      Amr/grid_dist_amr_key.hpp
+	      Amr/grid_dist_amr.hpp
+	      DESTINATION openfpm_pdata/include/Amr/ )
+
 install(FILES Grid/Iterators/grid_dist_id_iterator_util.hpp
               Grid/Iterators/grid_dist_id_iterator_dec.hpp
               Grid/Iterators/grid_dist_id_iterator_dec_skin.hpp
diff --git a/src/Grid/Iterators/grid_dist_id_iterator_dec.hpp b/src/Grid/Iterators/grid_dist_id_iterator_dec.hpp
index 3f5d37fcb..d90258809 100644
--- a/src/Grid/Iterators/grid_dist_id_iterator_dec.hpp
+++ b/src/Grid/Iterators/grid_dist_id_iterator_dec.hpp
@@ -40,6 +40,8 @@ class grid_dist_id_iterator_dec
 	//! Spacing
 	typename Decomposition::stype spacing[Decomposition::dims];
 
+	//! Domain
+	Box<Decomposition::dims,typename Decomposition::stype> domain;
 
 	/*! \brief from g_c increment g_c until you find a valid grid
 	 *
@@ -96,6 +98,8 @@ class grid_dist_id_iterator_dec
 		start = tmp.start;
 		stop = tmp.stop;
 
+		domain = tmp.domain;
+
 		return *this;
 	}
 
@@ -118,6 +122,8 @@ class grid_dist_id_iterator_dec
 	grid_dist_id_iterator_dec(Decomposition & dec, const size_t (& sz)[Decomposition::dims])
 	:g_c(0)
 	{
+		domain = dec.getDomain();
+
 		// Initialize start and stop
 		start.zero();
 		for (size_t i = 0 ; i < Decomposition::dims ; i++)
@@ -142,6 +148,8 @@ class grid_dist_id_iterator_dec
 	grid_dist_id_iterator_dec(Decomposition & dec, const size_t (& sz)[Decomposition::dims], grid_key_dx<Decomposition::dims> start, grid_key_dx<Decomposition::dims> stop)
 	:g_c(0),start(start),stop(stop)
 	{
+		domain = dec.getDomain();
+
 		// From the decomposition construct gdb_ext
 		create_gdb_ext<Decomposition::dims,Decomposition>(gdb_ext,dec,sz,dec.getDomain(),spacing);
 
@@ -276,6 +284,24 @@ class grid_dist_id_iterator_dec
 		return k_glob;
 	}
 
+	/*! \brief Return the point coordinates
+	 *
+	 * \return the point
+	 *
+	 */
+	inline Point<Decomposition::dims,typename Decomposition::stype> getPoint()
+	{
+		Point<Decomposition::dims,typename Decomposition::stype> p;
+		auto key = this->get();
+
+		for (int i = 0 ; i < Decomposition::dims ; i++)
+		{
+			p.get(i) = spacing[i] * key.get(i) + domain.getLow(i);
+		}
+
+		return p;
+	}
+
 	/*! \brief Get the actual grid key for a distributed grid
 	 *
 	 * \note if you are using this iterator and you need the position for grid_dist_id use this
diff --git a/src/Grid/grid_dist_id.hpp b/src/Grid/grid_dist_id.hpp
index 76c9d7f08..9bf3de068 100644
--- a/src/Grid/grid_dist_id.hpp
+++ b/src/Grid/grid_dist_id.hpp
@@ -2201,6 +2201,43 @@ public:
 		return loc_grid.get(v1.getSub()).template get<p>(v1.getKey());
 	}
 
+	/*! \brief Get the reference of the selected element
+	 *
+	 * \tparam p property to get (is an integer)
+	 * \param v1 grid_key that identify the element in the grid
+	 *
+	 * \return the selected element
+	 *
+	 */
+	template <typename bg_key>
+	inline Point<dim,St> getPos(const grid_dist_key_dx<dim,bg_key> & v1)
+	{
+#ifdef SE_CLASS2
+		check_valid(this,8);
+#endif
+		Point<dim,St> p;
+
+		for (int i = 0 ; i < dim ; i++)
+		{
+			p.get(i) = (gdb_ext.get(v1.getSub()).origin.get(i) + v1.getKeyRef().get(i)) * this->spacing(i);
+		}
+
+		return p;
+	}
+
+	/*! \brief Check if the point exist
+	 *
+	 * \param v1 grid_key that identify the element in the grid
+	 *
+	 * \return the true if the point exist
+	 *
+	 */
+	template<typename bg_key>
+	inline bool existPoint(const grid_dist_key_dx<dim,bg_key> & v1) const
+	{
+		return loc_grid.get(v1.getSub()).existPoint(v1.getKey());
+	}
+
 	/*! \brief Get the reference of the selected element
 	 *
 	 * \tparam p property to get (is an integer)
@@ -2347,7 +2384,7 @@ public:
 					// center point
 					auto Cp = it.template getStencil<0>();
 
-					dst.get_o(Cp) = src.get_o(Cp);
+					dst.insert_o(Cp) = src.get_o(Cp);
 
 					++it;
 				}
@@ -2357,6 +2394,35 @@ public:
 		return *this;
 	}
 
+	/*! \brief Copy the give grid into this grid
+	 *
+	 * It copy the first grid into the given grid (No ghost)
+	 *
+	 * \warning the Decomposition must be ensured to be the same, otherwise crashes can happen, if you want to copy the grid independently from the decomposition please use the operator equal
+	 *
+	 * \param g Grid to copy
+	 * \param use_memcpy use memcpy function if possible
+	 *
+	 * \return itself
+	 *
+	 */
+	grid_dist_id<dim,St,T,Decomposition,Memory,device_grid> & copy_sparse(grid_dist_id<dim,St,T,Decomposition,Memory,device_grid> & g, bool use_memcpy = true)
+	{
+		grid_key_dx<dim> cnt[1];
+		cnt[0].zero();
+
+		size_t ele_id;
+
+		for (size_t i = 0 ; i < this->getN_loc_grid() ; i++)
+		{
+			auto & dst = this->get_loc_grid(i);
+			auto & src = g.get_loc_grid(i);
+
+			dst = src;
+		}
+		return *this;
+	}
+
 	/*! \brief Get the spacing on each dimension
 	 *
 	 * \return the spacing of the grid on each dimension as a point
@@ -2659,7 +2725,7 @@ public:
 			for(int j = 0 ; j < dim ; j++)
 			{p_dw.get(j) = mvof.get(i).dw.get(j);}
 
-			loc_grid.get(i).construct_link_dw(grid_dw.get_loc_grid(i),p_dw,v_cl.getmgpuContext());
+			loc_grid.get(i).construct_link_dw(grid_dw.get_loc_grid(i),gdb_ext.get(i).Dbox,p_dw,v_cl.getmgpuContext());
 		}
 	}
 
@@ -2669,11 +2735,15 @@ public:
 	 * \param grid_dw grid level down
 	 *
 	 */
-	void construct_link_up(self & grid_up)
+	void construct_link_up(self & grid_up, openfpm::vector<offset_mv<dim>> & mvof)
 	{
 		for (int i = 0 ; i < loc_grid.size() ; i++)
 		{
-			loc_grid.get(i).construct_link_up(grid_up.get_loc_grid(i),v_cl.getmgpuContext());
+			Point<dim,int> p_up;
+			for(int j = 0 ; j < dim ; j++)
+			{p_up.get(j) = mvof.get(i).up.get(j);}
+
+			loc_grid.get(i).construct_link_up(grid_up.get_loc_grid(i),gdb_ext.get(i).Dbox,p_up,v_cl.getmgpuContext());
 		}
 	}
 
diff --git a/src/Grid/grid_dist_key.hpp b/src/Grid/grid_dist_key.hpp
index 666e2bd32..26edc906a 100644
--- a/src/Grid/grid_dist_key.hpp
+++ b/src/Grid/grid_dist_key.hpp
@@ -93,6 +93,16 @@ public:
 		return key;
 	}
 
+	/*! \brief Get the reference key
+	 *
+	 * \return the local key
+	 *
+	 */
+	inline const base_key & getKeyRef() const
+	{
+		return key;
+	}
+
 	/* \brief Check if two key are the same
 	 *
 	 * \param key_t key to check
diff --git a/src/Vector/vector_dist.hpp b/src/Vector/vector_dist.hpp
index d69adf2a8..949825477 100644
--- a/src/Vector/vector_dist.hpp
+++ b/src/Vector/vector_dist.hpp
@@ -2029,7 +2029,7 @@ public:
 		se3.getIterator();
 #endif
 
-		return v_pos.getGPUIteratorTo(size_local(),n_thr);
+		return v_pos.getGPUIteratorTo(v_pos.size(),n_thr);
 	}
 
 	/*! \brief Merge the properties calculated on the sorted vector on the original vector
-- 
GitLab