From 6bcf7186666a48b6519a45263815e843e24adc6b Mon Sep 17 00:00:00 2001 From: Pietro Incardona <incardon@mpi-cbg.de> Date: Mon, 19 Sep 2016 01:47:30 +0200 Subject: [PATCH] Complex properties with serialization completed --- example/Vector/4_complex_prop/Makefile | 10 +- example/Vector/4_complex_prop/main.cpp | 122 ++++++++++++++++++++----- openfpm_data | 2 +- openfpm_pdata.doc | 2 +- src/Vector/vector_dist_comm.hpp | 122 ++++++++++++++++--------- src/Vector/vector_dist_unit_test.hpp | 1 + 6 files changed, 186 insertions(+), 73 deletions(-) diff --git a/example/Vector/4_complex_prop/Makefile b/example/Vector/4_complex_prop/Makefile index 646357e95..93fc158bd 100644 --- a/example/Vector/4_complex_prop/Makefile +++ b/example/Vector/4_complex_prop/Makefile @@ -5,17 +5,21 @@ CC=mpic++ LDIR = OBJ = main.o +OBJ_SER = main_ser.o %.o: %.cpp $(CC) -O3 -c --std=c++11 -o $@ $< $(INCLUDE_PATH) -vect: $(OBJ) +vect_cp: $(OBJ) $(CC) -o $@ $^ $(CFLAGS) $(LIBS_PATH) $(LIBS) -all: vect +vect_ser: $(OBJ_SER) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS_PATH) $(LIBS) + +all: vect_cp vect_ser run: all - source $$HOME/openfpm_vars; mpirun -np 2 ./vect + source $$HOME/openfpm_vars && mpirun -np 2 ./vect_cp && mpirun -np 2 ./vect_ser .PHONY: clean all run diff --git a/example/Vector/4_complex_prop/main.cpp b/example/Vector/4_complex_prop/main.cpp index 915f2868e..028b2b33f 100644 --- a/example/Vector/4_complex_prop/main.cpp +++ b/example/Vector/4_complex_prop/main.cpp @@ -1,12 +1,19 @@ +/*! \page Vector_4_cp Vector 4 complex properties and serialization + * + * \subpage Vector_4_complex_prop + * \subpage Vector_4_complex_prop_ser + * + */ + /*! * - * \page Vector_4_complex_prop Vector 4 complex property + * \page Vector_4_complex_prop Vector 4 complex properties * * * [TOC] * * - * # Vector 4 complex property # {#vector_example_cp} + * # Vector 4 complex properties # {#vector_example_cp} * * * This example show how we can use complex properties in a vector @@ -19,7 +26,7 @@ int main(int argc, char* argv[]) { /*! * - * \page Vector_4_complex_prop Vector 4 complex property + * \page Vector_4_complex_prop Vector 4 complex properties * * * ## Initialization and vector creation ## @@ -29,13 +36,36 @@ int main(int argc, char* argv[]) * * \snippet Vector/4_complex_prop/main.cpp vect create * - * In This this particular case every particle carry a scalar, + * In this this particular case every particle carry a scalar, * a vector in form of float[3], a Point, a list - * in form of vector of float and a list of custom structures + * in form of vector of float and a list of custom structures, and a vector of vector. + * In general particles can have properties of arbitrary complexity. + * + * \warning For arbitrary complexity mean that we can use any openfpm data structure with and arbitrary nested complexity. + * For example a openfpm::vector<aggregate<grid_cpu<openfpm::vector<aggregate<double,double[3]>>>,openfpm::vector<float>> is valid + * \verbatim + + particle + * + vector + / \ + / \ + grid vector<float> + /\ + / \ + double double[3] + + * \endverbatim + * + * Our custom data-structure A is defined below. Note that this data-structure + * does not have pointers * * \snippet Vector/4_complex_prop/main.cpp struct A * * + * \warning custom data structure are allowed only if they does not have pointer. + * In case they have pointer we have to define how to serialize our data-structure + * */ // initialize the library @@ -82,20 +112,24 @@ int main(int argc, char* argv[]) // A listA constexpr int listA = 4; + // A list of list + constexpr int listlist = 5; + //! \cond [vect create] \endcond vector_dist<2,float, aggregate<float, float[3], Point<3,double>, openfpm::vector<float>, - openfpm::vector<A>>> + openfpm::vector<A>, + openfpm::vector<openfpm::vector<float>>> > vd(4096,domain,bc,g); //! \cond [vect create] \endcond /*! * - * \page Vector_4_complex_prop Vector 4 complex property + * \page Vector_4_complex_prop Vector 4 complex properties * * * ## Assign values to properties ## @@ -135,7 +169,7 @@ int main(int argc, char* argv[]) vd.getProp<point>(p).get(1) = 1.0; vd.getProp<point>(p).get(2) = 1.0; - size_t n_cp = (float)10 * rand()/RAND_MAX; + size_t n_cp = (float)10.0 * rand()/RAND_MAX; vd.getProp<listA>(p).resize(n_cp); @@ -146,10 +180,17 @@ int main(int argc, char* argv[]) vd.getProp<list>(p).add(i + 30); vd.getProp<listA>(p).get(i) = A(i+10.0,i+20.0); - vd.getProp<listA>(p).get(i) = A(i+30.0,i+40.0); - vd.getProp<listA>(p).get(i) = A(i+50.0,i+60.0); } + vd.getProp<listlist>(p).resize(2); + vd.getProp<listlist>(p).get(0).resize(2); + vd.getProp<listlist>(p).get(1).resize(2); + + vd.getProp<listlist>(p).get(0).get(0) = 1.0; + vd.getProp<listlist>(p).get(0).get(1) = 2.0; + vd.getProp<listlist>(p).get(1).get(0) = 3.0; + vd.getProp<listlist>(p).get(1).get(1) = 4.0; + // next particle ++it; } @@ -158,19 +199,15 @@ int main(int argc, char* argv[]) /*! * - * \page Vector_4_complex_prop Vector 4 complex property + * \page Vector_4_complex_prop Vector 4 complex properties * * * ## Mapping and ghost_get ## * - * Particles are redistributed across processors but only the scalar,vector and the point - * are communicated (properties 0,1,2). A lot of time complex properties can be recomputed and - * communicate them is not a good idea. The same concept also apply for ghost_get - * - * \note OpenFPM <= 0.5.0 cannot communicate complex properties like a vector or other structure - * that are not POD object - * - * \note OpenFPM > 0.5.0 Does not have such limitation + * Particles are redistributed across processors all properties are communicated but instead of + * using map we use map_list that we can use to select properties. + * A lot of time complex properties can be recomputed and communicate them is not a good idea. + * The same concept also apply for ghost_get. In general we choose which properties to communicate * * * \snippet Vector/4_complex_prop/main.cpp vect map ghost @@ -181,16 +218,16 @@ int main(int argc, char* argv[]) // Particles are redistribued across the processors but only the scalar,vector, and point properties // are transfert - vd.map_list<scalar,vector,point>(); + vd.map_list<scalar,vector,point,list,listA,listlist>(); // Synchronize the ghost - vd.ghost_get<scalar,vector,point>(); + vd.ghost_get<scalar,vector,point,listA,listlist>(); //! \cond [vect map ghost] \endcond /*! * - * \page Vector_4_complex_prop Vector 4 complex property + * \page Vector_4_complex_prop Vector 4 complex properties * * * ## Output and VTK visualization ## @@ -209,7 +246,44 @@ int main(int argc, char* argv[]) //! \cond [vtk] \endcond /*! - * \page Vector_4_complex_prop Vector 4 complex property + * + * \page Vector_4_complex_prop Vector 4 complex properties + * + * ## Print 4 particles in the ghost area ## + * + * Here we print that the first 4 particles to show that the list of A and the list of list are filled + * and the ghosts contain the correct information + * + * \snippet Vector/4_complex_prop/main.cpp print ghost info + * + */ + + //! \cond [print ghost info] \endcond + + size_t fg = vd.size_local(); + + Vcluster & v_cl = create_vcluster(); + if (v_cl.getProcessUnitID() == 0) + { + for ( ; fg < vd.size_local()+4 ; fg++) + { + std::cout << "List of A" << std::endl; + for (size_t i = 0 ; i < vd.getProp<listA>(fg).size() ; i++) + std::cout << "Element: " << i << " p1=" << vd.getProp<listA>(fg).get(i).p1 << " p2=" << vd.getProp<listA>(fg).get(i).p2 << std::endl; + + std::cout << "List of list" << std::endl; + for (size_t i = 0 ; i < vd.getProp<listlist>(fg).size() ; i++) + { + for (size_t j = 0 ; j < vd.getProp<listlist>(fg).get(i).size() ; j++) + std::cout << "Element: " << i << " " << j << " " << vd.getProp<listlist>(fg).get(i).get(j) << std::endl; + } + } + } + + //! \cond [print ghost info] \endcond + + /*! + * \page Vector_4_complex_prop Vector 4 complex properties * * ## Finalize ## {#finalize} * @@ -226,7 +300,7 @@ int main(int argc, char* argv[]) //! \cond [finalize] \endcond /*! - * \page Vector_4_complex_prop Vector 4 complex property + * \page Vector_4_complex_prop Vector 4 complex properties * * # Full code # {#code} * diff --git a/openfpm_data b/openfpm_data index dbfc39c70..f378ee11c 160000 --- a/openfpm_data +++ b/openfpm_data @@ -1 +1 @@ -Subproject commit dbfc39c70904fa40ac52d71e784cd6f54283f578 +Subproject commit f378ee11c3aa2be8d0fde9fe5308d86d1d705aa7 diff --git a/openfpm_pdata.doc b/openfpm_pdata.doc index b16dc1c02..94101cdb7 100644 --- a/openfpm_pdata.doc +++ b/openfpm_pdata.doc @@ -38,7 +38,7 @@ PROJECT_NAME = "OpenFPM_pdata" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.5.0 +PROJECT_NUMBER = 0.5.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/src/Vector/vector_dist_comm.hpp b/src/Vector/vector_dist_comm.hpp index 9f45b1c49..a22e80561 100644 --- a/src/Vector/vector_dist_comm.hpp +++ b/src/Vector/vector_dist_comm.hpp @@ -84,6 +84,67 @@ class vector_dist_comm //! replicated ghost particles that are local size_t lg_m; + //! process the particle with properties + struct proc_without_prp + { + template<typename T1, typename T2> inline static void proc(size_t lbl, size_t cnt, size_t id, T1 & v_prp, T2 & m_prp) + { + m_prp.get(lbl).set(cnt, v_prp.get(id)); + } + }; + + template<typename prp_object, int ... prp> + struct proc_with_prp + { + template<typename T1, typename T2> inline static void proc(size_t lbl, size_t cnt, size_t id, T1 & v_prp, T2 & m_prp) + { + // source object type + typedef encapc<1, prop, typename openfpm::vector<prop>::layout_type> encap_src; + // destination object type + typedef encapc<1, prp_object, typename openfpm::vector<prp_object>::layout_type> encap_dst; + + // Copy only the selected properties + object_si_d<encap_src, encap_dst, OBJ_ENCAP, prp...>(v_prp.get(id), m_prp.get(lbl).get(cnt)); + } + }; + + //! It process one particle + template<typename proc_class, typename T1, typename T2, typename T3, typename T4> inline void process_map_particle(size_t i, long int & end, long int & id_end, T1 & m_pos, T2 & m_prp, T3 & v_pos, T4 & v_prp, openfpm::vector<size_t> & cnt) + { + long int prc_id = m_opart.template get<2>(i); + size_t id = m_opart.template get<0>(i); + + if (prc_id >= 0) + { + size_t lbl = p_map_req.get(prc_id); + + m_pos.get(lbl).set(cnt.get(lbl), v_pos.get(id)); + proc_class::proc(lbl,cnt.get(lbl),id,v_prp,m_prp); + + cnt.get(lbl)++; + + // swap the particle + long int id_valid = get_end_valid(end,id_end); + + if (id_valid > 0 && (long int)id < id_valid) + { + v_pos.set(id,v_pos.get(id_valid)); + v_prp.set(id,v_prp.get(id_valid)); + } + } + else + { + // swap the particle + long int id_valid = get_end_valid(end,id_end); + + if (id_valid > 0 && (long int)id < id_valid) + { + v_pos.set(id,v_pos.get(id_valid)); + v_prp.set(id,v_prp.get(id_valid)); + } + } + } + /*! \brief Return a valid particle starting from end and tracing back * * \param end actual opart particle pointer @@ -492,21 +553,7 @@ class vector_dist_comm // Run through all the particles and fill the sending buffer for (size_t i = 0; i < m_opart.size(); i++) { - size_t lbl = p_map_req.get(m_opart.template get<2>(i)); - size_t id = m_opart.template get<0>(i); - - m_pos.get(lbl).set(cnt.get(lbl), v_pos.get(id)); - m_prp.get(lbl).set(cnt.get(lbl), v_prp.get(id)); - cnt.get(lbl)++; - - // swap the particle - long int id_valid = get_end_valid(end,id_end); - - if (id_valid > 0 && (long int)id < id_valid) - { - v_pos.set(id,v_pos.get(id_valid)); - v_prp.set(id,v_prp.get(id_valid)); - } + process_map_particle<proc_without_prp>(i,end,id_end,m_pos,m_prp,v_pos,v_prp,cnt); } v_pos.resize(v_pos.size() - m_opart.size()); @@ -523,17 +570,18 @@ class vector_dist_comm * \param pb send buffer * */ - template<typename prp_object,int ... prp> void fill_send_map_buf_list(openfpm::vector<Point<dim, St>> & v_pos, openfpm::vector<prop> & v_prp, openfpm::vector<size_t> & prc_r, openfpm::vector<size_t> & prc_sz_r, openfpm::vector<openfpm::vector<Point<dim,St>>> & m_pos, openfpm::vector<openfpm::vector<prp_object>> & m_prp) + template<typename prp_object,int ... prp> void fill_send_map_buf_list(openfpm::vector<Point<dim, St>> & v_pos, openfpm::vector<prop> & v_prp, openfpm::vector<size_t> & prc_sz_r, openfpm::vector<openfpm::vector<Point<dim,St>>> & m_pos, openfpm::vector<openfpm::vector<prp_object>> & m_prp) { - m_prp.resize(v_cl.getProcessingUnits()); - m_pos.resize(v_cl.getProcessingUnits()); - openfpm::vector<size_t> cnt(v_cl.getProcessingUnits()); + m_prp.resize(prc_sz_r.size()); + m_pos.resize(prc_sz_r.size()); + openfpm::vector<size_t> cnt(prc_sz_r.size()); - for (size_t i = 0; i < prc_r.size(); i++) + for (size_t i = 0; i < prc_sz_r.size(); i++) { // set the size and allocate, using mem warant that pos and prp is contiguous m_pos.get(i).resize(prc_sz_r.get(i)); m_prp.get(i).resize(prc_sz_r.get(i)); + cnt.get(i) = 0; } // end vector point @@ -545,31 +593,11 @@ class vector_dist_comm // Run through all the particles and fill the sending buffer for (size_t i = 0; i < m_opart.size(); i++) { - size_t lbl = m_opart.template get<2>(i); - size_t id = m_opart.template get<0>(i); - - m_pos.get(lbl).set(cnt.get(lbl), v_pos.get(id)); - - // source object type - typedef encapc<1, prop, typename openfpm::vector<prop>::layout_type> encap_src; - // destination object type - typedef encapc<1, prp_object, typename openfpm::vector<prp_object>::layout_type> encap_dst; - - // Copy only the selected properties - object_si_d<encap_src, encap_dst, OBJ_ENCAP, prp...>(v_prp.get(id), m_prp.get(lbl).get(cnt.get(lbl))); - - cnt.get(lbl)++; - - // swap the particle - long int id_valid = get_end_valid(end,id_end); - - if (id_valid > 0 && (long int)id < id_valid) - { - v_pos.set(id,v_pos.get(id_valid)); - v_prp.set(id,v_prp.get(id_valid)); - } + process_map_particle<proc_with_prp<prp_object,prp...>>(i,end,id_end,m_pos,m_prp,v_pos,v_prp,cnt); } + v_pos.resize(v_pos.size() - m_opart.size()); + v_prp.resize(v_prp.size() - m_opart.size()); } /*! \brief Label particles for mappings @@ -616,6 +644,12 @@ class vector_dist_comm lbl_p.last().template get<0>() = key; lbl_p.last().template get<2>() = p_id; } + else + { + lbl_p.add(); + lbl_p.last().template get<0>() = key; + lbl_p.last().template get<2>() = p_id; + } } // Add processors and add size @@ -930,7 +964,7 @@ public: //! properties vector openfpm::vector<openfpm::vector<prp_object>> m_prp; - fill_send_map_buf_list<prp_object,prp...>(v_pos,v_prp,prc_r, prc_sz_r, m_pos, m_prp); + fill_send_map_buf_list<prp_object,prp...>(v_pos,v_prp,prc_sz_r, m_pos, m_prp); v_cl.SSendRecv(m_pos,v_pos,prc_r,prc_recv_map,recv_sz_map); v_cl.SSendRecvP<openfpm::vector<prp_object>,decltype(v_prp),prp...>(m_prp,v_prp,prc_r,prc_recv_map,recv_sz_map); diff --git a/src/Vector/vector_dist_unit_test.hpp b/src/Vector/vector_dist_unit_test.hpp index 413bf7aac..a4ef53344 100644 --- a/src/Vector/vector_dist_unit_test.hpp +++ b/src/Vector/vector_dist_unit_test.hpp @@ -1773,6 +1773,7 @@ BOOST_AUTO_TEST_CASE( vector_dist_ghost_put ) #include "vector_dist_cell_list_tests.hpp" #include "vector_dist_NN_tests.hpp" +#include "vector_dist_complex_prp_unit_test.hpp" BOOST_AUTO_TEST_SUITE_END() -- GitLab