From 3b1592dcb6528e87bdc9cddf0e043a72288f1969 Mon Sep 17 00:00:00 2001
From: Pietro Incardona <incardon@mpi-cbg.de>
Date: Tue, 13 Jun 2017 14:11:36 +0200
Subject: [PATCH] Latest version of Vortex in Cell

---
 example/Grid/3_gray_scott/main.cpp            |   4 +-
 example/Numerics/Vortex_in_cell/main_vic.cpp  |  11 +-
 .../Vortex_in_cell/main_vic_petsc.cpp         | 624 ++++++++++++++----
 .../Vortex_in_cell/main_vic_petsc2.cpp        |  11 +-
 .../Vortex_in_cell/main_vic_petsc3.cpp        |  11 +-
 openfpm_pdata.doc                             |   4 +-
 6 files changed, 516 insertions(+), 149 deletions(-)

diff --git a/example/Grid/3_gray_scott/main.cpp b/example/Grid/3_gray_scott/main.cpp
index 3bb0eff83..180d9c95c 100644
--- a/example/Grid/3_gray_scott/main.cpp
+++ b/example/Grid/3_gray_scott/main.cpp
@@ -10,10 +10,10 @@
  * This example show the usage of periodic grid with ghost part given in grid units to solve
  * the following system of equations
  *
- * \f$\frac{\partial u}{\partial t} = D_u \nabla u - uv^2 + F(1-u)\f$
+ * \f$\frac{\partial u}{\partial t} = D_u \nabla^{2} u - uv^2 + F(1-u)\f$
  *
  *
- * \f$\frac{\partial v}{\partial t} = D_v \nabla v + uv^2 - (F + k)v\f$
+ * \f$\frac{\partial v}{\partial t} = D_v \nabla^{2} v + uv^2 - (F + k)v\f$
  * 
  * ## Constants and functions ##
  *
diff --git a/example/Numerics/Vortex_in_cell/main_vic.cpp b/example/Numerics/Vortex_in_cell/main_vic.cpp
index 12cd85550..55710c450 100644
--- a/example/Numerics/Vortex_in_cell/main_vic.cpp
+++ b/example/Numerics/Vortex_in_cell/main_vic.cpp
@@ -1,13 +1,4 @@
-/*!
- * \page Vortex_in_cell_petsc Vortex in Cell 3D
- *
- * # Vortex in Cell 3D ring with ring-lets # {#vic_ringlets}
- *
- * In this example we solve the Navier-Stokes in the vortex formulation in 3D
- * for an incompressible fluid
- *
- *
- */
+
 
 #define SE_CLASS1
 //#define PRINT_STACKTRACE
diff --git a/example/Numerics/Vortex_in_cell/main_vic_petsc.cpp b/example/Numerics/Vortex_in_cell/main_vic_petsc.cpp
index e9e6b9658..8cbb7b4b6 100644
--- a/example/Numerics/Vortex_in_cell/main_vic_petsc.cpp
+++ b/example/Numerics/Vortex_in_cell/main_vic_petsc.cpp
@@ -1,10 +1,89 @@
-/*!
- * \page Vortex_in_cell_petsc Vortex in Cell 3D
+/*! \page Vortex_in_cell_petsc Vortex in Cell 3D
  *
- * # Vortex in Cell 3D ring with ring-lets # {#vic_ringlets}
+ * # Vortex in Cell 3D ring with ringlets # {#vic_ringlets}
+ *
+ * In this example we solve the Navier-Stokes equation in the vortex formulation in 3D
+ * for an incompressible fluid.
+ *
+ * ## Numerical method ## {#num_vic_mt}
+ *
+ * In this code we solve the Navier-stokes equation for incompressible fluid in the
+ * vorticity formulation. We first recall the Navier-stokes equation in vorticity formulation
+ *
+ * \f$ \nabla \times u = -w \f$
+ *
+ * \f$  \frac{Dw}{dt} = (w \cdot \vec \nabla) u + \nu \nabla^{2} w \f$ (5)
+ *
+ * Where \f$w\f$ is the vorticity and \f$u\f$ is the velocity of the fluid.
+ * With high Reynold number \f$Re = \frac{uL}{\nu}\f$ and the term \f$uL\f$ significantly
+ * smaller than the reynold number we have that \f$\nu\f$ is small and the term \f$\nu \nabla^{2} w\f$ is
+ * negligible. The algorithm can be expressed with the following pseudo code.
+ *
+ * \verbatim
+
+	1) Initialize the vortex ring on grid
+	2) Do an helmotz hodge projection to make the vorticity divergent free
+	3) Initialize particles on the same position as the grid or remesh
+
+	while (t < t_end) do
+		4) Interpolate mesh vorticity on particles
+		5) calculate velocity u from the vorticity w
+		6) interpolate velocity u to particles
+		7) calculate the right-hand-side on grid and interpolate on particles
+		8) move particles accordingly to the velocity
+		9) interpolate vorticity w back to grid
+	end while
+
+   \endverbatim
+ *
+ * This pseudo code show how to solve the equation above using euler integration
+ * In case of Runge-kutta of order two the pseudo code change into
+ *
+ *
+ * \verbatim
+
+	1) Initialize the vortex ring on grid
+	2) Do an helmotz hodge projection to make the vorticity divergent free
+	3) Initialize particles on the same position as the grid or remesh
+
+	while (t < t_end) do
+		4) Interpolate mesh vorticity on particles
+		5) calculate velocity u from the vorticity w
+		6) interpolate velocity u to particles
+		7) calculate the right-hand-side on grid and interpolate on particles
+		8) move particles accordingly to the velocity and save the old position in x_old
+		9) interpolate vorticity w back to grid
+
+		10) Interpolate mesh vorticity on particles
+		11) calculate velocity u from the vorticity w
+		12) interpolate velocity u to particles
+		13) calculate the right-hand-side on grid and interpolate on particles
+		14) move particles accordingly to the velocity starting from x_old
+	end while
+
+   \endverbatim
+ *
+ * In the following we explain how each step is implemented in the code
+ *
+ * ## Inclusion ## {#num_vic_inc}
+ *
+ * This example code need several components. First because is a particle
+ * mesh example we have to activate "grid_dist_id.hpp" and "vector_dist_id.hpp".
+ * Because we use a finite-difference scheme and linear-algebra to calculate the
+ * velocity out of the vorticity, we have to include "FDScheme.hpp" to produce
+ * out of the finite difference scheme a matrix that represent the linear-system
+ * to solve. "SparseMatrix.hpp" is the Sparse-Matrix that contain the linear
+ * system. "Vector.hpp" is the data-structure that contain the solution of the
+ * linear system. "petsc_solver.hpp" is the library to invert the linear system.
+ * Because we have to interpolate between particles and grid we the to include
+ * "interpolate.hpp" as interpolation kernel we use the mp4, so we include the
+ * "mp4_kernel.hpp"
+ *
+ * For convenience we also define the particles type and the grid type and some
+ * convenient constants
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp inclusion
  *
- * In this example we solve the Navier-Stokes in the vortex formulation in 3D
- * for an incompressible fluid
  *
  *
  */
@@ -12,20 +91,14 @@
 //#define SE_CLASS1
 //#define PRINT_STACKTRACE
 
-//! \cond [def system] \endcond
+//! \cond [inclusion] \endcond
 
 #include "Grid/grid_dist_id.hpp"
 #include "Vector/vector_dist.hpp"
 #include "Matrix/SparseMatrix.hpp"
 #include "Vector/Vector.hpp"
-
-
 #include "FiniteDifference/FDScheme.hpp"
-#include "FiniteDifference/util/common.hpp"
-#include "FiniteDifference/eq.hpp"
-#include "Solvers/petsc_solver.hpp"
 #include "Solvers/petsc_solver.hpp"
-#include "Solvers/umfpack_solver.hpp"
 #include "interpolation/mp4_kernel.hpp"
 #include "interpolation/interpolation.hpp"
 
@@ -42,16 +115,16 @@ typedef vector_dist<3,float,aggregate<float[3],float[3],float[3],float[3],float[
 float ringr1 = 5.0/4.0;
 // radius of the core of the torus
 float ringr2 = 0.5;
-// Reinold number
+// Reynold number
 float tgtre  = 10000.0;
 // Noise factor for the ring vorticity on z
 float ringnz = 0.00009;
 
 // Kinematic viscosity
 float nu = 0.0001535;
-float sc = 2.0;
 
-float dt = 0.012;
+// Time step
+float dt = 0.006;
 
 
 constexpr unsigned int vorticity = 0;
@@ -61,13 +134,42 @@ constexpr int rhs_part = 2;
 constexpr unsigned int old_vort = 3;
 constexpr unsigned int old_pos = 4;
 
-//! \cond [bond def eq] \endcond
+//! \cond [inclusion] \endcond
 
-#include "Vector/vector_dist.hpp"
-#include "data_type/aggregate.hpp"
+/*! \page Vortex_in_cell_petsc Vortex in Cell 3D
+ *
+ * # Step 1: Initialization of the vortex ring # {#vic_ring_init}
+ *
+ * In this function we initialize the vortex ring. The vortex ring is
+ * initialized accordingly to these formula.
+ *
+ * \f$ w(t = 0) =  \frac{\Gamma}{\pi \sigma^{2}} e^{-(s/ \sigma)^2} \f$
+ *
+ * \f$ s^2 = (z-z_c)^{2} + ((x-x_c)^2 + (y-y_c)^2 - R^2) \f$
+ *
+ * \f$ \Gamma = \nu Re \f$
+ *
+ * With this initialization the vortex ring look like the one in figure
+ *
+ * \image html int_vortex_arrow_small.jpg "Vortex ring initialization the arrow indicate the direction where the vortex point while the colors indicate the magnitude from blue (low) to red (high)"
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp init_vort
+ *
+ *
+ *
+ */
 
+//! \cond [init_vort] \endcond
+
+/*
+ * gr is the grid where we are initializing the vortex ring
+ * domain is the simulation domain
+ *
+ */
 void init_ring(grid_type & gr, const Box<3,float> & domain)
 {
+	// To add some noise to the vortex ring we create two random
+	// vector
 	constexpr int nk = 32;
 
 	float ak[nk];
@@ -79,10 +181,12 @@ void init_ring(grid_type & gr, const Box<3,float> & domain)
 	     bk[i] = 0.0/*rand()/RAND_MAX*/;
 	}
 
+	// We calculate the circuitation gamma
 	float gamma = nu * tgtre;
 	float rinv2 = 1.0f/(ringr2*ringr2);
 	float max_vorticity = gamma*rinv2/M_PI;
 
+	// We go through the grid to initialize the vortex
 	auto it = gr.getDomainIterator();
 
 	while (it.isNext())
@@ -121,11 +225,16 @@ void init_ring(grid_type & gr, const Box<3,float> & domain)
 	}
 }
 
+//! \cond [init_vort] \endcond
+
+//! \cond [poisson_syseq] \endcond
+
 // Specification of the poisson equation for the helmotz-hodge projection
 // 3D (dims = 3). The field is a scalar value (nvar = 1), bournary are periodic
-// type of the the space is float. Final grid that will store \phi (grid_dist_id<.....>)
-// The other indicate to construct a Parallel Matrix and a parallel vector on PETSC
-// NORMAL_GRID indicate that is a standard grid (non-staggered)
+// type of the the space is float. Final grid that will store \phi, the result (grid_dist_id<.....>)
+// The other indicate which kind of Matrix to use to construct the linear system and
+// which kind of vector to construct for the right hand side. Here we use a PETSC Sparse Matrix
+// and PETSC vector. NORMAL_GRID indicate that is a standard grid (non-staggered)
 struct poisson_nn_helm
 {
         static const unsigned int dims = 3;
@@ -140,66 +249,202 @@ struct poisson_nn_helm
 
 const bool poisson_nn_helm::boundary[] = {PERIODIC,PERIODIC,PERIODIC};
 
+//! \cond [poisson_syseq] \endcond
 
+
+/*! \page Vortex_in_cell_petsc Vortex in Cell 3D
+ *
+ * # Step 2: Helmotz-hodge projection # {#vic_hlm_proj}
+ *
+ * The Helnotz hodge projection is required in order to make the vorticity divergent
+ * free. The Helmotz-holde projection work in this way. A field can be divided into
+ * a curl-free part and a divergent-free part.
+ *
+ * \f$ w = w_{rot} + w_{div} \f$
+ *
+ * with
+ *
+ * \f$ \vec \nabla \times w_{rot} = 0 \f$
+ *
+ * \f$  \nabla \cdot w_{div} = 0 \f$
+ *
+ * To have a vorticity divergent free we have to get the component (3) \f$w_{div} = w - w_{rot}\f$.
+ * In particular it hold
+ *
+ * \f$ \nabla \cdot w = \nabla \cdot w_{rot} \f$
+ *
+ * Bacause \f$ \vec \nabla \times w_{rot} = 0 \f$ we can introduce a field \f$ \psi \f$
+ * such that
+ *
+ * (2) \f$ w_{rot} = \vec \nabla \psi \f$
+ *
+ * Doing the  \f$  \nabla \cdot \vec \nabla \psi \f$ we obtain
+ *
+ * \f$ \nabla \cdot \vec \nabla \psi = \nabla^{2} \psi = \nabla \cdot w_{rot} = \nabla \cdot w \f$
+ *
+ * so we lead to this equation
+ *
+ * (1) \f$ \nabla^{2} \psi = \nabla \cdot w  \f$
+ *
+ * Solving the equation for \f$ \psi \f$ we can obtain \f$ w_{rot} \f$ doing the gradient of \f$ \psi \f$
+ * and finally correct \f$ w \f$ obtaining \f$ w_{div} \f$
+ *
+ * The **helmotz_hodge_projection** function do this correction to the vorticity
+ *
+ * In particular it solve the equation (1) it calculate \f$ w_{rot} \f$
+ * using (2) and correct the vorticity using using (3)
+ *
+ *
+ * ## Poisson equation ##
+ *
+ * To solve a poisson equation on a grid using finite-difference, we need to create
+ * an object that carry information about the system of equations
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp poisson_syseq
+ *
+ * Once created this object we can define the equation we are trying to solve
+ * the left-hand-side of the equation \f$ \nabla^{2} \psi \f$
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp poisson_obj_eq
+ *
+ * Before to construct the linear system we also calculate the divergence of the
+ * vorticity \f$ \nabla \cdot w \f$ that will be the right-hand-side
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp calc_div_vort
+ *
+ * For statistic purpose we also calculate the integral of the vorticity and
+ * the maximum divergence of the vorticity
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp sanity_div_integral
+ *
+ * Finally we can create the object FDScheme using the object **poisson_nn_helm**
+ * as template variable. In addition to the constructor we have to specify the maximum extension of the stencil, the domain and the
+ * grid that will store the result. At this point we can impose an equation to construct
+ * our SparseMatrix. In this example we are imposing the poisson equation with right hand
+ * side equal to the divergence of vorticity (note: to avoid to create another field we use
+ *  \f$ \psi \f$ to preliminary store the divergence of the vorticity). Imposing the
+ *  equations produce an invertible SparseMatrix **A** and a right-hand-side Vector **b**.
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp create_fdscheme
+ *
+ * Because we need \f$ x = A^{-1}b \f$. We have to invert and solve a linear system.
+ * In this case we use the Conjugate-gradient-Method an iterative solver. Such method
+ * is controlled by two parameters. One is the tollerance that determine when the
+ * method is converged, the second one is the maximum number of iterations to avoid that
+ * the method go into infinite loop. After we set the parameters of the solver we can the
+ * the solution **x**. Finaly we copy back the solution **x** into the grid \f$ \psi \f$.
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp div_free_check
+ *
+ * ### Note ###
+ *
+ * Because we are solving the poisson equation in periodic boundary conditions the Matrix has
+ * determinat equal to zero. This mean that \f$ \psi \f$ has no unique solution (if it has one).
+ * In order to recover one we have to ensure that the integral of the righ hand side or vorticity
+ * is zero. (In our case is the case). We have to ensure that across time the integral of the
+ * vorticity is conserved. (In our case is the case if we consider the \f$ \nu = 0 \f$ and \f$
+ * \nabla \cdot w = 0 \f$ we can rewrite (5) in a conservative way \f$  \frac{Dw}{dt} = div(w \otimes v) \f$ ).
+ * Is also good to notice that the solution that you get is the one with \f$ \int v  = 0 \f$
+ *
+ *
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp solve_petsc
+ *
+ * ## Correction ## {#vort_correction}
+ *
+ * After we got our solution for \f$ \psi \f$ we can calculate the correction of the vorticity
+ * doing the gradient of \f$ \psi \f$.
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp vort_correction
+ *
+ * We also do a sanity check and we control that the vorticity remain
+ * divergent-free. Getting the maximum value of the divergence and printing out
+ * its value
+ *
+ *
+ */
+
+/*
+ * gr vorticity grid where we apply the correction
+ * domain simulation domain
+ *
+ */
 void helmotz_hodge_projection(grid_type & gr, const Box<3,float> & domain)
 {
 	///////////////////////////////////////////////////////////////
 
-	// Convenient constants
+	 //! \cond [poisson_obj_eq] \endcond
+
+	// Convenient constant
 	constexpr unsigned int phi = 0;
 
-	// Constructing the poisson equation
+	// We define a field phi_f
 	typedef Field<phi,poisson_nn_helm> phi_f;
 
-	// Poisson equation
+	// We assemble the poisson equation doing the
+	// poisson of the Laplacian of phi using Laplacian
+	// central scheme (where the both derivative use central scheme, not
+	// forward composed backward like usually)
 	typedef Lap<phi_f,poisson_nn_helm,CENTRAL_SYM> poisson;
 
-	poisson ps;
+	//! \cond [poisson_obj_eq] \endcond
+
+	//! \cond [calc_div_vort] \endcond
 
 	// ghost get
 	gr.template ghost_get<vorticity>();
 
+	// ghost size of the psi function
     Ghost<3,long int> g(2);
 
 	// Here we create a distributed grid to store the result of the helmotz projection
-	grid_dist_id<3,float,aggregate<float>> gr_hl(gr.getDecomposition(),gr.getGridInfo().getSize(),g);
+	grid_dist_id<3,float,aggregate<float>> psi(gr.getDecomposition(),gr.getGridInfo().getSize(),g);
 
 	// Calculate the divergence of the vortex field
-
 	auto it = gr.getDomainIterator();	
 
 	while (it.isNext())
 	{
 		auto key = it.get();
 
-        gr_hl.template get<phi>(key) = 1.0f/gr.spacing(x)/2.0f*(gr.template get<vorticity>(key.move(x,1))[x] - gr.template get<vorticity>(key.move(x,-1))[x] ) +
+        psi.template get<phi>(key) = 1.0f/gr.spacing(x)/2.0f*(gr.template get<vorticity>(key.move(x,1))[x] - gr.template get<vorticity>(key.move(x,-1))[x] ) +
 			         	 	 1.0f/gr.spacing(y)/2.0f*(gr.template get<vorticity>(key.move(y,1))[y] - gr.template get<vorticity>(key.move(y,-1))[y] ) +
 							 1.0f/gr.spacing(z)/2.0f*(gr.template get<vorticity>(key.move(z,1))[z] - gr.template get<vorticity>(key.move(z,-1))[z] );
 
 		++it;
 	}
 
-	//  Check the integral of vorticity
+	//! \cond [calc_div_vort] \endcond
+
+	//! \cond [sanity_div_integral] \endcond
 
+	// Get iterator across the domain points
 	auto it5 = gr.getDomainIterator();
 
+	// maximum vorticity
 	double max_vort = 0.0;
+
+	// Total integral
 	double int_vort[3] = {0.0,0.0,0.0};
 
+	// For each grid point
 	while (it5.isNext())
 	{
 		auto key = it5.get();
 
 		double tmp;
 
+		// Calculate the vorticity
         tmp = 1.0f/gr.spacing(x)/2.0f*(gr.template get<vorticity>(key.move(x,1))[x] - gr.template get<vorticity>(key.move(x,-1))[x] ) +
 			         	 	 1.0f/gr.spacing(y)/2.0f*(gr.template get<vorticity>(key.move(y,1))[y] - gr.template get<vorticity>(key.move(y,-1))[y] ) +
 							 1.0f/gr.spacing(z)/2.0f*(gr.template get<vorticity>(key.move(z,1))[z] - gr.template get<vorticity>(key.move(z,-1))[z] );
 
+        // Calculate the integral of the vorticity on each direction
         int_vort[x] += gr.template get<vorticity>(key)[x];
         int_vort[y] += gr.template get<vorticity>(key)[y];
         int_vort[z] += gr.template get<vorticity>(key)[z];
 
+        // Store the maximum vorticity
         if (tmp > max_vort)
         	max_vort = tmp;
 
@@ -208,36 +453,50 @@ void helmotz_hodge_projection(grid_type & gr, const Box<3,float> & domain)
 
 	std::cout << "Max div for vorticity " << max_vort << "   Integral: " << int_vort[0] << "  " << int_vort[1] << "   " << int_vort[2] << std::endl;
 
-	///////////////////////////////////////
+	//! \cond [sanity_div_integral] \endcond
 
-	Padding<3>pd({0,0,0},{0,0,0});
+	//! \cond [create_fdscheme] \endcond
+
+	// In order to create a matrix that represent the poisson equation we have to indicate
+	// we have to indicate the maximum extension of the stencil and we we need an extra layer
+	// of points in case we have to impose particular boundary conditions.
 	Ghost<3,long int> stencil_max(2);
 
-	// Finite difference scheme
-	FDScheme<poisson_nn_helm> fd(pd, stencil_max, domain, gr_hl.getGridInfo(), gr_hl);
+	// Here we define our Finite difference disctetization scheme object
+	FDScheme<poisson_nn_helm> fd(stencil_max, domain, psi);
+
+	// impose the poisson equation, using right hand side psi on the full domain (psi.getDomainIterator)
+	// the template paramereter instead define which property of phi carry the righ-hand-side
+	// in this case phi has only one property, so the property 0 carry the right hand side
+	fd.template impose_dit<0>(poisson(),psi,psi.getDomainIterator());
 
+	//! \cond [create_fdscheme] \endcond
 
-	fd.template impose_dit<phi>(ps,gr_hl,0,gr_hl.getDomainIterator());
+	//! \cond [solve_petsc] \endcond
 
-	// Create an PETSC solver
+	// Create a PETSC solver to get the solution x
 	petsc_solver<double> solver;
 
+	// Set the conjugate-gradient as method to solve the linear solver
 	solver.setSolver(KSPCG);
+
+	// Set the absolute tolerance to determine that the method is converged
 	solver.setAbsTol(0.001);
-	solver.setRestart(250);
+
+	// Set the maximum number of iterations
 	solver.setMaxIter(500);
 
 	// Give to the solver A and b, return x, the solution
-	auto phi_s = solver.solve(fd.getA(),fd.getB());
+	auto x_ = solver.solve(fd.getA(),fd.getB());
+
+	// copy the solution x to the grid psi
+	fd.template copy<phi>(x_,psi);
 
-	long int szs[3] = {(long int)gr.getGridInfo().size(0),
-			           (long int)gr.getGridInfo().size(1),
-					   (long int)gr.getGridInfo().size(2)};
+	//! \cond [solve_petsc] \endcond
 
-	// copy the solution to grid
-	fd.template copy<phi>(phi_s,{0,0,0},szs,gr_hl);
+	//! \cond [vort_correction] \endcond
 
-	gr_hl.template ghost_get<phi>();
+	psi.template ghost_get<phi>();
 
 	// Correct the vorticity to make it divergence free
 
@@ -247,13 +506,16 @@ void helmotz_hodge_projection(grid_type & gr, const Box<3,float> & domain)
 	{
 		auto key = it2.get();
 
-		gr.template get<vorticity>(key)[x] -= 1.0f/2.0f/gr.spacing(x)*(gr_hl.template get<phi>(key.move(x,1))-gr_hl.template get<phi>(key.move(x,-1)));
-		gr.template get<vorticity>(key)[y] -= 1.0f/2.0f/gr.spacing(y)*(gr_hl.template get<phi>(key.move(y,1))-gr_hl.template get<phi>(key.move(y,-1)));
-		gr.template get<vorticity>(key)[z] -= 1.0f/2.0f/gr.spacing(z)*(gr_hl.template get<phi>(key.move(z,1))-gr_hl.template get<phi>(key.move(z,-1)));
+		gr.template get<vorticity>(key)[x] -= 1.0f/2.0f/psi.spacing(x)*(psi.template get<phi>(key.move(x,1))-psi.template get<phi>(key.move(x,-1)));
+		gr.template get<vorticity>(key)[y] -= 1.0f/2.0f/psi.spacing(y)*(psi.template get<phi>(key.move(y,1))-psi.template get<phi>(key.move(y,-1)));
+		gr.template get<vorticity>(key)[z] -= 1.0f/2.0f/psi.spacing(z)*(psi.template get<phi>(key.move(z,1))-psi.template get<phi>(key.move(z,-1)));
 
 		++it2;
 	}
 
+	//! \cond [vort_correction] \endcond
+
+	//! \cond [div_free_check] \endcond
 
 	// Here we check the maximum divergence of the ring
 	// We also copy the solution to the original grid
@@ -266,56 +528,164 @@ void helmotz_hodge_projection(grid_type & gr, const Box<3,float> & domain)
 	{
 		auto key = it3.get();
 
-        gr_hl.template get<phi>(key) = 1.0f/gr.spacing(x)/2.0f*(gr.template get<vorticity>(key.move(x,1))[x] - gr.template get<vorticity>(key.move(x,-1))[x] ) +
+        psi.template get<phi>(key) = 1.0f/gr.spacing(x)/2.0f*(gr.template get<vorticity>(key.move(x,1))[x] - gr.template get<vorticity>(key.move(x,-1))[x] ) +
 			         	 	 1.0f/gr.spacing(y)/2.0f*(gr.template get<vorticity>(key.move(y,1))[y] - gr.template get<vorticity>(key.move(y,-1))[y] ) +
 							 1.0f/gr.spacing(z)/2.0f*(gr.template get<vorticity>(key.move(z,1))[z] - gr.template get<vorticity>(key.move(z,-1))[z] );
 
 
 
-        if (gr_hl.template get<phi>(key) > max)
-        	max = gr_hl.template get<phi>(key);
+        if (psi.template get<phi>(key) > max)
+        	max = psi.template get<phi>(key);
 
 		++it3;
 	}
 
 	std::cout << "Maximum divergence of the ring MAX " << max << std::endl;
 
+	//! \cond [div_free_check] \endcond
+
 }
 
-/*! \brief Here we calculate the the velocity from vortex on grid
+/*! \page Vortex_in_cell_petsc Vortex in Cell 3D
+ *
+ * # Step 3: Remeshing vorticity # {#vic_remesh_vort}
  *
+ * After that we initialized the vorticity on the grid, initialize the particles
+ * in a grid like position and we interpolate the vorticity on particles. Because
+ * of the particles position being in a grid-like position and the symmetry of the
+ * interpolation kernels, the re-mesh step simply reduce to initialize the particle
+ * in a grid like position and assign the property vorticity of the particles equal to the
+ * grid vorticity.
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp remesh_part
  *
  */
+
+//! \cond [remesh_part] \endcond
+
+void remesh(particles_type & vd, grid_type & gr,Box<3,float> & domain)
+{
+	// Remove all particles because we reinitialize in a grid like position
+	vd.clear();
+
+	// Get a grid iterator
+	auto git = vd.getGridIterator(gr.getGridInfo().getSize());
+
+	// For each grid point
+	while (git.isNext())
+	{
+		// Get the grid point in global coordinates (key). p is in local coordinates
+		auto p = git.get();
+		auto key = git.get_dist();
+
+		// Add the particle
+		vd.add();
+
+		// Assign the position to the particle in a grid like way
+		vd.getLastPos()[x] = gr.spacing(x)*p.get(x) + domain.getLow(x);
+		vd.getLastPos()[y] = gr.spacing(y)*p.get(y) + domain.getLow(y);
+		vd.getLastPos()[z] = gr.spacing(z)*p.get(z) + domain.getLow(z);
+
+		// Initialize the vorticity
+		vd.template getLastProp<vorticity>()[x] = gr.template get<vorticity>(key)[x];
+		vd.template getLastProp<vorticity>()[y] = gr.template get<vorticity>(key)[y];
+		vd.template getLastProp<vorticity>()[z] = gr.template get<vorticity>(key)[z];
+
+		// next grid point
+		++git;
+	}
+
+	// redistribute the particles
+	vd.map();
+}
+
+//! \cond [remesh_part] \endcond
+
+/*! \page Vortex_in_cell_petsc Vortex in Cell 3D
+ *
+ * # Step 5: Compute velocity from vorticity # {#vic_vel_from_vort}
+ *
+ * Computing the velocity from vorticity is done in the following way. Given
+ *
+ * \f$ \vec \nabla \times u = -w \f$
+ *
+ * We intrododuce the stream line function defined as
+ *
+ * \f$ \nabla \times \phi = u \f$ (7)
+ *
+ * \f$ \nabla \cdot \phi = 0 \f$
+ *
+ * We obtain
+ *
+ * \f$ \nabla \times \nabla \times \phi = -w = \vec \nabla (\nabla \cdot  \phi) - \nabla^{2} \phi  \f$
+ *
+ * Because the divergence of \f$ \phi \f$ is defined to be zero we have
+ *
+ * \f$ \nabla^{2} \phi = w \f$
+ *
+ * The velocity can be recovered by the equation (7)
+ *
+ * Putting into code what explained before, we again generate a poisson
+ * object
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp poisson_obj_eq
+ *
+ * For statistic reason we do a check of the total integral of the vorticity
+ * and maximum divergence of the vorticity
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp sanity_int_div
+ *
+ * In order to calculate the velocity out of the vorticity, we solve a poisson
+ * equation like we did in helmotz-projection equation, but we do it for each
+ * component \f$ i \f$ of the vorticity.
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp solve_poisson_comp
+ *
+ * We save the \f$ \phi \f$ component into **phi_s**
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp solve_poisson_comp
+ *
+ * Once we filled phi_s we can implement (7) doing the curl of **phi_s**
+ * and recovering the velocity v
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp curl_phi_v
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp solve_poisson_comp
+ *
+ * \snippet Numerics/Vortex_in_cell/main_vic_petsc.cpp cross_check_curl_u_vort
+ *
+ */
+
+//! \cond [comp_vel] \endcond
+
 void comp_vel(Box<3,float> & domain, grid_type & g_vort,grid_type & g_vel, petsc_solver<double>::return_type (& phi_s)[3])
 {
-	// Convenient constants
+	//! \cond [poisson_obj_eq] \endcond
+
+	// Convenient constant
 	constexpr unsigned int phi = 0;
 
-	// Constructing the poisson equation
+	// We define a field phi_f
 	typedef Field<phi,poisson_nn_helm> phi_f;
 
-	// Poisson equation
+	// We assemble the poisson equation doing the
+	// poisson of the Laplacian of phi using Laplacian
+	// central scheme (where the both derivative use central scheme, not
+	// forward composed backward like usually)
 	typedef Lap<phi_f,poisson_nn_helm,CENTRAL_SYM> poisson;
 
-	Padding<3>pd({0,0,0},{0,0,0});
-	Ghost<3,long int> stencil_max(2);
+	//! \cond [poisson_obj_eq] \endcond
 
 	Ghost<3,long int> g(2);
 
-	long int szs[3] = {(long int)g_vort.getGridInfo().size(0),
-			           (long int)g_vort.getGridInfo().size(1),
-					   (long int)g_vort.getGridInfo().size(2)};
-
-	float inv_dx = 0.5f / g_vort.spacing(0);
-	float inv_dy = 0.5f / g_vort.spacing(1);
-	float inv_dz = 0.5f / g_vort.spacing(2);
-
 	// Here we create a distributed grid to store the result of the helmotz projection
 	grid_dist_id<3,float,aggregate<float>> gr_ps(g_vort.getDecomposition(),g_vort.getGridInfo().getSize(),g);
-	grid_dist_id<3,float,aggregate<float[3]>> gr_ps_v(g_vort.getDecomposition(),g_vort.getGridInfo().getSize(),g);
+	grid_dist_id<3,float,aggregate<float[3]>> phi_v(g_vort.getDecomposition(),g_vort.getGridInfo().getSize(),g);
 
 	// Check one we control the the divergence of vorticity is zero
 
+	//! \cond [sanity_int_div] \endcond
+
 	g_vort.template ghost_get<vorticity>();
 	auto it5 = g_vort.getDomainIterator();
 
@@ -345,9 +715,13 @@ void comp_vel(Box<3,float> & domain, grid_type & g_vort,grid_type & g_vel, petsc
 
 	std::cout << "Max div for vorticity " << max_vort << "   Integral: " << int_vort[0] << "  " << int_vort[1] << "   " << int_vort[2] << std::endl;
 
+	//! \cond [sanity_int_div] \endcond
+
 	// For each component solve a poisson
 	for (size_t i = 0 ; i < 3 ; i++)
 	{
+		//! \cond [solve_poisson_comp] \endcond
+
 		// Copy the vorticity in gr_ps
 		auto it2 = gr_ps.getDomainIterator();
 
@@ -361,33 +735,36 @@ void comp_vel(Box<3,float> & domain, grid_type & g_vort,grid_type & g_vel, petsc
 			++it2;
 		}
 
+		Ghost<3,long int> stencil_max(2);
 
 		// Finite difference scheme
-		FDScheme<poisson_nn_helm> fd(pd, stencil_max, domain, gr_ps.getGridInfo(), gr_ps);
+		FDScheme<poisson_nn_helm> fd(stencil_max, domain, gr_ps);
 
 		poisson ps;
 
-		fd.template impose_dit<phi>(ps,gr_ps,0,gr_ps.getDomainIterator());
+		fd.template impose_dit<phi>(ps,gr_ps,gr_ps.getDomainIterator());
 
 		// Create an PETSC solver
 		petsc_solver<double> solver;
 
 		solver.setSolver(KSPCG);
 		solver.setAbsTol(0.001);
-		solver.setRestart(250);
 		solver.setMaxIter(500);
 
 		std::cout << "Solving component " << i << std::endl;
 
 		PetscBool flg;
 		SparseMatrix<double,int,PETSC_BASE> & A = fd.getA();
-//		MatIsSymmetric(A.getMat(),0.000001,&flg);
 
 		Vector<double,PETSC_BASE> & b = fd.getB();
 
 		// Give to the solver A and b, return x, the solution
 		solver.solve(A,phi_s[i],b);
 
+		//! \cond [solve_poisson_comp] \endcond
+
+		//! \cond [print_residual_copy] \endcond
+
 		// Calculate the residual
 
 		petsc_solver<double>::return_type r(gr_ps.size(),gr_ps.getLocalDomainSize());
@@ -402,7 +779,7 @@ void comp_vel(Box<3,float> & domain, grid_type & g_vort,grid_type & g_vel, petsc
 		std::cout << "Solved component " << i << "  Error: " << ne << "   Symmetric: " << flg << std::endl;
 
 		// copy the solution to grid
-		fd.template copy<phi>(phi_s[i],{0,0,0},szs,gr_ps);
+		fd.template copy<phi>(phi_s[i],gr_ps);
 
 		auto it3 = gr_ps.getDomainIterator();
 
@@ -411,27 +788,35 @@ void comp_vel(Box<3,float> & domain, grid_type & g_vort,grid_type & g_vel, petsc
 		{
 			auto key = it3.get();
 
-			gr_ps_v.get<velocity>(key)[i] = gr_ps.get<phi>(key);
+			phi_v.get<velocity>(key)[i] = gr_ps.get<phi>(key);
 
 			++it3;
 		}
+
+		//! \cond [print_residual_copy] \endcond
 	}
 
-	gr_ps_v.ghost_get<phi>();
+	//! \cond [curl_phi_v] \endcond
+
+	phi_v.ghost_get<phi>();
 
-	auto it3 = gr_ps_v.getDomainIterator();
+	float inv_dx = 0.5f / g_vort.spacing(0);
+	float inv_dy = 0.5f / g_vort.spacing(1);
+	float inv_dz = 0.5f / g_vort.spacing(2);
+
+	auto it3 = phi_v.getDomainIterator();
 
 	// calculate the velocity from the curl of phi
 	while (it3.isNext())
 	{
 		auto key = it3.get();
 
-		float phi_xy = (gr_ps_v.get<phi>(key.move(y,1))[x] - gr_ps_v.get<phi>(key.move(y,-1))[x])*inv_dy;
-		float phi_xz = (gr_ps_v.get<phi>(key.move(z,1))[x] - gr_ps_v.get<phi>(key.move(z,-1))[x])*inv_dz;
-		float phi_yx = (gr_ps_v.get<phi>(key.move(x,1))[y] - gr_ps_v.get<phi>(key.move(x,-1))[y])*inv_dx;
-		float phi_yz = (gr_ps_v.get<phi>(key.move(z,1))[y] - gr_ps_v.get<phi>(key.move(z,-1))[y])*inv_dz;
-		float phi_zx = (gr_ps_v.get<phi>(key.move(x,1))[z] - gr_ps_v.get<phi>(key.move(x,-1))[z])*inv_dx;
-		float phi_zy = (gr_ps_v.get<phi>(key.move(y,1))[z] - gr_ps_v.get<phi>(key.move(y,-1))[z])*inv_dy;
+		float phi_xy = (phi_v.get<phi>(key.move(y,1))[x] - phi_v.get<phi>(key.move(y,-1))[x])*inv_dy;
+		float phi_xz = (phi_v.get<phi>(key.move(z,1))[x] - phi_v.get<phi>(key.move(z,-1))[x])*inv_dz;
+		float phi_yx = (phi_v.get<phi>(key.move(x,1))[y] - phi_v.get<phi>(key.move(x,-1))[y])*inv_dx;
+		float phi_yz = (phi_v.get<phi>(key.move(z,1))[y] - phi_v.get<phi>(key.move(z,-1))[y])*inv_dz;
+		float phi_zx = (phi_v.get<phi>(key.move(x,1))[z] - phi_v.get<phi>(key.move(x,-1))[z])*inv_dx;
+		float phi_zy = (phi_v.get<phi>(key.move(y,1))[z] - phi_v.get<phi>(key.move(y,-1))[z])*inv_dy;
 
 		g_vel.template get<velocity>(key)[x] = phi_zy - phi_yz;
 		g_vel.template get<velocity>(key)[y] = phi_xz - phi_zx;
@@ -440,11 +825,15 @@ void comp_vel(Box<3,float> & domain, grid_type & g_vort,grid_type & g_vel, petsc
 		++it3;
 	}
 
+	//! \cond [curl_phi_v] \endcond
+
+	//! \cond [cross_check_curl_u_vort] \endcond
+
 	g_vel.template ghost_get<velocity>();
 
 	// We check that curl u = vorticity
 
-	auto it4 = gr_ps_v.getDomainIterator();
+	auto it4 = phi_v.getDomainIterator();
 
 	double norm_max = 0.0;
 
@@ -460,51 +849,29 @@ void comp_vel(Box<3,float> & domain, grid_type & g_vort,grid_type & g_vel, petsc
 		float phi_zx = (g_vel.template get<phi>(key.move(x,1))[z] - g_vel.template get<phi>(key.move(x,-1))[z])*inv_dx;
 		float phi_zy = (g_vel.template get<phi>(key.move(y,1))[z] - g_vel.template get<phi>(key.move(y,-1))[z])*inv_dy;
 
-		gr_ps_v.template get<velocity>(key)[x] = phi_zy - phi_yz  + g_vort.template get<vorticity>(key)[x];
-		gr_ps_v.template get<velocity>(key)[y] = phi_xz - phi_zx + g_vort.template get<vorticity>(key)[y];
-		gr_ps_v.template get<velocity>(key)[z] = phi_yx - phi_xy + g_vort.template get<vorticity>(key)[z];
+		phi_v.template get<velocity>(key)[x] = phi_zy - phi_yz  + g_vort.template get<vorticity>(key)[x];
+		phi_v.template get<velocity>(key)[y] = phi_xz - phi_zx + g_vort.template get<vorticity>(key)[y];
+		phi_v.template get<velocity>(key)[z] = phi_yx - phi_xy + g_vort.template get<vorticity>(key)[z];
 
-		if (gr_ps_v.template get<velocity>(key)[x] > norm_max)
-			norm_max = gr_ps_v.template get<velocity>(key)[x];
+		if (phi_v.template get<velocity>(key)[x] > norm_max)
+			norm_max = phi_v.template get<velocity>(key)[x];
 
-		if (gr_ps_v.template get<velocity>(key)[y] > norm_max)
-			norm_max = gr_ps_v.template get<velocity>(key)[y];
+		if (phi_v.template get<velocity>(key)[y] > norm_max)
+			norm_max = phi_v.template get<velocity>(key)[y];
 
-		if (gr_ps_v.template get<velocity>(key)[z] > norm_max)
-			norm_max = gr_ps_v.template get<velocity>(key)[z];
+		if (phi_v.template get<velocity>(key)[z] > norm_max)
+			norm_max = phi_v.template get<velocity>(key)[z];
 
 		++it4;
 	}
 
 	std::cout << "Norm max: " << norm_max << std::endl;
-}
 
-void remesh(particles_type & vd, grid_type & gr,Box<3,float> & domain)
-{
-	// Remove all particles
-	vd.clear();
-
-	auto git = vd.getGridIterator(gr.getGridInfo().getSize());
-
-	while (git.isNext())
-	{
-		auto p = git.get();
-		auto key = git.get_dist();
-
-		vd.add();
-
-		vd.getLastPos()[x] = gr.spacing(x)*p.get(x) + domain.getLow(x);
-		vd.getLastPos()[y] = gr.spacing(y)*p.get(y) + domain.getLow(y);
-		vd.getLastPos()[z] = gr.spacing(z)*p.get(z) + domain.getLow(z);
-
-		vd.template getLastProp<vorticity>()[x] = gr.template get<vorticity>(key)[x];
-		vd.template getLastProp<vorticity>()[y] = gr.template get<vorticity>(key)[y];
-		vd.template getLastProp<vorticity>()[z] = gr.template get<vorticity>(key)[z];
-
-		++git;
-	}
+	//! \cond [cross_check_curl_u_vort] \endcond
 }
 
+//! \cond [comp_vel] \endcond
+
 void remesh(particles_type & vd, grid_type & g_rhs, grid_type & g_vel,Box<3,float> & domain)
 {
 	constexpr int rhs_g = 0;
@@ -535,6 +902,8 @@ void remesh(particles_type & vd, grid_type & g_rhs, grid_type & g_vel,Box<3,floa
 
 		++git;
 	}
+
+	vd.map();
 }
 
 template<unsigned int prp> void set_zero(grid_type & gr)
@@ -705,6 +1074,7 @@ void rk_step2(particles_type & particles)
 	particles.map();
 }
 
+
 template<typename grid, typename vector> void do_step(vector & particles,
 		                                              grid & g_vort,
 													  grid & g_vel,
@@ -752,7 +1122,7 @@ int main(int argc, char* argv[])
 	Ghost<3,long int> g(2);
 
 	// Grid points on x=128 y=64 z=64
-	long int sz[] = {256,64,64};
+	long int sz[] = {512,128,128};
 	size_t szu[] = {(size_t)sz[0],(size_t)sz[1],(size_t)sz[2]};
 
 	periodicity<3> bc = {{PERIODIC,PERIODIC,PERIODIC}};
@@ -793,9 +1163,27 @@ int main(int argc, char* argv[])
 
 	g_vort.write("grid_vorticity_init", VTK_WRITER | FORMAT_BINARY);
 
+
+	// Before entering the loop we check if we have to restart a previous simulation
+
+	size_t i = 0;
+
+	if (argc > 1)
+	{
+		std::string restart(argv[1]);
+
+		i = std::stoi(restart);
+
+		particles.load("check_point_" + std::to_string(i));
+
+		particles.map();
+
+		std::cout << "Restarting from " << i << std::endl;
+	}
+
 	// Time Integration
 
-	for (size_t i = 0 ; i < 10001 ; i++)
+	for ( ; i < 10001 ; i++)
 	{
 		do_step(particles,g_vort,g_vel,g_dvort,domain,inte,phi_s);
 
@@ -817,8 +1205,14 @@ int main(int argc, char* argv[])
 		{
 			particles.write("part_out_" + std::to_string(i),VTK_WRITER | FORMAT_BINARY);
 
+			g_vort.ghost_get<vorticity>();
+			g_vel.ghost_get<velocity>();
 			g_vel.write("grid_velocity_" + std::to_string(i), VTK_WRITER | FORMAT_BINARY);
 			g_vort.write("grid_vorticity_" + std::to_string(i), VTK_WRITER | FORMAT_BINARY);
+
+			// Save also for checkpoint restart
+
+			particles.save("check_point_" + std::to_string(i+1));
 		}
 
 	}
diff --git a/example/Numerics/Vortex_in_cell/main_vic_petsc2.cpp b/example/Numerics/Vortex_in_cell/main_vic_petsc2.cpp
index afe8239d1..22d153abc 100644
--- a/example/Numerics/Vortex_in_cell/main_vic_petsc2.cpp
+++ b/example/Numerics/Vortex_in_cell/main_vic_petsc2.cpp
@@ -1,13 +1,4 @@
-/*!
- * \page Vortex_in_cell_petsc Vortex in Cell 3D
- *
- * # Vortex in Cell 3D ring with ring-lets # {#vic_ringlets}
- *
- * In this example we solve the Navier-Stokes in the vortex formulation in 3D
- * for an incompressible fluid
- *
- *
- */
+
 
 #define SE_CLASS1
 //#define PRINT_STACKTRACE
diff --git a/example/Numerics/Vortex_in_cell/main_vic_petsc3.cpp b/example/Numerics/Vortex_in_cell/main_vic_petsc3.cpp
index 6a020f598..56452eab9 100644
--- a/example/Numerics/Vortex_in_cell/main_vic_petsc3.cpp
+++ b/example/Numerics/Vortex_in_cell/main_vic_petsc3.cpp
@@ -1,13 +1,4 @@
-/*!
- * \page Vortex_in_cell_petsc Vortex in Cell 3D
- *
- * # Vortex in Cell 3D ring with ring-lets # {#vic_ringlets}
- *
- * In this example we solve the Navier-Stokes in the vortex formulation in 3D
- * for an incompressible fluid
- *
- *
- */
+
 
 #define SE_CLASS1
 //#define PRINT_STACKTRACE
diff --git a/openfpm_pdata.doc b/openfpm_pdata.doc
index 335cc0cb0..d0e33a102 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.8.0
+PROJECT_NUMBER         = 0.9.0
 
 # 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
@@ -831,7 +831,7 @@ EXAMPLE_RECURSIVE      = YES
 # that contain images that are to be included in the documentation (see the
 # \image command).
 
-IMAGE_PATH             =
+IMAGE_PATH             = example/Numerics/Vortex_in_cell/
 
 # The INPUT_FILTER tag can be used to specify a program that doxygen should
 # invoke to filter for each input file. Doxygen will invoke the filter program
-- 
GitLab