MueLu  Version of the Day
MueLu_RfromP_Or_TransP_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_RFROMP_OR_TRANSP_DEF_HPP
47 #define MUELU_RFROMP_OR_TRANSP_DEF_HPP
48 
49 #include <Teuchos_ParameterList.hpp>
50 #include <Teuchos_Time.hpp>
51 
52 #include <Xpetra_Matrix.hpp>
53 
55 
57 
59 #include "MueLu_PFactory.hpp"
60 #include "MueLu_PgPFactory.hpp"
61 #include "MueLu_TogglePFactory.hpp"
62 #include "MueLu_Monitor.hpp"
63 #include "MueLu_PerfUtils.hpp"
64 #include "MueLu_Utilities.hpp"
65 
66 namespace MueLu {
67 
68  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
70  RCP<ParameterList> validParamList = rcp(new ParameterList());
71  validParamList->set< RCP<const FactoryBase> >("P", Teuchos::null, "Generating factory of the matrix P");
72  validParamList->set< RCP<const FactoryBase> >("RfromPfactory", Teuchos::null, "Generating factory of the matrix R");
73 
74  // Make sure we don't recursively validate options for the matrixmatrix kernels
75  ParameterList norecurse;
76  norecurse.disableRecursiveValidation();
77  validParamList->set<ParameterList> ("matrixmatrix: kernel params", norecurse, "MatrixMatrix kernel parameters");
78 
79  return validParamList;
80  }
81 
82  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
84  Input(coarseLevel, "RfromPfactory");
85 
86  // Using a PgPFactory in conjunction with a TogglePFactory is a bit problematic. Normally, PgPFactory is supposed to be
87  // invoked twice (once in standard mode and a second time in RestrictionMode). Unfortunately, TogglePFactory
88  // is not designed to produce R. A second issue is that TogglePFactory stores prolongators in an array,
89  // and there are some challenges in determining which array entry (i.e., factory) is needed when producing R.
90  // The way this is addressed is a bit clumsy. RfromP_Or_TransP invokes the prolongator factory to produce R.
91  // To do this, it must first check that this is needed (as opposed to just transposing P or using an already computed
92  // R that might be produced by SemiCoarsenPFactory). This check is needed in both DeclareInput() and in Build().
93  // The DeclareInput() check verifies that TogglePFactory was requested and that one of the prolongator factories
94  // within TogglePFactory is a PgPFactory. RfromP_Or_TransP's DeclareInput then invokes DeclareDependencies, and
95  // DeclareInput for the PgPFactory. The check within Build(), looks at "RfromPFactory" to see if it is an integer. This
96  // integer is used to find the prolongator factory that is invoked in RestrictionMode to produce R. Otherwise,
97  // "RfromPFactory" is used to get the pre-computed restriction matrix. If "RfromPFactory" is not present, then RfromP_Or_TransP
98  // just transposes P to get R.
99 
100  RCP<const FactoryBase> PFact = coarseLevel.GetFactoryManager()->GetFactory("P");
101  if (PFact == Teuchos::null) { PFact = GetFactory("P"); }
102  coarseLevel.DeclareInput("P", PFact.get(), this);
103  RCP<const MueLu::TogglePFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node> > myToggleFact = Teuchos::rcp_const_cast<const MueLu::TogglePFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(rcp_dynamic_cast<const MueLu::TogglePFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(PFact));
104  if (myToggleFact != Teuchos::null) {
105  for (size_t ii = 0; ii < myToggleFact->NumProlongatorFactories(); ii++) {
106  RCP<const MueLu::PgPFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node> > actualPFact = Teuchos::rcp_const_cast<const MueLu::PgPFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>>(rcp_dynamic_cast<const MueLu::PgPFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(myToggleFact->getProlongatorFactory(ii)));
107  if (actualPFact != Teuchos::null) {
108  RCP<PFactory> subFactory = Teuchos::rcp_const_cast<PFactory>(rcp_dynamic_cast<const PFactory>(myToggleFact->getProlongatorFactory(ii)));;
109  bool rmode = subFactory->isRestrictionModeSet();
110  subFactory->setRestrictionMode(true);
111  // Force request call for actualPFact
112  coarseLevel.DeclareDependencies(actualPFact.get());
113  coarseLevel.DeclareInput("R", actualPFact.get(), this);
114  subFactory->setRestrictionMode(rmode);
115  }
116  }
117  }
118  }
119 
120  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
122  FactoryMonitor m(*this, "Transpose P", coarseLevel);
123  std::string label = "MueLu::TransP-" + Teuchos::toString(coarseLevel.GetLevelID());
124 
125  const Teuchos::ParameterList& pL = GetParameterList();
126 
127  // Reuse pattern if available (multiple solve)
128  RCP<ParameterList> Tparams;
129  if(pL.isSublist("matrixmatrix: kernel params"))
130  Tparams=rcp(new ParameterList(pL.sublist("matrixmatrix: kernel params")));
131  else
132  Tparams= rcp(new ParameterList);
133 
134  // By default, we don't need global constants for transpose
135  Tparams->set("compute global constants: temporaries",Tparams->get("compute global constants: temporaries",false));
136  Tparams->set("compute global constants",Tparams->get("compute global constants",false));
137 
138  RCP<Matrix> R;
139  RCP<const FactoryBase> PFact = coarseLevel.GetFactoryManager()->GetFactory("P");
140  if (PFact == Teuchos::null) { PFact = GetFactory("P"); }
141 
142  RCP<Matrix> P = coarseLevel.Get< RCP<Matrix> >("P", PFact.get());
143 
144  if (coarseLevel.IsAvailable("RfromPfactory", PFact.get()))
145  {
146  std::string strType = coarseLevel.GetTypeName("RfromPfactory", PFact.get());
147  // Address case where a toggle factory is used in conjunction with a PgP factory. Here,
148  // we need to invoke the PgP factory a 2nd time to produce restriction. In this
149  // situation the PgP factory puts an int RfromPfactory on the level.
150  //
151  // See comments aboove in DeclareInput() method for more detailsd
152  if (strType == "int") {
153  RCP<const MueLu::TogglePFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node> > myToggleFact = Teuchos::rcp_const_cast<const MueLu::TogglePFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(rcp_dynamic_cast<const MueLu::TogglePFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(PFact));;
154  if (myToggleFact != Teuchos::null) {
155  MueLu::DisableMultipleCallCheck check(myToggleFact);
156  RCP<PFactory> actualPFact = Teuchos::rcp_const_cast<PFactory>(rcp_dynamic_cast<const PFactory>(myToggleFact->getProlongatorFactory((size_t) coarseLevel.Get<int>("RfromPfactory", PFact.get()))));
157  // toggle factory sets RfromPfactory to correct index into prolongatorFactory array
158  MueLu::DisableMultipleCallCheck check2(actualPFact);
159  bool rmode = actualPFact->isRestrictionModeSet();
160  actualPFact->setRestrictionMode(true);
161  R = coarseLevel.Get<RCP<Matrix> >("R",actualPFact.get());
162  actualPFact->setRestrictionMode(rmode);
163  }
164  else R = Utilities::Transpose(*P, true,label,Tparams);
165  }
166  else R = coarseLevel.Get< RCP<Matrix> >("RfromPfactory", PFact.get());
167  }
168  else
169  R = Utilities::Transpose(*P, true,label,Tparams);
170 
171  if (IsPrint(Statistics2)) {
172  RCP<ParameterList> params = rcp(new ParameterList());
173  params->set("printLoadBalancingInfo", true);
174  params->set("printCommInfo", true);
175  GetOStream(Statistics2) << PerfUtils::PrintMatrixInfo(*R, "R", params);
176  }
177 
178  Set(coarseLevel, "R", R);
179 
181  if (P->IsView("stridedMaps"))
182  R->CreateView("stridedMaps", P, true);
184 
185  }
186 
187 } //namespace MueLu
188 
189 #endif // MUELU_RFROMP_OR_TRANSP_DEF_HPP
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access). Usage: Level->Get< RCP<Matrix> >("A", factory) if factory == NULL => use default factory.
std::string toString(const T &what)
Little helper function to convert non-string types to strings.
void DeclareDependencies(const FactoryBase *factory, bool bRequestOnly=false, bool bReleaseOnly=false)
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput() to declare factory depe...
Timer to be used in factories. Similar to Monitor but with additional timers.
Namespace for MueLu classes and methods.
Print even more statistics.
int GetLevelID() const
Return level number.
Definition: MueLu_Level.cpp:76
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:99
std::string GetTypeName(const std::string &ename, const FactoryBase *factory=NoFactory::get())
GetTypeName returns type string of variable stored using ename and factory.
Prolongator factory which allows switching between two different prolongator strategies.
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Transpose(Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, bool optimizeTranspose=false, const std::string &label=std::string(), const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null)
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
An exception safe way to call the method TwoLevelFactoryBase::DisableMultipleCallCheck.
const RCP< const FactoryManagerBase > GetFactoryManager()
returns the current factory manager
Definition: MueLu_Level.cpp:96
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need&#39;s value has been saved.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
Factory that provides an interface for a concrete implementation of a prolongation operator...
Factory for building Petrov-Galerkin Smoothed Aggregation prolongators.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()