Epetra Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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  Epetra_Util_data_ptr(nonlocalRows->second.entries_));
250 
251  Epetra_Map* colMap = new Epetra_Map((int_type) -1, (int) allColumns.entries_.size(),
252  Epetra_Util_data_ptr(allColumns.entries_),
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  Epetra_Util_data_ptr(nonlocalRows->second.entries_)) );
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 
320 int Epetra_FECrsGraph::GlobalAssemble(const Epetra_Map& domain_map,
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 }
long long MinMyGID64() const
Epetra_Map: A class for partitioning vectors and matrices.
Definition: Epetra_Map.h:127
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.
const Epetra_Comm & Comm() const
Returns a pointer to the Epetra_Comm communicator associated with this graph.
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 IndexBase64() const
long long NumGlobalElements64() const
T * Epetra_Util_data_ptr(std::vector< T > &vec)
Function that returns either a pointer to the first entry in the vector or, if the vector is empty...
Definition: Epetra_Util.h:430
#define EPETRA_CHK_ERR(a)
Epetra_Export: This class builds an export object for efficient exporting of off-processor elements...
Definition: Epetra_Export.h:70
int GlobalAssemble(bool callFillComplete=true)
Gather any overlapping/shared data into the non-overlapping partitioning defined by the Map that was ...
bool GlobalIndicesInt() const
Returns true if map create with int NumGlobalElements.
Epetra_FECrsGraph(Epetra_DataAccess CV, const Epetra_BlockMap &RowMap, int *NumIndicesPerRow, bool ignoreNonLocalEntries=false, bool buildNonlocalGraph=false)
Constructor.
virtual ~Epetra_FECrsGraph()
Constructor.
Epetra_CrsGraphData * CrsGraphData_
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...
int NumMyElements() const
Number of elements on the calling processor.
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...
Epetra_BlockMap: A class for partitioning block element vectors and matrices.
const Epetra_BlockMap & RowMap() const
Returns the RowMap associated with this graph.
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.
const Epetra_Comm & Comm() const
Access function for Epetra_Comm communicator.
void AddEntries(const int n_cols, const int_type *col_nums)
Add many entries to one row.
virtual int ReportError(const std::string Message, int ErrorCode) const
Error reporting method.
long long IndexBase64() const
Epetra_DataAccess
int InsertIndicesIntoSorted(int Row, int NumIndices, int *Indices)
Epetra_CrsGraph: A class for constructing and using sparse compressed row graphs. ...
const Epetra_BlockMap & Map() const
Returns the address of the Epetra_BlockMap for this multi-vector.
bool GlobalIndicesTypeMatch(const Epetra_BlockMap &other) const