MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_ConstraintFactory_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_CONSTRAINTFACTORY_DEF_HPP
11#define MUELU_CONSTRAINTFACTORY_DEF_HPP
12
14
15#include "MueLu_Constraint.hpp"
16#include "MueLu_DenseConstraint.hpp"
17#include "MueLu_SparseConstraint.hpp"
18#include "MueLu_Monitor.hpp"
19#include "MueLu_MasterList.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("emin: constraint type");
29 validParamList->getEntry("emin: constraint type").setValidator(rcp(new Teuchos::StringValidator(Teuchos::tuple<std::string>("nullspace", "maxwell"))));
30
31 SET_VALID_ENTRY("emin: least squares solver type");
32 validParamList->getEntry("emin: least squares solver type").setValidator(rcp(new Teuchos::StringValidator(Teuchos::tuple<std::string>("Belos", "direct"))));
33#undef SET_VALID_ENTRY
34
35 validParamList->set<RCP<const FactoryBase>>("FineNullspace", Teuchos::null, "Generating factory for the nullspace");
36 validParamList->set<RCP<const FactoryBase>>("CoarseNullspace", Teuchos::null, "Generating factory for the nullspace");
37 validParamList->set<RCP<const FactoryBase>>("FineD0", Teuchos::null, "Generating factory for the fine discrete gradient");
38 validParamList->set<RCP<const FactoryBase>>("CoarseD0", Teuchos::null, "Generating factory for the coarse discrete gradient");
39 validParamList->set<RCP<const FactoryBase>>("Ppattern", Teuchos::null, "Generating factory for the nonzero pattern");
40 validParamList->set<RCP<const FactoryBase>>("PnodalEmin", Teuchos::null, "Generating factory for nodal P");
41
42 return validParamList;
43}
44
45template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
47 const ParameterList& pL = GetParameterList();
48 if (pL.get<std::string>("emin: constraint type") == "nullspace") {
49 Input(fineLevel, "Nullspace", "FineNullspace");
50 Input(coarseLevel, "Nullspace", "CoarseNullspace");
51 } else {
52 Input(fineLevel, "D0", "FineD0");
53 Input(coarseLevel, "D0", "CoarseD0");
54 Input(coarseLevel, "PnodalEmin", "PnodalEmin");
55 }
56 Input(coarseLevel, "Ppattern");
57}
58
59template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
61 FactoryMonitor m(*this, "Constraint", coarseLevel);
62
63 auto Ppattern = Get<RCP<const CrsGraph>>(coarseLevel, "Ppattern");
64 RCP<Constraint> constraint;
65 const ParameterList& pL = GetParameterList();
66
67 std::string solverType = pL.get<std::string>("emin: least squares solver type");
68
69 if (pL.get<std::string>("emin: constraint type") == "nullspace") {
70 RCP<MultiVector> fineNullspace = Get<RCP<MultiVector>>(fineLevel, "Nullspace", "FineNullspace");
71 RCP<MultiVector> coarseNullspace = Get<RCP<MultiVector>>(coarseLevel, "Nullspace", "CoarseNullspace");
72 {
73 SubFactoryMonitor m2(*this, "Dense Constraint", coarseLevel);
74 constraint = rcp(new DenseConstraint(fineNullspace, coarseNullspace, Ppattern, solverType));
75 }
76 } else {
77 RCP<Matrix> fineD0 = Get<RCP<Matrix>>(fineLevel, "D0", "FineD0");
78 RCP<Matrix> coarseD0 = Get<RCP<Matrix>>(coarseLevel, "D0", "CoarseD0");
79 RCP<Matrix> Pnodal = Get<RCP<Matrix>>(coarseLevel, "PnodalEmin", "PnodalEmin");
80 RCP<SparseConstraint> sparse_constraint;
81 {
82 SubFactoryMonitor m2(*this, "Sparse Constraint", coarseLevel);
83 sparse_constraint = rcp(new SparseConstraint(Pnodal, fineD0, coarseD0, Ppattern, solverType));
84 }
85
86 // Construct an initial guess.
87 // This is different from the nullspace constraint where we use the tentative prolongator as initial guess.
88 // Instead, we leverage the least-squares solve to construct a prolongator that satisfies the constraints.
89
90 auto X = sparse_constraint->GetConstraintMatrix();
91 auto vecPProjected = MultiVectorFactory::Build(sparse_constraint->getDomainMap(), 1);
92 auto temp = MultiVectorFactory::Build(X->getRangeMap(), 1);
93 auto rhs = MultiVectorFactory::Build(X->getRangeMap(), 1);
94
95 // We want
96 // P * coarseD0 = fineD0 * Pnodal
97 // which is, after vectorization
98 // X * vec(P) = vec(fineD0 * Pnodal)
99 // A solution of this is given by
100 // vec(P) = X^T * (X * X^T)^dagger * vec(fineD0 * Pnodal)
101
102 // rhs = fineD0 * Pnodal
103 {
104 RCP<Matrix> fineD0_Pnodal;
105 fineD0_Pnodal = MatrixMatrix::Multiply(*fineD0, false, *Pnodal, false, fineD0_Pnodal, GetOStream(Runtime0), true, true);
106 sparse_constraint->AssignMatrixEntriesToConstraintVector(*fineD0_Pnodal, *rhs);
107 }
108
109 // vecPProjected = X^T (X * X^T)^dagger * rhs
110 sparse_constraint->LeastSquaresSolve(*rhs, *temp);
111 X->apply(*temp, *vecPProjected, Teuchos::TRANS);
112
113 auto P0 = sparse_constraint->GetMatrixWithEntriesFromVector(*vecPProjected);
114
115 Set(coarseLevel, "P", P0);
116 constraint = sparse_constraint;
117 }
118
119 Set(coarseLevel, "Constraint", constraint);
120}
121
122} // namespace MueLu
123
124#endif // MUELU_CONSTRAINTFACTORY_DEF_HPP
#define SET_VALID_ENTRY(name)
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.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
Timer to be used in factories. Similar to Monitor but with additional timers.
Class that holds all level-specific information.
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
Namespace for MueLu classes and methods.
@ Runtime0
One-liner description of what is happening.