Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_mlutils.cpp
1 // @HEADER
2 // *****************************************************************************
3 // Teko: A package for block and physics based preconditioning
4 //
5 // Copyright 2010 NTESS and the Teko contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #include "Teko_mlutils.hpp"
11 
12 #include <vector>
13 
14 #ifdef HAVE_MPI
15 #include "mpi.h"
16 #include "Epetra_MpiComm.h"
17 #else
18 #include "Epetra_SerialComm.h"
19 #endif
20 #include "Epetra_Vector.h"
21 
22 #include "ml_epetra_utils.h"
23 #include "ml_op_utils.h"
24 
25 #include "Thyra_EpetraLinearOp.hpp"
26 
27 #include "EpetraExt_RowMatrixOut.h"
28 
29 #include "Teuchos_XMLParameterListHelpers.hpp"
30 
31 #include "Teko_InverseFactory.hpp"
32 #include "Teko_InverseLibrary.hpp"
33 #include "Teko_Utilities.hpp"
34 #include "Teko_PreconditionerFactory.hpp"
35 #include "Teko_EpetraOperatorWrapper.hpp"
36 #include "Teko_SmootherPreconditionerFactory.hpp"
37 
38 namespace Teko {
39 namespace mlutils {
40 
41 // build a very simple row map from the ML_Operator
42 Teuchos::RCP<Epetra_Map> buildRowMap(ML_Operator *mlOp) {
43  ML_Comm *comm = mlOp->comm;
44 #ifdef ML_MPI
45  MPI_Comm mpi_comm;
46  mpi_comm = comm->USR_comm;
47  Epetra_MpiComm eComm(mpi_comm);
48 #else
49  Epetra_SerialComm eComm;
50 #endif
51 
52  // get operators row count, build map...who cares what GIDs are
53  int rowCnt = mlOp->outvec_leng;
54  return Teuchos::rcp(new Epetra_Map(-1, rowCnt, 0, eComm));
55 }
56 
60 Teuchos::RCP<Epetra_CrsMatrix> convertToCrsMatrix(ML_Operator *mlOp,
61  const Teuchos::RCP<Epetra_Map> &rowMapArg) {
62  ML_Comm *comm = mlOp->comm;
63 #ifdef ML_MPI
64  MPI_Comm mpi_comm;
65  mpi_comm = comm->USR_comm;
66  Epetra_MpiComm eComm(mpi_comm);
67 #else
68  Epetra_SerialComm eComm;
69 #endif
70 
71  // build a default row map
72  Teuchos::RCP<Epetra_Map> rowMap = rowMapArg;
73  if (rowMapArg == Teuchos::null) rowMap = buildRowMap(mlOp);
74 
75  // build lightweight CrsMatrix wrapper
76  Epetra_CrsMatrix *crsMatrixPtr = 0;
77  int maxNumNonzeros = 0;
78  double cpuTime = 0.0;
79  bool verbose = false;
80  ML_Operator2EpetraCrsMatrix(mlOp, crsMatrixPtr, maxNumNonzeros, false, cpuTime, verbose);
81 
82  return Teuchos::rcp(crsMatrixPtr);
83 }
84 
85 Teko::LinearOp buildTekoBlockOp(ML_Operator *mlOp, int level) {
86  Teko_DEBUG_SCOPE("Teko::mlutils::buildTekoBlockOp", 0);
87 
88  using Teuchos::RCP;
89 
90  int numRows = ML_Operator_BlkMatNumBlockRows(mlOp);
91  int numCols = ML_Operator_BlkMatNumBlockCols(mlOp);
92 
93  Teko::BlockedLinearOp tekoOp = Teko::createBlockedOp();
94  Teko::beginBlockFill(tekoOp, numRows, numCols);
95  for (int i = 0; i < numRows; i++) {
96  for (int j = 0; j < numCols; j++) {
97  ML_Operator *subBlock = ML_Operator_BlkMatExtract(mlOp, i, j);
98 
99  // if required construct and add a block to tekoOp
100  if (subBlock != 0) {
101  // create a CRS matrix from ML operator
102  RCP<const Epetra_CrsMatrix> eCrsMat = convertToCrsMatrix(subBlock);
103 
104 #if 0
105  std::stringstream ss;
106  ss << "A(" << level << ")_" << i << "_" << j << ".mm";
107  EpetraExt::RowMatrixToMatrixMarketFile(ss.str().c_str(),*eCrsMat);
108 #endif
109 
110  // build Teko operator, add to Teko blocked operator
111  Teko::LinearOp tekoSubBlock = Thyra::epetraLinearOp(eCrsMat);
112  Teko::setBlock(i, j, tekoOp, tekoSubBlock);
113  }
114  }
115  }
116  Teko::endBlockFill(tekoOp);
117 
118  return tekoOp.getConst();
119 }
120 
121 int smoother(ML_Smoother *mydata, int leng1, double x[], int leng2, double rhs[]) {
122  Teko_DEBUG_SCOPE("Teko::mlutils::smoother", 10);
123 
124  // std::cout << "init guess = " << mydata->init_guess << std::endl;
125 
126  // grab data object
127  SmootherData *smootherData = (struct SmootherData *)ML_Get_MySmootherData(mydata);
128 
129  Epetra_Vector X(View, smootherData->Amat->OperatorDomainMap(), x);
130  Epetra_Vector Y(View, smootherData->Amat->OperatorRangeMap(), rhs);
131 
132  smootherData->smootherOperator->Apply(Y, X);
133 
134  return 0;
135 }
136 
137 Teuchos::RCP<Teko::InverseFactory> ML_Gen_Init_Teko_Prec(const std::string smoothName,
138  const Teko::InverseLibrary &invLib) {
139  Teko_DEBUG_SCOPE("Teko::mlutils::ML_Gen_Init_Teko_Prec", 10);
140 
141  // Teuchos::RCP<Teko::RequestHandler> rh = Teuchos::rcp(new Teko::RequestHandler());
142  // Teuchos::RCP<Teko::InverseLibrary> invLib
143  // = Teko::InverseLibrary::buildFromParameterList(pl);
144  // invLib->setRequestHandler(rh);
145 
146  Teuchos::RCP<Teko::PreconditionerFactory> precFact;
147  Teuchos::RCP<Teko::InverseFactory> invFact = invLib.getInverseFactory(smoothName);
148 
149  return invFact;
150 }
151 
152 extern "C" void ML_Destroy_Smoother_Teko(void *data) {
154  delete sData;
155 }
156 
157 extern "C" int ML_Gen_Smoother_Teko(ML *ml, int level, int pre_or_post, int ntimes,
158  const Teuchos::RCP<const Teuchos::ParameterList> &tekoPL,
159  const Teuchos::RCP<const Teko::InverseLibrary> &invLib_in,
160  const std::string &inverse, bool isBlocked) {
161  Teko_DEBUG_SCOPE("Teko::mlutils::ML_Gen_Smoother_Teko", 10);
162  ML_Operator *BlkMat = &(ml->Amat[level]);
163 
164  Teuchos::RCP<const Teko::InverseLibrary> invLib;
165  if (invLib_in == Teuchos::null) {
166  Teuchos::RCP<Teko::RequestHandler> rh = Teuchos::rcp(new Teko::RequestHandler());
167  Teuchos::RCP<Teko::InverseLibrary> ncInvLib =
168  Teko::InverseLibrary::buildFromParameterList(*tekoPL);
169  ncInvLib->setRequestHandler(rh);
170 
171  invLib = ncInvLib.getConst();
172  } else {
173  // this assumes a request handler has already been set
174  invLib = invLib_in;
175  }
176 
177  Teko::LinearOp tekoAmat;
178  if (isBlocked) {
179  // build teko blocked operator
180  tekoAmat = Teko::mlutils::buildTekoBlockOp(BlkMat, level);
181  } else {
182  // build unblocked operator
183  Teuchos::RCP<const Epetra_CrsMatrix> eCrsMat = convertToCrsMatrix(BlkMat);
184  tekoAmat = Thyra::epetraLinearOp(eCrsMat);
185  }
186 
187  // Teuchos::RCP<Teko::mlutils::SmootherData> data = Teuchos::rcp(new Teko::mlutils::SmootherData);
189  data->Amat = Teuchos::rcp(new Teko::Epetra::EpetraOperatorWrapper(tekoAmat));
190 
191  // Teuchos::ParameterList pl = *Teuchos::getParametersFromXmlFile(filename);
192  Teuchos::RCP<Teko::InverseFactory> invFact = ML_Gen_Init_Teko_Prec(inverse, *invLib);
193  Teuchos::RCP<Teko::RequestHandler> rh = invFact->getRequestHandler();
194 
195  // build smoother operator
196  Teko::LinearOp precOp = Teko::buildInverse(*invFact, tekoAmat);
197  Teko::LinearOp smootherOp = Teko::buildSmootherLinearOp(tekoAmat, precOp, ntimes, true);
198 
199  // get an epetra operator wrapper
200  data->smootherOperator = Teuchos::rcp(new Teko::Epetra::EpetraOperatorWrapper(smootherOp));
201 
202  int ret_val =
203  ML_Set_Smoother(ml, level, pre_or_post, (void *)data, Teko::mlutils::smoother, NULL);
204  ml->post_smoother[level].data_destroy = ML_Destroy_Smoother_Teko;
205 
206  return ret_val;
207 }
208 
209 } // namespace mlutils
210 } // namespace Teko
Implements the Epetra_Operator interface with a Thyra LinearOperator. This enables the use of absrtac...
InverseLinearOp buildInverse(const InverseFactory &factory, const LinearOp &A)
Build an inverse operator using a factory and a linear operator.