diff --git a/.github/workflows/AT2.yml b/.github/workflows/AT2.yml index c085620db33a..66d648bcd716 100644 --- a/.github/workflows/AT2.yml +++ b/.github/workflows/AT2.yml @@ -92,7 +92,7 @@ jobs: printf "\n\n\n" - echo "image: ${AT2_IMAGE:-unknown}" + echo "image: ${AT2_IMAGE_FULLPATH:-${AT2_IMAGE:-unknown}}" python3 ${GITHUB_WORKSPACE}/packages/framework/pr_tools/PullRequestLinuxDriverTest.py \ --target-branch-name ${{ github.event.pull_request.base.ref }} \ @@ -107,14 +107,16 @@ jobs: --ctest-driver /home/runner/_work/Trilinos/Trilinos/cmake/SimpleTesting/cmake/ctest-driver.cmake \ --ctest-drop-site sems-cdash-son.sandia.gov/cdash \ --filename-subprojects ./package_subproject_list.cmake \ - --filename-packageenables ./packageEnables.cmake + --filename-packageenables ./packageEnables.cmake \ + --max-cores-allowed=29 \ + --num-concurrent-tests=16 - name: Summary if: ${{ !cancelled() }} shell: bash -l {0} working-directory: /home/Trilinos/build run: | echo "## Image" >> $GITHUB_STEP_SUMMARY - echo "image: ${AT2_IMAGE:-unknown}" >> $GITHUB_STEP_SUMMARY + echo "image: ${AT2_IMAGE_FULLPATH:-${AT2_IMAGE:-unknown}}" >> $GITHUB_STEP_SUMMARY echo "## CDash Links" >> $GITHUB_STEP_SUMMARY echo "### Current Build" >> $GITHUB_STEP_SUMMARY AT2_URL=$(> $GITHUB_STEP_SUMMARY - echo "image: ${AT2_IMAGE:-unknown}" >> $GITHUB_STEP_SUMMARY + echo "image: ${AT2_IMAGE_FULLPATH:-${AT2_IMAGE:-unknown}}" >> $GITHUB_STEP_SUMMARY echo "## CDash Links" >> $GITHUB_STEP_SUMMARY echo "### Current Build" >> $GITHUB_STEP_SUMMARY AT2_URL=$(> $GITHUB_STEP_SUMMARY - echo "image: ${AT2_IMAGE:-unknown}" >> $GITHUB_STEP_SUMMARY + echo "image: ${AT2_IMAGE_FULLPATH:-${AT2_IMAGE:-unknown}}" >> $GITHUB_STEP_SUMMARY echo "## CDash Links" >> $GITHUB_STEP_SUMMARY echo "### Current Build" >> $GITHUB_STEP_SUMMARY AT2_URL=$(> $GITHUB_STEP_SUMMARY - echo "image: ${AT2_IMAGE:-unknown}" >> $GITHUB_STEP_SUMMARY + echo "image: ${AT2_IMAGE_FULLPATH:-${AT2_IMAGE:-unknown}}" >> $GITHUB_STEP_SUMMARY echo "## CDash Links" >> $GITHUB_STEP_SUMMARY echo "### Current Build" >> $GITHUB_STEP_SUMMARY AT2_URL=$(mat_->RowMap()); t_map = Util::tpetra_map_to_epetra_map(*map); - RCP t_mat = rcp(new Epetra_CrsMatrix(Copy, *t_map, this->getMaxRowNNZ())); + int maxRowNNZ = 0; // this->getMaxRowNNZ(); + RCP t_mat = rcp(new Epetra_CrsMatrix(Copy, *t_map, maxRowNNZ)); Epetra_Import importer(*t_map, *o_map); t_mat->Import(*(this->mat_), importer, Insert); diff --git a/packages/amesos2/src/Amesos2_ShyLUBasker_def.hpp b/packages/amesos2/src/Amesos2_ShyLUBasker_def.hpp index a4a5718e7498..6a7195f6b412 100644 --- a/packages/amesos2/src/Amesos2_ShyLUBasker_def.hpp +++ b/packages/amesos2/src/Amesos2_ShyLUBasker_def.hpp @@ -557,7 +557,7 @@ bool ShyLUBasker::loadA_impl(EPhase current_phase) { using Teuchos::as; - if(current_phase == SOLVE) return (false); + if(current_phase == SOLVE || current_phase == PREORDERING ) return( false ); #ifdef HAVE_AMESOS2_TIMERS Teuchos::TimeMonitor convTimer(this->timers_.mtxConvTime_); @@ -573,7 +573,8 @@ ShyLUBasker::loadA_impl(EPhase current_phase) { // Only the root image needs storage allocated - if( this->root_ ){ + if( this->root_ && current_phase == SYMBFACT ) + { Kokkos::resize(nzvals_view_, this->globalNumNonZeros_); Kokkos::resize(rowind_view_, this->globalNumNonZeros_); Kokkos::resize(colptr_view_, this->globalNumCols_ + 1); //this will be wrong for case of gapped col ids, e.g. 0,2,4,9; num_cols = 10 ([0,10)) but num GIDs = 4... diff --git a/packages/framework/pr_tools/PullRequestLinuxDriver.sh b/packages/framework/pr_tools/PullRequestLinuxDriver.sh index ab4b1fdf0fc9..01679dae2cdb 100755 --- a/packages/framework/pr_tools/PullRequestLinuxDriver.sh +++ b/packages/framework/pr_tools/PullRequestLinuxDriver.sh @@ -52,6 +52,8 @@ function bootstrap_modules() { module unload sems-python module load sems-git/2.37.0 module load sems-python/3.9.0 + execute_command_checked "module load sems-ccache" + configure_ccache module list else diff --git a/packages/intrepid2/src/Cell/Intrepid2_CellData.cpp b/packages/intrepid2/src/Cell/Intrepid2_CellData.cpp index 7fd508035a2f..23e184e60907 100644 --- a/packages/intrepid2/src/Cell/Intrepid2_CellData.cpp +++ b/packages/intrepid2/src/Cell/Intrepid2_CellData.cpp @@ -21,6 +21,9 @@ const CellTopologyData* Intrepid2::getCellTopologyData(const unsigned& cellTopologyKey){ const CellTopologyData* cellTopologyData; switch (cellTopologyKey) { + case shards::Node::key: + cellTopologyData = shards::getCellTopologyData(); + break; case shards::Line<2>::key: cellTopologyData = shards::getCellTopologyData>(); break; diff --git a/packages/muelu/doc/UsersGuide/masterList.xml b/packages/muelu/doc/UsersGuide/masterList.xml index 0a8a6b4f247f..d9e273f00443 100644 --- a/packages/muelu/doc/UsersGuide/masterList.xml +++ b/packages/muelu/doc/UsersGuide/masterList.xml @@ -876,6 +876,14 @@ parameter not existing in ML + + aggregation: output file: aggregate qualities + bool + false + Whether to plot the aggregate quality. + parameter not existing in ML + + aggregation: params \parameterlist diff --git a/packages/muelu/doc/UsersGuide/options_aggregation.tex b/packages/muelu/doc/UsersGuide/options_aggregation.tex index cd41f9039b16..ff17f69182ad 100644 --- a/packages/muelu/doc/UsersGuide/options_aggregation.tex +++ b/packages/muelu/doc/UsersGuide/options_aggregation.tex @@ -62,6 +62,8 @@ \cbb{aggregation: output file: build colormap}{bool}{false}{Whether to output a random colormap in a separate XML file.} +\cbb{aggregation: output file: aggregate qualities}{bool}{false}{Whether to plot the aggregate quality.} + \cbb{aggregation: mesh layout}{string}{Global Lexicographic}{Type of ordering for structured mesh aggregation. Possible values: "Global Lexicographic" and "Local Lexicographic".} \cbb{aggregation: output type}{string}{Aggregates}{Type of object holding the aggregation data. Possible values: "Aggregates" or "CrsGraph".} diff --git a/packages/muelu/doc/UsersGuide/paramlist.tex b/packages/muelu/doc/UsersGuide/paramlist.tex index c6b72a876af8..f9346acebbf1 100644 --- a/packages/muelu/doc/UsersGuide/paramlist.tex +++ b/packages/muelu/doc/UsersGuide/paramlist.tex @@ -115,6 +115,8 @@ \cbb{aggregation: output file: build colormap}{bool}{false}{Whether to output a random colormap in a separate XML file.} +\cbb{aggregation: output file: aggregate qualities}{bool}{false}{Whether to plot the aggregate quality.} + \cbb{aggregation: mesh layout}{string}{Global Lexicographic}{Type of ordering for structured mesh aggregation. Possible values: "Global Lexicographic" and "Local Lexicographic".} \cbb{aggregation: output type}{string}{Aggregates}{Type of object holding the aggregation data. Possible values: "Aggregates" or "CrsGraph".} diff --git a/packages/muelu/doc/UsersGuide/paramlist_hidden.tex b/packages/muelu/doc/UsersGuide/paramlist_hidden.tex index 3cce34b667ca..cbc68a68e2f9 100644 --- a/packages/muelu/doc/UsersGuide/paramlist_hidden.tex +++ b/packages/muelu/doc/UsersGuide/paramlist_hidden.tex @@ -183,6 +183,8 @@ \cbb{aggregation: output file: build colormap}{bool}{false}{Whether to output a random colormap in a separate XML file.} +\cbb{aggregation: output file: aggregate qualities}{bool}{false}{Whether to plot the aggregate quality.} + \cba{aggregation: params}{\parameterlist}{Sublist of options for use by aggregation.} \cba{strength-of-connection: params}{\parameterlist}{Sublist of options for use by coalesce/drop.} diff --git a/packages/muelu/src/Graph/MatrixTransformation/MueLu_CoalesceDropFactory_def.hpp b/packages/muelu/src/Graph/MatrixTransformation/MueLu_CoalesceDropFactory_def.hpp index 814450ffa710..6c8e857d6daf 100644 --- a/packages/muelu/src/Graph/MatrixTransformation/MueLu_CoalesceDropFactory_def.hpp +++ b/packages/muelu/src/Graph/MatrixTransformation/MueLu_CoalesceDropFactory_def.hpp @@ -1251,6 +1251,7 @@ void CoalesceDropFactory::Build(Level isBoundary = pointBoundaryNodes[row]; } else { // The amalgamated row is marked as Dirichlet iff all point rows are Dirichlet + isBoundary = true; for (LO j = 0; j < blkSize; j++) { if (!pointBoundaryNodes[row * blkSize + j]) { isBoundary = false; @@ -1514,7 +1515,7 @@ void CoalesceDropFactory::Build(Level } } - if ((GetVerbLevel() & Statistics1) && !(A->GetFixedBlockSize() > 1 && threshold != STS::zero())) { + if (GetVerbLevel() & Statistics1) { RCP> comm = A->getRowMap()->getComm(); GO numGlobalTotal, numGlobalDropped; MueLu_sumAll(comm, numTotal, numGlobalTotal); diff --git a/packages/muelu/src/Graph/UncoupledAggregation/MueLu_AggregationPhase2bAlgorithm_decl.hpp b/packages/muelu/src/Graph/UncoupledAggregation/MueLu_AggregationPhase2bAlgorithm_decl.hpp index b1dc9913bbb1..dd86190c590a 100644 --- a/packages/muelu/src/Graph/UncoupledAggregation/MueLu_AggregationPhase2bAlgorithm_decl.hpp +++ b/packages/muelu/src/Graph/UncoupledAggregation/MueLu_AggregationPhase2bAlgorithm_decl.hpp @@ -73,17 +73,13 @@ class AggregationPhase2bAlgorithm : public MueLu::AggregationAlgorithmBase::AggStatType& aggStat, LO& numNonAggregatedNodes) const; - void BuildAggregatesRandom(const ParameterList& params, - const LWGraph_kokkos& graph, - Aggregates& aggregates, - typename AggregationAlgorithmBase::AggStatType& aggStat, - LO& numNonAggregatedNodes) const; - - void BuildAggregatesDeterministic(const ParameterList& params, - const LWGraph_kokkos& graph, - Aggregates& aggregates, - typename AggregationAlgorithmBase::AggStatType& aggStat, - LO& numNonAggregatedNodes) const; + template + void BuildAggregates(const ParameterList& params, + const LWGraph_kokkos graph, + Aggregates& aggregates, + typename AggregationAlgorithmBase::AggStatType aggStat, + LO& numNonAggregatedNodes) const; + //@} std::string description() const { return "Phase 2b (expansion)"; } diff --git a/packages/muelu/src/Graph/UncoupledAggregation/MueLu_AggregationPhase2bAlgorithm_def.hpp b/packages/muelu/src/Graph/UncoupledAggregation/MueLu_AggregationPhase2bAlgorithm_def.hpp index ca6802c31f5f..7e2292cdccba 100644 --- a/packages/muelu/src/Graph/UncoupledAggregation/MueLu_AggregationPhase2bAlgorithm_def.hpp +++ b/packages/muelu/src/Graph/UncoupledAggregation/MueLu_AggregationPhase2bAlgorithm_def.hpp @@ -39,12 +39,12 @@ void AggregationPhase2bAlgorithm::BuildAggreg LO numLocalAggregates = aggregates.GetNumAggregates(); - const int defaultConnectWeight = 100; - const int penaltyConnectWeight = 10; + const LO defaultConnectWeight = 100; + const LO penaltyConnectWeight = 10; - std::vector aggWeight(numLocalAggregates, 0); - std::vector connectWeight(numRows, defaultConnectWeight); - std::vector aggPenalties(numRows, 0); + std::vector aggWeight(numLocalAggregates, 0); + std::vector connectWeight(numRows, defaultConnectWeight); + std::vector aggPenalties(numRows, 0); // We do this cycle twice. // I don't know why, but ML does it too @@ -118,24 +118,126 @@ void AggregationPhase2bAlgorithm:: LO& numNonAggregatedNodes) const { if (params.get("aggregation: deterministic")) { Monitor m(*this, "BuildAggregatesDeterministic"); - BuildAggregatesDeterministic(params, graph, aggregates, aggStat, numNonAggregatedNodes); + BuildAggregates(params, graph, aggregates, aggStat, numNonAggregatedNodes); } else { Monitor m(*this, "BuildAggregatesRandom"); - BuildAggregatesRandom(params, graph, aggregates, aggStat, numNonAggregatedNodes); + BuildAggregates(params, graph, aggregates, aggStat, numNonAggregatedNodes); } } // BuildAggregates -template -void AggregationPhase2bAlgorithm:: - BuildAggregatesRandom(const ParameterList& params, - const LWGraph_kokkos& graph, - Aggregates& aggregates, - typename AggregationAlgorithmBase::AggStatType& aggStat, - LO& numNonAggregatedNodes) const { +template +class ExpansionFunctor { + private: + AggStatType aggStat; + ProcWinnerType procWinner; + Vertex2AggType vertex2AggId; + ColorsType colors; + LocalGraphType lclLWGraph; + AggPenaltyType aggPenalties; + AggPenaltyType aggPenaltyUpdates; + AggPenaltyType connectWeight; + LO penaltyConnectWeight; + LO color; + LO myRank; + + public: + ExpansionFunctor(AggStatType& aggStat_, ProcWinnerType& procWinner_, Vertex2AggType& vertex2AggId_, ColorsType& colors_, LocalGraphType& lclLWGraph_, AggPenaltyType& aggPenalties_, AggPenaltyType& aggPenaltyUpdates_, AggPenaltyType& connectWeight_, LO penaltyConnectWeight_, LO color_, LO rank_) + : aggStat(aggStat_) + , procWinner(procWinner_) + , vertex2AggId(vertex2AggId_) + , colors(colors_) + , lclLWGraph(lclLWGraph_) + , aggPenalties(aggPenalties_) + , connectWeight(connectWeight_) + , aggPenaltyUpdates(aggPenaltyUpdates_) + , penaltyConnectWeight(penaltyConnectWeight_) + , color(color_) + , myRank(rank_) {} + + ExpansionFunctor(AggStatType& aggStat_, ProcWinnerType& procWinner_, Vertex2AggType& vertex2AggId_, ColorsType& colors_, LocalGraphType& lclLWGraph_, AggPenaltyType& aggPenalties_, AggPenaltyType& connectWeight_, LO penaltyConnectWeight_, LO color_, LO rank_) + : aggStat(aggStat_) + , procWinner(procWinner_) + , vertex2AggId(vertex2AggId_) + , colors(colors_) + , lclLWGraph(lclLWGraph_) + , aggPenalties(aggPenalties_) + , connectWeight(connectWeight_) + , penaltyConnectWeight(penaltyConnectWeight_) + , color(color_) + , myRank(rank_) {} + + KOKKOS_INLINE_FUNCTION + void operator()(const LO& i, LO& tmpNumAggregated) const { + if (aggStat(i) != READY || colors(i) != color) + return; + + int bestScore = -100000; + int bestAggId = -1; + int bestConnect = -1; + + auto neighOfINode = lclLWGraph.getNeighborVertices(i); + + for (int j = 0; j < neighOfINode.length; j++) { + LO neigh = neighOfINode(j); + + if (lclLWGraph.isLocalNeighborVertex(neigh) && + (aggStat(neigh) == AGGREGATED)) { + auto aggId = vertex2AggId(neigh, 0); + LO aggWeight = 0; + for (int k = 0; k < neighOfINode.length; k++) { + LO neigh2 = neighOfINode(k); + if (lclLWGraph.isLocalNeighborVertex(neigh2) && + (aggStat(neigh2) == AGGREGATED) && + (vertex2AggId(neigh2, 0) == aggId)) + aggWeight += connectWeight(neigh2); + } + + if (matchMLbehavior && (aggWeight == 0)) + return; + + int score = aggWeight - aggPenalties(aggId); + + if (score > bestScore) { + bestAggId = aggId; + bestScore = score; + bestConnect = connectWeight(neigh); + + } else if (aggId == bestAggId && + connectWeight(neigh) > bestConnect) { + bestConnect = connectWeight(neigh); + } + } + } + if (bestScore >= 0) { + aggStat(i) = AGGREGATED; + vertex2AggId(i, 0) = bestAggId; + procWinner(i, 0) = myRank; + + if constexpr (deterministic) { + Kokkos::atomic_add(&aggPenaltyUpdates(bestAggId), 1); + } else { + Kokkos::atomic_add(&aggPenalties(bestAggId), 1); + } + connectWeight(i) = bestConnect - penaltyConnectWeight; + tmpNumAggregated++; + } + } +}; + +template +template +void AggregationPhase2bAlgorithm:: + BuildAggregates(const ParameterList& params, + const LWGraph_kokkos graph, + Aggregates& aggregates, + typename AggregationAlgorithmBase::AggStatType aggStat, + LO& numNonAggregatedNodes) const { using device_type = typename LWGraph_kokkos::device_type; using execution_space = typename LWGraph_kokkos::execution_space; + bool matchMLbehavior = params.get("aggregation: match ML phase2b"); + const LO numRows = graph.GetNodeNumVertices(); const int myRank = graph.GetComm()->getRank(); @@ -145,14 +247,14 @@ void AggregationPhase2bAlgorithm:: const LO numColors = aggregates.GetGraphNumColors(); const LO numLocalAggregates = aggregates.GetNumAggregates(); - auto lclLWGraph = graph; - const LO defaultConnectWeight = 100; const LO penaltyConnectWeight = 10; - Kokkos::View aggWeight(Kokkos::ViewAllocateWithoutInitializing("aggWeight"), numLocalAggregates); // This gets re-initialized at the start of each "color" loop Kokkos::View connectWeight(Kokkos::ViewAllocateWithoutInitializing("connectWeight"), numRows); Kokkos::View aggPenalties("aggPenalties", numLocalAggregates); // This gets initialized to zero here + Kokkos::View aggPenaltyUpdates; + // if constexpr (deterministic) + aggPenaltyUpdates = Kokkos::View("aggPenaltyUpdates", numLocalAggregates); Kokkos::deep_copy(connectWeight, defaultConnectWeight); @@ -170,190 +272,59 @@ void AggregationPhase2bAlgorithm:: } for (int iter = 0; iter < maxIters; ++iter) { for (LO color = 1; color <= numColors; ++color) { - Kokkos::deep_copy(aggWeight, 0); - // the reduce counts how many nodes are aggregated by this phase, // which will then be subtracted from numNonAggregatedNodes LO numAggregated = 0; - Kokkos::parallel_reduce( - "Aggregation Phase 2b: aggregates expansion", - Kokkos::RangePolicy(0, numRows), - KOKKOS_LAMBDA(const LO i, LO& tmpNumAggregated) { - if (aggStat(i) != READY || colors(i) != color) - return; - - auto neighOfINode = lclLWGraph.getNeighborVertices(i); - for (int j = 0; j < neighOfINode.length; j++) { - LO neigh = neighOfINode(j); - - // We don't check (neigh != i), as it is covered by checking - // (aggStat[neigh] == AGGREGATED) - if (lclLWGraph.isLocalNeighborVertex(neigh) && - aggStat(neigh) == AGGREGATED) - Kokkos::atomic_add(&aggWeight(vertex2AggId(neigh, 0)), - connectWeight(neigh)); - } - - int bestScore = -100000; - int bestAggId = -1; - int bestConnect = -1; - - for (int j = 0; j < neighOfINode.length; j++) { - LO neigh = neighOfINode(j); - - if (lclLWGraph.isLocalNeighborVertex(neigh) && - aggStat(neigh) == AGGREGATED) { - auto aggId = vertex2AggId(neigh, 0); - int score = aggWeight(aggId) - aggPenalties(aggId); - - if (score > bestScore) { - bestAggId = aggId; - bestScore = score; - bestConnect = connectWeight(neigh); - - } else if (aggId == bestAggId && - connectWeight(neigh) > bestConnect) { - bestConnect = connectWeight(neigh); - } - } - } - if (bestScore >= 0) { - aggStat(i) = AGGREGATED; - vertex2AggId(i, 0) = bestAggId; - procWinner(i, 0) = myRank; - - Kokkos::atomic_add(&aggPenalties(bestAggId), 1); - connectWeight(i) = bestConnect - penaltyConnectWeight; - tmpNumAggregated++; - } - }, - numAggregated); // parallel_for - numNonAggregatedNodes -= numAggregated; - } - } // loop over maxIters -} // BuildAggregatesRandom - -template -void AggregationPhase2bAlgorithm:: - BuildAggregatesDeterministic(const ParameterList& params, - const LWGraph_kokkos& graph, - Aggregates& aggregates, - typename AggregationAlgorithmBase::AggStatType& aggStat, - LO& numNonAggregatedNodes) const { - using device_type = typename LWGraph_kokkos::device_type; - using execution_space = typename LWGraph_kokkos::execution_space; - - const LO numRows = graph.GetNodeNumVertices(); - const int myRank = graph.GetComm()->getRank(); - - auto vertex2AggId = aggregates.GetVertex2AggId()->getDeviceLocalView(Xpetra::Access::ReadWrite); - auto procWinner = aggregates.GetProcWinner()->getDeviceLocalView(Xpetra::Access::ReadWrite); - auto colors = aggregates.GetGraphColors(); - const LO numColors = aggregates.GetGraphNumColors(); - LO numLocalAggregates = aggregates.GetNumAggregates(); - - auto lclLWGraph = graph; - - const int defaultConnectWeight = 100; - const int penaltyConnectWeight = 10; - - Kokkos::View connectWeight(Kokkos::ViewAllocateWithoutInitializing("connectWeight"), numRows); - Kokkos::View aggWeight(Kokkos::ViewAllocateWithoutInitializing("aggWeight"), numLocalAggregates); // This gets re-initialized at the start of each "color" loop - Kokkos::View aggPenaltyUpdates("aggPenaltyUpdates", numLocalAggregates); - Kokkos::View aggPenalties("aggPenalties", numLocalAggregates); - - Kokkos::deep_copy(connectWeight, defaultConnectWeight); + if constexpr (deterministic) { + if (matchMLbehavior) { + auto functor = ExpansionFunctor(aggStat, procWinner, vertex2AggId, colors, graph, aggPenalties, aggPenaltyUpdates, connectWeight, penaltyConnectWeight, color, myRank); + + Kokkos::parallel_reduce("Aggregation Phase 2b: aggregates expansion", + Kokkos::RangePolicy(0, numRows), + functor, + numAggregated); + } else { + auto functor = ExpansionFunctor(aggStat, procWinner, vertex2AggId, colors, graph, aggPenalties, aggPenaltyUpdates, connectWeight, penaltyConnectWeight, color, myRank); + + Kokkos::parallel_reduce("Aggregation Phase 2b: aggregates expansion", + Kokkos::RangePolicy(0, numRows), + functor, + numAggregated); + } + } else { + if (matchMLbehavior) { + auto functor = ExpansionFunctor(aggStat, procWinner, vertex2AggId, colors, graph, aggPenalties, connectWeight, penaltyConnectWeight, color, myRank); + + Kokkos::parallel_reduce("Aggregation Phase 2b: aggregates expansion", + Kokkos::RangePolicy(0, numRows), + functor, + numAggregated); + } else { + auto functor = ExpansionFunctor(aggStat, procWinner, vertex2AggId, colors, graph, aggPenalties, connectWeight, penaltyConnectWeight, color, myRank); + + Kokkos::parallel_reduce("Aggregation Phase 2b: aggregates expansion", + Kokkos::RangePolicy(0, numRows), + functor, + numAggregated); + } + } - // We do this cycle twice. - // I don't know why, but ML does it too - // taw: by running the aggregation routine more than once there is a chance that also - // non-aggregated nodes with a node distance of two are added to existing aggregates. - // Assuming that the aggregate size is 3 in each direction running the algorithm only twice - // should be sufficient. - int maxIters = 2; - int maxNodesPerAggregate = params.get("aggregation: max agg size"); - if (maxNodesPerAggregate == std::numeric_limits::max()) { - maxIters = 1; - } - for (int iter = 0; iter < maxIters; ++iter) { - for (LO color = 1; color <= numColors; color++) { - Kokkos::deep_copy(aggWeight, 0); + if constexpr (deterministic) { + Kokkos::parallel_for( + "Aggregation Phase 2b: updating agg penalties", + Kokkos::RangePolicy(0, numLocalAggregates), + KOKKOS_LAMBDA(const LO agg) { + aggPenalties(agg) += aggPenaltyUpdates(agg); + aggPenaltyUpdates(agg) = 0; + }); + } - // the reduce counts how many nodes are aggregated by this phase, - // which will then be subtracted from numNonAggregatedNodes - LO numAggregated = 0; - Kokkos::parallel_for( - "Aggregation Phase 2b: updating agg weights", - Kokkos::RangePolicy(0, numRows), - KOKKOS_LAMBDA(const LO i) { - if (aggStat(i) != READY || colors(i) != color) - return; - auto neighOfINode = lclLWGraph.getNeighborVertices(i); - for (int j = 0; j < neighOfINode.length; j++) { - LO neigh = neighOfINode(j); - // We don't check (neigh != i), as it is covered by checking - // (aggStat[neigh] == AGGREGATED) - if (lclLWGraph.isLocalNeighborVertex(neigh) && - aggStat(neigh) == AGGREGATED) - Kokkos::atomic_add(&aggWeight(vertex2AggId(neigh, 0)), - connectWeight(neigh)); - } - }); - - Kokkos::parallel_reduce( - "Aggregation Phase 2b: aggregates expansion", - Kokkos::RangePolicy(0, numRows), - KOKKOS_LAMBDA(const LO i, LO& tmpNumAggregated) { - if (aggStat(i) != READY || colors(i) != color) - return; - int bestScore = -100000; - int bestAggId = -1; - int bestConnect = -1; - - auto neighOfINode = lclLWGraph.getNeighborVertices(i); - for (int j = 0; j < neighOfINode.length; j++) { - LO neigh = neighOfINode(j); - - if (lclLWGraph.isLocalNeighborVertex(neigh) && - aggStat(neigh) == AGGREGATED) { - auto aggId = vertex2AggId(neigh, 0); - int score = aggWeight(aggId) - aggPenalties(aggId); - - if (score > bestScore) { - bestAggId = aggId; - bestScore = score; - bestConnect = connectWeight(neigh); - - } else if (aggId == bestAggId && - connectWeight(neigh) > bestConnect) { - bestConnect = connectWeight(neigh); - } - } - } - if (bestScore >= 0) { - aggStat(i) = AGGREGATED; - vertex2AggId(i, 0) = bestAggId; - procWinner(i, 0) = myRank; - - Kokkos::atomic_add(&aggPenaltyUpdates(bestAggId), 1); - connectWeight(i) = bestConnect - penaltyConnectWeight; - tmpNumAggregated++; - } - }, - numAggregated); // parallel_reduce - - Kokkos::parallel_for( - "Aggregation Phase 2b: updating agg penalties", - Kokkos::RangePolicy(0, numLocalAggregates), - KOKKOS_LAMBDA(const LO agg) { - aggPenalties(agg) += aggPenaltyUpdates(agg); - aggPenaltyUpdates(agg) = 0; - }); numNonAggregatedNodes -= numAggregated; } - } // loop over k -} // BuildAggregatesDeterministic + } // loop over maxIters + +} // BuildAggregates } // namespace MueLu diff --git a/packages/muelu/src/Graph/UncoupledAggregation/MueLu_UncoupledAggregationFactory_def.hpp b/packages/muelu/src/Graph/UncoupledAggregation/MueLu_UncoupledAggregationFactory_def.hpp index 386451d1cfc3..170506f48d39 100644 --- a/packages/muelu/src/Graph/UncoupledAggregation/MueLu_UncoupledAggregationFactory_def.hpp +++ b/packages/muelu/src/Graph/UncoupledAggregation/MueLu_UncoupledAggregationFactory_def.hpp @@ -190,9 +190,8 @@ void UncoupledAggregationFactory::Build(Level runOnHost = false; TEUCHOS_TEST_FOR_EXCEPTION(pL.get("aggregation: use interface aggregation"), std::invalid_argument, "Option: 'aggregation: use interface aggregation' is not supported in the Kokkos version of uncoupled aggregation"); - // Sanity Checking: match ML behavior is not supported in UncoupledAggregation_Kokkos in Phase 1 or Phase 2b, but is in 2a + // Sanity Checking: match ML behavior is not supported in UncoupledAggregation_Kokkos in Phase 1 , but it is in 2a and 2b TEUCHOS_TEST_FOR_EXCEPTION(pL.get("aggregation: match ML phase1"), std::invalid_argument, "Option: 'aggregation: match ML phase1' is not supported in the Kokkos version of uncoupled aggregation"); - TEUCHOS_TEST_FOR_EXCEPTION(pL.get("aggregation: match ML phase2b"), std::invalid_argument, "Option: 'aggregation: match ML phase2b' is not supported in the Kokkos version of uncoupled aggregation"); } // Build diff --git a/packages/muelu/src/Interface/MueLu_ParameterListInterpreter_def.hpp b/packages/muelu/src/Interface/MueLu_ParameterListInterpreter_def.hpp index 207791bf5b5b..62fb5e8992f1 100644 --- a/packages/muelu/src/Interface/MueLu_ParameterListInterpreter_def.hpp +++ b/packages/muelu/src/Interface/MueLu_ParameterListInterpreter_def.hpp @@ -1313,6 +1313,7 @@ void ParameterListInterpreter:: aggQualityFact->SetParameterList(aggQualityParams); aggQualityFact->SetFactory("Aggregates", manager.GetFactory("Aggregates")); aggQualityFact->SetFactory("CoarseMap", manager.GetFactory("CoarseMap")); + manager.SetFactory("AggregateQualities", aggQualityFact); if (!RAP.is_null()) RAP->AddTransferFactory(aggQualityFact); @@ -1330,8 +1331,12 @@ void ParameterListInterpreter:: MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: fine graph edges", bool, aggExportParams); MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: coarse graph edges", bool, aggExportParams); MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: build colormap", bool, aggExportParams); + MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: aggregate qualities", bool, aggExportParams); aggExport->SetParameterList(aggExportParams); + aggExport->SetFactory("AggregateQualities", manager.GetFactory("AggregateQualities")); aggExport->SetFactory("DofsPerNode", manager.GetFactory("DofsPerNode")); + aggExport->SetFactory("Aggregates", manager.GetFactory("Aggregates")); + aggExport->SetFactory("Graph", manager.GetFactory("Graph")); if (!RAP.is_null()) RAP->AddTransferFactory(aggExport); diff --git a/packages/muelu/src/MueCentral/MueLu_MasterList.cpp b/packages/muelu/src/MueCentral/MueLu_MasterList.cpp index a7c8176126ca..658ab2275839 100644 --- a/packages/muelu/src/MueCentral/MueLu_MasterList.cpp +++ b/packages/muelu/src/MueCentral/MueLu_MasterList.cpp @@ -219,6 +219,7 @@ namespace MueLu { "" "" "" + "" "" "" "" @@ -703,6 +704,8 @@ namespace MueLu { ("aggregation: output file: build colormap","aggregation: output file: build colormap") + ("aggregation: output file: aggregate qualities","aggregation: output file: aggregate qualities") + ("aggregation: params","aggregation: params") ("strength-of-connection: params","strength-of-connection: params") diff --git a/packages/muelu/src/Utils/MueLu_AggregationExportFactory_decl.hpp b/packages/muelu/src/Utils/MueLu_AggregationExportFactory_decl.hpp index 58d2936e32ed..0702ce1afb7e 100644 --- a/packages/muelu/src/Utils/MueLu_AggregationExportFactory_decl.hpp +++ b/packages/muelu/src/Utils/MueLu_AggregationExportFactory_decl.hpp @@ -123,9 +123,11 @@ class AggregationExportFactory : public TwoLevelFactoryBase, public Visualizatio // Data that the different styles need to have available when building geometry mutable Teuchos::RCP coords_; // fine local coordinates mutable Teuchos::RCP coordsCoarse_; // coarse local coordinates - mutable Teuchos::ArrayRCP vertex2AggId_; + mutable Teuchos::RCP vertex2AggId_; + mutable Teuchos::RCP qualities_; mutable Teuchos::ArrayRCP aggSizes_; mutable std::vector isRoot_; + mutable bool doAggQuality_; mutable bool doFineGraphEdges_; mutable bool doCoarseGraphEdges_; mutable int numNodes_; diff --git a/packages/muelu/src/Utils/MueLu_AggregationExportFactory_def.hpp b/packages/muelu/src/Utils/MueLu_AggregationExportFactory_def.hpp index 823349a58b34..0d1b20354b94 100644 --- a/packages/muelu/src/Utils/MueLu_AggregationExportFactory_def.hpp +++ b/packages/muelu/src/Utils/MueLu_AggregationExportFactory_def.hpp @@ -24,6 +24,7 @@ #include "MueLu_AggregationExportFactory_decl.hpp" #include "MueLu_Level.hpp" #include "MueLu_Aggregates.hpp" +#include "MueLu_FactoryManagerBase.hpp" #include "MueLu_AmalgamationFactory.hpp" #include "MueLu_AmalgamationInfo.hpp" @@ -64,6 +65,7 @@ RCP AggregationExportFactoryset >("Coordinates", Teuchos::null, "Factory for Coordinates."); validParamList->set >("Graph", Teuchos::null, "Factory for Graph."); validParamList->set >("Aggregates", Teuchos::null, "Factory for Aggregates."); + validParamList->set >("AggregateQualities", Teuchos::null, "Factory for AggregateQualities."); validParamList->set >("UnAmalgamationInfo", Teuchos::null, "Factory for UnAmalgamationInfo."); validParamList->set >("DofsPerNode", Teuchos::null, "Factory for DofsPerNode."); // CMS/BMK: Old style factory-only options. Deprecate me. @@ -79,6 +81,7 @@ RCP AggregationExportFactoryset("aggregation: output file: fine graph edges", false, "Whether to draw all fine node connections along with the aggregates."); validParamList->set("aggregation: output file: coarse graph edges", false, "Whether to draw all coarse node connections along with the aggregates."); validParamList->set("aggregation: output file: build colormap", false, "Whether to output a random colormap for ParaView in a separate XML file."); + validParamList->set("aggregation: output file: aggregate qualities", false, "Whether to plot the aggregate quality."); return validParamList; } @@ -100,6 +103,10 @@ void AggregationExportFactory::Declar Input(coarseLevel, "Graph"); } } + + if (pL.get("aggregation: output file: aggregate qualities")) { + Input(coarseLevel, "AggregateQualities"); + } } template @@ -119,6 +126,7 @@ void AggregationExportFactory::Build( bool useVTK = false; doCoarseGraphEdges_ = pL.get("aggregation: output file: coarse graph edges"); doFineGraphEdges_ = pL.get("aggregation: output file: fine graph edges"); + doAggQuality_ = pL.get("aggregation: output file: aggregate qualities"); if (masterFilename.length()) { useVTK = true; filenameToWrite = masterFilename; @@ -136,8 +144,10 @@ void AggregationExportFactory::Build( Ac = Get >(coarseLevel, "A"); Teuchos::RCP coords = Teuchos::null; Teuchos::RCP coordsCoarse = Teuchos::null; - Teuchos::RCP fineGraph = Teuchos::null; - Teuchos::RCP coarseGraph = Teuchos::null; + if (doAggQuality_) + qualities_ = Get >(coarseLevel, "AggregateQualities"); + Teuchos::RCP fineGraph = Teuchos::null; + Teuchos::RCP coarseGraph = Teuchos::null; if (doFineGraphEdges_) fineGraph = Get >(fineLevel, "Graph"); if (doCoarseGraphEdges_) @@ -167,12 +177,9 @@ void AggregationExportFactory::Build( } } GetOStream(Runtime0) << "AggregationExportFactory: DofsPerNode: " << DofsPerNode << std::endl; - Teuchos::RCP vertex2AggId_vector = aggregates->GetVertex2AggId(); - Teuchos::RCP procWinner_vector = aggregates->GetProcWinner(); - Teuchos::ArrayRCP vertex2AggId = aggregates->GetVertex2AggId()->getDataNonConst(0); - Teuchos::ArrayRCP procWinner = aggregates->GetProcWinner()->getDataNonConst(0); - vertex2AggId_ = vertex2AggId; + Teuchos::RCP vertex2AggId = aggregates->GetVertex2AggId(); + vertex2AggId_ = vertex2AggId; // prepare for calculating global aggregate ids std::vector numAggsGlobal(numProcs, 0); @@ -263,9 +270,10 @@ void AggregationExportFactory::Build( } if (aggStyle == "Point Cloud") this->doPointCloud(vertices, geomSizes, numAggs_, numNodes_); - else if (aggStyle == "Jacks") - this->doJacks(vertices, geomSizes, numAggs_, numNodes_, isRoot_, vertex2AggId_); - else if (aggStyle == "Jacks++") // Not actually implemented + else if (aggStyle == "Jacks") { + auto vertex2AggIds = vertex2AggId_->getDataNonConst(0); + this->doJacks(vertices, geomSizes, numAggs_, numNodes_, isRoot_, vertex2AggIds); + } else if (aggStyle == "Jacks++") // Not actually implemented doJacksPlus_(vertices, geomSizes); else if (aggStyle == "Convex Hulls") doConvexHulls(vertices, geomSizes); @@ -305,11 +313,13 @@ void AggregationExportFactory::doConv Teuchos::ArrayRCP::coordinateType> yCoords = coords_->getData(1); Teuchos::ArrayRCP::coordinateType> zCoords = Teuchos::null; + auto vertex2AggIds = vertex2AggId_->getDataNonConst(0); + if (dims_ == 2) { - this->doConvexHulls2D(vertices, geomSizes, numAggs_, numNodes_, isRoot_, vertex2AggId_, xCoords, yCoords); + this->doConvexHulls2D(vertices, geomSizes, numAggs_, numNodes_, isRoot_, vertex2AggIds, xCoords, yCoords); } else { zCoords = coords_->getData(2); - this->doConvexHulls3D(vertices, geomSizes, numAggs_, numNodes_, isRoot_, vertex2AggId_, xCoords, yCoords, zCoords); + this->doConvexHulls3D(vertices, geomSizes, numAggs_, numNodes_, isRoot_, vertex2AggIds, xCoords, yCoords, zCoords); } } @@ -571,6 +581,12 @@ void AggregationExportFactory::writeF if (dims_ == 3) zCoords = coords_->getData(2); + auto vertex2AggIds = vertex2AggId_->getDataNonConst(0); + + Teuchos::ArrayRCP qualities; + if (doAggQuality_) + qualities = qualities_->getData(0); + vector uniqueFine = this->makeUnique(vertices); string indent = " "; fout << "" << endl; @@ -596,10 +612,10 @@ void AggregationExportFactory::writeF fout << " " << endl; fout << indent; for (size_t i = 0; i < uniqueFine.size(); i++) { - if (vertex2AggId_[uniqueFine[i]] == -1) - fout << vertex2AggId_[uniqueFine[i]] << " "; + if (vertex2AggIds[uniqueFine[i]] == -1) + fout << vertex2AggIds[uniqueFine[i]] << " "; else - fout << aggsOffset_ + vertex2AggId_[uniqueFine[i]] << " "; + fout << aggsOffset_ + vertex2AggIds[uniqueFine[i]] << " "; if (i % 10 == 9) fout << endl << indent; @@ -616,6 +632,18 @@ void AggregationExportFactory::writeF } fout << endl; fout << " " << endl; + if (doAggQuality_) { + fout << " " << endl; + fout << indent; + for (size_t i = 0; i < uniqueFine.size(); i++) { + fout << qualities[vertex2AggIds[uniqueFine[i]]] << " "; + if (i % 10 == 9) + fout << endl + << indent; + } + fout << endl; + fout << " " << endl; + } fout << " " << endl; fout << " " << endl; fout << " " << endl; diff --git a/packages/muelu/test/interface/kokkos/Output/operator_solve_1_np1_tpetra.gold b/packages/muelu/test/interface/kokkos/Output/operator_solve_1_np1_tpetra.gold index 61ecae9e7780..186ca4496970 100644 --- a/packages/muelu/test/interface/kokkos/Output/operator_solve_1_np1_tpetra.gold +++ b/packages/muelu/test/interface/kokkos/Output/operator_solve_1_np1_tpetra.gold @@ -120,14 +120,14 @@ Cycle type = V level rows nnz nnz/row c ratio procs 0 10000 49600 4.96 1 1 1700 14928 8.78 5.88 1 - 2 192 1682 8.76 8.85 1 - 3 24 200 8.33 8.00 1 + 2 192 1674 8.72 8.85 1 + 3 24 190 7.92 8.00 1 Smoother (level 0) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [10000, 10000], Global nnz: 49600} Smoother (level 1) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [1700, 1700], Global nnz: 14928} -Smoother (level 2) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [192, 192], Global nnz: 1682} +Smoother (level 2) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [192, 192], Global nnz: 1674} Smoother (level 3) pre : solver interface Smoother (level 3) post : no smoother diff --git a/packages/muelu/test/interface/kokkos/Output/operator_solve_1_np4_tpetra.gold b/packages/muelu/test/interface/kokkos/Output/operator_solve_1_np4_tpetra.gold index 0117cfa2fd4d..df9604a89b67 100644 --- a/packages/muelu/test/interface/kokkos/Output/operator_solve_1_np4_tpetra.gold +++ b/packages/muelu/test/interface/kokkos/Output/operator_solve_1_np4_tpetra.gold @@ -120,14 +120,14 @@ Cycle type = V level rows nnz nnz/row c ratio procs 0 10000 49600 4.96 4 1 1700 15318 9.01 5.88 4 - 2 216 2158 9.99 7.87 4 - 3 32 446 13.94 6.75 4 + 2 216 2150 9.95 7.87 4 + 3 32 434 13.56 6.75 4 Smoother (level 0) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [10000, 10000], Global nnz: 49600} Smoother (level 1) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [1700, 1700], Global nnz: 15318} -Smoother (level 2) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [216, 216], Global nnz: 2158} +Smoother (level 2) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [216, 216], Global nnz: 2150} Smoother (level 3) pre : solver interface Smoother (level 3) post : no smoother diff --git a/packages/muelu/test/interface/kokkos/Output/operator_solve_5_np1_tpetra.gold b/packages/muelu/test/interface/kokkos/Output/operator_solve_5_np1_tpetra.gold index 622442f2328f..0b51e98970e5 100644 --- a/packages/muelu/test/interface/kokkos/Output/operator_solve_5_np1_tpetra.gold +++ b/packages/muelu/test/interface/kokkos/Output/operator_solve_5_np1_tpetra.gold @@ -95,14 +95,14 @@ Cycle type = V level rows nnz nnz/row c ratio procs 0 10000 49600 4.96 1 1 1700 14928 8.78 5.88 1 - 2 192 1682 8.76 8.85 1 - 3 24 200 8.33 8.00 1 + 2 192 1674 8.72 8.85 1 + 3 24 190 7.92 8.00 1 Smoother (level 0) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [10000, 10000], Global nnz: 49600} Smoother (level 1) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [1700, 1700], Global nnz: 14928} -Smoother (level 2) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [192, 192], Global nnz: 1682} +Smoother (level 2) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [192, 192], Global nnz: 1674} Smoother (level 3) pre : solver interface Smoother (level 3) post : no smoother diff --git a/packages/muelu/test/interface/kokkos/Output/operator_solve_5_np4_tpetra.gold b/packages/muelu/test/interface/kokkos/Output/operator_solve_5_np4_tpetra.gold index a747e7c913f7..baf6c048c339 100644 --- a/packages/muelu/test/interface/kokkos/Output/operator_solve_5_np4_tpetra.gold +++ b/packages/muelu/test/interface/kokkos/Output/operator_solve_5_np4_tpetra.gold @@ -95,14 +95,14 @@ Cycle type = V level rows nnz nnz/row c ratio procs 0 10000 49600 4.96 4 1 1700 15318 9.01 5.88 4 - 2 216 2158 9.99 7.87 4 - 3 32 446 13.94 6.75 4 + 2 216 2150 9.95 7.87 4 + 3 32 434 13.56 6.75 4 Smoother (level 0) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [10000, 10000], Global nnz: 49600} Smoother (level 1) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [1700, 1700], Global nnz: 15318} -Smoother (level 2) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [216, 216], Global nnz: 2158} +Smoother (level 2) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [216, 216], Global nnz: 2150} Smoother (level 3) pre : solver interface Smoother (level 3) post : no smoother diff --git a/packages/muelu/test/interface/kokkos/Output/operator_solve_6_np1_tpetra.gold b/packages/muelu/test/interface/kokkos/Output/operator_solve_6_np1_tpetra.gold index fe5914900fb0..49df428e7ac1 100644 --- a/packages/muelu/test/interface/kokkos/Output/operator_solve_6_np1_tpetra.gold +++ b/packages/muelu/test/interface/kokkos/Output/operator_solve_6_np1_tpetra.gold @@ -100,14 +100,14 @@ Cycle type = V level rows nnz nnz/row c ratio procs 0 10000 49600 4.96 1 1 1700 14928 8.78 5.88 1 - 2 192 1682 8.76 8.85 1 - 3 24 200 8.33 8.00 1 + 2 192 1674 8.72 8.85 1 + 3 24 190 7.92 8.00 1 Smoother (level 0) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [10000, 10000], Global nnz: 49600} Smoother (level 1) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [1700, 1700], Global nnz: 14928} -Smoother (level 2) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [192, 192], Global nnz: 1682} +Smoother (level 2) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [192, 192], Global nnz: 1674} Smoother (level 3) pre : solver interface Smoother (level 3) post : no smoother diff --git a/packages/muelu/test/interface/kokkos/Output/operator_solve_6_np4_tpetra.gold b/packages/muelu/test/interface/kokkos/Output/operator_solve_6_np4_tpetra.gold index 0d4663cf3256..9fb6a3101a8b 100644 --- a/packages/muelu/test/interface/kokkos/Output/operator_solve_6_np4_tpetra.gold +++ b/packages/muelu/test/interface/kokkos/Output/operator_solve_6_np4_tpetra.gold @@ -100,14 +100,14 @@ Cycle type = V level rows nnz nnz/row c ratio procs 0 10000 49600 4.96 4 1 1700 15318 9.01 5.88 4 - 2 216 2158 9.99 7.87 4 - 3 32 446 13.94 6.75 4 + 2 216 2150 9.95 7.87 4 + 3 32 434 13.56 6.75 4 Smoother (level 0) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [10000, 10000], Global nnz: 49600} Smoother (level 1) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [1700, 1700], Global nnz: 15318} -Smoother (level 2) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [216, 216], Global nnz: 2158} +Smoother (level 2) both : "Ifpack2::Relaxation": {Initialized: true, Computed: true, Type: Symmetric Gauss-Seidel, sweeps: 1, damping factor: 1, Global matrix dimensions: [216, 216], Global nnz: 2150} Smoother (level 3) pre : solver interface Smoother (level 3) post : no smoother diff --git a/packages/muelu/test/unit_tests_kokkos/Aggregates_kokkos.cpp b/packages/muelu/test/unit_tests_kokkos/Aggregates_kokkos.cpp index cca61d42e331..5ea76cbaec3c 100644 --- a/packages/muelu/test/unit_tests_kokkos/Aggregates_kokkos.cpp +++ b/packages/muelu/test/unit_tests_kokkos/Aggregates_kokkos.cpp @@ -102,6 +102,7 @@ void gimmeUncoupledAggregates(const Teuchos::RCP("aggregation: deterministic", false); params.set("aggregation: match ML phase2a", true); + params.set("aggregation: match ML phase2b", false); params.set("aggregation: error on nodes with no on-rank neighbors", false); params.set("aggregation: phase3 avoid singletons", false); diff --git a/packages/muelu/test/unit_tests_kokkos/Regression.cpp b/packages/muelu/test/unit_tests_kokkos/Regression.cpp index e9ab09ea37a2..46f4f88777ce 100644 --- a/packages/muelu/test/unit_tests_kokkos/Regression.cpp +++ b/packages/muelu/test/unit_tests_kokkos/Regression.cpp @@ -98,12 +98,12 @@ TEUCHOS_UNIT_TEST_TEMPLATE_4_DECL(Regression, H2D, Scalar, LocalOrdinal, GlobalO } #ifdef KOKKOS_HAS_SHARED_SPACE else { - size_t targetNumDeepCopies = kkNativeDeepCopies + (std::is_same_v ? 19 : 34); + size_t targetNumDeepCopies = kkNativeDeepCopies + (std::is_same_v ? 19 : 31); TEST_EQUALITY(Tpetra::Details::DeepCopyCounter::get_count_different_space(), targetNumDeepCopies); } #else else { - TEST_EQUALITY(Tpetra::Details::DeepCopyCounter::get_count_different_space(), kkNativeDeepCopies + 34); + TEST_EQUALITY(Tpetra::Details::DeepCopyCounter::get_count_different_space(), kkNativeDeepCopies + 31); } #endif // KOKKOS_HAS_SHARED_SPACE @@ -130,7 +130,7 @@ TEUCHOS_UNIT_TEST_TEMPLATE_4_DECL(Regression, H2D, Scalar, LocalOrdinal, GlobalO } // H2D -TEUCHOS_UNIT_TEST_TEMPLATE_4_DECL(Regression, Aggregration, Scalar, LocalOrdinal, GlobalOrdinal, Node) { +TEUCHOS_UNIT_TEST_TEMPLATE_4_DECL(Regression, Aggregation, Scalar, LocalOrdinal, GlobalOrdinal, Node) { #include MUELU_TESTING_SET_OSTREAM; MUELU_TESTING_LIMIT_SCOPE(Scalar, GlobalOrdinal, Node); @@ -175,12 +175,12 @@ TEUCHOS_UNIT_TEST_TEMPLATE_4_DECL(Regression, Aggregration, Scalar, LocalOrdinal } #ifdef KOKKOS_HAS_SHARED_SPACE else { - size_t targetNumDeepCopies = std::is_same_v ? 17 : 23; + size_t targetNumDeepCopies = std::is_same_v ? 17 : 16; TEST_EQUALITY(Tpetra::Details::DeepCopyCounter::get_count_different_space(), targetNumDeepCopies); } #else else { - TEST_EQUALITY(Tpetra::Details::DeepCopyCounter::get_count_different_space(), 23); + TEST_EQUALITY(Tpetra::Details::DeepCopyCounter::get_count_different_space(), 16); } #endif @@ -193,7 +193,7 @@ TEUCHOS_UNIT_TEST_TEMPLATE_4_DECL(Regression, Aggregration, Scalar, LocalOrdinal #define MUELU_ETI_GROUP(Scalar, LO, GO, Node) \ TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT(Regression, H2D, Scalar, LO, GO, Node) \ - TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT(Regression, Aggregration, Scalar, LO, GO, Node) + TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT(Regression, Aggregation, Scalar, LO, GO, Node) #include diff --git a/packages/muelu/test/viz/AggExport.cpp b/packages/muelu/test/viz/AggExport.cpp index cb524a23c3d9..3e5f662f7ae0 100644 --- a/packages/muelu/test/viz/AggExport.cpp +++ b/packages/muelu/test/viz/AggExport.cpp @@ -254,14 +254,17 @@ int main_(Teuchos::CommandLineProcessor& clp, Xpetra::UnderlyingLib& lib, int ar std::string matrixType = galeriParameters.GetMatrixType(); std::string aggVizType = paramList.get("aggregation: output file: agg style"); + std::string aggQuality = ""; + if (paramList.isParameter("aggregation: output file: aggregate qualities")) + aggQuality = paramList.get("aggregation: output file: aggregate qualities") ? "-AggregateQuality" : ""; aggVizType.erase(std::remove_if(aggVizType.begin(), aggVizType.end(), ::isspace), aggVizType.end()); if (ndims == 2) - paramList.set("aggregation: output filename", "MPI-Viz-Output-2D-Level%LEVELID-Proc%PROCID"); + paramList.set("aggregation: output filename", "Output/MPI-Viz-Output-2D-Level%LEVELID-Proc%PROCID"); else if (ndims == 3) { if (comm->getSize() > 1) - paramList.set("aggregation: output filename", "MPI-Viz-Output-" + matrixType + "-" + aggVizType + "-Level%LEVELID-Proc%PROCID"); + paramList.set("aggregation: output filename", "Output/MPI-Viz-Output-" + matrixType + "-" + aggVizType + aggQuality + "-Level%LEVELID-Proc%PROCID"); else - paramList.set("aggregation: output filename", "MPI-Viz-Output-" + matrixType + "-" + aggVizType + "-Level%LEVELID"); + paramList.set("aggregation: output filename", "Output/MPI-Viz-Output-" + matrixType + "-" + aggVizType + aggQuality + "-Level%LEVELID"); } if (nullspace.is_null()) { @@ -330,9 +333,9 @@ int main_(Teuchos::CommandLineProcessor& clp, Xpetra::UnderlyingLib& lib, int ar // ========================================================================= std::string filenameToWrite; if (comm->getSize() > 1) - filenameToWrite = "MPI-Viz-Output-" + matrixType + "-" + aggVizType + "-Level0-Proc%PROCID"; + filenameToWrite = "Output/MPI-Viz-Output-" + matrixType + "-" + aggVizType + aggQuality + "-Level0-Proc%PROCID"; else - filenameToWrite = "MPI-Viz-Output-" + matrixType + "-" + aggVizType + "-Level0"; + filenameToWrite = "Output/MPI-Viz-Output-" + matrixType + "-" + aggVizType + aggQuality + "-Level0"; std::string outfileName = replaceAll(filenameToWrite, "%PROCID", MueLu::toString(comm->getRank())); aggMatch = compare_to_gold_all_ranks(comm->getRank(), outfileName); diff --git a/packages/muelu/test/viz/CMakeLists.txt b/packages/muelu/test/viz/CMakeLists.txt index 572cc5972964..5317f8b53fdb 100644 --- a/packages/muelu/test/viz/CMakeLists.txt +++ b/packages/muelu/test/viz/CMakeLists.txt @@ -50,6 +50,14 @@ IF (${PACKAGE_NAME}_ENABLE_Ifpack2 AND ${PACKAGE_NAME}_ENABLE_Amesos2) COMM serial mpi ) + MUELU_ADD_SERIAL_AND_MPI_TEST( + AggExport + NAME "VizLaplace3DPointCloudAggregateQualityTpetra" + ARGS "--matrixType=Laplace3D --nx=10 --ny=10 --nz=10 --linAlgebra=Tpetra --xml=vizLaplace3DPointCloudAggregateQuality.xml" + NUM_MPI_PROCS 4 + COMM serial mpi + ) + MUELU_ADD_SERIAL_AND_MPI_TEST( AggExport NAME "VizElasticity3DConvexHullsTpetra" @@ -66,6 +74,14 @@ IF (${PACKAGE_NAME}_ENABLE_Ifpack2 AND ${PACKAGE_NAME}_ENABLE_Amesos2) COMM serial mpi ) + MUELU_ADD_SERIAL_AND_MPI_TEST( + AggExport + NAME "VizLaplace3DConvexHullsAggregateQualityTpetra" + ARGS "--matrixType=Laplace3D --nx=10 --ny=10 --nz=10 --linAlgebra=Tpetra --xml=vizLaplace3DConvexHullsAggregateQuality.xml" + NUM_MPI_PROCS 4 + COMM serial mpi + ) + IF (${PACKAGE_NAME}_ENABLE_Zoltan AND ${PACKAGE_NAME}_ENABLE_AztecOO) @@ -116,28 +132,43 @@ IF (${PACKAGE_NAME}_ENABLE_Ifpack2 AND ${PACKAGE_NAME}_ENABLE_Amesos2) ENDIF() - - TRIBITS_COPY_FILES_TO_BINARY_DIR(Viz_cp - SOURCE_FILES viztest.xml vizElasticity3DPointCloud.xml vizLaplace3DPointCloud.xml vizElasticity3DConvexHulls.xml vizLaplace3DConvexHulls.xml - MPI-Viz-Output-Laplace3D-PointCloud-Level0.gold - MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc0.gold - MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc1.gold - MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc2.gold - MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc3.gold - MPI-Viz-Output-Elasticity3D-PointCloud-Level0.gold - MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc0.gold - MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc1.gold - MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc2.gold - MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc3.gold - MPI-Viz-Output-Laplace3D-ConvexHulls-Level0.gold - MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc0.gold - MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc1.gold - MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc2.gold - MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc3.gold - MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0.gold - MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc0.gold - MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc1.gold - MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc2.gold - MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc3.gold + SOURCE_FILES + viztest.xml + vizElasticity3DPointCloud.xml + vizLaplace3DPointCloud.xml + vizElasticity3DConvexHulls.xml + vizLaplace3DConvexHulls.xml + vizLaplace3DConvexHullsAggregateQuality.xml + vizLaplace3DPointCloudAggregateQuality.xml + Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0.gold + Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc0.gold + Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc1.gold + Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc2.gold + Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc3.gold + Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0.gold + Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc0.gold + Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc1.gold + Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc2.gold + Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc3.gold + Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0.gold + Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc0.gold + Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc1.gold + Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc2.gold + Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc3.gold + Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0.gold + Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc0.gold + Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc1.gold + Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc2.gold + Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc3.gold + Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0.gold + Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc0.gold + Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc1.gold + Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc2.gold + Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc3.gold + Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0.gold + Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc0.gold + Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc1.gold + Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc2.gold + Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc3.gold ) diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc0.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc0.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc0.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc0.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc1.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc1.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc1.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc1.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc2.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc2.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc2.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc2.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc3.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc3.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc3.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0-Proc3.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-ConvexHulls-Level0.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc0.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc0.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc0.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc0.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc1.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc1.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc1.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc1.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc2.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc2.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc2.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc2.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc3.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc3.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc3.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0-Proc3.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-PointCloud-Level0.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Elasticity3D-PointCloud-Level0.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Elasticity3D-PointCloud-Level0.gold diff --git a/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc0.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc0.gold new file mode 100644 index 000000000000..99c95bf253ab --- /dev/null +++ b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc0.gold @@ -0,0 +1,294 @@ + + + + + + + 0 1 2 4 10 11 12 13 14 20 + 22 23 30 31 32 33 34 40 41 42 + 44 100 101 102 103 104 110 111 113 114 + 120 121 123 124 130 131 132 133 134 140 + 141 142 143 144 200 202 203 210 211 212 + 213 214 221 222 224 230 231 232 233 234 + 240 242 243 300 301 302 303 304 310 311 + 312 313 314 320 321 323 324 330 331 333 + 334 340 341 342 343 344 401 402 404 410 + 411 412 413 414 420 422 423 430 431 432 + 433 434 441 442 444 500 501 502 503 504 + 510 511 513 514 520 521 523 524 530 531 + 532 533 534 540 541 542 543 544 600 602 + 603 610 611 612 613 614 621 622 624 630 + 631 632 633 640 642 643 700 701 702 703 + 704 710 711 712 713 714 720 721 723 724 + 730 731 733 734 740 741 742 743 744 801 + 802 804 811 812 813 820 822 823 831 833 + 834 841 842 844 900 901 902 903 904 910 + 911 913 914 920 921 922 923 930 931 932 + 933 934 940 941 942 943 944 + + + 0 0 1 1 0 2 6 1 3 2 + 2 3 4 2 2 5 3 4 4 5 + 5 0 7 6 1 8 0 6 6 3 + 9 2 10 3 4 11 6 5 12 4 + 11 5 5 12 7 7 8 9 7 6 + 10 8 9 10 10 9 11 13 10 12 + 11 11 12 14 7 7 15 8 9 16 + 13 10 8 9 16 10 17 18 13 13 + 17 18 11 13 19 12 14 15 15 14 + 16 20 15 17 16 16 17 18 16 13 + 19 17 18 19 19 14 21 20 15 22 + 14 20 20 22 23 16 24 17 23 25 + 20 19 26 18 25 19 19 26 21 21 + 22 23 21 20 24 22 23 24 24 23 + 25 27 24 25 25 26 28 21 21 29 + 22 28 30 27 24 31 23 30 24 31 + 32 27 27 26 32 25 27 33 26 28 + 29 29 30 34 29 30 30 31 30 33 + 31 32 33 33 28 34 34 29 29 28 + 34 34 31 30 30 34 34 32 30 27 + 33 31 32 32 33 33 33 + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + + + 4.71117 4.71117 6 6 4.71117 12.2679 26.5197 6 11.0268 12.2679 + 12.2679 11.0268 6.36105 12.2679 12.2679 9.04703 11.0268 6.36105 6.36105 9.04703 + 9.04703 4.71117 12.2679 26.5197 6 11.0268 4.71117 26.5197 26.5197 11.0268 + 12.2712 12.2679 17.0714 11.0268 6.36105 16.5078 26.5197 9.04703 15.7082 6.36105 + 16.5078 9.04703 9.04703 15.7082 12.2679 12.2679 11.0268 12.2712 12.2679 26.5197 + 17.0714 11.0268 12.2712 17.0714 17.0714 12.2712 16.5078 26.5197 17.0714 15.7082 + 16.5078 16.5078 15.7082 6.35236 12.2679 12.2679 11.6108 11.0268 12.2712 17.0714 + 26.5197 17.0714 11.0268 12.2712 17.0714 17.0714 16.5078 12.3728 26.5197 26.5197 + 16.5078 12.3728 16.5078 26.5197 15.5535 15.7082 6.35236 11.6108 11.6108 6.35236 + 17.0714 26.5197 11.6108 16.5078 17.0714 17.0714 16.5078 12.3728 17.0714 26.5197 + 15.5535 16.5078 12.3728 15.5535 15.5535 6.35236 12.2679 26.5197 11.6108 11.0268 + 6.35236 26.5197 26.5197 11.0268 12.2712 17.0714 17.0714 16.5078 12.2712 16.5078 + 26.5197 15.5535 14.1879 12.3728 16.5078 15.5535 15.5535 14.1879 12.2679 12.2679 + 11.0268 12.2712 12.2679 26.5197 17.0714 11.0268 12.2712 17.0714 17.0714 12.2712 + 16.5078 31.4164 17.0714 16.5078 16.5078 14.1879 6.24949 12.2679 12.2679 12.1555 + 11.0268 6.24949 21.217 31.4164 17.0714 14.6789 12.2712 21.217 17.0714 14.6789 + 8.49387 31.4164 31.4164 14.1879 8.49387 16.5078 31.4164 13.8718 14.1879 6.24949 + 12.1555 12.1555 21.217 12.5778 12.1555 21.217 21.217 14.6789 21.217 13.8718 + 14.6789 8.49387 13.8718 13.8718 6.24949 12.5778 12.5778 12.1555 12.1555 6.24949 + 12.5778 12.5778 14.6789 21.217 21.217 12.5778 12.5778 8.49387 21.217 31.4164 + 13.8718 14.6789 8.49387 8.49387 13.8718 13.8718 13.8718 + + + + + 0 0 0 0.111111 0 0 0.222222 0 0 + 0.444444 0 0 0 0.111111 0 0.111111 0.111111 0 + 0.222222 0.111111 0 0.333333 0.111111 0 0.444444 0.111111 0 + 0 0.222222 0 0.222222 0.222222 0 0.333333 0.222222 0 + 0 0.333333 0 0.111111 0.333333 0 0.222222 0.333333 0 + 0.333333 0.333333 0 0.444444 0.333333 0 0 0.444444 0 + 0.111111 0.444444 0 0.222222 0.444444 0 0.444444 0.444444 0 + 0 0 0.111111 0.111111 0 0.111111 0.222222 0 0.111111 + 0.333333 0 0.111111 0.444444 0 0.111111 0 0.111111 0.111111 + 0.111111 0.111111 0.111111 0.333333 0.111111 0.111111 0.444444 0.111111 0.111111 + 0 0.222222 0.111111 0.111111 0.222222 0.111111 0.333333 0.222222 0.111111 + 0.444444 0.222222 0.111111 0 0.333333 0.111111 0.111111 0.333333 0.111111 + 0.222222 0.333333 0.111111 0.333333 0.333333 0.111111 0.444444 0.333333 0.111111 + 0 0.444444 0.111111 0.111111 0.444444 0.111111 0.222222 0.444444 0.111111 + 0.333333 0.444444 0.111111 0.444444 0.444444 0.111111 0 0 0.222222 + 0.222222 0 0.222222 0.333333 0 0.222222 0 0.111111 0.222222 + 0.111111 0.111111 0.222222 0.222222 0.111111 0.222222 0.333333 0.111111 0.222222 + 0.444444 0.111111 0.222222 0.111111 0.222222 0.222222 0.222222 0.222222 0.222222 + 0.444444 0.222222 0.222222 0 0.333333 0.222222 0.111111 0.333333 0.222222 + 0.222222 0.333333 0.222222 0.333333 0.333333 0.222222 0.444444 0.333333 0.222222 + 0 0.444444 0.222222 0.222222 0.444444 0.222222 0.333333 0.444444 0.222222 + 0 0 0.333333 0.111111 0 0.333333 0.222222 0 0.333333 + 0.333333 0 0.333333 0.444444 0 0.333333 0 0.111111 0.333333 + 0.111111 0.111111 0.333333 0.222222 0.111111 0.333333 0.333333 0.111111 0.333333 + 0.444444 0.111111 0.333333 0 0.222222 0.333333 0.111111 0.222222 0.333333 + 0.333333 0.222222 0.333333 0.444444 0.222222 0.333333 0 0.333333 0.333333 + 0.111111 0.333333 0.333333 0.333333 0.333333 0.333333 0.444444 0.333333 0.333333 + 0 0.444444 0.333333 0.111111 0.444444 0.333333 0.222222 0.444444 0.333333 + 0.333333 0.444444 0.333333 0.444444 0.444444 0.333333 0.111111 0 0.444444 + 0.222222 0 0.444444 0.444444 0 0.444444 0 0.111111 0.444444 + 0.111111 0.111111 0.444444 0.222222 0.111111 0.444444 0.333333 0.111111 0.444444 + 0.444444 0.111111 0.444444 0 0.222222 0.444444 0.222222 0.222222 0.444444 + 0.333333 0.222222 0.444444 0 0.333333 0.444444 0.111111 0.333333 0.444444 + 0.222222 0.333333 0.444444 0.333333 0.333333 0.444444 0.444444 0.333333 0.444444 + 0.111111 0.444444 0.444444 0.222222 0.444444 0.444444 0.444444 0.444444 0.444444 + 0 0 0.555556 0.111111 0 0.555556 0.222222 0 0.555556 + 0.333333 0 0.555556 0.444444 0 0.555556 0 0.111111 0.555556 + 0.111111 0.111111 0.555556 0.333333 0.111111 0.555556 0.444444 0.111111 0.555556 + 0 0.222222 0.555556 0.111111 0.222222 0.555556 0.333333 0.222222 0.555556 + 0.444444 0.222222 0.555556 0 0.333333 0.555556 0.111111 0.333333 0.555556 + 0.222222 0.333333 0.555556 0.333333 0.333333 0.555556 0.444444 0.333333 0.555556 + 0 0.444444 0.555556 0.111111 0.444444 0.555556 0.222222 0.444444 0.555556 + 0.333333 0.444444 0.555556 0.444444 0.444444 0.555556 0 0 0.666667 + 0.222222 0 0.666667 0.333333 0 0.666667 0 0.111111 0.666667 + 0.111111 0.111111 0.666667 0.222222 0.111111 0.666667 0.333333 0.111111 0.666667 + 0.444444 0.111111 0.666667 0.111111 0.222222 0.666667 0.222222 0.222222 0.666667 + 0.444444 0.222222 0.666667 0 0.333333 0.666667 0.111111 0.333333 0.666667 + 0.222222 0.333333 0.666667 0.333333 0.333333 0.666667 0 0.444444 0.666667 + 0.222222 0.444444 0.666667 0.333333 0.444444 0.666667 0 0 0.777778 + 0.111111 0 0.777778 0.222222 0 0.777778 0.333333 0 0.777778 + 0.444444 0 0.777778 0 0.111111 0.777778 0.111111 0.111111 0.777778 + 0.222222 0.111111 0.777778 0.333333 0.111111 0.777778 0.444444 0.111111 0.777778 + 0 0.222222 0.777778 0.111111 0.222222 0.777778 0.333333 0.222222 0.777778 + 0.444444 0.222222 0.777778 0 0.333333 0.777778 0.111111 0.333333 0.777778 + 0.333333 0.333333 0.777778 0.444444 0.333333 0.777778 0 0.444444 0.777778 + 0.111111 0.444444 0.777778 0.222222 0.444444 0.777778 0.333333 0.444444 0.777778 + 0.444444 0.444444 0.777778 0.111111 0 0.888889 0.222222 0 0.888889 + 0.444444 0 0.888889 0.111111 0.111111 0.888889 0.222222 0.111111 0.888889 + 0.333333 0.111111 0.888889 0 0.222222 0.888889 0.222222 0.222222 0.888889 + 0.333333 0.222222 0.888889 0.111111 0.333333 0.888889 0.333333 0.333333 0.888889 + 0.444444 0.333333 0.888889 0.111111 0.444444 0.888889 0.222222 0.444444 0.888889 + 0.444444 0.444444 0.888889 0 0 1 0.111111 0 1 + 0.222222 0 1 0.333333 0 1 0.444444 0 1 + 0 0.111111 1 0.111111 0.111111 1 0.333333 0.111111 1 + 0.444444 0.111111 1 0 0.222222 1 0.111111 0.222222 1 + 0.222222 0.222222 1 0.333333 0.222222 1 0 0.333333 1 + 0.111111 0.333333 1 0.222222 0.333333 1 0.333333 0.333333 1 + 0.444444 0.333333 1 0 0.444444 1 0.111111 0.444444 1 + 0.222222 0.444444 1 0.333333 0.444444 1 0.444444 0.444444 1 + + + + + + 26 4 0 4 1 0 26 1 4 0 + 1 21 26 0 21 1 26 21 3 2 + 7 24 3 7 2 24 7 2 3 24 + 9 14 5 31 9 5 5 14 10 31 + 5 10 14 31 10 14 9 13 9 31 + 13 31 14 13 16 8 11 8 29 11 + 8 16 29 16 11 33 11 29 33 29 + 16 33 18 17 39 17 12 39 18 12 + 17 12 18 34 39 12 34 18 39 34 + 15 20 37 19 15 37 19 20 15 20 + 19 42 37 20 42 19 37 41 42 19 + 41 37 42 41 27 36 6 23 27 6 + 23 6 28 6 36 28 27 23 49 23 + 28 49 36 27 49 28 36 49 65 44 + 22 44 48 22 22 48 45 65 22 45 + 48 65 45 48 44 64 44 65 64 65 + 48 64 25 67 46 67 72 46 25 72 + 67 25 46 51 72 25 51 46 72 51 + 68 55 30 55 52 30 30 52 47 68 + 30 47 52 68 47 52 55 73 68 52 + 73 55 68 73 53 58 32 32 58 54 + 53 32 50 32 54 50 71 53 50 54 + 71 50 58 53 75 53 71 75 54 58 + 75 71 54 75 82 40 60 40 35 60 + 60 35 56 82 60 56 35 40 61 56 + 35 61 40 82 61 82 56 61 43 38 + 62 85 43 62 85 38 43 62 38 59 + 38 85 59 85 62 59 78 83 57 70 + 78 57 70 57 79 57 83 79 78 70 + 99 70 79 99 83 78 99 79 83 99 + 110 105 86 105 63 86 110 63 105 86 + 63 89 63 110 89 110 86 89 88 87 + 66 92 88 66 87 92 66 87 88 108 + 92 87 108 88 92 108 98 94 115 98 + 115 95 94 69 90 69 95 90 115 94 + 90 95 115 90 69 94 74 95 69 74 + 94 98 74 98 95 74 101 93 76 93 + 96 76 76 96 80 101 76 80 96 101 + 80 96 93 117 93 101 117 101 96 117 + 81 123 102 77 81 102 77 123 81 77 + 102 97 123 77 97 102 123 97 104 84 + 125 125 84 103 121 125 103 103 84 100 + 84 104 100 121 103 100 104 121 100 121 + 104 126 104 125 126 125 121 126 111 120 + 91 107 111 91 107 91 112 91 120 112 + 111 107 133 107 112 133 120 111 133 112 + 120 133 148 128 106 128 132 106 106 132 + 129 148 106 129 132 148 129 132 128 147 + 128 148 147 148 132 147 150 109 113 109 + 130 113 109 150 130 113 130 135 150 113 + 135 130 150 135 131 139 114 136 131 114 + 136 114 118 114 139 118 139 136 118 131 + 136 156 139 131 156 136 139 156 137 142 + 116 116 142 138 137 116 134 116 138 134 + 154 137 134 138 154 134 142 137 158 137 + 154 158 138 142 158 154 138 158 165 124 + 143 124 119 143 143 119 140 165 143 140 + 119 124 144 140 119 144 124 165 144 165 + 140 144 127 122 145 168 127 145 168 122 + 127 145 122 163 122 168 163 168 145 163 + 166 161 199 161 153 199 199 153 162 166 + 199 162 153 161 141 162 153 141 161 166 + 141 166 162 141 151 189 169 146 151 169 + 146 189 151 146 169 184 189 146 184 169 + 189 184 188 170 149 170 174 149 149 174 + 171 188 149 171 174 188 171 174 170 187 + 170 188 187 188 174 187 198 193 194 193 + 152 172 194 193 172 152 157 176 172 152 + 176 194 172 176 198 194 176 176 157 178 + 198 176 178 193 198 178 157 152 175 152 + 193 175 178 157 175 193 178 175 155 201 + 192 177 155 192 201 177 192 201 155 180 + 177 201 180 155 177 159 180 155 159 177 + 180 159 160 203 197 164 160 197 164 197 + 202 203 164 202 197 203 202 160 164 181 + 203 160 181 164 203 181 182 206 167 179 + 182 167 179 167 183 167 206 183 206 179 + 183 206 182 205 182 179 204 205 182 204 + 204 179 200 179 206 200 205 204 200 206 + 205 200 186 185 173 196 185 186 196 173 + 195 185 196 195 173 185 190 195 173 190 + 185 195 190 186 173 191 173 196 191 196 + 186 191 + + + 3 6 9 12 15 18 21 24 27 30 + 33 36 39 42 45 48 51 54 57 60 + 63 66 69 72 75 78 81 84 87 90 + 93 96 99 102 105 108 111 114 117 120 + 123 126 129 132 135 138 141 144 147 150 + 153 156 159 162 165 168 171 174 177 180 + 183 186 189 192 195 198 201 204 207 210 + 213 216 219 222 225 228 231 234 237 240 + 243 246 249 252 255 258 261 264 267 270 + 273 276 279 282 285 288 291 294 297 300 + 303 306 309 312 315 318 321 324 327 330 + 333 336 339 342 345 348 351 354 357 360 + 363 366 369 372 375 378 381 384 387 390 + 393 396 399 402 405 408 411 414 417 420 + 423 426 429 432 435 438 441 444 447 450 + 453 456 459 462 465 468 471 474 477 480 + 483 486 489 492 495 498 501 504 507 510 + 513 516 519 522 525 528 531 534 537 540 + 543 546 549 552 555 558 561 564 567 570 + 573 576 579 582 585 588 591 594 597 600 + 603 606 609 612 615 618 621 624 627 630 + 633 636 639 642 645 648 651 654 657 660 + 663 666 669 672 675 678 681 684 687 690 + 693 696 699 702 705 708 711 714 717 720 + 723 726 729 732 735 738 741 744 747 750 + 753 756 759 762 765 768 771 774 777 780 + 783 786 789 792 795 798 801 804 807 810 + 813 816 819 822 + + + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 + + + + + \ No newline at end of file diff --git a/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc1.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc1.gold new file mode 100644 index 000000000000..d80c44e8c17c --- /dev/null +++ b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc1.gold @@ -0,0 +1,294 @@ + + + + + + + 5 6 7 9 15 16 17 18 19 25 + 27 28 35 36 37 38 39 45 46 47 + 49 105 106 107 108 109 115 116 118 119 + 125 126 128 129 135 136 137 138 139 145 + 146 147 148 149 205 207 208 215 216 217 + 218 219 226 227 229 235 236 237 238 239 + 245 247 248 305 306 307 308 309 315 316 + 317 318 319 325 326 328 329 335 336 338 + 339 345 346 347 348 349 406 407 409 415 + 416 417 418 419 425 427 428 435 436 437 + 438 439 446 447 449 505 506 507 508 509 + 515 516 518 519 525 526 528 529 535 536 + 537 538 539 545 546 547 548 549 605 607 + 608 615 616 617 618 619 626 627 629 635 + 636 637 638 645 647 648 705 706 707 708 + 709 715 716 717 718 719 725 726 728 729 + 735 736 738 739 745 746 747 748 749 806 + 807 809 816 817 818 825 827 828 836 838 + 839 846 847 849 905 906 907 908 909 915 + 916 918 919 925 926 927 928 935 936 937 + 938 939 945 946 947 948 949 + + + 35 35 36 36 35 37 41 36 38 37 + 37 38 39 37 37 40 38 39 39 40 + 40 35 42 41 36 43 35 41 41 38 + 44 37 45 38 39 46 41 40 47 39 + 46 40 40 47 42 42 43 44 42 41 + 45 43 44 45 45 44 46 48 45 47 + 46 46 47 49 42 42 50 43 44 51 + 48 45 43 44 51 45 52 53 48 48 + 52 53 46 48 54 47 49 50 50 49 + 51 55 50 52 51 51 52 53 51 48 + 54 52 53 54 54 49 56 55 50 57 + 49 55 55 57 58 51 59 52 58 60 + 55 54 61 53 60 54 54 61 56 56 + 57 58 56 55 59 57 58 59 59 58 + 60 62 59 60 60 61 63 56 56 64 + 57 63 65 62 59 66 58 65 59 66 + 67 62 62 61 67 60 62 68 61 63 + 64 64 65 69 64 65 65 66 65 68 + 66 67 68 68 63 69 69 64 64 63 + 69 69 66 65 65 69 69 67 65 62 + 68 66 67 67 68 68 68 + + + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + + + 7.10619 7.10619 6 6 7.10619 12.2712 26.5197 6 6.35236 12.2712 + 12.2712 6.35236 9.65407 12.2712 12.2712 8.68328 6.35236 9.65407 9.65407 8.68328 + 8.68328 7.10619 12.2712 26.5197 6 6.35236 7.10619 26.5197 26.5197 6.35236 + 16.5078 12.2712 17.0714 6.35236 9.65407 16.5078 26.5197 8.68328 12.3728 9.65407 + 16.5078 8.68328 8.68328 12.3728 12.2712 12.2712 6.35236 16.5078 12.2712 26.5197 + 17.0714 6.35236 16.5078 17.0714 17.0714 16.5078 16.5078 26.5197 17.0714 12.3728 + 16.5078 16.5078 12.3728 11.0268 12.2712 12.2712 11.6029 6.35236 16.5078 17.0714 + 26.5197 17.0714 6.35236 16.5078 17.0714 17.0714 12.2712 15.7082 26.5197 26.5197 + 12.2712 15.7082 16.5078 26.5197 15.5535 12.3728 11.0268 11.6029 11.6029 11.0268 + 17.0714 26.5197 11.6029 12.2712 17.0714 17.0714 12.2712 15.7082 17.0714 26.5197 + 15.5535 12.2712 15.7082 15.5535 15.5535 11.0268 12.2712 26.5197 11.6029 6.35236 + 11.0268 26.5197 26.5197 6.35236 16.5078 17.0714 17.0714 12.2712 16.5078 16.5078 + 26.5197 15.5535 12.9067 15.7082 16.5078 15.5535 15.5535 12.9067 12.2712 12.2712 + 6.35236 16.5078 12.2712 26.5197 17.0714 6.35236 16.5078 17.0714 17.0714 16.5078 + 16.5078 31.4164 17.0714 16.5078 16.5078 12.9067 8.80585 12.2712 12.2712 12.1089 + 6.35236 8.80585 21.4164 31.4164 17.0714 12.8711 16.5078 21.4164 17.0714 12.8711 + 14.657 31.4164 31.4164 12.9067 14.657 16.5078 31.4164 13.7649 12.9067 8.80585 + 12.1089 12.1089 21.4164 12.5778 12.1089 21.4164 21.4164 12.8711 21.4164 13.7649 + 12.8711 14.657 13.7649 13.7649 8.80585 12.5778 12.5778 12.1089 12.1089 8.80585 + 12.5778 12.5778 12.8711 21.4164 21.4164 12.5778 12.5778 14.657 21.4164 31.4164 + 13.7649 12.8711 14.657 14.657 13.7649 13.7649 13.7649 + + + + + 0.555556 0 0 0.666667 0 0 0.777778 0 0 + 1 0 0 0.555556 0.111111 0 0.666667 0.111111 0 + 0.777778 0.111111 0 0.888889 0.111111 0 1 0.111111 0 + 0.555556 0.222222 0 0.777778 0.222222 0 0.888889 0.222222 0 + 0.555556 0.333333 0 0.666667 0.333333 0 0.777778 0.333333 0 + 0.888889 0.333333 0 1 0.333333 0 0.555556 0.444444 0 + 0.666667 0.444444 0 0.777778 0.444444 0 1 0.444444 0 + 0.555556 0 0.111111 0.666667 0 0.111111 0.777778 0 0.111111 + 0.888889 0 0.111111 1 0 0.111111 0.555556 0.111111 0.111111 + 0.666667 0.111111 0.111111 0.888889 0.111111 0.111111 1 0.111111 0.111111 + 0.555556 0.222222 0.111111 0.666667 0.222222 0.111111 0.888889 0.222222 0.111111 + 1 0.222222 0.111111 0.555556 0.333333 0.111111 0.666667 0.333333 0.111111 + 0.777778 0.333333 0.111111 0.888889 0.333333 0.111111 1 0.333333 0.111111 + 0.555556 0.444444 0.111111 0.666667 0.444444 0.111111 0.777778 0.444444 0.111111 + 0.888889 0.444444 0.111111 1 0.444444 0.111111 0.555556 0 0.222222 + 0.777778 0 0.222222 0.888889 0 0.222222 0.555556 0.111111 0.222222 + 0.666667 0.111111 0.222222 0.777778 0.111111 0.222222 0.888889 0.111111 0.222222 + 1 0.111111 0.222222 0.666667 0.222222 0.222222 0.777778 0.222222 0.222222 + 1 0.222222 0.222222 0.555556 0.333333 0.222222 0.666667 0.333333 0.222222 + 0.777778 0.333333 0.222222 0.888889 0.333333 0.222222 1 0.333333 0.222222 + 0.555556 0.444444 0.222222 0.777778 0.444444 0.222222 0.888889 0.444444 0.222222 + 0.555556 0 0.333333 0.666667 0 0.333333 0.777778 0 0.333333 + 0.888889 0 0.333333 1 0 0.333333 0.555556 0.111111 0.333333 + 0.666667 0.111111 0.333333 0.777778 0.111111 0.333333 0.888889 0.111111 0.333333 + 1 0.111111 0.333333 0.555556 0.222222 0.333333 0.666667 0.222222 0.333333 + 0.888889 0.222222 0.333333 1 0.222222 0.333333 0.555556 0.333333 0.333333 + 0.666667 0.333333 0.333333 0.888889 0.333333 0.333333 1 0.333333 0.333333 + 0.555556 0.444444 0.333333 0.666667 0.444444 0.333333 0.777778 0.444444 0.333333 + 0.888889 0.444444 0.333333 1 0.444444 0.333333 0.666667 0 0.444444 + 0.777778 0 0.444444 1 0 0.444444 0.555556 0.111111 0.444444 + 0.666667 0.111111 0.444444 0.777778 0.111111 0.444444 0.888889 0.111111 0.444444 + 1 0.111111 0.444444 0.555556 0.222222 0.444444 0.777778 0.222222 0.444444 + 0.888889 0.222222 0.444444 0.555556 0.333333 0.444444 0.666667 0.333333 0.444444 + 0.777778 0.333333 0.444444 0.888889 0.333333 0.444444 1 0.333333 0.444444 + 0.666667 0.444444 0.444444 0.777778 0.444444 0.444444 1 0.444444 0.444444 + 0.555556 0 0.555556 0.666667 0 0.555556 0.777778 0 0.555556 + 0.888889 0 0.555556 1 0 0.555556 0.555556 0.111111 0.555556 + 0.666667 0.111111 0.555556 0.888889 0.111111 0.555556 1 0.111111 0.555556 + 0.555556 0.222222 0.555556 0.666667 0.222222 0.555556 0.888889 0.222222 0.555556 + 1 0.222222 0.555556 0.555556 0.333333 0.555556 0.666667 0.333333 0.555556 + 0.777778 0.333333 0.555556 0.888889 0.333333 0.555556 1 0.333333 0.555556 + 0.555556 0.444444 0.555556 0.666667 0.444444 0.555556 0.777778 0.444444 0.555556 + 0.888889 0.444444 0.555556 1 0.444444 0.555556 0.555556 0 0.666667 + 0.777778 0 0.666667 0.888889 0 0.666667 0.555556 0.111111 0.666667 + 0.666667 0.111111 0.666667 0.777778 0.111111 0.666667 0.888889 0.111111 0.666667 + 1 0.111111 0.666667 0.666667 0.222222 0.666667 0.777778 0.222222 0.666667 + 1 0.222222 0.666667 0.555556 0.333333 0.666667 0.666667 0.333333 0.666667 + 0.777778 0.333333 0.666667 0.888889 0.333333 0.666667 0.555556 0.444444 0.666667 + 0.777778 0.444444 0.666667 0.888889 0.444444 0.666667 0.555556 0 0.777778 + 0.666667 0 0.777778 0.777778 0 0.777778 0.888889 0 0.777778 + 1 0 0.777778 0.555556 0.111111 0.777778 0.666667 0.111111 0.777778 + 0.777778 0.111111 0.777778 0.888889 0.111111 0.777778 1 0.111111 0.777778 + 0.555556 0.222222 0.777778 0.666667 0.222222 0.777778 0.888889 0.222222 0.777778 + 1 0.222222 0.777778 0.555556 0.333333 0.777778 0.666667 0.333333 0.777778 + 0.888889 0.333333 0.777778 1 0.333333 0.777778 0.555556 0.444444 0.777778 + 0.666667 0.444444 0.777778 0.777778 0.444444 0.777778 0.888889 0.444444 0.777778 + 1 0.444444 0.777778 0.666667 0 0.888889 0.777778 0 0.888889 + 1 0 0.888889 0.666667 0.111111 0.888889 0.777778 0.111111 0.888889 + 0.888889 0.111111 0.888889 0.555556 0.222222 0.888889 0.777778 0.222222 0.888889 + 0.888889 0.222222 0.888889 0.666667 0.333333 0.888889 0.888889 0.333333 0.888889 + 1 0.333333 0.888889 0.666667 0.444444 0.888889 0.777778 0.444444 0.888889 + 1 0.444444 0.888889 0.555556 0 1 0.666667 0 1 + 0.777778 0 1 0.888889 0 1 1 0 1 + 0.555556 0.111111 1 0.666667 0.111111 1 0.888889 0.111111 1 + 1 0.111111 1 0.555556 0.222222 1 0.666667 0.222222 1 + 0.777778 0.222222 1 0.888889 0.222222 1 0.555556 0.333333 1 + 0.666667 0.333333 1 0.777778 0.333333 1 0.888889 0.333333 1 + 1 0.333333 1 0.555556 0.444444 1 0.666667 0.444444 1 + 0.777778 0.444444 1 0.888889 0.444444 1 1 0.444444 1 + + + + + + 26 4 0 4 1 0 26 1 4 0 + 1 21 26 0 21 1 26 21 3 2 + 7 24 3 7 2 24 7 2 3 24 + 9 14 5 31 9 5 5 14 10 31 + 5 10 14 31 10 14 9 13 9 31 + 13 31 14 13 16 8 11 8 29 11 + 8 16 29 16 11 33 11 29 33 29 + 16 33 18 17 39 17 12 39 18 12 + 17 12 18 34 39 12 34 18 39 34 + 15 20 37 19 15 37 19 20 15 20 + 19 42 37 20 42 19 37 41 42 19 + 41 37 42 41 27 36 6 23 27 6 + 23 6 28 6 36 28 27 23 49 23 + 28 49 36 27 49 28 36 49 65 44 + 22 44 48 22 22 48 45 65 22 45 + 48 65 45 48 44 64 44 65 64 65 + 48 64 25 67 46 67 72 46 25 72 + 67 25 46 51 72 25 51 46 72 51 + 68 55 30 55 52 30 30 52 47 68 + 30 47 52 68 47 52 55 73 68 52 + 73 55 68 73 53 58 32 32 58 54 + 53 32 50 32 54 50 71 53 50 54 + 71 50 58 53 75 53 71 75 54 58 + 75 71 54 75 82 40 60 40 35 60 + 60 35 56 82 60 56 35 40 61 56 + 35 61 40 82 61 82 56 61 43 38 + 62 85 43 62 85 38 43 62 38 59 + 38 85 59 85 62 59 78 83 57 70 + 78 57 70 57 79 57 83 79 78 70 + 99 70 79 99 83 78 99 79 83 99 + 110 105 86 105 63 86 110 63 105 86 + 63 89 63 110 89 110 86 89 88 87 + 66 92 88 66 87 92 66 87 88 108 + 92 87 108 88 92 108 98 94 115 98 + 115 95 94 69 90 69 95 90 115 94 + 90 95 115 90 69 94 74 95 69 74 + 94 98 74 98 95 74 101 93 76 93 + 96 76 76 96 80 101 76 80 96 101 + 80 96 93 117 93 101 117 101 96 117 + 81 123 102 77 81 102 77 123 81 77 + 102 97 123 77 97 102 123 97 104 84 + 125 125 84 103 121 125 103 103 84 100 + 84 104 100 121 103 100 104 121 100 121 + 104 126 104 125 126 125 121 126 111 120 + 91 107 111 91 107 91 112 91 120 112 + 111 107 133 107 112 133 120 111 133 112 + 120 133 148 128 106 128 132 106 106 132 + 129 148 106 129 132 148 129 132 128 147 + 128 148 147 148 132 147 150 109 113 109 + 130 113 109 150 130 113 130 135 150 113 + 135 130 150 135 131 139 114 136 131 114 + 136 114 118 114 139 118 139 136 118 131 + 136 156 139 131 156 136 139 156 137 142 + 116 116 142 138 137 116 134 116 138 134 + 154 137 134 138 154 134 142 137 158 137 + 154 158 138 142 158 154 138 158 165 124 + 143 124 119 143 143 119 140 165 143 140 + 119 124 144 140 119 144 124 165 144 165 + 140 144 127 122 145 168 127 145 168 122 + 127 145 122 163 122 168 163 168 145 163 + 166 161 199 161 153 199 199 153 162 166 + 199 162 153 161 141 162 153 141 161 166 + 141 166 162 141 151 189 169 146 151 169 + 146 189 151 146 169 184 189 146 184 169 + 189 184 188 170 149 170 174 149 149 174 + 171 188 149 171 174 188 171 174 170 187 + 170 188 187 188 174 187 198 193 194 193 + 152 172 194 193 172 152 157 176 172 152 + 176 194 172 176 198 194 176 176 157 178 + 198 176 178 193 198 178 157 152 175 152 + 193 175 178 157 175 193 178 175 155 201 + 192 177 155 192 201 177 192 201 155 180 + 177 201 180 155 177 159 180 155 159 177 + 180 159 160 203 197 164 160 197 164 197 + 202 203 164 202 197 203 202 160 164 181 + 203 160 181 164 203 181 182 206 167 179 + 182 167 179 167 183 167 206 183 206 179 + 183 206 182 205 182 179 204 205 182 204 + 204 179 200 179 206 200 205 204 200 206 + 205 200 186 185 173 196 185 186 196 173 + 195 185 196 195 173 185 190 195 173 190 + 185 195 190 186 173 191 173 196 191 196 + 186 191 + + + 3 6 9 12 15 18 21 24 27 30 + 33 36 39 42 45 48 51 54 57 60 + 63 66 69 72 75 78 81 84 87 90 + 93 96 99 102 105 108 111 114 117 120 + 123 126 129 132 135 138 141 144 147 150 + 153 156 159 162 165 168 171 174 177 180 + 183 186 189 192 195 198 201 204 207 210 + 213 216 219 222 225 228 231 234 237 240 + 243 246 249 252 255 258 261 264 267 270 + 273 276 279 282 285 288 291 294 297 300 + 303 306 309 312 315 318 321 324 327 330 + 333 336 339 342 345 348 351 354 357 360 + 363 366 369 372 375 378 381 384 387 390 + 393 396 399 402 405 408 411 414 417 420 + 423 426 429 432 435 438 441 444 447 450 + 453 456 459 462 465 468 471 474 477 480 + 483 486 489 492 495 498 501 504 507 510 + 513 516 519 522 525 528 531 534 537 540 + 543 546 549 552 555 558 561 564 567 570 + 573 576 579 582 585 588 591 594 597 600 + 603 606 609 612 615 618 621 624 627 630 + 633 636 639 642 645 648 651 654 657 660 + 663 666 669 672 675 678 681 684 687 690 + 693 696 699 702 705 708 711 714 717 720 + 723 726 729 732 735 738 741 744 747 750 + 753 756 759 762 765 768 771 774 777 780 + 783 786 789 792 795 798 801 804 807 810 + 813 816 819 822 + + + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 + + + + + \ No newline at end of file diff --git a/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc2.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc2.gold new file mode 100644 index 000000000000..3bdb8049687f --- /dev/null +++ b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc2.gold @@ -0,0 +1,294 @@ + + + + + + + 50 51 52 54 60 61 62 63 64 70 + 72 73 80 81 82 83 84 90 91 92 + 94 150 151 152 153 154 160 161 163 164 + 170 171 173 174 180 181 182 183 184 190 + 191 192 193 194 250 252 253 260 261 262 + 263 264 271 272 274 280 281 282 283 284 + 290 292 293 350 351 352 353 354 360 361 + 362 363 364 370 371 373 374 380 381 383 + 384 390 391 392 393 394 451 452 454 460 + 461 462 463 464 470 472 473 480 481 482 + 483 484 491 492 494 550 551 552 553 554 + 560 561 563 564 570 571 573 574 580 581 + 582 583 584 590 591 592 593 594 650 652 + 653 660 661 662 663 664 671 672 674 680 + 681 682 683 690 692 693 750 751 752 753 + 754 760 761 762 763 764 770 771 773 774 + 780 781 783 784 790 791 792 793 794 851 + 852 854 861 862 863 870 872 873 881 883 + 884 891 892 894 950 951 952 953 954 960 + 961 963 964 970 971 972 973 980 981 982 + 983 984 990 991 992 993 994 + + + 70 70 71 71 70 72 76 71 73 72 + 72 73 74 72 72 75 73 74 74 75 + 75 70 77 76 71 78 70 76 76 73 + 79 72 80 73 74 81 76 75 82 74 + 81 75 75 82 77 77 78 79 77 76 + 80 78 79 80 80 79 81 83 80 82 + 81 81 82 84 77 77 85 78 79 86 + 83 80 78 79 86 80 87 88 83 83 + 87 88 81 83 89 82 84 85 85 84 + 86 90 85 87 86 86 87 88 86 83 + 89 87 88 89 89 84 91 90 85 92 + 84 90 90 92 93 86 94 87 93 95 + 90 89 96 88 95 89 89 96 91 91 + 92 93 91 90 94 92 93 94 94 93 + 95 97 94 95 95 96 98 91 91 99 + 92 98 100 97 94 101 93 100 94 101 + 102 97 97 96 102 95 97 103 96 98 + 99 99 100 104 99 100 100 101 100 103 + 101 102 103 103 98 104 104 99 99 98 + 104 104 101 100 100 104 104 102 100 97 + 103 101 102 102 103 103 103 + + + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 + + + 6.36105 6.36105 11.423 11.423 6.36105 12.2679 26.5197 11.423 11.0268 12.2679 + 12.2679 11.0268 4.71117 12.2679 12.2679 7.81935 11.0268 4.71117 4.71117 7.81935 + 7.81935 6.36105 16.5078 26.5197 11.423 15.7082 6.36105 26.5197 26.5197 11.0268 + 12.2712 12.2679 17.0714 11.0268 4.71117 11.7696 26.5197 7.81935 11.0268 4.71117 + 11.7696 7.81935 7.81935 11.0268 16.5078 16.5078 15.7082 12.2712 16.5078 26.5197 + 17.0714 15.7082 12.2712 17.0714 17.0714 12.2712 11.7696 26.5197 17.0714 11.0268 + 11.7696 11.7696 11.0268 12.3728 16.5078 16.5078 12 15.7082 12.2712 17.0714 + 26.5197 17.0714 15.7082 12.2712 17.0714 17.0714 16.5078 6.35236 26.5197 26.5197 + 16.5078 6.35236 11.7696 26.5197 11.377 11.0268 12.3728 12 12 12.3728 + 17.0714 26.5197 12 16.5078 17.0714 17.0714 16.5078 6.35236 17.0714 26.5197 + 11.377 16.5078 6.35236 11.377 11.377 12.3728 16.5078 26.5197 12 15.7082 + 12.3728 26.5197 26.5197 15.7082 12.2712 17.0714 17.0714 16.5078 12.2712 11.7696 + 26.5197 11.377 9.04703 6.35236 11.7696 11.377 11.377 9.04703 16.5078 16.5078 + 15.7082 12.2712 16.5078 26.5197 17.0714 15.7082 12.2712 17.0714 17.0714 12.2712 + 11.7696 28.5123 17.0714 11.7696 11.7696 9.04703 12.8435 16.5078 16.5078 16.2073 + 15.7082 12.8435 21.217 28.5123 17.0714 14.6789 12.2712 21.217 17.0714 14.6789 + 5.63662 28.5123 28.5123 9.04703 5.63662 11.7696 28.5123 7.99012 9.04703 12.8435 + 16.2073 16.2073 21.217 12.6149 16.2073 21.217 21.217 14.6789 21.217 7.99012 + 14.6789 5.63662 7.99012 7.99012 12.8435 12.6149 12.6149 16.2073 16.2073 12.8435 + 12.6149 12.6149 14.6789 21.217 21.217 12.6149 12.6149 5.63662 21.217 28.5123 + 7.99012 14.6789 5.63662 5.63662 7.99012 7.99012 7.99012 + + + + + 0 0.555556 0 0.111111 0.555556 0 0.222222 0.555556 0 + 0.444444 0.555556 0 0 0.666667 0 0.111111 0.666667 0 + 0.222222 0.666667 0 0.333333 0.666667 0 0.444444 0.666667 0 + 0 0.777778 0 0.222222 0.777778 0 0.333333 0.777778 0 + 0 0.888889 0 0.111111 0.888889 0 0.222222 0.888889 0 + 0.333333 0.888889 0 0.444444 0.888889 0 0 1 0 + 0.111111 1 0 0.222222 1 0 0.444444 1 0 + 0 0.555556 0.111111 0.111111 0.555556 0.111111 0.222222 0.555556 0.111111 + 0.333333 0.555556 0.111111 0.444444 0.555556 0.111111 0 0.666667 0.111111 + 0.111111 0.666667 0.111111 0.333333 0.666667 0.111111 0.444444 0.666667 0.111111 + 0 0.777778 0.111111 0.111111 0.777778 0.111111 0.333333 0.777778 0.111111 + 0.444444 0.777778 0.111111 0 0.888889 0.111111 0.111111 0.888889 0.111111 + 0.222222 0.888889 0.111111 0.333333 0.888889 0.111111 0.444444 0.888889 0.111111 + 0 1 0.111111 0.111111 1 0.111111 0.222222 1 0.111111 + 0.333333 1 0.111111 0.444444 1 0.111111 0 0.555556 0.222222 + 0.222222 0.555556 0.222222 0.333333 0.555556 0.222222 0 0.666667 0.222222 + 0.111111 0.666667 0.222222 0.222222 0.666667 0.222222 0.333333 0.666667 0.222222 + 0.444444 0.666667 0.222222 0.111111 0.777778 0.222222 0.222222 0.777778 0.222222 + 0.444444 0.777778 0.222222 0 0.888889 0.222222 0.111111 0.888889 0.222222 + 0.222222 0.888889 0.222222 0.333333 0.888889 0.222222 0.444444 0.888889 0.222222 + 0 1 0.222222 0.222222 1 0.222222 0.333333 1 0.222222 + 0 0.555556 0.333333 0.111111 0.555556 0.333333 0.222222 0.555556 0.333333 + 0.333333 0.555556 0.333333 0.444444 0.555556 0.333333 0 0.666667 0.333333 + 0.111111 0.666667 0.333333 0.222222 0.666667 0.333333 0.333333 0.666667 0.333333 + 0.444444 0.666667 0.333333 0 0.777778 0.333333 0.111111 0.777778 0.333333 + 0.333333 0.777778 0.333333 0.444444 0.777778 0.333333 0 0.888889 0.333333 + 0.111111 0.888889 0.333333 0.333333 0.888889 0.333333 0.444444 0.888889 0.333333 + 0 1 0.333333 0.111111 1 0.333333 0.222222 1 0.333333 + 0.333333 1 0.333333 0.444444 1 0.333333 0.111111 0.555556 0.444444 + 0.222222 0.555556 0.444444 0.444444 0.555556 0.444444 0 0.666667 0.444444 + 0.111111 0.666667 0.444444 0.222222 0.666667 0.444444 0.333333 0.666667 0.444444 + 0.444444 0.666667 0.444444 0 0.777778 0.444444 0.222222 0.777778 0.444444 + 0.333333 0.777778 0.444444 0 0.888889 0.444444 0.111111 0.888889 0.444444 + 0.222222 0.888889 0.444444 0.333333 0.888889 0.444444 0.444444 0.888889 0.444444 + 0.111111 1 0.444444 0.222222 1 0.444444 0.444444 1 0.444444 + 0 0.555556 0.555556 0.111111 0.555556 0.555556 0.222222 0.555556 0.555556 + 0.333333 0.555556 0.555556 0.444444 0.555556 0.555556 0 0.666667 0.555556 + 0.111111 0.666667 0.555556 0.333333 0.666667 0.555556 0.444444 0.666667 0.555556 + 0 0.777778 0.555556 0.111111 0.777778 0.555556 0.333333 0.777778 0.555556 + 0.444444 0.777778 0.555556 0 0.888889 0.555556 0.111111 0.888889 0.555556 + 0.222222 0.888889 0.555556 0.333333 0.888889 0.555556 0.444444 0.888889 0.555556 + 0 1 0.555556 0.111111 1 0.555556 0.222222 1 0.555556 + 0.333333 1 0.555556 0.444444 1 0.555556 0 0.555556 0.666667 + 0.222222 0.555556 0.666667 0.333333 0.555556 0.666667 0 0.666667 0.666667 + 0.111111 0.666667 0.666667 0.222222 0.666667 0.666667 0.333333 0.666667 0.666667 + 0.444444 0.666667 0.666667 0.111111 0.777778 0.666667 0.222222 0.777778 0.666667 + 0.444444 0.777778 0.666667 0 0.888889 0.666667 0.111111 0.888889 0.666667 + 0.222222 0.888889 0.666667 0.333333 0.888889 0.666667 0 1 0.666667 + 0.222222 1 0.666667 0.333333 1 0.666667 0 0.555556 0.777778 + 0.111111 0.555556 0.777778 0.222222 0.555556 0.777778 0.333333 0.555556 0.777778 + 0.444444 0.555556 0.777778 0 0.666667 0.777778 0.111111 0.666667 0.777778 + 0.222222 0.666667 0.777778 0.333333 0.666667 0.777778 0.444444 0.666667 0.777778 + 0 0.777778 0.777778 0.111111 0.777778 0.777778 0.333333 0.777778 0.777778 + 0.444444 0.777778 0.777778 0 0.888889 0.777778 0.111111 0.888889 0.777778 + 0.333333 0.888889 0.777778 0.444444 0.888889 0.777778 0 1 0.777778 + 0.111111 1 0.777778 0.222222 1 0.777778 0.333333 1 0.777778 + 0.444444 1 0.777778 0.111111 0.555556 0.888889 0.222222 0.555556 0.888889 + 0.444444 0.555556 0.888889 0.111111 0.666667 0.888889 0.222222 0.666667 0.888889 + 0.333333 0.666667 0.888889 0 0.777778 0.888889 0.222222 0.777778 0.888889 + 0.333333 0.777778 0.888889 0.111111 0.888889 0.888889 0.333333 0.888889 0.888889 + 0.444444 0.888889 0.888889 0.111111 1 0.888889 0.222222 1 0.888889 + 0.444444 1 0.888889 0 0.555556 1 0.111111 0.555556 1 + 0.222222 0.555556 1 0.333333 0.555556 1 0.444444 0.555556 1 + 0 0.666667 1 0.111111 0.666667 1 0.333333 0.666667 1 + 0.444444 0.666667 1 0 0.777778 1 0.111111 0.777778 1 + 0.222222 0.777778 1 0.333333 0.777778 1 0 0.888889 1 + 0.111111 0.888889 1 0.222222 0.888889 1 0.333333 0.888889 1 + 0.444444 0.888889 1 0 1 1 0.111111 1 1 + 0.222222 1 1 0.333333 1 1 0.444444 1 1 + + + + + + 26 4 0 4 1 0 26 1 4 0 + 1 21 26 0 21 1 26 21 3 2 + 7 24 3 7 2 24 7 2 3 24 + 9 14 5 31 9 5 5 14 10 31 + 5 10 14 31 10 14 9 13 9 31 + 13 31 14 13 16 8 11 8 29 11 + 8 16 29 16 11 33 11 29 33 29 + 16 33 18 17 39 17 12 39 18 12 + 17 12 18 34 39 12 34 18 39 34 + 15 20 37 19 15 37 19 20 15 20 + 19 42 37 20 42 19 37 41 42 19 + 41 37 42 41 27 36 6 23 27 6 + 23 6 28 6 36 28 27 23 49 23 + 28 49 36 27 49 28 36 49 65 44 + 22 44 48 22 22 48 45 65 22 45 + 48 65 45 48 44 64 44 65 64 65 + 48 64 25 67 46 67 72 46 25 72 + 67 25 46 51 72 25 51 46 72 51 + 47 55 30 55 52 30 52 47 30 55 + 47 73 52 55 73 47 52 68 73 47 + 68 52 73 68 53 71 75 71 54 75 + 32 53 58 54 32 58 53 75 58 75 + 54 58 53 32 50 32 54 50 71 53 + 50 54 71 50 82 40 60 40 35 60 + 60 35 56 82 60 56 35 40 61 56 + 35 61 40 82 61 82 56 61 43 38 + 62 85 43 62 85 38 43 62 38 59 + 38 85 59 85 62 59 78 83 57 70 + 78 57 70 57 79 57 83 79 78 70 + 99 70 79 99 83 78 99 79 83 99 + 110 105 86 105 63 86 110 63 105 86 + 63 89 63 110 89 110 86 89 88 87 + 66 92 88 66 87 92 66 87 88 108 + 92 87 108 88 92 108 98 94 115 98 + 115 95 94 69 90 69 95 90 115 94 + 90 95 115 90 69 94 74 95 69 74 + 94 98 74 98 95 74 101 93 76 93 + 96 76 76 96 80 101 76 80 96 101 + 80 96 93 117 93 101 117 101 96 117 + 81 123 102 77 81 102 77 123 81 77 + 102 97 123 77 97 102 123 97 103 104 + 84 104 103 126 121 104 126 103 121 125 + 126 103 125 121 126 125 103 84 100 84 + 104 100 121 103 100 104 121 100 111 120 + 91 107 111 91 107 91 112 91 120 112 + 111 107 133 107 112 133 120 111 133 112 + 120 133 148 128 106 128 132 106 106 132 + 129 148 106 129 132 148 129 132 128 147 + 128 148 147 148 132 147 150 109 113 109 + 130 113 109 150 130 113 130 135 150 113 + 135 130 150 135 131 139 114 136 131 114 + 136 114 118 114 139 118 139 136 118 131 + 136 156 139 131 156 136 139 156 137 142 + 116 116 142 138 137 116 134 116 138 134 + 154 137 134 138 154 134 142 137 158 137 + 154 158 138 142 158 154 138 158 165 124 + 143 124 119 143 143 119 140 165 143 140 + 119 124 144 140 119 144 124 165 144 165 + 140 144 127 122 145 168 127 145 168 122 + 127 145 122 163 122 168 163 168 145 163 + 166 161 199 161 153 199 199 153 162 166 + 199 162 153 161 141 162 153 141 161 166 + 141 166 162 141 151 189 169 146 151 169 + 146 189 151 146 169 184 189 146 184 169 + 189 184 188 170 149 170 174 149 149 174 + 171 188 149 171 174 188 171 174 170 187 + 170 188 187 188 174 187 198 193 194 193 + 152 172 194 193 172 152 157 176 172 152 + 176 194 172 176 198 194 176 176 157 178 + 198 176 178 193 198 178 157 152 175 152 + 193 175 178 157 175 193 178 175 155 201 + 192 177 155 192 201 177 192 201 155 180 + 177 201 180 155 177 159 180 155 159 177 + 180 159 160 203 197 164 160 197 164 197 + 202 203 164 202 197 203 202 160 164 181 + 203 160 181 164 203 181 182 206 167 179 + 182 167 179 167 183 167 206 183 206 179 + 183 206 182 205 182 179 204 205 182 204 + 204 179 200 179 206 200 205 204 200 206 + 205 200 186 185 173 196 185 186 196 173 + 195 185 196 195 173 185 190 195 173 190 + 185 195 190 186 173 191 173 196 191 196 + 186 191 + + + 3 6 9 12 15 18 21 24 27 30 + 33 36 39 42 45 48 51 54 57 60 + 63 66 69 72 75 78 81 84 87 90 + 93 96 99 102 105 108 111 114 117 120 + 123 126 129 132 135 138 141 144 147 150 + 153 156 159 162 165 168 171 174 177 180 + 183 186 189 192 195 198 201 204 207 210 + 213 216 219 222 225 228 231 234 237 240 + 243 246 249 252 255 258 261 264 267 270 + 273 276 279 282 285 288 291 294 297 300 + 303 306 309 312 315 318 321 324 327 330 + 333 336 339 342 345 348 351 354 357 360 + 363 366 369 372 375 378 381 384 387 390 + 393 396 399 402 405 408 411 414 417 420 + 423 426 429 432 435 438 441 444 447 450 + 453 456 459 462 465 468 471 474 477 480 + 483 486 489 492 495 498 501 504 507 510 + 513 516 519 522 525 528 531 534 537 540 + 543 546 549 552 555 558 561 564 567 570 + 573 576 579 582 585 588 591 594 597 600 + 603 606 609 612 615 618 621 624 627 630 + 633 636 639 642 645 648 651 654 657 660 + 663 666 669 672 675 678 681 684 687 690 + 693 696 699 702 705 708 711 714 717 720 + 723 726 729 732 735 738 741 744 747 750 + 753 756 759 762 765 768 771 774 777 780 + 783 786 789 792 795 798 801 804 807 810 + 813 816 819 822 + + + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 + + + + + \ No newline at end of file diff --git a/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc3.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc3.gold new file mode 100644 index 000000000000..442c1acdf559 --- /dev/null +++ b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0-Proc3.gold @@ -0,0 +1,294 @@ + + + + + + + 55 56 57 59 65 66 67 68 69 75 + 77 78 85 86 87 88 89 95 96 97 + 99 155 156 157 158 159 165 166 168 169 + 175 176 178 179 185 186 187 188 189 195 + 196 197 198 199 255 257 258 265 266 267 + 268 269 276 277 279 285 286 287 288 289 + 295 297 298 355 356 357 358 359 365 366 + 367 368 369 375 376 378 379 385 386 388 + 389 395 396 397 398 399 456 457 459 465 + 466 467 468 469 475 477 478 485 486 487 + 488 489 496 497 499 555 556 557 558 559 + 565 566 568 569 575 576 578 579 585 586 + 587 588 589 595 596 597 598 599 655 657 + 658 665 666 667 668 669 676 677 679 685 + 686 687 688 695 697 698 755 756 757 758 + 759 765 766 767 768 769 775 776 778 779 + 785 786 788 789 795 796 797 798 799 856 + 857 859 866 867 868 875 877 878 886 888 + 889 896 897 899 955 956 957 958 959 965 + 966 968 969 975 976 977 978 985 986 987 + 988 989 995 996 997 998 999 + + + 105 105 106 106 105 107 111 106 108 107 + 107 108 109 107 107 110 108 109 109 110 + 110 105 112 111 106 113 105 111 111 108 + 114 107 115 108 109 116 111 110 117 109 + 116 110 110 117 112 112 113 114 112 111 + 115 113 114 115 115 114 116 118 115 117 + 116 116 117 119 112 112 120 113 114 121 + 118 115 113 114 121 115 122 123 118 118 + 122 123 116 118 124 117 119 120 120 119 + 121 125 120 122 121 121 122 123 121 118 + 124 122 123 124 124 119 126 125 120 127 + 119 125 125 127 128 121 129 122 128 130 + 125 124 131 123 130 124 124 131 126 126 + 127 128 126 125 129 127 128 129 129 128 + 130 132 129 130 130 131 133 126 126 134 + 127 133 135 132 129 136 128 135 129 136 + 137 132 132 131 137 130 132 138 131 133 + 134 134 135 139 134 135 135 136 135 138 + 136 137 138 138 133 139 139 134 134 133 + 139 139 136 135 135 139 139 137 135 132 + 138 136 137 137 138 138 138 + + + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 + + + 9.65407 9.65407 11.4043 11.4043 9.65407 12.2712 26.5197 11.4043 6.35236 12.2712 + 12.2712 6.35236 7.10619 12.2712 12.2712 7.73649 6.35236 7.10619 7.10619 7.73649 + 7.73649 9.65407 16.5078 26.5197 11.4043 12.3728 9.65407 26.5197 26.5197 6.35236 + 16.5078 12.2712 17.0714 6.35236 7.10619 11.8886 26.5197 7.73649 6.35236 7.10619 + 11.8886 7.73649 7.73649 6.35236 16.5078 16.5078 12.3728 16.5078 16.5078 26.5197 + 17.0714 12.3728 16.5078 17.0714 17.0714 16.5078 11.8886 26.5197 17.0714 6.35236 + 11.8886 11.8886 6.35236 15.7082 16.5078 16.5078 12 12.3728 16.5078 17.0714 + 26.5197 17.0714 12.3728 16.5078 17.0714 17.0714 12.2712 11.0268 26.5197 26.5197 + 12.2712 11.0268 11.8886 26.5197 11.3048 6.35236 15.7082 12 12 15.7082 + 17.0714 26.5197 12 12.2712 17.0714 17.0714 12.2712 11.0268 17.0714 26.5197 + 11.3048 12.2712 11.0268 11.3048 11.3048 15.7082 16.5078 26.5197 12 12.3728 + 15.7082 26.5197 26.5197 12.3728 16.5078 17.0714 17.0714 12.2712 16.5078 11.8886 + 26.5197 11.3048 6.37469 11.0268 11.8886 11.3048 11.3048 6.37469 16.5078 16.5078 + 12.3728 16.5078 16.5078 26.5197 17.0714 12.3728 16.5078 17.0714 17.0714 16.5078 + 11.8886 28.5123 17.0714 11.8886 11.8886 6.37469 14.0596 16.5078 16.5078 15.9512 + 12.3728 14.0596 21.4164 28.5123 17.0714 12.8711 16.5078 21.4164 17.0714 12.8711 + 9.59794 28.5123 28.5123 6.37469 9.59794 11.8886 28.5123 7.93666 6.37469 14.0596 + 15.9512 15.9512 21.4164 12.6149 15.9512 21.4164 21.4164 12.8711 21.4164 7.93666 + 12.8711 9.59794 7.93666 7.93666 14.0596 12.6149 12.6149 15.9512 15.9512 14.0596 + 12.6149 12.6149 12.8711 21.4164 21.4164 12.6149 12.6149 9.59794 21.4164 28.5123 + 7.93666 12.8711 9.59794 9.59794 7.93666 7.93666 7.93666 + + + + + 0.555556 0.555556 0 0.666667 0.555556 0 0.777778 0.555556 0 + 1 0.555556 0 0.555556 0.666667 0 0.666667 0.666667 0 + 0.777778 0.666667 0 0.888889 0.666667 0 1 0.666667 0 + 0.555556 0.777778 0 0.777778 0.777778 0 0.888889 0.777778 0 + 0.555556 0.888889 0 0.666667 0.888889 0 0.777778 0.888889 0 + 0.888889 0.888889 0 1 0.888889 0 0.555556 1 0 + 0.666667 1 0 0.777778 1 0 1 1 0 + 0.555556 0.555556 0.111111 0.666667 0.555556 0.111111 0.777778 0.555556 0.111111 + 0.888889 0.555556 0.111111 1 0.555556 0.111111 0.555556 0.666667 0.111111 + 0.666667 0.666667 0.111111 0.888889 0.666667 0.111111 1 0.666667 0.111111 + 0.555556 0.777778 0.111111 0.666667 0.777778 0.111111 0.888889 0.777778 0.111111 + 1 0.777778 0.111111 0.555556 0.888889 0.111111 0.666667 0.888889 0.111111 + 0.777778 0.888889 0.111111 0.888889 0.888889 0.111111 1 0.888889 0.111111 + 0.555556 1 0.111111 0.666667 1 0.111111 0.777778 1 0.111111 + 0.888889 1 0.111111 1 1 0.111111 0.555556 0.555556 0.222222 + 0.777778 0.555556 0.222222 0.888889 0.555556 0.222222 0.555556 0.666667 0.222222 + 0.666667 0.666667 0.222222 0.777778 0.666667 0.222222 0.888889 0.666667 0.222222 + 1 0.666667 0.222222 0.666667 0.777778 0.222222 0.777778 0.777778 0.222222 + 1 0.777778 0.222222 0.555556 0.888889 0.222222 0.666667 0.888889 0.222222 + 0.777778 0.888889 0.222222 0.888889 0.888889 0.222222 1 0.888889 0.222222 + 0.555556 1 0.222222 0.777778 1 0.222222 0.888889 1 0.222222 + 0.555556 0.555556 0.333333 0.666667 0.555556 0.333333 0.777778 0.555556 0.333333 + 0.888889 0.555556 0.333333 1 0.555556 0.333333 0.555556 0.666667 0.333333 + 0.666667 0.666667 0.333333 0.777778 0.666667 0.333333 0.888889 0.666667 0.333333 + 1 0.666667 0.333333 0.555556 0.777778 0.333333 0.666667 0.777778 0.333333 + 0.888889 0.777778 0.333333 1 0.777778 0.333333 0.555556 0.888889 0.333333 + 0.666667 0.888889 0.333333 0.888889 0.888889 0.333333 1 0.888889 0.333333 + 0.555556 1 0.333333 0.666667 1 0.333333 0.777778 1 0.333333 + 0.888889 1 0.333333 1 1 0.333333 0.666667 0.555556 0.444444 + 0.777778 0.555556 0.444444 1 0.555556 0.444444 0.555556 0.666667 0.444444 + 0.666667 0.666667 0.444444 0.777778 0.666667 0.444444 0.888889 0.666667 0.444444 + 1 0.666667 0.444444 0.555556 0.777778 0.444444 0.777778 0.777778 0.444444 + 0.888889 0.777778 0.444444 0.555556 0.888889 0.444444 0.666667 0.888889 0.444444 + 0.777778 0.888889 0.444444 0.888889 0.888889 0.444444 1 0.888889 0.444444 + 0.666667 1 0.444444 0.777778 1 0.444444 1 1 0.444444 + 0.555556 0.555556 0.555556 0.666667 0.555556 0.555556 0.777778 0.555556 0.555556 + 0.888889 0.555556 0.555556 1 0.555556 0.555556 0.555556 0.666667 0.555556 + 0.666667 0.666667 0.555556 0.888889 0.666667 0.555556 1 0.666667 0.555556 + 0.555556 0.777778 0.555556 0.666667 0.777778 0.555556 0.888889 0.777778 0.555556 + 1 0.777778 0.555556 0.555556 0.888889 0.555556 0.666667 0.888889 0.555556 + 0.777778 0.888889 0.555556 0.888889 0.888889 0.555556 1 0.888889 0.555556 + 0.555556 1 0.555556 0.666667 1 0.555556 0.777778 1 0.555556 + 0.888889 1 0.555556 1 1 0.555556 0.555556 0.555556 0.666667 + 0.777778 0.555556 0.666667 0.888889 0.555556 0.666667 0.555556 0.666667 0.666667 + 0.666667 0.666667 0.666667 0.777778 0.666667 0.666667 0.888889 0.666667 0.666667 + 1 0.666667 0.666667 0.666667 0.777778 0.666667 0.777778 0.777778 0.666667 + 1 0.777778 0.666667 0.555556 0.888889 0.666667 0.666667 0.888889 0.666667 + 0.777778 0.888889 0.666667 0.888889 0.888889 0.666667 0.555556 1 0.666667 + 0.777778 1 0.666667 0.888889 1 0.666667 0.555556 0.555556 0.777778 + 0.666667 0.555556 0.777778 0.777778 0.555556 0.777778 0.888889 0.555556 0.777778 + 1 0.555556 0.777778 0.555556 0.666667 0.777778 0.666667 0.666667 0.777778 + 0.777778 0.666667 0.777778 0.888889 0.666667 0.777778 1 0.666667 0.777778 + 0.555556 0.777778 0.777778 0.666667 0.777778 0.777778 0.888889 0.777778 0.777778 + 1 0.777778 0.777778 0.555556 0.888889 0.777778 0.666667 0.888889 0.777778 + 0.888889 0.888889 0.777778 1 0.888889 0.777778 0.555556 1 0.777778 + 0.666667 1 0.777778 0.777778 1 0.777778 0.888889 1 0.777778 + 1 1 0.777778 0.666667 0.555556 0.888889 0.777778 0.555556 0.888889 + 1 0.555556 0.888889 0.666667 0.666667 0.888889 0.777778 0.666667 0.888889 + 0.888889 0.666667 0.888889 0.555556 0.777778 0.888889 0.777778 0.777778 0.888889 + 0.888889 0.777778 0.888889 0.666667 0.888889 0.888889 0.888889 0.888889 0.888889 + 1 0.888889 0.888889 0.666667 1 0.888889 0.777778 1 0.888889 + 1 1 0.888889 0.555556 0.555556 1 0.666667 0.555556 1 + 0.777778 0.555556 1 0.888889 0.555556 1 1 0.555556 1 + 0.555556 0.666667 1 0.666667 0.666667 1 0.888889 0.666667 1 + 1 0.666667 1 0.555556 0.777778 1 0.666667 0.777778 1 + 0.777778 0.777778 1 0.888889 0.777778 1 0.555556 0.888889 1 + 0.666667 0.888889 1 0.777778 0.888889 1 0.888889 0.888889 1 + 1 0.888889 1 0.555556 1 1 0.666667 1 1 + 0.777778 1 1 0.888889 1 1 1 1 1 + + + + + + 26 4 0 4 1 0 26 1 4 0 + 1 21 26 0 21 1 26 21 3 2 + 7 24 3 7 2 24 7 2 3 24 + 9 14 5 31 9 5 5 14 10 31 + 5 10 14 31 10 14 9 13 9 31 + 13 31 14 13 16 8 11 8 29 11 + 8 16 29 16 11 33 11 29 33 29 + 16 33 18 17 39 17 12 39 18 12 + 17 12 18 34 39 12 34 18 39 34 + 15 20 37 19 15 37 19 20 15 20 + 19 42 37 20 42 19 37 41 42 19 + 41 37 42 41 27 36 6 23 27 6 + 23 6 28 6 36 28 27 23 49 23 + 28 49 36 27 49 28 36 49 65 44 + 22 44 48 22 22 48 45 65 22 45 + 48 65 45 48 44 64 44 65 64 65 + 48 64 25 67 46 67 72 46 25 72 + 67 25 46 51 72 25 51 46 72 51 + 47 55 30 55 52 30 52 47 30 55 + 47 73 52 55 73 47 52 68 73 47 + 68 52 73 68 53 71 75 71 54 75 + 32 53 58 54 32 58 53 75 58 75 + 54 58 53 32 50 32 54 50 71 53 + 50 54 71 50 82 40 60 40 35 60 + 60 35 56 82 60 56 35 40 61 56 + 35 61 40 82 61 82 56 61 43 38 + 62 85 43 62 85 38 43 62 38 59 + 38 85 59 85 62 59 78 83 57 70 + 78 57 70 57 79 57 83 79 78 70 + 99 70 79 99 83 78 99 79 83 99 + 110 105 86 105 63 86 110 63 105 86 + 63 89 63 110 89 110 86 89 88 87 + 66 92 88 66 87 92 66 87 88 108 + 92 87 108 88 92 108 98 94 115 98 + 115 95 94 69 90 69 95 90 115 94 + 90 95 115 90 69 94 74 95 69 74 + 94 98 74 98 95 74 101 93 76 93 + 96 76 76 96 80 101 76 80 96 101 + 80 96 93 117 93 101 117 101 96 117 + 81 123 102 77 81 102 77 123 81 77 + 102 97 123 77 97 102 123 97 103 104 + 84 104 103 126 121 104 126 103 121 125 + 126 103 125 121 126 125 103 84 100 84 + 104 100 121 103 100 104 121 100 111 120 + 91 107 111 91 107 91 112 91 120 112 + 111 107 133 107 112 133 120 111 133 112 + 120 133 148 128 106 128 132 106 106 132 + 129 148 106 129 132 148 129 132 128 147 + 128 148 147 148 132 147 150 109 113 109 + 130 113 109 150 130 113 130 135 150 113 + 135 130 150 135 131 139 114 136 131 114 + 136 114 118 114 139 118 139 136 118 131 + 136 156 139 131 156 136 139 156 137 142 + 116 116 142 138 137 116 134 116 138 134 + 154 137 134 138 154 134 142 137 158 137 + 154 158 138 142 158 154 138 158 165 124 + 143 124 119 143 143 119 140 165 143 140 + 119 124 144 140 119 144 124 165 144 165 + 140 144 127 122 145 168 127 145 168 122 + 127 145 122 163 122 168 163 168 145 163 + 166 161 199 161 153 199 199 153 162 166 + 199 162 153 161 141 162 153 141 161 166 + 141 166 162 141 151 189 169 146 151 169 + 146 189 151 146 169 184 189 146 184 169 + 189 184 188 170 149 170 174 149 149 174 + 171 188 149 171 174 188 171 174 170 187 + 170 188 187 188 174 187 198 193 194 193 + 152 172 194 193 172 152 157 176 172 152 + 176 194 172 176 198 194 176 176 157 178 + 198 176 178 193 198 178 157 152 175 152 + 193 175 178 157 175 193 178 175 155 201 + 192 177 155 192 201 177 192 201 155 180 + 177 201 180 155 177 159 180 155 159 177 + 180 159 160 203 197 164 160 197 164 197 + 202 203 164 202 197 203 202 160 164 181 + 203 160 181 164 203 181 182 206 167 179 + 182 167 179 167 183 167 206 183 206 179 + 183 206 182 205 182 179 204 205 182 204 + 204 179 200 179 206 200 205 204 200 206 + 205 200 186 185 173 196 185 186 196 173 + 195 185 196 195 173 185 190 195 173 190 + 185 195 190 186 173 191 173 196 191 196 + 186 191 + + + 3 6 9 12 15 18 21 24 27 30 + 33 36 39 42 45 48 51 54 57 60 + 63 66 69 72 75 78 81 84 87 90 + 93 96 99 102 105 108 111 114 117 120 + 123 126 129 132 135 138 141 144 147 150 + 153 156 159 162 165 168 171 174 177 180 + 183 186 189 192 195 198 201 204 207 210 + 213 216 219 222 225 228 231 234 237 240 + 243 246 249 252 255 258 261 264 267 270 + 273 276 279 282 285 288 291 294 297 300 + 303 306 309 312 315 318 321 324 327 330 + 333 336 339 342 345 348 351 354 357 360 + 363 366 369 372 375 378 381 384 387 390 + 393 396 399 402 405 408 411 414 417 420 + 423 426 429 432 435 438 441 444 447 450 + 453 456 459 462 465 468 471 474 477 480 + 483 486 489 492 495 498 501 504 507 510 + 513 516 519 522 525 528 531 534 537 540 + 543 546 549 552 555 558 561 564 567 570 + 573 576 579 582 585 588 591 594 597 600 + 603 606 609 612 615 618 621 624 627 630 + 633 636 639 642 645 648 651 654 657 660 + 663 666 669 672 675 678 681 684 687 690 + 693 696 699 702 705 708 711 714 717 720 + 723 726 729 732 735 738 741 744 747 750 + 753 756 759 762 765 768 771 774 777 780 + 783 786 789 792 795 798 801 804 807 810 + 813 816 819 822 + + + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 + + + + + \ No newline at end of file diff --git a/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0.gold new file mode 100644 index 000000000000..23e239e5ea08 --- /dev/null +++ b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-AggregateQuality-Level0.gold @@ -0,0 +1,1120 @@ + + + + + + + 0 1 2 4 5 7 8 9 10 11 + 12 13 14 15 16 17 18 19 20 22 + 23 25 26 28 29 30 31 32 33 34 + 35 36 37 38 41 42 44 45 47 48 + 49 50 51 52 53 54 55 56 57 59 + 60 62 63 65 66 67 68 69 70 71 + 72 73 74 75 77 78 81 82 84 85 + 86 87 88 89 90 91 92 93 94 96 + 97 99 100 101 102 103 104 105 106 107 + 108 109 110 111 113 114 116 117 119 120 + 121 123 124 126 127 128 129 130 131 132 + 133 134 135 136 137 138 139 140 141 142 + 143 144 145 146 147 148 149 150 151 153 + 154 156 157 158 159 160 161 162 163 164 + 165 166 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 184 185 + 186 187 188 189 190 192 193 194 195 196 + 197 198 199 200 202 203 205 206 208 209 + 210 211 212 213 214 215 216 217 218 219 + 221 222 224 225 227 228 230 231 232 233 + 234 235 236 237 238 239 240 242 243 245 + 246 248 249 251 252 253 254 255 256 257 + 258 261 262 264 265 266 267 268 269 270 + 271 272 273 274 276 277 279 280 281 283 + 285 286 287 288 289 290 291 292 293 295 + 296 298 299 300 301 302 303 304 305 306 + 307 308 310 311 312 313 314 315 316 317 + 318 319 320 321 323 324 326 327 328 329 + 330 331 333 334 336 337 339 340 341 342 + 343 344 345 346 347 348 349 350 351 352 + 353 354 355 357 358 359 360 361 362 363 + 364 365 366 367 368 369 370 372 373 374 + 375 376 377 378 379 381 382 384 385 387 + 388 391 392 393 394 395 396 397 398 399 + 401 402 404 405 407 408 409 410 411 412 + 413 414 415 416 417 419 420 422 423 425 + 426 427 428 429 430 431 432 433 434 435 + 436 437 438 439 441 442 444 445 446 447 + 448 450 451 452 453 454 455 456 457 458 + 459 460 461 463 464 466 467 469 470 471 + 472 473 474 475 476 477 478 479 480 481 + 482 484 485 486 487 488 489 490 491 492 + 493 494 496 497 499 500 501 502 503 504 + 505 506 507 508 509 510 511 513 514 516 + 517 518 520 521 522 523 524 525 526 528 + 529 530 531 532 533 534 535 536 537 538 + 539 540 541 542 543 544 546 547 548 549 + 550 552 553 554 555 556 558 559 561 562 + 563 564 565 566 567 568 569 571 572 573 + 575 576 577 578 580 581 582 583 584 585 + 586 588 589 590 592 593 594 595 596 597 + 598 599 600 602 603 605 606 608 609 610 + 611 612 613 614 615 616 617 618 621 622 + 624 625 626 627 628 629 630 631 632 633 + 634 635 637 638 639 640 641 643 644 645 + 646 647 649 650 651 652 653 655 656 657 + 658 659 660 661 662 663 664 665 667 668 + 669 670 671 673 674 675 676 677 678 679 + 680 681 682 683 684 686 687 688 689 690 + 691 692 694 695 696 697 698 700 701 702 + 703 704 705 706 707 708 709 710 711 712 + 713 714 715 717 718 719 720 721 722 723 + 724 725 726 727 729 730 732 733 735 736 + 737 738 739 741 742 743 744 745 746 747 + 748 749 751 752 753 754 755 756 757 760 + 761 762 764 765 766 767 769 770 771 772 + 773 774 775 776 778 779 781 782 783 784 + 785 786 787 788 789 790 791 792 793 794 + 795 797 798 799 801 802 804 805 806 807 + 810 811 812 814 815 816 817 818 819 820 + 821 823 824 826 827 828 830 831 832 833 + 835 836 838 839 840 841 842 844 845 846 + 847 848 849 850 851 852 853 854 856 857 + 858 860 862 863 864 865 866 867 870 871 + 872 873 875 876 877 878 880 881 883 884 + 885 886 887 888 890 891 892 893 895 896 + 897 898 899 900 901 902 903 904 906 907 + 908 909 910 912 913 914 915 916 918 919 + 920 921 922 923 924 925 926 927 928 931 + 932 933 934 935 936 937 938 940 941 942 + 943 944 945 947 948 949 950 951 953 954 + 955 956 957 958 959 961 962 963 964 965 + 967 969 971 972 973 974 975 977 978 979 + 980 981 982 983 984 985 986 987 988 990 + 992 993 995 996 998 999 + + + 0 0 1 1 2 2 3 3 0 4 + 20 1 5 21 2 6 22 3 4 4 + 5 5 6 6 7 8 4 4 9 5 + 5 10 6 7 8 9 9 10 10 11 + 7 8 12 23 9 13 24 10 11 11 + 12 12 13 13 14 25 11 15 16 12 + 12 17 13 14 14 15 16 17 17 18 + 14 14 19 15 16 26 17 17 18 18 + 19 19 0 27 20 1 28 21 2 29 + 22 3 0 20 20 21 21 22 22 30 + 4 31 5 32 6 22 33 8 34 20 + 9 35 21 10 6 7 7 8 34 23 + 9 35 24 10 36 11 37 38 23 23 + 24 24 25 11 37 38 12 23 39 13 + 24 25 25 15 16 12 42 39 13 40 + 14 25 41 15 16 26 42 17 43 18 + 14 44 19 15 26 26 17 43 18 18 + 44 19 19 27 27 28 28 29 29 45 + 30 27 20 31 28 21 32 29 22 33 + 30 31 31 32 32 33 30 34 46 31 + 35 47 32 36 48 33 34 34 35 35 + 36 36 37 34 23 39 35 24 49 36 + 37 38 39 39 40 25 25 41 37 38 + 50 42 39 40 40 41 41 53 42 42 + 40 51 44 41 52 53 26 42 43 43 + 44 44 52 54 27 27 55 28 28 56 + 29 45 30 58 46 31 59 47 32 29 + 57 45 30 58 31 59 32 48 48 33 + 60 46 46 47 47 48 48 60 34 46 + 61 35 47 49 36 48 62 38 34 63 + 61 35 49 49 65 37 38 50 63 39 + 64 64 49 49 65 37 50 50 66 40 + 40 51 41 41 52 50 42 43 51 51 + 52 53 42 66 43 67 51 44 68 52 + 54 55 55 56 56 57 45 54 58 69 + 55 59 70 56 57 57 58 58 59 59 + 71 71 57 57 60 58 46 61 59 47 + 47 48 48 62 60 61 61 72 72 74 + 62 60 73 63 61 61 64 49 74 65 + 62 75 63 63 64 64 65 65 75 50 + 63 66 76 64 51 78 65 77 53 50 + 66 66 67 51 78 68 52 53 79 79 + 66 67 67 68 68 54 80 69 55 81 + 70 56 82 82 83 54 69 69 70 70 + 71 57 84 58 69 85 59 70 71 71 + 83 84 58 87 85 59 72 86 71 88 + 62 60 73 87 61 72 72 74 88 62 + 73 73 89 89 72 74 74 62 73 63 + 76 76 64 90 74 65 77 75 91 76 + 76 90 78 77 75 79 91 66 76 92 + 78 78 77 79 79 93 67 67 67 78 + 68 94 80 80 81 81 82 82 83 84 + 80 69 85 81 70 95 82 83 84 85 + 85 70 86 71 96 83 84 97 87 85 + 98 86 86 88 88 99 87 87 89 72 + 86 88 88 99 73 87 89 89 90 74 + 88 100 75 73 91 101 89 90 90 114 + 77 75 91 91 76 92 90 102 102 77 + 103 103 91 93 92 92 78 94 94 79 + 79 93 93 92 104 104 94 105 80 80 + 106 81 81 95 82 107 107 105 80 108 + 106 81 95 95 96 83 84 97 108 85 + 98 109 95 96 96 97 97 98 98 86 + 110 96 96 97 87 111 98 98 86 110 + 88 100 99 101 101 89 112 112 100 99 + 113 101 101 90 90 102 100 103 113 91 + 101 115 92 102 102 117 103 116 93 115 + 92 104 102 102 117 103 103 116 93 93 + 104 104 94 94 105 106 106 118 95 107 + 105 119 108 109 109 95 120 107 121 122 + 108 108 109 109 110 96 122 97 108 111 + 109 110 110 121 99 97 111 111 112 123 + 110 110 100 99 113 124 111 112 112 114 + 114 113 113 101 115 112 126 114 125 113 + 116 115 115 126 102 114 103 116 116 115 + 115 104 129 117 127 127 116 128 128 104 + 129 117 117 105 119 119 106 118 118 120 + 107 107 119 119 106 118 118 120 120 121 + 122 119 108 108 109 109 120 120 121 122 + 108 111 98 123 123 110 110 122 124 124 + 111 111 123 123 110 121 125 124 124 112 + 112 123 123 114 100 113 124 124 115 126 + 126 114 125 116 115 115 126 126 114 117 + 125 127 116 116 128 128 126 129 129 127 + 127 128 128 129 129 117 + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 + + + 4.71117 4.71117 6 6 6 6 4 4 4.71117 12.2679 + 26.5197 6 12.2712 26.5197 6 11.8886 12 4 12.2679 12.2679 + 12.2712 12.2712 11.8886 11.8886 8.08168 6.35236 12.2679 12.2679 11.8886 12.2712 + 12.2712 11.8886 11.8886 8.08168 6.35236 11.8886 11.8886 11.8886 11.8886 11.7696 + 8.08168 6.35236 11.3048 12 11.8886 11.8886 12 11.8886 11.7696 11.7696 + 11.3048 11.3048 11.8886 11.8886 11.377 17.0714 11.7696 6.37469 6.34127 11.3048 + 11.3048 7.93153 11.8886 11.377 11.377 6.37469 6.34127 7.93153 7.93153 7.81935 + 11.377 11.377 7.70682 6.37469 6.34127 11.5945 7.93153 7.93153 7.81935 7.81935 + 7.70682 7.70682 4.71117 12.2679 26.5197 6 12.2712 26.5197 6 11.8886 + 12 4 4.71117 26.5197 26.5197 26.5197 26.5197 12 12 12.2712 + 12.2679 17.0714 12.2712 17.0714 11.8886 12 11.6108 6.35236 20.4853 26.5197 + 11.8886 20.4853 26.5197 11.8886 11.8886 8.08168 8.08168 6.35236 20.4853 12 + 11.8886 20.4853 12 11.8886 12 11.7696 12.6149 12.6881 12 12 + 12 12 17.0714 11.7696 12.6149 12.6881 11.3048 12 17.0714 11.8886 + 12 17.0714 17.0714 6.37469 6.34127 11.3048 20.2353 17.0714 11.8886 17.0714 + 11.377 17.0714 17.0714 6.37469 6.34127 11.5945 20.2353 7.93153 10.3627 7.81935 + 11.377 11.8886 7.70682 6.37469 11.5945 11.5945 7.93153 10.3627 7.81935 7.81935 + 11.8886 7.70682 7.70682 12.2679 12.2679 12.2712 12.2712 11.8886 11.8886 6 + 12.2712 12.2679 26.5197 17.0714 12.2712 26.5197 17.0714 11.8886 12 11.6108 + 12.2712 17.0714 17.0714 17.0714 17.0714 11.6108 12.2712 20.4853 26.5197 17.0714 + 20.4853 28.2698 17.0714 12 16.5294 11.6108 20.4853 20.4853 20.4853 20.4853 + 12 12 12.6149 20.4853 12 17.0714 20.4853 12 17.0714 12 + 12.6149 12.6881 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 12.6149 12.6881 + 17.0714 20.2353 17.0714 17.0714 17.0714 17.0714 17.0714 6.37469 20.2353 20.2353 + 17.0714 17.0714 11.8886 17.0714 12.1555 6.37469 11.5945 20.2353 10.3627 10.3627 + 11.8886 11.8886 12.1555 6.35236 12.2679 12.2679 11.6108 12.2712 12.2712 11.6108 + 11.8886 6 12.2712 20.4853 26.5197 17.0714 20.4853 28.2698 17.0714 11.8886 + 14.5568 6 12.2712 20.4853 17.0714 20.4853 17.0714 16.5294 16.5294 11.6108 + 12.2712 26.5197 26.5197 28.2698 28.2698 16.5294 16.5294 12.2712 20.4853 26.5197 + 16.5294 20.4853 28.2698 17.0714 12 16.5294 12.6881 12.6881 20.4853 17.0714 + 16.5294 20.4853 17.0714 17.0714 17.0714 12.6149 12.6881 17.0714 17.0714 17.0714 + 17.0714 17.0714 17.0714 17.0714 17.0714 12.6149 17.0714 17.0714 16.3034 17.0714 + 17.0714 17.0714 17.0714 17.0714 12.1555 17.0714 20.2353 10.3627 17.0714 17.0714 + 12.1555 6.37469 20.2353 16.3034 10.3627 12.6881 17.0714 11.8886 11.6029 12.1555 + 6.35236 11.6108 11.6108 11.6108 11.6108 14.5568 6 6.35236 20.4853 12 + 11.6108 20.4853 17.0714 11.6108 14.5568 14.5568 20.4853 20.4853 20.4853 20.4853 + 17.0714 17.0714 14.5568 14.5568 12.2712 20.4853 26.5197 16.5294 20.4853 28.2698 + 28.2698 16.5294 16.5294 12.6881 12.2712 16.5294 16.5294 17.0714 17.0714 17.0714 + 12.6881 12.2712 17.0714 17.0714 16.5294 16.5294 17.0714 17.0714 17.0714 17.0714 + 12.6881 12.6881 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 12.6881 17.0714 + 17.0714 16.3034 17.0714 17.0714 17.0714 17.0714 17.0714 12.2712 6.37469 17.0714 + 16.3034 16.3034 12.6881 17.0714 17.0714 11.6029 12.1555 6.37469 12.5778 12.5778 + 16.3034 12.6881 12.6881 11.6029 11.6029 6.35236 11.3048 12 11.6108 11.377 + 17.0714 11.6108 12.2712 12.2712 12.6294 6.35236 12 12 17.0714 17.0714 + 17.0714 14.5568 12.2712 20.4853 12 17.0714 20.4853 17.0714 17.0714 17.0714 + 12.6294 12.2712 20.4853 17.0714 17.0714 20.4853 17.0714 17.0714 17.0714 16.3034 + 12.6881 12.2712 17.0714 17.0714 16.5294 17.0714 17.0714 17.0714 16.3034 12.6881 + 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 12.6881 17.0714 17.0714 + 17.0714 17.0714 17.0714 20.4853 17.0714 17.0714 12.2712 12.6881 17.0714 17.0714 + 17.0714 20.4853 17.0714 12.2712 12.6881 12.5778 17.0714 16.3034 17.0714 17.0714 + 17.0714 17.0714 12.2712 12.5778 12.5778 11.377 12.6881 12.6881 12.6881 17.0714 + 11.6029 7.81935 11.3048 11.3048 11.377 11.377 12.2712 12.2712 12.6294 12.2712 + 11.3048 12 17.0714 11.377 17.0714 16.7407 12.2712 12.6294 12.2712 17.0714 + 17.0714 17.0714 17.0714 17.0714 16.7407 12.6294 12.2712 17.0714 17.0714 17.0714 + 28.2698 17.0714 17.0714 16.3034 16.3034 12.6881 17.0714 17.0714 17.0714 17.0714 + 17.0714 16.3034 16.3034 12.6881 17.0714 17.0714 17.0714 17.0714 20.4853 17.0714 + 16.3034 27.9796 12.6881 17.0714 17.0714 17.0714 17.0714 20.4853 20.4853 30.2733 + 12.2712 12.6881 17.0714 17.0714 17.0714 17.0714 20.4853 16.5294 16.5294 12.2712 + 9.53799 9.53799 17.0714 11.377 17.0714 17.0714 17.0714 7.81935 7.81935 12.5778 + 12.5778 11.377 11.377 17.0714 13.2172 13.2172 7.81935 6.34127 11.3048 11.3048 + 9.53799 11.377 11.377 16.7407 12.2712 12.5415 12.5415 6.34127 11.3048 21.4164 + 9.53799 11.377 16.7407 16.7407 16.7407 12.6294 12.2712 17.0714 21.4164 17.0714 + 28.2698 16.3034 16.7407 16.7407 16.7407 17.0714 17.0714 28.2698 28.2698 17.0714 + 17.686 16.7407 16.7407 17.0714 17.0714 16.423 28.2698 28.2698 17.0714 17.686 + 16.3034 27.9796 12.6881 17.0714 17.0714 17.0714 20.2353 20.2353 27.9796 12.6881 + 17.0714 17.0714 17.0714 20.4853 20.4853 16.5294 27.9796 9.53799 17.0714 17.0714 + 17.0714 23.0102 17.0714 16.5294 16.5294 8.71109 9.53799 13.2233 11.377 23.0102 + 17.0714 13.2172 16.5294 16.5294 8.71109 9.53799 9.53799 13.2233 11.377 11.377 + 13.2172 13.2172 7.81935 7.81935 6.34127 9.53799 9.53799 6.35236 16.7407 12.5415 + 6.34127 12.1544 21.4164 16.3034 16.3034 16.7407 12.2679 12.5415 6.38316 6.35236 + 21.4164 21.4164 16.3034 16.3034 17.686 16.7407 6.35236 17.0714 21.4164 16.423 + 16.3034 17.686 17.686 6.38316 12.6881 17.0714 16.423 16.423 20.2353 12.6149 + 17.686 17.686 27.9796 12.6881 17.0714 12.6149 16.423 20.2353 20.2353 30.2733 + 30.2733 17.0714 17.0714 17.0714 23.0102 20.2353 11.3242 30.2733 6 17.0714 + 13.2233 23.0102 23.0102 11.3242 16.5294 30.2733 9.53799 13.2233 13.2233 23.0102 + 23.0102 13.2172 7.81935 8.71109 5.92419 5.92419 13.2233 6.37429 6.37429 13.2172 + 7.81935 8.71109 8.71109 6.34127 12.1544 12.1544 9.53799 6.35236 6.35236 12.2679 + 12.5415 12.5415 12.1544 12.1544 9.53799 6.35236 6.35236 12.2679 12.2679 6.38316 + 6.35236 12.1544 21.4164 21.4164 16.3034 16.3034 12.2679 12.2679 6.38316 6.35236 + 21.4164 16.423 28.2698 12.6149 12.6149 17.686 17.686 6.35236 12.6149 12.6149 + 16.423 16.423 12.6149 12.6149 17.686 6.38316 6 12.6149 12.6149 20.2353 + 20.2353 12.6149 12.6149 30.2733 27.9796 17.0714 12.6149 12.6149 23.0102 11.3242 + 11.3242 30.2733 6 13.2233 23.0102 23.0102 11.3242 11.3242 30.2733 8.71109 + 6 5.92419 13.2233 13.2233 6.37429 6.37429 11.3242 7.81935 7.81935 5.92419 + 5.92419 6.37429 6.37429 7.81935 7.81935 8.71109 + + + + + 0 0 0 0.111111 0 0 0.222222 0 0 + 0.444444 0 0 0.555556 0 0 0.777778 0 0 + 0.888889 0 0 1 0 0 0 0.111111 0 + 0.111111 0.111111 0 0.222222 0.111111 0 0.333333 0.111111 0 + 0.444444 0.111111 0 0.555556 0.111111 0 0.666667 0.111111 0 + 0.777778 0.111111 0 0.888889 0.111111 0 1 0.111111 0 + 0 0.222222 0 0.222222 0.222222 0 0.333333 0.222222 0 + 0.555556 0.222222 0 0.666667 0.222222 0 0.888889 0.222222 0 + 1 0.222222 0 0 0.333333 0 0.111111 0.333333 0 + 0.222222 0.333333 0 0.333333 0.333333 0 0.444444 0.333333 0 + 0.555556 0.333333 0 0.666667 0.333333 0 0.777778 0.333333 0 + 0.888889 0.333333 0 0.111111 0.444444 0 0.222222 0.444444 0 + 0.444444 0.444444 0 0.555556 0.444444 0 0.777778 0.444444 0 + 0.888889 0.444444 0 1 0.444444 0 0 0.555556 0 + 0.111111 0.555556 0 0.222222 0.555556 0 0.333333 0.555556 0 + 0.444444 0.555556 0 0.555556 0.555556 0 0.666667 0.555556 0 + 0.777778 0.555556 0 1 0.555556 0 0 0.666667 0 + 0.222222 0.666667 0 0.333333 0.666667 0 0.555556 0.666667 0 + 0.666667 0.666667 0 0.777778 0.666667 0 0.888889 0.666667 0 + 1 0.666667 0 0 0.777778 0 0.111111 0.777778 0 + 0.222222 0.777778 0 0.333333 0.777778 0 0.444444 0.777778 0 + 0.555556 0.777778 0 0.777778 0.777778 0 0.888889 0.777778 0 + 0.111111 0.888889 0 0.222222 0.888889 0 0.444444 0.888889 0 + 0.555556 0.888889 0 0.666667 0.888889 0 0.777778 0.888889 0 + 0.888889 0.888889 0 1 0.888889 0 0 1 0 + 0.111111 1 0 0.222222 1 0 0.333333 1 0 + 0.444444 1 0 0.666667 1 0 0.777778 1 0 + 1 1 0 0 0 0.111111 0.111111 0 0.111111 + 0.222222 0 0.111111 0.333333 0 0.111111 0.444444 0 0.111111 + 0.555556 0 0.111111 0.666667 0 0.111111 0.777778 0 0.111111 + 0.888889 0 0.111111 1 0 0.111111 0 0.111111 0.111111 + 0.111111 0.111111 0.111111 0.333333 0.111111 0.111111 0.444444 0.111111 0.111111 + 0.666667 0.111111 0.111111 0.777778 0.111111 0.111111 1 0.111111 0.111111 + 0 0.222222 0.111111 0.111111 0.222222 0.111111 0.333333 0.222222 0.111111 + 0.444444 0.222222 0.111111 0.666667 0.222222 0.111111 0.777778 0.222222 0.111111 + 0.888889 0.222222 0.111111 1 0.222222 0.111111 0 0.333333 0.111111 + 0.111111 0.333333 0.111111 0.222222 0.333333 0.111111 0.333333 0.333333 0.111111 + 0.444444 0.333333 0.111111 0.555556 0.333333 0.111111 0.666667 0.333333 0.111111 + 0.777778 0.333333 0.111111 0.888889 0.333333 0.111111 1 0.333333 0.111111 + 0 0.444444 0.111111 0.111111 0.444444 0.111111 0.222222 0.444444 0.111111 + 0.333333 0.444444 0.111111 0.444444 0.444444 0.111111 0.555556 0.444444 0.111111 + 0.666667 0.444444 0.111111 0.777778 0.444444 0.111111 0.888889 0.444444 0.111111 + 1 0.444444 0.111111 0 0.555556 0.111111 0.111111 0.555556 0.111111 + 0.333333 0.555556 0.111111 0.444444 0.555556 0.111111 0.666667 0.555556 0.111111 + 0.777778 0.555556 0.111111 0.888889 0.555556 0.111111 1 0.555556 0.111111 + 0 0.666667 0.111111 0.111111 0.666667 0.111111 0.222222 0.666667 0.111111 + 0.333333 0.666667 0.111111 0.444444 0.666667 0.111111 0.555556 0.666667 0.111111 + 0.666667 0.666667 0.111111 0.888889 0.666667 0.111111 1 0.666667 0.111111 + 0 0.777778 0.111111 0.111111 0.777778 0.111111 0.222222 0.777778 0.111111 + 0.333333 0.777778 0.111111 0.444444 0.777778 0.111111 0.555556 0.777778 0.111111 + 0.666667 0.777778 0.111111 0.777778 0.777778 0.111111 0.888889 0.777778 0.111111 + 1 0.777778 0.111111 0 0.888889 0.111111 0.111111 0.888889 0.111111 + 0.222222 0.888889 0.111111 0.333333 0.888889 0.111111 0.444444 0.888889 0.111111 + 0.555556 0.888889 0.111111 0.666667 0.888889 0.111111 0.777778 0.888889 0.111111 + 0.888889 0.888889 0.111111 1 0.888889 0.111111 0 1 0.111111 + 0.222222 1 0.111111 0.333333 1 0.111111 0.444444 1 0.111111 + 0.555556 1 0.111111 0.666667 1 0.111111 0.777778 1 0.111111 + 0.888889 1 0.111111 1 1 0.111111 0 0 0.222222 + 0.222222 0 0.222222 0.333333 0 0.222222 0.555556 0 0.222222 + 0.666667 0 0.222222 0.888889 0 0.222222 1 0 0.222222 + 0 0.111111 0.222222 0.111111 0.111111 0.222222 0.222222 0.111111 0.222222 + 0.333333 0.111111 0.222222 0.444444 0.111111 0.222222 0.555556 0.111111 0.222222 + 0.666667 0.111111 0.222222 0.777778 0.111111 0.222222 0.888889 0.111111 0.222222 + 1 0.111111 0.222222 0.111111 0.222222 0.222222 0.222222 0.222222 0.222222 + 0.444444 0.222222 0.222222 0.555556 0.222222 0.222222 0.777778 0.222222 0.222222 + 0.888889 0.222222 0.222222 0 0.333333 0.222222 0.111111 0.333333 0.222222 + 0.222222 0.333333 0.222222 0.333333 0.333333 0.222222 0.444444 0.333333 0.222222 + 0.555556 0.333333 0.222222 0.666667 0.333333 0.222222 0.777778 0.333333 0.222222 + 0.888889 0.333333 0.222222 1 0.333333 0.222222 0 0.444444 0.222222 + 0.222222 0.444444 0.222222 0.333333 0.444444 0.222222 0.555556 0.444444 0.222222 + 0.666667 0.444444 0.222222 0.888889 0.444444 0.222222 1 0.444444 0.222222 + 0.111111 0.555556 0.222222 0.222222 0.555556 0.222222 0.333333 0.555556 0.222222 + 0.444444 0.555556 0.222222 0.555556 0.555556 0.222222 0.666667 0.555556 0.222222 + 0.777778 0.555556 0.222222 0.888889 0.555556 0.222222 0.111111 0.666667 0.222222 + 0.222222 0.666667 0.222222 0.444444 0.666667 0.222222 0.555556 0.666667 0.222222 + 0.666667 0.666667 0.222222 0.777778 0.666667 0.222222 0.888889 0.666667 0.222222 + 1 0.666667 0.222222 0 0.777778 0.222222 0.111111 0.777778 0.222222 + 0.222222 0.777778 0.222222 0.333333 0.777778 0.222222 0.444444 0.777778 0.222222 + 0.666667 0.777778 0.222222 0.777778 0.777778 0.222222 1 0.777778 0.222222 + 0 0.888889 0.222222 0.111111 0.888889 0.222222 0.333333 0.888889 0.222222 + 0.555556 0.888889 0.222222 0.666667 0.888889 0.222222 0.777778 0.888889 0.222222 + 0.888889 0.888889 0.222222 1 0.888889 0.222222 0 1 0.222222 + 0.111111 1 0.222222 0.222222 1 0.222222 0.333333 1 0.222222 + 0.555556 1 0.222222 0.666667 1 0.222222 0.888889 1 0.222222 + 1 1 0.222222 0 0 0.333333 0.111111 0 0.333333 + 0.222222 0 0.333333 0.333333 0 0.333333 0.444444 0 0.333333 + 0.555556 0 0.333333 0.666667 0 0.333333 0.777778 0 0.333333 + 0.888889 0 0.333333 0 0.111111 0.333333 0.111111 0.111111 0.333333 + 0.222222 0.111111 0.333333 0.333333 0.111111 0.333333 0.444444 0.111111 0.333333 + 0.555556 0.111111 0.333333 0.666667 0.111111 0.333333 0.777778 0.111111 0.333333 + 0.888889 0.111111 0.333333 1 0.111111 0.333333 0 0.222222 0.333333 + 0.111111 0.222222 0.333333 0.333333 0.222222 0.333333 0.444444 0.222222 0.333333 + 0.666667 0.222222 0.333333 0.777778 0.222222 0.333333 0.888889 0.222222 0.333333 + 1 0.222222 0.333333 0 0.333333 0.333333 0.111111 0.333333 0.333333 + 0.333333 0.333333 0.333333 0.444444 0.333333 0.333333 0.666667 0.333333 0.333333 + 0.777778 0.333333 0.333333 1 0.333333 0.333333 0 0.444444 0.333333 + 0.111111 0.444444 0.333333 0.222222 0.444444 0.333333 0.333333 0.444444 0.333333 + 0.444444 0.444444 0.333333 0.555556 0.444444 0.333333 0.666667 0.444444 0.333333 + 0.777778 0.444444 0.333333 0.888889 0.444444 0.333333 1 0.444444 0.333333 + 0 0.555556 0.333333 0.111111 0.555556 0.333333 0.222222 0.555556 0.333333 + 0.333333 0.555556 0.333333 0.444444 0.555556 0.333333 0.555556 0.555556 0.333333 + 0.777778 0.555556 0.333333 0.888889 0.555556 0.333333 1 0.555556 0.333333 + 0 0.666667 0.333333 0.111111 0.666667 0.333333 0.222222 0.666667 0.333333 + 0.333333 0.666667 0.333333 0.444444 0.666667 0.333333 0.555556 0.666667 0.333333 + 0.666667 0.666667 0.333333 0.777778 0.666667 0.333333 0.888889 0.666667 0.333333 + 1 0.666667 0.333333 0 0.777778 0.333333 0.222222 0.777778 0.333333 + 0.333333 0.777778 0.333333 0.444444 0.777778 0.333333 0.555556 0.777778 0.333333 + 0.666667 0.777778 0.333333 0.777778 0.777778 0.333333 0.888889 0.777778 0.333333 + 1 0.777778 0.333333 0.111111 0.888889 0.333333 0.222222 0.888889 0.333333 + 0.444444 0.888889 0.333333 0.555556 0.888889 0.333333 0.777778 0.888889 0.333333 + 0.888889 0.888889 0.333333 0.111111 1 0.333333 0.222222 1 0.333333 + 0.333333 1 0.333333 0.444444 1 0.333333 0.555556 1 0.333333 + 0.666667 1 0.333333 0.777778 1 0.333333 0.888889 1 0.333333 + 1 1 0.333333 0.111111 0 0.444444 0.222222 0 0.444444 + 0.444444 0 0.444444 0.555556 0 0.444444 0.777778 0 0.444444 + 0.888889 0 0.444444 1 0 0.444444 0 0.111111 0.444444 + 0.111111 0.111111 0.444444 0.222222 0.111111 0.444444 0.333333 0.111111 0.444444 + 0.444444 0.111111 0.444444 0.555556 0.111111 0.444444 0.666667 0.111111 0.444444 + 0.777778 0.111111 0.444444 1 0.111111 0.444444 0 0.222222 0.444444 + 0.222222 0.222222 0.444444 0.333333 0.222222 0.444444 0.555556 0.222222 0.444444 + 0.666667 0.222222 0.444444 0.777778 0.222222 0.444444 0.888889 0.222222 0.444444 + 1 0.222222 0.444444 0 0.333333 0.444444 0.111111 0.333333 0.444444 + 0.222222 0.333333 0.444444 0.333333 0.333333 0.444444 0.444444 0.333333 0.444444 + 0.555556 0.333333 0.444444 0.666667 0.333333 0.444444 0.777778 0.333333 0.444444 + 0.888889 0.333333 0.444444 1 0.333333 0.444444 0.111111 0.444444 0.444444 + 0.222222 0.444444 0.444444 0.444444 0.444444 0.444444 0.555556 0.444444 0.444444 + 0.666667 0.444444 0.444444 0.777778 0.444444 0.444444 0.888889 0.444444 0.444444 + 0 0.555556 0.444444 0.111111 0.555556 0.444444 0.222222 0.555556 0.444444 + 0.333333 0.555556 0.444444 0.444444 0.555556 0.444444 0.555556 0.555556 0.444444 + 0.666667 0.555556 0.444444 0.777778 0.555556 0.444444 0.888889 0.555556 0.444444 + 1 0.555556 0.444444 0 0.666667 0.444444 0.111111 0.666667 0.444444 + 0.333333 0.666667 0.444444 0.444444 0.666667 0.444444 0.666667 0.666667 0.444444 + 0.777778 0.666667 0.444444 1 0.666667 0.444444 0 0.777778 0.444444 + 0.111111 0.777778 0.444444 0.222222 0.777778 0.444444 0.333333 0.777778 0.444444 + 0.444444 0.777778 0.444444 0.555556 0.777778 0.444444 0.666667 0.777778 0.444444 + 0.777778 0.777778 0.444444 0.888889 0.777778 0.444444 1 0.777778 0.444444 + 0 0.888889 0.444444 0.111111 0.888889 0.444444 0.222222 0.888889 0.444444 + 0.444444 0.888889 0.444444 0.555556 0.888889 0.444444 0.666667 0.888889 0.444444 + 0.777778 0.888889 0.444444 0.888889 0.888889 0.444444 1 0.888889 0.444444 + 0 1 0.444444 0.111111 1 0.444444 0.222222 1 0.444444 + 0.333333 1 0.444444 0.444444 1 0.444444 0.666667 1 0.444444 + 0.777778 1 0.444444 1 1 0.444444 0 0 0.555556 + 0.111111 0 0.555556 0.222222 0 0.555556 0.333333 0 0.555556 + 0.444444 0 0.555556 0.555556 0 0.555556 0.666667 0 0.555556 + 0.777778 0 0.555556 0.888889 0 0.555556 1 0 0.555556 + 0 0.111111 0.555556 0.111111 0.111111 0.555556 0.333333 0.111111 0.555556 + 0.444444 0.111111 0.555556 0.666667 0.111111 0.555556 0.777778 0.111111 0.555556 + 0.888889 0.111111 0.555556 0 0.222222 0.555556 0.111111 0.222222 0.555556 + 0.222222 0.222222 0.555556 0.333333 0.222222 0.555556 0.444444 0.222222 0.555556 + 0.555556 0.222222 0.555556 0.666667 0.222222 0.555556 0.888889 0.222222 0.555556 + 1 0.222222 0.555556 0 0.333333 0.555556 0.111111 0.333333 0.555556 + 0.222222 0.333333 0.555556 0.333333 0.333333 0.555556 0.444444 0.333333 0.555556 + 0.555556 0.333333 0.555556 0.666667 0.333333 0.555556 0.777778 0.333333 0.555556 + 0.888889 0.333333 0.555556 1 0.333333 0.555556 0 0.444444 0.555556 + 0.111111 0.444444 0.555556 0.222222 0.444444 0.555556 0.333333 0.444444 0.555556 + 0.444444 0.444444 0.555556 0.666667 0.444444 0.555556 0.777778 0.444444 0.555556 + 0.888889 0.444444 0.555556 1 0.444444 0.555556 0 0.555556 0.555556 + 0.222222 0.555556 0.555556 0.333333 0.555556 0.555556 0.444444 0.555556 0.555556 + 0.555556 0.555556 0.555556 0.666667 0.555556 0.555556 0.888889 0.555556 0.555556 + 1 0.555556 0.555556 0.111111 0.666667 0.555556 0.222222 0.666667 0.555556 + 0.333333 0.666667 0.555556 0.444444 0.666667 0.555556 0.555556 0.666667 0.555556 + 0.666667 0.666667 0.555556 0.777778 0.666667 0.555556 0.888889 0.666667 0.555556 + 1 0.666667 0.555556 0.111111 0.777778 0.555556 0.222222 0.777778 0.555556 + 0.333333 0.777778 0.555556 0.555556 0.777778 0.555556 0.666667 0.777778 0.555556 + 0.777778 0.777778 0.555556 0.888889 0.777778 0.555556 0 0.888889 0.555556 + 0.111111 0.888889 0.555556 0.222222 0.888889 0.555556 0.333333 0.888889 0.555556 + 0.444444 0.888889 0.555556 0.555556 0.888889 0.555556 0.666667 0.888889 0.555556 + 0.888889 0.888889 0.555556 1 0.888889 0.555556 0 1 0.555556 + 0.222222 1 0.555556 0.333333 1 0.555556 0.444444 1 0.555556 + 0.555556 1 0.555556 0.666667 1 0.555556 0.777778 1 0.555556 + 0.888889 1 0.555556 1 1 0.555556 0 0 0.666667 + 0.222222 0 0.666667 0.333333 0 0.666667 0.555556 0 0.666667 + 0.666667 0 0.666667 0.888889 0 0.666667 1 0 0.666667 + 0 0.111111 0.666667 0.111111 0.111111 0.666667 0.222222 0.111111 0.666667 + 0.333333 0.111111 0.666667 0.444444 0.111111 0.666667 0.555556 0.111111 0.666667 + 0.666667 0.111111 0.666667 0.777778 0.111111 0.666667 0.888889 0.111111 0.666667 + 0.111111 0.222222 0.666667 0.222222 0.222222 0.666667 0.444444 0.222222 0.666667 + 0.555556 0.222222 0.666667 0.666667 0.222222 0.666667 0.777778 0.222222 0.666667 + 0.888889 0.222222 0.666667 1 0.222222 0.666667 0 0.333333 0.666667 + 0.111111 0.333333 0.666667 0.222222 0.333333 0.666667 0.333333 0.333333 0.666667 + 0.444444 0.333333 0.666667 0.555556 0.333333 0.666667 0.777778 0.333333 0.666667 + 0.888889 0.333333 0.666667 1 0.333333 0.666667 0 0.444444 0.666667 + 0.111111 0.444444 0.666667 0.333333 0.444444 0.666667 0.444444 0.444444 0.666667 + 0.555556 0.444444 0.666667 0.666667 0.444444 0.666667 0.777778 0.444444 0.666667 + 1 0.444444 0.666667 0 0.555556 0.666667 0.111111 0.555556 0.666667 + 0.222222 0.555556 0.666667 0.333333 0.555556 0.666667 0.555556 0.555556 0.666667 + 0.666667 0.555556 0.666667 0.777778 0.555556 0.666667 0.888889 0.555556 0.666667 + 1 0.555556 0.666667 0 0.666667 0.666667 0.111111 0.666667 0.666667 + 0.222222 0.666667 0.666667 0.333333 0.666667 0.666667 0.444444 0.666667 0.666667 + 0.555556 0.666667 0.666667 0.777778 0.666667 0.666667 0.888889 0.666667 0.666667 + 1 0.666667 0.666667 0 0.777778 0.666667 0.111111 0.777778 0.666667 + 0.333333 0.777778 0.666667 0.444444 0.777778 0.666667 0.555556 0.777778 0.666667 + 0.666667 0.777778 0.666667 0.777778 0.777778 0.666667 0.888889 0.777778 0.666667 + 1 0.777778 0.666667 0 0.888889 0.666667 0.111111 0.888889 0.666667 + 0.222222 0.888889 0.666667 0.333333 0.888889 0.666667 0.444444 0.888889 0.666667 + 0.666667 0.888889 0.666667 0.777778 0.888889 0.666667 0.888889 0.888889 0.666667 + 1 0.888889 0.666667 0 1 0.666667 0.111111 1 0.666667 + 0.222222 1 0.666667 0.444444 1 0.666667 0.555556 1 0.666667 + 0.666667 1 0.666667 0.777778 1 0.666667 0.888889 1 0.666667 + 0 0 0.777778 0.111111 0 0.777778 0.222222 0 0.777778 + 0.333333 0 0.777778 0.444444 0 0.777778 0.555556 0 0.777778 + 0.666667 0 0.777778 0.777778 0 0.777778 0.888889 0 0.777778 + 1 0 0.777778 0 0.111111 0.777778 0.111111 0.111111 0.777778 + 0.222222 0.111111 0.777778 0.333333 0.111111 0.777778 0.444444 0.111111 0.777778 + 0.555556 0.111111 0.777778 0.777778 0.111111 0.777778 0.888889 0.111111 0.777778 + 1 0.111111 0.777778 0 0.222222 0.777778 0.111111 0.222222 0.777778 + 0.222222 0.222222 0.777778 0.333333 0.222222 0.777778 0.444444 0.222222 0.777778 + 0.555556 0.222222 0.777778 0.666667 0.222222 0.777778 0.777778 0.222222 0.777778 + 1 0.222222 0.777778 0 0.333333 0.777778 0.222222 0.333333 0.777778 + 0.333333 0.333333 0.777778 0.555556 0.333333 0.777778 0.666667 0.333333 0.777778 + 0.777778 0.333333 0.777778 0.888889 0.333333 0.777778 1 0.333333 0.777778 + 0.111111 0.444444 0.777778 0.222222 0.444444 0.777778 0.333333 0.444444 0.777778 + 0.444444 0.444444 0.777778 0.555556 0.444444 0.777778 0.666667 0.444444 0.777778 + 0.777778 0.444444 0.777778 0.888889 0.444444 0.777778 1 0.444444 0.777778 + 0.111111 0.555556 0.777778 0.222222 0.555556 0.777778 0.333333 0.555556 0.777778 + 0.444444 0.555556 0.777778 0.555556 0.555556 0.777778 0.666667 0.555556 0.777778 + 0.777778 0.555556 0.777778 0 0.666667 0.777778 0.111111 0.666667 0.777778 + 0.222222 0.666667 0.777778 0.444444 0.666667 0.777778 0.555556 0.666667 0.777778 + 0.666667 0.666667 0.777778 0.777778 0.666667 0.777778 1 0.666667 0.777778 + 0 0.777778 0.777778 0.111111 0.777778 0.777778 0.222222 0.777778 0.777778 + 0.333333 0.777778 0.777778 0.444444 0.777778 0.777778 0.555556 0.777778 0.777778 + 0.666667 0.777778 0.777778 0.888889 0.777778 0.777778 1 0.777778 0.777778 + 0.111111 0.888889 0.777778 0.222222 0.888889 0.777778 0.333333 0.888889 0.777778 + 0.444444 0.888889 0.777778 0.555556 0.888889 0.777778 0.666667 0.888889 0.777778 + 0.777778 0.888889 0.777778 0.888889 0.888889 0.777778 1 0.888889 0.777778 + 0 1 0.777778 0.111111 1 0.777778 0.222222 1 0.777778 + 0.333333 1 0.777778 0.444444 1 0.777778 0.555556 1 0.777778 + 0.777778 1 0.777778 0.888889 1 0.777778 1 1 0.777778 + 0.111111 0 0.888889 0.222222 0 0.888889 0.444444 0 0.888889 + 0.555556 0 0.888889 0.666667 0 0.888889 0.777778 0 0.888889 + 0 0.111111 0.888889 0.111111 0.111111 0.888889 0.222222 0.111111 0.888889 + 0.444444 0.111111 0.888889 0.555556 0.111111 0.888889 0.666667 0.111111 0.888889 + 0.777778 0.111111 0.888889 0.888889 0.111111 0.888889 1 0.111111 0.888889 + 0 0.222222 0.888889 0.111111 0.222222 0.888889 0.333333 0.222222 0.888889 + 0.444444 0.222222 0.888889 0.666667 0.222222 0.888889 0.777778 0.222222 0.888889 + 0.888889 0.222222 0.888889 0 0.333333 0.888889 0.111111 0.333333 0.888889 + 0.222222 0.333333 0.888889 0.333333 0.333333 0.888889 0.555556 0.333333 0.888889 + 0.666667 0.333333 0.888889 0.888889 0.333333 0.888889 1 0.333333 0.888889 + 0 0.444444 0.888889 0.111111 0.444444 0.888889 0.222222 0.444444 0.888889 + 0.444444 0.444444 0.888889 0.555556 0.444444 0.888889 0.666667 0.444444 0.888889 + 0.777778 0.444444 0.888889 0.888889 0.444444 0.888889 1 0.444444 0.888889 + 0 0.555556 0.888889 0.111111 0.555556 0.888889 0.222222 0.555556 0.888889 + 0.333333 0.555556 0.888889 0.444444 0.555556 0.888889 0.666667 0.555556 0.888889 + 0.777778 0.555556 0.888889 0.888889 0.555556 0.888889 0 0.666667 0.888889 + 0.222222 0.666667 0.888889 0.333333 0.666667 0.888889 0.444444 0.666667 0.888889 + 0.555556 0.666667 0.888889 0.666667 0.666667 0.888889 0.777778 0.666667 0.888889 + 0 0.777778 0.888889 0.111111 0.777778 0.888889 0.222222 0.777778 0.888889 + 0.333333 0.777778 0.888889 0.555556 0.777778 0.888889 0.666667 0.777778 0.888889 + 0.777778 0.777778 0.888889 0.888889 0.777778 0.888889 0 0.888889 0.888889 + 0.111111 0.888889 0.888889 0.333333 0.888889 0.888889 0.444444 0.888889 0.888889 + 0.555556 0.888889 0.888889 0.666667 0.888889 0.888889 0.777778 0.888889 0.888889 + 0.888889 0.888889 0.888889 0 1 0.888889 0.111111 1 0.888889 + 0.222222 1 0.888889 0.333333 1 0.888889 0.555556 1 0.888889 + 0.666667 1 0.888889 0.777778 1 0.888889 0.888889 1 0.888889 + 1 1 0.888889 0 0 1 0.111111 0 1 + 0.222222 0 1 0.333333 0 1 0.444444 0 1 + 0.666667 0 1 0.777778 0 1 0.888889 0 1 + 1 0 1 0 0.111111 1 0.222222 0.111111 1 + 0.333333 0.111111 1 0.444444 0.111111 1 0.555556 0.111111 1 + 0.666667 0.111111 1 0.888889 0.111111 1 1 0.111111 1 + 0 0.222222 1 0.111111 0.222222 1 0.222222 0.222222 1 + 0.333333 0.222222 1 0.444444 0.222222 1 0.555556 0.222222 1 + 0.666667 0.222222 1 0.777778 0.222222 1 0.888889 0.222222 1 + 0.111111 0.333333 1 0.222222 0.333333 1 0.333333 0.333333 1 + 0.444444 0.333333 1 0.555556 0.333333 1 0.666667 0.333333 1 + 0.777778 0.333333 1 0.888889 0.333333 1 0 0.444444 1 + 0.111111 0.444444 1 0.222222 0.444444 1 0.333333 0.444444 1 + 0.444444 0.444444 1 0.555556 0.444444 1 0.777778 0.444444 1 + 0.888889 0.444444 1 1 0.444444 1 0 0.555556 1 + 0.111111 0.555556 1 0.333333 0.555556 1 0.444444 0.555556 1 + 0.555556 0.555556 1 0.666667 0.555556 1 0.777778 0.555556 1 + 0.888889 0.555556 1 1 0.555556 1 0.111111 0.666667 1 + 0.222222 0.666667 1 0.333333 0.666667 1 0.444444 0.666667 1 + 0.555556 0.666667 1 0.777778 0.666667 1 1 0.666667 1 + 0.111111 0.777778 1 0.222222 0.777778 1 0.333333 0.777778 1 + 0.444444 0.777778 1 0.555556 0.777778 1 0.777778 0.777778 1 + 0.888889 0.777778 1 1 0.777778 1 0 0.888889 1 + 0.111111 0.888889 1 0.222222 0.888889 1 0.333333 0.888889 1 + 0.444444 0.888889 1 0.555556 0.888889 1 0.666667 0.888889 1 + 0.777778 0.888889 1 0.888889 0.888889 1 0 1 1 + 0.222222 1 1 0.333333 1 1 0.555556 1 1 + 0.666667 1 1 0.888889 1 1 1 1 1 + + + + + + 92 8 0 8 1 0 92 1 8 0 + 1 82 92 0 82 1 92 82 3 2 + 11 85 3 11 2 85 11 2 3 85 + 5 4 14 88 5 14 4 88 14 4 + 5 88 17 6 91 7 17 91 6 7 + 91 6 17 7 18 27 9 100 18 9 + 9 27 19 100 9 19 27 100 19 27 + 18 26 18 100 26 100 27 26 20 30 + 12 102 20 12 12 30 21 102 12 21 + 30 102 21 30 20 29 20 102 29 102 + 30 29 23 15 22 22 15 104 15 23 + 104 114 22 104 23 114 104 23 22 32 + 22 114 32 114 23 32 33 24 115 40 + 33 115 40 24 33 24 40 116 115 24 + 116 40 115 116 25 41 34 107 25 34 + 41 25 107 34 41 117 107 34 117 41 + 107 117 28 36 110 35 28 110 35 36 + 28 35 110 120 110 36 120 36 35 44 + 35 120 44 120 36 44 31 38 113 37 + 31 113 37 38 31 37 113 123 113 38 + 123 38 37 47 37 123 47 123 38 47 + 39 49 125 48 39 125 48 49 39 48 + 125 133 125 49 133 49 48 56 48 133 + 56 133 49 56 50 60 42 136 50 42 + 42 60 51 136 42 51 60 136 51 50 + 136 145 136 60 145 60 50 59 50 145 + 59 145 60 59 53 45 52 52 45 139 + 45 53 139 148 52 139 53 148 139 53 + 52 62 52 148 62 148 53 62 63 71 + 54 150 63 54 54 71 64 150 54 64 + 71 150 64 63 150 160 150 71 160 71 + 63 70 63 160 70 160 71 70 73 57 + 65 163 73 65 163 57 73 57 163 153 + 163 65 153 65 57 143 57 153 143 153 + 65 143 58 74 66 144 58 66 74 58 + 144 66 74 154 144 66 154 74 144 154 + 68 61 76 61 68 157 68 166 157 166 + 76 157 76 61 67 61 157 67 157 76 + 67 68 76 77 166 68 77 76 166 77 + 79 169 69 78 79 69 78 169 79 169 + 78 168 78 69 159 69 169 159 168 78 + 159 169 168 159 81 172 72 80 81 72 + 80 172 81 172 80 171 80 72 162 72 + 172 162 171 80 162 172 171 162 93 109 + 10 84 93 10 84 10 94 10 109 94 + 93 84 182 84 94 182 109 93 182 94 + 109 182 95 112 13 87 95 13 87 13 + 96 13 112 96 95 87 185 87 96 185 + 112 95 185 96 112 185 98 90 16 90 + 97 16 16 97 105 98 16 105 97 90 + 188 90 98 188 105 97 188 98 105 188 + 129 119 43 119 128 43 43 128 137 129 + 43 137 128 119 214 119 129 214 137 128 + 214 129 137 214 131 122 46 122 130 46 + 46 130 140 131 46 140 130 122 217 122 + 131 217 140 130 217 131 140 217 142 132 + 55 132 141 55 55 141 151 142 55 151 + 132 142 226 142 151 226 141 132 225 132 + 226 225 151 141 225 226 151 225 164 165 + 75 165 155 75 155 164 75 164 155 246 + 155 165 246 165 164 246 255 173 83 173 + 181 83 83 181 174 255 83 174 181 255 + 174 181 173 254 173 255 254 255 181 254 + 258 175 86 175 184 86 86 184 176 258 + 86 176 184 258 176 184 175 257 175 258 + 257 258 184 257 89 178 177 89 177 187 + 178 89 187 177 269 187 269 178 187 177 + 178 260 269 177 260 178 269 260 262 196 + 99 196 190 99 99 190 180 262 99 180 + 190 262 180 190 196 272 262 190 272 196 + 262 272 191 199 101 101 199 192 191 101 + 183 101 192 183 265 191 183 192 265 183 + 199 191 274 191 265 274 192 199 274 265 + 192 274 193 202 103 103 202 194 193 103 + 186 103 194 186 268 193 186 194 268 186 + 202 193 276 193 268 276 194 202 276 268 + 194 276 205 189 106 189 195 106 195 205 + 106 195 189 279 189 205 279 205 195 279 + 118 108 206 298 206 288 206 108 197 288 + 206 197 118 206 213 206 298 213 108 118 + 207 197 108 207 118 213 207 288 197 207 + 213 298 207 298 288 207 121 111 208 301 + 208 291 208 111 200 291 208 200 121 208 + 216 208 301 216 111 121 209 200 111 209 + 121 216 209 291 200 209 216 301 209 301 + 291 209 211 203 124 203 210 124 124 210 + 219 211 124 219 210 203 294 203 211 294 + 219 210 294 211 219 294 134 126 220 315 + 126 134 126 315 305 315 220 305 220 126 + 212 126 305 212 305 220 212 134 220 228 + 315 134 228 220 315 228 229 127 297 127 + 221 297 221 229 306 297 221 306 229 297 + 306 221 127 135 127 229 135 229 221 135 + 223 138 147 138 222 147 147 222 232 223 + 147 232 222 309 232 309 223 232 222 138 + 215 138 223 215 309 222 215 223 309 215 + 234 224 149 224 233 149 149 233 240 234 + 149 240 224 234 320 234 240 320 233 224 + 319 224 320 319 240 233 319 320 240 319 + 236 227 152 227 235 152 152 235 243 236 + 152 243 227 236 323 236 243 323 235 227 + 322 227 323 322 243 235 322 323 243 322 + 156 146 238 332 238 326 238 146 231 326 + 238 231 156 238 247 238 332 247 146 156 + 239 231 146 239 156 247 239 326 231 239 + 247 332 239 332 326 239 334 167 248 167 + 158 248 248 158 327 334 248 327 158 167 + 249 327 158 249 167 334 249 334 327 249 + 337 170 250 170 161 250 250 161 242 337 + 250 242 161 170 251 242 161 251 170 337 + 251 337 242 251 179 346 261 346 271 261 + 271 179 261 346 179 271 281 289 198 264 + 281 198 264 198 282 198 289 282 281 264 + 366 264 282 366 289 281 366 282 289 366 + 267 370 369 370 292 369 201 267 283 292 + 201 283 267 369 283 369 292 283 267 201 + 284 201 292 284 370 267 284 292 370 284 + 286 204 295 286 295 372 277 372 371 372 + 295 371 204 277 285 295 204 285 277 371 + 285 371 295 285 277 204 278 204 286 278 + 372 277 278 286 372 278 302 218 293 302 + 293 387 293 218 303 218 313 303 387 293 + 303 313 387 303 218 302 312 313 218 312 + 302 387 312 387 313 312 307 316 230 307 + 230 317 230 316 325 317 230 325 316 409 + 325 409 317 325 316 307 399 307 317 399 + 409 316 399 317 409 399 328 404 413 404 + 329 413 241 328 336 329 241 336 328 413 + 336 413 329 336 328 241 321 241 329 321 + 404 328 321 329 404 321 339 324 244 324 + 330 244 244 330 252 339 244 252 330 339 + 252 330 324 416 324 339 416 339 330 416 + 245 417 331 237 245 331 237 417 245 237 + 331 408 417 237 408 331 417 408 435 425 + 340 425 253 340 435 253 425 340 253 347 + 253 435 347 435 340 347 342 341 256 350 + 342 256 341 350 256 341 342 428 350 341 + 428 342 350 428 344 343 259 353 344 259 + 343 353 259 343 344 431 353 343 431 344 + 353 431 354 270 345 354 345 441 345 270 + 355 270 363 355 441 345 355 363 441 355 + 270 354 362 363 270 362 354 441 362 441 + 363 362 273 263 356 452 356 443 356 263 + 348 443 356 348 273 356 365 356 452 365 + 263 273 357 348 263 357 273 365 357 443 + 348 357 365 452 357 452 443 357 275 266 + 358 455 358 446 358 266 351 446 358 351 + 275 358 368 358 455 368 266 275 359 351 + 266 359 275 368 359 446 351 359 368 455 + 359 455 446 359 381 280 461 374 381 461 + 280 374 364 461 280 364 374 461 364 374 + 280 287 280 381 287 381 374 287 375 290 + 367 375 367 464 367 290 376 290 385 376 + 464 367 376 385 464 376 375 464 384 464 + 385 384 290 375 300 385 290 300 375 384 + 300 384 385 300 477 373 296 373 380 296 + 296 380 390 477 296 390 380 477 390 373 + 477 469 477 380 469 380 373 460 373 469 + 460 469 380 460 400 392 479 400 479 393 + 392 299 383 299 393 383 479 392 383 393 + 479 383 299 392 308 393 299 308 392 400 + 308 400 393 308 386 395 482 482 395 403 + 310 386 394 403 310 394 386 482 394 482 + 403 394 386 310 311 310 403 311 395 386 + 311 403 395 311 406 396 485 406 485 397 + 396 304 389 304 397 389 485 396 389 397 + 485 389 304 396 314 397 304 314 396 406 + 314 406 397 314 420 410 497 420 497 411 + 410 318 401 318 411 401 497 410 401 411 + 497 401 318 410 333 411 318 333 410 420 + 333 420 411 333 421 508 335 412 421 335 + 412 335 422 335 508 422 508 412 422 412 + 508 507 508 421 507 421 412 506 412 507 + 506 507 421 506 423 424 338 424 415 338 + 415 423 338 423 415 510 415 424 510 424 + 423 510 437 427 349 427 436 349 349 436 + 444 437 349 444 436 427 521 427 437 521 + 444 436 521 437 444 521 430 438 352 430 + 352 439 352 438 447 439 352 447 438 531 + 447 531 439 447 438 430 524 430 439 524 + 531 438 524 439 531 524 440 449 533 533 + 449 458 360 440 448 458 360 448 440 533 + 448 533 458 448 440 360 361 360 458 361 + 449 440 361 458 449 361 456 465 377 377 + 465 474 456 377 378 377 474 378 466 456 + 378 474 466 378 465 456 549 456 466 549 + 474 465 549 466 474 549 462 470 382 462 + 382 471 382 470 478 471 382 478 470 563 + 478 563 471 478 470 462 554 462 471 554 + 563 470 554 471 563 554 484 475 559 484 + 559 476 475 379 467 379 476 467 559 475 + 467 476 559 467 379 475 388 476 379 388 + 475 484 388 484 476 388 494 391 562 391 + 487 562 487 494 571 562 487 571 494 562 + 571 487 391 398 391 494 398 494 487 398 + 490 402 498 490 498 574 402 480 489 498 + 402 489 480 574 489 574 498 489 480 402 + 481 402 490 481 574 480 481 490 574 481 + 502 486 407 486 493 407 493 502 407 486 + 502 579 502 493 579 493 486 570 486 579 + 570 579 493 570 509 500 586 509 586 501 + 500 405 492 405 501 492 586 500 492 501 + 586 492 405 500 414 501 405 414 500 509 + 414 509 501 414 503 504 418 495 503 418 + 495 418 419 418 504 419 504 495 419 495 + 504 590 504 503 590 503 495 589 495 590 + 589 590 503 589 599 512 426 512 520 426 + 426 520 513 599 426 513 520 599 513 520 + 512 608 599 520 608 512 599 598 608 512 + 598 599 608 598 602 514 429 514 523 429 + 429 523 515 602 429 515 523 602 515 523 + 514 611 602 523 611 514 602 601 611 514 + 601 602 611 601 517 516 432 516 526 432 + 517 432 433 432 526 433 526 517 433 516 + 517 604 526 516 604 517 526 604 434 535 + 615 535 527 615 527 434 518 434 615 518 + 615 527 518 434 527 450 535 434 450 527 + 535 450 519 536 442 528 519 442 528 442 + 451 442 536 451 536 528 451 519 528 616 + 536 519 616 528 536 616 530 445 454 445 + 529 454 454 529 539 530 454 539 529 619 + 539 619 530 539 529 445 522 445 530 522 + 619 529 522 530 619 522 532 541 457 532 + 457 542 457 541 550 542 457 550 541 638 + 550 638 542 550 541 532 629 532 542 629 + 638 541 629 542 638 629 555 546 634 555 + 634 547 546 453 538 453 547 538 634 546 + 538 547 634 538 453 546 463 547 453 463 + 546 555 463 555 547 463 544 459 552 459 + 551 468 552 459 468 551 560 468 560 552 + 468 544 552 640 560 551 640 552 560 640 + 459 544 543 551 459 543 544 640 543 640 + 551 543 548 557 645 645 557 566 472 548 + 556 566 472 556 548 645 556 645 566 556 + 548 472 473 472 566 473 557 548 473 566 + 557 473 568 483 491 483 567 491 491 567 + 653 568 491 576 491 653 576 654 568 576 + 653 654 576 567 483 558 483 568 558 653 + 567 558 568 654 558 654 653 558 573 488 + 496 488 572 496 496 572 582 573 496 582 + 572 659 582 659 573 582 572 488 564 488 + 573 564 659 572 564 573 659 564 584 662 + 670 662 585 670 499 584 593 585 499 593 + 584 670 593 670 585 593 584 499 575 499 + 585 575 662 584 575 585 662 575 591 679 + 505 583 591 505 583 505 592 505 679 592 + 679 583 592 679 591 678 591 583 668 583 + 679 668 678 591 668 679 678 668 511 588 + 587 588 683 587 511 683 588 683 511 682 + 587 683 682 511 587 596 682 511 596 587 + 682 596 612 622 525 525 622 613 612 525 + 603 525 613 603 688 612 603 613 688 603 + 622 612 695 612 688 695 613 622 695 688 + 613 695 623 534 614 623 614 705 614 534 + 624 534 632 624 705 614 624 632 705 624 + 534 623 631 632 534 631 623 705 631 705 + 632 631 617 625 537 617 537 626 537 625 + 633 626 537 633 625 715 633 715 626 633 + 625 617 707 617 626 707 715 625 707 626 + 715 707 637 540 636 792 637 636 540 620 + 627 636 540 627 620 792 627 792 636 627 + 620 540 628 540 637 628 792 620 628 637 + 792 628 649 545 714 545 642 714 642 649 + 723 714 642 723 649 714 723 642 545 553 + 545 649 553 649 642 553 561 641 648 561 + 814 641 561 648 656 814 561 656 648 814 + 656 648 641 722 641 814 722 814 648 722 + 652 565 660 652 660 733 565 643 651 660 + 565 651 643 733 651 733 660 651 643 565 + 644 565 652 644 733 643 644 652 733 644 + 673 578 672 578 655 577 672 578 577 655 + 663 577 663 672 577 655 578 664 578 673 + 664 663 655 744 655 664 744 672 663 744 + 664 673 744 673 672 744 676 581 580 581 + 657 580 580 657 746 676 580 675 580 746 + 675 746 676 675 657 581 666 581 676 666 + 746 657 666 676 746 666 680 681 594 681 + 680 759 680 751 759 751 681 759 680 594 + 671 751 680 671 681 751 671 671 594 595 + 594 681 595 681 671 595 597 763 607 684 + 597 607 763 597 684 684 607 690 607 763 + 690 763 684 690 774 610 685 610 600 685 + 685 600 766 774 685 766 600 610 686 766 + 600 686 610 774 686 774 766 686 771 689 + 606 697 771 606 606 689 605 697 606 605 + 689 697 605 697 689 770 689 771 770 771 + 697 770 783 790 782 609 783 692 783 782 + 692 618 609 700 609 692 700 692 782 700 + 782 790 700 618 700 708 700 790 708 790 + 783 708 609 618 701 783 609 701 618 708 + 701 708 783 701 703 621 710 703 710 785 + 693 785 784 785 710 784 621 693 702 710 + 621 702 693 784 702 784 710 702 693 621 + 694 621 703 694 785 693 694 703 785 694 + 639 711 720 804 639 720 711 804 720 639 + 804 721 804 796 721 639 721 712 796 704 + 712 721 796 712 711 639 630 639 712 630 + 704 711 630 712 704 630 711 704 795 704 + 796 795 804 711 795 796 804 795 709 716 + 635 635 716 726 709 635 717 635 726 717 + 801 709 717 726 801 717 726 716 800 801 + 726 800 716 709 791 709 801 791 800 716 + 791 801 800 791 718 727 646 646 727 735 + 718 646 647 646 735 647 728 718 647 735 + 728 647 718 728 810 728 735 810 727 718 + 809 718 810 809 735 727 809 810 735 809 + 732 650 658 650 731 658 658 731 739 732 + 658 739 731 815 739 815 732 739 731 650 + 724 650 732 724 815 731 724 732 815 724 + 828 729 813 821 828 813 729 569 730 569 + 821 730 813 729 730 821 813 730 821 569 + 745 828 821 745 569 729 737 745 569 737 + 729 828 737 828 745 737 661 750 742 750 + 818 742 661 742 734 742 818 734 818 824 + 734 661 734 741 734 824 741 741 824 749 + 824 750 749 661 741 669 750 661 669 741 + 749 669 749 750 669 818 750 825 750 824 + 825 824 818 825 677 747 756 833 677 756 + 747 832 756 832 833 756 677 833 748 833 + 740 748 747 677 667 677 748 667 740 747 + 667 748 740 667 747 740 823 740 833 823 + 832 747 823 833 832 823 665 845 829 753 + 665 829 845 753 829 845 665 762 665 753 + 761 753 845 761 845 762 761 665 761 674 + 762 665 674 761 762 674 768 767 687 767 + 775 687 767 768 775 768 687 776 687 775 + 776 775 768 776 772 765 781 691 772 781 + 765 691 773 691 781 773 781 765 773 691 + 765 764 772 691 764 765 772 764 778 769 + 696 769 777 696 778 777 769 778 696 787 + 777 778 787 696 777 786 787 696 786 777 + 787 786 698 779 788 779 805 788 698 805 + 779 698 788 713 805 698 713 788 805 713 + 797 780 789 780 699 789 797 699 780 789 + 699 706 699 797 706 797 789 706 794 793 + 719 812 793 794 812 719 811 793 812 811 + 719 793 802 811 719 802 793 811 802 794 + 719 803 719 812 803 812 794 803 799 798 + 725 817 798 799 817 725 816 798 817 816 + 725 798 807 816 725 807 798 816 807 799 + 725 808 725 817 808 817 799 808 806 830 + 738 830 822 738 822 806 738 830 806 822 + 819 827 836 736 819 743 827 736 743 836 + 827 743 743 819 826 836 743 826 819 836 + 826 819 736 820 736 827 820 827 819 820 + 840 839 831 839 754 831 840 754 839 831 + 754 755 754 840 755 840 831 755 835 757 + 758 757 841 758 835 758 842 758 841 842 + 841 835 842 757 835 834 841 757 834 835 + 841 834 760 838 752 843 760 752 752 838 + 837 843 752 837 838 843 837 838 760 844 + 760 843 844 843 838 844 + + + 3 6 9 12 15 18 21 24 27 30 + 33 36 39 42 45 48 51 54 57 60 + 63 66 69 72 75 78 81 84 87 90 + 93 96 99 102 105 108 111 114 117 120 + 123 126 129 132 135 138 141 144 147 150 + 153 156 159 162 165 168 171 174 177 180 + 183 186 189 192 195 198 201 204 207 210 + 213 216 219 222 225 228 231 234 237 240 + 243 246 249 252 255 258 261 264 267 270 + 273 276 279 282 285 288 291 294 297 300 + 303 306 309 312 315 318 321 324 327 330 + 333 336 339 342 345 348 351 354 357 360 + 363 366 369 372 375 378 381 384 387 390 + 393 396 399 402 405 408 411 414 417 420 + 423 426 429 432 435 438 441 444 447 450 + 453 456 459 462 465 468 471 474 477 480 + 483 486 489 492 495 498 501 504 507 510 + 513 516 519 522 525 528 531 534 537 540 + 543 546 549 552 555 558 561 564 567 570 + 573 576 579 582 585 588 591 594 597 600 + 603 606 609 612 615 618 621 624 627 630 + 633 636 639 642 645 648 651 654 657 660 + 663 666 669 672 675 678 681 684 687 690 + 693 696 699 702 705 708 711 714 717 720 + 723 726 729 732 735 738 741 744 747 750 + 753 756 759 762 765 768 771 774 777 780 + 783 786 789 792 795 798 801 804 807 810 + 813 816 819 822 825 828 831 834 837 840 + 843 846 849 852 855 858 861 864 867 870 + 873 876 879 882 885 888 891 894 897 900 + 903 906 909 912 915 918 921 924 927 930 + 933 936 939 942 945 948 951 954 957 960 + 963 966 969 972 975 978 981 984 987 990 + 993 996 999 1002 1005 1008 1011 1014 1017 1020 + 1023 1026 1029 1032 1035 1038 1041 1044 1047 1050 + 1053 1056 1059 1062 1065 1068 1071 1074 1077 1080 + 1083 1086 1089 1092 1095 1098 1101 1104 1107 1110 + 1113 1116 1119 1122 1125 1128 1131 1134 1137 1140 + 1143 1146 1149 1152 1155 1158 1161 1164 1167 1170 + 1173 1176 1179 1182 1185 1188 1191 1194 1197 1200 + 1203 1206 1209 1212 1215 1218 1221 1224 1227 1230 + 1233 1236 1239 1242 1245 1248 1251 1254 1257 1260 + 1263 1266 1269 1272 1275 1278 1281 1284 1287 1290 + 1293 1296 1299 1302 1305 1308 1311 1314 1317 1320 + 1323 1326 1329 1332 1335 1338 1341 1344 1347 1350 + 1353 1356 1359 1362 1365 1368 1371 1374 1377 1380 + 1383 1386 1389 1392 1395 1398 1401 1404 1407 1410 + 1413 1416 1419 1422 1425 1428 1431 1434 1437 1440 + 1443 1446 1449 1452 1455 1458 1461 1464 1467 1470 + 1473 1476 1479 1482 1485 1488 1491 1494 1497 1500 + 1503 1506 1509 1512 1515 1518 1521 1524 1527 1530 + 1533 1536 1539 1542 1545 1548 1551 1554 1557 1560 + 1563 1566 1569 1572 1575 1578 1581 1584 1587 1590 + 1593 1596 1599 1602 1605 1608 1611 1614 1617 1620 + 1623 1626 1629 1632 1635 1638 1641 1644 1647 1650 + 1653 1656 1659 1662 1665 1668 1671 1674 1677 1680 + 1683 1686 1689 1692 1695 1698 1701 1704 1707 1710 + 1713 1716 1719 1722 1725 1728 1731 1734 1737 1740 + 1743 1746 1749 1752 1755 1758 1761 1764 1767 1770 + 1773 1776 1779 1782 1785 1788 1791 1794 1797 1800 + 1803 1806 1809 1812 1815 1818 1821 1824 1827 1830 + 1833 1836 1839 1842 1845 1848 1851 1854 1857 1860 + 1863 1866 1869 1872 1875 1878 1881 1884 1887 1890 + 1893 1896 1899 1902 1905 1908 1911 1914 1917 1920 + 1923 1926 1929 1932 1935 1938 1941 1944 1947 1950 + 1953 1956 1959 1962 1965 1968 1971 1974 1977 1980 + 1983 1986 1989 1992 1995 1998 2001 2004 2007 2010 + 2013 2016 2019 2022 2025 2028 2031 2034 2037 2040 + 2043 2046 2049 2052 2055 2058 2061 2064 2067 2070 + 2073 2076 2079 2082 2085 2088 2091 2094 2097 2100 + 2103 2106 2109 2112 2115 2118 2121 2124 2127 2130 + 2133 2136 2139 2142 2145 2148 2151 2154 2157 2160 + 2163 2166 2169 2172 2175 2178 2181 2184 2187 2190 + 2193 2196 2199 2202 2205 2208 2211 2214 2217 2220 + 2223 2226 2229 2232 2235 2238 2241 2244 2247 2250 + 2253 2256 2259 2262 2265 2268 2271 2274 2277 2280 + 2283 2286 2289 2292 2295 2298 2301 2304 2307 2310 + 2313 2316 2319 2322 2325 2328 2331 2334 2337 2340 + 2343 2346 2349 2352 2355 2358 2361 2364 2367 2370 + 2373 2376 2379 2382 2385 2388 2391 2394 2397 2400 + 2403 2406 2409 2412 2415 2418 2421 2424 2427 2430 + 2433 2436 2439 2442 2445 2448 2451 2454 2457 2460 + 2463 2466 2469 2472 2475 2478 2481 2484 2487 2490 + 2493 2496 2499 2502 2505 2508 2511 2514 2517 2520 + 2523 2526 2529 2532 2535 2538 2541 2544 2547 2550 + 2553 2556 2559 2562 2565 2568 2571 2574 2577 2580 + 2583 2586 2589 2592 2595 2598 2601 2604 2607 2610 + 2613 2616 2619 2622 2625 2628 2631 2634 2637 2640 + 2643 2646 2649 2652 2655 2658 2661 2664 2667 2670 + 2673 2676 2679 2682 2685 2688 2691 2694 2697 2700 + 2703 2706 2709 2712 2715 2718 2721 2724 2727 2730 + 2733 2736 2739 2742 2745 2748 2751 2754 2757 2760 + 2763 2766 2769 2772 2775 2778 2781 2784 2787 2790 + 2793 2796 2799 2802 2805 2808 2811 2814 2817 2820 + 2823 2826 2829 2832 2835 2838 2841 2844 2847 2850 + 2853 2856 2859 2862 2865 2868 2871 2874 2877 2880 + 2883 2886 2889 2892 2895 2898 2901 2904 2907 2910 + 2913 2916 2919 2922 2925 2928 2931 2934 2937 2940 + 2943 2946 2949 2952 2955 2958 2961 2964 2967 2970 + 2973 2976 2979 2982 2985 2988 2991 2994 2997 3000 + 3003 3006 3009 3012 3015 3018 3021 3024 3027 3030 + 3033 3036 3039 3042 3045 3048 3051 3054 3057 3060 + 3063 3066 3069 3072 3075 3078 3081 3084 3087 3090 + 3093 3096 3099 3102 3105 3108 3111 3114 3117 3120 + 3123 3126 3129 3132 3135 3138 3141 3144 3147 3150 + 3153 3156 3159 3162 3165 3168 3171 3174 3177 3180 + 3183 3186 3189 3192 3195 3198 3201 3204 3207 3210 + 3213 3216 3219 3222 3225 3228 3231 3234 3237 3240 + 3243 3246 3249 3252 3255 3258 3261 3264 3267 3270 + 3273 3276 3279 3282 3285 3288 3291 3294 3297 3300 + 3303 3306 3309 3312 3315 3318 3321 3324 3327 3330 + 3333 3336 3339 3342 3345 3348 3351 3354 3357 3360 + 3363 3366 3369 3372 3375 3378 3381 3384 3387 3390 + 3393 3396 3399 3402 3405 3408 3411 3414 3417 3420 + 3423 3426 3429 3432 3435 3438 3441 3444 3447 3450 + 3453 3456 3459 3462 3465 3468 3471 3474 3477 3480 + 3483 3486 3489 3492 3495 3498 3501 3504 3507 3510 + 3513 3516 + + + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 + + + + + \ No newline at end of file diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc0.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc0.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc0.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc0.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc1.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc1.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc1.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc1.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc2.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc2.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc2.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc2.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc3.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc3.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc3.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0-Proc3.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-ConvexHulls-Level0.gold diff --git a/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc0.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc0.gold new file mode 100644 index 000000000000..f92ccbc45cb9 --- /dev/null +++ b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc0.gold @@ -0,0 +1,265 @@ + + + + + + + 0 1 2 3 4 10 11 12 13 14 + 20 21 22 23 24 30 31 32 33 34 + 40 41 42 43 44 100 101 102 103 104 + 110 111 112 113 114 120 121 122 123 124 + 130 131 132 133 134 140 141 142 143 144 + 200 201 202 203 204 210 211 212 213 214 + 220 221 222 223 224 230 231 232 233 234 + 240 241 242 243 244 300 301 302 303 304 + 310 311 312 313 314 320 321 322 323 324 + 330 331 332 333 334 340 341 342 343 344 + 400 401 402 403 404 410 411 412 413 414 + 420 421 422 423 424 430 431 432 433 434 + 440 441 442 443 444 500 501 502 503 504 + 510 511 512 513 514 520 521 522 523 524 + 530 531 532 533 534 540 541 542 543 544 + 600 601 602 603 604 610 611 612 613 614 + 620 621 622 623 624 630 631 632 633 634 + 640 641 642 643 644 700 701 702 703 704 + 710 711 712 713 714 720 721 722 723 724 + 730 731 732 733 734 740 741 742 743 744 + 800 801 802 803 804 810 811 812 813 814 + 820 821 822 823 824 830 831 832 833 834 + 840 841 842 843 844 900 901 902 903 904 + 910 911 912 913 914 920 921 922 923 924 + 930 931 932 933 934 940 941 942 943 944 + + + + 0 0 1 1 1 0 2 6 1 3 + 2 2 2 3 3 4 2 2 5 3 + 4 4 5 5 5 0 7 6 1 8 + 0 6 6 6 3 9 2 6 10 3 + 4 11 6 5 12 4 11 5 5 12 + 7 7 7 8 8 9 7 6 10 8 + 9 9 10 10 10 9 11 13 10 12 + 11 11 11 12 12 14 7 7 15 8 + 9 16 13 10 8 9 16 13 10 17 + 18 13 13 13 17 18 11 13 19 12 + 14 14 15 15 15 14 16 20 15 17 + 16 16 16 17 17 18 16 13 19 17 + 18 18 19 19 19 14 21 20 15 22 + 14 20 20 20 22 23 16 20 24 17 + 23 25 20 19 26 18 25 19 19 26 + 21 21 21 22 22 23 21 20 24 22 + 23 23 24 24 24 23 25 27 24 26 + 25 25 25 26 26 28 21 21 29 22 + 28 30 27 24 31 23 30 27 24 31 + 32 27 27 27 26 32 25 27 33 26 + 28 28 29 29 29 28 30 34 29 31 + 30 30 30 31 31 32 30 27 33 31 + 32 32 33 33 33 28 34 34 29 29 + 28 34 34 34 31 30 30 34 34 31 + 32 30 27 33 31 32 32 33 33 33 + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 + + + 4.71117 4.71117 6 6 6 4.71117 12.2679 26.5197 6 11.0268 + 12.2679 12.2679 12.2679 11.0268 11.0268 6.36105 12.2679 12.2679 9.04703 11.0268 + 6.36105 6.36105 9.04703 9.04703 9.04703 4.71117 12.2679 26.5197 6 11.0268 + 4.71117 26.5197 26.5197 26.5197 11.0268 12.2712 12.2679 26.5197 17.0714 11.0268 + 6.36105 16.5078 26.5197 9.04703 15.7082 6.36105 16.5078 9.04703 9.04703 15.7082 + 12.2679 12.2679 12.2679 11.0268 11.0268 12.2712 12.2679 26.5197 17.0714 11.0268 + 12.2712 12.2712 17.0714 17.0714 17.0714 12.2712 16.5078 26.5197 17.0714 15.7082 + 16.5078 16.5078 16.5078 15.7082 15.7082 6.35236 12.2679 12.2679 11.6108 11.0268 + 12.2712 17.0714 26.5197 17.0714 11.0268 12.2712 17.0714 26.5197 17.0714 16.5078 + 12.3728 26.5197 26.5197 26.5197 16.5078 12.3728 16.5078 26.5197 15.5535 15.7082 + 6.35236 6.35236 11.6108 11.6108 11.6108 6.35236 17.0714 26.5197 11.6108 16.5078 + 17.0714 17.0714 17.0714 16.5078 16.5078 12.3728 17.0714 26.5197 15.5535 16.5078 + 12.3728 12.3728 15.5535 15.5535 15.5535 6.35236 12.2679 26.5197 11.6108 11.0268 + 6.35236 26.5197 26.5197 26.5197 11.0268 12.2712 17.0714 26.5197 17.0714 16.5078 + 12.2712 16.5078 26.5197 15.5535 14.1879 12.3728 16.5078 15.5535 15.5535 14.1879 + 12.2679 12.2679 12.2679 11.0268 11.0268 12.2712 12.2679 26.5197 17.0714 11.0268 + 12.2712 12.2712 17.0714 17.0714 17.0714 12.2712 16.5078 31.4164 17.0714 14.1879 + 16.5078 16.5078 16.5078 14.1879 14.1879 6.24949 12.2679 12.2679 12.1555 11.0268 + 6.24949 21.217 31.4164 17.0714 14.6789 12.2712 21.217 31.4164 17.0714 14.6789 + 8.49387 31.4164 31.4164 31.4164 14.1879 8.49387 16.5078 31.4164 13.8718 14.1879 + 6.24949 6.24949 12.1555 12.1555 12.1555 6.24949 21.217 12.5778 12.1555 14.6789 + 21.217 21.217 21.217 14.6789 14.6789 8.49387 21.217 31.4164 13.8718 14.6789 + 8.49387 8.49387 13.8718 13.8718 13.8718 6.24949 12.5778 12.5778 12.1555 12.1555 + 6.24949 12.5778 12.5778 12.5778 14.6789 21.217 21.217 12.5778 12.5778 14.6789 + 8.49387 21.217 31.4164 13.8718 14.6789 8.49387 8.49387 13.8718 13.8718 13.8718 + + + + + + 0 0 0 0.111111 0 0 0.222222 0 0 + 0.333333 0 0 0.444444 0 0 0 0.111111 0 + 0.111111 0.111111 0 0.222222 0.111111 0 0.333333 0.111111 0 + 0.444444 0.111111 0 0 0.222222 0 0.111111 0.222222 0 + 0.222222 0.222222 0 0.333333 0.222222 0 0.444444 0.222222 0 + 0 0.333333 0 0.111111 0.333333 0 0.222222 0.333333 0 + 0.333333 0.333333 0 0.444444 0.333333 0 0 0.444444 0 + 0.111111 0.444444 0 0.222222 0.444444 0 0.333333 0.444444 0 + 0.444444 0.444444 0 0 0 0.111111 0.111111 0 0.111111 + 0.222222 0 0.111111 0.333333 0 0.111111 0.444444 0 0.111111 + 0 0.111111 0.111111 0.111111 0.111111 0.111111 0.222222 0.111111 0.111111 + 0.333333 0.111111 0.111111 0.444444 0.111111 0.111111 0 0.222222 0.111111 + 0.111111 0.222222 0.111111 0.222222 0.222222 0.111111 0.333333 0.222222 0.111111 + 0.444444 0.222222 0.111111 0 0.333333 0.111111 0.111111 0.333333 0.111111 + 0.222222 0.333333 0.111111 0.333333 0.333333 0.111111 0.444444 0.333333 0.111111 + 0 0.444444 0.111111 0.111111 0.444444 0.111111 0.222222 0.444444 0.111111 + 0.333333 0.444444 0.111111 0.444444 0.444444 0.111111 0 0 0.222222 + 0.111111 0 0.222222 0.222222 0 0.222222 0.333333 0 0.222222 + 0.444444 0 0.222222 0 0.111111 0.222222 0.111111 0.111111 0.222222 + 0.222222 0.111111 0.222222 0.333333 0.111111 0.222222 0.444444 0.111111 0.222222 + 0 0.222222 0.222222 0.111111 0.222222 0.222222 0.222222 0.222222 0.222222 + 0.333333 0.222222 0.222222 0.444444 0.222222 0.222222 0 0.333333 0.222222 + 0.111111 0.333333 0.222222 0.222222 0.333333 0.222222 0.333333 0.333333 0.222222 + 0.444444 0.333333 0.222222 0 0.444444 0.222222 0.111111 0.444444 0.222222 + 0.222222 0.444444 0.222222 0.333333 0.444444 0.222222 0.444444 0.444444 0.222222 + 0 0 0.333333 0.111111 0 0.333333 0.222222 0 0.333333 + 0.333333 0 0.333333 0.444444 0 0.333333 0 0.111111 0.333333 + 0.111111 0.111111 0.333333 0.222222 0.111111 0.333333 0.333333 0.111111 0.333333 + 0.444444 0.111111 0.333333 0 0.222222 0.333333 0.111111 0.222222 0.333333 + 0.222222 0.222222 0.333333 0.333333 0.222222 0.333333 0.444444 0.222222 0.333333 + 0 0.333333 0.333333 0.111111 0.333333 0.333333 0.222222 0.333333 0.333333 + 0.333333 0.333333 0.333333 0.444444 0.333333 0.333333 0 0.444444 0.333333 + 0.111111 0.444444 0.333333 0.222222 0.444444 0.333333 0.333333 0.444444 0.333333 + 0.444444 0.444444 0.333333 0 0 0.444444 0.111111 0 0.444444 + 0.222222 0 0.444444 0.333333 0 0.444444 0.444444 0 0.444444 + 0 0.111111 0.444444 0.111111 0.111111 0.444444 0.222222 0.111111 0.444444 + 0.333333 0.111111 0.444444 0.444444 0.111111 0.444444 0 0.222222 0.444444 + 0.111111 0.222222 0.444444 0.222222 0.222222 0.444444 0.333333 0.222222 0.444444 + 0.444444 0.222222 0.444444 0 0.333333 0.444444 0.111111 0.333333 0.444444 + 0.222222 0.333333 0.444444 0.333333 0.333333 0.444444 0.444444 0.333333 0.444444 + 0 0.444444 0.444444 0.111111 0.444444 0.444444 0.222222 0.444444 0.444444 + 0.333333 0.444444 0.444444 0.444444 0.444444 0.444444 0 0 0.555556 + 0.111111 0 0.555556 0.222222 0 0.555556 0.333333 0 0.555556 + 0.444444 0 0.555556 0 0.111111 0.555556 0.111111 0.111111 0.555556 + 0.222222 0.111111 0.555556 0.333333 0.111111 0.555556 0.444444 0.111111 0.555556 + 0 0.222222 0.555556 0.111111 0.222222 0.555556 0.222222 0.222222 0.555556 + 0.333333 0.222222 0.555556 0.444444 0.222222 0.555556 0 0.333333 0.555556 + 0.111111 0.333333 0.555556 0.222222 0.333333 0.555556 0.333333 0.333333 0.555556 + 0.444444 0.333333 0.555556 0 0.444444 0.555556 0.111111 0.444444 0.555556 + 0.222222 0.444444 0.555556 0.333333 0.444444 0.555556 0.444444 0.444444 0.555556 + 0 0 0.666667 0.111111 0 0.666667 0.222222 0 0.666667 + 0.333333 0 0.666667 0.444444 0 0.666667 0 0.111111 0.666667 + 0.111111 0.111111 0.666667 0.222222 0.111111 0.666667 0.333333 0.111111 0.666667 + 0.444444 0.111111 0.666667 0 0.222222 0.666667 0.111111 0.222222 0.666667 + 0.222222 0.222222 0.666667 0.333333 0.222222 0.666667 0.444444 0.222222 0.666667 + 0 0.333333 0.666667 0.111111 0.333333 0.666667 0.222222 0.333333 0.666667 + 0.333333 0.333333 0.666667 0.444444 0.333333 0.666667 0 0.444444 0.666667 + 0.111111 0.444444 0.666667 0.222222 0.444444 0.666667 0.333333 0.444444 0.666667 + 0.444444 0.444444 0.666667 0 0 0.777778 0.111111 0 0.777778 + 0.222222 0 0.777778 0.333333 0 0.777778 0.444444 0 0.777778 + 0 0.111111 0.777778 0.111111 0.111111 0.777778 0.222222 0.111111 0.777778 + 0.333333 0.111111 0.777778 0.444444 0.111111 0.777778 0 0.222222 0.777778 + 0.111111 0.222222 0.777778 0.222222 0.222222 0.777778 0.333333 0.222222 0.777778 + 0.444444 0.222222 0.777778 0 0.333333 0.777778 0.111111 0.333333 0.777778 + 0.222222 0.333333 0.777778 0.333333 0.333333 0.777778 0.444444 0.333333 0.777778 + 0 0.444444 0.777778 0.111111 0.444444 0.777778 0.222222 0.444444 0.777778 + 0.333333 0.444444 0.777778 0.444444 0.444444 0.777778 0 0 0.888889 + 0.111111 0 0.888889 0.222222 0 0.888889 0.333333 0 0.888889 + 0.444444 0 0.888889 0 0.111111 0.888889 0.111111 0.111111 0.888889 + 0.222222 0.111111 0.888889 0.333333 0.111111 0.888889 0.444444 0.111111 0.888889 + 0 0.222222 0.888889 0.111111 0.222222 0.888889 0.222222 0.222222 0.888889 + 0.333333 0.222222 0.888889 0.444444 0.222222 0.888889 0 0.333333 0.888889 + 0.111111 0.333333 0.888889 0.222222 0.333333 0.888889 0.333333 0.333333 0.888889 + 0.444444 0.333333 0.888889 0 0.444444 0.888889 0.111111 0.444444 0.888889 + 0.222222 0.444444 0.888889 0.333333 0.444444 0.888889 0.444444 0.444444 0.888889 + 0 0 1 0.111111 0 1 0.222222 0 1 + 0.333333 0 1 0.444444 0 1 0 0.111111 1 + 0.111111 0.111111 1 0.222222 0.111111 1 0.333333 0.111111 1 + 0.444444 0.111111 1 0 0.222222 1 0.111111 0.222222 1 + 0.222222 0.222222 1 0.333333 0.222222 1 0.444444 0.222222 1 + 0 0.333333 1 0.111111 0.333333 1 0.222222 0.333333 1 + 0.333333 0.333333 1 0.444444 0.333333 1 0 0.444444 1 + 0.111111 0.444444 1 0.222222 0.444444 1 0.333333 0.444444 1 + 0.444444 0.444444 1 + + + + + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100 101 102 103 104 105 106 107 108 109 + 110 111 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 128 129 + 130 131 132 133 134 135 136 137 138 139 + 140 141 142 143 144 145 146 147 148 149 + 150 151 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 168 169 + 170 171 172 173 174 175 176 177 178 179 + 180 181 182 183 184 185 186 187 188 189 + 190 191 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 208 209 + 210 211 212 213 214 215 216 217 218 219 + 220 221 222 223 224 225 226 227 228 229 + 230 231 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 248 249 + + + + 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 + 81 82 83 84 85 86 87 88 89 90 + 91 92 93 94 95 96 97 98 99 100 + 101 102 103 104 105 106 107 108 109 110 + 111 112 113 114 115 116 117 118 119 120 + 121 122 123 124 125 126 127 128 129 130 + 131 132 133 134 135 136 137 138 139 140 + 141 142 143 144 145 146 147 148 149 150 + 151 152 153 154 155 156 157 158 159 160 + 161 162 163 164 165 166 167 168 169 170 + 171 172 173 174 175 176 177 178 179 180 + 181 182 183 184 185 186 187 188 189 190 + 191 192 193 194 195 196 197 198 199 200 + 201 202 203 204 205 206 207 208 209 210 + 211 212 213 214 215 216 217 218 219 220 + 221 222 223 224 225 226 227 228 229 230 + 231 232 233 234 235 236 237 238 239 240 + 241 242 243 244 245 246 247 248 249 250 + + + + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 + + + + + \ No newline at end of file diff --git a/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc1.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc1.gold new file mode 100644 index 000000000000..f49526050fae --- /dev/null +++ b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc1.gold @@ -0,0 +1,265 @@ + + + + + + + 5 6 7 8 9 15 16 17 18 19 + 25 26 27 28 29 35 36 37 38 39 + 45 46 47 48 49 105 106 107 108 109 + 115 116 117 118 119 125 126 127 128 129 + 135 136 137 138 139 145 146 147 148 149 + 205 206 207 208 209 215 216 217 218 219 + 225 226 227 228 229 235 236 237 238 239 + 245 246 247 248 249 305 306 307 308 309 + 315 316 317 318 319 325 326 327 328 329 + 335 336 337 338 339 345 346 347 348 349 + 405 406 407 408 409 415 416 417 418 419 + 425 426 427 428 429 435 436 437 438 439 + 445 446 447 448 449 505 506 507 508 509 + 515 516 517 518 519 525 526 527 528 529 + 535 536 537 538 539 545 546 547 548 549 + 605 606 607 608 609 615 616 617 618 619 + 625 626 627 628 629 635 636 637 638 639 + 645 646 647 648 649 705 706 707 708 709 + 715 716 717 718 719 725 726 727 728 729 + 735 736 737 738 739 745 746 747 748 749 + 805 806 807 808 809 815 816 817 818 819 + 825 826 827 828 829 835 836 837 838 839 + 845 846 847 848 849 905 906 907 908 909 + 915 916 917 918 919 925 926 927 928 929 + 935 936 937 938 939 945 946 947 948 949 + + + + 35 35 36 36 36 35 37 41 36 38 + 37 37 37 38 38 39 37 37 40 38 + 39 39 40 40 40 35 42 41 36 43 + 35 41 41 41 38 44 37 41 45 38 + 39 46 41 40 47 39 46 40 40 47 + 42 42 42 43 43 44 42 41 45 43 + 44 44 45 45 45 44 46 48 45 47 + 46 46 46 47 47 49 42 42 50 43 + 44 51 48 45 43 44 51 48 45 52 + 53 48 48 48 52 53 46 48 54 47 + 49 49 50 50 50 49 51 55 50 52 + 51 51 51 52 52 53 51 48 54 52 + 53 53 54 54 54 49 56 55 50 57 + 49 55 55 55 57 58 51 55 59 52 + 58 60 55 54 61 53 60 54 54 61 + 56 56 56 57 57 58 56 55 59 57 + 58 58 59 59 59 58 60 62 59 61 + 60 60 60 61 61 63 56 56 64 57 + 63 65 62 59 66 58 65 62 59 66 + 67 62 62 62 61 67 60 62 68 61 + 63 63 64 64 64 63 65 69 64 66 + 65 65 65 66 66 67 65 62 68 66 + 67 67 68 68 68 63 69 69 64 64 + 63 69 69 69 66 65 65 69 69 66 + 67 65 62 68 66 67 67 68 68 68 + + + + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 + + + 7.10619 7.10619 6 6 6 7.10619 12.2712 26.5197 6 6.35236 + 12.2712 12.2712 12.2712 6.35236 6.35236 9.65407 12.2712 12.2712 8.68328 6.35236 + 9.65407 9.65407 8.68328 8.68328 8.68328 7.10619 12.2712 26.5197 6 6.35236 + 7.10619 26.5197 26.5197 26.5197 6.35236 16.5078 12.2712 26.5197 17.0714 6.35236 + 9.65407 16.5078 26.5197 8.68328 12.3728 9.65407 16.5078 8.68328 8.68328 12.3728 + 12.2712 12.2712 12.2712 6.35236 6.35236 16.5078 12.2712 26.5197 17.0714 6.35236 + 16.5078 16.5078 17.0714 17.0714 17.0714 16.5078 16.5078 26.5197 17.0714 12.3728 + 16.5078 16.5078 16.5078 12.3728 12.3728 11.0268 12.2712 12.2712 11.6029 6.35236 + 16.5078 17.0714 26.5197 17.0714 6.35236 16.5078 17.0714 26.5197 17.0714 12.2712 + 15.7082 26.5197 26.5197 26.5197 12.2712 15.7082 16.5078 26.5197 15.5535 12.3728 + 11.0268 11.0268 11.6029 11.6029 11.6029 11.0268 17.0714 26.5197 11.6029 12.2712 + 17.0714 17.0714 17.0714 12.2712 12.2712 15.7082 17.0714 26.5197 15.5535 12.2712 + 15.7082 15.7082 15.5535 15.5535 15.5535 11.0268 12.2712 26.5197 11.6029 6.35236 + 11.0268 26.5197 26.5197 26.5197 6.35236 16.5078 17.0714 26.5197 17.0714 12.2712 + 16.5078 16.5078 26.5197 15.5535 12.9067 15.7082 16.5078 15.5535 15.5535 12.9067 + 12.2712 12.2712 12.2712 6.35236 6.35236 16.5078 12.2712 26.5197 17.0714 6.35236 + 16.5078 16.5078 17.0714 17.0714 17.0714 16.5078 16.5078 31.4164 17.0714 12.9067 + 16.5078 16.5078 16.5078 12.9067 12.9067 8.80585 12.2712 12.2712 12.1089 6.35236 + 8.80585 21.4164 31.4164 17.0714 12.8711 16.5078 21.4164 31.4164 17.0714 12.8711 + 14.657 31.4164 31.4164 31.4164 12.9067 14.657 16.5078 31.4164 13.7649 12.9067 + 8.80585 8.80585 12.1089 12.1089 12.1089 8.80585 21.4164 12.5778 12.1089 12.8711 + 21.4164 21.4164 21.4164 12.8711 12.8711 14.657 21.4164 31.4164 13.7649 12.8711 + 14.657 14.657 13.7649 13.7649 13.7649 8.80585 12.5778 12.5778 12.1089 12.1089 + 8.80585 12.5778 12.5778 12.5778 12.8711 21.4164 21.4164 12.5778 12.5778 12.8711 + 14.657 21.4164 31.4164 13.7649 12.8711 14.657 14.657 13.7649 13.7649 13.7649 + + + + + + 0.555556 0 0 0.666667 0 0 0.777778 0 0 + 0.888889 0 0 1 0 0 0.555556 0.111111 0 + 0.666667 0.111111 0 0.777778 0.111111 0 0.888889 0.111111 0 + 1 0.111111 0 0.555556 0.222222 0 0.666667 0.222222 0 + 0.777778 0.222222 0 0.888889 0.222222 0 1 0.222222 0 + 0.555556 0.333333 0 0.666667 0.333333 0 0.777778 0.333333 0 + 0.888889 0.333333 0 1 0.333333 0 0.555556 0.444444 0 + 0.666667 0.444444 0 0.777778 0.444444 0 0.888889 0.444444 0 + 1 0.444444 0 0.555556 0 0.111111 0.666667 0 0.111111 + 0.777778 0 0.111111 0.888889 0 0.111111 1 0 0.111111 + 0.555556 0.111111 0.111111 0.666667 0.111111 0.111111 0.777778 0.111111 0.111111 + 0.888889 0.111111 0.111111 1 0.111111 0.111111 0.555556 0.222222 0.111111 + 0.666667 0.222222 0.111111 0.777778 0.222222 0.111111 0.888889 0.222222 0.111111 + 1 0.222222 0.111111 0.555556 0.333333 0.111111 0.666667 0.333333 0.111111 + 0.777778 0.333333 0.111111 0.888889 0.333333 0.111111 1 0.333333 0.111111 + 0.555556 0.444444 0.111111 0.666667 0.444444 0.111111 0.777778 0.444444 0.111111 + 0.888889 0.444444 0.111111 1 0.444444 0.111111 0.555556 0 0.222222 + 0.666667 0 0.222222 0.777778 0 0.222222 0.888889 0 0.222222 + 1 0 0.222222 0.555556 0.111111 0.222222 0.666667 0.111111 0.222222 + 0.777778 0.111111 0.222222 0.888889 0.111111 0.222222 1 0.111111 0.222222 + 0.555556 0.222222 0.222222 0.666667 0.222222 0.222222 0.777778 0.222222 0.222222 + 0.888889 0.222222 0.222222 1 0.222222 0.222222 0.555556 0.333333 0.222222 + 0.666667 0.333333 0.222222 0.777778 0.333333 0.222222 0.888889 0.333333 0.222222 + 1 0.333333 0.222222 0.555556 0.444444 0.222222 0.666667 0.444444 0.222222 + 0.777778 0.444444 0.222222 0.888889 0.444444 0.222222 1 0.444444 0.222222 + 0.555556 0 0.333333 0.666667 0 0.333333 0.777778 0 0.333333 + 0.888889 0 0.333333 1 0 0.333333 0.555556 0.111111 0.333333 + 0.666667 0.111111 0.333333 0.777778 0.111111 0.333333 0.888889 0.111111 0.333333 + 1 0.111111 0.333333 0.555556 0.222222 0.333333 0.666667 0.222222 0.333333 + 0.777778 0.222222 0.333333 0.888889 0.222222 0.333333 1 0.222222 0.333333 + 0.555556 0.333333 0.333333 0.666667 0.333333 0.333333 0.777778 0.333333 0.333333 + 0.888889 0.333333 0.333333 1 0.333333 0.333333 0.555556 0.444444 0.333333 + 0.666667 0.444444 0.333333 0.777778 0.444444 0.333333 0.888889 0.444444 0.333333 + 1 0.444444 0.333333 0.555556 0 0.444444 0.666667 0 0.444444 + 0.777778 0 0.444444 0.888889 0 0.444444 1 0 0.444444 + 0.555556 0.111111 0.444444 0.666667 0.111111 0.444444 0.777778 0.111111 0.444444 + 0.888889 0.111111 0.444444 1 0.111111 0.444444 0.555556 0.222222 0.444444 + 0.666667 0.222222 0.444444 0.777778 0.222222 0.444444 0.888889 0.222222 0.444444 + 1 0.222222 0.444444 0.555556 0.333333 0.444444 0.666667 0.333333 0.444444 + 0.777778 0.333333 0.444444 0.888889 0.333333 0.444444 1 0.333333 0.444444 + 0.555556 0.444444 0.444444 0.666667 0.444444 0.444444 0.777778 0.444444 0.444444 + 0.888889 0.444444 0.444444 1 0.444444 0.444444 0.555556 0 0.555556 + 0.666667 0 0.555556 0.777778 0 0.555556 0.888889 0 0.555556 + 1 0 0.555556 0.555556 0.111111 0.555556 0.666667 0.111111 0.555556 + 0.777778 0.111111 0.555556 0.888889 0.111111 0.555556 1 0.111111 0.555556 + 0.555556 0.222222 0.555556 0.666667 0.222222 0.555556 0.777778 0.222222 0.555556 + 0.888889 0.222222 0.555556 1 0.222222 0.555556 0.555556 0.333333 0.555556 + 0.666667 0.333333 0.555556 0.777778 0.333333 0.555556 0.888889 0.333333 0.555556 + 1 0.333333 0.555556 0.555556 0.444444 0.555556 0.666667 0.444444 0.555556 + 0.777778 0.444444 0.555556 0.888889 0.444444 0.555556 1 0.444444 0.555556 + 0.555556 0 0.666667 0.666667 0 0.666667 0.777778 0 0.666667 + 0.888889 0 0.666667 1 0 0.666667 0.555556 0.111111 0.666667 + 0.666667 0.111111 0.666667 0.777778 0.111111 0.666667 0.888889 0.111111 0.666667 + 1 0.111111 0.666667 0.555556 0.222222 0.666667 0.666667 0.222222 0.666667 + 0.777778 0.222222 0.666667 0.888889 0.222222 0.666667 1 0.222222 0.666667 + 0.555556 0.333333 0.666667 0.666667 0.333333 0.666667 0.777778 0.333333 0.666667 + 0.888889 0.333333 0.666667 1 0.333333 0.666667 0.555556 0.444444 0.666667 + 0.666667 0.444444 0.666667 0.777778 0.444444 0.666667 0.888889 0.444444 0.666667 + 1 0.444444 0.666667 0.555556 0 0.777778 0.666667 0 0.777778 + 0.777778 0 0.777778 0.888889 0 0.777778 1 0 0.777778 + 0.555556 0.111111 0.777778 0.666667 0.111111 0.777778 0.777778 0.111111 0.777778 + 0.888889 0.111111 0.777778 1 0.111111 0.777778 0.555556 0.222222 0.777778 + 0.666667 0.222222 0.777778 0.777778 0.222222 0.777778 0.888889 0.222222 0.777778 + 1 0.222222 0.777778 0.555556 0.333333 0.777778 0.666667 0.333333 0.777778 + 0.777778 0.333333 0.777778 0.888889 0.333333 0.777778 1 0.333333 0.777778 + 0.555556 0.444444 0.777778 0.666667 0.444444 0.777778 0.777778 0.444444 0.777778 + 0.888889 0.444444 0.777778 1 0.444444 0.777778 0.555556 0 0.888889 + 0.666667 0 0.888889 0.777778 0 0.888889 0.888889 0 0.888889 + 1 0 0.888889 0.555556 0.111111 0.888889 0.666667 0.111111 0.888889 + 0.777778 0.111111 0.888889 0.888889 0.111111 0.888889 1 0.111111 0.888889 + 0.555556 0.222222 0.888889 0.666667 0.222222 0.888889 0.777778 0.222222 0.888889 + 0.888889 0.222222 0.888889 1 0.222222 0.888889 0.555556 0.333333 0.888889 + 0.666667 0.333333 0.888889 0.777778 0.333333 0.888889 0.888889 0.333333 0.888889 + 1 0.333333 0.888889 0.555556 0.444444 0.888889 0.666667 0.444444 0.888889 + 0.777778 0.444444 0.888889 0.888889 0.444444 0.888889 1 0.444444 0.888889 + 0.555556 0 1 0.666667 0 1 0.777778 0 1 + 0.888889 0 1 1 0 1 0.555556 0.111111 1 + 0.666667 0.111111 1 0.777778 0.111111 1 0.888889 0.111111 1 + 1 0.111111 1 0.555556 0.222222 1 0.666667 0.222222 1 + 0.777778 0.222222 1 0.888889 0.222222 1 1 0.222222 1 + 0.555556 0.333333 1 0.666667 0.333333 1 0.777778 0.333333 1 + 0.888889 0.333333 1 1 0.333333 1 0.555556 0.444444 1 + 0.666667 0.444444 1 0.777778 0.444444 1 0.888889 0.444444 1 + 1 0.444444 1 + + + + + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100 101 102 103 104 105 106 107 108 109 + 110 111 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 128 129 + 130 131 132 133 134 135 136 137 138 139 + 140 141 142 143 144 145 146 147 148 149 + 150 151 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 168 169 + 170 171 172 173 174 175 176 177 178 179 + 180 181 182 183 184 185 186 187 188 189 + 190 191 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 208 209 + 210 211 212 213 214 215 216 217 218 219 + 220 221 222 223 224 225 226 227 228 229 + 230 231 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 248 249 + + + + 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 + 81 82 83 84 85 86 87 88 89 90 + 91 92 93 94 95 96 97 98 99 100 + 101 102 103 104 105 106 107 108 109 110 + 111 112 113 114 115 116 117 118 119 120 + 121 122 123 124 125 126 127 128 129 130 + 131 132 133 134 135 136 137 138 139 140 + 141 142 143 144 145 146 147 148 149 150 + 151 152 153 154 155 156 157 158 159 160 + 161 162 163 164 165 166 167 168 169 170 + 171 172 173 174 175 176 177 178 179 180 + 181 182 183 184 185 186 187 188 189 190 + 191 192 193 194 195 196 197 198 199 200 + 201 202 203 204 205 206 207 208 209 210 + 211 212 213 214 215 216 217 218 219 220 + 221 222 223 224 225 226 227 228 229 230 + 231 232 233 234 235 236 237 238 239 240 + 241 242 243 244 245 246 247 248 249 250 + + + + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 + + + + + \ No newline at end of file diff --git a/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc2.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc2.gold new file mode 100644 index 000000000000..390bb3b68024 --- /dev/null +++ b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc2.gold @@ -0,0 +1,265 @@ + + + + + + + 50 51 52 53 54 60 61 62 63 64 + 70 71 72 73 74 80 81 82 83 84 + 90 91 92 93 94 150 151 152 153 154 + 160 161 162 163 164 170 171 172 173 174 + 180 181 182 183 184 190 191 192 193 194 + 250 251 252 253 254 260 261 262 263 264 + 270 271 272 273 274 280 281 282 283 284 + 290 291 292 293 294 350 351 352 353 354 + 360 361 362 363 364 370 371 372 373 374 + 380 381 382 383 384 390 391 392 393 394 + 450 451 452 453 454 460 461 462 463 464 + 470 471 472 473 474 480 481 482 483 484 + 490 491 492 493 494 550 551 552 553 554 + 560 561 562 563 564 570 571 572 573 574 + 580 581 582 583 584 590 591 592 593 594 + 650 651 652 653 654 660 661 662 663 664 + 670 671 672 673 674 680 681 682 683 684 + 690 691 692 693 694 750 751 752 753 754 + 760 761 762 763 764 770 771 772 773 774 + 780 781 782 783 784 790 791 792 793 794 + 850 851 852 853 854 860 861 862 863 864 + 870 871 872 873 874 880 881 882 883 884 + 890 891 892 893 894 950 951 952 953 954 + 960 961 962 963 964 970 971 972 973 974 + 980 981 982 983 984 990 991 992 993 994 + + + + 70 70 71 71 71 70 72 76 71 73 + 72 72 72 73 73 74 72 72 75 73 + 74 74 75 75 75 70 77 76 71 78 + 70 76 76 76 73 79 72 76 80 73 + 74 81 76 75 82 74 81 75 75 82 + 77 77 77 78 78 79 77 76 80 78 + 79 79 80 80 80 79 81 83 80 82 + 81 81 81 82 82 84 77 77 85 78 + 79 86 83 80 78 79 86 83 80 87 + 88 83 83 83 87 88 81 83 89 82 + 84 84 85 85 85 84 86 90 85 87 + 86 86 86 87 87 88 86 83 89 87 + 88 88 89 89 89 84 91 90 85 92 + 84 90 90 90 92 93 86 90 94 87 + 93 95 90 89 96 88 95 89 89 96 + 91 91 91 92 92 93 91 90 94 92 + 93 93 94 94 94 93 95 97 94 96 + 95 95 95 96 96 98 91 91 99 92 + 98 100 97 94 101 93 100 97 94 101 + 102 97 97 97 96 102 95 97 103 96 + 98 98 99 99 99 98 100 104 99 101 + 100 100 100 101 101 102 100 97 103 101 + 102 102 103 103 103 98 104 104 99 99 + 98 104 104 104 101 100 100 104 104 101 + 102 100 97 103 101 102 102 103 103 103 + + + + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 + + + 6.36105 6.36105 11.423 11.423 11.423 6.36105 12.2679 26.5197 11.423 11.0268 + 12.2679 12.2679 12.2679 11.0268 11.0268 4.71117 12.2679 12.2679 7.81935 11.0268 + 4.71117 4.71117 7.81935 7.81935 7.81935 6.36105 16.5078 26.5197 11.423 15.7082 + 6.36105 26.5197 26.5197 26.5197 11.0268 12.2712 12.2679 26.5197 17.0714 11.0268 + 4.71117 11.7696 26.5197 7.81935 11.0268 4.71117 11.7696 7.81935 7.81935 11.0268 + 16.5078 16.5078 16.5078 15.7082 15.7082 12.2712 16.5078 26.5197 17.0714 15.7082 + 12.2712 12.2712 17.0714 17.0714 17.0714 12.2712 11.7696 26.5197 17.0714 11.0268 + 11.7696 11.7696 11.7696 11.0268 11.0268 12.3728 16.5078 16.5078 12 15.7082 + 12.2712 17.0714 26.5197 17.0714 15.7082 12.2712 17.0714 26.5197 17.0714 16.5078 + 6.35236 26.5197 26.5197 26.5197 16.5078 6.35236 11.7696 26.5197 11.377 11.0268 + 12.3728 12.3728 12 12 12 12.3728 17.0714 26.5197 12 16.5078 + 17.0714 17.0714 17.0714 16.5078 16.5078 6.35236 17.0714 26.5197 11.377 16.5078 + 6.35236 6.35236 11.377 11.377 11.377 12.3728 16.5078 26.5197 12 15.7082 + 12.3728 26.5197 26.5197 26.5197 15.7082 12.2712 17.0714 26.5197 17.0714 16.5078 + 12.2712 11.7696 26.5197 11.377 9.04703 6.35236 11.7696 11.377 11.377 9.04703 + 16.5078 16.5078 16.5078 15.7082 15.7082 12.2712 16.5078 26.5197 17.0714 15.7082 + 12.2712 12.2712 17.0714 17.0714 17.0714 12.2712 11.7696 28.5123 17.0714 9.04703 + 11.7696 11.7696 11.7696 9.04703 9.04703 12.8435 16.5078 16.5078 16.2073 15.7082 + 12.8435 21.217 28.5123 17.0714 14.6789 12.2712 21.217 28.5123 17.0714 14.6789 + 5.63662 28.5123 28.5123 28.5123 9.04703 5.63662 11.7696 28.5123 7.99012 9.04703 + 12.8435 12.8435 16.2073 16.2073 16.2073 12.8435 21.217 12.6149 16.2073 14.6789 + 21.217 21.217 21.217 14.6789 14.6789 5.63662 21.217 28.5123 7.99012 14.6789 + 5.63662 5.63662 7.99012 7.99012 7.99012 12.8435 12.6149 12.6149 16.2073 16.2073 + 12.8435 12.6149 12.6149 12.6149 14.6789 21.217 21.217 12.6149 12.6149 14.6789 + 5.63662 21.217 28.5123 7.99012 14.6789 5.63662 5.63662 7.99012 7.99012 7.99012 + + + + + + 0 0.555556 0 0.111111 0.555556 0 0.222222 0.555556 0 + 0.333333 0.555556 0 0.444444 0.555556 0 0 0.666667 0 + 0.111111 0.666667 0 0.222222 0.666667 0 0.333333 0.666667 0 + 0.444444 0.666667 0 0 0.777778 0 0.111111 0.777778 0 + 0.222222 0.777778 0 0.333333 0.777778 0 0.444444 0.777778 0 + 0 0.888889 0 0.111111 0.888889 0 0.222222 0.888889 0 + 0.333333 0.888889 0 0.444444 0.888889 0 0 1 0 + 0.111111 1 0 0.222222 1 0 0.333333 1 0 + 0.444444 1 0 0 0.555556 0.111111 0.111111 0.555556 0.111111 + 0.222222 0.555556 0.111111 0.333333 0.555556 0.111111 0.444444 0.555556 0.111111 + 0 0.666667 0.111111 0.111111 0.666667 0.111111 0.222222 0.666667 0.111111 + 0.333333 0.666667 0.111111 0.444444 0.666667 0.111111 0 0.777778 0.111111 + 0.111111 0.777778 0.111111 0.222222 0.777778 0.111111 0.333333 0.777778 0.111111 + 0.444444 0.777778 0.111111 0 0.888889 0.111111 0.111111 0.888889 0.111111 + 0.222222 0.888889 0.111111 0.333333 0.888889 0.111111 0.444444 0.888889 0.111111 + 0 1 0.111111 0.111111 1 0.111111 0.222222 1 0.111111 + 0.333333 1 0.111111 0.444444 1 0.111111 0 0.555556 0.222222 + 0.111111 0.555556 0.222222 0.222222 0.555556 0.222222 0.333333 0.555556 0.222222 + 0.444444 0.555556 0.222222 0 0.666667 0.222222 0.111111 0.666667 0.222222 + 0.222222 0.666667 0.222222 0.333333 0.666667 0.222222 0.444444 0.666667 0.222222 + 0 0.777778 0.222222 0.111111 0.777778 0.222222 0.222222 0.777778 0.222222 + 0.333333 0.777778 0.222222 0.444444 0.777778 0.222222 0 0.888889 0.222222 + 0.111111 0.888889 0.222222 0.222222 0.888889 0.222222 0.333333 0.888889 0.222222 + 0.444444 0.888889 0.222222 0 1 0.222222 0.111111 1 0.222222 + 0.222222 1 0.222222 0.333333 1 0.222222 0.444444 1 0.222222 + 0 0.555556 0.333333 0.111111 0.555556 0.333333 0.222222 0.555556 0.333333 + 0.333333 0.555556 0.333333 0.444444 0.555556 0.333333 0 0.666667 0.333333 + 0.111111 0.666667 0.333333 0.222222 0.666667 0.333333 0.333333 0.666667 0.333333 + 0.444444 0.666667 0.333333 0 0.777778 0.333333 0.111111 0.777778 0.333333 + 0.222222 0.777778 0.333333 0.333333 0.777778 0.333333 0.444444 0.777778 0.333333 + 0 0.888889 0.333333 0.111111 0.888889 0.333333 0.222222 0.888889 0.333333 + 0.333333 0.888889 0.333333 0.444444 0.888889 0.333333 0 1 0.333333 + 0.111111 1 0.333333 0.222222 1 0.333333 0.333333 1 0.333333 + 0.444444 1 0.333333 0 0.555556 0.444444 0.111111 0.555556 0.444444 + 0.222222 0.555556 0.444444 0.333333 0.555556 0.444444 0.444444 0.555556 0.444444 + 0 0.666667 0.444444 0.111111 0.666667 0.444444 0.222222 0.666667 0.444444 + 0.333333 0.666667 0.444444 0.444444 0.666667 0.444444 0 0.777778 0.444444 + 0.111111 0.777778 0.444444 0.222222 0.777778 0.444444 0.333333 0.777778 0.444444 + 0.444444 0.777778 0.444444 0 0.888889 0.444444 0.111111 0.888889 0.444444 + 0.222222 0.888889 0.444444 0.333333 0.888889 0.444444 0.444444 0.888889 0.444444 + 0 1 0.444444 0.111111 1 0.444444 0.222222 1 0.444444 + 0.333333 1 0.444444 0.444444 1 0.444444 0 0.555556 0.555556 + 0.111111 0.555556 0.555556 0.222222 0.555556 0.555556 0.333333 0.555556 0.555556 + 0.444444 0.555556 0.555556 0 0.666667 0.555556 0.111111 0.666667 0.555556 + 0.222222 0.666667 0.555556 0.333333 0.666667 0.555556 0.444444 0.666667 0.555556 + 0 0.777778 0.555556 0.111111 0.777778 0.555556 0.222222 0.777778 0.555556 + 0.333333 0.777778 0.555556 0.444444 0.777778 0.555556 0 0.888889 0.555556 + 0.111111 0.888889 0.555556 0.222222 0.888889 0.555556 0.333333 0.888889 0.555556 + 0.444444 0.888889 0.555556 0 1 0.555556 0.111111 1 0.555556 + 0.222222 1 0.555556 0.333333 1 0.555556 0.444444 1 0.555556 + 0 0.555556 0.666667 0.111111 0.555556 0.666667 0.222222 0.555556 0.666667 + 0.333333 0.555556 0.666667 0.444444 0.555556 0.666667 0 0.666667 0.666667 + 0.111111 0.666667 0.666667 0.222222 0.666667 0.666667 0.333333 0.666667 0.666667 + 0.444444 0.666667 0.666667 0 0.777778 0.666667 0.111111 0.777778 0.666667 + 0.222222 0.777778 0.666667 0.333333 0.777778 0.666667 0.444444 0.777778 0.666667 + 0 0.888889 0.666667 0.111111 0.888889 0.666667 0.222222 0.888889 0.666667 + 0.333333 0.888889 0.666667 0.444444 0.888889 0.666667 0 1 0.666667 + 0.111111 1 0.666667 0.222222 1 0.666667 0.333333 1 0.666667 + 0.444444 1 0.666667 0 0.555556 0.777778 0.111111 0.555556 0.777778 + 0.222222 0.555556 0.777778 0.333333 0.555556 0.777778 0.444444 0.555556 0.777778 + 0 0.666667 0.777778 0.111111 0.666667 0.777778 0.222222 0.666667 0.777778 + 0.333333 0.666667 0.777778 0.444444 0.666667 0.777778 0 0.777778 0.777778 + 0.111111 0.777778 0.777778 0.222222 0.777778 0.777778 0.333333 0.777778 0.777778 + 0.444444 0.777778 0.777778 0 0.888889 0.777778 0.111111 0.888889 0.777778 + 0.222222 0.888889 0.777778 0.333333 0.888889 0.777778 0.444444 0.888889 0.777778 + 0 1 0.777778 0.111111 1 0.777778 0.222222 1 0.777778 + 0.333333 1 0.777778 0.444444 1 0.777778 0 0.555556 0.888889 + 0.111111 0.555556 0.888889 0.222222 0.555556 0.888889 0.333333 0.555556 0.888889 + 0.444444 0.555556 0.888889 0 0.666667 0.888889 0.111111 0.666667 0.888889 + 0.222222 0.666667 0.888889 0.333333 0.666667 0.888889 0.444444 0.666667 0.888889 + 0 0.777778 0.888889 0.111111 0.777778 0.888889 0.222222 0.777778 0.888889 + 0.333333 0.777778 0.888889 0.444444 0.777778 0.888889 0 0.888889 0.888889 + 0.111111 0.888889 0.888889 0.222222 0.888889 0.888889 0.333333 0.888889 0.888889 + 0.444444 0.888889 0.888889 0 1 0.888889 0.111111 1 0.888889 + 0.222222 1 0.888889 0.333333 1 0.888889 0.444444 1 0.888889 + 0 0.555556 1 0.111111 0.555556 1 0.222222 0.555556 1 + 0.333333 0.555556 1 0.444444 0.555556 1 0 0.666667 1 + 0.111111 0.666667 1 0.222222 0.666667 1 0.333333 0.666667 1 + 0.444444 0.666667 1 0 0.777778 1 0.111111 0.777778 1 + 0.222222 0.777778 1 0.333333 0.777778 1 0.444444 0.777778 1 + 0 0.888889 1 0.111111 0.888889 1 0.222222 0.888889 1 + 0.333333 0.888889 1 0.444444 0.888889 1 0 1 1 + 0.111111 1 1 0.222222 1 1 0.333333 1 1 + 0.444444 1 1 + + + + + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100 101 102 103 104 105 106 107 108 109 + 110 111 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 128 129 + 130 131 132 133 134 135 136 137 138 139 + 140 141 142 143 144 145 146 147 148 149 + 150 151 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 168 169 + 170 171 172 173 174 175 176 177 178 179 + 180 181 182 183 184 185 186 187 188 189 + 190 191 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 208 209 + 210 211 212 213 214 215 216 217 218 219 + 220 221 222 223 224 225 226 227 228 229 + 230 231 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 248 249 + + + + 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 + 81 82 83 84 85 86 87 88 89 90 + 91 92 93 94 95 96 97 98 99 100 + 101 102 103 104 105 106 107 108 109 110 + 111 112 113 114 115 116 117 118 119 120 + 121 122 123 124 125 126 127 128 129 130 + 131 132 133 134 135 136 137 138 139 140 + 141 142 143 144 145 146 147 148 149 150 + 151 152 153 154 155 156 157 158 159 160 + 161 162 163 164 165 166 167 168 169 170 + 171 172 173 174 175 176 177 178 179 180 + 181 182 183 184 185 186 187 188 189 190 + 191 192 193 194 195 196 197 198 199 200 + 201 202 203 204 205 206 207 208 209 210 + 211 212 213 214 215 216 217 218 219 220 + 221 222 223 224 225 226 227 228 229 230 + 231 232 233 234 235 236 237 238 239 240 + 241 242 243 244 245 246 247 248 249 250 + + + + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 + + + + + \ No newline at end of file diff --git a/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc3.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc3.gold new file mode 100644 index 000000000000..50af8a9cf8b6 --- /dev/null +++ b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0-Proc3.gold @@ -0,0 +1,265 @@ + + + + + + + 55 56 57 58 59 65 66 67 68 69 + 75 76 77 78 79 85 86 87 88 89 + 95 96 97 98 99 155 156 157 158 159 + 165 166 167 168 169 175 176 177 178 179 + 185 186 187 188 189 195 196 197 198 199 + 255 256 257 258 259 265 266 267 268 269 + 275 276 277 278 279 285 286 287 288 289 + 295 296 297 298 299 355 356 357 358 359 + 365 366 367 368 369 375 376 377 378 379 + 385 386 387 388 389 395 396 397 398 399 + 455 456 457 458 459 465 466 467 468 469 + 475 476 477 478 479 485 486 487 488 489 + 495 496 497 498 499 555 556 557 558 559 + 565 566 567 568 569 575 576 577 578 579 + 585 586 587 588 589 595 596 597 598 599 + 655 656 657 658 659 665 666 667 668 669 + 675 676 677 678 679 685 686 687 688 689 + 695 696 697 698 699 755 756 757 758 759 + 765 766 767 768 769 775 776 777 778 779 + 785 786 787 788 789 795 796 797 798 799 + 855 856 857 858 859 865 866 867 868 869 + 875 876 877 878 879 885 886 887 888 889 + 895 896 897 898 899 955 956 957 958 959 + 965 966 967 968 969 975 976 977 978 979 + 985 986 987 988 989 995 996 997 998 999 + + + + 105 105 106 106 106 105 107 111 106 108 + 107 107 107 108 108 109 107 107 110 108 + 109 109 110 110 110 105 112 111 106 113 + 105 111 111 111 108 114 107 111 115 108 + 109 116 111 110 117 109 116 110 110 117 + 112 112 112 113 113 114 112 111 115 113 + 114 114 115 115 115 114 116 118 115 117 + 116 116 116 117 117 119 112 112 120 113 + 114 121 118 115 113 114 121 118 115 122 + 123 118 118 118 122 123 116 118 124 117 + 119 119 120 120 120 119 121 125 120 122 + 121 121 121 122 122 123 121 118 124 122 + 123 123 124 124 124 119 126 125 120 127 + 119 125 125 125 127 128 121 125 129 122 + 128 130 125 124 131 123 130 124 124 131 + 126 126 126 127 127 128 126 125 129 127 + 128 128 129 129 129 128 130 132 129 131 + 130 130 130 131 131 133 126 126 134 127 + 133 135 132 129 136 128 135 132 129 136 + 137 132 132 132 131 137 130 132 138 131 + 133 133 134 134 134 133 135 139 134 136 + 135 135 135 136 136 137 135 132 138 136 + 137 137 138 138 138 133 139 139 134 134 + 133 139 139 139 136 135 135 139 139 136 + 137 135 132 138 136 137 137 138 138 138 + + + + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 + + + 9.65407 9.65407 11.4043 11.4043 11.4043 9.65407 12.2712 26.5197 11.4043 6.35236 + 12.2712 12.2712 12.2712 6.35236 6.35236 7.10619 12.2712 12.2712 7.73649 6.35236 + 7.10619 7.10619 7.73649 7.73649 7.73649 9.65407 16.5078 26.5197 11.4043 12.3728 + 9.65407 26.5197 26.5197 26.5197 6.35236 16.5078 12.2712 26.5197 17.0714 6.35236 + 7.10619 11.8886 26.5197 7.73649 6.35236 7.10619 11.8886 7.73649 7.73649 6.35236 + 16.5078 16.5078 16.5078 12.3728 12.3728 16.5078 16.5078 26.5197 17.0714 12.3728 + 16.5078 16.5078 17.0714 17.0714 17.0714 16.5078 11.8886 26.5197 17.0714 6.35236 + 11.8886 11.8886 11.8886 6.35236 6.35236 15.7082 16.5078 16.5078 12 12.3728 + 16.5078 17.0714 26.5197 17.0714 12.3728 16.5078 17.0714 26.5197 17.0714 12.2712 + 11.0268 26.5197 26.5197 26.5197 12.2712 11.0268 11.8886 26.5197 11.3048 6.35236 + 15.7082 15.7082 12 12 12 15.7082 17.0714 26.5197 12 12.2712 + 17.0714 17.0714 17.0714 12.2712 12.2712 11.0268 17.0714 26.5197 11.3048 12.2712 + 11.0268 11.0268 11.3048 11.3048 11.3048 15.7082 16.5078 26.5197 12 12.3728 + 15.7082 26.5197 26.5197 26.5197 12.3728 16.5078 17.0714 26.5197 17.0714 12.2712 + 16.5078 11.8886 26.5197 11.3048 6.37469 11.0268 11.8886 11.3048 11.3048 6.37469 + 16.5078 16.5078 16.5078 12.3728 12.3728 16.5078 16.5078 26.5197 17.0714 12.3728 + 16.5078 16.5078 17.0714 17.0714 17.0714 16.5078 11.8886 28.5123 17.0714 6.37469 + 11.8886 11.8886 11.8886 6.37469 6.37469 14.0596 16.5078 16.5078 15.9512 12.3728 + 14.0596 21.4164 28.5123 17.0714 12.8711 16.5078 21.4164 28.5123 17.0714 12.8711 + 9.59794 28.5123 28.5123 28.5123 6.37469 9.59794 11.8886 28.5123 7.93666 6.37469 + 14.0596 14.0596 15.9512 15.9512 15.9512 14.0596 21.4164 12.6149 15.9512 12.8711 + 21.4164 21.4164 21.4164 12.8711 12.8711 9.59794 21.4164 28.5123 7.93666 12.8711 + 9.59794 9.59794 7.93666 7.93666 7.93666 14.0596 12.6149 12.6149 15.9512 15.9512 + 14.0596 12.6149 12.6149 12.6149 12.8711 21.4164 21.4164 12.6149 12.6149 12.8711 + 9.59794 21.4164 28.5123 7.93666 12.8711 9.59794 9.59794 7.93666 7.93666 7.93666 + + + + + + 0.555556 0.555556 0 0.666667 0.555556 0 0.777778 0.555556 0 + 0.888889 0.555556 0 1 0.555556 0 0.555556 0.666667 0 + 0.666667 0.666667 0 0.777778 0.666667 0 0.888889 0.666667 0 + 1 0.666667 0 0.555556 0.777778 0 0.666667 0.777778 0 + 0.777778 0.777778 0 0.888889 0.777778 0 1 0.777778 0 + 0.555556 0.888889 0 0.666667 0.888889 0 0.777778 0.888889 0 + 0.888889 0.888889 0 1 0.888889 0 0.555556 1 0 + 0.666667 1 0 0.777778 1 0 0.888889 1 0 + 1 1 0 0.555556 0.555556 0.111111 0.666667 0.555556 0.111111 + 0.777778 0.555556 0.111111 0.888889 0.555556 0.111111 1 0.555556 0.111111 + 0.555556 0.666667 0.111111 0.666667 0.666667 0.111111 0.777778 0.666667 0.111111 + 0.888889 0.666667 0.111111 1 0.666667 0.111111 0.555556 0.777778 0.111111 + 0.666667 0.777778 0.111111 0.777778 0.777778 0.111111 0.888889 0.777778 0.111111 + 1 0.777778 0.111111 0.555556 0.888889 0.111111 0.666667 0.888889 0.111111 + 0.777778 0.888889 0.111111 0.888889 0.888889 0.111111 1 0.888889 0.111111 + 0.555556 1 0.111111 0.666667 1 0.111111 0.777778 1 0.111111 + 0.888889 1 0.111111 1 1 0.111111 0.555556 0.555556 0.222222 + 0.666667 0.555556 0.222222 0.777778 0.555556 0.222222 0.888889 0.555556 0.222222 + 1 0.555556 0.222222 0.555556 0.666667 0.222222 0.666667 0.666667 0.222222 + 0.777778 0.666667 0.222222 0.888889 0.666667 0.222222 1 0.666667 0.222222 + 0.555556 0.777778 0.222222 0.666667 0.777778 0.222222 0.777778 0.777778 0.222222 + 0.888889 0.777778 0.222222 1 0.777778 0.222222 0.555556 0.888889 0.222222 + 0.666667 0.888889 0.222222 0.777778 0.888889 0.222222 0.888889 0.888889 0.222222 + 1 0.888889 0.222222 0.555556 1 0.222222 0.666667 1 0.222222 + 0.777778 1 0.222222 0.888889 1 0.222222 1 1 0.222222 + 0.555556 0.555556 0.333333 0.666667 0.555556 0.333333 0.777778 0.555556 0.333333 + 0.888889 0.555556 0.333333 1 0.555556 0.333333 0.555556 0.666667 0.333333 + 0.666667 0.666667 0.333333 0.777778 0.666667 0.333333 0.888889 0.666667 0.333333 + 1 0.666667 0.333333 0.555556 0.777778 0.333333 0.666667 0.777778 0.333333 + 0.777778 0.777778 0.333333 0.888889 0.777778 0.333333 1 0.777778 0.333333 + 0.555556 0.888889 0.333333 0.666667 0.888889 0.333333 0.777778 0.888889 0.333333 + 0.888889 0.888889 0.333333 1 0.888889 0.333333 0.555556 1 0.333333 + 0.666667 1 0.333333 0.777778 1 0.333333 0.888889 1 0.333333 + 1 1 0.333333 0.555556 0.555556 0.444444 0.666667 0.555556 0.444444 + 0.777778 0.555556 0.444444 0.888889 0.555556 0.444444 1 0.555556 0.444444 + 0.555556 0.666667 0.444444 0.666667 0.666667 0.444444 0.777778 0.666667 0.444444 + 0.888889 0.666667 0.444444 1 0.666667 0.444444 0.555556 0.777778 0.444444 + 0.666667 0.777778 0.444444 0.777778 0.777778 0.444444 0.888889 0.777778 0.444444 + 1 0.777778 0.444444 0.555556 0.888889 0.444444 0.666667 0.888889 0.444444 + 0.777778 0.888889 0.444444 0.888889 0.888889 0.444444 1 0.888889 0.444444 + 0.555556 1 0.444444 0.666667 1 0.444444 0.777778 1 0.444444 + 0.888889 1 0.444444 1 1 0.444444 0.555556 0.555556 0.555556 + 0.666667 0.555556 0.555556 0.777778 0.555556 0.555556 0.888889 0.555556 0.555556 + 1 0.555556 0.555556 0.555556 0.666667 0.555556 0.666667 0.666667 0.555556 + 0.777778 0.666667 0.555556 0.888889 0.666667 0.555556 1 0.666667 0.555556 + 0.555556 0.777778 0.555556 0.666667 0.777778 0.555556 0.777778 0.777778 0.555556 + 0.888889 0.777778 0.555556 1 0.777778 0.555556 0.555556 0.888889 0.555556 + 0.666667 0.888889 0.555556 0.777778 0.888889 0.555556 0.888889 0.888889 0.555556 + 1 0.888889 0.555556 0.555556 1 0.555556 0.666667 1 0.555556 + 0.777778 1 0.555556 0.888889 1 0.555556 1 1 0.555556 + 0.555556 0.555556 0.666667 0.666667 0.555556 0.666667 0.777778 0.555556 0.666667 + 0.888889 0.555556 0.666667 1 0.555556 0.666667 0.555556 0.666667 0.666667 + 0.666667 0.666667 0.666667 0.777778 0.666667 0.666667 0.888889 0.666667 0.666667 + 1 0.666667 0.666667 0.555556 0.777778 0.666667 0.666667 0.777778 0.666667 + 0.777778 0.777778 0.666667 0.888889 0.777778 0.666667 1 0.777778 0.666667 + 0.555556 0.888889 0.666667 0.666667 0.888889 0.666667 0.777778 0.888889 0.666667 + 0.888889 0.888889 0.666667 1 0.888889 0.666667 0.555556 1 0.666667 + 0.666667 1 0.666667 0.777778 1 0.666667 0.888889 1 0.666667 + 1 1 0.666667 0.555556 0.555556 0.777778 0.666667 0.555556 0.777778 + 0.777778 0.555556 0.777778 0.888889 0.555556 0.777778 1 0.555556 0.777778 + 0.555556 0.666667 0.777778 0.666667 0.666667 0.777778 0.777778 0.666667 0.777778 + 0.888889 0.666667 0.777778 1 0.666667 0.777778 0.555556 0.777778 0.777778 + 0.666667 0.777778 0.777778 0.777778 0.777778 0.777778 0.888889 0.777778 0.777778 + 1 0.777778 0.777778 0.555556 0.888889 0.777778 0.666667 0.888889 0.777778 + 0.777778 0.888889 0.777778 0.888889 0.888889 0.777778 1 0.888889 0.777778 + 0.555556 1 0.777778 0.666667 1 0.777778 0.777778 1 0.777778 + 0.888889 1 0.777778 1 1 0.777778 0.555556 0.555556 0.888889 + 0.666667 0.555556 0.888889 0.777778 0.555556 0.888889 0.888889 0.555556 0.888889 + 1 0.555556 0.888889 0.555556 0.666667 0.888889 0.666667 0.666667 0.888889 + 0.777778 0.666667 0.888889 0.888889 0.666667 0.888889 1 0.666667 0.888889 + 0.555556 0.777778 0.888889 0.666667 0.777778 0.888889 0.777778 0.777778 0.888889 + 0.888889 0.777778 0.888889 1 0.777778 0.888889 0.555556 0.888889 0.888889 + 0.666667 0.888889 0.888889 0.777778 0.888889 0.888889 0.888889 0.888889 0.888889 + 1 0.888889 0.888889 0.555556 1 0.888889 0.666667 1 0.888889 + 0.777778 1 0.888889 0.888889 1 0.888889 1 1 0.888889 + 0.555556 0.555556 1 0.666667 0.555556 1 0.777778 0.555556 1 + 0.888889 0.555556 1 1 0.555556 1 0.555556 0.666667 1 + 0.666667 0.666667 1 0.777778 0.666667 1 0.888889 0.666667 1 + 1 0.666667 1 0.555556 0.777778 1 0.666667 0.777778 1 + 0.777778 0.777778 1 0.888889 0.777778 1 1 0.777778 1 + 0.555556 0.888889 1 0.666667 0.888889 1 0.777778 0.888889 1 + 0.888889 0.888889 1 1 0.888889 1 0.555556 1 1 + 0.666667 1 1 0.777778 1 1 0.888889 1 1 + 1 1 1 + + + + + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100 101 102 103 104 105 106 107 108 109 + 110 111 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 128 129 + 130 131 132 133 134 135 136 137 138 139 + 140 141 142 143 144 145 146 147 148 149 + 150 151 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 168 169 + 170 171 172 173 174 175 176 177 178 179 + 180 181 182 183 184 185 186 187 188 189 + 190 191 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 208 209 + 210 211 212 213 214 215 216 217 218 219 + 220 221 222 223 224 225 226 227 228 229 + 230 231 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 248 249 + + + + 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 + 81 82 83 84 85 86 87 88 89 90 + 91 92 93 94 95 96 97 98 99 100 + 101 102 103 104 105 106 107 108 109 110 + 111 112 113 114 115 116 117 118 119 120 + 121 122 123 124 125 126 127 128 129 130 + 131 132 133 134 135 136 137 138 139 140 + 141 142 143 144 145 146 147 148 149 150 + 151 152 153 154 155 156 157 158 159 160 + 161 162 163 164 165 166 167 168 169 170 + 171 172 173 174 175 176 177 178 179 180 + 181 182 183 184 185 186 187 188 189 190 + 191 192 193 194 195 196 197 198 199 200 + 201 202 203 204 205 206 207 208 209 210 + 211 212 213 214 215 216 217 218 219 220 + 221 222 223 224 225 226 227 228 229 230 + 231 232 233 234 235 236 237 238 239 240 + 241 242 243 244 245 246 247 248 249 250 + + + + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 + + + + + \ No newline at end of file diff --git a/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0.gold new file mode 100644 index 000000000000..08e530c1a54b --- /dev/null +++ b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-AggregateQuality-Level0.gold @@ -0,0 +1,953 @@ + + + + + + + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100 101 102 103 104 105 106 107 108 109 + 110 111 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 128 129 + 130 131 132 133 134 135 136 137 138 139 + 140 141 142 143 144 145 146 147 148 149 + 150 151 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 168 169 + 170 171 172 173 174 175 176 177 178 179 + 180 181 182 183 184 185 186 187 188 189 + 190 191 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 208 209 + 210 211 212 213 214 215 216 217 218 219 + 220 221 222 223 224 225 226 227 228 229 + 230 231 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 248 249 + 250 251 252 253 254 255 256 257 258 259 + 260 261 262 263 264 265 266 267 268 269 + 270 271 272 273 274 275 276 277 278 279 + 280 281 282 283 284 285 286 287 288 289 + 290 291 292 293 294 295 296 297 298 299 + 300 301 302 303 304 305 306 307 308 309 + 310 311 312 313 314 315 316 317 318 319 + 320 321 322 323 324 325 326 327 328 329 + 330 331 332 333 334 335 336 337 338 339 + 340 341 342 343 344 345 346 347 348 349 + 350 351 352 353 354 355 356 357 358 359 + 360 361 362 363 364 365 366 367 368 369 + 370 371 372 373 374 375 376 377 378 379 + 380 381 382 383 384 385 386 387 388 389 + 390 391 392 393 394 395 396 397 398 399 + 400 401 402 403 404 405 406 407 408 409 + 410 411 412 413 414 415 416 417 418 419 + 420 421 422 423 424 425 426 427 428 429 + 430 431 432 433 434 435 436 437 438 439 + 440 441 442 443 444 445 446 447 448 449 + 450 451 452 453 454 455 456 457 458 459 + 460 461 462 463 464 465 466 467 468 469 + 470 471 472 473 474 475 476 477 478 479 + 480 481 482 483 484 485 486 487 488 489 + 490 491 492 493 494 495 496 497 498 499 + 500 501 502 503 504 505 506 507 508 509 + 510 511 512 513 514 515 516 517 518 519 + 520 521 522 523 524 525 526 527 528 529 + 530 531 532 533 534 535 536 537 538 539 + 540 541 542 543 544 545 546 547 548 549 + 550 551 552 553 554 555 556 557 558 559 + 560 561 562 563 564 565 566 567 568 569 + 570 571 572 573 574 575 576 577 578 579 + 580 581 582 583 584 585 586 587 588 589 + 590 591 592 593 594 595 596 597 598 599 + 600 601 602 603 604 605 606 607 608 609 + 610 611 612 613 614 615 616 617 618 619 + 620 621 622 623 624 625 626 627 628 629 + 630 631 632 633 634 635 636 637 638 639 + 640 641 642 643 644 645 646 647 648 649 + 650 651 652 653 654 655 656 657 658 659 + 660 661 662 663 664 665 666 667 668 669 + 670 671 672 673 674 675 676 677 678 679 + 680 681 682 683 684 685 686 687 688 689 + 690 691 692 693 694 695 696 697 698 699 + 700 701 702 703 704 705 706 707 708 709 + 710 711 712 713 714 715 716 717 718 719 + 720 721 722 723 724 725 726 727 728 729 + 730 731 732 733 734 735 736 737 738 739 + 740 741 742 743 744 745 746 747 748 749 + 750 751 752 753 754 755 756 757 758 759 + 760 761 762 763 764 765 766 767 768 769 + 770 771 772 773 774 775 776 777 778 779 + 780 781 782 783 784 785 786 787 788 789 + 790 791 792 793 794 795 796 797 798 799 + 800 801 802 803 804 805 806 807 808 809 + 810 811 812 813 814 815 816 817 818 819 + 820 821 822 823 824 825 826 827 828 829 + 830 831 832 833 834 835 836 837 838 839 + 840 841 842 843 844 845 846 847 848 849 + 850 851 852 853 854 855 856 857 858 859 + 860 861 862 863 864 865 866 867 868 869 + 870 871 872 873 874 875 876 877 878 879 + 880 881 882 883 884 885 886 887 888 889 + 890 891 892 893 894 895 896 897 898 899 + 900 901 902 903 904 905 906 907 908 909 + 910 911 912 913 914 915 916 917 918 919 + 920 921 922 923 924 925 926 927 928 929 + 930 931 932 933 934 935 936 937 938 939 + 940 941 942 943 944 945 946 947 948 949 + 950 951 952 953 954 955 956 957 958 959 + 960 961 962 963 964 965 966 967 968 969 + 970 971 972 973 974 975 976 977 978 979 + 980 981 982 983 984 985 986 987 988 989 + 990 991 992 993 994 995 996 997 998 999 + + + + 0 0 1 1 1 2 2 2 3 3 + 0 4 20 1 5 21 2 6 22 3 + 4 4 4 5 5 5 6 6 6 7 + 8 4 4 9 5 5 10 6 7 7 + 8 8 9 9 9 10 10 10 11 7 + 8 12 23 9 13 24 10 11 11 11 + 12 12 12 13 13 13 14 25 11 15 + 16 12 12 17 13 14 14 14 15 15 + 16 16 17 17 17 18 14 14 19 15 + 16 26 17 17 18 18 18 19 19 19 + 0 27 20 1 28 21 2 29 22 3 + 0 20 20 20 21 21 21 22 22 22 + 30 4 20 31 5 21 32 6 22 33 + 8 34 20 9 35 21 10 6 7 7 + 8 34 23 9 35 24 10 36 11 37 + 38 23 23 23 24 24 24 25 11 37 + 38 12 23 39 13 24 25 25 25 15 + 16 12 42 39 13 40 14 25 41 15 + 16 26 42 17 43 18 14 44 19 15 + 26 26 26 17 43 18 18 44 19 19 + 27 27 27 28 28 28 29 29 29 45 + 30 27 20 31 28 21 32 29 22 33 + 30 30 31 31 31 32 32 32 33 33 + 30 34 46 31 35 47 32 36 48 33 + 34 34 34 35 35 35 36 36 36 37 + 38 34 23 39 35 24 49 36 37 37 + 38 38 39 39 39 40 25 25 41 37 + 38 50 42 39 40 40 40 41 41 41 + 53 42 42 42 43 40 51 44 41 52 + 53 26 42 43 43 43 44 44 44 52 + 54 27 27 55 28 28 56 29 45 45 + 30 58 46 31 59 47 32 29 57 45 + 30 58 46 31 59 47 32 48 48 33 + 60 46 46 46 47 47 47 48 48 48 + 60 34 46 61 35 47 49 36 48 62 + 38 34 63 61 35 49 49 49 65 37 + 38 50 63 39 64 64 49 49 65 37 + 50 50 50 66 40 40 51 41 41 52 + 53 50 42 66 43 51 51 51 52 52 + 53 53 42 66 43 67 51 44 68 52 + 54 54 55 55 55 56 56 56 57 45 + 54 58 69 55 59 70 56 57 57 57 + 58 58 58 59 59 59 71 71 57 57 + 60 58 46 61 59 47 47 48 48 62 + 60 60 61 61 61 72 72 74 62 62 + 60 73 63 61 61 64 49 74 65 62 + 75 63 63 63 64 64 64 65 65 65 + 75 50 63 66 76 64 51 78 65 77 + 53 50 66 66 66 67 51 78 68 52 + 53 79 79 66 67 67 67 68 68 68 + 54 80 69 55 81 70 56 82 82 83 + 54 69 69 69 70 70 70 71 57 83 + 84 58 69 85 59 70 71 71 71 83 + 84 58 87 85 59 72 86 71 88 62 + 60 73 87 61 72 72 72 74 88 62 + 73 73 73 89 89 72 74 74 74 62 + 75 73 63 76 76 64 90 74 65 77 + 75 75 91 76 76 76 90 78 77 77 + 75 79 91 66 76 92 78 78 78 77 + 79 79 79 93 67 67 67 78 68 94 + 80 80 80 81 81 81 82 82 82 83 + 84 80 69 85 81 70 95 82 83 83 + 84 84 85 85 85 70 86 71 96 83 + 84 97 87 85 98 86 86 86 88 88 + 99 87 87 87 89 72 86 88 88 88 + 99 73 87 89 89 89 90 74 88 100 + 75 73 91 101 89 90 90 90 114 77 + 75 91 91 91 76 92 90 102 102 77 + 103 103 91 93 92 92 92 78 94 94 + 79 79 93 93 93 92 104 104 94 94 + 105 80 80 106 81 81 95 82 107 107 + 105 80 108 106 81 95 95 95 96 83 + 84 97 108 85 98 109 95 96 96 96 + 97 97 97 98 98 98 86 110 96 96 + 99 97 87 111 98 98 86 110 88 100 + 99 99 101 101 89 112 112 100 100 100 + 99 113 101 101 101 90 90 102 114 100 + 103 113 91 101 115 92 102 102 102 117 + 103 103 116 93 115 92 104 102 102 117 + 103 103 116 93 93 104 104 104 94 94 + 105 105 106 106 106 118 95 107 107 107 + 105 119 108 106 109 109 95 120 107 121 + 122 108 108 108 109 109 109 110 96 121 + 122 97 108 111 98 109 110 110 110 121 + 99 97 111 111 111 112 123 110 110 100 + 99 113 124 111 112 112 112 114 114 100 + 113 113 113 101 115 112 126 114 114 114 + 125 113 116 115 115 115 126 102 114 117 + 103 116 116 116 115 115 104 129 117 117 + 127 127 116 128 128 128 104 129 117 117 + 105 119 119 106 118 118 118 120 107 107 + 119 119 119 106 118 118 120 120 120 121 + 122 119 108 108 109 109 120 120 121 121 + 122 122 108 111 98 123 123 110 110 121 + 122 124 124 111 111 123 123 123 110 121 + 125 124 124 124 112 112 123 123 114 100 + 125 113 124 124 115 126 126 126 114 114 + 125 125 116 115 115 126 126 126 114 117 + 125 127 116 116 128 128 126 129 129 117 + 127 127 127 128 128 128 129 129 129 117 + + + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + + 4.71117 4.71117 6 6 6 6 6 6 4 4 + 4.71117 12.2679 26.5197 6 12.2712 26.5197 6 11.8886 12 4 + 12.2679 12.2679 12.2679 12.2712 12.2712 12.2712 11.8886 11.8886 11.8886 8.08168 + 6.35236 12.2679 12.2679 11.8886 12.2712 12.2712 11.8886 11.8886 8.08168 8.08168 + 6.35236 6.35236 11.8886 11.8886 11.8886 11.8886 11.8886 11.8886 11.7696 8.08168 + 6.35236 11.3048 12 11.8886 11.8886 12 11.8886 11.7696 11.7696 11.7696 + 11.3048 11.3048 11.3048 11.8886 11.8886 11.8886 11.377 17.0714 11.7696 6.37469 + 6.34127 11.3048 11.3048 7.93153 11.8886 11.377 11.377 11.377 6.37469 6.37469 + 6.34127 6.34127 7.93153 7.93153 7.93153 7.81935 11.377 11.377 7.70682 6.37469 + 6.34127 11.5945 7.93153 7.93153 7.81935 7.81935 7.81935 7.70682 7.70682 7.70682 + 4.71117 12.2679 26.5197 6 12.2712 26.5197 6 11.8886 12 4 + 4.71117 26.5197 26.5197 26.5197 26.5197 26.5197 26.5197 12 12 12 + 12.2712 12.2679 26.5197 17.0714 12.2712 26.5197 17.0714 11.8886 12 11.6108 + 6.35236 20.4853 26.5197 11.8886 20.4853 26.5197 11.8886 11.8886 8.08168 8.08168 + 6.35236 20.4853 12 11.8886 20.4853 12 11.8886 12 11.7696 12.6149 + 12.6881 12 12 12 12 12 12 17.0714 11.7696 12.6149 + 12.6881 11.3048 12 17.0714 11.8886 12 17.0714 17.0714 17.0714 6.37469 + 6.34127 11.3048 20.2353 17.0714 11.8886 17.0714 11.377 17.0714 17.0714 6.37469 + 6.34127 11.5945 20.2353 7.93153 10.3627 7.81935 11.377 11.8886 7.70682 6.37469 + 11.5945 11.5945 11.5945 7.93153 10.3627 7.81935 7.81935 11.8886 7.70682 7.70682 + 12.2679 12.2679 12.2679 12.2712 12.2712 12.2712 11.8886 11.8886 11.8886 6 + 12.2712 12.2679 26.5197 17.0714 12.2712 26.5197 17.0714 11.8886 12 11.6108 + 12.2712 12.2712 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 11.6108 11.6108 + 12.2712 20.4853 26.5197 17.0714 20.4853 28.2698 17.0714 12 16.5294 11.6108 + 20.4853 20.4853 20.4853 20.4853 20.4853 20.4853 12 12 12 12.6149 + 12.6881 20.4853 12 17.0714 20.4853 12 17.0714 12 12.6149 12.6149 + 12.6881 12.6881 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 12.6149 + 12.6881 17.0714 20.2353 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 + 6.37469 20.2353 20.2353 20.2353 10.3627 17.0714 17.0714 11.8886 17.0714 12.1555 + 6.37469 11.5945 20.2353 10.3627 10.3627 10.3627 11.8886 11.8886 11.8886 12.1555 + 6.35236 12.2679 12.2679 11.6108 12.2712 12.2712 11.6108 11.8886 6 6 + 12.2712 20.4853 26.5197 17.0714 20.4853 28.2698 17.0714 11.8886 14.5568 6 + 12.2712 20.4853 26.5197 17.0714 20.4853 28.2698 17.0714 16.5294 16.5294 11.6108 + 12.2712 26.5197 26.5197 26.5197 28.2698 28.2698 28.2698 16.5294 16.5294 16.5294 + 12.2712 20.4853 26.5197 16.5294 20.4853 28.2698 17.0714 12 16.5294 12.6881 + 12.6881 20.4853 17.0714 16.5294 20.4853 17.0714 17.0714 17.0714 17.0714 12.6149 + 12.6881 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 12.6149 + 17.0714 17.0714 17.0714 16.3034 17.0714 17.0714 17.0714 17.0714 17.0714 12.1555 + 6.37469 17.0714 20.2353 16.3034 10.3627 17.0714 17.0714 17.0714 12.1555 12.1555 + 6.37469 6.37469 20.2353 16.3034 10.3627 12.6881 17.0714 11.8886 11.6029 12.1555 + 6.35236 6.35236 11.6108 11.6108 11.6108 11.6108 11.6108 11.6108 14.5568 6 + 6.35236 20.4853 12 11.6108 20.4853 17.0714 11.6108 14.5568 14.5568 14.5568 + 20.4853 20.4853 20.4853 20.4853 20.4853 20.4853 17.0714 17.0714 14.5568 14.5568 + 12.2712 20.4853 26.5197 16.5294 20.4853 28.2698 28.2698 16.5294 16.5294 12.6881 + 12.2712 12.2712 16.5294 16.5294 16.5294 17.0714 17.0714 17.0714 12.6881 12.6881 + 12.2712 17.0714 17.0714 16.5294 16.5294 17.0714 17.0714 17.0714 17.0714 12.6881 + 12.6881 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 + 12.6881 17.0714 17.0714 16.3034 17.0714 17.0714 17.0714 17.0714 17.0714 12.2712 + 6.37469 17.0714 16.3034 16.3034 16.3034 12.6881 17.0714 17.0714 11.6029 12.1555 + 6.37469 12.5778 12.5778 16.3034 12.6881 12.6881 12.6881 11.6029 11.6029 11.6029 + 6.35236 11.3048 12 11.6108 11.377 17.0714 11.6108 12.2712 12.2712 12.6294 + 6.35236 12 12 12 17.0714 17.0714 17.0714 17.0714 14.5568 12.6294 + 12.2712 20.4853 12 17.0714 20.4853 17.0714 17.0714 17.0714 17.0714 12.6294 + 12.2712 20.4853 17.0714 17.0714 20.4853 17.0714 17.0714 17.0714 16.3034 12.6881 + 12.2712 17.0714 17.0714 16.5294 17.0714 17.0714 17.0714 17.0714 16.3034 12.6881 + 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 12.6881 + 12.6881 17.0714 17.0714 17.0714 17.0714 17.0714 20.4853 17.0714 17.0714 12.2712 + 12.6881 12.6881 17.0714 17.0714 17.0714 17.0714 20.4853 17.0714 12.2712 12.2712 + 12.6881 12.5778 17.0714 16.3034 17.0714 17.0714 17.0714 17.0714 17.0714 12.2712 + 12.5778 12.5778 12.5778 11.377 12.6881 12.6881 12.6881 17.0714 11.6029 7.81935 + 11.3048 11.3048 11.3048 11.377 11.377 11.377 12.2712 12.2712 12.2712 12.6294 + 12.2712 11.3048 12 17.0714 11.377 17.0714 16.7407 12.2712 12.6294 12.6294 + 12.2712 12.2712 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 16.7407 12.6294 + 12.2712 17.0714 17.0714 17.0714 28.2698 17.0714 17.0714 17.0714 16.3034 16.3034 + 12.6881 17.0714 17.0714 17.0714 17.0714 17.0714 17.0714 16.3034 16.3034 16.3034 + 12.6881 17.0714 17.0714 17.0714 17.0714 17.0714 20.4853 17.0714 16.3034 27.9796 + 12.6881 17.0714 17.0714 17.0714 17.0714 20.4853 20.4853 20.4853 30.2733 12.2712 + 12.6881 17.0714 17.0714 17.0714 17.0714 17.0714 20.4853 16.5294 16.5294 12.2712 + 9.53799 9.53799 17.0714 11.377 17.0714 17.0714 17.0714 17.0714 7.81935 7.81935 + 12.5778 12.5778 11.377 11.377 11.377 17.0714 13.2172 13.2172 7.81935 7.81935 + 6.34127 11.3048 11.3048 9.53799 11.377 11.377 16.7407 12.2712 12.5415 12.5415 + 6.34127 11.3048 21.4164 9.53799 11.377 16.7407 16.7407 16.7407 16.7407 12.6294 + 12.2712 17.0714 21.4164 17.0714 28.2698 16.3034 16.7407 16.7407 16.7407 16.7407 + 17.0714 17.0714 17.0714 28.2698 28.2698 28.2698 17.0714 17.686 16.7407 16.7407 + 12.6881 17.0714 17.0714 16.423 28.2698 28.2698 17.0714 17.686 16.3034 27.9796 + 12.6881 12.6881 17.0714 17.0714 17.0714 20.2353 20.2353 27.9796 27.9796 27.9796 + 12.6881 17.0714 17.0714 17.0714 17.0714 20.4853 20.4853 16.5294 30.2733 27.9796 + 9.53799 17.0714 17.0714 17.0714 23.0102 17.0714 16.5294 16.5294 16.5294 8.71109 + 9.53799 9.53799 13.2233 11.377 23.0102 17.0714 13.2172 16.5294 16.5294 8.71109 + 9.53799 9.53799 13.2233 11.377 11.377 13.2172 13.2172 13.2172 7.81935 7.81935 + 6.34127 6.34127 9.53799 9.53799 9.53799 6.35236 16.7407 12.5415 12.5415 12.5415 + 6.34127 12.1544 21.4164 9.53799 16.3034 16.3034 16.7407 12.2679 12.5415 6.38316 + 6.35236 21.4164 21.4164 21.4164 16.3034 16.3034 16.3034 17.686 16.7407 6.38316 + 6.35236 17.0714 21.4164 16.423 28.2698 16.3034 17.686 17.686 17.686 6.38316 + 12.6881 17.0714 16.423 16.423 16.423 20.2353 12.6149 17.686 17.686 27.9796 + 12.6881 17.0714 12.6149 16.423 20.2353 20.2353 20.2353 30.2733 30.2733 27.9796 + 17.0714 17.0714 17.0714 17.0714 23.0102 20.2353 11.3242 30.2733 30.2733 30.2733 + 6 17.0714 13.2233 23.0102 23.0102 23.0102 11.3242 16.5294 30.2733 8.71109 + 9.53799 13.2233 13.2233 13.2233 23.0102 23.0102 13.2172 7.81935 8.71109 8.71109 + 5.92419 5.92419 13.2233 6.37429 6.37429 6.37429 13.2172 7.81935 8.71109 8.71109 + 6.34127 12.1544 12.1544 9.53799 6.35236 6.35236 6.35236 12.2679 12.5415 12.5415 + 12.1544 12.1544 12.1544 9.53799 6.35236 6.35236 12.2679 12.2679 12.2679 6.38316 + 6.35236 12.1544 21.4164 21.4164 16.3034 16.3034 12.2679 12.2679 6.38316 6.38316 + 6.35236 6.35236 21.4164 16.423 28.2698 12.6149 12.6149 17.686 17.686 6.38316 + 6.35236 12.6149 12.6149 16.423 16.423 12.6149 12.6149 12.6149 17.686 6.38316 + 6 12.6149 12.6149 12.6149 20.2353 20.2353 12.6149 12.6149 30.2733 27.9796 + 6 17.0714 12.6149 12.6149 23.0102 11.3242 11.3242 11.3242 30.2733 30.2733 + 6 6 13.2233 23.0102 23.0102 11.3242 11.3242 11.3242 30.2733 8.71109 + 6 5.92419 13.2233 13.2233 6.37429 6.37429 11.3242 7.81935 7.81935 8.71109 + 5.92419 5.92419 5.92419 6.37429 6.37429 6.37429 7.81935 7.81935 7.81935 8.71109 + + + + + + 0 0 0 0.111111 0 0 0.222222 0 0 + 0.333333 0 0 0.444444 0 0 0.555556 0 0 + 0.666667 0 0 0.777778 0 0 0.888889 0 0 + 1 0 0 0 0.111111 0 0.111111 0.111111 0 + 0.222222 0.111111 0 0.333333 0.111111 0 0.444444 0.111111 0 + 0.555556 0.111111 0 0.666667 0.111111 0 0.777778 0.111111 0 + 0.888889 0.111111 0 1 0.111111 0 0 0.222222 0 + 0.111111 0.222222 0 0.222222 0.222222 0 0.333333 0.222222 0 + 0.444444 0.222222 0 0.555556 0.222222 0 0.666667 0.222222 0 + 0.777778 0.222222 0 0.888889 0.222222 0 1 0.222222 0 + 0 0.333333 0 0.111111 0.333333 0 0.222222 0.333333 0 + 0.333333 0.333333 0 0.444444 0.333333 0 0.555556 0.333333 0 + 0.666667 0.333333 0 0.777778 0.333333 0 0.888889 0.333333 0 + 1 0.333333 0 0 0.444444 0 0.111111 0.444444 0 + 0.222222 0.444444 0 0.333333 0.444444 0 0.444444 0.444444 0 + 0.555556 0.444444 0 0.666667 0.444444 0 0.777778 0.444444 0 + 0.888889 0.444444 0 1 0.444444 0 0 0.555556 0 + 0.111111 0.555556 0 0.222222 0.555556 0 0.333333 0.555556 0 + 0.444444 0.555556 0 0.555556 0.555556 0 0.666667 0.555556 0 + 0.777778 0.555556 0 0.888889 0.555556 0 1 0.555556 0 + 0 0.666667 0 0.111111 0.666667 0 0.222222 0.666667 0 + 0.333333 0.666667 0 0.444444 0.666667 0 0.555556 0.666667 0 + 0.666667 0.666667 0 0.777778 0.666667 0 0.888889 0.666667 0 + 1 0.666667 0 0 0.777778 0 0.111111 0.777778 0 + 0.222222 0.777778 0 0.333333 0.777778 0 0.444444 0.777778 0 + 0.555556 0.777778 0 0.666667 0.777778 0 0.777778 0.777778 0 + 0.888889 0.777778 0 1 0.777778 0 0 0.888889 0 + 0.111111 0.888889 0 0.222222 0.888889 0 0.333333 0.888889 0 + 0.444444 0.888889 0 0.555556 0.888889 0 0.666667 0.888889 0 + 0.777778 0.888889 0 0.888889 0.888889 0 1 0.888889 0 + 0 1 0 0.111111 1 0 0.222222 1 0 + 0.333333 1 0 0.444444 1 0 0.555556 1 0 + 0.666667 1 0 0.777778 1 0 0.888889 1 0 + 1 1 0 0 0 0.111111 0.111111 0 0.111111 + 0.222222 0 0.111111 0.333333 0 0.111111 0.444444 0 0.111111 + 0.555556 0 0.111111 0.666667 0 0.111111 0.777778 0 0.111111 + 0.888889 0 0.111111 1 0 0.111111 0 0.111111 0.111111 + 0.111111 0.111111 0.111111 0.222222 0.111111 0.111111 0.333333 0.111111 0.111111 + 0.444444 0.111111 0.111111 0.555556 0.111111 0.111111 0.666667 0.111111 0.111111 + 0.777778 0.111111 0.111111 0.888889 0.111111 0.111111 1 0.111111 0.111111 + 0 0.222222 0.111111 0.111111 0.222222 0.111111 0.222222 0.222222 0.111111 + 0.333333 0.222222 0.111111 0.444444 0.222222 0.111111 0.555556 0.222222 0.111111 + 0.666667 0.222222 0.111111 0.777778 0.222222 0.111111 0.888889 0.222222 0.111111 + 1 0.222222 0.111111 0 0.333333 0.111111 0.111111 0.333333 0.111111 + 0.222222 0.333333 0.111111 0.333333 0.333333 0.111111 0.444444 0.333333 0.111111 + 0.555556 0.333333 0.111111 0.666667 0.333333 0.111111 0.777778 0.333333 0.111111 + 0.888889 0.333333 0.111111 1 0.333333 0.111111 0 0.444444 0.111111 + 0.111111 0.444444 0.111111 0.222222 0.444444 0.111111 0.333333 0.444444 0.111111 + 0.444444 0.444444 0.111111 0.555556 0.444444 0.111111 0.666667 0.444444 0.111111 + 0.777778 0.444444 0.111111 0.888889 0.444444 0.111111 1 0.444444 0.111111 + 0 0.555556 0.111111 0.111111 0.555556 0.111111 0.222222 0.555556 0.111111 + 0.333333 0.555556 0.111111 0.444444 0.555556 0.111111 0.555556 0.555556 0.111111 + 0.666667 0.555556 0.111111 0.777778 0.555556 0.111111 0.888889 0.555556 0.111111 + 1 0.555556 0.111111 0 0.666667 0.111111 0.111111 0.666667 0.111111 + 0.222222 0.666667 0.111111 0.333333 0.666667 0.111111 0.444444 0.666667 0.111111 + 0.555556 0.666667 0.111111 0.666667 0.666667 0.111111 0.777778 0.666667 0.111111 + 0.888889 0.666667 0.111111 1 0.666667 0.111111 0 0.777778 0.111111 + 0.111111 0.777778 0.111111 0.222222 0.777778 0.111111 0.333333 0.777778 0.111111 + 0.444444 0.777778 0.111111 0.555556 0.777778 0.111111 0.666667 0.777778 0.111111 + 0.777778 0.777778 0.111111 0.888889 0.777778 0.111111 1 0.777778 0.111111 + 0 0.888889 0.111111 0.111111 0.888889 0.111111 0.222222 0.888889 0.111111 + 0.333333 0.888889 0.111111 0.444444 0.888889 0.111111 0.555556 0.888889 0.111111 + 0.666667 0.888889 0.111111 0.777778 0.888889 0.111111 0.888889 0.888889 0.111111 + 1 0.888889 0.111111 0 1 0.111111 0.111111 1 0.111111 + 0.222222 1 0.111111 0.333333 1 0.111111 0.444444 1 0.111111 + 0.555556 1 0.111111 0.666667 1 0.111111 0.777778 1 0.111111 + 0.888889 1 0.111111 1 1 0.111111 0 0 0.222222 + 0.111111 0 0.222222 0.222222 0 0.222222 0.333333 0 0.222222 + 0.444444 0 0.222222 0.555556 0 0.222222 0.666667 0 0.222222 + 0.777778 0 0.222222 0.888889 0 0.222222 1 0 0.222222 + 0 0.111111 0.222222 0.111111 0.111111 0.222222 0.222222 0.111111 0.222222 + 0.333333 0.111111 0.222222 0.444444 0.111111 0.222222 0.555556 0.111111 0.222222 + 0.666667 0.111111 0.222222 0.777778 0.111111 0.222222 0.888889 0.111111 0.222222 + 1 0.111111 0.222222 0 0.222222 0.222222 0.111111 0.222222 0.222222 + 0.222222 0.222222 0.222222 0.333333 0.222222 0.222222 0.444444 0.222222 0.222222 + 0.555556 0.222222 0.222222 0.666667 0.222222 0.222222 0.777778 0.222222 0.222222 + 0.888889 0.222222 0.222222 1 0.222222 0.222222 0 0.333333 0.222222 + 0.111111 0.333333 0.222222 0.222222 0.333333 0.222222 0.333333 0.333333 0.222222 + 0.444444 0.333333 0.222222 0.555556 0.333333 0.222222 0.666667 0.333333 0.222222 + 0.777778 0.333333 0.222222 0.888889 0.333333 0.222222 1 0.333333 0.222222 + 0 0.444444 0.222222 0.111111 0.444444 0.222222 0.222222 0.444444 0.222222 + 0.333333 0.444444 0.222222 0.444444 0.444444 0.222222 0.555556 0.444444 0.222222 + 0.666667 0.444444 0.222222 0.777778 0.444444 0.222222 0.888889 0.444444 0.222222 + 1 0.444444 0.222222 0 0.555556 0.222222 0.111111 0.555556 0.222222 + 0.222222 0.555556 0.222222 0.333333 0.555556 0.222222 0.444444 0.555556 0.222222 + 0.555556 0.555556 0.222222 0.666667 0.555556 0.222222 0.777778 0.555556 0.222222 + 0.888889 0.555556 0.222222 1 0.555556 0.222222 0 0.666667 0.222222 + 0.111111 0.666667 0.222222 0.222222 0.666667 0.222222 0.333333 0.666667 0.222222 + 0.444444 0.666667 0.222222 0.555556 0.666667 0.222222 0.666667 0.666667 0.222222 + 0.777778 0.666667 0.222222 0.888889 0.666667 0.222222 1 0.666667 0.222222 + 0 0.777778 0.222222 0.111111 0.777778 0.222222 0.222222 0.777778 0.222222 + 0.333333 0.777778 0.222222 0.444444 0.777778 0.222222 0.555556 0.777778 0.222222 + 0.666667 0.777778 0.222222 0.777778 0.777778 0.222222 0.888889 0.777778 0.222222 + 1 0.777778 0.222222 0 0.888889 0.222222 0.111111 0.888889 0.222222 + 0.222222 0.888889 0.222222 0.333333 0.888889 0.222222 0.444444 0.888889 0.222222 + 0.555556 0.888889 0.222222 0.666667 0.888889 0.222222 0.777778 0.888889 0.222222 + 0.888889 0.888889 0.222222 1 0.888889 0.222222 0 1 0.222222 + 0.111111 1 0.222222 0.222222 1 0.222222 0.333333 1 0.222222 + 0.444444 1 0.222222 0.555556 1 0.222222 0.666667 1 0.222222 + 0.777778 1 0.222222 0.888889 1 0.222222 1 1 0.222222 + 0 0 0.333333 0.111111 0 0.333333 0.222222 0 0.333333 + 0.333333 0 0.333333 0.444444 0 0.333333 0.555556 0 0.333333 + 0.666667 0 0.333333 0.777778 0 0.333333 0.888889 0 0.333333 + 1 0 0.333333 0 0.111111 0.333333 0.111111 0.111111 0.333333 + 0.222222 0.111111 0.333333 0.333333 0.111111 0.333333 0.444444 0.111111 0.333333 + 0.555556 0.111111 0.333333 0.666667 0.111111 0.333333 0.777778 0.111111 0.333333 + 0.888889 0.111111 0.333333 1 0.111111 0.333333 0 0.222222 0.333333 + 0.111111 0.222222 0.333333 0.222222 0.222222 0.333333 0.333333 0.222222 0.333333 + 0.444444 0.222222 0.333333 0.555556 0.222222 0.333333 0.666667 0.222222 0.333333 + 0.777778 0.222222 0.333333 0.888889 0.222222 0.333333 1 0.222222 0.333333 + 0 0.333333 0.333333 0.111111 0.333333 0.333333 0.222222 0.333333 0.333333 + 0.333333 0.333333 0.333333 0.444444 0.333333 0.333333 0.555556 0.333333 0.333333 + 0.666667 0.333333 0.333333 0.777778 0.333333 0.333333 0.888889 0.333333 0.333333 + 1 0.333333 0.333333 0 0.444444 0.333333 0.111111 0.444444 0.333333 + 0.222222 0.444444 0.333333 0.333333 0.444444 0.333333 0.444444 0.444444 0.333333 + 0.555556 0.444444 0.333333 0.666667 0.444444 0.333333 0.777778 0.444444 0.333333 + 0.888889 0.444444 0.333333 1 0.444444 0.333333 0 0.555556 0.333333 + 0.111111 0.555556 0.333333 0.222222 0.555556 0.333333 0.333333 0.555556 0.333333 + 0.444444 0.555556 0.333333 0.555556 0.555556 0.333333 0.666667 0.555556 0.333333 + 0.777778 0.555556 0.333333 0.888889 0.555556 0.333333 1 0.555556 0.333333 + 0 0.666667 0.333333 0.111111 0.666667 0.333333 0.222222 0.666667 0.333333 + 0.333333 0.666667 0.333333 0.444444 0.666667 0.333333 0.555556 0.666667 0.333333 + 0.666667 0.666667 0.333333 0.777778 0.666667 0.333333 0.888889 0.666667 0.333333 + 1 0.666667 0.333333 0 0.777778 0.333333 0.111111 0.777778 0.333333 + 0.222222 0.777778 0.333333 0.333333 0.777778 0.333333 0.444444 0.777778 0.333333 + 0.555556 0.777778 0.333333 0.666667 0.777778 0.333333 0.777778 0.777778 0.333333 + 0.888889 0.777778 0.333333 1 0.777778 0.333333 0 0.888889 0.333333 + 0.111111 0.888889 0.333333 0.222222 0.888889 0.333333 0.333333 0.888889 0.333333 + 0.444444 0.888889 0.333333 0.555556 0.888889 0.333333 0.666667 0.888889 0.333333 + 0.777778 0.888889 0.333333 0.888889 0.888889 0.333333 1 0.888889 0.333333 + 0 1 0.333333 0.111111 1 0.333333 0.222222 1 0.333333 + 0.333333 1 0.333333 0.444444 1 0.333333 0.555556 1 0.333333 + 0.666667 1 0.333333 0.777778 1 0.333333 0.888889 1 0.333333 + 1 1 0.333333 0 0 0.444444 0.111111 0 0.444444 + 0.222222 0 0.444444 0.333333 0 0.444444 0.444444 0 0.444444 + 0.555556 0 0.444444 0.666667 0 0.444444 0.777778 0 0.444444 + 0.888889 0 0.444444 1 0 0.444444 0 0.111111 0.444444 + 0.111111 0.111111 0.444444 0.222222 0.111111 0.444444 0.333333 0.111111 0.444444 + 0.444444 0.111111 0.444444 0.555556 0.111111 0.444444 0.666667 0.111111 0.444444 + 0.777778 0.111111 0.444444 0.888889 0.111111 0.444444 1 0.111111 0.444444 + 0 0.222222 0.444444 0.111111 0.222222 0.444444 0.222222 0.222222 0.444444 + 0.333333 0.222222 0.444444 0.444444 0.222222 0.444444 0.555556 0.222222 0.444444 + 0.666667 0.222222 0.444444 0.777778 0.222222 0.444444 0.888889 0.222222 0.444444 + 1 0.222222 0.444444 0 0.333333 0.444444 0.111111 0.333333 0.444444 + 0.222222 0.333333 0.444444 0.333333 0.333333 0.444444 0.444444 0.333333 0.444444 + 0.555556 0.333333 0.444444 0.666667 0.333333 0.444444 0.777778 0.333333 0.444444 + 0.888889 0.333333 0.444444 1 0.333333 0.444444 0 0.444444 0.444444 + 0.111111 0.444444 0.444444 0.222222 0.444444 0.444444 0.333333 0.444444 0.444444 + 0.444444 0.444444 0.444444 0.555556 0.444444 0.444444 0.666667 0.444444 0.444444 + 0.777778 0.444444 0.444444 0.888889 0.444444 0.444444 1 0.444444 0.444444 + 0 0.555556 0.444444 0.111111 0.555556 0.444444 0.222222 0.555556 0.444444 + 0.333333 0.555556 0.444444 0.444444 0.555556 0.444444 0.555556 0.555556 0.444444 + 0.666667 0.555556 0.444444 0.777778 0.555556 0.444444 0.888889 0.555556 0.444444 + 1 0.555556 0.444444 0 0.666667 0.444444 0.111111 0.666667 0.444444 + 0.222222 0.666667 0.444444 0.333333 0.666667 0.444444 0.444444 0.666667 0.444444 + 0.555556 0.666667 0.444444 0.666667 0.666667 0.444444 0.777778 0.666667 0.444444 + 0.888889 0.666667 0.444444 1 0.666667 0.444444 0 0.777778 0.444444 + 0.111111 0.777778 0.444444 0.222222 0.777778 0.444444 0.333333 0.777778 0.444444 + 0.444444 0.777778 0.444444 0.555556 0.777778 0.444444 0.666667 0.777778 0.444444 + 0.777778 0.777778 0.444444 0.888889 0.777778 0.444444 1 0.777778 0.444444 + 0 0.888889 0.444444 0.111111 0.888889 0.444444 0.222222 0.888889 0.444444 + 0.333333 0.888889 0.444444 0.444444 0.888889 0.444444 0.555556 0.888889 0.444444 + 0.666667 0.888889 0.444444 0.777778 0.888889 0.444444 0.888889 0.888889 0.444444 + 1 0.888889 0.444444 0 1 0.444444 0.111111 1 0.444444 + 0.222222 1 0.444444 0.333333 1 0.444444 0.444444 1 0.444444 + 0.555556 1 0.444444 0.666667 1 0.444444 0.777778 1 0.444444 + 0.888889 1 0.444444 1 1 0.444444 0 0 0.555556 + 0.111111 0 0.555556 0.222222 0 0.555556 0.333333 0 0.555556 + 0.444444 0 0.555556 0.555556 0 0.555556 0.666667 0 0.555556 + 0.777778 0 0.555556 0.888889 0 0.555556 1 0 0.555556 + 0 0.111111 0.555556 0.111111 0.111111 0.555556 0.222222 0.111111 0.555556 + 0.333333 0.111111 0.555556 0.444444 0.111111 0.555556 0.555556 0.111111 0.555556 + 0.666667 0.111111 0.555556 0.777778 0.111111 0.555556 0.888889 0.111111 0.555556 + 1 0.111111 0.555556 0 0.222222 0.555556 0.111111 0.222222 0.555556 + 0.222222 0.222222 0.555556 0.333333 0.222222 0.555556 0.444444 0.222222 0.555556 + 0.555556 0.222222 0.555556 0.666667 0.222222 0.555556 0.777778 0.222222 0.555556 + 0.888889 0.222222 0.555556 1 0.222222 0.555556 0 0.333333 0.555556 + 0.111111 0.333333 0.555556 0.222222 0.333333 0.555556 0.333333 0.333333 0.555556 + 0.444444 0.333333 0.555556 0.555556 0.333333 0.555556 0.666667 0.333333 0.555556 + 0.777778 0.333333 0.555556 0.888889 0.333333 0.555556 1 0.333333 0.555556 + 0 0.444444 0.555556 0.111111 0.444444 0.555556 0.222222 0.444444 0.555556 + 0.333333 0.444444 0.555556 0.444444 0.444444 0.555556 0.555556 0.444444 0.555556 + 0.666667 0.444444 0.555556 0.777778 0.444444 0.555556 0.888889 0.444444 0.555556 + 1 0.444444 0.555556 0 0.555556 0.555556 0.111111 0.555556 0.555556 + 0.222222 0.555556 0.555556 0.333333 0.555556 0.555556 0.444444 0.555556 0.555556 + 0.555556 0.555556 0.555556 0.666667 0.555556 0.555556 0.777778 0.555556 0.555556 + 0.888889 0.555556 0.555556 1 0.555556 0.555556 0 0.666667 0.555556 + 0.111111 0.666667 0.555556 0.222222 0.666667 0.555556 0.333333 0.666667 0.555556 + 0.444444 0.666667 0.555556 0.555556 0.666667 0.555556 0.666667 0.666667 0.555556 + 0.777778 0.666667 0.555556 0.888889 0.666667 0.555556 1 0.666667 0.555556 + 0 0.777778 0.555556 0.111111 0.777778 0.555556 0.222222 0.777778 0.555556 + 0.333333 0.777778 0.555556 0.444444 0.777778 0.555556 0.555556 0.777778 0.555556 + 0.666667 0.777778 0.555556 0.777778 0.777778 0.555556 0.888889 0.777778 0.555556 + 1 0.777778 0.555556 0 0.888889 0.555556 0.111111 0.888889 0.555556 + 0.222222 0.888889 0.555556 0.333333 0.888889 0.555556 0.444444 0.888889 0.555556 + 0.555556 0.888889 0.555556 0.666667 0.888889 0.555556 0.777778 0.888889 0.555556 + 0.888889 0.888889 0.555556 1 0.888889 0.555556 0 1 0.555556 + 0.111111 1 0.555556 0.222222 1 0.555556 0.333333 1 0.555556 + 0.444444 1 0.555556 0.555556 1 0.555556 0.666667 1 0.555556 + 0.777778 1 0.555556 0.888889 1 0.555556 1 1 0.555556 + 0 0 0.666667 0.111111 0 0.666667 0.222222 0 0.666667 + 0.333333 0 0.666667 0.444444 0 0.666667 0.555556 0 0.666667 + 0.666667 0 0.666667 0.777778 0 0.666667 0.888889 0 0.666667 + 1 0 0.666667 0 0.111111 0.666667 0.111111 0.111111 0.666667 + 0.222222 0.111111 0.666667 0.333333 0.111111 0.666667 0.444444 0.111111 0.666667 + 0.555556 0.111111 0.666667 0.666667 0.111111 0.666667 0.777778 0.111111 0.666667 + 0.888889 0.111111 0.666667 1 0.111111 0.666667 0 0.222222 0.666667 + 0.111111 0.222222 0.666667 0.222222 0.222222 0.666667 0.333333 0.222222 0.666667 + 0.444444 0.222222 0.666667 0.555556 0.222222 0.666667 0.666667 0.222222 0.666667 + 0.777778 0.222222 0.666667 0.888889 0.222222 0.666667 1 0.222222 0.666667 + 0 0.333333 0.666667 0.111111 0.333333 0.666667 0.222222 0.333333 0.666667 + 0.333333 0.333333 0.666667 0.444444 0.333333 0.666667 0.555556 0.333333 0.666667 + 0.666667 0.333333 0.666667 0.777778 0.333333 0.666667 0.888889 0.333333 0.666667 + 1 0.333333 0.666667 0 0.444444 0.666667 0.111111 0.444444 0.666667 + 0.222222 0.444444 0.666667 0.333333 0.444444 0.666667 0.444444 0.444444 0.666667 + 0.555556 0.444444 0.666667 0.666667 0.444444 0.666667 0.777778 0.444444 0.666667 + 0.888889 0.444444 0.666667 1 0.444444 0.666667 0 0.555556 0.666667 + 0.111111 0.555556 0.666667 0.222222 0.555556 0.666667 0.333333 0.555556 0.666667 + 0.444444 0.555556 0.666667 0.555556 0.555556 0.666667 0.666667 0.555556 0.666667 + 0.777778 0.555556 0.666667 0.888889 0.555556 0.666667 1 0.555556 0.666667 + 0 0.666667 0.666667 0.111111 0.666667 0.666667 0.222222 0.666667 0.666667 + 0.333333 0.666667 0.666667 0.444444 0.666667 0.666667 0.555556 0.666667 0.666667 + 0.666667 0.666667 0.666667 0.777778 0.666667 0.666667 0.888889 0.666667 0.666667 + 1 0.666667 0.666667 0 0.777778 0.666667 0.111111 0.777778 0.666667 + 0.222222 0.777778 0.666667 0.333333 0.777778 0.666667 0.444444 0.777778 0.666667 + 0.555556 0.777778 0.666667 0.666667 0.777778 0.666667 0.777778 0.777778 0.666667 + 0.888889 0.777778 0.666667 1 0.777778 0.666667 0 0.888889 0.666667 + 0.111111 0.888889 0.666667 0.222222 0.888889 0.666667 0.333333 0.888889 0.666667 + 0.444444 0.888889 0.666667 0.555556 0.888889 0.666667 0.666667 0.888889 0.666667 + 0.777778 0.888889 0.666667 0.888889 0.888889 0.666667 1 0.888889 0.666667 + 0 1 0.666667 0.111111 1 0.666667 0.222222 1 0.666667 + 0.333333 1 0.666667 0.444444 1 0.666667 0.555556 1 0.666667 + 0.666667 1 0.666667 0.777778 1 0.666667 0.888889 1 0.666667 + 1 1 0.666667 0 0 0.777778 0.111111 0 0.777778 + 0.222222 0 0.777778 0.333333 0 0.777778 0.444444 0 0.777778 + 0.555556 0 0.777778 0.666667 0 0.777778 0.777778 0 0.777778 + 0.888889 0 0.777778 1 0 0.777778 0 0.111111 0.777778 + 0.111111 0.111111 0.777778 0.222222 0.111111 0.777778 0.333333 0.111111 0.777778 + 0.444444 0.111111 0.777778 0.555556 0.111111 0.777778 0.666667 0.111111 0.777778 + 0.777778 0.111111 0.777778 0.888889 0.111111 0.777778 1 0.111111 0.777778 + 0 0.222222 0.777778 0.111111 0.222222 0.777778 0.222222 0.222222 0.777778 + 0.333333 0.222222 0.777778 0.444444 0.222222 0.777778 0.555556 0.222222 0.777778 + 0.666667 0.222222 0.777778 0.777778 0.222222 0.777778 0.888889 0.222222 0.777778 + 1 0.222222 0.777778 0 0.333333 0.777778 0.111111 0.333333 0.777778 + 0.222222 0.333333 0.777778 0.333333 0.333333 0.777778 0.444444 0.333333 0.777778 + 0.555556 0.333333 0.777778 0.666667 0.333333 0.777778 0.777778 0.333333 0.777778 + 0.888889 0.333333 0.777778 1 0.333333 0.777778 0 0.444444 0.777778 + 0.111111 0.444444 0.777778 0.222222 0.444444 0.777778 0.333333 0.444444 0.777778 + 0.444444 0.444444 0.777778 0.555556 0.444444 0.777778 0.666667 0.444444 0.777778 + 0.777778 0.444444 0.777778 0.888889 0.444444 0.777778 1 0.444444 0.777778 + 0 0.555556 0.777778 0.111111 0.555556 0.777778 0.222222 0.555556 0.777778 + 0.333333 0.555556 0.777778 0.444444 0.555556 0.777778 0.555556 0.555556 0.777778 + 0.666667 0.555556 0.777778 0.777778 0.555556 0.777778 0.888889 0.555556 0.777778 + 1 0.555556 0.777778 0 0.666667 0.777778 0.111111 0.666667 0.777778 + 0.222222 0.666667 0.777778 0.333333 0.666667 0.777778 0.444444 0.666667 0.777778 + 0.555556 0.666667 0.777778 0.666667 0.666667 0.777778 0.777778 0.666667 0.777778 + 0.888889 0.666667 0.777778 1 0.666667 0.777778 0 0.777778 0.777778 + 0.111111 0.777778 0.777778 0.222222 0.777778 0.777778 0.333333 0.777778 0.777778 + 0.444444 0.777778 0.777778 0.555556 0.777778 0.777778 0.666667 0.777778 0.777778 + 0.777778 0.777778 0.777778 0.888889 0.777778 0.777778 1 0.777778 0.777778 + 0 0.888889 0.777778 0.111111 0.888889 0.777778 0.222222 0.888889 0.777778 + 0.333333 0.888889 0.777778 0.444444 0.888889 0.777778 0.555556 0.888889 0.777778 + 0.666667 0.888889 0.777778 0.777778 0.888889 0.777778 0.888889 0.888889 0.777778 + 1 0.888889 0.777778 0 1 0.777778 0.111111 1 0.777778 + 0.222222 1 0.777778 0.333333 1 0.777778 0.444444 1 0.777778 + 0.555556 1 0.777778 0.666667 1 0.777778 0.777778 1 0.777778 + 0.888889 1 0.777778 1 1 0.777778 0 0 0.888889 + 0.111111 0 0.888889 0.222222 0 0.888889 0.333333 0 0.888889 + 0.444444 0 0.888889 0.555556 0 0.888889 0.666667 0 0.888889 + 0.777778 0 0.888889 0.888889 0 0.888889 1 0 0.888889 + 0 0.111111 0.888889 0.111111 0.111111 0.888889 0.222222 0.111111 0.888889 + 0.333333 0.111111 0.888889 0.444444 0.111111 0.888889 0.555556 0.111111 0.888889 + 0.666667 0.111111 0.888889 0.777778 0.111111 0.888889 0.888889 0.111111 0.888889 + 1 0.111111 0.888889 0 0.222222 0.888889 0.111111 0.222222 0.888889 + 0.222222 0.222222 0.888889 0.333333 0.222222 0.888889 0.444444 0.222222 0.888889 + 0.555556 0.222222 0.888889 0.666667 0.222222 0.888889 0.777778 0.222222 0.888889 + 0.888889 0.222222 0.888889 1 0.222222 0.888889 0 0.333333 0.888889 + 0.111111 0.333333 0.888889 0.222222 0.333333 0.888889 0.333333 0.333333 0.888889 + 0.444444 0.333333 0.888889 0.555556 0.333333 0.888889 0.666667 0.333333 0.888889 + 0.777778 0.333333 0.888889 0.888889 0.333333 0.888889 1 0.333333 0.888889 + 0 0.444444 0.888889 0.111111 0.444444 0.888889 0.222222 0.444444 0.888889 + 0.333333 0.444444 0.888889 0.444444 0.444444 0.888889 0.555556 0.444444 0.888889 + 0.666667 0.444444 0.888889 0.777778 0.444444 0.888889 0.888889 0.444444 0.888889 + 1 0.444444 0.888889 0 0.555556 0.888889 0.111111 0.555556 0.888889 + 0.222222 0.555556 0.888889 0.333333 0.555556 0.888889 0.444444 0.555556 0.888889 + 0.555556 0.555556 0.888889 0.666667 0.555556 0.888889 0.777778 0.555556 0.888889 + 0.888889 0.555556 0.888889 1 0.555556 0.888889 0 0.666667 0.888889 + 0.111111 0.666667 0.888889 0.222222 0.666667 0.888889 0.333333 0.666667 0.888889 + 0.444444 0.666667 0.888889 0.555556 0.666667 0.888889 0.666667 0.666667 0.888889 + 0.777778 0.666667 0.888889 0.888889 0.666667 0.888889 1 0.666667 0.888889 + 0 0.777778 0.888889 0.111111 0.777778 0.888889 0.222222 0.777778 0.888889 + 0.333333 0.777778 0.888889 0.444444 0.777778 0.888889 0.555556 0.777778 0.888889 + 0.666667 0.777778 0.888889 0.777778 0.777778 0.888889 0.888889 0.777778 0.888889 + 1 0.777778 0.888889 0 0.888889 0.888889 0.111111 0.888889 0.888889 + 0.222222 0.888889 0.888889 0.333333 0.888889 0.888889 0.444444 0.888889 0.888889 + 0.555556 0.888889 0.888889 0.666667 0.888889 0.888889 0.777778 0.888889 0.888889 + 0.888889 0.888889 0.888889 1 0.888889 0.888889 0 1 0.888889 + 0.111111 1 0.888889 0.222222 1 0.888889 0.333333 1 0.888889 + 0.444444 1 0.888889 0.555556 1 0.888889 0.666667 1 0.888889 + 0.777778 1 0.888889 0.888889 1 0.888889 1 1 0.888889 + 0 0 1 0.111111 0 1 0.222222 0 1 + 0.333333 0 1 0.444444 0 1 0.555556 0 1 + 0.666667 0 1 0.777778 0 1 0.888889 0 1 + 1 0 1 0 0.111111 1 0.111111 0.111111 1 + 0.222222 0.111111 1 0.333333 0.111111 1 0.444444 0.111111 1 + 0.555556 0.111111 1 0.666667 0.111111 1 0.777778 0.111111 1 + 0.888889 0.111111 1 1 0.111111 1 0 0.222222 1 + 0.111111 0.222222 1 0.222222 0.222222 1 0.333333 0.222222 1 + 0.444444 0.222222 1 0.555556 0.222222 1 0.666667 0.222222 1 + 0.777778 0.222222 1 0.888889 0.222222 1 1 0.222222 1 + 0 0.333333 1 0.111111 0.333333 1 0.222222 0.333333 1 + 0.333333 0.333333 1 0.444444 0.333333 1 0.555556 0.333333 1 + 0.666667 0.333333 1 0.777778 0.333333 1 0.888889 0.333333 1 + 1 0.333333 1 0 0.444444 1 0.111111 0.444444 1 + 0.222222 0.444444 1 0.333333 0.444444 1 0.444444 0.444444 1 + 0.555556 0.444444 1 0.666667 0.444444 1 0.777778 0.444444 1 + 0.888889 0.444444 1 1 0.444444 1 0 0.555556 1 + 0.111111 0.555556 1 0.222222 0.555556 1 0.333333 0.555556 1 + 0.444444 0.555556 1 0.555556 0.555556 1 0.666667 0.555556 1 + 0.777778 0.555556 1 0.888889 0.555556 1 1 0.555556 1 + 0 0.666667 1 0.111111 0.666667 1 0.222222 0.666667 1 + 0.333333 0.666667 1 0.444444 0.666667 1 0.555556 0.666667 1 + 0.666667 0.666667 1 0.777778 0.666667 1 0.888889 0.666667 1 + 1 0.666667 1 0 0.777778 1 0.111111 0.777778 1 + 0.222222 0.777778 1 0.333333 0.777778 1 0.444444 0.777778 1 + 0.555556 0.777778 1 0.666667 0.777778 1 0.777778 0.777778 1 + 0.888889 0.777778 1 1 0.777778 1 0 0.888889 1 + 0.111111 0.888889 1 0.222222 0.888889 1 0.333333 0.888889 1 + 0.444444 0.888889 1 0.555556 0.888889 1 0.666667 0.888889 1 + 0.777778 0.888889 1 0.888889 0.888889 1 1 0.888889 1 + 0 1 1 0.111111 1 1 0.222222 1 1 + 0.333333 1 1 0.444444 1 1 0.555556 1 1 + 0.666667 1 1 0.777778 1 1 0.888889 1 1 + 1 1 1 + + + + + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100 101 102 103 104 105 106 107 108 109 + 110 111 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 128 129 + 130 131 132 133 134 135 136 137 138 139 + 140 141 142 143 144 145 146 147 148 149 + 150 151 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 168 169 + 170 171 172 173 174 175 176 177 178 179 + 180 181 182 183 184 185 186 187 188 189 + 190 191 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 208 209 + 210 211 212 213 214 215 216 217 218 219 + 220 221 222 223 224 225 226 227 228 229 + 230 231 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 248 249 + 250 251 252 253 254 255 256 257 258 259 + 260 261 262 263 264 265 266 267 268 269 + 270 271 272 273 274 275 276 277 278 279 + 280 281 282 283 284 285 286 287 288 289 + 290 291 292 293 294 295 296 297 298 299 + 300 301 302 303 304 305 306 307 308 309 + 310 311 312 313 314 315 316 317 318 319 + 320 321 322 323 324 325 326 327 328 329 + 330 331 332 333 334 335 336 337 338 339 + 340 341 342 343 344 345 346 347 348 349 + 350 351 352 353 354 355 356 357 358 359 + 360 361 362 363 364 365 366 367 368 369 + 370 371 372 373 374 375 376 377 378 379 + 380 381 382 383 384 385 386 387 388 389 + 390 391 392 393 394 395 396 397 398 399 + 400 401 402 403 404 405 406 407 408 409 + 410 411 412 413 414 415 416 417 418 419 + 420 421 422 423 424 425 426 427 428 429 + 430 431 432 433 434 435 436 437 438 439 + 440 441 442 443 444 445 446 447 448 449 + 450 451 452 453 454 455 456 457 458 459 + 460 461 462 463 464 465 466 467 468 469 + 470 471 472 473 474 475 476 477 478 479 + 480 481 482 483 484 485 486 487 488 489 + 490 491 492 493 494 495 496 497 498 499 + 500 501 502 503 504 505 506 507 508 509 + 510 511 512 513 514 515 516 517 518 519 + 520 521 522 523 524 525 526 527 528 529 + 530 531 532 533 534 535 536 537 538 539 + 540 541 542 543 544 545 546 547 548 549 + 550 551 552 553 554 555 556 557 558 559 + 560 561 562 563 564 565 566 567 568 569 + 570 571 572 573 574 575 576 577 578 579 + 580 581 582 583 584 585 586 587 588 589 + 590 591 592 593 594 595 596 597 598 599 + 600 601 602 603 604 605 606 607 608 609 + 610 611 612 613 614 615 616 617 618 619 + 620 621 622 623 624 625 626 627 628 629 + 630 631 632 633 634 635 636 637 638 639 + 640 641 642 643 644 645 646 647 648 649 + 650 651 652 653 654 655 656 657 658 659 + 660 661 662 663 664 665 666 667 668 669 + 670 671 672 673 674 675 676 677 678 679 + 680 681 682 683 684 685 686 687 688 689 + 690 691 692 693 694 695 696 697 698 699 + 700 701 702 703 704 705 706 707 708 709 + 710 711 712 713 714 715 716 717 718 719 + 720 721 722 723 724 725 726 727 728 729 + 730 731 732 733 734 735 736 737 738 739 + 740 741 742 743 744 745 746 747 748 749 + 750 751 752 753 754 755 756 757 758 759 + 760 761 762 763 764 765 766 767 768 769 + 770 771 772 773 774 775 776 777 778 779 + 780 781 782 783 784 785 786 787 788 789 + 790 791 792 793 794 795 796 797 798 799 + 800 801 802 803 804 805 806 807 808 809 + 810 811 812 813 814 815 816 817 818 819 + 820 821 822 823 824 825 826 827 828 829 + 830 831 832 833 834 835 836 837 838 839 + 840 841 842 843 844 845 846 847 848 849 + 850 851 852 853 854 855 856 857 858 859 + 860 861 862 863 864 865 866 867 868 869 + 870 871 872 873 874 875 876 877 878 879 + 880 881 882 883 884 885 886 887 888 889 + 890 891 892 893 894 895 896 897 898 899 + 900 901 902 903 904 905 906 907 908 909 + 910 911 912 913 914 915 916 917 918 919 + 920 921 922 923 924 925 926 927 928 929 + 930 931 932 933 934 935 936 937 938 939 + 940 941 942 943 944 945 946 947 948 949 + 950 951 952 953 954 955 956 957 958 959 + 960 961 962 963 964 965 966 967 968 969 + 970 971 972 973 974 975 976 977 978 979 + 980 981 982 983 984 985 986 987 988 989 + 990 991 992 993 994 995 996 997 998 999 + + + + 1 2 3 4 5 6 7 8 9 10 + 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 + 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 + 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 70 + 71 72 73 74 75 76 77 78 79 80 + 81 82 83 84 85 86 87 88 89 90 + 91 92 93 94 95 96 97 98 99 100 + 101 102 103 104 105 106 107 108 109 110 + 111 112 113 114 115 116 117 118 119 120 + 121 122 123 124 125 126 127 128 129 130 + 131 132 133 134 135 136 137 138 139 140 + 141 142 143 144 145 146 147 148 149 150 + 151 152 153 154 155 156 157 158 159 160 + 161 162 163 164 165 166 167 168 169 170 + 171 172 173 174 175 176 177 178 179 180 + 181 182 183 184 185 186 187 188 189 190 + 191 192 193 194 195 196 197 198 199 200 + 201 202 203 204 205 206 207 208 209 210 + 211 212 213 214 215 216 217 218 219 220 + 221 222 223 224 225 226 227 228 229 230 + 231 232 233 234 235 236 237 238 239 240 + 241 242 243 244 245 246 247 248 249 250 + 251 252 253 254 255 256 257 258 259 260 + 261 262 263 264 265 266 267 268 269 270 + 271 272 273 274 275 276 277 278 279 280 + 281 282 283 284 285 286 287 288 289 290 + 291 292 293 294 295 296 297 298 299 300 + 301 302 303 304 305 306 307 308 309 310 + 311 312 313 314 315 316 317 318 319 320 + 321 322 323 324 325 326 327 328 329 330 + 331 332 333 334 335 336 337 338 339 340 + 341 342 343 344 345 346 347 348 349 350 + 351 352 353 354 355 356 357 358 359 360 + 361 362 363 364 365 366 367 368 369 370 + 371 372 373 374 375 376 377 378 379 380 + 381 382 383 384 385 386 387 388 389 390 + 391 392 393 394 395 396 397 398 399 400 + 401 402 403 404 405 406 407 408 409 410 + 411 412 413 414 415 416 417 418 419 420 + 421 422 423 424 425 426 427 428 429 430 + 431 432 433 434 435 436 437 438 439 440 + 441 442 443 444 445 446 447 448 449 450 + 451 452 453 454 455 456 457 458 459 460 + 461 462 463 464 465 466 467 468 469 470 + 471 472 473 474 475 476 477 478 479 480 + 481 482 483 484 485 486 487 488 489 490 + 491 492 493 494 495 496 497 498 499 500 + 501 502 503 504 505 506 507 508 509 510 + 511 512 513 514 515 516 517 518 519 520 + 521 522 523 524 525 526 527 528 529 530 + 531 532 533 534 535 536 537 538 539 540 + 541 542 543 544 545 546 547 548 549 550 + 551 552 553 554 555 556 557 558 559 560 + 561 562 563 564 565 566 567 568 569 570 + 571 572 573 574 575 576 577 578 579 580 + 581 582 583 584 585 586 587 588 589 590 + 591 592 593 594 595 596 597 598 599 600 + 601 602 603 604 605 606 607 608 609 610 + 611 612 613 614 615 616 617 618 619 620 + 621 622 623 624 625 626 627 628 629 630 + 631 632 633 634 635 636 637 638 639 640 + 641 642 643 644 645 646 647 648 649 650 + 651 652 653 654 655 656 657 658 659 660 + 661 662 663 664 665 666 667 668 669 670 + 671 672 673 674 675 676 677 678 679 680 + 681 682 683 684 685 686 687 688 689 690 + 691 692 693 694 695 696 697 698 699 700 + 701 702 703 704 705 706 707 708 709 710 + 711 712 713 714 715 716 717 718 719 720 + 721 722 723 724 725 726 727 728 729 730 + 731 732 733 734 735 736 737 738 739 740 + 741 742 743 744 745 746 747 748 749 750 + 751 752 753 754 755 756 757 758 759 760 + 761 762 763 764 765 766 767 768 769 770 + 771 772 773 774 775 776 777 778 779 780 + 781 782 783 784 785 786 787 788 789 790 + 791 792 793 794 795 796 797 798 799 800 + 801 802 803 804 805 806 807 808 809 810 + 811 812 813 814 815 816 817 818 819 820 + 821 822 823 824 825 826 827 828 829 830 + 831 832 833 834 835 836 837 838 839 840 + 841 842 843 844 845 846 847 848 849 850 + 851 852 853 854 855 856 857 858 859 860 + 861 862 863 864 865 866 867 868 869 870 + 871 872 873 874 875 876 877 878 879 880 + 881 882 883 884 885 886 887 888 889 890 + 891 892 893 894 895 896 897 898 899 900 + 901 902 903 904 905 906 907 908 909 910 + 911 912 913 914 915 916 917 918 919 920 + 921 922 923 924 925 926 927 928 929 930 + 931 932 933 934 935 936 937 938 939 940 + 941 942 943 944 945 946 947 948 949 950 + 951 952 953 954 955 956 957 958 959 960 + 961 962 963 964 965 966 967 968 969 970 + 971 972 973 974 975 976 977 978 979 980 + 981 982 983 984 985 986 987 988 989 990 + 991 992 993 994 995 996 997 998 999 1000 + + + + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 + + + + + \ No newline at end of file diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc0.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc0.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc0.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc0.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc1.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc1.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc1.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc1.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc2.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc2.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc2.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc2.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc3.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc3.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc3.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0-Proc3.gold diff --git a/packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-PointCloud-Level0.gold b/packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0.gold similarity index 100% rename from packages/muelu/test/viz/MPI-Viz-Output-Laplace3D-PointCloud-Level0.gold rename to packages/muelu/test/viz/Output/MPI-Viz-Output-Laplace3D-PointCloud-Level0.gold diff --git a/packages/muelu/test/viz/Viz.cpp b/packages/muelu/test/viz/Viz.cpp index f963c1c28cb1..6acf93d1e8c8 100644 --- a/packages/muelu/test/viz/Viz.cpp +++ b/packages/muelu/test/viz/Viz.cpp @@ -253,9 +253,9 @@ int main_(Teuchos::CommandLineProcessor& clp, Xpetra::UnderlyingLib& lib, int ar galeriStream << "Galeri complete.\n========================================================" << std::endl; if (ndims == 2) - paramList.set("aggregation: output filename", "MPI-Viz-Output-2D-Level%LEVELID-Proc%PROCID"); + paramList.set("aggregation: output filename", "Output/MPI-Viz-Output-2D-Level%LEVELID-Proc%PROCID"); else if (ndims == 3) - paramList.set("aggregation: output filename", "MPI-Viz-Output-3D-Level%LEVELID-Proc%PROCID"); + paramList.set("aggregation: output filename", "Output/MPI-Viz-Output-3D-Level%LEVELID-Proc%PROCID"); int numReruns = 1; if (paramList.isParameter("number of reruns")) numReruns = paramList.get("number of reruns"); diff --git a/packages/muelu/test/viz/vizLaplace3DConvexHullsAggregateQuality.xml b/packages/muelu/test/viz/vizLaplace3DConvexHullsAggregateQuality.xml new file mode 100644 index 000000000000..8f0594a3a15e --- /dev/null +++ b/packages/muelu/test/viz/vizLaplace3DConvexHullsAggregateQuality.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + > + + + + + + + + + diff --git a/packages/muelu/test/viz/vizLaplace3DPointCloudAggregateQuality.xml b/packages/muelu/test/viz/vizLaplace3DPointCloudAggregateQuality.xml new file mode 100644 index 000000000000..4efdd9a0fe0b --- /dev/null +++ b/packages/muelu/test/viz/vizLaplace3DPointCloudAggregateQuality.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + > + + + + + + + + + diff --git a/packages/nox/src-petsc/NOX_Petsc_Group.C b/packages/nox/src-petsc/NOX_Petsc_Group.C index b33521cb94f3..f9b2a83d55fc 100644 --- a/packages/nox/src-petsc/NOX_Petsc_Group.C +++ b/packages/nox/src-petsc/NOX_Petsc_Group.C @@ -183,7 +183,7 @@ Group::computeF() if(status == false) { std::cout << "ERROR: Petsc::Group::computeF() - fill failed!!!" << std::endl; - throw std::runtime_error("NOX Error:) RHS Fill Failed"; + throw std::runtime_error("NOX Error: RHS Fill Failed"); } normRHS = RHSVector.norm(); @@ -214,7 +214,7 @@ Group::computeJacobian() if (status == false) { std::cout << "ERROR: Petsc::Group::computeJacobian() - fill failed!!!" << std::endl; - throw std::runtime_error("NOX Error:) Jacobian Fill Failed"; + throw std::runtime_error("NOX Error: Jacobian Fill Failed"); } } else if(jacType == "Finite Difference") { diff --git a/packages/nox/src-thyra/NOX_Thyra_Group.C b/packages/nox/src-thyra/NOX_Thyra_Group.C index 368e48e343b4..235d4d2a8fec 100644 --- a/packages/nox/src-thyra/NOX_Thyra_Group.C +++ b/packages/nox/src-thyra/NOX_Thyra_Group.C @@ -635,9 +635,13 @@ NOX::Thyra::Group::applyJacobianTransposeMultiVector( NOX::Abstract::MultiVector& result) const { if ( !(this->isJacobian()) ) { - TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, - "NOX Error - Jacobian is not valid. " << - "Call computeJacobian before calling applyJacobian!"); + // Should throw if algorithm hasn't updated the Jacobian (force + // devs to think about efficiency of reevaluating J within an + // algorithm) but a certain application needs this temporarily. + const_cast(this)->computeJacobian(); + // TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, + // "NOX Error - Jacobian is not valid. " << + // "Call computeJacobian before calling applyJacobian!"); } NOX_ASSERT(nonnull(lop_)); diff --git a/packages/panzer/adapters-stk/test/evaluator_tests/CMakeLists.txt b/packages/panzer/adapters-stk/test/evaluator_tests/CMakeLists.txt index d871d0375cb0..079cdad0848b 100644 --- a/packages/panzer/adapters-stk/test/evaluator_tests/CMakeLists.txt +++ b/packages/panzer/adapters-stk/test/evaluator_tests/CMakeLists.txt @@ -57,6 +57,13 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST( NUM_MPI_PROCS 2 ) +TRIBITS_ADD_EXECUTABLE_AND_TEST( + tScatterResidual_BlockedTpetra + SOURCES tpetra_blocked_scatter_residual.cpp ${UNIT_TEST_DRIVER} + COMM serial mpi + NUM_MPI_PROCS 2 + ) + TRIBITS_ADD_EXECUTABLE_AND_TEST( tScatterDirichletResidual_Tpetra SOURCES tpetra_scatter_dirichlet_residual.cpp ${UNIT_TEST_DRIVER} diff --git a/packages/panzer/adapters-stk/test/evaluator_tests/tpetra_blocked_scatter_residual.cpp b/packages/panzer/adapters-stk/test/evaluator_tests/tpetra_blocked_scatter_residual.cpp new file mode 100644 index 000000000000..60d1c6d87f75 --- /dev/null +++ b/packages/panzer/adapters-stk/test/evaluator_tests/tpetra_blocked_scatter_residual.cpp @@ -0,0 +1,909 @@ +// @HEADER +// ***************************************************************************** +// Panzer: A partial differential equation assembly +// engine for strongly coupled complex multiphysics systems +// +// Copyright 2011 NTESS and the Panzer contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +#include +#include +#include +#include + +using Teuchos::RCP; +using Teuchos::rcp; + +#include "Teuchos_DefaultComm.hpp" +#include "Teuchos_GlobalMPISession.hpp" + +#include "Panzer_FieldManagerBuilder.hpp" +#include "Panzer_BlockedDOFManager.hpp" +#include "Panzer_BlockedTpetraLinearObjFactory.hpp" +#include "Panzer_PureBasis.hpp" +#include "Panzer_BasisIRLayout.hpp" +#include "Panzer_Workset.hpp" +#include "Panzer_GatherOrientation.hpp" +#include "Panzer_ScatterResidual_BlockedTpetra.hpp" +#include "Panzer_GatherSolution_BlockedTpetra.hpp" +#include "Panzer_LOCPair_GlobalEvaluationData.hpp" +#include "Panzer_GlobalEvaluationDataContainer.hpp" +#include "Panzer_ParameterList_GlobalEvaluationData.hpp" + +#include "Panzer_STK_Version.hpp" +#include "PanzerAdaptersSTK_config.hpp" +#include "Panzer_STK_Interface.hpp" +#include "Panzer_STK_SquareQuadMeshFactory.hpp" +#include "Panzer_STK_SetupUtilities.hpp" +#include "Panzer_STKConnManager.hpp" + +#include "Teuchos_DefaultMpiComm.hpp" +#include "Teuchos_OpaqueWrapper.hpp" + +#include "Thyra_VectorStdOps.hpp" +#include "Thyra_ProductVectorBase.hpp" +#include "Thyra_SpmdVectorBase.hpp" + +#include "user_app_EquationSetFactory.hpp" + +#include // for get char +#include +#include + +#include "Panzer_Evaluator_WithBaseImpl.hpp" + +namespace panzer +{ + typedef Teuchos::ArrayRCP::size_type size_type; + + using TpetraBlockedLinObjFactoryType = panzer::BlockedTpetraLinearObjFactory; + using TpetraBlockedLinObjContainerType = panzer::BlockedTpetraLinearObjContainer; + + Teuchos::RCP buildBasis(std::size_t worksetSize, const std::string &basisName); + void testInitialization(const Teuchos::RCP &ipb); + Teuchos::RCP buildMesh(int elemX, int elemY); + + TEUCHOS_UNIT_TEST(block_assembly, scatter_solution_residual) + { + +#ifdef HAVE_MPI + Teuchos::RCP> tComm = Teuchos::rcp(new Teuchos::MpiComm(MPI_COMM_WORLD)); +#else + NOPE_PANZER_DOESNT_SUPPORT_SERIAL +#endif + + int myRank = tComm->getRank(); + + const std::size_t workset_size = 4; + const std::string fieldName1_q1 = "U"; + const std::string fieldName2_q1 = "V"; + const std::string fieldName_qedge1 = "B"; + + Teuchos::RCP mesh = buildMesh(2, 2); + + // build input physics block + Teuchos::RCP basis_q1 = buildBasis(workset_size, "Q1"); + Teuchos::RCP basis_qedge1 = buildBasis(workset_size, "QEdge1"); + + Teuchos::RCP ipb = Teuchos::parameterList(); + testInitialization(ipb); + + const int default_int_order = 1; + std::string eBlockID = "eblock-0_0"; + Teuchos::RCP eqset_factory = Teuchos::rcp(new user_app::MyFactory); + panzer::CellData cellData(workset_size, mesh->getCellTopology("eblock-0_0")); + Teuchos::RCP gd = panzer::createGlobalData(); + Teuchos::RCP physicsBlock = + Teuchos::rcp(new PhysicsBlock(ipb, eBlockID, default_int_order, cellData, eqset_factory, gd, false)); + + Teuchos::RCP> work_sets = panzer_stk::buildWorksets(*mesh, physicsBlock->elementBlockID(), + physicsBlock->getWorksetNeeds()); + TEST_EQUALITY(work_sets->size(), 1); + + // build connection manager and field manager + const Teuchos::RCP conn_manager = Teuchos::rcp(new panzer_stk::STKConnManager(mesh)); + RCP dofManager = Teuchos::rcp(new panzer::BlockedDOFManager(conn_manager, MPI_COMM_WORLD)); + + dofManager->addField(fieldName1_q1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_q1->getIntrepid2Basis()))); + dofManager->addField(fieldName2_q1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_q1->getIntrepid2Basis()))); + dofManager->addField(fieldName_qedge1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_qedge1->getIntrepid2Basis()))); + + std::vector> fieldOrder(3); + fieldOrder[0].push_back(fieldName1_q1); + fieldOrder[1].push_back(fieldName_qedge1); + fieldOrder[2].push_back(fieldName2_q1); + dofManager->setFieldOrder(fieldOrder); + + // dofManager->setOrientationsRequired(true); + dofManager->buildGlobalUnknowns(); + + // setup linear object factory + ///////////////////////////////////////////////////////////// + Teuchos::RCP bt_lof = Teuchos::rcp(new TpetraBlockedLinObjFactoryType(tComm.getConst(), dofManager)); + Teuchos::RCP> lof = bt_lof; + Teuchos::RCP loc = bt_lof->buildGhostedLinearObjContainer(); + bt_lof->initializeGhostedContainer(LinearObjContainer::X | LinearObjContainer::F, *loc); + loc->initialize(); + + Teuchos::RCP b_loc = Teuchos::rcp_dynamic_cast(loc); + + Teuchos::RCP> p_vec = Teuchos::rcp_dynamic_cast>(b_loc->get_x()); + Thyra::assign(p_vec->getNonconstVectorBlock(0).ptr(), 123.0 + myRank); + Thyra::assign(p_vec->getNonconstVectorBlock(1).ptr(), 456.0 + myRank); + Thyra::assign(p_vec->getNonconstVectorBlock(2).ptr(), 789.0 + myRank); + + // setup field manager, add evaluator under test + ///////////////////////////////////////////////////////////// + + PHX::FieldManager fm; + + std::string resName = ""; + Teuchos::RCP> names_map = + Teuchos::rcp(new std::map); + names_map->insert(std::make_pair(fieldName1_q1, resName + fieldName1_q1)); + names_map->insert(std::make_pair(fieldName2_q1, resName + fieldName2_q1)); + names_map->insert(std::make_pair(fieldName_qedge1, resName + fieldName_qedge1)); + + // evaluators under test + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(resName + fieldName1_q1); + names->push_back(resName + fieldName2_q1); + + Teuchos::ParameterList pl; + pl.set("Scatter Name", "ScatterQ1"); + pl.set("Basis", basis_q1.getConst()); + pl.set("Dependent Names", names); + pl.set("Dependent Map", names_map); + + Teuchos::RCP> evaluator = lof->buildScatter(pl); + + TEST_EQUALITY(evaluator->evaluatedFields().size(), 1); + + fm.registerEvaluator(evaluator); + fm.requireField(*evaluator->evaluatedFields()[0]); + } + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(resName + fieldName_qedge1); + + Teuchos::ParameterList pl; + pl.set("Scatter Name", "ScatterQEdge1"); + pl.set("Basis", basis_qedge1.getConst()); + pl.set("Dependent Names", names); + pl.set("Dependent Map", names_map); + + Teuchos::RCP> evaluator = lof->buildScatter(pl); + + TEST_EQUALITY(evaluator->evaluatedFields().size(), 1); + + fm.registerEvaluator(evaluator); + fm.requireField(*evaluator->evaluatedFields()[0]); + } + + // support evaluators + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(fieldName1_q1); + names->push_back(fieldName2_q1); + + Teuchos::ParameterList pl; + pl.set("Basis", basis_q1); + pl.set("DOF Names", names); + pl.set("Indexer Names", names); + + Teuchos::RCP> evaluator = lof->buildGather(pl); + + fm.registerEvaluator(evaluator); + } + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(fieldName_qedge1); + + Teuchos::ParameterList pl; + pl.set("Basis", basis_qedge1); + pl.set("DOF Names", names); + pl.set("Indexer Names", names); + + Teuchos::RCP> evaluator = lof->buildGather(pl); + + fm.registerEvaluator(evaluator); + } + + std::vector derivative_dimensions; + derivative_dimensions.push_back(12); + fm.setKokkosExtendedDataTypeDimensions(derivative_dimensions); + + panzer::Traits::SD sd; + sd.worksets_ = work_sets; + + fm.postRegistrationSetup(sd); + + panzer::Traits::PED ped; + ped.gedc->addDataObject("Solution Gather Container", loc); + ped.gedc->addDataObject("Residual Scatter Container", loc); + fm.preEvaluate(ped); + + // run tests + ///////////////////////////////////////////////////////////// + + panzer::Workset &workset = (*work_sets)[0]; + workset.alpha = 0.0; + workset.beta = 2.0; // derivatives multiplied by 2 + workset.time = 0.0; + workset.evaluate_transient_terms = false; + + fm.evaluateFields(workset); + + // test Residual fields + Teuchos::ArrayRCP data; + Teuchos::RCP> f_vec = Teuchos::rcp_dynamic_cast>(b_loc->get_f()); + + // check all the residual values. This is kind of crappy test since it simply checks twice the target + // value and the target. Its this way because you add two entries across elements. + + Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(0))->getLocalData(Teuchos::ptrFromRef(data)); + TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(0)->getLocalNumElements()); + for (size_type i = 0; i < data.size(); i++) + { + double target = 123.0 + myRank; + TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); + } + + Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(1))->getLocalData(Teuchos::ptrFromRef(data)); + TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(1)->getLocalNumElements()); + for (size_type i = 0; i < data.size(); i++) + { + double target = 456.0 + myRank; + TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); + } + + Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(2))->getLocalData(Teuchos::ptrFromRef(data)); + TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(2)->getLocalNumElements()); + for (size_type i = 0; i < data.size(); i++) + { + double target = 789.0 + myRank; + TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); + } + } + + TEUCHOS_UNIT_TEST(block_assembly, scatter_solution_jacobian) + { + +#ifdef HAVE_MPI + Teuchos::RCP> tComm = Teuchos::rcp(new Teuchos::MpiComm(MPI_COMM_WORLD)); +#else + NOPE_PANZER_DOESNT_SUPPORT_SERIAL +#endif + + int myRank = tComm->getRank(); + + const std::size_t workset_size = 4; + const std::string fieldName1_q1 = "U"; + const std::string fieldName2_q1 = "V"; + const std::string fieldName_qedge1 = "B"; + + Teuchos::RCP mesh = buildMesh(2, 2); + + // build input physics block + Teuchos::RCP basis_q1 = buildBasis(workset_size, "Q1"); + Teuchos::RCP basis_qedge1 = buildBasis(workset_size, "QEdge1"); + + Teuchos::RCP ipb = Teuchos::parameterList(); + testInitialization(ipb); + + const int default_int_order = 1; + std::string eBlockID = "eblock-0_0"; + Teuchos::RCP eqset_factory = Teuchos::rcp(new user_app::MyFactory); + panzer::CellData cellData(workset_size, mesh->getCellTopology("eblock-0_0")); + Teuchos::RCP gd = panzer::createGlobalData(); + Teuchos::RCP physicsBlock = + Teuchos::rcp(new PhysicsBlock(ipb, eBlockID, default_int_order, cellData, eqset_factory, gd, false)); + + Teuchos::RCP> work_sets = panzer_stk::buildWorksets(*mesh, physicsBlock->elementBlockID(), + physicsBlock->getWorksetNeeds()); + TEST_EQUALITY(work_sets->size(), 1); + + // build connection manager and field manager + const Teuchos::RCP conn_manager = Teuchos::rcp(new panzer_stk::STKConnManager(mesh)); + RCP dofManager = Teuchos::rcp(new panzer::BlockedDOFManager(conn_manager, MPI_COMM_WORLD)); + + dofManager->addField(fieldName1_q1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_q1->getIntrepid2Basis()))); + dofManager->addField(fieldName2_q1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_q1->getIntrepid2Basis()))); + dofManager->addField(fieldName_qedge1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_qedge1->getIntrepid2Basis()))); + + std::vector> fieldOrder(3); + fieldOrder[0].push_back(fieldName1_q1); + fieldOrder[1].push_back(fieldName_qedge1); + fieldOrder[2].push_back(fieldName2_q1); + dofManager->setFieldOrder(fieldOrder); + + // dofManager->setOrientationsRequired(true); + dofManager->buildGlobalUnknowns(); + + // setup linear object factory + ///////////////////////////////////////////////////////////// + + Teuchos::RCP bt_lof = Teuchos::rcp(new TpetraBlockedLinObjFactoryType(tComm.getConst(), dofManager)); + Teuchos::RCP> lof = bt_lof; + Teuchos::RCP loc = bt_lof->buildGhostedLinearObjContainer(); + bt_lof->initializeGhostedContainer(LinearObjContainer::X | LinearObjContainer::F | LinearObjContainer::Mat, *loc); + loc->initialize(); + + Teuchos::RCP b_loc = Teuchos::rcp_dynamic_cast(loc); + + Teuchos::RCP> p_vec = Teuchos::rcp_dynamic_cast>(b_loc->get_x()); + Thyra::assign(p_vec->getNonconstVectorBlock(0).ptr(), 123.0 + myRank); + Thyra::assign(p_vec->getNonconstVectorBlock(1).ptr(), 456.0 + myRank); + Thyra::assign(p_vec->getNonconstVectorBlock(2).ptr(), 789.0 + myRank); + + // setup field manager, add evaluator under test + ///////////////////////////////////////////////////////////// + + PHX::FieldManager fm; + + std::string resName = ""; + Teuchos::RCP> names_map = + Teuchos::rcp(new std::map); + names_map->insert(std::make_pair(fieldName1_q1, resName + fieldName1_q1)); + names_map->insert(std::make_pair(fieldName2_q1, resName + fieldName2_q1)); + names_map->insert(std::make_pair(fieldName_qedge1, resName + fieldName_qedge1)); + + // evaluators under test + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(resName + fieldName1_q1); + names->push_back(resName + fieldName2_q1); + + Teuchos::ParameterList pl; + pl.set("Scatter Name", "ScatterQ1"); + pl.set("Basis", basis_q1.getConst()); + pl.set("Dependent Names", names); + pl.set("Dependent Map", names_map); + + Teuchos::RCP> evaluator = lof->buildScatter(pl); + + TEST_EQUALITY(evaluator->evaluatedFields().size(), 1); + + fm.registerEvaluator(evaluator); + fm.requireField(*evaluator->evaluatedFields()[0]); + } + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(resName + fieldName_qedge1); + + Teuchos::ParameterList pl; + pl.set("Scatter Name", "ScatterQEdge1"); + pl.set("Basis", basis_qedge1.getConst()); + pl.set("Dependent Names", names); + pl.set("Dependent Map", names_map); + + Teuchos::RCP> evaluator = lof->buildScatter(pl); + + TEST_EQUALITY(evaluator->evaluatedFields().size(), 1); + + fm.registerEvaluator(evaluator); + fm.requireField(*evaluator->evaluatedFields()[0]); + } + + // support evaluators + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(fieldName1_q1); + names->push_back(fieldName2_q1); + + Teuchos::ParameterList pl; + pl.set("Basis", basis_q1); + pl.set("DOF Names", names); + pl.set("Indexer Names", names); + + Teuchos::RCP> evaluator = lof->buildGather(pl); + + fm.registerEvaluator(evaluator); + } + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(fieldName_qedge1); + + Teuchos::ParameterList pl; + pl.set("Basis", basis_qedge1); + pl.set("DOF Names", names); + pl.set("Indexer Names", names); + + Teuchos::RCP> evaluator = lof->buildGather(pl); + + fm.registerEvaluator(evaluator); + } + + std::vector derivative_dimensions; + derivative_dimensions.push_back(12); + fm.setKokkosExtendedDataTypeDimensions(derivative_dimensions); + + panzer::Traits::SD sd; + sd.worksets_ = work_sets; + + fm.postRegistrationSetup(sd); + + panzer::Traits::PED ped; + ped.gedc->addDataObject("Solution Gather Container", loc); + ped.gedc->addDataObject("Residual Scatter Container", loc); + fm.preEvaluate(ped); + + // run tests + ///////////////////////////////////////////////////////////// + + panzer::Workset &workset = (*work_sets)[0]; + workset.alpha = 0.0; + workset.beta = 2.0; // derivatives multiplied by 2 + workset.time = 0.0; + workset.evaluate_transient_terms = false; + + fm.evaluateFields(workset); + + // test Jacobian fields + Teuchos::ArrayRCP data; + Teuchos::RCP> f_vec = Teuchos::rcp_dynamic_cast>(b_loc->get_f()); + + // check all the residual values. This is kind of crappy test since it simply checks twice the target + // value and the target. Its this way because you add two entries across elements. + + Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(0))->getLocalData(Teuchos::ptrFromRef(data)); + TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(0)->getLocalNumElements()); + out << std::endl; + for (size_type i = 0; i < data.size(); i++) + { + double target = 123.0 + myRank; + TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); + out << data[i] << std::endl; + } + + Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(1))->getLocalData(Teuchos::ptrFromRef(data)); + TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(1)->getLocalNumElements()); + out << std::endl; + for (size_type i = 0; i < data.size(); i++) + { + double target = 456.0 + myRank; + TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); + out << data[i] << std::endl; + } + + Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(2))->getLocalData(Teuchos::ptrFromRef(data)); + TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(2)->getLocalNumElements()); + out << std::endl; + for (size_type i = 0; i < data.size(); i++) + { + double target = 789.0 + myRank; + TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); + out << data[i] << std::endl; + } + } + + TEUCHOS_UNIT_TEST(block_assembly, scatter_solution_tangent) + { + +#ifdef HAVE_MPI + Teuchos::RCP> tComm = Teuchos::rcp(new Teuchos::MpiComm(MPI_COMM_WORLD)); +#else + NOPE_PANZER_DOESNT_SUPPORT_SERIAL +#endif + + int myRank = tComm->getRank(); + + const std::size_t workset_size = 4; + const std::string fieldName1_q1 = "U"; + const std::string fieldName2_q1 = "V"; + const std::string fieldName_qedge1 = "B"; + const std::size_t numParams = 2; + + Teuchos::RCP mesh = buildMesh(2, 2); + + // build input physics block + Teuchos::RCP basis_q1 = buildBasis(workset_size, "Q1"); + Teuchos::RCP basis_qedge1 = buildBasis(workset_size, "QEdge1"); + + Teuchos::RCP ipb = Teuchos::parameterList(); + testInitialization(ipb); + + const int default_int_order = 1; + std::string eBlockID = "eblock-0_0"; + Teuchos::RCP eqset_factory = Teuchos::rcp(new user_app::MyFactory); + panzer::CellData cellData(workset_size, mesh->getCellTopology("eblock-0_0")); + Teuchos::RCP gd = panzer::createGlobalData(); + Teuchos::RCP physicsBlock = + Teuchos::rcp(new PhysicsBlock(ipb, eBlockID, default_int_order, cellData, eqset_factory, gd, false)); + + Teuchos::RCP> work_sets = panzer_stk::buildWorksets(*mesh, physicsBlock->elementBlockID(), + physicsBlock->getWorksetNeeds()); + TEST_EQUALITY(work_sets->size(), 1); + + // build connection manager and field manager + const Teuchos::RCP conn_manager = Teuchos::rcp(new panzer_stk::STKConnManager(mesh)); + RCP dofManager = Teuchos::rcp(new panzer::BlockedDOFManager(conn_manager, MPI_COMM_WORLD)); + + dofManager->addField(fieldName1_q1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_q1->getIntrepid2Basis()))); + dofManager->addField(fieldName2_q1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_q1->getIntrepid2Basis()))); + dofManager->addField(fieldName_qedge1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_qedge1->getIntrepid2Basis()))); + + std::vector> fieldOrder(3); + fieldOrder[0].push_back(fieldName1_q1); + fieldOrder[1].push_back(fieldName_qedge1); + fieldOrder[2].push_back(fieldName2_q1); + dofManager->setFieldOrder(fieldOrder); + + // dofManager->setOrientationsRequired(true); + dofManager->buildGlobalUnknowns(); + + // setup linear object factory + ///////////////////////////////////////////////////////////// + Teuchos::RCP bt_lof = Teuchos::rcp(new TpetraBlockedLinObjFactoryType(tComm.getConst(), dofManager)); + Teuchos::RCP> lof = bt_lof; + Teuchos::RCP loc = bt_lof->buildGhostedLinearObjContainer(); + bt_lof->initializeGhostedContainer(LinearObjContainer::X | LinearObjContainer::F, *loc); + loc->initialize(); + + Teuchos::RCP b_loc = Teuchos::rcp_dynamic_cast(loc); + + Teuchos::RCP> p_vec = Teuchos::rcp_dynamic_cast>(b_loc->get_x()); + Thyra::assign(p_vec->getNonconstVectorBlock(0).ptr(), 123.0 + myRank); + Thyra::assign(p_vec->getNonconstVectorBlock(1).ptr(), 456.0 + myRank); + Thyra::assign(p_vec->getNonconstVectorBlock(2).ptr(), 789.0 + myRank); + + std::vector> tangentContainers; + + using LOCPair = panzer::LOCPair_GlobalEvaluationData; + using Teuchos::rcp_dynamic_cast; + + // generate tangent data + for (std::size_t i=0;i(locPair->getGlobalLOC()); + Teuchos::RCP> global_p_vec = Teuchos::rcp_dynamic_cast>(global_bt_loc->get_x()); + Thyra::assign(global_p_vec->getNonconstVectorBlock(0).ptr(), 0.123 + myRank + i); + Thyra::assign(global_p_vec->getNonconstVectorBlock(1).ptr(), 0.456 + myRank + i); + Thyra::assign(global_p_vec->getNonconstVectorBlock(2).ptr(), 0.789 + myRank + i); + + auto ghosted_bt_loc = rcp_dynamic_cast(locPair->getGhostedLOC()); + Teuchos::RCP> ghosted_p_vec = Teuchos::rcp_dynamic_cast>(ghosted_bt_loc->get_x()); + Thyra::assign(ghosted_p_vec->getNonconstVectorBlock(0).ptr(), 0.123 + myRank + i); + Thyra::assign(ghosted_p_vec->getNonconstVectorBlock(1).ptr(), 0.456 + myRank + i); + Thyra::assign(ghosted_p_vec->getNonconstVectorBlock(2).ptr(), 0.789 + myRank + i); + + tangentContainers.push_back(locPair); + } + + // setup field manager, add evaluator under test + ///////////////////////////////////////////////////////////// + + auto fm = Teuchos::rcp(new PHX::FieldManager); + + std::vector derivative_dimensions; + derivative_dimensions.push_back(numParams); + fm->setKokkosExtendedDataTypeDimensions(derivative_dimensions); + + std::string resName = ""; + Teuchos::RCP> names_map = + Teuchos::rcp(new std::map); + names_map->insert(std::make_pair(fieldName1_q1, resName + fieldName1_q1)); + names_map->insert(std::make_pair(fieldName2_q1, resName + fieldName2_q1)); + names_map->insert(std::make_pair(fieldName_qedge1, resName + fieldName_qedge1)); + + // evaluators under test + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(resName + fieldName1_q1); + names->push_back(resName + fieldName2_q1); + + Teuchos::ParameterList pl; + pl.set("Scatter Name", "ScatterQ1"); + pl.set("Basis", basis_q1.getConst()); + pl.set("Dependent Names", names); + pl.set("Dependent Map", names_map); + + Teuchos::RCP> evaluator = lof->buildScatter(pl); + + TEST_EQUALITY(evaluator->evaluatedFields().size(), 1); + + fm->registerEvaluator(evaluator); + fm->requireField(*evaluator->evaluatedFields()[0]); + } + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(resName + fieldName_qedge1); + + Teuchos::ParameterList pl; + pl.set("Scatter Name", "ScatterQEdge1"); + pl.set("Basis", basis_qedge1.getConst()); + pl.set("Dependent Names", names); + pl.set("Dependent Map", names_map); + + Teuchos::RCP> evaluator = lof->buildScatter(pl); + + TEST_EQUALITY(evaluator->evaluatedFields().size(), 1); + + fm->registerEvaluator(evaluator); + fm->requireField(*evaluator->evaluatedFields()[0]); + } + + // support evaluators + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(fieldName1_q1); + names->push_back(fieldName2_q1); + + Teuchos::ParameterList pl; + pl.set("Basis", basis_q1); + pl.set("DOF Names", names); + pl.set("Indexer Names", names); + Teuchos::RCP>> tangent_names = + Teuchos::rcp(new std::vector>(2)); + for (std::size_t i = 0; i < numParams; ++i) + { + std::stringstream ss1, ss2; + ss1 << fieldName1_q1 << " Tangent " << i; + ss2 << fieldName2_q1 << " Tangent " << i; + (*tangent_names)[0].push_back(ss1.str()); + (*tangent_names)[1].push_back(ss2.str()); + } + pl.set("Tangent Names", tangent_names); + + Teuchos::RCP> evaluator = lof->buildGather(pl); + + fm->registerEvaluator(evaluator); + } + for (std::size_t i = 0; i < numParams; ++i) { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + RCP> tangent_names = rcp(new std::vector); + names->push_back(fieldName1_q1); + names->push_back(fieldName2_q1); + { + std::stringstream ss1, ss2; + ss1 << fieldName1_q1 << " Tangent " << i; + ss2 << fieldName2_q1 << " Tangent " << i; + tangent_names->push_back(ss1.str()); + tangent_names->push_back(ss2.str()); + } + + Teuchos::ParameterList pl; + pl.set("Basis", basis_q1); + pl.set("DOF Names", tangent_names); + pl.set("Indexer Names", names); + + std::stringstream ss; + ss << "Tangent Container " << i; + pl.set("Global Data Key", ss.str()); + + Teuchos::RCP> evaluator = + lof->buildGatherTangent(pl); + + fm->registerEvaluator(evaluator); + } + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(fieldName_qedge1); + + Teuchos::ParameterList pl; + pl.set("Basis", basis_qedge1); + pl.set("DOF Names", names); + pl.set("Indexer Names", names); + Teuchos::RCP>> tangent_names = + Teuchos::rcp(new std::vector>(1)); + for (std::size_t i = 0; i < numParams; ++i) + { + std::stringstream ss; + ss << fieldName_qedge1 << " Tangent " << i; + (*tangent_names)[0].push_back(ss.str()); + } + pl.set("Tangent Names", tangent_names); + + Teuchos::RCP> evaluator = lof->buildGather(pl); + + fm->registerEvaluator(evaluator); + } + for (std::size_t i = 0; i < numParams; ++i) { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + RCP> tangent_names = rcp(new std::vector); + names->push_back(fieldName_qedge1); + { + std::stringstream ss; + ss << fieldName_qedge1 << " Tangent " << i; + tangent_names->push_back(ss.str()); + } + + Teuchos::ParameterList pl; + pl.set("Basis", basis_qedge1); + pl.set("DOF Names", tangent_names); + pl.set("Indexer Names", names); + + std::stringstream ss; + ss << "Tangent Container " << i; + pl.set("Global Data Key", ss.str()); + + Teuchos::RCP> evaluator = + lof->buildGatherTangent(pl); + + fm->registerEvaluator(evaluator); + } + + panzer::Traits::SD sd; + sd.worksets_ = work_sets; + + fm->postRegistrationSetup(sd); + + panzer::Traits::PED ped; + ped.gedc->addDataObject("Solution Gather Container", loc); + ped.gedc->addDataObject("Residual Scatter Container", loc); + for (size_t i=0; iaddDataObject(ss.str(), tangentContainers[i]); + } + std::vector params; + std::vector> paramContainers; + for (std::size_t i = 0; iaddDataObject(ss.str(),paramContainer->getGhostedLOC()); + paramContainers.push_back(paramContainer); + } + Teuchos::RCP activeParams = + Teuchos::rcp(new panzer::ParameterList_GlobalEvaluationData(params)); + ped.gedc->addDataObject("PARAMETER_NAMES",activeParams); + fm->preEvaluate(ped); + + // run tests + ///////////////////////////////////////////////////////////// + + panzer::Workset &workset = (*work_sets)[0]; + workset.alpha = 0.0; + workset.beta = 2.0; // derivatives multiplied by 2 + workset.time = 0.0; + workset.evaluate_transient_terms = false; + + fm->evaluateFields(workset); + fm->postEvaluate(0); + + fm = Teuchos::null; + + // test Tangent fields + Teuchos::ArrayRCP data; + Teuchos::RCP> f_vec = Teuchos::rcp_dynamic_cast>(b_loc->get_f()); + + // check all the residual values. This is kind of crappy test since it simply checks twice the target + // value and the target. Its this way because you add two entries across elements. + + Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(0))->getLocalData(Teuchos::ptrFromRef(data)); + TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(0)->getLocalNumElements()); + for (size_type i = 0; i < data.size(); i++) + { + double target = 123.0 + myRank; + TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); + } + + Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(1))->getLocalData(Teuchos::ptrFromRef(data)); + TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(1)->getLocalNumElements()); + for (size_type i = 0; i < data.size(); i++) + { + double target = 456.0 + myRank; + TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); + } + + Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(2))->getLocalData(Teuchos::ptrFromRef(data)); + TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(2)->getLocalNumElements()); + for (size_type i = 0; i < data.size(); i++) + { + double target = 789.0 + myRank; + TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); + } + + for (std::size_t i=0; i> param_f_vec = + Teuchos::rcp_dynamic_cast>( + Teuchos::rcp_dynamic_cast(paramContainers[i]->getGhostedLOC())->get_f()); + + Teuchos::rcp_dynamic_cast>(param_f_vec->getVectorBlock(0))->getLocalData(Teuchos::ptrFromRef(data)); + TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(0)->getLocalNumElements()); + for (size_type j = 0; j < data.size(); j++) + { + double target = .123 + myRank + i; + TEST_ASSERT(data[j] == target || data[j] == 2.0 * target); + } + Teuchos::rcp_dynamic_cast>(param_f_vec->getVectorBlock(1))->getLocalData(Teuchos::ptrFromRef(data)); + TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(1)->getLocalNumElements()); + for (size_type j = 0; j < data.size(); j++) + { + double target = .456 + myRank + i; + TEST_ASSERT(data[j] == target || data[j] == 2.0 * target); + } + Teuchos::rcp_dynamic_cast>(param_f_vec->getVectorBlock(2))->getLocalData(Teuchos::ptrFromRef(data)); + TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(2)->getLocalNumElements()); + for (size_type j = 0; j < data.size(); j++) + { + double target = .789 + myRank + i; + TEST_ASSERT(data[j] == target || data[j] == 2.0 * target); + } + } + } + + Teuchos::RCP buildBasis(std::size_t worksetSize, const std::string &basisName) + { + Teuchos::RCP topo = + Teuchos::rcp(new shards::CellTopology(shards::getCellTopologyData>())); + + panzer::CellData cellData(worksetSize, topo); + return Teuchos::rcp(new panzer::PureBasis(basisName, 1, cellData)); + } + + Teuchos::RCP buildMesh(int elemX, int elemY) + { + RCP pl = rcp(new Teuchos::ParameterList); + pl->set("X Blocks", 1); + pl->set("Y Blocks", 1); + pl->set("X Elements", elemX); + pl->set("Y Elements", elemY); + + panzer_stk::SquareQuadMeshFactory factory; + factory.setParameterList(pl); + RCP mesh = factory.buildUncommitedMesh(MPI_COMM_WORLD); + factory.completeMeshConstruction(*mesh, MPI_COMM_WORLD); + + return mesh; + } + + void testInitialization(const Teuchos::RCP &ipb) + { + // Physics block + ipb->setName("test physics"); + { + Teuchos::ParameterList &p = ipb->sublist("a"); + p.set("Type", "Energy"); + p.set("Prefix", ""); + p.set("Model ID", "solid"); + p.set("Basis Type", "HGrad"); + p.set("Basis Order", 1); + p.set("Integration Order", 1); + } + { + Teuchos::ParameterList &p = ipb->sublist("b"); + p.set("Type", "Energy"); + p.set("Prefix", "ION_"); + p.set("Model ID", "solid"); + p.set("Basis Type", "HCurl"); + p.set("Basis Order", 1); + p.set("Integration Order", 1); + } + } + +} diff --git a/packages/panzer/adapters-stk/test/evaluator_tests/tpetra_scatter_residual.cpp b/packages/panzer/adapters-stk/test/evaluator_tests/tpetra_scatter_residual.cpp index a5e3d75d2362..1e86353a14bc 100644 --- a/packages/panzer/adapters-stk/test/evaluator_tests/tpetra_scatter_residual.cpp +++ b/packages/panzer/adapters-stk/test/evaluator_tests/tpetra_scatter_residual.cpp @@ -20,15 +20,17 @@ using Teuchos::rcp; #include "Teuchos_GlobalMPISession.hpp" #include "Panzer_FieldManagerBuilder.hpp" -#include "Panzer_BlockedDOFManager.hpp" -#include "Panzer_BlockedTpetraLinearObjFactory.hpp" +#include "Panzer_DOFManager.hpp" +#include "Panzer_TpetraLinearObjFactory.hpp" #include "Panzer_PureBasis.hpp" #include "Panzer_BasisIRLayout.hpp" #include "Panzer_Workset.hpp" #include "Panzer_GatherOrientation.hpp" -#include "Panzer_ScatterResidual_BlockedTpetra.hpp" -#include "Panzer_GatherSolution_BlockedTpetra.hpp" +#include "Panzer_ScatterResidual_Tpetra.hpp" +#include "Panzer_GatherSolution_Tpetra.hpp" #include "Panzer_GlobalEvaluationDataContainer.hpp" +#include "Panzer_LOCPair_GlobalEvaluationData.hpp" +#include "Panzer_ParameterList_GlobalEvaluationData.hpp" #include "Panzer_STK_Version.hpp" #include "PanzerAdaptersSTK_config.hpp" @@ -41,7 +43,7 @@ using Teuchos::rcp; #include "Teuchos_OpaqueWrapper.hpp" #include "Thyra_VectorStdOps.hpp" -#include "Thyra_ProductVectorBase.hpp" +#include "Thyra_VectorBase.hpp" #include "Thyra_SpmdVectorBase.hpp" #include "user_app_EquationSetFactory.hpp" @@ -56,14 +58,14 @@ namespace panzer { typedef Teuchos::ArrayRCP::size_type size_type; - using TpetraBlockedLinObjFactoryType = panzer::BlockedTpetraLinearObjFactory; - using TpetraBlockedLinObjContainerType = panzer::BlockedTpetraLinearObjContainer; + using TpetraLinObjFactoryType = panzer::TpetraLinearObjFactory; + using TpetraLinObjContainerType = panzer::TpetraLinearObjContainer; Teuchos::RCP buildBasis(std::size_t worksetSize, const std::string &basisName); void testInitialization(const Teuchos::RCP &ipb); Teuchos::RCP buildMesh(int elemX, int elemY); - TEUCHOS_UNIT_TEST(block_assembly, scatter_solution_residual) + TEUCHOS_UNIT_TEST(assembly, scatter_solution_residual) { #ifdef HAVE_MPI @@ -102,35 +104,32 @@ namespace panzer // build connection manager and field manager const Teuchos::RCP conn_manager = Teuchos::rcp(new panzer_stk::STKConnManager(mesh)); - RCP dofManager = Teuchos::rcp(new panzer::BlockedDOFManager(conn_manager, MPI_COMM_WORLD)); + RCP dofManager = Teuchos::rcp(new panzer::DOFManager(conn_manager, MPI_COMM_WORLD)); dofManager->addField(fieldName1_q1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_q1->getIntrepid2Basis()))); dofManager->addField(fieldName2_q1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_q1->getIntrepid2Basis()))); dofManager->addField(fieldName_qedge1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_qedge1->getIntrepid2Basis()))); - std::vector> fieldOrder(3); - fieldOrder[0].push_back(fieldName1_q1); - fieldOrder[1].push_back(fieldName_qedge1); - fieldOrder[2].push_back(fieldName2_q1); + std::vector fieldOrder; + fieldOrder.push_back(fieldName1_q1); + fieldOrder.push_back(fieldName_qedge1); + fieldOrder.push_back(fieldName2_q1); dofManager->setFieldOrder(fieldOrder); - // dofManager->setOrientationsRequired(true); dofManager->buildGlobalUnknowns(); // setup linear object factory ///////////////////////////////////////////////////////////// - Teuchos::RCP bt_lof = Teuchos::rcp(new TpetraBlockedLinObjFactoryType(tComm.getConst(), dofManager)); - Teuchos::RCP> lof = bt_lof; - Teuchos::RCP loc = bt_lof->buildGhostedLinearObjContainer(); - bt_lof->initializeGhostedContainer(LinearObjContainer::X | LinearObjContainer::F, *loc); + Teuchos::RCP t_lof = Teuchos::rcp(new TpetraLinObjFactoryType(tComm.getConst(), dofManager)); + Teuchos::RCP> lof = t_lof; + Teuchos::RCP loc = t_lof->buildGhostedLinearObjContainer(); + t_lof->initializeGhostedContainer(LinearObjContainer::X | LinearObjContainer::F, *loc); loc->initialize(); - Teuchos::RCP b_loc = Teuchos::rcp_dynamic_cast(loc); + Teuchos::RCP t_loc = Teuchos::rcp_dynamic_cast(loc); - Teuchos::RCP> p_vec = Teuchos::rcp_dynamic_cast>(b_loc->get_x()); - Thyra::assign(p_vec->getNonconstVectorBlock(0).ptr(), 123.0 + myRank); - Thyra::assign(p_vec->getNonconstVectorBlock(1).ptr(), 456.0 + myRank); - Thyra::assign(p_vec->getNonconstVectorBlock(2).ptr(), 789.0 + myRank); + Teuchos::RCP> x_vec = t_loc->get_x_th(); + Thyra::assign(x_vec.ptr(), 123.0 + myRank); // setup field manager, add evaluator under test ///////////////////////////////////////////////////////////// @@ -218,10 +217,6 @@ namespace panzer fm.registerEvaluator(evaluator); } - std::vector derivative_dimensions; - derivative_dimensions.push_back(12); - fm.setKokkosExtendedDataTypeDimensions(derivative_dimensions); - panzer::Traits::SD sd; sd.worksets_ = work_sets; @@ -242,41 +237,27 @@ namespace panzer workset.evaluate_transient_terms = false; fm.evaluateFields(workset); + fm.postEvaluate(0); // test Residual fields Teuchos::ArrayRCP data; - Teuchos::RCP> f_vec = Teuchos::rcp_dynamic_cast>(b_loc->get_f()); + Teuchos::RCP> f_vec = t_loc->get_f_th(); // check all the residual values. This is kind of crappy test since it simply checks twice the target // value and the target. Its this way because you add two entries across elements. - Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(0))->getLocalData(Teuchos::ptrFromRef(data)); - TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(0)->getLocalNumElements()); + Teuchos::rcp_dynamic_cast>(f_vec)->getLocalData(Teuchos::ptrFromRef(data)); for (size_type i = 0; i < data.size(); i++) { double target = 123.0 + myRank; TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); } - Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(1))->getLocalData(Teuchos::ptrFromRef(data)); - TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(1)->getLocalNumElements()); - for (size_type i = 0; i < data.size(); i++) - { - double target = 456.0 + myRank; - TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); - } - - Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(2))->getLocalData(Teuchos::ptrFromRef(data)); - TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(2)->getLocalNumElements()); - for (size_type i = 0; i < data.size(); i++) - { - double target = 789.0 + myRank; - TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); - } } - TEUCHOS_UNIT_TEST(block_assembly, scatter_solution_jacobian) + TEUCHOS_UNIT_TEST(assembly, scatter_solution_jacobian) { + // TODO BWR not checking the jacobian calculation, just the residual part!!! #ifdef HAVE_MPI Teuchos::RCP> tComm = Teuchos::rcp(new Teuchos::MpiComm(MPI_COMM_WORLD)); @@ -314,42 +295,42 @@ namespace panzer // build connection manager and field manager const Teuchos::RCP conn_manager = Teuchos::rcp(new panzer_stk::STKConnManager(mesh)); - RCP dofManager = Teuchos::rcp(new panzer::BlockedDOFManager(conn_manager, MPI_COMM_WORLD)); + RCP dofManager = Teuchos::rcp(new panzer::DOFManager(conn_manager, MPI_COMM_WORLD)); dofManager->addField(fieldName1_q1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_q1->getIntrepid2Basis()))); dofManager->addField(fieldName2_q1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_q1->getIntrepid2Basis()))); dofManager->addField(fieldName_qedge1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_qedge1->getIntrepid2Basis()))); - std::vector> fieldOrder(3); - fieldOrder[0].push_back(fieldName1_q1); - fieldOrder[1].push_back(fieldName_qedge1); - fieldOrder[2].push_back(fieldName2_q1); + std::vector fieldOrder; + fieldOrder.push_back(fieldName1_q1); + fieldOrder.push_back(fieldName_qedge1); + fieldOrder.push_back(fieldName2_q1); dofManager->setFieldOrder(fieldOrder); - // dofManager->setOrientationsRequired(true); dofManager->buildGlobalUnknowns(); // setup linear object factory ///////////////////////////////////////////////////////////// - - Teuchos::RCP bt_lof = Teuchos::rcp(new TpetraBlockedLinObjFactoryType(tComm.getConst(), dofManager)); - Teuchos::RCP> lof = bt_lof; - Teuchos::RCP loc = bt_lof->buildGhostedLinearObjContainer(); - bt_lof->initializeGhostedContainer(LinearObjContainer::X | LinearObjContainer::F | LinearObjContainer::Mat, *loc); + Teuchos::RCP t_lof = Teuchos::rcp(new TpetraLinObjFactoryType(tComm.getConst(), dofManager)); + Teuchos::RCP> lof = t_lof; + Teuchos::RCP loc = t_lof->buildGhostedLinearObjContainer(); + t_lof->initializeGhostedContainer(LinearObjContainer::X | LinearObjContainer::F | LinearObjContainer::Mat, *loc); loc->initialize(); - Teuchos::RCP b_loc = Teuchos::rcp_dynamic_cast(loc); + Teuchos::RCP t_loc = Teuchos::rcp_dynamic_cast(loc); - Teuchos::RCP> p_vec = Teuchos::rcp_dynamic_cast>(b_loc->get_x()); - Thyra::assign(p_vec->getNonconstVectorBlock(0).ptr(), 123.0 + myRank); - Thyra::assign(p_vec->getNonconstVectorBlock(1).ptr(), 456.0 + myRank); - Thyra::assign(p_vec->getNonconstVectorBlock(2).ptr(), 789.0 + myRank); + Teuchos::RCP> x_vec = t_loc->get_x_th(); + Thyra::assign(x_vec.ptr(), 123.0 + myRank); // setup field manager, add evaluator under test ///////////////////////////////////////////////////////////// PHX::FieldManager fm; + std::vector derivative_dimensions; + derivative_dimensions.push_back(12); + fm.setKokkosExtendedDataTypeDimensions(derivative_dimensions); + std::string resName = ""; Teuchos::RCP> names_map = Teuchos::rcp(new std::map); @@ -431,10 +412,6 @@ namespace panzer fm.registerEvaluator(evaluator); } - std::vector derivative_dimensions; - derivative_dimensions.push_back(12); - fm.setKokkosExtendedDataTypeDimensions(derivative_dimensions); - panzer::Traits::SD sd; sd.worksets_ = work_sets; @@ -455,42 +432,351 @@ namespace panzer workset.evaluate_transient_terms = false; fm.evaluateFields(workset); + fm.postEvaluate(0); // test Jacobian fields Teuchos::ArrayRCP data; - Teuchos::RCP> f_vec = Teuchos::rcp_dynamic_cast>(b_loc->get_f()); + Teuchos::RCP> f_vec = t_loc->get_f_th(); // check all the residual values. This is kind of crappy test since it simply checks twice the target // value and the target. Its this way because you add two entries across elements. - Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(0))->getLocalData(Teuchos::ptrFromRef(data)); - TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(0)->getLocalNumElements()); - out << std::endl; + Teuchos::rcp_dynamic_cast>(f_vec)->getLocalData(Teuchos::ptrFromRef(data)); for (size_type i = 0; i < data.size(); i++) { double target = 123.0 + myRank; TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); - out << data[i] << std::endl; } - Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(1))->getLocalData(Teuchos::ptrFromRef(data)); - TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(1)->getLocalNumElements()); - out << std::endl; - for (size_type i = 0; i < data.size(); i++) + } + + TEUCHOS_UNIT_TEST(assembly, scatter_solution_tangent) + { + +#ifdef HAVE_MPI + Teuchos::RCP> tComm = Teuchos::rcp(new Teuchos::MpiComm(MPI_COMM_WORLD)); +#else + NOPE_PANZER_DOESNT_SUPPORT_SERIAL +#endif + + int myRank = tComm->getRank(); + + const std::size_t workset_size = 4; + const std::string fieldName1_q1 = "U"; + const std::string fieldName2_q1 = "V"; + const std::string fieldName_qedge1 = "B"; + const std::size_t numParams = 3; + + Teuchos::RCP mesh = buildMesh(2, 2); + + // build input physics block + Teuchos::RCP basis_q1 = buildBasis(workset_size, "Q1"); + Teuchos::RCP basis_qedge1 = buildBasis(workset_size, "QEdge1"); + + Teuchos::RCP ipb = Teuchos::parameterList(); + testInitialization(ipb); + + const int default_int_order = 1; + std::string eBlockID = "eblock-0_0"; + Teuchos::RCP eqset_factory = Teuchos::rcp(new user_app::MyFactory); + panzer::CellData cellData(workset_size, mesh->getCellTopology("eblock-0_0")); + Teuchos::RCP gd = panzer::createGlobalData(); + Teuchos::RCP physicsBlock = + Teuchos::rcp(new PhysicsBlock(ipb, eBlockID, default_int_order, cellData, eqset_factory, gd, false)); + + Teuchos::RCP> work_sets = panzer_stk::buildWorksets(*mesh, physicsBlock->elementBlockID(), + physicsBlock->getWorksetNeeds()); + TEST_EQUALITY(work_sets->size(), 1); + + // build connection manager and field manager + const Teuchos::RCP conn_manager = Teuchos::rcp(new panzer_stk::STKConnManager(mesh)); + RCP dofManager = Teuchos::rcp(new panzer::DOFManager(conn_manager, MPI_COMM_WORLD)); + + dofManager->addField(fieldName1_q1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_q1->getIntrepid2Basis()))); + dofManager->addField(fieldName2_q1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_q1->getIntrepid2Basis()))); + dofManager->addField(fieldName_qedge1, Teuchos::rcp(new panzer::Intrepid2FieldPattern(basis_qedge1->getIntrepid2Basis()))); + + std::vector fieldOrder; + fieldOrder.push_back(fieldName1_q1); + fieldOrder.push_back(fieldName_qedge1); + fieldOrder.push_back(fieldName2_q1); + dofManager->setFieldOrder(fieldOrder); + + dofManager->buildGlobalUnknowns(); + + // setup linear object factory + ///////////////////////////////////////////////////////////// + Teuchos::RCP t_lof = Teuchos::rcp(new TpetraLinObjFactoryType(tComm.getConst(), dofManager)); + Teuchos::RCP> lof = t_lof; + Teuchos::RCP loc = t_lof->buildGhostedLinearObjContainer(); + t_lof->initializeGhostedContainer(LinearObjContainer::X | LinearObjContainer::F , *loc); + loc->initialize(); + + Teuchos::RCP t_loc = Teuchos::rcp_dynamic_cast(loc); + Teuchos::RCP> x_vec = t_loc->get_x_th(); + Thyra::assign(x_vec.ptr(), 123.0 + myRank); + + std::vector> tangentContainers; + + using LOCPair = panzer::LOCPair_GlobalEvaluationData; + using Teuchos::rcp_dynamic_cast; + + // generate tangent data + for (std::size_t i=0;i(locPair->getGlobalLOC()); + Teuchos::RCP> global_x_vec = global_t_loc->get_x_th(); + Thyra::assign(global_x_vec.ptr(), 0.123 + myRank + i); + + auto ghosted_t_loc = rcp_dynamic_cast(locPair->getGhostedLOC()); + Teuchos::RCP> ghosted_x_vec = ghosted_t_loc->get_x_th(); + Thyra::assign(ghosted_x_vec.ptr(), 0.123 + myRank + i); + + tangentContainers.push_back(locPair); + } + + // setup field manager, add evaluator under test + ///////////////////////////////////////////////////////////// + + auto fm = Teuchos::rcp(new PHX::FieldManager); + + std::vector derivative_dimensions; + derivative_dimensions.push_back(numParams); + fm->setKokkosExtendedDataTypeDimensions(derivative_dimensions); + + std::string resName = ""; + Teuchos::RCP> names_map = + Teuchos::rcp(new std::map); + names_map->insert(std::make_pair(fieldName1_q1, resName + fieldName1_q1)); + names_map->insert(std::make_pair(fieldName2_q1, resName + fieldName2_q1)); + names_map->insert(std::make_pair(fieldName_qedge1, resName + fieldName_qedge1)); + + // Guide to what's happening in this test + // 1) U,V,B gathers request tangent fields so those are first gathered with gatherTangent + // 2) When U,V,B gathers occur, the tangents are stored as derivatives. The first tangent is the first derivative and so on. + // 3) U,V,B are overloaded to also be the residual fields we are scattering + // 4) This means their derivatives, e.g., U.dx(i) are considered to be dfdp_i -> derivatives of the residuals w.r.t. parameters. + // 5) dfdp_i = f.dx(i) so the number of tangents is the number of params + + // evaluators under test { - double target = 456.0 + myRank; - TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); - out << data[i] << std::endl; + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(resName + fieldName1_q1); + names->push_back(resName + fieldName2_q1); + + Teuchos::ParameterList pl; + pl.set("Scatter Name", "ScatterQ1"); + pl.set("Basis", basis_q1.getConst()); + pl.set("Dependent Names", names); + pl.set("Dependent Map", names_map); + + Teuchos::RCP> evaluator = lof->buildScatter(pl); + + TEST_EQUALITY(evaluator->evaluatedFields().size(), 1); + + fm->registerEvaluator(evaluator); + fm->requireField(*evaluator->evaluatedFields()[0]); } + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(resName + fieldName_qedge1); - Teuchos::rcp_dynamic_cast>(f_vec->getVectorBlock(2))->getLocalData(Teuchos::ptrFromRef(data)); - TEST_EQUALITY(static_cast(data.size()), b_loc->getMapForBlock(2)->getLocalNumElements()); - out << std::endl; - for (size_type i = 0; i < data.size(); i++) + Teuchos::ParameterList pl; + pl.set("Scatter Name", "ScatterQEdge1"); + pl.set("Basis", basis_qedge1.getConst()); + pl.set("Dependent Names", names); + pl.set("Dependent Map", names_map); + + Teuchos::RCP> evaluator = lof->buildScatter(pl); + + TEST_EQUALITY(evaluator->evaluatedFields().size(), 1); + + fm->registerEvaluator(evaluator); + fm->requireField(*evaluator->evaluatedFields()[0]); + } + + // support evaluators { - double target = 789.0 + myRank; - TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); - out << data[i] << std::endl; + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(fieldName1_q1); + names->push_back(fieldName2_q1); + + Teuchos::ParameterList pl; + pl.set("Basis", basis_q1); + pl.set("DOF Names", names); + pl.set("Indexer Names", names); + Teuchos::RCP>> tangent_names = + Teuchos::rcp(new std::vector>(2)); + for (std::size_t i = 0; i < numParams; ++i) + { + std::stringstream ss1, ss2; + ss1 << fieldName1_q1 << " Tangent " << i; + ss2 << fieldName2_q1 << " Tangent " << i; + (*tangent_names)[0].push_back(ss1.str()); + (*tangent_names)[1].push_back(ss2.str()); + } + pl.set("Tangent Names", tangent_names); + + Teuchos::RCP> evaluator = lof->buildGather(pl); + + fm->registerEvaluator(evaluator); + } + for (std::size_t i = 0; i < numParams; ++i) { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + RCP> tangent_names = rcp(new std::vector); + names->push_back(fieldName1_q1); + names->push_back(fieldName2_q1); + { + std::stringstream ss1, ss2; + ss1 << fieldName1_q1 << " Tangent " << i; + ss2 << fieldName2_q1 << " Tangent " << i; + tangent_names->push_back(ss1.str()); + tangent_names->push_back(ss2.str()); + } + + Teuchos::ParameterList pl; + pl.set("Basis", basis_q1); + pl.set("DOF Names", tangent_names); + pl.set("Indexer Names", names); + + std::stringstream ss; + ss << "Tangent Container " << i; + pl.set("Global Data Key", ss.str()); + + Teuchos::RCP> evaluator = + lof->buildGatherTangent(pl); + + fm->registerEvaluator(evaluator); + } + { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + names->push_back(fieldName_qedge1); + + Teuchos::ParameterList pl; + pl.set("Basis", basis_qedge1); + pl.set("DOF Names", names); + pl.set("Indexer Names", names); + Teuchos::RCP>> tangent_names = + Teuchos::rcp(new std::vector>(1)); + for (std::size_t i = 0; i < numParams; ++i) + { + std::stringstream ss; + ss << fieldName_qedge1 << " Tangent " << i; + (*tangent_names)[0].push_back(ss.str()); + } + pl.set("Tangent Names", tangent_names); + + Teuchos::RCP> evaluator = lof->buildGather(pl); + + fm->registerEvaluator(evaluator); + } + for (std::size_t i = 0; i < numParams; ++i) { + using Teuchos::RCP; + using Teuchos::rcp; + RCP> names = rcp(new std::vector); + RCP> tangent_names = rcp(new std::vector); + names->push_back(fieldName_qedge1); + { + std::stringstream ss; + ss << fieldName_qedge1 << " Tangent " << i; + tangent_names->push_back(ss.str()); + } + + Teuchos::ParameterList pl; + pl.set("Basis", basis_qedge1); + pl.set("DOF Names", tangent_names); + pl.set("Indexer Names", names); + + std::stringstream ss; + ss << "Tangent Container " << i; + pl.set("Global Data Key", ss.str()); + + Teuchos::RCP> evaluator = + lof->buildGatherTangent(pl); + + fm->registerEvaluator(evaluator); + } + panzer::Traits::SD sd; + sd.worksets_ = work_sets; + + fm->postRegistrationSetup(sd); + + panzer::Traits::PED ped; + ped.gedc->addDataObject("Solution Gather Container", loc); + ped.gedc->addDataObject("Residual Scatter Container", loc); + for (size_t i=0; iaddDataObject(ss.str(), tangentContainers[i]); + } + std::vector params; + std::vector> paramContainers; + for (std::size_t i = 0; iaddDataObject(ss.str(),paramContainer->getGhostedLOC()); + paramContainers.push_back(paramContainer); + } + Teuchos::RCP activeParams = + Teuchos::rcp(new panzer::ParameterList_GlobalEvaluationData(params)); + ped.gedc->addDataObject("PARAMETER_NAMES",activeParams); + + fm->preEvaluate(ped); + + // run tests + ///////////////////////////////////////////////////////////// + + panzer::Workset &workset = (*work_sets)[0]; + workset.alpha = 0.0; + workset.beta = 2.0; // derivatives multiplied by 2 + workset.time = 0.0; + workset.evaluate_transient_terms = false; + + fm->evaluateFields(workset); + fm->postEvaluate(0); + + fm = Teuchos::null; + + // test Tangent fields + { + Teuchos::ArrayRCP data; + Teuchos::RCP> f_vec = t_loc->get_f_th(); + + // check all the residual values. This is kind of crappy test since it simply checks twice the target + // value and the target. Its this way because you add two entries across elements. + + Teuchos::rcp_dynamic_cast>(f_vec)->getLocalData(Teuchos::ptrFromRef(data)); + for (size_type i = 0; i < data.size(); i++) + { + double target = 123.0 + myRank; + TEST_ASSERT(data[i] == target || data[i] == 2.0 * target); + } + } + for (std::size_t i=0; i data; + Teuchos::RCP> f_vec = Teuchos::rcp_dynamic_cast(paramContainers[i]->getGhostedLOC())->get_f_th(); + Teuchos::rcp_dynamic_cast>(f_vec)->getLocalData(Teuchos::ptrFromRef(data)); + + for (size_type j = 0; j < data.size(); ++j) + { + const double target = .123 + myRank + i; + TEST_ASSERT(data[j] == target || data[j] == 2.0 * target); + } } } diff --git a/packages/panzer/disc-fe/src/Panzer_ModelEvaluator_impl.hpp b/packages/panzer/disc-fe/src/Panzer_ModelEvaluator_impl.hpp index 0ee307c88733..1f3101881359 100644 --- a/packages/panzer/disc-fe/src/Panzer_ModelEvaluator_impl.hpp +++ b/packages/panzer/disc-fe/src/Panzer_ModelEvaluator_impl.hpp @@ -1763,8 +1763,11 @@ evalModelImpl_basic_dgdp_scalar(const Thyra::ModelEvaluatorBase::InArgs RCP > resp = rcp_dynamic_cast >( responseLibrary_->getResponse(responseName)); - resp->setVector(vec); - is_active = true; + + if (nonnull(resp)) { + resp->setVector(vec); + is_active = true; + } } } diff --git a/packages/panzer/disc-fe/src/evaluators/Panzer_GatherSolution_BlockedTpetra_impl.hpp b/packages/panzer/disc-fe/src/evaluators/Panzer_GatherSolution_BlockedTpetra_impl.hpp index 52488585d37e..9c8533419013 100644 --- a/packages/panzer/disc-fe/src/evaluators/Panzer_GatherSolution_BlockedTpetra_impl.hpp +++ b/packages/panzer/disc-fe/src/evaluators/Panzer_GatherSolution_BlockedTpetra_impl.hpp @@ -305,9 +305,6 @@ postRegistrationSetup(typename TRAITS::SetupData d, maxElementBlockGIDCount); // Set up storage for tangentFields using view of views - // We also need storage for the number of tangent fields associated with - // each gatherField - if (has_tangent_fields_) { size_t inner_vector_max_size = 0; diff --git a/packages/panzer/disc-fe/src/evaluators/Panzer_GatherSolution_Tpetra_impl.hpp b/packages/panzer/disc-fe/src/evaluators/Panzer_GatherSolution_Tpetra_impl.hpp index bdff0f73574e..21be837adf3e 100644 --- a/packages/panzer/disc-fe/src/evaluators/Panzer_GatherSolution_Tpetra_impl.hpp +++ b/packages/panzer/disc-fe/src/evaluators/Panzer_GatherSolution_Tpetra_impl.hpp @@ -263,8 +263,8 @@ postRegistrationSetup(typename TRAITS::SetupData /* d */, } Kokkos::deep_copy(tangentInnerVectorSizes_,tangentInnerVectorSizes_host); - gatherFieldsVoV_.initialize("GatherSolution_Teptra::gatherFieldsVoV_",gatherFields_.size()); - tangentFieldsVoV_.initialize("GatherSolution_Teptra::tangentFieldsVoV_",gatherFields_.size(),inner_vector_max_size); + gatherFieldsVoV_.initialize("GatherSolution_Tpetra::gatherFieldsVoV_",gatherFields_.size()); + tangentFieldsVoV_.initialize("GatherSolution_Tpetra::tangentFieldsVoV_",gatherFields_.size(),inner_vector_max_size); for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) { const std::string& fieldName = indexerNames_[fd]; diff --git a/packages/panzer/disc-fe/src/evaluators/Panzer_GatherTangent_BlockedTpetra.hpp b/packages/panzer/disc-fe/src/evaluators/Panzer_GatherTangent_BlockedTpetra.hpp index bb0522da313a..382c27d64be0 100644 --- a/packages/panzer/disc-fe/src/evaluators/Panzer_GatherTangent_BlockedTpetra.hpp +++ b/packages/panzer/disc-fe/src/evaluators/Panzer_GatherTangent_BlockedTpetra.hpp @@ -51,7 +51,7 @@ class GatherTangent_BlockedTpetra public: GatherTangent_BlockedTpetra(const Teuchos::RCP & indexer) - : gidIndexer_(indexer) {} + : globalIndexer_(indexer) {} GatherTangent_BlockedTpetra(const Teuchos::RCP & indexer, const Teuchos::ParameterList& p); @@ -64,13 +64,13 @@ class GatherTangent_BlockedTpetra void evaluateFields(typename TRAITS::EvalData d); virtual Teuchos::RCP clone(const Teuchos::ParameterList & pl) const - { return Teuchos::rcp(new GatherTangent_BlockedTpetra(gidIndexer_,pl)); } + { return Teuchos::rcp(new GatherTangent_BlockedTpetra(globalIndexer_,pl)); } private: // We always use RealType for gathering as we never compute derivatives for this evaluator - //typedef typename panzer::Traits::RealType ScalarT; - typedef typename EvalT::ScalarT ScalarT; + typedef typename panzer::Traits::RealType ScalarT; + //typedef typename EvalT::ScalarT ScalarT; typedef BlockedTpetraLinearObjContainer ContainerType; typedef Tpetra::Vector VectorType; @@ -82,10 +82,17 @@ class GatherTangent_BlockedTpetra // maps the local (field,element,basis) triplet to a global ID // for scattering - Teuchos::RCP gidIndexer_; + Teuchos::RCP globalIndexer_; std::vector fieldIds_; // field IDs needing mapping + //! Vector of global indexers, one for each field to gather, respectively + std::vector> fieldGlobalIndexers_; + + //! Returns the index to the Thyra ProductVector sub-block. Size + //! of number of fields to gather + std::vector productVectorBlockIndex_; + std::vector< PHX::MDField > gatherFields_; Teuchos::RCP > indexerNames_; @@ -94,6 +101,12 @@ class GatherTangent_BlockedTpetra Teuchos::RCP > blockedContainer_; + //! Local indices for unknowns + PHX::View worksetLIDs_; + + //! Offset into the cell lids for each field + std::vector> fieldOffsets_; + GatherTangent_BlockedTpetra(); }; diff --git a/packages/panzer/disc-fe/src/evaluators/Panzer_GatherTangent_BlockedTpetra_impl.hpp b/packages/panzer/disc-fe/src/evaluators/Panzer_GatherTangent_BlockedTpetra_impl.hpp index adf75295efe8..6673e3bc8553 100644 --- a/packages/panzer/disc-fe/src/evaluators/Panzer_GatherTangent_BlockedTpetra_impl.hpp +++ b/packages/panzer/disc-fe/src/evaluators/Panzer_GatherTangent_BlockedTpetra_impl.hpp @@ -18,6 +18,7 @@ #include "Panzer_BlockedDOFManager.hpp" #include "Panzer_PureBasis.hpp" #include "Panzer_TpetraLinearObjFactory.hpp" +#include "Panzer_LOCPair_GlobalEvaluationData.hpp" #include "Panzer_BlockedTpetraLinearObjContainer.hpp" #include "Panzer_GlobalEvaluationDataContainer.hpp" @@ -33,7 +34,7 @@ panzer::GatherTangent_BlockedTpetra:: GatherTangent_BlockedTpetra( const Teuchos::RCP & indexer, const Teuchos::ParameterList& p) - : gidIndexer_(indexer) + : globalIndexer_(indexer) , useTimeDerivativeSolutionVector_(false) , globalDataKey_("Tangent Gather Container") { @@ -50,6 +51,10 @@ GatherTangent_BlockedTpetra( gatherFields_[fd] = PHX::MDField(names[fd],basis->functional); this->addEvaluatedField(gatherFields_[fd]); + // If blockedContainer_ is null, the evalaution is a no-op. In this + // case we need to preserve zero initial value. Do this by not + // sharing. + this->addUnsharedField(gatherFields_[fd].fieldTag().clone()); } if (p.isType("Use Time Derivative Solution Vector")) @@ -64,19 +69,44 @@ GatherTangent_BlockedTpetra( // ********************************************************************** template void panzer::GatherTangent_BlockedTpetra:: -postRegistrationSetup(typename TRAITS::SetupData /* d */, +postRegistrationSetup(typename TRAITS::SetupData d, PHX::FieldManager& /* fm */) { TEUCHOS_ASSERT(gatherFields_.size() == indexerNames_->size()); - fieldIds_.resize(gatherFields_.size()); + const Workset & workset_0 = (*d.worksets_)[0]; + const std::string blockId = this->wda(workset_0).block_id; + fieldIds_.resize(gatherFields_.size()); + fieldOffsets_.resize(gatherFields_.size()); + fieldGlobalIndexers_.resize(gatherFields_.size()); + productVectorBlockIndex_.resize(gatherFields_.size()); + int maxElementBlockGIDCount = -1; for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) { // get field ID from DOF manager const std::string& fieldName = (*indexerNames_)[fd]; - fieldIds_[fd] = gidIndexer_->getFieldNum(fieldName); + const int globalFieldNum = globalIndexer_->getFieldNum(fieldName); // Field number in the aggregate BlockDOFManager + productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum); + fieldGlobalIndexers_[fd] = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]]; + fieldIds_[fd] = fieldGlobalIndexers_[fd]->getFieldNum(fieldName); // Field number in the sub-global-indexer + + const std::vector& offsets = fieldGlobalIndexers_[fd]->getGIDFieldOffsets(blockId,fieldIds_[fd]); + fieldOffsets_[fd] = PHX::View("GatherSolution_BlockedTpetra(Residual):fieldOffsets",offsets.size()); + auto hostFieldOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]); + for(std::size_t i=0; i < offsets.size(); ++i) + hostFieldOffsets(i) = offsets[i]; + Kokkos::deep_copy(fieldOffsets_[fd],hostFieldOffsets); + + maxElementBlockGIDCount = std::max(fieldGlobalIndexers_[fd]->getElementBlockGIDCount(blockId),maxElementBlockGIDCount); } + // We will use one workset lid view for all fields, but has to be + // sized big enough to hold the largest elementBlockGIDCount in the + // ProductVector. + worksetLIDs_ = PHX::View("GatherSolution_BlockedTpetra(Residual):worksetLIDs", + gatherFields_[0].extent(0), + maxElementBlockGIDCount); + indexerNames_ = Teuchos::null; // Don't need this anymore } @@ -87,7 +117,18 @@ preEvaluate(typename TRAITS::PreEvalData d) { // try to extract linear object container if (d.gedc->containsDataObject(globalDataKey_)) { - blockedContainer_ = Teuchos::rcp_dynamic_cast(d.gedc->getDataObject(globalDataKey_),true); + Teuchos::RCP ged = d.gedc->getDataObject(globalDataKey_); + Teuchos::RCP loc_pair = + Teuchos::rcp_dynamic_cast(ged); + + if(loc_pair!=Teuchos::null) { + Teuchos::RCP loc = loc_pair->getGhostedLOC(); + blockedContainer_ = Teuchos::rcp_dynamic_cast(loc,true); + } + + if(blockedContainer_==Teuchos::null) { + blockedContainer_ = Teuchos::rcp_dynamic_cast(ged,true); + } } } @@ -96,73 +137,50 @@ template :: evaluateFields(typename TRAITS::EvalData workset) { - using Teuchos::RCP; - using Teuchos::ArrayRCP; - using Teuchos::ptrFromRef; - using Teuchos::rcp_dynamic_cast; - - using Thyra::VectorBase; - using Thyra::SpmdVectorBase; - using Thyra::ProductVectorBase; - - // If blockedContainer_ was not initialized, then no global evaluation data - // container was set, in which case this evaluator becomes a no-op - if (blockedContainer_ == Teuchos::null) - return; - - Teuchos::FancyOStream out(Teuchos::rcpFromRef(std::cout)); - out.setShowProcRank(true); - out.setOutputToRootOnly(-1); - - std::vector > GIDs; - std::vector LIDs; - - // for convenience pull out some objects from workset - std::string blockId = this->wda(workset).block_id; - const std::vector & localCellIds = this->wda(workset).cell_local_ids; - - Teuchos::RCP > x; - if (useTimeDerivativeSolutionVector_) - x = rcp_dynamic_cast >(blockedContainer_->get_dxdt()); - else - x = rcp_dynamic_cast >(blockedContainer_->get_x()); - - // gather operation for each cell in workset - for(std::size_t worksetCellIndex=0;worksetCellIndexgetElementGIDsPair(cellLocalId,GIDs,blockId); - - // caculate the local IDs for this element - LIDs.resize(GIDs.size()); - for(std::size_t i=0;i x_map = blockedContainer_->getMapForBlock(GIDs[i].first); - - LIDs[i] = x_map->getLocalElement(GIDs[i].second); + using Teuchos::RCP; + using Teuchos::rcp_dynamic_cast; + using Thyra::VectorBase; + using Thyra::ProductVectorBase; + + // If blockedContainer_ was not initialized, then no global evaluation data + // container was set, in which case this evaluator becomes a no-op + if (blockedContainer_ == Teuchos::null) return; + + const PHX::View& localCellIds = this->wda(workset).cell_local_ids_k; + + RCP> thyraBlockSolution; + if (useTimeDerivativeSolutionVector_) + thyraBlockSolution = rcp_dynamic_cast>(blockedContainer_->get_dxdt(),true); + else + thyraBlockSolution = rcp_dynamic_cast>(blockedContainer_->get_x(),true); + + // Loop over gathered fields + int currentWorksetLIDSubBlock = -1; + for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) { + // workset LIDs only change for different sub blocks + if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) { + const std::string blockId = this->wda(workset).block_id; + const int num_dofs = fieldGlobalIndexers_[fieldIndex]->getElementBlockGIDCount(blockId); + fieldGlobalIndexers_[fieldIndex]->getElementLIDs(localCellIds,worksetLIDs_,num_dofs); + currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex]; + } + + const auto& tpetraSolution = *((rcp_dynamic_cast>(thyraBlockSolution->getNonconstVectorBlock(productVectorBlockIndex_[fieldIndex]),true))->getTpetraVector()); + const auto& kokkosSolution = tpetraSolution.getLocalViewDevice(Tpetra::Access::ReadOnly); + + // Class data fields for lambda capture + const auto& fieldOffsets = fieldOffsets_[fieldIndex]; + const auto& worksetLIDs = worksetLIDs_; + const auto& fieldValues = gatherFields_[fieldIndex]; + + Kokkos::parallel_for(Kokkos::RangePolicy(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) { + for(int basis=0; basis < static_cast(fieldOffsets.size()); ++basis) { + const int lid = worksetLIDs(cell,fieldOffsets(basis)); + fieldValues(cell,basis) = kokkosSolution(lid,0); } + }); + } - // loop over the fields to be gathered - Teuchos::ArrayRCP local_x; - for (std::size_t fieldIndex=0; fieldIndexgetFieldBlock(fieldNum); - - // grab local data for inputing - RCP > block_x = rcp_dynamic_cast >(x->getNonconstVectorBlock(indexerId)); - block_x->getLocalData(ptrFromRef(local_x)); - - const std::vector & elmtOffset = gidIndexer_->getGIDFieldOffsets(blockId,fieldNum); - - // loop over basis functions and fill the fields - for(std::size_t basis=0;basis ScatterResidual_BlockedTpetra(); }; +// ************************************************************** +// Tangent +// ************************************************************** +template +class ScatterResidual_BlockedTpetra + : public panzer::EvaluatorWithBaseImpl, + public PHX::EvaluatorDerived, + public panzer::CloneableEvaluator { + +public: + ScatterResidual_BlockedTpetra(const Teuchos::RCP & indexer) + : globalIndexer_(indexer) {} + + ScatterResidual_BlockedTpetra(const Teuchos::RCP & indexer, + const Teuchos::ParameterList& p); + + void postRegistrationSetup(typename TRAITS::SetupData d, + PHX::FieldManager& vm); + + void preEvaluate(typename TRAITS::PreEvalData d); + + void evaluateFields(typename TRAITS::EvalData workset); + + virtual Teuchos::RCP clone(const Teuchos::ParameterList & pl) const + { return Teuchos::rcp(new ScatterResidual_BlockedTpetra(globalIndexer_,pl)); } + +private: + typedef typename panzer::Traits::Tangent::ScalarT ScalarT; + typedef typename TRAITS::RealType RealType; + + typedef BlockedTpetraLinearObjContainer ContainerType; + typedef Tpetra::Vector VectorType; + typedef Tpetra::CrsMatrix CrsMatrixType; + typedef Tpetra::CrsGraph CrsGraphType; + typedef Tpetra::Map MapType; + typedef Tpetra::Import ImportType; + typedef Tpetra::Export ExportType; + + //! Dummy evalauted field so that the evaluator will have something to do + Teuchos::RCP scatterHolder_; + + //! Fields that need to be scattered will be put in this vector + std::vector< PHX::MDField > scatterFields_; + + //! Maps the local (field,element,basis) triplet to a global ID for scattering + Teuchos::RCP globalIndexer_; + + //! Vector of global indexers, one for each scattered field respectively + std::vector> fieldGlobalIndexers_; + + //! Field IDs in the local product vector block (not global field id) + std::vector fieldIds_; + + //! Returns the index into the Thyra ProductVector sub-block. Size + //! of number of fields to scatter + std::vector productVectorBlockIndex_; + + // This maps the scattered field names to the DOF manager field + // For instance a Navier-Stokes map might look like + // fieldMap_["RESIDUAL_Velocity"] --> "Velocity" + // fieldMap_["RESIDUAL_Pressure"] --> "Pressure" + Teuchos::RCP > fieldMap_; + + std::string globalDataKey_; // what global data does this fill? + Teuchos::RCP > blockedContainer_; + + /// Storage for the tangent data + PHX::ViewOfViews<2,Kokkos::View> dfdpFieldsVoV_; + + //! Local indices for unknowns + PHX::View worksetLIDs_; + + //! Offset into the cell lids for each field + std::vector> fieldOffsets_; + + ScatterResidual_BlockedTpetra(); +}; + } #ifdef Panzer_BUILD_HESSIAN_SUPPORT diff --git a/packages/panzer/disc-fe/src/evaluators/Panzer_ScatterResidual_BlockedTpetra_impl.hpp b/packages/panzer/disc-fe/src/evaluators/Panzer_ScatterResidual_BlockedTpetra_impl.hpp index 3e8633c7f3ef..3bb426ec0d34 100644 --- a/packages/panzer/disc-fe/src/evaluators/Panzer_ScatterResidual_BlockedTpetra_impl.hpp +++ b/packages/panzer/disc-fe/src/evaluators/Panzer_ScatterResidual_BlockedTpetra_impl.hpp @@ -22,6 +22,7 @@ #include "Panzer_BlockedTpetraLinearObjContainer.hpp" #include "Panzer_LOCPair_GlobalEvaluationData.hpp" #include "Panzer_HashUtils.hpp" +#include "Panzer_ParameterList_GlobalEvaluationData.hpp" #include "Panzer_GlobalEvaluationDataContainer.hpp" #include "Thyra_ProductVectorBase.hpp" @@ -472,6 +473,171 @@ evaluateFields(typename TRAITS::EvalData workset) } +// ********************************************************************** +// Specialization: Tangent +// ********************************************************************** + +template +panzer::ScatterResidual_BlockedTpetra:: +ScatterResidual_BlockedTpetra(const Teuchos::RCP & indexer, + const Teuchos::ParameterList& p) + : globalIndexer_(indexer) + , globalDataKey_("Residual Scatter Container") +{ + std::string scatterName = p.get("Scatter Name"); + scatterHolder_ = + Teuchos::rcp(new PHX::Tag(scatterName,Teuchos::rcp(new PHX::MDALayout(0)))); + + // get names to be evaluated + const std::vector& names = + *(p.get< Teuchos::RCP< std::vector > >("Dependent Names")); + + // grab map from evaluated names to field names + fieldMap_ = p.get< Teuchos::RCP< std::map > >("Dependent Map"); + + Teuchos::RCP dl = + p.get< Teuchos::RCP >("Basis")->functional; + + // build the vector of fields that this is dependent on + scatterFields_.resize(names.size()); + for (std::size_t eq = 0; eq < names.size(); ++eq) { + scatterFields_[eq] = PHX::MDField(names[eq],dl); + + // tell the field manager that we depend on this field + this->addDependentField(scatterFields_[eq]); + } + + // this is what this evaluator provides + this->addEvaluatedField(*scatterHolder_); + + if (p.isType("Global Data Key")) + globalDataKey_ = p.get("Global Data Key"); + + this->setName(scatterName+" Scatter Residual (Tangent)"); +} + +// ********************************************************************** +template +void panzer::ScatterResidual_BlockedTpetra:: +postRegistrationSetup(typename TRAITS::SetupData d, + PHX::FieldManager& /* fm */) +{ + const Workset & workset_0 = (*d.worksets_)[0]; + const std::string blockId = this->wda(workset_0).block_id; + + fieldIds_.resize(scatterFields_.size()); + fieldOffsets_.resize(scatterFields_.size()); + fieldGlobalIndexers_.resize(scatterFields_.size()); + productVectorBlockIndex_.resize(scatterFields_.size()); + int maxElementBlockGIDCount = -1; + for(std::size_t fd=0; fd < scatterFields_.size(); ++fd) { + const std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second; + const int globalFieldNum = globalIndexer_->getFieldNum(fieldName); // Field number in the aggregate BlockDOFManager + productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum); + fieldGlobalIndexers_[fd] = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]]; + fieldIds_[fd] = fieldGlobalIndexers_[fd]->getFieldNum(fieldName); // Field number in the sub-global-indexer + + const std::vector& offsets = fieldGlobalIndexers_[fd]->getGIDFieldOffsets(blockId,fieldIds_[fd]); + fieldOffsets_[fd] = PHX::View("ScatterResidual_BlockedTpetra(Tangent):fieldOffsets",offsets.size()); + auto hostOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]); + for (std::size_t i=0; i < offsets.size(); ++i) + hostOffsets(i) = offsets[i]; + Kokkos::deep_copy(fieldOffsets_[fd], hostOffsets); + + maxElementBlockGIDCount = std::max(fieldGlobalIndexers_[fd]->getElementBlockGIDCount(blockId),maxElementBlockGIDCount); + } + + // We will use one workset lid view for all fields, but has to be + // sized big enough to hold the largest elementBlockGIDCount in the + // ProductVector. + worksetLIDs_ = PHX::View("ScatterResidual_BlockedTpetra(Tangent):worksetLIDs", + scatterFields_[0].extent(0), + maxElementBlockGIDCount); +} + +// ********************************************************************** +template +void panzer::ScatterResidual_BlockedTpetra:: +preEvaluate(typename TRAITS::PreEvalData d) +{ + using Teuchos::RCP; + using Teuchos::rcp_dynamic_cast; + using Thyra::ProductVectorBase; + + // this is the list of parameters and their names that this scatter has to account for + std::vector activeParameters = + rcp_dynamic_cast(d.gedc->getDataObject("PARAMETER_NAMES"))->getActiveParameters(); + + const int numBlocks = static_cast(globalIndexer_->getFieldDOFManagers().size()); + + dfdpFieldsVoV_.initialize("ScatterResidual_Tpetra::dfdpFieldsVoV_",activeParameters.size(),numBlocks); + + for(std::size_t i=0;i paramBlockedContainer = rcp_dynamic_cast(d.gedc->getDataObject(activeParameters[i]),true); + RCP> productVector = + rcp_dynamic_cast>(paramBlockedContainer->get_f(),true); + for(int j=0;j>(productVector->getNonconstVectorBlock(j),true))->getTpetraVector()); + const auto& dfdp_view = tpetraBlock.getLocalViewDevice(Tpetra::Access::ReadWrite); + dfdpFieldsVoV_.addView(dfdp_view,i,j); + } + } + + dfdpFieldsVoV_.syncHostToDevice(); + + // extract linear object container + blockedContainer_ = rcp_dynamic_cast(d.gedc->getDataObject(globalDataKey_)); + + if(blockedContainer_==Teuchos::null) { + RCP gdata = rcp_dynamic_cast(d.gedc->getDataObject(globalDataKey_),true); + blockedContainer_ = rcp_dynamic_cast(gdata->getGhostedLOC()); + } +} + +// ********************************************************************** +template +void panzer::ScatterResidual_BlockedTpetra:: +evaluateFields(typename TRAITS::EvalData workset) +{ + using Teuchos::RCP; + using Teuchos::rcp_dynamic_cast; + using Thyra::VectorBase; + using Thyra::ProductVectorBase; + + const auto& localCellIds = this->wda(workset).cell_local_ids_k; + const RCP> thyraBlockResidual = rcp_dynamic_cast >(blockedContainer_->get_f(),true); + + // Loop over scattered fields + int currentWorksetLIDSubBlock = -1; + for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) { + // workset LIDs only change for different sub blocks + if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) { + fieldGlobalIndexers_[fieldIndex]->getElementLIDs(localCellIds,worksetLIDs_); + currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex]; + } + + auto& tpetraResidual = *((rcp_dynamic_cast>(thyraBlockResidual->getNonconstVectorBlock(productVectorBlockIndex_[fieldIndex]),true))->getTpetraVector()); + const auto& kokkosResidual = tpetraResidual.getLocalViewDevice(Tpetra::Access::ReadWrite); + + // Class data fields for lambda capture + const auto& fieldOffsets = fieldOffsets_[fieldIndex]; + const auto& worksetLIDs = worksetLIDs_; + const auto& fieldValues = scatterFields_[fieldIndex].get_static_view(); + const auto& tangentFieldsDevice = dfdpFieldsVoV_.getViewDevice(); + const auto& kokkosTangents = Kokkos::subview(tangentFieldsDevice,Kokkos::ALL(),productVectorBlockIndex_[fieldIndex]); + const double num_params = Kokkos::dimension_scalar(fieldValues)-1; + + Kokkos::parallel_for(Kokkos::RangePolicy(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) { + for(int basis=0; basis < static_cast(fieldOffsets.size()); ++basis) { + const int lid = worksetLIDs(cell,fieldOffsets(basis)); + Kokkos::atomic_add(&kokkosResidual(lid,0), fieldValues(cell,basis).val()); + for(int i_param=0; i_param private: typedef typename panzer::Traits::Tangent::ScalarT ScalarT; + typedef typename panzer::Traits::RealType RealT; // dummy field so that the evaluator will have something to do Teuchos::RCP scatterHolder_; @@ -153,8 +155,13 @@ class ScatterResidual_Tpetra Teuchos::RCP > fieldMap_; std::string globalDataKey_; // what global data does this fill? + Teuchos::RCP > tpetraContainer_; + + /// Storage for the tangent data + PHX::ViewOfViews<1,Kokkos::View> dfdpFieldsVoV_; - std::vector< Teuchos::ArrayRCP > dfdp_vectors_; + PHX::View scratch_lids_; + std::vector > scratch_offsets_; ScatterResidual_Tpetra(); }; diff --git a/packages/panzer/disc-fe/src/evaluators/Panzer_ScatterResidual_Tpetra_impl.hpp b/packages/panzer/disc-fe/src/evaluators/Panzer_ScatterResidual_Tpetra_impl.hpp index 117f271faa56..b7c4291eda6e 100644 --- a/packages/panzer/disc-fe/src/evaluators/Panzer_ScatterResidual_Tpetra_impl.hpp +++ b/packages/panzer/disc-fe/src/evaluators/Panzer_ScatterResidual_Tpetra_impl.hpp @@ -130,6 +130,7 @@ ScatterResidual_Tpetra(const Teuchos::RCP & indexer : globalIndexer_(indexer) , globalDataKey_("Residual Scatter Container") { + std::string scatterName = p.get("Scatter Name"); scatterHolder_ = Teuchos::rcp(new PHX::Tag(scatterName,Teuchos::rcp(new PHX::MDALayout(0)))); @@ -146,6 +147,7 @@ ScatterResidual_Tpetra(const Teuchos::RCP & indexer // build the vector of fields that this is dependent on scatterFields_.resize(names.size()); + scratch_offsets_.resize(names.size()); for (std::size_t eq = 0; eq < names.size(); ++eq) { scatterFields_[eq] = PHX::MDField(names[eq],dl); @@ -165,16 +167,25 @@ ScatterResidual_Tpetra(const Teuchos::RCP & indexer // ********************************************************************** template void panzer::ScatterResidual_Tpetra:: -postRegistrationSetup(typename TRAITS::SetupData /* d */, +postRegistrationSetup(typename TRAITS::SetupData d, PHX::FieldManager& /* fm */) { fieldIds_.resize(scatterFields_.size()); + const Workset & workset_0 = (*d.worksets_)[0]; + std::string blockId = this->wda(workset_0).block_id; + // load required field numbers for fast use for(std::size_t fd=0;fdfind(scatterFields_[fd].fieldTag().name())->second; fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName); + + const std::vector & offsets = globalIndexer_->getGIDFieldOffsets(blockId,fieldIds_[fd]); + scratch_offsets_[fd] = PHX::View("offsets",offsets.size()); + Kokkos::deep_copy(scratch_offsets_[fd], Kokkos::View(offsets.data(), offsets.size())); } + scratch_lids_ = PHX::View("lids",scatterFields_[0].extent(0), + globalIndexer_->getElementBlockGIDCount(blockId)); } // ********************************************************************** @@ -191,50 +202,26 @@ preEvaluate(typename TRAITS::PreEvalData d) std::vector activeParameters = rcp_dynamic_cast(d.gedc->getDataObject("PARAMETER_NAMES"))->getActiveParameters(); - dfdp_vectors_.clear(); + dfdpFieldsVoV_.initialize("ScatterResidual_Tpetra::dfdpFieldsVoV_",activeParameters.size()); + for(std::size_t i=0;i vec = rcp_dynamic_cast(d.gedc->getDataObject(activeParameters[i]),true)->get_f(); - Teuchos::ArrayRCP vec_array = vec->get1dViewNonConst(); - dfdp_vectors_.push_back(vec_array); + auto dfdp_view = vec->getLocalViewDevice(Tpetra::Access::ReadWrite); + + dfdpFieldsVoV_.addView(dfdp_view,i); } -} -// ********************************************************************** -template -void panzer::ScatterResidual_Tpetra:: -evaluateFields(typename TRAITS::EvalData workset) -{ - // for convenience pull out some objects from workset - std::string blockId = this->wda(workset).block_id; - const std::vector & localCellIds = this->wda(workset).cell_local_ids; - - // NOTE: A reordering of these loops will likely improve performance - // The "getGIDFieldOffsets may be expensive. However the - // "getElementGIDs" can be cheaper. However the lookup for LIDs - // may be more expensive! - - // scatter operation for each cell in workset - for(std::size_t worksetCellIndex=0;worksetCellIndexgetElementLIDs(cellLocalId); - - // loop over each field to be scattered - for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) { - int fieldNum = fieldIds_[fieldIndex]; - const std::vector & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum); - - // loop over basis functions - for(std::size_t basis=0;basis(d.gedc->getDataObject(globalDataKey_)); + + if(tpetraContainer_==Teuchos::null) { + // extract linear object container + Teuchos::RCP loc = Teuchos::rcp_dynamic_cast(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC(); + tpetraContainer_ = Teuchos::rcp_dynamic_cast(loc); + } } // ********************************************************************** @@ -392,7 +379,6 @@ class ScatterResidual_Residual_Functor { PHX::View offsets; // how to get a particular field FieldType field; - KOKKOS_INLINE_FUNCTION void operator()(const unsigned int cell) const { @@ -407,6 +393,44 @@ class ScatterResidual_Residual_Functor { } }; +template +class ScatterResidual_Tangent_Functor { +public: + typedef typename PHX::Device execution_space; + typedef PHX::MDField FieldType; + + bool fillResidual; + Kokkos::View r_data; + + Kokkos::View lids; // local indices for unknowns. + PHX::View offsets; // how to get a particular field + FieldType field; + double num_params; + + Kokkos::View*> dfdp_fields; // tangent fields + + KOKKOS_INLINE_FUNCTION + void operator()(const unsigned int cell) const + { + + // loop over the basis functions (currently they are nodes) + for(std::size_t basis=0; basis < offsets.extent(0); basis++) { + typename FieldType::array_type::reference_type scatterField = field(cell,basis); + int offset = offsets(basis); + LO lid = lids(cell,offset); + + // Sum residual + if(fillResidual) + Kokkos::atomic_add(&r_data(lid,0), scatterField.val()); + + // loop over the tangents + for(int i_param=0; i_param +void panzer::ScatterResidual_Tpetra:: +evaluateFields(typename TRAITS::EvalData workset) +{ + typedef TpetraLinearObjContainer LOC; + + // for convenience pull out some objects from workset + std::string blockId = this->wda(workset).block_id; + + Teuchos::RCP r = tpetraContainer_->get_f(); + + globalIndexer_->getElementLIDs(this->wda(workset).getLocalCellIDs(),scratch_lids_); + + ScatterResidual_Tangent_Functor functor; + functor.fillResidual = (r!=Teuchos::null); + if(functor.fillResidual) + functor.r_data = r->getLocalViewDevice(Tpetra::Access::ReadWrite); + functor.lids = scratch_lids_; + functor.dfdp_fields = dfdpFieldsVoV_.getViewDevice(); + + // for each field, do a parallel for loop + for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) { + functor.offsets = scratch_offsets_[fieldIndex]; + functor.field = scatterFields_[fieldIndex]; + functor.num_params = Kokkos::dimension_scalar(scatterFields_[fieldIndex].get_view())-1; + + Kokkos::parallel_for(workset.num_cells,functor); + } +} + // ********************************************************************** #endif diff --git a/packages/panzer/mini-em/example/BlockPrec/solverMueLu.xml b/packages/panzer/mini-em/example/BlockPrec/solverMueLu.xml index 794d8ad984df..d71ba1fd5230 100644 --- a/packages/panzer/mini-em/example/BlockPrec/solverMueLu.xml +++ b/packages/panzer/mini-em/example/BlockPrec/solverMueLu.xml @@ -164,7 +164,7 @@ - + @@ -209,7 +209,7 @@ - + @@ -269,7 +269,7 @@ - + @@ -412,7 +412,7 @@ - + @@ -465,7 +465,7 @@ - + @@ -531,7 +531,7 @@ - + diff --git a/packages/panzer/mini-em/example/BlockPrec/solverMueLuEpetra.xml b/packages/panzer/mini-em/example/BlockPrec/solverMueLuEpetra.xml index deab8726c4da..45f092c25401 100644 --- a/packages/panzer/mini-em/example/BlockPrec/solverMueLuEpetra.xml +++ b/packages/panzer/mini-em/example/BlockPrec/solverMueLuEpetra.xml @@ -368,7 +368,7 @@ - + @@ -414,7 +414,7 @@ - + @@ -480,7 +480,7 @@ - + diff --git a/packages/rol/.gitignore b/packages/rol/.gitignore new file mode 100644 index 000000000000..e10e419d2535 --- /dev/null +++ b/packages/rol/.gitignore @@ -0,0 +1,10 @@ +*.zip +*.tar +*.tar.gz +*.bz2 +*.xz +*.swo +*.swp +*.pyc +__pycache__ + diff --git a/packages/rol/CMakeLists.txt b/packages/rol/CMakeLists.txt index 98c276b8c796..b6e045207d7b 100644 --- a/packages/rol/CMakeLists.txt +++ b/packages/rol/CMakeLists.txt @@ -30,6 +30,12 @@ TRIBITS_ADD_OPTION_AND_DEFINE(${PACKAGE_NAME}_ENABLE_PYROL OFF ) +TRIBITS_ADD_OPTION_AND_DEFINE(${PACKAGE_NAME}_ENABLE_PARAMETERLIST_VALIDATION + ENABLE_PARAMETERLIST_VALIDATION + "Build ROL with ParameterList validation." + OFF + ) + # Build Options SET( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) INCLUDE(BuildOptions) @@ -39,6 +45,7 @@ GET_PROPERTY( STACKTRACE_STRING GLOBAL PROPERTY STACKTRACE_IMPL ) #ENDIF() +include(ROLParameters) # diff --git a/packages/rol/cmake/ROLParameters.cmake b/packages/rol/cmake/ROLParameters.cmake new file mode 100644 index 000000000000..19a5e8e53014 --- /dev/null +++ b/packages/rol/cmake/ROLParameters.cmake @@ -0,0 +1,40 @@ +if( ROL_ENABLE_PARAMETERLIST_VALIDATION ) + + message("Enabling automated ParameterList detection and validation") + + if(NOT DEFINED ${PYTHON_EXECUTABLE}) + find_program(PYTHON_EXECUTABLE NAMES python3 python REQUIRED) + endif() + + set( ROL_SOURCE_DIR "${PROJECT_SOURCE_DIR}/packages/rol" ) + set( ROL_PARAMETERS_SOURCE_DIR "${ROL_SOURCE_DIR}/rol_parameters" ) + + set( ROL_BINARY_DIR "${PROJECT_BINARY_DIR}/packages/rol" ) + set( ROL_PARAMETERS_BINARY_DIR "${ROL_BINARY_DIR}/rol_parameters" ) + + # set( REQUIREMENTS_FILE "${ROL_PARAMETERS_SOURCE_DIR}/requirements.txt" ) + set( VENV_PATH "${ROL_PARAMETERS_BINARY_DIR}/venv" ) + + add_custom_target( setup_venv + COMMAND ${CMAKE_COMMAND} -E env ${PYTHON_EXECUTABLE} -m venv ${VENV_PATH} + # Install poetry in the virtual environment + COMMAND ${CMAKE_COMMAND} -E env ${VENV_PATH}/bin/pip install poetry + # Use poetry to install dependencies from pyproject.toml + COMMAND ${CMAKE_COMMAND} -E env ${VENV_PATH}/bin/poetry install + COMMENT "Setting up virtual environment and installing required Python packages with poetry" + WORKING_DIRECTORY ${ROL_PARAMETERS_SOURCE_DIR} ) + + message( "Python virtual environment path: ${VENV_PATH}" ) + message( STATUS "Run 'make setup_venv` or your equivalent build system command (e.g. ninja setup_venv') to setup the Python virtual environment before building rol_parameters") + + add_custom_target( rol_parameters + COMMAND ${CMAKE_COMMAND} -E env PYTHONPYCACHEPREFIX=${CMAKE_BINARY_DIR}/pycache + ${VENV_PATH}/bin/python ${ROL_PARAMETERS_SOURCE_DIR}/rol_parameters.py ${ROL_SOURCE_DIR} ${ROL_PARAMETERS_BINARY_DIR} + DEPENDS setup_venv + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Running rol_parameters.py using the virtual environment") + + message( STATUS "Run 'make rol_parameters` or your equivalent build system command (e.g. ninja rol_parameters') to build the hierarchical parameter list from the ROL source tree") + +endif() + diff --git a/packages/rol/cmake/ROL_config.h.in b/packages/rol/cmake/ROL_config.h.in index b406fe039165..e00923fea354 100644 --- a/packages/rol/cmake/ROL_config.h.in +++ b/packages/rol/cmake/ROL_config.h.in @@ -11,3 +11,6 @@ /* Define for python interface support. */ #cmakedefine ENABLE_PYBIND11_PYROL + +/* Define support for automated ParameterList validation. */ +#cmakedefine ENABLE_PARAMETERLIST_VALIDATION diff --git a/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_02.cpp b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_02.cpp index 12c41b6f9047..8881ba496138 100644 --- a/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_02.cpp +++ b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/example_02.cpp @@ -277,39 +277,41 @@ int main(int argc, char *argv[]) { /*************************************************************************/ z->zero(); if (useParametricControl) { - // Linearly interpolate between optimal values for angular velocity - // amplitude and Strouhal number obtained for Re=200, 1000 in - // JW He, R Glowinski, R Metcalfe, A Nordlander, J Periaux - // Active Control and Drag Optimization for Flow Past a - // Circular Cylinder - // Journal of Computation Physics, 163, pg. 83-117, 2000. - RealT Re = parlist->sublist("Problem").get("Reynolds Number",200.0); - RealT amp0 = 6.0 - (Re - 200.0)/1600.0; - RealT Se0 = 0.74 - (Re - 200.0) * (0.115/800.0); - RealT amp = parlist->sublist("Problem").sublist("Initial Guess").get("Amplitude", amp0); - RealT Se = parlist->sublist("Problem").sublist("Initial Guess").get("Strouhal Number", Se0); - RealT ph = parlist->sublist("Problem").sublist("Initial Guess").get("Phase Shift", 0.0); - for( int k=0; k> zn - = ROL::dynamicPtrCast>(z->get(k))->getParameter()->getVector(); - (*zn)[0] = -amp * std::sin(2.0 * M_PI * Se * timeStamp[k].t[0] + ph); + bool readFromFile = parlist->sublist("Initial Guess").get("Read From File",false); + if (!readFromFile) { + // Linearly interpolate between optimal values for angular velocity + // amplitude and Strouhal number obtained for Re=200, 1000 in + // JW He, R Glowinski, R Metcalfe, A Nordlander, J Periaux + // Active Control and Drag Optimization for Flow Past a + // Circular Cylinder + // Journal of Computation Physics, 163, pg. 83-117, 2000. + RealT Re = parlist->sublist("Problem").get("Reynolds Number",200.0); + RealT amp0 = 6.0 - (Re - 200.0)/1600.0; + RealT Se0 = 0.74 - (Re - 200.0) * (0.115/800.0); + RealT amp = parlist->sublist("Problem").sublist("Initial Guess").get("Amplitude", amp0); + RealT Se = parlist->sublist("Problem").sublist("Initial Guess").get("Strouhal Number", Se0); + RealT ph = parlist->sublist("Problem").sublist("Initial Guess").get("Phase Shift", 0.0); + for( int k=0; k> zn + = ROL::dynamicPtrCast>(z->get(k))->getParameter()->getVector(); + (*zn)[0] = -amp * std::sin(2.0 * M_PI * Se * timeStamp[k].t[0] + ph); + } + } + else { + for (int k = 1; k < nt; ++k) { + std::stringstream zname; + zname << "initial_control." << k-1 << ".txt"; + std::fstream zfile; + zfile.open(zname.str(),std::ios::in); + if (!zfile.is_open()) std::cout << "CANNOT OPEN " << zname.str() << std::endl; + zfile >> (*(ROL::dynamicPtrCast>(z->get(k-1))->getParameter()->getVector()))[0]; + zfile.close(); + } } } //parlist->sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Subproblem Solver", "NCG"); algo = ROL::makePtr>(*parlist); //algo = ROL::makePtr>(*parlist); - ROL::Ptr> ztemp = z->clone(); - ztemp->randomize(); - ROL::Ptr> pztemp = z->clone(); - -// RealT ptol = 1.0; -// nobj->prox(*pztemp, *ztemp, 1.0, ptol); -// -// pztemp->axpy(-1.0, *ztemp); -// -// *outStream << "Error = " -// << pztemp->norm() << std::endl; -// //ROL::OptimizationProblem problem(obj,z);// need to change this //ROL::OptimizationSolver solver(problem,*parlist);// need to change this std::clock_t timer = std::clock(); diff --git a/packages/rol/example/PDE-OPT/dynamic/navier-stokes/input_02.xml b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/input_02.xml index 2b4effe5daaa..2fca7dcd42f3 100644 --- a/packages/rol/example/PDE-OPT/dynamic/navier-stokes/input_02.xml +++ b/packages/rol/example/PDE-OPT/dynamic/navier-stokes/input_02.xml @@ -11,9 +11,9 @@ - - - + + + diff --git a/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/filtered_compliance_robj.hpp b/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/filtered_compliance_robj.hpp index c72679683eff..014182711b65 100644 --- a/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/filtered_compliance_robj.hpp +++ b/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/filtered_compliance_robj.hpp @@ -122,20 +122,12 @@ class TopOptFilteredComplianceObjective : public ROL::Objective { // Reject: flag = false, iter > -1 // Accept: flag = true, iter > -1 if (flag) { - if (iter > -1) { - update_accept(z,iter); - } - else { - update_temp(z,iter); - } + if (iter > -1) update_accept(z,iter); + else update_temp(z,iter); } else { - if (iter > -1) { - update_revert(z,iter); - } - else { - update_trial(z,iter); - } + if (iter > -1) update_revert(z,iter); + else update_trial(z,iter); } } comp_->update(*Fz_,flag,iter); diff --git a/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/pde_elasticity.hpp b/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/pde_elasticity.hpp index 6bb18cdf6a9d..bf6cb08dece7 100644 --- a/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/pde_elasticity.hpp +++ b/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/pde_elasticity.hpp @@ -83,42 +83,30 @@ class PDE_Elasticity : public PDE { int basisOrderDens = parlist.sublist("Problem").get("Density Basis Order",0); int cubDegree = parlist.sublist("Problem").get("Cubature Degree",4); int bdryCubDegree = parlist.sublist("Problem").get("Boundary Cubature Degree",2); - int probDim = parlist.sublist("Problem").get("Problem Dimension",2); - if (probDim > 3 || probDim < 2) { - TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, - ">>> PDE-OPT/poisson/pde_poisson.hpp: Problem dimension is not 2 or 3!"); - } - if (basisOrder > 2 || basisOrder < 1) { - TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, - ">>> PDE-OPT/poisson/pde_poisson.hpp: Basis order is not 1 or 2!"); - } + int probDim = parlist.sublist("Problem").get("Problem Dimension",3); + TEUCHOS_TEST_FOR_EXCEPTION(probDim > 3 || probDim < 2, std::invalid_argument, + ">>> PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/pde_elasticity.hpp: Problem dimension is not 2 or 3!"); + TEUCHOS_TEST_FOR_EXCEPTION(basisOrder > 2 || basisOrder < 1, std::invalid_argument, + ">>> PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/pde_elasticity.hpp: Basis order is not 1 or 2!"); if (probDim == 2) { - if (basisOrder == 1) { + if (basisOrder == 1) basisPtr_ = ROL::makePtr>>(); - } - else if (basisOrder == 2) { + else if (basisOrder == 2) basisPtr_ = ROL::makePtr>>(); - } - if (basisOrderDens == 1) { + if (basisOrderDens == 1) basisPtrDens_ = ROL::makePtr>>(); - } - else { + else basisPtrDens_ = ROL::makePtr>>(); - } } else if (probDim == 3) { - if (basisOrder == 1) { + if (basisOrder == 1) basisPtr_ = ROL::makePtr>>(); - } - else if (basisOrder == 2) { + else if (basisOrder == 2) basisPtr_ = ROL::makePtr>>(); - } basisPtrDens_ = ROL::makePtr>>(); } basisPtrs_.clear(); basisPtrsDens_.clear(); - for (int i=0; i { void setDensityFields(const std::vector>>> &basisPtrs) { if (getFields2called_) { TEUCHOS_TEST_FOR_EXCEPTION(getFields2called_, std::invalid_argument, - ">>> PDE-OPT/topo-opt/elasticity/src/pde_elasticity.hpp: Must call before getFields2!"); + ">>> PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/pde_elasticity.hpp: Must call before getFields2!"); } else { basisPtrDens_ = basisPtrs[0]; diff --git a/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/pde_filter.hpp b/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/pde_filter.hpp index cabeb961c0a9..6dfa4906a15f 100644 --- a/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/pde_filter.hpp +++ b/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/pde_filter.hpp @@ -54,7 +54,7 @@ class PDE_Filter : public PDE { int basisOrderDens = parlist.sublist("Problem").get("Density Basis Order",0); int cubDegree = parlist.sublist("Problem").get("Cubature Degree",4); // int bdryCubDegree = parlist.sublist("Problem").get("Boundary Cubature Degree",2); - int probDim = parlist.sublist("Problem").get("Problem Dimension",2); + int probDim = parlist.sublist("Problem").get("Problem Dimension",3); TEUCHOS_TEST_FOR_EXCEPTION(probDim>3||probDim<2, std::invalid_argument, ">>> PDE-OPT/poisson/pde_poisson.hpp: Problem dimension is not 2 or 3!"); TEUCHOS_TEST_FOR_EXCEPTION(basisOrder>2||basisOrder<1, std::invalid_argument, diff --git a/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/traction.hpp b/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/traction.hpp index bc03d5bc77fd..1af6491a072d 100644 --- a/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/traction.hpp +++ b/packages/rol/example/PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/traction.hpp @@ -44,7 +44,8 @@ class Traction { Traction(void) {}; Traction(int dim) : dim_(dim) { - assert(dim > 3 || dim < 2); + TEUCHOS_TEST_FOR_EXCEPTION(dim > 3 || dim < 2, std::invalid_argument, + ">>> PDE-OPT/published/NonsmoothTR_BaraldiKouri2022/src/traction.hpp: Problem dimension is not 2 or 3!"); if (dim==2) { offset_ = 0; sidesets_.push_back(2); diff --git a/packages/rol/example/PinT/tanks/LowerBandedMatrix.hpp b/packages/rol/example/PinT/tanks/LowerBandedMatrix.hpp index 731aeefb026a..fbc541760d14 100644 --- a/packages/rol/example/PinT/tanks/LowerBandedMatrix.hpp +++ b/packages/rol/example/PinT/tanks/LowerBandedMatrix.hpp @@ -17,7 +17,8 @@ #include "ROL_StdVector.hpp" namespace details { -using namespace std; + +using std::vector; /* \class LowerBandedMatrix \brief Implements linear solve and multiplication by diff --git a/packages/rol/example/PinT/tanks/TankState.hpp b/packages/rol/example/PinT/tanks/TankState.hpp index d34c4195ea29..e946b6b1ec10 100644 --- a/packages/rol/example/PinT/tanks/TankState.hpp +++ b/packages/rol/example/PinT/tanks/TankState.hpp @@ -18,7 +18,7 @@ namespace details { -using namespace std; +using std::vector; template class TankState { diff --git a/packages/rol/example/PinT/tanks/TankState_Impl.hpp b/packages/rol/example/PinT/tanks/TankState_Impl.hpp index ec5ebbd9ae1a..d6e10c57a645 100644 --- a/packages/rol/example/PinT/tanks/TankState_Impl.hpp +++ b/packages/rol/example/PinT/tanks/TankState_Impl.hpp @@ -13,7 +13,8 @@ namespace details { -using namespace std; +using std::vector; +using std::ostream; template TankState::TankState( ROL::ParameterList& pl ) : diff --git a/packages/rol/example/PinT/tanks/TankVector.hpp b/packages/rol/example/PinT/tanks/TankVector.hpp index 7afbc8194f67..6580efe69ff3 100644 --- a/packages/rol/example/PinT/tanks/TankVector.hpp +++ b/packages/rol/example/PinT/tanks/TankVector.hpp @@ -18,7 +18,11 @@ #include namespace details { -using namespace std; +using std::vector; +using std::string; +using std::ostream; +using std::endl; +using std::setw template class TankControlVector; diff --git a/packages/rol/example/PinT/tanks/TankVector_Impl.hpp b/packages/rol/example/PinT/tanks/TankVector_Impl.hpp index 3b4ee1e9e420..803fb0a284c6 100644 --- a/packages/rol/example/PinT/tanks/TankVector_Impl.hpp +++ b/packages/rol/example/PinT/tanks/TankVector_Impl.hpp @@ -13,7 +13,7 @@ namespace details { -using namespace std; +using std::vector; using size_type = typename vector::size_type; diff --git a/packages/rol/example/PinT/tanks/Tanks_ControlVector.hpp b/packages/rol/example/PinT/tanks/Tanks_ControlVector.hpp index e5a6a1524661..cd53a280887b 100644 --- a/packages/rol/example/PinT/tanks/Tanks_ControlVector.hpp +++ b/packages/rol/example/PinT/tanks/Tanks_ControlVector.hpp @@ -19,7 +19,11 @@ namespace Tanks { -using namespace std; +using std::vector; +using std::ostream; +using std::string; +using std::setw; +using std::endl; // Forward declaration template class StateVector; diff --git a/packages/rol/example/PinT/tanks/Tanks_ControlVector_Impl.hpp b/packages/rol/example/PinT/tanks/Tanks_ControlVector_Impl.hpp index f422d2953c64..ecc846a79a93 100644 --- a/packages/rol/example/PinT/tanks/Tanks_ControlVector_Impl.hpp +++ b/packages/rol/example/PinT/tanks/Tanks_ControlVector_Impl.hpp @@ -13,8 +13,6 @@ namespace Tanks { -using namespace std; - using size_type = typename vector::size_type; diff --git a/packages/rol/example/PinT/tanks/Tanks_DynamicConstraint.hpp b/packages/rol/example/PinT/tanks/Tanks_DynamicConstraint.hpp index 62ea9973ea95..66ae39488464 100644 --- a/packages/rol/example/PinT/tanks/Tanks_DynamicConstraint.hpp +++ b/packages/rol/example/PinT/tanks/Tanks_DynamicConstraint.hpp @@ -68,7 +68,7 @@ class DynamicConstraint : public ROL::DynamicConstraint { //--------- Subvector addressing --------------------------------------------- size_type h_, Qout_, Qin_, z_; - shared_ptr L_, R_, S_; + std::shared_ptr L_, R_, S_; State zero_state_; Control zero_ctrl_; @@ -113,9 +113,9 @@ class DynamicConstraint : public ROL::DynamicConstraint { p_( ptrows.at(i), ptcols.at(i) ) = 0.0; } - L_ = make_shared>( rows_, cols_, alphaL_, *(p_.getVector()) ); - R_ = make_shared>( rows_, cols_, -alphaR_, *(p_.getVector()) ); - S_ = make_shared>( rows_, cols_ ); + L_ = std::make_shared>( rows_, cols_, alphaL_, *(p_.getVector()) ); + R_ = std::make_shared>( rows_, cols_, -alphaR_, *(p_.getVector()) ); + S_ = std::make_shared>( rows_, cols_ ); } static ROL::Ptr create( ROL::ParameterList& pl ) { diff --git a/packages/rol/example/PinT/tanks/Tanks_StateVector.hpp b/packages/rol/example/PinT/tanks/Tanks_StateVector.hpp index d898e1944a26..87328758cf0a 100644 --- a/packages/rol/example/PinT/tanks/Tanks_StateVector.hpp +++ b/packages/rol/example/PinT/tanks/Tanks_StateVector.hpp @@ -19,7 +19,11 @@ namespace Tanks { -using namespace std; +using std::vector; +using std::ostream; +using std::string; +using std::setw; +using std::endl; // Forward declaration template class ControlVector; diff --git a/packages/rol/example/PinT/tanks/Tanks_StateVector_Impl.hpp b/packages/rol/example/PinT/tanks/Tanks_StateVector_Impl.hpp index f4046af8543d..2f53cc7cb966 100644 --- a/packages/rol/example/PinT/tanks/Tanks_StateVector_Impl.hpp +++ b/packages/rol/example/PinT/tanks/Tanks_StateVector_Impl.hpp @@ -13,8 +13,6 @@ namespace Tanks { -using namespace std; - using size_type = typename vector::size_type; template diff --git a/packages/rol/example/dense-hessian/example_01.cpp b/packages/rol/example/dense-hessian/example_01.cpp index fc6196abd36c..f85a31115e0a 100644 --- a/packages/rol/example/dense-hessian/example_01.cpp +++ b/packages/rol/example/dense-hessian/example_01.cpp @@ -15,7 +15,8 @@ #define USE_HESSVEC 1 #include "ROL_Rosenbrock.hpp" -#include "ROL_OptimizationSolver.hpp" +#include "ROL_Problem.hpp" +#include "ROL_Solver.hpp" #include "ROL_ScaledStdVector.hpp" #include "ROL_Stream.hpp" #include "ROL_HelperFunctions.hpp" @@ -48,6 +49,7 @@ int main(int argc, char *argv[]) { // Set algorithm parameters. ROL::ParameterList parlist; + parlist.sublist("General").set("Output Level", 1); parlist.sublist("Step").set("Type", "Line Search"); parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").set("Type", "Newton-Krylov"); parlist.sublist("Status Test").set("Gradient Tolerance",1.e-12); @@ -67,9 +69,10 @@ int main(int argc, char *argv[]) { ROL::PrimalScaledStdVector x(x_ptr, scale_ptr); // Define problem. - ROL::OptimizationProblem problem(ROL::makePtrFromRef(obj), ROL::makePtrFromRef(x)); - ROL::OptimizationSolver solver(problem, parlist); + ROL::Ptr> problem = ROL::makePtr>(ROL::makePtrFromRef(obj), ROL::makePtrFromRef(x)); + problem->finalize(false, true, *outStream); // Solve problem. + ROL::Solver solver(problem, parlist); solver.solve(*outStream); // Set true solution. diff --git a/packages/rol/example/tensor-opt/example_01.cpp b/packages/rol/example/tensor-opt/example_01.cpp index 5b8f9fdcfd78..e869cb578dd2 100644 --- a/packages/rol/example/tensor-opt/example_01.cpp +++ b/packages/rol/example/tensor-opt/example_01.cpp @@ -47,8 +47,8 @@ #include "ROL_Vector.hpp" #include "ROL_CArrayVector.hpp" #include "ROL_Bounds.hpp" -#include "ROL_OptimizationSolver.hpp" -#include "ROL_StatusTest.hpp" +#include "ROL_Problem.hpp" +#include "ROL_Solver.hpp" //#pragma GCC diagnostic pop @@ -431,6 +431,14 @@ class SemidefiniteProgramming ehv.scale(DT2_(0.5), ev); } + + void precond (ROL::Vector & hv, + const ROL::Vector & v, + const ROL::Vector & x, + DT2_ & tol) override + { + invHessVec(hv,v,x,tol); + } }; /******************************************************************************/ @@ -599,10 +607,10 @@ class SemidefiniteProgramming /******************************************************************************/ private: - const std::string _parfile; - const ROL::Ptr _parlist; + const std::string _parfile; + const ROL::Ptr _parlist; - const ROL::Ptr> _lower, _upper; + const ROL::Ptr> _lower, _upper; const ROL::Ptr> _x; const ROL::Ptr> _bnd; @@ -614,8 +622,8 @@ class SemidefiniteProgramming std::vector>> _ibnd; const ROL::Ptr> _obj; - ROL::Ptr> _problem; - ROL::Ptr> _solver; + ROL::Ptr> _problem; + ROL::Ptr> _solver; DT_ _A_i_up[6]; DT_ _A_i_lo[6]; @@ -657,8 +665,14 @@ class SemidefiniteProgramming my_cast &>(* _icon[3]).set_A(_A_j_lo); my_cast &>(* _icon[3]).set_F(_F_n); - _problem = ROL::makePtr>(_obj, _x, _bnd, _icon, _imul, _ibnd); - _solver = ROL::makePtr>(* _problem, * _parlist); + _problem = ROL::makePtr>(_obj, _x); + _problem->addBoundConstraint(_bnd); + _problem->addConstraint("Inequality Constraint 0", _icon[0], _imul[0], _ibnd[0]); + _problem->addConstraint("Inequality Constraint 1", _icon[1], _imul[1], _ibnd[1]); + _problem->addConstraint("Inequality Constraint 2", _icon[2], _imul[2], _ibnd[2]); + _problem->addConstraint("Inequality Constraint 3", _icon[3], _imul[3], _ibnd[3]); + _problem->finalize(false,true,std::cout); + _solver = ROL::makePtr>(_problem, * _parlist); _x->zero(); } @@ -716,8 +730,9 @@ class SemidefiniteProgramming { _x->wrap(x); for (auto& it : _imul) it->zero(); - _solver->reset(); - _problem->reset(); + _problem->edit(); + _problem->finalize(false,true,std::cout); + _solver = ROL::makePtr>(_problem, * _parlist); _solver->solve(outStream); return _x->data(); @@ -746,7 +761,7 @@ class SemidefiniteProgramming set_node(A_j, lambda_j_lo, lambda_j_up); set_flux(F); - _problem->check(outStream); + _problem->check(true,outStream); } void checkConstraints(DT_ sol[3]) @@ -833,21 +848,22 @@ int main(int argc, char *argv[]) { // start from zero solution DataType y[] = {0.0, 0.0, 0.0}; sp.solve(y); - std::cout << "y = [" << y[0] << ", " << y[1] << ", " << y[2] << "]" << std::endl; + std::cout << std::setprecision(16) << "y = [" << y[0] << ", " << y[1] << ", " << y[2] << "]" << std::endl; // solve one more time DataType z[] = {0.0, 0.0, 0.0}; sp.solve(z); - std::cout << "z = [" << z[0] << ", " << z[1] << ", " << z[2] << "]" << std::endl; + std::cout << std::setprecision(16) << "z = [" << z[0] << ", " << z[1] << ", " << z[2] << "]" << std::endl; // perform checks + DataType tol = std::sqrt(ROL::ROL_EPSILON()); // * xnorm; ROL::CArrayVector xx(&x[0],dim), yy(&y[0],dim), zz(&z[0],dim); xx.axpy(static_cast(-1), yy); - if (xx.norm() > std::sqrt(ROL::ROL_EPSILON())) { - *outStream << "\n\nxx.norm() = " << xx.norm() << "\n"; + if (xx.norm() > tol) { + *outStream << std::endl << "xx.norm() = " << xx.norm() << std::endl; errorFlag = 1000; } yy.axpy(static_cast(-1), zz); - if (yy.norm() > ROL::ROL_EPSILON()) { - *outStream << "\n\nyy.norm() = " << yy.norm() << "\n"; + if (yy.norm() > tol) { + *outStream << std::endl << "yy.norm() = " << yy.norm() << std::endl; errorFlag = 1000; } } diff --git a/packages/rol/example/tensor-opt/example_01.xml b/packages/rol/example/tensor-opt/example_01.xml index 0f158e6d4458..143414654144 100644 --- a/packages/rol/example/tensor-opt/example_01.xml +++ b/packages/rol/example/tensor-opt/example_01.xml @@ -1,42 +1,79 @@ + + + - - + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + - + + + + + + + + + + + + + + + + + + - + + - + @@ -46,56 +83,15 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + diff --git a/packages/rol/example/topology-optimization/example_02.cpp b/packages/rol/example/topology-optimization/example_02.cpp index 7e689c0af54c..ce5cec8aad40 100644 --- a/packages/rol/example/topology-optimization/example_02.cpp +++ b/packages/rol/example/topology-optimization/example_02.cpp @@ -23,7 +23,8 @@ #include "ROL_StdVector.hpp" #include "ROL_Reduced_Objective_SimOpt.hpp" #include "ROL_Bounds.hpp" -#include "ROL_OptimizationSolver.hpp" +#include "ROL_Problem.hpp" +#include "ROL_Solver.hpp" #include "ROL_ParameterList.hpp" #include "Teuchos_SerialDenseVector.hpp" @@ -892,7 +893,7 @@ int main(int argc, char *argv[]) { uint ny = 10; // Number of y-elements (20 for prob = 0, 20 for prob = 1). int P = 1; // SIMP penalization power. RealT frac = 0.4; // Volume fraction. - ROL::Ptr > pFEM = ROL::makePtr>(nx,ny,P,prob); + ROL::Ptr> pFEM = ROL::makePtr>(nx,ny,P,prob); // Read optimization input parameter list. std::string filename = "input_ex02.xml"; auto parlist = ROL::getParametersFromXmlFile( filename ); @@ -909,36 +910,39 @@ int main(int argc, char *argv[]) { // Initialize bound constraints. ROL::Ptr> lo_ptr = ROL::makePtr>(pFEM->numZ(),1.e-3); ROL::Ptr> hi_ptr = ROL::makePtr>(pFEM->numZ(),1.0); - ROL::Ptr > lop = ROL::makePtr>(lo_ptr); - ROL::Ptr > hip = ROL::makePtr>(hi_ptr); + ROL::Ptr> lop = ROL::makePtr>(lo_ptr); + ROL::Ptr> hip = ROL::makePtr>(hi_ptr); bound = ROL::makePtr>(lop,hip); // Initialize control vector. - ROL::Ptr > z_ptr = ROL::makePtr> (pFEM->numZ(), frac); + ROL::Ptr> z_ptr = ROL::makePtr> (pFEM->numZ(), frac); ROL::StdVector z(z_ptr); - ROL::Ptr > zp = ROL::makePtrFromRef(z); + ROL::Ptr> zp = ROL::makePtrFromRef(z); // Initialize state vector. - ROL::Ptr > u_ptr = ROL::makePtr>(pFEM->numU(), 0.0); + ROL::Ptr> u_ptr = ROL::makePtr>(pFEM->numU(), 0.0); ROL::StdVector u(u_ptr); - ROL::Ptr > up = ROL::makePtrFromRef(u); + ROL::Ptr> up = ROL::makePtrFromRef(u); // Initialize adjoint vector. - ROL::Ptr > p_ptr = ROL::makePtr>(pFEM->numU(), 0.0); + ROL::Ptr> p_ptr = ROL::makePtr>(pFEM->numU(), 0.0); ROL::StdVector p(p_ptr); - ROL::Ptr > pp = ROL::makePtrFromRef(p); + ROL::Ptr> pp = ROL::makePtrFromRef(p); // Initialize multiplier vector. - ROL::Ptr > l_ptr = ROL::makePtr>(1, 0.0); + ROL::Ptr> l_ptr = ROL::makePtr>(1, 0.0); ROL::StdVector l(l_ptr); - ROL::Ptr > lp = ROL::makePtrFromRef(l); + ROL::Ptr> lp = ROL::makePtrFromRef(l); // Initialize objective function. pobj = ROL::makePtr>(pFEM); // Initialize reduced objective function. robj = ROL::makePtr>(pobj,pcon,up,zp,pp); - // Run optimization. - ROL::OptimizationProblem problem(robj, zp, bound, vcon, lp); + + // Define optimization problem. + ROL::Ptr> problem = ROL::makePtr>(robj,zp); + problem->addBoundConstraint(bound); + problem->addLinearConstraint("Volume Constraint",vcon,lp); + problem->finalize(false,true,*outStream); bool derivCheck = true; // Derivative check flag. - if (derivCheck) { - problem.check(*outStream); - } - ROL::OptimizationSolver solver(problem, *parlist); + if (derivCheck) problem->check(true,*outStream); + // Solve optimization problem. + ROL::Solver solver(problem, *parlist); solver.solve(*outStream); } catch (std::logic_error& err) { diff --git a/packages/rol/example/topology-optimization/input.xml b/packages/rol/example/topology-optimization/input.xml index d5d8157988f9..04d6678df0d6 100644 --- a/packages/rol/example/topology-optimization/input.xml +++ b/packages/rol/example/topology-optimization/input.xml @@ -2,6 +2,7 @@ + diff --git a/packages/rol/example/topology-optimization/input_ex02.xml b/packages/rol/example/topology-optimization/input_ex02.xml index 1ed82585eaf7..e3c4e128bd15 100644 --- a/packages/rol/example/topology-optimization/input_ex02.xml +++ b/packages/rol/example/topology-optimization/input_ex02.xml @@ -23,8 +23,8 @@ - + @@ -52,7 +52,7 @@ - + @@ -92,7 +92,7 @@ - + diff --git a/packages/rol/pyrol/CMakeLists.txt b/packages/rol/pyrol/CMakeLists.txt index 9857e19eec0a..8efacf8edb59 100644 --- a/packages/rol/pyrol/CMakeLists.txt +++ b/packages/rol/pyrol/CMakeLists.txt @@ -22,14 +22,19 @@ TRIBITS_ADD_OPTION_AND_DEFINE(PYROL_BINDER_SUPPRESS_ERRORS "Enable the suppress errors option of Binder." OFF ) +TRIBITS_ADD_OPTION_AND_DEFINE(PYROL_BINDER_USE_ONE_FILE + PYROL_USE_ONE_FILE + "Enable the use of one file by Binder." + OFF ) + TRIBITS_ADD_OPTION_AND_DEFINE(PYROL_BINDER_CMAKE_ERROR PYROL_CMAKE_ERROR - "Stop the configuration if binder fails." + "Stop the configuration if Binder fails." ON ) TRIBITS_ADD_OPTION_AND_DEFINE(PYROL_BINDER_VERBOSE PYROL_B_VERBOSE - "Increase the verbosity of binder" + "Increase the verbosity of Binder" OFF ) TRIBITS_ADD_OPTION_AND_DEFINE(PYROL_ENABLE_BINDER_UPDATE @@ -87,6 +92,7 @@ list(APPEND ROL_all_include_dirs "${${PACKAGE_NAME}_SOURCE_DIR}/src/algorithm") list(APPEND ROL_all_include_dirs "${${PACKAGE_NAME}_SOURCE_DIR}/src/algorithm/TypeB") list(APPEND ROL_all_include_dirs "${${PACKAGE_NAME}_SOURCE_DIR}/src/algorithm/TypeE") list(APPEND ROL_all_include_dirs "${${PACKAGE_NAME}_SOURCE_DIR}/src/algorithm/TypeG") +list(APPEND ROL_all_include_dirs "${${PACKAGE_NAME}_SOURCE_DIR}/src/algorithm/TypeP") list(APPEND ROL_all_include_dirs "${${PACKAGE_NAME}_SOURCE_DIR}/src/algorithm/TypeU") list(APPEND ROL_all_include_dirs "${${PACKAGE_NAME}_SOURCE_DIR}/src/algorithm/TypeB/pqn") list(APPEND ROL_all_include_dirs "${${PACKAGE_NAME}_SOURCE_DIR}/src/algorithm/TypeG/augmentedlagrangian/") @@ -223,15 +229,6 @@ IF (PYROL_GENERATE_SRC) endforeach() endforeach() - - #list(REMOVE_DUPLICATES PyROL_all_include_files_without_dir) - #list(REMOVE_ITEM PyROL_all_include_files_without_dir "") - - #list(REMOVE_DUPLICATES PyROL_all_include_files_with_dir) - #list(REMOVE_ITEM PyROL_all_include_files_with_dir "") - - #MESSAGE("PyROL_all_include_files_with_dir = ${PyROL_all_include_files_with_dir}") - SET(CONTENTS "") FOREACH(line IN LISTS all_include_dirs) SET(CONTENTS "${CONTENTS}${line}\n") @@ -252,7 +249,7 @@ IF (PYROL_GENERATE_SRC) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/python) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src) - + file (GLOB PyROLPyFiles2 "${CMAKE_CURRENT_BINARY_DIR}/python/*.py") list (APPEND PyROLPyFiles ${PyROLPyFiles2}) @@ -264,7 +261,12 @@ IF (PYROL_GENERATE_SRC) list(APPEND BINDER_OPTIONS ${binder_include_name}) list(APPEND BINDER_OPTIONS --root-module pyrol) list(APPEND BINDER_OPTIONS --prefix ${CMAKE_CURRENT_BINARY_DIR}/binder) - list(APPEND BINDER_OPTIONS -max-file-size=1000000) + IF(PYROL_USE_ONE_FILE) + list(APPEND BINDER_OPTIONS -single-file) + ELSE() + list(APPEND BINDER_OPTIONS -max-file-size=1000000) + list(APPEND BINDER_OPTIONS -flat) + ENDIF() list(APPEND BINDER_OPTIONS --bind Teuchos) list(APPEND BINDER_OPTIONS --bind ROL) list(APPEND BINDER_OPTIONS --bind pyrol) @@ -274,7 +276,7 @@ IF (PYROL_GENERATE_SRC) list(APPEND BINDER_OPTIONS --config ${BINDER_CFG}) IF(PYROL_SUPPRESS_ERRORS) list(APPEND BINDER_OPTIONS --suppress-errors) - ENDIF() + ENDIF() list(APPEND BINDER_OPTIONS --) IF(TPL_ENABLE_CUDA) list(APPEND BINDER_OPTIONS -x cuda --cuda-host-only) @@ -294,10 +296,18 @@ IF (PYROL_GENERATE_SRC) message("BINDER_OPTIONS='${BINDER_OPTIONS}'") + IF(NOT PYROL_USE_ONE_FILE) + MATH(EXPR NUMBER_FILE "${PYROL_BINDER_NUM_FILES}") + + foreach(index RANGE 0 ${NUMBER_FILE}) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/binder/pyrol_${index}.cpp "") + endforeach() + ENDIF() + EXECUTE_PROCESS(COMMAND ${PyROL_BINDER_EXECUTABLE} ${BINDER_OPTIONS} RESULT_VARIABLE STATUS - OUTPUT_VARIABLE OUTPUT_BINDER + OUTPUT_VARIABLE OUTPUT_BINDER ) if(STATUS AND NOT STATUS EQUAL 0) @@ -308,7 +318,7 @@ IF (PYROL_GENERATE_SRC) message("BINDER FAILED: ${STATUS}") endif() else() - message(STATUS "BINDER SUCCESS:") + message(STATUS "BINDER SUCCESS:") message("${OUTPUT_BINDER}") endif() diff --git a/packages/rol/pyrol/example/pytorch/rosenbrock_torch.py b/packages/rol/pyrol/example/pytorch/rosenbrock_torch.py new file mode 100644 index 000000000000..a6e5da79f389 --- /dev/null +++ b/packages/rol/pyrol/example/pytorch/rosenbrock_torch.py @@ -0,0 +1,69 @@ +from TorchVectors import TensorVector +from TorchObjectives import TorchObjective + +from pyrol import getCout, Objective, Problem, Solver +from pyrol.vectors import NumPyVector + +from pyrol.pyrol.Teuchos import ParameterList + +import numpy as np +import time +import torch + + +class RosenbrockObjective(TorchObjective): + + def __init__(self): + super().__init__() + self.alpha = 100 + + def torch_value(self, x): + # return torch.sum(self.alpha*(x[::2]**2 - x[1::2])**2 + (x[::2] - 1)**2) + return torch.sum(self.alpha*(x[:-1]**2 - x[1:])**2 + (x[:-1] - 1)**2) + + +def build_parameter_list(): + params = ParameterList() + params['General'] = ParameterList() + params['General']['Output Level'] = 1 + params['Step'] = ParameterList() + params['Step']['Trust Region'] = ParameterList() + params['Step']['Trust Region']['Subproblem Solver'] = 'Truncated CG' + params['Status Test'] = ParameterList() + params['Status Test']['Iteration Limit'] = 10000 + + return params + + +def main(): + + torch.set_default_dtype(torch.float64) + + device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + #device = torch.device('cpu') + + start = time.time() + n = int(1e2) + print(device) + x = torch.empty(n, requires_grad=False, device=device) + x[ ::2] = -1.2 + x[1::2] = 1.0 + x = TensorVector(x) + + objective = RosenbrockObjective() + g = x.clone() + + stream = getCout() + + problem = Problem(objective, x, g) + # problem.checkDerivatives(True, stream) + + params = build_parameter_list() + solver = Solver(problem, params) + solver.solve(stream) + print(f"Solve time: {time.time() - start}\n") + + print(g.torch_object.device) + +if __name__ == "__main__": + main() diff --git a/packages/rol/pyrol/pyproject.toml b/packages/rol/pyrol/pyproject.toml index eadbd789546b..0138249c8c0e 100644 --- a/packages/rol/pyrol/pyproject.toml +++ b/packages/rol/pyrol/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["scikit-build-core>=0.3.3","pybind11 @ git+https://github.com/pybind/pybind11.git@smart_holder"] +requires = ["scikit-build-core>=0.3.3","pybind11 @ git+https://github.com/pybind/pybind11.git@c6c9a9e59b2b64393de0432aa6867ed27367912a"] build-backend = "scikit_build_core.build" @@ -47,3 +47,4 @@ ROL_ENABLE_PYROL = "ON" PYROL_ENABLE_BINDER = "OFF" PYROL_PIP_INSTALL = "ON" CMAKE_INSTALL_RPATH="$ORIGIN/lib64;$ORIGIN/lib;$ORIGIN;@loader_path/lib64;@loader_path/lib;@loader_path" +CMAKE_INTERPROCEDURAL_OPTIMIZATION="OFF" diff --git a/packages/rol/pyrol/python/__init__.py b/packages/rol/pyrol/python/__init__.py index 0aa9682944c4..1dbc5274c14d 100644 --- a/packages/rol/pyrol/python/__init__.py +++ b/packages/rol/pyrol/python/__init__.py @@ -1,6 +1,8 @@ import importlib from . getTypeName import getTypeName, getDefaultScalarType, ROL_classes, ROL_members +from pyrol.pyrol.Teuchos import ParameterList + __version__ = '0.1.0' def version(): diff --git a/packages/rol/pyrol/python/getTypeName.py b/packages/rol/pyrol/python/getTypeName.py index 7838425e1f0a..f71336fca1ac 100644 --- a/packages/rol/pyrol/python/getTypeName.py +++ b/packages/rol/pyrol/python/getTypeName.py @@ -19,13 +19,38 @@ def new_method(self, *args, **kwargs): return cls_method(self, *args, **kwargs) return new_method -def withTrackingConstructor(cls): +def _decorator23(value_method): + def value(*args): + if len(args) == 2: + x, tol = args + return value_method(x.get_1(), x.get_2(), tol) + elif len(args) == 3: + u, z, tol = args + return value_method(u, z, tol) + else: + raise ArgumentError("Unexcepted number of arguments") + return value + + +def _decorator34(value_method): + def value(*args): + if len(args) == 3: + c, x, tol = args + return value_method(c, x.get_1(), x.get_2(), tol) + elif len(args) == 4: + c, u, z, tol = args + return value_method(c, u, z, tol) + raise ArgumentError("Unexcepted number of arguments") + return value + + +def withTrackingConstructor(cls_name, cls): class newCls(cls): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._tracked_constructor_args = [] - + track(self, *args, **kwargs) method_names = [m for m in dir(cls) if callable(getattr(cls, m))] @@ -33,13 +58,18 @@ def __init__(self, *args, **kwargs): if name.startswith('add'): setattr(newCls, name, tracking_method(getattr(cls, name))) + if cls_name.find('Objective_SimOpt') == 0: + self.value = _decorator23(self.value) + elif cls_name.find('Constraint_SimOpt') == 0: + self.value = _decorator34(self.value) + return newCls ROL_members = {} for cls_name, cls_obj in inspect.getmembers(sys.modules['pyrol.pyrol.ROL']): if inspect.isclass(cls_obj): - cls_obj = withTrackingConstructor(cls_obj) + cls_obj = withTrackingConstructor(cls_name, cls_obj) trackedTypes.append(cls_obj) setattr(sys.modules['pyrol.pyrol.ROL'], cls_name, cls_obj) ROL_members[cls_name] = (cls_obj, inspect.isclass(cls_obj)) @@ -57,3 +87,11 @@ def getTypeName(class_name, scalar_type=getDefaultScalarType()): return ROL_classes[i][1] print("Warning: Unknown type \"{}\", the function returns None.".format(class_name)) return None + + +def getTypeName2(class_name): + for i in range(0, len(ROL_classes)): + if ROL_classes[i][0].lower().find(class_name.lower()) == 0: + return ROL_classes[i][1] + print("Warning: Unknown type \"{}\", the function returns None.".format(class_name)) + return None diff --git a/packages/rol/pyrol/scripts/PyROL_RCP.cfg b/packages/rol/pyrol/scripts/PyROL_RCP.cfg index f587597d046c..3d22c6b3fc4b 100644 --- a/packages/rol/pyrol/scripts/PyROL_RCP.cfg +++ b/packages/rol/pyrol/scripts/PyROL_RCP.cfg @@ -75,6 +75,7 @@ -function ROL::TypeB::AlgorithmFactory -function ROL::TypeE::AlgorithmFactory -function ROL::TypeG::AlgorithmFactory +-function ROL::TypeP::AlgorithmFactory -function ROL::TypeU::AlgorithmFactory -class ROL::ConstraintAssembler @@ -101,7 +102,7 @@ +trampoline_member_function_binder ROL::Vector::clone customClone +include_for_namespace ROL::PyROL --namespace ROL::details +# -namespace ROL::details #################################################r # std library # @@ -156,6 +157,7 @@ -class std::vector +class std::vector +class std::vector ++class std::vector> +class std::vector> -namespace __gnu_cxx diff --git a/packages/rol/pyrol/scripts/create_sdist b/packages/rol/pyrol/scripts/create_sdist index a19ba13ba4fc..6fb60d51e67f 100755 --- a/packages/rol/pyrol/scripts/create_sdist +++ b/packages/rol/pyrol/scripts/create_sdist @@ -4,10 +4,10 @@ # to and then run from the directory containing the ROL repository. -# - Users of this script should check that the variables below are defined +# - Users of this script should check that the variables below are defined # properly. ############################################################################## -TRILINOS_VERSION="14.5" +TRILINOS_VERSION="15.1" REPO_NAME="ROL-Trilinos" LLVM_PREFIX=$(spack location -i llvm) @@ -15,7 +15,7 @@ LLVM_VERSION=$(echo ${LLVM_PREFIX} | awk -F[\-\-] '{print $5}') GCC_PREFIX=$(spack location -i gcc) ############################################################################## -## Other prerequisites: +## Other prerequisites: # * Binder (after the changes on its smart_holder branch) if [ ! command -v binder &> /dev/null ] @@ -54,23 +54,20 @@ cmake -G Ninja \ -D CMAKE_INSTALL_PREFIX:PATH=install \ ./${REPO_NAME} -B./build -## Step 2: Run Binder. -make -C build - -## Step 3: Create the reduced tarball. +## Step 2: Create the reduced tarball. make package_source -C build TARBALL_NAME="trilinos-${TRILINOS_VERSION}-Source" -## Step 4: Unpack the reduced tarball. +## Step 3: Unpack the reduced tarball. [ -d ${TARBALL_NAME} ] && rm -rf ${TARBALL_NAME} tar -zxf "build/${TARBALL_NAME}.tar.gz" -mv ${TARBALL_NAME} pyrol +mv ${TARBALL_NAME} pyrol -## Step 5: Create an SDist from the tarball. +## Step 4: Create an SDist from the tarball. python -m pipx run build --sdist pyrol cp -r pyrol/dist/* . -## Step 6: Clean up. +## Step 5: Clean up. rm -rf build rm -rf ${REPO_NAME}/packages/rol/pyrol/binder rm -rf pyrol diff --git a/packages/rol/pyrol/src/CMakeLists.txt b/packages/rol/pyrol/src/CMakeLists.txt index 1ebc1e8ab97f..d086b86937d2 100644 --- a/packages/rol/pyrol/src/CMakeLists.txt +++ b/packages/rol/pyrol/src/CMakeLists.txt @@ -4,17 +4,41 @@ FILE(COPY ${PYROL_SRC} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) MESSAGE("CMAKE_CURRENT_BINARY_DIR = ${CMAKE_CURRENT_BINARY_DIR}") -file(STRINGS ${CMAKE_CURRENT_BINARY_DIR}/../binder/pyrol.sources BINDER_SRCS) +# file(STRINGS ${CMAKE_CURRENT_BINARY_DIR}/../binder/pyrol.sources BINDER_SRCS) list(TRANSFORM BINDER_SRCS PREPEND "${CMAKE_CURRENT_BINARY_DIR}/../binder/") list(APPEND PYROL_SRC ${BINDER_SRCS}) -MESSAGE("PYROL_SRC with binder = ${PYROL_SRC}") +list(APPEND PYROL_SRC ${CMAKE_CURRENT_BINARY_DIR}/../binder/pyrol.cpp) + +IF(NOT PYROL_USE_ONE_FILE) + MATH(EXPR NUMBER_FILE "${PYROL_BINDER_NUM_FILES}") + + foreach(index RANGE 0 ${NUMBER_FILE}) + list(APPEND PYROL_SRC ${CMAKE_CURRENT_BINARY_DIR}/../binder/pyrol_${index}.cpp) + endforeach() + + MATH(EXPR NUMBER_FILE "${NUMBER_FILE}+1") + + EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" + -D "NUMBER_FILE=${NUMBER_FILE}" + -P "${CMAKE_CURRENT_SOURCE_DIR}/checkNumberFiles.cmake" + RESULT_VARIABLE STATUS + OUTPUT_VARIABLE OUTPUT_CHECKNUMBERFILES + ) + + if(STATUS AND NOT STATUS EQUAL 0) + message("${OUTPUT_CHECKNUMBERFILES}") + message(FATAL_ERROR "checkNumberFiles FAILED: ${STATUS}") + endif() +ENDIF() + +MESSAGE("PYROL_SRC with Binder = ${PYROL_SRC}") pybind11_add_module(pyrol ${PYROL_SRC}) target_include_directories(pyrol PUBLIC ${Mpi4Py_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/../binder "$") target_compile_features(pyrol PUBLIC cxx_std_14) -foreach(depPkg IN LISTS ROL_LIB_ENABLED_DEPENDENCIES) +foreach(depPkg IN LISTS ROL_LIB_ENABLED_DEPENDENCIES) target_link_libraries(pyrol PUBLIC ${depPkg}::all_libs) endforeach() target_link_libraries(pyrol PUBLIC ${Trilinos_EXTRA_LINK_FLAGS}) @@ -25,5 +49,5 @@ INSTALL(TARGETS pyrol add_custom_command(TARGET pyrol POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/pyrol.so ${CMAKE_CURRENT_BINARY_DIR}/../pyrol/. - COMMENT "Copy ${PROJECT_BINARY_DIR}/src/PyROL.so" + COMMENT "Copy ${PROJECT_BINARY_DIR}/src/pyrol.so" ) diff --git a/packages/rol/pyrol/src/PyROL_ETI.hpp b/packages/rol/pyrol/src/PyROL_ETI.hpp index f46a1783ab21..857443539003 100644 --- a/packages/rol/pyrol/src/PyROL_ETI.hpp +++ b/packages/rol/pyrol/src/PyROL_ETI.hpp @@ -10,68 +10,83 @@ #ifndef PYROL_ETI #define PYROL_ETI -#include -#include -#include -#include -#include +#include -#include -#include -#include -#include #include -#include - +#include +#include +#include +#include +#include +#include #include +#include #include - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define BINDER_ETI_ABSTRACT(CLASS_NAME) \ template class CLASS_NAME; -#define BINDER_ETI_WITH_FOO(CLASS_NAME) \ - template class CLASS_NAME; \ - template <> inline void PyROL::foo(CLASS_NAME a){} +// #define BINDER_ETI_WITH_FOO(CLASS_NAME) \ +// template class CLASS_NAME; \ +// template <> inline void PyROL::foo(CLASS_NAME a){} -#define BINDER_ROL_VECTOR(SCALAR) \ - BINDER_ETI_ABSTRACT(Vector) \ - BINDER_ETI_ABSTRACT(Vector_SimOpt) - -#define BINDER_ROL_OBJECTIVE(SCALAR) \ +#define BINDER_ROL_CORE(SCALAR) \ + BINDER_ETI_ABSTRACT(Constraint) \ BINDER_ETI_ABSTRACT(Objective) \ - BINDER_ETI_ABSTRACT(Objective_SimOpt) \ - BINDER_ETI_ABSTRACT(Reduced_Objective_SimOpt) \ - BINDER_ETI_ABSTRACT(ReducedDynamicObjective) + BINDER_ETI_ABSTRACT(Problem) \ + BINDER_ETI_ABSTRACT(Solver) \ + BINDER_ETI_ABSTRACT(Vector) -#define BINDER_ROL_CONSTRAINT(SCALAR) \ - BINDER_ETI_ABSTRACT(Constraint) \ - BINDER_ETI_ABSTRACT(SimConstraint) \ +#define BINDER_ROL_SIMOPT(SCALAR) \ BINDER_ETI_ABSTRACT(BoundConstraint_SimOpt) \ - BINDER_ETI_ABSTRACT(SerialConstraint) + BINDER_ETI_ABSTRACT(Reduced_Objective_SimOpt) \ + BINDER_ETI_ABSTRACT(SimConstraint) \ + BINDER_ETI_ABSTRACT(Vector_SimOpt) -#define BINDER_ROL_SOLVER(SCALAR) \ - BINDER_ETI_ABSTRACT(Solver) +#define BINDER_ROL_DYNAMIC(SCALAR) \ + BINDER_ETI_ABSTRACT(DynamicConstraintCheck) \ + BINDER_ETI_ABSTRACT(DynamicObjectiveCheck) \ + BINDER_ETI_ABSTRACT(ReducedDynamicObjective) \ + BINDER_ETI_ABSTRACT(SerialConstraint) \ + BINDER_ETI_ABSTRACT(SerialObjective) -#define BINDER_ROL_PROBLEM(SCALAR) \ - BINDER_ETI_ABSTRACT(Problem) +#define BINDER_ROL_UTILS(SCALAR) \ + BINDER_ETI_ABSTRACT(ValidateFunction) + +#define BINDER_ROL_STOCHASTIC(SCALAR) \ + BINDER_ETI_ABSTRACT(MonteCarloGenerator) \ + BINDER_ETI_ABSTRACT(RiskNeutralObjective) \ + BINDER_ETI_ABSTRACT(SampleGenerator) #define BINDER_ROL_OED(SCALAR) \ BINDER_ETI_ABSTRACT(Factory) namespace ROL { - BINDER_ROL_VECTOR(double) - BINDER_ROL_OBJECTIVE(double) - BINDER_ROL_CONSTRAINT(double) - BINDER_ROL_SOLVER(double) - BINDER_ROL_PROBLEM(double) + BINDER_ROL_CORE(double) + BINDER_ROL_SIMOPT(double) + BINDER_ROL_DYNAMIC(double) + BINDER_ROL_STOCHASTIC(double) + +namespace details { + BINDER_ROL_UTILS(double) +} namespace OED { BINDER_ROL_OED(double) } + } #endif // PYROL_ETI diff --git a/packages/rol/pyrol/src/checkNumberFiles.cmake b/packages/rol/pyrol/src/checkNumberFiles.cmake new file mode 100644 index 000000000000..9cdbbcf3357d --- /dev/null +++ b/packages/rol/pyrol/src/checkNumberFiles.cmake @@ -0,0 +1,12 @@ +if(NOT NUMBER_FILE) + message(FATAL_ERROR "NUMBER_FILE must be specified") +endif() + +if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/../binder/pyrol_${NUMBER_FILE}.cpp) + MATH(EXPR INDEX "${NUMBER_FILE}+1") + while (EXISTS ${CMAKE_CURRENT_BINARY_DIR}/../binder/pyrol_${INDEX}.cpp) + MATH(EXPR INDEX "${INDEX}+1") + endwhile() + MATH(EXPR INDEX "${INDEX}-1") + message(FATAL_ERROR "File pyrol_${NUMBER_FILE}.cpp exists; please rerun the configuration with PyROL_BINDER_NUM_FILES at least equal to ${INDEX}.") +endif() diff --git a/packages/rol/refactor/parameterlist.py b/packages/rol/refactor/parameterlist.py new file mode 100644 index 000000000000..3acb9af9a135 --- /dev/null +++ b/packages/rol/refactor/parameterlist.py @@ -0,0 +1,115 @@ +import sys +import os +import re +import subprocess as sp +from pathlib import Path + +# +# regex pattern | meaning +# --------------+---------------------------------------------- +# \s* | arbitrary amount of whitespace including none +# \( | literal left parenthesis +# \) | literal right parenthesis +# \. | literal period +# +# ParameterList::get("name","value") +# +# re.search(r'\.\s*get\s*"[a-zA-Z0-9]+"\s*,', source_code) + + +def get_rol_headers(rol_path : Path, token : str) -> [Path]: + result = sp.Popen(['grep','-rl',token,'--include=*.hpp',rol_path],stdout=sp.PIPE) + return [Path(line.decode('utf-8').strip()) for line in result.stdout] + + +def read_file(pathfile : Path) -> str: + with open(pathfile,"r") as f: + text = f.read() + return text + +def strip_cpp_comments( cpp_source : str ) -> str: + + in_string = False + in_single_line_comment = False + in_multi_line_comment = False + result = [] + i = 0 + + while i < len(cpp_source): + + # Check for string start/end + if cpp_source[i] == '"' and not (in_single_line_comment or in_multi_line_comment): + in_string = not in_string + result.append(cpp_source[i]) + # Check for single-line comment start + + elif i+1 < len(cpp_source) and cpp_source[i:i+2] == "//" and not (in_string or in_multi_line_comment): + in_single_line_comment = True + i += 1 # Skip next character to avoid parsing '/' twice + + # Check for multi-line comment start + elif i + 1 < len(cpp_source) and cpp_source[i:i+2] == "/*" and not (in_string or in_single_line_comment): + in_multi_line_comment = True + i += 1 # Skip next character to avoid parsing '*' twice + + # Check for single-line comment end + elif in_single_line_comment and cpp_source[i] == "\n": + in_single_line_comment = False + result.append(cpp_source[i]) # Include newline in result + + # Check for multi-line comment end + elif i + 1 < len(cpp_source) and in_multi_line_comment and cpp_source[i:i+2] == "*/": + in_multi_line_comment = False + i += 1 # Skip next character to avoid parsing '/' twice + + # Append character if not in a comment + elif not (in_single_line_comment or in_multi_line_comment): + result.append(cpp_source[i]) + + i += 1 + + return ''.join(result) + + +def contains_escaped_quote_advanced(s: str) -> bool: + i = 0 + while i < len(s): + if s[i] == '\\': + backslash_count = 1 + i += 1 + + # Count consecutive backslashes + while i < len(s) and s[i] == '\\': + backslash_count += 1 + i += 1 + + # If there's an odd number of backslashes followed by a quote, then it is escaped + if i < len(s) and s[i] == '"' and backslash_count % 2 == 1: + return True + else: + i += 1 + return False + + +if __name__ == '__main__': + + """ + Currently iterates over all ROL header files that contain the token (default: ParameterList) + then looks for calls to ParameterList::get and prints the entire "line" from the start of the + line to the end of the statement (semicolon). Ignores code comments + """ + + assert( len(sys.argv) > 1 ) + rol_root_path = sys.argv[1] + + token = 'ParameterList' if len(sys.argv) < 3 else sys.argv[2] + + pattern = re.compile(r'^.*?(\.get\s*\(\s*"[^"]*"\s*,(.*)\)\s*;)',re.MULTILINE) + headers = get_rol_headers(rol_root_path,token) + for h in headers: + cpp = strip_cpp_comments(read_file(h)) + matches = re.finditer(pattern,cpp) + print(h) + for m in matches: + print(m.group(0)) + diff --git a/packages/rol/rol_parameters/find_parameters.sh b/packages/rol/rol_parameters/find_parameters.sh new file mode 100755 index 000000000000..0677cdad2821 --- /dev/null +++ b/packages/rol/rol_parameters/find_parameters.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# File: find_parameters.sh + +# Strip C/C++ style comments from source code +remove_comments() { + perl -0777 -pe 's{//.*$}{}gm; s{/\*.*?\*/}{}gs' +} + +# Check if a directory is provided as an argument, otherwise use the current directory +search_dir="${1:-.}" + +# Verify that the directory exists +if [ ! -d "${search_dir}" ]; then + echo "Error: Directory '${search_dir}' does not exist." + echo "Usage: ${0} [directory_to_search]" + exit 1 +fi + +# Updated pattern definitions +getset_pattern="(\.|\->)\s*((s|g)et|sublist)\s*\(\s*\"" +sublist_pattern="(\.|\->)\s*sublist\s*\(\s*\"" +pattern="${getset_pattern}|${sublist_pattern}" + +# Function to generate find's -not -path arguments for excluded directories +generate_exclude_args() { + local IFS=',' + local exclude_args="" + for dir in $1; do + exclude_args="${exclude_args} -not -path */${dir}/*" + done + echo ${exclude_args} +} + +excluded_dirs="compatability,dynamic,interiorpoint,oed,sol,zoo" +exclude_args=$(generate_exclude_args "${excluded_dirs}") + +find "${search_dir}" -type f -name '*.hpp' ${exclude_args} | while read -r file; do + result=$(remove_comments < "${file}" | grep -E "${pattern}" || true) + if [ -n "${result}" ]; then + echo "$result" | while IFS= read -r line; do + echo "${file}:${line}" + done + fi +done diff --git a/packages/rol/rol_parameters/poetry.lock b/packages/rol/rol_parameters/poetry.lock new file mode 100644 index 000000000000..1034779ff54e --- /dev/null +++ b/packages/rol/rol_parameters/poetry.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +package = [] + +[metadata] +lock-version = "2.0" +python-versions = "^3.12" +content-hash = "34e39677d8527182346093002688d17a5d2fc204b9eb3e094b2e6ac519028228" diff --git a/packages/rol/rol_parameters/pyproject.toml b/packages/rol/rol_parameters/pyproject.toml new file mode 100644 index 000000000000..19198f3c5d4a --- /dev/null +++ b/packages/rol/rol_parameters/pyproject.toml @@ -0,0 +1,9 @@ +[tool.poetry] +name = "rol_parameters" +version = "0.1.0" +description = "ROL Parameters - and automated parameter scraper and database maintainer" +authors = ["Greg von Winckel "] + +[tool.poetry.dependencies] +python = "^3.12" + diff --git a/packages/rol/rol_parameters/rol_parameters.py b/packages/rol/rol_parameters/rol_parameters.py new file mode 100644 index 000000000000..c3c970640819 --- /dev/null +++ b/packages/rol/rol_parameters/rol_parameters.py @@ -0,0 +1,175 @@ +# File rol_parameters.py +import sys +import json +import pathlib +import re +import subprocess +from typing import Dict, List +from collections import defaultdict + +def hierarchy_to_json(tuple_set): + def add_to_hierarchy(hierarchy, path, item_type): + current = hierarchy + for part in path[:-1]: + if part not in current["Sublists"]: + current["Sublists"][part] = {"Parameters": [], "Sublists": {}} + current = current["Sublists"][part] + + if item_type == "Parameter": + current["Parameters"].append(path[-1]) + elif item_type == "Sublist": + if path[-1] not in current["Sublists"]: + current["Sublists"][path[-1]] = {"Parameters": [], "Sublists": {}} + + root = {"Parameters": [], "Sublists": {}} + + for tuple_path in tuple_set: + path = [item[0] for item in tuple_path] + item_type = tuple_path[-1][1] + add_to_hierarchy(root, path, item_type) + + return root + +from xml.etree.ElementTree import Element, SubElement, tostring +from xml.dom import minidom + +def json_to_xml(json_obj): + def create_parameter_list(name, data): + param_list = Element("ParameterList", name=name) + + if "Parameters" in data and data["Parameters"]: + param_str = ",".join(data["Parameters"]) + param = SubElement(param_list, "Parameter", name="Parameters", type="Array(string)", value=f"{{{param_str}}}") + + if "Sublists" in data: + for sublist_name, sublist_data in data["Sublists"].items(): + sub_param_list = create_parameter_list(sublist_name, sublist_data) + if len(sub_param_list) > 0: + param_list.append(sub_param_list) + + return param_list + + root = create_parameter_list("ROL Parameters", json_obj) + + # Remove empty ParameterLists + for elem in root.iter("ParameterList"): + if len(elem) == 0: + root.remove(elem) + + # Convert to string and pretty print + rough_string = tostring(root, 'utf-8') + reparsed = minidom.parseString(rough_string) + return reparsed.toprettyxml(indent=" ") + +def pretty_print_xml(xml_str : str): + def remove_extra_newlines(string : str): + return '\n'.join(line for line in string.split('\n') if line.strip()) + parsed_xml = minidom.parseString(xml_str) + return remove_extra_newlines(parsed_xml.toprettyxml(indent=" ")) + + +def replace_whitespace(input_string): + return re.sub(r'\s{2,}', ' ', input_string) + +def dereference(code): + return re.sub(r'\&','',code) + + +def extract_quoted_strings(input_string): + # Use a regular expression to find all substrings in double quotes + matches = re.findall(r'"(.*?)"', input_string) + # Convert the list of matches to a tuple + return tuple(matches) + +def get_lines( search_path : pathlib.Path ) -> List[str]: + try: + result = subprocess.run(['./find_parameters.sh', search_path], capture_output=True, text=True, check=True) + return result.stdout.splitlines() + except subprocess.CalledProcessError as e: + print(f"Error occurred: {e}") + +def prune_tuples(data): + # Sort the tuples by length in descending order + sorted_data = sorted(data, key=len, reverse=True) + + result = [] + leading_elements_set = set() + + for tup in sorted_data: + # Create a leading element tuple (all but the last element) + leading_elements = tup[:-1] + + # Check if the leading elements are already in the set + if leading_elements not in leading_elements_set: + # If not, add the tuple to the result and update the set + result.append(tup) + leading_elements_set.add(leading_elements) + + return result + + +if __name__ == '__main__': + + src = sys.argv[1] + grep_pattern = r'(\.|\->)\s*((s|g)et|sublist)\s*\(\s*\"' + exclude_dirs = 'compatability,dynamic,interiorpoint,oed,sol,zoo' + + # Get all lines in C++ source in which a ParameterList's sublist, get, or set method is called + lines = get_lines(src) + + data = defaultdict(list) + + defines_local_sublist = lambda line: line.split('.')[-1].startswith('sublist') + + for line in lines: + filename,code = line.split(':',1) + if not code.startswith('//'): # Excluded commented out lines + data[filename].append(replace_whitespace(code.strip())) + + pattern = re.compile(r'(?:sublist|get|set)\s*\(\s*"([^"]*)"\s*(?:\)|,)') + + expanded_lines = list() + + for key, value in data.items(): + ldefs = dict() + for line in value: + if defines_local_sublist(line): + lhs, rhs = line.split('=') + if len(dereference(lhs).split()) == 2: + var = dereference(lhs).split()[1] + ldefs[var] = rhs.strip()[:-1] + + if len(ldefs): + for cycle in range(len(ldefs)): + for k,v in ldefs.items(): + vl,vr = v.split('.',1) + if vl in ldefs.keys(): + ldefs[k] = f'{ldefs[vl]}.{vr}' + + + for line in value: + exline = line + for k,v in ldefs.items(): + exline = re.sub(rf' {k}.',rf' {v}.', exline) + expanded_lines.append(exline) + + pair_tuples = set() + for line in expanded_lines: + if '=' in line: + line = line.split('=')[1] + if 'et(' in line and 'SOL' not in line: + line = line.split(',')[0] + token_tuple = extract_quoted_strings(line) + depth = len(token_tuple) + if depth > 1: + type_tuple = ('Sublist',) * (depth-1) + ('Parameter',) + pair_tuples.add(tuple(zip(token_tuple,type_tuple))) + + rol_json = hierarchy_to_json(set(pair_tuples)) + with open('rol_parameters.json','w') as jsonfile: + jsonfile.write(json.dumps(rol_json,indent=2)) + + xml_output = json_to_xml(rol_json) + pretty_xml_output = pretty_print_xml(xml_output) + with open('rol_parameters.xml','w') as xmlfile: + xmlfile.write(pretty_xml_output) diff --git a/packages/rol/src/algorithm/ROL_Problem.hpp b/packages/rol/src/algorithm/ROL_Problem.hpp index 46e53a6e1e14..26b4a153e773 100644 --- a/packages/rol/src/algorithm/ROL_Problem.hpp +++ b/packages/rol/src/algorithm/ROL_Problem.hpp @@ -31,6 +31,7 @@ class Problem { bool hasInequality_; bool hasLinearEquality_; bool hasLinearInequality_; + bool hasProximableObjective_; unsigned cnt_econ_; unsigned cnt_icon_; unsigned cnt_linear_econ_; @@ -39,6 +40,7 @@ class Problem { ParameterList ppa_list_; Ptr> obj_; + Ptr> nobj_; Ptr> xprim_; Ptr> xdual_; Ptr> bnd_; @@ -55,6 +57,7 @@ class Problem { protected: Ptr> INPUT_obj_; + Ptr> INPUT_nobj_; Ptr> INPUT_xprim_; Ptr> INPUT_xdual_; Ptr> INPUT_bnd_; @@ -85,12 +88,14 @@ class Problem { hasInequality_(problem.hasInequality_), hasLinearEquality_(problem.hasLinearEquality_), hasLinearInequality_(problem.hasLinearInequality_), + hasProximableObjective_(problem.hasProximableObjective_), cnt_econ_(problem.cnt_econ_), cnt_icon_(problem.cnt_icon_), cnt_linear_econ_(problem.cnt_linear_econ_), cnt_linear_icon_(problem.cnt_linear_icon_), ppa_list_(problem.ppa_list_), INPUT_obj_(problem.INPUT_obj_), + INPUT_nobj_(problem.INPUT_nobj_), INPUT_xprim_(problem.INPUT_xprim_), INPUT_xdual_(problem.INPUT_xdual_), INPUT_bnd_(problem.INPUT_bnd_), @@ -188,6 +193,15 @@ class Problem { @param[in] ppa polyhedral projection algorithm */ void setProjectionAlgorithm(ParameterList &parlist); + + /** Set Proximable objective function + */ + void addProximableObjective(const Ptr> &nobj); + + /** Remove Proximable objective function + */ + void removeProximableObjective(); + /***************************************************************************/ /*** Accessor methods ******************************************************/ @@ -196,6 +210,10 @@ class Problem { /** \brief Get the objective function. */ const Ptr>& getObjective(); + + /** \brief Get proximable objective + */ + const Ptr>& getProximableObjective(); /** \brief Get the primal optimization space vector. */ @@ -226,7 +244,7 @@ class Problem { */ const Ptr>& getPolyhedralProjection(); - /** \brief Get the optimization problem type (U, B, E, or G). + /** \brief Get the optimization problem type (U, B, E, G, or P). */ EProblem getProblemType(); diff --git a/packages/rol/src/algorithm/ROL_Problem_Def.hpp b/packages/rol/src/algorithm/ROL_Problem_Def.hpp index 4d0ff3c2d9f3..ae0d0d417a41 100644 --- a/packages/rol/src/algorithm/ROL_Problem_Def.hpp +++ b/packages/rol/src/algorithm/ROL_Problem_Def.hpp @@ -21,11 +21,13 @@ Problem::Problem( const Ptr> &obj, : isFinalized_(false), hasBounds_(false), hasEquality_(false), hasInequality_(false), hasLinearEquality_(false), hasLinearInequality_(false), + hasProximableObjective_(false), cnt_econ_(0), cnt_icon_(0), cnt_linear_econ_(0), cnt_linear_icon_(0), - obj_(nullPtr), xprim_(nullPtr), xdual_(nullPtr), bnd_(nullPtr), + obj_(nullPtr), nobj_(nullPtr), xprim_(nullPtr), xdual_(nullPtr), bnd_(nullPtr), con_(nullPtr), mul_(nullPtr), res_(nullPtr), proj_(nullPtr), problemType_(TYPE_U) { INPUT_obj_ = obj; + INPUT_nobj_ = nullPtr; INPUT_xprim_ = x; INPUT_bnd_ = nullPtr; INPUT_con_.clear(); @@ -52,6 +54,23 @@ void Problem::removeBoundConstraint() { hasBounds_ = false; } +template +void Problem::addProximableObjective(const Ptr> &nobj) { + ROL_TEST_FOR_EXCEPTION(isFinalized_,std::invalid_argument, + ">>> ROL::Problem: Cannot add regularizer after problem is finalized!"); + + INPUT_nobj_ = nobj; + hasProximableObjective_ = true; +} + +template +void Problem::removeProximableObjective() { + ROL_TEST_FOR_EXCEPTION(isFinalized_,std::invalid_argument, + ">>> ROL::Problem: Cannot remove regularizer after problem is finalized!"); + + INPUT_nobj_ = nullPtr; + hasProximableObjective_ = false; +} template void Problem::addConstraint( std::string name, const Ptr> &econ, @@ -176,10 +195,11 @@ template void Problem::finalize(bool lumpConstraints, bool printToStream, std::ostream &outStream) { if (!isFinalized_) { std::unordered_map> con, lcon, icon; - bool hasEquality = hasEquality_; - bool hasLinearEquality = hasLinearEquality_; - bool hasInequality = hasInequality_; - bool hasLinearInequality = hasLinearInequality_; + bool hasEquality = hasEquality_; + bool hasLinearEquality = hasLinearEquality_; + bool hasInequality = hasInequality_; + bool hasLinearInequality = hasLinearInequality_; + bool hasProximableObjective = hasProximableObjective_; con.insert(INPUT_con_.begin(),INPUT_con_.end()); if (lumpConstraints) { con.insert(INPUT_linear_con_.begin(),INPUT_linear_con_.end()); @@ -193,127 +213,146 @@ void Problem::finalize(bool lumpConstraints, bool printToStream, std::ostr } // Transform optimization problem //std::cout << hasBounds_ << " " << hasEquality << " " << hasInequality << " " << hasLinearEquality << " " << hasLinearInequality << std::endl; - if (!hasLinearEquality && !hasLinearInequality) { - proj_ = nullPtr; - if (!hasEquality && !hasInequality && !hasBounds_) { - problemType_ = TYPE_U; + nobj_ = nullPtr; + if (hasProximableObjective){ + if (!hasEquality && !hasInequality && !hasBounds_ && !hasLinearEquality && !hasLinearInequality){ + problemType_ = TYPE_P; obj_ = INPUT_obj_; + nobj_ = INPUT_nobj_; xprim_ = INPUT_xprim_; xdual_ = INPUT_xdual_; bnd_ = nullPtr; con_ = nullPtr; mul_ = nullPtr; res_ = nullPtr; - } - else if (!hasEquality && !hasInequality && hasBounds_) { - problemType_ = TYPE_B; - obj_ = INPUT_obj_; - xprim_ = INPUT_xprim_; - xdual_ = INPUT_xdual_; - bnd_ = INPUT_bnd_; - con_ = nullPtr; - mul_ = nullPtr; - res_ = nullPtr; - } - else if (hasEquality && !hasInequality && !hasBounds_) { - ConstraintAssembler cm(con,INPUT_xprim_,INPUT_xdual_); - problemType_ = TYPE_E; - obj_ = INPUT_obj_; - xprim_ = INPUT_xprim_; - xdual_ = INPUT_xdual_; - bnd_ = nullPtr; - con_ = cm.getConstraint(); - mul_ = cm.getMultiplier(); - res_ = cm.getResidual(); - } - else { - ConstraintAssembler cm(con,INPUT_xprim_,INPUT_xdual_,INPUT_bnd_); - problemType_ = TYPE_EB; - obj_ = INPUT_obj_; - if (cm.hasInequality()) { - obj_ = makePtr>(INPUT_obj_); - } - xprim_ = cm.getOptVector(); - xdual_ = cm.getDualOptVector(); - bnd_ = cm.getBoundConstraint(); - con_ = cm.getConstraint(); - mul_ = cm.getMultiplier(); - res_ = cm.getResidual(); - } + } + else { + throw Exception::NotImplemented(">>> ROL::TypeP - with constraints is not supported"); + } } - else { - if (!hasBounds_ && !hasLinearInequality) { - ConstraintAssembler cm(lcon,INPUT_xprim_,INPUT_xdual_); - xfeas_ = cm.getOptVector()->clone(); xfeas_->set(*cm.getOptVector()); - rlc_ = makePtr>(cm.getConstraint(),xfeas_,cm.getResidual()); - proj_ = nullPtr; - if (!hasEquality && !hasInequality) { + else { + if (!hasLinearEquality && !hasLinearInequality) { + proj_ = nullPtr; + if (!hasEquality && !hasInequality && !hasBounds_ ) { problemType_ = TYPE_U; - obj_ = rlc_->transform(INPUT_obj_); - xprim_ = xfeas_->clone(); xprim_->zero(); - xdual_ = cm.getDualOptVector(); + obj_ = INPUT_obj_; + xprim_ = INPUT_xprim_; + xdual_ = INPUT_xdual_; bnd_ = nullPtr; con_ = nullPtr; mul_ = nullPtr; res_ = nullPtr; } + else if (!hasEquality && !hasInequality && hasBounds_) { + problemType_ = TYPE_B; + obj_ = INPUT_obj_; + xprim_ = INPUT_xprim_; + xdual_ = INPUT_xdual_; + bnd_ = INPUT_bnd_; + con_ = nullPtr; + mul_ = nullPtr; + res_ = nullPtr; + } + else if (hasEquality && !hasInequality && !hasBounds_) { + ConstraintAssembler cm(con,INPUT_xprim_,INPUT_xdual_); + problemType_ = TYPE_E; + obj_ = INPUT_obj_; + xprim_ = INPUT_xprim_; + xdual_ = INPUT_xdual_; + bnd_ = nullPtr; + con_ = cm.getConstraint(); + mul_ = cm.getMultiplier(); + res_ = cm.getResidual(); + } else { - for (auto it = con.begin(); it != con.end(); ++it) { - icon.insert(std::pair>(it->first, - ConstraintData(rlc_->transform(it->second.constraint), - it->second.multiplier,it->second.residual,it->second.bounds))); + ConstraintAssembler cm(con,INPUT_xprim_,INPUT_xdual_,INPUT_bnd_); + problemType_ = TYPE_EB; + obj_ = INPUT_obj_; + if (cm.hasInequality()) { + obj_ = makePtr>(INPUT_obj_); } - Ptr> xtmp = xfeas_->clone(); xtmp->zero(); - ConstraintAssembler cm1(icon,xtmp,cm.getDualOptVector()); - xprim_ = cm1.getOptVector(); - xdual_ = cm1.getDualOptVector(); - con_ = cm1.getConstraint(); - mul_ = cm1.getMultiplier(); - res_ = cm1.getResidual(); - if (!hasInequality) { - problemType_ = TYPE_E; + xprim_ = cm.getOptVector(); + xdual_ = cm.getDualOptVector(); + bnd_ = cm.getBoundConstraint(); + con_ = cm.getConstraint(); + mul_ = cm.getMultiplier(); + res_ = cm.getResidual(); + } + } + else { + if (!hasBounds_ && !hasLinearInequality) { + ConstraintAssembler cm(lcon,INPUT_xprim_,INPUT_xdual_); + xfeas_ = cm.getOptVector()->clone(); xfeas_->set(*cm.getOptVector()); + rlc_ = makePtr>(cm.getConstraint(),xfeas_,cm.getResidual()); + proj_ = nullPtr; + if (!hasEquality && !hasInequality) { + problemType_ = TYPE_U; obj_ = rlc_->transform(INPUT_obj_); + xprim_ = xfeas_->clone(); xprim_->zero(); + xdual_ = cm.getDualOptVector(); bnd_ = nullPtr; + con_ = nullPtr; + mul_ = nullPtr; + res_ = nullPtr; } else { - problemType_ = TYPE_EB; - obj_ = makePtr>(rlc_->transform(INPUT_obj_)); - bnd_ = cm1.getBoundConstraint(); + for (auto it = con.begin(); it != con.end(); ++it) { + icon.insert(std::pair>(it->first, + ConstraintData(rlc_->transform(it->second.constraint), + it->second.multiplier,it->second.residual,it->second.bounds))); + } + Ptr> xtmp = xfeas_->clone(); xtmp->zero(); + ConstraintAssembler cm1(icon,xtmp,cm.getDualOptVector()); + xprim_ = cm1.getOptVector(); + xdual_ = cm1.getDualOptVector(); + con_ = cm1.getConstraint(); + mul_ = cm1.getMultiplier(); + res_ = cm1.getResidual(); + if (!hasInequality) { + problemType_ = TYPE_E; + obj_ = rlc_->transform(INPUT_obj_); + bnd_ = nullPtr; + } + else { + problemType_ = TYPE_EB; + obj_ = makePtr>(rlc_->transform(INPUT_obj_)); + bnd_ = cm1.getBoundConstraint(); + } } } - } - else if ((hasBounds_ || hasLinearInequality) && !hasEquality && !hasInequality) { - ConstraintAssembler cm(lcon,INPUT_xprim_,INPUT_xdual_,INPUT_bnd_); - problemType_ = TYPE_B; - obj_ = INPUT_obj_; - if (cm.hasInequality()) { - obj_ = makePtr>(INPUT_obj_); + else if ((hasBounds_ || hasLinearInequality) && !hasEquality && !hasInequality) { + ConstraintAssembler cm(lcon,INPUT_xprim_,INPUT_xdual_,INPUT_bnd_); + problemType_ = TYPE_B; + obj_ = INPUT_obj_; + if (cm.hasInequality()) { + obj_ = makePtr>(INPUT_obj_); + } + xprim_ = cm.getOptVector(); + xdual_ = cm.getDualOptVector(); + bnd_ = cm.getBoundConstraint(); + con_ = nullPtr; + mul_ = nullPtr; + res_ = nullPtr; + proj_ = PolyhedralProjectionFactory(*xprim_,*xdual_,bnd_, + cm.getConstraint(),*cm.getMultiplier(),*cm.getResidual(),ppa_list_); } - xprim_ = cm.getOptVector(); - xdual_ = cm.getDualOptVector(); - bnd_ = cm.getBoundConstraint(); - con_ = nullPtr; - mul_ = nullPtr; - res_ = nullPtr; - proj_ = PolyhedralProjectionFactory(*xprim_,*xdual_,bnd_, - cm.getConstraint(),*cm.getMultiplier(),*cm.getResidual(),ppa_list_); - } - else { - ConstraintAssembler cm(con,lcon,INPUT_xprim_,INPUT_xdual_,INPUT_bnd_); - problemType_ = TYPE_EB; - obj_ = INPUT_obj_; - if (cm.hasInequality()) { - obj_ = makePtr>(INPUT_obj_); + else { + ConstraintAssembler cm(con,lcon,INPUT_xprim_,INPUT_xdual_,INPUT_bnd_); + problemType_ = TYPE_EB; + obj_ = INPUT_obj_; + if (cm.hasInequality()) { + obj_ = makePtr>(INPUT_obj_); + } + xprim_ = cm.getOptVector(); + xdual_ = cm.getDualOptVector(); + con_ = cm.getConstraint(); + mul_ = cm.getMultiplier(); + res_ = cm.getResidual(); + bnd_ = cm.getBoundConstraint(); + proj_ = PolyhedralProjectionFactory(*xprim_,*xdual_,bnd_, + cm.getLinearConstraint(),*cm.getLinearMultiplier(), + *cm.getLinearResidual(),ppa_list_); } - xprim_ = cm.getOptVector(); - xdual_ = cm.getDualOptVector(); - con_ = cm.getConstraint(); - mul_ = cm.getMultiplier(); - res_ = cm.getResidual(); - bnd_ = cm.getBoundConstraint(); - proj_ = PolyhedralProjectionFactory(*xprim_,*xdual_,bnd_, - cm.getLinearConstraint(),*cm.getLinearMultiplier(), - *cm.getLinearResidual(),ppa_list_); } } isFinalized_ = true; @@ -321,6 +360,7 @@ void Problem::finalize(bool lumpConstraints, bool printToStream, std::ostr outStream << std::endl; outStream << " ROL::Problem::finalize" << std::endl; outStream << " Problem Summary:" << std::endl; + outStream << " Has Proximable Objective? .......... " << (hasProximableObjective ? "yes" : "no") << std::endl; outStream << " Has Bound Constraint? .............. " << (hasBounds_ ? "yes" : "no") << std::endl; outStream << " Has Equality Constraint? ........... " << (hasEquality ? "yes" : "no") << std::endl; if (hasEquality) { @@ -411,6 +451,12 @@ const Ptr>& Problem::getObjective() { return obj_; } +template +const Ptr>& Problem::getProximableObjective(){ + finalize(); + return nobj_; +} + template const Ptr>& Problem::getPrimalOptimizationVector() { finalize(); @@ -582,7 +628,7 @@ void Problem::checkDerivatives(bool printToStream, std::ostream &outStream INPUT_obj_->checkGradient(*x,*g,*d,printToStream,outStream); INPUT_obj_->checkHessVec(*x,*g,*d,printToStream,outStream); INPUT_obj_->checkHessSym(*x,*g,*d,*v,printToStream,outStream); - + //TODO: Proximable Objective Check // Constraint check for (auto it = INPUT_con_.begin(); it != INPUT_con_.end(); ++it) { c = it->second.residual->clone(); c->randomize(-scale,scale); @@ -612,6 +658,8 @@ void Problem::check(bool printToStream, std::ostream &outStream, const Ptr if (hasLinearEquality_ || hasLinearInequality_) checkLinearity(printToStream,outStream); checkDerivatives(printToStream,outStream,x0,scale); +// if (hasProximableObjective) +// checkProximableObjective(printToStream, outStream); } template diff --git a/packages/rol/src/algorithm/ROL_Solver.hpp b/packages/rol/src/algorithm/ROL_Solver.hpp index 4ae8c176861d..f4a79e12b409 100644 --- a/packages/rol/src/algorithm/ROL_Solver.hpp +++ b/packages/rol/src/algorithm/ROL_Solver.hpp @@ -14,6 +14,7 @@ #include "ROL_TypeB_AlgorithmFactory.hpp" #include "ROL_TypeE_AlgorithmFactory.hpp" #include "ROL_TypeG_AlgorithmFactory.hpp" +#include "ROL_TypeP_AlgorithmFactory.hpp" #include "ROL_Problem.hpp" #include "ROL_ParameterList.hpp" @@ -37,6 +38,7 @@ class Solver { Ptr> algoB_; Ptr> algoE_; Ptr> algoG_; + Ptr> algoP_; public: diff --git a/packages/rol/src/algorithm/ROL_Solver_Def.hpp b/packages/rol/src/algorithm/ROL_Solver_Def.hpp index 0b7c6ad5744a..40ae8f4fdb55 100644 --- a/packages/rol/src/algorithm/ROL_Solver_Def.hpp +++ b/packages/rol/src/algorithm/ROL_Solver_Def.hpp @@ -19,6 +19,7 @@ Solver::Solver( const Ptr> &opt, : opt_(opt), problemType_(opt_->getProblemType()) { switch (problemType_) { case TYPE_U: algoU_ = TypeU::AlgorithmFactory(parlist,secant); break; + case TYPE_P: algoP_ = TypeP::AlgorithmFactory(parlist,secant); break; case TYPE_B: algoB_ = TypeB::AlgorithmFactory(parlist,secant); break; case TYPE_E: algoE_ = TypeE::AlgorithmFactory(parlist,secant); break; case TYPE_EB: algoG_ = TypeG::AlgorithmFactory(parlist,secant); break; @@ -44,6 +45,10 @@ int Solver::solve( std::ostream &outStream, if (status != nullPtr) algoU_->setStatusTest(status,combineStatus); algoU_->run(*opt_,outStream); break; + case TYPE_P: + if (status != nullPtr) algoP_->setStatusTest(status,combineStatus); + algoP_->run(*opt_,outStream); + break; case TYPE_B: if (status != nullPtr) algoB_->setStatusTest(status,combineStatus); algoB_->run(*opt_,outStream); @@ -72,6 +77,7 @@ Ptr> Solver::getAlgorithmState() const { //Ptr>& Solver::getAlgorithmState() const { switch (problemType_) { case TYPE_U: return algoU_->getState(); + case TYPE_P: return algoP_->getState(); case TYPE_B: return algoB_->getState(); case TYPE_E: return algoE_->getState(); case TYPE_EB: return algoG_->getState(); @@ -86,6 +92,7 @@ template void Solver::reset() { switch (problemType_) { case TYPE_U: algoU_->reset(); break; + case TYPE_P: algoP_->reset(); break; case TYPE_B: algoB_->reset(); break; case TYPE_E: algoE_->reset(); break; case TYPE_EB: algoG_->reset(); break; diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_AlgorithmFactory.hpp index a015e79bf276..e16e2ded0888 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_AlgorithmFactory.hpp @@ -110,17 +110,16 @@ inline EAlgorithmB StringToEAlgorithmB(std::string s) { template inline Ptr> AlgorithmFactory(ParameterList &parlist, const Ptr> &secant = nullPtr) { - EAlgorithmB ealg = StringToEAlgorithmB(parlist.sublist("Step").get("Type","Trust Region")); + std::string stepType = parlist.sublist("Step").get("Type","Trust Region"); + EAlgorithmB ealg = StringToEAlgorithmB(stepType); switch(ealg) { case ALGORITHM_B_LINESEARCH: { - std::string desc - = parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").get("Type","Newton-Krylov"); + std::string desc = parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").get("Type","Newton-Krylov"); if (desc=="Newton-Krylov" || desc=="Newton") return makePtr>(parlist,secant); else if (desc=="Quasi-Newton Method" || desc=="Quasi-Newton") { - std::string method - = parlist.sublist("Step").sublist("Line Search").sublist("Quasi-Newton").get("Method","L-Secant-B"); + std::string method = parlist.sublist("Step").sublist("Line Search").sublist("Quasi-Newton").get("Method","L-Secant-B"); if (method == "L-Secant-B") return makePtr>(parlist,secant); // Similar to L-BFGS-B else @@ -132,8 +131,7 @@ inline Ptr> AlgorithmFactory(ParameterList &parlist, const Ptr>(parlist,secant); else if (trmod=="SPG") diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_ColemanLiAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_ColemanLiAlgorithm_Def.hpp index 85de385e5067..aeb09315ca46 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_ColemanLiAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_ColemanLiAlgorithm_Def.hpp @@ -59,7 +59,8 @@ ColemanLiAlgorithm::ColemanLiAlgorithm(ParameterList &list, // Initialize trust region model model_ = makePtr>(list,secant,mode); if (secant == nullPtr) { - esec_ = StringToESecant(list.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS")); + std::string secantType = list.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS"); + esec_ = StringToESecant(secantType); } } diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_KelleySachsAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_KelleySachsAlgorithm_Def.hpp index e26c4fe411e4..127fade65f9b 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_KelleySachsAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_KelleySachsAlgorithm_Def.hpp @@ -54,7 +54,8 @@ KelleySachsAlgorithm::KelleySachsAlgorithm(ParameterList &list, useSecantPrecond_ = list.sublist("General").sublist("Secant").get("Use as Preconditioner", false); useSecantHessVec_ = list.sublist("General").sublist("Secant").get("Use as Hessian", false); if (secant == nullPtr) { - esec_ = StringToESecant(list.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS")); + std::string secantType = list.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS"); + esec_ = StringToESecant(secantType); } } diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp index ae18673c7c43..1a6d23f929dd 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LSecantBAlgorithm_Def.hpp @@ -47,7 +47,8 @@ LSecantBAlgorithm::LSecantBAlgorithm(ParameterList &list, useSecantHessVec_ = true; ESecantMode mode = SECANTMODE_BOTH; if (secant == nullPtr) { - esec_ = StringToESecant(list.sublist("General").sublist("Secant").get("Type","Limited-Memory Secant")); + std::string secantType = list.sublist("General").sublist("Secant").get("Type","Limited-Memory Secant"); + esec_ = StringToESecant(secantType); secant_ = SecantFactory(list,mode); } } @@ -135,8 +136,11 @@ void LSecantBAlgorithm::run(Vector &x, bnd.pruneActive(*pwa1,x,zero); gfree->set(pwa1->dual()); if (hasEcon_) { - applyFreePrecond(*pwa1,*gfree,x,*secant_,bnd,tol0,*dwa1,*pwa2); - gfnorm = pwa1->norm(); + gfnorm = gfree->norm(); + if (gfnorm > zero) { + applyFreePrecond(*pwa1,*gfree,x,*secant_,bnd,tol0,*dwa1,*pwa2); + gfnorm = pwa1->norm(); + } } else { gfnorm = gfree->norm(); diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp index ddf0ca74709f..d3c4a3cf622a 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_LinMoreAlgorithm_Def.hpp @@ -84,7 +84,8 @@ LinMoreAlgorithm::LinMoreAlgorithm(ParameterList &list, // Initialize trust region model model_ = makePtr>(list,secant,mode); if (secant == nullPtr) { - esec_ = StringToESecant(list.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS")); + std::string secantType = list.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS"); + esec_ = StringToESecant(secantType); } } diff --git a/packages/rol/src/algorithm/TypeB/ROL_TypeB_TrustRegionSPGAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeB/ROL_TypeB_TrustRegionSPGAlgorithm_Def.hpp index 09fb9e1c3323..a8119adb1c6e 100644 --- a/packages/rol/src/algorithm/TypeB/ROL_TypeB_TrustRegionSPGAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeB/ROL_TypeB_TrustRegionSPGAlgorithm_Def.hpp @@ -61,7 +61,9 @@ TrustRegionSPGAlgorithm::TrustRegionSPGAlgorithm(ParameterList &list, tol2_ = lmlist.sublist("Solver").get("Relative Tolerance", 1e-2); useMin_ = lmlist.sublist("Solver").get("Use Smallest Model Iterate", true); useNMSP_ = lmlist.sublist("Solver").get("Use Nonmonotone Search", false); - useSimpleSPG_ = !lmlist.sublist("Solver").get("Compute Cauchy Point", true); + + bool useCachyPoint = lmlist.sublist("Solver").get("Compute Cauchy Point", true); + useSimpleSPG_ = !useCachyPoint; // Inexactness Information ParameterList &glist = list.sublist("General"); useInexact_.clear(); @@ -91,7 +93,8 @@ TrustRegionSPGAlgorithm::TrustRegionSPGAlgorithm(ParameterList &list, // Initialize trust region model model_ = makePtr>(list,secant,mode); if (secant == nullPtr) { - esec_ = StringToESecant(list.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS")); + std::string secantType = list.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS"); + esec_ = StringToESecant(secantType); } } diff --git a/packages/rol/src/algorithm/TypeE/ROL_TypeE_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeE/ROL_TypeE_AlgorithmFactory.hpp index bc0ac4d836c3..c21fc75018fd 100644 --- a/packages/rol/src/algorithm/TypeE/ROL_TypeE_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeE/ROL_TypeE_AlgorithmFactory.hpp @@ -89,7 +89,8 @@ inline EAlgorithmE StringToEAlgorithmE(std::string s) { template inline Ptr> AlgorithmFactory(ParameterList &parlist, const Ptr> &secant = nullPtr) { - EAlgorithmE ealg = StringToEAlgorithmE(parlist.sublist("Step").get("Type","Augmented Lagrangian")); + std::string stepType = parlist.sublist("Step").get("Type","Augmented Lagrangian"); + EAlgorithmE ealg = StringToEAlgorithmE(stepType); switch(ealg) { case ALGORITHM_E_AUGMENTEDLAGRANGIAN: return makePtr>(parlist,secant); case ALGORITHM_E_FLETCHER: return makePtr>(parlist,secant); diff --git a/packages/rol/src/algorithm/TypeG/ROL_TypeG_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeG/ROL_TypeG_AlgorithmFactory.hpp index f89100df98c0..b6700b805bbf 100644 --- a/packages/rol/src/algorithm/TypeG/ROL_TypeG_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeG/ROL_TypeG_AlgorithmFactory.hpp @@ -94,7 +94,8 @@ inline EAlgorithmG StringToEAlgorithmG(std::string s) { template inline Ptr> AlgorithmFactory(ParameterList &parlist, const Ptr> &secant = nullPtr) { - EAlgorithmG ealg = StringToEAlgorithmG(parlist.sublist("Step").get("Type","Augmented Lagrangian")); + std::string stepType = parlist.sublist("Step").get("Type","Augmented Lagrangian"); + EAlgorithmG ealg = StringToEAlgorithmG(stepType); switch(ealg) { case ALGORITHM_G_AUGMENTEDLAGRANGIAN: return makePtr>(parlist,secant); case ALGORITHM_G_MOREAUYOSIDA: return makePtr>(parlist,secant); diff --git a/packages/rol/src/algorithm/TypeG/augmentedlagrangian/ROL_AugmentedLagrangianObjective.hpp b/packages/rol/src/algorithm/TypeG/augmentedlagrangian/ROL_AugmentedLagrangianObjective.hpp index 20a49a8721d3..9fff8bf026b6 100644 --- a/packages/rol/src/algorithm/TypeG/augmentedlagrangian/ROL_AugmentedLagrangianObjective.hpp +++ b/packages/rol/src/algorithm/TypeG/augmentedlagrangian/ROL_AugmentedLagrangianObjective.hpp @@ -149,13 +149,12 @@ class AugmentedLagrangianObjective : public Objective { val *= fscale_; // Compute penalty term const Real half(0.5); - primConVector_->set(multiplier_->dual()); - primConVector_->axpy(half*cscale_*penaltyParameter_,*getConstraintVec(x,tol)); - val += cscale_*getConstraintVec(x,tol)->dot(*primConVector_); + dualConVector_->set(*multiplier_); + dualConVector_->axpy(half*cscale_*penaltyParameter_,getConstraintVec(x,tol)->dual()); + val += cscale_*dualConVector_->apply(*getConstraintVec(x,tol)); + //val += cscale_*getConstraintVec(x,tol)->dot(*primConVector_); // Scale augmented Lagrangian - if (scaleLagrangian_) { - val /= penaltyParameter_; - } + if (scaleLagrangian_) val /= penaltyParameter_; return val; } @@ -169,10 +168,7 @@ class AugmentedLagrangianObjective : public Objective { con_->applyAdjointJacobian(*dualOptVector_,*dualConVector_,x,tol); g.axpy(cscale_,*dualOptVector_); // Compute gradient of Augmented Lagrangian - if ( scaleLagrangian_ ) { - const Real one(1); - g.scale(one/penaltyParameter_); - } + if ( scaleLagrangian_ ) g.scale(static_cast(1)/penaltyParameter_); } void hessVec( Vector &hv, const Vector &v, const Vector &x, Real &tol ) { @@ -200,9 +196,7 @@ class AugmentedLagrangianObjective : public Objective { hv.zero(); } // Build hessVec of Augmented Lagrangian - if ( scaleLagrangian_ ) { - hv.scale(static_cast(1)/penaltyParameter_); - } + if ( scaleLagrangian_ ) hv.scale(static_cast(1)/penaltyParameter_); } // Return objective function value diff --git a/packages/rol/src/algorithm/TypeG/moreauyosida/ROL_MoreauYosidaObjective.hpp b/packages/rol/src/algorithm/TypeG/moreauyosida/ROL_MoreauYosidaObjective.hpp index 1531a8bcab0f..c915bfd68568 100644 --- a/packages/rol/src/algorithm/TypeG/moreauyosida/ROL_MoreauYosidaObjective.hpp +++ b/packages/rol/src/algorithm/TypeG/moreauyosida/ROL_MoreauYosidaObjective.hpp @@ -175,21 +175,35 @@ class MoreauYosidaObjective : public Objective { lam_->set(lam); } + void updateMultiplier(const Vector &x) { + computePenalty(x); + lam_->set(*u1_); + lam_->axpy(static_cast(-1),*l1_); + lam_->scale(mu_); + isPenEvaluated_ = false; + } + void updatePenalty(Real mu) { + mu_ = mu; + isPenEvaluated_ = false; + } + void updateMultipliers(Real mu, const Vector &x) { if ( bnd_->isActivated() ) { if ( updateMultiplier_ ) { - const Real one(1); - computePenalty(x); - lam_->set(*u1_); - lam_->axpy(-one,*l1_); - lam_->scale(mu_); + updateMultiplier(x); + //const Real one(1); + //computePenalty(x); + //lam_->set(*u1_); + //lam_->axpy(-one,*l1_); + //lam_->scale(mu_); } if ( updatePenalty_ ) { - mu_ = mu; + updatePenalty(mu); + //mu_ = mu; } } nfval_ = 0; ngrad_ = 0; - isPenEvaluated_ = false; + //isPenEvaluated_ = false; } void reset(const Real mu) { diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp index f76db678e49c..544b466af41e 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_AlgorithmFactory.hpp @@ -95,8 +95,9 @@ inline EAlgorithmP StringToEAlgorithmP(std::string s) { } template -inline Ptr> AlgorithmFactory(ParameterList &parlist) { - EAlgorithmP ealg = StringToEAlgorithmP(parlist.sublist("Step").get("Type","Trust Region")); +inline Ptr> AlgorithmFactory(ParameterList &parlist, const Ptr> &secant = nullPtr) { + std::string stepType = parlist.sublist("Step").get("Type","Trust Region"); + EAlgorithmP ealg = StringToEAlgorithmP(stepType); switch(ealg) { case ALGORITHM_P_LINESEARCH: { @@ -104,12 +105,12 @@ inline Ptr> AlgorithmFactory(ParameterList &parlist) { = parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").get("Type","Newton-Krylov"); if (desc=="Newton-Krylov" || desc=="Newton") return makePtr>(parlist); - else if (desc=="Quasi-Newton Method" || desc = "Quasi-Newton") - return makePtr>(parlist); + else if (desc=="Quasi-Newton Method" || desc == "Quasi-Newton") + return makePtr>(parlist, secant); else return makePtr>(parlist); } - case ALGORITHM_P_TRUSTREGION: return makePtr>(parlist); + case ALGORITHM_P_TRUSTREGION: return makePtr>(parlist, secant); case ALGORITHM_P_SPECTRALGRADIENT: return makePtr>(parlist); case ALGORITHM_P_IPIANO: return makePtr>(parlist); default: return nullPtr; diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp index 25e203f2a8ee..11b808b0f9dd 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_Algorithm_Def.hpp @@ -69,17 +69,17 @@ void Algorithm::setStatusTest(const Ptr> &status, template void Algorithm::run( Problem &problem, std::ostream &outStream ) { - /*if (problem.getProblemType() == TYPE_P) { + if (problem.getProblemType() == TYPE_P) { run(*problem.getPrimalOptimizationVector(), *problem.getDualOptimizationVector(), *problem.getObjective(), + *problem.getProximableObjective(), outStream); problem.finalizeIteration(); } else { throw Exception::NotImplemented(">>> ROL::TypeP::Algorithm::run : Optimization problem is not Type P!"); - }*/ - throw Exception::NotImplemented(">>> ROL::TypeP::Algorithm::run : Optimization problem is not available for Type P problems!"); + } } template diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm.hpp index d722ba5d07fd..12cbb9148c43 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm.hpp @@ -22,7 +22,7 @@ namespace TypeP { template class InexactNewtonAlgorithm : public TypeP::Algorithm { private: - int t0_; + Real t0_; bool initProx_; int maxit_; ///< Maximum number of line search steps (default: 20) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm_Def.hpp index ad1b77ea66ab..022f5df54bb3 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_InexactNewtonAlgorithm_Def.hpp @@ -7,8 +7,8 @@ // ***************************************************************************** // @HEADER -#ifndef ROL_TYPEP_QUASINEWTONALGORITHM_DEF_HPP -#define ROL_TYPEP_QUASINEWTONALGORITHM_DEF_HPP +#ifndef ROL_TYPEP_INEXACTNEWTONALGORITHM_DEF_HPP +#define ROL_TYPEP_INEXACTNEWTONALGORITHM_DEF_HPP #include "ROL_TypeP_ProxGradientAlgorithm.hpp" #include "ROL_TypeP_SpectralGradientAlgorithm.hpp" diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm.hpp index 8490492569be..ef8330439990 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_QuasiNewtonAlgorithm.hpp @@ -27,7 +27,7 @@ class QuasiNewtonAlgorithm : public TypeP::Algorithm { ESecant esec_; ///< Secant type std::string secantName_; ///< Secant name - int t0_; + Real t0_; bool initProx_; int maxit_; ///< Maximum number of line search steps (default: 20) diff --git a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp index b9f8da8a7151..16a6b9e6472d 100644 --- a/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeP/ROL_TypeP_TrustRegionAlgorithm_Def.hpp @@ -100,7 +100,8 @@ TrustRegionAlgorithm::TrustRegionAlgorithm(ParameterList &list, // Initialize trust region model model_ = makePtr>(list,secant,mode); if (secant == nullPtr) { - esec_ = StringToESecant(list.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS")); + std::string secantType = list.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS"); + esec_ = StringToESecant(secantType); } } diff --git a/packages/rol/src/algorithm/TypeU/ROL_TypeU_AlgorithmFactory.hpp b/packages/rol/src/algorithm/TypeU/ROL_TypeU_AlgorithmFactory.hpp index 97f84a41ddf0..84aad1f9680e 100644 --- a/packages/rol/src/algorithm/TypeU/ROL_TypeU_AlgorithmFactory.hpp +++ b/packages/rol/src/algorithm/TypeU/ROL_TypeU_AlgorithmFactory.hpp @@ -89,7 +89,8 @@ inline EAlgorithmU StringToEAlgorithmU(std::string s) { template inline Ptr> AlgorithmFactory(ParameterList &parlist, const Ptr> &secant = nullPtr) { - EAlgorithmU ealg = StringToEAlgorithmU(parlist.sublist("Step").get("Type","Trust Region")); + std::string stepType = parlist.sublist("Step").get("Type","Trust Region"); + EAlgorithmU ealg = StringToEAlgorithmU(stepType); switch(ealg) { case ALGORITHM_U_BUNDLE: return makePtr>(parlist); case ALGORITHM_U_LINESEARCH: return makePtr>(parlist,secant); diff --git a/packages/rol/src/algorithm/TypeU/ROL_TypeU_BundleAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeU/ROL_TypeU_BundleAlgorithm_Def.hpp index de069b56be24..f66c5c109d66 100644 --- a/packages/rol/src/algorithm/TypeU/ROL_TypeU_BundleAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeU/ROL_TypeU_BundleAlgorithm_Def.hpp @@ -48,7 +48,8 @@ BundleAlgorithm::BundleAlgorithm( ParameterList &parlist, Real omega = blist.get("Locality Measure Coefficient", two); unsigned maxSize = blist.get("Maximum Bundle Size", 200); unsigned remSize = blist.get("Removal Size for Bundle Update", 2); - if ( blist.get("Cutting Plane Solver",0) == 1 ) { + int cps = blist.get("Cutting Plane Solver",0); + if ( cps == 1 ) { bundle_ = makePtr>(maxSize,coeff,omega,remSize); } else { diff --git a/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm_Def.hpp index 1b6704728b4f..70e48260707a 100644 --- a/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeU/ROL_TypeU_LineSearchAlgorithm_Def.hpp @@ -31,7 +31,8 @@ LineSearchAlgorithm::LineSearchAlgorithm( ParameterList &parlist, // Parse parameter list ParameterList& Llist = parlist.sublist("Step").sublist("Line Search"); ParameterList& Glist = parlist.sublist("General"); - econd_ = StringToECurvatureConditionU(Llist.sublist("Curvature Condition").get("Type","Strong Wolfe Conditions") ); + std::string condType = Llist.sublist("Curvature Condition").get("Type","Strong Wolfe Conditions"); + econd_ = StringToECurvatureConditionU(condType); acceptLastAlpha_ = Llist.get("Accept Last Alpha", false); verbosity_ = Glist.get("Output Level",0); printHeader_ = verbosity_ > 2; diff --git a/packages/rol/src/algorithm/TypeU/ROL_TypeU_TrustRegionAlgorithm_Def.hpp b/packages/rol/src/algorithm/TypeU/ROL_TypeU_TrustRegionAlgorithm_Def.hpp index 40f378bfd030..d7ec29d9d642 100644 --- a/packages/rol/src/algorithm/TypeU/ROL_TypeU_TrustRegionAlgorithm_Def.hpp +++ b/packages/rol/src/algorithm/TypeU/ROL_TypeU_TrustRegionAlgorithm_Def.hpp @@ -57,14 +57,16 @@ TrustRegionAlgorithm::TrustRegionAlgorithm( ParameterList &parlist, updateIter_ = vlist.get("Forcing Sequence Update Frequency", static_cast(10)); forceFactor_ = vlist.get("Forcing Sequence Reduction Factor", static_cast(0.1)); // Initialize Trust Region Subproblem Solver Object - etr_ = StringToETrustRegionU(trlist.get("Subproblem Solver", "Dogleg")); + std::string solverName = trlist.get("Subproblem Solver", "Dogleg"); + etr_ = StringToETrustRegionU(solverName); solver_ = TrustRegionUFactory(parlist); verbosity_ = glist.get("Output Level", 0); // Secant Information useSecantPrecond_ = glist.sublist("Secant").get("Use as Preconditioner", false); useSecantHessVec_ = glist.sublist("Secant").get("Use as Hessian", false); if (secant == nullPtr) { - esec_ = StringToESecant(glist.sublist("Secant").get("Type","Limited-Memory BFGS")); + std::string secantType = glist.sublist("Secant").get("Type","Limited-Memory BFGS"); + esec_ = StringToESecant(secantType); } // Initialize trust region model model_ = makePtr>(parlist,secant); diff --git a/packages/rol/src/algorithm/TypeU/bundle/ROL_Bundle_U_TT_Def.hpp b/packages/rol/src/algorithm/TypeU/bundle/ROL_Bundle_U_TT_Def.hpp index b94c4e4cc120..2de18d970475 100644 --- a/packages/rol/src/algorithm/TypeU/bundle/ROL_Bundle_U_TT_Def.hpp +++ b/packages/rol/src/algorithm/TypeU/bundle/ROL_Bundle_U_TT_Def.hpp @@ -11,10 +11,10 @@ #define ROL_BUNDLE_U_TT_DEF_H #include "ROL_Types.hpp" -#include -#include -#include -#include +#include +#include +#include +#include #include // TT: std::find #define EXACT 1 @@ -27,7 +27,7 @@ template Bundle_U_TT::Bundle_U_TT(const unsigned maxSize, const Real coeff, const Real omega, - const unsigned remSize) + const unsigned remSize) : Bundle_U(maxSize,coeff,omega,remSize), maxSize_(maxSize), isInitialized_(false) { maxind_ = std::numeric_limits::max(); @@ -43,7 +43,7 @@ Real Bundle_U_TT::sgn(const Real x) const { return ((x < zero) ? -one : ((x > zero) ? one : zero)); } - + template unsigned Bundle_U_TT::solveDual(const Real t, const unsigned maxit, const Real tol) { unsigned iter = 0; @@ -119,16 +119,16 @@ void Bundle_U_TT::addSubgradToBase(unsigned ind, Real delta) { base_[currSize_-1] = tmp; ind--; } // end if dependent - + L_(ind,ind) = delta; - + // update z1 and z2 unsigned zsize = ind+1; z1_.resize(zsize); z2_.resize(zsize); z1_[ind] = ( static_cast(1) - lhz1_ ) / delta; - z2_[ind] = ( Bundle_U::alpha(base_[ind]) - lhz2_ ) / delta; - //z2[zsize-1] = ( Bundle_U::alpha(entering_) - lhz2_ ) / delta; - + z2_[ind] = ( Bundle_U::alpha(base_[ind]) - lhz2_ ) / delta; + //z2[zsize-1] = ( Bundle_U::alpha(entering_) - lhz2_ ) / delta; + // update kappa if(delta > L_(LiMax_,LiMax_)){ LiMax_ = ind; @@ -145,11 +145,11 @@ void Bundle_U_TT::deleteSubgradFromBase(unsigned ind, Real tol){ const Real zero(0), one(1); // update L, currSize, base_, z1, z2, dependent, dualVariables_, kappa if (ind >= currSize_-dependent_){ - // if dependent > 0, the last one or two rows of L are lin. dependent + // if dependent > 0, the last one or two rows of L are lin. dependent if (ind < currSize_-1){ // eliminate currSize_-2 but keep currSize_-1 // swap the last row with the second to last swapRowsL(ind,currSize_-1); - base_[ind] = base_[currSize_-1]; + base_[ind] = base_[currSize_-1]; #if( ! EXACT ) lhNorm = ljNorm; // new last row is lh #endif @@ -165,22 +165,22 @@ void Bundle_U_TT::deleteSubgradFromBase(unsigned ind, Real tol){ } // end if dependent item /* currently L_B is lower trapezoidal - + | L_1 0 0 | L_B = | l d 0 | - | Z v L_2 | - + | Z v L_2 | + Apply Givens rotations to transform it to - + | L_1 0 0 | | l d 0 | | Z 0 L_2' | - + then delete row and column to obtain factorization of L_B' with B' = B/{i} - + L_B' = | L_1 0 | | Z L_2' | - + */ for (unsigned j=ind+1; j::deleteSubgradFromBase(unsigned ind, Real tol){ // d = hypot(ai,aj); // Gc = aj/d; // Gs = -ai/d; - - L_(j,j) = d; L_(j,ind) = zero; + + L_(j,j) = d; L_(j,ind) = zero; // apply Givens to columns i,j of L for (unsigned h=j+1; h::deleteSubgradFromBase(unsigned ind, Real tol){ if( dependent_ > 1 ) // j = currSize_ - 1, h = currSize_ - 2 deltaLj_ = L_(currSize_-1,ind); } - + // shift rows and columns of L by exchanging i-th row with next row and i-th column with next column until the row to be deleted is the last, then deleting last row and column swapRowsL(ind,currSize_-1); swapRowsL(ind,currSize_-1,true); @@ -264,7 +264,7 @@ void Bundle_U_TT::deleteSubgradFromBase(unsigned ind, Real tol){ // update kappa updateK(); - + if(dependent_){ // if some previously dependent item have become independent // recompute deltaLh @@ -281,8 +281,8 @@ void Bundle_U_TT::deleteSubgradFromBase(unsigned ind, Real tol){ Real signum = sgn1 * sgn2; // sgn( deltaLh ) * sgn ( deltaLj ); deltaLh_ = std::abs( ghNorm - lhNorm + deltaLh_ * deltaLh_); #endif - - if( std::sqrt(deltaLh_) > tol*kappa_*std::max(static_cast(1),ghNorm) ){ // originally had deltaLh without sqrt + + if( std::sqrt(deltaLh_) > tol*kappa_*std::max(static_cast(1),ghNorm) ){ // originally had deltaLh without sqrt unsigned newind = currSize_-dependent_; dependent_--; // get the last row of L @@ -295,7 +295,7 @@ void Bundle_U_TT::deleteSubgradFromBase(unsigned ind, Real tol){ lhz2_ += lh_[ii]*z2_[ii]; } deltaLh_ = std::sqrt(deltaLh_); - addSubgradToBase(newind,deltaLh_); + addSubgradToBase(newind,deltaLh_); if(dependent_){ // dependent was 2 #if( ! EXACT ) @@ -332,13 +332,13 @@ void Bundle_U_TT::deleteSubgradFromBase(unsigned ind, Real tol){ #else deltaLj_ = std::abs( gjNorm - ljNorm + deltaLj_ * deltaLj_); #endif - + if( std::sqrt(deltaLj_) > tol*kappa_*std::max(static_cast(1),gjNorm) ){ // originally had deltaLj without sqrt unsigned newind = currSize_-1; dependent_--; // get the last row of L lj_.size(newind-1); // initialize to zeros; - Real ljz1_ = zero; + ljz1_ = zero; Real ljTz2 = zero; for (unsigned ii=0;ii::deleteSubgradFromBase(unsigned ind, Real tol){ ljTz2 += lj_[ii]*z2_[ii]; } deltaLj_ = std::sqrt(deltaLj_); - addSubgradToBase(newind,deltaLj_); + addSubgradToBase(newind,deltaLj_); #if( EXACT ) deltaLh_ = GiGj(base_[currSize_-2],base_[currSize_-1]); for (unsigned ii=0;ii::deleteSubgradFromBase(unsigned ind, Real tol){ } // end if ( dependent > 1 ) } // end if(dependent) }// end deleteSubgradFromBase() - + template void Bundle_U_TT::solveSystem(int size, char tran, LA::Matrix &L, LA::Vector &v){ int info; @@ -401,8 +401,8 @@ unsigned Bundle_U_TT::solveDual_TT(const Real t, const unsigned maxit, con entering_ = maxind_; // cold start - optimal_ = true; - dependent_ = 0; + optimal_ = true; + dependent_ = 0; rho_ = ROL_INF(); // value of rho = -v currSize_ = 1; // current base size base_.clear(); @@ -424,7 +424,7 @@ unsigned Bundle_U_TT::solveDual_TT(const Real t, const unsigned maxit, con kappa_ = one; // condition number of matrix L ( >= max|L_ii|/min|L_ii| ) objval_ = ROL_INF(); // value of objective minobjval_ = ROL_INF(); // min value of objective (ever reached) - + unsigned iter; //-------------------------- MAIN LOOP --------------------------------// for (iter=0;iter::solveDual_TT(const Real t, const unsigned maxit, con L = L_B' */ z1z2 = z1_.dot(z2_); - z1z1 = z1_.dot(z1_); + z1z1 = z1_.dot(z1_); rho_ = ( one + z1z2/t )/z1z1; tempv_ = z1_; tempv_.scale(rho_); tempw1_ = z2_; tempw1_.scale(one/t); @@ -446,26 +446,26 @@ unsigned Bundle_U_TT::solveDual_TT(const Real t, const unsigned maxit, con optimal_ = true; break; } - case(1): + case(1): { /* L = | L_B' 0 | \ currSize | l_h^T 0 | / */ - LA::Matrix LBprime( LA::Copy,L_,currSize_-1,currSize_-1); + LA::Matrix LBprime( LA::Copy,L_,currSize_-1,currSize_-1); lh_.size(currSize_-1); // initialize to zeros; lhz1_ = zero; lhz2_ = zero; for(unsigned i=0; i::solveDual_TT(const Real t, const unsigned maxit, con // system has (unique) solution rho_ = ( (Bundle_U::alpha(base_[currSize_-1]) - lhz2_)/t ) / ( one - lhz1_ ); z1z2 = z1_.dot(z2_); - z1z1 = z1_.dot(z1_); + z1z1 = z1_.dot(z1_); Real tmp = ( one + z1z2 / t - rho_ * z1z1 )/( one - lhz1_ ); tempw1_ = z1_; tempw1_.scale(rho_); tempw2_ = z2_; tempw2_.scale(one/t); @@ -505,13 +505,13 @@ unsigned Bundle_U_TT::solveDual_TT(const Real t, const unsigned maxit, con Real tmp1 = L_(currSize_-1,i); Real tmp2 = L_(currSize_-2,i); ljz1_ += tmp1*z1_(i); - lhz1_ += tmp2*z1_(i); + lhz1_ += tmp2*z1_(i); lj_[i] = tmp1; lh_[i] = tmp2; } - if(std::abs(ljz1_-one) <= tol*kappa_){ + if(std::abs(ljz1_-one) <= tol*kappa_){ // tempv is an infinite direction - tempv_ = lj_; + tempv_ = lj_; solveSystem(currSize_-2,'T',LBprime,tempv_); tempv_.resize(currSize_); // add two last entries tempv_[currSize_-2] = zero; @@ -539,7 +539,7 @@ unsigned Bundle_U_TT::solveDual_TT(const Real t, const unsigned maxit, con // set dual variables to values in tempv Bundle_U::resetDualVariables(); for (unsigned i=0; i::setDualVariable(base_[i],tempv_[i]); + Bundle_U::setDualVariable(base_[i],tempv_[i]); } } else{ @@ -579,19 +579,19 @@ unsigned Bundle_U_TT::solveDual_TT(const Real t, const unsigned maxit, con QPStatus_ = -1; // invalid step return iter; } - + for (unsigned i=0; i::setDualVariable(base_[i],Bundle_U::getDualVariable(base_[i]) + step * tempv_[i]); + Bundle_U::setDualVariable(base_[i],Bundle_U::getDualVariable(base_[i]) + step * tempv_[i]); }// if(!optimal) - + //------------------------- ITEMS ELIMINATION ---------------------------// - + // Eliminate items with 0 multipliers from base bool deleted = optimal_; for (unsigned baseitem=0; baseitem::getDualVariable(base_[baseitem]) <= tol){ deleted = true; - + #if( TABOO_LIST ) // item that just entered shouldn't exit; if it does, mark it as taboo if( base_[baseitem] == entering_ ){ @@ -600,18 +600,18 @@ unsigned Bundle_U_TT::solveDual_TT(const Real t, const unsigned maxit, con } #endif - // eliminate item from base; + // eliminate item from base; deleteSubgradFromBase(baseitem,tol); } // end if(dualVariables_[baseitem] < tol) - } // end loop over baseitem - + } // end loop over baseitem + if(!deleted){ // nothing deleted and not optimal QPStatus_ = -2; // loop return iter; } } // end inner loop - + Real newobjval(0), Lin(0), Quad(0); // new objective value for (unsigned i=0; i::alpha(base_[i])*Bundle_U::getDualVariable(base_[i]); @@ -626,12 +626,12 @@ unsigned Bundle_U_TT::solveDual_TT(const Real t, const unsigned maxit, con } #if( TABOO_LIST ) - // -- test for strict decrease -- // + // -- test for strict decrease -- // // if item didn't provide decrease, move it to taboo list ... if( ( entering_ < maxind_ ) && ( objval_ < ROL_INF() ) ){ if( newobjval >= objval_ - std::max( tol*std::abs(objval_), ROL_EPSILON() ) ){ taboo_.push_back(entering_); - } + } } #endif @@ -646,7 +646,7 @@ unsigned Bundle_U_TT::solveDual_TT(const Real t, const unsigned maxit, con //---------------------- OPTIMALITY TEST -------------------------// if ( (rho_ >= ROL_NINF()) && (objval_ <= ROL_NINF()) ) // if current x (dualVariables_) is feasible break; - + entering_ = maxind_; Real minro = - std::max( tol*currSize_*std::abs(objval_), ROL_EPSILON() ); #if ( ! FIRST_VIOLATED ) @@ -669,15 +669,15 @@ unsigned Bundle_U_TT::solveDual_TT(const Real t, const unsigned maxit, con if (rho_ >= ROL_NINF()){ - ro = ro - rho_; // note: rho = -v + ro = ro - rho_; // note: rho = -v } else{ ro = ROL_NINF(); minobjval_ = ROL_INF(); objval_ = ROL_INF(); } - - if (ro < minro){ + + if (ro < minro){ #if ( FIRST_VIOLATED ) entering_ = bundleitem; break; // skip going through rest of constraints; alternatively, could look for "most violated" @@ -689,11 +689,11 @@ unsigned Bundle_U_TT::solveDual_TT(const Real t, const unsigned maxit, con } #endif } - + } // end if item not in base }// end of loop over items in bundle - //----------------- INSERTING ITEM ------------------------// + //----------------- INSERTING ITEM ------------------------// if (entering_ < maxind_){ // dual constraint is violated optimal_ = false; Bundle_U::setDualVariable(entering_,zero); @@ -706,7 +706,7 @@ unsigned Bundle_U_TT::solveDual_TT(const Real t, const unsigned maxit, con for (unsigned i=0; i LBprime( LA::Copy,L_,zsize,zsize); + LA::Matrix LBprime( LA::Copy,L_,zsize,zsize); solveSystem(zsize,'N',LBprime,lh_); // lh = (L_B^{-1})*(G_B^T*g_h) for (unsigned i=0; i::solveDual_TT(const Real t, const unsigned maxit, con #endif currSize_++; // update base size - + L_.reshape(currSize_,currSize_); zsize = currSize_ - dependent_; // zsize is the size of L_Bprime (new one) for (unsigned i=0; i deltaeps ){ // new row is independent // add subgradient to the base unsigned ind = currSize_-1; @@ -754,7 +754,7 @@ unsigned Bundle_U_TT::solveDual_TT(const Real t, const unsigned maxit, con } if(optimal_) - break; + break; } // end main loop taboo_.clear(); diff --git a/packages/rol/src/algorithm/TypeU/linesearch/ROL_LineSearch_U.hpp b/packages/rol/src/algorithm/TypeU/linesearch/ROL_LineSearch_U.hpp index c7bd38793795..86bd47907c24 100644 --- a/packages/rol/src/algorithm/TypeU/linesearch/ROL_LineSearch_U.hpp +++ b/packages/rol/src/algorithm/TypeU/linesearch/ROL_LineSearch_U.hpp @@ -81,8 +81,10 @@ class LineSearch_U { LineSearch_U( ParameterList &parlist ) { Real one(1), p9(0.9), p6(0.6), p4(0.4), oem4(1.e-4), zero(0); // Enumerations - edesc_ = StringToEDescentU(parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").get("Type","Quasi-Newton Method")); - econd_ = StringToECurvatureConditionU(parlist.sublist("Step").sublist("Line Search").sublist("Curvature Condition").get("Type","Strong Wolfe Conditions")); + std::string descentType = parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").get("Type","Quasi-Newton Method"); + edesc_ = StringToEDescentU(descentType); + std::string condType = parlist.sublist("Step").sublist("Line Search").sublist("Curvature Condition").get("Type","Strong Wolfe Conditions"); + econd_ = StringToECurvatureConditionU(condType); // Linesearch Parameters alpha0_ = parlist.sublist("Step").sublist("Line Search").get("Initial Step Size",one); alpha0bnd_ = parlist.sublist("Step").sublist("Line Search").get("Lower Bound for Initial Step Size",one); diff --git a/packages/rol/src/algorithm/TypeU/linesearch/ROL_ScalarMinimizationLineSearch_U.hpp b/packages/rol/src/algorithm/TypeU/linesearch/ROL_ScalarMinimizationLineSearch_U.hpp index dde16e4ef09e..a33f2b5781bf 100644 --- a/packages/rol/src/algorithm/TypeU/linesearch/ROL_ScalarMinimizationLineSearch_U.hpp +++ b/packages/rol/src/algorithm/TypeU/linesearch/ROL_ScalarMinimizationLineSearch_U.hpp @@ -200,7 +200,8 @@ class ScalarMinimizationLineSearch_U : public LineSearch_U { sf_ = sf; // Status test for line search - econd_ = StringToECurvatureConditionU(list0.sublist("Curvature Condition").get("Type","Strong Wolfe Conditions")); + std::string condName = list0.sublist("Curvature Condition").get("Type","Strong Wolfe Conditions"); + econd_ = StringToECurvatureConditionU(condName); max_nfval_ = list0.get("Function Evaluation Limit",20); c1_ = list0.get("Sufficient Decrease Tolerance",oem4); c2_ = list0.sublist("Curvature Condition").get("General Parameter",p9); @@ -213,7 +214,8 @@ class ScalarMinimizationLineSearch_U : public LineSearch_U { c1_ = oem4; c2_ = p9; } - EDescentU edesc = StringToEDescentU(list0.sublist("Descent Method").get("Type","Quasi-Newton Method")); + std::string descentName = list0.sublist("Descent Method").get("Type","Quasi-Newton Method"); + EDescentU edesc = StringToEDescentU(descentName); if ( edesc == DESCENT_U_NONLINEARCG ) { c2_ = p4; c3_ = std::min(one-c2_,c3_); diff --git a/packages/rol/src/compatibility/backward_cpp/backward.hpp b/packages/rol/src/compatibility/backward_cpp/backward.hpp index 7f2562a61f94..c497e06afa1a 100644 --- a/packages/rol/src/compatibility/backward_cpp/backward.hpp +++ b/packages/rol/src/compatibility/backward_cpp/backward.hpp @@ -1193,9 +1193,9 @@ class TraceResolverLinuxImpl: return r; // damned, that's a stripped file that you got there! } - r.handle = move(bfd_handle); - r.symtab = move(symtab); - r.dynamic_symtab = move(dynamic_symtab); + r.handle = std::move(bfd_handle); + r.symtab = std::move(symtab); + r.dynamic_symtab = std::move(dynamic_symtab); return r; } @@ -2054,8 +2054,8 @@ class TraceResolverLinuxImpl: // If we have a valid elf handle, return the new elf handle // and file handle and discard the original ones if (debuglink_elf) { - elf_handle = move(debuglink_elf); - file_handle = move(debuglink_file); + elf_handle = std::move(debuglink_elf); + file_handle = std::move(debuglink_file); } } } @@ -2077,9 +2077,9 @@ class TraceResolverLinuxImpl: dwarf_handle.reset(dwarf_debug); - r.file_handle = move(file_handle); - r.elf_handle = move(elf_handle); - r.dwarf_handle = move(dwarf_handle); + r.file_handle = std::move(file_handle); + r.elf_handle = std::move(elf_handle); + r.dwarf_handle = std::move(dwarf_handle); return r; } @@ -3189,7 +3189,6 @@ class SourceFile { bool is_open() const { return _file->is_open(); } lines_t& get_lines(unsigned line_start, unsigned line_count, lines_t& lines) { - using namespace std; // This function make uses of the dumbest algo ever: // 1) seek(0) // 2) read lines one by one and discard until line_start @@ -3201,7 +3200,7 @@ class SourceFile { _file->clear(); _file->seekg(0); - string line; + std::string line; unsigned line_idx; for (line_idx = 1; line_idx < line_start; ++line_idx) { @@ -3599,7 +3598,6 @@ class Printer { Colorize& colorize, Color::type color_code, int context_size) { - using namespace std; typedef SnippetFactory::lines_t lines_t; lines_t lines = _snippets.get_snippet(source_loc.filename, diff --git a/packages/rol/src/compatibility/boost/property_tree/ROL_ParameterList.hpp b/packages/rol/src/compatibility/boost/property_tree/ROL_ParameterList.hpp index d3091235e991..12a939ffd8ad 100644 --- a/packages/rol/src/compatibility/boost/property_tree/ROL_ParameterList.hpp +++ b/packages/rol/src/compatibility/boost/property_tree/ROL_ParameterList.hpp @@ -34,8 +34,6 @@ namespace ROL { namespace details { -using namespace std; - // Try to get type of an object // FIXME: sometimes failing for std::string template struct value_type diff --git a/packages/rol/src/elementwise/ROL_GenericFunction.hpp b/packages/rol/src/elementwise/ROL_GenericFunction.hpp new file mode 100644 index 000000000000..aec705d39353 --- /dev/null +++ b/packages/rol/src/elementwise/ROL_GenericFunction.hpp @@ -0,0 +1,302 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#pragma once + +#include +#include +#include +#include +#include + +namespace ROL { + +constexpr std::size_t MAX_ARITY = 16; + +// Function traits to deduce arity +template +struct function_traits : public function_traits {}; + +template +struct function_traits { + static constexpr std::size_t arity = sizeof...(Args); + using result_type = ReturnType; +}; + + + +/** + * @brief A template class representing a function that can be applied to Vectors. + * + * This class provides a mechanism for applying functions to Vectors efficiently, + * using the Visitor pattern to avoid virtual function calls for each element. + * + * @tparam Real The type used for real numbers in the function and calculations. + */ +template +class GenericFunction { +protected: + /** + * @brief Abstract base class for visitors. + * + * This class is part of the Visitor pattern implementation, allowing for + * double dispatch without virtual function calls for each vector element. + */ + struct Visitor { + virtual void visit( const GenericFunction& ) = 0; + }; + + explicit GenericFunction( std::size_t arity ) : arity_{arity} {} + +public: + + GenericFunction( const GenericFunction& ) = delete; + GenericFunction& = operator ( const GenericFunction& ) = delete; + GenericFunction( GenericFunction&& ) = default; + GenericFunction& = operator ( GenericFunction&& ) = default; + + /** @brief Virtual destructor for proper cleanup of derived classes. */ + virtual ~GenericFunction() noexcept = default; + + /** + * @brief Apply the function to a single value. + * + * @param x The input values. + * @return The result of applying the function to x. + */ + [[nodiscard]] virtual Real operator()( const std::vector& x ) const = 0; + + /** + * @brief Accept a visitor, part of the Visitor pattern implementation. + * + * @param visitor The visitor to accept. + */ + virtual void accept( Visitor&& visitor ) const = 0; + + /** + * @brief Apply the function to a vector. + * + * This method uses the Visitor pattern to efficiently apply the function + * to all elements of the vector without virtual function calls per element. + * + * @tparam VecT The type of the vector. + * @tparam EvalT The type of the evaluator function. + * @param vec The vector to apply the function to. + * @param eval The evaluator function that defines how to apply the function to the vector. + * + * Example Usage: + * @code + * template + * class Vector { + * public: + * virtual void applyFunction( const GenericFunction&, const std::vector& ) {} + * virtual int dimension() const { return 0; } + * }; + * + * template + * class StdVector : public Vector { + * public: + * void dimension() const override { return vec_.size(); } + * void applyGenericUnary( const GenericFunction& gf, const std::vector*>& vecs ) override { + * std::vector stdVecs; + * stdVecs.reserve(vecs.size()); + * for(auto vec : vecs) { + * stdVecs.push_back(static_cast(vec)); + * } + * gf.apply_vectorized(stdVecs,[this](const auto& vecs, const auto& f){ this->applyFunctionImpl(f,vecs); }); + * } + * + * template + * void applyFunctionImpl( const F& f, const std::vector& vecs ) { + * std::vector args(vecs.size()); + * for( int i=0; i vec_; + * }; + * @endcode + */ + template + void apply_vectorized( VecT& vec, EvalT&& eval ) const { + accept(VectorVisitor(vec,std::forward(eval))); + } + + /** + * @brief A wrapper class that turns any callable into a GenericFunction. + * + * This class allows easy creation of GenericFunction objects from lambdas or other callables. + * + * @tparam Func The type of the callable to wrap. + * @tparam Base The base class to inherit from, defaults to GenericFunction. + */ + template + class Lambda : public Base { + public: + + static constexpr std::size_t arity = function_traits::arity; ///< Number of arguments wrapped callable takes + + /** + * @brief Construct a new Wrapper object. + * + * @param f The callable to wrap. + */ + explicit Lambda( Func&& f ) + : Base(arity), f_{std::forward(f)} { + static_assert( arity > 0, "Callable must take at least one argument" ); + static_assert( arity <= MAX_ARITY, "Callable must not take more than MAX_ARITY arguments" ); + } + + /** + * @brief Apply the wrapped function. + * + * @param x The input value. + * @return The result of applying the wrapped function to x. + */ + Real operator()( const std::vector& x ) const override { + if( x.size() != this->arity ) { + std::stringstream msg; + msg << "Received vector of " << x.size() << " arguments, but the wrapped callable's arity is " << this->arity << "."; + throw std::invalid_argument(msg.str()); + } + return call_impl(x, std::make_index_sequence{}); + } + + private: + + /** + * @brief Expands the elements of a vector into the arguments of a function + * @param x The vector of arguments to pass to the callable + */ + template + Real call_impl( const std::vector& x, std::index_sequence ) const { + return f_(x[I]...); + } + + /** + * @brief Accept a visitor, part of the Visitor pattern implementation. + * + * @param visitor The visitor to accept. + */ + void accept( Visitor&& visitor ) const override { visitor.visit(*this); } + + Func f_; ///< The wrapped callable. + }; // class Wrapper + + /** + * @brief Class Template Argument Deduction (CTAD) guide for Wrapper. + * + * This allows the compiler to deduce the template arguments for Wrapper + * when constructing it from a callable. + */ + template + Lambda( Func&& ) -> Lambda>; + +private: + /** + * @brief A base class for visitors that implements the visit method. + * + * This class uses the Curiously Recurring Template Pattern (CRTP) to + * achieve static polymorphism, avoiding virtual function calls. + * + * @tparam Derived The derived visitor class. + */ + template + struct DerivedVisitor : public Visitor { + /** + * @brief Visit a GenericFunction object. + * + * This method casts the visitor to the derived type and calls its visitImpl method. + * + * @param uf The GenericFunction to visit. + */ + void visit( const GenericFunction& gf ) override { + static_cast(this)->visitImpl(gf); + } + }; // struct DerivedVisitor + + /** + * @brief A visitor that applies a function to a vector. + * + * This class implements the actual logic of applying a function to a vector. + * + * @tparam VecT The type of the vector. + * @tparam EvalT The type of the evaluator function. + */ + template + class VectorVisitor : public DerivedVisitor> { + public: + /** + * @brief Construct a new VectorVisitor object. + * + * @param vec The vector to apply the function to. + * @param eval The evaluator function. + */ + VectorVisitor( const std::vector& vecs, EvalT&& eval ) + : vecs_{vecs}, eval_{std::forward(eval)} {} + + /** + * @brief Apply the function to the vector. + * + * This method is called by the visit method of the base DerivedVisitor. + * + * @param uf The GenericFunction to apply. + */ + void visitImpl( const GenericFunction& gf ) { + eval_(vecs_, gf); + } + + private: + const std::vector& vec_; ///< Reference to the pointers to vectors. + EvalT eval_; ///< The evaluator function. + }; // class VectorVisitor + + const std::size_t arity_; ///< Number of Real arguments the function takes + +}; // class GenericFunction + +} // namespace ROL diff --git a/packages/rol/src/elementwise/ROL_GenericUnaryFunction.hpp b/packages/rol/src/elementwise/ROL_GenericUnaryFunction.hpp new file mode 100644 index 000000000000..47b8ca8881a4 --- /dev/null +++ b/packages/rol/src/elementwise/ROL_GenericUnaryFunction.hpp @@ -0,0 +1,242 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#pragma once +#include + +namespace ROL { + +/** + * @brief A template class representing a unary function that can be applied to Vectors. + * + * This class provides a mechanism for applying unary functions to Vectors efficiently, + * using the Visitor pattern to avoid virtual function calls for each element. + * + * @tparam Real The type used for real numbers in the function and calculations. + */ +template +class GenericUnaryFunction { +private: + template class DerivedVisitor; ///< Forward declaration + +protected: + /** + * @brief Abstract base class for visitors. + * + * This class is part of the Visitor pattern implementation, allowing for + * double dispatch without virtual function calls for each vector element. + */ + struct Visitor { + virtual void visit( const GenericUnaryFunction& ) = 0; + }; + +public: + /** @brief Virtual destructor for proper cleanup of derived classes. */ + virtual ~GenericUnaryFunction() noexcept = default; + + /** + * @brief Apply the unary function to a single value. + * + * @param x The input value. + * @return The result of applying the function to x. + */ + [[nodiscard]] virtual Real operator()( Real x ) const = 0; + + /** + * @brief Accept a visitor, part of the Visitor pattern implementation. + * + * @param visitor The visitor to accept. + */ + virtual void accept( Visitor&& visitor ) const = 0; + + /** + * @brief Apply the unary function to a vector. + * + * This method uses the Visitor pattern to efficiently apply the function + * to all elements of the vector without virtual function calls per element. + * + * @tparam VecT The type of the vector. + * @tparam EvalT The type of the evaluator function. + * @param vec The vector to apply the function to. + * @param eval The evaluator function that defines how to apply the unary function to the vector. + * + * Example Usage: + * @code + * template + * class Vector { + * public: + * virtual void applyGenericUnary( const GenericUnaryFunction& ) {} + * }; + * + * template + * class StdVector : public Vector { + * public: + * void applyGenericUnary( const GenericUnaryFunction& guf ) override { + * guf.apply_vectorized(*this,[](StdVector& vec, const auto& f){ vec.applyGenericUnaryImpl(f); }); + * } + * + * template + * void applyGenericUnaryImpl( const unary_function& f ) { + * for( auto& e : vec_ ) e = f(e); + * } + * private: + * std::vector vec_; + * }; + * @endcode + */ + template + void apply_vectorized( VecT& vec, EvalT&& eval ) const { + accept(VectorVisitor(vec,std::forward(eval))); + } + + /** + * @brief A wrapper class that turns any callable into a GenericUnaryFunction. + * + * This class allows easy creation of GenericUnaryFunction objects from lambdas or other callables. + * + * @tparam Func The type of the callable to wrap. + * @tparam Base The base class to inherit from, defaults to GenericUnaryFunction. + */ + template + class Wrapper: public Base { + public: + + /** + * @brief Construct a new Wrapper object. + * + * @param f The callable to wrap. + */ + Wrapper( Func&& f ) : f_{std::forward(f)} { + static_assert( std::is_invocable_r_v,Real>, + "Callable must take and return Real" ); + } + + /** + * @brief Apply the wrapped function. + * + * @param x The input value. + * @return The result of applying the wrapped function to x. + */ + inline Real operator()( Real x ) const override { return f_(x); } + + private: + /** + * @brief Accept a visitor, part of the Visitor pattern implementation. + * + * @param visitor The visitor to accept. + */ + void accept( Visitor&& visitor ) const override { visitor.visit(*this); } + + Func f_; ///< The wrapped callable. + }; // class Wrapper + + /** + * @brief Class Template Argument Deduction (CTAD) guide for Wrapper. + * + * This allows the compiler to deduce the template arguments for Wrapper + * when constructing it from a callable. + */ + template + Wrapper( Func&& ) -> Wrapper>; + +private: + /** + * @brief A base class for visitors that implements the visit method. + * + * This class uses the Curiously Recurring Template Pattern (CRTP) to + * achieve static polymorphism, avoiding virtual function calls. + * + * @tparam Derived The derived visitor class. + */ + template + struct DerivedVisitor : public Visitor { + /** + * @brief Visit a GenericUnaryFunction object. + * + * This method casts the visitor to the derived type and calls its visitImpl method. + * + * @param uf The GenericUnaryFunction to visit. + */ + void visit( const GenericUnaryFunction& uf ) override { + static_cast(this)->visitImpl(uf); + } + }; // struct DerivedVisitor + + /** + * @brief A visitor that applies a unary function to a vector. + * + * This class implements the actual logic of applying a unary function to a vector. + * + * @tparam VecT The type of the vector. + * @tparam EvalT The type of the evaluator function. + */ + template + class VectorVisitor : public DerivedVisitor> { + public: + /** + * @brief Construct a new VectorVisitor object. + * + * @param vec The vector to apply the function to. + * @param eval The evaluator function. + */ + VectorVisitor( VecT& vec, EvalT&& eval ) + : vec_{vec}, eval_{std::forward(eval)} {} + + /** + * @brief Apply the unary function to the vector. + * + * This method is called by the visit method of the base DerivedVisitor. + * + * @param uf The GenericUnaryFunction to apply. + */ + void visitImpl( const GenericUnaryFunction& uf ) { + eval_(vec_, uf); + } + + private: + VecT& vec_; ///< Reference to the vector. + EvalT eval_; ///< The evaluator function. + }; // class VectorVisitor +}; // class GenericUnaryFunction + +} // namespace ROL diff --git a/packages/rol/src/function/constraint/ROL_ConstraintDef.hpp b/packages/rol/src/function/constraint/ROL_ConstraintDef.hpp index 82e75480cfe9..c5966746a2de 100644 --- a/packages/rol/src/function/constraint/ROL_ConstraintDef.hpp +++ b/packages/rol/src/function/constraint/ROL_ConstraintDef.hpp @@ -181,19 +181,19 @@ std::vector Constraint::solveAugmentedSystem(Vector &v1, v1.zero(); v2.zero(); // Allocate static memory. - ROL::Ptr > r1 = b1.clone(); - ROL::Ptr > r2 = b2.clone(); - ROL::Ptr > z1 = v1.clone(); - ROL::Ptr > z2 = v2.clone(); - ROL::Ptr > w1 = b1.clone(); - ROL::Ptr > w2 = b2.clone(); - std::vector > > V1; - std::vector > > V2; - ROL::Ptr > V2temp = b2.clone(); - std::vector > > Z1; - std::vector > > Z2; - ROL::Ptr > w1temp = b1.clone(); - ROL::Ptr > Z2temp = v2.clone(); + Ptr> r1 = b1.clone(); + Ptr> r2 = b2.clone(); + Ptr> z1 = v1.clone(); + Ptr> z2 = v2.clone(); + Ptr> w1 = b1.clone(); + Ptr> w2 = b2.clone(); + std::vector>> V1; + std::vector>> V2; + Ptr> V2temp = b2.clone(); + std::vector>> Z1; + std::vector>> Z2; + Ptr> w1temp = b1.clone(); + Ptr> Z2temp = v2.clone(); std::vector res(m+1, zero); LA::Matrix H(m+1,m); @@ -202,13 +202,14 @@ std::vector Constraint::solveAugmentedSystem(Vector &v1, LA::Vector s(m+1); LA::Vector y(m+1); LA::Vector cnorm(m); - ROL::LAPACK lapack; + LAPACK lapack; // Compute initial residual. - applyAdjointJacobian(*r1, v2, x, zerotol); - r1->scale(-one); r1->axpy(-one, v1.dual()); r1->plus(b1); - applyJacobian(*r2, v1, x, zerotol); - r2->scale(-one); r2->plus(b2); + //applyAdjointJacobian(*r1, v2, x, zerotol); + //r1->scale(-one); r1->axpy(-one, v1.dual()); r1->plus(b1); + //applyJacobian(*r2, v1, x, zerotol); + //r2->scale(-one); r2->plus(b2); + r1->set(b1); r2->set(b2); res[0] = std::sqrt(r1->dot(*r1) + r2->dot(*r2)); // Check if residual is identically zero. @@ -301,12 +302,13 @@ std::vector Constraint::solveAugmentedSystem(Vector &v1, if (res[i+1] <= tol) { // std::cout << " solved in " << i+1 << " iterations to " << res[i+1] << " (" << res[i+1]/res[0] << ")" << std::endl; // Update solution vector. - v1.plus(*z1); - v2.plus(*z2); + //v1.plus(*z1); + //v2.plus(*z2); break; } } // for (int i=0; i++; i::getNumberConstraintEvaluations(void) const { template Ptr> Constraint_Partitioned::get(int ind) const { - if (ind < 0 || ind > static_cast(cvec_.size())) { + if (ind < 0 || ind >= static_cast(cvec_.size())) { throw Exception::NotImplemented(">>> Constraint_Partitioned::get : Index out of bounds!"); } return cvec_[ind]; diff --git a/packages/rol/src/function/dynamic/ROL_DynamicConstraint.hpp b/packages/rol/src/function/dynamic/ROL_DynamicConstraint.hpp index eba92ada94b6..2eed45a00b4c 100644 --- a/packages/rol/src/function/dynamic/ROL_DynamicConstraint.hpp +++ b/packages/rol/src/function/dynamic/ROL_DynamicConstraint.hpp @@ -89,7 +89,9 @@ class DynamicConstraint : public DynamicFunction { virtual ~DynamicConstraint() {} - DynamicConstraint( std::initializer_list zero_deriv_terms={} ): + DynamicConstraint() : DynamicConstraint( {} ) {} + + DynamicConstraint( std::initializer_list zero_deriv_terms ): DynamicFunction(zero_deriv_terms), unew_ ( nullPtr ), jv_ ( nullPtr ), diff --git a/packages/rol/src/function/dynamic/ROL_DynamicConstraint_CheckInterface.hpp b/packages/rol/src/function/dynamic/ROL_DynamicConstraint_CheckInterface.hpp index 70aa901203e8..d14f0ab376f2 100644 --- a/packages/rol/src/function/dynamic/ROL_DynamicConstraint_CheckInterface.hpp +++ b/packages/rol/src/function/dynamic/ROL_DynamicConstraint_CheckInterface.hpp @@ -17,9 +17,6 @@ namespace ROL { namespace details { -using namespace std; -namespace ph = std::placeholders; - template class DynamicConstraint_CheckInterface { private: @@ -44,179 +41,179 @@ class DynamicConstraint_CheckInterface { } f_update_t update_uo( const V& un, const V& z ) { - return bind( &Con::update, &con_, ph::_1, cref(un), cref(z), ts_ ); + return std::bind( &Con::update, &con_, ph::_1, std::cref(un), std::cref(z), ts_ ); } f_update_t update_un( const V& uo, const V& z ) { - return bind( &Con::update, &con_, cref(uo), ph::_1, cref(z), ts_ ); + return std::bind( &Con::update, &con_, std::cref(uo), ph::_1, std::cref(z), ts_ ); } f_update_t update_z( const V& uo, const V& un ) { - return bind( &Con::update, &con_, cref(uo), cref(un), ph::_1, ts_ ); + return std::bind( &Con::update, &con_, std::cref(uo), std::cref(un), ph::_1, ts_ ); } //---------------------------------------------------------------------------- f_vector_t value_uo( const V& un, const V& z ) { - return bind( &Con::value, &con_, - ph::_1, ph::_2, cref(un), cref(z), ts_ ); + return std::bind( &Con::value, &con_, + ph::_1, ph::_2, std::cref(un), std::cref(z), ts_ ); } f_vector_t value_un( const V& uo, const V& z ) { - return bind( &Con::value, &con_, - ph::_1, cref(uo), ph::_2, cref(z), ts_ ); + return std::bind( &Con::value, &con_, + ph::_1, std::cref(uo), ph::_2, std::cref(z), ts_ ); } f_vector_t value_z( const V& uo, const V& un ) { - return bind( &Con::value, &con_, - ph::_1, cref(uo), cref(un), ph::_2, ts_ ); + return std::bind( &Con::value, &con_, + ph::_1, std::cref(uo), std::cref(un), ph::_2, ts_ ); } f_solve_t solve_un( const V& uo, const V& z ) { - return bind( &Con::solve, &con_, - ph::_1, cref(uo), ph::_2, cref(z), ts_ ); + return std::bind( &Con::solve, &con_, + ph::_1, std::cref(uo), ph::_2, std::cref(z), ts_ ); } //---------------------------------------------------------------------------- f_dderiv_t jacobian_uo( const V& un, const V& z ) { - return bind( &Con::applyJacobian_uo, &con_, ph::_1, ph::_2, ph::_3, - cref(un), cref(z), ts_ ); + return std::bind( &Con::applyJacobian_uo, &con_, ph::_1, ph::_2, ph::_3, + std::cref(un), std::cref(z), ts_ ); } f_dderiv_t jacobian_un( const V& uo, const V& z ) { - return bind( &Con::applyJacobian_un, &con_, ph::_1, ph::_2, cref(uo), - ph::_3, cref(z), ts_ ); + return std::bind( &Con::applyJacobian_un, &con_, ph::_1, ph::_2, std::cref(uo), + ph::_3, std::cref(z), ts_ ); } f_dderiv_t inverseJacobian_un( const V& uo, const V& z ) { - return bind( &Con::applyInverseJacobian_un, &con_, ph::_1, ph::_2, cref(uo), - ph::_3, cref(z), ts_ ); + return std::bind( &Con::applyInverseJacobian_un, &con_, ph::_1, ph::_2, std::cref(uo), + ph::_3, std::cref(z), ts_ ); } f_dderiv_t jacobian_z( const V& uo, const V& un ) { - return bind( &Con::applyJacobian_z, &con_, ph::_1, ph::_2, cref(uo), - cref(un), ph::_3, ts_ ); + return std::bind( &Con::applyJacobian_z, &con_, ph::_1, ph::_2, std::cref(uo), + std::cref(un), ph::_3, ts_ ); } //---------------------------------------------------------------------------- f_dderiv_t adjointJacobian_uo( const V& un, const V& z ) { - return bind( &Con::applyAdjointJacobian_uo, &con_, ph::_1, ph::_2, ph::_3, - cref(un), cref(z), ts_ ); + return std::bind( &Con::applyAdjointJacobian_uo, &con_, ph::_1, ph::_2, ph::_3, + std::cref(un), std::cref(z), ts_ ); } f_dderiv_t adjointJacobian_un( const V& uo, const V& z ) { - return bind( &Con::applyAdjointJacobian_un, &con_, ph::_1, ph::_2, cref(uo), - ph::_3, cref(z), ts_ ); + return std::bind( &Con::applyAdjointJacobian_un, &con_, ph::_1, ph::_2, std::cref(uo), + ph::_3, std::cref(z), ts_ ); } f_dderiv_t inverseAdjointJacobian_un( const V& uo, const V& z ) { - return bind( &Con::applyInverseAdjointJacobian_un, &con_, ph::_1, ph::_2, cref(uo), - ph::_3, cref(z), ts_ ); + return std::bind( &Con::applyInverseAdjointJacobian_un, &con_, ph::_1, ph::_2, std::cref(uo), + ph::_3, std::cref(z), ts_ ); } f_dderiv_t adjointJacobian_z( const V& uo, const V& un ) { - return bind( &Con::applyAdjointJacobian_z, &con_, ph::_1, ph::_2, cref(uo), - cref(un), ph::_3, ts_ ); + return std::bind( &Con::applyAdjointJacobian_z, &con_, ph::_1, ph::_2, std::cref(uo), + std::cref(un), ph::_3, ts_ ); } //---------------------------------------------------------------------------- f_dderiv_t adjointJacobian_uo_uo( const V& un, const V& z ) { - return bind( &Con::applyAdjointJacobian_uo, &con_, ph::_1, ph::_2, ph::_3, - cref(un), cref(z), ts_ ); + return std::bind( &Con::applyAdjointJacobian_uo, &con_, ph::_1, ph::_2, ph::_3, + std::cref(un), std::cref(z), ts_ ); } f_dderiv_t adjointJacobian_uo_un( const V& uo, const V& z ) { - return bind( &Con::applyAdjointJacobian_uo, &con_, ph::_1, ph::_2, cref(uo), - ph::_3, cref(z), ts_ ); + return std::bind( &Con::applyAdjointJacobian_uo, &con_, ph::_1, ph::_2, std::cref(uo), + ph::_3, std::cref(z), ts_ ); } f_dderiv_t adjointJacobian_uo_z( const V& uo, const V& un ) { - return bind( &Con::applyAdjointJacobian_uo, &con_, ph::_1, ph::_2, cref(uo), - cref(un), ph::_3, ts_ ); + return std::bind( &Con::applyAdjointJacobian_uo, &con_, ph::_1, ph::_2, std::cref(uo), + std::cref(un), ph::_3, ts_ ); } f_dderiv_t adjointJacobian_un_uo( const V& un, const V& z ) { - return bind( &Con::applyAdjointJacobian_un, &con_, ph::_1, ph::_2, ph::_3, - cref(un), cref(z), ts_ ); + return std::bind( &Con::applyAdjointJacobian_un, &con_, ph::_1, ph::_2, ph::_3, + std::cref(un), std::cref(z), ts_ ); } f_dderiv_t adjointJacobian_un_un( const V& uo, const V& z ) { - return bind( &Con::applyAdjointJacobian_un, &con_, ph::_1, ph::_2, cref(uo), - ph::_3, cref(z), ts_ ); + return std::bind( &Con::applyAdjointJacobian_un, &con_, ph::_1, ph::_2, std::cref(uo), + ph::_3, std::cref(z), ts_ ); } f_dderiv_t adjointJacobian_un_z( const V& uo, const V& un ) { - return bind( &Con::applyAdjointJacobian_un, &con_, ph::_1, ph::_2, cref(uo), - cref(un), ph::_3, ts_ ); + return std::bind( &Con::applyAdjointJacobian_un, &con_, ph::_1, ph::_2, std::cref(uo), + std::cref(un), ph::_3, ts_ ); } f_dderiv_t adjointJacobian_z_uo( const V& un, const V& z ) { - return bind( &Con::applyAdjointJacobian_z, &con_, ph::_1, ph::_2, ph::_3, - cref(un), cref(z), ts_ ); + return std::bind( &Con::applyAdjointJacobian_z, &con_, ph::_1, ph::_2, ph::_3, + std::cref(un), std::cref(z), ts_ ); } f_dderiv_t adjointJacobian_z_un( const V& uo, const V& z ) { - return bind( &Con::applyAdjointJacobian_z, &con_, ph::_1, ph::_2, cref(uo), - ph::_3, cref(z), ts_ ); + return std::bind( &Con::applyAdjointJacobian_z, &con_, ph::_1, ph::_2, std::cref(uo), + ph::_3, std::cref(z), ts_ ); } f_dderiv_t adjointJacobian_z_z( const V& uo, const V& un ) { - return bind( &Con::applyAdjointJacobian_z, &con_, ph::_1, ph::_2, cref(uo), - cref(un), ph::_3, ts_ ); + return std::bind( &Con::applyAdjointJacobian_z, &con_, ph::_1, ph::_2, std::cref(uo), + std::cref(un), ph::_3, ts_ ); } //---------------------------------------------------------------------------- f_dderiv_t adjointHessian_un_un( const V& uo, const V& z, const V& l ) { - return bind( &Con::applyAdjointHessian_un_un, &con_, ph::_1, cref(l), ph::_2, - cref(uo), ph::_3, cref(z), ts_ ); + return std::bind( &Con::applyAdjointHessian_un_un, &con_, ph::_1, std::cref(l), ph::_2, + std::cref(uo), ph::_3, std::cref(z), ts_ ); } f_dderiv_t adjointHessian_un_uo( const V& uo, const V& z, const V& l ) { - return bind( &Con::applyAdjointHessian_un_uo, &con_, ph::_1, cref(l), ph::_2, - cref(uo), ph::_3, cref(z), ts_ ); + return std::bind( &Con::applyAdjointHessian_un_uo, &con_, ph::_1, std::cref(l), ph::_2, + std::cref(uo), ph::_3, std::cref(z), ts_ ); } f_dderiv_t adjointHessian_un_z( const V& uo, const V& z, const V& l ) { - return bind( &Con::applyAdjointHessian_un_z, &con_, ph::_1, cref(l), ph::_2, - cref(uo), ph::_3, cref(z), ts_ ); + return std::bind( &Con::applyAdjointHessian_un_z, &con_, ph::_1, std::cref(l), ph::_2, + std::cref(uo), ph::_3, std::cref(z), ts_ ); } //---------------------------------------------------------------------------- f_dderiv_t adjointHessian_uo_un( const V& un, const V& z, const V& l ) { - return bind( &Con::applyAdjointHessian_uo_un, &con_, ph::_1, cref(l), ph::_2, - ph::_3, cref(un), cref(z), ts_ ); + return std::bind( &Con::applyAdjointHessian_uo_un, &con_, ph::_1, std::cref(l), ph::_2, + ph::_3, std::cref(un), std::cref(z), ts_ ); } f_dderiv_t adjointHessian_uo_uo( const V& un, const V& z, const V& l ) { - return bind( &Con::applyAdjointHessian_uo_uo, &con_, ph::_1, cref(l), ph::_2, - ph::_3, cref(un), cref(z), ts_ ); + return std::bind( &Con::applyAdjointHessian_uo_uo, &con_, ph::_1, std::cref(l), ph::_2, + ph::_3, std::cref(un), std::cref(z), ts_ ); } f_dderiv_t adjointHessian_uo_z( const V& un, const V& z, const V& l ) { - return bind( &Con::applyAdjointHessian_uo_z, &con_, ph::_1, cref(l), ph::_2, - ph::_3, cref(un), cref(z), ts_ ); + return std::bind( &Con::applyAdjointHessian_uo_z, &con_, ph::_1, std::cref(l), ph::_2, + ph::_3, std::cref(un), std::cref(z), ts_ ); } //---------------------------------------------------------------------------- f_dderiv_t adjointHessian_z_un( const V& uo, const V& un, const V& l ) { - return bind( &Con::applyAdjointHessian_z_un, &con_, ph::_1, cref(l), ph::_2, - cref(uo), cref(un), ph::_3, ts_ ); + return std::bind( &Con::applyAdjointHessian_z_un, &con_, ph::_1, std::cref(l), ph::_2, + std::cref(uo), std::cref(un), ph::_3, ts_ ); } f_dderiv_t adjointHessian_z_uo( const V& uo, const V& un, const V& l ) { - return bind( &Con::applyAdjointHessian_z_uo, &con_, ph::_1, cref(l), ph::_2, - cref(uo), cref(un), ph::_3, ts_ ); + return std::bind( &Con::applyAdjointHessian_z_uo, &con_, ph::_1, std::cref(l), ph::_2, + std::cref(uo), std::cref(un), ph::_3, ts_ ); } f_dderiv_t adjointHessian_z_z( const V& uo, const V& un, const V& l ) { - return bind( &Con::applyAdjointHessian_z_z, &con_, ph::_1, cref(l), ph::_2, - cref(uo), cref(un), ph::_3, ts_ ); + return std::bind( &Con::applyAdjointHessian_z_z, &con_, ph::_1, std::cref(l), ph::_2, + std::cref(uo), std::cref(un), ph::_3, ts_ ); } }; // class DynamicConstraint_CheckInterface diff --git a/packages/rol/src/function/dynamic/ROL_DynamicObjective.hpp b/packages/rol/src/function/dynamic/ROL_DynamicObjective.hpp index 84d0d7f18d0e..048293c54015 100644 --- a/packages/rol/src/function/dynamic/ROL_DynamicObjective.hpp +++ b/packages/rol/src/function/dynamic/ROL_DynamicObjective.hpp @@ -41,8 +41,9 @@ class DynamicObjective : public DynamicFunction { using V = Vector; using TS = TimeStamp; + DynamicObjective() : DynamicObjective( {} ) {} - DynamicObjective( std::initializer_list zero_deriv_terms={} ) : + DynamicObjective( std::initializer_list zero_deriv_terms ) : DynamicFunction( zero_deriv_terms ) {} virtual ~DynamicObjective() {} diff --git a/packages/rol/src/function/dynamic/ROL_DynamicObjective_CheckInterface.hpp b/packages/rol/src/function/dynamic/ROL_DynamicObjective_CheckInterface.hpp index 4134f758d95b..719b0aa2201d 100644 --- a/packages/rol/src/function/dynamic/ROL_DynamicObjective_CheckInterface.hpp +++ b/packages/rol/src/function/dynamic/ROL_DynamicObjective_CheckInterface.hpp @@ -20,7 +20,6 @@ namespace ROL { namespace details { -using namespace std; namespace ph = std::placeholders; template @@ -48,122 +47,122 @@ class DynamicObjective_CheckInterface { f_update_t update_uo( const V& un, const V& z ) { - return bind( &Obj::update, &obj_, ph::_1, cref(un), cref(z), ts_ ); + return std::bind( &Obj::update, &obj_, ph::_1, std::cref(un), std::cref(z), ts_ ); } f_update_t update_un( const V& uo, const V& z ) { - return bind( &Obj::update, &obj_, cref(uo), ph::_1, cref(z), ts_ ); + return std::bind( &Obj::update, &obj_, std::cref(uo), ph::_1, std::cref(z), ts_ ); } f_update_t update_z( const V& uo, const V& un ) { - return bind( &Obj::update, &obj_, cref(uo), cref(un), ph::_1, ts_ ); + return std::bind( &Obj::update, &obj_, std::cref(uo), std::cref(un), ph::_1, ts_ ); } //---------------------------------------------------------------------------- f_scalar_t value_uo( const V& un, const V& z ) { - return bind( &Obj::value, &obj_, ph::_1, cref(un), cref(z), ts_ ); + return std::bind( &Obj::value, &obj_, ph::_1, std::cref(un), std::cref(z), ts_ ); } f_scalar_t value_un( const V& uo, const V& z ) { - return bind( &Obj::value, &obj_, cref(uo), ph::_1, cref(z), ts_ ); + return std::bind( &Obj::value, &obj_, std::cref(uo), ph::_1, std::cref(z), ts_ ); } f_scalar_t value_z( const V& uo, const V& un ) { - return bind( &Obj::value, &obj_, cref(uo), cref(un), ph::_1, ts_ ); + return std::bind( &Obj::value, &obj_, std::cref(uo), std::cref(un), ph::_1, ts_ ); } //---------------------------------------------------------------------------- f_vector_t gradient_uo( const V& un, const V& z ) { - return bind( &Obj::gradient_uo, &obj_, ph::_1, ph::_2, cref(un), cref(z), ts_ ); + return std::bind( &Obj::gradient_uo, &obj_, ph::_1, ph::_2, std::cref(un), std::cref(z), ts_ ); } f_vector_t gradient_un( const V& uo, const V& z ) { - return bind( &Obj::gradient_un, &obj_, ph::_1, cref(uo), ph::_2, cref(z), ts_ ); + return std::bind( &Obj::gradient_un, &obj_, ph::_1, std::cref(uo), ph::_2, std::cref(z), ts_ ); } f_vector_t gradient_z( const V& uo, const V& un ) { - return bind( &Obj::gradient_z, &obj_, ph::_1, cref(uo), cref(un), ph::_2, ts_ ); + return std::bind( &Obj::gradient_z, &obj_, ph::_1, std::cref(uo), std::cref(un), ph::_2, ts_ ); } // For hessian checks f_vector_t gradient_uo_uo( const V& un, const V& z ) { - return bind( &Obj::gradient_uo, &obj_, ph::_1, ph::_2, cref(un), cref(z), ts_ ); + return std::bind( &Obj::gradient_uo, &obj_, ph::_1, ph::_2, std::cref(un), std::cref(z), ts_ ); } f_vector_t gradient_uo_un( const V& uo, const V& z ) { - return bind( &Obj::gradient_uo, &obj_, ph::_1, cref(uo), ph::_2, cref(z), ts_ ); + return std::bind( &Obj::gradient_uo, &obj_, ph::_1, std::cref(uo), ph::_2, std::cref(z), ts_ ); } f_vector_t gradient_uo_z( const V& uo, const V& un ) { - return bind( &Obj::gradient_uo, &obj_, ph::_1, cref(uo), cref(un), ph::_2, ts_ ); + return std::bind( &Obj::gradient_uo, &obj_, ph::_1, std::cref(uo), std::cref(un), ph::_2, ts_ ); } f_vector_t gradient_un_uo( const V& un, const V& z ) { - return bind( &Obj::gradient_un, &obj_, ph::_1, ph::_2, cref(un), cref(z), ts_ ); + return std::bind( &Obj::gradient_un, &obj_, ph::_1, ph::_2, std::cref(un), std::cref(z), ts_ ); } f_vector_t gradient_un_un( const V& uo, const V& z ) { - return bind( &Obj::gradient_un, &obj_, ph::_1, cref(uo), ph::_2, cref(z), ts_ ); + return std::bind( &Obj::gradient_un, &obj_, ph::_1, std::cref(uo), ph::_2, std::cref(z), ts_ ); } f_vector_t gradient_un_z( const V& uo, const V& un ) { - return bind( &Obj::gradient_un, &obj_, ph::_1, cref(uo), cref(un), ph::_2, ts_ ); + return std::bind( &Obj::gradient_un, &obj_, ph::_1, std::cref(uo), std::cref(un), ph::_2, ts_ ); } f_vector_t gradient_z_uo( const V& un, const V& z ) { - return bind( &Obj::gradient_z, &obj_, ph::_1, ph::_2, cref(un), cref(z), ts_ ); + return std::bind( &Obj::gradient_z, &obj_, ph::_1, ph::_2, std::cref(un), std::cref(z), ts_ ); } f_vector_t gradient_z_un( const V& uo, const V& z ) { - return bind( &Obj::gradient_z, &obj_, ph::_1, cref(uo), ph::_2, cref(z), ts_ ); + return std::bind( &Obj::gradient_z, &obj_, ph::_1, std::cref(uo), ph::_2, std::cref(z), ts_ ); } f_vector_t gradient_z_z( const V& uo, const V& un ) { - return bind( &Obj::gradient_z, &obj_, ph::_1, cref(uo), cref(un), ph::_2, ts_ ); + return std::bind( &Obj::gradient_z, &obj_, ph::_1, std::cref(uo), std::cref(un), ph::_2, ts_ ); } //---------------------------------------------------------------------------- f_dderiv_t hessVec_uo_uo( const V& un, const V& z ) { - return bind( &Obj::hessVec_uo_uo, &obj_, ph::_1, ph::_2, ph::_3, cref(un), cref(z), ts_ ); + return std::bind( &Obj::hessVec_uo_uo, &obj_, ph::_1, ph::_2, ph::_3, std::cref(un), std::cref(z), ts_ ); } f_dderiv_t hessVec_uo_un( const V& uo, const V& z ) { - return bind( &Obj::hessVec_uo_un, &obj_, ph::_1, ph::_2, cref(uo), ph::_3, cref(z), ts_ ); + return std::bind( &Obj::hessVec_uo_un, &obj_, ph::_1, ph::_2, std::cref(uo), ph::_3, std::cref(z), ts_ ); } f_dderiv_t hessVec_uo_z( const V& uo, const V& un ) { - return bind( &Obj::hessVec_uo_z, &obj_, ph::_1, ph::_2, cref(uo), cref(un), ph::_3, ts_ ); + return std::bind( &Obj::hessVec_uo_z, &obj_, ph::_1, ph::_2, std::cref(uo), std::cref(un), ph::_3, ts_ ); } //---------------------------------------------------------------------------- f_dderiv_t hessVec_un_uo( const V& un, const V& z ) { - return bind( &Obj::hessVec_un_uo, &obj_, ph::_1, ph::_2, ph::_3, cref(un), cref(z), ts_ ); + return std::bind( &Obj::hessVec_un_uo, &obj_, ph::_1, ph::_2, ph::_3, std::cref(un), std::cref(z), ts_ ); } f_dderiv_t hessVec_un_un( const V& uo, const V& z ) { - return bind( &Obj::hessVec_un_un, &obj_, ph::_1, ph::_2, cref(uo), ph::_3, cref(z), ts_ ); + return std::bind( &Obj::hessVec_un_un, &obj_, ph::_1, ph::_2, std::cref(uo), ph::_3, std::cref(z), ts_ ); } f_dderiv_t hessVec_un_z( const V& uo, const V& un ) { - return bind( &Obj::hessVec_un_z, &obj_, ph::_1, ph::_2, cref(uo), cref(un), ph::_3, ts_ ); + return std::bind( &Obj::hessVec_un_z, &obj_, ph::_1, ph::_2, std::cref(uo), std::cref(un), ph::_3, ts_ ); } //---------------------------------------------------------------------------- f_dderiv_t hessVec_z_uo( const V& un, const V& z ) { - return bind( &Obj::hessVec_z_uo, &obj_, ph::_1, ph::_2, ph::_3, cref(un), cref(z), ts_ ); + return std::bind( &Obj::hessVec_z_uo, &obj_, ph::_1, ph::_2, ph::_3, std::cref(un), std::cref(z), ts_ ); } f_dderiv_t hessVec_z_un( const V& uo, const V& z ) { - return bind( &Obj::hessVec_z_un, &obj_, ph::_1, ph::_2, cref(uo), ph::_3, cref(z), ts_ ); + return std::bind( &Obj::hessVec_z_un, &obj_, ph::_1, ph::_2, std::cref(uo), ph::_3, std::cref(z), ts_ ); } f_dderiv_t hessVec_z_z( const V& uo, const V& un ) { - return bind( &Obj::hessVec_z_z, &obj_, ph::_1, ph::_2, cref(uo), cref(un), ph::_3, ts_ ); + return std::bind( &Obj::hessVec_z_z, &obj_, ph::_1, ph::_2, std::cref(uo), std::cref(un), ph::_3, ts_ ); } diff --git a/packages/rol/src/function/objective/ROL_AffineTransformObjective.hpp b/packages/rol/src/function/objective/ROL_AffineTransformObjective.hpp index f966d760a0bd..598e43a2adb7 100644 --- a/packages/rol/src/function/objective/ROL_AffineTransformObjective.hpp +++ b/packages/rol/src/function/objective/ROL_AffineTransformObjective.hpp @@ -52,6 +52,7 @@ class AffineTransformObjective : public Objective { Real value( const Vector &x, Real &tol ) override; void gradient( Vector &g, const Vector &x, Real &tol ) override; void hessVec( Vector &hv, const Vector &v, const Vector &x, Real &tol ) override; + const Ptr> getObjective() const {return obj_;} public: void setParameter(const std::vector ¶m) override; diff --git a/packages/rol/src/function/objective/ROL_AffineTransformObjective_Def.hpp b/packages/rol/src/function/objective/ROL_AffineTransformObjective_Def.hpp index 3935d6d7a5e1..7468cc8e4a3a 100644 --- a/packages/rol/src/function/objective/ROL_AffineTransformObjective_Def.hpp +++ b/packages/rol/src/function/objective/ROL_AffineTransformObjective_Def.hpp @@ -16,7 +16,7 @@ template AffineTransformObjective::AffineTransformObjective(const Ptr> &obj, const Ptr> &acon, const Vector &range, - const Ptr> &storage) + const Ptr> &storage) : obj_(obj), acon_(acon), storage_(storage) { primal_ = range.clone(); Av_ = range.clone(); diff --git a/packages/rol/src/function/objective/ROL_Objective.hpp b/packages/rol/src/function/objective/ROL_Objective.hpp index 7493d30b8e1b..0edae01ac13f 100644 --- a/packages/rol/src/function/objective/ROL_Objective.hpp +++ b/packages/rol/src/function/objective/ROL_Objective.hpp @@ -152,14 +152,34 @@ class Objective { Pv.set(v.dual()); } - virtual void prox( Vector &Pv, const Vector &v, Real t, Real &tol){ + /** \brief Compute the proximity operator. + + This function returns the proximity operator. + @param[out] Pv is the proximity operator applied to \f$v\f$ (primal optimization vector). + @param[in] v is the input to the proximity operator (primal optimization vector). + @param[in] t is the proximity operator parameter (positive scalar). + @param[in] tol is a tolerance for inexact objective function computation. + */ + virtual void prox( Vector &Pv, const Vector &v, Real t, Real &tol){ ROL_UNUSED(Pv); ROL_UNUSED(v); ROL_UNUSED(t); ROL_UNUSED(tol); ROL_TEST_FOR_EXCEPTION(true, std::invalid_argument, ">>> ERROR (ROL::Objective): prox not implemented!"); - } + } + + + /** \brief Apply the Jacobian of the proximity operator. + + This function applies the Jacobian of the proximity operator. + @param[out] Jv is the Jacobian of the proximity operator at \f$x\f$ applied to \f$v\f$ (primal optimization vector). + @param[in] v is the direction vector (primal optimization vector). + @param[in] x is the input to the proximity operator (primal optimization vector). + @param[in] t is the proximity operator parameter (positive scalar). + @param[in] tol is a tolerance for inexact objective function computation. + */ + virtual void proxJacVec( Vector &Jv, const Vector &v, const Vector &x, Real t, Real &tol); /** \brief Finite-difference gradient check. @@ -451,6 +471,31 @@ class Objective { const bool printToStream = true, std::ostream & outStream = std::cout ); + /** \brief Finite-difference proximity operator Jacobian-applied-to-vector check. + + This function computes a sequence of one-sided finite-difference checks for the proximity + operator Jacobian. + At each step of the sequence, the finite difference step size is decreased. The output + compares the error + \f[ + \left\| \frac{\mathrm{prox}_{t f}(x+tv) - \mathrm{prox}_{t f}(x)}{t} - J_{t f}(x+tv)v\right\|_{\mathcal{X}}, + \f] + if the approximation is first order. Note that in some cases the proximity operator + is semismooth, which motivates the evaluation of \f$J_{t f}\f$ at \f$x+tv\f$. + @param[in] x is an optimization vector. + @param[in] v is a direction vector. + @param[in] t is the proximity operator parameter. + @param[in] printToStream is a flag that turns on/off output. + @param[out] outStream is the output stream. + @param[in] numSteps is a parameter which dictates the number of finite difference steps. + */ + virtual std::vector> checkProxJacVec( const Vector &x, + const Vector &v, + Real t = Real(1), + bool printToStream = true, + std::ostream &outStream = std::cout, + int numSteps = ROL_NUM_CHECKDERIV_STEPS); + // Definitions for parametrized (stochastic) objective functions private: std::vector param_; diff --git a/packages/rol/src/function/objective/ROL_ObjectiveDef.hpp b/packages/rol/src/function/objective/ROL_ObjectiveDef.hpp index c700c4b0114d..f58379a6e0da 100644 --- a/packages/rol/src/function/objective/ROL_ObjectiveDef.hpp +++ b/packages/rol/src/function/objective/ROL_ObjectiveDef.hpp @@ -81,6 +81,28 @@ void Objective::hessVec( Vector &hv, const Vector &v, const Ve } } +template +void Objective::proxJacVec(Vector &Jv, const Vector &v, const Vector &x, Real t, Real &tol) { + const Real zero(0), vnorm = v.norm(); + // Get Step Length + if ( vnorm == zero ) { + Jv.zero(); + } + else { + if (prim_ == nullPtr) prim_ = x.clone(); + + //Real h = 2.0/(v.norm()*v.norm())*tol; + const Real one(1), h(std::max(one,x.norm()/vnorm)*tol); + + prim_->set(x); prim_->axpy(h,v); // Set prim = x + hv + prox(Jv,*prim_,t,tol); // Compute prox at prim + prim_->zero(); + prox(*prim_,x,t,tol); // Compute prox at x + Jv.axpy(-one,*prim_); // Construct FD approximation + Jv.scale(one/h); + } +} + template std::vector> Objective::checkGradient( const Vector &x, const Vector &g, @@ -363,6 +385,82 @@ std::vector Objective::checkHessSym( const Vector &x, } // checkHessSym +template +std::vector> Objective::checkProxJacVec( const Vector &x, + const Vector &v, + Real t, + bool printToStream, + std::ostream & outStream, + int numSteps) { + + const Real one(1), scale(0.1); + Real tol = std::sqrt(ROL_EPSILON()); + + int numVals = 4; + std::vector tmp(numVals); + std::vector> hvCheck(numSteps, tmp); + + // Save the format state of the original outStream. + nullstream oldFormatState; + oldFormatState.copyfmt(outStream); + + // Compute prox at x. + Ptr> p = x.clone(); + prox(*p, x, t, tol); + + // Temporary vectors. + Ptr> pdif = x.clone(); + Ptr> Jnew = x.clone(); + Ptr> xnew = x.clone(); + + Real eta(10); + for (int i=0; iset(x); + xnew->axpy(eta, v); + prox(*pdif,*xnew,t,tol); + pdif->axpy(-one,*p); + pdif->scale(one/eta); + proxJacVec(*Jnew,v,*xnew,t,tol); + + // Compute norms of jacvec, finite-difference jacvec, and error. + hvCheck[i][0] = eta; + hvCheck[i][1] = Jnew->norm(); + hvCheck[i][2] = pdif->norm(); + pdif->axpy(-one, *Jnew); + hvCheck[i][3] = pdif->norm(); + + if (printToStream) { + if (i==0) { + outStream << std::right + << std::setw(20) << "Step size" + << std::setw(20) << "norm(Jac*vec)" + << std::setw(20) << "norm(FD approx)" + << std::setw(20) << "norm(abs error)" + << std::endl + << std::setw(20) << "---------" + << std::setw(20) << "--------------" + << std::setw(20) << "---------------" + << std::setw(20) << "---------------" + << std::endl; + } + outStream << std::scientific << std::setprecision(11) << std::right + << std::setw(20) << hvCheck[i][0] + << std::setw(20) << hvCheck[i][1] + << std::setw(20) << hvCheck[i][2] + << std::setw(20) << hvCheck[i][3] + << std::endl; + } + } + + // Reset format state of outStream. + outStream.copyfmt(oldFormatState); + + return hvCheck; +} // checkProxJacVec + } // namespace ROL #endif diff --git a/packages/rol/src/function/objective/ROL_l1Objective.hpp b/packages/rol/src/function/objective/ROL_l1Objective.hpp index d7955c506f76..3137ec66a9be 100644 --- a/packages/rol/src/function/objective/ROL_l1Objective.hpp +++ b/packages/rol/src/function/objective/ROL_l1Objective.hpp @@ -71,7 +71,8 @@ class l1Objective : public Objective { Pv.applyBinary(psb_, *weights_); Pv.scale(t); Pv.plus(v); - } + } +//TODO: input prox jacobian }; // class l1Objective } // namespace ROL diff --git a/packages/rol/src/function/polyproj/ROL_PolyhedralProjectionFactory.hpp b/packages/rol/src/function/polyproj/ROL_PolyhedralProjectionFactory.hpp index 4e969a17a9e6..4b42345f5a96 100644 --- a/packages/rol/src/function/polyproj/ROL_PolyhedralProjectionFactory.hpp +++ b/packages/rol/src/function/polyproj/ROL_PolyhedralProjectionFactory.hpp @@ -106,7 +106,8 @@ inline Ptr> PolyhedralProjectionFactory(const Vector< const Vector &mul, const Vector &res, ParameterList &list) { - EPolyProjAlgo ealg = StringToEPolyProjAlgo(list.sublist("General").sublist("Polyhedral Projection").get("Type","Dykstra")); + std::string projectionType = list.sublist("General").sublist("Polyhedral Projection").get("Type","Dykstra"); + EPolyProjAlgo ealg = StringToEPolyProjAlgo(projectionType); switch(ealg) { case PPA_DAIFLETCHER: return makePtr>(xprim,xdual,bnd,con,mul,res,list); break; case PPA_DYKSTRA: return makePtr>(xprim,xdual,bnd,con,mul,res,list); break; diff --git a/packages/rol/src/function/polyproj/ROL_SemismoothNewtonProjection_Def.hpp b/packages/rol/src/function/polyproj/ROL_SemismoothNewtonProjection_Def.hpp index 704c22374df6..0223a8c999f7 100644 --- a/packages/rol/src/function/polyproj/ROL_SemismoothNewtonProjection_Def.hpp +++ b/packages/rol/src/function/polyproj/ROL_SemismoothNewtonProjection_Def.hpp @@ -107,6 +107,7 @@ SemismoothNewtonProjection::SemismoothNewtonProjection(const Vector useproj_ = ppl.sublist("Semismooth Newton").get("Project onto Separating Hyperplane", DEFAULT_useproj_); ParameterList klist; + klist.sublist("General").sublist("Krylov") = ppl.sublist("Semismooth Newton").sublist("Krylov"); klist.sublist("General").set("Inexact Hessian-Times-A-Vector", false); krylov_ = KrylovFactory(klist); diff --git a/packages/rol/src/function/simopt/ROL_Constraint_SimOpt.hpp b/packages/rol/src/function/simopt/ROL_Constraint_SimOpt.hpp index 45bb97b52405..205c2b66d4bb 100644 --- a/packages/rol/src/function/simopt/ROL_Constraint_SimOpt.hpp +++ b/packages/rol/src/function/simopt/ROL_Constraint_SimOpt.hpp @@ -26,7 +26,7 @@ class Constraint_SimOpt; #include "ROL_SimConstraint.hpp" #include "ROL_Objective_FSsolver.hpp" #include "ROL_TypeU_TrustRegionAlgorithm.hpp" -#include "ROL_TypeE_AugmentedLagrangianAlgorithm.hpp" +#include "ROL_TypeE_CompositeStepAlgorithm.hpp" /** @ingroup func_group \class ROL::Constraint_SimOpt @@ -270,7 +270,7 @@ class Constraint_SimOpt : public Constraint { parlist.sublist("Status Test").set("Constraint Tolerance",ctol); parlist.sublist("Status Test").set("Step Tolerance",stol_); parlist.sublist("Status Test").set("Iteration Limit",maxit_); - Ptr> algo = makePtr>(parlist); + Ptr> algo = makePtr>(parlist); algo->run(u,*obj,*con,*l,*stream); value(c,u,z,tol); } diff --git a/packages/rol/src/function/simopt/ROL_Reduced_Constraint_SimOpt.hpp b/packages/rol/src/function/simopt/ROL_Reduced_Constraint_SimOpt.hpp index 7479f3d248ec..d9362c6af231 100644 --- a/packages/rol/src/function/simopt/ROL_Reduced_Constraint_SimOpt.hpp +++ b/packages/rol/src/function/simopt/ROL_Reduced_Constraint_SimOpt.hpp @@ -12,94 +12,49 @@ #include "ROL_Constraint_SimOpt.hpp" #include "ROL_VectorController.hpp" +#include "ROL_BatchManager.hpp" namespace ROL { template class Reduced_Constraint_SimOpt : public Constraint { private: - const ROL::Ptr> conVal_; - const ROL::Ptr> conRed_; - const ROL::Ptr> stateStore_; - ROL::Ptr> adjointStore_; + const ROL::Ptr> conVal_, conRed_; + const ROL::Ptr> stateStore_, adjointStore_; // Primal vectors - ROL::Ptr> state_; - ROL::Ptr> adjoint_; - ROL::Ptr> residual_; - ROL::Ptr> state_sens_; - ROL::Ptr> adjoint_sens_; + const ROL::Ptr> state_, adjoint_, residual_; + const ROL::Ptr> state_sens_, adjoint_sens_; // Dual vectors - ROL::Ptr> dualstate_; - ROL::Ptr> dualstate1_; - ROL::Ptr> dualadjoint_; - ROL::Ptr> dualcontrol_; - ROL::Ptr> dualresidual_; + const ROL::Ptr> dualstate_, dualstate1_, dualadjoint_; + const ROL::Ptr> dualcontrol_, dualresidual_; const bool storage_; const bool useFDhessVec_; + unsigned nupda_, nvalu_, njaco_, najac_, nhess_; + unsigned nstat_, nadjo_, nssen_, nasen_; + bool updateFlag_; int updateIter_; + UpdateType updateType_; + bool newUpdate_; + bool isUpdated_; - void solve_state_equation(const Vector &z, Real &tol) { - // Check if state has been computed. - bool isComputed = false; - if (storage_) { - isComputed = stateStore_->get(*state_,Constraint::getParameter()); - } - // Solve state equation if not done already. - if (!isComputed || !storage_) { - // Update equality constraint with new Opt variable. - conRed_->update_2(z,updateFlag_,updateIter_); - // Solve state equation. - conRed_->solve(*dualadjoint_,*state_,z,tol); - // Update equality constraint with new Sim variable. - conRed_->update_1(*state_,updateFlag_,updateIter_); - // Update full objective function. - conVal_->update(*state_,z,updateFlag_,updateIter_); - // Store state. - if (storage_) { - stateStore_->set(*state_,Constraint::getParameter()); - } - } - } + void solve_state_equation(const Vector &z, Real &tol); /** \brief Given \f$(u,z)\in\mathcal{U}\times\mathcal{Z}\f$ which solves the state equation, solve the adjoint equation \f$c_u(u,z)^*\lambda + c_u(u,z)^*w = 0\f$ for \f$\lambda=\lambda(u,z)\in\mathcal{C}^*\f$. */ - void solve_adjoint_equation(const Vector &w, const Vector &z, Real &tol) { - // Check if adjoint has been computed. - bool isComputed = false; - if (storage_) { - isComputed = adjointStore_->get(*adjoint_,Constraint::getParameter()); - } - // Solve adjoint equation if not done already. - if (!isComputed || !storage_) { - // Evaluate the full gradient wrt u - conVal_->applyAdjointJacobian_1(*dualstate_,w,*state_,z,tol); - // Solve adjoint equation - conRed_->applyInverseAdjointJacobian_1(*adjoint_,*dualstate_,*state_,z,tol); - adjoint_->scale(static_cast(-1)); - // Store adjoint - if (storage_) { - adjointStore_->set(*adjoint_,Constraint::getParameter()); - } - } - } + void solve_adjoint_equation(const Vector &w, const Vector &z, Real &tol); /** \brief Given \f$(u,z)\in\mathcal{U}\times\mathcal{Z}\f$ which solves the state equation and a direction \f$v\in\mathcal{Z}\f$, solve the state senstivity equation \f$c_u(u,z)s + c_z(u,z)v = 0\f$ for \f$s=u_z(z)v\in\mathcal{U}\f$. */ - void solve_state_sensitivity(const Vector &v, const Vector &z, Real &tol) { - // Solve state sensitivity equation - conRed_->applyJacobian_2(*dualadjoint_,v,*state_,z,tol); - dualadjoint_->scale(static_cast(-1)); - conRed_->applyInverseJacobian_1(*state_sens_,*dualadjoint_,*state_,z,tol); - } + void solve_state_sensitivity(const Vector &v, const Vector &z, Real &tol); /** \brief Given \f$(u,z)\in\mathcal{U}\times\mathcal{Z}\f$, the adjoint variable \f$\lambda\in\mathcal{C}^*\f$, and a direction \f$v\in\mathcal{Z}\f$, solve the @@ -108,122 +63,77 @@ class Reduced_Constraint_SimOpt : public Constraint { + c_{zu}(u,z)(\cdot,v)^*\lambda = 0\f$ for \f$p = \lambda_z(u(z),z)v\in\mathcal{C}^*\f$. */ - void solve_adjoint_sensitivity(const Vector &w, const Vector &v, const Vector &z, Real &tol) { - // Evaluate full hessVec in the direction (s,v) - conVal_->applyAdjointHessian_11(*dualstate_,w,*state_sens_,*state_,z,tol); - conVal_->applyAdjointHessian_12(*dualstate1_,w,v,*state_,z,tol); - dualstate_->plus(*dualstate1_); - // Apply adjoint Hessian of constraint - conRed_->applyAdjointHessian_11(*dualstate1_,*adjoint_,*state_sens_,*state_,z,tol); - dualstate_->plus(*dualstate1_); - conRed_->applyAdjointHessian_21(*dualstate1_,*adjoint_,v,*state_,z,tol); - dualstate_->plus(*dualstate1_); - // Solve adjoint sensitivity equation - dualstate_->scale(static_cast(-1)); - conRed_->applyInverseAdjointJacobian_1(*adjoint_sens_,*dualstate_,*state_,z,tol); - } + void solve_adjoint_sensitivity(const Vector &w, const Vector &v, const Vector &z, Real &tol); public: /** \brief Constructor. - @param[in] obj is a pointer to a SimOpt objective function. - @param[in] con is a pointer to a SimOpt equality constraint. + @param[in] conVal is a pointer to a SimOpt constraint, to be evaluated. + @param[in] conRed is a pointer to a SimOpt constraint, to be reduced. @param[in] stateStore is a pointer to a VectorController object. @param[in] state is a pointer to a state space vector, \f$\mathcal{U}\f$. @param[in] control is a pointer to a optimization space vector, \f$\mathcal{Z}\f$. - @param[in] adjoint is a pointer to a dual constraint space vector, \f$\mathcal{C}^*\f$. + @param[in] adjoint is a pointer to a dual constraint space vector, \f$\mathcal{C}_{\text{red}}^*\f$. + @param[in] residual is a pointer to a primal constraint space vector, \f$\mathcal{C}_{\text{val}}\f$. @param[in] storage is a flag whether or not to store computed states and adjoints. @param[in] useFDhessVec is a flag whether or not to use a finite-difference Hessian approximation. */ Reduced_Constraint_SimOpt( - const ROL::Ptr > &conVal, - const ROL::Ptr > &conRed, - const ROL::Ptr > &stateStore, - const ROL::Ptr > &state, - const ROL::Ptr > &control, - const ROL::Ptr > &adjoint, - const ROL::Ptr > &residual, - const bool storage = true, - const bool useFDhessVec = false) - : conVal_(conVal), conRed_(conRed), stateStore_(stateStore), - storage_(storage), useFDhessVec_(useFDhessVec), - updateFlag_(true), updateIter_(0) { - adjointStore_ = ROL::makePtr>(); - state_ = state->clone(); - adjoint_ = adjoint->clone(); - residual_ = residual->clone(); - state_sens_ = state->clone(); - adjoint_sens_ = adjoint->clone(); - dualstate_ = state->dual().clone(); - dualstate1_ = state->dual().clone(); - dualadjoint_ = adjoint->dual().clone(); - dualcontrol_ = control->dual().clone(); - dualresidual_ = residual->dual().clone(); - } + const ROL::Ptr> &conVal, + const ROL::Ptr> &conRed, + const ROL::Ptr> &stateStore, + const ROL::Ptr> &state, + const ROL::Ptr> &control, + const ROL::Ptr> &adjoint, + const ROL::Ptr> &residual, + bool storage = true, + bool useFDhessVec = false); /** \brief Secondary, general constructor for use with dual optimization vector spaces where the user does not define the dual() method. - @param[in] obj is a pointer to a SimOpt objective function. - @param[in] con is a pointer to a SimOpt equality constraint. + @param[in] conVal is a pointer to a SimOpt constraint, to be evaluated. + @param[in] conRed is a pointer to a SimOpt constraint, to be reduced. @param[in] stateStore is a pointer to a VectorController object. @param[in] state is a pointer to a state space vector, \f$\mathcal{U}\f$. @param[in] control is a pointer to a optimization space vector, \f$\mathcal{Z}\f$. - @param[in] adjoint is a pointer to a dual constraint space vector, \f$\mathcal{C}^*\f$. + @param[in] adjoint is a pointer to a dual constraint space vector, \f$\mathcal{C}_{\text{red}}^*\f$. + @param[in] residual is a pointer to a primal constraint space vector, \f$\mathcal{C}_{\text{val}}\f$. @param[in] dualstate is a pointer to a dual state space vector, \f$\mathcal{U}^*\f$. - @param[in] dualadjoint is a pointer to a constraint space vector, \f$\mathcal{C}\f$. + @param[in] dualadjoint is a pointer to a constraint space vector, \f$\mathcal{C}_{\text{red}}\f$. + @param[in] dualresidual is a pointer to a dual constraint space vector, \f$\mathcal{C}_{\text{val}}^*\f$. @param[in] storage is a flag whether or not to store computed states and adjoints. @param[in] useFDhessVec is a flag whether or not to use a finite-difference Hessian approximation. */ Reduced_Constraint_SimOpt( - const ROL::Ptr > &conVal, - const ROL::Ptr > &conRed, - const ROL::Ptr > &stateStore, - const ROL::Ptr > &state, - const ROL::Ptr > &control, - const ROL::Ptr > &adjoint, - const ROL::Ptr > &residual, - const ROL::Ptr > &dualstate, - const ROL::Ptr > &dualcontrol, - const ROL::Ptr > &dualadjoint, - const ROL::Ptr > &dualresidual, - const bool storage = true, - const bool useFDhessVec = false) - : conVal_(conVal), conRed_(conRed), stateStore_(stateStore), - storage_(storage), useFDhessVec_(useFDhessVec), - updateFlag_(true), updateIter_(0) { - adjointStore_ = ROL::makePtr>(); - state_ = state->clone(); - adjoint_ = adjoint->clone(); - residual_ = residual->clone(); - state_sens_ = state->clone(); - adjoint_sens_ = adjoint->clone(); - dualstate_ = dualstate->clone(); - dualstate1_ = dualstate->clone(); - dualadjoint_ = dualadjoint->clone(); - dualcontrol_ = dualcontrol->clone(); - dualresidual_ = dualresidual->clone(); - } + const ROL::Ptr> &conVal, + const ROL::Ptr> &conRed, + const ROL::Ptr> &stateStore, + const ROL::Ptr> &state, + const ROL::Ptr> &control, + const ROL::Ptr> &adjoint, + const ROL::Ptr> &residual, + const ROL::Ptr> &dualstate, + const ROL::Ptr> &dualcontrol, + const ROL::Ptr> &dualadjoint, + const ROL::Ptr> &dualresidual, + bool storage = true, + bool useFDhessVec = false); + + void summarize(std::ostream &stream, const Ptr> &bman = nullPtr) const; + + void reset(); /** \brief Update the SimOpt objective function and equality constraint. */ - void update( const Vector &z, bool flag = true, int iter = -1 ) { - updateFlag_ = flag; - updateIter_ = iter; - stateStore_->constraintUpdate(true); - adjointStore_->constraintUpdate(flag); - } + void update( const Vector &z, bool flag = true, int iter = -1 ); + void update( const Vector &z, UpdateType type, int iter = -1 ); /** \brief Given \f$z\in\mathcal{Z}\f$, evaluate the equality constraint \f$\widehat{c}(z) = c(u(z),z)\f$ where \f$u=u(z)\in\mathcal{U}\f$ solves \f$e(u,z) = 0\f$. */ - void value( Vector &c, const Vector &z, Real &tol ) { - // Solve state equation - solve_state_equation(z,tol); - // Get constraint value - conVal_->value(c,*state_,z,tol); - } + void value( Vector &c, const Vector &z, Real &tol ); /** \brief Given \f$z\in\mathcal{Z}\f$, apply the Jacobian to a vector \f$\widehat{c}'(z)v = c_u(u,z)s + c_z(u,z)v\f$ where @@ -231,61 +141,17 @@ class Reduced_Constraint_SimOpt : public Constraint { \f$e_u(u,z)s+e_z(u,z)v = 0\f$. */ void applyJacobian( Vector &jv, const Vector &v, - const Vector &z, Real &tol ) { - // Solve state equation. - solve_state_equation(z,tol); - // Solve state sensitivity equation. - solve_state_sensitivity(v,z,tol); - // Apply Sim Jacobian to state sensitivity. - conVal_->applyJacobian_1(*residual_,*state_sens_,*state_,z,tol); - // Apply Opt Jacobian to vector. - conVal_->applyJacobian_2(jv,v,*state_,z,tol); - jv.plus(*residual_); - } + const Vector &z, Real &tol ); void applyAdjointJacobian( Vector &ajw, const Vector &w, - const Vector &z, Real &tol ) { - // Solve state equation - solve_state_equation(z,tol); - // Solve adjoint equation - solve_adjoint_equation(w,z,tol); - // Evaluate the full gradient wrt z - conVal_->applyAdjointJacobian_2(*dualcontrol_,w,*state_,z,tol); - // Build gradient - conRed_->applyAdjointJacobian_2(ajw,*adjoint_,*state_,z,tol); - ajw.plus(*dualcontrol_); - } + const Vector &z, Real &tol ); /** \brief Given \f$z\in\mathcal{Z}\f$, evaluate the Hessian of the objective function \f$\nabla^2\widehat{J}(z)\f$ in the direction \f$v\in\mathcal{Z}\f$. */ void applyAdjointHessian( Vector &ahwv, const Vector &w, const Vector &v, const Vector &z, - Real &tol ) { - if ( useFDhessVec_ ) { - Constraint::applyAdjointHessian(ahwv,w,v,z,tol); - } - else { - // Solve state equation - solve_state_equation(z,tol); - // Solve adjoint equation - solve_adjoint_equation(w,z,tol); - // Solve state sensitivity equation - solve_state_sensitivity(v,z,tol); - // Solve adjoint sensitivity equation - solve_adjoint_sensitivity(w,v,z,tol); - // Build hessVec - conRed_->applyAdjointJacobian_2(ahwv,*adjoint_sens_,*state_,z,tol); - conVal_->applyAdjointHessian_21(*dualcontrol_,w,*state_sens_,*state_,z,tol); - ahwv.plus(*dualcontrol_); - conVal_->applyAdjointHessian_22(*dualcontrol_,w,v,*state_,z,tol); - ahwv.plus(*dualcontrol_); - conRed_->applyAdjointHessian_12(*dualcontrol_,*adjoint_,*state_sens_,*state_,z,tol); - ahwv.plus(*dualcontrol_); - conRed_->applyAdjointHessian_22(*dualcontrol_,*adjoint_,v,*state_,z,tol); - ahwv.plus(*dualcontrol_); - } - } + Real &tol ); // For parametrized (stochastic) objective functions and constraints public: @@ -298,4 +164,6 @@ class Reduced_Constraint_SimOpt : public Constraint { } // namespace ROL +#include "ROL_Reduced_Constraint_SimOpt_Def.hpp" + #endif diff --git a/packages/rol/src/function/simopt/ROL_Reduced_Constraint_SimOpt_Def.hpp b/packages/rol/src/function/simopt/ROL_Reduced_Constraint_SimOpt_Def.hpp new file mode 100644 index 000000000000..aec6fef556ab --- /dev/null +++ b/packages/rol/src/function/simopt/ROL_Reduced_Constraint_SimOpt_Def.hpp @@ -0,0 +1,329 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + + +#ifndef ROL_REDUCED_CONSTRAINT_SIMOPT_DEF_H +#define ROL_REDUCED_CONSTRAINT_SIMOPT_DEF_H + +namespace ROL { + +template +void Reduced_Constraint_SimOpt::solve_state_equation(const Vector &z, Real &tol) { + if (!isUpdated_) { + // Update equality constraint with new Opt variable. + if (newUpdate_) conRed_->update_2(z,updateType_,updateIter_); + else conRed_->update_2(z,updateFlag_,updateIter_); + } + // Check if state has been computed. + bool isComputed = storage_ ? stateStore_->get(*state_,Constraint::getParameter()) : false; + // Solve state equation if not done already. + if (!isComputed || !storage_) { + // Solve state equation. + conRed_->solve(*dualadjoint_,*state_,z,tol); + nstat_++; + // Store state. + if (storage_) stateStore_->set(*state_,Constraint::getParameter()); + } + if (!isUpdated_) { + // Update equality constraint with new Sim variable. + if (newUpdate_) conRed_->update_1(*state_,updateType_,updateIter_); + else conRed_->update_1(*state_,updateFlag_,updateIter_); + // Update full objective function. + if (newUpdate_) conVal_->update(*state_,z,updateType_,updateIter_); + else conVal_->update(*state_,z,updateFlag_,updateIter_); + isUpdated_ = true; + } +} + +template +void Reduced_Constraint_SimOpt::solve_adjoint_equation(const Vector &w, const Vector &z, Real &tol) { + // Check if adjoint has been computed. + bool isComputed = storage_ ? adjointStore_->get(*adjoint_,Constraint::getParameter()) : false; + // Solve adjoint equation if not done already. + if (!isComputed || !storage_) { + // Evaluate the full gradient wrt u + conVal_->applyAdjointJacobian_1(*dualstate_,w,*state_,z,tol); + // Solve adjoint equation + conRed_->applyInverseAdjointJacobian_1(*adjoint_,*dualstate_,*state_,z,tol); + adjoint_->scale(static_cast(-1)); + nadjo_++; + // Store adjoint + if (storage_) adjointStore_->set(*adjoint_,Constraint::getParameter()); + } +} + +template +void Reduced_Constraint_SimOpt::solve_state_sensitivity(const Vector &v, const Vector &z, Real &tol) { + // Solve state sensitivity equation + conRed_->applyJacobian_2(*dualadjoint_,v,*state_,z,tol); + dualadjoint_->scale(static_cast(-1)); + conRed_->applyInverseJacobian_1(*state_sens_,*dualadjoint_,*state_,z,tol); + nssen_++; +} + +template +void Reduced_Constraint_SimOpt::solve_adjoint_sensitivity(const Vector &w, const Vector &v, const Vector &z, Real &tol) { + // Evaluate full hessVec in the direction (s,v) + conVal_->applyAdjointHessian_11(*dualstate_,w,*state_sens_,*state_,z,tol); + conVal_->applyAdjointHessian_21(*dualstate1_,w,v,*state_,z,tol); + dualstate_->plus(*dualstate1_); + // Apply adjoint Hessian of constraint + conRed_->applyAdjointHessian_11(*dualstate1_,*adjoint_,*state_sens_,*state_,z,tol); + dualstate_->plus(*dualstate1_); + conRed_->applyAdjointHessian_21(*dualstate1_,*adjoint_,v,*state_,z,tol); + dualstate_->plus(*dualstate1_); + // Solve adjoint sensitivity equation + dualstate_->scale(static_cast(-1)); + conRed_->applyInverseAdjointJacobian_1(*adjoint_sens_,*dualstate_,*state_,z,tol); + nasen_++; +} + +template +Reduced_Constraint_SimOpt::Reduced_Constraint_SimOpt( + const ROL::Ptr> &conVal, + const ROL::Ptr> &conRed, + const ROL::Ptr> &stateStore, + const ROL::Ptr> &state, + const ROL::Ptr> &control, + const ROL::Ptr> &adjoint, + const ROL::Ptr> &residual, + bool storage, + bool useFDhessVec) + : conVal_( conVal ), + conRed_( conRed ), + stateStore_( stateStore ), + adjointStore_( ROL::makePtr>() ), + state_( state->clone() ), + adjoint_( adjoint->clone() ), + residual_( residual->clone() ), + state_sens_( state->clone() ), + adjoint_sens_( adjoint->clone() ), + dualstate_( state->dual().clone() ), + dualstate1_( state->dual().clone() ), + dualadjoint_( adjoint->dual().clone() ), + dualcontrol_( control->dual().clone() ), + dualresidual_( residual->dual().clone() ), + storage_(storage), useFDhessVec_(useFDhessVec), + nupda_(0), nvalu_(0), njaco_(0), najac_(0), nhess_(0), + nstat_(0), nadjo_(0), nssen_(0), nasen_(0), + updateFlag_(true), updateIter_(0), updateType_(UpdateType::Initial), + newUpdate_(false), isUpdated_(true) {} + +template +Reduced_Constraint_SimOpt::Reduced_Constraint_SimOpt( + const ROL::Ptr> &conVal, + const ROL::Ptr> &conRed, + const ROL::Ptr> &stateStore, + const ROL::Ptr> &state, + const ROL::Ptr> &control, + const ROL::Ptr> &adjoint, + const ROL::Ptr> &residual, + const ROL::Ptr> &dualstate, + const ROL::Ptr> &dualcontrol, + const ROL::Ptr> &dualadjoint, + const ROL::Ptr> &dualresidual, + bool storage, + bool useFDhessVec) + : conVal_( conVal ), + conRed_( conRed ), + stateStore_( stateStore ), + adjointStore_( ROL::makePtr>() ), + state_( state->clone() ), + adjoint_( adjoint->clone() ), + residual_( residual->clone() ), + state_sens_( state->clone() ), + adjoint_sens_( adjoint->clone() ), + dualstate_( dualstate->clone() ), + dualstate1_( dualstate->clone() ), + dualadjoint_( dualadjoint->clone() ), + dualcontrol_( dualcontrol->clone() ), + dualresidual_( dualresidual->clone() ), + storage_(storage), useFDhessVec_(useFDhessVec), + nupda_(0), nvalu_(0), njaco_(0), najac_(0), nhess_(0), + nstat_(0), nadjo_(0), nssen_(0), nasen_(0), + updateFlag_(true), updateIter_(0), updateType_(UpdateType::Initial), + newUpdate_(false), isUpdated_(true) {} + +template +void Reduced_Constraint_SimOpt::summarize(std::ostream &stream, const Ptr> &bman) const { + int nupda(0), nvalu(0), njaco(0), najac(0), nhess(0), nstat(0), nadjo(0), nssen(0), nasen(0); + if (bman == nullPtr) { + nupda = nupda_; + nvalu = nvalu_; + njaco = njaco_; + najac = najac_; + nhess = nhess_; + nstat = nstat_; + nadjo = nadjo_; + nssen = nssen_; + nasen = nasen_; + } + else { + auto sumAll = [bman](int val) { + Real global(0), local(val); + bman->sumAll(&local,&global,1); + return static_cast(global); + }; + nupda = sumAll(nupda_); + nvalu = sumAll(nvalu_); + njaco = sumAll(njaco_); + najac = sumAll(najac_); + nhess = sumAll(nhess_); + nstat = sumAll(nstat_); + nadjo = sumAll(nadjo_); + nssen = sumAll(nssen_); + nasen = sumAll(nasen_); + } + stream << std::endl; + stream << std::string(80,'=') << std::endl; + stream << " ROL::Reduced_Objective_SimOpt::summarize" << std::endl; + stream << " Number of calls to update: " << nupda << std::endl; + stream << " Number of calls to value: " << nvalu << std::endl; + stream << " Number of calls to applyJacobian: " << njaco << std::endl; + stream << " Number of calls to applyAdjointJacobian: " << najac << std::endl; + stream << " Number of calls to hessvec: " << nhess << std::endl; + stream << " Number of state solves: " << nstat << std::endl; + stream << " Number of adjoint solves: " << nadjo << std::endl; + stream << " Number of state sensitivity solves: " << nssen << std::endl; + stream << " Number of adjoint sensitivity solves: " << nasen << std::endl; + stream << std::string(80,'=') << std::endl; + stream << std::endl; +} + +template +void Reduced_Constraint_SimOpt::reset() { + nupda_ = 0; nvalu_ = 0; njaco_ = 0; najac_ = 0; nhess_ = 0; + nstat_ = 0; nadjo_ = 0; nssen_ = 0; nasen_ = 0; +} + +template +void Reduced_Constraint_SimOpt::update( const Vector &z, bool flag, int iter ) { + nupda_++; + updateFlag_ = flag; + updateIter_ = iter; + stateStore_->constraintUpdate(true); + adjointStore_->constraintUpdate(flag); +} +template +void Reduced_Constraint_SimOpt::update( const Vector &z, UpdateType type, int iter ) { + nupda_++; + isUpdated_ = false; + newUpdate_ = true; + updateType_ = type; + updateIter_ = iter; + stateStore_->objectiveUpdate(type); + adjointStore_->objectiveUpdate(type); +} + +template +void Reduced_Constraint_SimOpt::value( Vector &c, const Vector &z, Real &tol ) { + nvalu_++; + // Solve state equation + solve_state_equation(z,tol); + // Get constraint value + conVal_->value(c,*state_,z,tol); +} + +template +void Reduced_Constraint_SimOpt::applyJacobian( Vector &jv, const Vector &v, + const Vector &z, Real &tol ) { + njaco_++; + // Solve state equation. + solve_state_equation(z,tol); + // Solve state sensitivity equation. + solve_state_sensitivity(v,z,tol); + // Apply Sim Jacobian to state sensitivity. + conVal_->applyJacobian_1(*residual_,*state_sens_,*state_,z,tol); + // Apply Opt Jacobian to vector. + conVal_->applyJacobian_2(jv,v,*state_,z,tol); + jv.plus(*residual_); +} + +template +void Reduced_Constraint_SimOpt::applyAdjointJacobian( Vector &ajw, const Vector &w, + const Vector &z, Real &tol ) { + najac_++; + // Solve state equation + solve_state_equation(z,tol); + // Solve adjoint equation + solve_adjoint_equation(w,z,tol); + // Evaluate the full gradient wrt z + conVal_->applyAdjointJacobian_2(*dualcontrol_,w,*state_,z,tol); + // Build gradient + conRed_->applyAdjointJacobian_2(ajw,*adjoint_,*state_,z,tol); + ajw.plus(*dualcontrol_); +} + +template +void Reduced_Constraint_SimOpt::applyAdjointHessian( Vector &ahwv, const Vector &w, + const Vector &v, const Vector &z, + Real &tol ) { + nhess_++; + if ( useFDhessVec_ ) { + Constraint::applyAdjointHessian(ahwv,w,v,z,tol); + } + else { + // Solve state equation + solve_state_equation(z,tol); + // Solve adjoint equation + solve_adjoint_equation(w,z,tol); + // Solve state sensitivity equation + solve_state_sensitivity(v,z,tol); + // Solve adjoint sensitivity equation + solve_adjoint_sensitivity(w,v,z,tol); + // Build hessVec + conRed_->applyAdjointJacobian_2(ahwv,*adjoint_sens_,*state_,z,tol); + conVal_->applyAdjointHessian_12(*dualcontrol_,w,*state_sens_,*state_,z,tol); + ahwv.plus(*dualcontrol_); + conVal_->applyAdjointHessian_22(*dualcontrol_,w,v,*state_,z,tol); + ahwv.plus(*dualcontrol_); + conRed_->applyAdjointHessian_12(*dualcontrol_,*adjoint_,*state_sens_,*state_,z,tol); + ahwv.plus(*dualcontrol_); + conRed_->applyAdjointHessian_22(*dualcontrol_,*adjoint_,v,*state_,z,tol); + ahwv.plus(*dualcontrol_); + } +} + +} + +#endif diff --git a/packages/rol/src/oed/utilities/ROL_OED_Timer_Def.hpp b/packages/rol/src/oed/utilities/ROL_OED_Timer_Def.hpp index 71be333b0462..784920709625 100644 --- a/packages/rol/src/oed/utilities/ROL_OED_Timer_Def.hpp +++ b/packages/rol/src/oed/utilities/ROL_OED_Timer_Def.hpp @@ -72,8 +72,8 @@ void Timer::summarize(std::ostream &stream, std::ios_base::fmtflags old(stream.flags()); stream << std::setprecision(6); stream << " " << name_ << std::endl; - stream << std::setw(50) << std::right << "Ave. Time (s)" - << std::setw(25) << std::right << "Ave. #Calls" + stream << std::setw(50) << std::right << "Avg. Time (s)" + << std::setw(25) << std::right << "Avg. #Calls" << std::endl; for (typename std::map::iterator it = count_.begin(); it != count_.end(); ++it) { stream << std::setw(30) << std::right << it->first diff --git a/packages/rol/src/sol/algorithm/ROL_StochasticProblem.hpp b/packages/rol/src/sol/algorithm/ROL_StochasticProblem.hpp index ac35b18455bb..7cca350604b5 100644 --- a/packages/rol/src/sol/algorithm/ROL_StochasticProblem.hpp +++ b/packages/rol/src/sol/algorithm/ROL_StochasticProblem.hpp @@ -33,6 +33,7 @@ template class StochasticProblem : public Problem { private: Ptr> ORIGINAL_obj_; + Ptr> ORIGINAL_nobj_; Ptr> ORIGINAL_xprim_; Ptr> ORIGINAL_xdual_; Ptr> ORIGINAL_bnd_; @@ -46,6 +47,7 @@ class StochasticProblem : public Problem { std::unordered_map statMap_; using Problem::INPUT_obj_; + using Problem::INPUT_nobj_; using Problem::INPUT_xprim_; using Problem::INPUT_xdual_; using Problem::INPUT_bnd_; diff --git a/packages/rol/src/sol/function/ROL_RegressionError.hpp b/packages/rol/src/sol/function/ROL_RegressionError.hpp index bc5e5a341295..3fbc57d9d6d1 100644 --- a/packages/rol/src/sol/function/ROL_RegressionError.hpp +++ b/packages/rol/src/sol/function/ROL_RegressionError.hpp @@ -38,36 +38,23 @@ class RegressionError : public StdObjective { Real value( const std::vector &x, Real &tol ) { checkSize(x); - // Parse Input Vector - std::vector c; c.assign(x.begin()+1,x.end()); - Real c0 = x[0]; - // Parse Data const std::vector data = Objective::getParameter(); - std::vector X; X.assign(data.begin()+1,data.end()); - Real Y = data[0]; - // Build Error - int Xdim = X.size(); - Real val = Y-c0; - for (int i = 0; i < Xdim; ++i) { - val -= c[i]*X[i]; - } + const unsigned dim = x.size(); + Real val = data[0] - x[0]; + for (unsigned i = 1; i < dim; ++i) val -= data[i] * x[i]; return val; } void gradient( std::vector &g, const std::vector &x, Real &tol ) { - checkSize(x); checkSize(g); - // Parse Data + checkSize(g); const std::vector data = Objective::getParameter(); - std::vector X; X.assign(data.begin()+1,data.end()); - // Build Error - int Xdim = X.size(); + const unsigned dim = g.size(); g[0] = static_cast(-1); - for (int i = 0; i < Xdim; ++i) { - g[i+1] = -X[i]; - } + for (unsigned i = 1; i < dim; ++i) g[i] = -data[i]; } void hessVec( std::vector &hv, const std::vector &v, const std::vector &x, Real &tol ) { + checkSize(hv); hv.assign(hv.size(),static_cast(0)); } }; // class RegressionError diff --git a/packages/rol/src/status/ROL_ConstraintStatusTest.hpp b/packages/rol/src/status/ROL_ConstraintStatusTest.hpp index 52876fc9cc85..23c6487687fb 100644 --- a/packages/rol/src/status/ROL_ConstraintStatusTest.hpp +++ b/packages/rol/src/status/ROL_ConstraintStatusTest.hpp @@ -24,10 +24,11 @@ template class ConstraintStatusTest : public StatusTest { private: - Real gtol_; - Real ctol_; - Real stol_; + Real gtol_, gtol0_; + Real ctol_, ctol0_; + Real stol_, stol0_; int max_iter_; + bool use_rel_; public: @@ -39,14 +40,23 @@ class ConstraintStatusTest : public StatusTest { ctol_ = parlist.sublist("Status Test").get("Constraint Tolerance", em6); stol_ = parlist.sublist("Status Test").get("Step Tolerance", em6*gtol_); max_iter_ = parlist.sublist("Status Test").get("Iteration Limit", 100); + use_rel_ = parlist.sublist("Status Test").get("Use Relative Tolerances", false); + gtol0_ = gtol_; + ctol0_ = ctol_; + stol0_ = stol_; } - ConstraintStatusTest( Real gtol = 1e-6, Real ctol = 1e-6, Real stol = 1e-12, int max_iter = 100 ) : - gtol_(gtol), ctol_(ctol), stol_(stol), max_iter_(max_iter) {} + ConstraintStatusTest( Real gtol = 1e-6, Real ctol = 1e-6, Real stol = 1e-12, int max_iter = 100, bool use_rel = false ) : + gtol_(gtol), gtol0_(gtol), ctol_(ctol), ctol0_(ctol), stol_(stol), stol0_(stol), max_iter_(max_iter), use_rel_(use_rel) {} /** \brief Check algorithm status. */ virtual bool check( AlgorithmState &state ) { + if (state.iter==0 && use_rel_) { + gtol_ = gtol0_*std::max(state.gnorm,static_cast(1e-2)); + ctol_ = ctol0_*std::max(state.cnorm,static_cast(1e-2)); + stol_ = stol0_*std::max(std::min(state.gnorm,state.cnorm),static_cast(1e-2)); + } if ( ((state.gnorm > gtol_) || (state.cnorm > ctol_)) && (state.snorm > stol_) && (state.iter < max_iter_) ) { diff --git a/packages/rol/src/status/ROL_StatusTest.hpp b/packages/rol/src/status/ROL_StatusTest.hpp index e13bd1d27f39..36da43cfa750 100644 --- a/packages/rol/src/status/ROL_StatusTest.hpp +++ b/packages/rol/src/status/ROL_StatusTest.hpp @@ -24,8 +24,8 @@ template class StatusTest { private: - Real gtol_; - Real stol_; + Real gtol_, gtol0_; + Real stol_, stol0_; int max_iter_; bool use_rel_; @@ -33,23 +33,29 @@ class StatusTest { virtual ~StatusTest() {} - StatusTest( ROL::ParameterList &parlist ) { + StatusTest( ParameterList &parlist ) { Real em6(1e-6); gtol_ = parlist.sublist("Status Test").get("Gradient Tolerance", em6); stol_ = parlist.sublist("Status Test").get("Step Tolerance", em6*gtol_); max_iter_ = parlist.sublist("Status Test").get("Iteration Limit", 100); use_rel_ = parlist.sublist("Status Test").get("Use Relative Tolerances", false); + gtol0_ = gtol_; + stol0_ = stol_; } StatusTest( Real gtol = 1.e-6, Real stol = 1.e-12, int max_iter = 100, bool use_rel = false ) : - gtol_(gtol), stol_(stol), max_iter_(max_iter), use_rel_(use_rel) {} + gtol_(gtol), gtol0_(gtol), stol_(stol), stol0_(stol), max_iter_(max_iter), use_rel_(use_rel) {} /** \brief Check algorithm status. + + If "Use Relative Tolerances" is set to "true" upon construction, the + gradient and step tolerances are scaled by the norm of the initial + gradient. */ virtual bool check( AlgorithmState &state ) { if (state.iter==0 && use_rel_) { - gtol_ *= state.gnorm; - stol_ *= state.gnorm; + gtol_ = gtol0_*state.gnorm; + stol_ = stol0_*state.gnorm; } if ( (state.gnorm > gtol_) && (state.snorm > stol_) && diff --git a/packages/rol/src/step/ROL_BundleStep.hpp b/packages/rol/src/step/ROL_BundleStep.hpp index 75ef875a2458..2155a5aafb3d 100644 --- a/packages/rol/src/step/ROL_BundleStep.hpp +++ b/packages/rol/src/step/ROL_BundleStep.hpp @@ -106,7 +106,8 @@ class BundleStep : public Step { Real omega = parlist.sublist("Step").sublist("Bundle").get("Locality Measure Coefficient", two); unsigned maxSize = parlist.sublist("Step").sublist("Bundle").get("Maximum Bundle Size", 200); unsigned remSize = parlist.sublist("Step").sublist("Bundle").get("Removal Size for Bundle Update", 2); - if ( parlist.sublist("Step").sublist("Bundle").get("Cutting Plane Solver",0) == 1 ) { + int cps = parlist.sublist("Step").sublist("Bundle").get("Cutting Plane Solver",0); + if (cps) { bundle_ = ROL::makePtr>(maxSize,coeff,omega,remSize); //bundle_ = ROL::makePtr>(maxSize,coeff,omega,remSize); } diff --git a/packages/rol/src/step/ROL_FletcherStep.hpp b/packages/rol/src/step/ROL_FletcherStep.hpp index ebb3c87e1027..c7d517b391e7 100644 --- a/packages/rol/src/step/ROL_FletcherStep.hpp +++ b/packages/rol/src/step/ROL_FletcherStep.hpp @@ -142,7 +142,8 @@ class FletcherStep : public Step { else { step_ = makePtr>(trlist); } - etr_ = StringToETrustRegion(parlist_.sublist("Step").sublist("Trust Region").get("Subproblem Solver", "Truncated CG")); + std::string solverType = parlist_.sublist("Step").sublist("Trust Region").get("Subproblem Solver", "Truncated CG"); + etr_ = StringToETrustRegion(solverType); // Initialize class members g_ = g.clone(); diff --git a/packages/rol/src/step/ROL_LineSearchStep.hpp b/packages/rol/src/step/ROL_LineSearchStep.hpp index 24ae9d1e19f4..2decbde166bd 100644 --- a/packages/rol/src/step/ROL_LineSearchStep.hpp +++ b/packages/rol/src/step/ROL_LineSearchStep.hpp @@ -180,7 +180,8 @@ class LineSearchStep : public Step { // Parse parameter list ROL::ParameterList& Llist = parlist.sublist("Step").sublist("Line Search"); ROL::ParameterList& Glist = parlist.sublist("General"); - econd_ = StringToECurvatureCondition(Llist.sublist("Curvature Condition").get("Type","Strong Wolfe Conditions") ); + std::string condName = Llist.sublist("Curvature Condition").get("Type","Strong Wolfe Conditions"); + econd_ = StringToECurvatureCondition(condName); acceptLastAlpha_ = Llist.get("Accept Last Alpha", false); verbosity_ = Glist.get("Print Verbosity",0); computeObj_ = Glist.get("Recompute Objective Function",false); @@ -203,9 +204,9 @@ class LineSearchStep : public Step { d_ = x.clone(); // Initialize unglobalized step - ROL::ParameterList& list - = parlist_.sublist("Step").sublist("Line Search").sublist("Descent Method"); - EDescent edesc = StringToEDescent(list.get("Type","Quasi-Newton Method")); + ROL::ParameterList& list = parlist_.sublist("Step").sublist("Line Search").sublist("Descent Method"); + std::string descentName = list.get("Type","Quasi-Newton Method"); + EDescent edesc = StringToEDescent(descentName); if (bnd.isActivated()) { switch(edesc) { case DESCENT_STEEPEST: { diff --git a/packages/rol/src/step/ROL_PrimalDualActiveSetStep.hpp b/packages/rol/src/step/ROL_PrimalDualActiveSetStep.hpp index 5447c889a34f..ed90729600ab 100644 --- a/packages/rol/src/step/ROL_PrimalDualActiveSetStep.hpp +++ b/packages/rol/src/step/ROL_PrimalDualActiveSetStep.hpp @@ -260,7 +260,8 @@ class PrimalDualActiveSetStep : public Step { gtol_ = parlist.sublist("Step").sublist("Primal Dual Active Set").get("Relative Gradient Tolerance",oem6); scale_ = parlist.sublist("Step").sublist("Primal Dual Active Set").get("Dual Scaling", one); // Build secant object - esec_ = StringToESecant(parlist.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS")); + std::string secantType = parlist.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS"); + esec_ = StringToESecant(secantType); useSecantHessVec_ = parlist.sublist("General").sublist("Secant").get("Use as Hessian", false); useSecantPrecond_ = parlist.sublist("General").sublist("Secant").get("Use as Preconditioner", false); if ( useSecantHessVec_ || useSecantPrecond_ ) { diff --git a/packages/rol/src/step/ROL_ProjectedSecantStep.hpp b/packages/rol/src/step/ROL_ProjectedSecantStep.hpp index 9b14c2dec92f..ba6a79fd1e5e 100644 --- a/packages/rol/src/step/ROL_ProjectedSecantStep.hpp +++ b/packages/rol/src/step/ROL_ProjectedSecantStep.hpp @@ -59,7 +59,8 @@ class ProjectedSecantStep : public Step { verbosity_ = parlist.sublist("General").get("Print Verbosity",0); // Initialize secant object if ( secant == ROL::nullPtr ) { - esec_ = StringToESecant(parlist.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS")); + std::string secantType = parlist.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS"); + esec_ = StringToESecant(secantType); secant_ = SecantFactory(parlist); } } diff --git a/packages/rol/src/step/ROL_TrustRegionStep.hpp b/packages/rol/src/step/ROL_TrustRegionStep.hpp index 64e5c352d883..86472b0e2e75 100644 --- a/packages/rol/src/step/ROL_TrustRegionStep.hpp +++ b/packages/rol/src/step/ROL_TrustRegionStep.hpp @@ -156,16 +156,21 @@ class TrustRegionStep : public Step { // Inexactness Information ROL::ParameterList &glist = parlist.sublist("General"); useInexact_.clear(); - useInexact_.push_back(glist.get("Inexact Objective Function", false)); - useInexact_.push_back(glist.get("Inexact Gradient", false)); - useInexact_.push_back(glist.get("Inexact Hessian-Times-A-Vector", false)); + bool inexactObj = glist.get("Inexact Objective Function", false); + bool inexactGrad = glist.get("Inexact Gradient", false); + bool inexactHessVec = glist.get("Inexact Hessian-Times-A-Vector", false); + useInexact_.push_back(inexactObj ); + useInexact_.push_back(inexactGrad ); + useInexact_.push_back(inexactHessVec); // Trust-Region Inexactness Parameters ROL::ParameterList &ilist = list.sublist("Inexact").sublist("Gradient"); scale0_ = ilist.get("Tolerance Scaling", static_cast(0.1)); scale1_ = ilist.get("Relative Tolerance", static_cast(2)); // Initialize Trust Region Subproblem Solver Object - etr_ = StringToETrustRegion(list.get("Subproblem Solver", "Dogleg")); - TRmodel_ = StringToETrustRegionModel(list.get("Subproblem Model", "Kelley-Sachs")); + std::string solverName = list.get("Subproblem Solver", "Dogleg"); + etr_ = StringToETrustRegion(solverName); + std::string modelName = list.get("Subproblem Model", "Kelley-Sachs"); + TRmodel_ = StringToETrustRegionModel(modelName); useProjectedGrad_ = glist.get("Projected Gradient Criticality Measure", false); trustRegion_ = TrustRegionFactory(parlist); // Scale for epsilon active sets @@ -294,7 +299,8 @@ class TrustRegionStep : public Step { parseParameterList(parlist); // Create secant object ROL::ParameterList &glist = parlist.sublist("General"); - esec_ = StringToESecant(glist.sublist("Secant").get("Type","Limited-Memory BFGS")); + std::string secantName = glist.sublist("Secant").get("Type","Limited-Memory BFGS"); + esec_ = StringToESecant(secantName); useSecantPrecond_ = glist.sublist("Secant").get("Use as Preconditioner", false); useSecantHessVec_ = glist.sublist("Secant").get("Use as Hessian", false); secant_ = SecantFactory(parlist); diff --git a/packages/rol/src/step/krylov/ROL_BiCGSTAB.hpp b/packages/rol/src/step/krylov/ROL_BiCGSTAB.hpp new file mode 100644 index 000000000000..5e96b62d90ca --- /dev/null +++ b/packages/rol/src/step/krylov/ROL_BiCGSTAB.hpp @@ -0,0 +1,147 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +#ifndef ROL_BICGSTAB_H +#define ROL_BICGSTAB_H + +/** \class ROL::ConjugateGradients + \brief Provides definitions of the Conjugate Gradient solver. +*/ + +#include "ROL_Krylov.hpp" +#include "ROL_Types.hpp" + +namespace ROL { + +template +class BiCGSTAB : public Krylov { + + bool isInitialized_; + const bool useInexact_; + Ptr> r_, r1_, p_, v_, s_, t_, h_, y_, z_; + +public: + BiCGSTAB(Real absTol = 1.e-4, Real relTol = 1.e-2, unsigned maxit = 100, bool useInexact = false) + : Krylov(absTol,relTol,maxit), isInitialized_(false), useInexact_(useInexact) {} + + BiCGSTAB(ParameterList &parlist, bool useInexact = false) + : Krylov(parlist), isInitialized_(false), useInexact_(useInexact) {} + + Real run( Vector &x, LinearOperator &A, const Vector &b, LinearOperator &M, + int &iter, int &flag ) { + if ( !isInitialized_ ) { + r_ = b.clone(); r1_ = b.clone(); p_ = b.clone(); + v_ = b.clone(); s_ = b.clone(); t_ = b.clone(); + h_ = x.clone(); y_ = x.clone(); z_ = x.clone(); + isInitialized_ = true; + } + + Real rho(1), rho1(1), alpha(1), beta(0), omega(1); + Real rnorm = b.norm(); + Real itol = std::sqrt(ROL_EPSILON()); + const Real rtol = std::min(Krylov::getAbsoluteTolerance(),Krylov::getRelativeTolerance()*rnorm); + if (rnorm <= rtol) return rnorm; + + x.zero(); + v_->zero(); + p_->zero(); + r_->set(b); + r1_->set(*r_); + + iter = 0; + flag = 0; + + for (iter = 0; iter < (int)Krylov::getMaximumIteration(); iter++) { + rho1 = r_->dot(*r1_); + beta = (rho1/rho)*(alpha/omega); + p_->axpy(-omega,*v_); + p_->scale(beta); + p_->plus(*r_); + + if ( useInexact_ ) + itol = rtol/((Real)Krylov::getMaximumIteration() * rnorm); + M.applyInverse(*y_, *p_, itol); + A.apply(*v_, *y_, itol); + + alpha = rho1 / v_->dot(*r1_); + h_->set(x); + h_->axpy(alpha,*y_); + s_->set(*r_); + s_->axpy(-alpha,*v_); + + rnorm = s_->norm(); + if (rnorm <= rtol) { + x.set(*h_); + break; + } + + if ( useInexact_ ) + itol = rtol/((Real)Krylov::getMaximumIteration() * rnorm); + M.applyInverse(*z_, *s_, itol); + A.apply(*t_, *z_, itol); + + omega = t_->dot(*s_) / t_->dot(*t_); + x.set(*h_); + x.axpy(omega,*z_); + r_->set(*s_); + r_->axpy(-omega,*t_); + + rnorm = r_->norm(); + if (rnorm <= rtol) break; + + rho = rho1; + } + if (iter == (int)Krylov::getMaximumIteration()) { + flag = 1; + } + else { + iter++; + } + return rnorm; + } +}; + + +} + +#endif diff --git a/packages/rol/src/step/krylov/ROL_KrylovFactory.hpp b/packages/rol/src/step/krylov/ROL_KrylovFactory.hpp index a96421e1db4f..10f774dcbada 100644 --- a/packages/rol/src/step/krylov/ROL_KrylovFactory.hpp +++ b/packages/rol/src/step/krylov/ROL_KrylovFactory.hpp @@ -17,6 +17,7 @@ #include "ROL_ConjugateResiduals.hpp" #include "ROL_GMRES.hpp" #include "ROL_MINRES.hpp" +#include "ROL_BiCGSTAB.hpp" namespace ROL { /** \enum ROL::EKrylov @@ -26,6 +27,7 @@ namespace ROL { \arg CR Conjugate Residual Method \arg GMRES Generalized Minimum Residual Method \arg MINRES Minimum Residual Method + \arg BICGSTAB Stablized Bi-Conjugate Gradient Method \arg USERDEFINED User defined Krylov method \arg LAST Dummy type */ @@ -34,6 +36,7 @@ namespace ROL { KRYLOV_CR, KRYLOV_GMRES, KRYLOV_MINRES, + KRYLOV_BICGSTAB, KRYLOV_USERDEFINED, KRYLOV_LAST }; @@ -45,6 +48,7 @@ namespace ROL { case KRYLOV_CR: retString = "Conjugate Residuals"; break; case KRYLOV_GMRES: retString = "GMRES"; break; case KRYLOV_MINRES: retString = "MINRES"; break; + case KRYLOV_BICGSTAB: retString = "BiCGSTAB"; break; case KRYLOV_USERDEFINED: retString = "User Defined"; break; case KRYLOV_LAST: retString = "Last Type (Dummy)"; break; default: retString = "INVALID EKrylov"; @@ -58,9 +62,11 @@ namespace ROL { \return 1 if the argument is a valid Secant; 0 otherwise. */ inline int isValidKrylov(EKrylov type){ - return( (type == KRYLOV_CG) || - (type == KRYLOV_CR) || - (type == KRYLOV_GMRES) || + return( (type == KRYLOV_CG) || + (type == KRYLOV_CR) || + (type == KRYLOV_GMRES) || + (type == KRYLOV_MINRES) || + (type == KRYLOV_BICGSTAB) || (type == KRYLOV_USERDEFINED) ); } @@ -101,17 +107,19 @@ namespace ROL { parlist.sublist("General").sublist("Krylov").get("Type","GMRES")); Real absTol = parlist.sublist("General").sublist("Krylov").get("Absolute Tolerance", em4); Real relTol = parlist.sublist("General").sublist("Krylov").get("Relative Tolerance", em2); - int maxit = parlist.sublist("General").sublist("Krylov").get("Iteration Limit", 20); + int maxit = parlist.sublist("General").sublist("Krylov").get("Iteration Limit", 20); bool inexact = parlist.sublist("General").get("Inexact Hessian-Times-A-Vector",false); switch(ekv) { case KRYLOV_CR: return makePtr>(absTol,relTol,maxit,inexact); case KRYLOV_CG: return makePtr>(absTol,relTol,maxit,inexact); - case KRYLOV_MINRES: - return makePtr>(absTol,relTol,maxit,inexact); case KRYLOV_GMRES: return makePtr>(parlist); + case KRYLOV_MINRES: + return makePtr>(absTol,relTol,maxit,inexact); + case KRYLOV_BICGSTAB: + return makePtr>(absTol,relTol,maxit,inexact); default: return nullPtr; } diff --git a/packages/rol/src/step/krylov/ROL_MINRES.hpp b/packages/rol/src/step/krylov/ROL_MINRES.hpp index 264d3d3a0749..86b17cd9e975 100644 --- a/packages/rol/src/step/krylov/ROL_MINRES.hpp +++ b/packages/rol/src/step/krylov/ROL_MINRES.hpp @@ -25,8 +25,6 @@ namespace ROL { namespace details { -using namespace std; - template class MINRES : public Krylov { @@ -39,8 +37,8 @@ class MINRES : public Krylov { Real resnorm_; int maxiter_; bool useInexact_; - array H_; - array rhs_; + std::array H_; + std::array rhs_; VectorCloneMap clones_; @@ -51,23 +49,23 @@ class MINRES : public Krylov { if( b == zero ) { c = ( a >= zero ? one : -one ); s = zero; - r = abs(a); + r = std::abs(a); } else if( a == zero ) { c = zero; s = ( b >= zero ? one : -one ); - r = abs(b); + r = std::abs(b); } - else if( abs(a) > abs(b) ) { + else if( std::abs(a) > std::abs(b) ) { auto t = b/a; - auto u = copysign(sqrt(one+t*t),a); + auto u = std::copysign(std::sqrt(one+t*t),a); c = one/u; s = c*t; r = a*u; } else { auto t = a/b; - auto u = copysign(sqrt(one+t*t),b); + auto u = std::copysign(std::sqrt(one+t*t),b); s = 1/u; c = s*t; r = b*u; @@ -93,8 +91,8 @@ class MINRES : public Krylov { Real c_prev{0}, s_prev{0}, c_curr{0}, s_curr{0}, c_next{0}, s_next{0}; resnorm_ = v_curr->norm(); - Real rtol = min(Krylov::getAbsoluteTolerance(),Krylov::getRelativeTolerance()*resnorm_); - Real itol = sqrt(ROL_EPSILON()); + Real rtol = std::min(Krylov::getAbsoluteTolerance(),Krylov::getRelativeTolerance()*resnorm_); + Real itol = std::sqrt(ROL_EPSILON()); for( auto &e: H_ ) e = 0; @@ -162,7 +160,7 @@ class MINRES : public Krylov { H_[1] = H_[3]; - resnorm_ = abs( rhs_[1] ); + resnorm_ = std::abs( rhs_[1] ); } // for (iter) diff --git a/packages/rol/src/step/linesearch/ROL_Brents.hpp b/packages/rol/src/step/linesearch/ROL_Brents.hpp index 64af1e33f2e6..dd0ce90a9362 100644 --- a/packages/rol/src/step/linesearch/ROL_Brents.hpp +++ b/packages/rol/src/step/linesearch/ROL_Brents.hpp @@ -36,8 +36,7 @@ class Brents : public LineSearch { // Constructor Brents( ROL::ParameterList &parlist ) : LineSearch(parlist) { Real oem10(1.e-10); - ROL::ParameterList &list - = parlist.sublist("Step").sublist("Line Search").sublist("Line-Search Method").sublist("Brent's"); + ROL::ParameterList &list = parlist.sublist("Step").sublist("Line Search").sublist("Line-Search Method").sublist("Brent's"); tol_ = list.get("Tolerance",oem10); niter_ = list.get("Iteration Limit",1000); test_ = list.get("Run Test Upon Initialization",true); diff --git a/packages/rol/src/step/linesearch/ROL_LineSearch.hpp b/packages/rol/src/step/linesearch/ROL_LineSearch.hpp index 9f6901d371c2..51b1c8c35b60 100644 --- a/packages/rol/src/step/linesearch/ROL_LineSearch.hpp +++ b/packages/rol/src/step/linesearch/ROL_LineSearch.hpp @@ -60,8 +60,11 @@ class LineSearch { LineSearch( ROL::ParameterList &parlist ) : eps_(0) { Real one(1), p9(0.9), p6(0.6), p4(0.4), oem4(1.e-4), zero(0); // Enumerations - edesc_ = StringToEDescent(parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").get("Type","Quasi-Newton Method")); - econd_ = StringToECurvatureCondition(parlist.sublist("Step").sublist("Line Search").sublist("Curvature Condition").get("Type","Strong Wolfe Conditions")); + std::string descentName = parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").get("Type","Quasi-Newton Method"); + edesc_ = StringToEDescent(descentName); + + std::string condName = parlist.sublist("Step").sublist("Line Search").sublist("Curvature Condition").get("Type","Strong Wolfe Conditions"); + econd_ = StringToECurvatureCondition(condName); // Linesearch Parameters alpha0_ = parlist.sublist("Step").sublist("Line Search").get("Initial Step Size",one); alpha0bnd_ = parlist.sublist("Step").sublist("Line Search").get("Lower Bound for Initial Step Size",one); diff --git a/packages/rol/src/step/linesearch/ROL_ScalarMinimizationLineSearch.hpp b/packages/rol/src/step/linesearch/ROL_ScalarMinimizationLineSearch.hpp index 43a19ac88121..519aba6fbff0 100644 --- a/packages/rol/src/step/linesearch/ROL_ScalarMinimizationLineSearch.hpp +++ b/packages/rol/src/step/linesearch/ROL_ScalarMinimizationLineSearch.hpp @@ -184,9 +184,10 @@ class ScalarMinimizationLineSearch : public LineSearch { sf_ = sf; - + // Status test for line search - econd_ = StringToECurvatureCondition(list0.sublist("Curvature Condition").get("Type","Strong Wolfe Conditions")); + std::string condName = list0.sublist("Curvature Condition").get("Type","Strong Wolfe Conditions"); + econd_ = StringToECurvatureCondition(condName); max_nfval_ = list0.get("Function Evaluation Limit",20); c1_ = list0.get("Sufficient Decrease Tolerance",oem4); c2_ = list0.sublist("Curvature Condition").get("General Parameter",p9); @@ -199,7 +200,8 @@ class ScalarMinimizationLineSearch : public LineSearch { c1_ = oem4; c2_ = p9; } - EDescent edesc = StringToEDescent(list0.sublist("Descent Method").get("Type","Quasi-Newton Method")); + std::string descentName = list0.sublist("Descent Method").get("Type","Quasi-Newton Method"); + EDescent edesc = StringToEDescent(descentName); if ( edesc == DESCENT_NONLINEARCG ) { c2_ = p4; c3_ = std::min(one-c2_,c3_); diff --git a/packages/rol/src/step/secant/ROL_SecantFactory.hpp b/packages/rol/src/step/secant/ROL_SecantFactory.hpp index 14ff6b175290..5c30bc3a9e82 100644 --- a/packages/rol/src/step/secant/ROL_SecantFactory.hpp +++ b/packages/rol/src/step/secant/ROL_SecantFactory.hpp @@ -35,8 +35,8 @@ namespace ROL { template inline ROL::Ptr > SecantFactory( ROL::ParameterList &parlist, ESecantMode mode = SECANTMODE_BOTH ) { - ESecant esec = StringToESecant( - parlist.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS") ); + std::string secantName = parlist.sublist("General").sublist("Secant").get("Type","Limited-Memory BFGS"); + ESecant esec = StringToESecant(secantName); int L = parlist.sublist("General").sublist("Secant").get("Maximum Storage",10); int BB = parlist.sublist("General").sublist("Secant").get("Barzilai-Borwein",1); bool uds = parlist.sublist("General").sublist("Secant").get("Use Default Scaling",true); diff --git a/packages/rol/src/step/trustregion/ROL_TruncatedCG.hpp b/packages/rol/src/step/trustregion/ROL_TruncatedCG.hpp index 090ea2a1dc7e..817ac90dcecf 100644 --- a/packages/rol/src/step/trustregion/ROL_TruncatedCG.hpp +++ b/packages/rol/src/step/trustregion/ROL_TruncatedCG.hpp @@ -79,7 +79,7 @@ class TruncatedCG : public TrustRegion { model.precond(*v_,*g_,s,tol); // Initialize basis vector p_->set(*v_); p_->scale(-one); - Real pnorm2 = v_->dot(g_->dual()); + Real pnorm2 = g_->apply(*v_); if ( pnorm2 <= zero ) { iflag = 4; iter = 0; @@ -88,65 +88,57 @@ class TruncatedCG : public TrustRegion { // Initialize scalar storage iter = 0; iflag = 0; Real kappa(0), beta(0), sigma(0), alpha(0), tmp(0), sMp(0); - Real gv = v_->dot(g_->dual()); + Real gv = g_->apply(*v_); pRed_ = zero; // Iterate CG for (iter = 0; iter < maxit_; iter++) { // Apply Hessian to direction p model.hessVec(*Hp_,*p_,s,tol); // Check positivity of Hessian - kappa = p_->dot(Hp_->dual()); + kappa = Hp_->apply(*p_); if (kappa <= zero) { sigma = (-sMp+sqrt(sMp*sMp+pnorm2*(del*del-snorm2)))/pnorm2; s.axpy(sigma,*p_); - iflag = 2; + iflag = 2; break; } // Update step alpha = gv/kappa; - s_->set(s); + s_->set(s); s_->axpy(alpha,*p_); s1norm2 = snorm2 + two*alpha*sMp + alpha*alpha*pnorm2; // Check if step exceeds trust region radius if (s1norm2 >= del*del) { sigma = (-sMp+sqrt(sMp*sMp+pnorm2*(del*del-snorm2)))/pnorm2; s.axpy(sigma,*p_); - iflag = 3; + iflag = 3; break; } // Update model predicted reduction pRed_ += half*alpha*gv; // Set step to temporary step and store norm s.set(*s_); - snorm2 = s1norm2; + snorm2 = s1norm2; // Check for convergence g_->axpy(alpha,*Hp_); normg = g_->norm(); - if (normg < gtol) { - break; - } + if (normg < gtol) break; // Preconditioned updated (projected) gradient vector model.precond(*v_,*g_,s,tol); - tmp = gv; - gv = v_->dot(g_->dual()); - beta = gv/tmp; + tmp = gv; + gv = g_->apply(*v_); + beta = gv/tmp; // Update basis vector p_->scale(beta); p_->axpy(-one,*v_); sMp = beta*(sMp+alpha*pnorm2); - pnorm2 = gv + beta*beta*pnorm2; + pnorm2 = gv + beta*beta*pnorm2; } // Update model predicted reduction - if (iflag > 0) { - pRed_ += sigma*(gv-half*sigma*kappa); - } + if (iflag > 0) pRed_ += sigma*(gv-half*sigma*kappa); // Check iteration count - if (iter == maxit_) { - iflag = 1; - } - if (iflag != 1) { - iter++; - } + if (iter == maxit_) iflag = 1; + if (iflag != 1) iter++; // Update norm of step and update model predicted reduction model.primalTransform(*s_,s); s.set(*s_); diff --git a/packages/rol/src/step/trustregion/ROL_TrustRegion.hpp b/packages/rol/src/step/trustregion/ROL_TrustRegion.hpp index d8b770c34028..05ec1f1719b9 100644 --- a/packages/rol/src/step/trustregion/ROL_TrustRegion.hpp +++ b/packages/rol/src/step/trustregion/ROL_TrustRegion.hpp @@ -60,7 +60,8 @@ class TrustRegion { : pRed_(0), ftol_old_(ROL_OVERFLOW()), cnt_(0), verbosity_(0) { // Trust-Region Parameters ROL::ParameterList list = parlist.sublist("Step").sublist("Trust Region"); - TRmodel_ = StringToETrustRegionModel(list.get("Subproblem Model", "Kelley-Sachs")); + std::string modelName = list.get("Subproblem Model", "Kelley-Sachs"); + TRmodel_ = StringToETrustRegionModel(modelName); eta0_ = list.get("Step Acceptance Threshold", static_cast(0.05)); eta1_ = list.get("Radius Shrinking Threshold", static_cast(0.05)); eta2_ = list.get("Radius Growing Threshold", static_cast(0.9)); @@ -73,9 +74,13 @@ class TrustRegion { // General Inexactness Information ROL::ParameterList &glist = parlist.sublist("General"); useInexact_.clear(); - useInexact_.push_back(glist.get("Inexact Objective Function", false)); - useInexact_.push_back(glist.get("Inexact Gradient", false)); - useInexact_.push_back(glist.get("Inexact Hessian-Times-A-Vector", false)); + + bool inexactObj = glist.get("Inexact Objective Function", false); + bool inexactGrad = glist.get("Inexact Gradient", false); + bool inexactHessVec = glist.get("Inexact Hessian-Times-A-Vector", false); + useInexact_.push_back(inexactObj ); + useInexact_.push_back(inexactGrad ); + useInexact_.push_back(inexactHessVec); // Inexact Function Evaluation Information ROL::ParameterList &ilist = list.sublist("Inexact").sublist("Value"); scale_ = ilist.get("Tolerance Scaling", static_cast(1.e-1)); diff --git a/packages/rol/src/utils/function_bindings/ROL_Constraint_CheckInterface.hpp b/packages/rol/src/utils/function_bindings/ROL_Constraint_CheckInterface.hpp index 61a7809a1076..d3c2e62804ac 100644 --- a/packages/rol/src/utils/function_bindings/ROL_Constraint_CheckInterface.hpp +++ b/packages/rol/src/utils/function_bindings/ROL_Constraint_CheckInterface.hpp @@ -18,7 +18,6 @@ namespace ROL { namespace details { -using namespace std; namespace ph = std::placeholders; template @@ -34,28 +33,28 @@ class Constraint_CheckInterface { con_(con), tol_(sqrt(ROL_EPSILON())) {} f_update_t update() { - return bind( (void(Constraint::*)(const Vector&,bool,int))&Constraint::update, &con_, ph::_1, true, 0 ); + return std::bind( (void(Constraint::*)(const Vector&,bool,int))&Constraint::update, &con_, ph::_1, true, 0 ); } f_vector_t value() { - return bind( &Constraint::value, &con_, ph::_1, ph::_2, tol_); + return std::bind( &Constraint::value, &con_, ph::_1, ph::_2, tol_); } f_dderiv_t jacobian() { - return bind( &Constraint::applyJacobian, &con_, ph::_1, ph::_2, ph::_3, tol_); + return std::bind( &Constraint::applyJacobian, &con_, ph::_1, ph::_2, ph::_3, tol_); } // Provide a vector in the dual constraint space f_dderiv_t adjointJacobian( ) { - return bind( static_cast::*) + return std::bind( static_cast::*) ( V&, const V&, const V&, Real& )> (&Constraint::applyAdjointJacobian), &con_, ph::_1, ph::_2, ph::_3, tol_); } f_dderiv_t adjointHessian( const V& l ) { - return bind( &Constraint::applyAdjointHessian, &con_, ph::_1, cref(l), ph::_2, ph::_3, tol_); + return std::bind( &Constraint::applyAdjointHessian, &con_, ph::_1, std::cref(l), ph::_2, ph::_3, tol_); } diff --git a/packages/rol/src/utils/function_bindings/ROL_FiniteDifference.hpp b/packages/rol/src/utils/function_bindings/ROL_FiniteDifference.hpp index e79f53fa7879..2bbc5625caa5 100644 --- a/packages/rol/src/utils/function_bindings/ROL_FiniteDifference.hpp +++ b/packages/rol/src/utils/function_bindings/ROL_FiniteDifference.hpp @@ -28,8 +28,6 @@ namespace ROL { namespace details { -using namespace std; - template class FiniteDifference { public: diff --git a/packages/rol/src/utils/function_bindings/ROL_FiniteDifferenceDef.hpp b/packages/rol/src/utils/function_bindings/ROL_FiniteDifferenceDef.hpp index dda714a52e1e..5e6afb265f4b 100644 --- a/packages/rol/src/utils/function_bindings/ROL_FiniteDifferenceDef.hpp +++ b/packages/rol/src/utils/function_bindings/ROL_FiniteDifferenceDef.hpp @@ -11,13 +11,10 @@ #ifndef ROL_FINITEDIFFERENCEDEF_HPP #define ROL_FINITEDIFFERENCEDEF_HPP -#include - namespace ROL { namespace details { -using namespace std; using ::ROL::Finite_Difference_Arrays::shifts; using ::ROL::Finite_Difference_Arrays::weights; diff --git a/packages/rol/src/utils/function_bindings/ROL_FunctionBindings.hpp b/packages/rol/src/utils/function_bindings/ROL_FunctionBindings.hpp index ba569805374d..75b01ac96712 100644 --- a/packages/rol/src/utils/function_bindings/ROL_FunctionBindings.hpp +++ b/packages/rol/src/utils/function_bindings/ROL_FunctionBindings.hpp @@ -18,32 +18,31 @@ namespace ROL { namespace details { -using namespace std; namespace ph = std::placeholders; template -using f_update_t = function& )>; +using f_update_t = std::function& )>; template -using f_scalar_t = function& )>; +using f_scalar_t = std::function& )>; template -using f_vector_t = function&, const Vector& )>; +using f_vector_t = std::function&, const Vector& )>; template -using f_dderiv_t = function&, const Vector&, const Vector& )>; +using f_dderiv_t = std::function&, const Vector&, const Vector& )>; template -using f_solve_t = function &, Vector & )>; +using f_solve_t = std::function &, Vector & )>; template inline f_vector_t fix_direction( f_dderiv_t& f, const Vector& v ) { - return bind( f, ph::_1, cref(v), ph::_2 ); + return std::bind( f, ph::_1, std::cref(v), ph::_2 ); } template inline f_vector_t fix_position( f_dderiv_t& f, const Vector& x ) { - return bind( f, ph::_1, ph::_2, cref(x) ); + return std::bind( f, ph::_1, ph::_2, std::cref(x) ); } } // namespace details diff --git a/packages/rol/src/utils/function_bindings/ROL_Objective_CheckInterface.hpp b/packages/rol/src/utils/function_bindings/ROL_Objective_CheckInterface.hpp index d90a2f9404d1..2b336b50da26 100644 --- a/packages/rol/src/utils/function_bindings/ROL_Objective_CheckInterface.hpp +++ b/packages/rol/src/utils/function_bindings/ROL_Objective_CheckInterface.hpp @@ -17,7 +17,6 @@ namespace ROL { namespace details { -using namespace std; namespace ph = std::placeholders; template @@ -33,19 +32,19 @@ class Objective_CheckInterface { obj_(obj), tol_(sqrt(ROL_EPSILON())) {} f_update_t update() { - return bind( (void(Objective::*)(const Vector&,bool,int))&Objective::update, &obj_, ph::_1, true, 0 ); + return std::bind( (void(Objective::*)(const Vector&,bool,int))&Objective::update, &obj_, ph::_1, true, 0 ); } f_scalar_t value() { - return bind( &Objective::value, &obj_, ph::_1, tol_); + return std::bind( &Objective::value, &obj_, ph::_1, tol_); } f_vector_t gradient() { - return bind( &Objective::gradient, &obj_, ph::_1, ph::_2, tol_); + return std::bind( &Objective::gradient, &obj_, ph::_1, ph::_2, tol_); } f_dderiv_t hessVec() { - return bind( &Objective::hessVec, &obj_, ph::_1, ph::_2, ph::_3, tol_); + return std::bind( &Objective::hessVec, &obj_, ph::_1, ph::_2, ph::_3, tol_); } }; // Objective_CheckInterface diff --git a/packages/rol/src/utils/function_bindings/ROL_Objective_SimOpt_CheckInterfaceDef.hpp b/packages/rol/src/utils/function_bindings/ROL_Objective_SimOpt_CheckInterfaceDef.hpp index e20342976506..910214200fee 100644 --- a/packages/rol/src/utils/function_bindings/ROL_Objective_SimOpt_CheckInterfaceDef.hpp +++ b/packages/rol/src/utils/function_bindings/ROL_Objective_SimOpt_CheckInterfaceDef.hpp @@ -18,7 +18,6 @@ namespace ROL { namespace details { -using namespace std; namespace ph = std::placeholders; template @@ -35,24 +34,24 @@ class Objective_SimOpt_CheckInterface { // Takes a Vector_SimOpt f_update_t update() { - return bind( &Objective_SimOpt::update, &obj_, ph::_1, true, 0 ); + return std::bind( &Objective_SimOpt::update, &obj_, ph::_1, true, 0 ); } // Takes a Vector_SimOpt f_scalar_t value() { - return bind( &Objective_SimOpt::value, &obj_, ph::_1, tol_); + return std::bind( &Objective_SimOpt::value, &obj_, ph::_1, tol_); } f_vector_t gradient_1( const V& z ) { - return bind( &Objective_SimOpt::gradient_1, &obj_, ph::_1, ph::_2, cref(z), tol_); + return std::bind( &Objective_SimOpt::gradient_1, &obj_, ph::_1, ph::_2, std::cref(z), tol_); } f_vector_t gradient_2( const V& u ) { - return bind( &Objective_SimOpt::gradient_2, &obj_, ph::_1, cref(u), ph::_2, tol_); + return std::bind( &Objective_SimOpt::gradient_2, &obj_, ph::_1, std::cref(u), ph::_2, tol_); } f_dderiv_t hessVec_11( const ) { - return bind( &Objective_SimOpt::hessVec, &obj_, ph::_1, ph::_2, ph::_3, tol_); + return std::bind( &Objective_SimOpt::hessVec, &obj_, ph::_1, ph::_2, ph::_3, tol_); } }; // Objective_CheckInterface diff --git a/packages/rol/src/utils/function_bindings/ROL_ValidateFunction.hpp b/packages/rol/src/utils/function_bindings/ROL_ValidateFunction.hpp index 8330ac895fc3..a2ed8d54ed04 100644 --- a/packages/rol/src/utils/function_bindings/ROL_ValidateFunction.hpp +++ b/packages/rol/src/utils/function_bindings/ROL_ValidateFunction.hpp @@ -27,6 +27,20 @@ namespace ROL { namespace details { + +using std::cout; +using std::ostream; +using std::string; +using std::vector; +using std::setw; +using std::setprecision; +using std::scientific; +using std::abs; +using std::right; +using std::max; +using std::endl; + + template class ValidateFunction { public: diff --git a/packages/rol/src/utils/function_bindings/ROL_ValidateFunctionDef.hpp b/packages/rol/src/utils/function_bindings/ROL_ValidateFunctionDef.hpp index 6a1804fd69b5..98e0ba15e8d9 100644 --- a/packages/rol/src/utils/function_bindings/ROL_ValidateFunctionDef.hpp +++ b/packages/rol/src/utils/function_bindings/ROL_ValidateFunctionDef.hpp @@ -15,7 +15,6 @@ namespace ROL { namespace details { -using namespace std; template ValidateFunction::ValidateFunction( const int order, diff --git a/packages/rol/src/vector/ROL_VectorClone.hpp b/packages/rol/src/vector/ROL_VectorClone.hpp index 224f222a7103..f1bd941d8732 100644 --- a/packages/rol/src/vector/ROL_VectorClone.hpp +++ b/packages/rol/src/vector/ROL_VectorClone.hpp @@ -30,8 +30,6 @@ namespace ROL { namespace details { -using namespace std; - template class VectorClone { private: @@ -46,9 +44,9 @@ class VectorClone { Ptr> operator() ( const Vector& x ) { if( is_allocated_ ) { if( typeid(x) != typeid(*vec_) ) - throw logic_error("Argument and member vector types are different!"); + throw std::logic_error("Argument and member vector types are different!"); if( x.dimension() != vec_->dimension() ) - throw logic_error("Argument and member vector types have different dimensions!"); + throw std::logic_error("Argument and member vector types have different dimensions!"); } else { vec_ = x.clone(); @@ -60,9 +58,9 @@ class VectorClone { Ptr> operator() ( const Ptr>& x ) { if( is_allocated_ ) { if( typeid(*x) != typeid(*vec_) ) - throw logic_error("Argument and member vector types are different!"); + throw std::logic_error("Argument and member vector types are different!"); if( x->dimension() != vec_->dimension() ) - throw logic_error("Argument and member vector types have different dimensions!"); + throw std::logic_error("Argument and member vector types have different dimensions!"); } else { vec_ = x->clone(); @@ -84,7 +82,7 @@ class VectorClone { template class VectorCloneMap { private: - map> clones_; + std::map> clones_; template void Constructor_Impl( First first, Rest... rest ) { @@ -102,7 +100,7 @@ class VectorCloneMap { /** \brief Preallocate keys if desired */ template VectorCloneMap( Keys&&...keys ) { - Constructor_Impl( forward(keys)... ); + Constructor_Impl( keys... ); } Ptr> operator() ( const Vector& x, KeyType key ) { diff --git a/packages/rol/src/vector/ROL_VectorWorkspace.hpp b/packages/rol/src/vector/ROL_VectorWorkspace.hpp index e9364b1110aa..a7cd14876b00 100644 --- a/packages/rol/src/vector/ROL_VectorWorkspace.hpp +++ b/packages/rol/src/vector/ROL_VectorWorkspace.hpp @@ -26,22 +26,22 @@ Will allocate new memory of a clone of x *if needed* and return a pointer to the clone. A new clone is considered to be needed - only if these is not a previously allocated compatible vector + only if these is not a previously allocated compatible std::vector stored in the VectorWorkspace. Compatibility is determined by derived type (typeid::hash_code) - and vector dimension. Together these form a VectorKey. - When cloning a vector inside a member function, VectorWorkspace + and std::vector dimension. Together these form a VectorKey. + When cloning a std::vector inside a member function, VectorWorkspace will identify it's VectorKey type. If such a type exists in the database, with will then refer to the associated VectorStack that is specific to the VectorKey type. The VectorStack will be searched for the first available dynamically - allocated vector which has no external references to it and return - a pointer to it. If no such vector exists, a new one will be + allocated std::vector which has no external references to it and return + a pointer to it. If no such std::vector exists, a new one will be cloned and added to the stack. When the local pointers to the VectorStack elements go out of scope at the end of the member - function, the reference counts are decremented and the vectors + function, the reference counts are decremented and the std::vectors become available for use again. NOTE: Stored clones will have a reference count of 2 when there @@ -60,14 +60,11 @@ namespace ROL { namespace details { -using namespace std; - - template class VectorWorkspace { using V = ROL::Vector; - using size_type = typename vector::size_type; + using size_type = typename std::vector::size_type; private: @@ -83,10 +80,10 @@ class VectorWorkspace { VectorKey( const Ptr& x ) : VectorKey( *x ) {} - static string to_string( const VectorKey& key ) { - stringstream ss; - ss << "VectorKey(" << hex << key.hash_code << "," - << dec << key.dimension << ")"; + static std::string to_string( const VectorKey& key ) { + std::stringstream ss; + ss << "VectorKey(" << std::hex << key.hash_code << "," + << std::dec << key.dimension << ")"; return ss.str(); } @@ -107,7 +104,7 @@ class VectorWorkspace { struct VectorStack { friend class VectorWorkspace; - vector> vectors_; + std::vector> vectors_; VectorKey key_; VectorStack( const V& x ) : vectors_( 1, x.clone() ), @@ -129,37 +126,37 @@ class VectorWorkspace { Ptr clone( const V& x ) { VectorKey x_key(x); - ROL_TEST_FOR_EXCEPTION( key_.hash_code != x_key.hash_code, logic_error, - "VectorWorkspace::VectorStack tried to clone a vector of type " << - hex << key_.hash_code << ", but it can only clone vectors of type " << - hex << x_key.hash_code ); - - ROL_TEST_FOR_EXCEPTION( key_.dimension != x_key.dimension, logic_error, - "VectorWorkspace::VectorStack tried to clone a vector of dimension " << - hex << key_.dimension << ", but it can only clone vectors of dimension " << - hex << x_key.dimension ); - - for( auto e : vectors_ ) { // Return first unreferenced vector - if( getCount(e) <= 2 ) { // Storing pointers in vector increments count + ROL_TEST_FOR_EXCEPTION( key_.hash_code != x_key.hash_code, std::logic_error, + "VectorWorkspace::VectorStack tried to clone a std::vector of type " << + std::hex << key_.hash_code << ", but it can only clone std::vectors of type " << + std::hex << x_key.hash_code ); + + ROL_TEST_FOR_EXCEPTION( key_.dimension != x_key.dimension, std::logic_error, + "VectorWorkspace::VectorStack tried to clone a std::vector of dimension " << + std::hex << key_.dimension << ", but it can only clone std::vectors of dimension " << + std::hex << x_key.dimension ); + + for( auto e : vectors_ ) { // Return first unreferenced std::vector + if( getCount(e) <= 2 ) { // Storing pointers in std::vector increments count return e; } } - // If no unreferenced vectors exist, add a new one + // If no unreferenced std::vectors exist, add a new one auto v = x.clone(); vectors_.push_back( v ); return v; } // For testing purposes - vector getRefCounts( void ) const { - vector counts; + std::vector getRefCounts( void ) const { + std::vector counts; for( auto e: vectors_ ) counts.push_back( getCount(e) ); return counts; } }; // VectorStack - map> workspace_; + std::map> workspace_; public: @@ -173,7 +170,7 @@ class VectorWorkspace { if( key_count == 0 ) { // New key vstack = makePtr(x); - workspace_.insert( make_pair(key,vstack) ); + workspace_.insert( std::make_pair(key,vstack) ); } else vstack = workspace_[key]; @@ -191,18 +188,18 @@ class VectorWorkspace { Ptr copy( const Ptr& x ) { return copy(*x); } - void status( ostream& os ) const { - os << "\n\n" << string(80,'-') << std::endl; + void status( std::ostream& os ) const { + os << "\n\n" << std::string(80,'-') << std::endl; os << "VectorWorkspace contains the following VectorStack(hash_code,dim) entries:\n\n"; for( auto entry : workspace_ ) { - os << " VectorStack(" << hex << entry.first.hash_code << "," - << dec << entry.first.dimension << ")"; + os << " VectorStack(" << std::hex << entry.first.hash_code << "," + << std::dec << entry.first.dimension << ")"; os << "\n Reference Counts per element" << std::endl; for( auto e : entry.second->vectors_ ) { os << " " << getCount( e ) << std::endl; } } - os << string(80,'-') << std::endl; + os << std::string(80,'-') << std::endl; } diff --git a/packages/rol/src/zoo/ROL_Stream.hpp b/packages/rol/src/zoo/ROL_Stream.hpp index 7534e033bb54..582fb4383faa 100644 --- a/packages/rol/src/zoo/ROL_Stream.hpp +++ b/packages/rol/src/zoo/ROL_Stream.hpp @@ -27,27 +27,25 @@ namespace ROL { namespace details { -using namespace std; - template -class basic_nullstream : virtual public basic_ostream<_CharT, _Traits> { +class basic_nullstream : virtual public std::basic_ostream<_CharT, _Traits> { public: - explicit basic_nullstream() : basic_ostream<_CharT, _Traits>(NULL) {} + explicit basic_nullstream() : std::basic_ostream<_CharT, _Traits>(NULL) {} }; -using nullstream = basic_nullstream>; +using nullstream = basic_nullstream>; inline -Ptr makeStreamPtr( ostream& os, bool noSuppressOutput=true ) { - Ptr retstream; - if( noSuppressOutput ) retstream = makePtrFromRef(os); +Ptr makeStreamPtr( std::ostream& os, bool noSuppressOutput=true ) { + Ptr retstream; + if( noSuppressOutput ) retstream = makePtrFromRef(os); else retstream = makePtr(); return retstream; // noSuppressOutput ? makePtrFromRef( os ) : makePtr(); } inline -Ptr makeStreamPtr( Ptr os, bool noSuppressOutput=true ) { - Ptr retstream; +Ptr makeStreamPtr( Ptr os, bool noSuppressOutput=true ) { + Ptr retstream; if( noSuppressOutput ) retstream = os; else retstream = makePtr(); return retstream; // noSuppressOutput ? makePtrFromRef( os ) : makePtr(); diff --git a/packages/rol/src/zoo/ROL_Types.hpp b/packages/rol/src/zoo/ROL_Types.hpp index 03dc4564cb61..a349ba91ba94 100644 --- a/packages/rol/src/zoo/ROL_Types.hpp +++ b/packages/rol/src/zoo/ROL_Types.hpp @@ -222,6 +222,7 @@ namespace ROL { // Types of optimization problem enum EProblem { TYPE_U = 0, + TYPE_P, TYPE_B, TYPE_E, TYPE_EB, @@ -278,7 +279,9 @@ namespace ROL { (s == STEP_TRUSTREGION) || (s == STEP_BUNDLE) ); break; - + case TYPE_P: comp = ( (s == STEP_LINESEARCH) || + (s == STEP_TRUSTREGION)); + break; case TYPE_B: comp = ( (s == STEP_LINESEARCH) || (s == STEP_TRUSTREGION) || (s == STEP_MOREAUYOSIDAPENALTY) || @@ -307,6 +310,7 @@ namespace ROL { std::string retString; switch(p) { case TYPE_U: retString = "Type-U"; break; + case TYPE_P: retString = "Type-P"; break; case TYPE_E: retString = "Type-E"; break; case TYPE_B: retString = "Type-B"; break; case TYPE_EB: retString = "Type-EB"; break; diff --git a/packages/rol/src/zoo/testproblems/ROL_HS14.hpp b/packages/rol/src/zoo/testproblems/ROL_HS14.hpp index 3c036eb41ec2..13ddcba6adcf 100644 --- a/packages/rol/src/zoo/testproblems/ROL_HS14.hpp +++ b/packages/rol/src/zoo/testproblems/ROL_HS14.hpp @@ -52,7 +52,7 @@ class Objective_HS14 : public StdObjective { const Real c2(2); hv[0] = c2*v[0]; hv[1] = c2*v[1]; - } + } }; template @@ -63,7 +63,7 @@ class Constraint_HS14a : public StdConstraint { void value( std::vector &c, const std::vector &x, Real &tol ) { const Real c1(1), c2(2); c[0] = x[0] - c2*x[1] + c1; - } + } void applyJacobian(std::vector &jv, const std::vector &v, const std::vector &x, Real &tol) { @@ -93,7 +93,7 @@ class Constraint_HS14b : public StdConstraint { void value( std::vector &c, const std::vector &x, Real &tol ) { const Real c0(0.25), c1(1), c2(2); c[0] = -c0*std::pow(x[0],c2) - std::pow(x[1],c2) + c1; - } + } void applyJacobian(std::vector &jv, const std::vector &v, const std::vector &x, Real &tol) { @@ -105,7 +105,7 @@ class Constraint_HS14b : public StdConstraint { const std::vector &x, Real &tol ) { const Real c0(0.25), c2(2); ajv[0] = -c0*c2*x[0]*v[0]; - ajv[1] = -c2*x[1]*v[0]; + ajv[1] = -c2*x[1]*v[0]; } void applyAdjointHessian(std::vector &ahuv, const std::vector &u, diff --git a/packages/rol/test/algorithm/TypeP/CMakeLists.txt b/packages/rol/test/algorithm/TypeP/CMakeLists.txt index c0a93e5727ac..8a8572722d0b 100644 --- a/packages/rol/test/algorithm/TypeP/CMakeLists.txt +++ b/packages/rol/test/algorithm/TypeP/CMakeLists.txt @@ -62,6 +62,15 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST( ADD_DIR_TO_NAME ) +TRIBITS_ADD_EXECUTABLE_AND_TEST( + TestTypePSolver + SOURCES test_08.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + TRIBITS_COPY_FILES_TO_BINARY_DIR( TypePTestDataCopy SOURCE_FILES diff --git a/packages/rol/test/algorithm/TypeP/test_08.cpp b/packages/rol/test/algorithm/TypeP/test_08.cpp new file mode 100644 index 000000000000..9b459e7f8f08 --- /dev/null +++ b/packages/rol/test/algorithm/TypeP/test_08.cpp @@ -0,0 +1,255 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +/*! \file test_03.cpp + \brief Validate Trust Region algorithm. +*/ + +#include "ROL_TypeP_TrustRegionAlgorithm.hpp" +#include "ROL_StdObjective.hpp" +#include "ROL_l1Objective.hpp" +#include "ROL_Solver.hpp" +#include "ROL_Problem.hpp" +#include "ROL_Stream.hpp" +#include "Teuchos_GlobalMPISession.hpp" +#include +#include + +template +class QuadraticTypeP_Test01 : public ROL::StdObjective { +private: + int dim_; + std::vector a_, b_; + +public: + QuadraticTypeP_Test01(int dim) : dim_(dim) { + using seed_type = std::mt19937_64::result_type; + seed_type const seed = 123; + std::mt19937_64 eng{seed}; + std::uniform_real_distribution distA(0.0,5.0), distB(-10.0,10.0); + a_.resize(dim); + b_.resize(dim); + for (int i = 0; i < dim; ++i) { + a_[i] = distA(eng); + b_[i] = distB(eng); + } + } + + Real value(const std::vector &x, Real &tol) { + Real val(0); + for (int i = 0; i < dim_; ++i) + val += static_cast(0.5)*a_[i]*x[i]*x[i] + b_[i]*x[i]; + return val; + } + + void gradient(std::vector &g, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + g[i] = a_[i]*x[i] + b_[i]; + } + + void hessVec(std::vector &hv, const std::vector &v, const std::vector &x, Real &tol) { + for (int i = 0; i < dim_; ++i) + hv[i] = a_[i]*v[i]; + } + + void getSolution(std::vector &x, const std::vector &wts, const std::vector &y) const { + for (int i = 0; i < dim_; ++i) + x[i] = (std::min(wts[i], std::max(-wts[i], a_[i]*y[i] + b_[i])) - b_[i]) / a_[i]; + } +}; + +typedef double RealT; + +int main(int argc, char *argv[]) { + + Teuchos::GlobalMPISession mpiSession(&argc, &argv); + + // This little trick lets us print to std::cout only if a + // (dummy) command-line argument is provided. + int iprint = argc - 1; + ROL::Ptr outStream; + ROL::nullstream bhs; // outputs nothing + if (iprint > 0) + outStream = ROL::makePtrFromRef(std::cout); + else + outStream = ROL::makePtrFromRef(bhs); + + int errorFlag = 0; + + try { + RealT tol = 1e2*std::sqrt(ROL::ROL_EPSILON()); + + ROL::ParameterList list; + list.sublist("General").set("Output Level",iprint); + list.sublist("Step").set("Type","Trust Region"); + list.sublist("Status Test").set("Gradient Tolerance",1e-1*tol); + list.sublist("Status Test").set("Constraint Tolerance",1e-1*tol); + list.sublist("Status Test").set("Step Tolerance",1e-3*tol); + list.sublist("Status Test").set("Iteration Limit", 50); + int dim = 5; + ROL::Ptr> sol, wts, y; + ROL::Ptr> sobj; + ROL::Ptr> nobj; + + + ROL::Ptr> algo; + std::vector data; + RealT err(0); + + *outStream << std::endl << "Random Diagonal LASSO Test Problem" << std::endl << std::endl; + ROL::Ptr> wtsP = ROL::makePtr>(dim); + ROL::Ptr> yP = ROL::makePtr>(dim); + wts = ROL::makePtr>(wtsP);// wts->setSeed(234); + y = ROL::makePtr>(yP); // y->setSeed(345); + sol = ROL::makePtr>(dim); + wts->randomize(static_cast(0),static_cast(1)); + y->randomize(static_cast(-5),static_cast(5)); + + nobj = ROL::makePtr>(wts,y); + sobj = ROL::makePtr>(dim); + + std::vector xstar(dim); + sobj->getSolution(xstar, *wtsP, *yP); + RealT xmax(0); + for (int i = 0; i < dim; ++i) + xmax = std::max(xmax,std::abs(xstar[i])); + + // Check derivatives of smooth function + ROL::Ptr> xd = sol->clone(); + xd->randomize(-1.0,1.0); + ROL::Ptr> yd = sol->clone(); + yd->randomize(-1.0,1.0); + ROL::Ptr> zd = sol->clone(); + zd->randomize(-1.0,1.0); + sobj->checkGradient(*xd,*yd,true,*outStream); + sobj->checkHessVec(*xd,*yd,true,*outStream); + sobj->checkHessSym(*xd,*yd,*zd,true,*outStream); + + list.sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Subproblem Solver", "SPG"); + sol->zero(); + auto problem = ROL::makePtr>(sobj, sol); // check + problem->addProximableObjective(nobj); + problem->finalize(false, true, *outStream); + ROL::Solver solverspg(problem, list); + + auto begin = std::chrono::high_resolution_clock::now(); + solverspg.solve(*outStream); + auto end = std::chrono::high_resolution_clock::now(); + *outStream << " Optimization Time: " << std::chrono::duration_cast(end-begin).count() << " microseconds" << std::endl; + + err = static_cast(0); + data = *ROL::staticPtrCast>(sol)->getVector(); + *outStream << " Result: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << data[i]; + err = std::max(err,std::abs(data[i]-xstar[i])); + } + *outStream << std::endl; + *outStream << " Truth: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << xstar[i]; + } + *outStream << std::endl; + *outStream << " Max Relative Error = " << err/xmax << std::endl; + errorFlag += (err > tol ? 1 : 0); + + list.sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Subproblem Solver", "Simplified SPG"); + sol->zero(); + ROL::Solver solverspg2(problem, list); + begin = std::chrono::high_resolution_clock::now(); + solverspg2.solve(*outStream); + end = std::chrono::high_resolution_clock::now(); + *outStream << " Optimization Time: " << std::chrono::duration_cast(end-begin).count() << " microseconds" << std::endl; + + err = static_cast(0); + data = *ROL::staticPtrCast>(sol)->getVector(); + *outStream << " Result: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << data[i]; + err = std::max(err,std::abs(data[i]-xstar[i])); + } + *outStream << std::endl; + *outStream << " Truth: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << xstar[i]; + } + *outStream << std::endl; + *outStream << " Max Relative Error = " << err/xmax << std::endl; + errorFlag += (err > tol ? 1 : 0); + + list.sublist("Step").sublist("Trust Region").sublist("TRN").sublist("Solver").set("Subproblem Solver", "NCG"); + sol->zero(); + ROL::Solver solverncg(problem, list); + begin = std::chrono::high_resolution_clock::now(); + solverncg.solve(*outStream); + end = std::chrono::high_resolution_clock::now(); + *outStream << " Optimization Time: " << std::chrono::duration_cast(end-begin).count() << " microseconds" << std::endl; + + err = static_cast(0); + data = *ROL::staticPtrCast>(sol)->getVector(); + *outStream << " Result: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << data[i]; + err = std::max(err,std::abs(data[i]-xstar[i])); + } + *outStream << std::endl; + *outStream << " Truth: "; + for (int i = 0; i < dim; ++i) { + *outStream << " x" << i+1 << " = " << xstar[i]; + } + *outStream << std::endl; + *outStream << " Max Relative Error = " << err/xmax << std::endl; + errorFlag += (err > tol ? 1 : 0); + } + catch (std::logic_error& err) { + *outStream << err.what() << "\n"; + errorFlag = -1000; + }; // end try + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return 0; +} diff --git a/packages/rol/test/function/CMakeLists.txt b/packages/rol/test/function/CMakeLists.txt index 22aa23c105df..c1a7ad12c762 100644 --- a/packages/rol/test/function/CMakeLists.txt +++ b/packages/rol/test/function/CMakeLists.txt @@ -155,6 +155,14 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST( ADD_DIR_TO_NAME ) +TRIBITS_ADD_EXECUTABLE_AND_TEST( + ReducedConstraintSimOptCheck + SOURCES test_19.cpp + ARGS PrintItAll + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + TRIBITS_COPY_FILES_TO_BINARY_DIR( BinaryConstraintDataCopy SOURCE_FILES diff --git a/packages/rol/test/function/test_19.cpp b/packages/rol/test/function/test_19.cpp new file mode 100644 index 000000000000..3d1b5f0c68fa --- /dev/null +++ b/packages/rol/test/function/test_19.cpp @@ -0,0 +1,482 @@ +// @HEADER +// ************************************************************************ +// +// Rapid Optimization Library (ROL) Package +// Copyright (2014) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact lead developers: +// Drew Kouri (dpkouri@sandia.gov) and +// Denis Ridzal (dridzal@sandia.gov) +// +// ************************************************************************ +// @HEADER + +/*! \file test_19.cpp + \brief Test ReducedConstraintSimOpt class + +*/ + +#include "ROL_StdVector.hpp" +#include "ROL_Constraint_SimOpt.hpp" +#include "ROL_Reduced_Constraint_SimOpt.hpp" +#include "ROL_Stream.hpp" +#include "Teuchos_GlobalMPISession.hpp" +#include + +template +class constraint1 : public ROL::Constraint_SimOpt { +public: + constraint1() {} + void value(ROL::Vector &c, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(c.dimension()==1); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector cs = dynamic_cast&>(c); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + Real z2 = (*(zs.getVector()))[1]; + (*(cs.getVector()))[0] = std::exp(z1*u1)-z2*z2; + } + void solve(ROL::Vector &c, ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(c.dimension()==1); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real z1 = (*(zs.getVector()))[0]; + Real z2 = (*(zs.getVector()))[1]; + (*(us.getVector()))[0] = static_cast(2)*std::log(std::abs(z2)) / z1; + constraint1::value(c,u,z,tol); + } + void applyJacobian_1(ROL::Vector &jv, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(jv.dimension()==1); + assert(v.dimension()==1); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector jvs = dynamic_cast&>(jv); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real v1 = (*(vs.getVector()))[0]; + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + (*(jvs.getVector()))[0] = z1*std::exp(z1*u1)*v1; + } + void applyJacobian_2(ROL::Vector &jv, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(jv.dimension()==1); + assert(v.dimension()==2); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector jvs = dynamic_cast&>(jv); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real v1 = (*(vs.getVector()))[0]; + Real v2 = (*(vs.getVector()))[1]; + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + Real z2 = (*(zs.getVector()))[1]; + (*(jvs.getVector()))[0] = u1*std::exp(z1*u1)*v1 - static_cast(2)*z2*v2; + } + void applyInverseJacobian_1(ROL::Vector &ijv, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(ijv.dimension()==1); + assert(v.dimension()==1); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector ijvs = dynamic_cast&>(ijv); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real v1 = (*(vs.getVector()))[0]; + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + (*(ijvs.getVector()))[0] = v1 / (z1*std::exp(z1*u1)); + } + void applyAdjointJacobian_1(ROL::Vector &ajv, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + constraint1::applyJacobian_1(ajv,v,u,z,tol); + } + void applyAdjointJacobian_2(ROL::Vector &ajv, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(ajv.dimension()==2); + assert(v.dimension()==1); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector ajvs = dynamic_cast&>(ajv); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real v1 = (*(vs.getVector()))[0]; + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + Real z2 = (*(zs.getVector()))[1]; + (*(ajvs.getVector()))[0] = u1*std::exp(z1*u1)*v1; + (*(ajvs.getVector()))[1] = -static_cast(2)*z2*v1; + } + void applyInverseAdjointJacobian_1(ROL::Vector &iajv, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + constraint1::applyInverseJacobian_1(iajv,v,u,z,tol); + } + void applyAdjointHessian_11(ROL::Vector &ahwv, const ROL::Vector &w, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(ahwv.dimension()==1); + assert(w.dimension()==1); + assert(v.dimension()==1); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector ahwvs = dynamic_cast&>(ahwv); + const ROL::StdVector ws = dynamic_cast&>(w); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real w1 = (*(ws.getVector()))[0]; + Real v1 = (*(vs.getVector()))[0]; + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + (*(ahwvs.getVector()))[0] = z1*z1*std::exp(z1*u1)*v1*w1; + } + void applyAdjointHessian_12(ROL::Vector &ahwv, const ROL::Vector &w, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(ahwv.dimension()==2); + assert(w.dimension()==1); + assert(v.dimension()==1); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector ahwvs = dynamic_cast&>(ahwv); + const ROL::StdVector ws = dynamic_cast&>(w); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real w1 = (*(ws.getVector()))[0]; + Real v1 = (*(vs.getVector()))[0]; + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + (*(ahwvs.getVector()))[0] = std::exp(z1*u1)*(static_cast(1)+u1*z1)*v1*w1; + (*(ahwvs.getVector()))[1] = static_cast(0); + } + void applyAdjointHessian_21(ROL::Vector &ahwv, const ROL::Vector &w, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(ahwv.dimension()==1); + assert(w.dimension()==1); + assert(v.dimension()==2); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector ahwvs = dynamic_cast&>(ahwv); + const ROL::StdVector ws = dynamic_cast&>(w); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real w1 = (*(ws.getVector()))[0]; + Real v1 = (*(vs.getVector()))[0]; + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + (*(ahwvs.getVector()))[0] = std::exp(z1*u1)*(static_cast(1)+u1*z1)*v1*w1; + } + void applyAdjointHessian_22(ROL::Vector &ahwv, const ROL::Vector &w, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(ahwv.dimension()==2); + assert(w.dimension()==1); + assert(v.dimension()==2); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector ahwvs = dynamic_cast&>(ahwv); + const ROL::StdVector ws = dynamic_cast&>(w); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real w1 = (*(ws.getVector()))[0]; + Real v1 = (*(vs.getVector()))[0]; + Real v2 = (*(vs.getVector()))[1]; + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + (*(ahwvs.getVector()))[0] = u1*u1*std::exp(z1*u1)*v1*w1; + (*(ahwvs.getVector()))[1] = -static_cast(2)*v2*w1; + } +}; + + +template +class constraint2 : public ROL::Constraint_SimOpt { +public: + constraint2() {} + void value(ROL::Vector &c, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(c.dimension()==3); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector cs = dynamic_cast&>(c); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + Real z2 = (*(zs.getVector()))[1]; + (*(cs.getVector()))[0] = z1*z2*u1; + (*(cs.getVector()))[1] = (z1-z2)*u1; + (*(cs.getVector()))[2] = u1*u1; + } + void applyJacobian_1(ROL::Vector &jv, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(jv.dimension()==3); + assert(v.dimension()==1); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector jvs = dynamic_cast&>(jv); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + const Real two(2); + Real v1 = (*(vs.getVector()))[0]; + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + Real z2 = (*(zs.getVector()))[1]; + (*(jvs.getVector()))[0] = z1*z2*v1; + (*(jvs.getVector()))[1] = (z1-z2)*v1; + (*(jvs.getVector()))[2] = two*u1*v1; + } + void applyJacobian_2(ROL::Vector &jv, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(jv.dimension()==3); + assert(v.dimension()==2); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector jvs = dynamic_cast&>(jv); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real v1 = (*(vs.getVector()))[0]; + Real v2 = (*(vs.getVector()))[1]; + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + Real z2 = (*(zs.getVector()))[1]; + (*(jvs.getVector()))[0] = z2*u1*v1 + z1*u1*v2; + (*(jvs.getVector()))[1] = (v1-v2)*u1; + (*(jvs.getVector()))[2] = static_cast(0); + } + void applyAdjointJacobian_1(ROL::Vector &ajv, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(ajv.dimension()==1); + assert(v.dimension()==3); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector ajvs = dynamic_cast&>(ajv); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + const Real two(2); + Real v1 = (*(vs.getVector()))[0]; + Real v2 = (*(vs.getVector()))[1]; + Real v3 = (*(vs.getVector()))[2]; + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + Real z2 = (*(zs.getVector()))[1]; + (*(ajvs.getVector()))[0] = z1*z2*v1 + (z1-z2)*v2 + two*u1*v3; + } + void applyAdjointJacobian_2(ROL::Vector &ajv, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(ajv.dimension()==2); + assert(v.dimension()==3); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector ajvs = dynamic_cast&>(ajv); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real v1 = (*(vs.getVector()))[0]; + Real v2 = (*(vs.getVector()))[1]; + Real u1 = (*(us.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + Real z2 = (*(zs.getVector()))[1]; + (*(ajvs.getVector()))[0] = (z2*u1*v1 + u1*v2); + (*(ajvs.getVector()))[1] = (z1*u1*v1 - u1*v2); + } + void applyAdjointHessian_11(ROL::Vector &ahwv, const ROL::Vector &w, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(ahwv.dimension()==1); + assert(w.dimension()==3); + assert(v.dimension()==1); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector ahwvs = dynamic_cast&>(ahwv); + const ROL::StdVector ws = dynamic_cast&>(w); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + const Real two(2); + Real w3 = (*(ws.getVector()))[2]; + Real v1 = (*(vs.getVector()))[0]; + (*(ahwvs.getVector()))[0] = two*v1*w3; + } + void applyAdjointHessian_12(ROL::Vector &ahwv, const ROL::Vector &w, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(ahwv.dimension()==2); + assert(w.dimension()==3); + assert(v.dimension()==1); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector ahwvs = dynamic_cast&>(ahwv); + const ROL::StdVector ws = dynamic_cast&>(w); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real w1 = (*(ws.getVector()))[0]; + Real w2 = (*(ws.getVector()))[1]; + Real v1 = (*(vs.getVector()))[0]; + Real z1 = (*(zs.getVector()))[0]; + Real z2 = (*(zs.getVector()))[1]; + (*(ahwvs.getVector()))[0] = (z2*v1*w1 + v1*w2); + (*(ahwvs.getVector()))[1] = (z1*v1*w1 - v1*w2); + } + void applyAdjointHessian_21(ROL::Vector &ahwv, const ROL::Vector &w, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(ahwv.dimension()==1); + assert(w.dimension()==3); + assert(v.dimension()==2); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector ahwvs = dynamic_cast&>(ahwv); + const ROL::StdVector ws = dynamic_cast&>(w); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real w1 = (*(ws.getVector()))[0]; + Real w2 = (*(ws.getVector()))[1]; + Real v1 = (*(vs.getVector()))[0]; + Real v2 = (*(vs.getVector()))[1]; + Real z1 = (*(zs.getVector()))[0]; + Real z2 = (*(zs.getVector()))[1]; + (*(ahwvs.getVector()))[0] = (v1*z2+z1*v2)*w1 + (v1-v2)*w2; + } + void applyAdjointHessian_22(ROL::Vector &ahwv, const ROL::Vector &w, const ROL::Vector &v, const ROL::Vector &u, const ROL::Vector &z, Real &tol) { + assert(ahwv.dimension()==2); + assert(w.dimension()==3); + assert(v.dimension()==2); + assert(u.dimension()==1); + assert(z.dimension()==2); + ROL::StdVector ahwvs = dynamic_cast&>(ahwv); + const ROL::StdVector ws = dynamic_cast&>(w); + const ROL::StdVector vs = dynamic_cast&>(v); + const ROL::StdVector us = dynamic_cast&>(u); + const ROL::StdVector zs = dynamic_cast&>(z); + Real w1 = (*(ws.getVector()))[0]; + Real v1 = (*(vs.getVector()))[0]; + Real v2 = (*(vs.getVector()))[1]; + Real u1 = (*(us.getVector()))[0]; + (*(ahwvs.getVector()))[0] = v2*u1*w1; + (*(ahwvs.getVector()))[1] = v1*u1*w1; + } +}; + +int main(int argc, char *argv[]) { + using RealT = double; + + Teuchos::GlobalMPISession mpiSession(&argc, &argv); + + // This little trick lets us print to std::cout only if a (dummy) command-line argument is provided. + int iprint = argc - 1; + ROL::Ptr outStream; + ROL::nullstream bhs; // outputs nothing + if (iprint > 0) + outStream = ROL::makePtrFromRef(std::cout); + else + outStream = ROL::makePtrFromRef(bhs); + + // Save the format state of the original std::cout. + ROL::nullstream oldFormatState; + oldFormatState.copyfmt(std::cout); + +// RealT errtol = std::sqrt(ROL::ROL_THRESHOLD()); + + int errorFlag = 0; + + // *** Test body. + + try { + + unsigned c1_dim = 1; // Constraint1 dimension + unsigned c2_dim = 3; // Constraint1 dimension + unsigned u_dim = 1; // State dimension + unsigned z_dim = 2; // Control dimension + + auto c1 = ROL::makePtr>(c1_dim); + auto c2 = ROL::makePtr>(c2_dim); + auto u = ROL::makePtr>(u_dim); + auto z = ROL::makePtr>(z_dim); + auto vc1 = ROL::makePtr>(c1_dim); + auto vc2 = ROL::makePtr>(c2_dim); + auto vu = ROL::makePtr>(u_dim); + auto vz = ROL::makePtr>(z_dim); + auto du = ROL::makePtr>(u_dim); + auto dz = ROL::makePtr>(z_dim); + c1->randomize(static_cast(-1),static_cast(1)); + c2->randomize(static_cast(-1),static_cast(1)); + u->randomize(static_cast(-1),static_cast(1)); + z->randomize(static_cast(-1),static_cast(1)); + vc1->randomize(static_cast(-1),static_cast(1)); + vc2->randomize(static_cast(-1),static_cast(1)); + vu->randomize(static_cast(-1),static_cast(1)); + vz->randomize(static_cast(-1),static_cast(1)); + du->randomize(static_cast(-1),static_cast(1)); + dz->randomize(static_cast(-1),static_cast(1)); + + auto con1 = ROL::makePtr>(); + auto con2 = ROL::makePtr>(); + auto stateStore = ROL::makePtr>(); + auto rcon = ROL::makePtr>(con2,con1,stateStore,u,z,vc1,c2,true,false); + + con1->checkSolve(*u,*z,*c1,true,*outStream); + con1->checkAdjointConsistencyJacobian_1(*vc1,*vu,*u,*z,true,*outStream); + con1->checkAdjointConsistencyJacobian_2(*vc1,*vz,*u,*z,true,*outStream); + con1->checkInverseJacobian_1(*c1,*vu,*u,*z,true,*outStream); + con1->checkInverseAdjointJacobian_1(*c1,*vu,*u,*z,true,*outStream); + con1->checkApplyJacobian_1(*u,*z,*vu,*vc1,true,*outStream); + con1->checkApplyJacobian_2(*u,*z,*vz,*vc1,true,*outStream); + con1->checkApplyAdjointHessian_11(*u,*z,*vc1,*vu,*du,true,*outStream); + con1->checkApplyAdjointHessian_12(*u,*z,*vc1,*vu,*dz,true,*outStream); + con1->checkApplyAdjointHessian_21(*u,*z,*vc1,*vz,*du,true,*outStream); + con1->checkApplyAdjointHessian_22(*u,*z,*vc1,*vz,*dz,true,*outStream); + + con2->checkAdjointConsistencyJacobian_1(*vc2,*vu,*u,*z,true,*outStream); + con2->checkAdjointConsistencyJacobian_2(*vc2,*vz,*u,*z,true,*outStream); + con2->checkApplyJacobian_1(*u,*z,*vu,*vc2,true,*outStream); + con2->checkApplyJacobian_2(*u,*z,*vz,*vc2,true,*outStream); + con2->checkApplyAdjointHessian_11(*u,*z,*vc2,*vu,*du,true,*outStream); + con2->checkApplyAdjointHessian_12(*u,*z,*vc2,*vu,*dz,true,*outStream); + con2->checkApplyAdjointHessian_21(*u,*z,*vc2,*vz,*du,true,*outStream); + con2->checkApplyAdjointHessian_22(*u,*z,*vc2,*vz,*dz,true,*outStream); + + rcon->checkAdjointConsistencyJacobian(*vc2,*vz,*z,true,*outStream); + rcon->checkApplyJacobian(*z,*vz,*vc2,true,*outStream); + rcon->checkApplyAdjointHessian(*z,*vc2,*vz,*dz,true,*outStream); + } + catch (std::logic_error& err) { + *outStream << err.what() << "\n"; + errorFlag = -1000; + }; // end try + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return 0; + + +} + diff --git a/packages/rol/tutorial/example_unc.cpp b/packages/rol/tutorial/example_unc.cpp index ccb662bb9a6d..266e43b7e947 100644 --- a/packages/rol/tutorial/example_unc.cpp +++ b/packages/rol/tutorial/example_unc.cpp @@ -13,7 +13,7 @@ #define OPTIMIZATION_PROBLEM_REFACTOR -#include "ROL_OptimizationSolver.hpp" +#include "ROL_Solver.hpp" #include "ROL_RandomVector.hpp" #include "ROL_StdObjective.hpp" @@ -73,6 +73,7 @@ int main(int argc, char *argv[]) { try { ROL::ParameterList parlist; + parlist.sublist("General").set("Output Level", 1); parlist.sublist("General").sublist("Secant").set("Use as Hessian",false); parlist.sublist("Step").set("Type","Trust Region"); parlist.sublist("Step").sublist("Trust Region").set("Subproblem Solver","Truncated CG"); @@ -84,10 +85,10 @@ int main(int argc, char *argv[]) { ROL::Ptr > obj = ROL::makePtr>(); - ROL::OptimizationProblem problem( obj, x ); - problem.check(*outStream); + ROL::Ptr > problem = ROL::makePtr>( obj, x ); + problem->check(true, *outStream); - ROL::OptimizationSolver solver( problem, parlist ); + ROL::Solver solver( problem, parlist ); solver.solve(*outStream); *outStream << "x_opt = [" << (*x_ptr)[0] << ", " << (*x_ptr)[1] << "]" << std::endl; @@ -104,8 +105,6 @@ int main(int argc, char *argv[]) { return 0; - - return 0; } diff --git a/packages/shylu/shylu_node/basker/src/shylubasker_decl.hpp b/packages/shylu/shylu_node/basker/src/shylubasker_decl.hpp index 09e3f6f98382..7fd24c7fb1d7 100644 --- a/packages/shylu/shylu_node/basker/src/shylubasker_decl.hpp +++ b/packages/shylu/shylu_node/basker/src/shylubasker_decl.hpp @@ -528,25 +528,6 @@ namespace BaskerNS Int off_diag ); - BASKER_INLINE - void L_blk_sfactor - ( - BASKER_MATRIX &MV, - BASKER_SYMBOLIC_TREE &ST, - INT_1DARRAY gcol, - INT_1DARRAY grow - ); - - //old - BASKER_INLINE - void L_blk_sfactor - ( - BASKER_MATRIX_VIEW &MV, - BASKER_SYMBOLIC_TREE &ST, - INT_1DARRAY gcol, - INT_1DARRAY grow - ); - BASKER_INLINE void S_sfactor_reduce ( diff --git a/packages/shylu/shylu_node/basker/src/shylubasker_error_manager.hpp b/packages/shylu/shylu_node/basker/src/shylubasker_error_manager.hpp index cd2c9f57bf0a..b56d378de8a7 100644 --- a/packages/shylu/shylu_node/basker/src/shylubasker_error_manager.hpp +++ b/packages/shylu/shylu_node/basker/src/shylubasker_error_manager.hpp @@ -77,7 +77,7 @@ namespace BaskerNS << " DOMBLK MALLOC : blk=" << thread_array(ti).error_blk << " subblk=" << thread_array(ti).error_subblk << " newsize=" << thread_array(ti).error_info - << std::endl; + << std::endl << std::flush; } //If on diagonal, want to compare L and U @@ -113,7 +113,7 @@ namespace BaskerNS { if(Options.verbose == BASKER_TRUE) { - std::cout << " ++ resize L( tid = " << ti << " ): new size = " << resize_L << std::endl; + std::cout << " ++ resize L( tid = " << ti << " ): new size = " << resize_L << std::endl << std::flush; } BASKER_MATRIX &L = LL(thread_array(ti).error_blk)(thread_array(ti).error_subblk); @@ -139,7 +139,7 @@ namespace BaskerNS { if(Options.verbose == BASKER_TRUE) { - std::cout << " ++ resize U( tid = " << ti << " ): new size = " << resize_U << std::endl; + std::cout << " ++ resize U( tid = " << ti << " ): new size = " << resize_U << std::endl << std::flush; } BASKER_MATRIX &U = LU(thread_array(ti).error_blk)(0); diff --git a/packages/shylu/shylu_node/basker/src/shylubasker_nfactor_blk.hpp b/packages/shylu/shylu_node/basker/src/shylubasker_nfactor_blk.hpp index 2e0434796e33..614663f193a9 100644 --- a/packages/shylu/shylu_node/basker/src/shylubasker_nfactor_blk.hpp +++ b/packages/shylu/shylu_node/basker/src/shylubasker_nfactor_blk.hpp @@ -546,37 +546,37 @@ namespace BaskerNS if (Options.replace_tiny_pivot && normA_blk > abs(zero)) { // just insert tiny pivot on diagonal maxindex = k; - while (gperm(maxindex+brow_g) != BASKER_MAX_IDX && maxindex < M.ncol) { + while (gperm(maxindex+brow_g) != BASKER_MAX_IDX && maxindex < M.ncol) { maxindex ++; - } - if (maxindex < M.ncol) { + } + if (maxindex < M.ncol) { if (Options.verbose == BASKER_TRUE) { cout << " thread-" << kid << " Explicit tiny pivot for maxind = " << maxindex << endl; - } + } pivot = normA_blk * sqrt(eps); lastU = pivot; npivots ++; - explicit_pivot = true; - } + explicit_pivot = true; + } } else if (Options.replace_zero_pivot && normA_blk > abs(zero)) { // just insert tiny pivot on diagonal maxindex = k; - while (gperm(maxindex+brow_g) != BASKER_MAX_IDX && maxindex < M.ncol-1) { + while (gperm(maxindex+brow_g) != BASKER_MAX_IDX && maxindex < M.ncol-1) { maxindex ++; - } - if (maxindex < M.ncol) { + } + if (maxindex < M.ncol) { if (Options.verbose == BASKER_TRUE) { cout << " thread-" << kid << " Explicit nonzero pivot for maxind = " << maxindex << "(" << gperm(maxindex+brow_g) << ")" << endl; - } + } pivot = normA_blk * eps; lastU = pivot; npivots ++; - explicit_pivot = true; - } + explicit_pivot = true; + } } - if (!explicit_pivot) { + if (!explicit_pivot) { thread_array(kid).error_type = BASKER_ERROR_SINGULAR; thread_array(kid).error_blk = b; @@ -1543,8 +1543,8 @@ namespace BaskerNS #ifdef BASKER_DEBUG_NFACTOR_BLK - printf("t_dense_move_offdiag_L, kid=%d, k=%d: L (%d %d) X (%d %d)\n", - kid, k, blkcol,blkrow, X_col, X_row); + printf("t_dense_move_offdiag_L, kid=%d, k=%d: L (%d %d) X (%d %d), nnz=%d\n", + kid, k, blkcol,blkrow, X_col, X_row, L.nnz); #endif @@ -1565,7 +1565,6 @@ namespace BaskerNS } */ - ///for(Int i = 0; i < p_size; i++) for(Int j = 0; j < L.nrow; ++j) { //Int j = pattern[i]; @@ -1573,7 +1572,15 @@ namespace BaskerNS if(X(j) != (Entry)(0) ) { //Int t = gperm(j+brow); - + if (lnnz >= L.nnz) { // this should not happen since allocated as dense separator blocks + if (Options.verbose == BASKER_TRUE) + { + printf("Move Off-diag L failed with insufficient storage L(%d,%d).nnz = %d\n", + (int)blkcol, (int)blkrow, (int)L.nnz ); + } + BASKER_ASSERT(true, "\n Not enough memory allocated for off-diagonal L\n"); + return BASKER_ERROR; + } #ifdef BASKER_DEBUG_NFACTOR_BLK printf("L-Moving, kid: %d j: %d val: %f lnnz: %d \n", kid, j, X[j]/pivot, lnnz); @@ -1594,7 +1601,6 @@ namespace BaskerNS #ifdef BASKER_INC_LVL L.inc_lvl[lnnz] = INC_LVL_TEMP[j]; #endif - lnnz++; } } @@ -1756,7 +1762,7 @@ namespace BaskerNS printf("t_back_solve_diag, kid: %d, ws: %d starting psize: %d \n", kid, ws_size, nnz); printf("t_back_solve_diag, kid: %d, ALM(%d)(%d): %dx%d\n",kid,blkcol,blkrow,B.nrow,B.ncol ); - printf("t_back_solve_diag, kid: %d, LL(%d)(%d): %dx%d\n",kid,blkcol,blkrow,L.nrow,L.ncol ); + printf("t_back_solve_diag, kid: %d, LL(%d)(%d): %dx%d, nnz=%d, X.nnz=%d\n",kid,blkcol,blkrow,L.nrow,L.ncol,LL(blkcol)(blkrow).nnz,X.extent(0) ); printf("\n\n"); fflush(stdout); #endif //B.info(); diff --git a/packages/shylu/shylu_node/basker/src/shylubasker_nfactor_col2.hpp b/packages/shylu/shylu_node/basker/src/shylubasker_nfactor_col2.hpp index 5e9345ed02ec..7b65e1d94ed0 100644 --- a/packages/shylu/shylu_node/basker/src/shylubasker_nfactor_col2.hpp +++ b/packages/shylu/shylu_node/basker/src/shylubasker_nfactor_col2.hpp @@ -233,7 +233,7 @@ namespace BaskerNS }//for - over all sublevel 1...lvl-2 #ifdef BASKER_TIMER printf("Time Upper-Col(%d): %lf \n", (int)kid, timer.seconds()); - timer.reset(); + fflush(stdout); timer.reset(); #endif //---------Lower Factor (old sublevel lvl-1)------- @@ -255,11 +255,11 @@ namespace BaskerNS } } #endif - #ifdef BASKER_DEBUG_NFACTOR_COL2 + #ifdef BASKER_TIMER printf("\n done with UPPER, kid: %d \n\n", kid); + printf("\n\n======= LOWER, KID: %d ======= \n\n", kid); + fflush(stdout); #endif - - //printf("\n\n======= LOWER, KID: %d ======= \n\n", kid); //return; // > accumulate the last update // > factor the diagonal block LU(U_col)(U_row) @@ -284,7 +284,8 @@ namespace BaskerNS if (info == BASKER_SUCCESS) { #ifdef BASKER_DEBUG_NFACTOR_COL2 - printf( " kid=%d: calling t_add_extend(k=%d/%d)\n",kid,k,ncol ); fflush(stdout); + printf( " kid=%d: calling t_add_extend(k=%d/%d) with LU(%d,%d).nnz = %d\n", + kid,k,ncol,U_col,U_row,LU(U_col)(U_row).nnz ); fflush(stdout); #endif t_add_extend(thread, kid,lvl,lvl-1, k, LU(U_col)(U_row).scol, @@ -316,13 +317,13 @@ namespace BaskerNS } } #ifdef BASKER_DEBUG_NFACTOR_COL2 - printf(" > done calling lower factor, kid: %d k: %d info=%d\n", kid, k, info); fflush(stdout); - #endif - #ifdef BASKER_DEBUG_NFACTOR_COL2 else { printf(" + skipping lower factor, kid: %d k: %d \n", kid, k); fflush(stdout); } #endif + #ifdef BASKER_DEBUG_NFACTOR_COL2 + printf(" > done calling lower factor, kid: %d k: %d info=%d\n", kid, k, info); fflush(stdout); + #endif //need barrier if multiple thread uppdate #ifdef USE_TEAM_BARRIER_NFACTOR_COL2 thread.team_barrier(); @@ -356,12 +357,12 @@ namespace BaskerNS timer_facoff.reset(); #endif #ifdef BASKER_DEBUG_NFACTOR_COL2 - printf(" calling lower diag factor, kid: %d k: %d \n", + printf(" calling lower offdiag factor, kid: %d k: %d \n", kid, k); fflush(stdout); #endif t_lower_col_factor_offdiag2(kid, lvl, lvl-1, k, pivot); #ifdef BASKER_DEBUG_NFACTOR_COL2 - printf(" done lower diag factor, kid: %d k: %d \n", + printf(" done lower offdiag factor, kid: %d k: %d \n", kid, k); fflush(stdout); #endif } @@ -906,7 +907,10 @@ namespace BaskerNS L_row < LL_size(L_col); X_row+=(lteam_size), L_row+=(lteam_size)) { - //printf("OFF_DIAG_LOWER. kid: %d k: %d U: %d %d L: %d %d X: %d %d pivot: %f \n", kid, k, U_col, U_row, L_col, L_row, X_col, X_row, pivot); + #ifdef BASKER_TIMER + printf("OFF_DIAG_LOWER. kid: %d k: %d U(%d, %d).nnz = %d L(%d, %d) X(%d, %d) pivot: %f \n", + kid, k, U_col, U_row, LU(U_col)(U_row).nnz, L_col, L_row, X_col, X_row, pivot); + #endif /*old t_back_solve_offdiag(leader_id, L_col, L_row, diff --git a/packages/shylu/shylu_node/basker/src/shylubasker_order.hpp b/packages/shylu/shylu_node/basker/src/shylubasker_order.hpp index 82ea04be3754..e9cddba1b3bb 100644 --- a/packages/shylu/shylu_node/basker/src/shylubasker_order.hpp +++ b/packages/shylu/shylu_node/basker/src/shylubasker_order.hpp @@ -1160,8 +1160,10 @@ static int basker_sort_matrix_col(const void *arg1, const void *arg2) std::cout << " > scotch_partition returned with info = " << info_scotch << " and apply_nd = " << apply_nd << std::endl; } return info_scotch; + } else if(Options.verbose == BASKER_TRUE) { + printf( "\n part_scotch done (num_threads = %d,%d)\n",num_threads,part_tree.leaf_nnz.extent(0) ); + //for (Int i = 0; i < num_threads; i++) printf( " nnz_leaf[%d] = %d\n",i,part_tree.leaf_nnz[i] ); printf( "\n" ); } - nd_flag = BASKER_TRUE; //permute permute_row(M, part_tree.permtab); @@ -2200,7 +2202,9 @@ static int basker_sort_matrix_col(const void *arg1, const void *arg2) INT_1DARRAY row ) { - permute_row(M.nnz, &(M.row_idx(0)), &(row(0))); + if (M.nnz > 0) { + permute_row(M.nnz, &(M.row_idx(0)), &(row(0))); + } return 0; }//end permute_row(matrix,int) diff --git a/packages/shylu/shylu_node/basker/src/shylubasker_order_btf.hpp b/packages/shylu/shylu_node/basker/src/shylubasker_order_btf.hpp index 9bf36d48eef8..00b0a3c43cc1 100644 --- a/packages/shylu/shylu_node/basker/src/shylubasker_order_btf.hpp +++ b/packages/shylu/shylu_node/basker/src/shylubasker_order_btf.hpp @@ -175,6 +175,9 @@ namespace BaskerNS //printf("\n"); }//if verbose + //printf( "P=[\n" ); + //for(Int j = 0; j < M.ncol; j++) printf( "%d\n",order_btf_array[j] ); + //printf( "];\n" ); /*printf(" A = [\n" ); for(Int j = 0; j < M.ncol; j++) { for(Int k = M.col_ptr[j]; k < M.col_ptr[j+1]; k++) { @@ -189,6 +192,13 @@ namespace BaskerNS permute_row(M, order_btf_array); permute_inv(vals_perm_composition, vals_order_btf_array, M.nnz); + /*printf(" B = [\n" ); + for(Int j = 0; j < M.ncol; j++) { + for(Int k = M.col_ptr[j]; k < M.col_ptr[j+1]; k++) { + printf("%d %d %.16e\n", M.row_idx[k], j, M.val[k]); + } + } + printf("];\n");*/ //================================================================ @@ -637,6 +647,7 @@ namespace BaskerNS //Short circuit, //If nblks == 1, than only BTF_A exists // NDE: In this case, vals_block_map_perm_pair is not allocated nor used - A is assigned to BTF_A directly + bool replace_zero_pivot_in = Options.replace_zero_pivot; if(nblks == 1) { #ifdef BASKER_DEBUG_ORDER_BTF @@ -760,6 +771,12 @@ namespace BaskerNS if(Options.verbose == BASKER_TRUE) { printf("Basker: blk=%d break due to size (work: %d > %d, size: %d > %d)\n",(int)blk_idx-1, (int)blk_work,(int)break_work_size, (int)blk_size,(int)break_block_size); } + if (nblks == 1) { + if(Options.verbose == BASKER_TRUE && replace_zero_pivot_in == BASKER_TRUE) { + printf("Basker: turning back replace-zero-pivot back because one block is big\n"); + Options.replace_zero_pivot = BASKER_TRUE; + } + } move_fwd = BASKER_FALSE; } //break due to end i.e. no 'large' BTF_A block for ND; only fine BTF structure @@ -771,7 +788,7 @@ namespace BaskerNS //printf("break last blk\n"); blk_idx = 0; t_size = t_size + blk_size; - scol = _btf_tabs[blk_idx]; + scol = _btf_tabs[blk_idx]; move_fwd = BASKER_FALSE; } //should not be called @@ -945,9 +962,9 @@ namespace BaskerNS if(Options.verbose == BASKER_TRUE) { printf( "\n > btf_tabs_offset = %d, btf_top_tabs_offset = %d\n", (int)btf_tabs_offset, (int)btf_top_tabs_offset ); - for (blk_idx = 0; blk_idx < btf_top_tabs_offset; blk_idx++) printf( " x %d: %d (%d)\n", (int)blk_idx, (int)(btf_tabs[blk_idx+1]-btf_tabs[blk_idx]),(int)btf_blk_work(blk_idx) ); - for (blk_idx = btf_top_tabs_offset; blk_idx < btf_tabs_offset; blk_idx++) printf( " + %d: %d (%d)\n", (int)blk_idx, (int)(_btf_tabs[blk_idx+1]-_btf_tabs[blk_idx]),(int)btf_blk_work(blk_idx) ); - for (blk_idx = btf_tabs_offset; blk_idx < nblks; blk_idx++) printf( " - %d: %d (%d)\n", (int)blk_idx, (int)(_btf_tabs[blk_idx+1]-_btf_tabs[blk_idx]),(int)btf_blk_work(blk_idx) ); + for (blk_idx = 0; blk_idx < btf_top_tabs_offset; blk_idx++) printf( " x %d: %d (%d, %d)\n", (int)blk_idx, (int)(btf_tabs[blk_idx+1]-btf_tabs[blk_idx]),(int)btf_tabs[blk_idx],(int)btf_blk_work(blk_idx) ); + for (blk_idx = btf_top_tabs_offset; blk_idx < btf_tabs_offset; blk_idx++) printf( " + %d: %d (%d, %d)\n", (int)blk_idx, (int)(_btf_tabs[blk_idx+1]-_btf_tabs[blk_idx]),(int)btf_tabs[blk_idx],(int)btf_blk_work(blk_idx) ); + for (blk_idx = btf_tabs_offset; blk_idx < nblks; blk_idx++) printf( " - %d: %d (%d, %d)\n", (int)blk_idx, (int)(_btf_tabs[blk_idx+1]-_btf_tabs[blk_idx]),(int)btf_tabs[blk_idx],(int)btf_blk_work(blk_idx) ); printf( "\n" ); } diff --git a/packages/shylu/shylu_node/basker/src/shylubasker_order_scotch.hpp b/packages/shylu/shylu_node/basker/src/shylubasker_order_scotch.hpp index c70fe3507862..e30606385847 100644 --- a/packages/shylu/shylu_node/basker/src/shylubasker_order_scotch.hpp +++ b/packages/shylu/shylu_node/basker/src/shylubasker_order_scotch.hpp @@ -235,7 +235,9 @@ namespace BaskerNS // id of the first leaf node (BF order, post_order maps from BF to ND) Int leaves_id = pow(2.0, (double)(num_levels)) - 1; - //printf( " num_levels = %d, num_doms = %d, leves_id = %d\n",num_levels,num_doms,leaves_id ); + if (Options.verbose == BASKER_TRUE) { + printf( " num_domains = %d: num_levels = %d, num_doms = %d, leves_id = %d\n",num_domains,num_levels,num_doms,leaves_id ); + } // > insert root Int num_queued = 0; @@ -297,11 +299,14 @@ namespace BaskerNS // level goes to num_leaves so that we can call ND on the final leaf nodes last_level = num_levels; } - if (Options.verbose == BASKER_TRUE) { - if (run_nd_on_leaves) { + if (run_nd_on_leaves) { + if (Options.verbose == BASKER_TRUE) { std::cout << std::endl << " + Using ND on leaves + " << std::endl; - } else if (run_amd_on_leaves) { - std::cout << std::endl << " + Using AMD on leaves + " << std::endl; + } + } else if (run_amd_on_leaves) { + MALLOC_INT_1DARRAY(BT.leaf_nnz, num_doms); + if (Options.verbose == BASKER_TRUE) { + std::cout << std::endl << " + Using AMD on leaves (# doms = " << num_doms << ") + " << std::endl; } } // -------------------------------------------------- // @@ -551,11 +556,16 @@ namespace BaskerNS for(Int i = 0; i < metis_size_k; i++) { metis_iperm_k(metis_perm_k(i)) = i; } + if (Options.verbose == BASKER_TRUE) { + std::cout << std::endl << " > Basker AMD on leaf : estimated nnz(L(" << leaf_id << ") = " << l_nnz + << " <" << std::endl << std::endl; + } info = METIS_OK; } else { std::cout << std::endl << " > Basker AMD failed < " << std::endl << std::endl; return BASKER_ERROR; // TODO: what to do here? } + BT.leaf_nnz(leaf_id) = l_nnz; } // update perm/ @@ -888,7 +898,7 @@ namespace BaskerNS sg.nz = sg.Ap[sg.m]; //printf("num self_edge: %d sg.m: %d \n", - // self_edge, sg.m); + // self_edge, sg.m); if(self_edge != (sg.m)) { BASKER_ASSERT(self_edge == (sg.m-1), @@ -990,11 +1000,11 @@ namespace BaskerNS #ifdef BASKER_DEBUG_ORDER_SCOTCH printf("FIX SCOTCH PRINT OUT\n"); printf("SCOTCH: NUM_LEVELS ASKED = %d, NUM DOMS GOT = %d, NUM TREES = %d \n", - num_levels, sg.cblk, num_trees); + num_levels, sg.cblk, num_trees); printf("\n"); printf("%d %d should blks: %f \n", - 2, ((Int)num_levels+1), - pow(2.0,((double)num_levels+1))-1); + 2, ((Int)num_levels+1), + pow(2.0,((double)num_levels+1))-1); #endif if(((sg.cblk) != pow(2.0,((double)num_levels+1))-1) || (num_trees != 1)) @@ -1028,7 +1038,7 @@ namespace BaskerNS #ifdef BASKER_DEBUG_ORDER_SCOTCH printf("\n\n Starting DEBUG COMPLETE OUT \n\n"); printf("Tree: "); - ` for(Int i = 0; i < iblks+1; i++) + for(Int i = 0; i < iblks+1; i++) { printf("%d, ", ttree(i)); } @@ -1217,11 +1227,11 @@ namespace BaskerNS Int mynum = iblks-1; otree(iblks) = -1; rec_build_tree(lvl, - lpos,rpos, - mynum, - otree); + lpos,rpos, + mynum, + otree); - + INT_1DARRAY ws; BASKER_ASSERT((iblks+1)>0, "scotch iblks 2"); MALLOC_INT_1DARRAY(ws, iblks+1); @@ -1486,7 +1496,7 @@ namespace BaskerNS ) { //printf("assign, lpos: %d rpos: %d number: %d\n", - // lpos, rpos, mynum); + // lpos, rpos, mynum); if(lvl > 0) { diff --git a/packages/shylu/shylu_node/basker/src/shylubasker_sfactor.hpp b/packages/shylu/shylu_node/basker/src/shylubasker_sfactor.hpp index c955ff952551..7a91f6c8a577 100644 --- a/packages/shylu/shylu_node/basker/src/shylubasker_sfactor.hpp +++ b/packages/shylu/shylu_node/basker/src/shylubasker_sfactor.hpp @@ -39,7 +39,7 @@ using namespace std; #endif #include "Teuchos_OrdinalTraits.hpp" -//#define BASKER_TIMER +//#define BASKER_TIMER //#define BASKER_DEBUG_SFACTOR //Functor for Kokkos @@ -76,7 +76,7 @@ namespace BaskerNS { #ifdef BASKER_KOKKOS //Int kid = (Int)(thread.league_rank()*thread.team_size()+ - // thread.team_rank()); + // thread.team_rank()); Int kid = basker->t_get_kid(thread); #endif @@ -114,7 +114,7 @@ namespace BaskerNS { #ifdef BASKER_KOKKOS //Int kid = (Int)(thread.league_rank()*thread.team_size()+ - // thread.team_rank()); + // thread.team_rank()); Int kid = basker->t_get_kid(thread); #endif printf( " * kokkos_sfactor_init_factor(%d) *\n",kid ); fflush(stdout); @@ -172,8 +172,8 @@ int Basker::sfactor() //Allocate Factorspace #ifdef BASKER_TIMER - printf(" >> kokkos_sfactor_init_factor( btf_tabs_offset = %d, allocate_nd_workspace = %d ) <<\n", - btf_tabs_offset,allocate_nd_workspace); fflush(stdout); + printf(" >> kokkos_sfactor_init_factor( btf_tabs_offset = %d, allocate_nd_workspace = %d, num_threads= %d ) <<\n", + btf_tabs_offset,allocate_nd_workspace,num_threads); fflush(stdout); #endif if(btf_tabs_offset != 0 && allocate_nd_workspace) { @@ -316,8 +316,6 @@ int Basker::sfactor() timer2.reset(); #endif - //split_num = num_threads/2; - //for(Int p =0; p < 1; ++p) if(Options.verbose == BASKER_TRUE) { printf("\n"); @@ -378,21 +376,35 @@ int Basker::sfactor() //Assign nnz here //leaf_assign_nnz(LL(blk)(0), stree, 0); //leaf_assign_nnz(LU(blk)(LU_size[blk]-1), stree, 0); - if(Options.verbose == BASKER_TRUE) - { - printf( " >> leaf_assign_nnz(LL(%d)(%d))\n",(int)blk,0); - printf( " >> leaf_assign_nnz(LU(%d)(%d))\n",(int)blk,(int)LU_size(blk)-1); - } #if defined(BASKER_TIMER) & !defined(SHYLU_BASKER_STREE_LIST) timer1.reset(); #endif - #ifdef SHYLU_BASKER_STREE_LIST - leaf_assign_nnz(LL(blk)(0), stree_p, 0); - leaf_assign_nnz(LU(blk)(LU_size(blk)-1), stree_p, 0); - #else - leaf_assign_nnz(LL(blk)(0), stree, 0); - leaf_assign_nnz(LU(blk)(LU_size(blk)-1), stree, 0); - #endif + if (!Options.run_nd_on_leaves && Options.run_amd_on_leaves) { + double fill_factor = 1.0 + BASKER_DOM_NNZ_OVER+Options.user_fill; + if(Options.verbose == BASKER_TRUE) + { + printf( " >> leaf_assign_nnz(LL(%d)(%d)) = (1.0 + %.1f + %.1f) + leaf_nnz[%d] = %d from AMD\n",(int)blk,0, + BASKER_DOM_NNZ_OVER,Options.user_fill,p,part_tree.leaf_nnz[p] ); + printf( " >> leaf_assign_nnz(LU(%d)(%d)) = (1.0 + %.1f + %.1f) + leaf_nnz[%d] = %d from AMD\n",(int)blk,(int)LU_size(blk)-1, + BASKER_DOM_NNZ_OVER,Options.user_fill,p,part_tree.leaf_nnz[p] ); + } + LL(blk)(0).nnz = part_tree.leaf_nnz[p] * fill_factor; + LU(blk)(LU_size(blk)-1).nnz = part_tree.leaf_nnz[p] * fill_factor; + global_nnz += (LL(blk)(0).nnz + LU(blk)(LU_size(blk)-1).nnz); + } else { + if(Options.verbose == BASKER_TRUE) + { + printf( " >> leaf_assign_nnz(LL(%d)(%d))\n",(int)blk,0); + printf( " >> leaf_assign_nnz(LU(%d)(%d))\n",(int)blk,(int)LU_size(blk)-1); + } + #ifdef SHYLU_BASKER_STREE_LIST + leaf_assign_nnz(LL(blk)(0), stree_p, 0); + leaf_assign_nnz(LU(blk)(LU_size(blk)-1), stree_p, 0); + #else + leaf_assign_nnz(LL(blk)(0), stree, 0); + leaf_assign_nnz(LU(blk)(LU_size(blk)-1), stree, 0); + #endif + } #if defined(BASKER_TIMER) & !defined(SHYLU_BASKER_STREE_LIST) time2 += timer1.seconds(); #endif @@ -406,8 +418,18 @@ int Basker::sfactor() std::cout << " DOMAIN BLKs done : " << dom_time << std::endl << std::endl; #endif + if(Options.verbose == BASKER_TRUE) + { + printf("\n"); + printf("\n --------------- OVER OFF-DIAGS ---------------\n"); + printf("\n"); + } for(Int p = 0; p < num_threads; ++p) { + if(Options.verbose == BASKER_TRUE) + { + printf(" ============= OFF-DIAG BLK (p=%d) ============\n",(int)p); + } //Do off diag Int blk = S(0)(p); #ifdef SHYLU_BASKER_STREE_LIST @@ -436,7 +458,7 @@ int Basker::sfactor() Int off_diag = 1; //printf( " U_blk_sfactor(AVM(%d,%d))\n",U_col,U_row ); //U_blk_sfactor(AV[U_col][U_row], stree, - // gScol(l), gSrow(glvl),0); + // gScol(l), gSrow(glvl),0); #ifdef BASKER_TIMER timer1.reset(); #endif @@ -457,7 +479,7 @@ int Basker::sfactor() //Reduce all into global (don't need in serial) //S_sfactor_reduce(AV[U_col][U_row], - // stree, gScol, gSrow); + // stree, gScol, gSrow); //Assign nnz counts for leaf off-diag //U_assign_nnz(LU(U_col)(U_row), stree, 0); @@ -493,7 +515,6 @@ int Basker::sfactor() timer.reset(); #endif - //do all the sep if(Options.verbose == BASKER_TRUE) { @@ -503,6 +524,10 @@ int Basker::sfactor() } for(Int lvl=0; lvl < tree.nlvls; lvl++) { + if(Options.verbose == BASKER_TRUE) + { + printf(" ============= SEPARATOR BLK (level=%d) ============\n",(int)lvl); + } //Number of seps in the level Int p = pow(tree.nparts, tree.nlvls-lvl-1); @@ -554,7 +579,6 @@ int Basker::sfactor() printf( " >>> -> nnz = %d\n",ALM(U_col)(U_row).nnz ); fflush(stdout); #endif - //S_assign_nnz(LL(U_col)(U_row), stree, 0); if(Options.verbose == BASKER_TRUE) { printf( " >> S_assign_nnz( LL(%d,%d) )\n",(int)U_col,(int)U_row ); fflush(stdout); @@ -612,7 +636,7 @@ int Basker::sfactor() printf("BLK: %d %d Col: %d Row: %d \n", U_col, U_row, l, pp); #endif - Int off_diag = 1; + Int off_diag = -1; // dense #ifdef SHYLU_BASKER_STREE_LIST U_blk_sfactor(AVM(U_col)(U_row), stree_p, gScol(l), gSrow(pp), off_diag); @@ -626,7 +650,7 @@ int Basker::sfactor() //Don't need in serial //S_sfactor_reduce(AV[U_col][U_row], - // stree, gScol, gSrow); + // stree, gScol, gSrow); //Assign nnz @@ -635,7 +659,7 @@ int Basker::sfactor() { printf( " ++ leaf_assign_nnz(LU(%d, %d)) fill-factor x(%d+%f = %f)\n",(int)U_col,(int)U_row, (int)BASKER_SEP_NNZ_OVER,Options.user_fill,fill_factor); printf( " ++ leaf_assign_nnz(LL(%d, %d)) fill-factor x(%d+%f = %f)\n",(int)inner_blk,(int)(l-lvl), (int)BASKER_SEP_NNZ_OVER,Options.user_fill,fill_factor); - fflush(stdout); + fflush(stdout); } #ifdef SHYLU_BASKER_STREE_LIST U_assign_nnz(LU(U_col)(U_row), stree_p, fill_factor, 0); @@ -1470,8 +1494,8 @@ int Basker::sfactor() printf("\n\n"); printf("BLK: %d %d \n", brow, bcol); printf("row: %d %d col: %d %d \n", - MV.srow, MV.nrow+MV.srow, - MV.scol, MV.ncol+MV.scol); + MV.srow, MV.nrow+MV.srow, + MV.scol, MV.ncol+MV.scol); printf("\n\n"); #endif @@ -1720,6 +1744,10 @@ int Basker::sfactor() { ST.L_row_counts(j) = 0; ST.U_col_counts(j) = 0; + } + // diagonal => square + for(Int j = 0; j < MV.ncol; j++) + { for(Int k = MV.col_ptr(j); k < MV.col_ptr(j+1); ++k) { Int i = MV.row_idx(k); if (i < j) { @@ -1732,26 +1760,59 @@ int Basker::sfactor() } } } + #ifdef BASKER_TIMER + std::cout << " >> U_blk_sfactor(diag): " << timer.seconds() << " seconds" << std::endl; + timer.reset(); + #endif } - #ifdef BASKER_TIMER - std::cout << " >> U_blk_sfactor::loop-columns : " << timer.seconds() << " seconds" << std::endl; - #endif #endif - - //Temp Patch fix - //Note Comebaske if(off_diag == 1) { - for(Int i = 0; i < MV.ncol; i++) + Int tot_nnz = 0; + for(Int j = 0; j < MV.ncol; j++) + { + #if 1 + /*{ // original + Int nnz = MV.col_ptr(j+1) - MV.col_ptr(j); + ST.L_row_counts(j) = nnz; + ST.U_col_counts(j) = nnz; + } */ + // dense after first nz in each column + Int min_i = MV.nrow; + for(Int k = MV.col_ptr(j); k < MV.col_ptr(j+1); ++k) { + Int i = MV.row_idx(k); + min_i = min(i, min_i); + } + ST.L_row_counts(j) = MV.nrow - min_i; + ST.U_col_counts(j) = MV.nrow - min_i; + #else // fully dense + ST.U_col_counts(j) = MV.nrow; + ST.L_row_counts(j) = MV.nrow; + #endif + tot_nnz += ST.L_row_counts(j); + } + #ifdef BASKER_TIMER + std::cout << " >> U_blk_sfactor::off-diag ("<< MV.nrow << " x " << MV.ncol << "): with nnz = " << tot_nnz << " => " + << double(tot_nnz) / double (MV.ncol*MV.nrow) << ", " << double(tot_nnz) / double (MV.nnz) + << ": " << timer.seconds() << " seconds" << std::endl; + timer.reset(); + #endif + } + if(off_diag == -1) + { + Int tot_nnz = 0; + for(Int j = 0; j < MV.ncol; j++) { - ST.U_col_counts(i) = MV.nrow; - ST.L_row_counts(i) = MV.nrow; + ST.U_col_counts(j) = MV.nrow; + ST.L_row_counts(j) = MV.nrow; + tot_nnz += ST.L_row_counts(j); } + #ifdef BASKER_TIMER + std::cout << " >> U_blk_sfactor::dense ("<< MV.nrow << " x " << MV.ncol << "): with nnz = " << tot_nnz << " => " << double(tot_nnz) / double (MV.ncol*MV.nrow) + << ": " << timer.seconds() << " seconds" << std::endl; + timer.reset(); + #endif } - #ifdef BASKER_TIMER - std::cout << " >> U_blk_sfactor::copy : " << timer.seconds() << " seconds" << std::endl; - timer.reset(); - #endif FREE(U_col_count); FREE(color); @@ -1994,8 +2055,9 @@ int Basker::sfactor() //Temp Patch fix //Note Comebaske - if(off_diag ==1) + if(off_diag == 1) { + printf( " U_blk_sfactor(off-diag: %d x %d)\n",MV.nrow,MV.ncol ); for(Int i = 0; i < MV.ncol; i++) { ST.U_col_counts[i] = MV.nrow; @@ -2012,43 +2074,6 @@ int Basker::sfactor() FREE(first_row); }//end U_blk_sfactor() - - template - void Basker::L_blk_sfactor - ( - BASKER_MATRIX &MV, - BASKER_SYMBOLIC_TREE &ST, - INT_1DARRAY gcol, - INT_1DARRAY grow - ) - { - printf("Basker: This L_blk_sfactor algorithm is not implemented\n"); - //Algorithm - //You can either use the Row-count method or - //Assume same as U_blk for symmtric case. - //Note, Very unsymmtric and HUND will most likely not - //Need this called as we will use the QR on nxns - }//end L_blk_sfactor() - - - template - void Basker::L_blk_sfactor - ( - BASKER_MATRIX_VIEW &MV, - BASKER_SYMBOLIC_TREE &ST, - INT_1DARRAY gcol, - INT_1DARRAY grow - ) - { - printf("Basker: This L_blk_sfactor algorithm is not implemented\n"); - //Algorithm - //You can either use the Row-count method or - //Assume same as U_blk for symmtric case. - //Note, Very unsymmtric and HUND will most likely not - //Need this called as we will use the QR on nxns - }//end L_blk_sfactor() - - template void Basker::S_sfactor_reduce ( @@ -2095,9 +2120,7 @@ int Basker::sfactor() //Give a = nnz(L(:,1)) and b = nnz(U(1,:)) //If a*b == (size-size)^2 .... adjust padding - //Int brow = MV.srow; //Not used - //Int bcol = MV.scol; //Not used - + #if 0 //Find nnz L(:,1) Int nnz_c = 0; for(Int i = MV.srow; i < (MV.srow+MV.nrow); i++) @@ -2108,7 +2131,7 @@ int Basker::sfactor() } } nnz_c += 1; - + #endif #ifdef BASKER_DEBUG_SFACTOR printf("S - nnz(L(:,1)): %d \n", nnz_c); #endif @@ -2141,8 +2164,8 @@ int Basker::sfactor() nnz_S = Teuchos::OrdinalTraits::max()/2; } - #ifdef BASKER_DEBUG_SFACTOR - printf("Snnz: %d \n", nnz_S); + #ifdef BASKER_TIMER + printf(" > Snnz: %d \n", nnz_S); #endif ST.init_S_col_counts(1); @@ -2276,11 +2299,16 @@ int Basker::sfactor() t_nnz += ST.col_counts[i]; } else { // let's just hope it is enough, if overflow + t_nnz = Int_MAX; + #ifdef BASKER_TIMER + printf( " - overflow nnz = %ld (%d/%d)\n",t_nnz,i,M.ncol ); + for (Int ii = 0; ii <= i; ii++) printf( " * col_counts[%d] = %ld\n",ii,ST.col_counts[ii] ); + #endif break; } } #ifdef BASKER_TIMER - printf(" > leaf nnz: (%ld + %ld) / 2 = %ld\n", (long)t_nnz,(long)M.ncol,(long)(t_nnz+M.ncol)/2); + printf(" > leaf nnz: (t_nnz = %ld + ncol = %ld) / 2 = %ld\n", (long)t_nnz,(long)M.ncol,(long)(t_nnz+M.ncol)/2); #endif t_nnz = long(t_nnz+M.ncol)/2; @@ -2321,35 +2349,48 @@ int Basker::sfactor() Int option ) { - if(option == 0) + if(option == 0 || option == 1) { const Int Int_MAX = std::numeric_limits::max(); - Int t_nnz = 0; - for(Int i = 0; i < M.ncol; i++) - { - if (t_nnz <= Int_MAX-ST.U_col_counts[i]) { - t_nnz += ST.U_col_counts[i]; - } else { - // let's just hope it is enough, if overflow - break; - } - } - - #ifdef BASKER_TIMER - printf("U_assing_nnz: %ld \n", t_nnz); - #endif - - //double fill_factor = 1.05; - Int temp = min(M.nrow*M.ncol, Int(fill_factor*t_nnz)); - if (temp >= t_nnz) { - M.nnz = temp; + Int t_nnz = 0; + if (option == 1) { + // dense + t_nnz = (M.nrow*M.ncol); } else { + Int k_nnz = 0; + for(Int i = 0; i < M.ncol; i++) + { + if (k_nnz <= Int_MAX-ST.U_col_counts[i]) { + k_nnz += ST.U_col_counts[i]; + } else { + // let's just hope it is enough, if overflow + k_nnz = Int_MAX; + #ifdef BASKER_TIMER + printf( " - overflow U_nnz = %ld (%d/%d)\n",k_nnz,i,M.ncol ); + for (Int ii = 0; ii <= i; ii++) printf( " * U_col_counts[%d] = %ld\n",ii,ST.U_col_counts[ii] ); + #endif + break; + } + } + t_nnz = Int(fill_factor*double(k_nnz)); + if (fill_factor > 1.0 && k_nnz > t_nnz) { + t_nnz = k_nnz; + } + Int mn = max(0,M.nrow*M.ncol); + if (mn > 0 && mn < t_nnz) { + t_nnz = mn; + } M.nnz = t_nnz; + #ifdef BASKER_TIMER + printf("U_assing_nnz: %ld min(%d, %d)-> %ld\n", k_nnz,M.nrow*M.ncol, Int(fill_factor*double(k_nnz)), M.nnz); + #endif } if (global_nnz <= Int_MAX-t_nnz) { // let's just hope it is enough, if overflow global_nnz += t_nnz; + } else { + global_nnz = Int_MAX; } #if 0 printf( " debug: set U.nnz = 0 to force realloc\n" ); @@ -2358,8 +2399,8 @@ int Basker::sfactor() #endif if(Options.verbose == BASKER_TRUE) { - printf("U_assing with elbow global_nnz = %ld, t_nnz = %ld (fill_factor = %f), M.nnz = %ld (%ld x %ld)\n", - (long)global_nnz,(long)t_nnz, fill_factor, (long)M.nnz,(long)M.nrow,(long)M.ncol); + printf("U_assing with elbow global_nnz = %ld, t_nnz = %ld (fill_factor = %f), M.nnz = %ld (%ld x %ld) -> %.2f\n", + (long)global_nnz,(long)t_nnz, fill_factor, (long)M.nnz,(long)M.nrow,(long)M.ncol, ((double)M.nnz)/((double)(M.nrow*M.ncol))); } } }//end assign_upper_nnz @@ -2386,6 +2427,11 @@ int Basker::sfactor() t_nnz += ST.L_row_counts[i]; } else { // let's just hope it is enough, if overflow + t_nnz = Int_MAX; + #ifdef BASKER_TIMER + printf( " - overflow L_nnz = %ld (%d/%d)\n",t_nnz,i,M.ncol ); + for (Int ii = 0; ii <= i; ii++) printf( " * L_col_counts[%d] = %ld\n",ii,ST.L_row_counts[ii] ); + #endif break; } } @@ -2394,9 +2440,8 @@ int Basker::sfactor() printf("L_assign_nnz: %ld \n", t_nnz); #endif - // double fill_factor = 2.05; double old_nnz = M.nnz; - Int temp = min(M.nrow*M.ncol, Int(fill_factor*t_nnz)); + Int temp = min(M.nrow*M.ncol, Int(fill_factor*double(t_nnz))); if (temp >= t_nnz) { M.nnz = temp; } else { @@ -2432,7 +2477,7 @@ int Basker::sfactor() if(option == 0) { M.nnz = ST.S_col_counts(0); - #ifdef BASKER_DEBUG_SFACTOR + #ifdef BASKER_TIMER printf("S_assign_nnz: %ld \n", M.nnz); #endif @@ -2443,7 +2488,7 @@ int Basker::sfactor() } if(Options.verbose == BASKER_TRUE) { - printf("S_assign elbow global_nnz = %ld, M.nnz = %ld + 2\n", (long)global_nnz, (long)M.nnz); + printf("S_assign elbow global_nnz = %ld, M.nnz = %ld + 2 (%d x %d)\n", (long)global_nnz, (long)M.nnz, (int)M.nrow,(int)M.ncol); } if (M.nnz <= Int_MAX - 2) { M.nnz += 2; @@ -2461,9 +2506,9 @@ int Basker::sfactor() #ifdef BASKER_DEBUG_SFACTOR //printf("Test btf_last_dense \n"); //printf("btf_tabs_offset: %d col: %d \n", - // btf_tabs_offset, btf_tabs[btf_tabs_offset]); + // btf_tabs_offset, btf_tabs[btf_tabs_offset]); //printf("number of blks: %d \n", - // btf_nblks-btf_tabs_offset); + // btf_nblks-btf_tabs_offset); #endif #ifdef BASKER_TIMER printf( " > btf_last_dense(%s) <\n",(flag ? "true" : "false") ); fflush(stdout); @@ -2520,7 +2565,7 @@ int Basker::sfactor() //Malloc L and U #ifdef BASKER_DEBUG_SFACTOR printf("btf_nblks %d btf_tabs_offset %d \n", - btf_nblks, btf_tabs_offset); + btf_nblks, btf_tabs_offset); #endif Int nblks_left = btf_nblks - btf_tabs_offset; diff --git a/packages/shylu/shylu_node/basker/src/shylubasker_structs.hpp b/packages/shylu/shylu_node/basker/src/shylubasker_structs.hpp index ef1e29d597e4..706066f3011b 100644 --- a/packages/shylu/shylu_node/basker/src/shylubasker_structs.hpp +++ b/packages/shylu/shylu_node/basker/src/shylubasker_structs.hpp @@ -117,7 +117,7 @@ namespace BaskerNS //Used to store information about the tree template struct basker_tree - { + { BASKER_INLINE basker_tree() { @@ -235,6 +235,7 @@ namespace BaskerNS INT_1DARRAY rowptr; INT_1DARRAY child; INT_1DARRAY sibling; + INT_1DARRAY leaf_nnz; };//end basker_tree diff --git a/packages/shylu/shylu_node/basker/src/shylubasker_thread.hpp b/packages/shylu/shylu_node/basker/src/shylubasker_thread.hpp index 6e4d1554c754..161be9122f49 100644 --- a/packages/shylu/shylu_node/basker/src/shylubasker_thread.hpp +++ b/packages/shylu/shylu_node/basker/src/shylubasker_thread.hpp @@ -127,6 +127,12 @@ namespace BaskerNS Int ltask = (l*ntasks) + task; //printf("Enter Domain Barrier. leader=%d, lsize=%d (%d:%d), my_id=%d, task=%d, k=%d, l=%d -> ltask=%d\n", // my_leader, lsize, my_leader,my_leader+lsize-1, my_id, task, k, l, ltask); fflush(stdout); + #if 0 // debug + if (token[my_id][ltask] == k) { + printf( "\n BarrierDomain already k ??\n " ); + exit(0); + } + #endif token[my_id][ltask] = k; for(Int dp = (my_leader+lsize)-1; dp >= my_leader; dp--) { @@ -179,7 +185,7 @@ namespace BaskerNS //Atomic BaskerBarrier(volatile Int &value_in, volatile Int &value_out, - const Int l_size ) + const Int l_size ) { //jdb value ->value_in atomic_barrier(value_in,l_size); @@ -278,7 +284,6 @@ namespace BaskerNS BASKER_NO_OP; } } - }; //end BaskerBarrier diff --git a/packages/shylu/shylu_node/basker/src/shylubasker_types.hpp b/packages/shylu/shylu_node/basker/src/shylubasker_types.hpp index f57447b10906..9d30b714553d 100644 --- a/packages/shylu/shylu_node/basker/src/shylubasker_types.hpp +++ b/packages/shylu/shylu_node/basker/src/shylubasker_types.hpp @@ -73,7 +73,7 @@ enum BASKER_MATCHING_CODE #define BASKER_BTF_PRUNE_SIZE 100 #define BASKER_DOM_NNZ_OVER 1.0 //Added to control estimate for DOM blocks -#define BASKER_SEP_NNZ_OVER 3.0 //Added to control estimate for SEP blocks +#define BASKER_SEP_NNZ_OVER 2.0 //Added to control estimate for SEP blocks enum BASKER_INCOMPLETE_CODE { diff --git a/packages/shylu/shylu_node/basker/src/shylubasker_util.hpp b/packages/shylu/shylu_node/basker/src/shylubasker_util.hpp index 455b76004a98..aae9b141aaf8 100644 --- a/packages/shylu/shylu_node/basker/src/shylubasker_util.hpp +++ b/packages/shylu/shylu_node/basker/src/shylubasker_util.hpp @@ -464,9 +464,9 @@ namespace BaskerNS for(Int row = 0; row < LL_size(b); row++) { - #ifdef BASKER_DEBUG_INIT - printf("L Factor Init: %d %d , kid: %d, nnz: %ld \n", - b, row, kid, LL(b)(row).nnz); + #ifdef BASKER_TIMER + printf("L Factor Init: L(%d %d) , kid: %d, nnz = %ld (%d x %d)\n", + b, row, kid, LL(b)(row).nnz, LL(b)(row).nrow,LL(b)(row).ncol); #endif #ifdef BASKER_TIMER diff --git a/packages/stk/CHANGELOG.md b/packages/stk/CHANGELOG.md index 6160baab2c76..514f7e831a1a 100644 --- a/packages/stk/CHANGELOG.md +++ b/packages/stk/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG +5.21.6-1 (STK_VERSION 5210601) 10/31/2024 + stk_mesh, stk_search: more fixes for HIP unified and Cuda no-uvm builds + 5.21.6 (STK_VERSION 5210600) 10/25/2024 stk_search: fix build-error (instantiation error for morton_lbvh_search) for gcc 13.2 stk_util: added parallel/OutputStreams.hpp diff --git a/packages/stk/CMakeLists.txt b/packages/stk/CMakeLists.txt index f9ff77e06c1c..fa8d3c733a63 100644 --- a/packages/stk/CMakeLists.txt +++ b/packages/stk/CMakeLists.txt @@ -32,9 +32,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -cmake_minimum_required(VERSION 3.16 FATAL_ERROR) +cmake_minimum_required(VERSION 3.23 FATAL_ERROR) -message("starting STK cmake configuration, CMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR}") +message("Starting STK cmake configuration, CMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR}") option(STK_BUILT_FOR_SIERRA "Enable SIERRA capability" OFF) set(SIERRA_MIGRATION ${STK_BUILT_FOR_SIERRA} CACHE BOOL "Enable SIERRA capability") @@ -46,14 +46,14 @@ endif() IF(COMMAND TRIBITS_PACKAGE_DECL) SET(HAVE_STK_Trilinos ON) TRIBITS_PACKAGE_DECL(STK) - MESSAGE("*** Building STK as a Trilinos package. ***") + message("*** Building STK as a Trilinos package. ***") ELSE() SET(HAVE_STK_Trilinos OFF) project(STK CXX Fortran) SET(PACKAGE_NAME "STK") - MESSAGE("*** Building STK as a stand-alone cmake package. ***") + message("*** Building STK as a stand-alone cmake package. ***") ENDIF() SET(STK_TOPLEVEL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) @@ -87,9 +87,9 @@ endif() STK_ADD_DEBUG_AND_DEPRECATED_OPTIONS() -MESSAGE("\nPROJECT_NAME: '${PROJECT_NAME}'") -MESSAGE("PACKAGE_NAME: '${PACKAGE_NAME}'") -MESSAGE("${PACKAGE_NAME}_SOURCE_DIR: '${${PACKAGE_NAME}_SOURCE_DIR}'\n") +message("\nPROJECT_NAME: '${PROJECT_NAME}'") +message("PACKAGE_NAME: '${PACKAGE_NAME}'") +message("${PACKAGE_NAME}_SOURCE_DIR: '${${PACKAGE_NAME}_SOURCE_DIR}'\n") IF (HAVE_STK_Trilinos) SET(STK_HAVE_KOKKOS ON) @@ -110,12 +110,12 @@ ELSE() IF(DEFINED STK_ENABLE_MPI) IF(STK_ENABLE_MPI) - MESSAGE("MPI requested via STK_ENABLE_MPI=ON") + message("MPI requested via STK_ENABLE_MPI=ON") ELSE() - MESSAGE("MPI disabled via STK_ENABLE_MPI=OFF") + message("MPI disabled via STK_ENABLE_MPI=OFF") ENDIF() ELSE() - MESSAGE("MPI defaulting to off. (STK_ENABLE_MPI not defined)") + message("MPI defaulting to off. (STK_ENABLE_MPI not defined)") ENDIF() IF(STK_ENABLE_MPI) @@ -125,36 +125,51 @@ ELSE() include_directories(SYSTEM ${MPI_INCLUDE_PATH}) message("MPI_INCLUDE_PATH: ${MPI_INCLUDE_PATH}") ELSE() - MESSAGE(FATAL_ERROR "MPI enabled by '-DSTK_ENABLE_MPI' but not found.") + message(FATAL_ERROR "MPI enabled by '-DSTK_ENABLE_MPI' but not found.") ENDIF() ELSE() - MESSAGE("Building serial without MPI. (To enable MPI, use '-DSTK_ENABLE_MPI:BOOL=ON')") + message("Building serial without MPI. (To enable MPI, use '-DSTK_ENABLE_MPI:BOOL=ON')") ENDIF() ENDIF() -find_package(ArborX QUIET) -if(TARGET ArborX::ArborX) - MESSAGE("Found ArborX, making it available within stk") - SET(STK_HAS_ARBORX ON) +IF (STK_ENABLE_ARBORX OR (NOT HAVE_STK_Trilinos)) + if (HAVE_STK_Trilinos) + message("Caution: when building in Trilinos with ArborX enabled, Kokkos versions need to be consistent.") + endif() + find_package(ArborX QUIET) + if(TARGET ArborX::ArborX) + message("Found ArborX, making it available for stk search") + SET(STK_HAS_ARBORX ON) + else() + message("Optional search library ArborX is not enabled.") + endif() else() - MESSAGE("Optional search library ArborX is not enabled.") + message("Optional search library ArborX is not enabled.") endif() +stk_check_fp_handling() + if(NOT HAVE_STK_Trilinos) - find_package(SEACAS) + find_package(SEACAS QUIET) endif() if(SEACAS_ENABLE_SEACASIoss) message("Enabling stk usage of SEACASIoss") SET(STK_HAS_SEACAS_IOSS ON) +else() + message("Optional SEACASIoss usage not enabled") endif() if(SEACAS_ENABLE_SEACASExodus) message("Enabling stk usage of SEACASExodus") SET(STK_HAS_SEACAS_EXODUS ON) +else() + message("Optional SEACASExodus usage not enabled") endif() if(SEACAS_ENABLE_SEACASNemesis) message("Enabling stk usage of SEACASNemesis") SET(STK_HAS_SEACAS_NEMESIS ON) +else() + message("Optional SEACASNemesis usage not enabled") endif() if (Trilinos_ENABLE_Intrepid2) @@ -206,11 +221,11 @@ ELSEIF("${FC_FN_UNDERSCORE}" STREQUAL "UNDER") ELSEIF("${FC_FN_UNDERSCORE}" STREQUAL "SECOND_UNDER") SET(FORTRAN_TWO_UNDERSCORES ON) ELSE() - MESSAGE("Could not determine the Fortran mangling; defaulting to one underscore.") + message("Could not determine the Fortran mangling; defaulting to one underscore.") SET(FORTRAN_ONE_UNDERSCORE ON) ENDIF() -MESSAGE("\nCMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") +message("\nCMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") STK_CONFIGURE_FILE(STK_Trilinos_config.h) diff --git a/packages/stk/cmake/STK_Trilinos_config.h.in b/packages/stk/cmake/STK_Trilinos_config.h.in index 40aea3c9cd45..dcd83299ed83 100644 --- a/packages/stk/cmake/STK_Trilinos_config.h.in +++ b/packages/stk/cmake/STK_Trilinos_config.h.in @@ -80,6 +80,9 @@ #cmakedefine FORTRAN_TWO_UNDERSCORES #endif +#cmakedefine STK_HAVE_FP_EXCEPT +#cmakedefine STK_HAVE_FP_ERRNO + #cmakedefine SIERRA_MIGRATION #cmakedefine STK_16BIT_UPWARDCONN_INDEX_TYPE diff --git a/packages/stk/cmake/fperrno/fperrno_test.cpp b/packages/stk/cmake/fperrno/fperrno_test.cpp new file mode 100644 index 000000000000..ea77ba40b8d3 --- /dev/null +++ b/packages/stk/cmake/fperrno/fperrno_test.cpp @@ -0,0 +1,23 @@ + +#include +#include +#include + +int main(int argc, char** argv) +{ + bool haveFpErrno = false; + if (math_errhandling & MATH_ERRNO) { + [[maybe_unused]] auto result = std::log(0.0); + if (errno == ERANGE) { + haveFpErrno = true; + std::cout<<"ON"; //no newline, this output will set a cmake variable + } + } + + if (!haveFpErrno) { + std::cout<<"OFF"; + } + + return 0; +} + diff --git a/packages/stk/cmake/fpexcept/fpexcept_test.cpp b/packages/stk/cmake/fpexcept/fpexcept_test.cpp new file mode 100644 index 000000000000..1532ceb60c25 --- /dev/null +++ b/packages/stk/cmake/fpexcept/fpexcept_test.cpp @@ -0,0 +1,23 @@ + +#include +#include +#include + +int main(int argc, char** argv) +{ + bool haveFpExcept = false; + if (math_errhandling & MATH_ERREXCEPT) { + [[maybe_unused]] auto result = std::log(0.0); + if (std::fetestexcept(FE_DIVBYZERO)) { + haveFpExcept = true; + std::cout<<"ON"; //no newline, this output will set a cmake variable + } + } + + if (!haveFpExcept) { + std::cout<<"OFF"; + } + + return 0; +} + diff --git a/packages/stk/cmake/stk_wrappers.cmake b/packages/stk/cmake/stk_wrappers.cmake index 8a88fa9aba8c..f141f6f3c0f8 100644 --- a/packages/stk/cmake/stk_wrappers.cmake +++ b/packages/stk/cmake/stk_wrappers.cmake @@ -17,6 +17,35 @@ macro(STK_CONFIGURE_FILE filename) endif() endmacro() +function(stk_check_fp_handling) +# +# The following try_run commands use syntax that is supposed to work for +# cmake versions older than 3.25, as stated in cmake documentation +# here: https://cmake.org/cmake/help/latest/command/try_run.html +# As of Nov 8, 2024, trilinos and stk require cmake 3.23 +# + message("calling try_run with bindir=${CMAKE_CURRENT_BINARY_DIR}/fpexcept, srcfile=${${PACKAGE_NAME}_SOURCE_DIR}/cmake/fpexcept/fpexcept_test.cpp") + try_run(RUN_RESULT COMPILE_RESULT + ${CMAKE_CURRENT_BINARY_DIR}/fpexcept + ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/fpexcept/fpexcept_test.cpp + RUN_OUTPUT_VARIABLE FP_RESULT) + + message("FP-EXCEPT-CHECK COMPILE_RESULT: ${COMPILE_RESULT}") + message("FP-EXCEPT-CHECK RUN_RESULT: ${RUN_RESULT}") + set(STK_HAVE_FP_EXCEPT ${FP_RESULT} CACHE BOOL "") + message("STK_HAVE_FP_EXCEPT: ${STK_HAVE_FP_EXCEPT}") + + try_run(RUN_RESULT COMPILE_RESULT + ${CMAKE_CURRENT_BINARY_DIR}/fperrno + ${${PACKAGE_NAME}_SOURCE_DIR}/cmake/fperrno/fperrno_test.cpp + RUN_OUTPUT_VARIABLE FP_RESULT) + + message("FP-ERRNO-CHECK COMPILE_RESULT: ${COMPILE_RESULT}") + message("FP-ERRNO-CHECK RUN_RESULT: ${RUN_RESULT}") + set(STK_HAVE_FP_ERRNO ${FP_RESULT} CACHE BOOL "") + message("STK_HAVE_FP_ERRNO: ${STK_HAVE_FP_ERRNO}") +endfunction() + function(stk_process_enables) message("******** Begin stk_process_enables ******") if(STK_ENABLE_ALL) diff --git a/packages/stk/stk_expreval/stk_expreval/Eval.cpp b/packages/stk/stk_expreval/stk_expreval/Eval.cpp index ae20873d80d0..21f5f0a61832 100644 --- a/packages/stk/stk_expreval/stk_expreval/Eval.cpp +++ b/packages/stk/stk_expreval/stk_expreval/Eval.cpp @@ -46,6 +46,7 @@ Eval::Eval(VariableMap::Resolver & resolver, const std::string & expression, Var m_expression(expression), m_syntaxStatus(false), m_parseStatus(false), + m_fpErrorBehavior(FPErrorBehavior::Warn), m_headNode(nullptr), m_arrayOffsetType(arrayOffsetType), m_parsedEval(nullptr) @@ -58,6 +59,7 @@ Eval::Eval(const std::string & expression, Variable::ArrayOffset arrayOffsetType m_expression(expression), m_syntaxStatus(false), m_parseStatus(false), + m_fpErrorBehavior(FPErrorBehavior::Warn), m_headNode(nullptr), m_arrayOffsetType(arrayOffsetType), m_parsedEval(nullptr) diff --git a/packages/stk/stk_expreval/stk_expreval/Eval.hpp b/packages/stk/stk_expreval/stk_expreval/Eval.hpp index 57882db67167..4935b0010a2c 100644 --- a/packages/stk/stk_expreval/stk_expreval/Eval.hpp +++ b/packages/stk/stk_expreval/stk_expreval/Eval.hpp @@ -57,6 +57,12 @@ class Eval public: typedef std::set UndefinedFunctionSet; + enum class FPErrorBehavior { + Ignore, + Warn, + Error + }; + Eval(VariableMap::Resolver &resolver = VariableMap::getDefaultResolver(), const std::string &expr = "", const Variable::ArrayOffset arrayOffsetType = Variable::ZERO_BASED_INDEX); @@ -113,6 +119,10 @@ class Eval UndefinedFunctionSet &getUndefinedFunctionSet() { return m_undefinedFunctionSet; } + void set_fp_error_behavior(FPErrorBehavior flag) { m_fpErrorBehavior = flag; } + + FPErrorBehavior get_fp_error_behavior() const { return m_fpErrorBehavior; } + bool getSyntaxStatus() const { return m_syntaxStatus; } bool getParseStatus() const { return m_parseStatus; } @@ -198,6 +208,7 @@ class Eval std::string m_expression; bool m_syntaxStatus; bool m_parseStatus; + FPErrorBehavior m_fpErrorBehavior; Node* m_headNode; std::vector> m_nodes; diff --git a/packages/stk/stk_expreval/stk_expreval/NgpNode.cpp b/packages/stk/stk_expreval/stk_expreval/NgpNode.cpp index b24c9dacf7be..6aca63f58286 100644 --- a/packages/stk/stk_expreval/stk_expreval/NgpNode.cpp +++ b/packages/stk/stk_expreval/stk_expreval/NgpNode.cpp @@ -34,6 +34,7 @@ #include "stk_expreval/NgpNode.hpp" #include "stk_expreval/Function.hpp" +#include "stk_expreval/Eval.hpp" namespace stk { namespace expreval { @@ -47,7 +48,8 @@ NgpNode::NgpNode(const Node& node) m_ternaryFalseNextNodeIndex(node.m_ternaryFalseNextNodeIndex), m_leftNodeIndex((node.m_left != nullptr) ? node.m_left->m_currentNodeIndex : -1), m_rightNodeIndex((node.m_right != nullptr) ? node.m_right->m_currentNodeIndex : -1), - m_ternaryOtherNodeIndex((node.m_ternaryOther != nullptr) ? node.m_ternaryOther->m_currentNodeIndex : -1) + m_ternaryOtherNodeIndex((node.m_ternaryOther != nullptr) ? node.m_ternaryOther->m_currentNodeIndex : -1), + m_fpErrorBehavior(node.m_owner->get_fp_error_behavior()) { if (m_opcode == OPCODE_CONSTANT) { m_data.constant.value = node.m_data.constant.value; diff --git a/packages/stk/stk_expreval/stk_expreval/NgpNode.hpp b/packages/stk/stk_expreval/stk_expreval/NgpNode.hpp index d57c16746808..bde87345c68a 100644 --- a/packages/stk/stk_expreval/stk_expreval/NgpNode.hpp +++ b/packages/stk/stk_expreval/stk_expreval/NgpNode.hpp @@ -36,10 +36,12 @@ #define NGPNODE_HPP #include "Kokkos_Core.hpp" +#include "stk_expreval/NgpNode.hpp" #include "stk_util/ngp/NgpSpaces.hpp" #include "stk_expreval/Variable.hpp" #include "stk_expreval/Node.hpp" #include "stk_expreval/Function.hpp" +#include "stk_expreval/Eval.hpp" namespace stk { namespace expreval { @@ -64,7 +66,8 @@ class NgpNode m_ternaryFalseNextNodeIndex(-1), m_leftNodeIndex(-1), m_rightNodeIndex(-1), - m_ternaryOtherNodeIndex(-1) + m_ternaryOtherNodeIndex(-1), + m_fpErrorBehavior(Eval::FPErrorBehavior::Error) {} explicit NgpNode(const Node& node); @@ -78,6 +81,17 @@ class NgpNode KOKKOS_DEFAULTED_FUNCTION ~NgpNode() = default; +#define checkNgpNodeFPError(val, name) \ + { \ + do { \ + if (m_fpErrorBehavior == stk::expreval::Eval::FPErrorBehavior::Warn && !std::isfinite(val)) { \ + printf("error in expression evaluator function " name ": " __FILE__ ": " LINE_STRING); \ + } else if (m_fpErrorBehavior == stk::expreval::Eval::FPErrorBehavior::Error && !std::isfinite(val)) { \ + STK_NGP_ThrowErrorMsg("error in expression evaluator function " name); \ + } \ + } while (false); \ + } + template KOKKOS_FUNCTION double @@ -106,11 +120,15 @@ class NgpNode break; } case OPCODE_EXPONENIATION: { - setResult(resultBuffer) = std::pow(get_left_node()->getResult(resultBuffer),get_right_node()->getResult(resultBuffer)); + double val = std::pow(get_left_node()->getResult(resultBuffer),get_right_node()->getResult(resultBuffer)); + checkNgpNodeFPError(val, "std::pow"); + setResult(resultBuffer) = val; break; } case OPCODE_DIVIDE: { - setResult(resultBuffer) = get_left_node()->getResult(resultBuffer)/get_right_node()->getResult(resultBuffer); + double val = get_left_node()->getResult(resultBuffer)/get_right_node()->getResult(resultBuffer); + checkNgpNodeFPError(val, "division operator"); + setResult(resultBuffer) = val; break; } case OPCODE_MODULUS: { @@ -275,6 +293,7 @@ class NgpNode int m_leftNodeIndex; int m_rightNodeIndex; int m_ternaryOtherNodeIndex; + Eval::FPErrorBehavior m_fpErrorBehavior; KOKKOS_FUNCTION double evaluate_function(int argumentCount, double* arguments) const @@ -357,14 +376,18 @@ class NgpNode } case FunctionType::POW : { if (argumentCount == 2) { - return std::pow(arguments[0], arguments[1]); + double val = std::pow(arguments[0], arguments[1]); + checkNgpNodeFPError(val, "pow"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for pow function"); break; } case FunctionType::SQRT : { if (argumentCount == 1) { - return std::sqrt(arguments[0]); + double val = std::sqrt(arguments[0]); + checkNgpNodeFPError(val, "sqrt"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for sqrt function"); break; @@ -378,14 +401,18 @@ class NgpNode } case FunctionType::LN : { if (argumentCount == 1) { - return std::log(arguments[0]); + double val = std::log(arguments[0]); + checkNgpNodeFPError(val, "ln"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for ln or log function"); break; } case FunctionType::LOG10 : { if (argumentCount == 1) { - return std::log10(arguments[0]); + double val = std::log10(arguments[0]); + checkNgpNodeFPError(val, "log10"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for log10 function"); break; @@ -427,14 +454,18 @@ class NgpNode } case FunctionType::ASIN : { if (argumentCount == 1) { - return std::asin(arguments[0]); + double val = std::asin(arguments[0]); + checkNgpNodeFPError(val, "asin"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for asin function"); break; } case FunctionType::ACOS : { if (argumentCount == 1) { - return std::acos(arguments[0]); + double val = std::acos(arguments[0]); + checkNgpNodeFPError(val, "acos"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for acos function"); break; @@ -476,35 +507,45 @@ class NgpNode } case FunctionType::ASINH : { if (argumentCount == 1) { - return std::asinh(arguments[0]); + double val = std::asinh(arguments[0]); + checkNgpNodeFPError(val, "asinh"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for asinh function"); break; } case FunctionType::ACOSH : { if (argumentCount == 1) { - return std::acosh(arguments[0]); + double val = std::acosh(arguments[0]); + checkNgpNodeFPError(val, "acosh"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for acosh function"); break; } case FunctionType::ATANH : { if (argumentCount == 1) { - return std::atanh(arguments[0]); + double val = std::atanh(arguments[0]); + checkNgpNodeFPError(val , "atanh"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for atanh function"); break; } case FunctionType::ERF : { if (argumentCount == 1) { - return std::erf(arguments[0]); + double val = std::erf(arguments[0]); + checkNgpNodeFPError(val, "erf"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for erf function"); break; } case FunctionType::ERFC : { if (argumentCount == 1) { - return std::erfc(arguments[0]); + double val = std::erfc(arguments[0]); + checkNgpNodeFPError(val, "erfc"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for erfc function"); break; @@ -546,62 +587,82 @@ class NgpNode } case FunctionType::CYCLOIDAL_RAMP : { if (argumentCount == 3) { - return cycloidal_ramp(arguments[0], arguments[1], arguments[2]); + double val = cycloidal_ramp(arguments[0], arguments[1], arguments[2]); + checkNgpNodeFPError(val, "cycloidal_ramp"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for cycloidal_ramp function"); break; } case FunctionType::COS_RAMP : { if (argumentCount == 1) { - return cosine_ramp1(arguments[0]); + double val = cosine_ramp1(arguments[0]); + checkNgpNodeFPError(val, "cosine_ramp1"); + return val; } else if (argumentCount == 2) { - return cosine_ramp2(arguments[0], arguments[1]); + double val = cosine_ramp2(arguments[0], arguments[1]); + checkNgpNodeFPError(val, "cosine_ramp2"); + return val; } else if (argumentCount == 3) { - return cosine_ramp3(arguments[0], arguments[1], arguments[2]); + double val = cosine_ramp3(arguments[0], arguments[1], arguments[2]); + checkNgpNodeFPError(val, "cosine_ramp3"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for cos_ramp or cosine_ramp function"); break; } case FunctionType::LINEAR_RAMP : { if (argumentCount == 3) { - return linear_ramp3(arguments[0], arguments[1], arguments[2]); + double val = linear_ramp3(arguments[0], arguments[1], arguments[2]); + checkNgpNodeFPError(val, "linear_ramp3"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for linear_ramp function"); break; } case FunctionType::HAVERSINE_PULSE : { if (argumentCount == 3) { - return haversine_pulse(arguments[0], arguments[1], arguments[2]); + double val = haversine_pulse(arguments[0], arguments[1], arguments[2]); + checkNgpNodeFPError(val, "haversine_pulse"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for haversine_pulse function"); break; } case FunctionType::POINT2D : { if (argumentCount == 4) { - return point_2(arguments[0], arguments[1], arguments[2], arguments[3]); + double val = point_2(arguments[0], arguments[1], arguments[2], arguments[3]); + checkNgpNodeFPError(val, "point_2d"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for pulse_2 function"); break; } case FunctionType::POINT3D : { if (argumentCount == 5) { - return point_3(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]); + double val = point_3(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]); + checkNgpNodeFPError(val, "point_3d"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for pulse_3 function"); break; } case FunctionType::EXPONENTIAL_PDF : { if (argumentCount == 2) { - return exponential_pdf(arguments[0], arguments[1]); + double val = exponential_pdf(arguments[0], arguments[1]); + checkNgpNodeFPError(val, "exponential_pdf"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for exponential_pdf function"); break; } case FunctionType::LOG_UNIFORM_PDF : { if (argumentCount == 3) { - return log_uniform_pdf(arguments[0], arguments[1], arguments[2]); + double val = log_uniform_pdf(arguments[0], arguments[1], arguments[2]); + checkNgpNodeFPError(val, "log_uniform_pdf"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for log_uniform_pdf function"); break; @@ -615,14 +676,18 @@ class NgpNode } case FunctionType::WEIBULL_PDF : { if (argumentCount == 3) { - return weibull_pdf(arguments[0], arguments[1], arguments[2]); + double val = weibull_pdf(arguments[0], arguments[1], arguments[2]); + checkNgpNodeFPError(val, "weibull_pdf"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for weibull_pdf function"); break; } case FunctionType::GAMMA_PDF : { if (argumentCount == 3) { - return gamma_pdf(arguments[0], arguments[1], arguments[2]); + double val = gamma_pdf(arguments[0], arguments[1], arguments[2]); + checkNgpNodeFPError(val, "gamma_pdf"); + return val; } STK_NGP_ThrowErrorMsg("Incorrect number of arguments for gamma_pdf function"); break; @@ -655,6 +720,8 @@ class NgpNode } }; + + } } diff --git a/packages/stk/stk_expreval/stk_expreval/Node.cpp b/packages/stk/stk_expreval/stk_expreval/Node.cpp index 8d73bc036a19..83916c8c7c9c 100644 --- a/packages/stk/stk_expreval/stk_expreval/Node.cpp +++ b/packages/stk/stk_expreval/stk_expreval/Node.cpp @@ -35,6 +35,7 @@ #include "stk_expreval/Node.hpp" #include "stk_expreval/Eval.hpp" #include "stk_expreval/Constants.hpp" +#include "stk_util/util/FPExceptions.hpp" #include namespace stk { @@ -81,6 +82,7 @@ double& Node::setResult() { void Node::eval() { + stk::util::clear_fp_errors(); switch (m_opcode) { case OPCODE_STATEMENT: { setResult() = m_left->getResult(); @@ -105,6 +107,7 @@ Node::eval() } case OPCODE_EXPONENIATION: { setResult() = std::pow(m_left->getResult(),m_right->getResult()); + checkFPError("std::pow"); break; } case OPCODE_DIVIDE: { @@ -205,12 +208,15 @@ Node::eval() } setResult() = (*m_data.function.function)(argc, argv); + checkFPError(m_data.function.functionName); + break; } default: { STK_ThrowErrorMsg("Unknown OpCode (" + std::to_string(m_opcode) + ")"); } } + checkFPError(); m_hasBeenEvaluated = true; } @@ -429,5 +435,21 @@ Node::evalTrace(const NodeWeightMap & nodeWeights, EvalNodesType & evaluationNod } } +void Node::checkFPError(const char* fname) +{ + Eval::FPErrorBehavior behavior = m_owner->get_fp_error_behavior(); + if (behavior == Eval::FPErrorBehavior::Ignore) + { + return; + } else if (behavior == Eval::FPErrorBehavior::Warn) + { + stk::util::warn_on_fp_error(fname); + } else if (behavior == Eval::FPErrorBehavior::Error) + { + stk::util::throw_on_fp_error(fname); + } +} + + } } diff --git a/packages/stk/stk_expreval/stk_expreval/Node.hpp b/packages/stk/stk_expreval/stk_expreval/Node.hpp index 0c93c9f89d0f..d2337092350e 100644 --- a/packages/stk/stk_expreval/stk_expreval/Node.hpp +++ b/packages/stk/stk_expreval/stk_expreval/Node.hpp @@ -171,6 +171,8 @@ class Node double& setResult(); + void checkFPError(const char* fname = nullptr); + const Opcode m_opcode; union _data diff --git a/packages/stk/stk_expreval/stk_expreval/Parser.cpp b/packages/stk/stk_expreval/stk_expreval/Parser.cpp index 9f454b35eb5c..ac2ad798beed 100644 --- a/packages/stk/stk_expreval/stk_expreval/Parser.cpp +++ b/packages/stk/stk_expreval/stk_expreval/Parser.cpp @@ -571,7 +571,10 @@ parseFunction(Eval & eval, function->m_data.function.functionType = functionType; std::strncpy(function->m_data.function.functionName, function_name.c_str(), - function_name.length() < Node::MAXIMUM_FUNCTION_NAME_LENGTH-1 ? function_name.length() : Node::MAXIMUM_FUNCTION_NAME_LENGTH-1); + std::min(function_name.length()+1, std::string::size_type(Node::MAXIMUM_FUNCTION_NAME_LENGTH)) + ); + function->m_data.function.functionName[Node::MAXIMUM_FUNCTION_NAME_LENGTH-1] = '\0'; + break; } } diff --git a/packages/stk/stk_integration_tests/cmake_install_test/run_cmake_stk_standalone_serial b/packages/stk/stk_integration_tests/cmake_install_test/run_cmake_stk_standalone_serial index 30ac86d21f52..4ed2a5dcc355 100755 --- a/packages/stk/stk_integration_tests/cmake_install_test/run_cmake_stk_standalone_serial +++ b/packages/stk/stk_integration_tests/cmake_install_test/run_cmake_stk_standalone_serial @@ -34,6 +34,7 @@ cmake \ -DCMAKE_CXX_COMPILER=${OMPI_CXX} \ -DCMAKE_CXX_FLAGS:STRING="${cmake_cxx_flags}" \ -DSTK_ENABLE_ALL=ON \ +-DSTK_ENABLE_ARBORX=ON \ -DSTK_ENABLE_MPI:BOOL=OFF \ -DSTK_ENABLE_STKMiddle_mesh=OFF \ -DSTK_ENABLE_STKMiddle_mesh_util=OFF \ diff --git a/packages/stk/stk_integration_tests/cmake_install_test/spack.cuda.yaml b/packages/stk/stk_integration_tests/cmake_install_test/spack.cuda.yaml index f0c30bcf6301..1622329941f5 100644 --- a/packages/stk/stk_integration_tests/cmake_install_test/spack.cuda.yaml +++ b/packages/stk/stk_integration_tests/cmake_install_test/spack.cuda.yaml @@ -9,13 +9,15 @@ spack: - zlib - openmpi@4.1.6 - kokkos+cuda+cuda_constexpr+cuda_lambda+cuda_relocatable_device_code~cuda_uvm~shared+wrapper cuda_arch=70 - - trilinos@develop~boost+cuda+cuda_rdc+exodus+kokkos~shared+stk+test~uvm+wrapper cuda_arch=70 cxxstd=17 + - trilinos@master~boost+cuda+cuda_rdc+exodus+kokkos~shared~uvm+wrapper cuda_arch=70 cxxstd=17 view: true concretizer: unify: true config: install_tree: root: SED_REPLACE_INSTALL_PATH + build_stage: + - /fgs/$USER/spack-stage compilers: - compiler: spec: gcc@=10.3.0 @@ -43,10 +45,6 @@ spack: modules: [] environment: {} extra_rpaths: [] - develop: - trilinos: - path: SED_REPLACE_TRILINOS_PATH - spec: trilinos@=develop packages: binutils: externals: diff --git a/packages/stk/stk_integration_tests/cmake_install_test/stk_spack_build_test_cuda.sh b/packages/stk/stk_integration_tests/cmake_install_test/stk_spack_build_test_cuda.sh index d1dc0f318ff8..633d07cb0545 100755 --- a/packages/stk/stk_integration_tests/cmake_install_test/stk_spack_build_test_cuda.sh +++ b/packages/stk/stk_integration_tests/cmake_install_test/stk_spack_build_test_cuda.sh @@ -12,40 +12,30 @@ exe() { # To specify custom paths for one or more of the following, set # the variable on the command line when running this script. # Example: -# $ TRILINOS=/my/path/trilinos source stk_spack_create_env_cuda.sh +# $ SIERRA=/my/path/code source stk_spack_create_env_cuda.sh work_dir=${STK_SPACK_WORK_DIR:-/fgs/$USER/stk-spack-testing-cuda} -trilinos_source=${TRILINOS:-/fgs/$USER/Trilinos} sierra_source=${SIERRA:-/fgs/$USER/code} -stk_spack_env=CUDA STK_SPACK_WORK_DIR=${work_dir} -TRILINOS=${trilinos_source} SIERRA=${sierra_source} printf "using STK_SPACK_WORK_DIR=${STK_SPACK_WORK_DIR}\n"; -printf "using TRILINOS=${TRILINOS}\n"; printf "using SIERRA=${SIERRA}\n"; -if [ ! -d ${trilinos_source} ] ; then - printf "ERROR, TRILINOS location not specified or not a directory.\n"; - return 1; -fi - if [ ! -d ${sierra_source} ] ; then printf "ERROR, SIERRA location not specified or not a directory.\n"; return 1; fi -printf "copying stk directory from SIERRA to TRILINOS...\n"; -exe rm -rf ${trilinos_source}/packages/stk -exe cp -r ${sierra_source}/stk ${trilinos_source}/packages - printf "Setting up spack env 'stkSpackTesting' in STK_SPACK_WORK_DIR=${work_dir}\n" exe mkdir -p ${work_dir} exe cd ${work_dir} -exe rm -rf spack spack.yaml stk_test_app +exe rm -rf spack spack.yaml + +exe mkdir -p ${work_dir}/tmp +exe export TMPDIR=${work_dir}/tmp exe module load aue/python/3.11.6 exe module load aue/git/2.42.0 @@ -66,7 +56,6 @@ exe cp ${sierra_source}/stk/stk_integration_tests/cmake_install_test/spack.cuda. spack_yaml_file=${work_dir}/spack.yaml exe sed -i s@SED_REPLACE_INSTALL_PATH@"${work_dir}/install"@g ${spack_yaml_file} -exe sed -i s@SED_REPLACE_TRILINOS_PATH@"${trilinos_source}"@g ${spack_yaml_file} exe spack config add -f ${spack_yaml_file} exe spack env activate stkSpackTesting @@ -79,12 +68,9 @@ exe spack add zlib exe spack add ncurses@6.3 exe spack add openmpi@4.1.6 exe spack add cuda@11.4.4 -exe spack add kokkos+cuda+wrapper+cuda_constexpr+cuda_lambda+cuda_relocatable_device_code~shared cuda_arch=70 -exe spack add trilinos@develop+cuda+cuda_rdc+exodus+stk+kokkos+wrapper~amesos~epetra~shared~boost cuda_arch=70 cxxstd=17 - -# don't need the following 'spack develop' command since we have specified it in -# our pre-packaged spack.cuda.yaml file. -# exe spack develop trilinos@develop -p ${trilinos_source} +exe spack add googletest cxxstd=17 +exe spack add kokkos+cuda~cuda_uvm+wrapper+cuda_constexpr+cuda_lambda+cuda_relocatable_device_code~shared cuda_arch=70 +exe spack add trilinos@master+cuda+cuda_rdc~uvm+exodus+kokkos+shards+intrepid2+zoltan2+wrapper~amesos~epetra~shared~boost cuda_arch=70 cxxstd=17 exe spack concretize -f if [ $? -ne 0 ] ; then @@ -98,18 +84,23 @@ if [ $? -ne 0 ] ; then return 1; fi +exe spack load googletest exe spack load cmake exe spack load openmpi printf "setting OMPI_CXX for CUDA environment\n"; export OMPI_CXX=$(find $(spack location -i kokkos) -name nvcc_wrapper) -printf "copying stk test app from SIERRA...\n"; -exe cp -r ${sierra_source}/stk/stk_integration_tests/cmake_install_test/stk_test_app . +printf "making build-dir for stk build...\n"; +stk_build_dir=${work_dir}/build_stk +exe mkdir -p ${stk_build_dir} -exe cd stk_test_app +exe cp ${sierra_source}/stk/stk_integration_tests/cmake_install_test/stk_test_app/run_cmake_in_spack_env ${stk_build_dir} + +exe cd ${stk_build_dir} + +exe STK_SOURCE_DIR=${sierra_source}/stk source run_cmake_in_spack_env -exe source run_cmake_in_spack_env if [ $? -ne 0 ] ; then printf "!! error running cmake\n"; return 1; @@ -121,12 +112,6 @@ if [ $? -ne 0 ] ; then return 1; fi -exe mpirun --np 4 ./test_stk_app -if [ $? -ne 0 ] ; then - printf "!! error running test_stk_app\n"; - return 1; -fi - -printf "all done, SUCCESS!\n"; +printf "all done, SUCCESS building!\n"; return 0 diff --git a/packages/stk/stk_integration_tests/cmake_install_test/stk_test_app/run_cmake_in_spack_env b/packages/stk/stk_integration_tests/cmake_install_test/stk_test_app/run_cmake_in_spack_env index c42f7adf585a..8d6826d19df9 100755 --- a/packages/stk/stk_integration_tests/cmake_install_test/stk_test_app/run_cmake_in_spack_env +++ b/packages/stk/stk_integration_tests/cmake_install_test/stk_test_app/run_cmake_in_spack_env @@ -2,14 +2,21 @@ spack env status spack find -v trilinos -TEST_STK_APP_SOURCE_DIR=$(pwd) +if [ -z ${STK_SOURCE_DIR+x} ]; then + echo "STK_SOURCE_DIR is unset"; + return 1; +else + echo "STK_SOURCE_DIR is set to '$STK_SOURCE_DIR'"; +fi -mkdir -p build - -cd build +stk_source_dir=${STK_SOURCE_DIR} cmake \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE:-RELEASE} \ -DCMAKE_CXX_COMPILER=mpicxx \ -${TEST_STK_APP_SOURCE_DIR} +-DSTK_ENABLE_ALL:BOOL=ON \ +-DSTK_ENABLE_MPI:BOOL=ON \ +-DSTK_ENABLE_TESTS:BOOL=ON \ +-DSTK_ENABLE_STKMiddle_mesh:BOOL=OFF \ +${stk_source_dir} diff --git a/packages/stk/stk_io/stk_io/IossBridge.cpp b/packages/stk/stk_io/stk_io/IossBridge.cpp index e645230b9b33..a69dc2a801f3 100644 --- a/packages/stk/stk_io/stk_io/IossBridge.cpp +++ b/packages/stk/stk_io/stk_io/IossBridge.cpp @@ -187,20 +187,9 @@ void STKIORequire(bool cond) namespace { - static const std::string invalid("invalid"); static const std::string scalar("scalar"); static const std::string vector_2d("vector_2d"); static const std::string vector_3d("vector_3d"); - static const std::string full_tensor_36("full_tensor_36"); - static const std::string full_tensor_32("full_tensor_32"); - static const std::string full_tensor_22("full_tensor_22"); - static const std::string full_tensor_16("full_tensor_16"); - static const std::string full_tensor_12("full_tensor_12"); - static const std::string sym_tensor_33("sym_tensor_33"); - static const std::string sym_tensor_31("sym_tensor_31"); - static const std::string sym_tensor_21("sym_tensor_21"); - static const std::string matrix_22("matrix_22"); - static const std::string matrix_33("matrix_33"); const std::string base_stk_part_name = "_base_stk_part_name"; @@ -2211,8 +2200,6 @@ const stk::mesh::FieldBase *declare_stk_field_internal(stk::mesh::MetaData &meta stk::mesh::EntityRank rank = get_output_rank(params); //-------------------------------- // Create the special universal node block: - mesh::Selector sharedSelector = params.has_shared_selector() ? *(params.get_shared_selector()) - : meta.globally_shared_part(); mesh::Selector allSelector = meta.globally_shared_part() | meta.locally_owned_part(); if (params.get_subset_selector( )) allSelector &= *params.get_subset_selector(); @@ -2255,9 +2242,6 @@ const stk::mesh::FieldBase *declare_stk_field_internal(stk::mesh::MetaData &meta mesh::MetaData & meta = mesh::MetaData::get(part); Ioss::Region & ioRegion = params.io_region(); - mesh::Selector sharedSelector = params.has_shared_selector() ? *(params.get_shared_selector()) - : meta.globally_shared_part(); - mesh::Selector allSelector = (meta.globally_shared_part() | meta.locally_owned_part()) & part; if (params.get_subset_selector( )) allSelector &= *params.get_subset_selector(); if (params.get_output_selector(rank)) allSelector &= *params.get_output_selector(rank); diff --git a/packages/stk/stk_mesh/stk_mesh/base/Bucket.cpp b/packages/stk/stk_mesh/stk_mesh/base/Bucket.cpp index 9343a4992358..4eb2e69024ce 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/Bucket.cpp +++ b/packages/stk/stk_mesh/stk_mesh/base/Bucket.cpp @@ -95,7 +95,7 @@ struct ClearEntityFunctor {} template - void operator()(Bucket&, ConnectivityType& connectivity) + void operator()(Bucket&, ConnectivityType& /*connectivity*/) {} void operator()(Bucket&, impl::BucketConnDynamic& connectivity) @@ -144,7 +144,7 @@ struct DeclareRelationFunctor {} template - void operator()(Bucket& bucket, Connectivity& connectivity) + void operator()(Bucket& /*bucket*/, Connectivity& connectivity) { STK_ThrowAssert(!m_modified); m_modified = connectivity.add_connectivity(m_bucket_ordinal, m_to, m_ordinal, m_permutation); @@ -167,7 +167,7 @@ struct DestroyRelationFunctor {} template - void operator()(Bucket& bucket, Connectivity& connectivity) + void operator()(Bucket& /*bucket*/, Connectivity& connectivity) { STK_ThrowAssert(!m_modified); m_modified = connectivity.remove_connectivity(m_bucket_ordinal, m_to, m_ordinal); @@ -195,7 +195,7 @@ struct ReplaceRelationFunctor {} template - void operator()(Bucket& bucket, Connectivity& connectivity) + void operator()(Bucket& /*bucket*/, Connectivity& connectivity) { STK_ThrowAssert(!m_modified); m_modified = connectivity.replace_connectivity(m_bucket_ordinal, m_numConnectivity, @@ -249,7 +249,7 @@ bool raw_part_equal( const unsigned * lhs , const unsigned * rhs ) { bool result = true ; { - const unsigned * const end_lhs = lhs + *lhs ; + const unsigned * const end_lhs = lhs + *lhs + 1 ; while ( result && end_lhs != lhs ) { result = *lhs == *rhs ; ++lhs ; ++rhs ; @@ -287,7 +287,7 @@ Bucket::Bucket(BulkData & mesh, m_entity_rank(entityRank), m_topology(), m_key(key), - m_partOrdsBeginEnd(m_key.data()+1,m_key.data()+m_key[0]), + m_partOrdsBeginEnd(m_key.data()+1,m_key.data()+1+m_key[0]), m_capacity(initialCapacity), m_maxCapacity(maximumCapacity), m_size(0), @@ -323,7 +323,7 @@ Bucket::Bucket(BulkData & mesh, setup_connectivity(m_topology, entityRank, stk::topology::FACE_RANK, m_face_kind, m_fixed_face_connectivity); setup_connectivity(m_topology, entityRank, stk::topology::ELEMENT_RANK, m_element_kind, m_fixed_element_connectivity); - m_parts.reserve(m_key.size()); + m_parts.reserve(m_key.size()-1); supersets(m_parts); m_mesh.new_bucket_callback(m_entity_rank, m_parts, m_capacity, this); @@ -655,17 +655,15 @@ unsigned Bucket::get_ngp_field_bucket_is_modified(unsigned fieldOrdinal) const void Bucket::reset_part_ord_begin_end() { m_partOrdsBeginEnd.first = m_key.data()+1; - m_partOrdsBeginEnd.second = m_key.data()+m_key[0]; + m_partOrdsBeginEnd.second = m_key.data()+1+m_key[0]; } void Bucket::reset_bucket_key(const OrdinalVector& newPartOrdinals) { - unsigned partitionCount = m_key[m_key.size() - 1]; unsigned newPartCount = newPartOrdinals.size(); - m_key.resize(newPartCount + 2); - m_key[0] = newPartCount + 1; - m_key[newPartCount+1] = partitionCount; + m_key.resize(newPartCount + 1); + m_key[0] = newPartCount; for(unsigned i = 0; i < newPartCount; i++) { m_key[i+1] = newPartOrdinals[i]; diff --git a/packages/stk/stk_mesh/stk_mesh/base/BulkData.cpp b/packages/stk/stk_mesh/stk_mesh/base/BulkData.cpp index 9870058c6a6d..5a1655330001 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/BulkData.cpp +++ b/packages/stk/stk_mesh/stk_mesh/base/BulkData.cpp @@ -62,15 +62,11 @@ #include "stk_mesh/baseImpl/ConnectEdgesImpl.hpp" #include "stk_mesh/baseImpl/Partition.hpp" #include "stk_topology/topology.hpp" // for topology, etc -#include "stk_util/diag/StringUtil.hpp" #include "stk_util/parallel/Parallel.hpp" // for ParallelMachine, etc -#include "stk_util/util/NamedPair.hpp" #include "stk_util/util/PairIter.hpp" // for PairIter -#include "stk_util/util/SameType.hpp" // for SameType, etc #include "stk_util/util/SortAndUnique.hpp" #include "stk_util/util/GetEnv.hpp" #include // for sort, lower_bound, unique, etc -#include #include // for operator<<, basic_ostream, etc #include // for back_insert_iterator, etc #include // for set, set<>::iterator, etc @@ -439,20 +435,6 @@ BulkData::register_device_mesh() const m_isDeviceMeshRegistered = true; } -void -BulkData::unregister_device_mesh() const -{ - m_isDeviceMeshRegistered = false; - - const stk::mesh::EntityRank endRank = static_cast(mesh_meta_data().entity_rank_count()); - for (stk::mesh::EntityRank rank = stk::topology::NODE_RANK; rank < endRank; ++rank) { - const stk::mesh::BucketVector & stkBuckets = buckets(rank); - for (Bucket * bucket : stkBuckets) { - bucket->set_ngp_bucket_id(INVALID_BUCKET_ID); - } - } -} - void BulkData::set_automatic_aura_option(AutomaticAuraOption auraOption, bool applyImmediately) { STK_ThrowRequireMsg(in_synchronized_state(),"set_automatic_aura_option currently can only be used when the mesh is not already being modified."); @@ -1026,17 +1008,15 @@ void BulkData::internal_verify_and_change_entity_parts( const EntityVector& enti OrdinalVector removePartsAndSubsetsMinusPartsInAddPartsList; OrdinalVector scratchOrdinalVec, scratchSpace; - for(Entity entity : entities) { - addPartsAndSupersets.clear(); - impl::fill_add_parts_and_supersets(add_parts, addPartsAndSupersets); + impl::fill_add_parts_and_supersets(add_parts, addPartsAndSupersets); + for(Entity entity : entities) { impl::fill_remove_parts_and_subsets_minus_parts_in_add_parts_list(remove_parts, addPartsAndSupersets, bucket_ptr(entity), removePartsAndSubsetsMinusPartsInAddPartsList); - internal_change_entity_parts(entity, - addPartsAndSupersets, + internal_change_entity_parts(entity, addPartsAndSupersets, removePartsAndSubsetsMinusPartsInAddPartsList, scratchOrdinalVec, scratchSpace); } @@ -1739,6 +1719,7 @@ void BulkData::comm_shared_procs(Entity entity, std::vector & procs ) const void BulkData::shared_procs_intersection(const std::vector & keys, std::vector & procs ) const { + confirm_host_mesh_is_synchronized_from_device(); procs.clear(); int num = keys.size(); std::vector procs_tmp; @@ -1768,6 +1749,7 @@ void BulkData::shared_procs_intersection(const std::vector & keys, st void BulkData::shared_procs_intersection(const EntityVector& entities, std::vector & procs ) const { + confirm_host_mesh_is_synchronized_from_device(); procs.clear(); int num = entities.size(); for (int i = 0; i < num; ++i) { @@ -2070,6 +2052,7 @@ void BulkData::update_field_data_states(bool rotateNgpFieldViews) const_entity_iterator BulkData::begin_entities(EntityRank ent_rank) const { + confirm_host_mesh_is_synchronized_from_device(); return m_entityKeyMapping->begin_rank(ent_rank); } @@ -2080,6 +2063,7 @@ const_entity_iterator BulkData::end_entities(EntityRank ent_rank) const Entity BulkData::get_entity( EntityRank ent_rank , EntityId entity_id ) const { + confirm_host_mesh_is_synchronized_from_device(); if (!impl::is_good_rank_and_id(mesh_meta_data(), ent_rank, entity_id)) { return Entity(); } @@ -2088,6 +2072,7 @@ Entity BulkData::get_entity( EntityRank ent_rank , EntityId entity_id ) const Entity BulkData::get_entity( const EntityKey key ) const { + confirm_host_mesh_is_synchronized_from_device(); return m_entityKeyMapping->get_entity(key); } @@ -2137,6 +2122,8 @@ void BulkData::erase_and_clear_if_empty(Entity entity, RelationIterator rel_itr) BucketVector const& BulkData::get_buckets(EntityRank rank, Selector const& selector) const { + confirm_host_mesh_is_synchronized_from_device(); + if (rank == stk::topology::INVALID_RANK) { static BucketVector empty; return empty; @@ -2168,6 +2155,7 @@ BucketVector const& BulkData::get_buckets(EntityRank rank, Selector const& selec } void BulkData::get_entities(EntityRank rank, Selector const& selector, EntityVector& output_entities) const { + confirm_host_mesh_is_synchronized_from_device(); output_entities.clear(); const stk::mesh::BucketVector &bucket_ptrs = get_buckets(rank, selector); for(size_t ib=0, ib_end=bucket_ptrs.size(); ib& BulkData::all_sharing_procs(stk::mesh::EntityRank rank) const { + confirm_host_mesh_is_synchronized_from_device(); internal_update_all_sharing_procs(); return m_all_sharing_procs[rank]; } @@ -5185,9 +5174,9 @@ void BulkData::internal_insert_all_parts_induced_from_higher_rank_entities_to_ve int num_upward_rels = num_connectivity(e_to, to_rel_rank_i); Entity const* upward_rel_entities = begin(e_to, to_rel_rank_i); + const Bucket* prevBucketPtr = nullptr; for (int k = 0; k < num_upward_rels; ++k) { - const Bucket* prevBucketPtr = nullptr; if (entity != upward_rel_entities[k]) // Already did this entity { const Bucket* curBucketPtr = bucket_ptr(upward_rel_entities[k]); @@ -5825,5 +5814,13 @@ EntityRank BulkData::get_entity_rank_count() const return mesh_meta_data().entity_rank_count(); } +void BulkData::confirm_host_mesh_is_synchronized_from_device(const char * fileName, int lineNumber) const +{ + STK_ThrowRequireMsg((not get_ngp_mesh()) || (not get_ngp_mesh()->need_sync_to_host()), + std::string(fileName) + ":" + std::to_string(lineNumber) + + " Accessing host-side BulkData or Field data after a device-side mesh modification without " + "calling NgpMesh::sync_to_host()"); +} + } // namespace mesh } // namespace stk diff --git a/packages/stk/stk_mesh/stk_mesh/base/BulkData.hpp b/packages/stk/stk_mesh/stk_mesh/base/BulkData.hpp index 6942896ee20a..d5f491b8cff8 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/BulkData.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/BulkData.hpp @@ -39,7 +39,6 @@ //---------------------------------------------------------------------- #include // for size_t #include // for uint16_t -#include // for max #include #include // for Entity, etc #include // for EntityCommDatabase @@ -56,6 +55,7 @@ #include "stk_mesh/base/Bucket.hpp" // for Bucket #include "stk_mesh/base/EntityKey.hpp" // for EntityKey, hash_value #include "stk_mesh/base/FieldDataManager.hpp" +#include "stk_mesh/base/FieldSyncDebugging.hpp" #include "stk_topology/topology.hpp" // for topology, etc #include "stk_util/util/ReportHandler.hpp" // for ThrowAssert, etc #include "stk_mesh/base/ModificationSummary.hpp" @@ -232,6 +232,7 @@ class BulkData { bool modification_begin(const std::string description = std::string("UNSPECIFIED")) { ProfilingBlock block("mod begin:" + description); + confirm_host_mesh_is_synchronized_from_device(); if(m_meshModification.in_modifiable_state()) { return false; } @@ -324,7 +325,10 @@ class BulkData { /** \brief Query all buckets of a given entity rank * Don't call inside BucketRepository member functions! */ - const BucketVector & buckets( EntityRank rank ) const { return m_bucket_repository.buckets(rank); } + const BucketVector & buckets( EntityRank rank ) const { + confirm_host_mesh_is_synchronized_from_device(); + return m_bucket_repository.buckets(rank); + } //iterator that traverses entities of the specified rank, in order of ascending global identifier const_entity_iterator begin_entities(EntityRank ent_rank) const; @@ -591,8 +595,14 @@ class BulkData { * Is likely to be stale if ownership or sharing has changed * and the 'modification_end' has not been called. */ - Ghosting & aura_ghosting() const { return *m_ghosting[AURA] ; } - Ghosting & shared_ghosting() const { return *m_ghosting[SHARED] ; } + Ghosting & aura_ghosting() const { + confirm_host_mesh_is_synchronized_from_device(); + return *m_ghosting[AURA]; + } + Ghosting & shared_ghosting() const { + confirm_host_mesh_is_synchronized_from_device(); + return *m_ghosting[SHARED]; + } /** Return the part corresponding to the specified ghosting. */ @@ -637,7 +647,10 @@ class BulkData { void destroy_all_ghosting(); // Mod Mark /** \brief Vector of all ghostings */ - const std::vector & ghostings() const { return m_ghosting ; } + const std::vector & ghostings() const { + confirm_host_mesh_is_synchronized_from_device(); + return m_ghosting; + } size_t get_num_communicated_entities() const { return m_entity_comm_list.size(); } @@ -889,6 +902,9 @@ class BulkData { bool is_mesh_consistency_check_on() const { return m_runConsistencyCheck; } + void confirm_host_mesh_is_synchronized_from_device(const char * fileName = HOST_DEBUG_FILE_NAME, + int lineNumber = HOST_DEBUG_LINE_NUMBER) const; + protected: //functions BulkData(std::shared_ptr mesh_meta_data, ParallelMachine parallel, @@ -2080,6 +2096,7 @@ template inline NgpCommMapIndicesHostMirrorT BulkData::volatile_fast_shared_comm_map(EntityRank rank, int proc) const { + confirm_host_mesh_is_synchronized_from_device(); STK_ThrowAssert(this->in_synchronized_state()); STK_ThrowAssertMsg(rank < stk::topology::ELEMENT_RANK, "Cannot share entities of rank: " << rank); if (m_ngpMeshHostDataBase == nullptr || diff --git a/packages/stk/stk_mesh/stk_mesh/base/DeviceField.hpp b/packages/stk/stk_mesh/stk_mesh/base/DeviceField.hpp index 7793036e1248..0756cb18a676 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/DeviceField.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/DeviceField.hpp @@ -247,23 +247,21 @@ class DeviceField : public NgpFieldBase KOKKOS_FUNCTION unsigned get_component_stride() const { - unsigned stride = 1; #ifdef STK_USE_DEVICE_MESH - stride = bucketCapacity; + return bucketCapacity; +#else + return 1; #endif - return stride; } KOKKOS_FUNCTION unsigned get_num_components_per_entity(const FastMeshIndex& entityIndex) const { - const unsigned bucketId = entityIndex.bucket_id; - return deviceAllFieldsBucketsLayoutPerEntity(bucketId, NUM_COMPONENTS_INDEX); + return deviceAllFieldsBucketsLayoutPerEntity(entityIndex.bucket_id, NUM_COMPONENTS_INDEX); } KOKKOS_FUNCTION unsigned get_extent0_per_entity(const FastMeshIndex& entityIndex) const { - const unsigned bucketId = entityIndex.bucket_id; - return deviceAllFieldsBucketsLayoutPerEntity(bucketId, FIRST_DIMENSION_INDEX); + return deviceAllFieldsBucketsLayoutPerEntity(entityIndex.bucket_id, FIRST_DIMENSION_INDEX); } KOKKOS_FUNCTION @@ -325,8 +323,7 @@ class DeviceField : public NgpFieldBase { fieldSyncDebugger.device_stale_access_check(this, index, fileName, lineNumber); T* dataPtr = &deviceData(deviceSelectedBucketOffset(index.bucket_id), ORDER_INDICES(index.bucket_ord, 0)); - const unsigned numScalars = get_num_components_per_entity(index); - return EntityFieldData(dataPtr, numScalars, get_component_stride()); + return EntityFieldData(dataPtr, get_num_components_per_entity(index), get_component_stride()); } template diff --git a/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.hpp b/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.hpp index 492e189e2545..27faedc82158 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.hpp @@ -46,7 +46,6 @@ #include #include #include -#include #include #include @@ -182,16 +181,17 @@ class DeviceMeshT : public NgpMeshBase bulk(nullptr), spatial_dimension(0), synchronizedCount(0), + m_needSyncToHost(false), deviceMeshHostData(nullptr) {} explicit DeviceMeshT(const stk::mesh::BulkData& b) : NgpMeshBase(), - bulk(&b), + bulk(&const_cast(b)), spatial_dimension(b.mesh_meta_data().spatial_dimension()), synchronizedCount(0), + m_needSyncToHost(false), endRank(static_cast(bulk->mesh_meta_data().entity_rank_count())), - copyCounter("copy_counter"), deviceMeshHostData(nullptr) { bulk->register_device_mesh(); @@ -206,6 +206,7 @@ class DeviceMeshT : public NgpMeshBase KOKKOS_FUNCTION virtual ~DeviceMeshT() override { + m_needSyncToHost = false; clear_buckets_and_views(); } @@ -422,6 +423,12 @@ class DeviceMeshT : public NgpMeshBase buckets[rank] = BucketView(); } + stk::mesh::BulkData &get_bulk_on_host() + { + STK_ThrowRequireMsg(bulk != nullptr, "DeviceMesh::get_bulk_on_host, bulk==nullptr"); + return *bulk; + } + const stk::mesh::BulkData &get_bulk_on_host() const { STK_ThrowRequireMsg(bulk != nullptr, "DeviceMeshT::get_bulk_on_host, bulk==nullptr"); @@ -433,6 +440,88 @@ class DeviceMeshT : public NgpMeshBase return synchronizedCount == bulk->synchronized_count(); } + // This is an initial crude implementation that brings the device-side Views back to + // the host and then kicks off a host-side mesh modification. The modified host mesh + // is then synchronized back to device. This will not perform well and the semantics + // are a little different from the final device-side capability (because the host mesh + // will not be left in an unsynchronized state), but it can serve as a stand-in for + // the final device-side mesh modification capability in the meantime. + // + template + void batch_change_entity_parts(const Kokkos::View& entities, + const Kokkos::View& addPartOrdinals, + const Kokkos::View& removePartOrdinals) + { + using EntitiesMemorySpace = typename std::remove_reference::type::memory_space; + using AddPartOrdinalsMemorySpace = typename std::remove_reference::type::memory_space; + using RemovePartOrdinalsMemorySpace = typename std::remove_reference::type::memory_space; + + static_assert(Kokkos::SpaceAccessibility::accessible, + "The memory space of the 'entities' View is inaccessible from the DeviceMesh execution space"); + static_assert(Kokkos::SpaceAccessibility::accessible, + "The memory space of the 'addPartOrdinals' View is inaccessible from the DeviceMesh execution space"); + static_assert(Kokkos::SpaceAccessibility::accessible, + "The memory space of the 'removePartOrdinals' View is inaccessible from the DeviceMesh execution space"); + + using HostEntitiesType = typename std::remove_reference::type::HostMirror; + using HostAddPartOrdinalsType = typename std::remove_reference::type::HostMirror; + using HostRemovePartOrdinalsType = typename std::remove_reference::type::HostMirror; + + HostEntitiesType copiedEntities = Kokkos::create_mirror_view(entities); + HostAddPartOrdinalsType copiedAddPartOrdinals = Kokkos::create_mirror_view(addPartOrdinals); + HostRemovePartOrdinalsType copiedRemovePartOrdinals = Kokkos::create_mirror_view(removePartOrdinals); + + Kokkos::deep_copy(copiedEntities, entities); + Kokkos::deep_copy(copiedAddPartOrdinals, addPartOrdinals); + Kokkos::deep_copy(copiedRemovePartOrdinals, removePartOrdinals); + + std::vector hostEntities; + std::vector hostAddParts; + std::vector hostRemoveParts; + + hostEntities.reserve(copiedEntities.extent(0)); + for (size_t i = 0; i < copiedEntities.extent(0); ++i) { + hostEntities.push_back(copiedEntities[i]); + } + + const stk::mesh::PartVector& parts = bulk->mesh_meta_data().get_parts(); + + hostAddParts.reserve(copiedAddPartOrdinals.extent(0)); + for (size_t i = 0; i < copiedAddPartOrdinals.extent(0); ++i) { + const size_t partOrdinal = copiedAddPartOrdinals[i]; + STK_ThrowRequire(partOrdinal < parts.size()); + hostAddParts.push_back(parts[partOrdinal]); + } + + hostRemoveParts.reserve(copiedRemovePartOrdinals.extent(0)); + for (size_t i = 0; i < copiedRemovePartOrdinals.extent(0); ++i) { + const size_t partOrdinal = copiedRemovePartOrdinals[i]; + STK_ThrowRequire(partOrdinal < parts.size()); + hostRemoveParts.push_back(parts[partOrdinal]); + } + + m_needSyncToHost = false; + bulk->batch_change_entity_parts(hostEntities, hostAddParts, hostRemoveParts); + + update_mesh(); + m_needSyncToHost = true; + } + + // This function should be called before doing any host-side mesh operations after a + // device-side mesh modification, to avoid accessing stale data. Accessing the host + // mesh without syncing it first should result in a throw. + // + void sync_to_host() { + m_needSyncToHost = false; + } + + // This can be used to check if the device-side mesh has been modified without + // synchronizing it to the host. + // + bool need_sync_to_host() const override { + return m_needSyncToHost; + } + private: void set_entity_keys(const stk::mesh::BulkData& bulk_in); @@ -440,12 +529,6 @@ class DeviceMeshT : public NgpMeshBase void fill_sparse_connectivities(const stk::mesh::BulkData& bulk_in); - KOKKOS_FUNCTION - bool is_last_mesh_copy() const - { - return (copyCounter.use_count() == 1); - } - KOKKOS_FUNCTION bool is_last_bucket_reference(unsigned rank = stk::topology::NODE_RANK) const { @@ -456,10 +539,6 @@ class DeviceMeshT : public NgpMeshBase void clear_buckets_and_views() { KOKKOS_IF_ON_HOST(( - if (is_last_mesh_copy()) { - bulk->unregister_device_mesh(); - } - if (is_last_bucket_reference()) { for (stk::mesh::EntityRank rank=stk::topology::NODE_RANK; rank*, stk::ngp::UVMMemSpace>; - const stk::mesh::BulkData *bulk; + stk::mesh::BulkData* bulk; unsigned spatial_dimension; unsigned synchronizedCount; + bool m_needSyncToHost; stk::mesh::EntityRank endRank; - Kokkos::View copyCounter; impl::NgpMeshHostData* deviceMeshHostData; EntityKeyViewType entityKeys; diff --git a/packages/stk/stk_mesh/stk_mesh/base/FEMHelpers.cpp b/packages/stk/stk_mesh/stk_mesh/base/FEMHelpers.cpp index ceb6e6bdb27a..ca5a1b61ba11 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/FEMHelpers.cpp +++ b/packages/stk/stk_mesh/stk_mesh/base/FEMHelpers.cpp @@ -357,8 +357,7 @@ inline void sub_topology_check(const stk::mesh::EntityVector& candidateSideNodes << ", expected: " << subTopology.num_nodes()); } -inline void sub_topology_check(const stk::mesh::Entity* candidateSideNodes, - size_t numCandidateSideNodes, +inline void sub_topology_check(size_t numCandidateSideNodes, stk::topology elemTopology, stk::topology subTopology) { @@ -445,7 +444,7 @@ EquivAndPositive is_side_equivalent_and_positive(const stk::mesh::BulkData& mesh } stk::topology subTopology = elemTopology.sub_topology(mesh.mesh_meta_data().side_rank(), sideOrdinal); - sub_topology_check(candidateSideNodes, numCandidateSideNodes, elemTopology, subTopology); + sub_topology_check(numCandidateSideNodes, elemTopology, subTopology); return is_equivalent_and_positive(mesh, element, sideOrdinal, mesh.mesh_meta_data().side_rank(), candidateSideNodes); } diff --git a/packages/stk/stk_mesh/stk_mesh/base/FieldDataManager.cpp b/packages/stk/stk_mesh/stk_mesh/base/FieldDataManager.cpp index a2a606c51d97..05e11510bdea 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/FieldDataManager.cpp +++ b/packages/stk/stk_mesh/stk_mesh/base/FieldDataManager.cpp @@ -947,9 +947,16 @@ void ContiguousFieldDataManager::add_field_data_for_entity(const std::vector m_num_bytes_allocated_per_field[field_ordinal]; + const size_t newFieldSizeNeeded = m_num_bytes_used_per_field[field_ordinal] + extraAllocationNeeded; + + bool requiresNewAllocation = false; + size_t newFieldSize = m_num_bytes_allocated_per_field[field_ordinal]; + + // Only reallocate if we've outgrown the extra capacity + if (newFieldSizeNeeded > m_num_bytes_allocated_per_field[field_ordinal]) { + requiresNewAllocation = true; + newFieldSize = newFieldSizeNeeded + m_extra_capacity; + } unsigned char* new_field_data = m_field_raw_data[field_ordinal]; FieldMetaDataVector& field_meta_data_vector = const_cast(field.get_meta_data_for_field()); diff --git a/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp b/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp index b9254509fe57..cf3e7d2faefd 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp +++ b/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp @@ -101,6 +101,7 @@ void communicate_field_data(const Ghosting& ghosts, const std::vector & fields) { + mesh.confirm_host_mesh_is_synchronized_from_device(); const int parallel_size = mesh.parallel_size(); if ( fields.empty() || parallel_size == 1) { return; @@ -406,6 +408,7 @@ void parallel_op_impl(const BulkData& mesh, std::vector fields if (fields.empty()) { return; } + mesh.confirm_host_mesh_is_synchronized_from_device(); std::vector comm_procs = mesh.all_sharing_procs(fields[0]->entity_rank()); stk::mesh::EntityRank first_field_rank = fields[0]->entity_rank(); @@ -728,6 +731,7 @@ template void parallel_op_including_ghosts_impl(const BulkData & mesh, const std::vector & fields) { if ( fields.empty() ) { return; } + mesh.confirm_host_mesh_is_synchronized_from_device(); const int parallel_size = mesh.parallel_size(); diff --git a/packages/stk/stk_mesh/stk_mesh/base/HostMesh.hpp b/packages/stk/stk_mesh/stk_mesh/base/HostMesh.hpp index 93109961ed67..36823b3ede6f 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/HostMesh.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/HostMesh.hpp @@ -46,8 +46,6 @@ #include #include #include -#include -#include #include #include @@ -81,7 +79,7 @@ class HostMeshT : public NgpMeshBase HostMeshT(const stk::mesh::BulkData& b) : NgpMeshBase(), - bulk(&b), + bulk(&const_cast(b)), m_syncCountWhenUpdated(bulk->synchronized_count()) { require_ngp_mesh_rank_limit(bulk->mesh_meta_data()); @@ -128,7 +126,7 @@ class HostMeshT : public NgpMeshBase ConnectedEntities get_connected_entities(stk::mesh::EntityRank rank, const stk::mesh::FastMeshIndex &entity, stk::mesh::EntityRank connectedRank) const { const stk::mesh::Bucket& bucket = get_bucket(rank, entity.bucket_id); - return ConnectedEntities(bucket.begin(entity.bucket_ord, connectedRank), bucket.num_connectivity(entity.bucket_ord, connectedRank)); + return bucket.get_connected_entities(entity.bucket_ord, connectedRank); } ConnectedOrdinals get_connected_ordinals(stk::mesh::EntityRank rank, const stk::mesh::FastMeshIndex &entity, stk::mesh::EntityRank connectedRank) const @@ -239,6 +237,11 @@ class HostMeshT : public NgpMeshBase return bulk->volatile_fast_shared_comm_map(rank, proc); } + stk::mesh::BulkData &get_bulk_on_host() + { + return *bulk; + } + const stk::mesh::BulkData &get_bulk_on_host() const { return *bulk; @@ -249,8 +252,58 @@ class HostMeshT : public NgpMeshBase return m_syncCountWhenUpdated == bulk->synchronized_count(); } + template + void batch_change_entity_parts(const Kokkos::View& entities, + const Kokkos::View& addPartOrdinals, + const Kokkos::View& removePartOrdinals) + { + using EntitiesMemorySpace = typename std::remove_reference::type::memory_space; + using AddPartOrdinalsMemorySpace = typename std::remove_reference::type::memory_space; + using RemovePartOrdinalsMemorySpace = typename std::remove_reference::type::memory_space; + + static_assert(Kokkos::SpaceAccessibility::accessible, + "The memory space of the 'entities' View is inaccessible from the HostMesh execution space"); + static_assert(Kokkos::SpaceAccessibility::accessible, + "The memory space of the 'addPartOrdinals' View is inaccessible from the HostMesh execution space"); + static_assert(Kokkos::SpaceAccessibility::accessible, + "The memory space of the 'removePartOrdinals' View is inaccessible from the HostMesh execution space"); + + std::vector hostEntities; + std::vector hostAddParts; + std::vector hostRemoveParts; + + hostEntities.reserve(entities.extent(0)); + for (size_t i = 0; i < entities.extent(0); ++i) { + hostEntities.push_back(entities[i]); + } + + const stk::mesh::PartVector& parts = bulk->mesh_meta_data().get_parts(); + + hostAddParts.reserve(addPartOrdinals.extent(0)); + for (size_t i = 0; i < addPartOrdinals.extent(0); ++i) { + const size_t partOrdinal = addPartOrdinals[i]; + STK_ThrowRequire(partOrdinal < parts.size()); + hostAddParts.push_back(parts[partOrdinal]); + } + + hostRemoveParts.reserve(removePartOrdinals.extent(0)); + for (size_t i = 0; i < removePartOrdinals.extent(0); ++i) { + const size_t partOrdinal = removePartOrdinals[i]; + STK_ThrowRequire(partOrdinal < parts.size()); + hostRemoveParts.push_back(parts[partOrdinal]); + } + + bulk->batch_change_entity_parts(hostEntities, hostAddParts, hostRemoveParts); + } + + void sync_to_host() {} + + bool need_sync_to_host() const override { + return false; + } + private: - const stk::mesh::BulkData *bulk; + stk::mesh::BulkData *bulk; size_t m_syncCountWhenUpdated; }; diff --git a/packages/stk/stk_mesh/stk_mesh/base/NgpFieldParallel.hpp b/packages/stk/stk_mesh/stk_mesh/base/NgpFieldParallel.hpp index a0b4128d299d..22ee83a98373 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/NgpFieldParallel.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/NgpFieldParallel.hpp @@ -187,7 +187,7 @@ class ParallelSumDataExchangeSymPackUnpackHandler for (stk::mesh::NgpField* field : m_ngpFields) { stk::mesh::FieldBase* stkField = m_ngpMesh.get_bulk_on_host().mesh_meta_data().get_fields()[field->get_ordinal()]; - stk::mesh::HostCommMapIndices commMapIndices = m_ngpMesh.get_bulk_on_host().volatile_fast_shared_comm_map(field->get_rank(), proc); + stk::mesh::HostCommMapIndices commMapIndices = m_ngpMesh.get_bulk_on_host().volatile_fast_shared_comm_map(field->get_rank(), proc); for (size_t i = 0; i < commMapIndices.extent(0); ++i) { const unsigned bucketId = commMapIndices(i).bucket_id; const unsigned numScalarsPerEntity = stk::mesh::field_scalars_per_entity(*stkField, bucketId); diff --git a/packages/stk/stk_mesh/stk_mesh/base/NgpMeshBase.hpp b/packages/stk/stk_mesh/stk_mesh/base/NgpMeshBase.hpp index 3ce2687afa10..b980a2cff561 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/NgpMeshBase.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/NgpMeshBase.hpp @@ -19,6 +19,7 @@ class NgpMeshBase KOKKOS_DEFAULTED_FUNCTION NgpMeshBase& operator=(NgpMeshBase&&) = default; virtual void update_mesh() = 0; + virtual bool need_sync_to_host() const = 0; }; }} diff --git a/packages/stk/stk_mesh/stk_mesh/base/NgpParallelComm.hpp b/packages/stk/stk_mesh/stk_mesh/base/NgpParallelComm.hpp index c2674c75f6a9..d39df0626a63 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/NgpParallelComm.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/NgpParallelComm.hpp @@ -34,9 +34,10 @@ #ifndef STK_MESH_NGPPARALLELCOMM_HPP #define STK_MESH_NGPPARALLELCOMM_HPP -#include "stk_util/parallel/Parallel.hpp" // for ParallelMachine -#include "stk_util/ngp/NgpSpaces.hpp" -#include "Kokkos_Core.hpp" +#include +#include +#include +#include namespace stk { namespace mesh { @@ -58,7 +59,6 @@ void ngp_parallel_data_exchange_sym_pack_unpack(MPI_Comm mpi_communicator, const int pRank = stk::parallel_machine_rank(mpi_communicator); const int msgTag = 10242; size_t num_comm_procs = comm_procs.size(); - int dataTypeSize = sizeof(T); CommProcsViewType deviceCommProcs("DeviceCommProcs", num_comm_procs); CommProcsViewType::HostMirror hostCommProcs = Kokkos::create_mirror_view(deviceCommProcs); @@ -98,14 +98,15 @@ void ngp_parallel_data_exchange_sym_pack_unpack(MPI_Comm mpi_communicator, BufferViewType buffer = Kokkos::subview( deviceSendData, Kokkos::pair(dataBegin, dataEnd)); exchangeHandler.devicePackMessage(pRank, deviceCommProcs(iproc), buffer); }); + Kokkos::fence(); for (size_t proc = 0; proc < num_comm_procs; ++proc) { int iproc = comm_procs[proc]; const size_t dataBegin = hostBufferOffsets[proc]; const size_t dataEnd = hostBufferOffsets[proc+1]; - int bufSize = (dataEnd-dataBegin) * dataTypeSize; - MPI_Irecv((deviceRecvData.data()+dataBegin), bufSize, MPI_CHAR, iproc, msgTag, mpi_communicator, &recvRequests[proc]); - MPI_Isend((deviceSendData.data()+dataBegin), bufSize, MPI_CHAR, iproc, msgTag, mpi_communicator, &sendRequests[proc]); + int bufSize = (dataEnd-dataBegin); + MPI_Irecv((deviceRecvData.data()+dataBegin), bufSize, sierra::MPI::Datatype::type(), iproc, msgTag, mpi_communicator, &recvRequests[proc]); + MPI_Isend((deviceSendData.data()+dataBegin), bufSize, sierra::MPI::Datatype::type(), iproc, msgTag, mpi_communicator, &sendRequests[proc]); } for (size_t proc = 0; proc < num_comm_procs; ++proc) { diff --git a/packages/stk/stk_mesh/stk_mesh/base/NgpTypes.hpp b/packages/stk/stk_mesh/stk_mesh/base/NgpTypes.hpp index 0a128c4f29e4..85099a167005 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/NgpTypes.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/NgpTypes.hpp @@ -68,8 +68,8 @@ using HostPartOrdinalViewType = Kokkos::View; template using PermutationViewTypeT = Kokkos::View; using FastSharedCommMapViewType = DeviceCommMapIndices; -using HostMeshIndexType = Kokkos::View::HostMirror; using MeshIndexType = Kokkos::View>; +using HostMeshIndexType = MeshIndexType::HostMirror; using BucketEntityOffsetsViewType = Kokkos::View; diff --git a/packages/stk/stk_mesh/stk_mesh/base/Selector.hpp b/packages/stk/stk_mesh/stk_mesh/base/Selector.hpp index 0d0c686000f3..f831c7f7a925 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/Selector.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/Selector.hpp @@ -322,12 +322,6 @@ class Selector { friend std::ostream & operator << ( std::ostream & out, const Selector & selector); -private: - bool select_part_impl(Part const& part, impl::SelectorNode const* root) const; - bool select_bucket_impl(Bucket const& bucket, impl::SelectorNode const* root) const; - - const BulkData* find_mesh() const; - bool is_null() const { if(m_expr.size() > 1) return false; if(m_expr.back().m_type == SelectorNodeType::PART && m_expr.back().part() == InvalidPartOrdinal) { @@ -338,6 +332,12 @@ class Selector { return false; } +private: + bool select_part_impl(Part const& part, impl::SelectorNode const* root) const; + bool select_bucket_impl(Bucket const& bucket, impl::SelectorNode const* root) const; + + const BulkData* find_mesh() const; + Selector& add_binary_op(SelectorNodeType::node_type type, const Selector& rhs); std::vector m_expr; diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/BucketRepository.cpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/BucketRepository.cpp index e5a12eb5ca37..9f58a66dd2fc 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/BucketRepository.cpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/BucketRepository.cpp @@ -198,7 +198,7 @@ void BucketRepository::fill_key_ptr(const OrdinalVector& parts, PartOrdinal** ke { const size_t part_count = parts.size(); - const size_t keyLen = 2 + part_count; + const size_t keyLen = 1 + part_count; *keyPtr = keyTmpBuffer; *keyEnd = *keyPtr+keyLen; @@ -211,16 +211,12 @@ void BucketRepository::fill_key_ptr(const OrdinalVector& parts, PartOrdinal** ke //---------------------------------- // Key layout: - // { part_count + 1 , { part_ordinals } , partition_count } - // Thus partition_count = key[ key[0] ] + // { part_count , { part_ordinals } } // - // for upper bound search use the maximum key for a bucket in the partition. - const unsigned max = static_cast(-1); - (*keyPtr)[0] = part_count+1; - (*keyPtr)[ (*keyPtr)[0] ] = max ; + (*keyPtr)[0] = part_count; - { - for ( unsigned i = 0 ; i < part_count ; ++i ) { (*keyPtr)[i+1] = parts[i] ; } + for ( unsigned i = 0 ; i < part_count ; ++i ) { + (*keyPtr)[i+1] = parts[i]; } } @@ -246,22 +242,19 @@ Partition *BucketRepository::get_partition( PartOrdinal* keyPtr, PartOrdinal* keyEnd) { - STK_ThrowRequireMsg(m_mesh.mesh_meta_data().check_rank(arg_entity_rank), "Entity rank " << arg_entity_rank - << " is invalid"); + STK_ThrowAssertMsg(m_mesh.mesh_meta_data().check_rank(arg_entity_rank), + "Entity rank " << arg_entity_rank << " is invalid"); ensure_data_structures_sized(); std::vector & partitions = m_partitions[ arg_entity_rank ]; - // If the partition is found, the iterator will be right after it, thanks to the - // trickiness above. ik = lower_bound( partitions , keyPtr ); - const bool partition_exists = - (ik != partitions.begin()) && raw_part_equal( ik[-1]->key() , keyPtr ); + const bool partition_exists = (ik != partitions.end()) && raw_part_equal( (*ik)->key() , keyPtr ); if (partition_exists) { - return ik[-1]; + return *ik; } return nullptr; @@ -274,8 +267,6 @@ Partition* BucketRepository::create_partition( PartOrdinal* keyPtr, PartOrdinal* keyEnd) { - keyPtr[keyPtr[0]] = 0; - Partition *partition = new Partition(m_mesh, this, arg_entity_rank, keyPtr, keyEnd); STK_ThrowRequire(partition != nullptr); @@ -420,7 +411,8 @@ Bucket *BucketRepository::allocate_bucket(EntityRank entityRank, unsigned initialCapacity, unsigned maximumCapacity) { - STK_ThrowAssertMsg(stk::util::is_sorted_and_unique(std::vector(key.begin()+1,key.end()-1),std::less()), + std::vector tmp(key.begin()+1,key.end()); + STK_ThrowAssertMsg(stk::util::is_sorted_and_unique(tmp,std::less()), "bucket created with 'key' vector that's not sorted and unique"); BucketVector &bucket_vec = m_buckets[entityRank]; const unsigned bucket_id = bucket_vec.size(); @@ -465,15 +457,9 @@ void BucketRepository::sync_bucket_ids(EntityRank entity_rank) m_mesh.reorder_buckets_callback(entity_rank, id_map); } -std::vector BucketRepository::get_partitions(EntityRank rank) const +const std::vector& BucketRepository::get_partitions(EntityRank rank) const { - std::vector retval; - std::vector const& bf_vec = m_partitions[rank]; - for (size_t i = 0; i < bf_vec.size(); ++i) - { - retval.push_back(bf_vec[i]); - } - return retval; + return m_partitions[rank]; } void BucketRepository::delete_bucket(Bucket * bucket) diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/BucketRepository.hpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/BucketRepository.hpp index 749814a90781..27366e248101 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/BucketRepository.hpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/BucketRepository.hpp @@ -137,8 +137,7 @@ class BucketRepository void sync_from_partitions(); void sync_from_partitions(EntityRank rank); - // Used in unit tests. Returns the current partitions. - std::vector get_partitions(EntityRank rank) const; + const std::vector& get_partitions(EntityRank rank) const; Partition* get_partition(const EntityRank arg_entity_rank, const OrdinalVector &parts); diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/NgpFieldBLASImpl.hpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/NgpFieldBLASImpl.hpp index f3368b340236..84fa51cfdd90 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/NgpFieldBLASImpl.hpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/NgpFieldBLASImpl.hpp @@ -99,6 +99,16 @@ void mark_field_modified(const mesh::FieldBase& field, EXEC_SPACE execSpace, boo } } +template +void construct_device_fields(FieldViewType& ngpFields) +{ + using NgpFieldType = typename FieldViewType::value_type; + Kokkos::parallel_for(stk::ngp::DeviceRangePolicy(0, ngpFields.size()), + KOKKOS_LAMBDA(const unsigned& i) { + new (&ngpFields(i)) NgpFieldType(); + }); +} + template class FieldFill { public: @@ -113,8 +123,18 @@ class FieldFill { } } else { - Kokkos::resize(ngpFieldsDynamic, nfields); + constexpr bool accessible = Kokkos::SpaceAccessibility::accessible; + + if (accessible) { + Kokkos::resize(ngpFieldsDynamic, nfields); + } + else { + Kokkos::resize(Kokkos::WithoutInitializing, ngpFieldsDynamic, nfields); + construct_device_fields(ngpFieldsDynamic); + } + auto ngpFieldsDynamicHost = Kokkos::create_mirror_view(ngpFieldsDynamic); + for (int i=0; i < nfields; ++i) { ngpFieldsDynamicHost[i] = fields[i]; @@ -123,6 +143,8 @@ class FieldFill { } } + KOKKOS_FUNCTION ~FieldFill() { } + KOKKOS_FUNCTION void operator()(const stk::mesh::FastMeshIndex& entityIndex) const { @@ -152,6 +174,7 @@ class FieldFill { using FieldView = Kokkos::View; using FieldHostView = typename FieldView::HostMirror; + using MemorySpace = typename FieldView::traits::memory_space; static constexpr int STATIC_FIELD_LIMIT = 4; NGP_FIELD_TYPE ngpFieldsStatic[STATIC_FIELD_LIMIT]; FieldView ngpFieldsDynamic; @@ -175,8 +198,18 @@ class FieldFillComponent { } } else { - Kokkos::resize(ngpFieldsDynamic, nfields); + constexpr bool accessible = Kokkos::SpaceAccessibility::accessible; + + if constexpr (accessible) { + Kokkos::resize(ngpFieldsDynamic, nfields); + } + else { + Kokkos::resize(Kokkos::WithoutInitializing, ngpFieldsDynamic, nfields); + construct_device_fields(ngpFieldsDynamic); + } + auto ngpFieldsDynamicHost = Kokkos::create_mirror_view(ngpFieldsDynamic); + for (int i=0; i < nfields; ++i) { ngpFieldsDynamicHost(i) = fields[i]; @@ -217,6 +250,7 @@ class FieldFillComponent { using FieldView = Kokkos::View; using FieldHostView = typename FieldView::HostMirror; + using MemorySpace = typename FieldView::traits::memory_space; static constexpr int STATIC_FIELD_LIMIT = 4; NGP_FIELD_TYPE ngpFieldsStatic[STATIC_FIELD_LIMIT]; FieldView ngpFieldsDynamic; @@ -237,10 +271,12 @@ void field_fill_for_each_entity(const NGP_MESH_TYPE& ngpMesh, if (component == -1) { FieldFill fieldFill(ngpFields, nfields, alpha); stk::mesh::for_each_entity_run(ngpMesh, ngpFields[0].get_rank(), selector, fieldFill, execSpace); + Kokkos::fence(); } else { FieldFillComponent fieldFill(ngpFields, nfields, alpha, component); stk::mesh::for_each_entity_run(ngpMesh, ngpFields[0].get_rank(), selector, fieldFill, execSpace); + Kokkos::fence(); } } @@ -334,6 +370,8 @@ template Scalar field_amax_no_mark_t( const stk::mesh::FieldBase& xField, const stk::mesh::Selector& selector, const EXEC_SPACE& execSpace) { + Scalar amaxOut = 0; + if constexpr (operate_on_ngp_mesh()) { xField.sync_to_device(); stk::mesh::NgpField& ngpX = stk::mesh::get_updated_ngp_field(xField); @@ -342,16 +380,16 @@ Scalar field_amax_no_mark_t( stk::mesh::for_each_entity_run(ngpMesh, xField.entity_rank(), selector, fieldAMax); Scalar localAmax = fieldAMax.get_amax_val(); - Scalar globalAmax = localAmax; auto comm = xField.get_mesh().parallel(); - stk::all_reduce_max(comm, &localAmax, &globalAmax, 1u); - return globalAmax; + stk::all_reduce_max(comm, &localAmax, &amaxOut, 1u); } else { xField.sync_to_host(); - double amaxOut{0.0}; - stk::mesh::field_amax(amaxOut, xField, selector); - return amaxOut; + double tmpAmax = 0.0; + stk::mesh::field_amax(tmpAmax, xField, selector); + amaxOut = tmpAmax; } + + return amaxOut; } template diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/Partition.cpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/Partition.cpp index 59d4e7a10076..cc95d6223656 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/Partition.cpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/Partition.cpp @@ -327,8 +327,6 @@ stk::mesh::FieldVector get_fields_for_bucket(const stk::mesh::BulkData& mesh, void Partition::sort(const EntitySorterBase& sorter) { std::vector partition_key = get_legacy_partition_id(); - //index of bucket in partition - partition_key[ partition_key[0] ] = 0; std::vector entities(m_size); @@ -543,7 +541,6 @@ stk::mesh::Bucket *Partition::get_bucket_for_adds() if (no_buckets()) { std::vector partition_key = get_legacy_partition_id(); - partition_key[ partition_key[0] ] = 0; Bucket *bucket = m_repository->allocate_bucket(m_rank, partition_key, m_repository->get_initial_bucket_capacity(), m_repository->get_maximum_bucket_capacity()); @@ -558,7 +555,6 @@ stk::mesh::Bucket *Partition::get_bucket_for_adds() if (bucket->size() == bucket->capacity()) { if (bucket->size() == m_repository->get_maximum_bucket_capacity()) { std::vector partition_key = get_legacy_partition_id(); - partition_key[ partition_key[0] ] = m_buckets.size(); bucket = m_repository->allocate_bucket(m_rank, partition_key, m_repository->get_initial_bucket_capacity(), m_repository->get_maximum_bucket_capacity()); diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/Partition.hpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/Partition.hpp index 1708c6093b85..a10a754fb2a2 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/Partition.hpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/Partition.hpp @@ -209,34 +209,30 @@ class Partition std::ostream &operator<<(std::ostream &, const stk::mesh::impl::Partition &); -struct PartitionLess { - bool operator()( const Partition * lhs_Partition , const unsigned * rhs ) const ; - bool operator()( const unsigned * lhs , const Partition * rhs_Partition ) const ; -}; - inline bool partition_key_less( const unsigned * lhs , const unsigned * rhs ) { -// const unsigned * const last_lhs = lhs + ( *lhs < *rhs ? *lhs : *rhs ); -// while ( last_lhs != lhs && *lhs == *rhs ) { ++lhs ; ++rhs ; } +// The following (very old) code is clever... So I'm adding some comments. +// +// A partition key is an array of unsigned, laid out like this: +// key[num-part-ordinals, first-part-ordinal, ..., last-part-ordinal] - if (*lhs == *rhs) { + if (*lhs == *rhs) { //num-part-ordinals is equal for lhs and rhs... const unsigned * const last_lhs = lhs + *lhs; do { ++lhs ; ++rhs ; } while ( last_lhs != lhs && *lhs == *rhs ); } - return *lhs < *rhs ; + return *lhs < *rhs; } -// The part count and part ordinals are less -inline bool PartitionLess::operator()( const Partition * lhs_partition , - const unsigned * rhs ) const -{ return partition_key_less( lhs_partition->key() , rhs ); } +struct PartitionLess { + bool operator()( const Partition * lhs_Partition , const unsigned * rhs ) const + { return partition_key_less( lhs_Partition->key() , rhs ); } -inline bool PartitionLess::operator()( const unsigned * lhs , - const Partition * rhs_partition ) const -{ return partition_key_less( lhs , rhs_partition->key() ); } + bool operator()( const unsigned * lhs , const Partition * rhs_Partition ) const + { return partition_key_less( lhs , rhs_Partition->key() ); } +}; inline std::vector::iterator @@ -247,4 +243,5 @@ lower_bound( std::vector & v , const unsigned * key ) } // mesh } // stk -#endif /* PartitionFAMILY_HPP_ */ +#endif /* STK_MESH_IMPL_PARTITION_HPP_ */ + diff --git a/packages/stk/stk_performance_tests/stk_mesh/NgpFieldAccess.cpp b/packages/stk/stk_performance_tests/stk_mesh/NgpFieldAccess.cpp index afb163cd5f13..0a8b1d1837c1 100644 --- a/packages/stk/stk_performance_tests/stk_mesh/NgpFieldAccess.cpp +++ b/packages/stk/stk_performance_tests/stk_mesh/NgpFieldAccess.cpp @@ -124,7 +124,7 @@ class NgpFieldAccess : public stk::unit_test_util::MeshFixture TEST_F(NgpFieldAccess, Centroid) { - if (get_parallel_size() != 1) return; + if (get_parallel_size() != 1) { GTEST_SKIP(); } const unsigned NUM_RUNS = 5; const int NUM_ITERS = 100; @@ -149,7 +149,7 @@ TEST_F(NgpFieldAccess, Centroid) TEST_F(NgpFieldAccess, HostCentroid) { - if (get_parallel_size() != 1) return; + if (get_parallel_size() != 1) { GTEST_SKIP(); } const unsigned NUM_RUNS = 5; const int NUM_ITERS = 100; diff --git a/packages/stk/stk_performance_tests/stk_mesh/ParallelSum.cpp b/packages/stk/stk_performance_tests/stk_mesh/ParallelSum.cpp index 3539d763c041..43f897e8cbd1 100644 --- a/packages/stk/stk_performance_tests/stk_mesh/ParallelSum.cpp +++ b/packages/stk/stk_performance_tests/stk_mesh/ParallelSum.cpp @@ -11,11 +11,15 @@ #include #include // for parallel_machine_rank #include // for parallel_data_exchange... +#include "stk_mesh/base/Types.hpp" // for BucketVector, EntityPr... #include // for Bucket #include // for BulkData, BulkData::NO... #include #include // for field_data, FieldBase #include // for parallel_sum, parallel... +#include +#include +#include #include // for count_selected_entities #include // for Part #include // for Selector, operator| @@ -25,7 +29,6 @@ #include "stk_mesh/base/Entity.hpp" // for Entity #include "stk_mesh/base/Field.hpp" // for Field #include "stk_mesh/base/MetaData.hpp" // for MetaData, put_field_on... -#include "stk_mesh/base/Types.hpp" // for BucketVector, EntityPr... #include "stk_util/environment/Env.hpp" // for parallel_rank, paralle... #include "stk_util/environment/perf_util.hpp" // for get_max_hwm_across_procs #include // for size_t @@ -51,7 +54,7 @@ stk::mesh::EntityId node_id( unsigned x , unsigned y , unsigned z, unsigned nx, return 1 + x + ( nx + 1 ) * ( y + ( ny + 1 ) * z ); } -void do_stk_test(bool with_ghosts=false) +void do_stk_test(bool with_ghosts=false, bool device_mpi=false) { using namespace stk::mesh; @@ -68,14 +71,15 @@ void do_stk_test(bool with_ghosts=false) } return; } - int z_dim = parallel_size*2; - //vector of mesh-dimensions holds the number of elements in each dimension. - //Hard-wired to 3. This test can run with spatial-dimension less than 3, - //(if generated-mesh can do that) but not greater than 3. + const int xdim = device_mpi ? 21 : X_DIM; + const int ydim = device_mpi ? 21 : Y_DIM; + const int zdim = parallel_size*2; + const int numFields = device_mpi ? 5 : NUM_FIELDS; + const int numIters = device_mpi ? 5 : NUM_ITERS; std::ostringstream oss; - oss << "generated:" << X_DIM << "x" << Y_DIM << "x" << z_dim; + oss << "generated:" << xdim << "x" << ydim << "x" << zdim; stk::mesh::MeshBuilder builder(pm); unsigned spatialDim = 3; @@ -89,8 +93,8 @@ void do_stk_test(bool with_ghosts=false) std::cerr << "Mesh: " << oss.str() << std::endl; } - std::vector fields(NUM_FIELDS); - for (int i = 0; i < NUM_FIELDS; ++i) { + std::vector fields(numFields); + for (int i = 0; i < numFields; ++i) { std::ostringstream oss2; oss2 << "field_" << i; FieldBase* field = &meta.declare_field(stk::topology::NODE_RANK, oss2.str()); @@ -162,7 +166,7 @@ void do_stk_test(bool with_ghosts=false) stk::mesh::BucketVector const& node_buckets = bulk.get_buckets(stk::topology::NODE_RANK, communicated_nodes); for (int b = 0, be = node_buckets.size(); b < be; ++b) { stk::mesh::Bucket const& bucket = *node_buckets[b]; - for (int i = 0; i < NUM_FIELDS; ++i) { + for (int i = 0; i < numFields; ++i) { const ScalarField& field = dynamic_cast(*fields[i]); double* data = stk::mesh::field_data(field, bucket); for (int n = 0, ne = bucket.size(); n < ne; ++n) { @@ -174,15 +178,30 @@ void do_stk_test(bool with_ghosts=false) MPI_Barrier(pm); double start_time = stk::cpu_time(); + NgpMesh* ngpMesh = nullptr; + if (device_mpi) { + ngpMesh = & stk::mesh::get_updated_ngp_mesh(bulk); + } - for (int t = 0; t < NUM_ITERS; ++t) { - if (with_ghosts) - { + std::vector*> ngpFields(numFields); + if (device_mpi) { + for (int i = 0; i < numFields; ++i) { + ngpFields[i] = &stk::mesh::get_updated_ngp_field(*fields[i]); + } + } + + for (int t = 0; t < numIters; ++t) { + if (with_ghosts) { + STK_ThrowRequireMsg(!device_mpi, "NGP parallel_sum_including_ghosts not implemented yet."); stk::mesh::parallel_sum_including_ghosts(bulk, fields); } - else - { - stk::mesh::parallel_sum(bulk, fields); + else { + if (device_mpi) { + stk::mesh::parallel_sum_device_mpi(*ngpMesh, ngpFields); + } + else { + stk::mesh::parallel_sum(bulk, fields); + } } } @@ -191,17 +210,23 @@ void do_stk_test(bool with_ghosts=false) double max_time; MPI_Reduce(static_cast(&stk_sum_time), static_cast(&max_time), 1, MPI_DOUBLE, MPI_MAX, 0 /*root*/, MPI_COMM_WORLD); - double power2 = std::pow(2,NUM_ITERS); - double power3 = std::pow(3,NUM_ITERS); + double power2 = std::pow(2,numIters); + double power3 = std::pow(3,numIters); const double tolerance = 1.e-8; + if (device_mpi) { + for (int i = 0; i < numFields; ++i) { + ngpFields[i]->sync_to_host(); + } + } + // Sanity check size_t num_comm_nodes = 0; for (int b = 0, be = node_buckets.size(); b < be; ++b) { stk::mesh::Bucket const& bucket = *node_buckets[b]; const bool isShared = bucket.shared(); num_comm_nodes += bucket.size(); - for (int f = 0; f < NUM_FIELDS; ++f) { + for (int f = 0; f < numFields; ++f) { const ScalarField& field = dynamic_cast(*fields[f]); const double* stk_data = stk::mesh::field_data(field, bucket); const double expected_shared_value = static_cast(f+1) * power2; @@ -209,15 +234,15 @@ void do_stk_test(bool with_ghosts=false) const double expected = isShared ? expected_shared_value : expected_ghosted_value; for (int n = 0, ne = bucket.size(); n < ne; ++n) { const double relativeError = std::abs(stk_data[n] - expected) / expected; - EXPECT_NEAR(0.0, relativeError, tolerance); + EXPECT_NEAR(0.0, relativeError, tolerance)<<"node "< +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +TEST(PrintTimersTable, performance) +{ + stk::ParallelMachine comm = MPI_COMM_WORLD; + + const unsigned NUM_BATCHES = 5; + const unsigned NUM_RUNS = 5; + + stk::unit_test_util::BatchTimer batchTimer(comm); + batchTimer.initialize_batch_timer(); + + for(unsigned b=0; b(stk::topology::NODE_RANK, "Coordinates") ), owns_mesh(false) { + if (!elemPartAlias.empty()) { + m_meta.add_part_alias(*m_elem_parts[0], elemPartAlias); + } //put coord-field on all nodes: put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -151,6 +155,24 @@ HexFixture::HexFixture(stk::ParallelMachine pm, put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } +void HexFixture::fill_mesh(size_t nx, + size_t ny, + size_t nz, + BulkData& bulk, + const std::string& elemPartAlias) +{ + size_t nidStart = 1; + size_t eidStart = 1; + if (!bulk.mesh_meta_data().is_initialized()) { + const size_t spatialDim = 3; + const std::string coordFieldName("Coordinates"); + bulk.mesh_meta_data().initialize(spatialDim, stk::mesh::entity_rank_names(), coordFieldName); + } + HexFixture hexFixture(bulk.mesh_meta_data(), bulk, nx, ny, nz, nidStart, eidStart, elemPartAlias); + hexFixture.m_meta.commit(); + hexFixture.generate_mesh(); +} + HexFixture::~HexFixture() { diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/HexFixture.hpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/HexFixture.hpp index ad4c6d701d9b..30c6c1a5891a 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/HexFixture.hpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/HexFixture.hpp @@ -84,7 +84,8 @@ class HexFixture size_t ny, size_t nz, size_t nid_start, - size_t eid_start); + size_t eid_start, + const std::string& elemPartAlias = std::string("")); HexFixture(stk::ParallelMachine pm, size_t nx, @@ -103,6 +104,12 @@ class HexFixture size_t nz, bool auraOn); + static void fill_mesh(size_t nx, + size_t ny, + size_t nz, + BulkData& bulk, + const std::string& elemPartAlias = std::string("")); + const int m_spatial_dimension; const size_t m_nx; const size_t m_ny; diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestStkBalanceDecomposition.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestStkBalanceDecomposition.cpp index bd492095fbd8..86b06bf01e60 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestStkBalanceDecomposition.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestStkBalanceDecomposition.cpp @@ -96,8 +96,7 @@ class StkBalanceDecomposition : public stk::unit_test_util::MeshFixture TEST_F(StkBalanceDecomposition, 4Elem1ProcMesh_EntireDomain) { - if (stk::parallel_machine_size(get_comm()) != 1) return; - + if (stk::parallel_machine_size(get_comm()) != 1) { GTEST_SKIP(); } setup_initial_mesh("generated:1x1x4"); balance_mesh({get_meta().universal_part()}); diff --git a/packages/stk/stk_unit_tests/stk_expreval/UnitTestEvaluator.cpp b/packages/stk/stk_unit_tests/stk_expreval/UnitTestEvaluator.cpp index 16b8daf7da74..f4c24d8b8174 100644 --- a/packages/stk/stk_unit_tests/stk_expreval/UnitTestEvaluator.cpp +++ b/packages/stk/stk_unit_tests/stk_expreval/UnitTestEvaluator.cpp @@ -36,17 +36,22 @@ #include #include #include +#include #include #include #include #include #include #include +#include "stk_expreval/NgpNode.hpp" +#include "stk_expreval/Node.hpp" namespace { using ViewInt1DHostType = Kokkos::View; +using FPErrorBehavior = stk::expreval::Eval::FPErrorBehavior; + bool has_variable(const std::vector& variableNames, const std::string& variableName) { @@ -87,6 +92,7 @@ double evaluate(const std::string & expression, const stk::expreval::Variable::ArrayOffset arrayOffsetType = stk::expreval::Variable::ZERO_BASED_INDEX) { stk::expreval::Eval eval(expression, arrayOffsetType); + eval.set_fp_error_behavior(stk::expreval::Eval::FPErrorBehavior::Error); eval.parse(); for (ScalarBinding & scalar : boundScalars) { @@ -565,6 +571,37 @@ TEST( UnitTestEvaluator, testEvaluateEmptyString) EXPECT_EQ(0.0, result); } +TEST( UnitTestEvaluator, FunctionNameNullTerminated) +{ + stk::expreval::Eval eval("sin(0.5)"); + eval.parse(); + for (int i=0; i < eval.get_node_count(); ++i) + { + stk::expreval::Node* node = eval.get_node(i); + if (node->m_opcode == stk::expreval::OPCODE_FUNCTION) + { + EXPECT_EQ(std::strcmp(node->m_data.function.functionName, "sin"), 0); + } + } +} + +#ifndef STK_ENABLE_GPU + +TEST(UnitTestEvaluator, CheckNGPNodeFPError_Ignore) +{ + FPErrorBehavior m_fpErrorBehavior = FPErrorBehavior::Ignore; + EXPECT_NO_THROW(checkNgpNodeFPError(NAN, "foo")); +} + +TEST(UnitTestEvaluator, CheckNGPNodeFPError_Error) +{ + FPErrorBehavior m_fpErrorBehavior = FPErrorBehavior::Error; + EXPECT_ANY_THROW(checkNgpNodeFPError(NAN, "foo")); +} + +#endif + + TEST(UnitTestEvaluator, test_copy_constructor) { double a = 1.0; @@ -2224,6 +2261,9 @@ TEST(UnitTestEvaluator, testFunction_sqrt) EXPECT_DOUBLE_EQ(evaluate("sqrt(9)"), 3); EXPECT_DOUBLE_EQ(evaluate("sqrt(2)"), std::sqrt(2)); EXPECT_DOUBLE_EQ(evaluate("sqrt(1.21)"), 1.1); + if (stk::util::have_errno() || stk::util::have_errexcept()) { + EXPECT_ANY_THROW(evaluate("sqrt(-1)")); + } } TEST(UnitTestEvaluator, Ngp_testFunction_sqrt) @@ -2234,6 +2274,36 @@ TEST(UnitTestEvaluator, Ngp_testFunction_sqrt) EXPECT_DOUBLE_EQ(device_evaluate("sqrt(9)"), 3); EXPECT_DOUBLE_EQ(device_evaluate("sqrt(2)"), std::sqrt(2)); EXPECT_DOUBLE_EQ(device_evaluate("sqrt(1.21)"), 1.1); + if (stk::util::have_errno() || stk::util::have_errexcept()) { + KOKKOS_IF_ON_HOST( + EXPECT_ANY_THROW(evaluate("sqrt(-1)")); + ) + } +} + +TEST(UnitTestEvaluator, IgnoreFloatingPointError) +{ + stk::expreval::Eval eval("sqrt(-1)"); + eval.set_fp_error_behavior(stk::expreval::Eval::FPErrorBehavior::Ignore); + eval.parse(); + EXPECT_NO_THROW(eval.evaluate()); +} + +TEST(UnitTestEvaluator, WarnFloatingPointError) +{ + stk::expreval::Eval eval("sqrt(-1)"); + eval.set_fp_error_behavior(stk::expreval::Eval::FPErrorBehavior::Warn); + eval.parse(); + EXPECT_NO_THROW(eval.evaluate()); +} + +TEST(UnitTestEvaluator, ThrowFloatingPointError) +{ + if (!stk::util::have_errno() && !stk::util::have_errexcept()) { GTEST_SKIP(); } + stk::expreval::Eval eval("sqrt(-1)"); + eval.set_fp_error_behavior(stk::expreval::Eval::FPErrorBehavior::Error); + eval.parse(); + EXPECT_ANY_THROW(eval.evaluate()); } TEST(UnitTestEvaluator, testFunction_exp) @@ -2598,7 +2668,7 @@ TEST(UnitTestEvaluator, testFunction_atanh) EXPECT_DOUBLE_EQ(evaluate("atanh(0)"), 0); EXPECT_DOUBLE_EQ(evaluate("atanh(0.1)"), std::atanh(0.1)); EXPECT_DOUBLE_EQ(evaluate("atanh(0.5)"), std::atanh(0.5)); - EXPECT_DOUBLE_EQ(evaluate("atanh(1)"), std::atanh(1)); + EXPECT_DOUBLE_EQ(evaluate("atanh(0.9)"), std::atanh(0.9)); } TEST(UnitTestEvaluator, Ngp_testFunction_atanh) @@ -2607,7 +2677,7 @@ TEST(UnitTestEvaluator, Ngp_testFunction_atanh) EXPECT_DOUBLE_EQ(device_evaluate("atanh(0)"), 0); EXPECT_DOUBLE_EQ(device_evaluate("atanh(0.1)"), std::atanh(0.1)); EXPECT_DOUBLE_EQ(device_evaluate("atanh(0.5)"), std::atanh(0.5)); - EXPECT_DOUBLE_EQ(device_evaluate("atanh(1)"), std::atanh(1)); + EXPECT_DOUBLE_EQ(device_evaluate("atanh(0.9)"), std::atanh(0.9)); } TEST(UnitTestEvaluator, testFunction_erf) diff --git a/packages/stk/stk_unit_tests/stk_io/UnitTestWriteSTKMesh.cpp b/packages/stk/stk_unit_tests/stk_io/UnitTestWriteSTKMesh.cpp index 75e180bd1c8b..7ca4388e788f 100644 --- a/packages/stk/stk_unit_tests/stk_io/UnitTestWriteSTKMesh.cpp +++ b/packages/stk/stk_unit_tests/stk_io/UnitTestWriteSTKMesh.cpp @@ -1,44 +1,42 @@ #include -#include "mpi.h" #include #include #include #include -#include #include #include #include #include #include -#include #include #include #include #include #include +#include #include #include +#include #include #include -#include #include #include #include #include -#include +#include #include #include #include +#include #include #include // for unlink -#include "stk_util/environment/Env.hpp" #include namespace { @@ -62,24 +60,83 @@ Ioss::DatabaseIO* create_output_db_io(const std::string &filename) return db_io; } -//BeginDocTest1 -TEST(StkIo, write_stk_mesh_to_file) +void verify_num_nodes_in_file(MPI_Comm comm, + const std::string& meshFileName, + unsigned expectedNumNodes) +{ + std::shared_ptr bulkData = build_mesh(comm); + stk::io::fill_mesh(meshFileName, *bulkData); + + std::vector entity_counts; + stk::mesh::comm_mesh_counts(*bulkData, entity_counts); + EXPECT_EQ(expectedNumNodes, entity_counts[stk::topology::NODE_RANK]); +} + +void fill_node_ids_and_coords(const stk::mesh::BulkData& bulk, + std::vector& node_ids, + std::vector& coordinates) +{ + const stk::mesh::MetaData& meta = bulk.mesh_meta_data(); + stk::mesh::Field * coordField = meta.get_field(stk::topology::NODE_RANK, "coordinates"); + int spatial_dim = meta.spatial_dimension(); + + STK_ThrowAssert(coordField != NULL); + + stk::mesh::Selector locallyOwned = meta.locally_owned_part(); + + int node_counter = 0; + stk::mesh::for_each_entity_run_no_threads(bulk, stk::topology::NODE_RANK, locallyOwned, + [&](const stk::mesh::BulkData& mesh, stk::mesh::Entity node) + { + int node_id = mesh.identifier(node); + node_ids[node_counter] = node_id; + + const double* coords = stk::mesh::field_data(*coordField, node); + for(int k=0;k& elem_ids, + std::vector& connectivity) +{ + stk::mesh::EntityVector elems; + stk::mesh::get_entities(bulkData, stk::topology::ELEM_RANK, *elemBlock, elems); + + elem_ids.resize(elems.size()); + const unsigned connectivity_size = elems.size()*elemBlock->topology().num_nodes(); + connectivity.resize(connectivity_size); + + unsigned conn_counter = 0; + for(size_t j=0;j bulkData = build_mesh(comm); stk::mesh::MetaData& meta = bulkData->mesh_meta_data(); stk::io::fill_mesh("generated:2x2x2|sideset:xX|nodeset:x", *bulkData); - const stk::mesh::PartVector & all_parts = meta.get_parts(); - Ioss::DatabaseIO* db_io = create_output_db_io(file_written); - Ioss::Region output_region(db_io); EXPECT_TRUE(db_io->ok()); + Ioss::Region output_region(db_io); //////////////////////////////////////////////////////////// @@ -96,26 +153,19 @@ TEST(StkIo, write_stk_mesh_to_file) Ioss::NodeBlock *output_node_block = new Ioss::NodeBlock(db_io, NodeBlockName, num_nodes, spatial_dim); output_region.add(output_node_block); - for(stk::mesh::PartVector::const_iterator i = all_parts.begin(); i != all_parts.end(); ++i) - { - stk::mesh::Part * const part = *i; - - if(stk::io::is_part_io_part(*part)) // this means it is an io_part - { - if(part->primary_entity_rank() == stk::topology::ELEMENT_RANK) - { - stk::mesh::EntityVector entities; - const stk::mesh::BucketVector &input_buckets = bulkData->buckets(stk::topology::ELEMENT_RANK); - stk::mesh::get_selected_entities(*part, input_buckets, entities); - Ioss::ElementBlock *output_element_block = new Ioss::ElementBlock(db_io, part->name(), part->topology().name(), entities.size()); - - output_element_block->property_add(Ioss::Property("original_topology_type", part->topology().name())); - output_element_block->property_add(Ioss::Property("id", part->id())); - output_region.add(output_element_block); - - // how about attributes? - } - } + stk::mesh::PartVector elemBlockParts; + stk::mesh::fill_element_block_parts(meta, stk::topology::HEX_8, elemBlockParts); + + for(const stk::mesh::Part* elemBlock : elemBlockParts) { + STK_ThrowRequireMsg(stk::io::is_part_io_part(*elemBlock),"element-block-part "<name()<<" is not an IO part."); + unsigned numElems = stk::mesh::count_entities(*bulkData, stk::topology::ELEM_RANK, *elemBlock); + Ioss::ElementBlock *output_element_block = new Ioss::ElementBlock(db_io, elemBlock->name(), elemBlock->topology().name(), numElems); + + output_element_block->property_add(Ioss::Property("original_topology_type", elemBlock->topology().name())); + output_element_block->property_add(Ioss::Property("id", elemBlock->id())); + output_region.add(output_element_block); + + // how about attributes? } output_region.end_mode(Ioss::STATE_DEFINE_MODEL); @@ -126,94 +176,32 @@ TEST(StkIo, write_stk_mesh_to_file) Ioss::NodeBlock *node_block = output_region.get_node_blocks()[0]; - stk::mesh::Field * coordField = meta.get_field(stk::topology::NODE_RANK, "coordinates"); - - ASSERT_TRUE(coordField != NULL); - std::vector coordinates(spatial_dim*num_nodes); std::vector node_ids(num_nodes); - stk::mesh::Selector local_nodes = meta.locally_owned_part(); - - const stk::mesh::BucketVector &input_buckets = bulkData->get_buckets(stk::topology::NODE_RANK, local_nodes); - - int node_counter = 0; - for(size_t i=0;iidentifier(node); - node_ids[node_counter] = node_id; - - double* coords = stk::mesh::field_data(*coordField, node); - for(int k=0;kput_field_data("mesh_model_coordinates", coordinates); node_block->put_field_data("ids", node_ids); - for(stk::mesh::PartVector::const_iterator i = all_parts.begin(); i != all_parts.end(); ++i) - { - stk::mesh::Part * const part = *i; - - if(stk::io::is_part_io_part(*part)) // this means it is an io_part - { - if(part->primary_entity_rank() == stk::topology::ELEMENT_RANK) - { - stk::mesh::EntityVector entities; - const stk::mesh::BucketVector &input_bucketsA = bulkData->buckets(stk::topology::ELEMENT_RANK); - stk::mesh::get_selected_entities(*part, input_bucketsA, entities); - Ioss::ElementBlock *output_element_block = output_region.get_element_block(part->id()); - - std::vector elem_ids(entities.size()); - unsigned connectivity_size = entities.size()*part->topology().num_nodes(); - std::vector connectivity(connectivity_size); - unsigned conn_counter = 0; - - for(size_t j=0;jidentifier(entities[j]); - unsigned num_nodes_per = bulkData->num_nodes(entities[j]); - const stk::mesh::Entity *nodes = bulkData->begin_nodes(entities[j]); - for(unsigned k=0;kidentifier(nodes[k]); - conn_counter++; - } - } - - output_element_block->put_field_data("connectivity_raw", connectivity); - output_element_block->put_field_data("ids", elem_ids); - } - } + for(const stk::mesh::Part* elemBlock : elemBlockParts) { + std::vector elem_ids; + std::vector connectivity; + + fill_elem_ids_and_connectivity(*bulkData, elemBlock, elem_ids, connectivity); + + Ioss::ElementBlock *output_element_block = output_region.get_element_block(elemBlock->id()); + output_element_block->put_field_data("connectivity_raw", connectivity); + output_element_block->put_field_data("ids", elem_ids); } output_region.end_mode(Ioss::STATE_MODEL); //////////////////////////////////////////////////////////// } - if(stk::parallel_machine_size(comm) == 1) - { - std::shared_ptr bulkData = build_mesh(comm); - - stk::io::fill_mesh(file_written, *bulkData); - - std::vector entity_counts; - stk::mesh::comm_mesh_counts(*bulkData, entity_counts); - EXPECT_EQ(27u, entity_counts[stk::topology::NODE_RANK]); - } - + verify_num_nodes_in_file(comm, file_written, 27); unlink(file_written.c_str()); - } -//EndDocTest1 class StkIoResultsOutput : public stk::unit_test_util::MeshFixture { diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestBulkData.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestBulkData.cpp index 95de942fa434..f384a8949659 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestBulkData.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestBulkData.cpp @@ -5815,8 +5815,7 @@ TEST(FaceCreation, test_face_creation_2Hexes_2procs) stk::mesh::MetaData meta(3); stk::unit_test_util::BulkDataFaceSharingTester mesh(meta, MPI_COMM_WORLD); - const std::string generatedMeshSpec = "generated:1x1x2"; - stk::io::fill_mesh(generatedMeshSpec, mesh); + stk::mesh::fixtures::HexFixture::fill_mesh(1,1,2, mesh); int procId = stk::parallel_machine_rank(MPI_COMM_WORLD); @@ -6018,8 +6017,7 @@ TEST(ChangeEntityId, test_throw_on_shared_node) std::shared_ptr bulkPtr = stk::unit_test_util::build_mesh(spatialDim, MPI_COMM_WORLD); stk::mesh::BulkData& mesh = *bulkPtr; - const std::string generatedMeshSpec = "generated:1x1x2"; - stk::io::fill_mesh(generatedMeshSpec, mesh); + stk::mesh::fixtures::HexFixture::fill_mesh(1,1,2, mesh); stk::mesh::Entity sharedNode5 = mesh.get_entity(stk::topology::NODE_RANK, 5); @@ -6041,8 +6039,7 @@ TEST(AmbiguousTopology, hexRedefinedAsShell) stk::mesh::MetaData& meta= bulkPtr->mesh_meta_data(); stk::mesh::BulkData& mesh = *bulkPtr; - const std::string generatedMeshSpec = "generated:1x1x1"; - stk::io::fill_mesh(generatedMeshSpec, mesh); + stk::mesh::fixtures::HexFixture::fill_mesh(1,1,1, mesh); stk::mesh::Part& shellPart = meta.get_topology_root_part(stk::topology::SHELL_QUAD_4); stk::mesh::EntityId elemId = 1; diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeParts.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeParts.cpp index c55edaf4185c..d1b2f883f726 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeParts.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeParts.cpp @@ -96,14 +96,78 @@ TEST(UnitTestChangeParts, test_throw_on_internal_part_change) EXPECT_THROW(bulkData.change_entity_parts(node, addParts, removeParts), std::runtime_error); } +void do_simple_batch_part_change_test(stk::mesh::BulkData& bulkData) +{ + stk::mesh::MetaData& metaData = bulkData.mesh_meta_data(); + stk::mesh::Part& bluePart = metaData.declare_part("blue_part"); + stk::mesh::Part& redPart = metaData.declare_part("red_part"); + + stk::mesh::Entity elem1 = bulkData.get_entity(stk::topology::ELEM_RANK, 1u); + EXPECT_TRUE(bulkData.is_valid(elem1)); + + stk::mesh::EntityVector nodes(bulkData.begin_nodes(elem1), bulkData.begin_nodes(elem1)+bulkData.num_nodes(elem1)); + EXPECT_EQ(8u, nodes.size()); + + for(stk::mesh::Entity node : nodes) { + EXPECT_FALSE(bulkData.bucket(node).member(bluePart)); + EXPECT_FALSE(bulkData.bucket(node).member(redPart)); + } + + stk::mesh::PartVector blue_parts(1, &bluePart); + stk::mesh::PartVector red_parts(1, &redPart); + bulkData.batch_change_entity_parts(nodes, blue_parts, {}); + nodes.resize(4); + bulkData.batch_change_entity_parts(nodes, red_parts, blue_parts); + + for(stk::mesh::Entity node : nodes) { + EXPECT_TRUE(bulkData.bucket(node).member(redPart)); + EXPECT_FALSE(bulkData.bucket(node).member(bluePart)); + } + + nodes.resize(1); + bulkData.batch_change_entity_parts(nodes, blue_parts, red_parts); + + EXPECT_TRUE(bulkData.bucket(nodes[0]).member(bluePart)); + EXPECT_FALSE(bulkData.bucket(nodes[0]).member(redPart)); +} + +TEST(UnitTestChangeParts, genmesh_test_batch_part_change_1_node) +{ + stk::ParallelMachine pm = MPI_COMM_WORLD; + const int p_size = stk::parallel_machine_size( pm ); + + if (p_size != 1) { GTEST_SKIP(); } + + const int spatialDim = 3; + std::shared_ptr bulkPtr = build_mesh(spatialDim, pm, stk::mesh::BulkData::NO_AUTO_AURA); + + stk::io::fill_mesh("generated:1x1x1", *bulkPtr); + + do_simple_batch_part_change_test(*bulkPtr); +} + +TEST(UnitTestChangeParts, test_batch_part_change_1_node) +{ + stk::ParallelMachine pm = MPI_COMM_WORLD; + const int p_size = stk::parallel_machine_size( pm ); + + if (p_size != 1) { GTEST_SKIP(); } + + const int spatialDim = 3; + std::shared_ptr bulkPtr = build_mesh(spatialDim, pm, stk::mesh::BulkData::NO_AUTO_AURA); + + std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8,block_1"; + stk::unit_test_util::setup_text_mesh(*bulkPtr, meshDesc); + + do_simple_batch_part_change_test(*bulkPtr); +} + TEST(UnitTestChangeParts, test_batch_part_change) { stk::ParallelMachine pm = MPI_COMM_WORLD; const int p_size = stk::parallel_machine_size( pm ); - if (p_size != 1) { - return; - } + if (p_size != 1) { GTEST_SKIP(); } const int spatialDim = 3; std::shared_ptr bulkPtr = build_mesh(spatialDim, pm, stk::mesh::BulkData::NO_AUTO_AURA); diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestCreateFaces.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestCreateFaces.cpp index 9f446199215a..28241beec212 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestCreateFaces.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestCreateFaces.cpp @@ -113,14 +113,12 @@ TEST ( UnitTestCreateFaces, Hex_2x1x1 ) const size_t NY = 1; const size_t NZ = 1; - stk::mesh::fixtures::HexFixture fixture( MPI_COMM_WORLD, NX, NY, NZ); - - fixture.m_meta.commit(); - fixture.generate_mesh(); + std::shared_ptr bulkPtr = build_mesh(MPI_COMM_WORLD); + stk::mesh::fixtures::HexFixture::fill_mesh(NX, NY, NZ, *bulkPtr); { std::vector counts ; - stk::mesh::comm_mesh_counts( fixture.m_bulk_data , counts); + stk::mesh::comm_mesh_counts( *bulkPtr , counts); EXPECT_EQ( exp_node_count(NX, NY, NZ), counts[node_rank] ); // nodes EXPECT_EQ( 0u, counts[edge_rank] ); // edges @@ -128,11 +126,11 @@ TEST ( UnitTestCreateFaces, Hex_2x1x1 ) EXPECT_EQ( exp_hex_count(NX, NY, NZ), counts[elem_rank] ); // elements } - stk::mesh::create_faces(fixture.m_bulk_data); + stk::mesh::create_faces(*bulkPtr); { std::vector counts ; - stk::mesh::comm_mesh_counts( fixture.m_bulk_data , counts); + stk::mesh::comm_mesh_counts( *bulkPtr , counts); EXPECT_EQ( exp_node_count(NX, NY, NZ), counts[node_rank] ); // nodes EXPECT_EQ( 0u , counts[edge_rank] ); // edges diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestDestroyElements.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestDestroyElements.cpp index b9528d885cff..2172852b1a7f 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestDestroyElements.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestDestroyElements.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -660,7 +661,7 @@ TEST(DestroyElements, destroyAll) builder.set_maximum_bucket_capacity(2); std::shared_ptr bulkPtr = builder.create(); - stk::io::fill_mesh("generated:1x1x4", *bulkPtr); + stk::mesh::fixtures::HexFixture::fill_mesh(1,1,4, *bulkPtr, "block_1"); stk::mesh::Part* block1 = bulkPtr->mesh_meta_data().get_part("block_1"); stk::mesh::Part& block2 = bulkPtr->mesh_meta_data().declare_part("block_2", stk::topology::ELEM_RANK); stk::mesh::EntityVector elemsToMove = { diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestField.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestField.cpp index 1dced60a826b..979e9725ab88 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestField.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestField.cpp @@ -79,6 +79,7 @@ namespace Ioss { class DatabaseIO; } namespace { const stk::topology::rank_t NODE_RANK = stk::topology::NODE_RANK; +using ngp_unit_test_utils::check_bucket_layout; using stk::unit_test_util::build_mesh; TEST(UnitTestField, testFieldMaxSize) @@ -1562,7 +1563,7 @@ TEST_F(VariableCapacityBuckets, createNodes_initialCapacity1_maxCapacity1) check_num_buckets(*m_bulk, 1); check_bucket_sizes(*m_bulk, {1}); check_bucket_capacities(*m_bulk, {1}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1}}}, bucketRank); } { SCOPED_TRACE("Create Node 2"); @@ -1571,7 +1572,7 @@ TEST_F(VariableCapacityBuckets, createNodes_initialCapacity1_maxCapacity1) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {1, 1}); check_bucket_capacities(*m_bulk, {1, 1}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1}}, {"block_1", {2}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1}}, {{"block_1"}, {2}}}, bucketRank); } { SCOPED_TRACE("Create Node 3"); @@ -1580,7 +1581,7 @@ TEST_F(VariableCapacityBuckets, createNodes_initialCapacity1_maxCapacity1) check_num_buckets(*m_bulk, 3); check_bucket_sizes(*m_bulk, {1, 1, 1}); check_bucket_capacities(*m_bulk, {1, 1, 1}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1}}, {"block_1", {2}}, {"block_1", {3}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1}}, {{"block_1"}, {2}}, {{"block_1"}, {3}}}, bucketRank); } } @@ -1599,7 +1600,7 @@ TEST_F(VariableCapacityBuckets, createNodes_initialCapacity2_maxCapacity2) check_num_buckets(*m_bulk, 1); check_bucket_sizes(*m_bulk, {1}); check_bucket_capacities(*m_bulk, {2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1}}}, bucketRank); } { SCOPED_TRACE("Create Node 2"); @@ -1608,7 +1609,7 @@ TEST_F(VariableCapacityBuckets, createNodes_initialCapacity2_maxCapacity2) check_num_buckets(*m_bulk, 1); check_bucket_sizes(*m_bulk, {2}); check_bucket_capacities(*m_bulk, {2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1, 2}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1, 2}}}, bucketRank); } { SCOPED_TRACE("Create Node 3"); @@ -1617,7 +1618,7 @@ TEST_F(VariableCapacityBuckets, createNodes_initialCapacity2_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1, 2}}, {"block_1", {3}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1, 2}}, {{"block_1"}, {3}}}, bucketRank); } } @@ -1636,7 +1637,7 @@ TEST_F(VariableCapacityBuckets, createNodes_initialCapacity1_maxCapacity2) check_num_buckets(*m_bulk, 1); check_bucket_sizes(*m_bulk, {1}); check_bucket_capacities(*m_bulk, {1}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1}}}, bucketRank); } { SCOPED_TRACE("Create Node 2"); @@ -1645,7 +1646,7 @@ TEST_F(VariableCapacityBuckets, createNodes_initialCapacity1_maxCapacity2) check_num_buckets(*m_bulk, 1); check_bucket_sizes(*m_bulk, {2}); check_bucket_capacities(*m_bulk, {2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1, 2}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1, 2}}}, bucketRank); } { SCOPED_TRACE("Create Node 3"); @@ -1654,7 +1655,7 @@ TEST_F(VariableCapacityBuckets, createNodes_initialCapacity1_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 1}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1, 2}}, {"block_1", {3}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1, 2}}, {{"block_1"}, {3}}}, bucketRank); } } @@ -1676,7 +1677,7 @@ TEST_F(VariableCapacityBuckets, changeNodeParts_initialCapacity2_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1, 2}}, {"block_1", {3}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1, 2}}, {{"block_1"}, {3}}}, bucketRank); } { SCOPED_TRACE("Change parts for Node 1"); @@ -1685,7 +1686,7 @@ TEST_F(VariableCapacityBuckets, changeNodeParts_initialCapacity2_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {2, 3}}, {"block_2", {1}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {2, 3}}, {{"block_2"}, {1}}}, bucketRank); } { SCOPED_TRACE("Change parts for Node 2"); @@ -1694,7 +1695,7 @@ TEST_F(VariableCapacityBuckets, changeNodeParts_initialCapacity2_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {1, 2}); check_bucket_capacities(*m_bulk, {2, 2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {3}}, {"block_2", {1, 2}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {3}}, {{"block_2"}, {1, 2}}}, bucketRank); } { SCOPED_TRACE("Change parts for Node 3"); @@ -1703,7 +1704,7 @@ TEST_F(VariableCapacityBuckets, changeNodeParts_initialCapacity2_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_2", {1, 2}}, {"block_2", {3}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_2"}, {1, 2}}, {{"block_2"}, {3}}}, bucketRank); } } @@ -1725,7 +1726,7 @@ TEST_F(VariableCapacityBuckets, changeNodeParts_initialCapacity1_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 1}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1, 2}}, {"block_1", {3}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1, 2}}, {{"block_1"}, {3}}}, bucketRank); } { @@ -1735,7 +1736,7 @@ TEST_F(VariableCapacityBuckets, changeNodeParts_initialCapacity1_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 1}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {2, 3}}, {"block_2", {1}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {2, 3}}, {{"block_2"}, {1}}}, bucketRank); } { @@ -1745,7 +1746,7 @@ TEST_F(VariableCapacityBuckets, changeNodeParts_initialCapacity1_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {1, 2}); check_bucket_capacities(*m_bulk, {2, 2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {3}}, {"block_2", {1, 2}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {3}}, {{"block_2"}, {1, 2}}}, bucketRank); } { @@ -1755,7 +1756,7 @@ TEST_F(VariableCapacityBuckets, changeNodeParts_initialCapacity1_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 1}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_2", {1, 2}}, {"block_2", {3}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_2"}, {1, 2}}, {{"block_2"}, {3}}}, bucketRank); } } @@ -1772,12 +1773,12 @@ TEST_F(VariableCapacityBuckets, initialMeshConstruction_initialCapacity2_maxCapa stk::mesh::EntityVector newNodes; m_bulk->modification_begin(); m_bulk->declare_entities(stk::topology::NODE_RANK, ids, stk::mesh::PartVector{&block1}, newNodes); + m_bulk->modification_end(); check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1, 2}}, {"block_1", {3}}}, bucketRank); - m_bulk->modification_end(); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1, 2}}, {{"block_1"}, {3}}}, bucketRank); } } @@ -1794,12 +1795,12 @@ TEST_F(VariableCapacityBuckets, initialMeshConstruction_initialCapacity1_maxCapa stk::mesh::EntityVector newNodes; m_bulk->modification_begin(); m_bulk->declare_entities(stk::topology::NODE_RANK, ids, stk::mesh::PartVector{&block1}, newNodes); + m_bulk->modification_end(); check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 1}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1, 2}}, {"block_1", {3}}}, bucketRank); - m_bulk->modification_end(); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1, 2}}, {{"block_1"}, {3}}}, bucketRank); } } @@ -1860,7 +1861,7 @@ class VariableCapacityFieldData : public ::testing::TestWithParam(numRanks, alignment); } else if (GetParam() == FieldDataManagerType::CONTIGUOUS) { - const unsigned extraCapacity = 0; + const unsigned extraCapacity = 4; // Room for 1 extra int, for occasional in-place sorting const unsigned alignment = 4; fieldDataManager = std::make_unique(extraCapacity, alignment); } @@ -2203,7 +2204,7 @@ TEST_P(VariableCapacityFieldData, changeNodeParts_initialCapacity2_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1, 2}}, {"block_1", {3}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1, 2}}, {{"block_1"}, {3}}}, bucketRank); check_expected_bytes_allocated(*m_bulk, field); check_field_values(*m_bulk, field); } @@ -2215,7 +2216,7 @@ TEST_P(VariableCapacityFieldData, changeNodeParts_initialCapacity2_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {2, 3}}, {"block_2", {1}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {2, 3}}, {{"block_2"}, {1}}}, bucketRank); check_expected_bytes_allocated(*m_bulk, field); check_field_values(*m_bulk, field); } @@ -2227,7 +2228,7 @@ TEST_P(VariableCapacityFieldData, changeNodeParts_initialCapacity2_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {1, 2}); check_bucket_capacities(*m_bulk, {2, 2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {3}}, {"block_2", {1, 2}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {3}}, {{"block_2"}, {1, 2}}}, bucketRank); check_expected_bytes_allocated(*m_bulk, field); check_field_values(*m_bulk, field); } @@ -2238,7 +2239,7 @@ TEST_P(VariableCapacityFieldData, changeNodeParts_initialCapacity2_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_2", {1, 2}}, {"block_2", {3}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_2"}, {1, 2}}, {{"block_2"}, {3}}}, bucketRank); check_expected_bytes_allocated(*m_bulk, field); check_field_values(*m_bulk, field); } @@ -2265,7 +2266,7 @@ TEST_P(VariableCapacityFieldData, changeNodeParts_initialCapacity1_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 1}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {1, 2}}, {"block_1", {3}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {1, 2}}, {{"block_1"}, {3}}}, bucketRank); check_expected_bytes_allocated(*m_bulk, field); check_field_values(*m_bulk, field); } @@ -2277,7 +2278,7 @@ TEST_P(VariableCapacityFieldData, changeNodeParts_initialCapacity1_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 1}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {2, 3}}, {"block_2", {1}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {2, 3}}, {{"block_2"}, {1}}}, bucketRank); check_expected_bytes_allocated(*m_bulk, field); check_field_values(*m_bulk, field); } @@ -2289,7 +2290,7 @@ TEST_P(VariableCapacityFieldData, changeNodeParts_initialCapacity1_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {1, 2}); check_bucket_capacities(*m_bulk, {2, 2}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_1", {3}}, {"block_2", {1, 2}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_1"}, {3}}, {{"block_2"}, {1, 2}}}, bucketRank); check_expected_bytes_allocated(*m_bulk, field); check_field_values(*m_bulk, field); } @@ -2300,7 +2301,7 @@ TEST_P(VariableCapacityFieldData, changeNodeParts_initialCapacity1_maxCapacity2) check_num_buckets(*m_bulk, 2); check_bucket_sizes(*m_bulk, {2, 1}); check_bucket_capacities(*m_bulk, {2, 1}); - ngp_unit_test_utils::check_bucket_layout(*m_bulk, {{"block_2", {1, 2}}, {"block_2", {3}}}, bucketRank); + check_bucket_layout(*m_bulk, {{{"block_2"}, {1, 2}}, {{"block_2"}, {3}}}, bucketRank); check_expected_bytes_allocated(*m_bulk, field); check_field_values(*m_bulk, field); } @@ -2325,10 +2326,10 @@ TEST_P(VariableCapacityFieldData, initialMeshConstruction_initialCapacity2_maxCa m_bulk->modification_begin(); m_bulk->declare_entities(stk::topology::NODE_RANK, ids, stk::mesh::PartVector{&block1}, newNodes); m_bulk->allocate_field_data(); + m_bulk->modification_end(); check_num_buckets(*m_bulk, 2); check_expected_bytes_allocated(*m_bulk, field); - m_bulk->modification_end(); } } @@ -2351,10 +2352,10 @@ TEST_P(VariableCapacityFieldData, initialMeshConstruction_initialCapacity1_maxCa m_bulk->modification_begin(); m_bulk->declare_entities(stk::topology::NODE_RANK, ids, stk::mesh::PartVector{&block1}, newNodes); m_bulk->allocate_field_data(); + m_bulk->modification_end(); check_num_buckets(*m_bulk, 2); check_expected_bytes_allocated(*m_bulk, field); - m_bulk->modification_end(); } } diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestPartitions.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestPartitions.cpp index 1569f62adc60..065836bb136d 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestPartitions.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestPartitions.cpp @@ -270,7 +270,7 @@ void check_test_partition_invariant(SelectorFixture& fix, EXPECT_TRUE(check_nonempty_strictly_ordered(field_data, bkt.size())); } const unsigned *bucket_key = bkt.key(); - for (size_t k = 0; k < partition_key.size() - 1; ++k) + for (size_t k = 0; k < partition_key.size(); ++k) { EXPECT_EQ(partition_key[k], bucket_key[k]); } diff --git a/packages/stk/stk_unit_tests/stk_mesh/face_creation/skin_mesh/UnitTestSkinMeshRefined.cpp b/packages/stk/stk_unit_tests/stk_mesh/face_creation/skin_mesh/UnitTestSkinMeshRefined.cpp index f24f4d1c49d7..980c9b1540d5 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/face_creation/skin_mesh/UnitTestSkinMeshRefined.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/face_creation/skin_mesh/UnitTestSkinMeshRefined.cpp @@ -22,7 +22,6 @@ TEST(ElementGraph, RefinedQuad) stk::mesh::Part &quad_part = meta.declare_part_with_topology("Quads", stk::topology::QUADRILATERAL_4_2D); stk::mesh::Part &skin = meta.declare_part_with_topology("Edges", stk::topology::LINE_2); stk::io::put_io_part_attribute(skin); - stk::mesh::PartVector skin_parts = {&skin}; stk::mesh::Part &active = meta.declare_part("active"); stk::mesh::Field & node_coord = meta.declare_field(stk::topology::NODE_RANK, "coordinates"); diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpFieldTestUtils.hpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpFieldTestUtils.hpp index 17768ef7edfc..7c52397c85cc 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpFieldTestUtils.hpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpFieldTestUtils.hpp @@ -7,6 +7,7 @@ #include #include #include +#include "stk_mesh/base/NgpForEachEntity.hpp" namespace ngp_field_test_utils { diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpMeshTest.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpMeshTest.cpp index b95d67c4c016..e96770e3cbe3 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpMeshTest.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpMeshTest.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -278,3 +279,43 @@ TEST(NgpHostMesh, FieldForEachEntityReduceOnHost_fromTylerVoskuilen) EXPECT_EQ(1.0, maxZ); } +void add_elements(std::unique_ptr& bulk) +{ + stk::mesh::MetaData& meta = bulk->mesh_meta_data(); + stk::mesh::Part& part_1 = meta.declare_part_with_topology("part_1", stk::topology::HEX_8); + + const int rank = stk::parallel_machine_rank(MPI_COMM_WORLD); + const stk::mesh::EntityId elemId = rank + 1; + const stk::mesh::EntityId firstNodeId = rank * 8 + 1; + + stk::mesh::EntityIdVector nodeIds(8, 0); + for (unsigned i = 0; i < nodeIds.size(); ++i) { + nodeIds[i] = firstNodeId + i; + } + + bulk->modification_begin(); + stk::mesh::declare_element(*bulk, part_1, elemId, nodeIds); + bulk->modification_end(); +} + +TEST(NgpTeardownOrdering, BulkDataOutlivesNgpMesh) +{ + std::unique_ptr bulk = stk::mesh::MeshBuilder(MPI_COMM_WORLD).set_spatial_dimension(3).create(); + add_elements(bulk); + + [[maybe_unused]] stk::mesh::NgpMesh ngpMesh = stk::mesh::get_updated_ngp_mesh(*bulk); + + // The "expect" for this test is a clean Valgrind run and no seg-faults +} + +TEST(NgpTeardownOrdering, NgpMeshOutlivesBulkData) +{ + stk::mesh::NgpMesh ngpMesh; + std::unique_ptr bulk = stk::mesh::MeshBuilder(MPI_COMM_WORLD).set_spatial_dimension(3).create(); + add_elements(bulk); + + ngpMesh = stk::mesh::get_updated_ngp_mesh(*bulk); + + // The "expect" for this test is a clean Valgrind run and no seg-faults +} + diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpParallelSumTest.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpParallelSumTest.cpp index 2562c7f3aca1..ee0e5667a0d0 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpParallelSumTest.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpParallelSumTest.cpp @@ -595,7 +595,7 @@ NGP_TEST_F(NgpCommunicateFieldData, simpleVersion_takesBulkData_noSyncToDeviceAf check_field_on_device(ngpMesh, deviceUserField, deviceGoldValues); } -NGP_TEST_F(NgpParallelSum, DISABLED_DeviceMPIVersion) +NGP_TEST_F(NgpParallelSum, DeviceMPIVersion) { if (!stk::have_device_aware_mpi()) { GTEST_SKIP(); } diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpUnitTestUtils.hpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpUnitTestUtils.hpp index 1b623df4984b..4d7b9e514485 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpUnitTestUtils.hpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpUnitTestUtils.hpp @@ -16,9 +16,11 @@ namespace ngp_unit_test_utils { +constexpr unsigned MaxNumParts = 4; + struct BucketContents { - std::string partName; + std::vector partNames; std::vector entities; }; @@ -63,9 +65,9 @@ inline void setup_mesh_2hex_2block(stk::mesh::BulkData& bulk, unsigned bucketCap stk::unit_test_util::setup_text_mesh(bulk, meshDesc); } -struct CheckPartMembership { +struct CheckBucketParts { using BucketPartOrdinalType = Kokkos::View; - CheckPartMembership( + CheckBucketParts( const stk::mesh::NgpMesh& _ngpMesh, BucketPartOrdinalType _bucketPartOrdinals, size_t _numBuckets, const stk::topology::rank_t _bucketRank) : ngpMesh(_ngpMesh), @@ -78,8 +80,13 @@ struct CheckPartMembership { KOKKOS_FUNCTION void operator()(size_t) const { - for (unsigned i = 0; i < numBuckets; ++i) { - NGP_EXPECT_TRUE(ngpMesh.get_bucket(bucketRank, i).member(bucketPartOrdinals[i])); + for (unsigned bucketIdx = 0; bucketIdx < numBuckets; ++bucketIdx) { + for (unsigned partIdx = 0; partIdx < MaxNumParts; ++partIdx) { + unsigned partOffset = bucketIdx*MaxNumParts + partIdx; + if (bucketPartOrdinals[partOffset] != stk::mesh::InvalidOrdinal) { + NGP_EXPECT_TRUE(ngpMesh.get_bucket(bucketRank, bucketIdx).member(bucketPartOrdinals[partOffset])); + } + } } } @@ -90,42 +97,59 @@ struct CheckPartMembership { stk::topology::rank_t bucketRank; }; -inline void check_bucket_layout(const stk::mesh::BulkData& bulk, const std::vector & expectedBucketLayout, +inline void check_bucket_layout(const stk::mesh::BulkData& bulk, + const std::vector & expectedBucketLayout, const stk::topology::rank_t bucketRank = stk::topology::ELEM_RANK) { const stk::mesh::MetaData& meta = bulk.mesh_meta_data(); const stk::mesh::BucketVector & buckets = bulk.buckets(bucketRank); size_t numBuckets = buckets.size(); - ASSERT_EQ(numBuckets, expectedBucketLayout.size()); + ASSERT_EQ(numBuckets, expectedBucketLayout.size()) << "Found " << numBuckets << " Host Buckets when expecting " + << expectedBucketLayout.size(); size_t numEntitiesAcrossBuckets = 0; for (size_t bucketIdx = 0; bucketIdx < numBuckets; ++bucketIdx) { const stk::mesh::Bucket & bucket = *buckets[bucketIdx]; const BucketContents & bucketContents = expectedBucketLayout[bucketIdx]; - const stk::mesh::Part & expectedPart = *meta.get_part(bucketContents.partName); - EXPECT_TRUE(bucket.member(expectedPart)); + for (const std::string& partName : bucketContents.partNames) { + const stk::mesh::Part& expectedPart = *meta.get_part(partName); + EXPECT_TRUE(bucket.member(expectedPart)) << "Host Bucket " << bucket.bucket_id() << " not a member of Part " + << expectedPart.name(); + } numEntitiesAcrossBuckets += bucket.size(); - ASSERT_EQ(bucket.size(), bucketContents.entities.size()); + ASSERT_EQ(bucket.size(), bucketContents.entities.size()) << "Found " << bucket.size() + << " Entities in Host Bucket when expecting " + << bucketContents.entities.size(); for (unsigned i = 0; i < bucket.size(); ++i) { - EXPECT_EQ(bulk.identifier(bucket[i]), bucketContents.entities[i]); + EXPECT_EQ(bulk.identifier(bucket[i]), bucketContents.entities[i]) << "Found " << bucket[i] + << " in Host Bucket when expecting " + << bucketContents.entities[i]; } } using BucketPartOrdinalType = Kokkos::View; - BucketPartOrdinalType bucketPartOrdinals("bucketPartOrdinals", numBuckets); + BucketPartOrdinalType bucketPartOrdinals("bucketPartOrdinals", numBuckets*MaxNumParts); BucketPartOrdinalType::HostMirror hostBucketPartOrdinals = Kokkos::create_mirror_view(bucketPartOrdinals); - for (size_t i = 0; i < buckets.size(); ++i) { - hostBucketPartOrdinals[i] = meta.get_part(expectedBucketLayout[i].partName)->mesh_meta_data_ordinal(); + Kokkos::deep_copy(hostBucketPartOrdinals, stk::mesh::InvalidOrdinal); + for (size_t bucketIdx = 0; bucketIdx < buckets.size(); ++bucketIdx) { + const unsigned numExpectedParts = expectedBucketLayout[bucketIdx].partNames.size(); + STK_ThrowRequireMsg(numExpectedParts <= MaxNumParts, "Checking more Parts than test fixture supports"); + for (size_t partIdx = 0; partIdx < numExpectedParts; ++partIdx) { + const std::string& partName = expectedBucketLayout[bucketIdx].partNames[partIdx]; + unsigned partOffset = bucketIdx*MaxNumParts + partIdx; + hostBucketPartOrdinals[partOffset] = meta.get_part(partName)->mesh_meta_data_ordinal(); + } } Kokkos::deep_copy(bucketPartOrdinals, hostBucketPartOrdinals); stk::mesh::NgpMesh & ngpMesh = stk::mesh::get_updated_ngp_mesh(bulk); - CheckPartMembership checkElementMembership(ngpMesh, bucketPartOrdinals, numBuckets, bucketRank); - Kokkos::parallel_for(stk::ngp::DeviceRangePolicy(0, 1), checkElementMembership); + CheckBucketParts checkBucketParts(ngpMesh, bucketPartOrdinals, numBuckets, bucketRank); + Kokkos::parallel_for(stk::ngp::DeviceRangePolicy(0, 1), checkBucketParts); - ASSERT_EQ(ngpMesh.num_buckets(bucketRank), numBuckets); + ASSERT_EQ(ngpMesh.num_buckets(bucketRank), numBuckets) << "Found " << ngpMesh.num_buckets(bucketRank) + << " Device Buckets when expecting " << numBuckets; for (unsigned bucketIdx = 0; bucketIdx < numBuckets; ++bucketIdx) { const stk::mesh::NgpMesh::BucketType & ngpBucket = ngpMesh.get_bucket(bucketRank, bucketIdx); @@ -133,7 +157,7 @@ inline void check_bucket_layout(const stk::mesh::BulkData& bulk, const std::vec ASSERT_EQ(bucket.size(), ngpBucket.size()); } - using BucketEntitiesType = Kokkos::View; + using BucketEntitiesType = Kokkos::View; BucketEntitiesType bucketEntities("bucketEntities", numEntitiesAcrossBuckets); BucketEntitiesType::HostMirror hostBucketEntities = Kokkos::create_mirror_view(bucketEntities); @@ -143,7 +167,7 @@ inline void check_bucket_layout(const stk::mesh::BulkData& bulk, const std::vec for (unsigned bucketIdx = 0; bucketIdx < numBuckets; ++bucketIdx) { const stk::mesh::NgpMesh::BucketType & bucket = ngpMesh.get_bucket(bucketRank, bucketIdx); for (size_t i = 0; i < bucket.size(); ++i) { - bucketEntities[idx++] = ngpMesh.identifier(bucket[i]); + bucketEntities[idx++] = bucket[i]; } } }); @@ -154,7 +178,9 @@ inline void check_bucket_layout(const stk::mesh::BulkData& bulk, const std::vec for (size_t bucketIdx = 0; bucketIdx < numBuckets; ++bucketIdx) { const stk::mesh::Bucket & bucket = *buckets[bucketIdx]; for (unsigned i = 0; i < bucket.size(); ++i) { - EXPECT_EQ(bulk.identifier(bucket[i]), hostBucketEntities[index++]); + const stk::mesh::Entity deviceEntity = hostBucketEntities[index++]; + EXPECT_EQ(bucket[i], deviceEntity) << "Found " << deviceEntity << " in Device Bucket when expecting " + << bucket[i]; } } } diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/TestNgpMeshUpdate.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/TestNgpMeshUpdate.cpp index 2dd63a22b895..8880e9de6a1b 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/TestNgpMeshUpdate.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/TestNgpMeshUpdate.cpp @@ -12,6 +12,7 @@ namespace { +using ngp_unit_test_utils::check_bucket_layout; using NgpMeshDefaultMemSpace = stk::mesh::NgpMeshDefaultMemSpace; class UpdateNgpMesh : public stk::unit_test_util::MeshFixture @@ -185,7 +186,7 @@ TEST_F(BucketLayoutModification, DeleteBucketInMiddle) stk::mesh::NgpMesh & ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_2", {2}}, {"block_3", {3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_2"}, {2}}, {{"block_3"}, {3}}}); get_bulk().modification_begin(); stk::mesh::PartVector addParts{get_meta().get_part("block_1")}; @@ -195,7 +196,7 @@ TEST_F(BucketLayoutModification, DeleteBucketInMiddle) ngpMesh.update_mesh(); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1,2}}, {"block_3", {3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1,2}}, {{"block_3"}, {3}}}); } // ------------------------- ------------------------- @@ -213,7 +214,7 @@ TEST_F(BucketLayoutModification, AddBucketInMiddle) stk::mesh::NgpMesh & ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_2", {2}}, {"block_3", {3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_2"}, {2}}, {{"block_3"}, {3}}}); get_bulk().modification_begin(); stk::mesh::PartVector addParts{get_meta().get_part("block_1")}; @@ -223,7 +224,7 @@ TEST_F(BucketLayoutModification, AddBucketInMiddle) ngpMesh.update_mesh(); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_1", {3}}, {"block_2", {2}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_1"}, {3}}, {{"block_2"}, {2}}}); } // ------------------------- ------------------------- @@ -241,7 +242,7 @@ TEST_F(BucketLayoutModification, ChangeBucketContents) stk::mesh::NgpMesh & ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1,2}}, {"block_3", {3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1,2}}, {{"block_3"}, {3}}}); get_bulk().modification_begin(); stk::mesh::PartVector addParts{get_meta().get_part("block_3")}; @@ -251,7 +252,7 @@ TEST_F(BucketLayoutModification, ChangeBucketContents) ngpMesh.update_mesh(); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_3", {2,3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_3"}, {2,3}}}); } // ------------------------- ------------------------- @@ -269,7 +270,7 @@ TEST_F(BucketLayoutModification, DeleteBucketInMiddle_WithCopy) stk::mesh::NgpMesh ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_2", {2}}, {"block_3", {3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_2"}, {2}}, {{"block_3"}, {3}}}); get_bulk().modification_begin(); stk::mesh::PartVector addParts{get_meta().get_part("block_1")}; @@ -279,7 +280,7 @@ TEST_F(BucketLayoutModification, DeleteBucketInMiddle_WithCopy) stk::mesh::get_updated_ngp_mesh(get_bulk()); // Trigger an update - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1,2}}, {"block_3", {3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1,2}}, {{"block_3"}, {3}}}); } // ------------------------- ------------------------- @@ -297,7 +298,7 @@ TEST_F(BucketLayoutModification, AddBucketInMiddle_WithCopy) stk::mesh::NgpMesh ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_2", {2}}, {"block_3", {3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_2"}, {2}}, {{"block_3"}, {3}}}); get_bulk().modification_begin(); stk::mesh::PartVector addParts{get_meta().get_part("block_1")}; @@ -307,7 +308,7 @@ TEST_F(BucketLayoutModification, AddBucketInMiddle_WithCopy) stk::mesh::get_updated_ngp_mesh(get_bulk()); // Trigger an update - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_1", {3}}, {"block_2", {2}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_1"}, {3}}, {{"block_2"}, {2}}}); } // ------------------------- ------------------------- @@ -325,7 +326,7 @@ TEST_F(BucketLayoutModification, ChangeBucketContents_WithCopy) stk::mesh::NgpMesh ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1,2}}, {"block_3", {3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1,2}}, {{"block_3"}, {3}}}); get_bulk().modification_begin(); stk::mesh::PartVector addParts{get_meta().get_part("block_3")}; @@ -335,7 +336,7 @@ TEST_F(BucketLayoutModification, ChangeBucketContents_WithCopy) stk::mesh::get_updated_ngp_mesh(get_bulk()); // Trigger an update - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_3", {2,3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_3"}, {2,3}}}); } -} +} // namespace diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/UnitTestNgp.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/UnitTestNgp.cpp index 0472a7af4b76..4c869fb317de 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/UnitTestNgp.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/UnitTestNgp.cpp @@ -52,6 +52,16 @@ void test_view_of_fields(const stk::mesh::BulkData& bulk, EXPECT_EQ(1, result.h_view(0)); EXPECT_EQ(1, result.h_view(1)); + +#if !defined(KOKKOS_ENABLE_CUDA) && !defined(KOKKOS_ENABLE_HIP) + for (unsigned i = 0; i < 2; ++i) { +#ifdef STK_USE_DEVICE_MESH // Compiler can't resolve destructor type through NgpField using statement + fields(i).~DeviceField(); +#else + fields(i).~HostField(); +#endif + } +#endif } TEST(UnitTestNgp, viewOfFields) diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/UnitTestNgpMeshModification.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/UnitTestNgpMeshModification.cpp new file mode 100644 index 000000000000..7e70384d89f9 --- /dev/null +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/UnitTestNgpMeshModification.cpp @@ -0,0 +1,444 @@ +// Copyright 2002 - 2008, 2010, 2011 National Technology Engineering +// Solutions of Sandia, LLC (NTESS). Under the terms of Contract +// DE-NA0003525 with NTESS, the U.S. Government retains certain rights +// in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// * Neither the name of NTESS nor the names of its contributors +// may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include +#include "ngp/NgpUnitTestUtils.hpp" +#include "stk_mesh/base/MeshBuilder.hpp" +#include "stk_mesh/base/BulkData.hpp" +#include "stk_mesh/base/MetaData.hpp" +#include "stk_mesh/base/Part.hpp" +#include "stk_mesh/base/Types.hpp" +#include "stk_mesh/base/SkinMesh.hpp" + +namespace +{ +using ngp_unit_test_utils::check_bucket_layout; + +class NgpBatchChangeEntityParts : public ::testing::Test +{ +public: + NgpBatchChangeEntityParts() + { + } + + void build_empty_mesh(unsigned initialBucketCapacity, unsigned maximumBucketCapacity) + { + stk::mesh::MeshBuilder builder(MPI_COMM_WORLD); + builder.set_spatial_dimension(3); + builder.set_initial_bucket_capacity(initialBucketCapacity); + builder.set_maximum_bucket_capacity(maximumBucketCapacity); + m_bulk = builder.create(); + m_meta = &m_bulk->mesh_meta_data(); + stk::mesh::get_updated_ngp_mesh(*m_bulk); + } + +protected: + std::unique_ptr m_bulk; + stk::mesh::MetaData * m_meta; +}; + +stk::mesh::Entity create_node(stk::mesh::BulkData& bulk, stk::mesh::EntityId nodeId, + const stk::mesh::PartVector& initialParts = stk::mesh::PartVector()) +{ + bulk.modification_begin(); + stk::mesh::Entity newNode = bulk.declare_node(nodeId, initialParts); + bulk.modification_end(); + + return newNode; +} + +template +void confirm_host_mesh_is_not_synchronized_from_device(const MeshType& ngpMesh) +{ + if constexpr (std::is_same_v) { + EXPECT_EQ(ngpMesh.need_sync_to_host(), true); + } + else { + EXPECT_EQ(ngpMesh.need_sync_to_host(), false); // If host build, HostMesh can't ever be stale + } +} + +template +void confirm_host_mesh_is_synchronized_from_device(const MeshType& ngpMesh) +{ + EXPECT_EQ(ngpMesh.need_sync_to_host(), false); +} + +using DeviceEntitiesType = Kokkos::View; +using DevicePartOrdinalsType = Kokkos::View; + +using HostEntitiesType = Kokkos::View; +using HostPartOrdinalsType = Kokkos::View; + +void fill_device_views_add_remove_part_from_node(DeviceEntitiesType& entities, DevicePartOrdinalsType& addPartOrdinals, + DevicePartOrdinalsType& removePartOrdinals, stk::mesh::NgpMesh& ngpMesh, + stk::mesh::Entity node, stk::mesh::Part* addPart, + stk::mesh::Part* removePart) +{ + const stk::mesh::BulkData& bulk = ngpMesh.get_bulk_on_host(); + stk::mesh::EntityId nodeId = bulk.identifier(node); + const stk::mesh::PartOrdinal addPartOrdinal = (addPart) ? addPart->mesh_meta_data_ordinal() + : stk::mesh::InvalidPartOrdinal; + const stk::mesh::PartOrdinal removePartOrdinal = (removePart) ? removePart->mesh_meta_data_ordinal() + : stk::mesh::InvalidPartOrdinal; + + Kokkos::parallel_for("Fill Device Views for Part Addition", stk::ngp::DeviceRangePolicy(0, 1), + KOKKOS_LAMBDA(size_t /*index*/) { + STK_NGP_ThrowRequireMsg(ngpMesh.identifier(node) == nodeId, "Unexpected node found on device"); + entities(0) = node; + + if (addPartOrdinal != stk::mesh::InvalidPartOrdinal) { + addPartOrdinals(0) = addPartOrdinal; + } + + if (removePartOrdinal != stk::mesh::InvalidPartOrdinal) { + removePartOrdinals(0) = removePartOrdinal; + } + }); +} + + +TEST_F(NgpBatchChangeEntityParts, addPartToNode_host) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 1) GTEST_SKIP(); + + build_empty_mesh(1, 1); + + stk::mesh::Part & part1 = m_meta->declare_part_with_topology("part1", stk::topology::NODE); + stk::mesh::Part & part2 = m_meta->declare_part_with_topology("part2", stk::topology::NODE); + const unsigned nodeId = 1; + const stk::mesh::Entity node1 = create_node(*m_bulk, nodeId, {&part1}); + check_bucket_layout(*m_bulk, {{{"part1"}, {nodeId}}}, stk::topology::NODE_RANK); + + std::vector entities {node1}; + std::vector addParts {&part2}; + std::vector removeParts; + + m_bulk->batch_change_entity_parts(entities, addParts, removeParts); + + check_bucket_layout(*m_bulk, {{{"part1", "part2"}, {nodeId}}}, stk::topology::NODE_RANK); +} + +TEST_F(NgpBatchChangeEntityParts, addPartToNode_ngpHost) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 1) GTEST_SKIP(); + + build_empty_mesh(1, 1); + + stk::mesh::Part & part1 = m_meta->declare_part_with_topology("part1", stk::topology::NODE); + stk::mesh::Part & part2 = m_meta->declare_part_with_topology("part2", stk::topology::NODE); + const unsigned nodeId = 1; + const stk::mesh::Entity node1 = create_node(*m_bulk, nodeId, {&part1}); + check_bucket_layout(*m_bulk, {{{"part1"}, {nodeId}}}, stk::topology::NODE_RANK); + + HostEntitiesType entities("hostEntities", 1); + HostPartOrdinalsType addPartOrdinals("hostAddParts", 1); + HostPartOrdinalsType removePartOrdinals("hostRemoveParts", 0); + + entities(0) = node1; + addPartOrdinals(0) = part2.mesh_meta_data_ordinal(); + + stk::mesh::HostMesh hostMesh(*m_bulk); + hostMesh.batch_change_entity_parts(entities, addPartOrdinals, removePartOrdinals); + confirm_host_mesh_is_synchronized_from_device(hostMesh); + + hostMesh.sync_to_host(); + confirm_host_mesh_is_synchronized_from_device(hostMesh); + + check_bucket_layout(*m_bulk, {{{"part1", "part2"}, {nodeId}}}, stk::topology::NODE_RANK); +} + +TEST_F(NgpBatchChangeEntityParts, addPartToNode_ngpDevice) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 1) GTEST_SKIP(); + + build_empty_mesh(1, 1); + + stk::mesh::Part & part1 = m_meta->declare_part_with_topology("part1", stk::topology::NODE); + stk::mesh::Part & part2 = m_meta->declare_part_with_topology("part2", stk::topology::NODE); + const unsigned nodeId = 1; + const stk::mesh::Entity node1 = create_node(*m_bulk, nodeId, {&part1}); + check_bucket_layout(*m_bulk, {{{"part1"}, {nodeId}}}, stk::topology::NODE_RANK); + + DeviceEntitiesType entities("deviceEntities", 1); + DevicePartOrdinalsType addPartOrdinals("deviceAddParts", 1); + DevicePartOrdinalsType removePartOrdinals("deviceRemoveParts", 0); + + stk::mesh::NgpMesh & ngpMesh = stk::mesh::get_updated_ngp_mesh(*m_bulk); + fill_device_views_add_remove_part_from_node(entities, addPartOrdinals, removePartOrdinals, ngpMesh, + node1, &part2, nullptr); + + ngpMesh.batch_change_entity_parts(entities, addPartOrdinals, removePartOrdinals); + confirm_host_mesh_is_not_synchronized_from_device(ngpMesh); + + ngpMesh.sync_to_host(); + confirm_host_mesh_is_synchronized_from_device(ngpMesh); + + check_bucket_layout(*m_bulk, {{{"part1", "part2"}, {nodeId}}}, stk::topology::NODE_RANK); +} + + +TEST_F(NgpBatchChangeEntityParts, removePartFromNode_host) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 1) GTEST_SKIP(); + + build_empty_mesh(1, 1); + + stk::mesh::Part & part1 = m_meta->declare_part_with_topology("part1", stk::topology::NODE); + stk::mesh::Part & part2 = m_meta->declare_part_with_topology("part2", stk::topology::NODE); + const unsigned nodeId = 1; + const stk::mesh::Entity node1 = create_node(*m_bulk, nodeId, {&part1, &part2}); + check_bucket_layout(*m_bulk, {{{"part1", "part2"}, {nodeId}}}, stk::topology::NODE_RANK); + + std::vector entities {node1}; + std::vector addParts; + std::vector removeParts {&part1}; + + m_bulk->batch_change_entity_parts(entities, addParts, removeParts); + stk::mesh::get_updated_ngp_mesh(*m_bulk); + + check_bucket_layout(*m_bulk, {{{"part2"}, {nodeId}}}, stk::topology::NODE_RANK); +} + +TEST_F(NgpBatchChangeEntityParts, removePartFromNode_ngpHost) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 1) GTEST_SKIP(); + + build_empty_mesh(1, 1); + + stk::mesh::Part & part1 = m_meta->declare_part_with_topology("part1", stk::topology::NODE); + stk::mesh::Part & part2 = m_meta->declare_part_with_topology("part2", stk::topology::NODE); + const unsigned nodeId = 1; + const stk::mesh::Entity node1 = create_node(*m_bulk, nodeId, {&part1, &part2}); + check_bucket_layout(*m_bulk, {{{"part1", "part2"}, {nodeId}}}, stk::topology::NODE_RANK); + + HostEntitiesType entities("hostEntities", 1); + HostPartOrdinalsType addPartOrdinals("hostAddParts", 0); + HostPartOrdinalsType removePartOrdinals("hostRemoveParts", 1); + + entities(0) = node1; + removePartOrdinals(0) = part1.mesh_meta_data_ordinal(); + + stk::mesh::HostMesh hostMesh(*m_bulk); + hostMesh.batch_change_entity_parts(entities, addPartOrdinals, removePartOrdinals); + confirm_host_mesh_is_synchronized_from_device(hostMesh); + + hostMesh.sync_to_host(); + confirm_host_mesh_is_synchronized_from_device(hostMesh); + + check_bucket_layout(*m_bulk, {{{"part2"}, {nodeId}}}, stk::topology::NODE_RANK); +} + +TEST_F(NgpBatchChangeEntityParts, removePartFromNode_ngpDevice) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 1) GTEST_SKIP(); + + build_empty_mesh(1, 1); + + stk::mesh::Part & part1 = m_meta->declare_part_with_topology("part1", stk::topology::NODE); + stk::mesh::Part & part2 = m_meta->declare_part_with_topology("part2", stk::topology::NODE); + const unsigned nodeId = 1; + const stk::mesh::Entity node1 = create_node(*m_bulk, nodeId, {&part1, &part2}); + check_bucket_layout(*m_bulk, {{{"part1", "part2"}, {nodeId}}}, stk::topology::NODE_RANK); + + DeviceEntitiesType entities("deviceEntities", 1); + DevicePartOrdinalsType addPartOrdinals("deviceAddParts", 0); + DevicePartOrdinalsType removePartOrdinals("deviceRemoveParts", 1); + + stk::mesh::NgpMesh & ngpMesh = stk::mesh::get_updated_ngp_mesh(*m_bulk); + fill_device_views_add_remove_part_from_node(entities, addPartOrdinals, removePartOrdinals, ngpMesh, + node1, nullptr, &part1); + + ngpMesh.batch_change_entity_parts(entities, addPartOrdinals, removePartOrdinals); + confirm_host_mesh_is_not_synchronized_from_device(ngpMesh); + + ngpMesh.sync_to_host(); + confirm_host_mesh_is_synchronized_from_device(ngpMesh); + + check_bucket_layout(*m_bulk, {{{"part2"}, {nodeId}}}, stk::topology::NODE_RANK); +} + + +TEST_F(NgpBatchChangeEntityParts, addAndRemovePartFromNode_host) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 1) GTEST_SKIP(); + + build_empty_mesh(1, 1); + + stk::mesh::Part & part1 = m_meta->declare_part_with_topology("part1", stk::topology::NODE); + stk::mesh::Part & part2 = m_meta->declare_part_with_topology("part2", stk::topology::NODE); + const unsigned nodeId = 1; + const stk::mesh::Entity node1 = create_node(*m_bulk, nodeId, {&part1}); + check_bucket_layout(*m_bulk, {{{"part1"}, {nodeId}}}, stk::topology::NODE_RANK); + + std::vector entities {node1}; + std::vector addParts {&part2}; + std::vector removeParts {&part1}; + + m_bulk->batch_change_entity_parts(entities, addParts, removeParts); + stk::mesh::get_updated_ngp_mesh(*m_bulk); + + check_bucket_layout(*m_bulk, {{{"part2"}, {nodeId}}}, stk::topology::NODE_RANK); +} + +TEST_F(NgpBatchChangeEntityParts, addAndRemovePartFromNode_ngpHost) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 1) GTEST_SKIP(); + + build_empty_mesh(1, 1); + + stk::mesh::Part & part1 = m_meta->declare_part_with_topology("part1", stk::topology::NODE); + stk::mesh::Part & part2 = m_meta->declare_part_with_topology("part2", stk::topology::NODE); + const unsigned nodeId = 1; + const stk::mesh::Entity node1 = create_node(*m_bulk, nodeId, {&part1}); + check_bucket_layout(*m_bulk, {{{"part1"}, {nodeId}}}, stk::topology::NODE_RANK); + + HostEntitiesType entities("hostEntities", 1); + HostPartOrdinalsType addPartOrdinals("hostAddParts", 1); + HostPartOrdinalsType removePartOrdinals("hostRemoveParts", 1); + + entities(0) = node1; + addPartOrdinals(0) = part2.mesh_meta_data_ordinal(); + removePartOrdinals(0) = part1.mesh_meta_data_ordinal(); + + stk::mesh::HostMesh hostMesh(*m_bulk); + hostMesh.batch_change_entity_parts(entities, addPartOrdinals, removePartOrdinals); + confirm_host_mesh_is_synchronized_from_device(hostMesh); + + hostMesh.sync_to_host(); + confirm_host_mesh_is_synchronized_from_device(hostMesh); + + check_bucket_layout(*m_bulk, {{{"part2"}, {nodeId}}}, stk::topology::NODE_RANK); +} + +TEST_F(NgpBatchChangeEntityParts, addAndRemovePartFromNode_ngpDevice) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 1) GTEST_SKIP(); + + build_empty_mesh(1, 1); + + stk::mesh::Part & part1 = m_meta->declare_part_with_topology("part1", stk::topology::NODE); + stk::mesh::Part & part2 = m_meta->declare_part_with_topology("part2", stk::topology::NODE); + const unsigned nodeId = 1; + const stk::mesh::Entity node1 = create_node(*m_bulk, nodeId, {&part1}); + check_bucket_layout(*m_bulk, {{{"part1"}, {nodeId}}}, stk::topology::NODE_RANK); + + DeviceEntitiesType entities("deviceEntities", 1); + DevicePartOrdinalsType addPartOrdinals("deviceAddParts", 1); + DevicePartOrdinalsType removePartOrdinals("deviceRemoveParts", 1); + + stk::mesh::NgpMesh & ngpMesh = stk::mesh::get_updated_ngp_mesh(*m_bulk); + fill_device_views_add_remove_part_from_node(entities, addPartOrdinals, removePartOrdinals, ngpMesh, + node1, &part2, &part1); + + ngpMesh.batch_change_entity_parts(entities, addPartOrdinals, removePartOrdinals); + confirm_host_mesh_is_not_synchronized_from_device(ngpMesh); + + ngpMesh.sync_to_host(); + confirm_host_mesh_is_synchronized_from_device(ngpMesh); + + check_bucket_layout(*m_bulk, {{{"part2"}, {nodeId}}}, stk::topology::NODE_RANK); +} + +TEST_F(NgpBatchChangeEntityParts, multipleDeviceMeshMods) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 1) GTEST_SKIP(); + + build_empty_mesh(1, 1); + + stk::mesh::Part & part1 = m_meta->declare_part_with_topology("part1", stk::topology::NODE); + stk::mesh::Part & part2 = m_meta->declare_part_with_topology("part2", stk::topology::NODE); + stk::mesh::Part & part3 = m_meta->declare_part_with_topology("part3", stk::topology::NODE); + const unsigned nodeId = 1; + const stk::mesh::Entity node1 = create_node(*m_bulk, nodeId, {&part1}); + check_bucket_layout(*m_bulk, {{{"part1"}, {nodeId}}}, stk::topology::NODE_RANK); + + DeviceEntitiesType entities("deviceEntities", 1); + DevicePartOrdinalsType addPartOrdinals("deviceAddParts", 1); + DevicePartOrdinalsType removePartOrdinals("deviceRemoveParts", 0); + + stk::mesh::NgpMesh & ngpMesh = stk::mesh::get_updated_ngp_mesh(*m_bulk); + fill_device_views_add_remove_part_from_node(entities, addPartOrdinals, removePartOrdinals, ngpMesh, + node1, &part2, nullptr); + + ngpMesh.batch_change_entity_parts(entities, addPartOrdinals, removePartOrdinals); + confirm_host_mesh_is_not_synchronized_from_device(ngpMesh); + + fill_device_views_add_remove_part_from_node(entities, addPartOrdinals, removePartOrdinals, ngpMesh, + node1, &part3, nullptr); + + ngpMesh.batch_change_entity_parts(entities, addPartOrdinals, removePartOrdinals); + confirm_host_mesh_is_not_synchronized_from_device(ngpMesh); + + ngpMesh.sync_to_host(); + confirm_host_mesh_is_synchronized_from_device(ngpMesh); + + check_bucket_layout(*m_bulk, {{{"part1", "part2"}, {nodeId}}}, stk::topology::NODE_RANK); +} + +TEST_F(NgpBatchChangeEntityParts, failedHostAccessAfterDeviceMeshMod) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 1) GTEST_SKIP(); + + build_empty_mesh(1, 1); + + stk::mesh::Part & part1 = m_meta->declare_part_with_topology("part1", stk::topology::NODE); + stk::mesh::Part & part2 = m_meta->declare_part_with_topology("part2", stk::topology::NODE); + const unsigned nodeId = 1; + const stk::mesh::Entity node1 = create_node(*m_bulk, nodeId, {&part1}); + check_bucket_layout(*m_bulk, {{{"part1"}, {nodeId}}}, stk::topology::NODE_RANK); + + DeviceEntitiesType entities("deviceEntities", 1); + DevicePartOrdinalsType addPartOrdinals("deviceAddParts", 1); + DevicePartOrdinalsType removePartOrdinals("deviceRemoveParts", 0); + + stk::mesh::NgpMesh & ngpMesh = stk::mesh::get_updated_ngp_mesh(*m_bulk); + fill_device_views_add_remove_part_from_node(entities, addPartOrdinals, removePartOrdinals, ngpMesh, + node1, &part2, nullptr); + + ngpMesh.batch_change_entity_parts(entities, addPartOrdinals, removePartOrdinals); + confirm_host_mesh_is_not_synchronized_from_device(ngpMesh); + + if constexpr (std::is_same_v) { + EXPECT_ANY_THROW(m_bulk->buckets(stk::topology::NODE_RANK)); + EXPECT_ANY_THROW(m_bulk->get_buckets(stk::topology::NODE_RANK, m_meta->universal_part())); + EXPECT_ANY_THROW(m_bulk->modification_begin()); + EXPECT_ANY_THROW(m_bulk->batch_change_entity_parts(stk::mesh::EntityVector{node1}, stk::mesh::PartVector{}, + stk::mesh::PartVector{})); + EXPECT_ANY_THROW(stk::mesh::skin_mesh(*m_bulk, stk::mesh::PartVector{&part1})); + } +} + +} // namespace diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpFieldTest.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpFieldTest.cpp index 4dc9cadf14c6..8cd3fb2dafad 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpFieldTest.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpFieldTest.cpp @@ -63,6 +63,8 @@ namespace ngp_field_test { +using ngp_unit_test_utils::check_bucket_layout; + class NgpFieldFixture : public stk::unit_test_util::MeshFixture { public: @@ -656,7 +658,7 @@ class OptimizedNgpFieldFixture : public NgpFieldFixture void modify_mesh_add_and_delete_bucket(stk::mesh::Field& stkIntField, stk::mesh::NgpField& ngpIntField) { stk::mesh::NgpMesh& ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_2", {2}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_2"}, {2}}}); check_field_data_on_device(ngpIntField, stkIntField); get_bulk().modification_begin(); stk::mesh::PartVector addParts{get_meta().get_part("block_3")}; @@ -664,7 +666,7 @@ class OptimizedNgpFieldFixture : public NgpFieldFixture get_bulk().change_entity_parts(get_bulk().get_entity(stk::topology::ELEM_RANK, 1), addParts, removeParts); get_bulk().modification_end(); ngpMesh.update_mesh(); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_3", {1}}, {"block_2", {2}}}); + check_bucket_layout(get_bulk(), {{{"block_3"}, {1}}, {{"block_2"}, {2}}}); } void fill_nodes(const stk::mesh::Entity element, unsigned numNodes, stk::mesh::EntityVector& nodes) @@ -727,19 +729,19 @@ class OptimizedNgpFieldFixture : public NgpFieldFixture void modify_mesh_add_and_delete_bucket3(stk::mesh::Field& stkIntField, stk::mesh::NgpField& ngpIntField) { stk::mesh::NgpMesh& ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_2", {2}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_2"}, {2}}}); check_field_data_on_device(ngpIntField, stkIntField); get_bulk().modification_begin(); replace_element_and_place_in_block("block_3"); get_bulk().modification_end(); ngpMesh.update_mesh(); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_3", {4}}, {"block_2", {2}}}); + check_bucket_layout(get_bulk(), {{{"block_3"}, {4}}, {{"block_2"}, {2}}}); } void modify_mesh_add_and_delete_bucket2(stk::mesh::Field& stkIntField, stk::mesh::NgpField& ngpIntField) { stk::mesh::NgpMesh& ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_2", {2}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_2"}, {2}}}); check_field_data_on_device(ngpIntField, stkIntField); get_bulk().modification_begin(); stk::mesh::PartVector addParts{get_meta().get_part("block_2")}; @@ -750,13 +752,13 @@ class OptimizedNgpFieldFixture : public NgpFieldFixture get_bulk().change_entity_parts(get_bulk().get_entity(stk::topology::ELEM_RANK, 2), addParts, removeParts); get_bulk().modification_end(); ngpMesh.update_mesh(); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_3", {2}}, {"block_2", {1}}}); + check_bucket_layout(get_bulk(), {{{"block_3"}, {2}}, {{"block_2"}, {1}}}); } void modify_mesh_delete_bucket_in_middle(stk::mesh::Field& stkIntField, stk::mesh::NgpField& ngpIntField) { stk::mesh::NgpMesh& ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_2", {2}}, {"block_3", {3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_2"}, {2}}, {{"block_3"}, {3}}}); check_field_data_on_device(ngpIntField, stkIntField); get_bulk().modification_begin(); stk::mesh::PartVector addParts{get_meta().get_part("block_1")}; @@ -764,13 +766,13 @@ class OptimizedNgpFieldFixture : public NgpFieldFixture get_bulk().change_entity_parts(get_bulk().get_entity(stk::topology::ELEM_RANK, 2), addParts, removeParts); get_bulk().modification_end(); ngpMesh.update_mesh(); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1,2}}, {"block_3", {3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1,2}}, {{"block_3"}, {3}}}); } void modify_mesh_add_bucket_in_middle(stk::mesh::Field& stkIntField, stk::mesh::NgpField& ngpIntField) { stk::mesh::NgpMesh & ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_2", {2}}, {"block_3", {3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_2"}, {2}}, {{"block_3"}, {3}}}); check_field_data_on_device(ngpIntField, stkIntField); get_bulk().modification_begin(); stk::mesh::PartVector addParts{get_meta().get_part("block_1")}; @@ -778,13 +780,13 @@ class OptimizedNgpFieldFixture : public NgpFieldFixture get_bulk().change_entity_parts(get_bulk().get_entity(stk::topology::ELEM_RANK, 3), addParts, removeParts); get_bulk().modification_end(); ngpMesh.update_mesh(); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_1", {3}}, {"block_2", {2}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_1"}, {3}}, {{"block_2"}, {2}}}); } void modify_mesh_add_element(stk::mesh::Field& stkIntField, stk::mesh::NgpField& ngpIntField, unsigned bucketCapacity) { stk::mesh::NgpMesh & ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_2", {2}}, {"block_3", {3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_2"}, {2}}, {{"block_3"}, {3}}}); check_field_data_on_device(ngpIntField, stkIntField); get_bulk().modification_begin(); @@ -796,17 +798,17 @@ class OptimizedNgpFieldFixture : public NgpFieldFixture ngpMesh.update_mesh(); if(bucketCapacity == 1) { - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_2", {2}}, {"block_3", {3}}, {"block_3", {4}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_2"}, {2}}, {{"block_3"}, {3}}, {{"block_3"}, {4}}}); } else if(bucketCapacity == 2) { - ngp_unit_test_utils::check_bucket_layout(get_bulk(), {{"block_1", {1}}, {"block_2", {2}}, {"block_3", {3,4}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1}}, {{"block_2"}, {2}}, {{"block_3"}, {3,4}}}); } } void modify_mesh_change_bucket_content(stk::mesh::Field& stkIntField, stk::mesh::NgpField& ngpIntField) { stk::mesh::NgpMesh& ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), { {"block_1", {1, 2}}, {"block_3", {3}}}); + check_bucket_layout(get_bulk(), {{{"block_1"}, {1, 2}}, {{"block_3"}, {3}}}); check_field_data_on_device(ngpIntField, stkIntField); get_bulk().modification_begin(); stk::mesh::PartVector addParts {get_meta().get_part("block_3")}; @@ -814,7 +816,7 @@ class OptimizedNgpFieldFixture : public NgpFieldFixture get_bulk().change_entity_parts(get_bulk().get_entity(stk::topology::ELEM_RANK, 2), addParts, removeParts); get_bulk().modification_end(); ngpMesh.update_mesh(); - ngp_unit_test_utils::check_bucket_layout(get_bulk(), { {"block_1", {1}}, {"block_3", {2, 3}}}); + check_bucket_layout(get_bulk(), { {{"block_1"}, {1}}, {{"block_3"}, {2, 3}}}); } }; @@ -2630,4 +2632,4 @@ TEST_F(NgpFieldUpdate, MoveBackwardForwardBackward) check_field_values(); } -} +} // namespace ngp_field_test diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpMultiStateFieldTests.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpMultiStateFieldTests.cpp index 78f708dc9517..8ad20403ba53 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpMultiStateFieldTests.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpMultiStateFieldTests.cpp @@ -200,8 +200,8 @@ NGP_TEST_F(NgpMultiStateFieldTest, multistateField_rotateDeviceStates_syncStates const double valueNew = 44.4; const double valueOld = 22.2; - stk::mesh::field_fill(valueNew, get_field_new(), stk::ngp::HostExecSpace()); - stk::mesh::field_fill(valueOld, get_field_old(), stk::ngp::HostExecSpace()); + stk::mesh::field_fill(valueNew, get_field_new()); + stk::mesh::field_fill(valueOld, get_field_old()); stk::mesh::NgpMesh& ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); stk::mesh::NgpField& ngpFieldNew = stk::mesh::get_updated_ngp_field(get_field_new()); @@ -230,8 +230,8 @@ NGP_TEST_F(NgpMultiStateFieldTest, multistateField_copyHasCorrectDataAfterStateR const double valueNew = 44.4; const double valueOld = 22.2; - stk::mesh::field_fill(valueNew, get_field_new(), stk::ngp::HostExecSpace()); - stk::mesh::field_fill(valueOld, get_field_old(), stk::ngp::HostExecSpace()); + stk::mesh::field_fill(valueNew, get_field_new()); + stk::mesh::field_fill(valueOld, get_field_old()); stk::mesh::NgpMesh& ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); stk::mesh::NgpField& ngpFieldNew = stk::mesh::get_updated_ngp_field(get_field_new()); @@ -260,8 +260,8 @@ NGP_TEST_F(NgpMultiStateFieldTest, multistateField_copyHasWrongDataAfterDeviceSt const double valueNew = 44.4; const double valueOld = 22.2; - stk::mesh::field_fill(valueNew, get_field_new(), stk::ngp::HostExecSpace()); - stk::mesh::field_fill(valueOld, get_field_old(), stk::ngp::HostExecSpace()); + stk::mesh::field_fill(valueNew, get_field_new()); + stk::mesh::field_fill(valueOld, get_field_old()); stk::mesh::NgpMesh& ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); stk::mesh::NgpField& ngpFieldNew = stk::mesh::get_updated_ngp_field(get_field_new()); @@ -293,8 +293,8 @@ NGP_TEST_F(NgpMultiStateFieldTest, persistentDeviceField_hasCorrectDataAfterStat const double valueNew = 44.4; const double valueOld = 22.2; - stk::mesh::field_fill(valueNew, get_field_new(), stk::ngp::HostExecSpace()); - stk::mesh::field_fill(valueOld, get_field_old(), stk::ngp::HostExecSpace()); + stk::mesh::field_fill(valueNew, get_field_new()); + stk::mesh::field_fill(valueOld, get_field_old()); stk::mesh::NgpMesh& ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); stk::mesh::NgpField& ngpFieldNew = stk::mesh::get_updated_ngp_field(get_field_new()); @@ -322,8 +322,8 @@ NGP_TEST_F(NgpMultiStateFieldTest, persistentDeviceField_hasWrongDataAfterDevice const double valueNew = 44.4; const double valueOld = 22.2; - stk::mesh::field_fill(valueNew, get_field_new(), stk::ngp::HostExecSpace()); - stk::mesh::field_fill(valueOld, get_field_old(), stk::ngp::HostExecSpace()); + stk::mesh::field_fill(valueNew, get_field_new()); + stk::mesh::field_fill(valueOld, get_field_old()); stk::mesh::NgpMesh& ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); stk::mesh::NgpField& ngpFieldNew = stk::mesh::get_updated_ngp_field(get_field_new()); diff --git a/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestDeviceAwareMPI.cpp b/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestDeviceAwareMPI.cpp index 371565fcea7d..aa3b8f2fe19d 100644 --- a/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestDeviceAwareMPI.cpp +++ b/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestDeviceAwareMPI.cpp @@ -37,25 +37,146 @@ #include "stk_util/parallel/DeviceAwareMPI.hpp" #include "stk_util/ngp/NgpSpaces.hpp" -TEST(DeviceAwareMPI, DISABLED_trueIfOpenMPIAndCuda) +#ifdef STK_HAS_MPI + +TEST(DeviceAwareMPI, trueIfOpenMPIAndCuda) { #if defined(OMPI_MAJOR_VERSION) && defined(KOKKOS_ENABLE_CUDA) EXPECT_TRUE(stk::have_device_aware_mpi()); +#else + GTEST_SKIP()<<"trueIfOpenMPIAndCuda"; +#endif +} + +TEST(DeviceAwareMPI, trueIfATS2MPIAndCuda) +{ +#if defined(IBM_SPECTRUM_MPI) && defined(KOKKOS_ENABLE_CUDA) + EXPECT_TRUE(stk::have_device_aware_mpi()); +#else + GTEST_SKIP()<<"trueIfATS2MPIAndCuda"; #endif } -TEST(DeviceAwareMPI, DISABLED_falseIfOpenMpiButNoCuda) +TEST(DeviceAwareMPI, falseIfOpenMpiButNoCuda) { -#if defined(OMPI_MAJOR_VERSION) && !defined(KOKKOS_ENABLED_CUDA) +#if defined(OMPI_MAJOR_VERSION) && !defined(KOKKOS_ENABLE_CUDA) EXPECT_FALSE(stk::have_device_aware_mpi()); +#else + GTEST_SKIP()<<"falseIfOpenMpiButNoCuda"; #endif } -TEST(DeviceAwareMPI, DISABLED_falseIfIntel) +TEST(DeviceAwareMPI, falseIfIntelMpi) { #if defined(I_MPI_VERSION) EXPECT_FALSE(stk::have_device_aware_mpi()); +#else + GTEST_SKIP()<<"falseIfIntel, I_MPI_VERSION not defined"; #endif } +void check_device_aware_mpi_send_recv(MPI_Comm comm) +{ + const int numProcs = stk::parallel_machine_size(comm); + ASSERT_EQ(2, numProcs); + const int myProc = stk::parallel_machine_rank(comm); + const int otherProc = 1 - myProc; + const int msgTag = 10101; + + using BufferViewType = Kokkos::View; + constexpr size_t N = 8; + constexpr double tol = 1.e-7; + constexpr double goldValue = 3.14159; + + if (myProc == 0) { + BufferViewType sendBuf("sendBuf",N); + Kokkos::deep_copy(sendBuf, goldValue); + EXPECT_EQ(MPI_SUCCESS, MPI_Send(sendBuf.data(), N, MPI_DOUBLE, otherProc, msgTag, comm)); + } + else { + BufferViewType recvBuf("recvBuf",N); + Kokkos::deep_copy(recvBuf, 0.0); + MPI_Status status; + EXPECT_EQ( MPI_SUCCESS, MPI_Recv(recvBuf.data(), N, MPI_DOUBLE, otherProc, msgTag, comm, &status)); + + BufferViewType::HostMirror hostRecvBuf = Kokkos::create_mirror_view(recvBuf); + Kokkos::deep_copy(hostRecvBuf, recvBuf); + for(size_t i=0; i; + constexpr size_t N = 4200; + constexpr double tol = 1.e-7; + constexpr double goldValue = 3.14159; + + const int numCommProcs = 1; + std::vector sendRequests(numCommProcs); + std::vector recvRequests(numCommProcs); + std::vector statuses(numCommProcs); + + BufferViewType sendBuf("sendBuf",N); + BufferViewType recvBuf("recvBuf",N); + + stk::parallel_machine_barrier(comm); + + if (myProc == 1) { + Kokkos::deep_copy(recvBuf, 0.0); //theoretically unnecessary since Views initialize by default. + EXPECT_EQ(MPI_SUCCESS, MPI_Irecv(recvBuf.data(), N, MPI_DOUBLE, otherProc, msgTag, comm, &recvRequests[0])); + } + if (myProc == 0) { + Kokkos::deep_copy(sendBuf, goldValue); + EXPECT_EQ(MPI_SUCCESS, MPI_Isend(sendBuf.data(), N, MPI_DOUBLE, otherProc, msgTag, comm, &sendRequests[0])); + } + + Kokkos::fence(); + + if (myProc == 1) { + int idx = 99; + MPI_Waitany(numCommProcs, recvRequests.data(), &idx, MPI_STATUS_IGNORE); + EXPECT_EQ(0, idx); + + BufferViewType::HostMirror hostRecvBuf = Kokkos::create_mirror_view(recvBuf); + Kokkos::deep_copy(hostRecvBuf, recvBuf); + for(size_t i=0; i + +TEST(FPExceptions, SimpleAdditionNoError) +{ + if (!stk::util::have_errno() && !stk::util::have_errexcept()) GTEST_SKIP(); + + stk::util::clear_fp_errors(); + double x = 1.0 + 2.0; + EXPECT_NO_THROW(stk::util::throw_on_fp_error()); + EXPECT_EQ(x, 3.0); // appease the compiler +} + +TEST(FPExceptions, Log0Error) +{ + if (!stk::util::have_errno() && !stk::util::have_errexcept()) GTEST_SKIP(); + + stk::util::clear_fp_errors(); + std::log(0.0); + EXPECT_ANY_THROW(stk::util::throw_on_fp_error()); +} + +TEST(FPExceptions, FlagsAreClearedAfterThrow) +{ + if (!stk::util::have_errno() && !stk::util::have_errexcept()) GTEST_SKIP(); + + stk::util::clear_fp_errors(); + std::log(0.0); + EXPECT_ANY_THROW(stk::util::throw_on_fp_error()); + EXPECT_NO_THROW(stk::util::throw_on_fp_error()); +} + +TEST(FPExceptions, ErrorMessageContainsName) +{ + if (!stk::util::have_errno() && !stk::util::have_errexcept()) GTEST_SKIP(); + + stk::util::clear_fp_errors(); + std::log(0.0); + + std::string fname = "my_very_specific_and_clear_function_name"; + try { + stk::util::throw_on_fp_error(fname.c_str()); + } catch (std::exception& except) + { + std::string msg(except.what()); + size_t pos = msg.find(fname); + EXPECT_NE(pos, std::string::npos); + } +} + +TEST(FPExceptions, NoWarning) +{ + if (!stk::util::have_errno() && !stk::util::have_errexcept()) GTEST_SKIP(); + + stk::util::clear_fp_errors(); + double x = 1.0 + 2.0; + std::stringstream ss; + EXPECT_NO_THROW(stk::util::warn_on_fp_error(nullptr, ss)); + EXPECT_EQ(ss.str().size(), 0U); + EXPECT_EQ(x, 3.0); // appease the compiler +} + +TEST(FPExceptions, Warning) +{ + if (!stk::util::have_errno() && !stk::util::have_errexcept()) GTEST_SKIP(); + + stk::util::clear_fp_errors(); + std::log(0.0); + std::stringstream ss; + EXPECT_NO_THROW(stk::util::warn_on_fp_error(nullptr, ss)); + EXPECT_GT(ss.str().size(), 0U); +} diff --git a/packages/stk/stk_util/stk_util/Version.hpp b/packages/stk/stk_util/stk_util/Version.hpp index 244712c23833..4f4efaf1655d 100644 --- a/packages/stk/stk_util/stk_util/Version.hpp +++ b/packages/stk/stk_util/stk_util/Version.hpp @@ -44,7 +44,7 @@ //See the file CHANGELOG.md for a listing that shows the //correspondence between version numbers and API changes. -#define STK_VERSION 5210600 +#define STK_VERSION 5210601 namespace stk diff --git a/packages/stk/stk_util/stk_util/ngp/NgpSpaces.hpp b/packages/stk/stk_util/stk_util/ngp/NgpSpaces.hpp index d17990ca2a23..c0dc9a2d8f34 100644 --- a/packages/stk/stk_util/stk_util/ngp/NgpSpaces.hpp +++ b/packages/stk/stk_util/stk_util/ngp/NgpSpaces.hpp @@ -40,45 +40,36 @@ namespace stk { namespace ngp { using ExecSpace = Kokkos::DefaultExecutionSpace; - using HostExecSpace = Kokkos::DefaultHostExecutionSpace; -#ifdef KOKKOS_ENABLE_CUDA -using MemSpace = Kokkos::CudaSpace; -#elif defined(KOKKOS_ENABLE_HIP) -using MemSpace = Kokkos::HIPSpace; +#ifndef KOKKOS_HAS_SHARED_HOST_PINNED_SPACE +#ifndef _MSC_VER +#warning "Kokkos::SharedHostPinnedSpace is not defined." #else -using MemSpace = ExecSpace::memory_space; +#pragma message("Kokkos::SharedHostPinnedSpace is not defined.") #endif - -#ifdef KOKKOS_HAS_SHARED_SPACE -using UVMMemSpace = Kokkos::SharedSpace; -#else -#ifdef KOKKOS_ENABLE_CUDA -#ifdef KOKKOS_ENABLE_CUDA_UVM -using UVMMemSpace = Kokkos::CudaUVMSpace; +using HostPinnedSpace = Kokkos::HostSpace; #else -using UVMMemSpace = Kokkos::CudaHostPinnedSpace; +using HostPinnedSpace = Kokkos::SharedHostPinnedSpace; #endif -#elif defined(KOKKOS_ENABLE_HIP) -using UVMMemSpace = Kokkos::HIPHostPinnedSpace; -#elif defined(KOKKOS_ENABLE_OPENMP) -using UVMMemSpace = Kokkos::OpenMP; + +#ifndef KOKKOS_HAS_SHARED_SPACE +#ifndef _MSC_VER +#warning "Kokkos::SharedSpace is not defined." #else -using UVMMemSpace = Kokkos::HostSpace; +#pragma message("Kokkos::SharedSpace is not defined.") #endif +using UVMMemSpace = Kokkos::HostSpace; +#else +using UVMMemSpace = Kokkos::SharedSpace; #endif -#ifdef KOKKOS_HAS_SHARED_SPACE -using HostPinnedSpace = Kokkos::SharedHostPinnedSpace; -#else #ifdef KOKKOS_ENABLE_CUDA -using HostPinnedSpace = Kokkos::CudaHostPinnedSpace; +using MemSpace = Kokkos::CudaSpace; #elif defined(KOKKOS_ENABLE_HIP) -using HostPinnedSpace = Kokkos::HIPHostPinnedSpace; +using MemSpace = Kokkos::HIPSpace; #else -using HostPinnedSpace = MemSpace; -#endif +using MemSpace = ExecSpace::memory_space; #endif #ifdef KOKKOS_ENABLE_HIP diff --git a/packages/stk/stk_util/stk_util/parallel/DeviceAwareMPI.cpp b/packages/stk/stk_util/stk_util/parallel/DeviceAwareMPI.cpp index 64efda9af165..99a227352018 100644 --- a/packages/stk/stk_util/stk_util/parallel/DeviceAwareMPI.cpp +++ b/packages/stk/stk_util/stk_util/parallel/DeviceAwareMPI.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #ifdef OMPI_MAJOR_VERSION @@ -44,8 +45,15 @@ namespace stk { bool have_device_aware_mpi() { -#if defined(MPIX_CUDA_AWARE_SUPPORT) && MPIX_CUDA_AWARE_SUPPORT - return true; +#if defined(STK_ENABLE_GPU) && defined(MPIX_CUDA_AWARE_SUPPORT) + //This runtime-check is described at this web page: + //https://www.open-mpi.org/faq/?category=runcuda + if (1 == MPIX_Query_cuda_support()) { + return true; + } + else { + return false; + } #endif return false; diff --git a/packages/stk/stk_util/stk_util/parallel/OutputStreams.cpp b/packages/stk/stk_util/stk_util/parallel/OutputStreams.cpp index b99379794fea..8a84880ee6d5 100644 --- a/packages/stk/stk_util/stk_util/parallel/OutputStreams.cpp +++ b/packages/stk/stk_util/stk_util/parallel/OutputStreams.cpp @@ -105,7 +105,9 @@ void output_flush() void set_outputP0(std::ostream* ostreamPtr, ParallelMachine comm) { - reset_default_output_streams(comm); + if (comm != OutputStreams::instance().m_comm) { + reset_default_output_streams(comm); + } if (stk::parallel_machine_rank(comm) == 0) { OutputStreams::instance().m_outputP0 = ostreamPtr; } diff --git a/packages/stk/stk_util/stk_util/registry/ProductRegistry.cpp b/packages/stk/stk_util/stk_util/registry/ProductRegistry.cpp index d1396ef1b150..c2b9f9ded275 100644 --- a/packages/stk/stk_util/stk_util/registry/ProductRegistry.cpp +++ b/packages/stk/stk_util/stk_util/registry/ProductRegistry.cpp @@ -42,7 +42,7 @@ //In Sierra, STK_VERSION_STRING is provided on the compile line by bake. //For Trilinos stk snapshots, the following macro definition gets populated with //the real version string by the trilinos_snapshot.sh script. -#define STK_VERSION_STRING "5.21.6-340-g20e31875" +#define STK_VERSION_STRING "5.23.1-605-g31b54b7f" #endif namespace stk { diff --git a/packages/stk/stk_util/stk_util/stk_config.h b/packages/stk/stk_util/stk_util/stk_config.h index 491d6c5bb090..14164584d5b9 100644 --- a/packages/stk/stk_util/stk_util/stk_config.h +++ b/packages/stk/stk_util/stk_util/stk_config.h @@ -49,6 +49,8 @@ #define STK_HAS_SEACAS_IOSS #define STK_HAS_SEACAS_EXODUS #define STK_HAS_SEACAS_NEMESIS +#define STK_HAVE_FP_EXCEPT +#define STK_HAVE_FP_ERRNO #else // This file gets created by cmake during a Trilinos build diff --git a/packages/stk/stk_util/stk_util/util/FPExceptions.cpp b/packages/stk/stk_util/stk_util/util/FPExceptions.cpp new file mode 100644 index 000000000000..f09fdf77f462 --- /dev/null +++ b/packages/stk/stk_util/stk_util/util/FPExceptions.cpp @@ -0,0 +1,51 @@ +#include "FPExceptions.hpp" + +namespace stk { +namespace util { + +namespace { +void append_string(std::string& all_exceptions_string, const std::string& new_string) +{ + if (all_exceptions_string.size() == 0) + { + all_exceptions_string = new_string; + } else + { + all_exceptions_string = all_exceptions_string + ", " + new_string; + } +} +} + +std::string get_fe_except_string(int fe_except_bitmask) +{ + std::string all_exceptions_string; + if (fe_except_bitmask & FE_DIVBYZERO) + { + append_string(all_exceptions_string, "FE_DIVBYZERO"); + } + + if (fe_except_bitmask & FE_INEXACT) + { + append_string(all_exceptions_string, "FE_INEXACT"); + } + + if ( fe_except_bitmask & FE_INVALID) + { + append_string(all_exceptions_string, "FE_INVALID"); + } + + if (fe_except_bitmask & FE_OVERFLOW) + { + append_string(all_exceptions_string, "FE_OVERFLOW"); + } + + if (fe_except_bitmask & FE_UNDERFLOW) + { + append_string(all_exceptions_string, "FE_UNDERFLOW"); + } + + return all_exceptions_string; +} + +} +} \ No newline at end of file diff --git a/packages/stk/stk_util/stk_util/util/FPExceptions.hpp b/packages/stk/stk_util/stk_util/util/FPExceptions.hpp new file mode 100644 index 000000000000..3d65d0a6017a --- /dev/null +++ b/packages/stk/stk_util/stk_util/util/FPExceptions.hpp @@ -0,0 +1,95 @@ +#ifndef STK_UTIL_FPEXCEPTIONS +#define STK_UTIL_FPEXCEPTIONS + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace stk { +namespace util { + +constexpr bool have_errno() +{ +#ifdef STK_HAVE_FP_ERRNO + return math_errhandling & MATH_ERRNO; +#else + return false; +#endif +} + +constexpr bool have_errexcept() +{ +#ifdef STK_HAVE_FP_EXCEPT + return math_errhandling & MATH_ERREXCEPT; +#else + return false; +#endif +} + +std::string get_fe_except_string(int fe_except_bitmask); + +inline void clear_fp_errors() +{ + if constexpr (have_errexcept()) + { + std::feclearexcept(FE_ALL_EXCEPT); + } else if constexpr (have_errno()) + { + errno = 0; + } +} + +inline void throw_or_warn_on_fp_error(const char* fname = nullptr, bool warn=false, std::ostream& os = std::cerr) +{ + if constexpr (have_errexcept()) + { + int fe_except_bitmask = std::fetestexcept(FE_ALL_EXCEPT & ~FE_INEXACT); + if (fe_except_bitmask != 0) + { + std::string msg = std::string(fname ? fname : "") + " raised floating point error(s): " + get_fe_except_string(fe_except_bitmask); + clear_fp_errors(); + if (warn) + { + os << msg << std::endl; + } else { + STK_ThrowRequireMsg(fe_except_bitmask == 0, msg); + } + } + } else if constexpr (have_errno()) + { + if (errno != 0) + { + std::string msg = std::string(fname ? fname : "") + " raised floating point error(s) " + std::strerror(errno); + clear_fp_errors(); + if (warn) + { + os << msg << std::endl; + } else + { + STK_ThrowRequireMsg(errno == 0, msg); + } + } + } +} + +inline void warn_on_fp_error(const char* fname = nullptr, std::ostream& os = std::cerr) +{ + throw_or_warn_on_fp_error(fname, true, os); +} + +inline void throw_on_fp_error(const char* fname = nullptr) +{ + throw_or_warn_on_fp_error(fname, false); +} + + +} +} + +#endif diff --git a/packages/tpetra/core/src/CMakeLists.txt b/packages/tpetra/core/src/CMakeLists.txt index e77abc4d98c6..0cfece8b18f5 100644 --- a/packages/tpetra/core/src/CMakeLists.txt +++ b/packages/tpetra/core/src/CMakeLists.txt @@ -729,6 +729,10 @@ IF (${PACKAGE_NAME}_ENABLE_EXPLICIT_INSTANTIATION) TPETRA_PROCESS_ALL_SLGN_TEMPLATES(BLOCKMULTIVECTOR_OUTPUT_FILES "Tpetra_ETI_SC_LO_GO_NT.tmpl" "BlockMultiVector" "BLOCKMULTIVECTOR" "${CrsMatrix_ETI_SCALARS}" "${TpetraCore_ETI_LORDS}" "${TpetraCore_ETI_GORDS}" "${TpetraCore_ETI_NODES}" TRUE ) LIST(APPEND SOURCES ${BLOCKMULTIVECTOR_OUTPUT_FILES}) + # Generate ETI .cpp files for Tpetra::LinearProblem. + TPETRA_PROCESS_ALL_SLGN_TEMPLATES(LINEARPROBLEM_OUTPUT_FILES "Tpetra_ETI_SC_LO_GO_NT.tmpl" "LinearProblem" "LINEARPROBLEM" "${CrsMatrix_ETI_SCALARS}" "${TpetraCore_ETI_LORDS}" "${TpetraCore_ETI_GORDS}" "${TpetraCore_ETI_NODES}" TRUE) + LIST(APPEND SOURCES ${LINEARPROBLEM_OUTPUT_FILES}) + # Generate ETI .cpp files for Tpetra::BlockVector. TPETRA_PROCESS_ALL_SLGN_TEMPLATES(BLOCKVECTOR_OUTPUT_FILES "Tpetra_ETI_SC_LO_GO_NT.tmpl" "BlockVector" "BLOCKVECTOR" diff --git a/packages/tpetra/core/src/Tpetra_CrsMatrix_def.hpp b/packages/tpetra/core/src/Tpetra_CrsMatrix_def.hpp index a88b5ca649ba..f0eef6b3b32e 100644 --- a/packages/tpetra/core/src/Tpetra_CrsMatrix_def.hpp +++ b/packages/tpetra/core/src/Tpetra_CrsMatrix_def.hpp @@ -47,7 +47,6 @@ #include "KokkosBlas1_scal.hpp" #include "KokkosSparse_getDiagCopy.hpp" #include "KokkosSparse_spmv.hpp" -#include "Kokkos_StdAlgorithms.hpp" #include #include @@ -8302,16 +8301,24 @@ CrsMatrix:: << std::endl; std::cerr << os.str (); } - destMat->numExportPacketsPerLID_.sync_device(); - auto numExportPacketsPerLID = destMat->numExportPacketsPerLID_.view_device(); - auto numImportPacketsPerLID = destMat->numImportPacketsPerLID_.view_device(); + // Make sure that host has the latest version, since we're + // using the version on host. If host has the latest + // version, syncing to host does nothing. + destMat->numExportPacketsPerLID_.sync_host (); + Teuchos::ArrayView numExportPacketsPerLID = + getArrayViewFromDualView (destMat->numExportPacketsPerLID_); + destMat->numImportPacketsPerLID_.sync_host (); + Teuchos::ArrayView numImportPacketsPerLID = + getArrayViewFromDualView (destMat->numImportPacketsPerLID_); + if (verbose) { std::ostringstream os; os << *verbosePrefix << "Calling 3-arg doReversePostsAndWaits" << std::endl; std::cerr << os.str (); } - Distor.doReversePostsAndWaits(numExportPacketsPerLID, 1, numImportPacketsPerLID); + Distor.doReversePostsAndWaits(destMat->numExportPacketsPerLID_.view_host(), 1, + destMat->numImportPacketsPerLID_.view_host()); if (verbose) { std::ostringstream os; os << *verbosePrefix << "Finished 3-arg doReversePostsAndWaits" @@ -8319,26 +8326,34 @@ CrsMatrix:: std::cerr << os.str (); } - size_t totalImportPackets = Kokkos::Experimental::reduce(typename Node::execution_space(), numImportPacketsPerLID); + size_t totalImportPackets = 0; + for (Array_size_type i = 0; i < numImportPacketsPerLID.size (); ++i) { + totalImportPackets += numImportPacketsPerLID[i]; + } // Reallocation MUST go before setting the modified flag, // because it may clear out the flags. destMat->reallocImportsIfNeeded (totalImportPackets, verbose, verbosePrefix.get ()); destMat->imports_.modify_host (); - auto deviceImports = destMat->imports_.view_device(); - auto deviceExports = destMat->exports_.view_device(); + auto hostImports = destMat->imports_.view_host(); + // This is a legacy host pack/unpack path, so use the host + // version of exports_. + destMat->exports_.sync_host (); + auto hostExports = destMat->exports_.view_host(); if (verbose) { std::ostringstream os; - os << *verbosePrefix << "Calling 4-arg doReversePostsAndWaitsKokkos" + os << *verbosePrefix << "Calling 4-arg doReversePostsAndWaits" << std::endl; std::cerr << os.str (); } - destMat->imports_.sync_device(); - Distor.doReversePostsAndWaitsKokkos (deviceExports, numExportPacketsPerLID, deviceImports, numImportPacketsPerLID); + Distor.doReversePostsAndWaits (hostExports, + numExportPacketsPerLID, + hostImports, + numImportPacketsPerLID); if (verbose) { std::ostringstream os; - os << *verbosePrefix << "Finished 4-arg doReversePostsAndWaitsKokkos" + os << *verbosePrefix << "Finished 4-arg doReversePostsAndWaits" << std::endl; std::cerr << os.str (); } @@ -8381,16 +8396,23 @@ CrsMatrix:: << std::endl; std::cerr << os.str (); } - destMat->numExportPacketsPerLID_.sync_device (); - auto numExportPacketsPerLID = destMat->numExportPacketsPerLID_.view_device(); - auto numImportPacketsPerLID = destMat->numImportPacketsPerLID_.view_device(); + // Make sure that host has the latest version, since we're + // using the version on host. If host has the latest + // version, syncing to host does nothing. + destMat->numExportPacketsPerLID_.sync_host (); + Teuchos::ArrayView numExportPacketsPerLID = + getArrayViewFromDualView (destMat->numExportPacketsPerLID_); + destMat->numImportPacketsPerLID_.sync_host (); + Teuchos::ArrayView numImportPacketsPerLID = + getArrayViewFromDualView (destMat->numImportPacketsPerLID_); if (verbose) { std::ostringstream os; os << *verbosePrefix << "Calling 3-arg doPostsAndWaits" << std::endl; std::cerr << os.str (); } - Distor.doPostsAndWaits(numExportPacketsPerLID, 1, numImportPacketsPerLID); + Distor.doPostsAndWaits(destMat->numExportPacketsPerLID_.view_host(), 1, + destMat->numImportPacketsPerLID_.view_host()); if (verbose) { std::ostringstream os; os << *verbosePrefix << "Finished 3-arg doPostsAndWaits" @@ -8398,26 +8420,34 @@ CrsMatrix:: std::cerr << os.str (); } - size_t totalImportPackets = Kokkos::Experimental::reduce(typename Node::execution_space(), numImportPacketsPerLID); + size_t totalImportPackets = 0; + for (Array_size_type i = 0; i < numImportPacketsPerLID.size (); ++i) { + totalImportPackets += numImportPacketsPerLID[i]; + } // Reallocation MUST go before setting the modified flag, // because it may clear out the flags. destMat->reallocImportsIfNeeded (totalImportPackets, verbose, verbosePrefix.get ()); destMat->imports_.modify_host (); - auto deviceImports = destMat->imports_.view_device(); - auto deviceExports = destMat->exports_.view_device(); + auto hostImports = destMat->imports_.view_host(); + // This is a legacy host pack/unpack path, so use the host + // version of exports_. + destMat->exports_.sync_host (); + auto hostExports = destMat->exports_.view_host(); if (verbose) { std::ostringstream os; - os << *verbosePrefix << "Calling 4-arg doPostsAndWaitsKokkos" + os << *verbosePrefix << "Calling 4-arg doPostsAndWaits" << std::endl; std::cerr << os.str (); } - destMat->imports_.sync_device (); - Distor.doPostsAndWaitsKokkos (deviceExports, numExportPacketsPerLID, deviceImports, numImportPacketsPerLID); + Distor.doPostsAndWaits (hostExports, + numExportPacketsPerLID, + hostImports, + numImportPacketsPerLID); if (verbose) { std::ostringstream os; - os << *verbosePrefix << "Finished 4-arg doPostsAndWaitsKokkos" + os << *verbosePrefix << "Finished 4-arg doPostsAndWaits" << std::endl; std::cerr << os.str (); } @@ -8464,6 +8494,12 @@ CrsMatrix:: Teuchos::Array RemotePids; if (runOnHost) { Teuchos::Array TargetPids; + // Backwards compatibility measure. We'll use this again below. + + // TODO JHU Need to track down why numImportPacketsPerLID_ has not been corrently marked as modified on host (which it has been) + // TODO JHU somewhere above, e.g., call to Distor.doPostsAndWaits(). + // TODO JHU This only becomes apparent as we begin to convert TAFC to run on device. + destMat->numImportPacketsPerLID_.modify_host(); //FIXME # ifdef HAVE_TPETRA_MMM_TIMINGS RCP tmCopySPRdata = rcp(new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string("TAFC unpack-count-resize + copy same-perm-remote data")))); @@ -8655,6 +8691,14 @@ CrsMatrix:: } else { // run on device + + // Backwards compatibility measure. We'll use this again below. + + // TODO JHU Need to track down why numImportPacketsPerLID_ has not been corrently marked as modified on host (which it has been) + // TODO JHU somewhere above, e.g., call to Distor.doPostsAndWaits(). + // TODO JHU This only becomes apparent as we begin to convert TAFC to run on device. + destMat->numImportPacketsPerLID_.modify_host(); //FIXME + # ifdef HAVE_TPETRA_MMM_TIMINGS RCP tmCopySPRdata = rcp(new TimeMonitor(*TimeMonitor::getNewTimer(prefix + std::string("TAFC unpack-count-resize + copy same-perm-remote data")))); # endif diff --git a/packages/tpetra/core/src/Tpetra_Details_DistributorActor.hpp b/packages/tpetra/core/src/Tpetra_Details_DistributorActor.hpp index 24e8351a6133..9b021ac53e9b 100644 --- a/packages/tpetra/core/src/Tpetra_Details_DistributorActor.hpp +++ b/packages/tpetra/core/src/Tpetra_Details_DistributorActor.hpp @@ -22,7 +22,6 @@ #include "Teuchos_Time.hpp" #include "Kokkos_TeuchosCommAdapters.hpp" -#include "Kokkos_StdAlgorithms.hpp" #ifdef HAVE_TPETRA_MPI #include "mpi.h" @@ -54,13 +53,6 @@ class DistributorActor { const ImpView &imports, const Teuchos::ArrayView& numImportPacketsPerLID); - template - void doPostsAndWaitsKokkos(const DistributorPlan& plan, - const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID); - template void doPosts(const DistributorPlan& plan, const ExpView& exports, @@ -74,27 +66,6 @@ class DistributorActor { const ImpView &imports, const Teuchos::ArrayView& numImportPacketsPerLID); - template - void doPostsKokkos(const DistributorPlan& plan, - const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID); - - template - void doPostsAllToAllKokkos( - const DistributorPlan &plan, const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID); - - template - void doPostsNbrAllToAllVKokkos( - const DistributorPlan &plan, const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID); - void doWaits(const DistributorPlan& plan); bool isReady() const; @@ -176,22 +147,6 @@ void DistributorActor::doPostsAndWaits(const DistributorPlan& plan, doWaits(plan); } - -template -void DistributorActor::doPostsAndWaitsKokkos(const DistributorPlan& plan, - const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID) -{ - static_assert(areKokkosViews, - "Data arrays for DistributorActor::doPostsAndWaitsKokkos must be Kokkos::Views"); - static_assert(areKokkosViews, - "Num packets arrays for DistributorActor::doPostsAndWaitsKokkos must be Kokkos::Views"); - doPostsKokkos(plan, exports, numExportPacketsPerLID, imports, numImportPacketsPerLID); - doWaits(plan); -} - template using HostAccessibility = Kokkos::SpaceAccessibility; @@ -805,140 +760,6 @@ void DistributorActor::doPostsAllToAll( << "\"."); } -template -void DistributorActor::doPostsAllToAllKokkos( - const DistributorPlan &plan, const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID) { - TEUCHOS_TEST_FOR_EXCEPTION( - !plan.getIndicesTo().is_null(), std::runtime_error, - "Send Type=\"Alltoall\" only works for fast-path communication."); - - using size_type = Teuchos::Array::size_type; - using ExpExecSpace = typename ExpPacketsView::execution_space; - using ImpExecSpace = typename ImpPacketsView::execution_space; - - auto comm = plan.getComm(); - Kokkos::View sendcounts("sendcounts", comm->getSize()); - Kokkos::View sdispls("sdispls", comm->getSize()); - Kokkos::View recvcounts("recvcounts", comm->getSize()); - Kokkos::View rdispls("rdispls", comm->getSize()); - - auto sendcounts_d = Kokkos::create_mirror_view(ExpExecSpace(), sendcounts); - auto sdispls_d = Kokkos::create_mirror_view(ExpExecSpace(), sdispls); - auto recvcounts_d = Kokkos::create_mirror_view(ImpExecSpace(), recvcounts); - auto rdispls_d = Kokkos::create_mirror_view(ImpExecSpace(), rdispls); - - auto getStartsTo = Kokkos::Compat::getKokkosViewDeepCopy(plan.getStartsTo()); - auto getLengthsTo = Kokkos::Compat::getKokkosViewDeepCopy(plan.getLengthsTo()); - auto getProcsTo = Kokkos::Compat::getKokkosViewDeepCopy(plan.getProcsTo()); - - size_t curPKToffset = 0; - Kokkos::parallel_scan(Kokkos::RangePolicy(0, plan.getNumSends()), KOKKOS_LAMBDA(const size_t pp, size_t& offset, bool is_final) { - sdispls_d(getProcsTo(pp)) = offset; - size_t numPackets = 0; - for (size_t j = getStartsTo(pp); j < getStartsTo(pp) + getLengthsTo(pp); ++j) { - numPackets += numExportPacketsPerLID(j); - } - sendcounts_d(getProcsTo(pp)) = static_cast(numPackets); - offset += numPackets; - }, curPKToffset); - - int overflow; - Kokkos::parallel_reduce(Kokkos::RangePolicy(0, plan.getNumSends()), KOKKOS_LAMBDA(const size_t pp, int& index) { - if(sendcounts_d(getProcsTo(pp)) < 0) { - index = pp+1; - } - }, overflow); - - // numPackets is converted down to int, so make sure it can be represented - TEUCHOS_TEST_FOR_EXCEPTION(overflow, std::logic_error, - "Tpetra::Distributor::doPostsKokkos(4 args, Kokkos): " - "Send count for send " - << overflow-1 << " is too large " - "to be represented as int."); - - const size_type actualNumReceives = - Teuchos::as(plan.getNumReceives()) + - Teuchos::as(plan.hasSelfMessage() ? 1 : 0); - - auto getLengthsFrom = Kokkos::Compat::getKokkosViewDeepCopy(plan.getLengthsFrom()); - auto getProcsFrom = Kokkos::Compat::getKokkosViewDeepCopy(plan.getProcsFrom()); - - Kokkos::View curLIDoffset("curLIDoffset", actualNumReceives); - Kokkos::parallel_scan(Kokkos::RangePolicy(0, actualNumReceives), KOKKOS_LAMBDA(const size_type i, size_t& offset, bool is_final) { - if(is_final) curLIDoffset(i) = offset; - offset += getLengthsFrom(i); - }); - - Kokkos::parallel_scan(Kokkos::RangePolicy(0, actualNumReceives), KOKKOS_LAMBDA(const size_type i, size_t& curBufferOffset, bool is_final) { - size_t totalPacketsFrom_i = 0; - for(size_t j = 0; j < getLengthsFrom(i); j++) { - totalPacketsFrom_i += numImportPacketsPerLID(curLIDoffset(i) + j); - } - - if(is_final) rdispls_d(getProcsFrom(i)) = curBufferOffset; - if(is_final) recvcounts_d(getProcsFrom(i)) = static_cast(totalPacketsFrom_i); - curBufferOffset += totalPacketsFrom_i; - }); - - Kokkos::parallel_reduce(Kokkos::RangePolicy(0, actualNumReceives), KOKKOS_LAMBDA(const size_type i, int& index) { - if(recvcounts_d(getProcsFrom(i)) < 0) { - index = i+1; - } - }, overflow); - - // totalPacketsFrom_i is converted down to int, so make sure it can be - // represented - TEUCHOS_TEST_FOR_EXCEPTION(overflow, std::logic_error, - "Tpetra::Distributor::doPostsKokkos(4 args, Kokkos): " - "Recv count for receive " - << overflow-1 << " is too large " - "to be represented as int."); - - Kokkos::deep_copy(sendcounts, sendcounts_d); - Kokkos::deep_copy(sdispls, sdispls_d); - Kokkos::deep_copy(recvcounts, recvcounts_d); - Kokkos::deep_copy(rdispls, rdispls_d); - - Teuchos::RCP> mpiComm = - Teuchos::rcp_dynamic_cast>(comm); - Teuchos::RCP> rawComm = - mpiComm->getRawMpiComm(); - using T = typename ExpView::non_const_value_type; - MPI_Datatype rawType = ::Tpetra::Details::MpiTypeTraits::getType(T()); - -#if defined(HAVE_TPETRACORE_MPI_ADVANCE) - if (Details::DISTRIBUTOR_MPIADVANCE_ALLTOALL == plan.getSendType()) { - MPIX_Comm *mpixComm = *plan.getMPIXComm(); - TEUCHOS_TEST_FOR_EXCEPTION(!mpixComm, std::runtime_error, - "MPIX_Comm is null in doPostsAllToAll \"" - << __FILE__ << ":" << __LINE__); - - const int err = MPIX_Alltoallv( - exports.data(), sendcounts.data(), sdispls.data(), rawType, - imports.data(), recvcounts.data(), rdispls.data(), rawType, mpixComm); - - TEUCHOS_TEST_FOR_EXCEPTION(err != MPI_SUCCESS, std::runtime_error, - "MPIX_Alltoallv failed with error \"" - << Teuchos::mpiErrorCodeToString(err) - << "\"."); - - return; - } -#endif // HAVE_TPETRACORE_MPI_ADVANCE - - const int err = MPI_Alltoallv( - exports.data(), sendcounts.data(), sdispls.data(), rawType, - imports.data(), recvcounts.data(), rdispls.data(), rawType, (*rawComm)()); - - TEUCHOS_TEST_FOR_EXCEPTION(err != MPI_SUCCESS, std::runtime_error, - "MPI_Alltoallv failed with error \"" - << Teuchos::mpiErrorCodeToString(err) - << "\"."); -} - #if defined(HAVE_TPETRACORE_MPI_ADVANCE) template void DistributorActor::doPostsNbrAllToAllV( @@ -1019,117 +840,6 @@ void DistributorActor::doPostsNbrAllToAllV( << Teuchos::mpiErrorCodeToString(err) << "\"."); } - -template -void DistributorActor::doPostsNbrAllToAllVKokkos( - const DistributorPlan &plan, const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID) { - TEUCHOS_TEST_FOR_EXCEPTION( - !plan.getIndicesTo().is_null(), std::runtime_error, - "Send Type=\"Alltoall\" only works for fast-path communication."); - - const Teuchos_Ordinal numSends = plan.getProcsTo().size(); - const Teuchos_Ordinal numRecvs = plan.getProcsFrom().size(); - - auto comm = plan.getComm(); - Kokkos::View sendcounts("sendcounts", comm->getSize()); - Kokkos::View sdispls("sdispls", comm->getSize()); - Kokkos::View recvcounts("recvcounts", comm->getSize()); - Kokkos::View rdispls("rdispls", comm->getSize()); - - auto sendcounts_d = Kokkos::create_mirror_view(ExpExecSpace(), sendcounts); - auto sdispls_d = Kokkos::create_mirror_view(ExpExecSpace(), sdispls); - auto recvcounts_d = Kokkos::create_mirror_view(ImpExecSpace(), recvcounts); - auto rdispls_d = Kokkos::create_mirror_view(ImpExecSpace(), rdispls); - - auto getStartsTo = Kokkos::Compat::getKokkosViewDeepCopy(plan.getStartsTo()); - auto getLengthsTo = Kokkos::Compat::getKokkosViewDeepCopy(plan.getLengthsTo()); - - Teuchos::RCP> mpiComm = - Teuchos::rcp_dynamic_cast>(comm); - Teuchos::RCP> rawComm = - mpiComm->getRawMpiComm(); - using T = typename ExpView::non_const_value_type; - using ExpExecSpace = typename ExpPacketsView::execution_space; - using ImpExecSpace = typename ImpPacketsView::execution_space; - MPI_Datatype rawType = ::Tpetra::Details::MpiTypeTraits::getType(T()); - - // unlike standard alltoall, entry `i` in sdispls and sendcounts - // refer to the ith participating rank, rather than rank i - Kokkos::parallel_scan(Kokkos::RangePolicy(0, numSends), KOKKOS_LAMBDA(const Teuchos_Ordinal pp, size_t& curPKToffset, bool is_final) { - sdispls_d(pp) = curPKToffset; - size_t numPackets = 0; - for (size_t j = getStartsTo(pp); j < getStartsTo(pp) + getLengthsTo(pp); ++j) { - numPackets += numExportPacketsPerLID(j); - } - sendcounts_d(pp) = static_cast(numPackets); - curPKToffset += numPackets; - }); - - int overflow; - Kokkos::parallel_reduce(Kokkos::RangePolicy(0, numSends), KOKKOS_LAMBDA(const Teuchos_Ordinal pp, int& index) { - if(sendcounts_d(pp) < 0) { - index = i+1; - } - }, overflow); - - // numPackets is converted down to int, so make sure it can be represented - TEUCHOS_TEST_FOR_EXCEPTION(overflow, std::logic_error, - "Tpetra::Distributor::doPostsKokkos(4 args, Kokkos): " - "Send count for send " - << overflow-1 << " is too large " - "to be represented as int."); - - auto getLengthsFrom = Kokkos::Compat::getKokkosViewDeepCopy(plan.getLengthsFrom()); - - Kokkos::View curLIDoffset("curLIDoffset", numRecvs); - Kokkos::parallel_scan(Kokkos::RangePolicy(0, numRecvs), KOKKOS_LAMBDA(const Teuchos_Ordinal i, size_t& offset, bool is_final) { - if(is_final) curLIDoffset(i) = offset; - offset += getLengthsFrom(i); - }); - - Kokkos::parallel_scan(Kokkos::RangePolicy(0, numRecvs), KOKKOS_LAMBDA(const Teuchos_Ordinal i, size_t& curBufferOffset, bool is_final) { - rdispls_d(i) = curBufferOffset; - size_t totalPacketsFrom_i = 0; - for(size_t j = 0; j < getLengthsFrom(i); j++) { - totalPacketsFrom_i += numImportPacketsPerLID(curLIDoffset(i) + j); - } - - recvcounts_d(i) = static_cast(totalPacketsFrom_i); - curBufferOffset += totalPacketsFrom_i; - }); - - Kokkos::parallel_reduce(Kokkos::RangePolicy(0, numRecvs), KOKKOS_LAMBDA(const Teuchos_Ordinal i, int& index) { - if(recvcounts_d(pp) < 0) { - index = i+1; - } - }, overflow); - - // totalPacketsFrom_i is converted down to int, so make sure it can be - // represented - TEUCHOS_TEST_FOR_EXCEPTION(overflow, std::logic_error, - "Tpetra::Distributor::doPostsKokkos(4 args, Kokkos): " - "Recv count for receive " - << overflow-1 << ") is too large " - "to be represented as int."); - - Kokkos::deep_copy(sendcounts, sendcounts_d); - Kokkos::deep_copy(sdispls, sdispls_d); - Kokkos::deep_copy(recvcounts, recvcounts_d); - Kokkos::deep_copy(rdispls, rdispls_d); - - MPIX_Comm *mpixComm = *plan.getMPIXComm(); - const int err = MPIX_Neighbor_alltoallv( - exports.data(), sendcounts.data(), sdispls.data(), rawType, - imports.data(), recvcounts.data(), rdispls.data(), rawType, mpixComm); - - TEUCHOS_TEST_FOR_EXCEPTION(err != MPI_SUCCESS, std::runtime_error, - "MPIX_Neighbor_alltoallv failed with error \"" - << Teuchos::mpiErrorCodeToString(err) - << "\"."); -} #endif // HAVE_TPETRACORE_MPI_ADVANCE #endif // HAVE_TPETRA_MPI // clang-format off @@ -1397,16 +1107,16 @@ void DistributorActor::doPosts(const DistributorPlan& plan, // This buffer is long enough for only one message at a time. // Thus, we use DISTRIBUTOR_SEND always in this case, regardless - // of sendType requested by user. + // of sendType requested by user. // This code path formerly errored out with message: - // Tpetra::Distributor::doPosts(4-arg, Kokkos): + // Tpetra::Distributor::doPosts(4-arg, Kokkos): // The "send buffer" code path // doesn't currently work with nonblocking sends. // Now, we opt to just do the communication in a way that works. #ifdef HAVE_TPETRA_DEBUG if (sendType != Details::DISTRIBUTOR_SEND) { if (plan.getComm()->getRank() == 0) - std::cout << "The requested Tpetra send type " + std::cout << "The requested Tpetra send type " << DistributorSendTypeEnumToString(sendType) << " requires Distributor data to be ordered by" << " the receiving processor rank. Since these" @@ -1415,7 +1125,7 @@ void DistributorActor::doPosts(const DistributorPlan& plan, } #endif - Kokkos::View sendArray ("sendArray", + Kokkos::View sendArray ("sendArray", maxNumPackets); Array indicesOffsets (numExportPacketsPerLID.size(), 0); @@ -1470,360 +1180,6 @@ void DistributorActor::doPosts(const DistributorPlan& plan, } } -template -void DistributorActor::doPostsKokkos(const DistributorPlan& plan, - const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID) -{ - static_assert(areKokkosViews, - "Data arrays for DistributorActor::doPostsKokkos must be Kokkos::Views"); - static_assert(areKokkosViews, - "Num packets arrays for DistributorActor::doPostsKokkos must be Kokkos::Views"); - using Teuchos::Array; - using Teuchos::as; - using Teuchos::ireceive; - using Teuchos::isend; - using Teuchos::send; - using Teuchos::TypeNameTraits; - using std::endl; - using Kokkos::Compat::create_const_view; - using Kokkos::Compat::create_view; - using Kokkos::Compat::subview_offset; - using Kokkos::Compat::deep_copy_offset; - using ExpExecSpace = typename ExpPacketsView::execution_space; - using ImpExecSpace = typename ImpPacketsView::execution_space; - typedef Array::size_type size_type; - typedef ExpView exports_view_type; - typedef ImpView imports_view_type; - -#ifdef KOKKOS_ENABLE_CUDA - static_assert (! std::is_same::value && - ! std::is_same::value, - "Please do not use Tpetra::Distributor with UVM " - "allocations. See GitHub issue #1088."); -#endif // KOKKOS_ENABLE_CUDA - -#ifdef KOKKOS_ENABLE_SYCL - static_assert (! std::is_same::value && - ! std::is_same::value, - "Please do not use Tpetra::Distributor with SharedUSM " - "allocations. See GitHub issue #1088 (corresponding to CUDA)."); -#endif // KOKKOS_ENABLE_SYCL - -#ifdef HAVE_TPETRA_DISTRIBUTOR_TIMINGS - Teuchos::TimeMonitor timeMon (*timer_doPosts4KV_); -#endif // HAVE_TPETRA_DISTRIBUTOR_TIMINGS - - // Run-time configurable parameters that come from the input - // ParameterList set by setParameterList(). - const Details::EDistributorSendType sendType = plan.getSendType(); - -#ifdef HAVE_TPETRA_MPI - // All-to-all communication layout is quite different from - // point-to-point, so we handle it separately. - if (sendType == Details::DISTRIBUTOR_ALLTOALL) { - doPostsAllToAllKokkos(plan, exports, numExportPacketsPerLID, imports, numImportPacketsPerLID); - return; - } -#ifdef HAVE_TPETRACORE_MPI_ADVANCE - else if (sendType == Details::DISTRIBUTOR_MPIADVANCE_ALLTOALL) - { - doPostsAllToAllKokkos(plan, exports, numExportPacketsPerLID, imports, numImportPacketsPerLID); - return; - } else if (sendType == Details::DISTRIBUTOR_MPIADVANCE_NBRALLTOALLV) { - doPostsNbrAllToAllVKokkos(plan, exports, numExportPacketsPerLID, imports, numImportPacketsPerLID); - return; - } -#endif - -#else // HAVE_TPETRA_MPI - if (plan.hasSelfMessage()) { - size_t packetsPerSend; - Kokkos::parallel_reduce(Kokkos::RangePolicy(plan.getStartsTo()[0], plan.getStartsTo()[0]+plan.getLengthsTo()[0]), KOKKOS_LAMBDA(const size_t j, size_t& packets) { - packets += numExportPacketsPerLID(j); - }, packetsPerSend); - - deep_copy_offset(imports, exports, (size_t)0, (size_t)0, packetsPerSend); - } -#endif // HAVE_TPETRA_MPI - - const int myProcID = plan.getComm()->getRank (); - size_t selfReceiveOffset = 0; - -#ifdef HAVE_TPETRA_DEBUG - // Different messages may have different numbers of packets. - size_t totalNumImportPackets = Kokkos::Experimental::reduce(ImpExecSpace(), numImportPacketsPerLID); - TEUCHOS_TEST_FOR_EXCEPTION( - imports.extent (0) < totalNumImportPackets, std::runtime_error, - "Tpetra::Distributor::doPostsKokkos(4 args, Kokkos): The 'imports' array must have " - "enough entries to hold the expected number of import packets. " - "imports.extent(0) = " << imports.extent (0) << " < " - "totalNumImportPackets = " << totalNumImportPackets << "."); - TEUCHOS_TEST_FOR_EXCEPTION - (requests_.size () != 0, std::logic_error, "Tpetra::Distributor::" - "doPostsKokkos(4 args, Kokkos): Process " << myProcID << ": requests_.size () = " - << requests_.size () << " != 0."); -#endif // HAVE_TPETRA_DEBUG - // Distributor uses requests_.size() as the number of outstanding - // nonblocking message requests, so we resize to zero to maintain - // this invariant. - // - // getNumReceives() does _not_ include the self message, if there is - // one. Here, we do actually send a message to ourselves, so we - // include any self message in the "actual" number of receives to - // post. - // - // NOTE (mfh 19 Mar 2012): Epetra_MpiDistributor::DoPosts() - // doesn't (re)allocate its array of requests. That happens in - // CreateFromSends(), ComputeRecvs_(), DoReversePosts() (on - // demand), or Resize_(). - const size_type actualNumReceives = as (plan.getNumReceives()) + - as (plan.hasSelfMessage() ? 1 : 0); - requests_.resize (0); - - // Post the nonblocking receives. It's common MPI wisdom to post - // receives before sends. In MPI terms, this means favoring - // adding to the "posted queue" (of receive requests) over adding - // to the "unexpected queue" (of arrived messages not yet matched - // with a receive). - { -#ifdef HAVE_TPETRA_DISTRIBUTOR_TIMINGS - Teuchos::TimeMonitor timeMonRecvs (*timer_doPosts4KV_recvs_); -#endif // HAVE_TPETRA_DISTRIBUTOR_TIMINGS - - size_t curBufferOffset = 0; - size_t curLIDoffset = 0; - for (size_type i = 0; i < actualNumReceives; ++i) { - size_t totalPacketsFrom_i = 0; - Kokkos::parallel_reduce(Kokkos::RangePolicy(0, plan.getLengthsFrom()[i]), KOKKOS_LAMBDA(const size_t j, size_t& total) { - total += numImportPacketsPerLID(curLIDoffset+j); - }, totalPacketsFrom_i); - // totalPacketsFrom_i is converted down to int, so make sure it can be represented - TEUCHOS_TEST_FOR_EXCEPTION(totalPacketsFrom_i > size_t(INT_MAX), - std::logic_error, "Tpetra::Distributor::doPostsKokkos(3 args, Kokkos): " - "Recv count for receive " << i << " (" << totalPacketsFrom_i << ") is too large " - "to be represented as int."); - curLIDoffset += plan.getLengthsFrom()[i]; - if (plan.getProcsFrom()[i] != myProcID && totalPacketsFrom_i) { - // If my process is receiving these packet(s) from another - // process (not a self-receive), and if there is at least - // one packet to receive: - // - // 1. Set up the persisting view (recvBuf) into the imports - // array, given the offset and size (total number of - // packets from process getProcsFrom()[i]). - // 2. Start the Irecv and save the resulting request. - imports_view_type recvBuf = - subview_offset (imports, curBufferOffset, totalPacketsFrom_i); - requests_.push_back (ireceive (recvBuf, plan.getProcsFrom()[i], - mpiTag_, *plan.getComm())); - } - else { // Receiving these packet(s) from myself - selfReceiveOffset = curBufferOffset; // Remember the offset - } - curBufferOffset += totalPacketsFrom_i; - } - } - -#ifdef HAVE_TPETRA_DISTRIBUTOR_TIMINGS - Teuchos::TimeMonitor timeMonSends (*timer_doPosts4KV_sends_); -#endif // HAVE_TPETRA_DISTRIBUTOR_TIMINGS - - // setup views containing starting-offsets into exports for each send, - // and num-packets-to-send for each send. - Kokkos::View sendPacketOffsets("sendPacketOffsets", plan.getNumSends()); - Kokkos::View packetsPerSend("packetsPerSend", plan.getNumSends()); - auto sendPacketOffsets_d = Kokkos::create_mirror_view(ExpExecSpace(), sendPacketOffsets); - auto packetsPerSend_d = Kokkos::create_mirror_view(ExpExecSpace(), packetsPerSend); - - auto starts = Kokkos::Compat::getKokkosViewDeepCopy(plan.getStartsTo()); - auto lengths = Kokkos::Compat::getKokkosViewDeepCopy(plan.getLengthsTo()); - - Kokkos::parallel_scan(Kokkos::RangePolicy(0, plan.getNumSends()), KOKKOS_LAMBDA(const size_t pp, size_t& curPKToffset, bool final_pass) { - if(final_pass) sendPacketOffsets_d(pp) = curPKToffset; - size_t numPackets = 0; - for(size_t j = starts(pp); j < starts(pp) + lengths(pp); j++) { - numPackets += numExportPacketsPerLID(j); - } - if(final_pass) packetsPerSend_d(pp) = numPackets; - curPKToffset += numPackets; - }); - - size_t maxNumPackets; - Kokkos::parallel_reduce(Kokkos::RangePolicy(0, plan.getNumSends()), KOKKOS_LAMBDA(const size_t pp, size_t& max) { - if(packetsPerSend_d(pp) > max) { - max = packetsPerSend_d(pp); - } - }, Kokkos::Max(maxNumPackets)); - - // numPackets will be used as a message length, so make sure it can be represented as int - TEUCHOS_TEST_FOR_EXCEPTION(maxNumPackets > size_t(INT_MAX), - std::logic_error, "Tpetra::Distributor::doPostsKokkos(4 args, Kokkos): " - "numPackets = " << maxNumPackets << " is too large " - "to be represented as int."); - - Kokkos::deep_copy(sendPacketOffsets, sendPacketOffsets_d); - Kokkos::deep_copy(packetsPerSend, packetsPerSend_d); - - // setup scan through getProcsTo() list starting with higher numbered procs - // (should help balance message traffic) - size_t numBlocks = plan.getNumSends() + plan.hasSelfMessage(); - size_t procIndex = 0; - while ((procIndex < numBlocks) && (plan.getProcsTo()[procIndex] < myProcID)) { - ++procIndex; - } - if (procIndex == numBlocks) { - procIndex = 0; - } - - size_t selfNum = 0; - size_t selfIndex = 0; - if (plan.getIndicesTo().is_null()) { - -#ifdef HAVE_TPETRA_DISTRIBUTOR_TIMINGS - Teuchos::TimeMonitor timeMonSends2 (*timer_doPosts4KV_sends_fast_); -#endif // HAVE_TPETRA_DISTRIBUTOR_TIMINGS - - // Data are already blocked (laid out) by process, so we don't - // need a separate send buffer (besides the exports array). - for (size_t i = 0; i < numBlocks; ++i) { - size_t p = i + procIndex; - if (p > (numBlocks - 1)) { - p -= numBlocks; - } - - if (plan.getProcsTo()[p] != myProcID && packetsPerSend[p] > 0) { - exports_view_type tmpSend = - subview_offset(exports, sendPacketOffsets[p], packetsPerSend[p]); - - if (sendType == Details::DISTRIBUTOR_ISEND) { - exports_view_type tmpSendBuf = - subview_offset (exports, sendPacketOffsets[p], packetsPerSend[p]); - requests_.push_back (isend (tmpSendBuf, plan.getProcsTo()[p], - mpiTag_, *plan.getComm())); - } - else { // DISTRIBUTOR_SEND - send (tmpSend, - as (tmpSend.size ()), - plan.getProcsTo()[p], mpiTag_, *plan.getComm()); - } - } - else { // "Sending" the message to myself - selfNum = p; - } - } - - if (plan.hasSelfMessage()) { - deep_copy_offset(imports, exports, selfReceiveOffset, - sendPacketOffsets[selfNum], packetsPerSend[selfNum]); - } - } - else { // data are not blocked by proc, use send buffer - -#ifdef HAVE_TPETRA_DISTRIBUTOR_TIMINGS - Teuchos::TimeMonitor timeMonSends2 (*timer_doPosts4KV_sends_slow_); -#endif // HAVE_TPETRA_DISTRIBUTOR_TIMINGS - - // FIXME (mfh 05 Mar 2013) This may be broken for Isend. - typedef typename ExpView::non_const_value_type Packet; - typedef typename ExpView::array_layout Layout; - typedef typename ExpView::device_type Device; - typedef typename ExpView::memory_traits Mem; - - // This buffer is long enough for only one message at a time. - // Thus, we use DISTRIBUTOR_SEND always in this case, regardless - // of sendType requested by user. - // This code path formerly errored out with message: - // Tpetra::Distributor::doPostsKokkos(4-arg, Kokkos): - // The "send buffer" code path - // doesn't currently work with nonblocking sends. - // Now, we opt to just do the communication in a way that works. -#ifdef HAVE_TPETRA_DEBUG - if (sendType != Details::DISTRIBUTOR_SEND) { - if (plan.getComm()->getRank() == 0) - std::cout << "The requested Tpetra send type " - << DistributorSendTypeEnumToString(sendType) - << " requires Distributor data to be ordered by" - << " the receiving processor rank. Since these" - << " data are not ordered, Tpetra will use Send" - << " instead." << std::endl; - } -#endif - - Kokkos::View sendArray ("sendArray", - maxNumPackets); - - Kokkos::View indicesOffsets ("indicesOffsets", numExportPacketsPerLID.extent(0)); - size_t ioffset = 0; - Kokkos::parallel_scan(Kokkos::RangePolicy(0, numExportPacketsPerLID.extent(0)), KOKKOS_LAMBDA(const size_t j, size_t& offset, bool is_final) { - if(is_final) indicesOffsets(j) = offset; - offset += numExportPacketsPerLID(j); - }, ioffset); - - for (size_t i = 0; i < numBlocks; ++i) { - size_t p = i + procIndex; - if (p > (numBlocks - 1)) { - p -= numBlocks; - } - - if (plan.getProcsTo()[p] != myProcID) { - size_t j = plan.getStartsTo()[p]; - size_t numPacketsTo_p = 0; - //mirror in case execspaces are different - auto sendArrayMirror = Kokkos::create_mirror_view_and_copy(ExpExecSpace(), sendArray); - auto exportsMirror = Kokkos::create_mirror_view_and_copy(ExpExecSpace(), exports); - Kokkos::parallel_scan(Kokkos::RangePolicy(0, plan.getLengthsTo()[p]), KOKKOS_LAMBDA(const size_t k, size_t& offset, bool is_final) { - if(is_final) { - const size_t dst_end = offset + numExportPacketsPerLID(j + k); - const size_t src_end = indicesOffsets(j + k) + numExportPacketsPerLID(j + k); - auto dst_sub = Kokkos::subview(sendArrayMirror, Kokkos::make_pair(offset, dst_end)); - auto src_sub = Kokkos::subview(exportsMirror, Kokkos::make_pair(indicesOffsets(j + k), src_end)); - Kokkos::Experimental::local_deep_copy(dst_sub, src_sub); - } - offset += numExportPacketsPerLID(j + k); - }, numPacketsTo_p); - Kokkos::deep_copy(sendArray, sendArrayMirror); - typename ExpView::execution_space().fence(); - - if (numPacketsTo_p > 0) { - ImpView tmpSend = - subview_offset(sendArray, size_t(0), numPacketsTo_p); - - send (tmpSend, - as (tmpSend.size ()), - plan.getProcsTo()[p], mpiTag_, *plan.getComm()); - } - } - else { // "Sending" the message to myself - selfNum = p; - selfIndex = plan.getStartsTo()[p]; - } - } - - if (plan.hasSelfMessage()) { - //mirror in case execspaces are different - auto importsMirror = Kokkos::create_mirror_view_and_copy(ExpExecSpace(), imports); - auto exportsMirror = Kokkos::create_mirror_view_and_copy(ExpExecSpace(), exports); - size_t temp; - Kokkos::parallel_scan(Kokkos::RangePolicy(0, plan.getLengthsTo()[selfNum]), KOKKOS_LAMBDA(const size_t k, size_t& offset, bool is_final) { - if(is_final) { - const size_t dst_end = selfReceiveOffset + offset + numExportPacketsPerLID(selfIndex + k); - const size_t src_end = indicesOffsets(selfIndex + k) + numExportPacketsPerLID(selfIndex + k); - auto dst_sub = Kokkos::subview(importsMirror, Kokkos::make_pair(selfReceiveOffset + offset, dst_end)); - auto src_sub = Kokkos::subview(exportsMirror, Kokkos::make_pair(indicesOffsets(selfIndex + k), src_end)); - Kokkos::Experimental::local_deep_copy(dst_sub, src_sub); - } - offset += numExportPacketsPerLID(selfIndex + k); - }, temp); - Kokkos::deep_copy(imports, importsMirror); - selfIndex += plan.getLengthsTo()[selfNum]; - selfReceiveOffset += temp; - } - } -} - } } diff --git a/packages/tpetra/core/src/Tpetra_Distributor.hpp b/packages/tpetra/core/src/Tpetra_Distributor.hpp index a8beece8ee9d..c0c31a0f8b54 100644 --- a/packages/tpetra/core/src/Tpetra_Distributor.hpp +++ b/packages/tpetra/core/src/Tpetra_Distributor.hpp @@ -23,7 +23,6 @@ #include "KokkosCompat_View.hpp" #include "Kokkos_Core.hpp" #include "Kokkos_TeuchosCommAdapters.hpp" -#include "Kokkos_StdAlgorithms.hpp" #include #include #include @@ -427,13 +426,6 @@ namespace Tpetra { const ImpView &imports, const Teuchos::ArrayView& numImportPacketsPerLID); - template - typename std::enable_if<(Kokkos::is_view::value && Kokkos::is_view::value)>::type - doPostsAndWaitsKokkos (const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID); - /// \brief Post the data for a forward plan, but do not execute the waits yet. /// /// Call this overload when you have the same number of Packets @@ -488,13 +480,6 @@ namespace Tpetra { const Teuchos::ArrayView& numExportPacketsPerLID, const ImpView &imports, const Teuchos::ArrayView& numImportPacketsPerLID); - - template - typename std::enable_if<(Kokkos::is_view::value && Kokkos::is_view::value)>::type - doPostsKokkos (const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID); /// \brief Execute the reverse communication plan. /// @@ -516,14 +501,7 @@ namespace Tpetra { const Teuchos::ArrayView& numExportPacketsPerLID, const ImpView &imports, const Teuchos::ArrayView& numImportPacketsPerLID); - - template - typename std::enable_if<(Kokkos::is_view::value && Kokkos::is_view::value)>::type - doReversePostsAndWaitsKokkos (const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID); - + /// \brief Post the data for a reverse plan, but do not execute the waits yet. /// /// This method takes the same arguments as the three-argument @@ -544,14 +522,7 @@ namespace Tpetra { const Teuchos::ArrayView& numExportPacketsPerLID, const ImpView &imports, const Teuchos::ArrayView& numImportPacketsPerLID); - - template - typename std::enable_if<(Kokkos::is_view::value && Kokkos::is_view::value)>::type - doReversePostsKokkos (const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID); - + //@} //! @name Implementation of Teuchos::Describable //@{ @@ -669,16 +640,6 @@ namespace Tpetra { actor_.doPostsAndWaits(plan_, exports, numExportPacketsPerLID, imports, numImportPacketsPerLID); } - template - typename std::enable_if<(Kokkos::is_view::value && Kokkos::is_view::value)>::type - Distributor:: - doPostsAndWaitsKokkos (const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID) - { - actor_.doPostsAndWaitsKokkos(plan_, exports, numExportPacketsPerLID, imports, numImportPacketsPerLID); - } template typename std::enable_if<(Kokkos::is_view::value && Kokkos::is_view::value)>::type @@ -700,17 +661,6 @@ namespace Tpetra { { actor_.doPosts(plan_, exports, numExportPacketsPerLID, imports, numImportPacketsPerLID); } - - template - typename std::enable_if<(Kokkos::is_view::value && Kokkos::is_view::value)>::type - Distributor:: - doPostsKokkos (const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID) - { - actor_.doPostsKokkos(plan_, exports, numExportPacketsPerLID, imports, numImportPacketsPerLID); - } template typename std::enable_if<(Kokkos::is_view::value && Kokkos::is_view::value)>::type @@ -735,19 +685,6 @@ namespace Tpetra { numImportPacketsPerLID); doReverseWaits (); } - - template - typename std::enable_if<(Kokkos::is_view::value && Kokkos::is_view::value)>::type - Distributor:: - doReversePostsAndWaitsKokkos (const ExpView& exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView& imports, - const ImpPacketsView &numImportPacketsPerLID) - { - doReversePostsKokkos (exports, numExportPacketsPerLID, imports, - numImportPacketsPerLID); - doReverseWaits (); - } template typename std::enable_if<(Kokkos::is_view::value && Kokkos::is_view::value)>::type @@ -786,27 +723,7 @@ namespace Tpetra { reverseDistributor_->doPosts (exports, numExportPacketsPerLID, imports, numImportPacketsPerLID); } - - template - typename std::enable_if<(Kokkos::is_view::value && Kokkos::is_view::value)>::type - Distributor:: - doReversePostsKokkos (const ExpView &exports, - const ExpPacketsView &numExportPacketsPerLID, - const ImpView &imports, - const ImpPacketsView &numImportPacketsPerLID) - { - // FIXME (mfh 29 Mar 2012) WHY? - TEUCHOS_TEST_FOR_EXCEPTION( - ! plan_.getIndicesTo().is_null(), std::runtime_error, - "Tpetra::Distributor::doReversePosts(3 args): Can only do " - "reverse communication when original data are blocked by process."); - if (reverseDistributor_.is_null ()) { - createReverseDistributor (); - } - reverseDistributor_->doPostsKokkos (exports, numExportPacketsPerLID, - imports, numImportPacketsPerLID); - } - + template void Distributor:: computeSends(const Teuchos::ArrayView& importGIDs, diff --git a/packages/tpetra/core/src/Tpetra_LinearProblem_decl.hpp b/packages/tpetra/core/src/Tpetra_LinearProblem_decl.hpp new file mode 100644 index 000000000000..0b951f99124f --- /dev/null +++ b/packages/tpetra/core/src/Tpetra_LinearProblem_decl.hpp @@ -0,0 +1,197 @@ +// @HEADER +// ***************************************************************************** +// Tpetra: Templated Linear Algebra Services Package +// +// Copyright 2008 NTESS and the Tpetra contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +#ifndef TPETRA_LINEARPROBLEM_DECL_HPP +#define TPETRA_LINEARPROBLEM_DECL_HPP + +/// \file Tpetra_LinearProblem_decl.hpp +/// \brief Declaration of the Tpetra::LinearProblem class + +#include "Teuchos_DataAccess.hpp" + +#include "Tpetra_Vector_decl.hpp" +#include "Tpetra_MultiVector_decl.hpp" +#include "Tpetra_RowMatrix_decl.hpp" +#include "Tpetra_DistObject.hpp" +#include "Tpetra_Details_ExecutionSpacesUser.hpp" + +namespace Tpetra { + + /// \class LinearProblem + /// \brief Class that encapulates linear problem (Ax = b). + /// + /// The LinearProblem class is a wrapper that encapsulates the + /// general information needed for solving a linear system of + /// equations. Currently it accepts a Tpetra matrix/operator, + /// initial guess and RHS and returns the solution. + /// + /// \tparam Scalar The type of the numerical entries of the matrix. + /// (You can use real-valued or complex-valued types here.) + /// \tparam LocalOrdinal The type of local indices. See the + /// documentation of Map for requirements. + /// \tparam GlobalOrdinal The type of global indices. See the + /// documentation of Map for requirements. + /// \tparam Node The Kokkos Node type. See the documentation + /// of Map for requirements. + + template + class LinearProblem : + public DistObject, + public Details::Spaces::User + { + + private: + /// Type of the DistObject specialization from which this class inherits. + using dist_object_type = DistObject; + + public: + //! @name Typedefs + //@{ + + using map_type = Map; + using row_matrix_type = RowMatrix; + using multivector_type = MultiVector; + using vector_type = Vector; + using linear_problem_type = LinearProblem; + + //@} + + //! @name Constructors/Destructor + //@{ + + /// \brief Default Constructor. + /// + /// Creates an empty LinearProblem instance. The matrix + /// A, left-hand-side X and right-hand-side B must be set + /// use the setMatrix(), SetLHS() and SetRHS() methods + /// respectively. + LinearProblem(); + + /// \brief Constructor with a matrix. + /// + /// Creates a LinearProblem instance with a matrix. + LinearProblem(const Teuchos::RCP & A, + const Teuchos::RCP& X, + const Teuchos::RCP& B); + + //! Copy Constructor. + LinearProblem(const LinearProblem& Problem); + + //! LinearProblem Destructor. + virtual ~LinearProblem() = default; + + //@} + + //! @name Integrity check method + //@{ + + /// \brief Check input parameters for existence and size consistency. + /// + /// Returns 0 if all input parameters are valid. Returns +1 + /// if operator is not a matrix. This is not necessarily + /// an error, but no scaling can be done if the user passes + /// in an operator that is not an matrix. + void checkInput() const; + + //@} + + //! @name Implementation of DistObject interface + //@{ + + virtual bool + checkSizes (const SrcDistObject& source) override; + + //@} + + + //! @name Set methods + //@{ + + /// \brief Set Matrix A of linear problem AX = B using a RowMatrix. + /// + /// Sets an RCP to a RowMatrix. No copy of the operator is made. + void setMatrix(Teuchos::RCP A) + { A_ = A; } + + /// \brief Set left-hand-side X of linear problem AX = B. + /// + /// Sets an RCP to a MultiVector. No copy of the object is made. + void setLHS(Teuchos::RCP X) {X_ = X;} + + /// \brief Set right-hand-side B of linear problem AX = B. + /// + /// Sets an RCP to a MultiVector. No copy of the object is made. + void setRHS(Teuchos::RCP B) {B_ = B;} + + //@} + + //! @name Computational methods + //@{ + + /// \brief Perform left scaling of a linear problem. + /// + /// Applies the scaling vector D to the left side of the + /// matrix A() and to the right hand side B(). + /// + /// \param In + /// D - Vector containing scaling values. D[i] will + /// be applied to the ith row of A() and B(). + /// mode - Indicating if transposed. + /// \return Integer error code, set to 0 if successful. + /// Return -1 if operator is not a matrix. + void leftScale(const Teuchos::RCP & D, + Teuchos::ETransp mode = Teuchos::NO_TRANS); + + /// \brief Perform right scaling of a linear problem. + /// + /// Applies the scaling vector D to the right side of the + /// matrix A(). Apply the inverse of D to the initial + /// guess. + /// + /// \param In + /// D - Vector containing scaling values. D[i] will + /// be applied to the ith row of A(). 1/D[i] will + /// be applied to the ith row of B(). + /// mode - Indicating if transposed. + /// \return Integer error code, set to 0 if successful. + /// Return -1 if operator is not a matrix. + void rightScale(const Teuchos::RCP & D, + Teuchos::ETransp mode = Teuchos::NO_TRANS); + + //@} + + //! @name Accessor methods + //@{ + + //! Get an RCP to the matrix A. + Teuchos::RCP getMatrix() const {return(A_);} + //! Get an RCP to the left-hand-side X. + Teuchos::RCP getLHS() const {return(X_);} + //! Get an RCP to the right-hand-side B. + Teuchos::RCP getRHS() const {return(B_);} + + //@} + + private: + + Teuchos::RCP A_; + Teuchos::RCP X_; + Teuchos::RCP B_; + + LinearProblem & operator=(const LinearProblem& Problem) = default; +}; + +} // namespace Tpetra + +#endif // TPETRA_LINEARPROBLEM_DECL_HPP diff --git a/packages/tpetra/core/src/Tpetra_LinearProblem_def.hpp b/packages/tpetra/core/src/Tpetra_LinearProblem_def.hpp new file mode 100644 index 000000000000..ff0134852b74 --- /dev/null +++ b/packages/tpetra/core/src/Tpetra_LinearProblem_def.hpp @@ -0,0 +1,156 @@ +// @HEADER +// ***************************************************************************** +// Tpetra: Templated Linear Algebra Services Package +// +// Copyright 2008 NTESS and the Tpetra contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +#ifndef TPETRA_LINEARPROBLEM_DEF_HPP +#define TPETRA_LINEARPROBLEM_DEF_HPP + +/// \file Tpetra_LinearProblem_def.hpp +/// \brief Definition of the Tpetra::LinearProblem class +/// +/// If you want to use Tpetra::LinearProblem, include +/// "Tpetra_LinearProblem.hpp" (a file which CMake generates and installs +/// for you). If you only want the declaration of Tpetra::LinearProblem, +/// include "Tpetra_LinearProblem_decl.hpp". + +#include "Teuchos_DataAccess.hpp" +#include "Teuchos_TestForException.hpp" +#include "Tpetra_Details_Behavior.hpp" +#include "Tpetra_MultiVector.hpp" +#include "Tpetra_MultiVector_decl.hpp" + +namespace Tpetra { + + template + LinearProblem:: + LinearProblem () + : dist_object_type (Teuchos::rcp (new map_type ())), + A_(Teuchos::null), + X_(Teuchos::null), + B_(Teuchos::null) + { + } + + template + LinearProblem:: + LinearProblem (const Teuchos::RCP & A, + const Teuchos::RCP& X, + const Teuchos::RCP& B) + : dist_object_type (A->getDomainMap()), + A_(A), + X_(X), + B_(B) + { + } + + template + LinearProblem:: + LinearProblem (const LinearProblem& Problem) + : dist_object_type (Problem), + A_(Problem.A_), + X_(Problem.X_), + B_(Problem.B_) + { + } + + template + void LinearProblem:: + leftScale(const Teuchos::RCP & D, Teuchos::ETransp mode) + { + const Scalar ST0 = Teuchos::ScalarTraits::zero(); + const Scalar ST1 = Teuchos::ScalarTraits::one(); + if (mode == Teuchos::NO_TRANS) { + A_->leftScale(*D); + B_->elementWiseMultiply(ST1, *D, *B_, ST0); + } + else { + A_->rightScale(*D); + vector_type R(*D, Teuchos::DataAccess::Copy); + R.reciprocal(*D); + X_->elementWiseMultiply(ST1, R, *X_, ST0); + } + + return; + } + + template + void LinearProblem:: + rightScale(const Teuchos::RCP & D, Teuchos::ETransp mode) + { + const Scalar ST0 = Teuchos::ScalarTraits::zero(); + const Scalar ST1 = Teuchos::ScalarTraits::one(); + if (mode == Teuchos::NO_TRANS) { + A_->rightScale(*D); + vector_type R(*D, Teuchos::DataAccess::Copy); + R.reciprocal(*D); + X_->elementWiseMultiply(ST1, R, *X_, ST0); + } + else { + A_->leftScale(*D); + B_->elementWiseMultiply(ST1, *D, *B_, ST0); + } + return; + } + + template + void LinearProblem:: + checkInput() const { + + const char tfecfFuncName[] = "checkInput: "; + + TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(A_==Teuchos::null, std::runtime_error, + "Linear problem does not have a matrix (A_)."); + + TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(X_==Teuchos::null, + std::logic_error, "Solution vector (X_) is unset."); + + TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(B_==Teuchos::null, + std::logic_error, "RHS vector (B_) is unset."); + + TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!A_->getRowMap()->isSameAs(*(X_->getMap())), + std::logic_error, "Domain map of matrix is not the 'same as' the solution map."); + + TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!A_->getRowMap()->isSameAs(*(B_->getMap())), + std::logic_error, "Range map of matrix is not the 'same as' the RHS map."); + + return; + } + + template + bool LinearProblem:: + checkSizes (const SrcDistObject& sourceObj) + { + // Check whether the source object is a LinearProblem. If not, then + // we can't even compare sizes. + typedef LinearProblem LP; + const LP* src = dynamic_cast (&sourceObj); + if (src == nullptr) { + return false; + } + else { + this->checkInput(); + src->checkInput(); + + return ((this->A_->getDomainMap() == src->getMatrix()->getDomainMap()) and + (this->A_->getRangeMap() == src->getMatrix()->getRangeMap())); + } + } + +} // namespace Tpetra + +// +// Explicit instantiation macro +// +// Must be expanded from within the Tpetra namespace! +// + +#define TPETRA_LINEARPROBLEM_INSTANT(SCALAR,LO,GO,NODE) \ + template class LinearProblem< SCALAR , LO , GO , NODE >; + + +#endif // TPETRA_LINEARPROBLEM_DEF_HPP diff --git a/packages/tpetra/core/src/Tpetra_LinearProblem_fwd.hpp b/packages/tpetra/core/src/Tpetra_LinearProblem_fwd.hpp new file mode 100644 index 000000000000..143e5a89d719 --- /dev/null +++ b/packages/tpetra/core/src/Tpetra_LinearProblem_fwd.hpp @@ -0,0 +1,29 @@ +// @HEADER +// ***************************************************************************** +// Tpetra: Templated Linear Algebra Services Package +// +// Copyright 2008 NTESS and the Tpetra contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +#ifndef TPETRA_LINEARPROBLEM_FWD_HPP +#define TPETRA_LINEARPROBLEM_FWD_HPP + +#include "Tpetra_Details_DefaultTypes.hpp" + +/// \file Tpetra_LinearProblem_fwd.hpp +/// \brief Forward declaration of Tpetra::LinearProblem + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +namespace Tpetra { +template +class LinearProblem; + +} // namespace Tpetra +#endif // DOXYGEN_SHOULD_SKIP_THIS + +#endif // TPETRA_LINEARPROBLEM_FWD_HPP diff --git a/packages/tpetra/core/src/Tpetra_MultiVector_decl.hpp b/packages/tpetra/core/src/Tpetra_MultiVector_decl.hpp index fe1c639c02c2..17d51223c3d0 100644 --- a/packages/tpetra/core/src/Tpetra_MultiVector_decl.hpp +++ b/packages/tpetra/core/src/Tpetra_MultiVector_decl.hpp @@ -2016,7 +2016,7 @@ namespace Tpetra { /// \brief Multiply a Vector A elementwise by a MultiVector B. /// /// Compute this = scalarThis * this + scalarAB * B @ A - /// where @ denotes element-wise multiplication. In + /// where \@ denotes element-wise multiplication. In /// pseudocode, if C denotes *this MultiVector: /// \code /// C(i,j) = scalarThis * C(i,j) + scalarAB * B(i,j) * A(i,1); diff --git a/packages/tpetra/core/test/CMakeLists.txt b/packages/tpetra/core/test/CMakeLists.txt index 2144ebaf2c07..a53e978403c5 100644 --- a/packages/tpetra/core/test/CMakeLists.txt +++ b/packages/tpetra/core/test/CMakeLists.txt @@ -22,6 +22,7 @@ ADD_SUBDIRECTORIES( ImportExport ImportExport2 inout + LinearProblem Map MatrixMatrix Merge diff --git a/packages/tpetra/core/test/LinearProblem/CMakeLists.txt b/packages/tpetra/core/test/LinearProblem/CMakeLists.txt new file mode 100644 index 000000000000..732166cb223b --- /dev/null +++ b/packages/tpetra/core/test/LinearProblem/CMakeLists.txt @@ -0,0 +1,8 @@ +TRIBITS_ADD_EXECUTABLE_AND_TEST( + LinearProblem_UnitsTests + SOURCES + LinearProblem_UnitTests.cpp + ${TEUCHOS_STD_UNIT_TEST_MAIN} + COMM serial mpi + STANDARD_PASS_OUTPUT + ) diff --git a/packages/tpetra/core/test/LinearProblem/LinearProblem_UnitTests.cpp b/packages/tpetra/core/test/LinearProblem/LinearProblem_UnitTests.cpp new file mode 100644 index 000000000000..153be74694fc --- /dev/null +++ b/packages/tpetra/core/test/LinearProblem/LinearProblem_UnitTests.cpp @@ -0,0 +1,305 @@ +// @HEADER +// ***************************************************************************** +// Tpetra: Templated Linear Algebra Services Package +// +// Copyright 2008 NTESS and the Tpetra contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +#include "Tpetra_TestingUtilities.hpp" +#include "Tpetra_LinearProblem.hpp" +#include "Tpetra_CrsMatrix.hpp" + +#include "Teuchos_ScalarTraits.hpp" + + +namespace { // (anonymous) + + using Tpetra::TestingUtilities::getDefaultComm; + using Tpetra::createContigMapWithNode; + using Teuchos::RCP; + using Teuchos::rcp; + using Teuchos::Comm; + using Teuchos::Array; + using Teuchos::tuple; + //using Teuchos::NO_TRANS; + //using Teuchos::TRANS; + //using Teuchos::CONJ_TRANS; + using std::endl; + using GST = Tpetra::global_size_t; + + +#undef DEBUG_TEST +#ifdef DEBUG_TEST + /// \brief Print out pretty version of RowMatrix. + template + void Display_CrsMatrix (std::string label, RCP > A, RCP< const Comm< int > > comm, Teuchos::FancyOStream& myOut) + { + using local_ordinal_type = typename Tpetra::Vector::local_ordinal_type; + + using crs_matrix_type = typename Tpetra::CrsMatrix; + + using crs_local_inds_host_view_type = typename crs_matrix_type::local_inds_host_view_type; + using crs_values_host_view_type = typename crs_matrix_type::values_host_view_type; + + const local_ordinal_type INVALID = Teuchos::OrdinalTraits::invalid(); + + // Get the number of rows and columns + GST numRows = A->getGlobalNumRows(); + GST numCols = A->getGlobalNumCols(); + + // Loop over all global rows + for (GST globalRow = 0; globalRow < numRows; ++globalRow) { + // Check if this row belongs to the current process + if (A->getRowMap()->getLocalElement(globalRow) != INVALID) { + myOut << "Row " << std::setw(2) << globalRow << " [ "; + + // Extract the row view + crs_local_inds_host_view_type localIndices; + crs_values_host_view_type values; + size_t localRow = A->getRowMap()->getLocalElement(globalRow); + A->getLocalRowView(localRow, localIndices, values); + + // Initialize a vector to track printed entries + std::vector printed(numCols, false); + + // Print the entries in the row + size_t numEntries = A->getNumEntriesInLocalRow(localRow); + for (size_t k = 0; k < numEntries; ++k) { + // Convert local index to global index + GST globalIndex = A->getColMap()->getGlobalElement(localIndices(k)); + printed[globalIndex] = true; // Mark the index as having a non-zero entry + } + + // Print the values for each column + for (GST j = 0; j < numCols; ++j) { + if (printed[j]) { + // Find the corresponding value for the global index + for (size_t k = 0; k < numEntries; ++k) { + // Convert local index to global index + GST globalIndex = A->getColMap()->getGlobalElement(localIndices(k)); + if (globalIndex == j) { + myOut << std::setw(3) << values(k) << " "; + break; + } + } + } else { + myOut << std::setw(3) << 0 << " "; + } + } + myOut << "]" << endl; + } + // Synchronize processes before printing + comm->barrier(); + } + } + + template + void Display_MultiVector (std::string label, Teuchos::RCP> multivector, Teuchos::RCP< const Teuchos::Comm< int > > comm, Teuchos::FancyOStream& myOut) + { + using local_ordinal_type = typename Tpetra::Vector<>::local_ordinal_type; + const local_ordinal_type INVALID = Teuchos::OrdinalTraits::invalid(); + + auto map = multivector->getMap(); + const size_t myImageID = comm->getRank(); + + if (myImageID==0) { + myOut << label << endl; + myOut << std::setw(8) << "Rank" << std::setw(12) << "GID" << std::setw(20) << "Value(s)" << endl; + } + GST numRows = multivector->getGlobalLength(); + for (GST globalRow = 0; globalRow < numRows; ++globalRow) { + // Check if this row belongs to the current process + if (map->getLocalElement(globalRow) != INVALID) { + size_t localElement = map->getLocalElement(globalRow); + myOut << std::setw(8) << myImageID << std::setw(12) << globalRow << " "; + for (size_t j = 0; j < multivector->getNumVectors(); ++j) { + myOut << std::setw(10) << multivector->getData(j)[localElement]; + } + myOut << endl; + } + comm->barrier(); + } + } + + template + void Display_Vector (std::string label, Teuchos::RCP> vector, Teuchos::RCP< const Teuchos::Comm< int > > comm, Teuchos::FancyOStream& myOut) + { + auto multivector = Teuchos::rcp_dynamic_cast> (vector); + Display_MultiVector(label, multivector, comm, myOut); + } +#endif + + + // + // UNIT TESTS + // + + //// + TEUCHOS_UNIT_TEST_TEMPLATE_4_DECL( LinearProblem, basic, LO, GO, Scalar, Node ) + { + using map_type = Tpetra::Map; + using ST = typename Teuchos::ScalarTraits; + using mag_type = typename ST::magnitudeType; + + using MAT = Tpetra::CrsMatrix; + using VT = Tpetra::Vector; + using MV = Tpetra::MultiVector; + using LPT = Tpetra::LinearProblem; + //using local_ordinal_type = typename Tpetra::Vector::local_ordinal_type; + using global_ordinal_type = typename Tpetra::Vector::global_ordinal_type; + + + const global_ordinal_type INVALID = Teuchos::OrdinalTraits::invalid(); + constexpr bool debug = true; + + RCP outPtr = debug ? + Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr)) : + Teuchos::rcpFromRef (out); + Teuchos::FancyOStream& myOut = *outPtr; + Teuchos::OSTab tab0 (myOut); + + myOut << "Test: LinearProblem, Constructors" << endl; + + RCP > comm = getDefaultComm(); + //const size_t numImages = comm->getSize(); + const size_t myImageID = comm->getRank(); + // create a Map + const size_t numLocal = 5; + const size_t numVecs = 1; + RCP map = createContigMapWithNode(INVALID,numLocal,comm); + GO base = numLocal*myImageID; + GST globalNumElements = map->getGlobalNumElements(); + RCP > A; + { + RCP A_crs = rcp(new MAT(map,3)); + for (size_t i=0; iinsertGlobalValues(base + i, tuple(base + i), tuple(2.0)); // Diagonal entry + + GST globalIndex = base + i; + // Insert the first subdiagonal entry if not in the first row + if (globalIndex > 0) { + A_crs->insertGlobalValues(base + i, tuple(base + i - 1), tuple(1.0)); // Subdiagonal entry + } + + // Insert the first superdiagonal entry if not in the last row + if (globalIndex < globalNumElements - 1) { + A_crs->insertGlobalValues(base + i, tuple(base + i + 1), tuple(1.0)); // Superdiagonal entry + } + } + A_crs->fillComplete(); + A = A_crs; + } + + // create solution, rhs and scaling vector + RCP X = rcp (new MV (map, numVecs)); + RCP B = rcp (new MV (map, numVecs)); + RCP S = rcp (new VT (map)); + + // Assign values to the MultiVector based on the global index + for (size_t localIndex = 0; localIndex < numLocal; ++localIndex) { + auto globalIndex = map->getGlobalElement(localIndex); + S->replaceLocalValue(localIndex, Teuchos::as(globalIndex + 1)); + for (size_t j = 0; j < numVecs; ++j) { // Loop over each vector (column) + // Assign a value (for example, the global index plus the vector index) + X->replaceLocalValue(localIndex, j, Teuchos::as(globalIndex + j + 1)); + B->replaceLocalValue(localIndex, j, Teuchos::as(globalIndex + j + 1)); + } + } + + RCP linearProblem = rcp(new LPT()); + + linearProblem->setMatrix(A); + linearProblem->setLHS(X); + linearProblem->setRHS(B); + + linearProblem->checkInput(); + +#ifdef DEBUG_TEST + if (myImageID==0) myOut << "Original LinearProblem" << endl; + Display_CrsMatrix("A", A, comm, myOut); + Display_MultiVector("Solution Vector", X, comm, myOut); + Display_MultiVector("RHS Vector", B, comm, myOut); + Display_Vector("Scaling Vector", S, comm, myOut); +#endif + + GST N = globalNumElements; + mag_type eps = ST::magnitude(Teuchos::as(100)*Teuchos::ScalarTraits::eps()); + // Original LinearProblem + mag_type normF = ST::magnitude(std::sqrt(6*N - 2)); + mag_type matrix_normF = ST::magnitude(linearProblem->getMatrix()->getFrobeniusNorm()); + TEST_FLOATING_EQUALITY(matrix_normF, normF, eps); + + mag_type vector_sum = ST::magnitude(N*(N+1)/2); + Array norms(numVecs); + linearProblem->getLHS()->norm1(norms()); + TEST_FLOATING_EQUALITY(ST::magnitude(norms[0]), vector_sum, eps); + linearProblem->getRHS()->norm1(norms()); + TEST_FLOATING_EQUALITY(ST::magnitude(norms[0]), vector_sum, eps); + + // Left Scaling + linearProblem->leftScale(S); + + mag_type vector_sum_squared = ST::magnitude(N*(N+1)*(2*N+1)/6); + normF = ST::magnitude(std::sqrt(6*vector_sum_squared - N*N - 1)); + matrix_normF = ST::magnitude(linearProblem->getMatrix()->getFrobeniusNorm()); + TEST_FLOATING_EQUALITY(matrix_normF, normF, eps); + linearProblem->getLHS()->norm1(norms()); + TEST_FLOATING_EQUALITY(ST::magnitude(norms[0]), vector_sum, eps); + linearProblem->getRHS()->norm1(norms()); + TEST_FLOATING_EQUALITY(ST::magnitude(norms[0]), vector_sum_squared, eps); + +#ifdef DEBUG_TEST + if (myImageID==0) myOut << "After Left Scaling" << endl; + Display_CrsMatrix("A", A, comm, myOut); + Display_MultiVector("Solution Vector", X, comm, myOut); + Display_MultiVector("RHS Vector", B, comm, myOut); + Display_Vector("Scaling Vector", S, comm, myOut); +#endif + + // Right Scaling + linearProblem->rightScale(S); + + N = N-1; + mag_type off_diags = ST::magnitude(2.0*((N * (N + 1) * (2 * N + 1) * (3 * N * N + 3 * N - 1)) / 30.0 + + (N * N * (N + 1) * (N + 1)) / 2.0 + + (N * (N + 1) * (2 * N + 1)) / 6.0)); + N = N+1; + mag_type diag = ST::magnitude((2.0 * N * (N + 1) * (2 * N + 1) * (3 * N * N + 3 * N - 1)) / 15.0); + normF = ST::magnitude(std::sqrt(diag + off_diags)); + matrix_normF = ST::magnitude(linearProblem->getMatrix()->getFrobeniusNorm()); + TEST_FLOATING_EQUALITY(matrix_normF, normF, eps); + linearProblem->getLHS()->norm1(norms()); + TEST_FLOATING_EQUALITY(ST::magnitude(norms[0]), ST::magnitude(N), eps); + linearProblem->getRHS()->norm1(norms()); + TEST_FLOATING_EQUALITY(ST::magnitude(norms[0]), vector_sum_squared, eps); + +#ifdef DEBUG_TEST + if (myImageID==0) myOut << "After Right Scaling" << endl; + Display_CrsMatrix("A", A, comm, myOut); + Display_MultiVector("Solution Vector", X, comm, myOut); + Display_MultiVector("RHS Vector", B, comm, myOut); + Display_Vector("Scaling Vector", S, comm, myOut); +#endif + + // Constructor with matrix + { + RCP linearProblem_Matrix = rcp(new LPT(A,X,B)); + linearProblem_Matrix->checkInput(); + } + + } + +// +// INSTANTIATIONS +// + +#define UNIT_TEST_GROUP( SCALAR, LO, GO, NODE ) \ + TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( LinearProblem, basic, LO, GO, SCALAR, NODE ) + + TPETRA_ETI_MANGLING_TYPEDEFS() + + TPETRA_INSTANTIATE_SLGN( UNIT_TEST_GROUP ) + +}