Teko Version of the Day
Loading...
Searching...
No Matches
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
38namespace Teko {
39namespace mlutils {
40
41// build a very simple row map from the ML_Operator
42Teuchos::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
60Teuchos::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
85Teko::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
121int 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
137Teuchos::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
152extern "C" void ML_Destroy_Smoother_Teko(void *data) {
153 Teko::mlutils::SmootherData *sData = (Teko::mlutils::SmootherData *)data;
154 delete sData;
155}
156
157extern "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);
188 Teko::mlutils::SmootherData *data = 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