Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_BlockedMappingStrategy.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 "Epetra/Teko_BlockedMappingStrategy.hpp"
11 #include "Epetra/Teko_EpetraHelpers.hpp"
12 
13 #include "Thyra_EpetraThyraWrappers.hpp"
14 #include "Thyra_EpetraLinearOp.hpp"
15 #include "Thyra_DefaultProductMultiVector.hpp"
16 #include "Thyra_DefaultProductVectorSpace.hpp"
17 #include "Thyra_DefaultSpmdMultiVector.hpp"
18 #include "Thyra_DefaultBlockedLinearOp.hpp"
19 #include "Thyra_get_Epetra_Operator.hpp"
20 
21 using Teuchos::RCP;
22 using Teuchos::rcp;
23 using Teuchos::rcp_dynamic_cast;
24 
25 namespace Teko {
26 namespace Epetra {
27 
28 // Creates a strided mapping strategy. This class is useful
29 // for breaking up nodally ordered matrices (i.e. the unknowns
30 // in a FEM problem are ordered [u0,v0,p0,u1,v1,p1,...]). Current
31 // implimentation only supports a fixed number of variables
32 //
33 // arguments:
34 // vars - Number of different variables
35 // map - original Epetra_Map to be broken up
36 // comm - Epetra_Comm object related to the map
37 //
38 BlockedMappingStrategy::BlockedMappingStrategy(const std::vector<std::vector<int> >& vars,
39  const Teuchos::RCP<const Epetra_Map>& map,
40  const Epetra_Comm& comm) {
41  rangeMap_ = map;
42  domainMap_ = map;
43  buildBlockTransferData(vars, rangeMap_, comm);
44 }
45 
46 // Virtual function defined in MappingStrategy. This copies
47 // an Epetra_MultiVector into a Thyra::MultiVectorBase with
48 // blocking handled by the strides defined in the constructor.
49 //
50 // arguments:
51 // X - source Epetra_MultiVector
52 // thyra_X - destination Thyra::MultiVectorBase
53 //
54 void BlockedMappingStrategy::copyEpetraIntoThyra(
55  const Epetra_MultiVector& X,
56  const Teuchos::Ptr<Thyra::MultiVectorBase<double> >& thyra_X) const {
57  int count = X.NumVectors();
58 
59  std::vector<RCP<Epetra_MultiVector> > subX;
60 
61  // allocate vectors to copy into
62  Blocking::buildSubVectors(blockMaps_, subX, count);
63 
64  // copy source vector to X vector
65  Blocking::one2many(subX, X, blockImport_);
66 
67  // convert subX to an array of multi vectors
68  Teuchos::Array<RCP<Thyra::MultiVectorBase<double> > > thyra_subX;
69  Teuchos::Ptr<Thyra::ProductMultiVectorBase<double> > prod_X =
70  Teuchos::ptr_dynamic_cast<Thyra::ProductMultiVectorBase<double> >(thyra_X);
71  for (unsigned int i = 0; i < blockMaps_.size(); i++) {
72  RCP<Thyra::DefaultSpmdMultiVector<double> > vec =
73  rcp_dynamic_cast<Thyra::DefaultSpmdMultiVector<double> >(
74  prod_X->getNonconstMultiVectorBlock(i));
75  fillDefaultSpmdMultiVector(vec, subX[i]);
76  }
77 }
78 
79 // Virtual function defined in MappingStrategy. This copies
80 // an Epetra_MultiVector into a Thyra::MultiVectorBase with
81 // blocking handled by the strides defined in the constructor.
82 //
83 // arguments:
84 // thyra_Y - source Thyra::MultiVectorBase
85 // Y - destination Epetra_MultiVector
86 //
87 void BlockedMappingStrategy::copyThyraIntoEpetra(
88  const RCP<const Thyra::MultiVectorBase<double> >& thyra_Y, Epetra_MultiVector& Y) const {
89  std::vector<RCP<const Epetra_MultiVector> > subY;
90  RCP<const Thyra::DefaultProductMultiVector<double> > prod_Y =
91  rcp_dynamic_cast<const Thyra::DefaultProductMultiVector<double> >(thyra_Y);
92 
93  // convert thyra product vector to subY
94  for (unsigned int i = 0; i < blockMaps_.size(); i++)
95  subY.push_back(
96  Thyra::get_Epetra_MultiVector(*blockMaps_[i].second, prod_Y->getMultiVectorBlock(i)));
97 
98  // endow the subVectors with required information about the maps
99  // Blocking::associateSubVectors(blockMaps_,subY);
100 
101  // copy solution vectors to Y vector
102  Blocking::many2one(Y, subY, blockExport_);
103 }
104 
105 // this is the core routine that builds the maps
106 // and importers/exporters neccessary for all the
107 // transfers. Currently it simply calls out to the
108 // interlaced epetra functions. (Comment: this
109 // routine should probably be private or protected
110 // ... it is basically the meat of the constructor)
111 //
112 // arguments:
113 // vars - Vector describing the blocking of variables
114 // baseMap - basic map to use in the transfers
115 // comm - Epetra_Comm object
116 //
117 void BlockedMappingStrategy::buildBlockTransferData(const std::vector<std::vector<int> >& vars,
118  const Teuchos::RCP<const Epetra_Map>& baseMap,
119  const Epetra_Comm& comm) {
120  // build block for each vector
121  for (std::size_t i = 0; i < vars.size(); i++) {
122  // build maps and exporters/importers
123  Blocking::MapPair mapPair = Blocking::buildSubMap(vars[i], comm);
124  Blocking::ImExPair iePair = Blocking::buildExportImport(*baseMap, mapPair);
125 
126  blockMaps_.push_back(mapPair);
127  blockImport_.push_back(iePair.first);
128  blockExport_.push_back(iePair.second);
129  }
130 }
131 
132 // Builds a blocked Thyra operator that uses the strided
133 // mapping strategy to define sub blocks.
134 //
135 // arguments:
136 // mat - Epetra_CrsMatrix with FillComplete called, this
137 // matrix is assumed to be square, with the same
138 // range and domain maps
139 // returns: Blocked Thyra linear operator with sub blocks
140 // defined by this mapping strategy
141 //
142 const Teuchos::RCP<Thyra::BlockedLinearOpBase<double> > BlockedMappingStrategy::buildBlockedThyraOp(
143  const RCP<const Epetra_CrsMatrix>& crsContent, const std::string& label) const {
144  int dim = blockMaps_.size();
145 
146  RCP<Thyra::DefaultBlockedLinearOp<double> > A = Thyra::defaultBlockedLinearOp<double>();
147 
148  A->beginBlockFill(dim, dim);
149  for (int i = 0; i < dim; i++) {
150  for (int j = 0; j < dim; j++) {
151  // label block correctly
152  std::stringstream ss;
153  ss << label << "_" << i << "," << j;
154 
155  // build the blocks and place it the right location
156  RCP<Epetra_CrsMatrix> blk = Blocking::buildSubBlock(i, j, *crsContent, blockMaps_);
157  A->setNonconstBlock(i, j, Thyra::nonconstEpetraLinearOp(blk, ss.str()));
158  }
159  } // end for i
160  A->endBlockFill();
161 
162  return A;
163 }
164 
165 // Rebuilds a blocked Thyra operator that uses the strided
166 // mapping strategy to define sub blocks.
167 //
168 // arguments:
169 // crsContent - Epetra_CrsMatrix with FillComplete called, this
170 // matrix is assumed to be square, with the same
171 // range and domain maps
172 // A - Destination block linear op composed of blocks of
173 // Epetra_CrsMatrix at all relevant locations
174 //
175 void BlockedMappingStrategy::rebuildBlockedThyraOp(
176  const RCP<const Epetra_CrsMatrix>& crsContent,
177  const RCP<Thyra::BlockedLinearOpBase<double> >& A) const {
178  int dim = blockMaps_.size();
179 
180  for (int i = 0; i < dim; i++) {
181  for (int j = 0; j < dim; j++) {
182  // get Epetra version of desired block
183  RCP<Thyra::LinearOpBase<double> > Aij = A->getNonconstBlock(i, j);
184  RCP<Epetra_CrsMatrix> eAij =
185  rcp_dynamic_cast<Epetra_CrsMatrix>(Thyra::get_Epetra_Operator(*Aij), true);
186 
187  // rebuild the blocks and place it the right location
188  Blocking::rebuildSubBlock(i, j, *crsContent, blockMaps_, *eAij);
189  }
190  } // end for i
191 }
192 
193 } // end namespace Epetra
194 } // end namespace Teko