MueLu  Version of the Day
MueLu_NullspaceFactory_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_NULLSPACEFACTORY_DEF_HPP
47 #define MUELU_NULLSPACEFACTORY_DEF_HPP
48 
49 #include <Xpetra_Matrix.hpp>
50 #include <Xpetra_MultiVectorFactory.hpp>
51 #include <Xpetra_BlockedMultiVector.hpp>
52 #include <Xpetra_VectorFactory.hpp>
53 
55 #include "MueLu_Level.hpp"
56 #include "MueLu_Monitor.hpp"
57 
58 namespace MueLu {
59 
60  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
62  RCP<ParameterList> validParamList = rcp(new ParameterList());
63 
64  validParamList->set< std::string >("Fine level nullspace", "Nullspace", "Variable name which is used to store null space multi vector on the finest level (default=\"Nullspace\"). For block matrices also \"Nullspace1\" to \"Nullspace9\" are accepted to describe the null space vectors for the (i,i) block (i=1..9).");
65 
66  validParamList->set< RCP<const FactoryBase> >("A", Teuchos::null, "Generating factory of the fine level matrix (only needed if default null space is generated)");
67  validParamList->set< RCP<const FactoryBase> >("Nullspace", Teuchos::null, "Generating factory of the fine level null space");
68 
69  // TODO not very elegant.
70  // 1/20/2016: we could add a sublist (e.g. "Nullspaces" which is excluded from parameter validation)
71  validParamList->set< RCP<const FactoryBase> >("Nullspace1", Teuchos::null, "Generating factory of the fine level null space associated with the (1,1) block in your n x n block matrix.");
72  validParamList->set< RCP<const FactoryBase> >("Nullspace2", Teuchos::null, "Generating factory of the fine level null space associated with the (2,2) block in your n x n block matrix.");
73  validParamList->set< RCP<const FactoryBase> >("Nullspace3", Teuchos::null, "Generating factory of the fine level null space associated with the (3,3) block in your n x n block matrix.");
74  validParamList->set< RCP<const FactoryBase> >("Nullspace4", Teuchos::null, "Generating factory of the fine level null space associated with the (4,4) block in your n x n block matrix.");
75  validParamList->set< RCP<const FactoryBase> >("Nullspace5", Teuchos::null, "Generating factory of the fine level null space associated with the (5,5) block in your n x n block matrix.");
76  validParamList->set< RCP<const FactoryBase> >("Nullspace6", Teuchos::null, "Generating factory of the fine level null space associated with the (6,6) block in your n x n block matrix.");
77  validParamList->set< RCP<const FactoryBase> >("Nullspace7", Teuchos::null, "Generating factory of the fine level null space associated with the (7,7) block in your n x n block matrix.");
78  validParamList->set< RCP<const FactoryBase> >("Nullspace8", Teuchos::null, "Generating factory of the fine level null space associated with the (8,8) block in your n x n block matrix.");
79  validParamList->set< RCP<const FactoryBase> >("Nullspace9", Teuchos::null, "Generating factory of the fine level null space associated with the (9,9) block in your n x n block matrix.");
80 
81  return validParamList;
82  }
83 
84  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
86 
87  const ParameterList & pL = GetParameterList();
88  std::string nspName = pL.get<std::string>("Fine level nullspace");
89 
90  // only request "A" in DeclareInput if
91  // 1) there is not nspName (e.g. "Nullspace") is available in Level, AND
92  // 2) it is the finest level (i.e. LevelID == 0)
93  if (currentLevel.IsAvailable(nspName, NoFactory::get()) == false && currentLevel.GetLevelID() == 0)
94  Input(currentLevel, "A");
95 
96  if (currentLevel.GetLevelID() != 0) {
97  // validate nullspaceFact_
98  // 1) The factory for "Nullspace" (or nspName) must not be Teuchos::null, since the default factory
99  // for "Nullspace" is a NullspaceFactory
100  // 2) The factory for "Nullspace" (or nspName) must be a TentativePFactory or any other TwoLevelFactoryBase derived object
101  // which generates the variable "Nullspace" as output
102  TEUCHOS_TEST_FOR_EXCEPTION(GetFactory(nspName)==Teuchos::null, Exceptions::RuntimeError, "MueLu::NullspaceFactory::DeclareInput(): You must declare an existing factory which produces the variable \"Nullspace\" in the NullspaceFactory (e.g. a TentativePFactory).");
103  currentLevel.DeclareInput("Nullspace", GetFactory(nspName).get(), this); /* ! "Nullspace" and nspName mismatch possible here */
104  }
105  }
106 
107  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
109  FactoryMonitor m(*this, "Nullspace factory", currentLevel);
110 
111  RCP<MultiVector> nullspace;
112 
113  //TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.GetLevelID() != 0, Exceptions::RuntimeError, "MueLu::NullspaceFactory::Build(): NullspaceFactory can be used for finest level (LevelID == 0) only.");
114  const ParameterList & pL = GetParameterList();
115  std::string nspName = pL.get<std::string>("Fine level nullspace");
116 
117  if (currentLevel.GetLevelID() == 0) {
118 
119  if (currentLevel.IsAvailable(nspName, NoFactory::get())) {
120  // When a fine nullspace have already been defined by user using Set("Nullspace", ...) or
121  // Set("Nullspace1", ...), we use it.
122  nullspace = currentLevel.Get< RCP<MultiVector> >(nspName, NoFactory::get());
123  GetOStream(Runtime1) << "Use user-given nullspace " << nspName << ": nullspace dimension=" << nullspace->getNumVectors() << " nullspace length=" << nullspace->getGlobalLength() << std::endl;
124  } else {
125  // "Nullspace" (nspName) is not available
126  RCP<Matrix> A = Get< RCP<Matrix> >(currentLevel, "A");
127 
128  // determine numPDEs
129  LocalOrdinal numPDEs = 1;
130  if(A->IsView("stridedMaps")==true) {
131  Xpetra::viewLabel_t oldView = A->SwitchToView("stridedMaps"); // note: "stridedMaps are always non-overlapping (correspond to range and domain maps!)
132  TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<const StridedMap>(A->getRowMap()) == Teuchos::null, Exceptions::BadCast, "MueLu::CoalesceFactory::Build: cast to strided row map failed.");
133  numPDEs = Teuchos::rcp_dynamic_cast<const StridedMap>(A->getRowMap())->getFixedBlockSize();
134  oldView = A->SwitchToView(oldView);
135  }
136 
137  GetOStream(Runtime1) << "Generating canonical nullspace: dimension = " << numPDEs << std::endl;
138  nullspace = MultiVectorFactory::Build(A->getDomainMap(), numPDEs);
139 
140  RCP<BlockedMultiVector> bnsp = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(nullspace);
141  if(bnsp.is_null() == true) {
142  for (int i=0; i<numPDEs; ++i) {
143  ArrayRCP<Scalar> nsValues = nullspace->getDataNonConst(i);
144  int numBlocks = nsValues.size() / numPDEs;
145  for (int j=0; j< numBlocks; ++j) {
146  nsValues[j*numPDEs + i] = 1.0;
147  }
148  }
149  } else {
150  fillNullspaceVector(bnsp,numPDEs);
151  }
152  } // end if "Nullspace" not available
153  } else {
154  // on coarser levels always use "Nullspace" as variable name, since it is expected by
155  // tentative P factory to be "Nullspace"
156 
157  nullspace = currentLevel.Get< RCP<MultiVector> >("Nullspace", GetFactory(nspName).get()); /* ! "Nullspace" and nspName mismatch possible here */
158 
159  }
160 
161  // provide "Nullspace" variable on current level (used by TentativePFactory)
162  Set(currentLevel, "Nullspace", nullspace);
163 
164  } // Build
165 
166  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
168  RCP< const BlockedMap> bmap = nsp->getBlockedMap();
169 
170  for(size_t r = 0; r < bmap->getNumMaps(); r++) {
171  Teuchos::RCP<MultiVector> part = nsp->getMultiVector(r);
172  Teuchos::RCP<BlockedMultiVector> bpart = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(part);
173  if(bpart.is_null() == true) {
174  for (int i=0; i<numPDEs; ++i) {
175  ArrayRCP<Scalar> nsValues = part->getDataNonConst(i);
176  int numBlocks = nsValues.size() / numPDEs;
177  for (int j=0; j< numBlocks; ++j) {
178  nsValues[j*numPDEs + i] = 1.0;
179  }
180  }
181  } else {
182  // call this routine recursively
183  fillNullspaceVector(bpart,numPDEs);
184  }
185  }
186  }
187 
188 } //namespace MueLu
189 
190 #endif // MUELU_NULLSPACEFACTORY_DEF_HPP
MueLu::DefaultLocalOrdinal LocalOrdinal
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.
Definition: MueLu_Level.hpp:99
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.
Definition: MueLu_Level.cpp:76
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 Build(Level &currentLevel) const
Build an object with this factory.
void fillNullspaceVector(const RCP< BlockedMultiVector > &nsp, LocalOrdinal numPDEs) const
Helper function to recursively fill BlockedMultiVector with default null space vectors.
RCP< const ParameterList > GetValidParameterList() const
Define valid parameters for internal factory parameters.
void DeclareInput(Level &currentLevel) const
Specifies the data that this class needs, and the factories that generate that data.
Namespace for MueLu classes and methods.
@ Runtime1
Description of what is happening (more verbose)