MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_InterfaceAggregationFactory_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_INTERFACEAGGREGATIONFACTORY_DEF_HPP_
47#define MUELU_INTERFACEAGGREGATIONFACTORY_DEF_HPP_
48
49#include <Xpetra_Map.hpp>
50#include <Xpetra_MapFactory.hpp>
51#include <Xpetra_StridedMap.hpp>
52
53#include "MueLu_Aggregates.hpp"
54#include "MueLu_AmalgamationFactory.hpp"
55#include "MueLu_AmalgamationInfo.hpp"
56#include "MueLu_Level.hpp"
57#include "MueLu_Monitor.hpp"
58
60
61namespace MueLu
62{
63
64template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
66{
67 RCP<ParameterList> validParamList = rcp(new ParameterList());
68
69 validParamList->set<RCP<const FactoryBase>>("A", Teuchos::null, "Generating factory of A (matrix block related to dual DOFs)");
70 validParamList->set<RCP<const FactoryBase>>("Aggregates", Teuchos::null, "Generating factory of the Aggregates (for block 0,0)");
71
72 validParamList->set<std::string>("Dual/primal mapping strategy", "vague",
73 "Strategy to represent mapping between dual and primal quantities [node-based, dof-based]");
74
75 validParamList->set<RCP<const FactoryBase>>("DualNodeID2PrimalNodeID", Teuchos::null,
76 "Generating factory of the DualNodeID2PrimalNodeID map as input data in a Moertel-compatible std::map<LO,LO> to map local IDs of dual nodes to local IDs of primal nodes");
77 validParamList->set<LocalOrdinal>("number of DOFs per dual node", -Teuchos::ScalarTraits<LocalOrdinal>::one(),
78 "Number of DOFs per dual node");
79
80 validParamList->set<RCP<const FactoryBase>>("Primal interface DOF map", Teuchos::null,
81 "Generating factory of the primal DOF row map of slave side of the coupling surface");
82
83 return validParamList;
84} // GetValidParameterList()
85
86template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
88{
89 Input(currentLevel, "A"); // matrix block of dual variables
90 Input(currentLevel, "Aggregates");
91
92 const ParameterList &pL = GetParameterList();
93 TEUCHOS_TEST_FOR_EXCEPTION(pL.get<std::string>("Dual/primal mapping strategy")=="vague", Exceptions::InvalidArgument,
94 "Strategy for dual/primal mapping not selected. Please select one of the available strategies.")
95 if (pL.get<std::string>("Dual/primal mapping strategy") == "node-based")
96 {
97 if (currentLevel.GetLevelID() == 0)
98 {
99 TEUCHOS_TEST_FOR_EXCEPTION(!currentLevel.IsAvailable("DualNodeID2PrimalNodeID", NoFactory::get()),
100 Exceptions::RuntimeError, "DualNodeID2PrimalNodeID was not provided by the user on level 0!");
101
102 currentLevel.DeclareInput("DualNodeID2PrimalNodeID", NoFactory::get(), this);
103 }
104 else
105 {
106 Input(currentLevel, "DualNodeID2PrimalNodeID");
107 }
108 }
109 else if (pL.get<std::string>("Dual/primal mapping strategy") == "dof-based")
110 {
111 if (currentLevel.GetLevelID() == 0)
112 currentLevel.DeclareInput("Primal interface DOF map", NoFactory::get(), this);
113 else
114 Input(currentLevel, "Primal interface DOF map");
115 }
116 else
117 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::InvalidArgument, "Unknown strategy for dual/primal mapping.")
118
119} // DeclareInput
120
121template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
123{
124 const std::string prefix = "MueLu::InterfaceAggregationFactory::Build: ";
125
126 FactoryMonitor m(*this, "Build", currentLevel);
127
128 // Call a specialized build routine based on the format of user-given input
129 const ParameterList &pL = GetParameterList();
130 const std::string parameterName = "Dual/primal mapping strategy";
131 if (pL.get<std::string>(parameterName) == "node-based")
132 BuildBasedOnNodeMapping(prefix, currentLevel);
133 else if (pL.get<std::string>(parameterName) == "dof-based")
134 BuildBasedOnPrimalInterfaceDofMap(prefix, currentLevel);
135 else
136 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::InvalidArgument,
137 "MueLu::InterfaceAggregationFactory::Builld(): Unknown strategy for dual/primal mapping. Set a valid value for the parameter \"" << parameterName << "\".")
138}
139
140template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
142 Level &currentLevel) const
143{
144 using Dual2Primal_type = std::map<LocalOrdinal, LocalOrdinal>;
145
146 const ParameterList &pL = GetParameterList();
147
148 RCP<const Matrix> A = Get<RCP<Matrix>>(currentLevel, "A");
149 const LocalOrdinal numDofsPerDualNode = pL.get<LocalOrdinal>("number of DOFs per dual node");
150 TEUCHOS_TEST_FOR_EXCEPTION(numDofsPerDualNode<Teuchos::ScalarTraits<LocalOrdinal>::one(), Exceptions::InvalidArgument,
151 "Number of dual DOFs per node < 0 (default value). Specify a valid \"number of DOFs per dual node\" in the parameter list for the InterfaceAggregationFactory.");
152
153 RCP<const Aggregates> primalAggregates = Get<RCP<Aggregates>>(currentLevel, "Aggregates");
154 ArrayRCP<const LocalOrdinal> primalVertex2AggId = primalAggregates->GetVertex2AggId()->getData(0);
155
156 // Get the user-prescribed mapping of dual to primal node IDs
157 RCP<Dual2Primal_type> mapNodesDualToPrimal;
158 if (currentLevel.GetLevelID() == 0)
159 mapNodesDualToPrimal = currentLevel.Get<RCP<Dual2Primal_type>>("DualNodeID2PrimalNodeID", NoFactory::get());
160 else
161 mapNodesDualToPrimal = Get<RCP<Dual2Primal_type>>(currentLevel, "DualNodeID2PrimalNodeID");
162
163 RCP<const Map> operatorRangeMap = A->getRangeMap();
164 const size_t myRank = operatorRangeMap->getComm()->getRank();
165
166 LocalOrdinal globalNumDualNodes = operatorRangeMap->getGlobalNumElements() / numDofsPerDualNode;
167 LocalOrdinal localNumDualNodes = operatorRangeMap->getLocalNumElements() / numDofsPerDualNode;
168
169 TEUCHOS_TEST_FOR_EXCEPTION(localNumDualNodes != Teuchos::as<LocalOrdinal>(mapNodesDualToPrimal->size()),
170 std::runtime_error, prefix << " MueLu requires the range map and the DualNodeID2PrimalNodeID map to be compatible.");
171
172 RCP<const Map> dualNodeMap = Teuchos::null;
173 if (numDofsPerDualNode == 1)
174 dualNodeMap = operatorRangeMap;
175 else
176 {
177 GlobalOrdinal indexBase = operatorRangeMap->getIndexBase();
178 auto comm = operatorRangeMap->getComm();
179 std::vector<GlobalOrdinal> myDualNodes = {};
180
181 for (size_t i = 0; i < operatorRangeMap->getLocalNumElements(); i += numDofsPerDualNode)
182 myDualNodes.push_back((operatorRangeMap->getGlobalElement(i) - indexBase) / numDofsPerDualNode + indexBase);
183
184 dualNodeMap = MapFactory::Build(operatorRangeMap->lib(), globalNumDualNodes, myDualNodes, indexBase, comm);
185 }
186 TEUCHOS_TEST_FOR_EXCEPTION(localNumDualNodes != Teuchos::as<LocalOrdinal>(dualNodeMap->getLocalNumElements()),
187 std::runtime_error, prefix << " Local number of dual nodes given by user is incompatible to the dual node map.");
188
189 RCP<Aggregates> dualAggregates = rcp(new Aggregates(dualNodeMap));
190 dualAggregates->setObjectLabel("InterfaceAggregation");
191
192 // Copy setting from primal aggregates, as we copy the interface part of primal aggregates anyways
193 dualAggregates->AggregatesCrossProcessors(primalAggregates->AggregatesCrossProcessors());
194
195 ArrayRCP<LocalOrdinal> dualVertex2AggId = dualAggregates->GetVertex2AggId()->getDataNonConst(0);
196 ArrayRCP<LocalOrdinal> dualProcWinner = dualAggregates->GetProcWinner()->getDataNonConst(0);
197
198 RCP<Dual2Primal_type> coarseMapNodesDualToPrimal = rcp(new Dual2Primal_type());
199 RCP<Dual2Primal_type> coarseMapNodesPrimalToDual = rcp(new Dual2Primal_type());
200
201 LocalOrdinal numLocalDualAggregates = 0;
202
203 /* Loop over the local dual nodes and
204 *
205 * - assign dual nodes to dual aggregates
206 * - recursively coarsen the dual-to-primal node mapping
207 */
208 LocalOrdinal localPrimalNodeID = - Teuchos::ScalarTraits<LocalOrdinal>::one();
209 LocalOrdinal currentPrimalAggId = - Teuchos::ScalarTraits<LocalOrdinal>::one();
210 for (LocalOrdinal localDualNodeID = 0; localDualNodeID < localNumDualNodes; ++localDualNodeID)
211 {
212 // Get local ID of the primal node associated to the current dual node
213 localPrimalNodeID = (*mapNodesDualToPrimal)[localDualNodeID];
214
215 // Find the primal aggregate that owns the current primal node
216 currentPrimalAggId = primalVertex2AggId[localPrimalNodeID];
217
218 // Test if the current primal aggregate has no associated dual aggregate, yet.
219 // Create new dual aggregate, if necessary.
220 if (coarseMapNodesPrimalToDual->count(currentPrimalAggId) == 0)
221 {
222 // Associate a new dual aggregate w/ the current primal aggregate
223 (*coarseMapNodesPrimalToDual)[currentPrimalAggId] = numLocalDualAggregates;
224 (*coarseMapNodesDualToPrimal)[numLocalDualAggregates] = currentPrimalAggId;
225 ++numLocalDualAggregates;
226 }
227
228 // Fill the dual aggregate
229 dualVertex2AggId[localDualNodeID] = (*coarseMapNodesPrimalToDual)[currentPrimalAggId];
230 dualProcWinner[localDualNodeID] = myRank;
231 }
232
233 // Store dual aggregeate data as well as coarsening information
234 dualAggregates->SetNumAggregates(numLocalDualAggregates);
235 Set(currentLevel, "Aggregates", dualAggregates);
236 Set(currentLevel, "CoarseDualNodeID2PrimalNodeID", coarseMapNodesDualToPrimal);
237 GetOStream(Statistics1) << dualAggregates->description() << std::endl;
238} // BuildBasedOnNodeMapping
239
240template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
242 const std::string& prefix, Level &currentLevel) const
243{
244 const GlobalOrdinal GO_ZERO = Teuchos::ScalarTraits<LocalOrdinal>::zero();
245 const GlobalOrdinal GO_ONE = Teuchos::ScalarTraits<GlobalOrdinal>::one();
246
247 // filled with striding information from A01
248 LocalOrdinal numDofsPerDualNode = 0;
249 LocalOrdinal numDofsPerPrimalNode = 0;
250
251 // Grab the off-diagonal block (0,1) from the global blocked operator
252 RCP<const Matrix> A01 = Get<RCP<Matrix>>(currentLevel, "A");
253 RCP<const Aggregates> primalAggregates = Get<RCP<Aggregates>>(currentLevel, "Aggregates");
254 ArrayRCP<const LocalOrdinal> primalVertex2AggId = primalAggregates->GetVertex2AggId()->getData(0);
255
256 auto comm = A01->getRowMap()->getComm();
257 const int myRank = comm->getRank();
258
259 RCP<const Map> primalInterfaceDofRowMap = Teuchos::null;
260 if (currentLevel.GetLevelID() == 0) {
261 // Use NoFactory, since the fine level asks for user data
262 primalInterfaceDofRowMap = currentLevel.Get<RCP<const Map>>("Primal interface DOF map", NoFactory::get());
263 } else {
264 primalInterfaceDofRowMap = Get<RCP<const Map>>(currentLevel, "Primal interface DOF map");
265 }
266 TEUCHOS_ASSERT(!primalInterfaceDofRowMap.is_null());
267
268 if (A01->IsView("stridedMaps") && rcp_dynamic_cast<const StridedMap>(A01->getRowMap("stridedMaps")) != Teuchos::null) {
269 auto stridedRowMap = rcp_dynamic_cast<const StridedMap>(A01->getRowMap("stridedMaps"));
270 auto stridedColMap = rcp_dynamic_cast<const StridedMap>(A01->getColMap("stridedMaps"));
271 numDofsPerPrimalNode = Teuchos::as<LocalOrdinal>(stridedRowMap->getFixedBlockSize());
272 numDofsPerDualNode = Teuchos::as<LocalOrdinal>(stridedColMap->getFixedBlockSize());
273
274 if (numDofsPerPrimalNode != numDofsPerDualNode) {
275 GetOStream(Warnings) << "InterfaceAggregation attempts to work with "
276 << numDofsPerPrimalNode << " primal DOFs per node and " << numDofsPerDualNode << " dual DOFs per node."
277 << "Be careful! Algorithm is not well-tested, if number of primal and dual DOFs per node differ." << std::endl;
278 }
279 }
280
281 TEUCHOS_TEST_FOR_EXCEPTION(numDofsPerPrimalNode==0, Exceptions::RuntimeError,
282 "InterfaceAggregationFactory could not extract the number of primal DOFs per node from striding information. At least, make sure that StridedMap information has actually been provided.");
283 TEUCHOS_TEST_FOR_EXCEPTION(numDofsPerDualNode==0, Exceptions::RuntimeError,
284 "InterfaceAggregationFactory could not extract the number of dual DOFs per node from striding information. At least, make sure that StridedMap information has actually been provided.");
285
286 /* Determine block information for primal block
287 *
288 * primalDofOffset: global offset of primal DOF GIDs (usually is zero (default))
289 * primalBlockDim: block dim for fixed size blocks
290 * - is 2 or 3 (for 2d or 3d problems) on the finest level (# displacement dofs per node)
291 * - is 3 or 6 (for 2d or 3d problems) on coarser levels (# nullspace vectors)
292 */
293 GlobalOrdinal primalDofOffset = GO_ZERO;
294 LocalOrdinal primalBlockDim = numDofsPerPrimalNode;
295
296 /* Determine block information for Lagrange multipliers
297 *
298 * dualDofOffset: usually > zero (set by domainOffset for Ptent11Fact)
299 * dualBlockDim:
300 * - is primalBlockDim (for 2d or 3d problems) on the finest level (1 Lagrange multiplier per
301 * displacement dof)
302 * - is 2 or 3 (for 2d or 3d problems) on coarser levels (same as on finest level, whereas there
303 * are 3 or 6 displacement dofs per node)
304 */
305 GlobalOrdinal dualDofOffset = A01->getColMap()->getMinAllGlobalIndex();
306 LocalOrdinal dualBlockDim = numDofsPerDualNode;
307
308 // Generate global replicated mapping "lagrNodeId -> dispNodeId"
309 RCP<const Map> dualDofMap = A01->getDomainMap();
311 dualDofMap->getMaxAllGlobalIndex(), dualBlockDim, dualDofOffset, dualDofMap->getIndexBase());
313 dualDofMap->getMinAllGlobalIndex(), dualBlockDim, dualDofOffset, dualDofMap->getIndexBase());
314
315 GetOStream(Runtime1) << " Dual DOF map: index base = " << dualDofMap->getIndexBase()
316 << ", block dim = " << dualBlockDim
317 << ", gid offset = " << dualDofOffset
318 << std::endl;
319
320 GetOStream(Runtime1) << " [primal / dual] DOFs per node = [" << numDofsPerPrimalNode
321 << "/" << numDofsPerDualNode << "]" << std::endl;
322
323 // Generate locally replicated vector for mapping dual node IDs to primal node IDs
324 Array<GlobalOrdinal> dualNodeId2primalNodeId(gMaxDualNodeId - gMinDualNodeId + 1, -GO_ONE);
325 Array<GlobalOrdinal> local_dualNodeId2primalNodeId(gMaxDualNodeId - gMinDualNodeId + 1, -GO_ONE);
326
327 // Generate locally replicated vector for mapping dual node IDs to primal aggregate ID
328 Array<GlobalOrdinal> dualNodeId2primalAggId(gMaxDualNodeId - gMinDualNodeId + 1, -GO_ONE);
329 Array<GlobalOrdinal> local_dualNodeId2primalAggId(gMaxDualNodeId - gMinDualNodeId + 1, -GO_ONE);
330
331 Array<GlobalOrdinal> dualDofId2primalDofId(primalInterfaceDofRowMap->getGlobalNumElements(), -GO_ONE);
332 Array<GlobalOrdinal> local_dualDofId2primalDofId(primalInterfaceDofRowMap->getGlobalNumElements(), -GO_ONE);
333
334 // Fill mapping of Lagrange Node IDs to displacement aggregate IDs
335 const size_t numMyPrimalInterfaceDOFs = primalInterfaceDofRowMap->getLocalNumElements();
336 for (size_t r = 0; r < numMyPrimalInterfaceDOFs; r += numDofsPerPrimalNode)
337 {
338 GlobalOrdinal gPrimalRowId = primalInterfaceDofRowMap->getGlobalElement(r);
339
340 if (A01->getRowMap()->isNodeGlobalElement(gPrimalRowId)) // Remove this if?
341 {
342 const LocalOrdinal lPrimalRowId = A01->getRowMap()->getLocalElement(gPrimalRowId);
343 const GlobalOrdinal gPrimalNodeId = AmalgamationFactory::DOFGid2NodeId(gPrimalRowId, primalBlockDim, primalDofOffset, primalInterfaceDofRowMap->getIndexBase());
344 const LocalOrdinal lPrimalNodeId = lPrimalRowId / numDofsPerPrimalNode;
345 const LocalOrdinal primalAggId = primalVertex2AggId[lPrimalNodeId];
346
347 const GlobalOrdinal gDualDofId = A01->getColMap()->getGlobalElement(r);
348
349 const GlobalOrdinal gDualNodeId = AmalgamationFactory::DOFGid2NodeId(gDualDofId, dualBlockDim, dualDofOffset, 0);
350
351 if (local_dualNodeId2primalNodeId[gDualNodeId - gMinDualNodeId] == -GO_ONE) {
352 local_dualNodeId2primalNodeId[gDualNodeId - gMinDualNodeId] = gPrimalNodeId;
353 local_dualNodeId2primalAggId[gDualNodeId - gMinDualNodeId] = primalAggId;
354 } else {
355 GetOStream(Warnings) << "PROC: " << myRank << " gDualNodeId " << gDualNodeId << " is already connected to primal nodeId "
356 << local_dualNodeId2primalNodeId[gDualNodeId - gMinDualNodeId]
357 << ". Ignore new dispNodeId: " << gPrimalNodeId << std::endl;
358 }
359
360 }
361 }
362
363 const int dualNodeId2primalNodeIdSize = Teuchos::as<int>(local_dualNodeId2primalNodeId.size());
364 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, dualNodeId2primalNodeIdSize,
365 &local_dualNodeId2primalNodeId[0], &dualNodeId2primalNodeId[0]);
366 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, dualNodeId2primalNodeIdSize,
367 &local_dualNodeId2primalAggId[0], &dualNodeId2primalAggId[0]);
368
369 // build node map for dual variables
370 // generate "artificial nodes" for lagrange multipliers
371 // the node map is also used for defining the Aggregates for the lagrange multipliers
372 std::vector<GlobalOrdinal> dualNodes;
373 for (size_t r = 0; r < A01->getDomainMap()->getLocalNumElements(); r++)
374 {
375 // determine global Lagrange multiplier row Dof
376 // generate a node id using the grid, lagr_blockdim and lagr_offset // todo make sure, that
377 // nodeId is unique and does not interfer with the displacement nodes
378 GlobalOrdinal gDualDofId = A01->getDomainMap()->getGlobalElement(r);
379 GlobalOrdinal gDualNodeId = AmalgamationFactory::DOFGid2NodeId(gDualDofId, dualBlockDim, dualDofOffset, 0);
380 dualNodes.push_back(gDualNodeId);
381 }
382
383 // remove all duplicates
384 dualNodes.erase(std::unique(dualNodes.begin(), dualNodes.end()), dualNodes.end());
385
386 // define node map for Lagrange multipliers
387 Teuchos::RCP<const Map> dualNodeMap = MapFactory::Build(A01->getRowMap()->lib(),
388 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), dualNodes, A01->getRowMap()->getIndexBase(), comm);
389
390 // Build aggregates using the lagrange multiplier node map
391 Teuchos::RCP<Aggregates> dualAggregates = Teuchos::rcp(new Aggregates(dualNodeMap));
392 dualAggregates->setObjectLabel("UC (dual variables)");
393
394 // extract aggregate data structures to fill
395 Teuchos::ArrayRCP<LocalOrdinal> dualVertex2AggId = dualAggregates->GetVertex2AggId()->getDataNonConst(0);
396 Teuchos::ArrayRCP<LocalOrdinal> dualProcWinner = dualAggregates->GetProcWinner()->getDataNonConst(0);
397
398 // loop over local lagrange multiplier node ids
399 LocalOrdinal nLocalAggregates = 0;
400 std::map<GlobalOrdinal, LocalOrdinal> primalAggId2localDualAggId;
401 for (size_t lDualNodeID = 0; lDualNodeID < dualNodeMap->getLocalNumElements(); ++lDualNodeID)
402 {
403 const GlobalOrdinal gDualNodeId = dualNodeMap->getGlobalElement(lDualNodeID);
404 const GlobalOrdinal primalAggId = dualNodeId2primalAggId[gDualNodeId - gMinDualNodeId];
405 if (primalAggId2localDualAggId.count(primalAggId) == 0)
406 primalAggId2localDualAggId[primalAggId] = nLocalAggregates++;
407 dualVertex2AggId[lDualNodeID] = primalAggId2localDualAggId[primalAggId];
408 dualProcWinner[lDualNodeID] = myRank;
409 }
410
411 const LocalOrdinal fullblocksize = numDofsPerDualNode;
412 const GlobalOrdinal offset = A01->getColMap()->getMinAllGlobalIndex();
413 const LocalOrdinal blockid = -1;
414 const LocalOrdinal nStridedOffset = 0;
415 const LocalOrdinal stridedblocksize = fullblocksize;
416
417 RCP<Array<LO>> rowTranslation = rcp(new Array<LO>());
418 RCP<Array<LO>> colTranslation = rcp(new Array<LO>());
419 const size_t numMyDualNodes = dualNodeMap->getLocalNumElements();
420 for (size_t lDualNodeID = 0; lDualNodeID < numMyDualNodes; ++lDualNodeID) {
421 for (LocalOrdinal dof = 0; dof < numDofsPerDualNode; ++dof) {
422 rowTranslation->push_back(lDualNodeID);
423 colTranslation->push_back(lDualNodeID);
424 }
425 }
426
427 TEUCHOS_ASSERT(A01->isFillComplete());
428
429 RCP<AmalgamationInfo> dualAmalgamationInfo = rcp(new AmalgamationInfo(rowTranslation, colTranslation,
430 A01->getDomainMap(), A01->getDomainMap(), A01->getDomainMap(),
431 fullblocksize, offset, blockid, nStridedOffset, stridedblocksize));
432
433 dualAggregates->SetNumAggregates(nLocalAggregates);
434 dualAggregates->AggregatesCrossProcessors(primalAggregates->AggregatesCrossProcessors());
435
436 if (dualAggregates->AggregatesCrossProcessors())
437 GetOStream(Runtime1) << "Interface aggregates cross processor boundaries." << std::endl;
438 else
439 GetOStream(Runtime1) << "Interface aggregates do not cross processor boundaries." << std::endl;
440
441 currentLevel.Set("Aggregates", dualAggregates, this);
442 currentLevel.Set("UnAmalgamationInfo", dualAmalgamationInfo, this);
443
444} // BuildBasedOnPrimalInterfaceDofMap
445
446} // namespace MueLu
447
448#endif /* MUELU_INTERFACEAGGREGATIONFACTORY_DEF_HPP_ */
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultGlobalOrdinal GlobalOrdinal
Container class for aggregation information.
static const GlobalOrdinal DOFGid2NodeId(GlobalOrdinal gid, LocalOrdinal blockSize, const GlobalOrdinal offset, const GlobalOrdinal indexBase)
Translate global (row/column) id to global amalgamation block id.
minimal container class for storing amalgamation information
Exception throws to report invalid user entry.
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.
void Input(Level &level, const std::string &varName) const
T Get(Level &level, const std::string &varName) const
void Set(Level &level, const std::string &varName, const T &data) const
void Build(Level &currentLevel) const override
Build aggregates.
void BuildBasedOnNodeMapping(const std::string &prefix, Level &currentLevel) const
Build dual aggregates based on a given dual-to-primal node mapping.
void DeclareInput(Level &currentLevel) const override
Specifies the data that this class needs, and the factories that generate that data.
void BuildBasedOnPrimalInterfaceDofMap(const std::string &prefix, Level &currentLevel) const
Build dual aggregates based on a given interface row map of the primal and dual problem.
RCP< const ParameterList > GetValidParameterList() const override
Input.
Class that holds all level-specific information.
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.
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()
virtual const Teuchos::ParameterList & GetParameterList() const
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
Namespace for MueLu classes and methods.
@ Warnings
Print all warning messages.
@ Statistics1
Print more statistics.
@ Runtime1
Description of what is happening (more verbose).