From 7d9e18793f54edd7ca9cb2622e4d69cfed91c8a9 Mon Sep 17 00:00:00 2001 From: "K. Devine" Date: Wed, 8 Jul 2020 10:30:19 -0500 Subject: [PATCH] tpetra: removing computation of unused fields lowerTriangular_, upperTriangular_, nodeNumDiags_, globalNumDiags_ for #7446, #2630, #2658 --- .../tpetra/core/src/Tpetra_CrsGraph_decl.hpp | 47 +- .../tpetra/core/src/Tpetra_CrsGraph_def.hpp | 145 +-- .../tpetra/core/src/Tpetra_CrsMatrix_def.hpp | 6 +- .../test/CrsGraph/CrsGraph_UnitTests0.cpp | 888 +++++++----------- .../Tpetra_Test_CrsMatrix_WithGraph.hpp | 47 - .../CrsGraph/Xpetra_TpetraCrsGraph_def.hpp | 3 +- 6 files changed, 369 insertions(+), 767 deletions(-) diff --git a/packages/tpetra/core/src/Tpetra_CrsGraph_decl.hpp b/packages/tpetra/core/src/Tpetra_CrsGraph_decl.hpp index 4f2b162eb369..e4644c8f4d2b 100644 --- a/packages/tpetra/core/src/Tpetra_CrsGraph_decl.hpp +++ b/packages/tpetra/core/src/Tpetra_CrsGraph_decl.hpp @@ -1937,7 +1937,6 @@ namespace Tpetra { /// Global constants include: /// /// @@ -1946,17 +1945,7 @@ namespace Tpetra { ///
  • globalNumEntries_
  • ///
  • globalMaxNumRowEntries_
  • /// - /// - /// Only compute the following if the input argument - /// computeLocalTriangularConstants is true: - /// - /// The bool input argument comes from an input ParameterList bool - /// parameter "compute local triangular constants", named - /// analogously to the existing bool parameter "compute global - /// constants". - void computeGlobalConstants (const bool computeLocalTriangularConstants); + void computeGlobalConstants (); protected: /// \brief Compute local constants, if they have not yet been computed. @@ -1968,9 +1957,6 @@ namespace Tpetra { /// /// Local constants include: /// /// @@ -1979,21 +1965,9 @@ namespace Tpetra { ///
  • nodeMaxNumRowEntries_
  • /// /// - /// Only compute the following if the input argument - /// computeLocalTriangularConstants is true: - /// - /// The bool input argument comes from an input ParameterList bool - /// parameter "compute local triangular constants", named - /// analogously to the existing bool parameter "compute global - /// constants". - /// /// computeGlobalConstants calls this method, if global constants /// have not yet been computed. - void computeLocalConstants (const bool computeLocalTriangularConstants); + void computeLocalConstants (); /// \brief Get information about the locally owned row with local /// index myRow. @@ -2159,11 +2133,6 @@ namespace Tpetra { //! Local graph; only initialized after first fillComplete() call. local_graph_type lclGraph_; - /// \brief Local number of (populated) diagonal entries. - /// - /// Computed in computeLocalConstants(); only valid when isFillComplete(). - size_t nodeNumDiags_ = Teuchos::OrdinalTraits::invalid(); - /// \brief Local maximum of the number of entries in each row. /// /// Computed in computeLocalConstants; only valid when @@ -2177,13 +2146,6 @@ namespace Tpetra { global_size_t globalNumEntries_ = Teuchos::OrdinalTraits::invalid(); - /// \brief Global number of (populated) diagonal entries. - /// - /// Computed in computeGlobalConstants; only valid when - /// isFillComplete() is true. - global_size_t globalNumDiags_ = - Teuchos::OrdinalTraits::invalid(); - /// \brief Global maximum of the number of entries in each row. /// /// Computed in computeGlobalConstants(); only valid when @@ -2321,10 +2283,6 @@ namespace Tpetra { bool indicesAreGlobal_ = false; bool fillComplete_ = false; - //! Whether the graph is locally lower triangular. - bool lowerTriangular_ = false; - //! Whether the graph is locally upper triangular. - bool upperTriangular_ = false; //! Whether the graph's indices are sorted in each row, on this process. bool indicesAreSorted_ = true; /// \brief Whether the graph's indices are non-redundant (merged) @@ -2361,7 +2319,6 @@ namespace Tpetra { static bool getDebug(); /// \brief Whether to do extra debug checks. - /// /// This comes from Tpetra::Details::Behavior::debug("CrsGraph"). bool debug_ = getDebug(); diff --git a/packages/tpetra/core/src/Tpetra_CrsGraph_def.hpp b/packages/tpetra/core/src/Tpetra_CrsGraph_def.hpp index facc53e66ed6..6c5e52ef4e9e 100644 --- a/packages/tpetra/core/src/Tpetra_CrsGraph_def.hpp +++ b/packages/tpetra/core/src/Tpetra_CrsGraph_def.hpp @@ -64,7 +64,6 @@ #include "Tpetra_Import_Util2.hpp" #include "Tpetra_Details_packCrsGraph.hpp" #include "Tpetra_Details_unpackCrsGraphAndCombine.hpp" -#include "Tpetra_Details_determineLocalTriangularStructure.hpp" #include "Tpetra_Details_CrsPadding.hpp" #include "Tpetra_Util.hpp" #include @@ -655,11 +654,9 @@ namespace Tpetra { const bool callComputeGlobalConstants = params.get () == nullptr || params->get ("compute global constants", true); - const bool computeLocalTriangularConstants = params.get () == nullptr || - params->get ("compute local triangular constants", true); if (callComputeGlobalConstants) { - this->computeGlobalConstants (computeLocalTriangularConstants); + this->computeGlobalConstants (); } this->fillComplete_ = true; this->checkInternalState (); @@ -710,11 +707,8 @@ namespace Tpetra { const bool callComputeGlobalConstants = params.get () == nullptr || params->get ("compute global constants", true); - const bool computeLocalTriangularConstants = - params.get () == nullptr || - params->get ("compute local triangular constants", true); if (callComputeGlobalConstants) { - this->computeGlobalConstants (computeLocalTriangularConstants); + this->computeGlobalConstants (); } fillComplete_ = true; checkInternalState (); @@ -2069,7 +2063,6 @@ namespace Tpetra { const auto INV = Teuchos::OrdinalTraits::invalid(); globalNumEntries_ = INV; - globalNumDiags_ = INV; globalMaxNumRowEntries_ = INV; haveGlobalConstants_ = false; } @@ -3378,8 +3371,6 @@ namespace Tpetra { { clearGlobalConstants(); if (params != Teuchos::null) this->setParameterList (params); - lowerTriangular_ = false; - upperTriangular_ = false; // either still sorted/merged or initially sorted/merged indicesAreSorted_ = true; noRedundancies_ = true; @@ -3619,13 +3610,11 @@ namespace Tpetra { const bool callComputeGlobalConstants = params.get () == nullptr || params->get ("compute global constants", true); - const bool computeLocalTriangularConstants = params.get () == nullptr || - params->get ("compute local triangular constants", true); if (callComputeGlobalConstants) { - this->computeGlobalConstants (computeLocalTriangularConstants); + this->computeGlobalConstants (); } else { - this->computeLocalConstants (computeLocalTriangularConstants); + this->computeLocalConstants (); } this->fillComplete_ = true; this->checkInternalState (); @@ -3754,22 +3743,20 @@ namespace Tpetra { const bool callComputeGlobalConstants = params.get () == nullptr || params->get ("compute global constants", true); - const bool computeLocalTriangularConstants = params.get () == nullptr || - params->get ("compute local triangular constants", true); if (callComputeGlobalConstants) { #ifdef HAVE_TPETRA_MMM_TIMINGS MM = Teuchos::null; MM = Teuchos::rcp(new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string("ESFC-G-cGC (const)")))); #endif // HAVE_TPETRA_MMM_TIMINGS - this->computeGlobalConstants (computeLocalTriangularConstants); + this->computeGlobalConstants (); } else { #ifdef HAVE_TPETRA_MMM_TIMINGS MM = Teuchos::null; MM = Teuchos::rcp(new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string("ESFC-G-cGC (noconst)")))); #endif // HAVE_TPETRA_MMM_TIMINGS - this->computeLocalConstants (computeLocalTriangularConstants); + this->computeLocalConstants (); } fillComplete_ = true; @@ -4327,7 +4314,7 @@ namespace Tpetra { template void CrsGraph:: - computeGlobalConstants (const bool computeLocalTriangularConstants) + computeGlobalConstants () { using ::Tpetra::Details::ProfilingRegion; using Teuchos::ArrayView; @@ -4337,7 +4324,7 @@ namespace Tpetra { ProfilingRegion regionCGC ("Tpetra::CrsGraph::computeGlobalConstants"); - this->computeLocalConstants (computeLocalTriangularConstants); + this->computeLocalConstants (); // Compute global constants from local constants. Processes that // already have local constants still participate in the @@ -4356,29 +4343,11 @@ namespace Tpetra { // good idea to use nonblocking all-reduces (MPI 3), so that we // don't have to wait around for the first one to finish before // starting the second one. - GST lcl[2], gbl[2]; - lcl[0] = static_cast (this->getNodeNumEntries ()); - - // mfh 03 May 2018: nodeNumDiags_ is invalid if - // computeLocalTriangularConstants is false, but there's no - // practical network latency difference between an all-reduce of - // length 1 and an all-reduce of length 2, so it's not worth - // distinguishing between the two. However, we do want to avoid - // integer overflow, so we'll just set the input local sum to - // zero in that case. - lcl[1] = computeLocalTriangularConstants ? - static_cast (this->nodeNumDiags_) : - static_cast (0); - - reduceAll (comm, Teuchos::REDUCE_SUM, 2, lcl, gbl); - this->globalNumEntries_ = gbl[0]; - - // mfh 03 May 2018: If not computing local triangular - // properties, users want this to be invalid, not just zero. - // This will help with debugging. - this->globalNumDiags_ = computeLocalTriangularConstants ? - gbl[1] : - Teuchos::OrdinalTraits::invalid (); + GST lcl, gbl; + lcl = static_cast (this->getNodeNumEntries ()); + + reduceAll (comm, Teuchos::REDUCE_SUM, 1, &lcl, &gbl); + this->globalNumEntries_ = gbl; const GST lclMaxNumRowEnt = static_cast (this->nodeMaxNumRowEntries_); reduceAll (comm, Teuchos::REDUCE_MAX, lclMaxNumRowEnt, @@ -4391,9 +4360,8 @@ namespace Tpetra { template void CrsGraph:: - computeLocalConstants (const bool computeLocalTriangularConstants) + computeLocalConstants () { - using ::Tpetra::Details::determineLocalTriangularStructure; using ::Tpetra::Details::ProfilingRegion; ProfilingRegion regionCLC ("Tpetra::CrsGraph::computeLocalConstants"); @@ -4402,63 +4370,30 @@ namespace Tpetra { } // Reset local properties - this->lowerTriangular_ = false; - this->upperTriangular_ = false; this->nodeMaxNumRowEntries_ = Teuchos::OrdinalTraits::invalid(); - this->nodeNumDiags_ = Teuchos::OrdinalTraits::invalid(); - - if (computeLocalTriangularConstants) { - const bool hasRowAndColumnMaps = - this->rowMap_.get () != nullptr && this->colMap_.get () != nullptr; - if (hasRowAndColumnMaps) { - auto lclRowMap = this->rowMap_->getLocalMap (); - auto lclColMap = this->colMap_->getLocalMap (); - - // KJ: We need this fence even though it passes tests. Map uses kokkos - // view with relying on UVM (it does not have a dual view context). So, - // the values can be touched somewhere and we need to make sure the - // updates should be done before we use it. - execution_space().fence (); - - // mfh 01 May 2018: See GitHub Issue #2658. - constexpr bool ignoreMapsForTriStruct = true; - auto result = - determineLocalTriangularStructure (this->lclGraph_, lclRowMap, - lclColMap, ignoreMapsForTriStruct); - this->lowerTriangular_ = result.couldBeLowerTriangular; - this->upperTriangular_ = result.couldBeUpperTriangular; - this->nodeMaxNumRowEntries_ = result.maxNumRowEnt; - this->nodeNumDiags_ = result.diagCount; - } - else { - this->nodeMaxNumRowEntries_ = 0; - this->nodeNumDiags_ = 0; - } - } - else { - using LO = local_ordinal_type; - // KJ: This one is a bit different from the above. Conservatively thinking, - // we also need the fence here as lclGraph_.row_map is on UVM and it can be - // still updated. In practice, the local graph construction should be done - // before this is called. This routine is computeLocalConstants. If we want - // a better code, we need a flag stating that the local graph is completed - // and safe to use it without fence. - // For now, I recommend to put the fence. Defining the state of local - // object can be improvements in the code. - execution_space().fence (); - - auto ptr = this->lclGraph_.row_map; - const LO lclNumRows = ptr.extent(0) == 0 ? - static_cast (0) : - (static_cast (ptr.extent(0)) - static_cast (1)); - - const LO lclMaxNumRowEnt = - ::Tpetra::Details::maxDifference ("Tpetra::CrsGraph: nodeMaxNumRowEntries", - ptr, lclNumRows); - this->nodeMaxNumRowEntries_ = static_cast (lclMaxNumRowEnt); - } + using LO = local_ordinal_type; + + // KJ: This one is a bit different from the above. Conservatively thinking, + // we also need the fence here as lclGraph_.row_map is on UVM and it can be + // still updated. In practice, the local graph construction should be done + // before this is called. This routine is computeLocalConstants. If we want + // a better code, we need a flag stating that the local graph is completed + // and safe to use it without fence. + // For now, I recommend to put the fence. Defining the state of local + // object can be improvements in the code. + execution_space().fence (); + + auto ptr = this->lclGraph_.row_map; + const LO lclNumRows = ptr.extent(0) == 0 ? + static_cast (0) : + (static_cast (ptr.extent(0)) - static_cast (1)); + + const LO lclMaxNumRowEnt = + ::Tpetra::Details::maxDifference ("Tpetra::CrsGraph: nodeMaxNumRowEntries", + ptr, lclNumRows); + this->nodeMaxNumRowEntries_ = static_cast (lclMaxNumRowEnt); this->haveLocalConstants_ = true; } @@ -4914,7 +4849,6 @@ namespace Tpetra { if (myImageID == 0) out << this->description() << std::endl; // O(1) globals, minus what was already printed by description() if (isFillComplete() && myImageID == 0) { - out << "Global number of diagonals = " << globalNumDiags_ << std::endl; out << "Global max number of row entries = " << globalMaxNumRowEntries_ << std::endl; } // constituent objects @@ -4940,7 +4874,6 @@ namespace Tpetra { if (myImageID == imageCtr) { out << "Node ID = " << imageCtr << std::endl << "Node number of entries = " << this->getNodeNumEntries () << std::endl - << "Node number of diagonals = " << nodeNumDiags_ << std::endl << "Node max number of entries = " << nodeMaxNumRowEntries_ << std::endl; if (! indicesAreAllocated ()) { out << "Indices are not allocated." << std::endl; @@ -7601,11 +7534,9 @@ namespace Tpetra { std::swap(graph.lclGraph_, this->lclGraph_); - std::swap(graph.nodeNumDiags_, this->nodeNumDiags_); std::swap(graph.nodeMaxNumRowEntries_, this->nodeMaxNumRowEntries_); std::swap(graph.globalNumEntries_, this->globalNumEntries_); - std::swap(graph.globalNumDiags_, this->globalNumDiags_); std::swap(graph.globalMaxNumRowEntries_, this->globalMaxNumRowEntries_); std::swap(graph.numAllocForAllRows_, this->numAllocForAllRows_); @@ -7621,8 +7552,6 @@ namespace Tpetra { std::swap(graph.indicesAreLocal_, this->indicesAreLocal_); std::swap(graph.indicesAreGlobal_, this->indicesAreGlobal_); std::swap(graph.fillComplete_, this->fillComplete_); - std::swap(graph.lowerTriangular_, this->lowerTriangular_); - std::swap(graph.upperTriangular_, this->upperTriangular_); std::swap(graph.indicesAreSorted_, this->indicesAreSorted_); std::swap(graph.noRedundancies_, this->noRedundancies_); std::swap(graph.haveLocalConstants_, this->haveLocalConstants_); @@ -7672,11 +7601,9 @@ namespace Tpetra { output = this->rangeMap_->isSameAs( *(graph.rangeMap_) ) ? output : false; output = this->domainMap_->isSameAs( *(graph.domainMap_) ) ? output : false; - output = this->nodeNumDiags_ == graph.nodeNumDiags_ ? output : false; output = this->nodeMaxNumRowEntries_ == graph.nodeMaxNumRowEntries_ ? output : false; output = this->globalNumEntries_ == graph.globalNumEntries_ ? output : false; - output = this->globalNumDiags_ == graph.globalNumDiags_ ? output : false; output = this->globalMaxNumRowEntries_ == graph.globalMaxNumRowEntries_ ? output : false; output = this->numAllocForAllRows_ == graph.numAllocForAllRows_ ? output : false; @@ -7687,8 +7614,6 @@ namespace Tpetra { output = this->indicesAreLocal_ == graph.indicesAreLocal_ ? output : false; output = this->indicesAreGlobal_ == graph.indicesAreGlobal_ ? output : false; output = this->fillComplete_ == graph.fillComplete_ ? output : false; - output = this->lowerTriangular_ == graph.lowerTriangular_ ? output : false; - output = this->upperTriangular_ == graph.upperTriangular_ ? output : false; output = this->indicesAreSorted_ == graph.indicesAreSorted_ ? output : false; output = this->noRedundancies_ == graph.noRedundancies_ ? output : false; output = this->haveLocalConstants_ == graph.haveLocalConstants_ ? output : false; diff --git a/packages/tpetra/core/src/Tpetra_CrsMatrix_def.hpp b/packages/tpetra/core/src/Tpetra_CrsMatrix_def.hpp index 25b88cf5fd3c..c46c0d19f308 100644 --- a/packages/tpetra/core/src/Tpetra_CrsMatrix_def.hpp +++ b/packages/tpetra/core/src/Tpetra_CrsMatrix_def.hpp @@ -4856,13 +4856,11 @@ namespace Tpetra { const bool callGraphComputeGlobalConstants = params.get () == nullptr || params->get ("compute global constants", true); - const bool computeLocalTriangularConstants = params.get () == nullptr || - params->get ("compute local triangular constants", true); if (callGraphComputeGlobalConstants) { - this->myGraph_->computeGlobalConstants (computeLocalTriangularConstants); + this->myGraph_->computeGlobalConstants (); } else { - this->myGraph_->computeLocalConstants (computeLocalTriangularConstants); + this->myGraph_->computeLocalConstants (); } this->myGraph_->fillComplete_ = true; this->myGraph_->checkInternalState (); diff --git a/packages/tpetra/core/test/CrsGraph/CrsGraph_UnitTests0.cpp b/packages/tpetra/core/test/CrsGraph/CrsGraph_UnitTests0.cpp index f2b976e957b3..6d7b46ff0062 100644 --- a/packages/tpetra/core/test/CrsGraph/CrsGraph_UnitTests0.cpp +++ b/packages/tpetra/core/test/CrsGraph/CrsGraph_UnitTests0.cpp @@ -41,26 +41,10 @@ #include "Tpetra_CrsGraph.hpp" #include "Tpetra_Details_Behavior.hpp" -#include "Tpetra_Details_determineLocalTriangularStructure.hpp" #include "Tpetra_TestingUtilities.hpp" namespace { // (anonymous) - template - Tpetra::Details::LocalTriangularStructureResult - getLocalTriangularStructure (const Tpetra::RowGraph& G) - { - using Tpetra::Details::determineLocalTriangularStructure; - using crs_graph_type = Tpetra::CrsGraph; - - const crs_graph_type& G_crs = dynamic_cast (G); - - auto G_lcl = G_crs.getLocalGraph (); - auto lclRowMap = G.getRowMap ()->getLocalMap (); - auto lclColMap = G.getColMap ()->getLocalMap (); - return determineLocalTriangularStructure (G_lcl, lclRowMap, lclColMap, true); - } - using Tpetra::ProfileType; using Tpetra::StaticProfile; using Teuchos::arcp; @@ -249,40 +233,26 @@ namespace { // (anonymous) RCP map = rcp (new map_type (INVALID, numLocal, indexBase, comm)); - // Test (GitHub Issue) #2565 fix, while we're at it. - // - // clts == 0: Don't set "compute local triangular constants" - // clts == 1: Set "compute local triangular constants" to false - // clts == 2: Set "compute local triangular constants" to true - for (int clts : {0, 1, 2}) { - // send in a parameterlist, check the defaults - RCP params = parameterList(); - if (clts == 1) { - params->set ("compute local triangular constants", false); - } - else if (clts == 2) { - params->set ("compute local triangular constants", true); - } - - // create static-profile graph, fill-complete without inserting (and therefore, without allocating) - GRPH graph (map, 3, StaticProfile); - for (GO i = map->getMinGlobalIndex(); i <= map->getMaxGlobalIndex(); ++i) { - graph.insertGlobalIndices (i, tuple (i)); - } - params->set("Optimize Storage",false); - graph.fillComplete(params); - TEST_EQUALITY(graph.getNodeNumEntries(), (size_t)numLocal); - TEST_EQUALITY_CONST(graph.isStorageOptimized(), false); - // - graph.resumeFill(); - for (int i=0; i < numLocal; ++i) graph.removeLocalIndices(i); - params->set("Optimize Storage",true); - graph.fillComplete(params); - TEST_EQUALITY_CONST(params->get("Optimize Storage"), true); - TEST_EQUALITY(graph.getNodeNumEntries(), 0); - TEST_EQUALITY_CONST(graph.getProfileType(), StaticProfile); - TEST_EQUALITY_CONST(graph.isStorageOptimized(), true); + // send in a parameterlist, check the defaults + RCP params = parameterList(); + // create static-profile graph, fill-complete without inserting (and therefore, without allocating) + GRPH graph (map, 3, StaticProfile); + for (GO i = map->getMinGlobalIndex(); i <= map->getMaxGlobalIndex(); ++i) { + graph.insertGlobalIndices (i, tuple (i)); } + params->set("Optimize Storage",false); + graph.fillComplete(params); + TEST_EQUALITY(graph.getNodeNumEntries(), (size_t)numLocal); + TEST_EQUALITY_CONST(graph.isStorageOptimized(), false); + // + graph.resumeFill(); + for (int i=0; i < numLocal; ++i) graph.removeLocalIndices(i); + params->set("Optimize Storage",true); + graph.fillComplete(params); + TEST_EQUALITY_CONST(params->get("Optimize Storage"), true); + TEST_EQUALITY(graph.getNodeNumEntries(), 0); + TEST_EQUALITY_CONST(graph.getProfileType(), StaticProfile); + TEST_EQUALITY_CONST(graph.isStorageOptimized(), true); int lclSuccess = success ? 1 : 0; int gblSuccess = 1; @@ -313,24 +283,23 @@ namespace { // (anonymous) const GO indexBase = 0; RCP map = rcp (new map_type (INVALID, numLocal, indexBase, comm)); - { - Array lids(1); - lids[0] = myRank; - GRAPH diaggraph(map,map,1); - TEST_EQUALITY(diaggraph.hasColMap(), true); - const LO row = 0; - // insert - diaggraph.insertLocalIndices(row, lids()); - TEST_EQUALITY( static_cast (diaggraph.getNumEntriesInLocalRow (row)), - static_cast (lids.size ()) ); - // remove the row - diaggraph.removeLocalIndices(row); - TEST_EQUALITY(diaggraph.getNumEntriesInLocalRow(row), 0) - // now inserting the index again, should make the row-length be 1 again... - diaggraph.insertLocalIndices(row, lids()); - TEST_EQUALITY( static_cast (diaggraph.getNumEntriesInLocalRow (row)), - static_cast (lids.size ()) ); - } + + Array lids(1); + lids[0] = myRank; + GRAPH diaggraph(map,map,1); + TEST_EQUALITY(diaggraph.hasColMap(), true); + const LO row = 0; + // insert + diaggraph.insertLocalIndices(row, lids()); + TEST_EQUALITY( static_cast (diaggraph.getNumEntriesInLocalRow (row)), + static_cast (lids.size ()) ); + // remove the row + diaggraph.removeLocalIndices(row); + TEST_EQUALITY(diaggraph.getNumEntriesInLocalRow(row), 0) + // now inserting the index again, should make the row-length be 1 again... + diaggraph.insertLocalIndices(row, lids()); + TEST_EQUALITY(static_cast (diaggraph.getNumEntriesInLocalRow (row)), + static_cast (lids.size ()) ); int lclSuccess = success ? 1 : 0; int gblSuccess = 1; @@ -385,64 +354,51 @@ namespace { // (anonymous) RCP cmap = rcp (new map_type (INVALID, ginds, 0, comm)); - // Test (GitHub Issue) #2565 fix, while we're at it. - // - // clts == 0: Don't set "compute local triangular constants" - // clts == 1: Set "compute local triangular constants" to false - // clts == 2: Set "compute local triangular constants" to true - for (int clts : {0, 1, 2}) { - RCP params = parameterList(); - if (clts == 1) { - params->set ("compute local triangular constants", false); + RCP params = parameterList(); + for (int T=0; T<4; ++T) { + if ( (T & 1) != 1 ) continue; + ProfileType pftype = StaticProfile; + params->set("Optimize Storage",((T & 2) == 2)); + GRAPH trigraph(rmap,cmap, ginds.size(),pftype); // only allocate as much room as necessary + Array GCopy(4); Array LCopy(4); + ArrayView GView; + ArrayView LView; + size_t numindices; + // at this point, there are no global or local indices, but views and copies should succeed + trigraph.getLocalRowCopy(0,LCopy,numindices); + trigraph.getLocalRowView(0,LView); + trigraph.getGlobalRowCopy(myrowind,GCopy,numindices); + trigraph.getGlobalRowView(myrowind,GView); + // use multiple inserts: this illustrated an overwrite bug for column-map-specified graphs + typedef typename Teuchos::ArrayView::size_type size_type; + for (size_type j=0; j < ginds.size(); ++j) { + trigraph.insertGlobalIndices(myrowind,ginds(j,1)); } - else if (clts == 2) { - params->set ("compute local triangular constants", true); + TEST_EQUALITY( trigraph.getNumEntriesInLocalRow(0), trigraph.getNumAllocatedEntriesInLocalRow(0) ); // test that we only allocated as much room as necessary + // If StaticProfile, then attempt to insert one additional entry + // in my row that is not already in the row, and verify that it + // throws an exception. + if (pftype == StaticProfile) { + TEST_THROW( trigraph.insertGlobalIndices(myrowind,tuple(myrowind+2)), std::runtime_error ); } - - for (int T=0; T<4; ++T) { - if ( (T & 1) != 1 ) continue; - ProfileType pftype = StaticProfile; - params->set("Optimize Storage",((T & 2) == 2)); - GRAPH trigraph(rmap,cmap, ginds.size(),pftype); // only allocate as much room as necessary - Array GCopy(4); Array LCopy(4); - ArrayView GView; - ArrayView LView; - size_t numindices; - // at this point, there are no global or local indices, but views and copies should succeed - trigraph.getLocalRowCopy(0,LCopy,numindices); - trigraph.getLocalRowView(0,LView); - trigraph.getGlobalRowCopy(myrowind,GCopy,numindices); - trigraph.getGlobalRowView(myrowind,GView); - // use multiple inserts: this illustrated an overwrite bug for column-map-specified graphs - typedef typename Teuchos::ArrayView::size_type size_type; - for (size_type j=0; j < ginds.size(); ++j) { - trigraph.insertGlobalIndices(myrowind,ginds(j,1)); - } - TEST_EQUALITY( trigraph.getNumEntriesInLocalRow(0), trigraph.getNumAllocatedEntriesInLocalRow(0) ); // test that we only allocated as much room as necessary - // If StaticProfile, then attempt to insert one additional entry - // in my row that is not already in the row, and verify that it - // throws an exception. - if (pftype == StaticProfile) { - TEST_THROW( trigraph.insertGlobalIndices(myrowind,tuple(myrowind+2)), std::runtime_error ); - } - trigraph.fillComplete(params); - // check that inserting global entries throws (inserting local entries is still allowed) - { - Array zero(0); - TEST_THROW( trigraph.insertGlobalIndices(0,zero()), std::runtime_error ); - } - // check for throws and no-throws/values - TEST_THROW( trigraph.getGlobalRowView(myrowind,GView), std::runtime_error ); - TEST_THROW( trigraph.getLocalRowCopy( 0 ,LCopy(0,1),numindices), std::runtime_error ); - TEST_THROW( trigraph.getGlobalRowCopy(myrowind,GCopy(0,1),numindices), std::runtime_error ); - TEST_NOTHROW( trigraph.getLocalRowView(0,LView) ); - TEST_COMPARE_ARRAYS( LView, linds ); - TEST_NOTHROW( trigraph.getLocalRowCopy(0,LCopy,numindices) ); - TEST_COMPARE_ARRAYS( LCopy(0,numindices), linds ); - TEST_NOTHROW( trigraph.getGlobalRowCopy(myrowind,GCopy,numindices) ); - TEST_COMPARE_ARRAYS( GCopy(0,numindices), ginds ); - STD_TESTS(trigraph); + trigraph.fillComplete(params); + // check that inserting global entries throws (inserting local entries is still allowed) + { + Array zero(0); + TEST_THROW( trigraph.insertGlobalIndices(0,zero()), std::runtime_error ); } + // check for throws and no-throws/values + TEST_THROW( trigraph.getGlobalRowView(myrowind,GView), std::runtime_error ); + TEST_THROW( trigraph.getLocalRowCopy( 0 ,LCopy(0,1),numindices), std::runtime_error ); + TEST_THROW( trigraph.getGlobalRowCopy(myrowind,GCopy(0,1),numindices), std::runtime_error ); + TEST_NOTHROW( trigraph.getLocalRowView(0,LView) ); + TEST_COMPARE_ARRAYS( LView, linds ); + TEST_NOTHROW( trigraph.getLocalRowCopy(0,LCopy,numindices) ); + TEST_COMPARE_ARRAYS( LCopy(0,numindices), linds ); + TEST_NOTHROW( trigraph.getGlobalRowCopy(myrowind,GCopy,numindices) ); + TEST_COMPARE_ARRAYS( GCopy(0,numindices), ginds ); + STD_TESTS(trigraph); + // All procs fail if any node fails int globalSuccess_int = -1; reduceAll( *comm, REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) ); @@ -463,16 +419,16 @@ namespace { // (anonymous) // create a Map, one row per processor const size_t numLocal = 1; RCP map = rcp (new map_type (INVALID, numLocal, 0, comm)); - { - // add too many entries to a static graph - // let node i contribute to row i+1, where node the last node contributes to row 0 - GRAPH diaggraph(map,1,StaticProfile); - GO grow = myRank; - Array colinds(1); - colinds[0] = grow; - TEST_NOTHROW( diaggraph.insertGlobalIndices(grow,colinds()) ); - TEST_THROW( diaggraph.insertGlobalIndices(grow, Teuchos::tuple (grow+1)), std::runtime_error ); - } + + // add too many entries to a static graph + // let node i contribute to row i+1, where node the last node contributes to row 0 + GRAPH diaggraph(map,1,StaticProfile); + GO grow = myRank; + Array colinds(1); + colinds[0] = grow; + TEST_NOTHROW( diaggraph.insertGlobalIndices(grow,colinds()) ); + TEST_THROW( diaggraph.insertGlobalIndices(grow, Teuchos::tuple (grow+1)), std::runtime_error ); + // All procs fail if any node fails int globalSuccess_int = -1; reduceAll( *comm, REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) ); @@ -503,76 +459,33 @@ namespace { // (anonymous) RCP map = rcp (new map_type (INVALID, (myRank == 1 ? 0 : numLocal), 0, comm)); - // Test (GitHub Issue) #2565 fix, while we're at it. - // - // clts == 0: Don't set "compute local triangular constants" - // clts == 1: Set "compute local triangular constants" to false - // clts == 2: Set "compute local triangular constants" to true - // clts == 3: Don't give a ParameterList to fillComplete at all - for (int clts : {0, 1, 2, 3}) { - - if (clts == 0) { - out << "Don't set \"compute local triangular constants\"" << endl; - } - else if (clts == 1) { - out << "Set \"compute local triangular constants to false\"" << endl; - } - else if (clts == 2) { - out << "Set \"compute local triangular constants to true\"" << endl; - } - else if (clts == 3) { - out << "Don't give a ParameterList to fillComplete at all" << endl; - } - Teuchos::OSTab tab1 (out); + Teuchos::OSTab tab1 (out); - RCP test_row; - { - // allocate - RCP test_crs = rcp (new crs_graph_type (map, 1)); - // invalid, because none are allocated yet - TEST_EQUALITY_CONST( test_crs->getNodeAllocationSize(), STINV ); - if (myRank != 1) { - test_crs->insertGlobalIndices (map->getMinGlobalIndex (), - tuple (map->getMinGlobalIndex ())); - } - if (clts == 3) { - test_crs->fillComplete (); - } - else { - RCP params (new ParameterList); - if (clts == 1) { - params->set ("compute local triangular constants", false); - } - else if (clts == 2) { - params->set ("compute local triangular constants", true); - } - test_crs->fillComplete (params); - } - TEST_EQUALITY( test_crs->getNodeAllocationSize(), numLocal ); - test_row = test_crs; - } - RCP cmap = test_row->getColMap(); - TEST_EQUALITY( cmap->getGlobalNumElements(), (size_t)numProcs-1 ); - TEST_EQUALITY( test_row->getGlobalNumRows(), (size_t)numProcs-1 ); - TEST_EQUALITY( test_row->getNodeNumRows(), numLocal ); - TEST_EQUALITY( test_row->getGlobalNumCols(), (size_t)numProcs-1 ); - TEST_EQUALITY( test_row->getNodeNumCols(), numLocal ); - TEST_EQUALITY( test_row->getIndexBase(), 0 ); - - auto lclTri = getLocalTriangularStructure (*test_row); - TEST_ASSERT( lclTri.couldBeLowerTriangular ); - TEST_ASSERT( lclTri.couldBeUpperTriangular ); - TEST_EQUALITY( lclTri.diagCount, static_cast (numLocal) ); - GO gblDiagCount = 0; - reduceAll (*comm, REDUCE_SUM, static_cast (lclTri.diagCount), outArg (gblDiagCount)); - TEST_EQUALITY( gblDiagCount, static_cast (numProcs-1) ); - - TEST_EQUALITY( test_row->getGlobalNumEntries(), (size_t)numProcs-1 ); - TEST_EQUALITY( test_row->getNodeNumEntries(), numLocal ); - TEST_EQUALITY( test_row->getGlobalMaxNumRowEntries(), 1 ); - TEST_EQUALITY( test_row->getNodeMaxNumRowEntries(), numLocal ); - STD_TESTS((*test_row)); + RCP test_row; + // allocate + RCP test_crs = rcp (new crs_graph_type (map, 1)); + // invalid, because none are allocated yet + TEST_EQUALITY_CONST( test_crs->getNodeAllocationSize(), STINV ); + if (myRank != 1) { + test_crs->insertGlobalIndices (map->getMinGlobalIndex (), + tuple (map->getMinGlobalIndex ())); } + test_crs->fillComplete (); + TEST_EQUALITY( test_crs->getNodeAllocationSize(), numLocal ); + test_row = test_crs; + RCP cmap = test_row->getColMap(); + TEST_EQUALITY( cmap->getGlobalNumElements(), (size_t)numProcs-1 ); + TEST_EQUALITY( test_row->getGlobalNumRows(), (size_t)numProcs-1 ); + TEST_EQUALITY( test_row->getNodeNumRows(), numLocal ); + TEST_EQUALITY( test_row->getGlobalNumCols(), (size_t)numProcs-1 ); + TEST_EQUALITY( test_row->getNodeNumCols(), numLocal ); + TEST_EQUALITY( test_row->getIndexBase(), 0 ); + + TEST_EQUALITY( test_row->getGlobalNumEntries(), (size_t)numProcs-1 ); + TEST_EQUALITY( test_row->getNodeNumEntries(), numLocal ); + TEST_EQUALITY( test_row->getGlobalMaxNumRowEntries(), 1 ); + TEST_EQUALITY( test_row->getNodeMaxNumRowEntries(), numLocal ); + STD_TESTS((*test_row)); } // this one is empty on all nodes because of zero allocation size @@ -582,36 +495,16 @@ namespace { // (anonymous) RCP map = rcp (new map_type (INVALID, numLocal, 0, comm)); - // Test (GitHub Issue) #2565 fix, while we're at it. - // - // clts == 0: Don't set "compute local triangular constants" - // clts == 1: Set "compute local triangular constants" to false - // clts == 2: Set "compute local triangular constants" to true - // clts == 3: Don't give a ParameterList to fillComplete at all - for (int clts : {0, 1, 2, 3}) { + { RCP zero; - { - // allocate with no space - RCP zero_crs = rcp (new crs_graph_type (map, 0)); - // invalid, because none are allocated yet - TEST_EQUALITY_CONST( zero_crs->getNodeAllocationSize(), STINV ); - if (clts == 3) { - zero_crs->fillComplete (); - } - else { - RCP params (new ParameterList); - if (clts == 1) { - params->set ("compute local triangular constants", false); - } - else if (clts == 2) { - params->set ("compute local triangular constants", true); - } - zero_crs->fillComplete (params); - } - // zero, because none were allocated. - TEST_EQUALITY_CONST( zero_crs->getNodeAllocationSize(), 0 ); - zero = zero_crs; - } + // allocate with no space + RCP zero_crs = rcp (new crs_graph_type (map, 0)); + // invalid, because none are allocated yet + TEST_EQUALITY_CONST( zero_crs->getNodeAllocationSize(), STINV ); + zero_crs->fillComplete (); + // zero, because none were allocated. + TEST_EQUALITY_CONST( zero_crs->getNodeAllocationSize(), 0 ); + zero = zero_crs; RCP cmap = zero->getColMap(); TEST_EQUALITY( cmap->getGlobalNumElements(), 0 ); TEST_EQUALITY( zero->getGlobalNumRows(), numProcs*numLocal ); @@ -620,14 +513,6 @@ namespace { // (anonymous) TEST_EQUALITY( zero->getNodeNumCols(), 0 ); TEST_EQUALITY( zero->getIndexBase(), 0 ); - auto lclTri = getLocalTriangularStructure (*zero); - TEST_ASSERT( lclTri.couldBeLowerTriangular ); - TEST_ASSERT( lclTri.couldBeUpperTriangular ); - TEST_EQUALITY( lclTri.diagCount, static_cast (0) ); - GO gblDiagCount = 0; - reduceAll (*comm, REDUCE_SUM, static_cast (lclTri.diagCount), outArg (gblDiagCount)); - TEST_EQUALITY( gblDiagCount, static_cast (0) ); - TEST_EQUALITY( zero->getGlobalNumEntries(), 0 ); TEST_EQUALITY( zero->getNodeNumEntries(), 0 ); TEST_EQUALITY( zero->getGlobalMaxNumRowEntries(), 0 ); @@ -641,58 +526,28 @@ namespace { // (anonymous) const size_t numLocal = 0; RCP map = rcp (new map_type (INVALID, numLocal, 0, comm)); - // Test (GitHub Issue) #2565 fix, while we're at it. - // - // clts == 0: Don't set "compute local triangular constants" - // clts == 1: Set "compute local triangular constants" to false - // clts == 2: Set "compute local triangular constants" to true - // clts == 3: Don't give a ParameterList to fillComplete at all - for (int clts : {0, 1, 2, 3}) { - RCP zero; - { - // allocate with no space - RCP zero_crs = rcp (new crs_graph_type (map, 0)); - // invalid, because none are allocated yet - TEST_EQUALITY_CONST( zero_crs->getNodeAllocationSize(), STINV ); - if (clts == 3) { - zero_crs->fillComplete (); - } - else { - RCP params (new ParameterList); - if (clts == 1) { - params->set ("compute local triangular constants", false); - } - else if (clts == 2) { - params->set ("compute local triangular constants", true); - } - zero_crs->fillComplete (params); - } - // zero, because none were allocated. - TEST_EQUALITY_CONST( zero_crs->getNodeAllocationSize(), 0 ); - zero = zero_crs; - } - RCP cmap = zero->getColMap(); - TEST_EQUALITY( cmap->getGlobalNumElements(), 0 ); - TEST_EQUALITY( zero->getGlobalNumRows(), numProcs*numLocal ); - TEST_EQUALITY( zero->getNodeNumRows(), numLocal ); - TEST_EQUALITY( zero->getGlobalNumCols(), numProcs*numLocal ); - TEST_EQUALITY( zero->getNodeNumCols(), 0 ); - TEST_EQUALITY( zero->getIndexBase(), 0 ); - - auto lclTri = getLocalTriangularStructure (*zero); - TEST_ASSERT( lclTri.couldBeLowerTriangular ); - TEST_ASSERT( lclTri.couldBeUpperTriangular ); - TEST_EQUALITY( lclTri.diagCount, static_cast (0) ); - GO gblDiagCount = 0; - reduceAll (*comm, REDUCE_SUM, static_cast (lclTri.diagCount), outArg (gblDiagCount)); - TEST_EQUALITY( gblDiagCount, static_cast (0) ); + RCP zero; + // allocate with no space + RCP zero_crs = rcp (new crs_graph_type (map, 0)); + // invalid, because none are allocated yet + TEST_EQUALITY_CONST( zero_crs->getNodeAllocationSize(), STINV ); + zero_crs->fillComplete (); + // zero, because none were allocated. + TEST_EQUALITY_CONST( zero_crs->getNodeAllocationSize(), 0 ); + zero = zero_crs; + RCP cmap = zero->getColMap(); + TEST_EQUALITY( cmap->getGlobalNumElements(), 0 ); + TEST_EQUALITY( zero->getGlobalNumRows(), numProcs*numLocal ); + TEST_EQUALITY( zero->getNodeNumRows(), numLocal ); + TEST_EQUALITY( zero->getGlobalNumCols(), numProcs*numLocal ); + TEST_EQUALITY( zero->getNodeNumCols(), 0 ); + TEST_EQUALITY( zero->getIndexBase(), 0 ); - TEST_EQUALITY( zero->getGlobalNumEntries(), 0 ); - TEST_EQUALITY( zero->getNodeNumEntries(), 0 ); - TEST_EQUALITY( zero->getGlobalMaxNumRowEntries(), 0 ); - TEST_EQUALITY( zero->getNodeMaxNumRowEntries(), 0 ); - STD_TESTS((*zero)); - } + TEST_EQUALITY( zero->getGlobalNumEntries(), 0 ); + TEST_EQUALITY( zero->getNodeNumEntries(), 0 ); + TEST_EQUALITY( zero->getGlobalMaxNumRowEntries(), 0 ); + TEST_EQUALITY( zero->getNodeMaxNumRowEntries(), 0 ); + STD_TESTS((*zero)); } // All procs fail if any proc fails @@ -717,60 +572,30 @@ namespace { // (anonymous) // create the empty graph RCP > zero; - // Test (GitHub Issue) #2565 fix, while we're at it. - // - // clts == 0: Don't set "compute local triangular constants" - // clts == 1: Set "compute local triangular constants" to false - // clts == 2: Set "compute local triangular constants" to true - // clts == 3: Don't give a ParameterList to fillComplete at all - for (int clts : {0, 1, 2, 3}) { - { - // allocated with space for one entry per row - RCP zero_crs = rcp (new graph_type (map,1)); - TEST_EQUALITY( zero_crs->getNodeAllocationSize(), STINV ); // zero, because none are allocated yet - - if (clts == 3) { - zero_crs->fillComplete (); - } - else { - RCP params (new ParameterList); - if (clts == 1) { - params->set ("compute local triangular constants", false); - } - else if (clts == 2) { - params->set ("compute local triangular constants", true); - } - zero_crs->fillComplete (params); - } - zero = zero_crs; - } - RCP cmap = zero->getColMap(); - TEST_EQUALITY( cmap->getGlobalNumElements(), 0 ); - TEST_EQUALITY( zero->getGlobalNumRows(), numProcs*numLocal ); - TEST_EQUALITY( zero->getNodeNumRows(), numLocal ); - TEST_EQUALITY( zero->getGlobalNumCols(), numProcs*numLocal ); - TEST_EQUALITY( zero->getNodeNumCols(), 0 ); - TEST_EQUALITY( zero->getIndexBase(), 0 ); - - auto lclTri = getLocalTriangularStructure (*zero); - TEST_ASSERT( lclTri.couldBeLowerTriangular ); - TEST_ASSERT( lclTri.couldBeUpperTriangular ); - TEST_EQUALITY( lclTri.diagCount, static_cast (0) ); - GO gblDiagCount = 0; - reduceAll (*comm, REDUCE_SUM, static_cast (lclTri.diagCount), outArg (gblDiagCount)); - TEST_EQUALITY( gblDiagCount, static_cast (0) ); + // allocated with space for one entry per row + RCP zero_crs = rcp (new graph_type (map,1)); + TEST_EQUALITY( zero_crs->getNodeAllocationSize(), STINV ); // zero, because none are allocated yet + + zero_crs->fillComplete (); + zero = zero_crs; + RCP cmap = zero->getColMap(); + TEST_EQUALITY( cmap->getGlobalNumElements(), 0 ); + TEST_EQUALITY( zero->getGlobalNumRows(), numProcs*numLocal ); + TEST_EQUALITY( zero->getNodeNumRows(), numLocal ); + TEST_EQUALITY( zero->getGlobalNumCols(), numProcs*numLocal ); + TEST_EQUALITY( zero->getNodeNumCols(), 0 ); + TEST_EQUALITY( zero->getIndexBase(), 0 ); + + TEST_EQUALITY( zero->getGlobalNumEntries(), 0 ); + TEST_EQUALITY( zero->getNodeNumEntries(), 0 ); + TEST_EQUALITY( zero->getGlobalMaxNumRowEntries(), 0 ); + TEST_EQUALITY( zero->getNodeMaxNumRowEntries(), 0 ); + STD_TESTS((*zero)); - TEST_EQUALITY( zero->getGlobalNumEntries(), 0 ); - TEST_EQUALITY( zero->getNodeNumEntries(), 0 ); - TEST_EQUALITY( zero->getGlobalMaxNumRowEntries(), 0 ); - TEST_EQUALITY( zero->getNodeMaxNumRowEntries(), 0 ); - STD_TESTS((*zero)); - - // All procs fail if any proc fails - int globalSuccess_int = -1; - reduceAll( *comm, REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) ); - TEST_EQUALITY_CONST( globalSuccess_int, 0 ); - } + // All procs fail if any proc fails + int globalSuccess_int = -1; + reduceAll( *comm, REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) ); + TEST_EQUALITY_CONST( globalSuccess_int, 0 ); } TEUCHOS_UNIT_TEST_TEMPLATE_3_DECL( CrsGraph, DottedDiag, LO, GO , Node ) @@ -793,54 +618,35 @@ namespace { // (anonymous) RCP params = parameterList (); params->set("Optimize Storage",((T & 2) == 2)); - // Test (GitHub Issue) #2565 fix, while we're at it. - // - // clts == 0: Don't set "compute local triangular constants" - // clts == 1: Set "compute local triangular constants" to false - // clts == 2: Set "compute local triangular constants" to true - for (int clts : {0, 1, 2}) { - if (clts == 1) { - params->set ("compute local triangular constants", false); - } - else if (clts == 2) { - params->set ("compute local triangular constants", true); - } - // create a diagonal graph, but where only my middle row has an entry - ArrayRCP toalloc = arcpClone( tuple(0,1,0) ); - GRAPH ddgraph(map, toalloc (), pftype); - ddgraph.insertGlobalIndices(mymiddle, tuple(mymiddle)); - // before globalAssemble(), there should be one local entry on middle, none on the others - ArrayView myrow_gbl; - ddgraph.getGlobalRowView(mymiddle-1,myrow_gbl); TEST_EQUALITY( myrow_gbl.size(), 0 ); - ddgraph.getGlobalRowView(mymiddle ,myrow_gbl); TEST_COMPARE_ARRAYS( myrow_gbl, tuple(mymiddle) ); - ddgraph.getGlobalRowView(mymiddle+1,myrow_gbl); TEST_EQUALITY( myrow_gbl.size(), 0 ); - if (pftype == StaticProfile) { // no room for more, on any row - TEST_THROW( ddgraph.insertGlobalIndices(mymiddle-1,tuple(mymiddle+1)), std::runtime_error ); - TEST_THROW( ddgraph.insertGlobalIndices(mymiddle ,tuple(mymiddle+1)), std::runtime_error ); - TEST_THROW( ddgraph.insertGlobalIndices(mymiddle+1,tuple(mymiddle+1)), std::runtime_error ); - } - ddgraph.fillComplete(params); - // after fillComplete(), there should be a single entry on my middle, corresponding to the diagonal, none on the others - ArrayView myrow_lcl; - TEST_EQUALITY_CONST( ddgraph.getNumEntriesInLocalRow(0), 0 ); - TEST_EQUALITY_CONST( ddgraph.getNumEntriesInLocalRow(2), 0 ); - ddgraph.getLocalRowView(1,myrow_lcl); - TEST_EQUALITY_CONST( myrow_lcl.size(), 1 ); - if (myrow_lcl.size() == 1) { - TEST_EQUALITY( ddgraph.getColMap()->getGlobalElement(myrow_lcl[0]), mymiddle ); - } - // also, the row map and column map should be equivalent - TEST_EQUALITY( ddgraph.getGlobalNumCols(), static_cast (3*numProcs) ); - TEST_EQUALITY( ddgraph.getGlobalNumRows(), ddgraph.getGlobalNumCols() ); - - auto lclTri = getLocalTriangularStructure (ddgraph); - TEST_EQUALITY( lclTri.diagCount, static_cast (1) ); - GO gblDiagCount = 0; - reduceAll (*comm, REDUCE_SUM, static_cast (lclTri.diagCount), outArg (gblDiagCount)); - TEST_EQUALITY( gblDiagCount, static_cast (numProcs) ); - - STD_TESTS(ddgraph); + // create a diagonal graph, but where only my middle row has an entry + ArrayRCP toalloc = arcpClone( tuple(0,1,0) ); + GRAPH ddgraph(map, toalloc (), pftype); + ddgraph.insertGlobalIndices(mymiddle, tuple(mymiddle)); + // before globalAssemble(), there should be one local entry on middle, none on the others + ArrayView myrow_gbl; + ddgraph.getGlobalRowView(mymiddle-1,myrow_gbl); TEST_EQUALITY( myrow_gbl.size(), 0 ); + ddgraph.getGlobalRowView(mymiddle ,myrow_gbl); TEST_COMPARE_ARRAYS( myrow_gbl, tuple(mymiddle) ); + ddgraph.getGlobalRowView(mymiddle+1,myrow_gbl); TEST_EQUALITY( myrow_gbl.size(), 0 ); + if (pftype == StaticProfile) { // no room for more, on any row + TEST_THROW( ddgraph.insertGlobalIndices(mymiddle-1,tuple(mymiddle+1)), std::runtime_error ); + TEST_THROW( ddgraph.insertGlobalIndices(mymiddle ,tuple(mymiddle+1)), std::runtime_error ); + TEST_THROW( ddgraph.insertGlobalIndices(mymiddle+1,tuple(mymiddle+1)), std::runtime_error ); + } + ddgraph.fillComplete(params); + // after fillComplete(), there should be a single entry on my middle, corresponding to the diagonal, none on the others + ArrayView myrow_lcl; + TEST_EQUALITY_CONST( ddgraph.getNumEntriesInLocalRow(0), 0 ); + TEST_EQUALITY_CONST( ddgraph.getNumEntriesInLocalRow(2), 0 ); + ddgraph.getLocalRowView(1,myrow_lcl); + TEST_EQUALITY_CONST( myrow_lcl.size(), 1 ); + if (myrow_lcl.size() == 1) { + TEST_EQUALITY( ddgraph.getColMap()->getGlobalElement(myrow_lcl[0]), mymiddle ); } + // also, the row map and column map should be equivalent + TEST_EQUALITY( ddgraph.getGlobalNumCols(), static_cast (3*numProcs) ); + TEST_EQUALITY( ddgraph.getGlobalNumRows(), ddgraph.getGlobalNumCols() ); + + STD_TESTS(ddgraph); } // All procs fail if any node fails int globalSuccess_int = -1; @@ -870,187 +676,151 @@ namespace { // (anonymous) GO myrowind = map->getGlobalElement (0); - // Test (GitHub Issue) #2565 fix, while we're at it. - // - // clts == 0: Don't set "compute local triangular constants" - // clts == 1: Set "compute local triangular constants" to false - // clts == 2: Set "compute local triangular constants" to true - for (int clts : {0, 1, 2}) { - if (clts == 0) { - out << "Don't set \"compute local triangular constants\"" << endl; - } - else if (clts == 1) { - out << "Set \"compute local triangular constants\" to false" << endl; - } - else if (clts == 2) { - out << "Set \"compute local triangular constants\" to true" << endl; - } - Teuchos::OSTab tab1 (out); + Teuchos::OSTab tab1 (out); + + const Tpetra::ProfileType profileTypes[1] = {Tpetra::StaticProfile}; + for (ProfileType pftype : profileTypes) { + Teuchos::OSTab tab2 (out); + for (bool optimizeStorage : {false, true}) { + out << "Optimize Storage: " << (optimizeStorage ? "true" : "false") + << endl; + Teuchos::OSTab tab3 (out); - const Tpetra::ProfileType profileTypes[1] = {Tpetra::StaticProfile}; - for (ProfileType pftype : profileTypes) { - Teuchos::OSTab tab2 (out); - for (bool optimizeStorage : {false, true}) { - out << "Optimize Storage: " << (optimizeStorage ? "true" : "false") - << endl; - Teuchos::OSTab tab3 (out); - - RCP params = parameterList (); - if (clts == 1) { - params->set ("compute local triangular constants", false); + RCP params = parameterList (); + params->set ("Optimize Storage", optimizeStorage); + + // Diagonal graph + { + out << "Diagonal graph test" << endl; + Teuchos::OSTab tab4 (out); + + // create a diagonal graph, where the graph entries are + // contributed by a single off-node contribution, no + // filtering. let node i contribute to row i+1, where node + // the last node contributes to row 0 + GRAPH diaggraph (map, 1, pftype); + GO grow = myRank+1; + if (as (grow) == numProcs) { + grow = 0; } - else if (clts == 2) { - params->set ("compute local triangular constants", true); + diaggraph.insertGlobalIndices (grow, tuple (grow)); + // before globalAssemble(), there should be no local entries if numProcs > 1 + ArrayView myrow_gbl; + diaggraph.getGlobalRowView (myrowind, myrow_gbl); + TEST_EQUALITY( myrow_gbl.size (), (numProcs == 1 ? 1 : 0) ); + diaggraph.globalAssemble (); + // after globalAssemble(), there should be one local entry per + // row, corresponding to the diagonal + diaggraph.getGlobalRowView (myrowind, myrow_gbl); + TEST_COMPARE_ARRAYS( myrow_gbl, tuple (myrowind) ); + + if (pftype == StaticProfile) { // no room for more + out << "Attempt to insert global column index " << (myrowind+1) << " into" + " global row " << myrowind << "; it should throw, because the graph" + " is StaticProfile, has an upper bound of one entry per row, and " + "already has a different column index " << grow << " in this row." + << endl; + TEST_THROW( diaggraph.insertGlobalIndices(myrowind,tuple(myrowind+1)), + std::runtime_error ); } - params->set ("Optimize Storage", optimizeStorage); - - // Diagonal graph - { - out << "Diagonal graph test" << endl; - Teuchos::OSTab tab4 (out); - - // create a diagonal graph, where the graph entries are - // contributed by a single off-node contribution, no - // filtering. let node i contribute to row i+1, where node - // the last node contributes to row 0 - GRAPH diaggraph (map, 1, pftype); - GO grow = myRank+1; - if (as (grow) == numProcs) { - grow = 0; - } - diaggraph.insertGlobalIndices (grow, tuple (grow)); - // before globalAssemble(), there should be no local entries if numProcs > 1 - ArrayView myrow_gbl; - diaggraph.getGlobalRowView (myrowind, myrow_gbl); - TEST_EQUALITY( myrow_gbl.size (), (numProcs == 1 ? 1 : 0) ); - diaggraph.globalAssemble (); - // after globalAssemble(), there should be one local entry per - // row, corresponding to the diagonal - diaggraph.getGlobalRowView (myrowind, myrow_gbl); - TEST_COMPARE_ARRAYS( myrow_gbl, tuple (myrowind) ); - - if (pftype == StaticProfile) { // no room for more - out << "Attempt to insert global column index " << (myrowind+1) << " into" - " global row " << myrowind << "; it should throw, because the graph" - " is StaticProfile, has an upper bound of one entry per row, and " - "already has a different column index " << grow << " in this row." - << endl; - TEST_THROW( diaggraph.insertGlobalIndices(myrowind,tuple(myrowind+1)), - std::runtime_error ); - } - diaggraph.fillComplete (params); + diaggraph.fillComplete (params); - // after fillComplete(), there should be a single entry on my - // row, corresponding to the diagonal - ArrayView myrow_lcl; - diaggraph.getLocalRowView (0, myrow_lcl); - TEST_EQUALITY_CONST( myrow_lcl.size (), 1 ); - if (myrow_lcl.size() == 1) { - TEST_EQUALITY( diaggraph.getColMap ()->getGlobalElement (myrow_lcl[0]), - myrowind ); - } - // also, the row map and column map should be equivalent - TEST_EQUALITY_CONST( diaggraph.getRowMap()->isSameAs(*diaggraph.getColMap()), true ); - - auto lclTri = getLocalTriangularStructure (diaggraph); - TEST_ASSERT( lclTri.couldBeLowerTriangular ); - TEST_ASSERT( lclTri.couldBeUpperTriangular ); - TEST_EQUALITY( lclTri.diagCount, static_cast (1) ); - GO gblDiagCount = 0; - reduceAll (*comm, REDUCE_SUM, static_cast (lclTri.diagCount), outArg (gblDiagCount)); - TEST_EQUALITY( gblDiagCount, static_cast (numProcs) ); - - STD_TESTS(diaggraph); + // after fillComplete(), there should be a single entry on my + // row, corresponding to the diagonal + ArrayView myrow_lcl; + diaggraph.getLocalRowView (0, myrow_lcl); + TEST_EQUALITY_CONST( myrow_lcl.size (), 1 ); + if (myrow_lcl.size() == 1) { + TEST_EQUALITY( diaggraph.getColMap ()->getGlobalElement (myrow_lcl[0]), + myrowind ); } + // also, the row map and column map should be equivalent + TEST_EQUALITY_CONST( diaggraph.getRowMap()->isSameAs(*diaggraph.getColMap()), true ); - // Next-door-neighbor graph - { - out << "Next-door-neighbor graph test" << endl; - Teuchos::OSTab tab4 (out); - - // create a next-door-neighbor graph (tridiagonal plus - // corners), where the graph entries are contributed by single - // off-node contribution, no filtering. let node i add the - // contributions for column i of the graph: (i-1,i), (i,i), - // (i+1,i). allocate only as much space as we need. some - // hacking here to support this test when numProcs == 1 or 2 - GRAPH ngraph(map,3,pftype); - Array grows(3); - grows[0] = (numProcs+myRank-1) % numProcs; // my left neighbor - grows[1] = (numProcs+myRank ) % numProcs; // myself - grows[2] = (numProcs+myRank+1) % numProcs; // my right neighbor - - // Add me to the graph for my neighbors - ngraph.insertGlobalIndices (grows[0], tuple (myRank)); - ngraph.insertGlobalIndices (grows[1], tuple (myRank)); - ngraph.insertGlobalIndices (grows[2], tuple (myRank)); - - // before globalAssemble(), there should be a single local - // entry on parallel runs, three on serial runs - ArrayView myrow_gbl; - ngraph.getGlobalRowView (myrowind, myrow_gbl); - - // after globalAssemble(), storage should be maxed out - out << "Calling globalAssemble()" << endl; - ngraph.globalAssemble(); - TEST_EQUALITY( ngraph.getNumEntriesInLocalRow(0), - ( numProcs == 1 && pftype == StaticProfile ? 1 : - ngraph.getNumAllocatedEntriesInLocalRow(0) )); - out << "Calling fillComplete(params)" << endl; - ngraph.fillComplete (params); - - // after fillComplete(), there should be entries for me and my - // neighbors on my row - ArrayView myrow_lcl; - ngraph.getLocalRowView (0, myrow_lcl); - out << "Returned view of column indices on Proc 0: " - << Teuchos::toString (myrow_lcl) << endl; - - { - // check indices on my row - typename Array::iterator glast; - std::sort (grows.begin (), grows.end ()); - glast = std::unique (grows.begin (), grows.end ()); - size_t numunique = glast - grows.begin (); - // test the test: numunique == min(numProcs,3) - TEST_EQUALITY( numunique, (size_t)min(numProcs,3) ); - TEST_EQUALITY_CONST( (size_t)myrow_lcl.size(), numunique ); - if ((size_t)myrow_lcl.size() == numunique) { - size_t numinds; - Array inds(numunique+1); - TEST_THROW( - ngraph.getGlobalRowCopy (myrowind, inds (0, numunique-1), numinds), - std::runtime_error ); - TEST_NOTHROW( - ngraph.getGlobalRowCopy (myrowind, inds (0, numunique), numinds) ); - TEST_NOTHROW( ngraph.getGlobalRowCopy (myrowind,inds (), numinds) ); - std::sort (inds.begin (), inds.begin () + numinds); - TEST_COMPARE_ARRAYS( inds (0, numinds), grows (0, numunique) ); - - out << "On Proc 0:" << endl; - Teuchos::OSTab tab5 (out); - out << "numinds: " << numinds << endl - << "inds(0,numinds): " << inds (0, numinds) << endl - << "numunique: " << numunique << endl - << "grows(0,numunique): " << grows (0, numunique) << endl; - } - } - TEST_EQUALITY_CONST( ngraph.getRowMap ()->isSameAs (* (ngraph.getColMap ())), - (numProcs == 1 ? true : false) ); + STD_TESTS(diaggraph); + } - auto lclTri = getLocalTriangularStructure (ngraph); - TEST_EQUALITY( lclTri.diagCount, 1 ); - GO gblDiagCount = 0; - reduceAll (*comm, REDUCE_SUM, static_cast (lclTri.diagCount), outArg (gblDiagCount)); - TEST_EQUALITY( gblDiagCount, static_cast (numProcs) ); + // Next-door-neighbor graph + { + out << "Next-door-neighbor graph test" << endl; + Teuchos::OSTab tab4 (out); + + // create a next-door-neighbor graph (tridiagonal plus + // corners), where the graph entries are contributed by single + // off-node contribution, no filtering. let node i add the + // contributions for column i of the graph: (i-1,i), (i,i), + // (i+1,i). allocate only as much space as we need. some + // hacking here to support this test when numProcs == 1 or 2 + GRAPH ngraph(map,3,pftype); + Array grows(3); + grows[0] = (numProcs+myRank-1) % numProcs; // my left neighbor + grows[1] = (numProcs+myRank ) % numProcs; // myself + grows[2] = (numProcs+myRank+1) % numProcs; // my right neighbor + + // Add me to the graph for my neighbors + ngraph.insertGlobalIndices (grows[0], tuple (myRank)); + ngraph.insertGlobalIndices (grows[1], tuple (myRank)); + ngraph.insertGlobalIndices (grows[2], tuple (myRank)); + + // before globalAssemble(), there should be a single local + // entry on parallel runs, three on serial runs + ArrayView myrow_gbl; + ngraph.getGlobalRowView (myrowind, myrow_gbl); + + // after globalAssemble(), storage should be maxed out + out << "Calling globalAssemble()" << endl; + ngraph.globalAssemble(); + TEST_EQUALITY( ngraph.getNumEntriesInLocalRow(0), + ( numProcs == 1 && pftype == StaticProfile ? 1 : + ngraph.getNumAllocatedEntriesInLocalRow(0) )); + out << "Calling fillComplete(params)" << endl; + ngraph.fillComplete (params); + + // after fillComplete(), there should be entries for me and my + // neighbors on my row + ArrayView myrow_lcl; + ngraph.getLocalRowView (0, myrow_lcl); + out << "Returned view of column indices on Proc 0: " + << Teuchos::toString (myrow_lcl) << endl; - out << "Concluding with standard graph tests" << endl; - STD_TESTS(ngraph); + { + // check indices on my row + typename Array::iterator glast; + std::sort (grows.begin (), grows.end ()); + glast = std::unique (grows.begin (), grows.end ()); + size_t numunique = glast - grows.begin (); + // test the test: numunique == min(numProcs,3) + TEST_EQUALITY( numunique, (size_t)min(numProcs,3) ); + TEST_EQUALITY_CONST( (size_t)myrow_lcl.size(), numunique ); + if ((size_t)myrow_lcl.size() == numunique) { + size_t numinds; + Array inds(numunique+1); + TEST_THROW( + ngraph.getGlobalRowCopy (myrowind, inds (0, numunique-1), numinds), + std::runtime_error ); + TEST_NOTHROW( + ngraph.getGlobalRowCopy (myrowind, inds (0, numunique), numinds) ); + TEST_NOTHROW( ngraph.getGlobalRowCopy (myrowind,inds (), numinds) ); + std::sort (inds.begin (), inds.begin () + numinds); + TEST_COMPARE_ARRAYS( inds (0, numinds), grows (0, numunique) ); + + out << "On Proc 0:" << endl; + Teuchos::OSTab tab5 (out); + out << "numinds: " << numinds << endl + << "inds(0,numinds): " << inds (0, numinds) << endl + << "numunique: " << numunique << endl + << "grows(0,numunique): " << grows (0, numunique) << endl; + } } - } // optimizeStorage - } // pftype - } // clts + TEST_EQUALITY_CONST( ngraph.getRowMap ()->isSameAs (* (ngraph.getColMap ())), + (numProcs == 1 ? true : false) ); + + out << "Concluding with standard graph tests" << endl; + STD_TESTS(ngraph); + } + } // optimizeStorage + } // pftype // All procs fail if any node fails int globalSuccess_int = -1; diff --git a/packages/tpetra/core/test/CrsMatrix/Tpetra_Test_CrsMatrix_WithGraph.hpp b/packages/tpetra/core/test/CrsMatrix/Tpetra_Test_CrsMatrix_WithGraph.hpp index c48b1fa1eb27..b991d08604a2 100644 --- a/packages/tpetra/core/test/CrsMatrix/Tpetra_Test_CrsMatrix_WithGraph.hpp +++ b/packages/tpetra/core/test/CrsMatrix/Tpetra_Test_CrsMatrix_WithGraph.hpp @@ -48,31 +48,6 @@ #include "Tpetra_CrsMatrix.hpp" #include "Tpetra_Vector.hpp" #include "Tpetra_Details_getNumDiags.hpp" -#include "Tpetra_Details_determineLocalTriangularStructure.hpp" - -namespace { // (anonymous) - template - Tpetra::Details::LocalTriangularStructureResult - getLocalTriangularStructure (const Tpetra::RowGraph& G) - { - using Tpetra::Details::determineLocalTriangularStructure; - using crs_graph_type = Tpetra::CrsGraph; - - const crs_graph_type& G_crs = dynamic_cast (G); - - auto G_lcl = G_crs.getLocalGraph (); - auto lclRowMap = G.getRowMap ()->getLocalMap (); - auto lclColMap = G.getColMap ()->getLocalMap (); - return determineLocalTriangularStructure (G_lcl, lclRowMap, lclColMap, true); - } - - template - Tpetra::Details::LocalTriangularStructureResult - getLocalTriangularStructure (const Tpetra::CrsMatrix& A) - { - return getLocalTriangularStructure (* (A.getGraph ())); - } -} // namespace (anonymous) // TODO: add test where some nodes have zero rows // TODO: add test where non-"zero" graph is used to build matrix; if no values are added to matrix, the operator effect should be zero. This tests that matrix values are initialized properly. @@ -319,13 +294,6 @@ inline void tupleToArray(Array &arr, const tuple &tup) out << "Call fillComplete on the CrsMatrix" << endl; matrix.fillComplete(); - { - auto lclTri = getLocalTriangularStructure (matrix); - TEST_EQUALITY( lclTri.diagCount, static_cast (numLocal) ); - GO gblDiagCount = 0; - reduceAll (*comm, REDUCE_SUM, static_cast (lclTri.diagCount), outArg (gblDiagCount)); - TEST_EQUALITY( gblDiagCount, static_cast (numImages*numLocal) ); - } TEST_EQUALITY( matrix.getGlobalNumEntries(), 3*numImages*numLocal - 2 ); out << "Check the diagonal entries of the CrsMatrix, using getLocalDiagCopy" << endl; @@ -418,11 +386,6 @@ inline void tupleToArray(Array &arr, const tuple &tup) TEST_EQUALITY_CONST( diaggraph.isFillComplete(), true ); TEST_EQUALITY_CONST( diaggraph.isStorageOptimized(), true ); - { - auto lclTri = getLocalTriangularStructure (diaggraph); - TEST_ASSERT( lclTri.couldBeLowerTriangular ); - TEST_ASSERT( lclTri.couldBeUpperTriangular ); - } // Make sure that if you create a CrsMatrix with an optimized, // fillComplete CrsGraph, that the resulting CrsMatrix is @@ -440,11 +403,6 @@ inline void tupleToArray(Array &arr, const tuple &tup) TEST_EQUALITY_CONST( matrix.isFillComplete(), true ); TEST_EQUALITY_CONST( matrix.isStorageOptimized(), true ); - { - auto lclTri = getLocalTriangularStructure (matrix); - TEST_ASSERT( lclTri.couldBeLowerTriangular ); - TEST_ASSERT( lclTri.couldBeUpperTriangular ); - } // init x to ones(); multiply into y, solve in-situ in y, check result V x(map,false), y(map,false); x.putScalar(SONE); @@ -484,11 +442,6 @@ inline void tupleToArray(Array &arr, const tuple &tup) TEST_EQUALITY_CONST( diaggraph->isFillComplete(), true ); TEST_EQUALITY_CONST( diaggraph->isStorageOptimized(), true ); - { - auto lclTri = getLocalTriangularStructure (*diaggraph); - TEST_ASSERT( lclTri.couldBeLowerTriangular ); - TEST_ASSERT( lclTri.couldBeUpperTriangular ); - } out << "Construct a CrsMatrix with the diagonal CrsGraph" << endl; MAT matrix1(diaggraph); diff --git a/packages/xpetra/src/CrsGraph/Xpetra_TpetraCrsGraph_def.hpp b/packages/xpetra/src/CrsGraph/Xpetra_TpetraCrsGraph_def.hpp index afb19ccd2b55..009d78261702 100644 --- a/packages/xpetra/src/CrsGraph/Xpetra_TpetraCrsGraph_def.hpp +++ b/packages/xpetra/src/CrsGraph/Xpetra_TpetraCrsGraph_def.hpp @@ -249,8 +249,7 @@ typename Xpetra::CrsGraph::local_graph_type Tpe template void TpetraCrsGraph::computeGlobalConstants() { // mfh 07 May 2018: See GitHub Issue #2565. - constexpr bool computeLocalTriangularConstants = true; - graph_->computeGlobalConstants(computeLocalTriangularConstants); + graph_->computeGlobalConstants(); } template