4#ifndef HYPREINTERFACE_HH
5#define HYPREINTERFACE_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"
30class HypreParameters {
86 double strongthreshold = 0.75;
101template <
typename GFS,
typename Matrix,
typename U>
102class HypreSolver :
public Dune::PDELab::LinearResultStorage {
105 static constexpr int mBlock = Matrix::block_type::rows;
106 static constexpr int nBlock = Matrix::block_type::cols;
109 HypreSolver (
const GFS& gfs_, U& u_, Matrix& a_, U& b_,
110 const double tolerance_=1e-6) :
111 gfs(gfs_), u(u_), b(b_), a(a_),
113 tolerance(tolerance_),
115 ParCSRPCG_printlevel(3),
116 globalNumbering(gfs_) {
117 HypreParameters hypre_param;
120 HYPRE_BoomerAMGCreate(&prec);
121 HYPRE_BoomerAMGSetTol(prec,tolerance);
122 HYPRE_BoomerAMGSetMaxIter(prec,1);
124 HYPRE_BoomerAMGSetNumFunctions(prec, hypre_param.dim);
126 HYPRE_BoomerAMGSetInterpType(prec, hypre_param.interptype);
127 HYPRE_BoomerAMGSetPMaxElmts(prec, hypre_param.pmaxelmts);
128 HYPRE_BoomerAMGSetCoarsenType(prec, hypre_param.coarsentype);
129 HYPRE_BoomerAMGSetAggNumLevels(prec, hypre_param.aggnumlevels);
130 HYPRE_BoomerAMGSetRelaxType(prec, hypre_param.relaxtype);
131 HYPRE_BoomerAMGSetRelaxOrder(prec, hypre_param.relaxorder);
132 HYPRE_BoomerAMGSetMaxLevels (prec, hypre_param.maxlevel);
133 HYPRE_BoomerAMGSetCycleNumSweeps(prec, hypre_param.ncoarserelax,3);
134 HYPRE_BoomerAMGSetCycleRelaxType(prec, hypre_param.coarsesolver,3);
135 HYPRE_BoomerAMGSetPrintLevel(prec,hypre_param.printlevel);
136 HYPRE_BoomerAMGSetStrongThreshold(prec,hypre_param.strongthreshold);
138 HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD,&solver);
139 HYPRE_ParCSRPCGSetTol(solver,tolerance);
140 HYPRE_ParCSRPCGSetMaxIter(solver,maxiter);
141 HYPRE_ParCSRPCGSetPrintLevel(solver, ParCSRPCG_printlevel);
142 HYPRE_PCGSetTwoNorm(solver,1);
144 HYPRE_ParCSRPCGSetPrecond(solver,
145 HYPRE_BoomerAMGSolve,
146 HYPRE_BoomerAMGSetup,
152 HYPRE_BoomerAMGDestroy(prec);
153 HYPRE_ParCSRPCGDestroy(solver);
154 HYPRE_IJVectorDestroy(b_hypre);
155 HYPRE_IJMatrixDestroy(a_hypre);
163 AssembleHypreMatrix(a,a_hypre);
164 AssembleHypreVector(b,b_hypre);
165 HYPRE_IJVector u_hypre;
166 AssembleHypreVector(u,u_hypre);
167 if (gv.comm().rank()==0)
168 std::cout <<
" assembled hypre matrices" << std::endl;
170 HYPRE_ParCSRMatrix a_parcsr;
171 HYPRE_ParVector b_parcsr;
172 HYPRE_ParVector u_parcsr;
173 HYPRE_IJMatrixGetObject(a_hypre,(
void **) &a_parcsr);
174 HYPRE_IJVectorGetObject(b_hypre,(
void **) &b_parcsr);
175 HYPRE_IJVectorGetObject(u_hypre,(
void **) &u_parcsr);
176 if (gv.comm().rank()==0)
177 std::cout <<
" assembled parcrs hypre matrices" << std::endl;
181 HYPRE_ParCSRPCGSetup(solver, a_parcsr, b_parcsr, u_parcsr);
182 double timeBoomerAMGSetup = watch.elapsed();
183 timeBoomerAMGSetup = gv.comm().max(timeBoomerAMGSetup);
185 HYPRE_ParCSRPCGSolve(solver, a_parcsr, b_parcsr,u_parcsr);
186 double timeBoomerAMGSolve = watch.elapsed();
187 timeBoomerAMGSolve = gv.comm().max(timeBoomerAMGSolve);
190 ReadHypreVector(u_hypre,u);
191 HYPRE_IJVectorDestroy(u_hypre);
192 HYPRE_Int iterations;
194 HYPRE_ParCSRPCGGetNumIterations(solver,&iterations);
195 HYPRE_ParCSRPCGGetFinalRelativeResidualNorm(solver,&resreduction);
198 res.converged = (resreduction <= tolerance);
199 res.iterations = iterations;
200 res.reduction = resreduction;
201 res.elapsed = timeBoomerAMGSolve;
202 res.conv_rate = pow(resreduction,1./iterations);
207 void AssembleHypreMatrix(
const Matrix& a, HYPRE_IJMatrix& hypre_matrix) {
208 HYPRE_Int ilower, iupper;
209 HYPRE_Int jlower, jupper;
210 ilower = nBlock*globalNumbering.globalIndexOffset() ;
211 iupper = nBlock*(globalNumbering.globalIndexOffset() + globalNumbering.numberOfLocalDOFs()) -1;
214 HYPRE_IJMatrixCreate(gv.comm(),
218 HYPRE_IJMatrixSetObjectType(hypre_matrix, HYPRE_PARCSR);
219 HYPRE_IJMatrixInitialize(hypre_matrix);
220 using Dune::PDELab::Backend::native;
224 for (
auto row_iter = native(a).begin(); row_iter != native(a).end(); row_iter++) {
225 if(globalNumbering.claimedByRank(row_iter.index()) == gv.comm().rank()){
226 for (
auto col_iter = row_iter->begin(); col_iter != row_iter->end(); col_iter++) {
227 for(
int block_i = 0; block_i < mBlock; block_i++){
228 for(
int block_j = 0; block_j < mBlock; block_j++){
229 HYPRE_Int row_idx = mBlock*globalNumbering.globalIndex(row_iter.index())+block_i;
230 HYPRE_Int col_idx = nBlock*globalNumbering.globalIndex(col_iter.index())+block_j;
231 double value = (*col_iter)[block_i][block_j];
232 HYPRE_IJMatrixSetValues(hypre_matrix,nrows,&ncol,&row_idx,&col_idx,&value);
238 HYPRE_IJMatrixAssemble(hypre_matrix);
243void AssembleHypreVector(
const U& u, HYPRE_IJVector& u_hypre) {
245 HYPRE_Int jlower = nBlock*globalNumbering.globalIndexOffset();
246 HYPRE_Int jupper = nBlock*(globalNumbering.globalIndexOffset() + globalNumbering.numberOfLocalDOFs()) -1;
247 HYPRE_IJVectorCreate(gv.comm(), jlower, jupper, &u_hypre);
248 HYPRE_IJVectorSetObjectType(u_hypre, HYPRE_PARCSR);
249 HYPRE_IJVectorInitialize(u_hypre);
250 using Dune::PDELab::Backend::native;
252 for (
unsigned int i = 0; i < u.N(); i++) {
253 if(globalNumbering.claimedByRank(i) == gv.comm().rank()){
254 for(
int block_i = 0; block_i < mBlock; block_i++){
255 HYPRE_Int indices = nBlock*globalNumbering.globalIndex(i)+block_i;
256 double values = native(u)[i][block_i];
257 HYPRE_IJVectorSetValues(u_hypre, nvalues, &indices, &values);
261 HYPRE_IJVectorAssemble(u_hypre);
267void ReadHypreVector(
const HYPRE_IJVector& u_hypre, U& u) {
270 using Dune::PDELab::Backend::native;
271 for (
unsigned int i = 0; i < u.N(); i++) {
272 if(globalNumbering.claimedByRank(i) == gv.comm().rank()){
273 for(
int block_i = 0; block_i < mBlock; block_i++){
274 HYPRE_Int indices = nBlock*globalNumbering.globalIndex(i) + block_i;
275 HYPRE_IJVectorGetValues(u_hypre, nvalues, &indices, &values);
276 native(u)[i][block_i] = values;
279 for(
int block_i = 0; block_i < mBlock; block_i++){
280 native(u)[i][block_i] = 0.0;
284 Dune::PDELab::AddDataHandle<GFS,U> adddh(gfs,u);
285 gv.communicate(adddh,Dune::All_All_Interface,Dune::ForwardCommunication);
296typedef typename GFS::Traits::GridView GV;
301int ParCSRPCG_printlevel;
303GlobalNumbering<U, GFS> globalNumbering;
305HYPRE_IJMatrix a_hypre;
306HYPRE_IJVector b_hypre;