50 typedef Teuchos::ScalarTraits<SC> STS;
52 const ParameterList& pL = GetParameterList();
54 RCP<Matrix> A = Get<RCP<Matrix> >(currentLevel,
"A");
56 Teuchos::RCP<const Teuchos::Comm<int> > comm = A->getRowMap()->getComm();
57 Xpetra::UnderlyingLib lib = A->getRowMap()->lib();
59 typedef Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO> dxMV;
60 RCP<dxMV> Coords = Get<RCP<Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO> > >(currentLevel,
"Coordinates");
62 int maxDofPerNode = pL.get<
int>(
"maxDofPerNode");
63 Scalar dirDropTol = Teuchos::as<Scalar>(pL.get<
double>(
"Advanced Dirichlet: threshold"));
64 Scalar amalgDropTol = Teuchos::as<Scalar>(pL.get<
double>(
"Variable DOF amalgamation: threshold"));
66 bool bHasZeroDiagonal =
false;
70 Teuchos::ArrayRCP<LocalOrdinal> dofPresent;
72 dofPresent = currentLevel.
Get<Teuchos::ArrayRCP<LocalOrdinal> >(
"DofPresent",
NoFactory::get());
75 dofPresent = Teuchos::ArrayRCP<LocalOrdinal>(A->getRowMap()->getLocalNumElements(), 1);
84 std::vector<LocalOrdinal> map(A->getLocalNumRows());
85 this->buildPaddedMap(dofPresent, map, A->getLocalNumRows());
88 std::vector<LocalOrdinal> myLocalNodeIds(A->getColMap()->getLocalNumElements());
91 size_t nLocalNodes, nLocalPlusGhostNodes;
92 this->assignGhostLocalNodeIds(A->getRowMap(), A->getColMap(), myLocalNodeIds, map, maxDofPerNode, nLocalNodes, nLocalPlusGhostNodes, comm);
96 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::as<size_t>(dofPresent.size()) != Teuchos::as<size_t>(nLocalNodes * maxDofPerNode),
MueLu::Exceptions::RuntimeError,
"VariableDofLaplacianFactory: size of provided DofPresent array is " << dofPresent.size() <<
" but should be " << nLocalNodes * maxDofPerNode <<
" on the current processor.");
102 Teuchos::ArrayView<const GlobalOrdinal> myGids = A->getColMap()->getLocalElementList();
106 size_t nLocalDofs = A->getRowMap()->getLocalNumElements();
107 size_t nLocalPlusGhostDofs = A->getColMap()->getLocalNumElements();
111 Teuchos::Array<GlobalOrdinal> amalgRowMapGIDs(nLocalNodes);
112 Teuchos::Array<GlobalOrdinal> amalgColMapGIDs(nLocalPlusGhostNodes);
116 if (nLocalDofs > 0) {
117 amalgRowMapGIDs[count] = myGids[0];
118 amalgColMapGIDs[count] = myGids[0];
122 for (
size_t i = 1; i < nLocalDofs; i++) {
123 if (myLocalNodeIds[i] != myLocalNodeIds[i - 1]) {
124 amalgRowMapGIDs[count] = myGids[i];
125 amalgColMapGIDs[count] = myGids[i];
130 RCP<GOVector> tempAmalgColVec = GOVectorFactory::Build(A->getDomainMap());
132 Teuchos::ArrayRCP<GlobalOrdinal> tempAmalgColVecData = tempAmalgColVec->getDataNonConst(0);
133 for (
size_t i = 0; i < A->getDomainMap()->getLocalNumElements(); i++)
134 tempAmalgColVecData[i] = amalgColMapGIDs[myLocalNodeIds[i]];
137 RCP<GOVector> tempAmalgColVecTarget = GOVectorFactory::Build(A->getColMap());
138 Teuchos::RCP<Import> dofImporter = ImportFactory::Build(A->getDomainMap(), A->getColMap());
139 tempAmalgColVecTarget->doImport(*tempAmalgColVec, *dofImporter, Xpetra::INSERT);
142 Teuchos::ArrayRCP<const GlobalOrdinal> tempAmalgColVecBData = tempAmalgColVecTarget->getData(0);
144 for (
size_t i = 0; i < myLocalNodeIds.size(); i++)
145 amalgColMapGIDs[myLocalNodeIds[i]] = tempAmalgColVecBData[i];
148 Teuchos::RCP<Map> amalgRowMap = MapFactory::Build(lib,
149 Teuchos::OrdinalTraits<GlobalOrdinal>::invalid(),
151 A->getRowMap()->getIndexBase(),
154 Teuchos::RCP<Map> amalgColMap = MapFactory::Build(lib,
155 Teuchos::OrdinalTraits<GlobalOrdinal>::invalid(),
157 A->getRangeMap()->getIndexBase(),
164 Teuchos::RCP<CrsMatrix> Acrs = toCrsMatrix(A);
167 size_t nNonZeros = 0;
168 std::vector<bool> isNonZero(nLocalPlusGhostDofs,
false);
169 std::vector<size_t> nonZeroList(nLocalPlusGhostDofs);
172 Teuchos::RCP<Vector> diagVecUnique = VectorFactory::Build(A->getRowMap());
173 Teuchos::RCP<Vector> diagVec = VectorFactory::Build(A->getColMap());
174 A->getLocalDiagCopy(*diagVecUnique);
175 diagVec->doImport(*diagVecUnique, *dofImporter, Xpetra::INSERT);
176 Teuchos::ArrayRCP<const Scalar> diagVecData = diagVec->getData(0);
178 Teuchos::ArrayRCP<const size_t> rowptr(Acrs->getLocalNumRows());
179 Teuchos::ArrayRCP<const LocalOrdinal> colind(Acrs->getLocalNumEntries());
180 Teuchos::ArrayRCP<const Scalar> values(Acrs->getLocalNumEntries());
181 Acrs->getAllValues(rowptr, colind, values);
184 Teuchos::ArrayRCP<size_t> amalgRowPtr(nLocalNodes + 1);
185 Teuchos::ArrayRCP<LocalOrdinal> amalgCols(rowptr[rowptr.size() - 1]);
192 amalgRowPtr[0] = newNzs;
194 bool doNotDrop =
false;
195 if (amalgDropTol == Teuchos::ScalarTraits<Scalar>::zero()) doNotDrop =
true;
196 if (values.size() == 0) doNotDrop =
true;
198 for (
decltype(rowptr.size()) i = 0; i < rowptr.size() - 1; i++) {
199 blockRow = std::floor<LocalOrdinal>(map[i] / maxDofPerNode);
200 if (blockRow != oldBlockRow) {
202 for (
size_t j = 0; j < nNonZeros; j++) isNonZero[nonZeroList[j]] =
false;
204 amalgRowPtr[blockRow] = newNzs;
206 for (
size_t j = rowptr[i]; j < rowptr[i + 1]; j++) {
207 if (doNotDrop ==
true ||
208 (STS::magnitude(values[j] / STS::magnitude(sqrt(STS::magnitude(diagVecData[i]) * STS::magnitude(diagVecData[colind[j]])))) >= STS::magnitude(amalgDropTol))) {
209 blockColumn = myLocalNodeIds[colind[j]];
210 if (isNonZero[blockColumn] ==
false) {
211 isNonZero[blockColumn] =
true;
212 nonZeroList[nNonZeros++] = blockColumn;
213 amalgCols[newNzs++] = blockColumn;
217 oldBlockRow = blockRow;
219 amalgRowPtr[blockRow + 1] = newNzs;
221 TEUCHOS_TEST_FOR_EXCEPTION((blockRow + 1 != Teuchos::as<LO>(nLocalNodes)) && (nLocalNodes != 0),
MueLu::Exceptions::RuntimeError,
"VariableDofsPerNodeAmalgamation: error, computed # block rows (" << blockRow + 1 <<
") != nLocalNodes (" << nLocalNodes <<
")");
223 amalgCols.resize(amalgRowPtr[nLocalNodes]);
242 Teuchos::ArrayRCP<LocalOrdinal> uniqueId(nLocalPlusGhostNodes);
243 std::vector<bool> keep(amalgRowPtr[amalgRowPtr.size() - 1],
true);
246 for (
decltype(amalgRowPtr.size()) i = 0; i < amalgRowPtr.size() - 1; i++) {
249 for (
decltype(maxDofPerNode) j = 0; j < maxDofPerNode; j++) {
250 if (dofPresent[ii++]) uniqueId[i] += temp;
255 Teuchos::RCP<Import> nodeImporter = ImportFactory::Build(amalgRowMap, amalgColMap);
257 RCP<LOVector> nodeIdSrc = Xpetra::VectorFactory<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node>::Build(amalgRowMap,
true);
258 RCP<LOVector> nodeIdTarget = Xpetra::VectorFactory<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node>::Build(amalgColMap,
true);
260 Teuchos::ArrayRCP<LocalOrdinal> nodeIdSrcData = nodeIdSrc->getDataNonConst(0);
261 for (
decltype(amalgRowPtr.size()) i = 0; i < amalgRowPtr.size() - 1; i++) {
262 nodeIdSrcData[i] = uniqueId[i];
265 nodeIdTarget->doImport(*nodeIdSrc, *nodeImporter, Xpetra::INSERT);
267 Teuchos::ArrayRCP<const LocalOrdinal> nodeIdTargetData = nodeIdTarget->getData(0);
268 for (
decltype(uniqueId.size()) i = 0; i < uniqueId.size(); i++) {
269 uniqueId[i] = nodeIdTargetData[i];
276 for (
decltype(amalgRowPtr.size()) i = 0; i < amalgRowPtr.size() - 1; i++) {
277 for (
size_t j = amalgRowPtr[i]; j < amalgRowPtr[i + 1]; j++) {
278 if (uniqueId[i] != uniqueId[amalgCols[j]]) keep[j] =
false;
283 Teuchos::ArrayRCP<Scalar> amalgVals;
284 this->squeezeOutNnzs(amalgRowPtr, amalgCols, amalgVals, keep);
286 typedef Xpetra::MultiVectorFactory<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO> dxMVf;
287 RCP<dxMV> ghostedCoords = dxMVf::Build(amalgColMap, Coords->getNumVectors());
289 TEUCHOS_TEST_FOR_EXCEPTION(amalgRowMap->getLocalNumElements() != Coords->getMap()->getLocalNumElements(),
MueLu::Exceptions::RuntimeError,
"MueLu::VariableDofLaplacianFactory: the number of Coordinates and amalgamated nodes is inconsistent.");
297 RCP<dxMV> CoordsCopy = dxMVf::Build(Coords, Teuchos::Copy);
298 CoordsCopy->replaceMap(amalgRowMap);
299 ghostedCoords->doImport(*CoordsCopy, *nodeImporter, Xpetra::INSERT);
301 Teuchos::ArrayRCP<Scalar> lapVals(amalgRowPtr[nLocalNodes]);
302 this->buildLaplacian(amalgRowPtr, amalgCols, lapVals, Coords->getNumVectors(), ghostedCoords);
305 for (
decltype(amalgRowPtr.size()) i = 0; i < amalgRowPtr.size() - 1; i++) {
306 size_t j = amalgRowPtr[i];
307 this->MueLu_az_sort<LocalOrdinal>(&(amalgCols[j]), amalgRowPtr[i + 1] - j, NULL, &(lapVals[j]));
311 Teuchos::Array<char> status(nLocalNodes * maxDofPerNode);
314 for (
decltype(status.size()) i = 0; i < status.size(); i++) status[i] =
's';
315 for (
decltype(status.size()) i = 0; i < status.size(); i++) {
316 if (dofPresent[i] ==
false) status[i] =
'p';
318 if (dirOrNot.size() > 0) {
319 for (
decltype(map.size()) i = 0; i < map.size(); i++) {
320 if (dirOrNot[i] ==
true) {
321 status[map[i]] =
'd';
325 Set(currentLevel,
"DofStatus", status);
329 Teuchos::RCP<CrsMatrix> lapCrsMat = CrsMatrixFactory::Build(amalgRowMap, amalgColMap, 10);
331 for (
size_t i = 0; i < nLocalNodes; i++) {
332 lapCrsMat->insertLocalValues(i, amalgCols.view(amalgRowPtr[i], amalgRowPtr[i + 1] - amalgRowPtr[i]),
333 lapVals.view(amalgRowPtr[i], amalgRowPtr[i + 1] - amalgRowPtr[i]));
335 lapCrsMat->fillComplete(amalgRowMap, amalgRowMap);
339 Teuchos::RCP<Matrix> lapMat = Teuchos::rcp(
new CrsMatrixWrap(lapCrsMat));
340 Set(currentLevel,
"A", lapMat);
344void VariableDofLaplacianFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::buildLaplacian(
const Teuchos::ArrayRCP<size_t>& rowPtr,
const Teuchos::ArrayRCP<LocalOrdinal>& cols, Teuchos::ArrayRCP<Scalar>& vals,
const size_t& numdim,
const RCP<Xpetra::MultiVector<
typename Teuchos::ScalarTraits<Scalar>::magnitudeType,
LocalOrdinal,
GlobalOrdinal,
Node> >& ghostedCoords)
const {
345 TEUCHOS_TEST_FOR_EXCEPTION(numdim != 2 && numdim != 3,
MueLu::Exceptions::RuntimeError,
"buildLaplacian only works for 2d or 3d examples. numdim = " << numdim);
348 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::magnitudeType> x = ghostedCoords->getData(0);
349 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::magnitudeType> y = ghostedCoords->getData(1);
351 for (
decltype(rowPtr.size()) i = 0; i < rowPtr.size() - 1; i++) {
352 Scalar sum = Teuchos::ScalarTraits<Scalar>::zero();
354 for (
size_t j = rowPtr[i]; j < rowPtr[i + 1]; j++) {
355 if (cols[j] != Teuchos::as<LO>(i)) {
356 vals[j] = std::sqrt((x[i] - x[cols[j]]) * (x[i] - x[cols[j]]) +
357 (y[i] - y[cols[j]]) * (y[i] - y[cols[j]]));
358 TEUCHOS_TEST_FOR_EXCEPTION(vals[j] == Teuchos::ScalarTraits<Scalar>::zero(),
MueLu::Exceptions::RuntimeError,
"buildLaplacian: error, " << i <<
" and " << cols[j] <<
" have same coordinates: " << x[i] <<
" and " << y[i]);
359 vals[j] = -Teuchos::ScalarTraits<SC>::one() / vals[j];
364 if (sum == Teuchos::ScalarTraits<Scalar>::zero()) sum = Teuchos::ScalarTraits<Scalar>::one();
370 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::magnitudeType> x = ghostedCoords->getData(0);
371 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::magnitudeType> y = ghostedCoords->getData(1);
372 Teuchos::ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::magnitudeType> z = ghostedCoords->getData(2);
374 for (
decltype(rowPtr.size()) i = 0; i < rowPtr.size() - 1; i++) {
375 Scalar sum = Teuchos::ScalarTraits<Scalar>::zero();
377 for (
size_t j = rowPtr[i]; j < rowPtr[i + 1]; j++) {
378 if (cols[j] != Teuchos::as<LO>(i)) {
379 vals[j] = std::sqrt((x[i] - x[cols[j]]) * (x[i] - x[cols[j]]) +
380 (y[i] - y[cols[j]]) * (y[i] - y[cols[j]]) +
381 (z[i] - z[cols[j]]) * (z[i] - z[cols[j]]));
383 TEUCHOS_TEST_FOR_EXCEPTION(vals[j] == Teuchos::ScalarTraits<Scalar>::zero(),
MueLu::Exceptions::RuntimeError,
"buildLaplacian: error, " << i <<
" and " << cols[j] <<
" have same coordinates: " << x[i] <<
" and " << y[i] <<
" and " << z[i]);
385 vals[j] = -Teuchos::ScalarTraits<SC>::one() / vals[j];
390 if (sum == Teuchos::ScalarTraits<Scalar>::zero()) sum = Teuchos::ScalarTraits<Scalar>::one();
441void VariableDofLaplacianFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::assignGhostLocalNodeIds(
const Teuchos::RCP<const Map>& rowDofMap,
const Teuchos::RCP<const Map>& colDofMap, std::vector<LocalOrdinal>& myLocalNodeIds,
const std::vector<LocalOrdinal>& dofMap,
size_t maxDofPerNode,
size_t& nLocalNodes,
size_t& nLocalPlusGhostNodes, Teuchos::RCP<
const Teuchos::Comm<int> > comm)
const {
442 size_t nLocalDofs = rowDofMap->getLocalNumElements();
443 size_t nLocalPlusGhostDofs = colDofMap->getLocalNumElements();
446 Teuchos::RCP<Import> importer = ImportFactory::Build(rowDofMap, colDofMap);
449 Teuchos::RCP<LOVector> localNodeIdsTemp = LOVectorFactory::Build(rowDofMap,
true);
450 Teuchos::RCP<LOVector> localNodeIds = LOVectorFactory::Build(colDofMap,
true);
454 Teuchos::ArrayRCP<LocalOrdinal> localNodeIdsTempData = localNodeIdsTemp->getDataNonConst(0);
455 for (
size_t i = 0; i < localNodeIdsTemp->getLocalLength(); i++)
456 localNodeIdsTempData[i] = std::floor<LocalOrdinal>(dofMap[i] / maxDofPerNode);
459 localNodeIds->doImport(*localNodeIdsTemp, *importer, Xpetra::INSERT);
460 Teuchos::ArrayRCP<const LocalOrdinal> localNodeIdsData = localNodeIds->getData(0);
465 Teuchos::RCP<LOVector> myProcTemp = LOVectorFactory::Build(rowDofMap,
true);
466 Teuchos::RCP<LOVector> myProc = LOVectorFactory::Build(colDofMap,
true);
470 Teuchos::ArrayRCP<LocalOrdinal> myProcTempData = myProcTemp->getDataNonConst(0);
471 for (
size_t i = 0; i < myProcTemp->getLocalLength(); i++)
472 myProcTempData[i] = Teuchos::as<LocalOrdinal>(comm->getRank());
474 myProc->doImport(*myProcTemp, *importer, Xpetra::INSERT);
475 Teuchos::ArrayRCP<LocalOrdinal> myProcData = myProc->getDataNonConst(0);
489 std::vector<size_t> location(nLocalPlusGhostDofs - nLocalDofs + 1);
490 std::vector<size_t> tempId(nLocalPlusGhostDofs - nLocalDofs + 1);
491 std::vector<size_t> tempProc(nLocalPlusGhostDofs - nLocalDofs + 1);
493 size_t notProcessed = nLocalDofs;
494 size_t tempIndex = 0;
495 size_t first = tempIndex;
498 while (notProcessed < nLocalPlusGhostDofs) {
499 neighbor = myProcData[notProcessed];
501 location[tempIndex] = notProcessed;
502 tempId[tempIndex++] = localNodeIdsData[notProcessed];
503 myProcData[notProcessed] = -1 - neighbor;
505 for (
size_t i = notProcessed + 1; i < nLocalPlusGhostDofs; i++) {
506 if (myProcData[i] == neighbor) {
507 location[tempIndex] = i;
508 tempId[tempIndex++] = localNodeIdsData[i];
512 this->MueLu_az_sort<size_t>(&(tempId[first]), tempIndex - first, &(location[first]), NULL);
513 for (
size_t i = first; i < tempIndex; i++) tempProc[i] = neighbor;
517 while ((notProcessed < nLocalPlusGhostDofs) && (myProcData[notProcessed] < 0))
520 TEUCHOS_TEST_FOR_EXCEPTION(tempIndex != nLocalPlusGhostDofs - nLocalDofs,
MueLu::Exceptions::RuntimeError,
"Number of nonzero ghosts is inconsistent.");
527 if (nLocalDofs > 0) nLocalNodes = localNodeIdsData[nLocalDofs - 1] + 1;
529 nLocalPlusGhostNodes = nLocalNodes;
530 if (nLocalDofs < nLocalPlusGhostDofs) nLocalPlusGhostNodes++;
537 for (
size_t i = nLocalDofs + 1; i < nLocalPlusGhostDofs; i++) {
538 size_t lagged = nLocalPlusGhostNodes - 1;
541 if ((tempId[i - nLocalDofs] != tempId[i - 1 - nLocalDofs]) ||
542 (tempProc[i - nLocalDofs] != tempProc[i - 1 - nLocalDofs]))
543 nLocalPlusGhostNodes++;
544 tempId[i - 1 - nLocalDofs] = lagged;
546 if (nLocalPlusGhostDofs > nLocalDofs)
547 tempId[nLocalPlusGhostDofs - 1 - nLocalDofs] = nLocalPlusGhostNodes - 1;
550 for (
size_t i = 0; i < nLocalDofs; i++)
551 myLocalNodeIds[i] = std::floor<LocalOrdinal>(dofMap[i] / maxDofPerNode);
554 for (
size_t i = nLocalDofs; i < nLocalPlusGhostDofs; i++)
555 myLocalNodeIds[location[i - nLocalDofs]] = tempId[i - nLocalDofs];