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