142 Level ¤tLevel)
const
144 using Dual2Primal_type = std::map<LocalOrdinal, LocalOrdinal>;
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.");
154 ArrayRCP<const LocalOrdinal> primalVertex2AggId = primalAggregates->GetVertex2AggId()->getData(0);
157 RCP<Dual2Primal_type> mapNodesDualToPrimal;
159 mapNodesDualToPrimal = currentLevel.
Get<RCP<Dual2Primal_type>>(
"DualNodeID2PrimalNodeID",
NoFactory::get());
163 RCP<const Map> operatorRangeMap = A->getRangeMap();
164 const size_t myRank = operatorRangeMap->getComm()->getRank();
166 LocalOrdinal globalNumDualNodes = operatorRangeMap->getGlobalNumElements() / numDofsPerDualNode;
167 LocalOrdinal localNumDualNodes = operatorRangeMap->getLocalNumElements() / numDofsPerDualNode;
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.");
172 RCP<const Map> dualNodeMap = Teuchos::null;
173 if (numDofsPerDualNode == 1)
174 dualNodeMap = operatorRangeMap;
178 auto comm = operatorRangeMap->getComm();
179 std::vector<GlobalOrdinal> myDualNodes = {};
181 for (
size_t i = 0; i < operatorRangeMap->getLocalNumElements(); i += numDofsPerDualNode)
182 myDualNodes.push_back((operatorRangeMap->getGlobalElement(i) - indexBase) / numDofsPerDualNode + indexBase);
184 dualNodeMap = MapFactory::Build(operatorRangeMap->lib(), globalNumDualNodes, myDualNodes, indexBase, comm);
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.");
189 RCP<Aggregates> dualAggregates = rcp(
new Aggregates(dualNodeMap));
190 dualAggregates->setObjectLabel(
"InterfaceAggregation");
193 dualAggregates->AggregatesCrossProcessors(primalAggregates->AggregatesCrossProcessors());
195 ArrayRCP<LocalOrdinal> dualVertex2AggId = dualAggregates->GetVertex2AggId()->getDataNonConst(0);
196 ArrayRCP<LocalOrdinal> dualProcWinner = dualAggregates->GetProcWinner()->getDataNonConst(0);
198 RCP<Dual2Primal_type> coarseMapNodesDualToPrimal = rcp(
new Dual2Primal_type());
199 RCP<Dual2Primal_type> coarseMapNodesPrimalToDual = rcp(
new Dual2Primal_type());
208 LocalOrdinal localPrimalNodeID = - Teuchos::ScalarTraits<LocalOrdinal>::one();
209 LocalOrdinal currentPrimalAggId = - Teuchos::ScalarTraits<LocalOrdinal>::one();
210 for (
LocalOrdinal localDualNodeID = 0; localDualNodeID < localNumDualNodes; ++localDualNodeID)
213 localPrimalNodeID = (*mapNodesDualToPrimal)[localDualNodeID];
216 currentPrimalAggId = primalVertex2AggId[localPrimalNodeID];
220 if (coarseMapNodesPrimalToDual->count(currentPrimalAggId) == 0)
223 (*coarseMapNodesPrimalToDual)[currentPrimalAggId] = numLocalDualAggregates;
224 (*coarseMapNodesDualToPrimal)[numLocalDualAggregates] = currentPrimalAggId;
225 ++numLocalDualAggregates;
229 dualVertex2AggId[localDualNodeID] = (*coarseMapNodesPrimalToDual)[currentPrimalAggId];
230 dualProcWinner[localDualNodeID] = myRank;
234 dualAggregates->SetNumAggregates(numLocalDualAggregates);
235 Set(currentLevel,
"Aggregates", dualAggregates);
236 Set(currentLevel,
"CoarseDualNodeID2PrimalNodeID", coarseMapNodesDualToPrimal);
242 const std::string& prefix,
Level ¤tLevel)
const
244 const GlobalOrdinal GO_ZERO = Teuchos::ScalarTraits<LocalOrdinal>::zero();
245 const GlobalOrdinal GO_ONE = Teuchos::ScalarTraits<GlobalOrdinal>::one();
254 ArrayRCP<const LocalOrdinal> primalVertex2AggId = primalAggregates->GetVertex2AggId()->getData(0);
256 auto comm = A01->getRowMap()->getComm();
257 const int myRank = comm->getRank();
259 RCP<const Map> primalInterfaceDofRowMap = Teuchos::null;
262 primalInterfaceDofRowMap = currentLevel.
Get<RCP<const Map>>(
"Primal interface DOF map",
NoFactory::get());
264 primalInterfaceDofRowMap =
Get<RCP<const Map>>(currentLevel,
"Primal interface DOF map");
266 TEUCHOS_ASSERT(!primalInterfaceDofRowMap.is_null());
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());
274 if (numDofsPerPrimalNode != numDofsPerDualNode) {
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;
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.");
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.");
305 GlobalOrdinal dualDofOffset = A01->getColMap()->getMinAllGlobalIndex();
309 RCP<const Map> dualDofMap = A01->getDomainMap();
311 dualDofMap->getMaxAllGlobalIndex(), dualBlockDim, dualDofOffset, dualDofMap->getIndexBase());
313 dualDofMap->getMinAllGlobalIndex(), dualBlockDim, dualDofOffset, dualDofMap->getIndexBase());
316 <<
", block dim = " << dualBlockDim
317 <<
", gid offset = " << dualDofOffset
321 <<
"/" << numDofsPerDualNode <<
"]" << std::endl;
324 Array<GlobalOrdinal> dualNodeId2primalNodeId(gMaxDualNodeId - gMinDualNodeId + 1, -GO_ONE);
325 Array<GlobalOrdinal> local_dualNodeId2primalNodeId(gMaxDualNodeId - gMinDualNodeId + 1, -GO_ONE);
328 Array<GlobalOrdinal> dualNodeId2primalAggId(gMaxDualNodeId - gMinDualNodeId + 1, -GO_ONE);
329 Array<GlobalOrdinal> local_dualNodeId2primalAggId(gMaxDualNodeId - gMinDualNodeId + 1, -GO_ONE);
331 Array<GlobalOrdinal> dualDofId2primalDofId(primalInterfaceDofRowMap->getGlobalNumElements(), -GO_ONE);
332 Array<GlobalOrdinal> local_dualDofId2primalDofId(primalInterfaceDofRowMap->getGlobalNumElements(), -GO_ONE);
335 const size_t numMyPrimalInterfaceDOFs = primalInterfaceDofRowMap->getLocalNumElements();
336 for (
size_t r = 0; r < numMyPrimalInterfaceDOFs; r += numDofsPerPrimalNode)
338 GlobalOrdinal gPrimalRowId = primalInterfaceDofRowMap->getGlobalElement(r);
340 if (A01->getRowMap()->isNodeGlobalElement(gPrimalRowId))
342 const LocalOrdinal lPrimalRowId = A01->getRowMap()->getLocalElement(gPrimalRowId);
344 const LocalOrdinal lPrimalNodeId = lPrimalRowId / numDofsPerPrimalNode;
345 const LocalOrdinal primalAggId = primalVertex2AggId[lPrimalNodeId];
347 const GlobalOrdinal gDualDofId = A01->getColMap()->getGlobalElement(r);
351 if (local_dualNodeId2primalNodeId[gDualNodeId - gMinDualNodeId] == -GO_ONE) {
352 local_dualNodeId2primalNodeId[gDualNodeId - gMinDualNodeId] = gPrimalNodeId;
353 local_dualNodeId2primalAggId[gDualNodeId - gMinDualNodeId] = primalAggId;
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;
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]);
372 std::vector<GlobalOrdinal> dualNodes;
373 for (
size_t r = 0; r < A01->getDomainMap()->getLocalNumElements(); r++)
378 GlobalOrdinal gDualDofId = A01->getDomainMap()->getGlobalElement(r);
380 dualNodes.push_back(gDualNodeId);
384 dualNodes.erase(std::unique(dualNodes.begin(), dualNodes.end()), dualNodes.end());
387 Teuchos::RCP<const Map> dualNodeMap = MapFactory::Build(A01->getRowMap()->lib(),
388 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), dualNodes, A01->getRowMap()->getIndexBase(), comm);
391 Teuchos::RCP<Aggregates> dualAggregates = Teuchos::rcp(
new Aggregates(dualNodeMap));
392 dualAggregates->setObjectLabel(
"UC (dual variables)");
395 Teuchos::ArrayRCP<LocalOrdinal> dualVertex2AggId = dualAggregates->GetVertex2AggId()->getDataNonConst(0);
396 Teuchos::ArrayRCP<LocalOrdinal> dualProcWinner = dualAggregates->GetProcWinner()->getDataNonConst(0);
400 std::map<GlobalOrdinal, LocalOrdinal> primalAggId2localDualAggId;
401 for (
size_t lDualNodeID = 0; lDualNodeID < dualNodeMap->getLocalNumElements(); ++lDualNodeID)
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;
412 const GlobalOrdinal offset = A01->getColMap()->getMinAllGlobalIndex();
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);
427 TEUCHOS_ASSERT(A01->isFillComplete());
429 RCP<AmalgamationInfo> dualAmalgamationInfo = rcp(
new AmalgamationInfo(rowTranslation, colTranslation,
430 A01->getDomainMap(), A01->getDomainMap(), A01->getDomainMap(),
431 fullblocksize, offset, blockid, nStridedOffset, stridedblocksize));
433 dualAggregates->SetNumAggregates(nLocalAggregates);
434 dualAggregates->AggregatesCrossProcessors(primalAggregates->AggregatesCrossProcessors());
436 if (dualAggregates->AggregatesCrossProcessors())
437 GetOStream(
Runtime1) <<
"Interface aggregates cross processor boundaries." << std::endl;
439 GetOStream(
Runtime1) <<
"Interface aggregates do not cross processor boundaries." << std::endl;
441 currentLevel.
Set(
"Aggregates", dualAggregates,
this);
442 currentLevel.
Set(
"UnAmalgamationInfo", dualAmalgamationInfo,
this);