MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_UncoupledAggregationFactory_def.hpp
Go to the documentation of this file.
1// @HEADER
2//
3// ***********************************************************************
4//
5// MueLu: A package for multigrid based preconditioning
6// Copyright 2012 Sandia Corporation
7//
8// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9// the U.S. Government retains certain rights in this software.
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17//
18// 2. Redistributions in binary form must reproduce the above copyright
19// notice, this list of conditions and the following disclaimer in the
20// documentation and/or other materials provided with the distribution.
21//
22// 3. Neither the name of the Corporation nor the names of the
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Questions? Contact
39// Jonathan Hu (jhu@sandia.gov)
40// Andrey Prokopenko (aprokop@sandia.gov)
41// Ray Tuminaro (rstumin@sandia.gov)
42//
43// ***********************************************************************
44//
45// @HEADER
46#ifndef MUELU_UNCOUPLEDAGGREGATIONFACTORY_DEF_HPP_
47#define MUELU_UNCOUPLEDAGGREGATIONFACTORY_DEF_HPP_
48
49#include <climits>
50
51#include <Xpetra_Map.hpp>
52#include <Xpetra_Vector.hpp>
53#include <Xpetra_MultiVectorFactory.hpp>
54#include <Xpetra_VectorFactory.hpp>
55
57
58#include "MueLu_InterfaceAggregationAlgorithm.hpp"
59#include "MueLu_OnePtAggregationAlgorithm.hpp"
60#include "MueLu_PreserveDirichletAggregationAlgorithm.hpp"
61
62#include "MueLu_AggregationPhase1Algorithm.hpp"
63#include "MueLu_AggregationPhase2aAlgorithm.hpp"
64#include "MueLu_AggregationPhase2bAlgorithm.hpp"
65#include "MueLu_AggregationPhase3Algorithm.hpp"
66
67#include "MueLu_Level.hpp"
68#include "MueLu_GraphBase.hpp"
69#include "MueLu_Aggregates.hpp"
70#include "MueLu_MasterList.hpp"
71#include "MueLu_Monitor.hpp"
72
73namespace MueLu {
74
75 template <class LocalOrdinal, class GlobalOrdinal, class Node>
79
80 template <class LocalOrdinal, class GlobalOrdinal, class Node>
82 RCP<ParameterList> validParamList = rcp(new ParameterList());
83
84 // Aggregation parameters (used in aggregation algorithms)
85 // TODO introduce local member function for each aggregation algorithm such that each aggregation algorithm can define its own parameters
86
87 typedef Teuchos::StringToIntegralParameterEntryValidator<int> validatorType;
88#define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
89 SET_VALID_ENTRY("aggregation: max agg size");
90 SET_VALID_ENTRY("aggregation: min agg size");
91 SET_VALID_ENTRY("aggregation: max selected neighbors");
92 SET_VALID_ENTRY("aggregation: ordering");
93 validParamList->getEntry("aggregation: ordering").setValidator(
94 rcp(new validatorType(Teuchos::tuple<std::string>("natural", "graph", "random"), "aggregation: ordering")));
95 SET_VALID_ENTRY("aggregation: enable phase 1");
96 SET_VALID_ENTRY("aggregation: enable phase 2a");
97 SET_VALID_ENTRY("aggregation: enable phase 2b");
98 SET_VALID_ENTRY("aggregation: enable phase 3");
99 SET_VALID_ENTRY("aggregation: match ML phase2a");
100 SET_VALID_ENTRY("aggregation: phase2a agg factor");
101 SET_VALID_ENTRY("aggregation: preserve Dirichlet points");
102 SET_VALID_ENTRY("aggregation: allow user-specified singletons");
103 SET_VALID_ENTRY("aggregation: use interface aggregation");
104 SET_VALID_ENTRY("aggregation: error on nodes with no on-rank neighbors");
105 SET_VALID_ENTRY("aggregation: phase3 avoid singletons");
106 SET_VALID_ENTRY("aggregation: compute aggregate qualities");
107 SET_VALID_ENTRY("aggregation: phase 1 algorithm");
108#undef SET_VALID_ENTRY
109
110 // general variables needed in AggregationFactory
111 validParamList->set< RCP<const FactoryBase> >("Graph", null, "Generating factory of the graph");
112 validParamList->set< RCP<const FactoryBase> >("DofsPerNode", null, "Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
113 validParamList->set< RCP<const FactoryBase> >("AggregateQualities", null, "Generating factory for variable \'AggregateQualities\'");
114
115 // special variables necessary for OnePtAggregationAlgorithm
116 validParamList->set< std::string > ("OnePt aggregate map name", "", "Name of input map for single node aggregates. (default='')");
117 validParamList->set< std::string > ("OnePt aggregate map factory", "", "Generating factory of (DOF) map for single node aggregates.");
118 //validParamList->set< RCP<const FactoryBase> >("OnePt aggregate map factory", NoFactory::getRCP(), "Generating factory of (DOF) map for single node aggregates.");
119
120 // InterfaceAggregation parameters
121 //validParamList->set< bool > ("aggregation: use interface aggregation", "false", "Flag to trigger aggregation along an interface using specified aggregate seeds.");
122 validParamList->set< std::string > ("Interface aggregate map name", "", "Name of input map for interface aggregates. (default='')");
123 validParamList->set< std::string > ("Interface aggregate map factory", "", "Generating factory of (DOF) map for interface aggregates.");
124 validParamList->set<RCP<const FactoryBase> > ("nodeOnInterface", Teuchos::null, "Array specifying whether or not a node is on the interface (1 or 0).");
125
126 return validParamList;
127 }
128
129 template <class LocalOrdinal, class GlobalOrdinal, class Node>
131 Input(currentLevel, "Graph");
132 Input(currentLevel, "DofsPerNode");
133
134 const ParameterList& pL = GetParameterList();
135
136 // request special data necessary for OnePtAggregationAlgorithm
137 std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
138 if (mapOnePtName.length() > 0) {
139 std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
140 if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
141 currentLevel.DeclareInput(mapOnePtName, NoFactory::get());
142 } else {
143 RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
144 currentLevel.DeclareInput(mapOnePtName, mapOnePtFact.get());
145 }
146 }
147
148 // request special data necessary for InterfaceAggregation
149 if (pL.get<bool>("aggregation: use interface aggregation") == true){
150 if(currentLevel.GetLevelID() == 0) {
151 if(currentLevel.IsAvailable("nodeOnInterface", NoFactory::get())) {
152 currentLevel.DeclareInput("nodeOnInterface", NoFactory::get(), this);
153 } else {
154 TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("nodeOnInterface", NoFactory::get()),
156 "nodeOnInterface was not provided by the user on level0!");
157 }
158 } else {
159 Input(currentLevel, "nodeOnInterface");
160 }
161 }
162
163 if (pL.get<bool>("aggregation: compute aggregate qualities")) {
164 Input(currentLevel, "AggregateQualities");
165 }
166 }
167
168 template <class LocalOrdinal, class GlobalOrdinal, class Node>
170 FactoryMonitor m(*this, "Build", currentLevel);
171
172 ParameterList pL = GetParameterList();
173 bDefinitionPhase_ = false; // definition phase is finished, now all aggregation algorithm information is fixed
174
175 if (pL.get<int>("aggregation: max agg size") == -1)
176 pL.set("aggregation: max agg size", INT_MAX);
177
178 // define aggregation algorithms
179 RCP<const FactoryBase> graphFact = GetFactory("Graph");
180
181 // TODO Can we keep different aggregation algorithms over more Build calls?
182 algos_.clear();
183 algos_.push_back(rcp(new PreserveDirichletAggregationAlgorithm(graphFact)));
184 if (pL.get<bool>("aggregation: use interface aggregation") == true) algos_.push_back(rcp(new InterfaceAggregationAlgorithm (graphFact)));
185 if (pL.get<bool>("aggregation: allow user-specified singletons") == true) algos_.push_back(rcp(new OnePtAggregationAlgorithm (graphFact)));
186 if (pL.get<bool>("aggregation: enable phase 1" ) == true) algos_.push_back(rcp(new AggregationPhase1Algorithm (graphFact)));
187 if (pL.get<bool>("aggregation: enable phase 2a") == true) algos_.push_back(rcp(new AggregationPhase2aAlgorithm (graphFact)));
188 if (pL.get<bool>("aggregation: enable phase 2b") == true) algos_.push_back(rcp(new AggregationPhase2bAlgorithm (graphFact)));
189 if (pL.get<bool>("aggregation: enable phase 3" ) == true) algos_.push_back(rcp(new AggregationPhase3Algorithm (graphFact)));
190
191 // TODO: remove old aggregation mode
192 //if (pL.get<bool>("UseOnePtAggregationAlgorithm") == true) algos_.push_back(rcp(new OnePtAggregationAlgorithm (graphFact)));
193 //if (pL.get<bool>("UseUncoupledAggregationAlgorithm") == true) algos_.push_back(rcp(new AggregationPhase1Algorithm (graphFact)));
194 //if (pL.get<bool>("UseMaxLinkAggregationAlgorithm") == true) algos_.push_back(rcp(new MaxLinkAggregationAlgorithm (graphFact)));
195 //if (pL.get<bool>("UseEmergencyAggregationAlgorithm") == true) algos_.push_back(rcp(new EmergencyAggregationAlgorithm (graphFact)));
196
197 std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
198 RCP<Map> OnePtMap = Teuchos::null;
199 if (mapOnePtName.length()) {
200 std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
201 if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
202 OnePtMap = currentLevel.Get<RCP<Map> >(mapOnePtName, NoFactory::get());
203 } else {
204 RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
205 OnePtMap = currentLevel.Get<RCP<Map> >(mapOnePtName, mapOnePtFact.get());
206 }
207 }
208
209 // Set map for interface aggregates
210 std::string mapInterfaceName = pL.get<std::string>("Interface aggregate map name");
211 RCP<Map> InterfaceMap = Teuchos::null;
212
213 RCP<const GraphBase> graph = Get< RCP<GraphBase> >(currentLevel, "Graph");
214
215 // Build
216 RCP<Aggregates> aggregates = rcp(new Aggregates(*graph));
217 aggregates->setObjectLabel("UC");
218
219 const LO numRows = graph->GetNodeNumVertices();
220
221 // construct aggStat information
222 std::vector<unsigned> aggStat(numRows, READY);
223
224 // interface
225 if (pL.get<bool>("aggregation: use interface aggregation") == true){
226 Teuchos::Array<LO> nodeOnInterface = Get<Array<LO>>(currentLevel,"nodeOnInterface");
227 for (LO i = 0; i < numRows; i++) {
228 if (nodeOnInterface[i])
229 aggStat[i] = INTERFACE;
230 }
231 }
232
233 ArrayRCP<const bool> dirichletBoundaryMap = graph->GetBoundaryNodeMap();
234 if (dirichletBoundaryMap != Teuchos::null)
235 for (LO i = 0; i < numRows; i++)
236 if (dirichletBoundaryMap[i] == true)
237 aggStat[i] = BOUNDARY;
238
239 LO nDofsPerNode = Get<LO>(currentLevel, "DofsPerNode");
240 GO indexBase = graph->GetDomainMap()->getIndexBase();
241 if (OnePtMap != Teuchos::null) {
242 for (LO i = 0; i < numRows; i++) {
243 // reconstruct global row id (FIXME only works for contiguous maps)
244 GO grid = (graph->GetDomainMap()->getGlobalElement(i)-indexBase) * nDofsPerNode + indexBase;
245
246 for (LO kr = 0; kr < nDofsPerNode; kr++)
247 if (OnePtMap->isNodeGlobalElement(grid + kr))
248 aggStat[i] = ONEPT;
249 }
250 }
251
252
253
254 const RCP<const Teuchos::Comm<int> > comm = graph->GetComm();
255 GO numGlobalRows = 0;
256 if (IsPrint(Statistics1))
257 MueLu_sumAll(comm, as<GO>(numRows), numGlobalRows);
258
259 LO numNonAggregatedNodes = numRows;
260 GO numGlobalAggregatedPrev = 0, numGlobalAggsPrev = 0;
261 for (size_t a = 0; a < algos_.size(); a++) {
262 std::string phase = algos_[a]->description();
263 SubFactoryMonitor sfm(*this, "Algo " + phase, currentLevel);
264
265 int oldRank = algos_[a]->SetProcRankVerbose(this->GetProcRankVerbose());
266 algos_[a]->BuildAggregates(pL, *graph, *aggregates, aggStat, numNonAggregatedNodes);
267 algos_[a]->SetProcRankVerbose(oldRank);
268
269 if (IsPrint(Statistics1)) {
270 GO numLocalAggregated = numRows - numNonAggregatedNodes, numGlobalAggregated = 0;
271 GO numLocalAggs = aggregates->GetNumAggregates(), numGlobalAggs = 0;
272 MueLu_sumAll(comm, numLocalAggregated, numGlobalAggregated);
273 MueLu_sumAll(comm, numLocalAggs, numGlobalAggs);
274
275 double aggPercent = 100*as<double>(numGlobalAggregated)/as<double>(numGlobalRows);
276 if (aggPercent > 99.99 && aggPercent < 100.00) {
277 // Due to round off (for instance, for 140465733/140466897), we could
278 // get 100.00% display even if there are some remaining nodes. This
279 // is bad from the users point of view. It is much better to change
280 // it to display 99.99%.
281 aggPercent = 99.99;
282 }
283 GetOStream(Statistics1) << " aggregated : " << (numGlobalAggregated - numGlobalAggregatedPrev) << " (phase), " << std::fixed
284 << std::setprecision(2) << numGlobalAggregated << "/" << numGlobalRows << " [" << aggPercent << "%] (total)\n"
285 << " remaining : " << numGlobalRows - numGlobalAggregated << "\n"
286 << " aggregates : " << numGlobalAggs-numGlobalAggsPrev << " (phase), " << numGlobalAggs << " (total)" << std::endl;
287 numGlobalAggregatedPrev = numGlobalAggregated;
288 numGlobalAggsPrev = numGlobalAggs;
289 }
290 }
291
292 TEUCHOS_TEST_FOR_EXCEPTION(numNonAggregatedNodes, Exceptions::RuntimeError, "MueLu::UncoupledAggregationFactory::Build: Leftover nodes found! Error!");
293
294 aggregates->AggregatesCrossProcessors(false);
295 aggregates->ComputeAggregateSizes(true/*forceRecompute*/);
296
297 Set(currentLevel, "Aggregates", aggregates);
298
299 if (pL.get<bool>("aggregation: compute aggregate qualities")) {
300 RCP<Xpetra::MultiVector<DefaultScalar,LO,GO,Node>> aggQualities = Get<RCP<Xpetra::MultiVector<DefaultScalar,LO,GO,Node>>>(currentLevel, "AggregateQualities");
301 }
302
303 }
304
305} //namespace MueLu
306
307
308#endif /* MUELU_UNCOUPLEDAGGREGATIONFACTORY_DEF_HPP_ */
#define SET_VALID_ENTRY(name)
#define MueLu_sumAll(rcpComm, in, out)
Container class for aggregation information.
Algorithm for coarsening a graph with uncoupled aggregation.
Among unaggregated points, see if we can make a reasonable size aggregate out of it.
Handle leftover nodes. Try to avoid singleton nodes.
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.
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
const RCP< const FactoryBase > GetFactory(const std::string &varName) const
Default implementation of FactoryAcceptor::GetFactory().
Algorithm for coarsening a graph with uncoupled aggregation. creates aggregates along an interface us...
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()
Algorithm for coarsening a graph with uncoupled aggregation. keep special marked nodes as singleton n...
virtual const Teuchos::ParameterList & GetParameterList() const
Builds one-to-one aggregates for all Dirichlet boundary nodes. For some applications this might be ne...
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
void Build(Level &currentLevel) const
Build aggregates.
std::vector< RCP< MueLu::AggregationAlgorithmBase< LocalOrdinal, GlobalOrdinal, Node > > > algos_
Append a new aggregation algorithm to list of aggregation algorithms.
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
bool IsPrint(MsgType type, int thisProcRankOnly=-1) const
Find out whether we need to print out information for a specific message type.
int GetProcRankVerbose() const
Get proc rank used for printing. Do not use this information for any other purpose....
Namespace for MueLu classes and methods.
@ Statistics1
Print more statistics.