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.
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()
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
Namespace for MueLu classes and methods.
@ Statistics1
Print more statistics.