Hypre.cxx
1 #ifndef SELDON_FILE_HYPRE_CXX
2 
3 #include "Hypre.hxx"
4 #include "HypreInline.cxx"
5 
6 namespace Seldon
7 {
8 
10  template<class T>
12  {
13  solver_created = false;
14  nodl_scalar = 0;
15  nb_u = 1;
16 
17  comm = MPI_COMM_SELF;
18  print_level = 0;
19 
20  type_preconditioner = BOOMER_AMG;
21 
22  ProcNumber = NULL;
23  DofNumber = NULL;
24 
25  amg_max_levels = 20;
26  amg_num_sweeps = 1;
27  amg_smoother = HYBRID_GS_BACKWARD;
28 
29  sai_filter = 0.1;
30  sai_threshold = 0.1;
31  sai_max_levels = 1;
32  sai_sym = 1;
33 
34  euclid_use_ilut = false;
35  euclid_level = 0;
36  euclid_threshold = 0;
37  euclid_droptol = 0.01;
38  }
39 
40 
42  template<class T>
44  {
45  Clear();
46  }
47 
48 
50  template<class T>
52  {
53  if (solver_created)
54  {
55  if (type_preconditioner == BOOMER_AMG)
56  HYPRE_BoomerAMGDestroy(solver);
57  else if (type_preconditioner == PARASAILS)
58  HYPRE_ParaSailsDestroy(solver);
59  else if (type_preconditioner == EUCLID)
60  HYPRE_EuclidDestroy(solver);
61  else if (type_preconditioner == AMS)
62  HYPRE_AMSDestroy(solver);
63 
64  HYPRE_IJMatrixDestroy(A);
65  HYPRE_IJVectorDestroy(vec_b);
66  HYPRE_IJVectorDestroy(vec_x);
67  }
68 
69  solver_created = false;
70  }
71 
72 
74  template<class T>
75  void HyprePreconditioner<T>::SetInputPreconditioning(const string& keyword, const Vector<string>& params)
76  {
77  if (keyword == "AMG")
78  {
79  type_preconditioner = BOOMER_AMG;
80  for (int k = 0; k < params.GetM(); k += 2)
81  {
82  if (params(k) == "MaximumLevel")
83  amg_max_levels = to_num<int>(params(k+1));
84  else if (params(k) == "NumberSweeps")
85  amg_num_sweeps = to_num<int>(params(k+1));
86  else if (params(k) == "Smoother")
87  {
88  if (params(k+1) == "Jacobi")
89  amg_smoother = JACOBI;
90  else if (params(k+1) == "GaussSeidel")
91  amg_smoother = GS_PAR_SEQ;
92  else if (params(k+1) == "HybridGaussSeidel")
93  amg_smoother = HYBRID_GS_BACKWARD;
94  else if (params(k+1) == "HybridGaussSeidelForward")
95  amg_smoother = HYBRID_GS_FORWARD;
96  else if (params(k+1) == "HybridGaussSeidelSymmetric")
97  amg_smoother = HYBRID_GS_SYMMETRIC;
98  else if (params(k+1) == "L1_GaussSeidel")
99  amg_smoother = L1_GAUSS_SEIDEL;
100  else if (params(k+1) == "Chebyshev")
101  amg_smoother = CHEBYSHEV;
102  else if (params(k+1) == "FCF_Jacobi")
103  amg_smoother = FCF_JACOBI;
104  else if (params(k+1) == "L1_Jacobi")
105  amg_smoother = L1_JACOBI;
106  else
107  amg_smoother = to_num<int>(params(k+1));
108  }
109  }
110  }
111  else if (keyword == "ParaSails")
112  {
113  type_preconditioner = PARASAILS;
114  for (int k = 0; k < params.GetM(); k += 2)
115  {
116  if (params(k) == "Filter")
117  sai_filter = to_num<HYPRE_Real>(params(k+1));
118  else if (params(k) == "Threshold")
119  sai_threshold = to_num<HYPRE_Real>(params(k+1));
120  else if (params(k) == "MaximumLevel")
121  sai_max_levels = to_num<int>(params(k+1));
122  else if (params(k) == "Symmetry")
123  sai_sym = to_num<int>(params(k+1));
124  }
125  }
126  else if (keyword == "Euclid")
127  {
128  type_preconditioner = EUCLID;
129  for (int k = 0; k < params.GetM(); k += 2)
130  {
131  if (params(k) == "Threshold")
132  euclid_threshold = to_num<HYPRE_Real>(params(k+1));
133  else if (params(k) == "Droptol")
134  euclid_droptol = to_num<HYPRE_Real>(params(k+1));
135  else if (params(k) == "Level")
136  euclid_level = to_num<int>(params(k+1));
137  else if (params(k) == "Algorithm")
138  {
139  if (params(k+1) == "ILU")
140  euclid_use_ilut = false;
141  else if (params(k+1) == "ILUT")
142  euclid_use_ilut = true;
143  }
144  }
145  }
146  else if (keyword == "AMS")
147  {
148  type_preconditioner = AMS;
149  }
150  else
151  {
152  cout << "Unknown preconditioning : " << keyword << endl;
153  abort();
154  }
155  }
156 
157 
159  template<class T> template<class Prop, class Storage, class Allocator>
162  bool keep_matrix)
163  {
164  // previous preconditioning is cleared if existing
165  Clear();
166 
167  comm = A0.GetCommunicator();
168  int nb_proc; MPI_Comm_size(comm, &nb_proc);
169  General prop; Vector<int> row_numbers;
170  Vector<long> size_rows; Vector<int> cols; Vector<HYPRE_Complex> values;
171 
172  if (nb_proc > 1)
173  {
174  ProcNumber = &A0.GetProcessorSharingRows();
175  DofNumber = &A0.GetSharingRowNumbers();
176  nodl_scalar = A0.GetNodlScalar();
177  nb_u = A0.GetNbScalarUnknowns();
178 
179  if (keep_matrix)
180  {
182  A = A0;
183  AssembleDistributed(A, prop, comm, row_numbers,
184  local_rows, size_rows, cols, values, false, true);
185  }
186  else
187  AssembleDistributed(A0, prop, comm, row_numbers,
188  local_rows, size_rows, cols, values, false, true);
189  }
190  else
191  {
192  int N = A0.GetM();
193  ConvertToCSR(A0, prop, size_rows, cols, values);
194  if (!keep_matrix)
195  A0.Clear();
196 
197  row_numbers.Reallocate(N);
198  row_numbers.Fill();
199  local_rows.Reallocate(N);
200  local_rows.Fill();
201  }
202 
203  // we call a non-template function to avoid many instantiations of a lengthy code
204  FinalizePreconditioner(row_numbers, size_rows, cols, values);
205  }
206 
207 
209  template<class T>
212  Vector<int>& cols, Vector<HYPRE_Complex>& values)
213  {
214  int Nloc = local_rows.GetM();
215  int ilower = row_numbers(0);
216  int iupper = row_numbers(Nloc-1);
217 
218  // size_rows is a ptr array (incremented numbers)
219  // we decrement to have the size of rows
220  Vector<int> length_rows(Nloc);
221  for (int i = 0; i < Nloc; i++)
222  length_rows(i) = size_rows(i+1) - size_rows(i);
223 
224  // Create the matrix.
225  // Note that this is a square matrix, so we indicate the row partition
226  // size twice (since number of rows = number of cols)
227  HYPRE_IJMatrixCreate(comm, ilower, iupper, ilower, iupper, &A);
228 
229  // Choose a parallel csr format storage
230  HYPRE_IJMatrixSetObjectType(A, HYPRE_PARCSR);
231 
232  // Initialize before setting coefficients
233  HYPRE_IJMatrixInitialize(A);
234 
235  // setting coefficients
236  HYPRE_IJMatrixSetValues(A, Nloc, length_rows.GetData(), row_numbers.GetData(), cols.GetData(), values.GetData());
237 
238  // we clear intermediate arrays cols, values and size_rows
239  cols.Clear(); values.Clear(); size_rows.Clear();
240  length_rows.Clear();
241 
242  // Assemble after setting the coefficients
243  HYPRE_IJMatrixAssemble(A);
244 
245  // Get the parcsr matrix object to use
246  HYPRE_IJMatrixGetObject(A, (void**) &parcsr_A);
247 
248  // create two vectors for x and b
249  HYPRE_IJVectorCreate(comm, ilower, iupper, &vec_b);
250  HYPRE_IJVectorSetObjectType(vec_b, HYPRE_PARCSR);
251  HYPRE_IJVectorInitialize(vec_b);
252 
253  HYPRE_IJVectorCreate(comm, ilower, iupper, &vec_x);
254  HYPRE_IJVectorSetObjectType(vec_x, HYPRE_PARCSR);
255  HYPRE_IJVectorInitialize(vec_x);
256 
257  HYPRE_IJVectorGetObject(vec_b, (void **) &par_b);
258  HYPRE_IJVectorGetObject(vec_x, (void **) &par_x);
259 
260  // now constructing the preconditioning
261  solver_created = true;
262  if (type_preconditioner == BOOMER_AMG)
263  {
264  HYPRE_BoomerAMGCreate(&solver);
265  HYPRE_BoomerAMGSetPrintLevel(solver, print_level);
266 
267  HYPRE_BoomerAMGSetOldDefault(solver); // Falgout coarsening with modified classical interpolaiton
268  HYPRE_BoomerAMGSetRelaxType(solver, amg_smoother);
269  HYPRE_BoomerAMGSetRelaxOrder(solver, 1); // uses C/F relaxation
270  HYPRE_BoomerAMGSetNumSweeps(solver, amg_num_sweeps); // Sweeps on each level
271  HYPRE_BoomerAMGSetMaxLevels(solver, amg_max_levels); // maximum number of levels
272  HYPRE_BoomerAMGSetTol(solver, 0); // conv. tolerance
273  HYPRE_BoomerAMGSetMaxIter(solver, 1); // only one iteration for preconditioning
274 
275  // Now setup
276  HYPRE_BoomerAMGSetup(solver, parcsr_A, par_b, par_x);
277 
278  // to avoid printing each time Solve is called
279  HYPRE_BoomerAMGSetPrintLevel(solver, 0);
280  }
281  else if (type_preconditioner == PARASAILS)
282  {
283  // Now set up the ParaSails preconditioner and specify any parameters
284  HYPRE_ParaSailsCreate(comm, &solver);
285 
286  // Set some parameters (See Reference Manual for more parameters)
287  HYPRE_ParaSailsSetParams(solver, sai_threshold, sai_max_levels);
288  HYPRE_ParaSailsSetFilter(solver, sai_filter);
289  HYPRE_ParaSailsSetSym(solver, sai_sym);
290  HYPRE_ParaSailsSetLogging(solver, print_level);
291 
292  // setup
293  HYPRE_ParaSailsSetup(solver, parcsr_A, par_b, par_x);
294  }
295  else if (type_preconditioner == EUCLID)
296  {
297  HYPRE_EuclidCreate(comm, &solver);
298  HYPRE_EuclidSetLevel(solver, euclid_level);
299 
300  HYPRE_EuclidSetSparseA(solver, euclid_threshold);
301  if (euclid_use_ilut)
302  HYPRE_EuclidSetILUT(solver, euclid_droptol);
303 
304  if (print_level > 0)
305  {
306  HYPRE_EuclidSetStats(solver, 1);
307  HYPRE_EuclidSetMem(solver, 1);
308  }
309 
310  // setup
311  HYPRE_EuclidSetup(solver, parcsr_A, par_b, par_x);
312  }
313  else
314  {
315  cout << "Unknown preconditioning : " << type_preconditioner << endl;
316  abort();
317  }
318  }
319 
320 
322  template<class T>
325  const Vector<T>& r, Vector<T>& z)
326  {
327  HYPRE_Complex* b_data = par_b->local_vector->data;
328  HYPRE_Complex* x_data = par_x->local_vector->data;
329  Vector<int>& num = local_rows;
330 
331  // we extract the original values of r to put in par_b (shared values are ignored)
332  for (int i = 0; i < num.GetM(); i++)
333  b_data[i] = r(num(i));
334 
335  for (int i = 0; i < num.GetM(); i++)
336  x_data[i] = 0;
337 
338  // the appropriate hypre solver is called
339  if (trans.NoTrans() || A.IsSymmetric())
340  {
341  switch(type_preconditioner)
342  {
343  case BOOMER_AMG:
344  HYPRE_BoomerAMGSolve(solver, parcsr_A, par_b, par_x);
345  break;
346  case PARASAILS:
347  HYPRE_ParaSailsSolve(solver, parcsr_A, par_b, par_x);
348  break;
349  case EUCLID:
350  HYPRE_EuclidSolve(solver, parcsr_A, par_b, par_x);
351  break;
352  }
353  }
354  else
355  {
356  switch(type_preconditioner)
357  {
358  case BOOMER_AMG:
359  HYPRE_BoomerAMGSolveT(solver, parcsr_A, par_b, par_x);
360  break;
361  default :
362  cout << "Transpose preconditioning not available" << endl;
363  abort();
364  }
365  }
366 
367  // then we expand the values in vector z (including shared rows)
368  z.Zero();
369  for (int i = 0; i < num.GetM(); i++)
370  z(num(i)) = x_data[i];
371 
372  int nb_proc; MPI_Comm_size(comm, &nb_proc);
373  if (nb_proc > 1)
374  AssembleVector(z, MPI_SUM, *ProcNumber, *DofNumber, comm, nodl_scalar, nb_u, 11);
375  }
376 
377 }
378 
379 #define SELDON_FILE_HYPRE_CXX
380 #endif
381 
Seldon::HyprePreconditioner::~HyprePreconditioner
~HyprePreconditioner()
destructor
Definition: Hypre.cxx:43
Seldon::DistributedMatrix_Base::GetNbScalarUnknowns
int GetNbScalarUnknowns() const
returns the number of scalar unknowns
Definition: DistributedMatrixInline.cxx:82
Seldon::SeldonTranspose
Definition: MatrixFlag.hxx:32
Seldon::DistributedMatrix::Clear
void Clear()
Clears the matrix.
Definition: DistributedMatrix.cxx:4851
Seldon::Vector
Definition: SeldonHeader.hxx:207
Seldon::HyprePreconditioner::HyprePreconditioner
HyprePreconditioner()
default constructor
Definition: Hypre.cxx:11
Seldon::HyprePreconditioner::FinalizePreconditioner
void FinalizePreconditioner(Vector< int > &row_numbers, Vector< long > &size_rows, Vector< int > &cols, Vector< HYPRE_Complex > &values)
internal function to finalize the computation of preconditioning
Definition: Hypre.cxx:211
Seldon::HyprePreconditioner::SetInputPreconditioning
void SetInputPreconditioning(const string &, const Vector< string > &)
sets parameters from a keyword and associated parameters
Definition: Hypre.cxx:75
Seldon::HyprePreconditioner::Solve
void Solve(const SeldonTranspose &trans, const VirtualMatrix< T > &A, const Vector< T > &r, Vector< T > &z)
applies preconditioning z = M r (or its transpose z = M^T r)
Definition: Hypre.cxx:324
Seldon::DistributedMatrix_Base::GetSharingRowNumbers
Vector< IVect > & GetSharingRowNumbers()
returns row numbers for each set of shared rows
Definition: DistributedMatrix.cxx:2133
Seldon::DistributedMatrix_Base::GetProcessorSharingRows
IVect & GetProcessorSharingRows()
returns processor numbers for each set of shared rows
Definition: DistributedMatrix.cxx:2103
Seldon::HyprePreconditioner::Clear
void Clear()
erases the current object
Definition: Hypre.cxx:51
Seldon::General
Definition: Properties.hxx:26
Seldon::DistributedMatrix_Base::GetNodlScalar
int GetNodlScalar() const
returns the number of scalar unknowns
Definition: DistributedMatrixInline.cxx:74
Seldon::DistributedMatrix
matrix distributed over all the processors
Definition: DistributedMatrix.hxx:506
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::HyprePreconditioner::ConstructPreconditioner
void ConstructPreconditioner(DistributedMatrix< HYPRE_Complex, Prop, Storage, Allocator > &A0, bool keep_matrix=false)
main function constructing hypre preconditioning from a given sparse matrix
Definition: Hypre.cxx:161
Seldon::DistributedMatrix_Base::GetCommunicator
MPI_Comm & GetCommunicator()
returns MPI communicator (processors that will share the matrix)
Definition: DistributedMatrixInline.cxx:34
Seldon::VirtualMatrix
Abstract base class for all matrices.
Definition: Matrix_Base.hxx:42