Teko Version of the Day
Loading...
Searching...
No Matches
Teko_TpetraHelpers.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_TpetraHelpers.hpp"
11#include "Teko_ConfigDefs.hpp"
12
13// Thyra Includes
14#include "Thyra_BlockedLinearOpBase.hpp"
15#include "Thyra_DefaultMultipliedLinearOp.hpp"
16#include "Thyra_DefaultDiagonalLinearOp.hpp"
17#include "Thyra_DefaultZeroLinearOp.hpp"
18#include "Thyra_DefaultBlockedLinearOp.hpp"
19
20#include "Thyra_SpmdVectorBase.hpp"
21#include "Thyra_SpmdVectorSpaceBase.hpp"
22#include "Thyra_ScalarProdVectorSpaceBase.hpp"
23
24// Teko includes
25#include "Teko_Utilities.hpp"
26
27// Tpetra
28#include "Thyra_TpetraLinearOp.hpp"
29#include "Thyra_TpetraMultiVector.hpp"
30#include "Tpetra_CrsMatrix.hpp"
31#include "Tpetra_Vector.hpp"
32#include "Thyra_TpetraThyraWrappers.hpp"
33#include "TpetraExt_MatrixMatrix.hpp"
34#include "Tpetra_RowMatrixTransposer.hpp"
35
36using Teuchos::null;
37using Teuchos::RCP;
38using Teuchos::rcp;
39using Teuchos::rcp_dynamic_cast;
40using Teuchos::rcpFromRef;
41
42namespace Teko {
43namespace TpetraHelpers {
44
55const Teuchos::RCP<const Thyra::LinearOpBase<ST> > thyraDiagOp(
56 const RCP<const Tpetra::Vector<ST, LO, GO, NT> >& tv, const Tpetra::Map<LO, GO, NT>& map,
57 const std::string& lbl) {
58 const RCP<const Thyra::VectorBase<ST> > thyraVec // need a Thyra::VectorBase object
59 = Thyra::createConstVector<ST, LO, GO, NT>(
60 tv, Thyra::createVectorSpace<ST, LO, GO, NT>(rcpFromRef(map)));
61 Teuchos::RCP<Thyra::LinearOpBase<ST> > op =
62 Teuchos::rcp(new Thyra::DefaultDiagonalLinearOp<ST>(thyraVec));
63 op->setObjectLabel(lbl);
64 return op;
65}
66
77const Teuchos::RCP<Thyra::LinearOpBase<ST> > thyraDiagOp(
78 const RCP<Tpetra::Vector<ST, LO, GO, NT> >& tv, const Tpetra::Map<LO, GO, NT>& map,
79 const std::string& lbl) {
80 const RCP<Thyra::VectorBase<ST> > thyraVec // need a Thyra::VectorBase object
81 = Thyra::createVector<ST, LO, GO, NT>(
82 tv, Thyra::createVectorSpace<ST, LO, GO, NT>(rcpFromRef(map)));
83 Teuchos::RCP<Thyra::LinearOpBase<ST> > op =
84 Teuchos::rcp(new Thyra::DefaultDiagonalLinearOp<ST>(thyraVec));
85 op->setObjectLabel(lbl);
86 return op;
87}
88
98void fillDefaultSpmdMultiVector(Teuchos::RCP<Thyra::TpetraMultiVector<ST, LO, GO, NT> >& spmdMV,
99 Teuchos::RCP<Tpetra::MultiVector<ST, LO, GO, NT> >& tpetraMV) {
100 // first get desired range and domain
101 // const RCP<const Thyra::SpmdVectorSpaceBase<ST> > range = spmdMV->spmdSpace();
102 const RCP<Thyra::TpetraVectorSpace<ST, LO, GO, NT> > range =
103 Thyra::tpetraVectorSpace<ST, LO, GO, NT>(tpetraMV->getMap());
104 const RCP<const Thyra::ScalarProdVectorSpaceBase<ST> > domain =
105 rcp_dynamic_cast<const Thyra::ScalarProdVectorSpaceBase<ST> >(spmdMV->domain());
106
107 TEUCHOS_ASSERT((size_t)domain->dim() == tpetraMV->getNumVectors());
108
109 // New local view of raw data
110 if (!tpetraMV->isConstantStride())
111 TEUCHOS_TEST_FOR_EXCEPT(true); // ToDo: Implement views of non-contiguous mult-vectors!
112
113 // Build the MultiVector
114 spmdMV->initialize(range, domain, tpetraMV);
115
116 // make sure the Tpetra::MultiVector doesn't disappear prematurely
117 Teuchos::set_extra_data<RCP<Tpetra::MultiVector<ST, LO, GO, NT> > >(
118 tpetraMV, "Tpetra::MultiVector", Teuchos::outArg(spmdMV));
119}
120
130void identityRowIndices(const Tpetra::Map<LO, GO, NT>& rowMap,
131 const Tpetra::CrsMatrix<ST, LO, GO, NT>& mat, std::vector<GO>& outIndices) {
132 // loop over elements owned by this processor
133 for (size_t i = 0; i < rowMap.getLocalNumElements(); i++) {
134 bool rowIsIdentity = true;
135 GO rowGID = rowMap.getGlobalElement(i);
136
137 size_t numEntries = mat.getNumEntriesInGlobalRow(i);
138 auto indices = typename Tpetra::CrsMatrix<ST, LO, GO, NT>::nonconst_global_inds_host_view_type(
139 Kokkos::ViewAllocateWithoutInitializing("rowIndices"), numEntries);
140 auto values = typename Tpetra::CrsMatrix<ST, LO, GO, NT>::nonconst_values_host_view_type(
141 Kokkos::ViewAllocateWithoutInitializing("rowIndices"), numEntries);
142
143 mat.getGlobalRowCopy(rowGID, indices, values, numEntries);
144
145 // loop over the columns of this row
146 for (size_t j = 0; j < numEntries; j++) {
147 GO colGID = indices(j);
148
149 // look at row entries
150 if (colGID == rowGID)
151 rowIsIdentity &= values(j) == 1.0;
152 else
153 rowIsIdentity &= values(j) == 0.0;
154
155 // not a dirchlet row...quit
156 if (not rowIsIdentity) break;
157 }
158
159 // save a row that is dirchlet
160 if (rowIsIdentity) outIndices.push_back(rowGID);
161 }
162}
163
174void zeroMultiVectorRowIndices(Tpetra::MultiVector<ST, LO, GO, NT>& mv,
175 const std::vector<GO>& zeroIndices) {
176 LO colCnt = mv.getNumVectors();
177 std::vector<GO>::const_iterator itr;
178
179 // loop over the indices to zero
180 for (itr = zeroIndices.begin(); itr != zeroIndices.end(); ++itr) {
181 // loop over columns
182 for (int j = 0; j < colCnt; j++) mv.replaceGlobalValue(*itr, j, 0.0);
183 }
184}
185
195ZeroedOperator::ZeroedOperator(const std::vector<GO>& zeroIndices,
196 const Teuchos::RCP<const Tpetra::Operator<ST, LO, GO, NT> >& op)
197 : zeroIndices_(zeroIndices), tpetraOp_(op) {}
198
200void ZeroedOperator::apply(const Tpetra::MultiVector<ST, LO, GO, NT>& X,
201 Tpetra::MultiVector<ST, LO, GO, NT>& Y, Teuchos::ETransp mode, ST alpha,
202 ST beta) const {
203 /*
204 Tpetra::MultiVector temp(X);
205 zeroMultiVectorRowIndices(temp,zeroIndices_);
206 int result = TpetraOp_->Apply(temp,Y);
207 */
208
209 tpetraOp_->apply(X, Y, mode, alpha, beta);
210
211 // zero a few of the rows
212 zeroMultiVectorRowIndices(Y, zeroIndices_);
213}
214
215bool isTpetraLinearOp(const LinearOp& op) {
216 // See if the operator is a TpetraLinearOp
217 RCP<const Thyra::TpetraLinearOp<ST, LO, GO, NT> > tOp =
218 rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(op);
219 if (!tOp.is_null()) return true;
220
221 // See if the operator is a wrapped TpetraLinearOp
222 ST scalar = 0.0;
223 Thyra::EOpTransp transp = Thyra::NOTRANS;
224 RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
225 Thyra::unwrap(op, &scalar, &transp, &wrapped_op);
226 tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(wrapped_op);
227 if (!tOp.is_null()) return true;
228
229 return false;
230}
231
232RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT> > getTpetraCrsMatrix(const LinearOp& op, ST* scalar,
233 bool* transp) {
234 // If the operator is a TpetraLinearOp
235 RCP<const Thyra::TpetraLinearOp<ST, LO, GO, NT> > tOp =
236 rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(op);
237 if (!tOp.is_null()) {
238 RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT> > matrix =
239 rcp_dynamic_cast<const Tpetra::CrsMatrix<ST, LO, GO, NT> >(tOp->getConstTpetraOperator(),
240 true);
241 *scalar = 1.0;
242 *transp = false;
243 return matrix;
244 }
245
246 // If the operator is a wrapped TpetraLinearOp
247 RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
248 Thyra::EOpTransp eTransp = Thyra::NOTRANS;
249 Thyra::unwrap(op, scalar, &eTransp, &wrapped_op);
250 tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(wrapped_op, true);
251 if (!tOp.is_null()) {
252 RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT> > matrix =
253 rcp_dynamic_cast<const Tpetra::CrsMatrix<ST, LO, GO, NT> >(tOp->getConstTpetraOperator(),
254 true);
255 *transp = true;
256 if (eTransp == Thyra::NOTRANS) *transp = false;
257 return matrix;
258 }
259
260 return Teuchos::null;
261}
262
263RCP<Tpetra::CrsMatrix<ST, LO, GO, NT> > materializeTpetraCrsMatrix(const LinearOp& op) {
264 ST scalar = 0.0;
265 bool transp = false;
266 auto tCrsOp = getTpetraCrsMatrix(op, &scalar, &transp);
267 auto explicitCrsOp = transp
268 ? Tpetra::RowMatrixTransposer<ST, LO, GO, NT>(tCrsOp).createTranspose()
269 : rcp(new Tpetra::CrsMatrix<ST, LO, GO, NT>(*tCrsOp, Teuchos::Copy));
270 if (scalar != Teuchos::ScalarTraits<ST>::one()) explicitCrsOp->scale(scalar);
271 return explicitCrsOp;
272}
273
274ModifiableLinearOp materializeTpetraLinearOp(const LinearOp& op, const ModifiableLinearOp& destOp) {
275 auto explicitCrsOp = materializeTpetraCrsMatrix(op);
276
277 RCP<Thyra::LinearOpBase<ST> > explicitOp;
278 if (destOp != Teuchos::null)
279 explicitOp = destOp;
280 else
281 explicitOp = rcp(new Thyra::TpetraLinearOp<ST, LO, GO, NT>());
282
283 auto tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST, LO, GO, NT> >(explicitOp, true);
284 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST, LO, GO, NT>(explicitCrsOp->getRangeMap()),
285 Thyra::tpetraVectorSpace<ST, LO, GO, NT>(explicitCrsOp->getDomainMap()),
286 explicitCrsOp);
287 return tExplicitOp;
288}
289
290} // end namespace TpetraHelpers
291} // end namespace Teko
void apply(const Tpetra::MultiVector< ST, LO, GO, NT > &X, Tpetra::MultiVector< ST, LO, GO, NT > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, ST alpha=Teuchos::ScalarTraits< ST >::one(), ST beta=Teuchos::ScalarTraits< ST >::zero()) const
Perform a matrix-vector product with certain rows zeroed out.
ZeroedOperator(const std::vector< GO > &zeroIndices, const Teuchos::RCP< const Tpetra::Operator< ST, LO, GO, NT > > &op)
Constructor for a ZeroedOperator.