Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_BlockingEpetra.cpp
1 /*
2 // @HEADER
3 //
4 // ***********************************************************************
5 //
6 // Teko: A package for block and physics based preconditioning
7 // Copyright 2010 Sandia Corporation
8 //
9 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Eric C. Cyr (eccyr@sandia.gov)
40 //
41 // ***********************************************************************
42 //
43 // @HEADER
44 
45 */
46 
47 #include "Teko_BlockingEpetra.hpp"
48 
49 #include "Epetra_IntVector.h"
50 #include "Epetra_LocalMap.h"
51 
52 using Teuchos::RCP;
53 using Teuchos::rcp;
54 
55 namespace Teko {
56 namespace Epetra {
57 namespace Blocking {
58 
72 const MapPair buildSubMap(const std::vector<int> &gid, const Epetra_Comm &comm) {
73  Teuchos::RCP<Epetra_Map> gidMap = rcp(new Epetra_Map(-1, gid.size(), &gid[0], 0, comm));
74  Teuchos::RCP<Epetra_Map> contigMap = rcp(new Epetra_Map(-1, gid.size(), 0, comm));
75 
76  return std::make_pair(gidMap, contigMap);
77 }
78 
88 const ImExPair buildExportImport(const Epetra_Map &baseMap, const MapPair &maps) {
89  return std::make_pair(rcp(new Epetra_Import(*maps.first, baseMap)),
90  rcp(new Epetra_Export(*maps.first, baseMap)));
91 }
92 
100 void buildSubVectors(const std::vector<MapPair> &maps,
101  std::vector<RCP<Epetra_MultiVector> > &vectors, int count) {
102  std::vector<MapPair>::const_iterator mapItr;
103 
104  // loop over all maps
105  for (mapItr = maps.begin(); mapItr != maps.end(); mapItr++) {
106  // add new elements to vectors
107  RCP<Epetra_MultiVector> mv = rcp(new Epetra_MultiVector(*(*mapItr).second, count));
108  vectors.push_back(mv);
109  }
110 }
111 
119 void one2many(std::vector<RCP<Epetra_MultiVector> > &many, const Epetra_MultiVector &single,
120  const std::vector<RCP<Epetra_Import> > &subImport) {
121  // std::vector<RCP<Epetra_Vector> >::const_iterator vecItr;
122  std::vector<RCP<Epetra_MultiVector> >::const_iterator vecItr;
123  std::vector<RCP<Epetra_Import> >::const_iterator impItr;
124 
125  // using Importers fill the sub vectors from the mama vector
126  for (vecItr = many.begin(), impItr = subImport.begin(); vecItr != many.end();
127  ++vecItr, ++impItr) {
128  // for ease of access to the destination
129  RCP<Epetra_MultiVector> destVec = *vecItr;
130 
131  // extract the map with global indicies from the current vector
132  const Epetra_BlockMap &globalMap = (*impItr)->TargetMap();
133 
134  // build the import vector as a view on the destination
135  Epetra_MultiVector importVector(View, globalMap, destVec->Values(), destVec->Stride(),
136  destVec->NumVectors());
137 
138  // perform the import
139  importVector.Import(single, **impItr, Insert);
140  }
141 }
142 
153 void many2one(Epetra_MultiVector &one, const std::vector<RCP<const Epetra_MultiVector> > &many,
154  const std::vector<RCP<Epetra_Export> > &subExport) {
155  // std::vector<RCP<const Epetra_Vector> >::const_iterator vecItr;
156  std::vector<RCP<const Epetra_MultiVector> >::const_iterator vecItr;
157  std::vector<RCP<Epetra_Export> >::const_iterator expItr;
158 
159  // using Exporters fill the empty vector from the sub-vectors
160  for (vecItr = many.begin(), expItr = subExport.begin(); vecItr != many.end();
161  ++vecItr, ++expItr) {
162  // for ease of access to the source
163  RCP<const Epetra_MultiVector> srcVec = *vecItr;
164 
165  // extract the map with global indicies from the current vector
166  const Epetra_BlockMap &globalMap = (*expItr)->SourceMap();
167 
168  // build the export vector as a view of the destination
169  Epetra_MultiVector exportVector(View, globalMap, srcVec->Values(), srcVec->Stride(),
170  srcVec->NumVectors());
171  one.Export(exportVector, **expItr, Insert);
172  }
173 }
174 
180 RCP<Epetra_IntVector> getSubBlockColumnGIDs(const Epetra_CrsMatrix &A, const MapPair &mapPair) {
181  RCP<const Epetra_Map> blkGIDMap = mapPair.first;
182  RCP<const Epetra_Map> blkContigMap = mapPair.second;
183 
184  // fill index vector for rows
185  Epetra_IntVector rIndex(A.RowMap(), true);
186  for (int i = 0; i < A.NumMyRows(); i++) {
187  // LID is need to get to contiguous map
188  int lid = blkGIDMap->LID(A.GRID(i)); // this LID makes me nervous
189  if (lid > -1)
190  rIndex[i] = blkContigMap->GID(lid);
191  else
192  rIndex[i] = -1;
193  }
194 
195  // get relavant column indices
196  Epetra_Import import(A.ColMap(), A.RowMap());
197  RCP<Epetra_IntVector> cIndex = rcp(new Epetra_IntVector(A.ColMap(), true));
198  cIndex->Import(rIndex, import, Insert);
199 
200  return cIndex;
201 }
202 
203 // build a single subblock Epetra_CrsMatrix
204 RCP<Epetra_CrsMatrix> buildSubBlock(int i, int j, const Epetra_CrsMatrix &A,
205  const std::vector<MapPair> &subMaps) {
206  // get the number of variables families
207  int numVarFamily = subMaps.size();
208 
209  TEUCHOS_ASSERT(i >= 0 && i < numVarFamily);
210  TEUCHOS_ASSERT(j >= 0 && j < numVarFamily);
211 
212  const Epetra_Map &gRowMap = *subMaps[i].first; // new GIDs
213  const Epetra_Map &rowMap = *subMaps[i].second; // contiguous GIDs
214  const Epetra_Map &colMap = *subMaps[j].second;
215 
216  const RCP<Epetra_IntVector> plocal2ContigGIDs = getSubBlockColumnGIDs(A, subMaps[j]);
217  Epetra_IntVector &local2ContigGIDs = *plocal2ContigGIDs;
218 
219  RCP<Epetra_CrsMatrix> mat = rcp(new Epetra_CrsMatrix(Copy, rowMap, 0));
220 
221  // get entry information
222  int numMyRows = rowMap.NumMyElements();
223  int maxNumEntries = A.MaxNumEntries();
224 
225  // for extraction
226  std::vector<int> indices(maxNumEntries);
227  std::vector<double> values(maxNumEntries);
228 
229  // for insertion
230  std::vector<int> colIndices(maxNumEntries);
231  std::vector<double> colValues(maxNumEntries);
232 
233  // insert each row into subblock
234  // let FillComplete handle column distribution
235  for (int localRow = 0; localRow < numMyRows; localRow++) {
236  int numEntries = -1;
237  int globalRow = gRowMap.GID(localRow);
238  int lid = A.RowMap().LID(globalRow);
239  int contigRow = rowMap.GID(localRow);
240  TEUCHOS_ASSERT(lid > -1);
241 
242  int err = A.ExtractMyRowCopy(lid, maxNumEntries, numEntries, &values[0], &indices[0]);
243  TEUCHOS_ASSERT(err == 0);
244 
245  int numOwnedCols = 0;
246  for (int localCol = 0; localCol < numEntries; localCol++) {
247  TEUCHOS_ASSERT(indices[localCol] > -1);
248 
249  // if global id is not owned by this column
250  int gid = local2ContigGIDs[indices[localCol]];
251  if (gid == -1) continue; // in contiguous row
252 
253  colIndices[numOwnedCols] = gid;
254  colValues[numOwnedCols] = values[localCol];
255  numOwnedCols++;
256  }
257 
258  // insert it into the new matrix
259  mat->InsertGlobalValues(contigRow, numOwnedCols, &colValues[0], &colIndices[0]);
260  }
261 
262  // fill it and automagically optimize the storage
263  mat->FillComplete(colMap, rowMap);
264 
265  return mat;
266 }
267 
268 // build a single subblock Epetra_CrsMatrix
269 void rebuildSubBlock(int i, int j, const Epetra_CrsMatrix &A, const std::vector<MapPair> &subMaps,
270  Epetra_CrsMatrix &mat) {
271  // get the number of variables families
272  int numVarFamily = subMaps.size();
273 
274  TEUCHOS_ASSERT(i >= 0 && i < numVarFamily);
275  TEUCHOS_ASSERT(j >= 0 && j < numVarFamily);
276 
277  const Epetra_Map &gRowMap = *subMaps[i].first; // new GIDs
278  const Epetra_Map &rowMap = *subMaps[i].second; // contiguous GIDs
279 
280  const RCP<Epetra_IntVector> plocal2ContigGIDs = getSubBlockColumnGIDs(A, subMaps[j]);
281  Epetra_IntVector &local2ContigGIDs = *plocal2ContigGIDs;
282 
283  mat.PutScalar(0.0);
284 
285  // get entry information
286  int numMyRows = rowMap.NumMyElements();
287  int maxNumEntries = A.MaxNumEntries();
288 
289  // for extraction
290  std::vector<int> indices(maxNumEntries);
291  std::vector<double> values(maxNumEntries);
292 
293  // for insertion
294  std::vector<int> colIndices(maxNumEntries);
295  std::vector<double> colValues(maxNumEntries);
296 
297  // insert each row into subblock
298  // let FillComplete handle column distribution
299  for (int localRow = 0; localRow < numMyRows; localRow++) {
300  int numEntries = -1;
301  int globalRow = gRowMap.GID(localRow);
302  int lid = A.RowMap().LID(globalRow);
303  int contigRow = rowMap.GID(localRow);
304  TEUCHOS_ASSERT(lid > -1);
305 
306  int err = A.ExtractMyRowCopy(lid, maxNumEntries, numEntries, &values[0], &indices[0]);
307  TEUCHOS_ASSERT(err == 0);
308 
309  int numOwnedCols = 0;
310  for (int localCol = 0; localCol < numEntries; localCol++) {
311  TEUCHOS_ASSERT(indices[localCol] > -1);
312 
313  // if global id is not owned by this column
314  int gid = local2ContigGIDs[indices[localCol]];
315  if (gid == -1) continue; // in contiguous row
316 
317  colIndices[numOwnedCols] = gid;
318  colValues[numOwnedCols] = values[localCol];
319  numOwnedCols++;
320  }
321 
322  // insert it into the new matrix
323  mat.SumIntoGlobalValues(contigRow, numOwnedCols, &colValues[0], &colIndices[0]);
324  }
325 }
326 
327 } // namespace Blocking
328 } // namespace Epetra
329 } // namespace Teko