Epetra Package Browser (Single Doxygen Collection)  Development
Epetra_FECrsGraph.cpp
Go to the documentation of this file.
1 
2 //@HEADER
3 // ************************************************************************
4 //
5 // Epetra: Linear Algebra Services Package
6 // Copyright 2011 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
39 //
40 // ************************************************************************
41 //@HEADER
42 
43 #include "Epetra_ConfigDefs.h"
44 #include "Epetra_FECrsGraph.h"
45 #include "Epetra_Import.h"
46 #include "Epetra_Export.h"
47 #include "Epetra_Distributor.h"
48 #include "Epetra_Util.h"
49 #include "Epetra_Comm.h"
50 #include "Epetra_HashTable.h"
51 #include "Epetra_BlockMap.h"
52 #include "Epetra_Map.h"
53 #include "Epetra_RowMatrix.h"
56 #include "Epetra_OffsetIndex.h"
57 
58 //-------------------------------------------------------------------------------
60  const Epetra_BlockMap& rowMap,
61  int* numIndicesPerRow,
62  bool ignoreNonLocalEntries,
63  bool buildNonlocalGraph)
64  : Epetra_CrsGraph(CV, rowMap, numIndicesPerRow),
65  myFirstRow_(0),
66  myNumRows_(0),
67  ignoreNonLocalEntries_(ignoreNonLocalEntries),
68  nonlocalGraph_ (NULL),
69  buildNonlocalGraph_ (buildNonlocalGraph)
70 {
71 }
72 
73 //-------------------------------------------------------------------------------
75  const Epetra_BlockMap& rowMap,
76  int numIndicesPerRow,
77  bool ignoreNonLocalEntries,
78  bool buildNonlocalGraph)
79  : Epetra_CrsGraph(CV, rowMap, numIndicesPerRow),
80  myFirstRow_(0),
81  myNumRows_(0),
82  ignoreNonLocalEntries_(ignoreNonLocalEntries),
83  nonlocalGraph_ (NULL),
84  buildNonlocalGraph_ (buildNonlocalGraph)
85 {
86  myFirstRow_ = rowMap.MinMyGID64();
87  myNumRows_ = rowMap.NumMyElements();
88 }
89 
90 //-------------------------------------------------------------------------------
92  const Epetra_BlockMap& rowMap,
93  const Epetra_BlockMap& colMap,
94  int* numIndicesPerRow,
95  bool ignoreNonLocalEntries,
96  bool buildNonlocalGraph)
97  : Epetra_CrsGraph(CV, rowMap, colMap, numIndicesPerRow),
98  myFirstRow_(0),
99  myNumRows_(0),
100  ignoreNonLocalEntries_(ignoreNonLocalEntries),
101  nonlocalGraph_ (NULL),
102  buildNonlocalGraph_ (buildNonlocalGraph)
103 {
104  myFirstRow_ = rowMap.MinMyGID64();
105  myNumRows_ = rowMap.NumMyElements();
106 }
107 
108 //-------------------------------------------------------------------------------
110  const Epetra_BlockMap& rowMap,
111  const Epetra_BlockMap& colMap,
112  int numIndicesPerRow,
113  bool ignoreNonLocalEntries,
114  bool buildNonlocalGraph)
115  : Epetra_CrsGraph(CV, rowMap, colMap, numIndicesPerRow),
116  myFirstRow_(0),
117  myNumRows_(0),
118  ignoreNonLocalEntries_(ignoreNonLocalEntries),
119  nonlocalGraph_ (NULL),
120  buildNonlocalGraph_ (buildNonlocalGraph)
121 {
122  myFirstRow_ = rowMap.MinMyGID64();
123  myNumRows_ = rowMap.NumMyElements();
124 }
125 
126 //-------------------------------------------------------------------------------
128 {
129  DeleteMemory();
130 }
131 
132 //----------------------------------------------------------------------------
134 {
135  if (nonlocalGraph_ != 0)
136  delete nonlocalGraph_;
137  // nothing else to do here, since the STL map has an appropriate
138  // destructor
139 }
140 
141 //----------------------------------------------------------------------------
142 template<typename int_type>
143 int Epetra_FECrsGraph::InsertGlobalIndices(int numRows, const int_type* rows,
144  int numCols, const int_type* cols)
145 {
146  int returncode = 0;
147  int err = 0;
148 
149  Epetra_CrsGraph* thisgraph = static_cast<Epetra_CrsGraph*>(this);
150 
151  for(int i=0; i<numRows; ++i) {
152  const int LID = thisgraph->LRID(rows[i]);
153  if (LID > -1) {
154  thisgraph->SetIndicesAreGlobal(true);
155  err = thisgraph->InsertIndicesIntoSorted(LID, numCols,
156  const_cast<int_type*>(cols));
157  }
158  else {
159  nonlocalRowData<int_type>()[rows[i]].AddEntries(numCols,cols);
160  }
161 
162  if (err < 0) return (err);
163  if (err > 0) returncode = err;
164  }
165 
166  return(returncode);
167 }
168 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
169 int Epetra_FECrsGraph::InsertGlobalIndices(int numRows, const int* rows, int numCols, const int* cols)
170 {
171  if(RowMap().GlobalIndicesInt())
172  return InsertGlobalIndices<int>(numRows, rows, numCols, cols);
173  else
174  throw ReportError("Epetra_FECrsGraph::InsertGlobalIndices int version called for a matrix that is not int.", -1);
175 }
176 #endif
177 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
178 int Epetra_FECrsGraph::InsertGlobalIndices(int numRows, const long long* rows, int numCols, const long long* cols)
179 {
180  if(RowMap().GlobalIndicesLongLong())
181  return InsertGlobalIndices<long long>(numRows, rows, numCols, cols);
182  else
183  throw ReportError("Epetra_FECrsGraph::InsertGlobalIndices long long version called for a matrix that is not long long.", -1);
184 }
185 #endif
186 
187 //----------------------------------------------------------------------------
188 int Epetra_FECrsGraph::GlobalAssemble(bool callFillComplete)
189 {
190  return GlobalAssemble (static_cast<Epetra_Map&>(this->CrsGraphData_->RowMap_),
191  static_cast<Epetra_Map&>(this->CrsGraphData_->RowMap_),
192  callFillComplete);
193 }
194 
195 //----------------------------------------------------------------------------
196 template<typename int_type>
198  const Epetra_Map& range_map,
199  bool callFillComplete)
200 {
201  if (Map().Comm().NumProc() < 2 || ignoreNonLocalEntries_) {
202  if (callFillComplete) {
203  EPETRA_CHK_ERR( FillComplete(domain_map, range_map) );
204  }
205  return(0);
206  }
207 
208  //In this method we need to gather all the non-local (overlapping) data
209  //that's been input on each processor, into the
210  //non-overlapping distribution defined by the map that 'this' graph was
211  //constructed with.
212 
213  // First build a map that describes our nonlocal data.
214  // We'll use the arbitrary distribution constructor of Map.
215  // Start by extracting the column numbers from the STL map.
216 
217  std::map<int_type,Epetra_CrsGraphData::EntriesInOneRow<int_type> >& nonlocalRowData_var = nonlocalRowData<int_type>();
218 
219  const int numRows = (int) nonlocalRowData_var.size();
220  int_type * presentRowIndices = new int_type[numRows];
221  typename std::map<int_type,Epetra_CrsGraphData::EntriesInOneRow<int_type> >::iterator nonlocalRows
222  = nonlocalRowData<int_type>().begin();
223  for (int i=0 ; nonlocalRows != nonlocalRowData_var.end(); ++nonlocalRows, ++i)
224  presentRowIndices[i] = (int_type) nonlocalRows->first;
225 
226  Epetra_Map* sourceMap = new Epetra_Map((int_type) -1, (int) nonlocalRowData<int_type>().size(),
227  presentRowIndices,
228  (int_type) Map().IndexBase64(), Map().Comm());
229 
230  //If sourceMap has global size 0, then no nonlocal data exists and we can
231  //skip most of this function.
232  if (sourceMap->NumGlobalElements64() < 1) {
233  if (callFillComplete) {
234  EPETRA_CHK_ERR( FillComplete(domain_map, range_map) );
235  }
236  delete [] presentRowIndices;
237  delete sourceMap;
238  return(0);
239  }
240 
241  //We also need to build a column-map, containing the columns in our
242  //nonlocal data. To do that, create a list of all column-indices that
243  //occur in our nonlocal rows. This is most easily done using the
244  //EntriesInOneRow struct, since that is sorted.
246  for (nonlocalRows = nonlocalRowData_var.begin();
247  nonlocalRows != nonlocalRowData_var.end(); ++nonlocalRows)
248  allColumns.AddEntries((int) nonlocalRows->second.entries_.size(),
249  nonlocalRows->second.entries_.size() ? &nonlocalRows->second.entries_[0] : 0);
250 
251  Epetra_Map* colMap = new Epetra_Map((int_type) -1, (int) allColumns.entries_.size(),
252  allColumns.entries_.size() ? &allColumns.entries_[0] : 0,
253  (int_type) Map().IndexBase64(), Map().Comm());
254 
255  //now we need to create a graph with sourceMap and colMap, and fill it with
256  //our nonlocal data so we can then export it to the correct owning processors
257 
258  int * rowLengths = new int[numRows];
259  {
260  int i = 0;
261  for (nonlocalRows = nonlocalRowData_var.begin();
262  nonlocalRows != nonlocalRowData_var.end() ; ++nonlocalRows, ++i)
263  rowLengths[i] = (int) nonlocalRows->second.entries_.size();
264  }
265 
266  Epetra_CrsGraph* tempGrph = NULL;
267  if (buildNonlocalGraph_) {
268  nonlocalGraph_ = new Epetra_CrsGraph(Copy, *sourceMap, *colMap, rowLengths);
269  tempGrph = nonlocalGraph_;
270  }
271  else
272  tempGrph = new Epetra_CrsGraph(Copy, *sourceMap, *colMap, rowLengths);
273 
274  //Next we need to make sure the 'indices-are-global' attribute of tempGrph
275  //is set to true, in case this processor doesn't end up calling the
276  //InsertGlobalIndices method...
277 
278  tempGrph->SetIndicesAreGlobal(true);
279 
280  for (nonlocalRows = nonlocalRowData_var.begin();
281  nonlocalRows != nonlocalRowData_var.end(); ++nonlocalRows)
282  EPETRA_CHK_ERR( tempGrph->InsertGlobalIndices(nonlocalRows->first,
283  (int) nonlocalRows->second.entries_.size(),
284  nonlocalRows->second.entries_.size() ? &nonlocalRows->second.entries_[0] : 0) );
285 
286 
287  //Now we need to call FillComplete on our temp graph. We need to
288  //pass a DomainMap and RangeMap.
289 
290  EPETRA_CHK_ERR(tempGrph->FillComplete(domain_map, range_map));
291 
293  tempGrph->OptimizeStorage();
294 
295  Epetra_Export* exporter = new Epetra_Export(*sourceMap, RowMap());
296 
297  EPETRA_CHK_ERR(Export(*tempGrph, *exporter, Add));
298 
299  if(callFillComplete) {
300  EPETRA_CHK_ERR(FillComplete(domain_map, range_map));
301  }
302 
303  //now reset the values in our nonlocal data
304  for (nonlocalRows = nonlocalRowData_var.begin();
305  nonlocalRows != nonlocalRowData_var.end(); ++nonlocalRows)
306  nonlocalRows->second.entries_.clear();
307  nonlocalRowData_var.clear();
308 
309  delete [] rowLengths;
310  delete [] presentRowIndices;
311  delete exporter;
312  if (!buildNonlocalGraph_)
313  delete tempGrph;
314  delete sourceMap;
315  delete colMap;
316 
317  return(0);
318 }
319 
321  const Epetra_Map& range_map,
322  bool callFillComplete)
323 {
324  if(!domain_map.GlobalIndicesTypeMatch(range_map))
325  throw ReportError("Epetra_FECrsGraph::GlobalAssemble: cannot be called with different indices types for domainMap and rangeMap", -1);
326 
327  if(!RowMap().GlobalIndicesTypeMatch(domain_map))
328  throw ReportError("Epetra_FECrsGraph::GlobalAssemble: cannot be called with different indices types for row map and incoming rangeMap", -1);
329 
330  if(RowMap().GlobalIndicesInt())
331 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
332  return GlobalAssemble<int>(domain_map, range_map, callFillComplete);
333 #else
334  throw ReportError("Epetra_FECrsGraph::GlobalAssemble: ERROR, GlobalIndicesInt but no API for it.",-1);
335 #endif
336 
337  if(RowMap().GlobalIndicesLongLong())
338 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
339  return GlobalAssemble<long long>(domain_map, range_map, callFillComplete);
340 #else
341  throw ReportError("Epetra_FECrsGraph::GlobalAssemble: ERROR, GlobalIndicesLongLong but no API for it.",-1);
342 #endif
343 
344  throw ReportError("Epetra_FECrsGraph::GlobalAssemble: cannot determine global index type", -1);
345 }
const Epetra_BlockMap & Map() const
Returns the address of the Epetra_BlockMap for this multi-vector.
Epetra_Map: A class for partitioning vectors and matrices.
Definition: Epetra_Map.h:119
int InsertGlobalIndices(int numRows, const int *rows, int numCols, const int *cols)
Insert a rectangular, dense &#39;submatrix&#39; of entries (matrix nonzero positions) into the graph...
int FillComplete()
Tranform to local index space. Perform other operations to allow optimal matrix operations.
Store some data for each row describing which entries of this row are nonzero.
Epetra_CrsGraph * nonlocalGraph_
A CrsGraph holding non-local data in case the respective flag is set in the constructor.
long long MinMyGID64() const
const Epetra_Comm & Comm() const
Returns a pointer to the Epetra_Comm communicator associated with this graph.
long long IndexBase64() const
#define EPETRA_CHK_ERR(a)
Epetra_Export: This class builds an export object for efficient exporting of off-processor elements...
Definition: Epetra_Export.h:62
int GlobalAssemble(bool callFillComplete=true)
Gather any overlapping/shared data into the non-overlapping partitioning defined by the Map that was ...
Epetra_FECrsGraph(Epetra_DataAccess CV, const Epetra_BlockMap &RowMap, int *NumIndicesPerRow, bool ignoreNonLocalEntries=false, bool buildNonlocalGraph=false)
Constructor.
virtual ~Epetra_FECrsGraph()
Constructor.
virtual int ReportError(const std::string Message, int ErrorCode) const
Error reporting method.
long long NumGlobalElements64() const
const Epetra_BlockMap & RowMap() const
Returns the RowMap associated with this graph.
Epetra_CrsGraphData * CrsGraphData_
int Export(const Epetra_SrcDistObject &A, const Epetra_Import &Importer, Epetra_CombineMode CombineMode, const Epetra_OffsetIndex *Indexor=0)
Exports an Epetra_DistObject using the Epetra_Import object.
Epetra_CrsGraph(Epetra_DataAccess CV, const Epetra_BlockMap &RowMap, const int *NumIndicesPerRow, bool StaticProfile=false)
Epetra_CrsGraph constuctor with variable number of indices per row.
void SetIndicesAreGlobal(bool Flag)
int OptimizeStorage()
Make consecutive row index sections contiguous, minimize internal storage used for constructing graph...
bool GlobalIndicesInt() const
Returns true if map create with int NumGlobalElements.
int NumMyElements() const
Number of elements on the calling processor.
Epetra_BlockMap: A class for partitioning block element vectors and matrices.
const Epetra_Comm & Comm() const
Access function for Epetra_Comm communicator.
std::vector< int_type > entries_
Storage for the column indices of this row.
int InsertGlobalIndices(int GlobalRow, int NumIndices, int *Indices)
Enter a list of elements in a specified global row of the graph.
void AddEntries(const int n_cols, const int_type *col_nums)
Add many entries to one row.
long long IndexBase64() const
bool GlobalIndicesTypeMatch(const Epetra_BlockMap &other) const
Epetra_DataAccess
int InsertIndicesIntoSorted(int Row, int NumIndices, int *Indices)
int LRID(int GRID_in) const
Returns the local row index for given global row index, returns -1 if no local row for this global ro...
Epetra_CrsGraph: A class for constructing and using sparse compressed row graphs. ...