Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Ifpack2_Hypre_def.hpp
1 /*@HEADER
2 // ***********************************************************************
3 //
4 // Ifpack2: Templated Object-Oriented Algebraic Preconditioner Package
5 // Copyright (2009) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 //@HEADER
41 */
42 
43 #ifndef IFPACK2_HYPRE_DEF_HPP
44 #define IFPACK2_HYPRE_DEF_HPP
45 
46 #include "Ifpack2_Hypre_decl.hpp"
47 #if defined(HAVE_IFPACK2_HYPRE) && defined(HAVE_IFPACK2_MPI)
48 #include <stdexcept>
49 
50 #include "Tpetra_Import.hpp"
52 #include "Teuchos_RCP.hpp"
54 #include "HYPRE_IJ_mv.h"
55 #include "HYPRE_parcsr_ls.h"
56 #include "krylov.h"
57 #include "_hypre_parcsr_mv.h"
58 #include "_hypre_IJ_mv.h"
59 #include "HYPRE_parcsr_mv.h"
60 #include "HYPRE.h"
61 
62 
63 using Teuchos::RCP;
64 using Teuchos::rcp;
65 using Teuchos::rcpFromRef;
66 
67 
68 namespace Ifpack2 {
69 
70 template<class LocalOrdinal, class Node>
71 Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::
73  A_(A),
74  IsInitialized_(false),
75  IsComputed_(false), NumInitialize_(0),
76  NumCompute_(0),
77  NumApply_(0),
78  InitializeTime_(0.0),
79  ComputeTime_(0.0),
80  ApplyTime_(0.0),
81  HypreA_(0),
82  HypreG_(0),
83  xHypre_(0),
84  yHypre_(0),
85  zHypre_(0),
86  IsSolverCreated_(false),
87  IsPrecondCreated_(false),
88  SolveOrPrec_(Hypre_Is_Solver),
89  NumFunsToCall_(0),
90  SolverType_(PCG),
91  PrecondType_(Euclid),
92  UsePreconditioner_(false),
93  Dump_(false)
94 {
95  MPI_Comm comm = * (Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int> >(A->getRowMap()->getComm())->getRawMpiComm());
96 
97  // Check that RowMap and RangeMap are the same. While this could handle the
98  // case where RowMap and RangeMap are permutations, other Ifpack PCs don't
99  // handle this either.
100  if (!A_->getRowMap()->isSameAs(*A_->getRangeMap())) {
101  IFPACK2_CHK_ERRV(-1);
102  }
103  // Hypre expects the RowMap to be Linear.
104  if (A_->getRowMap()->isContiguous()) {
105  GloballyContiguousRowMap_ = A_->getRowMap();
106  GloballyContiguousColMap_ = A_->getColMap();
107  } else {
108  // Must create GloballyContiguous Maps for Hypre
109  if(A_->getDomainMap()->isSameAs(*A_->getRowMap())) {
110  Teuchos::RCP<const crs_matrix_type> Aconst = Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A_);
111  GloballyContiguousColMap_ = MakeContiguousColumnMap(Aconst);
112  GloballyContiguousRowMap_ = rcp(new map_type(A_->getRowMap()->getGlobalNumElements(),
113  A_->getRowMap()->getLocalNumElements(), 0, A_->getRowMap()->getComm()));
114  }
115  else {
116  throw std::runtime_error("Ifpack_Hypre: Unsupported map configuration: Row/Domain maps do not match");
117  }
118  }
119  // Next create vectors that will be used when ApplyInverse() is called
120  HYPRE_Int ilower = GloballyContiguousRowMap_->getMinGlobalIndex();
121  HYPRE_Int iupper = GloballyContiguousRowMap_->getMaxGlobalIndex();
122  // X in AX = Y
123  IFPACK2_CHK_ERRV(HYPRE_IJVectorCreate(comm, ilower, iupper, &XHypre_));
124  IFPACK2_CHK_ERRV(HYPRE_IJVectorSetObjectType(XHypre_, HYPRE_PARCSR));
125  IFPACK2_CHK_ERRV(HYPRE_IJVectorInitialize(XHypre_));
126  IFPACK2_CHK_ERRV(HYPRE_IJVectorAssemble(XHypre_));
127  IFPACK2_CHK_ERRV(HYPRE_IJVectorGetObject(XHypre_, (void**) &ParX_));
128  XVec_ = Teuchos::rcp((hypre_ParVector *) hypre_IJVectorObject(((hypre_IJVector *) XHypre_)),false);
129 
130  // Y in AX = Y
131  IFPACK2_CHK_ERRV(HYPRE_IJVectorCreate(comm, ilower, iupper, &YHypre_));
132  IFPACK2_CHK_ERRV(HYPRE_IJVectorSetObjectType(YHypre_, HYPRE_PARCSR));
133  IFPACK2_CHK_ERRV(HYPRE_IJVectorInitialize(YHypre_));
134  IFPACK2_CHK_ERRV(HYPRE_IJVectorAssemble(YHypre_));
135  IFPACK2_CHK_ERRV(HYPRE_IJVectorGetObject(YHypre_, (void**) &ParY_));
136  YVec_ = Teuchos::rcp((hypre_ParVector *) hypre_IJVectorObject(((hypre_IJVector *) YHypre_)),false);
137 
138  // Cache
139  VectorCache_.resize(A->getRowMap()->getLocalNumElements());
140 } //Constructor
141 
142 //==============================================================================
143 template<class LocalOrdinal, class Node>
144 Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::~Hypre() {
145  Destroy();
146 }
147 
148 //==============================================================================
149 template<class LocalOrdinal, class Node>
150 void Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Destroy(){
151  if(isInitialized()){
152  IFPACK2_CHK_ERRV(HYPRE_IJMatrixDestroy(HypreA_));
153  }
154  IFPACK2_CHK_ERRV(HYPRE_IJVectorDestroy(XHypre_));
155  IFPACK2_CHK_ERRV(HYPRE_IJVectorDestroy(YHypre_));
156  if(IsSolverCreated_){
157  IFPACK2_CHK_ERRV(SolverDestroyPtr_(Solver_));
158  }
159  if(IsPrecondCreated_){
160  IFPACK2_CHK_ERRV(PrecondDestroyPtr_(Preconditioner_));
161  }
162 
163  // Maxwell
164  if(HypreG_) {
165  IFPACK2_CHK_ERRV(HYPRE_IJMatrixDestroy(HypreG_));
166  }
167  if(xHypre_) {
168  IFPACK2_CHK_ERRV(HYPRE_IJVectorDestroy(xHypre_));
169  }
170  if(yHypre_) {
171  IFPACK2_CHK_ERRV(HYPRE_IJVectorDestroy(yHypre_));
172  }
173  if(zHypre_) {
174  IFPACK2_CHK_ERRV(HYPRE_IJVectorDestroy(zHypre_));
175  }
176 } //Destroy()
177 
178 //==============================================================================
179 template<class LocalOrdinal, class Node>
180 void Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::initialize(){
181  const std::string timerName ("Ifpack2::Hypre::initialize");
183  if (timer.is_null ()) timer = Teuchos::TimeMonitor::getNewCounter (timerName);
184 
185  if(IsInitialized_) return;
186  double startTime = timer->wallTime();
187  {
188  Teuchos::TimeMonitor timeMon (*timer);
189 
190  // set flags
191  IsInitialized_=true;
192  NumInitialize_++;
193  }
194  InitializeTime_ += (timer->wallTime() - startTime);
195 } //Initialize()
196 
197 //==============================================================================
198 template<class LocalOrdinal, class Node>
199 void Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::setParameters(const Teuchos::ParameterList& list){
200 
201  std::map<std::string, Hypre_Solver> solverMap;
202  solverMap["BoomerAMG"] = BoomerAMG;
203  solverMap["ParaSails"] = ParaSails;
204  solverMap["Euclid"] = Euclid;
205  solverMap["AMS"] = AMS;
206  solverMap["Hybrid"] = Hybrid;
207  solverMap["PCG"] = PCG;
208  solverMap["GMRES"] = GMRES;
209  solverMap["FlexGMRES"] = FlexGMRES;
210  solverMap["LGMRES"] = LGMRES;
211  solverMap["BiCGSTAB"] = BiCGSTAB;
212 
213  std::map<std::string, Hypre_Chooser> chooserMap;
214  chooserMap["Solver"] = Hypre_Is_Solver;
215  chooserMap["Preconditioner"] = Hypre_Is_Preconditioner;
216 
217  List_ = list;
218  Hypre_Solver solType;
219  if (list.isType<std::string>("hypre: Solver"))
220  solType = solverMap[list.get<std::string>("hypre: Solver")];
221  else if(list.isParameter("hypre: Solver"))
222  solType = (Hypre_Solver) list.get<int>("hypre: Solver");
223  else
224  solType = PCG;
225  SolverType_ = solType;
226  Hypre_Solver precType;
227  if (list.isType<std::string>("hypre: Preconditioner"))
228  precType = solverMap[list.get<std::string>("hypre: Preconditioner")];
229  else if(list.isParameter("hypre: Preconditioner"))
230  precType = (Hypre_Solver) list.get<int>("hypre: Preconditioner");
231  else
232  precType = Euclid;
233  PrecondType_ = precType;
234  Hypre_Chooser chooser;
235  if (list.isType<std::string>("hypre: SolveOrPrecondition"))
236  chooser = chooserMap[list.get<std::string>("hypre: SolveOrPrecondition")];
237  else if(list.isParameter("hypre: SolveOrPrecondition"))
238  chooser = (Hypre_Chooser) list.get<int>("hypre: SolveOrPrecondition");
239  else
240  chooser = Hypre_Is_Solver;
241  SolveOrPrec_ = chooser;
242  bool SetPrecond = list.isParameter("hypre: SetPreconditioner") ? list.get<bool>("hypre: SetPreconditioner") : false;
243  IFPACK2_CHK_ERR(SetParameter(SetPrecond));
244  int NumFunctions = list.isParameter("hypre: NumFunctions") ? list.get<int>("hypre: NumFunctions") : 0;
245  FunsToCall_.clear();
246  NumFunsToCall_ = 0;
247  if(NumFunctions > 0){
248  RCP<FunctionParameter>* params = list.get<RCP<FunctionParameter>*>("hypre: Functions");
249  for(int i = 0; i < NumFunctions; i++){
250  IFPACK2_CHK_ERR(AddFunToList(params[i]));
251  }
252  }
253 
254  if (list.isSublist("hypre: Solver functions")) {
255  Teuchos::ParameterList solverList = list.sublist("hypre: Solver functions");
256  for (auto it = solverList.begin(); it != solverList.end(); ++it) {
257  std::string funct_name = it->first;
258  if (it->second.isType<HYPRE_Int>()) {
259  IFPACK2_CHK_ERR(AddFunToList(rcp(new FunctionParameter(Hypre_Is_Solver, funct_name , Teuchos::getValue<HYPRE_Int>(it->second)))));
260  } else if (!std::is_same<HYPRE_Int,int>::value && it->second.isType<int>()) {
261  IFPACK2_CHK_ERR(AddFunToList(rcp(new FunctionParameter(Hypre_Is_Solver, funct_name , Teuchos::as<HYPRE_Int>(Teuchos::getValue<int>(it->second))))));
262  } else if (it->second.isType<HYPRE_Real>()) {
263  IFPACK2_CHK_ERR(AddFunToList(rcp(new FunctionParameter(Hypre_Is_Solver, funct_name , Teuchos::getValue<HYPRE_Real>(it->second)))));
264  } else {
265  IFPACK2_CHK_ERR(-1);
266  }
267  }
268  }
269 
270  if (list.isSublist("hypre: Preconditioner functions")) {
271  Teuchos::ParameterList precList = list.sublist("hypre: Preconditioner functions");
272  for (auto it = precList.begin(); it != precList.end(); ++it) {
273  std::string funct_name = it->first;
274  if (it->second.isType<HYPRE_Int>()) {
275  IFPACK2_CHK_ERR(AddFunToList(rcp(new FunctionParameter(Hypre_Is_Preconditioner, funct_name , Teuchos::getValue<HYPRE_Int>(it->second)))));
276  } else if (!std::is_same<HYPRE_Int,int>::value && it->second.isType<int>()) {
277  IFPACK2_CHK_ERR(AddFunToList(rcp(new FunctionParameter(Hypre_Is_Preconditioner, funct_name , Teuchos::as<HYPRE_Int>(Teuchos::getValue<int>(it->second))))));
278  } else if (it->second.isType<HYPRE_Real>()) {
279  IFPACK2_CHK_ERR(AddFunToList(rcp(new FunctionParameter(Hypre_Is_Preconditioner, funct_name , Teuchos::getValue<HYPRE_Real>(it->second)))));
280  } else if (it->second.isList()) {
281  Teuchos::ParameterList pl = Teuchos::getValue<Teuchos::ParameterList>(it->second);
282  if (FunctionParameter::isFuncIntInt(funct_name)) {
283  HYPRE_Int arg0 = pl.get<HYPRE_Int>("arg 0");
284  HYPRE_Int arg1 = pl.get<HYPRE_Int>("arg 1");
285  IFPACK2_CHK_ERR(AddFunToList(rcp(new FunctionParameter(Hypre_Is_Preconditioner, funct_name , arg0, arg1))));
286  } else if (FunctionParameter::isFuncIntIntDoubleDouble(funct_name)) {
287  HYPRE_Int arg0 = pl.get<HYPRE_Int>("arg 0");
288  HYPRE_Int arg1 = pl.get<HYPRE_Int>("arg 1");
289  HYPRE_Real arg2 = pl.get<HYPRE_Real>("arg 2");
290  HYPRE_Real arg3 = pl.get<HYPRE_Real>("arg 3");
291  IFPACK2_CHK_ERR(AddFunToList(rcp(new FunctionParameter(Hypre_Is_Preconditioner, funct_name , arg0, arg1, arg2, arg3))));
292  } else if (FunctionParameter::isFuncIntIntIntDoubleIntInt(funct_name)) {
293  HYPRE_Int arg0 = pl.get<HYPRE_Int>("arg 0");
294  HYPRE_Int arg1 = pl.get<HYPRE_Int>("arg 1");
295  HYPRE_Int arg2 = pl.get<HYPRE_Int>("arg 2");
296  HYPRE_Real arg3 = pl.get<HYPRE_Real>("arg 3");
297  HYPRE_Int arg4 = pl.get<HYPRE_Int>("arg 4");
298  HYPRE_Int arg5 = pl.get<HYPRE_Int>("arg 5");
299  IFPACK2_CHK_ERR(AddFunToList(rcp(new FunctionParameter(Hypre_Is_Preconditioner, funct_name , arg0, arg1, arg2, arg3, arg4, arg5))));
300  } else {
301  IFPACK2_CHK_ERR(-1);
302  }
303  }
304  }
305  }
306 
307  if (list.isSublist("Coordinates") && list.sublist("Coordinates").isType<Teuchos::RCP<multivector_type> >("Coordinates"))
308  Coords_ = list.sublist("Coordinates").get<Teuchos::RCP<multivector_type> >("Coordinates");
309  if (list.isSublist("Operators") && list.sublist("Operators").isType<Teuchos::RCP<const crs_matrix_type> >("G"))
310  G_ = list.sublist("Operators").get<Teuchos::RCP<const crs_matrix_type> >("G");
311 
312  Dump_ = list.isParameter("hypre: Dump") ? list.get<bool>("hypre: Dump") : false;
313 } //setParameters()
314 
315 //==============================================================================
316 template<class LocalOrdinal, class Node>
317 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::AddFunToList(RCP<FunctionParameter> NewFun){
318  NumFunsToCall_ = NumFunsToCall_+1;
319  FunsToCall_.resize(NumFunsToCall_);
320  FunsToCall_[NumFunsToCall_-1] = NewFun;
321  return 0;
322 } //AddFunToList()
323 
324 //==============================================================================
325 template<class LocalOrdinal, class Node>
326 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::SetParameter(Hypre_Chooser chooser, HYPRE_Int (*pt2Func)(HYPRE_Solver, HYPRE_Int), HYPRE_Int parameter){
327  RCP<FunctionParameter> temp = rcp(new FunctionParameter(chooser, pt2Func, parameter));
328  IFPACK2_CHK_ERR(AddFunToList(temp));
329  return 0;
330 } //SetParameter() - int function pointer
331 
332 //=============================================================================
333 template<class LocalOrdinal, class Node>
334 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::SetParameter(Hypre_Chooser chooser, HYPRE_Int (*pt2Func)(HYPRE_Solver, HYPRE_Real), HYPRE_Real parameter){
335  RCP<FunctionParameter> temp = rcp(new FunctionParameter(chooser, pt2Func, parameter));
336  IFPACK2_CHK_ERR(AddFunToList(temp));
337  return 0;
338 } //SetParameter() - double function pointer
339 
340 //==============================================================================
341 template<class LocalOrdinal, class Node>
342 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::SetParameter(Hypre_Chooser chooser, HYPRE_Int (*pt2Func)(HYPRE_Solver, HYPRE_Real, HYPRE_Int), HYPRE_Real parameter1, HYPRE_Int parameter2){
343  RCP<FunctionParameter> temp = rcp(new FunctionParameter(chooser, pt2Func, parameter1, parameter2));
344  IFPACK2_CHK_ERR(AddFunToList(temp));
345  return 0;
346 } //SetParameter() - double,int function pointer
347 
348 //==============================================================================
349 template<class LocalOrdinal, class Node>
350 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::SetParameter(Hypre_Chooser chooser, HYPRE_Int (*pt2Func)(HYPRE_Solver, HYPRE_Int, HYPRE_Real), HYPRE_Int parameter1, HYPRE_Real parameter2){
351  RCP<FunctionParameter> temp = rcp(new FunctionParameter(chooser, pt2Func, parameter1, parameter2));
352  IFPACK2_CHK_ERR(AddFunToList(temp));
353  return 0;
354 } //SetParameter() - int,double function pointer
355 
356 //==============================================================================
357 template<class LocalOrdinal, class Node>
358 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::SetParameter(Hypre_Chooser chooser, HYPRE_Int (*pt2Func)(HYPRE_Solver, HYPRE_Int, HYPRE_Int), HYPRE_Int parameter1, HYPRE_Int parameter2){
359  RCP<FunctionParameter> temp = rcp(new FunctionParameter(chooser, pt2Func, parameter1, parameter2));
360  IFPACK2_CHK_ERR(AddFunToList(temp));
361  return 0;
362 } //SetParameter() int,int function pointer
363 
364 //==============================================================================
365 template<class LocalOrdinal, class Node>
366 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::SetParameter(Hypre_Chooser chooser, HYPRE_Int (*pt2Func)(HYPRE_Solver, HYPRE_Real*), HYPRE_Real* parameter){
367  RCP<FunctionParameter> temp = rcp(new FunctionParameter(chooser, pt2Func, parameter));
368  IFPACK2_CHK_ERR(AddFunToList(temp));
369  return 0;
370 } //SetParameter() - double* function pointer
371 
372 //==============================================================================
373 template<class LocalOrdinal, class Node>
374 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::SetParameter(Hypre_Chooser chooser, HYPRE_Int (*pt2Func)(HYPRE_Solver, HYPRE_Int*), HYPRE_Int* parameter){
375  RCP<FunctionParameter> temp = rcp(new FunctionParameter(chooser, pt2Func, parameter));
376  IFPACK2_CHK_ERR(AddFunToList(temp));
377  return 0;
378 } //SetParameter() - int* function pointer
379 
380 //==============================================================================
381 template<class LocalOrdinal, class Node>
382 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::SetParameter(Hypre_Chooser chooser, HYPRE_Int (*pt2Func)(HYPRE_Solver, HYPRE_Int**), HYPRE_Int** parameter){
383  RCP<FunctionParameter> temp = rcp(new FunctionParameter(chooser, pt2Func, parameter));
384  IFPACK2_CHK_ERR(AddFunToList(temp));
385  return 0;
386 } //SetParameter() - int** function pointer
387 
388 //==============================================================================
389 template<class LocalOrdinal, class Node>
390 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::SetParameter(Hypre_Chooser chooser, Hypre_Solver solver){
391  if(chooser == Hypre_Is_Solver){
392  SolverType_ = solver;
393  } else {
394  PrecondType_ = solver;
395  }
396  return 0;
397 } //SetParameter() - set type of solver
398 
399 //==============================================================================
400 template<class LocalOrdinal, class Node>
401 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::SetDiscreteGradient(Teuchos::RCP<const crs_matrix_type> G){
402  using LO = local_ordinal_type;
403  using GO = global_ordinal_type;
404  // using SC = scalar_type;
405 
406  // Sanity check
407  if(!A_->getRowMap()->isSameAs(*G->getRowMap()))
408  throw std::runtime_error("Hypre<Tpetra::RowMatrix<double, HYPRE_Int, long long, Node>: Edge map mismatch: A and discrete gradient");
409 
410  // Get the maps for the nodes (assuming the edge map from A is OK);
411  GloballyContiguousNodeRowMap_ = rcp(new map_type(G->getDomainMap()->getGlobalNumElements(),
412  G->getDomainMap()->getLocalNumElements(), 0, A_->getRowMap()->getComm()));
413  GloballyContiguousNodeColMap_ = MakeContiguousColumnMap(G);
414 
415  // Start building G
416  MPI_Comm comm = * (Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int> >(A_->getRowMap()->getComm())->getRawMpiComm());
417  GO ilower = GloballyContiguousRowMap_->getMinGlobalIndex();
418  GO iupper = GloballyContiguousRowMap_->getMaxGlobalIndex();
419  GO jlower = GloballyContiguousNodeRowMap_->getMinGlobalIndex();
420  GO jupper = GloballyContiguousNodeRowMap_->getMaxGlobalIndex();
421  IFPACK2_CHK_ERR(HYPRE_IJMatrixCreate(comm, ilower, iupper, jlower, jupper, &HypreG_));
422  IFPACK2_CHK_ERR(HYPRE_IJMatrixSetObjectType(HypreG_, HYPRE_PARCSR));
423  IFPACK2_CHK_ERR(HYPRE_IJMatrixInitialize(HypreG_));
424 
425  std::vector<GO> new_indices(G->getLocalMaxNumRowEntries());
426  for(LO i = 0; i < (LO)G->getLocalNumRows(); i++){
427  typename crs_matrix_type::values_host_view_type values;
428  typename crs_matrix_type::local_inds_host_view_type indices;
429  G->getLocalRowView(i, indices, values);
430  for(LO j = 0; j < (LO) indices.extent(0); j++){
431  new_indices[j] = GloballyContiguousNodeColMap_->getGlobalElement(indices(j));
432  }
433  GO GlobalRow[1];
434  GO numEntries = (GO) indices.extent(0);
435  GlobalRow[0] = GloballyContiguousRowMap_->getGlobalElement(i);
436  IFPACK2_CHK_ERR(HYPRE_IJMatrixSetValues(HypreG_, 1, &numEntries, GlobalRow, new_indices.data(), values.data()));
437  }
438  IFPACK2_CHK_ERR(HYPRE_IJMatrixAssemble(HypreG_));
439  IFPACK2_CHK_ERR(HYPRE_IJMatrixGetObject(HypreG_, (void**)&ParMatrixG_));
440 
441  if (Dump_)
442  HYPRE_ParCSRMatrixPrint(ParMatrixG_,"G.mat");
443 
444  if(SolverType_ == AMS)
445  HYPRE_AMSSetDiscreteGradient(Solver_, ParMatrixG_);
446  if(PrecondType_ == AMS)
447  HYPRE_AMSSetDiscreteGradient(Preconditioner_, ParMatrixG_);
448  return 0;
449 } //SetDiscreteGradient()
450 
451 //==============================================================================
452 template<class LocalOrdinal, class Node>
453 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::SetCoordinates(Teuchos::RCP<multivector_type> coords) {
454 
455  if(!G_.is_null() && !G_->getDomainMap()->isSameAs(*coords->getMap()))
456  throw std::runtime_error("Hypre<Tpetra::RowMatrix<double, HYPRE_Int, long long, Node>: Node map mismatch: G->DomainMap() and coords");
457 
458  if(SolverType_ != AMS && PrecondType_ != AMS)
459  return 0;
460 
461  scalar_type *xPtr = coords->getDataNonConst(0).getRawPtr();
462  scalar_type *yPtr = coords->getDataNonConst(1).getRawPtr();
463  scalar_type *zPtr = coords->getDataNonConst(2).getRawPtr();
464 
465  MPI_Comm comm = * (Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int> >(A_->getRowMap()->getComm())->getRawMpiComm());
466  local_ordinal_type NumEntries = coords->getLocalLength();
467  global_ordinal_type * indices = const_cast<global_ordinal_type*>(GloballyContiguousNodeRowMap_->getLocalElementList().getRawPtr());
468 
469  global_ordinal_type ilower = GloballyContiguousNodeRowMap_->getMinGlobalIndex();
470  global_ordinal_type iupper = GloballyContiguousNodeRowMap_->getMaxGlobalIndex();
471 
472  if( NumEntries != iupper-ilower+1) {
473  std::cout<<"Ifpack2::Hypre::SetCoordinates(): Error on rank "<<A_->getRowMap()->getComm()->getRank()<<": MyLength = "<<coords->getLocalLength()<<" GID range = ["<<ilower<<","<<iupper<<"]"<<std::endl;
474  throw std::runtime_error("Hypre<Tpetra::RowMatrix<double, HYPRE_Int, long long, Node>: SetCoordinates: Length mismatch");
475  }
476 
477  IFPACK2_CHK_ERR(HYPRE_IJVectorCreate(comm, ilower, iupper, &xHypre_));
478  IFPACK2_CHK_ERR(HYPRE_IJVectorSetObjectType(xHypre_, HYPRE_PARCSR));
479  IFPACK2_CHK_ERR(HYPRE_IJVectorInitialize(xHypre_));
480  IFPACK2_CHK_ERR(HYPRE_IJVectorSetValues(xHypre_,NumEntries,indices,xPtr));
481  IFPACK2_CHK_ERR(HYPRE_IJVectorAssemble(xHypre_));
482  IFPACK2_CHK_ERR(HYPRE_IJVectorGetObject(xHypre_, (void**) &xPar_));
483 
484  IFPACK2_CHK_ERR(HYPRE_IJVectorCreate(comm, ilower, iupper, &yHypre_));
485  IFPACK2_CHK_ERR(HYPRE_IJVectorSetObjectType(yHypre_, HYPRE_PARCSR));
486  IFPACK2_CHK_ERR(HYPRE_IJVectorInitialize(yHypre_));
487  IFPACK2_CHK_ERR(HYPRE_IJVectorSetValues(yHypre_,NumEntries,indices,yPtr));
488  IFPACK2_CHK_ERR(HYPRE_IJVectorAssemble(yHypre_));
489  IFPACK2_CHK_ERR(HYPRE_IJVectorGetObject(yHypre_, (void**) &yPar_));
490 
491  IFPACK2_CHK_ERR(HYPRE_IJVectorCreate(comm, ilower, iupper, &zHypre_));
492  IFPACK2_CHK_ERR(HYPRE_IJVectorSetObjectType(zHypre_, HYPRE_PARCSR));
493  IFPACK2_CHK_ERR(HYPRE_IJVectorInitialize(zHypre_));
494  IFPACK2_CHK_ERR(HYPRE_IJVectorSetValues(zHypre_,NumEntries,indices,zPtr));
495  IFPACK2_CHK_ERR(HYPRE_IJVectorAssemble(zHypre_));
496  IFPACK2_CHK_ERR(HYPRE_IJVectorGetObject(zHypre_, (void**) &zPar_));
497 
498  if (Dump_) {
499  HYPRE_ParVectorPrint(xPar_,"coordX.dat");
500  HYPRE_ParVectorPrint(yPar_,"coordY.dat");
501  HYPRE_ParVectorPrint(zPar_,"coordZ.dat");
502  }
503 
504  if(SolverType_ == AMS)
505  HYPRE_AMSSetCoordinateVectors(Solver_, xPar_, yPar_, zPar_);
506  if(PrecondType_ == AMS)
507  HYPRE_AMSSetCoordinateVectors(Preconditioner_, xPar_, yPar_, zPar_);
508 
509  return 0;
510 
511 } //SetCoordinates
512 
513 //==============================================================================
514 template<class LocalOrdinal, class Node>
515 void Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::compute(){
516  const std::string timerName ("Ifpack2::Hypre::compute");
518  if (timer.is_null ()) timer = Teuchos::TimeMonitor::getNewCounter (timerName);
519  double startTime = timer->wallTime();
520  // Start timing here.
521  {
522  Teuchos::TimeMonitor timeMon (*timer);
523 
524  if(isInitialized() == false){
525  initialize();
526  }
527 
528  // Create the Hypre matrix and copy values. Note this uses values (which
529  // Initialize() shouldn't do) but it doesn't care what they are (for
530  // instance they can be uninitialized data even). It should be possible to
531  // set the Hypre structure without copying values, but this is the easiest
532  // way to get the structure.
533  MPI_Comm comm = * (Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int> >(A_->getRowMap()->getComm())->getRawMpiComm());
534  global_ordinal_type ilower = GloballyContiguousRowMap_->getMinGlobalIndex();
535  global_ordinal_type iupper = GloballyContiguousRowMap_->getMaxGlobalIndex();
536  IFPACK2_CHK_ERR(HYPRE_IJMatrixCreate(comm, ilower, iupper, ilower, iupper, &HypreA_));
537  IFPACK2_CHK_ERR(HYPRE_IJMatrixSetObjectType(HypreA_, HYPRE_PARCSR));
538  IFPACK2_CHK_ERR(HYPRE_IJMatrixInitialize(HypreA_));
539  CopyTpetraToHypre();
540  if(SolveOrPrec_ == Hypre_Is_Solver) {
541  IFPACK2_CHK_ERR(SetSolverType(SolverType_));
542  if (SolverPrecondPtr_ != NULL && UsePreconditioner_) {
543  // both method allows a PC (first condition) and the user wants a PC (second)
544  IFPACK2_CHK_ERR(SetPrecondType(PrecondType_));
545  CallFunctions();
546  IFPACK2_CHK_ERR(SolverPrecondPtr_(Solver_, PrecondSolvePtr_, PrecondSetupPtr_, Preconditioner_));
547  } else {
548  CallFunctions();
549  }
550  } else {
551  IFPACK2_CHK_ERR(SetPrecondType(PrecondType_));
552  CallFunctions();
553  }
554 
555  if (!G_.is_null()) {
556  SetDiscreteGradient(G_);
557  }
558 
559  if (!Coords_.is_null()) {
560  SetCoordinates(Coords_);
561  }
562 
563  // Hypre Setup must be called after matrix has values
564  if(SolveOrPrec_ == Hypre_Is_Solver){
565  IFPACK2_CHK_ERR(SolverSetupPtr_(Solver_, ParMatrix_, ParX_, ParY_));
566  } else {
567  IFPACK2_CHK_ERR(PrecondSetupPtr_(Preconditioner_, ParMatrix_, ParX_, ParY_));
568  }
569 
570  IsComputed_ = true;
571  NumCompute_++;
572  }
573 
574  ComputeTime_ += (timer->wallTime() - startTime);
575 } //Compute()
576 
577 //==============================================================================
578 template<class LocalOrdinal, class Node>
579 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::CallFunctions() const{
580  for(int i = 0; i < NumFunsToCall_; i++){
581  IFPACK2_CHK_ERR(FunsToCall_[i]->CallFunction(Solver_, Preconditioner_));
582  }
583  return 0;
584 } //CallFunctions()
585 
586 //==============================================================================
587 template<class LocalOrdinal, class Node>
588 void Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::apply (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
589  Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
590  Teuchos::ETransp mode,
591  scalar_type alpha,
592  scalar_type beta) const {
593  using LO = local_ordinal_type;
594  using SC = scalar_type;
595  const std::string timerName ("Ifpack2::Hypre::apply");
597  if (timer.is_null ()) timer = Teuchos::TimeMonitor::getNewCounter (timerName);
598  double startTime = timer->wallTime();
599  // Start timing here.
600  {
601  Teuchos::TimeMonitor timeMon (*timer);
602 
603  if(isComputed() == false){
604  IFPACK2_CHK_ERR(-1);
605  }
606  hypre_Vector *XLocal_ = hypre_ParVectorLocalVector(XVec_);
607  hypre_Vector *YLocal_ = hypre_ParVectorLocalVector(YVec_);
608  bool SameVectors = false;
609  size_t NumVectors = X.getNumVectors();
610  if (NumVectors != Y.getNumVectors()) IFPACK2_CHK_ERR(-1); // X and Y must have same number of vectors
611  if(&X == &Y) { //FIXME: Maybe not the right way to check this
612  SameVectors = true;
613  }
614 
615  // NOTE: Here were assuming that the local ordering of Epetra's X/Y-vectors and
616  // Hypre's X/Y-vectors are the same. Seeing as as this is more or less how we constructed
617  // the Hypre matrices, this seems pretty reasoanble.
618 
619  for(int VecNum = 0; VecNum < (int) NumVectors; VecNum++) {
620  //Get values for current vector in multivector.
621  // FIXME amk Nov 23, 2015: This will not work for funky data layouts
622  SC * XValues = const_cast<SC*>(X.getData(VecNum).getRawPtr());
623  SC * YValues;
624  if(!SameVectors){
625  YValues = const_cast<SC*>(Y.getData(VecNum).getRawPtr());
626  } else {
627  YValues = VectorCache_.getRawPtr();
628  }
629  // Temporarily make a pointer to data in Hypre for end
630  SC *XTemp = XLocal_->data;
631  // Replace data in Hypre vectors with Epetra data
632  XLocal_->data = XValues;
633  SC *YTemp = YLocal_->data;
634  YLocal_->data = YValues;
635 
636  IFPACK2_CHK_ERR(HYPRE_ParVectorSetConstantValues(ParY_, 0.0));
637  if(SolveOrPrec_ == Hypre_Is_Solver){
638  // Use the solver methods
639  IFPACK2_CHK_ERR(SolverSolvePtr_(Solver_, ParMatrix_, ParX_, ParY_));
640  } else {
641  // Apply the preconditioner
642  IFPACK2_CHK_ERR(PrecondSolvePtr_(Preconditioner_, ParMatrix_, ParX_, ParY_));
643  }
644 
645  if(SameVectors){
646  Teuchos::ArrayView<SC> Yv = Y.getDataNonConst(VecNum)();
647  LO NumEntries = Y.getLocalLength();
648  for(LO i = 0; i < NumEntries; i++)
649  Yv[i] = YValues[i];
650  }
651  XLocal_->data = XTemp;
652  YLocal_->data = YTemp;
653  }
654  NumApply_++;
655  }
656  ApplyTime_ += (timer->wallTime() - startTime);
657 } //apply()
658 
659 
660 //==============================================================================
661 template<class LocalOrdinal, class Node>
662 void Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::applyMat (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
663  Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
664  Teuchos::ETransp mode) const {
665  A_->apply(X,Y,mode);
666 } //applyMat()
667 
668 //==============================================================================
669 template<class LocalOrdinal, class Node>
670 std::string Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::description() const {
671  std::ostringstream out;
672 
673  // Output is a valid YAML dictionary in flow style. If you don't
674  // like everything on a single line, you should call describe()
675  // instead.
676  out << "\"Ifpack2::Hypre\": {";
677  out << "Initialized: " << (isInitialized () ? "true" : "false") << ", "
678  << "Computed: " << (isComputed () ? "true" : "false") << ", ";
679 
680  if (A_.is_null ()) {
681  out << "Matrix: null";
682  }
683  else {
684  out << "Global matrix dimensions: ["
685  << A_->getGlobalNumRows () << ", "
686  << A_->getGlobalNumCols () << "]"
687  << ", Global nnz: " << A_->getGlobalNumEntries();
688  }
689 
690  out << "}";
691  return out.str ();
692 } //description()
693 
694 //==============================================================================
695 template<class LocalOrdinal, class Node>
696 void Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::describe(Teuchos::FancyOStream &os, const Teuchos::EVerbosityLevel verbLevel) const {
697  using std::endl;
698  os << endl;
699  os << "================================================================================" << endl;
700  os << "Ifpack2::Hypre: " << endl << endl;
701  os << "Using " << A_->getComm()->getSize() << " processors." << endl;
702  os << "Global number of rows = " << A_->getGlobalNumRows() << endl;
703  os << "Global number of nonzeros = " << A_->getGlobalNumEntries() << endl;
704  // os << "Condition number estimate = " << Condest() << endl;
705  os << endl;
706  os << "Phase # calls Total Time (s)"<<endl;
707  os << "----- ------- --------------"<<endl;
708  os << "Initialize() " << std::setw(5) << NumInitialize_
709  << " " << std::setw(15) << InitializeTime_<<endl;
710  os << "Compute() " << std::setw(5) << NumCompute_
711  << " " << std::setw(15) << ComputeTime_ << endl;
712  os << "ApplyInverse() " << std::setw(5) << NumApply_
713  << " " << std::setw(15) << ApplyTime_ <<endl;
714  os << "================================================================================" << endl;
715  os << endl;
716 } //description
717 
718 //==============================================================================
719 template<class LocalOrdinal, class Node>
720 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::SetSolverType(Hypre_Solver Solver){
721  switch(Solver) {
722  case BoomerAMG:
723  if(IsSolverCreated_){
724  SolverDestroyPtr_(Solver_);
725  IsSolverCreated_ = false;
726  }
727  SolverCreatePtr_ = &Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_BoomerAMGCreate;
728  SolverDestroyPtr_ = &HYPRE_BoomerAMGDestroy;
729  SolverSetupPtr_ = &HYPRE_BoomerAMGSetup;
730  SolverPrecondPtr_ = NULL;
731  SolverSolvePtr_ = &HYPRE_BoomerAMGSolve;
732  break;
733  case AMS:
734  if(IsSolverCreated_){
735  SolverDestroyPtr_(Solver_);
736  IsSolverCreated_ = false;
737  }
738  SolverCreatePtr_ = &Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_AMSCreate;
739  SolverDestroyPtr_ = &HYPRE_AMSDestroy;
740  SolverSetupPtr_ = &HYPRE_AMSSetup;
741  SolverSolvePtr_ = &HYPRE_AMSSolve;
742  SolverPrecondPtr_ = NULL;
743  break;
744  case Hybrid:
745  if(IsSolverCreated_){
746  SolverDestroyPtr_(Solver_);
747  IsSolverCreated_ = false;
748  }
749  SolverCreatePtr_ = &Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParCSRHybridCreate;
750  SolverDestroyPtr_ = &HYPRE_ParCSRHybridDestroy;
751  SolverSetupPtr_ = &HYPRE_ParCSRHybridSetup;
752  SolverSolvePtr_ = &HYPRE_ParCSRHybridSolve;
753  SolverPrecondPtr_ = &HYPRE_ParCSRHybridSetPrecond;
754  break;
755  case PCG:
756  if(IsSolverCreated_){
757  SolverDestroyPtr_(Solver_);
758  IsSolverCreated_ = false;
759  }
760  SolverCreatePtr_ = &Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParCSRPCGCreate;
761  SolverDestroyPtr_ = &HYPRE_ParCSRPCGDestroy;
762  SolverSetupPtr_ = &HYPRE_ParCSRPCGSetup;
763  SolverSolvePtr_ = &HYPRE_ParCSRPCGSolve;
764  SolverPrecondPtr_ = &HYPRE_ParCSRPCGSetPrecond;
765  break;
766  case GMRES:
767  if(IsSolverCreated_){
768  SolverDestroyPtr_(Solver_);
769  IsSolverCreated_ = false;
770  }
771  SolverCreatePtr_ = &Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParCSRGMRESCreate;
772  SolverDestroyPtr_ = &HYPRE_ParCSRGMRESDestroy;
773  SolverSetupPtr_ = &HYPRE_ParCSRGMRESSetup;
774  SolverPrecondPtr_ = &HYPRE_ParCSRGMRESSetPrecond;
775  break;
776  case FlexGMRES:
777  if(IsSolverCreated_){
778  SolverDestroyPtr_(Solver_);
779  IsSolverCreated_ = false;
780  }
781  SolverCreatePtr_ = &Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParCSRFlexGMRESCreate;
782  SolverDestroyPtr_ = &HYPRE_ParCSRFlexGMRESDestroy;
783  SolverSetupPtr_ = &HYPRE_ParCSRFlexGMRESSetup;
784  SolverSolvePtr_ = &HYPRE_ParCSRFlexGMRESSolve;
785  SolverPrecondPtr_ = &HYPRE_ParCSRFlexGMRESSetPrecond;
786  break;
787  case LGMRES:
788  if(IsSolverCreated_){
789  SolverDestroyPtr_(Solver_);
790  IsSolverCreated_ = false;
791  }
792  SolverCreatePtr_ = &Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParCSRLGMRESCreate;
793  SolverDestroyPtr_ = &HYPRE_ParCSRLGMRESDestroy;
794  SolverSetupPtr_ = &HYPRE_ParCSRLGMRESSetup;
795  SolverSolvePtr_ = &HYPRE_ParCSRLGMRESSolve;
796  SolverPrecondPtr_ = &HYPRE_ParCSRLGMRESSetPrecond;
797  break;
798  case BiCGSTAB:
799  if(IsSolverCreated_){
800  SolverDestroyPtr_(Solver_);
801  IsSolverCreated_ = false;
802  }
803  SolverCreatePtr_ = &Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParCSRBiCGSTABCreate;
804  SolverDestroyPtr_ = &HYPRE_ParCSRBiCGSTABDestroy;
805  SolverSetupPtr_ = &HYPRE_ParCSRBiCGSTABSetup;
806  SolverSolvePtr_ = &HYPRE_ParCSRBiCGSTABSolve;
807  SolverPrecondPtr_ = &HYPRE_ParCSRBiCGSTABSetPrecond;
808  break;
809  default:
810  return -1;
811  }
812  CreateSolver();
813  return 0;
814 } //SetSolverType()
815 
816 //==============================================================================
817 template<class LocalOrdinal, class Node>
818 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::SetPrecondType(Hypre_Solver Precond){
819  switch(Precond) {
820  case BoomerAMG:
821  if(IsPrecondCreated_){
822  PrecondDestroyPtr_(Preconditioner_);
823  IsPrecondCreated_ = false;
824  }
825  PrecondCreatePtr_ = &Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_BoomerAMGCreate;
826  PrecondDestroyPtr_ = &HYPRE_BoomerAMGDestroy;
827  PrecondSetupPtr_ = &HYPRE_BoomerAMGSetup;
828  PrecondSolvePtr_ = &HYPRE_BoomerAMGSolve;
829  break;
830  case ParaSails:
831  if(IsPrecondCreated_){
832  PrecondDestroyPtr_(Preconditioner_);
833  IsPrecondCreated_ = false;
834  }
835  PrecondCreatePtr_ = &Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParaSailsCreate;
836  PrecondDestroyPtr_ = &HYPRE_ParaSailsDestroy;
837  PrecondSetupPtr_ = &HYPRE_ParaSailsSetup;
838  PrecondSolvePtr_ = &HYPRE_ParaSailsSolve;
839  break;
840  case Euclid:
841  if(IsPrecondCreated_){
842  PrecondDestroyPtr_(Preconditioner_);
843  IsPrecondCreated_ = false;
844  }
845  PrecondCreatePtr_ = &Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_EuclidCreate;
846  PrecondDestroyPtr_ = &HYPRE_EuclidDestroy;
847  PrecondSetupPtr_ = &HYPRE_EuclidSetup;
848  PrecondSolvePtr_ = &HYPRE_EuclidSolve;
849  break;
850  case AMS:
851  if(IsPrecondCreated_){
852  PrecondDestroyPtr_(Preconditioner_);
853  IsPrecondCreated_ = false;
854  }
855  PrecondCreatePtr_ = &Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_AMSCreate;
856  PrecondDestroyPtr_ = &HYPRE_AMSDestroy;
857  PrecondSetupPtr_ = &HYPRE_AMSSetup;
858  PrecondSolvePtr_ = &HYPRE_AMSSolve;
859  break;
860  default:
861  return -1;
862  }
863  CreatePrecond();
864  return 0;
865 
866 } //SetPrecondType()
867 
868 //==============================================================================
869 template<class LocalOrdinal, class Node>
870 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::CreateSolver(){
871  MPI_Comm comm;
872  HYPRE_ParCSRMatrixGetComm(ParMatrix_, &comm);
873  int ierr = (this->*SolverCreatePtr_)(comm, &Solver_);
874  IsSolverCreated_ = true;
875  return ierr;
876 } //CreateSolver()
877 
878 //==============================================================================
879 template<class LocalOrdinal, class Node>
880 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::CreatePrecond(){
881  MPI_Comm comm;
882  HYPRE_ParCSRMatrixGetComm(ParMatrix_, &comm);
883  int ierr = (this->*PrecondCreatePtr_)(comm, &Preconditioner_);
884  IsPrecondCreated_ = true;
885  return ierr;
886 } //CreatePrecond()
887 
888 
889 //==============================================================================
890 template<class LocalOrdinal, class Node>
891 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::CopyTpetraToHypre(){
892  using LO = local_ordinal_type;
893  using GO = global_ordinal_type;
894  // using SC = scalar_type;
895 
896  Teuchos::RCP<const crs_matrix_type> Matrix = Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A_);
897  if(Matrix.is_null())
898  throw std::runtime_error("Hypre<Tpetra::RowMatrix<double, LocalOrdinal, HYPRE_Int, Node>: Unsupported matrix configuration: Tpetra::CrsMatrix required");
899 
900  std::vector<HYPRE_Int> new_indices(Matrix->getLocalMaxNumRowEntries());
901  for(LO i = 0; i < (LO) Matrix->getLocalNumRows(); i++){
902  typename crs_matrix_type::values_host_view_type values;
903  typename crs_matrix_type::local_inds_host_view_type indices;
904  Matrix->getLocalRowView(i, indices, values);
905  for(LO j = 0; j < (LO)indices.extent(0); j++){
906  new_indices[j] = GloballyContiguousColMap_->getGlobalElement(indices(j));
907  }
908  HYPRE_Int GlobalRow[1];
909  HYPRE_Int numEntries = (GO) indices.extent(0);
910  GlobalRow[0] = GloballyContiguousRowMap_->getGlobalElement(i);
911  IFPACK2_CHK_ERR(HYPRE_IJMatrixSetValues(HypreA_, 1, &numEntries, GlobalRow, new_indices.data(), values.data()));
912  }
913  IFPACK2_CHK_ERR(HYPRE_IJMatrixAssemble(HypreA_));
914  IFPACK2_CHK_ERR(HYPRE_IJMatrixGetObject(HypreA_, (void**)&ParMatrix_));
915  if (Dump_)
916  HYPRE_ParCSRMatrixPrint(ParMatrix_,"A.mat");
917  return 0;
918 } //CopyTpetraToHypre()
919 
920 //==============================================================================
921 template<class LocalOrdinal, class Node>
922 HYPRE_Int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_BoomerAMGCreate(MPI_Comm /*comm*/, HYPRE_Solver *solver)
923  { return HYPRE_BoomerAMGCreate(solver);}
924 
925 //==============================================================================
926 template<class LocalOrdinal, class Node>
927 HYPRE_Int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParaSailsCreate(MPI_Comm comm, HYPRE_Solver *solver)
928  { return HYPRE_ParaSailsCreate(comm, solver);}
929 
930 //==============================================================================
931 template<class LocalOrdinal, class Node>
932 HYPRE_Int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_EuclidCreate(MPI_Comm comm, HYPRE_Solver *solver)
933  { return HYPRE_EuclidCreate(comm, solver);}
934 
935 //==============================================================================
936 template<class LocalOrdinal, class Node>
937 HYPRE_Int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_AMSCreate(MPI_Comm /*comm*/, HYPRE_Solver *solver)
938  { return HYPRE_AMSCreate(solver);}
939 
940 //==============================================================================
941 template<class LocalOrdinal, class Node>
942 HYPRE_Int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParCSRHybridCreate(MPI_Comm /*comm*/, HYPRE_Solver *solver)
943  { return HYPRE_ParCSRHybridCreate(solver);}
944 
945 //==============================================================================
946 template<class LocalOrdinal, class Node>
947 HYPRE_Int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParCSRPCGCreate(MPI_Comm comm, HYPRE_Solver *solver)
948  { return HYPRE_ParCSRPCGCreate(comm, solver);}
949 
950 //==============================================================================
951 template<class LocalOrdinal, class Node>
952 HYPRE_Int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParCSRGMRESCreate(MPI_Comm comm, HYPRE_Solver *solver)
953  { return HYPRE_ParCSRGMRESCreate(comm, solver);}
954 
955 //==============================================================================
956 template<class LocalOrdinal, class Node>
957 HYPRE_Int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParCSRFlexGMRESCreate(MPI_Comm comm, HYPRE_Solver *solver)
958  { return HYPRE_ParCSRFlexGMRESCreate(comm, solver);}
959 
960 //==============================================================================
961 template<class LocalOrdinal, class Node>
962 HYPRE_Int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParCSRLGMRESCreate(MPI_Comm comm, HYPRE_Solver *solver)
963  { return HYPRE_ParCSRLGMRESCreate(comm, solver);}
964 
965 //==============================================================================
966 template<class LocalOrdinal, class Node>
967 HYPRE_Int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::Hypre_ParCSRBiCGSTABCreate(MPI_Comm comm, HYPRE_Solver *solver)
968  { return HYPRE_ParCSRBiCGSTABCreate(comm, solver);}
969 
970 //==============================================================================
971 template<class LocalOrdinal, class Node>
973 Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::MakeContiguousColumnMap(Teuchos::RCP<const crs_matrix_type> &Matrix) const{
974  using import_type = Tpetra::Import<local_ordinal_type,global_ordinal_type,node_type>;
975  using go_vector_type = Tpetra::Vector<global_ordinal_type,local_ordinal_type,global_ordinal_type,node_type>;
976 
977  // Must create GloballyContiguous DomainMap (which is a permutation of Matrix_'s
978  // DomainMap) and the corresponding permuted ColumnMap.
979  // Epetra_GID ---------> LID ----------> HYPRE_GID
980  // via DomainMap.LID() via GloballyContiguousDomainMap.GID()
981  if(Matrix.is_null())
982  throw std::runtime_error("Hypre<Tpetra::RowMatrix<HYPRE_Real, HYPRE_Int, long long, Node>: Unsupported matrix configuration: Tpetra::CrsMatrix required");
983  RCP<const map_type> DomainMap = Matrix->getDomainMap();
984  RCP<const map_type> ColumnMap = Matrix->getColMap();
985  RCP<const import_type> importer = Matrix->getGraph()->getImporter();
986 
987  if(DomainMap->isContiguous() ) {
988  // If the domain map is linear, then we can just use the column map as is.
989  return ColumnMap;
990  }
991  else {
992  // The domain map isn't linear, so we need a new domain map
993  Teuchos::RCP<map_type> ContiguousDomainMap = rcp(new map_type(DomainMap->getGlobalNumElements(),
994  DomainMap->getLocalNumElements(), 0, DomainMap->getComm()));
995  if(importer) {
996  // If there's an importer then we can use it to get a new column map
997  go_vector_type MyGIDsHYPRE(DomainMap,ContiguousDomainMap->getLocalElementList());
998 
999  // import the HYPRE GIDs
1000  go_vector_type ColGIDsHYPRE(ColumnMap);
1001  ColGIDsHYPRE.doImport(MyGIDsHYPRE, *importer, Tpetra::INSERT);
1002 
1003  // Make a HYPRE numbering-based column map.
1004  return Teuchos::rcp(new map_type(ColumnMap->getGlobalNumElements(),ColGIDsHYPRE.getDataNonConst()(),0, ColumnMap->getComm()));
1005  }
1006  else {
1007  // The problem has matching domain/column maps, and somehow the domain map isn't linear, so just use the new domain map
1008  return Teuchos::rcp(new map_type(ColumnMap->getGlobalNumElements(),ContiguousDomainMap->getLocalElementList(), 0, ColumnMap->getComm()));
1009  }
1010  }
1011 }
1012 
1013 
1014 
1015 template<class LocalOrdinal, class Node>
1016 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::getNumInitialize() const {
1017  return NumInitialize_;
1018 }
1019 
1020 
1021 template<class LocalOrdinal, class Node>
1022 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::getNumCompute() const {
1023  return NumCompute_;
1024 }
1025 
1026 
1027 template<class LocalOrdinal, class Node>
1028 int Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::getNumApply() const {
1029  return NumApply_;
1030 }
1031 
1032 
1033 template<class LocalOrdinal, class Node>
1034 double Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::getInitializeTime() const {
1035  return InitializeTime_;
1036 }
1037 
1038 
1039 template<class LocalOrdinal, class Node>
1040 double Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::getComputeTime() const {
1041  return ComputeTime_;
1042 }
1043 
1044 
1045 template<class LocalOrdinal, class Node>
1046 double Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::getApplyTime() const {
1047  return ApplyTime_;
1048 }
1049 
1050 template<class LocalOrdinal, class Node>
1052 Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::
1053 getDomainMap () const
1054 {
1055  Teuchos::RCP<const row_matrix_type> A = getMatrix();
1057  A.is_null (), std::runtime_error, "Ifpack2::Hypre::getDomainMap: The "
1058  "input matrix A is null. Please call setMatrix() with a nonnull input "
1059  "matrix before calling this method.");
1060  return A->getDomainMap ();
1061 }
1062 
1063 
1064 template<class LocalOrdinal, class Node>
1066 Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::
1067 getRangeMap () const
1068 {
1069  Teuchos::RCP<const row_matrix_type> A = getMatrix();
1071  A.is_null (), std::runtime_error, "Ifpack2::Hypre::getRangeMap: The "
1072  "input matrix A is null. Please call setMatrix() with a nonnull input "
1073  "matrix before calling this method.");
1074  return A->getRangeMap ();
1075 }
1076 
1077 
1078 template<class LocalOrdinal, class Node>
1079 void Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::setMatrix (const Teuchos::RCP<const row_matrix_type>& A)
1080 {
1081  if (A.getRawPtr () != getMatrix().getRawPtr ()) {
1082  IsInitialized_ = false;
1083  IsComputed_ = false;
1084  A_ = A;
1085  }
1086 }
1087 
1088 
1089 template<class LocalOrdinal, class Node>
1091 Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::
1092 getMatrix() const {
1093  return A_;
1094 }
1095 
1096 
1097 template<class LocalOrdinal, class Node>
1098 bool Hypre<Tpetra::RowMatrix<HYPRE_Real, LocalOrdinal, HYPRE_Int, Node> >::hasTransposeApply() const {
1099  return false;
1100 }
1101 
1102 }// Ifpack2 namespace
1103 
1104 
1105 #define IFPACK2_HYPRE_INSTANT(S,LO,GO,N) \
1106  template class Ifpack2::Hypre< Tpetra::RowMatrix<S, LO, GO, N> >;
1107 
1108 
1109 #endif // HAVE_HYPRE && HAVE_MPI
1110 #endif // IFPACK2_HYPRE_DEF_HPP
ConstIterator end() const
T & get(const std::string &name, T def_value)
static RCP< Time > getNewCounter(const std::string &name)
static RCP< Time > lookupCounter(const std::string &name)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
T * data() const
bool isParameter(const std::string &name) const
T * getRawPtr() const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
bool isSublist(const std::string &name) const
ConstIterator begin() const
bool isType(const std::string &name) const
Uses AztecOO&#39;s GMRES.
Definition: Ifpack2_CondestType.hpp:53
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
static double wallTime()
bool is_null() const