Epetra Package Browser (Single Doxygen Collection) Development
Loading...
Searching...
No Matches
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//-------------------------------------------------------------------------------
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//----------------------------------------------------------------------------
142template<typename int_type>
143int 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
169int 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
178int 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//----------------------------------------------------------------------------
188int 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//----------------------------------------------------------------------------
196template<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;
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;
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}
#define EPETRA_CHK_ERR(a)
Epetra_DataAccess
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,...
Epetra_BlockMap: A class for partitioning block element vectors and matrices.
bool GlobalIndicesTypeMatch(const Epetra_BlockMap &other) const
long long NumGlobalElements64() const
long long MinMyGID64() const
int NumMyElements() const
Number of elements on the calling processor.
Epetra_CrsGraph: A class for constructing and using sparse compressed row graphs.
int InsertGlobalIndices(int GlobalRow, int NumIndices, int *Indices)
Enter a list of elements in a specified global row of the graph.
friend class Epetra_FECrsGraph
const Epetra_BlockMap & RowMap() const
Returns the RowMap associated with this graph.
Epetra_CrsGraphData * CrsGraphData_
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.
void SetIndicesAreGlobal(bool Flag)
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.
long long IndexBase64() const
int InsertIndicesIntoSorted(int Row, int NumIndices, int *Indices)
int OptimizeStorage()
Make consecutive row index sections contiguous, minimize internal storage used for constructing graph...
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...
const Epetra_BlockMap & Map() const
Returns the address of the Epetra_BlockMap for this multi-vector.
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_Export: This class builds an export object for efficient exporting of off-processor elements.
int InsertGlobalIndices(int numRows, const int *rows, int numCols, const int *cols)
Insert a rectangular, dense 'submatrix' of entries (matrix nonzero positions) into the graph.
virtual ~Epetra_FECrsGraph()
Constructor.
Epetra_CrsGraph * nonlocalGraph_
A CrsGraph holding non-local data in case the respective flag is set in the constructor.
int GlobalAssemble(bool callFillComplete=true)
Gather any overlapping/shared data into the non-overlapping partitioning defined by the Map that was ...
Epetra_Map: A class for partitioning vectors and matrices.
Definition Epetra_Map.h:119
virtual int ReportError(const std::string Message, int ErrorCode) const
Error reporting method.
Store some data for each row describing which entries of this row are nonzero.
void AddEntries(const int n_cols, const int_type *col_nums)
Add many entries to one row.
std::vector< int_type > entries_
Storage for the column indices of this row.