From 20b2b64d19b44b01815e7755a8f29578837086f8 Mon Sep 17 00:00:00 2001 From: Pietro Incardona <i-bird@localhost.localdomain> Date: Wed, 20 Jul 2016 18:59:54 +0200 Subject: [PATCH] Small changes + example refactor --- example/Numerics/PSE/1_Diffusion_1D/Makefile | 2 +- example/Numerics/PSE/1_Diffusion_1D/main.cpp | 487 +++++++++++------- example/Vector/2_molecular_dynamic/Makefile | 21 - example/Vector/2_molecular_dynamic/config.cfg | 2 - example/Vector/2_molecular_dynamic/main.cpp | 379 -------------- openfpm_numerics | 2 +- src/Grid/grid_dist_id.hpp | 4 +- src/Vector/vector_dist.hpp | 17 + 8 files changed, 334 insertions(+), 580 deletions(-) delete mode 100644 example/Vector/2_molecular_dynamic/Makefile delete mode 100644 example/Vector/2_molecular_dynamic/config.cfg delete mode 100644 example/Vector/2_molecular_dynamic/main.cpp diff --git a/example/Numerics/PSE/1_Diffusion_1D/Makefile b/example/Numerics/PSE/1_Diffusion_1D/Makefile index a4360521..4cf11983 100644 --- a/example/Numerics/PSE/1_Diffusion_1D/Makefile +++ b/example/Numerics/PSE/1_Diffusion_1D/Makefile @@ -7,7 +7,7 @@ LDIR = OBJ = main.o %.o: %.cpp - $(CC) -O0 -c --std=c++11 -o $@ $< $(INCLUDE_PATH) + $(CC) -O3 -c --std=c++11 -o $@ $< $(INCLUDE_PATH) diff_1d: $(OBJ) $(CC) -o $@ $^ $(CFLAGS) $(LIBS_PATH) $(LIBS) diff --git a/example/Numerics/PSE/1_Diffusion_1D/main.cpp b/example/Numerics/PSE/1_Diffusion_1D/main.cpp index 0fb0d3db..93299113 100644 --- a/example/Numerics/PSE/1_Diffusion_1D/main.cpp +++ b/example/Numerics/PSE/1_Diffusion_1D/main.cpp @@ -3,7 +3,11 @@ * * ## Simple example * - * In this example we show 1D PSE derivative function approximation + * In this example we show The 1D PSE Diffusion equation + * + * in particular we integrate the following equation + * + * \$ \frac{u}{t} = D \laplacian u \$ * * ### WIKI END ### * @@ -21,7 +25,7 @@ /* * ### WIKI 2 ### * - * Here we define the function x*e^(-x*x) and its + * Here we define the function x*e^(-x*x) the initial condition * */ @@ -35,6 +39,7 @@ double f_xex2(Point<1,double> & x) return x.get(0)*exp(-x.get(0)*x.get(0)); } + /* * * ### WIKI 3 ### @@ -52,15 +57,15 @@ double f_xex2(Point<1,double> & x) * \param cl CellList * */ -template<typename CellL> double calcLap(Point<1,double> p, vect_dist_key_dx key, vector_dist<1,double, aggregate<double>, CartDecomposition<1,double> > & vd, double eps, double spacing, CellL & cl) +template<typename CellL> double calcLap(Point<1,double> p, vect_dist_key_dx key, vector_dist<1,double, aggregate<double,double> > & vd, double eps, double spacing, CellL & cl) { - // Laplacian PSE kernel 1 dimension, on double, second order + // Laplacian PSE kernel<1,double,2> = 1 dimension, on double, second order Lap_PSE<1,double,2> lker(eps); // double PSE integration accumulator double pse = 0; - // Get f(x) at the position of the particle + // f(x_p) double prp_x = vd.template getProp<0>(key); // Get the neighborhood of the particles @@ -69,17 +74,16 @@ template<typename CellL> double calcLap(Point<1,double> p, vect_dist_key_dx key, { auto nnp = NN.get(); - // Calculate contribution given by the kernel value at position p, - // given by the Near particle + // Calculate contribution given by the particle q near to p if (nnp != key.getKey()) { - // W(x-y) + // W(x_p-x_q) x = position of p, y = position of q double ker = lker.value(p,vd.getPos(nnp)); - // f(y) + // f(x_q) double prp_y = vd.template getProp<0>(nnp); - // 1.0/(eps)^2 [f(y)-f(x)]*W(x,y)*V_q + // 1.0/(eps)^2 [f(x_q)-f(x_p)]*W(x_p-x_q)*V_q double prp = 1.0/eps/eps * (prp_y - prp_x) * spacing; pse += prp * ker; } @@ -88,9 +92,72 @@ template<typename CellL> double calcLap(Point<1,double> p, vect_dist_key_dx key, ++NN; } + // return the calculated laplacian return pse; } +/* + * + * ### WIKI 4 ### + * + * It mirror the particles at the border of the domain, in particular on the left we do the operation + * show in figure + * + * \verbatim + * + * -0.6 -0.5 0.5 0.6 Strength + +----+----*----*----*- + 0.0 Position + + with * = real particle + + = mirror particle + + \endverbatim + * + * We create particle on the negative part of the domain and we assign a strength opposite to the particle in the + * positive part + * + * On the right instead we prolong the initial condition (Ideally should remain almost fixed) + * + * \param vd vector of particles + * \param key particle + * \param m_pad border box(interval) on the left + * \param m_pad2 border box(interval) on the right + * \param box domain + * + */ +inline void mirror(vector_dist<1,double, aggregate<double,double> > & vd, vect_dist_key_dx & key, const Box<1,double> & m_pad, Box<1,double> & m_pad2, const Box<1,double> & box) +{ + // If the particle is inside the box (interval), it mean that is at the left border + if (m_pad.isInsideNB(vd.getPos(key)) == true) + { + // Add a new particle + vd.add(); + + //Set the added particle position, symmetrically positioned on the negative part of the domain + vd.getLastPos()[0] = - vd.getPos(key)[0]; + + // Set the property of the particle to be negative + vd.template getLastProp<0>() = - vd.template getProp<0>(key); + } + + // If the particle is inside the box (interval), it mean that is at the right border + if (m_pad2.isInsideNB(vd.getPos(key)) == true) + { + // Add a new particle + vd.add(); + + //Set the added particle position, symmetrically positioned around x = 4.0 + // 4.0 Added + // *------|------* + // + vd.getLastPos()[0] = 2.0 * box.getHigh(0) - vd.getPos(key)[0]; + + // Prolongate the initial condition + vd.template getLastProp<0>() = f_xex2(vd.getLastPos()[0]); + } +} + /* * * ### WIKI END ### @@ -100,28 +167,24 @@ template<typename CellL> double calcLap(Point<1,double> p, vect_dist_key_dx key, int main(int argc, char* argv[]) { // - // ### WIKI 3 ### - // - // Some useful parameters. Like + // ### WIKI 5 ### // - // * Number of particles - // * Minimum number of padding particles - // * The computational domain - // * The spacing - // * The mollification length - // * Second order Laplacian kernel in 1D + // Some useful parameters. // // Number of particles const size_t Npart = 1000; + + // A different way to write Npart + size_t NpartA[1] = {Npart+1}; - // Number of step + // Number of steps const size_t Nstep = 1000; // Delta t const double dt = 10.0 / Nstep; - // Number of padding particles (At least) + // Number of padding particles, particles outside the domain const size_t Npad = 20; // The domain @@ -133,8 +196,15 @@ int main(int argc, char* argv[]) // The mollification length const double eps = 2*spacing; + // Diffusion constant + double D = 1e-4; + + // 2 constants + constexpr int U = 0; + constexpr int Lap_U = 1; + // - // ### WIKI 2 ### + // ### WIKI 6 ### // // Here we Initialize the library and we define Ghost size // and non-periodic boundary conditions @@ -142,62 +212,64 @@ int main(int argc, char* argv[]) openfpm_init(&argc,&argv); Vcluster & v_cl = create_vcluster(); - size_t bc[1]={NON_PERIODIC}; + size_t bc[1]={NON_PERIODIC}; Ghost<1,double> g(12*eps); // - // ### WIKI 3 ### - // - // Here we are creating a distributed vector defined by the following parameters + // ### WIKI 7 ### // - // we create a set of N+1 particles to have a fully covered domain of particles between 0.0 and 4.0 - // Suppose we have a spacing given by 1.0 you need 4 +1 particles to cover your domain + // Here we are creating a distributed vector defined by the following parameters + // + // <1,double, aggregate<double,double> > = 1 dimension, space with type double, 2 properties double,double (aggregate is like tuples, a way to encapsulate types). The first property is the field value u, the second is the Laplacian of u + // with Npart+1 particles, on the box domain [0.0,4.0], with bc boundary condition NON_PERIODIC, and an extended ghost part of size g // - vector_dist<1,double, aggregate<double>, CartDecomposition<1,double> > vd(Npart+1,box,bc,g); + vector_dist<1,double, aggregate<double,double> > vd(Npart+1,box,bc,g); // - // ### WIKI 4 ### - // - // We assign the position to the particles, the scalar property is set to - // the function x*e^(-x*x) value. - // Each processor has parts of the particles and fill part of the space, the - // position is assigned independently from the decomposition. - // - // In this case, if there are 1001 particles and 3 processors the in the - // domain from 0.0 to 4.0 + // ### WIKI 8 ### // - // * processor 0 place particles from 0.0 to 1.332 (334 particles) - // * processor 1 place particles from 1.336 to 2.668 (334 particles) - // * processor 2 place particles from 2.672 to 4.0 (333 particles) + // We assign the position to the particles in order to be equally spaced in a grid like position, the scalar property is set to + // the function x*e^(-x*x) value the initial condition + // + // P.S. In a Multi processor context getGridIterator adapt based on the underline space division across processors // + + // Create a grid like iterator + auto itp = vd.getGridIterator(NpartA); - // It return how many particles the processors with id < rank has in total - size_t base = vd.init_size_accum(Npart+1); - auto it2 = vd.getIterator(); - - while (it2.isNext()) + // Counter starting from 0 + size_t p = 0; + + // For each point in the grid + while (itp.isNext()) { - auto key = it2.get(); - - // set the position of the particles - vd.getPos(key)[0] = (key.getKey() + base) * spacing; - //set the property of the particles - vd.template getProp<0>(key) = f_xex2((key.getKey() + base) * spacing); - - ++it2; + // Get the grid index + auto key = itp.get(); + + // Assign the particle position + vd.getPos(p)[0] = key.get(0) * spacing; + + // Assign the property 0 based on the initial condition + vd.template getProp<U>(p) = f_xex2(key.get(0) * spacing); + + // Next particle + ++p; + + // Next grid point + ++itp; } // - // ### WIKI 5 ### + // ### WIKI 9 ### // // Once defined the position, we distribute them across the processors - // following the decomposition, finally we get the ghost part + // following the decomposition, finally we update the ghost part for the vield U // vd.map(); - vd.ghost_get<0>(); + vd.ghost_get<U>(); // - // ### WIKI 6 ### + // ### WIKI 10 ### // // near the boundary we have two options, or we use one sided kernels, // or we add additional particles, it is required that such particles @@ -219,11 +291,19 @@ int main(int argc, char* argv[]) // \endverbatim // // + + // The particle that we have to mirror are ... + + // ... on the box m_pad for the laft part Box<1,double> m_pad({0.0},{0.1}); + + // ... on the box m_pad2 for the right part Box<1,double> m_pad2({3.9},{4.0}); - double enlarge = 0.1; + + // It contain how much we enlarge the domain + double enlarge = m_pad.getHigh(0) - m_pad.getLow(0); - // Create a box + // In general 0.1 should be a sufficent padding, but in case it is not we recalculate the left and right boxes if (Npad * spacing > 0.1) { m_pad.setHigh(0,Npad * spacing); @@ -231,144 +311,205 @@ int main(int argc, char* argv[]) enlarge = Npad * spacing; } + + // + // ### WIKI 11 ### + // + // Here we mirror the particles if needed + // + // + auto it = vd.getDomainIterator(); + size_t n_part = vd.size_local(); while (it.isNext()) { auto key = it.get(); - // set the position of the particles - if (m_pad.isInsideNB(vd.getPos(key)) == true) - { - vd.add(); - vd.getLastPos()[0] = - vd.getPos(key)[0]; - vd.template getLastProp<0>() = - vd.template getProp<0>(key); - } - - // set the position of the particles - if (m_pad2.isInsideNB(vd.getPos(key)) == true) - { - vd.add(); - vd.getLastPos()[0] = 2.0 * box.getHigh(0) - vd.getPos(key)[0]; - vd.template getLastProp<0>() = f_xex2(vd.getLastPos()[0]); - } + mirror(vd,key,m_pad,m_pad2,box); ++it; } // - // ### WIKI 6 ### - // - // We create a CellList with cell spacing 12 sigma + // ### WIKI 12 ### // - - // get and construct the Cell list + // We create a CellList with cell spacing 8 epsilon, on the part of space domain + ghost + padding + // The padding area, can be bigger than the ghost part. In practice there is no reason to do it, but + // keeping ghost size and padding area unrelated give us the possibility to show how to create a CellList + // on a area bigger than the domain + ghost + Ghost<1,double> gp(enlarge); - auto cl = vd.getCellList(8*eps,gp); + + // Create a Cell list with Cell spaping 8*epsilon, the CellList is created on a domain+ghost+enlarge space + auto cl = vd.getCellList(8*eps,gp); - // Maximum infinity norm - double linf = 0.0; + // Maximum infinity norm + double linf = 0.0; // - // ### WIKI 7 ### + // ### WIKI 13 ### // - // Euler time integration - // - // + // Euler time integration until t = 10.0 + // + // - for (double t = 0; t <= 10 ; t += dt) - { - auto it_p = vd.getDomainIterator(); - while (it_p.isNext()) - { - // key - vect_dist_key_dx key = it_p.get(); + for (double t = 0; t <= 10.0 ; t += dt) + { + + // Iterate all the particles, including padding because are real particles + auto it_p = vd.getDomainIterator(); + while (it_p.isNext()) + { + // Get particle p + auto p = it_p.get(); - Point<1,double> p = vd.getPos(key); + // Get the position of the particle p + Point<1,double> x_p = vd.getPos(p); - // We are not interested in calculating out the domain - // note added padding particle are considered domain particles - if (p.get(0) < 0.0 || p.get(0) >= 4.0) + // We are not interested in calculating out the domain (So on the padded particles) + if (x_p.get(0) < 0.0 || x_p.get(0) >= 4.0) { ++it_p; continue; } - double pse = calcLap(p,key,vd,eps,spacing,cl); - - // Euler update step - vd.template getProp<0>(key) = vd.template getProp<0>(key) + pse * dt; + // Here we calculate the Laplacian of u on position x_p and we store the result on the particle p + vd.template getProp<Lap_U>(p) = calcLap(x_p,p,vd,eps,spacing,cl); + // Next particle ++it_p; - } - } - - // Once we have the value of the Laplacian we update with the eulerian step - - - // - // ### WIKI 8 ### - // - // Collect the solution in one processor - // - - // Resize a vector with the local size of the vector - openfpm::vector<double> v; - v.resize(vd.size_local()); - - // y contain 2 vectors the first is the calculated solution - // the second contain the analytical solution - openfpm::vector<openfpm::vector<double>> y; - - // Copy the property we want to Plot - for (size_t i = 0 ; i < vd.size_local() ; i++) - y.get(i) = vd.template getProp<0>(i); - - // Gather the solution on master - v_cl.SGather(v,y.get(0),0); - - // - // ### WIKI 9 ### - // - // Here we plot - // - - // If there are too many points terminate - if (y.get(0).size() > 16000) - { - std::cerr << "Too many points for plotting " << std::endl; - return 1; - } - - openfpm::vector<double> x; - - // It fill the vector x with vg.size() points with interval values between 0.0 and 4.0 - // and fill the vector y; - - // Total points to plot - size_t tot_p = y.get(0).size(); - - Fill1D(0.0,4.0,tot_p,x); - - // It fill y.get(1) with the Analytical solution - Fill1D(0.0,4.0,tot_p,y.get(1),f_xex2); - - // Plot with GooglePlot - // Google charts options - GCoptions options; - - options.yAxis = std::string("Y Axis"); - options.xAxis = std::string("X Axis"); - options.lineWidth = 1.0; - - GoogleChart cg; - cg.AddLinesGraph(x,y,options); - cg.write("PSE_plot.html"); - - // - // ### WIKI 8 ### - // - // Deinitialize the library - // - openfpm_finalize(); + } + + // Once we calculated the Laplacian we do not need enymore the padding particle eliminate them + // n_part is the original size of the vector without padding particles + vd.resize(n_part); + + // Iterate again on all particles + auto it_p2 = vd.getDomainIterator(); + while (it_p2.isNext()) + { + // Get particle p + auto p = it_p2.get(); + + // Get the Laplacian + double pse = vd.template getProp<Lap_U>(p); + + // Integrate with Euler step + vd.template getProp<0>(p) += D * pse * dt; + + // mirror again the particles if needed (this for the next step) + mirror(vd,p,m_pad,m_pad2,box); + + // Next particle + ++it_p2; + } + + // Update the ghost part + vd.ghost_get<U>(); + } + + // + // ### WIKI 14 ### + // + // U now contain the solution scattered across processors. Because it is not possible plot on multiple + // processors (Google chart does not support it) we collect the solution on one processor + // + + struct pos_val + { + // position of the particle + double pos; + + // value of U of the particle + double val; + + // usefull to sort the particle by position + bool operator<(const pos_val & p) + { + return pos < p.pos; + } + }; + + // Resize a vector with the local size of the vector + openfpm::vector<pos_val> v(vd.size_local()); + + // This will contail all the particles on the master processor + openfpm::vector<pos_val> v_tot; + + + // Copy the particle position and the field U, into the vector v + for (size_t i = 0 ; i < vd.size_local() ; i++) + { + // particle position + v.get(i).pos = vd.getPos(i)[0]; + + // Field U + v.get(i).val = vd.template getProp<U>(i); + } + + // from the partial solution vector v we Gather the total solution v_tot on master (processor=0) + v_cl.SGather(v,v_tot,0); + + // + // ### WIKI 15 ### + // + // Once we gather the solution on master we plot it. Only processor 0 do this + // + + // Only processor = 0 + if (v_cl.getProcessUnitID() == 0) + { + // sort the solution by particle position + v_tot.sort(); + + // y contain 2 vectors the first is the calculated solution + // the second contain the initial condition + openfpm::vector<openfpm::vector<double>> y(2); + + // vector with the particle position for plotting + openfpm::vector<double> x; + + // We fill the plotting variables + for (size_t i = 0 ; i < v_tot.size() ; i++) + { + // fill x with the particle position + x.add(v_tot.get(i).pos); + + // fill y with the value of the field U contained by the particles + y.get(0).add(v_tot.get(i).val); + + // fill y with the initial condition + y.get(1).add(f_xex2(v_tot.get(i).pos)); + } + + // Plot with GooglePlot + // Google charts options + GCoptions options; + + // Assign a name for the Y axis + options.yAxis = std::string("U Axis"); + + // Assign a name for the X Axis + options.xAxis = std::string("X Axis"); + + // width of the line + options.lineWidth = 1.0; + + // Create a google plot object + GoogleChart cg; + + // add a line plot + cg.AddLines(x,y,options); + + // write the plot file + cg.write("PSE_plot.html"); + } + + // + // ### WIKI 16 ### + // + // Deinitialize the library + // + openfpm_finalize(); } diff --git a/example/Vector/2_molecular_dynamic/Makefile b/example/Vector/2_molecular_dynamic/Makefile deleted file mode 100644 index c4a841ff..00000000 --- a/example/Vector/2_molecular_dynamic/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -include ../../example.mk - -CC=mpic++ - -LDIR = - -OBJ = main.o - -%.o: %.cpp - $(CC) -O3 -g -c --std=c++11 -o $@ $< $(INCLUDE_PATH) - -md_dyn: $(OBJ) - $(CC) -o $@ $^ $(CFLAGS) $(LIBS_PATH) $(LIBS) - -all: md_dyn - -.PHONY: clean all - -clean: - rm -f *.o *~ core md_dyn - diff --git a/example/Vector/2_molecular_dynamic/config.cfg b/example/Vector/2_molecular_dynamic/config.cfg deleted file mode 100644 index 1eecbac3..00000000 --- a/example/Vector/2_molecular_dynamic/config.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[pack] -files = main.cpp Makefile diff --git a/example/Vector/2_molecular_dynamic/main.cpp b/example/Vector/2_molecular_dynamic/main.cpp deleted file mode 100644 index b8ae1efe..00000000 --- a/example/Vector/2_molecular_dynamic/main.cpp +++ /dev/null @@ -1,379 +0,0 @@ - -#include "Vector/vector_dist.hpp" -#include "Decomposition/CartDecomposition.hpp" -#include "data_type/aggregate.hpp" -#include "Plot/GoogleChart.hpp" -#include "Plot/util.hpp" - -/* - * ### WIKI 1 ### - * - * ## Molecular Dynamic with Lennard-Jones potential - * - * This example show a simple Lennard-Jones molecular dynamic simulation in a stable regime - * - * ### WIKI END ### - * - */ - -constexpr int velocity = 0; -constexpr int force = 1; - -/* ### WIKI 11 ### - * - * The function to calculate the forces between particles. It require the vector of particles - * Cell list and scaling factor. - * - */ -void calc_forces(vector_dist<3,double, aggregate<double[3],double[3]> > & vd, CellList<3, double, FAST, shift<3, double> > & NN, double L) -{ - - // ### WIKI 12 ### - // - // Update the cell list from the actual particle configuration - // - // - vd.updateCellList(NN); - - // ### WIKI 13 ### - // - // Calculate the forces - // - auto it2 = vd.getDomainIterator(); - while (it2.isNext()) - { - auto p = it2.get(); - - Point<3,double> xp = vd.getPos(p); - - vd.template getProp<force>(p)[0] = 0.0; - vd.template getProp<force>(p)[1] = 0.0; - vd.template getProp<force>(p)[2] = 0.0; - - // For each neighborhood particle - auto Np = NN.template getNNIterator<NO_CHECK>(NN.getCell(vd.getPos(p))); - - while (Np.isNext()) - { - // Neighborhood particle q - auto q = Np.get(); - - if (q == p.getKey()) {++Np; continue;}; - - // repulsive - Point<3,double> xq = vd.getPos(q); - Point<3,double> r = xp - xq; - - // take the norm, normalize - float rn = r.norm(); - r /= rn; - rn *= L; - - // Calculate the force, using pow is slower - Point<3,double> f = 24.0*(2.0 / (rn*rn*rn*rn*rn*rn*rn*rn*rn*rn*rn*rn*rn) - 1.0 / (rn*rn*rn*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); - - ++Np; - } - - ++it2; - } -} - -/* ### WIKI 14 ### - * - * The function to calculate the total energy. It require the same parameter as calculate forces - * - */ -double calc_energy(vector_dist<3,double, aggregate<double[3],double[3]> > & vd, CellList<3, double, FAST, shift<3, double> > & NN, double L) -{ - // ### WIKI 15 ### - // - // Reset the counter for the energy and - // update the cell list from the actual particle configuration - // - // - double E = 0.0; - vd.updateCellList(NN); - - // ### WIKI 16 ### - // - // Calculate the forces - // - auto it2 = vd.getDomainIterator(); - while (it2.isNext()) - { - auto p = it2.get(); - - Point<3,double> xp = vd.getPos(p); - - vd.template getProp<force>(p)[0] = 0.0; - vd.template getProp<force>(p)[1] = 0.0; - vd.template getProp<force>(p)[2] = 0.0; - - // For each neighborhood particle - auto Np = NN.template getNNIterator<NO_CHECK>(NN.getCell(vd.getPos(p))); - - while (Np.isNext()) - { - // Neighborhood particle q - auto q = Np.get(); - - if (q == p.getKey()) {++Np; continue;}; - - Point<3,double> xq = vd.getPos(q); - Point<3,double> r = xp - xq; - - // take the normalized direction - float rn = r.norm(); - r /= rn; - - rn *= L; - - // potential energy (using pow is slower) - E += 4.0 * ( 1.0 / (rn*rn*rn*rn*rn*rn*rn*rn*rn*rn*rn*rn) + 1.0 / ( rn*rn*rn*rn*rn*rn) ); - - // Kinetic energy - E += sqrt(vd.template getProp<force>(p)[0]*vd.template getProp<force>(p)[0] + - vd.template getProp<force>(p)[1]*vd.template getProp<force>(p)[1] + - vd.template getProp<force>(p)[2]*vd.template getProp<force>(p)[2]); - - ++Np; - } - - ++it2; - } - - return E; -} - -int main(int argc, char* argv[]) -{ - // - // ### WIKI 2 ### - // - // Here we define important parameters or the simulation, time step integration, - // size of the box, and cut-off radius of the interaction - // - double dt = 0.005; - double L = 10.0; - float r_cut = 0.3; - - openfpm::vector<double> x; - openfpm::vector<openfpm::vector<double>> y; - - // - // ### WIKI 2 ### - // - // Here we Initialize the library, we create a Box that define our domain, boundary conditions, ghost - // and the grid size - // - openfpm_init(&argc,&argv); - Vcluster & v_cl = create_vcluster(); - - // we create a 10x10x10 Grid iterator - size_t sz[3] = {10,10,10}; - - 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_cut); - - // - // ### WIKI 3 ### - // - // Here we define a distributed vector in 3D, containing 3 properties, a - // scalar double, a vector double[3], and a tensor or rank 2 double[3][3]. - // In this case the vector contain 0 particles in total - // - vector_dist<3,double, aggregate<double[3],double[3]> > vd(0,box,bc,ghost); - - // - // ### WIKI 4 ### - // - // We define a grid iterator, to create particles on a grid like way. - // An important note is that the grid iterator, iterate only on the - // local nodes for each processor for example suppose to have a domain like - // the one in figure - // - // +---------+ - // |* * *|* *| - // | 2 | | - // |* * *|* *| - // | --- | - // |* *|* * *| - // | | | - // |* *|* * *| - // | | 1 | - // |* *|* * *| - // +---------+ - // - // divided in 2 processors, the processor 1 will iterate only on the points - // inside the portion of space marked with one. Also the grid iterator follow the - // boundary condition specified in vector. For a perdiodic 2D 5x5 grid we have - // - // +---------+ - // * * * * * | - // | | - // * * * * * | - // | | - // * * * * * | - // | | - // * * * * * | - // | | - // *-*-*-*-*-+ - // - // Because the right border is equivalent to the left border, while for a non periodic we have the - // following distribution of points - // - // *-*-*-*-* - // | | - // * * * * * - // | | - // * * * * * - // | | - // * * * * * - // | | - // *-*-*-*-* - // - // The loop will place particles on a grid like on each processor - // - 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; - } - - vd.map(); - - // - // ### WIKI 5 ### - // - // we get the cell list to compute the neighborhood of the particles - auto NN = vd.getCellList(r_cut); - - // calculate forces a(tn) - calc_forces(vd,NN,L); - unsigned long int f = 0; - - // - // ### WIKI 6 ### - // - // Here we do 100 MD steps using verlet integrator - // - // $$ \vec{v}(t_{n+1/2}) = \vec{v}_p(t_n) + \frac{1}{2} \delta t \vec{a}(t_n) $$ - // $$ \vec{x}(t_{n}) = \vec{x}_p(t_n) + \delta t \vec{v}(t_n+1/2) $$ - // - // calculate the forces $$ \vec{a} (t_{n}) $$ from $$ \vec{x} (t_{n}) $$ - // - // $$ \vec{v}(t_{n+1}) = \vec{v}_p(t_n+1/2) + \frac{1}{2} \delta t \vec{a}(t_n+1) $$ - // - // - for (size_t i = 0; i < 10000 ; i++) - { - auto it3 = vd.getDomainIterator(); - - 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]; - - // here we calculate x(tn + 1) - vd.getPos(p)[0] += vd.template getProp<velocity>(p)[0]*dt; - vd.getPos(p)[1] += vd.template getProp<velocity>(p)[1]*dt; - vd.getPos(p)[2] += vd.template getProp<velocity>(p)[2]*dt; - - ++it3; - } - - vd.map(); - vd.template ghost_get<>(); - - // calculate forces or a(tn + 1) - calc_forces(vd,NN,L); - - 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; - } - - if (i % 100 == 0) - { - vd.deleteGhost(); - vd.write("particles_",f); - double energy = calc_energy(vd,NN,L); - auto & vcl = create_vcluster(); - vcl.sum(energy); - vcl.execute(); - - vd.ghost_get<>(); - - x.add(i); - y.add({energy}); - if (vcl.getProcessUnitID() == 0) - std::cout << "Energy: " << energy << std::endl; - - f++; - } - } - - // Google charts options - 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"); - - // - // ### WIKI 10 ### - // - // Deinitialize the library - // - openfpm_finalize(); -} - - - - diff --git a/openfpm_numerics b/openfpm_numerics index ce33014d..df19a7de 160000 --- a/openfpm_numerics +++ b/openfpm_numerics @@ -1 +1 @@ -Subproject commit ce33014d668526a01d02cc1bb28e1ee91e6ab0bb +Subproject commit df19a7de48ebbbea0c3c2a1f8ebca60bdfef6618 diff --git a/src/Grid/grid_dist_id.hpp b/src/Grid/grid_dist_id.hpp index 57929aea..674eb447 100644 --- a/src/Grid/grid_dist_id.hpp +++ b/src/Grid/grid_dist_id.hpp @@ -1405,9 +1405,7 @@ public: Point<dim,St> offset = getOffset(i); vtk_g.add(loc_grid.get(i),offset,cd_sm.getCellBox().getP2(),gdb_ext.get(i).Dbox); } - vtk_g.write(output + "_grid_" + std::to_string(v_cl.getProcessUnitID()) + ".vtk"); - - write_ie_boxes(output); + vtk_g.write(output + "_" + std::to_string(v_cl.getProcessUnitID()) + ".vtk"); return true; } diff --git a/src/Vector/vector_dist.hpp b/src/Vector/vector_dist.hpp index 14ce55bf..e2e9a195 100644 --- a/src/Vector/vector_dist.hpp +++ b/src/Vector/vector_dist.hpp @@ -1600,6 +1600,23 @@ public: v_prp.resize(g_m); } + /*! \brief Resize the vector (locally) + * + * \warning It automaticallt delete the ghosts + * + * \param rs + * + */ + void resize(size_t rs) + { + deleteGhost(); + + v_pos.resize(rs); + v_prp.resize(rs); + + g_m = rs; + } + /*! \brief Output particle position and properties * * \param out output -- GitLab