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
58namespace 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)