From d28f7bd39f5cf816674f33db85e4498826ef6f74 Mon Sep 17 00:00:00 2001
From: Pietro Incardona <incardon@mpi-cbg.de>
Date: Wed, 21 Sep 2016 22:45:37 +0200
Subject: [PATCH] Fixing example

---
 .../3_molecular_dynamic/main_expr_vl.cpp      | 151 +++++
 .../Vector/3_molecular_dynamic/main_vl.cpp    | 482 +++++++++++++++
 .../3_molecular_dynamic/main_vl_sym.cpp       | 552 ++++++++++++++++++
 example/Vector/4_complex_prop/main_ser.cpp    | 504 ++++++++++++++++
 example/Vector/4_reorder/main_expr.cpp        | 139 +++++
 .../vector_dist_complex_prp_unit_test.hpp     | 231 ++++++++
 6 files changed, 2059 insertions(+)
 create mode 100644 example/Vector/3_molecular_dynamic/main_expr_vl.cpp
 create mode 100644 example/Vector/3_molecular_dynamic/main_vl.cpp
 create mode 100644 example/Vector/3_molecular_dynamic/main_vl_sym.cpp
 create mode 100644 example/Vector/4_complex_prop/main_ser.cpp
 create mode 100644 example/Vector/4_reorder/main_expr.cpp
 create mode 100644 src/Vector/vector_dist_complex_prp_unit_test.hpp

diff --git a/example/Vector/3_molecular_dynamic/main_expr_vl.cpp b/example/Vector/3_molecular_dynamic/main_expr_vl.cpp
new file mode 100644
index 00000000..5e214636
--- /dev/null
+++ b/example/Vector/3_molecular_dynamic/main_expr_vl.cpp
@@ -0,0 +1,151 @@
+#include "Vector/vector_dist.hpp"
+#include "Plot/GoogleChart.hpp"
+#include "Operators/Vector/vector_dist_operators.hpp"
+#include "timer.hpp"
+
+constexpr int velocity = 0;
+constexpr int force = 1;
+
+struct ln_potential
+{
+	double sigma12,sigma6,r_cut2,shift;
+
+	ln_potential(double sigma12_, double sigma6_, double r_cut2_, double shift_) {sigma12 = sigma12_; sigma6 = sigma6_; r_cut2 = r_cut2_;shift = shift_;}
+
+	Point<2,double> value(const Point<3,double> & xp, const Point<3,double> xq)
+	{
+		double rn = norm2(xp - xq);
+		if (rn >= r_cut2)	return 0.0;
+
+		Point<2,double> E({2.0 * ( sigma12 / (rn*rn*rn*rn*rn*rn) - sigma6 / ( rn*rn*rn) ) - shift,0.0});
+
+		return E;
+	}
+};
+
+struct ln_force
+{
+	double sigma12,sigma6,r_cut2;
+
+	ln_force(double sigma12_, double sigma6_, double r_cut2_) {sigma12 = sigma12_; sigma6 = sigma6_;r_cut2 = r_cut2_;}
+
+	Point<3,double> value(const Point<3,double> & xp, const Point<3,double> xq)
+	{
+		Point<3,double> r = xp - xq;
+		double rn = norm2(r);
+
+		if (rn > r_cut2)	return 0.0;
+
+		return 24.0*(2.0 * sigma12 / (rn*rn*rn*rn*rn*rn*rn) -  sigma6 / (rn*rn*rn*rn)) * r;
+	}
+};
+
+int main(int argc, char* argv[])
+{
+	double dt = 0.0005, sigma = 0.1, r_cut = 3.0*sigma;
+
+	double sigma6 = pow(sigma,6), sigma12 = pow(sigma,12);
+	double rc2 = r_cut * r_cut;
+	double shift = 2.0 * ( sigma12 / (rc2*rc2*rc2*rc2*rc2*rc2) - sigma6 / ( rc2*rc2*rc2) );
+
+	openfpm::vector<double> x;
+	openfpm::vector<openfpm::vector<double>> y;
+
+
+	openfpm_init(&argc,&argv);
+	Vcluster & vcl = create_vcluster();
+
+	size_t sz[3] = {10,10,10};
+	Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
+	size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
+	Ghost<3,float> ghost(r_cut);
+
+	ln_force lf(sigma12,sigma6,r_cut*r_cut);
+	ln_potential lp(sigma12,sigma6,r_cut*r_cut,shift);
+
+	vector_dist<3,double, aggregate<Point<3,double>,Point<3,double>> > vd(0,box,bc,ghost);
+
+	auto v_force = getV<force>(vd);
+	auto v_velocity = getV<velocity>(vd);
+	auto v_pos = getV<PROP_POS>(vd);
+
+	auto it = vd.getGridIterator(sz);
+
+	while (it.isNext())
+	{
+		vd.add();
+
+		auto key = it.get();
+
+		vd.getLastPos()[0] = key.get(0) * it.getSpacing(0);
+		vd.getLastPos()[1] = key.get(1) * it.getSpacing(1);
+		vd.getLastPos()[2] = key.get(2) * it.getSpacing(2);
+
+		++it;
+	}
+
+	v_force = 0;
+	v_velocity = 0;
+
+	timer tsim;
+	tsim.start();
+
+	auto NN = vd.getCellList(r_cut);
+
+	vd.updateCellList(NN);
+	v_force = applyKernel_in_sim(vd,NN,lf);
+	unsigned long int f = 0;
+
+	// MD time stepping
+	for (size_t i = 0; i < 10000 ; i++)
+	{
+		assign(v_velocity, v_velocity + 0.5*dt*v_force,
+			   v_pos, v_pos + v_velocity*dt);
+
+		vd.map();
+		vd.template ghost_get<>();
+
+		// calculate forces or a(tn + 1) Step 2
+		vd.updateCellList(NN);
+		v_force = applyKernel_in_sim(vd,NN,lf);
+
+		v_velocity = v_velocity + 0.5*dt*v_force;
+
+		if (i % 100 == 0)
+		{
+			vd.deleteGhost();
+			vd.write("particles_",f);
+			vd.ghost_get<>();
+
+			vd.updateCellList(NN);
+			Point<2,double> E = rsum(applyKernel_in_sim(vd,NN,lp) + (v_velocity * v_velocity)/2.0,vd).get();
+
+			vcl.sum(E.get(0));vcl.sum(E.get(1));
+			vcl.execute();
+
+			// we save the energy calculated at time step i c contain the time-step y contain the energy
+			x.add(i);
+			y.add({E.get(0),E.get(1),E.get(0) - E.get(1)});
+
+			if (vcl.getProcessUnitID() == 0)
+				std::cout << "Energy Total: " << E.get(0) << "   Kinetic: " <<  E.get(1) << "   Potential: " << E.get(0) - E.get(1) << std::endl;
+
+			f++;
+		}
+	}
+
+	tsim.stop();
+	std::cout << "Time: " << tsim.getwct() << std::endl;
+
+	GCoptions options;
+	options.title = std::string("Energy with time");
+	options.yAxis = std::string("Energy");
+	options.xAxis = std::string("iteration");
+	options.lineWidth = 1.0;
+
+	GoogleChart cg;
+	cg.AddLinesGraph(x,y,options);
+	cg.write("gc_plot2_out.html");
+
+	openfpm_finalize();
+}
diff --git a/example/Vector/3_molecular_dynamic/main_vl.cpp b/example/Vector/3_molecular_dynamic/main_vl.cpp
new file mode 100644
index 00000000..c039c991
--- /dev/null
+++ b/example/Vector/3_molecular_dynamic/main_vl.cpp
@@ -0,0 +1,482 @@
+
+#include "Vector/vector_dist.hpp"
+#include "Decomposition/CartDecomposition.hpp"
+#include "data_type/aggregate.hpp"
+#include "Plot/GoogleChart.hpp"
+#include "Plot/util.hpp"
+#include "timer.hpp"
+
+/*!
+ * \page Vector_3_md_vl Vector 3 molecular dynamic with Verlet list
+ *
+ *
+ * [TOC]
+ *
+ * # Molecular Dynamic with Lennard-Jones potential with verlet list # {#e3_md_vl}
+ *
+ * This example show a simple Lennard-Jones molecular dynamic simulation in a stable regime.
+ * We will use Verlet-list in order to get a speed-up from force calculation
+ *
+ * ## Constants ##
+ *
+ * Here we define some useful constants
+ *
+ * \snippet Vector/3_molecular_dynamic/main_vl.cpp constants
+ *
+ */
+
+//! \cond [constants] \endcond
+
+constexpr int velocity = 0;
+constexpr int force = 1;
+
+//! \cond [constants] \endcond
+
+/*!
+ *
+ * \page Vector_3_md_vl Vector 3 molecular dynamic with Verlet list
+ *
+ * ## Calculate forces ## {#e3_md_vl_cf}
+ *
+ * In this function we calculate the forces between particles. It require the vector of particles,
+ * the Verlet-list and sigma for the Lennard-Jhones potential. The function is exactly the same
+ * as the original with the following changes
+ *
+ * \see \ref e3_md_cf
+ *
+ * * The function accept a VerletList instead of a CellList
+ *  \snippet main_vl.cpp arg diff
+ *
+ * * There is no call to updateCellList
+ *
+ * * How to get an iterator over neighborhood of a particle
+ *   \snippet main_vl.cpp NN iterator
+ *
+ * Teh rest remain the same
+ *
+ * \snippet Vector/3_molecular_dynamic/main_vl.cpp calc forces vl
+ *
+ */
+
+//! \cond [calc forces vl] \endcond
+
+//! \cond [arg diff] \endcond
+
+void calc_forces(vector_dist<3,double, aggregate<double[3],double[3]> > & vd, VerletList<3, double, FAST, shift<3, double> > & NN, double sigma12, double sigma6, double r_cut)
+{
+	//! \cond [arg diff] \endcond
+
+	// Get an iterator over particles
+	auto it2 = vd.getDomainIterator();
+
+	// For each particle p ...
+	while (it2.isNext())
+	{
+		// ... get the particle p
+		auto p = it2.get();
+
+		// Get the position xp of the particle
+		Point<3,double> xp = vd.getPos(p);
+
+		// Reset the forice counter
+		vd.template getProp<force>(p)[0] = 0.0;
+		vd.template getProp<force>(p)[1] = 0.0;
+		vd.template getProp<force>(p)[2] = 0.0;
+
+		//! \cond [NN iterator] \endcond
+
+		// Get an iterator over the neighborhood particles of p
+		auto Np = NN.template getNNIterator<NO_CHECK>(p.getKey());
+
+		//! \cond [NN iterator] \endcond
+
+		// For each neighborhood particle ...
+		while (Np.isNext())
+		{
+			// ... q
+			auto q = Np.get();
+
+			// if (p == q) skip this particle
+			if (q == p.getKey())	{++Np; continue;};
+
+			// Get the position of p
+			Point<3,double> xq = vd.getPos(q);
+
+			// Get the distance between p and q
+			Point<3,double> r = xp - xq;
+
+			// take the norm of this vector
+			double rn = norm2(r);
+
+			if (rn > r_cut * r_cut) {++Np;continue;}
+
+			// Calculate the force, using pow is slower
+			Point<3,double> f = 24.0*(2.0 *sigma12 / (rn*rn*rn*rn*rn*rn*rn) -  sigma6 / (rn*rn*rn*rn)) * r;
+
+			// we sum the force produced by q on p
+			vd.template getProp<force>(p)[0] += f.get(0);
+			vd.template getProp<force>(p)[1] += f.get(1);
+			vd.template getProp<force>(p)[2] += f.get(2);
+
+			// Next neighborhood
+			++Np;
+		}
+
+		// Next particle
+		++it2;
+	}
+}
+
+//! \cond [calc forces vl] \endcond
+
+/*!
+ * \page Vector_3_md_vl Vector 3 molecular dynamic with verlet list
+ *
+ * ## Calculate energy ## {#e3_md_vl_ce}
+ *
+ * We also need a function to calculate energy, this function require the same parameter as calculate forces
+ *
+ * \see \ref e3_md_ce
+ *
+ * The following changes has been made
+ *
+ * * The function accept a VerletList instead of a cell-List
+ * * There is no call to updateCellList
+ * * How to get an iterator over neigborhood particles
+ *
+ * \snippet Vector/3_molecular_dynamic/main_vl.cpp calc energy vl
+ *
+ */
+
+//! \cond [calc energy vl] \endcond
+
+double calc_energy(vector_dist<3,double, aggregate<double[3],double[3]> > & vd, VerletList<3, double, FAST, shift<3, double> > & NN, double sigma12, double sigma6, double r_cut)
+{
+	double E = 0.0;
+
+	double rc = r_cut*r_cut;
+	double shift = 2.0 * ( sigma12 / (rc*rc*rc*rc*rc*rc) - sigma6 / ( rc*rc*rc) );
+
+	// Get the iterator
+	auto it2 = vd.getDomainIterator();
+
+	// For each particle ...
+	while (it2.isNext())
+	{
+		// ... p
+		auto p = it2.get();
+
+		// Get the position of the particle p
+		Point<3,double> xp = vd.getPos(p);
+
+		// Get an iterator over the neighborhood of the particle p
+		auto Np = NN.template getNNIterator<NO_CHECK>(p.getKey());
+
+		// For each neighborhood of the particle p
+		while (Np.isNext())
+		{
+			// Neighborhood particle q
+			auto q = Np.get();
+
+			// if p == q skip this particle
+			if (q == p.getKey())	{++Np; continue;};
+
+			// Get position of the particle q
+			Point<3,double> xq = vd.getPos(q);
+
+			// take the normalized direction
+			double rn = norm2(xp - xq);
+
+			if (rn >= r_cut*r_cut)
+			{++Np;continue;}
+
+			// potential energy (using pow is slower)
+			E += 2.0 * ( sigma12 / (rn*rn*rn*rn*rn*rn) - sigma6 / ( rn*rn*rn) ) - shift;
+
+			// Next neighborhood
+			++Np;
+		}
+
+		// Kinetic energy of the particle given by its actual speed
+		E +=   (vd.template getProp<velocity>(p)[0]*vd.template getProp<velocity>(p)[0] +
+				vd.template getProp<velocity>(p)[1]*vd.template getProp<velocity>(p)[1] +
+				vd.template getProp<velocity>(p)[2]*vd.template getProp<velocity>(p)[2]) / 2;
+
+		// Next Particle
+		++it2;
+	}
+
+	// Calculated energy
+	return E;
+}
+
+//! \cond [calc energy vl] \endcond
+
+int main(int argc, char* argv[])
+{
+	/*!
+	 * \page Vector_3_md_vl Vector 3 molecular dynamic with Verlet list
+	 *
+	 * ## Simulation ## {#e3_md_vl_sim}
+	 *
+	 * The simulation is equal to the simulation explained in the example molecular dynamic
+	 *
+	 * \see \ref e3_md
+	 *
+	 * The differences are that:
+	 *
+	 * * The Ghost must be r_cut+skin
+	 * \snippet
+	 *
+	 * * We create a Verlet list with skin instead of a Cell list
+	 * \snippet Vector/3_molecular_dynamic/main_vl.cpp verlet skin
+	 *
+	 * * every 10 steps we do a map and update the verlet-list, in all the other case we just do skip labelling
+	 * \snippet Vector/3_molecular_dynamic/main_vl.cpp update verlet
+	 *
+	 * **Explanation**
+	 *
+	 * Updating the verlet list is extremely expensive. For this reason we create a Verlet list
+	 * that contain r_cut + skin particles. Using the fact that during the full simulation each
+	 *  particle does not move more than 0.0015 in one iteration, if the skin is 0.03
+	 *  we can update the Verlet list every \f$ \frac{0.03}{2 \cdot 0.0015} = 10 \f$. The 2 factor if given by the fact
+	 *  that in the worst case where one particle is going left and one on the right from the prospective of
+	 *  one particle the particle moove \f$ 2 \cdot 0.0015 \f$.
+	 *
+	 * Because the Verlet lists are constructed based on the local-id of the particles a map or a ghost_get
+	 *  would invalidate the verlet. For this reason the map is called every 10 time-step (when we
+	 *  update the verlet), and a particular ghost_get with SKIP_LABELLING is used during every iteration.
+	 *
+	 *  The function ghost_get with skip labeling does not recompute the particle to send but use the
+	 *  the ids of the old particles updating the positions (and properties if needed) and keeping the old
+	 *   indexes without invalidating the Verlet-list. Doing this we can avoid to send particles that are
+	 *   entering the ghost area r_cut+skin. Because we know that no particle in 10 iteration can travel for a
+	 *   distance bigger than the skin, we are sure that in 10 iteration no-new particle that were not in the
+	 *   r_cut+skin ghost area can enter the ghost area r_cut.
+	 *
+	 *
+	 * \snippet Vector/3_molecular_dynamic/main_vl.cpp simulation
+	 *
+	 */
+
+	//! \cond [simulation] \endcond
+
+	double dt = 0.00025;
+	double sigma = 0.1;
+	double r_cut = 3.0*sigma;
+	double r_gskin = 1.3*r_cut;
+	double sigma12 = pow(sigma,12);
+	double sigma6 = pow(sigma,6);
+
+	openfpm::vector<double> x;
+	openfpm::vector<openfpm::vector<double>> y;
+
+	openfpm_init(&argc,&argv);
+	Vcluster & v_cl = create_vcluster();
+
+	// we will use it do place particles on a 10x10x10 Grid like
+	size_t sz[3] = {10,10,10};
+
+	// domain
+	Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
+
+	// Boundary conditions
+	size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
+
+	// ghost, big enough to contain the interaction radius
+	Ghost<3,float> ghost(r_gskin);
+
+	vector_dist<3,double, aggregate<double[3],double[3]> > vd(0,box,bc,ghost);
+
+	auto it = vd.getGridIterator(sz);
+
+	while (it.isNext())
+	{
+		vd.add();
+
+		auto key = it.get();
+
+		vd.getLastPos()[0] = key.get(0) * it.getSpacing(0);
+		vd.getLastPos()[1] = key.get(1) * it.getSpacing(1);
+		vd.getLastPos()[2] = key.get(2) * it.getSpacing(2);
+
+		vd.template getLastProp<velocity>()[0] = 0.0;
+		vd.template getLastProp<velocity>()[1] = 0.0;
+		vd.template getLastProp<velocity>()[2] = 0.0;
+
+		vd.template getLastProp<force>()[0] = 0.0;
+		vd.template getLastProp<force>()[1] = 0.0;
+		vd.template getLastProp<force>()[2] = 0.0;
+
+		++it;
+	}
+
+	timer tsim;
+	tsim.start();
+
+	//! \cond [verlet skin] \endcond
+
+	// Get the Cell list structure
+	auto NN = vd.getVerlet(r_gskin);
+
+	//! \cond [verlet skin] \endcond
+
+	// calculate forces
+	calc_forces(vd,NN,sigma12,sigma6,r_cut);
+	unsigned long int f = 0;
+
+	int cnt = 0;
+	double max_disp = 0.0;
+
+	// MD time stepping
+	for (size_t i = 0; i < 10000 ; i++)
+	{
+		// Get the iterator
+		auto it3 = vd.getDomainIterator();
+
+		double max_displ = 0.0;
+
+		// integrate velicity and space based on the calculated forces (Step1)
+		while (it3.isNext())
+		{
+			auto p = it3.get();
+
+			// here we calculate v(tn + 0.5)
+			vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
+			vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
+			vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
+
+			Point<3,double> disp({vd.template getProp<velocity>(p)[0]*dt,vd.template getProp<velocity>(p)[1]*dt,vd.template getProp<velocity>(p)[2]*dt});
+
+			// here we calculate x(tn + 1)
+			vd.getPos(p)[0] += disp.get(0);
+			vd.getPos(p)[1] += disp.get(1);
+			vd.getPos(p)[2] += disp.get(2);
+
+			if (disp.norm() > max_displ)
+				max_displ = disp.norm();
+
+			++it3;
+		}
+
+		if (max_disp < max_displ)
+			max_disp = max_displ;
+
+		//! \cond [update verlet] \endcond
+
+		// Because we moved the particles in space we have to map them and re-sync the ghost
+		if (cnt % 10 == 0)
+		{
+			vd.map();
+			vd.template ghost_get<>();
+			// Get the Cell list structure
+			vd.updateVerlet(NN,r_gskin);
+		}
+		else
+		{
+			vd.template ghost_get<>(SKIP_LABELLING);
+		}
+
+		//! \cond [update verlet] \endcond
+
+		cnt++;
+
+		// calculate forces or a(tn + 1) Step 2
+		calc_forces(vd,NN,sigma12,sigma6,r_cut);
+
+		// Integrate the velocity Step 3
+		auto it4 = vd.getDomainIterator();
+
+		while (it4.isNext())
+		{
+			auto p = it4.get();
+
+			// here we calculate v(tn + 1)
+			vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
+			vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
+			vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
+
+			++it4;
+		}
+
+		// After every iteration collect some statistic about the confoguration
+		if (i % 100 == 0)
+		{
+			// We write the particle position for visualization (Without ghost)
+			vd.deleteGhost();
+			vd.write("particles_",f);
+
+			// we resync the ghost
+			vd.ghost_get<>(SKIP_LABELLING);
+
+			// We calculate the energy
+			double energy = calc_energy(vd,NN,sigma12,sigma6,r_cut);
+			auto & vcl = create_vcluster();
+			vcl.sum(energy);
+			vcl.max(max_disp);
+			vcl.execute();
+
+			// we save the energy calculated at time step i c contain the time-step y contain the energy
+			x.add(i);
+			y.add({energy});
+
+			// We also print on terminal the value of the energy
+			// only one processor (master) write on terminal
+			if (vcl.getProcessUnitID() == 0)
+				std::cout << "Energy: " << energy << "   " << max_disp << "  " << std::endl;
+
+			max_disp = 0.0;
+
+			f++;
+		}
+	}
+
+	tsim.stop();
+	std::cout << "Time: " << tsim.getwct()  << std::endl;
+
+	//! \cond [simulation] \endcond
+
+	// Google charts options, it store the options to draw the X Y graph
+	GCoptions options;
+
+	// Title of the graph
+	options.title = std::string("Energy with time");
+
+	// Y axis name
+	options.yAxis = std::string("Energy");
+
+	// X axis name
+	options.xAxis = std::string("iteration");
+
+	// width of the line
+	options.lineWidth = 1.0;
+
+	// Object that draw the X Y graph
+	GoogleChart cg;
+
+	// Add the graph
+	// The graph that it produce is in svg format that can be opened on browser
+	cg.AddLinesGraph(x,y,options);
+
+	// Write into html format
+	cg.write("gc_plot2_out.html");
+
+	//! \cond [google chart] \endcond
+
+	/*!
+	 * \page Vector_3_md_vl Vector 3 molecular dynamic with Verlet list
+	 *
+	 * ## Finalize ## {#finalize_v_e3_md_vl}
+	 *
+	 *  At the very end of the program we have always to de-initialize the library
+	 *
+	 * \snippet Vector/3_molecular_dynamic/main_vl.cpp finalize
+	 *
+	 */
+
+	//! \cond [finalize] \endcond
+
+	openfpm_finalize();
+
+	//! \cond [finalize] \endcond
+}
diff --git a/example/Vector/3_molecular_dynamic/main_vl_sym.cpp b/example/Vector/3_molecular_dynamic/main_vl_sym.cpp
new file mode 100644
index 00000000..07136e19
--- /dev/null
+++ b/example/Vector/3_molecular_dynamic/main_vl_sym.cpp
@@ -0,0 +1,552 @@
+#include "Vector/vector_dist.hpp"
+#include "Decomposition/CartDecomposition.hpp"
+#include "data_type/aggregate.hpp"
+#include "Plot/GoogleChart.hpp"
+#include "Plot/util.hpp"
+#include "timer.hpp"
+
+/*!
+ * \page Vector_3_md_vl Vector 3 molecular dynamic with Verlet list
+ *
+ *
+ * ## Variations for symmetric interaction ##
+ *
+ * In this example we show the variation in case of symmetric interations.
+ *
+ */
+
+//! \cond [constants] \endcond
+
+constexpr int velocity = 0;
+constexpr int force = 1;
+
+//! \cond [constants] \endcond
+
+/*!
+ *
+ * \page Vector_3_md_vl Vector 3 molecular dynamic with Verlet list symmetric
+ *
+ * ## Calculate forces ##
+ *
+ * In this function we calculate the forces between particles. It require the vector of particles
+ * Cell list and sigma factor for the Lennard-Jhones potential. The function is exactly the same
+ * as the original with the following changes
+ *
+ *  \see \ref e3_md_vl_cf
+ *
+ * * We have to reset for force counter for each particles
+ *  \snippet Vector/3_molecular_dynamic/main_vl_sym.cpp reset
+ *
+ * * The iterator go through real AND ghost.
+ *  \snippet Vector/3_molecular_dynamic/main_vl_sym.cpp real and ghost
+ *
+ * * If we calculate the force for p-q we are also adding this force to q-p
+ *  \snippet Vector/3_molecular_dynamic/main_vl_sym.cpp add to q
+ *
+ * ** Explanation**
+ *
+ * The reason why symmetric Verlet exist is to reduce the computation. In a symmetric interaction
+ * we have that the interaction p-q is is the same as q-p. This mean that we are calculating 2 times
+ * the same quantity one when we are on particle p and one when we are on particle q. Symmetric verlet
+ *  avoid this. Every time we calculate a force p-q we also increment the force q-p.
+ *
+ * The reason instead why we have to go through ghost is the following
+ *
+ *
+	\verbatim
+
+	|      |
+	| Ghost|
+	|      |
+	|      |
+	|      |
+	|      |
+	|      |
+	|   +----+----+----+
+	|   |  | |    |    |
+	|   | 1| | 2  | 3  |
+	|   |  | |    |    |
+	|   +--------------+
+	|      | |  * | 4  |
+	|      +--------------------
+	|    X   | 5  |    |
+	|        +---------+
+	+---------------------------
+
+	\endverbatim
+ *
+ * Where * is a particle and X is another particle on ghost
+ *
+ * The symmetric verlet list is constructed from the cell-List 1,2,3,4,5.
+ * As you can see the interaction X-* is not present in the neighborhood of *
+ * (cells 1,2,3,4,5). But is present if we draw the neighborhood of X. This
+ * mean we have to iterate also across X if we want the interation X-*
+ *
+ *
+ * \snippet Vector/3_molecular_dynamic/main_vl_sym.cpp calc forces vl
+ *
+ * The symmetric force calculation is faster than the normal one. but is not 2
+ * time faster. The reason can be founded in 2 factors.
+ *
+ * * We have to reset the force
+ *
+ * * Every particle in the ghost
+ * that interact with one in the domain is still calculated twice by the same
+ * processor or some other.
+ *
+ * * The access pattern is worst we alternate read and write stressing more the Memory
+ *
+ * * We have to iterate across domain + ghost
+ *
+ * Overall the function calc_force is faster
+ *
+ * \snippet Vector/3_molecular_dynamic/main_vl_sym.cpp calc forces vl
+ *
+ */
+
+//! \cond [calc forces vl] \endcond
+
+void calc_forces(vector_dist<3,double, aggregate<double[3],double[3]> > & vd, VerletList<3, double, FAST, shift<3, double> > & NN, double sigma12, double sigma6, double r_cut)
+{
+	//! \cond [reset] \endcond
+
+	// Reset the force for all particles
+	auto it3 = vd.getDomainIterator();
+
+	// For each particle p ...
+	while (it3.isNext())
+	{
+		// ... get the particle p
+		auto p = it3.get();
+
+		// Reset the forice counter
+		vd.template getProp<force>(p)[0] = 0.0;
+		vd.template getProp<force>(p)[1] = 0.0;
+		vd.template getProp<force>(p)[2] = 0.0;
+
+		// Next particle p
+		++it3;
+	}
+
+	//! \cond [reset] \endcond
+
+	//! \cond [real and ghost] \endcond
+
+	// Get an iterator over particles
+	auto it2 = vd.getDomainAndGhostIterator();
+
+	//! \cond [real and ghost] \endcond
+
+	// For each particle p ...
+	while (it2.isNext())
+	{
+		// ... get the particle p
+		auto p = it2.get();
+
+		// Get the position xp of the particle
+		Point<3,double> xp = vd.getPos(p);
+
+		// Get an iterator over the neighborhood particles of p
+		// Note that in case of symmetric
+		auto Np = NN.template getNNIterator<NO_CHECK>(p.getKey());
+
+		// For each neighborhood particle ...
+		while (Np.isNext())
+		{
+			// ... q
+			auto q = Np.get();
+
+			// if (p == q) skip this particle
+			if (q == p.getKey() || (p.getKey() >= vd.size_local() && q >= vd.size_local()))	{++Np; continue;};
+
+			// Get the position of p
+			Point<3,double> xq = vd.getPos(q);
+
+			// Get the distance between p and q
+			Point<3,double> r = xp - xq;
+
+			// take the norm of this vector
+			double rn = norm2(r);
+
+			if (rn > r_cut * r_cut) {++Np;continue;}
+
+			// Calculate the force, using pow is slower
+			Point<3,double> f = 24.0*(2.0 *sigma12 / (rn*rn*rn*rn*rn*rn*rn) -  sigma6 / (rn*rn*rn*rn)) * r;
+
+			// we sum the force produced by q on p
+			vd.template getProp<force>(p)[0] += f.get(0);
+			vd.template getProp<force>(p)[1] += f.get(1);
+			vd.template getProp<force>(p)[2] += f.get(2);
+
+			//! \cond [add to q] \endcond
+
+			// we sum the force produced by p on q
+			vd.template getProp<force>(q)[0] -= f.get(0);
+			vd.template getProp<force>(q)[1] -= f.get(1);
+			vd.template getProp<force>(q)[2] -= f.get(2);
+
+			//! \cond [add to q] \endcond
+
+			// Next neighborhood
+			++Np;
+		}
+
+		// Next particle
+		++it2;
+	}
+}
+
+//! \cond [calc forces vl] \endcond
+
+
+/*!
+ * \page Vector_3_md_vl Vector 3 molecular dynamic with Verlet list symmetric
+ *
+ * ## Calculate energy ##
+ *
+ * No changes that been made to this code compared to the molecular dynamic example
+ * with Verlet-list
+ *
+ * \see \ref e3_md_vl
+ *
+ *
+ * \snippet Vector/3_molecular_dynamic/main_vl_sym.cpp calc energy vl
+ *
+ */
+
+//! \cond [calc energy vl] \endcond
+
+double calc_energy(vector_dist<3,double, aggregate<double[3],double[3]> > & vd, VerletList<3, double, FAST, shift<3, double> > & NN, double sigma12, double sigma6, double r_cut)
+{
+	double E = 0.0;
+
+	double rc = r_cut*r_cut;
+	double shift = 2.0 * ( sigma12 / (rc*rc*rc*rc*rc*rc) - sigma6 / ( rc*rc*rc) );
+
+	// Get the iterator
+	auto it2 = vd.getDomainIterator();
+
+	// For each particle ...
+	while (it2.isNext())
+	{
+		// ... p
+		auto p = it2.get();
+
+		// Get the position of the particle p
+		Point<3,double> xp = vd.getPos(p);
+
+		// Get an iterator over the neighborhood of the particle p
+		auto Np = NN.template getNNIterator<NO_CHECK>(p.getKey());
+
+		double Ep = E;
+
+		// For each neighborhood of the particle p
+		while (Np.isNext())
+		{
+			// Neighborhood particle q
+			auto q = Np.get();
+
+			// if p == q skip this particle
+			if (q == p.getKey() && q < vd.size_local())	{++Np; continue;};
+
+			// Get position of the particle q
+			Point<3,double> xq = vd.getPos(q);
+
+			// take the normalized direction
+			double rn = norm2(xp - xq);
+
+			if (rn >= r_cut*r_cut)
+			{++Np;continue;}
+
+			// potential energy (using pow is slower)
+			E += 2.0 * ( sigma12 / (rn*rn*rn*rn*rn*rn) - sigma6 / ( rn*rn*rn) ) - shift;
+
+			// Next neighborhood
+			++Np;
+		}
+
+		// Kinetic energy of the particle given by its actual speed
+		E +=   (vd.template getProp<velocity>(p)[0]*vd.template getProp<velocity>(p)[0] +
+				vd.template getProp<velocity>(p)[1]*vd.template getProp<velocity>(p)[1] +
+				vd.template getProp<velocity>(p)[2]*vd.template getProp<velocity>(p)[2]) / 2;
+
+		// Next Particle
+		++it2;
+	}
+
+	// Calculated energy
+	return E;
+}
+
+//! \cond [calc energy vl] \endcond
+
+int main(int argc, char* argv[])
+{
+	/*!
+	 * \page Vector_3_md_vl Vector 3 molecular dynamic with Verlet list symmetric
+	 *
+	 * ## Simulation ##
+	 *
+	 * The simulation is equal to the simulation explained in the example molecular dynamic
+	 *
+	 * \see \ref e3_md_vl
+	 *
+	 * The differences are that:
+	 *
+	 * * Create symmetric Verlet-list
+	 *   \snippet Vector/3_molecular_dynamic/main_vl_sym.cpp sim verlet
+	 *
+	 * * For Energy calculation we have to create another verlet in this case a normal Verlet-list
+	 *  \snippet Vector/3_molecular_dynamic/main_vl_sym.cpp norm verlet
+	 *
+	 * We need 2 verlet-list with one normal because we cannot use
+	 * symmetric Verlet to calculate total reductions like total energy
+	 *
+	 * \snippet Vector/3_molecular_dynamic/main_vl_sym.cpp simulation
+	 *
+	 */
+
+	//! \cond [simulation] \endcond
+
+	double dt = 0.00025;
+	double sigma = 0.1;
+	double r_cut = 3.0*sigma;
+	double r_gskin = 1.3*r_cut;
+	double sigma12 = pow(sigma,12);
+	double sigma6 = pow(sigma,6);
+
+	openfpm::vector<double> x;
+	openfpm::vector<openfpm::vector<double>> y;
+
+	openfpm_init(&argc,&argv);
+	Vcluster & v_cl = create_vcluster();
+
+	// we will use it do place particles on a 10x10x10 Grid like
+	size_t sz[3] = {10,10,10};
+
+	// domain
+	Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
+
+	// Boundary conditions
+	size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
+
+	// ghost, big enough to contain the interaction radius
+	Ghost<3,float> ghost(r_gskin);
+
+	vector_dist<3,double, aggregate<double[3],double[3]> > vd(0,box,bc,ghost);
+
+	auto it = vd.getGridIterator(sz);
+
+	while (it.isNext())
+	{
+		vd.add();
+
+		auto key = it.get();
+
+		vd.getLastPos()[0] = key.get(0) * it.getSpacing(0);
+		vd.getLastPos()[1] = key.get(1) * it.getSpacing(1);
+		vd.getLastPos()[2] = key.get(2) * it.getSpacing(2);
+
+		vd.template getLastProp<velocity>()[0] = 0.0;
+		vd.template getLastProp<velocity>()[1] = 0.0;
+		vd.template getLastProp<velocity>()[2] = 0.0;
+
+		vd.template getLastProp<force>()[0] = 0.0;
+		vd.template getLastProp<force>()[1] = 0.0;
+		vd.template getLastProp<force>()[2] = 0.0;
+
+		++it;
+	}
+
+	timer tsim;
+	tsim.start();
+
+	//! \cond [sim verlet] \endcond
+
+	// Get the Cell list structure
+	auto NN = vd.getVerlet(r_gskin,VL_SYMMETRIC);
+
+	//! \cond [sim verlet] \endcond
+
+	//! \cond [norm verlet] \endcond
+
+	auto NNE = vd.getVerlet(r_gskin);
+
+	//! \cond [norm verlet] \endcond
+
+	// calculate forces
+	calc_forces(vd,NN,sigma12,sigma6,r_cut);
+	unsigned long int f = 0;
+
+	int cnt = 0;
+	double max_disp = 0.0;
+
+	// MD time stepping
+	for (size_t i = 0; i < 10000 ; i++)
+	{
+		// Get the iterator
+		auto it3 = vd.getDomainIterator();
+
+		double max_displ = 0.0;
+
+		// integrate velicity and space based on the calculated forces (Step1)
+		while (it3.isNext())
+		{
+			auto p = it3.get();
+
+			// here we calculate v(tn + 0.5)
+			vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
+			vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
+			vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
+
+			Point<3,double> disp({vd.template getProp<velocity>(p)[0]*dt,vd.template getProp<velocity>(p)[1]*dt,vd.template getProp<velocity>(p)[2]*dt});
+
+			// here we calculate x(tn + 1)
+			vd.getPos(p)[0] += disp.get(0);
+			vd.getPos(p)[1] += disp.get(1);
+			vd.getPos(p)[2] += disp.get(2);
+
+			if (disp.norm() > max_displ)
+				max_displ = disp.norm();
+
+			++it3;
+		}
+
+		if (max_disp < max_displ)
+			max_disp = max_displ;
+
+		// Because we moved the particles in space we have to map them and re-sync the ghost
+		if (cnt % 10 == 0)
+		{
+			vd.map();
+			vd.template ghost_get<>();
+			// Get the Cell list structure
+			vd.updateVerlet(NN,r_gskin,VL_SYMMETRIC);
+		}
+		else
+		{
+			vd.template ghost_get<>(SKIP_LABELLING);
+		}
+
+		cnt++;
+
+		// calculate forces or a(tn + 1) Step 2
+		calc_forces(vd,NN,sigma12,sigma6,r_cut);
+
+		// Integrate the velocity Step 3
+		auto it4 = vd.getDomainIterator();
+
+		while (it4.isNext())
+		{
+			auto p = it4.get();
+
+			// here we calculate v(tn + 1)
+			vd.template getProp<velocity>(p)[0] += 0.5*dt*vd.template getProp<force>(p)[0];
+			vd.template getProp<velocity>(p)[1] += 0.5*dt*vd.template getProp<force>(p)[1];
+			vd.template getProp<velocity>(p)[2] += 0.5*dt*vd.template getProp<force>(p)[2];
+
+			++it4;
+		}
+
+		// After every iteration collect some statistic about the confoguration
+		if (i % 100 == 0)
+		{
+			// We write the particle position for visualization (Without ghost)
+			vd.deleteGhost();
+			vd.write("particles_",f);
+
+			// we resync the ghost
+			vd.ghost_get<>(SKIP_LABELLING);
+
+			// update the verlet for energy calculation
+			vd.updateVerlet(NNE,r_gskin);
+
+			// We calculate the energy
+			double energy = calc_energy(vd,NNE,sigma12,sigma6,r_cut);
+			auto & vcl = create_vcluster();
+			vcl.sum(energy);
+			vcl.max(max_disp);
+			vcl.execute();
+
+			// we save the energy calculated at time step i c contain the time-step y contain the energy
+			x.add(i);
+			y.add({energy});
+
+			// We also print on terminal the value of the energy
+			// only one processor (master) write on terminal
+			if (vcl.getProcessUnitID() == 0)
+				std::cout << "Energy: " << energy << "   " << max_disp << "   " << std::endl;
+
+			max_disp = 0.0;
+
+			f++;
+		}
+	}
+
+	tsim.stop();
+	std::cout << "Time: " << tsim.getwct()  << std::endl;
+
+	//! \cond [simulation] \endcond
+
+	// Google charts options, it store the options to draw the X Y graph
+	GCoptions options;
+
+	// Title of the graph
+	options.title = std::string("Energy with time");
+
+	// Y axis name
+	options.yAxis = std::string("Energy");
+
+	// X axis name
+	options.xAxis = std::string("iteration");
+
+	// width of the line
+	options.lineWidth = 1.0;
+
+	// Object that draw the X Y graph
+	GoogleChart cg;
+
+	// Add the graph
+	// The graph that it produce is in svg format that can be opened on browser
+	cg.AddLinesGraph(x,y,options);
+
+	// Write into html format
+	cg.write("gc_plot2_out.html");
+
+	//! \cond [google chart] \endcond
+
+	/*!
+	 * \page Vector_3_md_vl Vector 3 molecular dynamic with Verlet list symmetric
+	 *
+	 * ## Finalize ## {#finalize_v_e3_md_sym}
+	 *
+	 *  At the very end of the program we have always to de-initialize the library
+	 *
+	 * \snippet Vector/3_molecular_dynamic/main_vl_sym.cpp finalize
+	 *
+	 */
+
+	//! \cond [finalize] \endcond
+
+	openfpm_finalize();
+
+	//! \cond [finalize] \endcond
+
+	/*!
+	 * \page Vector_3_md_vl Vector 3 molecular dynamic
+	 *
+	 * ## Full code ## {#code_v_e3_md_vl}
+	 *
+	 * \include Vector/3_molecular_dynamic/main_vl.cpp
+	 *
+	 */
+
+	/*!
+	 * \page Vector_3_md_vl Vector 3 molecular dynamic with Verlet list symmetric
+	 *
+	 * ## Full code symmetric ## {#code_v_e3_md_sym}
+	 *
+	 * \include Vector/3_molecular_dynamic/main_vl_sym.cpp
+	 *
+	 */
+}
diff --git a/example/Vector/4_complex_prop/main_ser.cpp b/example/Vector/4_complex_prop/main_ser.cpp
new file mode 100644
index 00000000..3a7e91db
--- /dev/null
+++ b/example/Vector/4_complex_prop/main_ser.cpp
@@ -0,0 +1,504 @@
+/*!
+ *
+ * \page Vector_4_complex_prop_ser Vector 4 property serialization
+ *
+ *
+ * [TOC]
+ *
+ *
+ * # Vector 4 property serialization # {#vector_example_cp_ser}
+ *
+ *
+ * This example show how we can use complex properties in a vector when we use a custom structure with
+ * a pointer inside. In particular we will show how to construct the serialization and de-serialization
+ * methods for the structure my_struct defined here
+ *
+ * \snippet Vector/4_complex_prop/main_ser.cpp my structure
+ *
+ * \snippet Vector/4_complex_prop/main_ser.cpp my structure end
+ *
+ */
+
+#include "Vector/vector_dist.hpp"
+
+//! \cond [my structure] \endcond
+
+struct my_struct
+{
+	//! C string size
+	size_t size;
+
+	//! C string pointer
+	char * ptr;
+
+	//! C++ string
+	std::string str;
+
+	//! vector
+	openfpm::vector<int> v;
+
+//! \cond [my structure] \endcond
+
+public:
+
+	//! Functions to check if the packing object is complex
+	static bool pack()	{return true;}
+
+
+	//! \cond [con and dest] \endcond
+
+	my_struct()
+	{
+		size = 0;
+		ptr = NULL;
+	}
+
+	~my_struct()
+	{
+		if (ptr != NULL)
+			delete [] ptr;
+	}
+
+	//! \cond [con and dest] \endcond
+
+	//! \cond [pack request] \endcond
+
+	//! Serialization request
+	template<int ... prp> inline void packRequest(size_t & req) const
+	{
+		req += 2*sizeof(size_t) + size + str.size()+1;
+		v.packRequest(req);
+	}
+
+	//! \cond [pack request] \endcond
+
+	//! \cond [pack serialize] \endcond
+
+	//! Serialize the data structure
+	template<typename Memory, int ... prp> inline void pack(ExtPreAlloc<Memory> & mem, Pack_stat & sts) const
+	{
+		//! \cond [packer ser pack] \endcond
+
+		//Serialize the number that determine the C-string size
+		Packer<size_t, Memory>::pack(mem,size,sts);
+
+		//! \cond [packer ser pack] \endcond
+
+		//! \cond [pack ser copy] \endcond
+
+		// Allocate and copy the string
+		mem.allocate(size);
+		void * t_ptr = mem.getPointer();
+		memcpy(t_ptr,ptr,size);
+
+		//! \cond [pack ser copy] \endcond
+
+		//! \cond [pack ser other] \endcond
+
+		//Serialize the number that determine the C++-string str.size()+1 given by the null terminator
+		Packer<size_t, Memory>::pack(mem,str.size()+1,sts);
+
+		// Allocate and copy the string
+		mem.allocate(str.size()+1);
+		char * t_ptr2 = (char *)mem.getPointer();
+		memcpy(t_ptr2,str.c_str(),str.size());
+
+		// Add null terminator
+		t_ptr2[str.size()] = 0;
+
+		Packer<decltype(v), Memory>::pack(mem,v,sts);
+
+		//! \cond [pack ser other] \endcond
+	}
+
+	//! \cond [pack serialize] \endcond
+
+	//! \cond [unpack de-serialize] \endcond
+
+	//! De-serialize the data structure
+	template<typename Memory, int ... prp> inline void unpack(ExtPreAlloc<Memory> & mem, Unpack_stat & ps)
+	{
+		//! \cond [unpacker ser pack] \endcond
+
+		// unpack the size of the C string
+		Unpacker<size_t, Memory>::unpack(mem,size,ps);
+
+		//! \cond [unpacker ser pack] \endcond
+
+		//! \cond [unpacker ser create] \endcond
+
+		// Allocate the C string
+		ptr = new char[size];
+
+		// source pointer
+		char * ptr_src = (char *)mem.getPointerOffset(ps.getOffset());
+
+		// copy from the buffer to the destination
+		memcpy(ptr,ptr_src,size);
+
+		// update the pointer
+		ps.addOffset(size);
+
+		//! \cond [unpacker ser create] \endcond
+
+		//! \cond [unpacker ser other] \endcond
+
+		// get the the C++ string size
+		size_t cpp_size;
+		Unpacker<size_t, Memory>::unpack(mem,cpp_size,ps);
+
+		// Create the string from the serialized data (de-serialize)
+		char * ptr_src2 = (char *)mem.getPointerOffset(ps.getOffset());
+		str = std::string(ptr_src2);
+		ps.addOffset(cpp_size);
+
+		// Unpack the vector
+		Unpacker<decltype(v), Memory>::unpack(mem,v,ps);
+
+		//! \cond [unpacker ser other] \endcond
+	}
+
+	//! \cond [unpack de-serialize] \endcond
+
+//! \cond [my structure end] \endcond
+
+};
+
+//! \cond [my structure end] \endcond
+
+/*!
+ *
+ * \page Vector_4_complex_prop_ser Vector 4 property serialization
+ *
+ * In order to make my_struct serializable we need 3 methods
+ *
+ * * **packRequest** This method indicate how many byte are needed to serialize this structure
+ * * **pack** This method serialize the data-structure
+ * * **unpack** This method de-serialize the data structure
+ *
+ * ### packRequest ###
+ *
+ * \snippet Vector/4_complex_prop/main_ser.cpp pack request
+ *
+ * This function calculate the size in byte to serialize this structure in this case we serialize
+ * 2 numbers so 2*sizeof(size_t). One C string of size "size" and one C++ string of size str.size(). Because
+ * std::string has a constructor from null terminating string we add the null terminator to easy construct an
+ * std::string. This mean that
+ * the C++ string will be serialized in str.size()+1 bytes. The result must be summed to counter req that is used
+ * to allocate a buffer big enough for serialization. The function is template and has a variadic argument
+ * "int ... prp" this can be ignored
+ *
+ * ### pack ###
+ *
+ * Here we serialize the object. The function give as argument
+ *
+ * * **ExtPreAlloc<Memory>** mem The memory where we have to serialize the information
+ * * **Pack_stat** unused
+ * * **int ... prp** unused
+ *
+ * The only important parameter is the object mem where we will serialize the information
+ *
+ * We first pack the number that indicate the size of the C string. A convenient way
+ * is use the function
+ *
+ * \snippet Vector/4_complex_prop/main_ser.cpp packer ser pack
+ *
+ * The function **Packer<decltype(object),Memory>::pack(object,sts)** work if **object** is a
+ * fundamental C++ type, a struct that does not contain pointers, any object that
+ * implement the interface pack,unpack,packRequest (like my_struct). Most openfpm
+ * data-structure like openfpm::vector and grid implement such interface and
+ * can be used directly with **Packer<...>::pack(...)**.
+ * After packed the size of the string we have to serialize the content of the pointer string.
+ * unfortunately there is no Packer<...>::pack(...) function to do this and must be
+ * manually done. This can be done with the following steps
+ *
+ * * Allocate the memory to copy the value of the string
+ * * Get the pointer to the memory allocated
+ * * copy the content of the string into the allocated memory
+ *
+ * \snippet Vector/4_complex_prop/main_ser.cpp pack ser copy
+ *
+ * For the C++ string the concept is the same, the difference is that we put a null terminator at the end
+ * of the serialized string
+ *
+ * \snippet Vector/4_complex_prop/main_ser.cpp pack ser other
+ *
+ * ### unpack ###
+ *
+ * Here we de-serialize the object. The function take a reference to object
+ *
+ * * **ExtPreAlloc<Memory>** mem, contain the serialized information that must be de-serialized
+ * * **Pack_stat** contain the offset to the memory to de-serialize
+ * * **int ... prp** unused
+ *
+ * De-serialization must be in general done in the same order as we serialized
+ * We first unpack the number that indicate the size of the C string. A convenient way
+ * is to use the function
+ *
+ * \snippet Vector/4_complex_prop/main_ser.cpp unpacker ser pack
+ *
+ * the variable **size** contain now the size of the packed string we can now
+ *
+ * * create memory with **new** that store the C string
+ * * Get the pointer to the serialized information
+ * * copy the string from mem into the created memory
+ * * update the offset pointer
+ *
+ * \snippet Vector/4_complex_prop/main_ser.cpp unpacker ser create
+ *
+ * For the C++ string is just the same
+ *
+ * * We get the size of the string
+ * * we create an std::string out of the null terminating serialized string
+ * * we assign the created std::string to str
+ *
+ * \snippet Vector/4_complex_prop/main_ser.cpp unpacker ser other
+ *
+ * ### Constructor and destructor ###
+ *
+ * Constructor and destructor are not releated to serialization and de-serialization concept.
+ * But on how my_struct is constructed and destructed in order to avoid memory
+ * leak/corruption. In the constructor we set ptr to NULL in the destructor we
+ *  destroy the pointer (if different from NULL) to avoid memory leak
+ *
+ * \snippet Vector/4_complex_prop/main_ser.cpp con and dest
+ *
+ */
+
+int main(int argc, char* argv[])
+{
+	/*!
+	 *
+	 * \page Vector_4_complex_prop_ser Vector 4 property serialization
+	 *
+	 *
+	 * ## Initialization and vector creation ##
+	 *
+	 * After we initialize the library we can create a vector with complex properties
+	 * with the following line
+	 *
+	 * \snippet Vector/4_complex_prop/main.cpp vect create
+	 *
+	 * In this this particular case every particle carry two my_struct object
+	 *
+	 */
+
+    // initialize the library
+	openfpm_init(&argc,&argv);
+
+	// Here we define our domain a 2D box with internals from 0 to 1.0 for x and y
+	Box<2,float> domain({0.0,0.0},{1.0,1.0});
+
+	// Here we define the boundary conditions of our problem
+    size_t bc[2]={PERIODIC,PERIODIC};
+
+	// extended boundary around the domain, and the processor domain
+	Ghost<2,float> g(0.01);
+
+	// my_struct at position 0 in the aggregate
+	constexpr int my_s1 = 0;
+
+	// my_struct at position 1 in the aggregate
+	constexpr int my_s2 = 1;
+
+	//! \cond [vect create] \endcond
+
+	vector_dist<2,float, aggregate<my_struct,my_struct>>
+	vd(4096,domain,bc,g);
+
+	std::cout << "HAS PACK: " << has_pack_agg<aggregate<my_struct,my_struct>>::result::value << std::endl;
+
+	//! \cond [vect create] \endcond
+
+	/*!
+	 *
+	 * \page Vector_4_complex_prop_ser Vector 4 property serialization
+	 *
+	 *
+	 * ## Assign values to properties ##
+	 *
+	 * In this loop we assign position to particles and we fill the two my_struct
+	 * that each particle contain. As demostration the first my_struct is filled
+	 *  with the string representation of the particle coordinates. The second my struct
+	 *   is filled with the string representation of the particle position multiplied by 2.0.
+	 * The the vectors of the two my_struct are filled respectively with the sequence
+	 * 1,2,3 and 1,2,3,4
+	 *
+	 *
+	 *
+	 * \snippet Vector/4_complex_prop/main_ser.cpp vect assign
+	 *
+	 */
+
+	//! \cond [vect assign] \endcond
+
+	auto it = vd.getDomainIterator();
+
+	while (it.isNext())
+	{
+		auto p = it.get();
+
+		// we define x, assign a random position between 0.0 and 1.0
+		vd.getPos(p)[0] = (float)rand() / RAND_MAX;
+
+		// we define y, assign a random position between 0.0 and 1.0
+		vd.getPos(p)[1] = (float)rand() / RAND_MAX;
+
+		// Get the particle position as point
+		Point<2,float> pt = vd.getPos(p);
+
+		// create a C string from the particle coordinates
+		// and copy into my struct
+		vd.getProp<my_s1>(p).size = 32;
+		vd.getProp<my_s1>(p).ptr = new char[32];
+		strcpy(vd.getProp<my_s1>(p).ptr,pt.toString().c_str());
+
+		// create a C++ string from the particle coordinates
+		vd.getProp<my_s1>(p).str = std::string(pt.toString());
+
+		vd.getProp<my_s1>(p).v.add(1);
+		vd.getProp<my_s1>(p).v.add(2);
+		vd.getProp<my_s1>(p).v.add(3);
+
+		pt = pt * 2.0;
+
+		// create a C string from the particle coordinates multiplied by 2.0
+		// and copy into my struct
+		vd.getProp<my_s2>(p).size = 32;
+		vd.getProp<my_s2>(p).ptr = new char[32];
+		strcpy(vd.getProp<my_s2>(p).ptr,pt.toString().c_str());
+
+		// create a C++ string from the particle coordinates
+		vd.getProp<my_s2>(p).str = std::string(pt.toString());
+
+		vd.getProp<my_s2>(p).v.add(1);
+		vd.getProp<my_s2>(p).v.add(2);
+		vd.getProp<my_s2>(p).v.add(3);
+		vd.getProp<my_s2>(p).v.add(4);
+
+		// next particle
+		++it;
+	}
+
+	//! \cond [vect assign] \endcond
+
+	/*!
+	 *
+	 * \page Vector_4_complex_prop_ser Vector 4 property serialization
+	 *
+	 *
+	 * ## Mapping and ghost_get ##
+	 *
+	 * Particles are redistributed across processors and we also synchronize the ghost
+	 *
+	 * \see \ref e0_s_map
+	 *
+	 * \see \ref e1_part_ghost
+	 *
+	 * \snippet Vector/4_complex_prop/main_ser.cpp vect map ghost
+	 *
+	 */
+
+	//! \cond [vect map ghost] \endcond
+
+	// Particles are redistribued across the processors
+	vd.map();
+
+	// Synchronize the ghost
+	vd.ghost_get<my_s1,my_s2>();
+
+	//! \cond [vect map ghost] \endcond
+
+	/*!
+	 *
+	 * \page Vector_4_complex_prop_ser Vector 4 property serialization
+	 *
+	 *
+	 * ## Output and VTK visualization ##
+	 *
+	 * Vector with complex properties can be still be visualized, because unknown properties are
+	 * automatically excluded
+	 *
+	 * \see \ref e0_s_vis_vtk
+	 *
+	 * \snippet Vector/4_complex_prop/main.cpp vtk
+	 *
+	 */
+
+	//! \cond [vtk] \endcond
+
+	vd.write("particles");
+
+	//! \cond [vtk] \endcond
+
+	/*!
+	 *
+	 * \page Vector_4_complex_prop_ser Vector 4 property serialization
+	 *
+	 * ## Print 4 particles in the ghost area ##
+	 *
+	 * Here we print that the first 4 particles to show that the two my_struct contain the
+	 * right information
+	 *
+	 * \snippet Vector/4_complex_prop/main_ser.cpp print ghost info
+	 *
+	 */
+
+	//! \cond [print ghost info] \endcond
+
+	size_t fg = vd.size_local();
+
+	Vcluster & v_cl = create_vcluster();
+
+	// Only the master processor print
+	if (v_cl.getProcessUnitID() == 0)
+	{
+		// Print 4 particles
+		for ( ; fg < vd.size_local()+4 ; fg++)
+		{
+			// Print my struct1 information
+			std::cout << "my_struct1:" << std::endl;
+			std::cout << "C-string: " << vd.getProp<my_s1>(fg).ptr << std::endl;
+			std::cout << "Cpp-string: " << vd.getProp<my_s1>(fg).str << std::endl;
+
+			for (size_t i = 0 ; i < vd.getProp<my_s1>(fg).v.size() ; i++)
+				std::cout << "Element: " << i << "   " << vd.getProp<my_s1>(fg).v.get(i) << std::endl;
+
+			// Print my struct 2 information
+			std::cout << "my_struct2" << std::endl;
+			std::cout << "C-string: " << vd.getProp<my_s2>(fg).ptr << std::endl;
+			std::cout << "Cpp-string: " << vd.getProp<my_s2>(fg).str << std::endl;
+
+			for (size_t i = 0 ; i < vd.getProp<my_s2>(fg).v.size() ; i++)
+				std::cout << "Element: " << i << "   " << vd.getProp<my_s2>(fg).v.get(i) << std::endl;
+		}
+	}
+
+	//! \cond [print ghost info] \endcond
+
+	/*!
+	 * \page Vector_4_complex_prop_ser Vector 4 property serialization
+	 *
+	 * ## Finalize ## {#finalize}
+	 *
+	 *  At the very end of the program we have always to de-initialize the library
+	 *
+	 * \snippet Vector/4_complex_prop/main_ser.cpp finalize
+	 *
+	 */
+
+	//! \cond [finalize] \endcond
+
+	openfpm_finalize();
+
+	//! \cond [finalize] \endcond
+
+	/*!
+	 * \page Vector_4_complex_prop_ser Vector 4 property serialization
+	 *
+	 * # Full code # {#code}
+	 *
+	 * \include Vector/4_complex_prop/main_ser.cpp
+	 *
+	 */
+}
diff --git a/example/Vector/4_reorder/main_expr.cpp b/example/Vector/4_reorder/main_expr.cpp
new file mode 100644
index 00000000..86c7e31b
--- /dev/null
+++ b/example/Vector/4_reorder/main_expr.cpp
@@ -0,0 +1,139 @@
+#include "Vector/vector_dist.hpp"
+#include "Plot/GoogleChart.hpp"
+#include "Operators/Vector/vector_dist_operators.hpp"
+
+constexpr int velocity = 0;
+constexpr int force = 1;
+
+struct ln_potential
+{
+	double sigma12,sigma6;
+
+	ln_potential(double sigma12_, double sigma6_) {sigma12 = sigma12_, sigma6 = sigma6_;}
+
+	Point<2,double> value(const Point<3,double> & xp, const Point<3,double> xq)
+	{
+		double rn = norm2(xp - xq);
+
+		Point<2,double> E({4.0 * ( sigma12 / (rn*rn*rn*rn*rn*rn) - sigma6 / ( rn*rn*rn) ),
+						 0.0});
+
+		return E;
+	}
+};
+
+struct ln_force
+{
+	double sigma12,sigma6;
+
+	ln_force(double sigma12_, double sigma6_) {sigma12 = sigma12_; sigma6 = sigma6_;}
+
+	Point<3,double> value(const Point<3,double> & xp, const Point<3,double> xq)
+	{
+		Point<3,double> r = xp - xq;
+		double rn = norm2(r);
+
+		return 24.0*(2.0 * sigma12 / (rn*rn*rn*rn*rn*rn*rn) -  sigma6 / (rn*rn*rn*rn)) * r;
+	}
+};
+
+int main(int argc, char* argv[])
+{
+	double dt = 0.0005, sigma = 0.1, r_cut = 0.3;
+
+	double sigma6 = pow(sigma,6), sigma12 = pow(sigma,12);
+
+	openfpm::vector<double> x;
+	openfpm::vector<openfpm::vector<double>> y;
+
+
+	openfpm_init(&argc,&argv);
+	Vcluster & vcl = create_vcluster();
+
+	size_t sz[3] = {10,10,10};
+	Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
+	size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
+	Ghost<3,float> ghost(r_cut);
+
+	ln_force lf(sigma12,sigma6);
+	ln_potential lp(sigma12,sigma6);
+
+	vector_dist<3,double, aggregate<Point<3,double>,Point<3,double>> > vd(0,box,bc,ghost);
+
+	auto v_force = getV<force>(vd);
+	auto v_velocity = getV<velocity>(vd);
+	auto v_pos = getV<PROP_POS>(vd);
+
+	auto it = vd.getGridIterator(sz);
+
+	while (it.isNext())
+	{
+		vd.add();
+
+		auto key = it.get();
+
+		vd.getLastPos()[0] = key.get(0) * it.getSpacing(0);
+		vd.getLastPos()[1] = key.get(1) * it.getSpacing(1);
+		vd.getLastPos()[2] = key.get(2) * it.getSpacing(2);
+
+		++it;
+	}
+
+	v_force = 0;
+	v_velocity = 0;
+
+	auto NN = vd.getCellList(r_cut);
+
+	vd.updateCellList(NN);
+	v_force = applyKernel_in_sim(vd,NN,lf);
+	unsigned long int f = 0;
+
+	// MD time stepping
+	for (size_t i = 0; i < 10000 ; i++)
+	{
+		assign(v_velocity, v_velocity + 0.5*dt*v_force,
+			   v_pos, v_pos + v_velocity*dt);
+
+		vd.map();
+		vd.template ghost_get<>();
+
+		// calculate forces or a(tn + 1) Step 2
+		vd.updateCellList(NN);
+		v_force = applyKernel_in_sim(vd,NN,lf);
+
+		v_velocity = v_velocity + 0.5*dt*v_force;
+
+		if (i % 100 == 0)
+		{
+			vd.deleteGhost();
+			vd.write("particles_",f);
+			vd.ghost_get<>();
+
+			Point<2,double> E = rsum(applyKernel_in_sim(vd,NN,lp) + (v_velocity * v_velocity)/2.0,vd).get();
+
+			vcl.sum(E.get(0));vcl.sum(E.get(1));
+			vcl.execute();
+
+			// we save the energy calculated at time step i c contain the time-step y contain the energy
+			x.add(i);
+			y.add({E.get(0),E.get(1),E.get(0) - E.get(1)});
+
+			if (vcl.getProcessUnitID() == 0)
+				std::cout << "Energy Total: " << E.get(0) << "   Kinetic: " <<  E.get(1) << "   Potential: " << E.get(0) - E.get(1) << std::endl;
+
+			f++;
+		}
+	}
+
+	GCoptions options;
+	options.title = std::string("Energy with time");
+	options.yAxis = std::string("Energy");
+	options.xAxis = std::string("iteration");
+	options.lineWidth = 1.0;
+
+	GoogleChart cg;
+	cg.AddLinesGraph(x,y,options);
+	cg.write("gc_plot2_out.html");
+
+	openfpm_finalize();
+}
diff --git a/src/Vector/vector_dist_complex_prp_unit_test.hpp b/src/Vector/vector_dist_complex_prp_unit_test.hpp
new file mode 100644
index 00000000..253259a8
--- /dev/null
+++ b/src/Vector/vector_dist_complex_prp_unit_test.hpp
@@ -0,0 +1,231 @@
+/*
+ * vector_dist_complex_prp_unit_test.hpp
+ *
+ *  Created on: Sep 18, 2016
+ *      Author: i-bird
+ */
+
+#ifndef SRC_VECTOR_VECTOR_DIST_COMPLEX_PRP_UNIT_TEST_HPP_
+#define SRC_VECTOR_VECTOR_DIST_COMPLEX_PRP_UNIT_TEST_HPP_
+
+
+BOOST_AUTO_TEST_CASE( vector_dist_periodic_complex_prp_test_use_3d )
+{
+	Vcluster & v_cl = create_vcluster();
+
+	if (v_cl.getProcessingUnits() > 48)
+		return;
+
+    // set the seed
+	// create the random generator engine
+	std::srand(v_cl.getProcessUnitID());
+    std::default_random_engine eg;
+    std::uniform_real_distribution<float> ud(0.0f, 1.0f);
+
+    long int k = 124288 * v_cl.getProcessingUnits();
+
+	long int big_step = k / 4;
+	big_step = (big_step == 0)?1:big_step;
+
+	print_test_v( "Testing 3D vector full complex prp vector k<=",k);
+
+	// 3D test
+	for ( ; k >= 2 ; k-= decrement(k,big_step) )
+	{
+		BOOST_TEST_CHECKPOINT( "Testing 3D full complex prp vector k=" << k );
+
+		Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
+
+		// Boundary conditions
+		size_t bc[3]={NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
+
+		// factor
+		float factor = pow(create_vcluster().getProcessingUnits()/2.0f,1.0f/3.0f);
+
+		// ghost
+		Ghost<3,float> ghost(0.05 / factor);
+
+		// ghost2 (a little bigger because of round off error)
+		Ghost<3,float> ghost2(0.05001 / factor);
+
+		// Distributed vector
+		vector_dist<3,float, aggregate<openfpm::vector<float>,grid_cpu<3,aggregate<double,double[3]>> > > vd(k,box,bc,ghost);
+
+		auto it = vd.getIterator();
+
+		while (it.isNext())
+		{
+			auto key = it.get();
+
+			vd.getPos(key)[0] = ud(eg);
+			vd.getPos(key)[1] = ud(eg);
+			vd.getPos(key)[2] = ud(eg);
+
+			// initalize vector property and grid
+
+			vd.template getProp<0>(key).add(vd.getPos(key)[0]);
+			vd.template getProp<0>(key).add(vd.getPos(key)[1]);
+			vd.template getProp<0>(key).add(vd.getPos(key)[2]);
+
+			vd.template getProp<0>(key).add(vd.getPos(key)[0]+vd.getPos(key)[1]);
+			vd.template getProp<0>(key).add(vd.getPos(key)[1]+vd.getPos(key)[2]);
+			vd.template getProp<0>(key).add(vd.getPos(key)[0]+vd.getPos(key)[2]);
+
+			// Grid
+			size_t sz[] = {3,3,3};
+			vd.template getProp<1>(key).resize(sz);
+
+			vd.template getProp<1>(key).template get<0>({0,0,0}) = vd.getPos(key)[0];
+			vd.template getProp<1>(key).template get<0>({0,0,1}) = vd.getPos(key)[1];
+			vd.template getProp<1>(key).template get<0>({0,0,2}) = vd.getPos(key)[2];
+
+			vd.template getProp<1>(key).template get<0>({0,1,0}) = 2.0*vd.getPos(key)[0];
+			vd.template getProp<1>(key).template get<0>({0,1,1}) = 2.0*vd.getPos(key)[1];
+			vd.template getProp<1>(key).template get<0>({0,1,2}) = 2.0*vd.getPos(key)[2];
+
+			vd.template getProp<1>(key).template get<0>({0,2,0}) = 3.0*vd.getPos(key)[0];
+			vd.template getProp<1>(key).template get<0>({0,2,1}) = 3.0*vd.getPos(key)[1];
+			vd.template getProp<1>(key).template get<0>({0,2,2}) = 3.0*vd.getPos(key)[2];
+
+			vd.template getProp<1>(key).template get<0>({1,0,0}) = 4.0*vd.getPos(key)[0];
+			vd.template getProp<1>(key).template get<0>({1,0,1}) = 4.0*vd.getPos(key)[1];
+			vd.template getProp<1>(key).template get<0>({1,0,2}) = 4.0*vd.getPos(key)[2];
+
+			vd.template getProp<1>(key).template get<0>({1,1,0}) = 5.0*vd.getPos(key)[0];
+			vd.template getProp<1>(key).template get<0>({1,1,1}) = 5.0*vd.getPos(key)[1];
+			vd.template getProp<1>(key).template get<0>({1,1,2}) = 5.0*vd.getPos(key)[2];
+
+			vd.template getProp<1>(key).template get<0>({1,2,0}) = 6.0*vd.getPos(key)[0];
+			vd.template getProp<1>(key).template get<0>({1,2,1}) = 6.0*vd.getPos(key)[1];
+			vd.template getProp<1>(key).template get<0>({1,2,2}) = 6.0*vd.getPos(key)[2];
+
+			vd.template getProp<1>(key).template get<0>({2,0,0}) = 7.0*vd.getPos(key)[0];
+			vd.template getProp<1>(key).template get<0>({2,0,1}) = 7.0*vd.getPos(key)[1];
+			vd.template getProp<1>(key).template get<0>({2,0,2}) = 7.0*vd.getPos(key)[2];
+
+			vd.template getProp<1>(key).template get<0>({2,1,0}) = 8.0*vd.getPos(key)[0];
+			vd.template getProp<1>(key).template get<0>({2,1,1}) = 8.0*vd.getPos(key)[1];
+			vd.template getProp<1>(key).template get<0>({2,1,2}) = 8.0*vd.getPos(key)[2];
+
+			vd.template getProp<1>(key).template get<0>({2,2,0}) = 9.0*vd.getPos(key)[0];
+			vd.template getProp<1>(key).template get<0>({2,2,1}) = 9.0*vd.getPos(key)[1];
+			vd.template getProp<1>(key).template get<0>({2,2,2}) = 9.0*vd.getPos(key)[2];
+
+			++it;
+		}
+
+		vd.map();
+
+		// sync the ghost
+		vd.ghost_get<0,1>();
+
+		// Domain + ghost
+		Box<3,float> dom_ext = box;
+		dom_ext.enlarge(ghost2);
+
+		// Iterate on all particles domain + ghost
+		size_t l_cnt = 0;
+		size_t nl_cnt = 0;
+		size_t n_out = 0;
+
+		auto it2 = vd.getIterator();
+		count_local_n_local<3,vector_dist<3,float, aggregate<openfpm::vector<float>,grid_cpu<3,aggregate<double,double[3]>>>>  >(vd,it2,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
+
+		// No particles should be out of domain + ghost
+		BOOST_REQUIRE_EQUAL(n_out,0ul);
+
+		// Ghost must populated because we synchronized them
+		if (k > 524288)
+		{
+			BOOST_REQUIRE(nl_cnt != 0);
+			BOOST_REQUIRE(l_cnt > nl_cnt);
+		}
+
+		// Sum all the particles inside the domain
+		v_cl.sum(l_cnt);
+		v_cl.execute();
+		BOOST_REQUIRE_EQUAL(l_cnt,(size_t)k);
+
+		l_cnt = 0;
+		nl_cnt = 0;
+
+		// Iterate only on the ghost particles
+		auto itg = vd.getGhostIterator();
+		count_local_n_local<3, vector_dist<3,float, aggregate<openfpm::vector<float>,grid_cpu<3,aggregate<double,double[3]>>>> >(vd,itg,bc,box,dom_ext,l_cnt,nl_cnt,n_out);
+
+		// No particle on the ghost must be inside the domain
+		BOOST_REQUIRE_EQUAL(l_cnt,0ul);
+
+		// Ghost must be populated
+		if (k > 524288)
+		{
+			BOOST_REQUIRE(nl_cnt != 0);
+		}
+
+		// check that the particles contain the correct information
+
+		bool ret = true;
+		auto it3 = vd.getDomainAndGhostIterator();
+
+		while (it3.isNext())
+		{
+			auto key = it3.get();
+
+			ret &= vd.template getProp<0>(key).size() == 6;
+
+			ret &= vd.template getProp<0>(key).get(0) == vd.getPos(key)[0];
+			ret &= vd.template getProp<0>(key).get(1) == vd.getPos(key)[1];
+			ret &= vd.template getProp<0>(key).get(2) == vd.getPos(key)[2];
+
+			ret &= vd.template getProp<0>(key).get(3) == vd.getPos(key)[0]+vd.getPos(key)[1];
+			ret &= vd.template getProp<0>(key).get(4) == vd.getPos(key)[1]+vd.getPos(key)[2];
+			ret &= vd.template getProp<0>(key).get(5) == vd.getPos(key)[0]+vd.getPos(key)[2];
+
+//			BOOST_REQUIRE_EQUAL(vd.template getProp<0>(key).get(0),vd.getPos(key)[0]);
+
+			ret &= vd.template getProp<1>(key).size() == 3*3*3;
+			ret &= vd.template getProp<1>(key).template get<0>({0,0,0}) == vd.getPos(key)[0];
+			ret &= vd.template getProp<1>(key).template get<0>({0,0,1}) == vd.getPos(key)[1];
+			ret &= vd.template getProp<1>(key).template get<0>({0,0,2}) == vd.getPos(key)[2];
+
+			ret &= vd.template getProp<1>(key).template get<0>({0,1,0}) == 2.0*vd.getPos(key)[0];
+			ret &= vd.template getProp<1>(key).template get<0>({0,1,1}) == 2.0*vd.getPos(key)[1];
+			ret &= vd.template getProp<1>(key).template get<0>({0,1,2}) == 2.0*vd.getPos(key)[2];
+
+			ret &= vd.template getProp<1>(key).template get<0>({0,2,0}) == 3.0*vd.getPos(key)[0];
+			ret &= vd.template getProp<1>(key).template get<0>({0,2,1}) == 3.0*vd.getPos(key)[1];
+			ret &= vd.template getProp<1>(key).template get<0>({0,2,2}) == 3.0*vd.getPos(key)[2];
+
+			ret &= vd.template getProp<1>(key).template get<0>({1,0,0}) == 4.0*vd.getPos(key)[0];
+			ret &= vd.template getProp<1>(key).template get<0>({1,0,1}) == 4.0*vd.getPos(key)[1];
+			ret &= vd.template getProp<1>(key).template get<0>({1,0,2}) == 4.0*vd.getPos(key)[2];
+
+			ret &= vd.template getProp<1>(key).template get<0>({1,1,0}) == 5.0*vd.getPos(key)[0];
+			ret &= vd.template getProp<1>(key).template get<0>({1,1,1}) == 5.0*vd.getPos(key)[1];
+			ret &= vd.template getProp<1>(key).template get<0>({1,1,2}) == 5.0*vd.getPos(key)[2];
+
+			ret &= vd.template getProp<1>(key).template get<0>({1,2,0}) == 6.0*vd.getPos(key)[0];
+			ret &= vd.template getProp<1>(key).template get<0>({1,2,1}) == 6.0*vd.getPos(key)[1];
+			ret &= vd.template getProp<1>(key).template get<0>({1,2,2}) == 6.0*vd.getPos(key)[2];
+
+			ret &= vd.template getProp<1>(key).template get<0>({2,0,0}) == 7.0*vd.getPos(key)[0];
+			ret &= vd.template getProp<1>(key).template get<0>({2,0,1}) == 7.0*vd.getPos(key)[1];
+			ret &= vd.template getProp<1>(key).template get<0>({2,0,2}) == 7.0*vd.getPos(key)[2];
+
+			ret &= vd.template getProp<1>(key).template get<0>({2,1,0}) == 8.0*vd.getPos(key)[0];
+			ret &= vd.template getProp<1>(key).template get<0>({2,1,1}) == 8.0*vd.getPos(key)[1];
+			ret &= vd.template getProp<1>(key).template get<0>({2,1,2}) == 8.0*vd.getPos(key)[2];
+
+			ret &= vd.template getProp<1>(key).template get<0>({2,2,0}) == 9.0*vd.getPos(key)[0];
+			ret &= vd.template getProp<1>(key).template get<0>({2,2,1}) == 9.0*vd.getPos(key)[1];
+			ret &= vd.template getProp<1>(key).template get<0>({2,2,2}) == 9.0*vd.getPos(key)[2];
+
+			++it3;
+		}
+
+		BOOST_REQUIRE_EQUAL(ret,true);
+	}
+}
+
+
+#endif /* SRC_VECTOR_VECTOR_DIST_COMPLEX_PRP_UNIT_TEST_HPP_ */
-- 
GitLab