KASKADE 7 development version
hyprecond.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2002-2020 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef BOOMERAMG_HH
14#define BOOMERAMG_HH
15
16#include <math.h>
17// #include "defs.h" <--- defines min() and max() macros colliding with std::min() etc. Do NOT include in header files.
18
19extern "C" {
20#include "protos.h"
21#ifndef MAX_HBNAME
22#include "ios.h"
23#endif
24}
25
26#include "HYPRE_sstruct_ls.h"
27// delete preprocessor macros min and max which were defined in itsol-1/hypre-2.6.0b headers,
28// since these macros may interfere with subsequently included Kaskade7 headers or program code
29#undef min
30#undef max
31
32#include <vector>
33
34#include "dune/istl/preconditioners.hh"
35
36#include "linalg/triplet.hh"
38
39namespace Kaskade
40{
41 //---------------------------------------------------------------------
42 //---------------------------------------------------------------------
43
49 template <class Op>
50 class BoomerAMG: public Dune::Preconditioner<typename Op::range_type, typename Op::range_type>
51 {
52 typedef typename Op::range_type range_type;
53 typedef range_type domain_type;
54 typedef typename Op::field_type field_type;
55
56 public:
57 BoomerAMG(Op& op, int steps_=1, int coarsentype=21, int interpoltype=0, double tol=1.0e-8,
58 int cycleType=1, int relaxType=2, double strongThreshold=0.3,
59 int variant=0, int overlap=1, int syseqn=1, int verbosity_=2)
60 : op(op), steps(steps_), verbosity(verbosity_), eqnIndex(0)
61 {
62 static char main[] = "main"; // ISO C++ forbids writable string literals - need to have a variable.
63
64 MatrixAsTriplet<field_type> A = op.template get<MatrixAsTriplet<field_type> >();
65 n = A.nrows();
66 int nnz = A.nnz(); /* ierr; */
67 std::vector<int> Ap, Ai;
68 std::vector<double> Az;
69 // FILE *flog = stdout;
70
71 if ( verbosity>=2 )
72 {
73 std::cout << "HYPRE_BoomerAMG: n=" << n << ", nnz=" << nnz <<
74 " steps=" << steps <<
75 ", coarsentype=" << coarsentype << ", interpolationtype=" <<
76 interpoltype << "\n";
77 };
78 Ap.resize(n+1); Ai.resize(nnz); Az.resize(nnz);
80 Ap,Ai,Az);
81 for (int i=0;i<n;i++) Ap[i]=Ap[i+1]-Ap[i];
82 ixx = (int *)Malloc(n*sizeof(int), main);
83 for (int i=0;i<n;i++) ixx[i]=i;
84
85 HYPRE_IJMatrixCreate(0, 0, n-1, 0, n-1, &ij_matrix);
86 HYPRE_IJMatrixSetPrintLevel(ij_matrix,10); /* Debug */
87 HYPRE_IJMatrixSetObjectType(ij_matrix, HYPRE_PARCSR);
88 HYPRE_IJMatrixInitialize(ij_matrix);
89 /* set matrix coefficients */
90 HYPRE_IJMatrixSetValues(ij_matrix,n,&Ap[0],ixx,&Ai[0],&Az[0]);
91 HYPRE_IJMatrixAssemble(ij_matrix);
92 HYPRE_IJMatrixGetObject(ij_matrix, (void **) &parcsr_matrix);
93
94 HYPRE_BoomerAMGCreate(&preconditioner);
95 HYPRE_BoomerAMGSetPrintLevel(preconditioner,1); /* Debug */
96 HYPRE_BoomerAMGSetCoarsenType(preconditioner,coarsentype);
97 HYPRE_BoomerAMGSetInterpType(preconditioner,interpoltype);
98 HYPRE_BoomerAMGSetMaxIter(preconditioner,steps);
99 HYPRE_BoomerAMGSetTol(preconditioner,tol);
100 HYPRE_BoomerAMGSetStrongThreshold(preconditioner, strongThreshold); //RR 0.6 3D
101 HYPRE_BoomerAMGSetCycleType(preconditioner, cycleType); //RR 2 W-Zyklus
102 HYPRE_BoomerAMGSetRelaxType(preconditioner, relaxType); //RR 3 PrecondType::SSOR smoother
103 HYPRE_BoomerAMGSetVariant (preconditioner, variant);
104 HYPRE_BoomerAMGSetOverlap (preconditioner, overlap) ;
105 if (syseqn>1)
106 {
107 HYPRE_BoomerAMGSetNodal(preconditioner, 1);
108 HYPRE_BoomerAMGSetNumFunctions(preconditioner, syseqn);
109 int i, k, lng = n/syseqn;
110 eqnIndex = (int *)Malloc(n*sizeof(int), main);
111 for (i=0; i<syseqn; i++)
112 for (k=0; k<lng; k++)
113 eqnIndex[i*lng+k] = i;
114
115 HYPRE_BoomerAMGSetDofFunc(preconditioner, eqnIndex);
116 }
117
118 // HYPRE_BoomerAMGSetCycleRelaxType(preconditioner,6,1);
119 // HYPRE_BoomerAMGSetCycleRelaxType(preconditioner,6,2);
120 // HYPRE_BoomerAMGSetCycleRelaxType(preconditioner,6,3);
121 HYPRE_BoomerAMGSetup(preconditioner,parcsr_matrix,0,0);
122
123 xxraw = (double *)Malloc(n*sizeof(double), main);
124 yyraw = (double *)Malloc(n*sizeof(double), main);
125
126 HYPRE_IJVectorCreate(0, 0, n-1, &xxij);
127 HYPRE_IJVectorSetPrintLevel(xxij,10); /* Debug */
128 HYPRE_IJVectorSetObjectType(xxij, HYPRE_PARCSR);
129 HYPRE_IJVectorInitialize(xxij);
130 HYPRE_IJVectorAssemble(xxij);
131 HYPRE_IJVectorGetObject(xxij, (void **) &xx);
132
133 HYPRE_IJVectorCreate(0, 0, n-1, &yyij);
134 HYPRE_IJVectorSetPrintLevel(yyij,10); /* Debug */
135 HYPRE_IJVectorSetObjectType(yyij, HYPRE_PARCSR);
136 HYPRE_IJVectorInitialize(yyij);
137 HYPRE_IJVectorAssemble(yyij);
138 HYPRE_IJVectorGetObject(yyij, (void **) &yy);
139 }
141 {
142 HYPRE_IJMatrixDestroy (ij_matrix);
143 HYPRE_BoomerAMGDestroy(preconditioner);
144 HYPRE_IJVectorDestroy (xxij);
145 HYPRE_IJVectorDestroy (yyij);
146 free(xxraw);
147 free(yyraw);
148 free(ixx);
149 if (eqnIndex) free(eqnIndex);
150 }
151
152 virtual void pre (domain_type&, range_type&) {}
153 virtual void post (domain_type&) {}
154
155 virtual void apply (domain_type& x, range_type const& y) {
156 /* set vector values */
157 y.write(yyraw);
158 for (int i=0; i<n; i++)
159 xxraw[i] = 0.0;
160
161 HYPRE_IJVectorSetValues(yyij, n, ixx, yyraw);
162 HYPRE_IJVectorSetValues(xxij, n, ixx, xxraw);
163 HYPRE_BoomerAMGSolve(preconditioner,parcsr_matrix,yy,xx);
164 if (steps>1)
165 {
166 int num_iterations;
167 double rel_resid_norm;
168 HYPRE_BoomerAMGGetNumIterations (preconditioner,&num_iterations);
169 HYPRE_BoomerAMGGetFinalRelativeResidualNorm (preconditioner, &rel_resid_norm);
170 if ( verbosity>=2 )
171 {
172 std::cout << "HYPRE_BoomerAMG1: " << num_iterations << " steps, rel_resid_norm="
173 << rel_resid_norm << std::endl;
174 }
175 }
176 HYPRE_IJVectorGetValues(xxij,n,ixx,xxraw);
177 x.read(xxraw);
178 }
179
185 virtual Dune::SolverCategory::Category category() const override
186 {
187 return Dune::SolverCategory::sequential;
188 }
189 private:
190 Op& op;
191 HYPRE_Solver preconditioner;
192 HYPRE_IJMatrix ij_matrix;
193 HYPRE_ParCSRMatrix parcsr_matrix;
194 HYPRE_IJVector xxij, yyij;
195 HYPRE_ParVector xx, yy;
196 int n, steps, verbosity;
197 double *xxraw, *yyraw;
198 int *ixx, *eqnIndex;
199 };
200
201 //---------------------------------------------------------------------
202
208 template <class Op>
209 class Euclid: public Dune::Preconditioner<typename Op::range_type, typename Op::range_type>
210 {
211 typedef typename Op::range_type range_type;
212 typedef range_type domain_type;
213 typedef typename Op::field_type field_type;
214
215 public:
216
217 Euclid(Op& op, int level=1, double droptol=0.0, int printlevel=0, int bj=0,
218 int verbosity=2)
219 : op(op)
220 {
221 static char main[] = "main"; // ISO C++ forbids writable string literals - need to have a variable.
222
223 MatrixAsTriplet<field_type> A = op.template get<MatrixAsTriplet<field_type> >();
224 n = A.nrows();
225 int nnz = A.nnz(); /* ierr; */
226 std::vector<int> Ap, Ai;
227 std::vector<double> Az;
228 // FILE *flog = stdout;
229
230 if ( verbosity>=2 )
231 {
232 std::cout << "PrecondType::EUCLID: n=" << n << ", nnz=" << nnz << ", level=" <<
233 level << ", droptol=" << droptol << ", printlevel=" << printlevel <<
234 ", bj=" << bj << "\n";
235 };
236 Ap.resize(n+1); Ai.resize(nnz); Az.resize(nnz);
238 Ap,Ai,Az);
239 for (int i=0;i<n;i++) Ap[i]=Ap[i+1]-Ap[i];
240 ixx = (int *)Malloc(n*sizeof(int), main);
241 for (int i=0;i<n;i++) ixx[i]=i;
242
243 HYPRE_IJMatrixCreate(0, 0, n-1, 0, n-1, &ij_matrix);
244 HYPRE_IJMatrixSetPrintLevel(ij_matrix,10); /* Debug */
245 HYPRE_IJMatrixSetObjectType(ij_matrix, HYPRE_PARCSR);
246 HYPRE_IJMatrixInitialize(ij_matrix);
247 /* set matrix coefficients */
248 HYPRE_IJMatrixSetValues(ij_matrix,n,&Ap[0],ixx,&Ai[0],&Az[0]);
249 HYPRE_IJMatrixAssemble(ij_matrix);
250 HYPRE_IJMatrixGetObject(ij_matrix, (void **) &parcsr_matrix);
251
252 HYPRE_EuclidCreate(0,&preconditioner);
253 HYPRE_EuclidSetStats(preconditioner,printlevel);
254 HYPRE_EuclidSetMem(preconditioner,printlevel);
255 HYPRE_EuclidSetLevel(preconditioner,level);
256 // HYPRE_EuclidSetSparseA(preconditioner,droptol);
257 HYPRE_EuclidSetRowScale(preconditioner,0);
258 if (bj)
259 HYPRE_EuclidSetBJ(preconditioner,bj);
260 if (droptol!=0.0)
261 HYPRE_EuclidSetILUT(preconditioner,droptol);
262 HYPRE_EuclidSetup(preconditioner,parcsr_matrix,0,0);
263
264 xxraw = (double *)Malloc(n*sizeof(double), main);
265 yyraw = (double *)Malloc(n*sizeof(double), main);
266
267 HYPRE_IJVectorCreate(0, 0, n-1, &xxij);
268 HYPRE_IJVectorSetPrintLevel(xxij,10); /* Debug */
269 HYPRE_IJVectorSetObjectType(xxij, HYPRE_PARCSR);
270 HYPRE_IJVectorInitialize(xxij);
271 HYPRE_IJVectorAssemble(xxij);
272 HYPRE_IJVectorGetObject(xxij, (void **) &xx);
273
274 HYPRE_IJVectorCreate(0, 0, n-1, &yyij);
275 HYPRE_IJVectorSetPrintLevel(yyij,10); /* Debug */
276 HYPRE_IJVectorSetObjectType(yyij, HYPRE_PARCSR);
277 HYPRE_IJVectorInitialize(yyij);
278 }
279
281 { free(xxraw);
282 free(yyraw);
283 free(ixx);
284 HYPRE_EuclidDestroy(preconditioner);
285 HYPRE_IJMatrixDestroy(ij_matrix);
286 HYPRE_IJVectorDestroy(xxij);
287 HYPRE_IJVectorDestroy(yyij);
288 }
289
290 virtual void pre (domain_type&, range_type&) {}
291 virtual void post (domain_type&) {}
292
293 virtual void apply (domain_type& x, range_type const& y) {
294 /* set vector values */
295 y.write(yyraw);
296 HYPRE_IJVectorSetValues(yyij, n, ixx, yyraw);
297 HYPRE_IJVectorAssemble(yyij);
298 HYPRE_IJVectorGetObject(yyij, (void **) &yy);
299
300 HYPRE_EuclidSolve(preconditioner,parcsr_matrix,yy,xx);
301
302 HYPRE_IJVectorGetValues(xxij,n,ixx,xxraw);
303 x.read(xxraw);
304 }
305
311 virtual Dune::SolverCategory::Category category() const override
312 {
313 return Dune::SolverCategory::sequential;
314 }
315
316 private:
317 Op& op;
318 HYPRE_Solver preconditioner;
319 HYPRE_IJMatrix ij_matrix;
320 HYPRE_ParCSRMatrix parcsr_matrix;
321 HYPRE_IJVector xxij, yyij;
322 HYPRE_ParVector xx, yy;
323 int n;
324 double *xxraw, *yyraw;
325 int *ixx;
326 };
327
328} // namespace Kaskade
329#endif
virtual void apply(domain_type &x, range_type const &y)
Definition: hyprecond.hh:155
virtual void post(domain_type &)
Definition: hyprecond.hh:153
virtual void pre(domain_type &, range_type &)
Definition: hyprecond.hh:152
virtual Dune::SolverCategory::Category category() const override
returns the category of the operator
Definition: hyprecond.hh:185
BoomerAMG(Op &op, int steps_=1, int coarsentype=21, int interpoltype=0, double tol=1.0e-8, int cycleType=1, int relaxType=2, double strongThreshold=0.3, int variant=0, int overlap=1, int syseqn=1, int verbosity_=2)
Definition: hyprecond.hh:57
virtual void pre(domain_type &, range_type &)
Definition: hyprecond.hh:290
virtual void post(domain_type &)
Definition: hyprecond.hh:291
Euclid(Op &op, int level=1, double droptol=0.0, int printlevel=0, int bj=0, int verbosity=2)
Definition: hyprecond.hh:217
virtual void apply(domain_type &x, range_type const &y)
Definition: hyprecond.hh:293
virtual Dune::SolverCategory::Category category() const override
returns the category of the operator
Definition: hyprecond.hh:311
size_t nnz() const
Definition: triplet.hh:254
SparseIndexInt nrows() const
Returns number of rows (computes them, if not known)
Definition: triplet.hh:202
std::vector< SparseIndexInt > ridx
row indices
Definition: triplet.hh:669
std::vector< SparseIndexInt > cidx
column indices
Definition: triplet.hh:671
std::vector< Scalar > data
data
Definition: triplet.hh:673
void umfpack_triplet_to_col(int rows, int cols, std::vector< long > const &ridx, std::vector< long > const &cidx, std::vector< double > const &values, std::vector< long > &Ap, std::vector< long > &Ai, std::vector< double > &Az)
Triplet to compressed column storage conversion . This is just a frontent to DirectType::UMFPACK util...