MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_SegregatedAFactory_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_SEGREGATEDAFACTORY_DEF_HPP
11#define MUELU_SEGREGATEDAFACTORY_DEF_HPP
12
13#include <Xpetra_Matrix.hpp>
14#include <Xpetra_MatrixFactory.hpp>
15
17
18#include "MueLu_Level.hpp"
19#include "MueLu_Monitor.hpp"
21
22namespace MueLu {
23
24template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
26 RCP<ParameterList> validParamList = rcp(new ParameterList());
27
28 validParamList->set<RCP<const FactoryBase>>("A", Teuchos::null, "Generating factory of the matrix A to be filtered");
29 validParamList->set<std::string>("droppingScheme", "vague", "Strategy to drop entries from matrix A based on the input of some map(s) [blockmap, map-pair]");
30
31 validParamList->set<RCP<const FactoryBase>>("dropMap1", Teuchos::null, "Generating factory for dropMap1");
32 validParamList->set<RCP<const FactoryBase>>("dropMap2", Teuchos::null, "Generating factory for dropMap2'");
33
34 return validParamList;
35} // GetValidParameterList
36
37template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
39 const ParameterList &pL = GetParameterList();
40
41 TEUCHOS_TEST_FOR_EXCEPTION(pL.get<RCP<const FactoryBase>>("A") == Teuchos::null, Exceptions::InvalidArgument,
42 "Please specify a generating factory for the matrix \"A\" to be filtered.")
43 TEUCHOS_TEST_FOR_EXCEPTION(pL.get<std::string>("droppingScheme") == "vague", Exceptions::InvalidArgument,
44 "Input map type not selected. Please select one of the available strategies.")
45 TEUCHOS_TEST_FOR_EXCEPTION(
46 (pL.get<std::string>("droppingScheme") != "blockmap" && pL.get<std::string>("droppingScheme") != "map-pair"),
48 "Unknown User Input: droppingScheme (=" << pL.get<std::string>("droppingScheme") << ")")
49
50 Input(currentLevel, "A");
51
52 if (pL.get<std::string>("droppingScheme") == "blockmap") {
53 if (currentLevel.GetLevelID() == 0) {
54 currentLevel.DeclareInput("dropMap1", NoFactory::get(), this);
55 } else {
56 Input(currentLevel, "dropMap1");
57 }
58 } else if (pL.get<std::string>("droppingScheme") == "map-pair") {
59 if (currentLevel.GetLevelID() == 0) {
60 currentLevel.DeclareInput("dropMap1", NoFactory::get(), this);
61 currentLevel.DeclareInput("dropMap2", NoFactory::get(), this);
62 } else {
63 Input(currentLevel, "dropMap1");
64 Input(currentLevel, "dropMap2");
65 }
66 } else
67 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::InvalidArgument, "Unknown droppingScheme.")
68
69} // DeclareInput
70
71template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
73 // Call a specialized build routine based on the format of user-given input
74 const ParameterList &pL = GetParameterList();
75 const std::string parameterName = "droppingScheme";
76 if (pL.get<std::string>(parameterName) == "blockmap") {
77 BuildBasedOnBlockmap(currentLevel);
78 } else if (pL.get<std::string>(parameterName) == "map-pair") {
79 BuildBasedOnMapPair(currentLevel);
80 } else {
81 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::InvalidArgument,
82 "MueLu::SegregatedAFactory::Build(): Unknown map type of user input. "
83 "Set a valid value for the parameter \""
84 << parameterName << "\".")
85 }
86} // Build
87
88template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
90 FactoryMonitor m(*this, "Matrix filtering (segregation, blockmap)", currentLevel);
91
92 RCP<Matrix> Ain = Get<RCP<Matrix>>(currentLevel, "A");
93 RCP<const Map> dropMap1 = Teuchos::null;
94 const std::string dropMap1Name = "dropMap1";
95
96 // fetch maps from level
97 if (currentLevel.GetLevelID() == 0) {
98 dropMap1 = currentLevel.Get<RCP<const Map>>(dropMap1Name, NoFactory::get());
99 GetOStream(Statistics0) << "User provided dropMap1 \"" << dropMap1Name << "\": length dimension=" << dropMap1->getGlobalNumElements() << std::endl;
100 } else {
101 dropMap1 = Get<RCP<const Map>>(currentLevel, dropMap1Name);
102 }
103 TEUCHOS_ASSERT(!dropMap1.is_null());
104
105 // create new empty Operator
106 Teuchos::RCP<Matrix> Aout = MatrixFactory::Build(Ain->getRowMap(), Ain->getGlobalMaxNumRowEntries());
107
108 size_t numLocalRows = Ain->getLocalNumRows();
109 for (size_t row = 0; row < numLocalRows; row++) {
110 GlobalOrdinal grid = Ain->getRowMap()->getGlobalElement(row); // global row id
111 bool isInMap = dropMap1->isNodeGlobalElement(grid);
112
113 // extract row information from input matrix
114 auto lclMat = Ain->getLocalMatrixHost();
115 auto rowView = lclMat.row(row);
116
117 // just copy all values in output
118 Teuchos::ArrayRCP<GO> indout(rowView.length, Teuchos::ScalarTraits<GO>::zero());
119 Teuchos::ArrayRCP<SC> valout(rowView.length, Teuchos::ScalarTraits<SC>::zero());
120
121 size_t nNonzeros = 0;
122 for (LO jj = 0; jj < rowView.length; ++jj) {
123 LO lcid = rowView.colidx(jj);
124 GO gcid = Ain->getColMap()->getGlobalElement(lcid);
125 auto val = rowView.value(jj);
126 bool isInMap2 = dropMap1->isNodeGlobalElement(gcid);
127
128 if (isInMap == isInMap2) {
129 indout[nNonzeros] = gcid;
130 valout[nNonzeros] = val;
131 nNonzeros++;
132 }
133 }
134 indout.resize(nNonzeros);
135 valout.resize(nNonzeros);
136
137 Aout->insertGlobalValues(Ain->getRowMap()->getGlobalElement(row), indout.view(0, indout.size()), valout.view(0, valout.size()));
138 }
139
140 Aout->fillComplete(Ain->getDomainMap(), Ain->getRangeMap());
141
142 // copy block size information
143 Aout->SetFixedBlockSize(Ain->GetFixedBlockSize());
144
145 GetOStream(Statistics0, 0) << "Nonzeros in A (input): " << Ain->getGlobalNumEntries() << ", Nonzeros after filtering A: " << Aout->getGlobalNumEntries() << std::endl;
146
147 Set(currentLevel, "A", Aout);
148} // BuildBasedOnBlockmap
149
150template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
152 FactoryMonitor m(*this, "Matrix filtering (segregation, map-pair)", currentLevel);
153
154 RCP<Matrix> Ain = Get<RCP<Matrix>>(currentLevel, "A");
155
156 // fetch maps from level
157 RCP<const Map> dropMap1 = Teuchos::null;
158 RCP<const Map> dropMap2 = Teuchos::null;
159
160 const std::string dropMap1Name = "dropMap1";
161 const std::string dropMap2Name = "dropMap2";
162
163 if (currentLevel.GetLevelID() == 0) {
164 dropMap1 = currentLevel.Get<RCP<const Map>>(dropMap1Name, NoFactory::get());
165 dropMap2 = currentLevel.Get<RCP<const Map>>(dropMap2Name, NoFactory::get());
166 GetOStream(Statistics0) << "User provided dropMap1 \"" << dropMap1Name << "\": length dimension=" << dropMap1->getGlobalNumElements() << std::endl;
167 GetOStream(Statistics0) << "User provided dropMap2 \"" << dropMap2Name << "\": length dimension=" << dropMap2->getGlobalNumElements() << std::endl;
168 } else {
169 dropMap1 = Get<RCP<const Map>>(currentLevel, dropMap1Name);
170 dropMap2 = Get<RCP<const Map>>(currentLevel, dropMap2Name);
171 }
172
173 TEUCHOS_ASSERT(!dropMap1.is_null());
174 TEUCHOS_ASSERT(!dropMap2.is_null());
175
176 // create new empty Operator
177 Teuchos::RCP<Matrix> Aout = MatrixFactory::Build(Ain->getRowMap(), Ain->getGlobalMaxNumRowEntries());
178
179 // import the dropping information from other procs for off Rank entries
180 Teuchos::RCP<const Map> finalDropMap1 = Teuchos::null;
181 Teuchos::RCP<const Map> finalDropMap2 = Teuchos::null;
182
183 finalDropMap1 = MueLu::importOffRankDroppingInfo(dropMap1, Ain);
184 finalDropMap2 = MueLu::importOffRankDroppingInfo(dropMap2, Ain);
185
186 // Start copying the matrix row by row and dropping any entries that are contained as a combination of entries of
187 // dropMap1 and dropMap2
188 size_t numLocalMatrixRows = Ain->getLocalNumRows();
189
190 for (size_t row = 0; row < numLocalMatrixRows; row++) {
191 GO grid = Ain->getRowMap()->getGlobalElement(row); // global row id
192 bool rowIsInMap1 = finalDropMap1->isNodeGlobalElement(grid);
193 bool rowIsInMap2 = finalDropMap2->isNodeGlobalElement(grid);
194
195 // extract row information from input matrix
196 auto lclMat = Ain->getLocalMatrixHost();
197 auto rowView = lclMat.row(row);
198
199 // just copy all values in output
200 Teuchos::ArrayRCP<GO> indout(rowView.length, Teuchos::ScalarTraits<GO>::zero());
201 Teuchos::ArrayRCP<SC> valout(rowView.length, Teuchos::ScalarTraits<SC>::zero());
202
203 size_t nNonzeros = 0;
204 for (LO jj = 0; jj < rowView.length; ++jj) {
205 LO lcid = rowView.colidx(jj);
206 GO gcid = Ain->getColMap()->getGlobalElement(lcid); // global column id
207 auto val = rowView.value(jj);
208 bool colIsInMap1 = finalDropMap1->isNodeGlobalElement(gcid);
209 bool colIsInMap2 = finalDropMap2->isNodeGlobalElement(gcid);
210
211 if ((rowIsInMap1 && colIsInMap2) || (rowIsInMap2 && colIsInMap1)) {
212 // do nothing == drop this entry
213 } else {
214 indout[nNonzeros] = gcid;
215 valout[nNonzeros] = val;
216 nNonzeros++;
217 }
218 }
219 indout.resize(nNonzeros);
220 valout.resize(nNonzeros);
221 Aout->insertGlobalValues(Ain->getRowMap()->getGlobalElement(row), indout.view(0, indout.size()), valout.view(0, valout.size()));
222 }
223
224 Aout->fillComplete(Ain->getDomainMap(), Ain->getRangeMap());
225
226 // copy block size information
227 Aout->SetFixedBlockSize(Ain->GetFixedBlockSize());
228
229 GetOStream(Statistics0, 0) << "Nonzeros in A (input): " << Ain->getGlobalNumEntries() << ", Nonzeros after filtering A: " << Aout->getGlobalNumEntries() << std::endl;
230
231 currentLevel.Set("A", Aout, this);
232} // BuildBasedOnMapPair
233
234} // namespace MueLu
235
236#endif // MUELU_SEGREGATEDAFACTORY_DEF_HPP
MueLu::DefaultGlobalOrdinal GlobalOrdinal
Exception throws to report invalid user entry.
Timer to be used in factories. Similar to Monitor but with additional timers.
Class that holds all level-specific information.
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.
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
static const NoFactory * get()
void Build(Level &currentLevel) const override
Build method.
RCP< const ParameterList > GetValidParameterList() const override
Input.
void BuildBasedOnMapPair(Level &currentLevel) const
void DeclareInput(Level &currentLevel) const override
Specifies the data that this class needs, and the factories that generate that data.
void BuildBasedOnBlockmap(Level &currentLevel) const
Namespace for MueLu classes and methods.
@ Statistics0
Print statistics that do not involve significant additional computation.
Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > importOffRankDroppingInfo(Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &localDropMap, Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &Ain)