MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_TogglePFactory_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_TOGGLEPFACTORY_DEF_HPP
11#define MUELU_TOGGLEPFACTORY_DEF_HPP
12
13#include <Xpetra_Matrix.hpp>
14
16
17#include "MueLu_Level.hpp"
18#include "MueLu_MasterList.hpp"
19#include "MueLu_Monitor.hpp"
20
21namespace MueLu {
22
23template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
25 RCP<ParameterList> validParamList = rcp(new ParameterList());
26
27#define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
28 SET_VALID_ENTRY("toggle: mode");
29 SET_VALID_ENTRY("semicoarsen: number of levels");
30#undef SET_VALID_ENTRY
31
32 return validParamList;
33}
34
35template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
37 // request/release "P" and coarse level "Nullspace"
38 for (std::vector<RCP<const FactoryBase> >::const_iterator it = prolongatorFacts_.begin(); it != prolongatorFacts_.end(); ++it) {
39 coarseLevel.DeclareInput("P", (*it).get(), this); // request/release "P" (dependencies are not affected)
40 coarseLevel.DeclareInput("RfromPfactory", (*it).get(), this);
41 (*it)->CallDeclareInput(coarseLevel); // request dependencies
42 }
43 for (std::vector<RCP<const FactoryBase> >::const_iterator it = ptentFacts_.begin(); it != ptentFacts_.end(); ++it) {
44 coarseLevel.DeclareInput("P", (*it).get(), this); // request/release "Ptent" (dependencies are not affected)
45 (*it)->CallDeclareInput(coarseLevel); // request dependencies
46 }
47 for (std::vector<RCP<const FactoryBase> >::const_iterator it = nspFacts_.begin(); it != nspFacts_.end(); ++it) {
48 coarseLevel.DeclareInput("Nullspace", (*it).get(), this); // request/release coarse "Nullspace" (dependencies are not affected)
49 (*it)->CallDeclareInput(coarseLevel); // request dependencies
50 }
51
52 // The factory needs the information about the number of z-layers. While this information is
53 // provided by the user for the finest level, the factory itself is responsible to provide the
54 // corresponding information on the coarser levels. Since a factory cannot be dependent on itself
55 // we use the NoFactory class as generator class, but remove the UserData keep flag, such that
56 // "NumZLayers" is part of the request/release mechanism.
57 // Please note, that this prevents us from having several (independent) CoarsePFactory instances!
58 // TODO: allow factory to dependent on self-generated data for TwoLevelFactories -> introduce ExpertRequest/Release in Level
59 fineLevel.DeclareInput("NumZLayers", NoFactory::get(), this);
60 fineLevel.RemoveKeepFlag("NumZLayers", NoFactory::get(), MueLu::UserData);
61
62 hasDeclaredInput_ = true;
63}
64
65template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
67 FactoryMonitor m(*this, "Prolongator toggle", coarseLevel);
68 std::ostringstream levelstr;
69 levelstr << coarseLevel.GetLevelID();
70
71 TEUCHOS_TEST_FOR_EXCEPTION(nspFacts_.size() != prolongatorFacts_.size(), Exceptions::RuntimeError, "MueLu::TogglePFactory::Build: The number of provided prolongator factories and coarse nullspace factories must be identical.");
72 TEUCHOS_TEST_FOR_EXCEPTION(nspFacts_.size() != 2, Exceptions::RuntimeError, "MueLu::TogglePFactory::Build: TogglePFactory needs two different transfer operator strategies for toggling."); // TODO adapt this/weaken this as soon as other toggling strategies are introduced.
73
74 // decision routine which prolongator factory to be used
75 int nProlongatorFactory = 0; // default behavior: use first prolongator in list
76
77 // extract user parameters
78 const Teuchos::ParameterList& pL = GetParameterList();
79 std::string mode = Teuchos::as<std::string>(pL.get<std::string>("toggle: mode"));
80 int semicoarsen_levels = Teuchos::as<int>(pL.get<int>("semicoarsen: number of levels"));
81
82 TEUCHOS_TEST_FOR_EXCEPTION(mode != "semicoarsen", Exceptions::RuntimeError, "MueLu::TogglePFactory::Build: The 'toggle: mode' parameter must be set to 'semicoarsen'. No other mode supported, yet.");
83
84 LO NumZDir = -1;
85 if (fineLevel.IsAvailable("NumZLayers", NoFactory::get())) {
86 NumZDir = fineLevel.Get<LO>("NumZLayers", NoFactory::get()); // obtain info
87 GetOStream(Runtime1) << "Number of layers for semicoarsening: " << NumZDir << std::endl;
88 }
89
90 // Make a decision which prolongator to be used.
91 if (fineLevel.GetLevelID() >= semicoarsen_levels || NumZDir == 1) {
92 nProlongatorFactory = 1;
93 } else {
94 nProlongatorFactory = 0;
95 }
96
97 RCP<Matrix> P = Teuchos::null;
98 RCP<Matrix> Ptent = Teuchos::null;
99 RCP<MultiVector> coarseNullspace = Teuchos::null;
100
101 // call Build for selected transfer operator
102 GetOStream(Runtime0) << "TogglePFactory: call transfer factory: " << (prolongatorFacts_[nProlongatorFactory])->description() << std::endl;
103 prolongatorFacts_[nProlongatorFactory]->CallBuild(coarseLevel);
104 P = coarseLevel.Get<RCP<Matrix> >("P", (prolongatorFacts_[nProlongatorFactory]).get());
105 RCP<Matrix> R = Teuchos::null;
106 int Rplaceholder = -1; // Used to indicate that an R matrix has not been produced by a prolongator factory, but
107 // that it is capable of producing one and should be invoked a 2nd time in restrictor mode
108 // (e.g. with PgPFactory). prolongatorFacts_[Rplaceholder] is factory that can produce R
109 // matrix, which might be later invoked by MueLu_RfromP_Or_TransP
110 if (coarseLevel.IsAvailable("RfromPfactory", (prolongatorFacts_[nProlongatorFactory]).get())) {
111 std::string strType = coarseLevel.GetTypeName("RfromPfactory", (prolongatorFacts_[nProlongatorFactory]).get());
112 if (strType == "int")
113 Rplaceholder = nProlongatorFactory;
114 else
115 R = coarseLevel.Get<RCP<Matrix> >("RfromPfactory", (prolongatorFacts_[nProlongatorFactory]).get());
116 // Need to get R (and set it below) so that TogglePFactory is given credit for creating R
117 }
118 // do not call "Build" for "Ptent" factory since it should automatically be called recursively
119 // through the "Build" call for "P"
120 Ptent = coarseLevel.Get<RCP<Matrix> >("P", (ptentFacts_[nProlongatorFactory]).get());
121 coarseNullspace = coarseLevel.Get<RCP<MultiVector> >("Nullspace", (nspFacts_[nProlongatorFactory]).get());
122
123 // Release dependencies of all prolongator and coarse level null spaces
124 for (size_t t = 0; t < nspFacts_.size(); ++t) {
125 coarseLevel.Release(*(prolongatorFacts_[t]));
126 coarseLevel.Release(*(ptentFacts_[t]));
127 coarseLevel.Release(*(nspFacts_[t]));
128 }
129
130 // store prolongator with this factory identification.
131 Set(coarseLevel, "P", P);
132 // Three cases:
133 // 1) R already computed and TogglePFactory takes credit for constructing it
134 // 2) R not computed but prolongatorFacts_[Rplaceholder] can produce it
135 // 3) R not computed and prolongator can not produce it
136 if (R != Teuchos::null)
137 Set(coarseLevel, "RfromPfactory", R);
138 else if (Rplaceholder != -1)
139 Set(coarseLevel, "RfromPfactory", Teuchos::as<int>(Rplaceholder));
140 Set(coarseLevel, "Nullspace", coarseNullspace);
141 Set(coarseLevel, "Ptent", Ptent);
142 Set(coarseLevel, "Chosen P", nProlongatorFactory);
143} // Build()
144
145template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
147 // check if it's a TwoLevelFactoryBase based transfer factory
148 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<const TwoLevelFactoryBase>(factory) == Teuchos::null, Exceptions::BadCast,
149 "MueLu::TogglePFactory::AddProlongatorFactory: Transfer factory is not derived from TwoLevelFactoryBase. "
150 "This is very strange. (Note: you can remove this exception if there's a good reason for)");
151 TEUCHOS_TEST_FOR_EXCEPTION(hasDeclaredInput_, Exceptions::RuntimeError, "MueLu::TogglePFactory::AddProlongatorFactory: Factory is being added after we have already declared input");
152 prolongatorFacts_.push_back(factory);
153}
154
155template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
157 // check if it's a TwoLevelFactoryBase based transfer factory
158 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<const TwoLevelFactoryBase>(factory) == Teuchos::null, Exceptions::BadCast,
159 "MueLu::TogglePFactory::AddPtentFactory: Transfer factory is not derived from TwoLevelFactoryBase. "
160 "This is very strange. (Note: you can remove this exception if there's a good reason for)");
161 TEUCHOS_TEST_FOR_EXCEPTION(hasDeclaredInput_, Exceptions::RuntimeError, "MueLu::TogglePFactory::AddPtentFactory: Factory is being added after we have already declared input");
162 ptentFacts_.push_back(factory);
163}
164
165template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
167 // check if it's a TwoLevelFactoryBase based transfer factory
168 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<const TwoLevelFactoryBase>(factory) == Teuchos::null, Exceptions::BadCast,
169 "MueLu::TogglePFactory::AddCoarseNullspaceFactory: Transfer factory is not derived from TwoLevelFactoryBase. Make sure you provide the factory which generates the coarse level nullspace information. Usually this is a prolongator factory."
170 "This is very strange. (Note: you can remove this exception if there's a good reason for)");
171 TEUCHOS_TEST_FOR_EXCEPTION(hasDeclaredInput_, Exceptions::RuntimeError, "MueLu::TogglePFactory::AddCoarseNullspaceFactory: Factory is being added after we have already declared input");
172 nspFacts_.push_back(factory);
173}
174
175} // namespace MueLu
176
177#endif // MUELU_TOGGLEPFACTORY_DEF_HPP
#define SET_VALID_ENTRY(name)
Exception indicating invalid cast attempted.
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.
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()
void Release(const FactoryBase &factory)
Decrement the storage counter for all the inputs of a factory.
void RemoveKeepFlag(const std::string &ename, const FactoryBase *factory, KeepType keep=MueLu::All)
int GetLevelID() const
Return level number.
std::string GetTypeName(const std::string &ename, const FactoryBase *factory=NoFactory::get())
GetTypeName returns type string of variable stored using ename and factory.
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()
void AddCoarseNullspaceFactory(const RCP< const FactoryBase > &factory)
Add a coarse nullspace factory in the end of list of coarse nullspace factories.
void AddProlongatorFactory(const RCP< const FactoryBase > &factory)
Add a prolongator factory in the end of list of prolongator factories.
void AddPtentFactory(const RCP< const FactoryBase > &factory)
Add a tentative prolongator factory in the end of list of prolongator factories.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
void Build(Level &fineLevel, Level &coarseLevel) const
Build method.
Namespace for MueLu classes and methods.
@ UserData
User data are always kept. This flag is set automatically when Level::Set("data", data) is used....
@ Runtime0
One-liner description of what is happening.
@ Runtime1
Description of what is happening (more verbose)