Teko Version of the Day
Loading...
Searching...
No Matches
Teko_TpetraBlockedMappingStrategy.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_TpetraBlockedMappingStrategy.hpp"
11#include "Teko_TpetraHelpers.hpp"
12
13#include "Thyra_TpetraThyraWrappers.hpp"
14#include "Thyra_TpetraLinearOp.hpp"
15#include "Thyra_DefaultProductMultiVector.hpp"
16#include "Thyra_DefaultProductVectorSpace.hpp"
17#include "Thyra_DefaultSpmdMultiVector.hpp"
18#include "Thyra_DefaultBlockedLinearOp.hpp"
19
20using Teuchos::RCP;
21using Teuchos::rcp;
22using Teuchos::rcp_dynamic_cast;
23
24namespace Teko {
25namespace TpetraHelpers {
26
27// Creates a strided mapping strategy. This class is useful
28// for breaking up nodally ordered matrices (i.e. the unknowns
29// in a FEM problem are ordered [u0,v0,p0,u1,v1,p1,...]). Current
30// implimentation only supports a fixed number of variables
31//
32// arguments:
33// vars - Number of different variables
34// map - original Tpetra::Map<LO,GO,NT> to be broken up
35// comm - Teuchos::RCP<Teuchos::Comm<int> > object related to the map
36//
37TpetraBlockedMappingStrategy::TpetraBlockedMappingStrategy(
38 const std::vector<std::vector<GO>>& vars,
39 const Teuchos::RCP<const Tpetra::Map<LO, GO, NT>>& map, const Teuchos::Comm<int>& comm) {
40 rangeMap_ = map;
41 domainMap_ = map;
42 buildBlockTransferData(vars, rangeMap_, comm);
43}
44
45// Virtual function defined in MappingStrategy. This copies
46// an Tpetra::MultiVector<ST,LO,GO,NT> into a Thyra::MultiVectorBase with
47// blocking handled by the strides defined in the constructor.
48//
49// arguments:
50// X - source Tpetra::MultiVector<ST,LO,GO,NT>
51// thyra_X - destination Thyra::MultiVectorBase
52//
53void TpetraBlockedMappingStrategy::copyTpetraIntoThyra(
54 const Tpetra::MultiVector<ST, LO, GO, NT>& X,
55 const Teuchos::Ptr<Thyra::MultiVectorBase<ST>>& thyra_X) const {
56 if (blockMaps_.empty()) {
57 auto prod_X = Teuchos::ptr_dynamic_cast<Thyra::ProductMultiVectorBase<ST>>(thyra_X);
58 auto vec = rcp_dynamic_cast<Thyra::TpetraMultiVector<ST, LO, GO, NT>>(
59 prod_X->getNonconstMultiVectorBlock(0), true);
60
61 Teuchos::RCP<Tpetra::MultiVector<ST, LO, GO, NT>> X_rcp_nonconst =
62 Teuchos::rcp_const_cast<Tpetra::MultiVector<ST, LO, GO, NT>>(Teuchos::rcpFromRef(X));
63 fillDefaultSpmdMultiVector(vec, X_rcp_nonconst);
64 return;
65 }
66
67 int count = X.getNumVectors();
68
69 std::vector<RCP<Tpetra::MultiVector<ST, LO, GO, NT>>> subX;
70
71 // allocate vectors to copy into
72 Blocking::buildSubVectors(blockMaps_, subX, count);
73
74 // copy source vector to X vector
75 Blocking::one2many(subX, X, blockImport_);
76
77 // convert subX to an array of multi vectors
78 Teuchos::Array<RCP<Thyra::MultiVectorBase<ST>>> thyra_subX;
79 Teuchos::Ptr<Thyra::ProductMultiVectorBase<ST>> prod_X =
80 Teuchos::ptr_dynamic_cast<Thyra::ProductMultiVectorBase<ST>>(thyra_X);
81 for (unsigned int i = 0; i < blockMaps_.size(); i++) {
82 RCP<Thyra::TpetraMultiVector<ST, LO, GO, NT>> vec =
83 rcp_dynamic_cast<Thyra::TpetraMultiVector<ST, LO, GO, NT>>(
84 prod_X->getNonconstMultiVectorBlock(i), true);
85
86 fillDefaultSpmdMultiVector(vec, subX[i]);
87 }
88}
89
90// Virtual function defined in MappingStrategy. This copies
91// an Tpetra::MultiVector<ST,LO,GO,NT> into a Thyra::MultiVectorBase with
92// blocking handled by the strides defined in the constructor.
93//
94// arguments:
95// thyra_Y - source Thyra::MultiVectorBase
96// Y - destination Tpetra::MultiVector<ST,LO,GO,NT>
97//
98void TpetraBlockedMappingStrategy::copyThyraIntoTpetra(
99 const RCP<const Thyra::MultiVectorBase<ST>>& thyra_Y,
100 Tpetra::MultiVector<ST, LO, GO, NT>& Y) const {
101 if (blockMaps_.empty()) {
102 auto prod_Y = rcp_dynamic_cast<const Thyra::DefaultProductMultiVector<ST>>(thyra_Y);
103 auto tmv = rcp_dynamic_cast<const Thyra::TpetraMultiVector<ST, LO, GO, NT>>(
104 prod_Y->getMultiVectorBlock(0), true)
105 ->getConstTpetraMultiVector();
106 Y.assign(*tmv);
107 return;
108 }
109
110 std::vector<RCP<const Tpetra::MultiVector<ST, LO, GO, NT>>> subY;
111 RCP<const Thyra::DefaultProductMultiVector<ST>> prod_Y =
112 rcp_dynamic_cast<const Thyra::DefaultProductMultiVector<ST>>(thyra_Y);
113
114 // convert thyra product vector to subY
115 for (unsigned int i = 0; i < blockMaps_.size(); i++) {
116 RCP<const Thyra::TpetraMultiVector<ST, LO, GO, NT>> tmv =
117 rcp_dynamic_cast<const Thyra::TpetraMultiVector<ST, LO, GO, NT>>(
118 prod_Y->getMultiVectorBlock(i), true);
119 subY.push_back(tmv->getConstTpetraMultiVector());
120 }
121
122 // endow the subVectors with required information about the maps
123 // Blocking::associateSubVectors(blockMaps_,subY);
124
125 // copy solution vectors to Y vector
126 Blocking::many2one(Y, subY, blockExport_);
127}
128
129// this is the core routine that builds the maps
130// and importers/exporters neccessary for all the
131// transfers. Currently it simply calls out to the
132// interlaced tpetra functions. (Comment: this
133// routine should probably be private or protected
134// ... it is basically the meat of the constructor)
135//
136// arguments:
137// vars - Vector describing the blocking of variables
138// baseMap - basic map to use in the transfers
139// comm - Teuchos::RCP<Teuchos::Comm<int> > object
140//
141void TpetraBlockedMappingStrategy::buildBlockTransferData(
142 const std::vector<std::vector<GO>>& vars,
143 const Teuchos::RCP<const Tpetra::Map<LO, GO, NT>>& baseMap, const Teuchos::Comm<int>& comm) {
144 if (vars.size() == 1) return;
145
146 // build block for each vector
147 for (std::size_t i = 0; i < vars.size(); i++) {
148 // build maps and exporters/importers
149 Blocking::MapPair mapPair = Blocking::buildSubMap(vars[i], comm);
150 Blocking::ImExPair iePair = Blocking::buildExportImport(*baseMap, mapPair);
151
152 blockMaps_.push_back(mapPair);
153 blockImport_.push_back(iePair.first);
154 blockExport_.push_back(iePair.second);
155 }
156}
157
158// Builds a blocked Thyra operator that uses the strided
159// mapping strategy to define sub blocks.
160//
161// arguments:
162// mat - Tpetra::CrsMatrix<ST,LO,GO,NT> with FillComplete called, this
163// matrix is assumed to be square, with the same
164// range and domain maps
165// returns: Blocked Thyra linear operator with sub blocks
166// defined by this mapping strategy
167//
168const Teuchos::RCP<Thyra::BlockedLinearOpBase<ST>>
169TpetraBlockedMappingStrategy::buildBlockedThyraOp(
170 const RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT>>& crsContent,
171 const std::string& label) const {
172 if (blockMaps_.empty()) {
173 RCP<Thyra::DefaultBlockedLinearOp<ST>> A = Thyra::defaultBlockedLinearOp<ST>();
174
175 auto crsCopy = Teuchos::make_rcp<Tpetra::CrsMatrix<ST, LO, GO, NT>>(*crsContent,
176 Teuchos::DataAccess::View);
177
178 A->beginBlockFill(1, 1);
179 A->setNonconstBlock(
180 0, 0,
181 Thyra::tpetraLinearOp<ST, LO, GO, NT>(
182 Thyra::tpetraVectorSpace<ST, LO, GO, NT>(crsCopy->getRangeMap()),
183 Thyra::tpetraVectorSpace<ST, LO, GO, NT>(crsCopy->getDomainMap()), crsCopy));
184 A->endBlockFill();
185
186 return A;
187 }
188
189 int dim = blockMaps_.size();
190
191 plocal2ContigGIDs.resize(dim);
192 for (int j = 0; j < dim; j++) {
193 plocal2ContigGIDs[j] = Blocking::getSubBlockColumnGIDs(*crsContent, blockMaps_[j]);
194 }
195
196 RCP<Thyra::DefaultBlockedLinearOp<ST>> A = Thyra::defaultBlockedLinearOp<ST>();
197
198 A->beginBlockFill(dim, dim);
199 for (int i = 0; i < dim; i++) {
200 for (int j = 0; j < dim; j++) {
201 // label block correctly
202 std::stringstream ss;
203 ss << label << "_" << i << "," << j;
204
205 // build the blocks and place it the right location
206 RCP<Tpetra::CrsMatrix<ST, LO, GO, NT>> blk =
207 Blocking::buildSubBlock(i, j, crsContent, blockMaps_, plocal2ContigGIDs[j]);
208 A->setNonconstBlock(i, j,
209 Thyra::tpetraLinearOp<ST, LO, GO, NT>(
210 Thyra::tpetraVectorSpace<ST, LO, GO, NT>(blk->getRangeMap()),
211 Thyra::tpetraVectorSpace<ST, LO, GO, NT>(blk->getDomainMap()), blk));
212 }
213 } // end for i
214 A->endBlockFill();
215
216 return A;
217}
218
219// Rebuilds a blocked Thyra operator that uses the strided
220// mapping strategy to define sub blocks.
221//
222// arguments:
223// crsContent - Tpetra::CrsMatrix<ST,LO,GO,NT> with FillComplete called, this
224// matrix is assumed to be square, with the same
225// range and domain maps
226// A - Destination block linear op composed of blocks of
227// Tpetra::CrsMatrix<ST,LO,GO,NT> at all relevant locations
228//
229void TpetraBlockedMappingStrategy::rebuildBlockedThyraOp(
230 const RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT>>& crsContent,
231 const RCP<Thyra::BlockedLinearOpBase<ST>>& A) const {
232 if (blockMaps_.empty()) {
233 auto Aij = A->getNonconstBlock(0, 0);
234 auto tAij = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST, LO, GO, NT>>(Aij, true);
235 auto eAij =
236 rcp_dynamic_cast<Tpetra::CrsMatrix<ST, LO, GO, NT>>(tAij->getTpetraOperator(), true);
237 auto values_dest = eAij->getLocalMatrixDevice().values;
238 const auto values_src = crsContent->getLocalMatrixDevice().values;
239 TEUCHOS_DEBUG_ASSERT(eAij->getCrsGraph()->isIdenticalTo(*crsContent->getCrsGraph()));
240 TEUCHOS_DEBUG_ASSERT(values_dest.extent(0) == values_src.extent(0));
241 Kokkos::deep_copy(values_dest, values_src);
242 return;
243 }
244
245 int dim = blockMaps_.size();
246
247 for (int i = 0; i < dim; i++) {
248 for (int j = 0; j < dim; j++) {
249 // get Tpetra version of desired block
250 RCP<Thyra::LinearOpBase<ST>> Aij = A->getNonconstBlock(i, j);
251 RCP<Thyra::TpetraLinearOp<ST, LO, GO, NT>> tAij =
252 rcp_dynamic_cast<Thyra::TpetraLinearOp<ST, LO, GO, NT>>(Aij, true);
253 RCP<Tpetra::CrsMatrix<ST, LO, GO, NT>> eAij =
254 rcp_dynamic_cast<Tpetra::CrsMatrix<ST, LO, GO, NT>>(tAij->getTpetraOperator(), true);
255
256 // rebuild the blocks and place it the right location
257 Blocking::rebuildSubBlock(i, j, crsContent, blockMaps_, *eAij, plocal2ContigGIDs[j]);
258 }
259 } // end for i
260}
261
262} // namespace TpetraHelpers
263} // end namespace Teko