4#ifndef HYPREINTERFACE_SEQUENTIAL_HH
5#define HYPREINTERFACE_SEQUENTIAL_HH
11#include <dune/common/parallel/communication.hh>
12#include <dune/common/parallel/mpihelper.hh>
13#include <dune/pdelab/gridoperator/gridoperator.hh>
14#include <dune/grid/common/indexidset.hh>
15#include <dune/grid/common/gridview.hh>
16#include <dune/istl/bcrsmatrix.hh>
17#include <dune/istl/solvers.hh>
20#include <HYPRE_IJ_mv.h>
21#include <HYPRE_parcsr_ls.h>
22#include <HYPRE_krylov.h>
24#include "globalDOFNumbering.hh"
29class SequentialHypreParameters {
86 double strongthreshold = 0.9;
101template <
typename GV,
typename Matrix,
typename U>
102class SequentialHypreSolver :
public Dune::PDELab::LinearResultStorage {
105 static constexpr int mBlock = Matrix::block_type::rows;
106 static constexpr int nBlock = Matrix::block_type::cols;
109 SequentialHypreSolver (GV& gv_, U& u_, Matrix& a_, U& b_,
110 const double tolerance_) :
113 tolerance(tolerance_),
115 ParCSRPCG_printlevel(0) {
116 SequentialHypreParameters hypre_param;
119 HYPRE_BoomerAMGCreate(&prec);
120 HYPRE_BoomerAMGSetTol(prec,0);
121 HYPRE_BoomerAMGSetMaxIter(prec,1);
123 HYPRE_BoomerAMGSetNumFunctions(prec, hypre_param.dim);
125 HYPRE_BoomerAMGSetInterpType(prec, hypre_param.interptype);
126 HYPRE_BoomerAMGSetPMaxElmts(prec, hypre_param.pmaxelmts);
127 HYPRE_BoomerAMGSetCoarsenType(prec, hypre_param.coarsentype);
128 HYPRE_BoomerAMGSetAggNumLevels(prec, hypre_param.aggnumlevels);
129 HYPRE_BoomerAMGSetRelaxType(prec, hypre_param.relaxtype);
130 HYPRE_BoomerAMGSetRelaxOrder(prec, hypre_param.relaxorder);
131 HYPRE_BoomerAMGSetMaxLevels (prec, hypre_param.maxlevel);
132 HYPRE_BoomerAMGSetCycleNumSweeps(prec, hypre_param.ncoarserelax,3);
133 HYPRE_BoomerAMGSetCycleRelaxType(prec, hypre_param.coarsesolver,3);
134 HYPRE_BoomerAMGSetPrintLevel(prec,hypre_param.printlevel);
135 HYPRE_BoomerAMGSetStrongThreshold(prec,hypre_param.strongthreshold);
137 HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD,&solver);
138 HYPRE_ParCSRPCGSetTol(solver,tolerance);
139 HYPRE_ParCSRPCGSetMaxIter(solver,maxiter);
140 HYPRE_ParCSRPCGSetPrintLevel(solver, ParCSRPCG_printlevel);
141 HYPRE_PCGSetTwoNorm(solver,1);
143 HYPRE_ParCSRPCGSetPrecond(solver,
144 HYPRE_BoomerAMGSolve,
145 HYPRE_BoomerAMGSetup,
149 MPI_Comm_split(gv.comm(), gv.comm().rank(), gv.comm().rank(), &row_comm);
152 AssembleHypreMatrix(a,a_hypre);
153 AssembleHypreVector(b,b_hypre);
154 AssembleHypreVector(u,u_hypre);
156 HYPRE_IJMatrixGetObject(a_hypre,(
void **) &a_parcsr);
157 HYPRE_IJVectorGetObject(b_hypre,(
void **) &b_parcsr);
158 HYPRE_IJVectorGetObject(u_hypre,(
void **) &u_parcsr);
162 ~SequentialHypreSolver() {
163 HYPRE_BoomerAMGDestroy(prec);
164 HYPRE_ParCSRPCGDestroy(solver);
165 HYPRE_IJVectorDestroy(b_hypre);
166 HYPRE_IJMatrixDestroy(a_hypre);
167 MPI_Comm_free(&row_comm);
176 HYPRE_ParCSRPCGSetup(solver, a_parcsr, b_parcsr, u_parcsr);
177 double timeBoomerAMGSetup = watch.elapsed();
178 timeBoomerAMGSetup = gv.comm().max(timeBoomerAMGSetup);
181 HYPRE_ParCSRPCGSolve(solver, a_parcsr, b_parcsr,u_parcsr);
182 double timeBoomerAMGSolve = watch.elapsed();
183 timeBoomerAMGSolve = gv.comm().max(timeBoomerAMGSolve);
184 MPI_Barrier(gv.comm());
187 ReadHypreVector(u_hypre,u);
188 HYPRE_IJVectorDestroy(u_hypre);
189 HYPRE_Int iterations;
191 HYPRE_ParCSRPCGGetNumIterations(solver,&iterations);
192 HYPRE_ParCSRPCGGetFinalRelativeResidualNorm(solver,&resreduction);
195 res.converged = (resreduction <= tolerance);
196 if (gv.comm().rank()==0)
197 std::cout <<
" Converged to " << resreduction <<
" in " << iterations <<
" iterations." << std::endl;
198 res.iterations = iterations;
199 res.reduction = resreduction;
200 res.elapsed = timeBoomerAMGSolve;
201 res.conv_rate = pow(resreduction,1./iterations);
205 double Tolerance()
const {
return tolerance; }
209 void AssembleHypreMatrix(
const Matrix& a, HYPRE_IJMatrix& hypre_matrix) {
210 HYPRE_Int ilower, iupper;
211 HYPRE_Int jlower, jupper;
213 iupper = nBlock*a.N();
217 HYPRE_IJMatrixCreate(row_comm,
221 HYPRE_IJMatrixSetObjectType(hypre_matrix, HYPRE_PARCSR);
222 HYPRE_IJMatrixInitialize(hypre_matrix);
223 using Dune::PDELab::Backend::native;
227 for (
auto row_iter = native(a).begin(); row_iter != native(a).end(); row_iter++) {
228 for (
auto col_iter = row_iter->begin(); col_iter != row_iter->end(); col_iter++) {
229 for(
int block_i = 0; block_i < mBlock; block_i++){
230 for(
int block_j = 0; block_j < mBlock; block_j++){
231 HYPRE_Int row_idx = mBlock*row_iter.index()+block_i;
232 HYPRE_Int col_idx = nBlock*col_iter.index()+block_j;
233 double value = (*col_iter)[block_i][block_j];
234 HYPRE_IJMatrixSetValues(hypre_matrix,nrows,&ncol,&row_idx,&col_idx,&value);
239 HYPRE_IJMatrixAssemble(hypre_matrix);
244void AssembleHypreVector(
const U& u, HYPRE_IJVector& u_hypre) {
246 HYPRE_Int jlower = 0;
247 HYPRE_Int jupper = nBlock*a.N();
248 HYPRE_IJVectorCreate(row_comm, jlower, jupper, &u_hypre);
249 HYPRE_IJVectorSetObjectType(u_hypre, HYPRE_PARCSR);
250 HYPRE_IJVectorInitialize(u_hypre);
251 using Dune::PDELab::Backend::native;
253 for (
unsigned int i = 0; i < u.N(); i++) {
254 for(
int block_i = 0; block_i < mBlock; block_i++){
255 HYPRE_Int indices = nBlock*i+block_i;
256 double values = native(u)[i][block_i];
257 HYPRE_IJVectorSetValues(u_hypre, nvalues, &indices, &values);
260 HYPRE_IJVectorAssemble(u_hypre);
266void ReadHypreVector(
const HYPRE_IJVector& u_hypre, U& u) {
269 using Dune::PDELab::Backend::native;
270 for (
unsigned int i = 0; i < u.N(); i++) {
271 for(
int block_i = 0; block_i < mBlock; block_i++){
272 HYPRE_Int indices = nBlock*i + block_i;
273 HYPRE_IJVectorGetValues(u_hypre, nvalues, &indices, &values);
274 native(u)[i][block_i] = values;
289int ParCSRPCG_printlevel;
293HYPRE_IJMatrix a_hypre;
294HYPRE_IJVector b_hypre;
295HYPRE_IJVector u_hypre;
300HYPRE_ParCSRMatrix a_parcsr;
301HYPRE_ParVector b_parcsr;
302HYPRE_ParVector u_parcsr;