Epetra Package Browser (Single Doxygen Collection) Development
Loading...
Searching...
No Matches
Epetra_CrsGraphData.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
44#include "Epetra_ConfigDefs.h"
45#include "Epetra_CrsGraphData.h"
46#include "Epetra_Import.h"
47#include "Epetra_Export.h"
48//#include "Epetra_ConfigDefs.h" //DATA_DEBUG
49
50//=============================================================================
52 // maps
53 : RowMap_(RowMap),
54 ColMap_(RowMap),
55 DomainMap_(RowMap),
56 RangeMap_(RowMap),
57 // importer & exporter
58 Importer_(0),
59 Exporter_(0),
60 // booleans
61 HaveColMap_(false),
62 Filled_(false),
63 Allocated_(false),
64 // for non-static profile, we insert always into sorted lists, so the
65 // graph will always be sorted. The same holds for the redundancies.
66 Sorted_(!StaticProfile),
67 StorageOptimized_(false),
68 NoRedundancies_(!StaticProfile),
69 IndicesAreGlobal_(false),
70 IndicesAreLocal_(false),
72 LowerTriangular_(true),
73 UpperTriangular_(true),
74 NoDiagonal_(true),
76 StaticProfile_(StaticProfile),
78
79 // ints
80 IndexBase_(RowMap.IndexBase64()),
82 NumGlobalBlockRows_(RowMap.NumGlobalElements64()),
86 NumMyBlockRows_(RowMap.NumMyElements()),
89 MaxRowDim_(RowMap.MaxElementSize()),
91 GlobalMaxRowDim_(RowMap.MaxElementSize()),
96 NumGlobalRows_(RowMap.NumGlobalPoints64()),
100 NumMyRows_(RowMap.NumMyPoints()),
108 IndexOffset_(0),
109 CV_(CV),
110 data(0)
111#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
112 ,LL_data(0)
113#endif
114{
115 if(RowMap.GlobalIndicesInt() == false && RowMap.GlobalIndicesLongLong() == false)
116 throw "Epetra_CrsGraphData::Epetra_CrsGraphData: cannot be called without any index type for RowMap";
117
118 data = new IndexData<int>(NumMyBlockRows_, ! StaticProfile);
119#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
120 LL_data = new IndexData<long long>(RowMap.GlobalIndicesLongLong() ? NumMyBlockRows_ : 0, ! StaticProfile);
121#endif
122 //cout << "--CRSGD created(rowmap ctr), addr: " << this << std::endl; //DATA_DEBUG
123}
124
125//=============================================================================
127 const Epetra_BlockMap& RowMap,
128 const Epetra_BlockMap& ColMap, bool StaticProfile)
129 // maps
130 : RowMap_(RowMap),
131 ColMap_(ColMap),
132 DomainMap_(ColMap),
133 RangeMap_(RowMap),
134 // importer & exporter
135 Importer_(0),
136 Exporter_(0),
137 // booleans
138 HaveColMap_(true),
139 Filled_(false),
140 Allocated_(false),
141 Sorted_(!StaticProfile),
142 StorageOptimized_(false),
143 NoRedundancies_(!StaticProfile),
144 IndicesAreGlobal_(false),
145 IndicesAreLocal_(false),
147 LowerTriangular_(true),
148 UpperTriangular_(true),
149 NoDiagonal_(true),
151 StaticProfile_(StaticProfile),
153 // ints
154 IndexBase_(RowMap.IndexBase64()),
156 NumGlobalBlockRows_(RowMap.NumGlobalElements64()),
157 NumGlobalBlockCols_(ColMap.NumGlobalElements64()),
159 NumMyEntries_(0),
160 NumMyBlockRows_(RowMap.NumMyElements()),
161 NumMyBlockCols_(ColMap.NumMyElements()),
163 MaxRowDim_(RowMap.MaxElementSize()),
164 MaxColDim_(ColMap.MaxElementSize()),
165 GlobalMaxRowDim_(RowMap.MaxElementSize()),
166 GlobalMaxColDim_(ColMap.MaxElementSize()),
170 NumGlobalRows_(RowMap.NumGlobalPoints64()),
171 NumGlobalCols_(ColMap.NumGlobalPoints64()),
174 NumMyRows_(RowMap.NumMyPoints()),
175 NumMyCols_(ColMap.NumMyPoints()),
182 IndexOffset_(0),
183 CV_(CV),
184 data(0)
185#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
186 ,LL_data(0)
187#endif
188{
189 if(RowMap.GlobalIndicesInt() == false && RowMap.GlobalIndicesLongLong() == false)
190 throw "Epetra_CrsGraphData::Epetra_CrsGraphData: cannot be called without any index type for RowMap";
191
192 if(!RowMap.GlobalIndicesTypeMatch(ColMap))
193 throw "Epetra_CrsGraphData::Epetra_CrsGraphData: cannot be called with different indices types for RowMap and ColMap";
194
195 data = new IndexData<int>(NumMyBlockRows_, ! StaticProfile);
196#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
197 LL_data = new IndexData<long long>(RowMap.GlobalIndicesLongLong() ? NumMyBlockRows_ : 0, ! StaticProfile);
198#endif
199 //cout << "--CRSGD created(rowmap&colmap ctr), addr: " << this << std::endl; //DATA_DEBUG
200}
201
202//=============================================================================
204
205 if(data->Indices_ != 0 && !StorageOptimized_) {
206 for (int i=0; i<NumMyBlockRows_; i++) {
207 data->Indices_[i] = 0;
208 }
209 delete[] data->Indices_;
210 data->Indices_ = 0;
211 }
212
213#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
214 if(LL_data->Indices_ != 0 && !StorageOptimized_) {
215 for (int i=0; i<NumMyBlockRows_; i++) {
216 LL_data->Indices_[i] = 0;
217 }
218 delete[] LL_data->Indices_;
219 LL_data->Indices_ = 0;
220 }
221#endif
222
223 if (data->TempColIndices_ != 0) {
224 delete [] data->TempColIndices_;
225 data->TempColIndices_ = 0;
226 }
227
228#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
229 if (LL_data->TempColIndices_ != 0) {
230 delete [] LL_data->TempColIndices_;
231 LL_data->TempColIndices_ = 0;
232 }
233#endif
234
235 delete data;
236#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
237 delete LL_data;
238#endif
239
240 if(Importer_ != 0) {
241 delete Importer_;
242 Importer_ = 0;
243 }
244
245 if(Exporter_ != 0) {
246 delete Exporter_;
247 Exporter_ = 0;
248 }
249
250 NumMyBlockRows_ = 0; // are these needed?
251 Filled_ = false; // they're about to go out of scope, after all
252 Allocated_ = false;
253
254 //cout << "--CRSGD destroyed, addr: " << this << std::endl; //DATA_DEBUG
255}
256
257//==========================================================================
259 // Create Import object for use by matrix classes. This is only needed if ColMap and DomainMap are different
260 if (!ColMap_.SameAs(DomainMap_)) {
261 if (Importer_ != 0) {
262 delete Importer_;
263 Importer_ = 0;
264 }
266 }
267
268 // Now see if we need to define an export map. This is only needed if RowMap and RangeMap are different
269 if (!RowMap_.SameAs(RangeMap_)) {
270 if (Exporter_ != 0) {
271 delete Exporter_;
272 Exporter_ = 0;
273 }
274 Exporter_ = new Epetra_Export(RowMap_, RangeMap_); // Create Export object.
275 }
276
277 return(0);
278}
279
280//==========================================================================
281int Epetra_CrsGraphData::ReAllocateAndCast(char*& UserPtr, int& Length, const int IntPacketSizeTimesNumTrans) {
282 if(IntPacketSizeTimesNumTrans > Length) {
283 if(Length > 0)
284 delete[] UserPtr;
285 Length = IntPacketSizeTimesNumTrans;
286 int* newPtr = new int[Length];
287 UserPtr = reinterpret_cast<char*> (newPtr);
288 }
289 return(0);
290}
291
292//==========================================================================
293void Epetra_CrsGraphData::Print(std::ostream& os, int level) const {
294 bool four_bit = (level >= 4); // 4-bit = BlockMaps
295 bool two_bit = ((level % 4) >= 2); // 2-bit = Indices
296 bool one_bit = ((level % 2) == 1); // 1-bit = Everything else
297
298 os << "\n***** CrsGraphData (output level " << level << ") *****" << std::endl;
299
300 if(four_bit) {
301 os << "RowMap_:\n" << RowMap_ << std::endl;
302 os << "ColMap_:\n" << ColMap_ << std::endl;
303 os << "DomainMap_:\n" << DomainMap_ << std::endl;
304 os << "RangeMap_:\n" << RangeMap_ << std::endl;
305 }
306
307 if(one_bit) {
308 os.width(26); os << "HaveColMap_: " << HaveColMap_;
309 os.width(25); os << "Filled_: " << Filled_;
310 os.width(25); os << "Allocated_: " << Allocated_;
311 os.width(25); os << "Sorted_: " << Sorted_ << std::endl;
312 os.width(26); os << "StorageOptimized_: " << StorageOptimized_;
313 os.width(25); os << "SortGhostsAssociatedWithEachProcessor_: " << SortGhostsAssociatedWithEachProcessor_;
314 os.width(25); os << "NoRedundancies_: " << NoRedundancies_;
315 os.width(25); os << "IndicesAreGlobal_: " << IndicesAreGlobal_;
316 os.width(25); os << "IndicesAreLocal_: " << IndicesAreLocal_ << std::endl;
317 os.width(26); os << "IndicesAreContiguous_: " << IndicesAreContiguous_;
318 os.width(25); os << "LowerTriangular_: " << LowerTriangular_;
319 os.width(25); os << "UpperTriangular_: " << UpperTriangular_;
320 os.width(25); os << "NoDiagonal_: " << NoDiagonal_ << std::endl;
321 os.width(25); os << "GlobalConstantsComputed_: " << GlobalConstantsComputed_ << std::endl;
322 os.width(25); os << "StaticProfile_: " << StaticProfile_ << std::endl << std::endl;
323
324 os.width(10); os << "NGBR_: " << NumGlobalBlockRows_;
325 os.width(10); os << "NGBC_: " << NumGlobalBlockCols_;
326 os.width(10); os << "NGBD_: " << NumGlobalBlockDiagonals_;
327 os.width(10); os << "NGE_: " << NumGlobalEntries_;
328 os.width(10); os << "NGR_: " << NumGlobalRows_;
329 os.width(10); os << "NGC_: " << NumGlobalCols_;
330 os.width(10); os << "NGD_: " << NumGlobalDiagonals_;
331 os.width(10); os << "NGN_: " << NumGlobalNonzeros_;
332 os.width(10); os << "IB_: " << IndexBase_ << std::endl;
333 os.width(10); os << "GMRD_: " << GlobalMaxRowDim_;
334 os.width(11); os << "GMCD_: " << GlobalMaxColDim_;
335 os.width(11); os << "GMNI_: " << GlobalMaxNumIndices_;
336 os.width(11); os << "NMBR_: " << NumMyBlockRows_;
337 os.width(10); os << "NMBC_: " << NumMyBlockCols_;
338 os.width(10); os << "NMBD_: " << NumMyBlockDiagonals_;
339 os.width(10); os << "NME_: " << NumMyEntries_;
340 os.width(10); os << "NMR_: " << NumMyRows_;
341 os.width(10); os << "CV_: " << CV_ << std::endl;
342 os.width(10); os << "NMC_: " << NumMyCols_;
343 os.width(10); os << "NMD_: " << NumMyDiagonals_;
344 os.width(10); os << "NMN_: " << NumMyNonzeros_;
345 os.width(10); os << "MRD_: " << MaxRowDim_;
346 os.width(11); os << "MCD_: " << MaxColDim_;
347 os.width(11); os << "MNI_: " << MaxNumIndices_;
348 os.width(11); os << "MNN_: " << MaxNumNonzeros_;
349 os.width(11); os << "GMNN_: " << GlobalMaxNumNonzeros_;
350 os.width(11); os << "RC: " << ReferenceCount() << std::endl << std::endl;
351
352 os << "NIPR_: " << NumIndicesPerRow_ << std::endl;
353 os << "NAIPR_: " << NumAllocatedIndicesPerRow_ << std::endl;
354 os << "IndexOffset_: " << IndexOffset_ << std::endl;
355 if(RowMap_.GlobalIndicesInt() || (RowMap_.GlobalIndicesLongLong() && IndicesAreLocal_))
356 os << "All_Indices_: " << data->All_Indices_ << std::endl;
357
358 if(RowMap_.GlobalIndicesLongLong() && IndicesAreGlobal_)
359#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
360 os << "All_Indices_: " << LL_data->All_Indices_ << std::endl;
361#else
362 throw "Epetra_CrsGraphData::Print: GlobalIndicesLongLong but no long long API";
363#endif
364 }
365
366 if(two_bit) {
367 if(RowMap_.GlobalIndicesInt() || (RowMap_.GlobalIndicesLongLong() && IndicesAreLocal_))
368 {
369 os << "Indices_: " << data->Indices_ << std::endl;
370 if(data->Indices_ != 0) {
371 for(int i = 0; i < NumMyBlockRows_; i++) {
372 os << "Indices_[" << i << "]: (" << data->Indices_[i] << ") ";
373 if(data->Indices_[i] != 0) {
374 for(int j = 0; j < NumAllocatedIndicesPerRow_[i]; j++)
375 os << data->Indices_[i][j] << " ";
376 }
377 os << std::endl;
378 }
379 }
380 }
381
382 if(RowMap_.GlobalIndicesLongLong() && IndicesAreGlobal_)
383 {
384#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
385 os << "Indices_: " << LL_data->Indices_ << std::endl;
386 if(LL_data->Indices_ != 0) {
387 for(int i = 0; i < NumMyBlockRows_; i++) {
388 os << "Indices_[" << i << "]: (" << LL_data->Indices_[i] << ") ";
389 if(LL_data->Indices_[i] != 0) {
390 for(int j = 0; j < NumAllocatedIndicesPerRow_[i]; j++)
391 os << LL_data->Indices_[i][j] << " ";
392 }
393 os << std::endl;
394 }
395 }
396#else
397 throw "Epetra_CrsGraphData::Print: GlobalIndicesLongLong but no long long API";
398#endif
399 }
400 }
401
402 os << "***** End CrsGraphData *****" << std::endl;
403}
404
405
406//==========================================================================
407template<typename int_type>
408void
410{
411 // first check the last element (or if line is still empty)
412 if ( (entries_.size()==0) || ( entries_.back() < Col) )
413 {
414 entries_.push_back(Col);
415 return;
416 }
417
418 // do a binary search to find the place where to insert:
419 typename std::vector<int_type>::iterator it = std::lower_bound(entries_.begin(),
420 entries_.end(),
421 Col);
422
423 // If this entry is a duplicate, exit immediately
424 if (*it == Col)
425 return;
426
427 // Insert at the right place in the vector. Vector grows automatically to
428 // fit elements. Always doubles its size.
429 entries_.insert(it, Col);
430}
431
432
433//==========================================================================
434template<typename int_type>
435void
437 const int_type *Indices)
438{
439 if (numCols == 0)
440 return;
441
442 // Check whether the indices are sorted. Can do more efficient then.
443 bool indicesAreSorted = true;
444 for (int i=1; i<numCols; ++i)
445 if (Indices[i] <= Indices[i-1]) {
446 indicesAreSorted = false;
447 break;
448 }
449
450 if (indicesAreSorted && numCols > 3) {
451 const int_type * curInput = &Indices[0];
452 int_type col = *curInput;
453 const int_type * endInput = &Indices[numCols];
454
455 // easy case: list of entries is empty or all entries are smaller than
456 // the ones to be inserted
457 if (entries_.size() == 0 || entries_.back() < col)
458 {
459 entries_.insert(entries_.end(), &Indices[0], &Indices[numCols]);
460 return;
461 }
462
463 // find a possible insertion point for the first entry. check whether
464 // the first entry is a duplicate before actually doing something.
465 typename std::vector<int_type>::iterator it =
466 std::lower_bound(entries_.begin(), entries_.end(), col);
467 while (*it == col) {
468 ++curInput;
469 if (curInput == endInput)
470 break;
471 col = *curInput;
472
473 // check the very next entry in the current array
474 ++it;
475 if (it == entries_.end())
476 break;
477 if (*it > col)
478 break;
479 if (*it == col)
480 continue;
481
482 // ok, it wasn't the very next one, do a binary search to find the
483 // insert point
484 it = std::lower_bound(it, entries_.end(), col);
485 if (it == entries_.end())
486 break;
487 }
488
489 // all input entries were duplicates.
490 if (curInput == endInput)
491 return;
492
493 // Resize vector by just inserting the list at the correct point. Note
494 // that the list will not yet be sorted, but rather have the insert
495 // indices in the middle and the old indices from the list on the
496 // end. Next we will have to merge the two lists.
497 const int pos1 = (int) (it - entries_.begin());
498 entries_.insert (it, curInput, endInput);
499 it = entries_.begin() + pos1;
500
501 // Now merge the two lists...
502 typename std::vector<int_type>::iterator it2 = it + (endInput - curInput);
503
504 // As long as there are indices both in the end of the entries list and
505 // in the input list, always continue with the smaller index.
506 while (curInput != endInput && it2 != entries_.end())
507 {
508 if (*curInput < *it2)
509 *it++ = *curInput++;
510 else if (*curInput == *it2)
511 {
512 *it++ = *it2++;
513 ++curInput;
514 }
515 else
516 *it++ = *it2++;
517 }
518 // in case there are indices left in the input list or in the end of
519 // entries, we have to use the entries that are left. Only one of the
520 // two while loops will actually be entered.
521 while (curInput != endInput)
522 *it++ = *curInput++;
523
524 while (it2 != entries_.end())
525 *it++ = *it2++;
526
527 // resize and return
528 const int new_size = (int) (it - entries_.begin());
529 entries_.resize (new_size);
530 return;
531 }
532
533 // for unsorted or just a few indices, go to the one-by-one entry
534 // function.
535 for (int i=0; i<numCols; ++i)
536 AddEntry(Indices[i]);
537}
538
539// explicit instantiation.
540template void Epetra_CrsGraphData::EntriesInOneRow<int>::AddEntry(const int Col);
541template void Epetra_CrsGraphData::EntriesInOneRow<int>::AddEntries(const int numCols, const int *Indices);
542
543#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
544template void Epetra_CrsGraphData::EntriesInOneRow<long long>::AddEntry(const long long Col);
545template void Epetra_CrsGraphData::EntriesInOneRow<long long>::AddEntries(const int numCols, const long long *Indices);
546#endif
Epetra_DataAccess
Epetra_BlockMap: A class for partitioning block element vectors and matrices.
bool GlobalIndicesTypeMatch(const Epetra_BlockMap &other) const
bool GlobalIndicesInt() const
Returns true if map create with int NumGlobalElements.
bool GlobalIndicesLongLong() const
Returns true if map create with long long NumGlobalElements.
IndexData< long long > * LL_data
int ReAllocateAndCast(char *&UserPtr, int &Length, const int IntPacketSizeTimesNumTrans)
called by PackAndPrepare
void Print(std::ostream &os, int level=3) const
Outputs state of almost all data members. (primarily used for testing purposes).
IndexData< int > * data
const Epetra_Import * Importer_
Epetra_IntSerialDenseVector NumIndicesPerRow_
Epetra_IntSerialDenseVector NumAllocatedIndicesPerRow_
int MakeImportExport()
called by FillComplete (and TransformToLocal)
Epetra_CrsGraphData(Epetra_DataAccess CV, const Epetra_BlockMap &RowMap, bool StaticProfile)
Epetra_CrsGraphData Default Constructor.
const Epetra_Export * Exporter_
Epetra_IntSerialDenseVector IndexOffset_
~Epetra_CrsGraphData()
Epetra_CrsGraphData Destructor.
int ReferenceCount() const
Get reference count.
Epetra_Export: This class builds an export object for efficient exporting of off-processor elements.
Epetra_Import: This class builds an import object for efficient importing of off-processor elements.
void AddEntry(const int_type col_num)
Add the given column number to this line.
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.