MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_StructuredAggregationFactory_kokkos_def.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// MueLu: A package for multigrid based preconditioning
4//
5// Copyright 2012 NTESS and the MueLu contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef MUELU_STRUCTUREDAGGREGATIONFACTORY_KOKKOS_DEF_HPP
11#define MUELU_STRUCTUREDAGGREGATIONFACTORY_KOKKOS_DEF_HPP
12
13// Xpetra includes
14#include <Xpetra_Map.hpp>
15#include <Xpetra_CrsGraph.hpp>
16
17// MueLu generic includes
18#include "MueLu_Level.hpp"
19#include "MueLu_MasterList.hpp"
20#include "MueLu_Monitor.hpp"
21
22// MueLu specific includes (kokkos version)
23#include "MueLu_LWGraph_kokkos.hpp"
24#include "MueLu_Aggregates.hpp"
25#include "MueLu_IndexManager_kokkos.hpp"
26#include "MueLu_AggregationStructuredAlgorithm.hpp"
27
29
30namespace MueLu {
31
32template <class LocalOrdinal, class GlobalOrdinal, class Node>
36
37template <class LocalOrdinal, class GlobalOrdinal, class Node>
40 RCP<ParameterList> validParamList = rcp(new ParameterList());
41
42#define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
43 SET_VALID_ENTRY("aggregation: preserve Dirichlet points");
44 SET_VALID_ENTRY("aggregation: allow user-specified singletons");
45 SET_VALID_ENTRY("aggregation: error on nodes with no on-rank neighbors");
46 SET_VALID_ENTRY("aggregation: phase3 avoid singletons");
47#undef SET_VALID_ENTRY
48
49 // general variables needed in StructuredAggregationFactory
50 validParamList->set<std::string>("aggregation: output type", "Aggregates",
51 "Type of object holding the aggregation data: Aggregtes or CrsGraph");
52 validParamList->set<std::string>("aggregation: coarsening rate", "{3}",
53 "Coarsening rate per spatial dimensions");
54 validParamList->set<int>("aggregation: coarsening order", 0,
55 "The interpolation order used to construct grid transfer operators based off these aggregates.");
56 validParamList->set<RCP<const FactoryBase> >("Graph", Teuchos::null,
57 "Graph of the matrix after amalgamation but without dropping.");
58 validParamList->set<RCP<const FactoryBase> >("DofsPerNode", Teuchos::null,
59 "Number of degrees of freedom per mesh node, provided by the coalsce drop factory.");
60 validParamList->set<RCP<const FactoryBase> >("numDimensions", Teuchos::null,
61 "Number of spatial dimension provided by CoordinatesTransferFactory.");
62 validParamList->set<RCP<const FactoryBase> >("lNodesPerDim", Teuchos::null,
63 "Number of nodes per spatial dimmension provided by CoordinatesTransferFactory.");
64
65 return validParamList;
66} // GetValidParameterList()
67
68template <class LocalOrdinal, class GlobalOrdinal, class Node>
70 DeclareInput(Level& currentLevel) const {
71 Input(currentLevel, "Graph");
72 Input(currentLevel, "DofsPerNode");
73
74 // Request the local number of nodes per dimensions
75 if (currentLevel.GetLevelID() == 0) {
76 if (currentLevel.IsAvailable("numDimensions", NoFactory::get())) {
77 currentLevel.DeclareInput("numDimensions", NoFactory::get(), this);
78 } else {
79 TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("numDimensions", NoFactory::get()),
81 "numDimensions was not provided by the user on level0!");
82 }
83 if (currentLevel.IsAvailable("lNodesPerDim", NoFactory::get())) {
84 currentLevel.DeclareInput("lNodesPerDim", NoFactory::get(), this);
85 } else {
86 TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("lNodesPerDim", NoFactory::get()),
88 "lNodesPerDim was not provided by the user on level0!");
89 }
90 } else {
91 Input(currentLevel, "lNodesPerDim");
92 Input(currentLevel, "numDimensions");
93 }
94} // DeclareInput()
95
96template <class LocalOrdinal, class GlobalOrdinal, class Node>
98 Build(Level& currentLevel) const {
99 FactoryMonitor m(*this, "Build", currentLevel);
100
101 RCP<Teuchos::FancyOStream> out;
102 if (const char* dbg = std::getenv("MUELU_STRUCTUREDAGGREGATION_DEBUG")) {
103 out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
104 out->setShowAllFrontMatter(false).setShowProcRank(true);
105 } else {
106 out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
107 }
108
109 using device_type = typename LWGraph_kokkos::local_graph_type::device_type;
110 using execution_space = typename LWGraph_kokkos::local_graph_type::device_type::execution_space;
111 using memory_space = typename LWGraph_kokkos::local_graph_type::device_type::memory_space;
112
113 *out << "Entering structured aggregation" << std::endl;
114
115 ParameterList pL = GetParameterList();
116 bDefinitionPhase_ = false; // definition phase is finished, now all aggregation algorithm information is fixed
117
118 // General problem informations are gathered from data stored in the problem matix.
119 RCP<const LWGraph_kokkos> graph = Get<RCP<LWGraph_kokkos> >(currentLevel, "Graph");
120 RCP<const Map> fineMap = graph->GetDomainMap();
121 const int myRank = fineMap->getComm()->getRank();
122 const LO dofsPerNode = Get<LO>(currentLevel, "DofsPerNode");
123
124 // Since we want to operate on nodes and not dof, we need to modify the rowMap in order to
125 // obtain a nodeMap.
126 const int interpolationOrder = pL.get<int>("aggregation: coarsening order");
127 std::string outputType = pL.get<std::string>("aggregation: output type");
128 const bool outputAggregates = (outputType == "Aggregates" ? true : false);
129 Array<LO> lFineNodesPerDir(3);
130 int numDimensions;
131 if (currentLevel.GetLevelID() == 0) {
132 // On level 0, data is provided by applications and has no associated factory.
133 lFineNodesPerDir = currentLevel.Get<Array<LO> >("lNodesPerDim", NoFactory::get());
134 numDimensions = currentLevel.Get<int>("numDimensions", NoFactory::get());
135 } else {
136 // On level > 0, data is provided directly by generating factories.
137 lFineNodesPerDir = Get<Array<LO> >(currentLevel, "lNodesPerDim");
138 numDimensions = Get<int>(currentLevel, "numDimensions");
139 }
140
141 // First make sure that input parameters are set logically based on dimension
142 for (int dim = 0; dim < 3; ++dim) {
143 if (dim >= numDimensions) {
144 lFineNodesPerDir[dim] = 1;
145 }
146 }
147
148 // Get the coarsening rate
149 std::string coarseningRate = pL.get<std::string>("aggregation: coarsening rate");
150 Teuchos::Array<LO> coarseRate;
151 try {
152 coarseRate = Teuchos::fromStringToArray<LO>(coarseningRate);
153 } catch (const Teuchos::InvalidArrayStringRepresentation& e) {
154 GetOStream(Errors, -1) << " *** \"aggregation: coarsening rate\" must be a string convertible into an array! *** "
155 << std::endl;
156 throw e;
157 }
158 TEUCHOS_TEST_FOR_EXCEPTION((coarseRate.size() > 1) && (coarseRate.size() < numDimensions),
160 "\"aggregation: coarsening rate\" must have at least as many"
161 " components as the number of spatial dimensions in the problem.");
162
163 // Now that we have extracted info from the level, create the IndexManager
164 RCP<IndexManager_kokkos> geoData = rcp(new IndexManager_kokkos(numDimensions,
165 interpolationOrder, myRank,
166 lFineNodesPerDir,
167 coarseRate));
168
169 *out << "The index manager has now been built" << std::endl;
170 TEUCHOS_TEST_FOR_EXCEPTION(fineMap->getLocalNumElements() != static_cast<size_t>(geoData->getNumLocalFineNodes()),
172 "The local number of elements in the graph's map is not equal to "
173 "the number of nodes given by: lNodesPerDim!");
174
175 // Now we are ready for the big loop over the fine node that will assign each
176 // node on the fine grid to an aggregate and a processor.
177 RCP<AggregationStructuredAlgorithm> myStructuredAlgorithm = rcp(new AggregationStructuredAlgorithm());
178
179 if (interpolationOrder == 0 && outputAggregates) {
180 RCP<Aggregates> aggregates = rcp(new Aggregates(graph->GetDomainMap()));
181 aggregates->setObjectLabel("ST");
182 aggregates->SetIndexManagerKokkos(geoData);
183 aggregates->AggregatesCrossProcessors(false);
184 aggregates->SetNumAggregates(geoData->getNumCoarseNodes());
185
186 LO numNonAggregatedNodes = geoData->getNumLocalFineNodes();
187 Kokkos::View<unsigned*, device_type> aggStat("aggStat", numNonAggregatedNodes);
188 Kokkos::parallel_for(
189 "StructuredAggregation: initialize aggStat",
190 Kokkos::RangePolicy<execution_space>(0, numNonAggregatedNodes),
191 KOKKOS_LAMBDA(const LO nodeIdx) { aggStat(nodeIdx) = READY; });
192
193 myStructuredAlgorithm->BuildAggregates(pL, *graph, *aggregates, aggStat,
194 numNonAggregatedNodes);
195
196 *out << "numNonAggregatedNodes: " << numNonAggregatedNodes << std::endl;
197
198 TEUCHOS_TEST_FOR_EXCEPTION(numNonAggregatedNodes, Exceptions::RuntimeError,
199 "MueLu::StructuredAggregationFactory::Build: Leftover nodes found! Error!");
200 aggregates->ComputeAggregateSizes(true /*forceRecompute*/);
201 GetOStream(Statistics1) << aggregates->description() << std::endl;
202 Set(currentLevel, "Aggregates", aggregates);
203
204 } else {
205 // Create Coarse Data
206 RCP<CrsGraph> myGraph;
207 myStructuredAlgorithm->BuildGraph(*graph, geoData, dofsPerNode, myGraph);
208 Set(currentLevel, "prolongatorGraph", myGraph);
209 }
210
211 Set(currentLevel, "lCoarseNodesPerDim", geoData->getCoarseNodesPerDirArray());
212 Set(currentLevel, "indexManager", geoData);
213 Set(currentLevel, "structuredInterpolationOrder", interpolationOrder);
214 Set(currentLevel, "numDimensions", numDimensions);
215
216} // Build()
217
218} // namespace MueLu
219
220#endif /* MUELU_STRUCTUREDAGGREGATIONFACTORY_KOKKOS_DEF_HPP */
#define SET_VALID_ENTRY(name)
Container class for aggregation information.
Algorithm for coarsening a graph with structured aggregation.
Exception throws to report errors in the internal logical of the program.
void Input(Level &level, const std::string &varName) const
T Get(Level &level, const std::string &varName) const
void Set(Level &level, const std::string &varName, const T &data) const
Timer to be used in factories. Similar to Monitor but with additional timers.
Container class for mesh layout and indices calculation.
Class that holds all level-specific information.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput().
int GetLevelID() const
Return level number.
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
static const NoFactory * get()
virtual const Teuchos::ParameterList & GetParameterList() const
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
Namespace for MueLu classes and methods.
@ Statistics1
Print more statistics.