Teko Version of the Day
Loading...
Searching...
No Matches
Teko_TpetraThyraConverter.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_TpetraThyraConverter.hpp"
11#include "Tpetra_Core.hpp"
12
13// Teuchos includes
14#include "Teuchos_Array.hpp"
15#include "Teuchos_ArrayRCP.hpp"
16
17// Thyra includes
18#include "Thyra_DefaultProductVectorSpace.hpp"
19#include "Thyra_DefaultProductMultiVector.hpp"
20#include "Thyra_SpmdMultiVectorBase.hpp"
21#include "Thyra_SpmdVectorSpaceBase.hpp"
22#include "Thyra_MultiVectorStdOps.hpp"
23
24#include <iostream>
25#include <vector>
26
27using Teuchos::null;
28using Teuchos::Ptr;
29using Teuchos::ptr_dynamic_cast;
30using Teuchos::RCP;
31using Teuchos::rcp;
32using Teuchos::rcp_dynamic_cast;
33using Teuchos::rcpFromRef;
34
35namespace Teko {
36namespace TpetraHelpers {
37
38// const Teuchos::RCP<const Thyra::MultiVectorBase<double> >
39// blockTpetraToThyra(int numVectors,const double * tpetraData,int leadingDim,const
40// Teuchos::RCP<const Thyra::VectorSpaceBase<double> > & vs,int & localDim)
41
42void blockTpetraToThyra(int numVectors, Teuchos::ArrayRCP<const ST> tpetraData, int leadingDim,
43 const Teuchos::Ptr<Thyra::MultiVectorBase<ST> >& mv, int& localDim) {
44 localDim = 0;
45
46 // check the base case
47 const Ptr<Thyra::ProductMultiVectorBase<ST> > prodMV =
48 ptr_dynamic_cast<Thyra::ProductMultiVectorBase<ST> >(mv);
49 if (prodMV == Teuchos::null) {
50 // VS object must be a SpmdMultiVector object
51 const Ptr<Thyra::SpmdMultiVectorBase<ST> > spmdX =
52 ptr_dynamic_cast<Thyra::SpmdMultiVectorBase<ST> >(mv, true);
53 const RCP<const Thyra::SpmdVectorSpaceBase<ST> > spmdVS = spmdX->spmdSpace();
54
55 int localSubDim = spmdVS->localSubDim();
56
57 Thyra::Ordinal thyraLeadingDim = 0;
58
59 Teuchos::ArrayRCP<ST> thyraData_arcp;
60 Teuchos::ArrayView<ST> thyraData;
61 spmdX->getNonconstLocalData(Teuchos::outArg(thyraData_arcp), Teuchos::outArg(thyraLeadingDim));
62 thyraData = thyraData_arcp(); // build array view
63
64 for (int i = 0; i < localSubDim; i++) {
65 // copy each vector
66 for (int v = 0; v < numVectors; v++)
67 thyraData[i + thyraLeadingDim * v] = tpetraData[i + leadingDim * v];
68 }
69
70 // set the local dimension
71 localDim = localSubDim;
72
73 return;
74 }
75
76 // this keeps track of current location in the tpetraData vector
77 Teuchos::ArrayRCP<const ST> localData = tpetraData;
78
79 // loop over all the blocks in the vector space
80 for (int blkIndex = 0; blkIndex < prodMV->productSpace()->numBlocks(); blkIndex++) {
81 int subDim = 0;
82 const RCP<Thyra::MultiVectorBase<ST> > blockVec = prodMV->getNonconstMultiVectorBlock(blkIndex);
83
84 // perform the recusive copy
85 blockTpetraToThyra(numVectors, localData, leadingDim, blockVec.ptr(), subDim);
86
87 // shift to the next block
88 localData += subDim;
89
90 // account for the size of this subblock
91 localDim += subDim;
92 }
93}
94
95// Convert a Tpetra_MultiVector with assumed block structure dictated by the
96// vector space into a Thyra::MultiVectorBase object.
97// const Teuchos::RCP<const Thyra::MultiVectorBase<double> > blockTpetraToThyra(const
98// Tpetra_MultiVector & e,const Teuchos::RCP<const Thyra::VectorSpaceBase<double> > & vs)
99void blockTpetraToThyra(const Tpetra::MultiVector<ST, LO, GO, NT>& tpetraX,
100 const Teuchos::Ptr<Thyra::MultiVectorBase<ST> >& thyraX) {
101 TEUCHOS_ASSERT((Tpetra::global_size_t)thyraX->range()->dim() == tpetraX.getGlobalLength());
102
103 // extract local information from the Tpetra_MultiVector
104 LO leadingDim = 0, localDim = 0;
105 leadingDim = tpetraX.getStride();
106 Teuchos::ArrayRCP<const ST> tpetraData = tpetraX.get1dView();
107
108 int numVectors = tpetraX.getNumVectors();
109
110 blockTpetraToThyra(numVectors, tpetraData, leadingDim, thyraX.ptr(), localDim);
111
112 TEUCHOS_ASSERT((size_t)localDim == tpetraX.getLocalLength());
113}
114
115void blockThyraToTpetra(LO numVectors, Teuchos::ArrayRCP<ST> tpetraData, LO leadingDim,
116 const Teuchos::RCP<const Thyra::MultiVectorBase<ST> >& tX, LO& localDim) {
117 localDim = 0;
118
119 // check the base case
120 const RCP<const Thyra::ProductMultiVectorBase<ST> > prodX =
121 rcp_dynamic_cast<const Thyra::ProductMultiVectorBase<ST> >(tX);
122 if (prodX == Teuchos::null) {
123 // the base case
124
125 // VS object must be a SpmdMultiVector object
126 RCP<const Thyra::SpmdMultiVectorBase<ST> > spmdX =
127 rcp_dynamic_cast<const Thyra::SpmdMultiVectorBase<ST> >(tX, true);
128 RCP<const Thyra::SpmdVectorSpaceBase<ST> > spmdVS = spmdX->spmdSpace();
129
130 Thyra::Ordinal thyraLeadingDim = 0;
131 Teuchos::ArrayView<const ST> thyraData;
132 Teuchos::ArrayRCP<const ST> thyraData_arcp;
133 spmdX->getLocalData(Teuchos::outArg(thyraData_arcp), Teuchos::outArg(thyraLeadingDim));
134 thyraData = thyraData_arcp(); // grab the array view
135
136 LO localSubDim = spmdVS->localSubDim();
137 for (LO i = 0; i < localSubDim; i++) {
138 // copy each vector
139 for (LO v = 0; v < numVectors; v++) {
140 tpetraData[i + leadingDim * v] = thyraData[i + thyraLeadingDim * v];
141 }
142 }
143
144 // set the local dimension
145 localDim = localSubDim;
146
147 return;
148 }
149
150 const RCP<const Thyra::ProductVectorSpaceBase<ST> > prodVS = prodX->productSpace();
151
152 // this keeps track of current location in the tpetraData vector
153 Teuchos::ArrayRCP<ST> localData = tpetraData;
154
155 // loop over all the blocks in the vector space
156 for (int blkIndex = 0; blkIndex < prodVS->numBlocks(); blkIndex++) {
157 int subDim = 0;
158
159 // construct the block vector
160 blockThyraToTpetra(numVectors, localData, leadingDim, prodX->getMultiVectorBlock(blkIndex),
161 subDim);
162
163 // shift to the next block
164 localData += subDim;
165
166 // account for the size of this subblock
167 localDim += subDim;
168 }
169
170 return;
171}
172
173// Convert a Thyra::MultiVectorBase object to a Tpetra_MultiVector object with
174// the map defined by the Tpetra_Map.
175// const Teuchos::RCP<const Tpetra_MultiVector>
176// blockThyraToTpetra(const Teuchos::RCP<const Thyra::MultiVectorBase<double> > & tX,const RCP<const
177// Tpetra_Map> & map)
178void blockThyraToTpetra(const Teuchos::RCP<const Thyra::MultiVectorBase<ST> >& thyraX,
179 Tpetra::MultiVector<ST, LO, GO, NT>& tpetraX) {
180 // build an Tpetra_MultiVector object
181 LO numVectors = thyraX->domain()->dim();
182
183 // make sure the number of vectors are the same
184 TEUCHOS_ASSERT((size_t)numVectors == tpetraX.getNumVectors());
185 TEUCHOS_ASSERT((Tpetra::global_size_t)thyraX->range()->dim() == tpetraX.getGlobalLength());
186
187 // extract local information from the Tpetra_MultiVector
188 LO leadingDim = 0, localDim = 0;
189 leadingDim = tpetraX.getStride();
190 Teuchos::ArrayRCP<ST> tpetraData = tpetraX.get1dViewNonConst();
191
192 // perform recursive copy
193 blockThyraToTpetra(numVectors, tpetraData, leadingDim, thyraX, localDim);
194
195 // sanity check
196 TEUCHOS_ASSERT((size_t)localDim == tpetraX.getLocalLength());
197}
198
199void thyraVSToTpetraMap(std::vector<GO>& myIndicies, int blockOffset,
200 const Thyra::VectorSpaceBase<ST>& vs, int& localDim) {
201 // zero out set local dimension
202 localDim = 0;
203
204 const RCP<const Thyra::ProductVectorSpaceBase<ST> > prodVS =
205 rcp_dynamic_cast<const Thyra::ProductVectorSpaceBase<ST> >(rcpFromRef(vs));
206
207 // is more recursion needed?
208 if (prodVS == Teuchos::null) {
209 // base case
210
211 // try to cast to an SPMD capable vector space
212 const RCP<const Thyra::SpmdVectorSpaceBase<ST> > spmdVS =
213 rcp_dynamic_cast<const Thyra::SpmdVectorSpaceBase<ST> >(rcpFromRef(vs));
214 TEUCHOS_TEST_FOR_EXCEPTION(spmdVS == Teuchos::null, std::runtime_error,
215 "thyraVSToTpetraMap requires all subblocks to be SPMD");
216
217 // get local data storage information
218 int localOffset = spmdVS->localOffset();
219 int localSubDim = spmdVS->localSubDim();
220
221 // add indicies to matrix
222 for (int i = 0; i < localSubDim; i++) myIndicies.push_back(blockOffset + localOffset + i);
223
224 localDim += localSubDim;
225
226 return;
227 }
228
229 // loop over all the blocks in the vector space
230 for (int blkIndex = 0; blkIndex < prodVS->numBlocks(); blkIndex++) {
231 int subDim = 0;
232
233 // construct the block vector
234 thyraVSToTpetraMap(myIndicies, blockOffset, *prodVS->getBlock(blkIndex), subDim);
235
236 blockOffset += prodVS->getBlock(blkIndex)->dim();
237
238 // account for the size of this subblock
239 localDim += subDim;
240 }
241}
242
243// From a Thyra vector space create a compatable Tpetra_Map
244const RCP<Tpetra::Map<LO, GO, NT> > thyraVSToTpetraMap(
245 const Thyra::VectorSpaceBase<ST>& vs,
246 const RCP<const Teuchos::Comm<Thyra::Ordinal> >& /* comm */) {
247 int localDim = 0;
248 std::vector<GO> myGIDs;
249
250 // call recursive routine that constructs the mapping
251 thyraVSToTpetraMap(myGIDs, 0, vs, localDim);
252
253 TEUCHOS_ASSERT(myGIDs.size() == (size_t)localDim);
254
255 // FIXME (mfh 12 Jul 2018) This ignores the input comm, so it can't
256 // be right.
257
258 // create the map
259 return rcp(new Tpetra::Map<LO, GO, NT>(vs.dim(), Teuchos::ArrayView<const GO>(myGIDs), 0,
260 Tpetra::getDefaultComm()));
261}
262
263} // namespace TpetraHelpers
264} // end namespace Teko