CircleActor::State Orbital::integrate( State state, int dt, value_type maxSpeed ) { if( !isMovable ) return state; if( isActive ) { // Reset gravity accumulator. g *= 0; for( size_t i=0; i < attractors.size(); i++ ) { std::tr1::shared_ptr<CircleActor> attr = attractors[i].lock(); if( attr->isActive && attr.get() != this ) { vector_type r = attr->s - state.s; g += magnitude ( r, attr->mass() * g_multiplier() / g_dist(r) * Arena::scale ); } } state.a = g; } else { state.a *= 0; } return CircleActor::integrate( state, dt, maxSpeed ); }
Greedy::State Greedy::integrate( State state, int dt, value_type maxSpeed ) { if( !isMovable ) return state; if( isActive && !Orbital::target.expired() ) { // Reset gravity accumulator. g *= 0; std::tr1::shared_ptr<CircleActor> attr = Orbital::target.lock(); vector_type r = attr->s - state.s; g += magnitude ( r, attr->mass() * g_multiplier() / g_dist(r) * Arena::scale ); state.a = g; } else { state.a *= 0; } return CircleActor::integrate( state, dt, maxSpeed ); }
int main(int argc, char* argv[]) { /*! * \page Grid_1_stencil Grid 1 stencil * * ## Initialization ## {#e1_st_init} * * Initialize the library and several objects * * \see \ref e0_s_initialization * * \snippet Grid/1_stencil/main.cpp parameters * * */ //! \cond [parameters] \endcond openfpm_init(&argc,&argv); // domain Box<3,float> domain({0.0,0.0,0.0},{1.0,1.0,1.0}); // grid sizes size_t sz[3] = {100,100,100}; // ghost extension Ghost<3,float> g(0.03); //! \cond [parameters] \endcond /*! * \page Grid_1_stencil Grid 1 stencil * * ## Grid create ## {#e1_st_inst} * * Create a distributed grid in 3D. With typedef we create an alias name for aggregate<float[3],float[3]>. * In practice the type of grid_point == aggregate<float[3],float[3]> * * \see \ref e0_s_grid_inst * * \snippet Grid/1_stencil/main.cpp grid * */ //! \cond [grid] \endcond // a convenient alias for aggregate<...> typedef aggregate<float,float> grid_point; grid_dist_id<3, float, grid_point> g_dist(sz,domain,g); //! \cond [grid] \endcond /*! * \page Grid_1_stencil Grid 1 stencil * * ## Loop over grid points ## {#e1_s_loop_gp} * * Get an iterator that go through the point of the domain (No ghost) * * \see \ref e0_s_loop_gp * * \snippet Grid/1_stencil/main.cpp iterator * \snippet Grid/1_stencil/main.cpp iterator2 * */ //! \cond [iterator] \endcond auto dom = g_dist.getDomainIterator(); while (dom.isNext()) { //! \cond [iterator] \endcond /*! * \page Grid_1_stencil Grid 1 stencil * * Inside the cycle we get the local grid key * * \see \ref e0_s_grid_coord * * \snippet Grid/1_stencil/main.cpp local key * */ //! \cond [local key] \endcond auto key = dom.get(); //! \cond [local key] \endcond /*! * \page Grid_1_stencil Grid 1 stencil * * We convert the local grid position, into global position, key_g contain 3 integers that identify the position * of the grid point in global coordinates * * \see \ref e0_s_grid_coord * * \snippet Grid/1_stencil/main.cpp global key * */ //! \cond [global key] \endcond auto key_g = g_dist.getGKey(key); //! \cond [global key] \endcond /*! * \page Grid_1_stencil Grid 1 stencil * * we write on the grid point of position (i,j,k) the value i*i + j*j + k*k on the property A. * Mathematically is equivalent to the function * * \f$ f(x,y,z) = x^2 + y^2 + z^2 \f$ * * \snippet Grid/1_stencil/main.cpp function * */ //! \cond [function] \endcond g_dist.template get<A>(key) = key_g.get(0)*key_g.get(0) + key_g.get(1)*key_g.get(1) + key_g.get(2)*key_g.get(2); //! \cond [function] \endcond //! \cond [iterator2] \endcond ++dom; } //! \cond [iterator2] \endcond /*! * \page Grid_1_stencil Grid 1 stencil * * ## Ghost ## {#e1_s_ghost} * * Each sub-domain has an extended part, that is materially contained into another processor. * In general is not synchronized * ghost_get<A> synchronize the property A in the ghost part * * \snippet Grid/1_stencil/main.cpp ghost * */ //! \cond [ghost] \endcond g_dist.template ghost_get<A>(); //! \cond [ghost] \endcond /*! * \page Grid_1_stencil Grid 1 stencil * * Get again another iterator, iterate across all the domain points, calculating a Laplace stencil. Write the * result on B * * \snippet Grid/1_stencil/main.cpp laplacian * */ //! \cond [laplacian] \endcond auto dom2 = g_dist.getDomainIterator(); while (dom2.isNext()) { auto key = dom2.get(); // Laplace stencil g_dist.template get<B>(key) = g_dist.template get<A>(key.move(x,1)) + g_dist.template get<A>(key.move(x,-1)) + g_dist.template get<A>(key.move(y,1)) + g_dist.template get<A>(key.move(y,-1)) + g_dist.template get<A>(key.move(z,1)) + g_dist.template get<A>(key.move(z,-1)) - 6*g_dist.template get<A>(key); ++dom2; } //! \cond [laplacian] \endcond /*! * \page Grid_1_stencil Grid 1 stencil * * * Finally we want a nice output to visualize the information stored by the distributed grid * * \see \ref e0_s_VTK_vis * * \snippet Grid/1_stencil/main.cpp output * */ //! \cond [output] \endcond g_dist.write("output"); //! \cond [output] \endcond /*! * \page Grid_1_stencil Grid 1 stencil * * Deinitialize the library * * \snippet Grid/1_stencil/main.cpp finalize * */ //! \cond [finalize] \endcond openfpm_finalize(); //! \cond [finalize] \endcond /*! * \page Grid_1_stencil Grid 1 stencil * * # Full code # {#code} * * \include Grid/1_stencil/main.cpp * */ }
int main(int argc, char* argv[]) { /*! * \page Stokes_1_3D_petsc Stokes incompressible 3D petsc * * ## Initialization ## {#num_sk_inc_petsc_3D_init} * * After model our equation we: * * Initialize the library * * Define some useful constants * * define Ghost size * * Non-periodic boundary conditions * * Padding domain expansion * * Padding and Ghost differ in the fact the padding extend the domain. * Ghost is an extension for each sub-domain * * \snippet Numerics/Stoke_flow/0_2D_incompressible/main_petsc.cpp init * */ //! \cond [init] \endcond // Initialize openfpm_init(&argc,&argv); // velocity in the grid is the property 0, pressure is the property 1 constexpr int velocity = 0; constexpr int pressure = 1; // Domain Box<3,float> domain({0.0,0.0,0.0},{3.0,1.0,1.0}); // Ghost (Not important in this case but required) Ghost<3,float> g(0.01); // Grid points on x=36 and y=12 z=12 long int sz[] = {36,12,12}; size_t szu[3]; szu[0] = (size_t)sz[0]; szu[1] = (size_t)sz[1]; szu[2] = (size_t)sz[2]; // We need one more point on the left and down part of the domain // This is given by the boundary conditions that we impose. // Padding<3> pd({1,1,1},{0,0,0}); //! \cond [init] \endcond /*! * \page Stokes_1_3D_petsc Stokes incompressible 3D petsc * * Distributed grid that store the solution * * \see \ref e0_s_grid_inst * * \snippet Numerics/Stoke_flow/1_3D_incompressible/main_petsc.cpp grid inst * */ //! \cond [grid inst] \endcond grid_dist_id<3,float,aggregate<float[3],float>> g_dist(szu,domain,g); //! \cond [grid inst] \endcond /*! * \page Stokes_1_3D_petsc Stokes incompressible 3D petsc * * Solving the system above require the solution of a system like that * * \f$ Ax = b \quad x = A^{-1}b\f$ * * where A is the system the discretize the left hand side of the equations + boundary conditions * and b discretize the right hand size + boundary conditions * * FDScheme is the object that we use to produce the Matrix A and the vector b. * Such object require the maximum extension of the stencil * * \snippet Numerics/Stoke_flow/1_3D_incompressible/main_petsc.cpp fd scheme * */ //! \cond [fd scheme] \endcond // It is the maximum extension of the stencil (order 2 laplacian stencil has extension 1) Ghost<3,long int> stencil_max(1); // Finite difference scheme FDScheme<lid_nn> fd(pd, stencil_max, domain, g_dist.getGridInfo(), g_dist); //! \cond [fd scheme] \endcond /*! * \page Stokes_1_3D_petsc Stokes incompressible 3D petsc * * ## Impose the equation on the domain ## {#num_sk_inc_3D_ied} * * Here we impose the system of equation, we start from the incompressibility Eq imposed in the bulk with the * exception of the first point {0,0} and than we set P = 0 in {0,0}, why we are doing this is again * mathematical to have a well defined system, an intuitive explanation is that P and P + c are both * solution for the incompressibility equation, this produce an ill-posed problem to make it well posed * we set one point in this case {0,0} the pressure to a fixed constant for convenience P = 0 * * The best way to understand what we are doing is to draw a smaller example like 8x8. * Considering that we have one additional point on the left for padding we have a grid * 9x9. If on each point we have v_x v_y and P unknown we have * 9x9x3 = 243 unknown. In order to fully determine and unique solution we have to * impose 243 condition. The code under impose (in the case of 9x9) between domain * and bulk 243 conditions. * * \snippet Numerics/Stoke_flow/1_3D_incompressible/main_petsc.cpp impose eq dom * * */ //! \cond [impose eq dom] \endcond // start and end of the bulk fd.impose(ic_eq(),0.0, EQ_4, {0,0,0},{sz[0]-2,sz[1]-2,sz[2]-2},true); fd.impose(Prs(), 0.0, EQ_4, {0,0,0},{0,0,0}); fd.impose(vx_eq(),0.0, EQ_1, {1,0},{sz[0]-2,sz[1]-2,sz[2]-2}); fd.impose(vy_eq(),0.0, EQ_2, {0,1},{sz[0]-2,sz[1]-2,sz[2]-2}); fd.impose(vz_eq(),0.0, EQ_3, {0,0,1},{sz[0]-2,sz[1]-2,sz[2]-2}); // v_x // R L (Right,Left) fd.impose(v_x(),0.0, EQ_1, {0,0,0}, {0,sz[1]-2,sz[2]-2}); fd.impose(v_x(),0.0, EQ_1, {sz[0]-1,0,0},{sz[0]-1,sz[1]-2,sz[2]-2}); // T B (Top,Bottom) fd.impose(avg_y_vx_f(),0.0, EQ_1, {0,-1,0}, {sz[0]-1,-1,sz[2]-2}); fd.impose(avg_y_vx(),0.0, EQ_1, {0,sz[1]-1,0},{sz[0]-1,sz[1]-1,sz[2]-2}); // A F (Forward,Backward) fd.impose(avg_z_vx_f(),0.0, EQ_1, {0,-1,-1}, {sz[0]-1,sz[1]-1,-1}); fd.impose(avg_z_vx(),0.0, EQ_1, {0,-1,sz[2]-1},{sz[0]-1,sz[1]-1,sz[2]-1}); // v_y // R L fd.impose(avg_x_vy_f(),0.0, EQ_2, {-1,0,0}, {-1,sz[1]-1,sz[2]-2}); fd.impose(avg_x_vy(),1.0, EQ_2, {sz[0]-1,0,0},{sz[0]-1,sz[1]-1,sz[2]-2}); // T B fd.impose(v_y(), 0.0, EQ_2, {0,0,0}, {sz[0]-2,0,sz[2]-2}); fd.impose(v_y(), 0.0, EQ_2, {0,sz[1]-1,0},{sz[0]-2,sz[1]-1,sz[2]-2}); // F A fd.impose(avg_z_vy(),0.0, EQ_2, {-1,0,sz[2]-1}, {sz[0]-1,sz[1]-1,sz[2]-1}); fd.impose(avg_z_vy_f(),0.0, EQ_2, {-1,0,-1}, {sz[0]-1,sz[1]-1,-1}); // v_z // R L fd.impose(avg_x_vz_f(),0.0, EQ_3, {-1,0,0}, {-1,sz[1]-2,sz[2]-1}); fd.impose(avg_x_vz(),1.0, EQ_3, {sz[0]-1,0,0},{sz[0]-1,sz[1]-2,sz[2]-1}); // T B fd.impose(avg_y_vz(),0.0, EQ_3, {-1,sz[1]-1,0},{sz[0]-1,sz[1]-1,sz[2]-1}); fd.impose(avg_y_vz_f(),0.0, EQ_3, {-1,-1,0}, {sz[0]-1,-1,sz[2]-1}); // F A fd.impose(v_z(),0.0, EQ_3, {0,0,0}, {sz[0]-2,sz[1]-2,0}); fd.impose(v_z(),0.0, EQ_3, {0,0,sz[2]-1},{sz[0]-2,sz[1]-2,sz[2]-1}); // When we pad the grid, there are points of the grid that are not // touched by the previous condition. Mathematically this lead // to have too many variables for the conditions that we are imposing. // Here we are imposing variables that we do not touch to zero // // L R fd.impose(Prs(), 0.0, EQ_4, {-1,-1,-1},{-1,sz[1]-1,sz[2]-1}); fd.impose(Prs(), 0.0, EQ_4, {sz[0]-1,-1,-1},{sz[0]-1,sz[1]-1,sz[2]-1}); // T B fd.impose(Prs(), 0.0, EQ_4, {0,sz[1]-1,-1}, {sz[0]-2,sz[1]-1,sz[2]-1}); fd.impose(Prs(), 0.0, EQ_4, {0,-1 ,-1}, {sz[0]-2,-1, sz[2]-1}); // F A fd.impose(Prs(), 0.0, EQ_4, {0,0,sz[2]-1}, {sz[0]-2,sz[1]-2,sz[2]-1}); fd.impose(Prs(), 0.0, EQ_4, {0,0,-1}, {sz[0]-2,sz[1]-2,-1}); // Impose v_x v_y v_z padding fd.impose(v_x(), 0.0, EQ_1, {-1,-1,-1},{-1,sz[1]-1,sz[2]-1}); fd.impose(v_y(), 0.0, EQ_2, {-1,-1,-1},{sz[0]-1,-1,sz[2]-1}); fd.impose(v_z(), 0.0, EQ_3, {-1,-1,-1},{sz[0]-1,sz[1]-1,-1}); //! \cond [impose eq dom] \endcond /*! * \page Stokes_1_3D_petsc Stokes incompressible 3D petsc * * ## Solve the system of equation ## {#num_sk_inc_3D_petsc_sse} * * Once we imposed all the equations we can retrieve the Matrix A and the vector b * and pass these two element to the solver. In this example we are using PETSC solvers * direct/Iterative solvers. While Umfpack * has only one solver, PETSC wrap several solvers. The function best_solve set the solver in * the modality to try multiple solvers to solve your system. The subsequent call to solve produce a report * of all the solvers tried comparing them in error-convergence and speed. If you do not use * best_solve try to solve your system with the default solver GMRES (That is the most robust iterative solver * method) * * \snippet Numerics/Stoke_flow/1_3D_incompressible/main_petsc.cpp solver * */ //! \cond [solver] \endcond // Create an PETSC solver petsc_solver<double> solver; // Warning try many solver and collect statistics require a lot of time // To just solve you can comment this line // solver.best_solve(); // Give to the solver A and b, return x, the solution auto x = solver.solve(fd.getA(),fd.getB()); //! \cond [solver] \endcond /*! * \page Stokes_1_3D_petsc Stokes incompressible 3D petsc * * ## Copy the solution on the grid and write on VTK ## {#num_sk_inc_3D_petsc_csg} * * Once we have the solution we copy it on the grid * * \snippet Numerics/Stoke_flow/1_3D_incompressible/main_petsc.cpp copy write * */ //! \cond [copy write] \endcond // Bring the solution to grid fd.template copy<velocity,pressure>(x,{0,0},{sz[0]-1,sz[1]-1,sz[2]-1},g_dist); g_dist.write("lid_driven_cavity_p_petsc"); //! \cond [copy write] \endcond /*! * \page Stokes_1_3D_petsc Stokes incompressible 3D petsc * * ## Finalize ## {#num_sk_inc_3D_petsc_fin} * * At the very end of the program we have always to de-initialize the library * * \snippet Numerics/Stoke_flow/1_3D_incompressible/main_petsc.cpp fin lib * */ //! \cond [fin lib] \endcond openfpm_finalize(); //! \cond [fin lib] \endcond /*! * \page Stokes_1_3D_petsc Stokes incompressible 3D petsc * * # Full code # {#num_sk_inc_3D_petsc_code} * * \include Numerics/Stoke_flow/1_3D_incompressible/main_petsc.cpp * */ }
template<typename solver_type,typename lid_nn> void lid_driven_cavity_2d() { Vcluster & v_cl = create_vcluster(); if (v_cl.getProcessingUnits() > 3) return; //! [lid-driven cavity 2D] // velocity in the grid is the property 0, pressure is the property 1 constexpr int velocity = 0; constexpr int pressure = 1; // Domain, a rectangle Box<2,float> domain({0.0,0.0},{3.0,1.0}); // Ghost (Not important in this case but required) Ghost<2,float> g(0.01); // Grid points on x=256 and y=64 long int sz[] = {256,64}; size_t szu[2]; szu[0] = (size_t)sz[0]; szu[1] = (size_t)sz[1]; // We need one more point on the left and down part of the domain // This is given by the boundary conditions that we impose, the // reason is mathematical in order to have a well defined system // and cannot be discussed here Padding<2> pd({1,1},{0,0}); // Distributed grid that store the solution grid_dist_id<2,float,aggregate<float[2],float>,CartDecomposition<2,float>> g_dist(szu,domain,g); // It is the maximum extension of the stencil Ghost<2,long int> stencil_max(1); // Finite difference scheme FDScheme<lid_nn> fd(pd, stencil_max, domain, g_dist.getGridInfo(), g_dist); // Here we impose the equation, we start from the incompressibility Eq imposed in the bulk with the // exception of the first point {0,0} and than we set P = 0 in {0,0}, why we are doing this is again // mathematical to have a well defined system, an intuitive explanation is that P and P + c are both // solution for the incompressibility equation, this produce an ill-posed problem to make it well posed // we set one point in this case {0,0} the pressure to a fixed constant for convenience P = 0 fd.impose(ic_eq(),0.0, EQ_3, {0,0},{sz[0]-2,sz[1]-2},true); fd.impose(Prs(), 0.0, EQ_3, {0,0},{0,0}); // Here we impose the Eq1 and Eq2 fd.impose(vx_eq(),0.0, EQ_1, {1,0},{sz[0]-2,sz[1]-2}); fd.impose(vy_eq(),0.0, EQ_2, {0,1},{sz[0]-2,sz[1]-2}); // v_x and v_y // Imposing B1 fd.impose(v_x(),0.0, EQ_1, {0,0},{0,sz[1]-2}); fd.impose(avg_vy_f(),0.0, EQ_2 , {-1,0},{-1,sz[1]-1}); // Imposing B2 fd.impose(v_x(),0.0, EQ_1, {sz[0]-1,0},{sz[0]-1,sz[1]-2}); fd.impose(avg_vy(),1.0, EQ_2, {sz[0]-1,0},{sz[0]-1,sz[1]-1}); // Imposing B3 fd.impose(avg_vx_f(),0.0, EQ_1, {0,-1},{sz[0]-1,-1}); fd.impose(v_y(), 0.0, EQ_2, {0,0},{sz[0]-2,0}); // Imposing B4 fd.impose(avg_vx(),0.0, EQ_1, {0,sz[1]-1},{sz[0]-1,sz[1]-1}); fd.impose(v_y(), 0.0, EQ_2, {0,sz[1]-1},{sz[0]-2,sz[1]-1}); // When we pad the grid, there are points of the grid that are not // touched by the previous condition. Mathematically this lead // to have too many variables for the conditions that we are imposing. // Here we are imposing variables that we do not touch to zero // // Padding pressure fd.impose(Prs(), 0.0, EQ_3, {-1,-1},{sz[0]-1,-1}); fd.impose(Prs(), 0.0, EQ_3, {-1,sz[1]-1},{sz[0]-1,sz[1]-1}); fd.impose(Prs(), 0.0, EQ_3, {-1,0},{-1,sz[1]-2}); fd.impose(Prs(), 0.0, EQ_3, {sz[0]-1,0},{sz[0]-1,sz[1]-2}); // Impose v_x Padding Impose v_y padding fd.impose(v_x(), 0.0, EQ_1, {-1,-1},{-1,sz[1]-1}); fd.impose(v_y(), 0.0, EQ_2, {-1,-1},{sz[0]-1,-1}); solver_type solver; auto x = solver.solve(fd.getA(),fd.getB()); //! [lid-driven cavity 2D] //! [Copy the solution to grid] fd.template copy<velocity,pressure>(x,{0,0},{sz[0]-1,sz[1]-1},g_dist); std::string s = std::string(demangle(typeid(solver_type).name())); s += "_"; //! [Copy the solution to grid] g_dist.write(s + "lid_driven_cavity_p" + std::to_string(v_cl.getProcessingUnits()) + "_grid"); #ifdef HAVE_OSX std::string file1 = std::string("test/") + s + "lid_driven_cavity_p" + std::to_string(v_cl.getProcessingUnits()) + "_grid_" + std::to_string(v_cl.getProcessUnitID()) + "_test_osx.vtk"; std::string file2 = s + "lid_driven_cavity_p" + std::to_string(v_cl.getProcessingUnits()) + "_grid_" + std::to_string(v_cl.getProcessUnitID()) + ".vtk"; #else #if __GNUC__ == 5 std::string file1 = std::string("test/") + s + "lid_driven_cavity_p" + std::to_string(v_cl.getProcessingUnits()) + "_grid_" + std::to_string(v_cl.getProcessUnitID()) + "_test_GCC5.vtk"; std::string file2 = s + "lid_driven_cavity_p" + std::to_string(v_cl.getProcessingUnits()) + "_grid_" + std::to_string(v_cl.getProcessUnitID()) + ".vtk"; #else std::string file1 = std::string("test/") + s + "lid_driven_cavity_p" + std::to_string(v_cl.getProcessingUnits()) + "_grid_" + std::to_string(v_cl.getProcessUnitID()) + "_test_GCC4.vtk"; std::string file2 = s + "lid_driven_cavity_p" + std::to_string(v_cl.getProcessingUnits()) + "_grid_" + std::to_string(v_cl.getProcessUnitID()) + ".vtk"; #endif #endif std::cout << "File1: " << file1 << std::endl; std::cout << "File2: " << file2 << std::endl; // Check that match bool test = compare(file1,file2); BOOST_REQUIRE_EQUAL(test,true); }