OpenFPM  5.2.0
Project that contain the implementation of distributed structures
petsc_solver_unit_tests.cpp
1 /*
2  * petsc_solver_unit_tests.hpp
3  *
4  * Created on: Jun 19, 2017
5  * Author: i-bird
6  */
7 
8 #ifndef OPENFPM_NUMERICS_SRC_SOLVERS_PETSC_SOLVER_UNIT_TESTS_CPP_
9 #define OPENFPM_NUMERICS_SRC_SOLVERS_PETSC_SOLVER_UNIT_TESTS_CPP_
10 
11 #include "config.h"
12 #ifdef HAVE_PETSC
13 
14 #define BOOST_TEST_DYN_LINK
15 #include <boost/test/unit_test.hpp>
16 
17 #include "petsc_solver_report_unit_tests.hpp"
18 
19 #include "Grid/grid_dist_id.hpp"
20 #include "Matrix/SparseMatrix.hpp"
21 #include "Vector/Vector.hpp"
22 #include "FiniteDifference/Laplacian.hpp"
23 #include "FiniteDifference/FDScheme.hpp"
24 #include "Solvers/petsc_solver.hpp"
25 
26 
27 BOOST_AUTO_TEST_SUITE( mg_solvers_test )
28 
29 
30 BOOST_AUTO_TEST_CASE( laplacian_3D_int_zero_mg )
31 {
32  constexpr unsigned int phi = 0;
33  typedef Field<phi,poisson_nn_helm> phi_f;
34 
35  Vcluster<> & v_cl = create_vcluster();
36  if (v_cl.getProcessingUnits() != 3)
37  return;
38 
39  Ghost<3,long int> g(2);
40  Ghost<3,long int> stencil_max(2);
41  Box<3,float> domain({0.0,0.0,0.0},{1.0,1.0,1.0});
42 
43  periodicity<3> p({PERIODIC,PERIODIC,PERIODIC});
44 
46  grid_dist_id<3,float,aggregate<float>> psi({64,64,64},domain,g,p);
47  grid_dist_id<3,float,aggregate<float>> psi2(psi.getDecomposition(),{64,64,64},g);
48 
49  // Fill B
50 
51  size_t center_x = psi.size(0) / 2;
52  size_t center_y = psi.size(1) / 2;
53  size_t center_z = psi.size(2) / 2;
54  auto it = psi.getDomainIterator();
55 
56  while (it.isNext())
57  {
58  auto key = it.get();
59  auto gkey = it.getGKey(key);
60 
61  float sx = (float)(gkey.get(0))-center_x;
62  float sy = (float)(gkey.get(1))-center_y;
63  float sz = (float)(gkey.get(2))-center_z;
64 
65  float gs = 100.0*exp(-((sx*sx)+(sy*sy)+(sz*sz))/100.0);
66 
67  psi.get<0>(key) = sin(2*M_PI*sx/psi.size(0))*sin(2*M_PI*sy/psi.size(1))*sin(2*M_PI*sz/psi.size(2))*gs;
68  psi2.get<0>(key) = sin(2*M_PI*sx/psi.size(0))*sin(2*M_PI*sy/psi.size(1))*sin(2*M_PI*sz/psi.size(2))*gs;
69 
70  ++it;
71  }
72 
73  FDScheme<poisson_nn_helm> fd(stencil_max, domain, psi);
74 
75  fd.template impose_dit<0>(poisson(),psi,psi.getDomainIterator());
76 
77  petsc_solver<double> solver;
78  solver.setSolver(KSPBCGS);
79  solver.setAbsTol(0.01);
80  solver.setMaxIter(500);
81 
83 
84  solver.setPreconditioner(PCHYPRE_BOOMERAMG);
85  solver.setPreconditionerAMG_nl(6);
87  solver.setPreconditionerAMG_relax("SOR/Jacobi");
88  solver.setPreconditionerAMG_cycleType("V",6,6);
89  solver.setPreconditionerAMG_coarsen("HMIS");
91 
92  timer tm_solve;
93  tm_solve.start();
94  auto x_ = solver.solve(fd.getA(),fd.getB());
95  tm_solve.stop();
96 
97  fd.template copy<phi>(x_,psi);
98  psi.write("AMG_psi");
99 
100  #ifdef HAVE_OSX
101  bool check = compare("AMG_psi_" + std::to_string(v_cl.getProcessUnitID()) + ".vtk","test/AMG_psi_" + std::to_string(v_cl.getProcessUnitID()) + "_test_osx.vtk");
102  #elif __GNUC__ == 6
103  bool check = compare("AMG_psi_" + std::to_string(v_cl.getProcessUnitID()) + ".vtk","test/AMG_psi_" + std::to_string(v_cl.getProcessUnitID()) + "_test_GCC6.vtk");
104  #elif __GNUC__ == 4
105  bool check = compare("AMG_psi_" + std::to_string(v_cl.getProcessUnitID()) + ".vtk","test/AMG_psi_" + std::to_string(v_cl.getProcessUnitID()) + "_test_GCC4.vtk");
106  #else
107  bool check = true;
108  #endif
109 
110  BOOST_REQUIRE_EQUAL(check,true);
111 
112 
113  // Resolve
114  timer tm_solve2;
115  tm_solve2.start();
116  auto x2_ = solver.solve(fd.getB());
117  tm_solve2.stop();
118 
119  fd.template copy<phi>(x_,psi2);
120  psi2.write("AMG_psi2");
121 
122  #ifdef HAVE_OSX
123  check = compare("AMG_psi2_" + std::to_string(v_cl.getProcessUnitID()) + ".vtk","test/AMG_psi2_" + std::to_string(v_cl.getProcessUnitID()) + "_test_osx.vtk");
124  #elif __GNUC__ == 6
125  check = compare("AMG_psi2_" + std::to_string(v_cl.getProcessUnitID()) + ".vtk","test/AMG_psi2_" + std::to_string(v_cl.getProcessUnitID()) + "_test_GCC6.vtk");
126  #elif __GNUC__ == 4
127  check = compare("AMG_psi2_" + std::to_string(v_cl.getProcessUnitID()) + ".vtk","test/AMG_psi2_" + std::to_string(v_cl.getProcessUnitID()) + "_test_GCC4.vtk");
128  #else
129  check = true;
130  #endif
131  BOOST_REQUIRE_EQUAL(check,true);
132 }
133 
134 BOOST_AUTO_TEST_SUITE_END()
135 
136 #endif
137 
138 #endif /* OPENFPM_NUMERICS_SRC_SOLVERS_PETSC_SOLVER_UNIT_TESTS_CPP_ */
Finite Differences.
Definition: FDScheme.hpp:127
Definition: eq.hpp:83
Definition: Ghost.hpp:40
Laplacian second order on h (spacing)
Definition: Laplacian.hpp:23
size_t getProcessUnitID()
Get the process unit id.
size_t getProcessingUnits()
Get the total number of processors.
Implementation of VCluster class.
Definition: VCluster.hpp:59
This is a distributed grid.
This class is able to do Matrix inversion in parallel with PETSC solvers.
Vector< T, PETSC_BASE > solve(SparseMatrix< T, int, PETSC_BASE > &A, const Vector< T, PETSC_BASE > &b, bool initial_guess=false)
Here we invert the matrix and solve the system.
void setPreconditionerAMG_cycleType(const std::string &cycle_type, int sweep_up=-1, int sweep_dw=-1, int sweep_crs=-1)
It set the type of cycle and optionally the number of sweep.
void setPreconditionerAMG_nl(int nl)
Set the number of levels for the algebraic-multigrid preconditioner.
void setPreconditionerAMG_coarsenNodalType(int norm)
Set the block coarsening norm type.
void setPreconditioner(PCType type)
Set the preconditioner of the linear solver.
void setPreconditionerAMG_coarsen(const std::string &type)
Set the coarsening method for the algebraic-multi-grid preconditioner.
void setSolver(KSPType type)
Set the Petsc solver.
void setPreconditionerAMG_relax(const std::string &type, int k=REL_ALL)
Set the relaxation method for the algebraic-multi-grid preconditioner.
void setMaxIter(PetscInt n)
Set the maximum number of iteration for Krylov solvers.
void setAbsTol(PetscReal abstol_)
Set the absolute tolerance as stop criteria.
void setPreconditionerAMG_maxit(int nit)
Set the maximum number of V or W cycle for algebraic-multi-grid.
Class for cpu time benchmarking.
Definition: timer.hpp:28
void stop()
Stop the timer.
Definition: timer.hpp:119
void start()
Start the timer.
Definition: timer.hpp:90
Boundary conditions.
Definition: common.hpp:22