MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_EdgeProlongatorPatternFactory_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_EDGEPROLONGATORPATTERNFACTORY_DEF_HPP
11#define MUELU_EDGEPROLONGATORPATTERNFACTORY_DEF_HPP
12
13#include <Xpetra_Matrix.hpp>
14#include <Xpetra_MatrixMatrix.hpp>
15
17
18#include "MueLu_Monitor.hpp"
19#include "Teuchos_ScalarTraits.hpp"
20
21namespace MueLu {
22
23template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
25 RCP<ParameterList> validParamList = rcp(new ParameterList());
26
27 validParamList->set<RCP<const FactoryBase> >("FineD0", Teuchos::null, "Generating factory for the fine discrete gradient");
28 validParamList->set<RCP<const FactoryBase> >("CoarseD0", Teuchos::null, "Generating factory for the coarse discrete gradient");
29 validParamList->set<RCP<const FactoryBase> >("PnodalEmin", Teuchos::null, "Generating factory for the nodal prolongator");
30
31 return validParamList;
32}
33
34template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
36 Input(fineLevel, "D0", "FineD0");
37 Input(coarseLevel, "D0", "CoarseD0");
38 Input(coarseLevel, "PnodalEmin");
39}
40
41template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
43 FactoryMonitor m(*this, "EdgeProlongatorPattern", coarseLevel);
44
45 auto D = Get<RCP<Matrix> >(fineLevel, "D0", "FineD0");
46 auto Dc = Get<RCP<Matrix> >(coarseLevel, "D0", "CoarseD0");
47 auto Pn = Get<RCP<Matrix> >(coarseLevel, "PnodalEmin");
48
49 const auto one = Teuchos::ScalarTraits<Scalar>::one();
50 const auto invalid = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
51
52 // |FineD| * |Pnodal| * |CoarseD^T|
53
54 RCP<Matrix> absD_absPn_absDcT;
55 RCP<Matrix> absDc;
56 {
57 SubFactoryMonitor m2(*this, "Matrix manipulations", coarseLevel);
58
59 auto absD = MatrixFactory::BuildCopy(D);
60 absD->setAllToScalar(one);
61
62 auto absPn = MatrixFactory::BuildCopy(Pn);
63 absPn->setAllToScalar(one);
64
65 RCP<Matrix> absD_absPn = MatrixMatrix::Multiply(*absD, false, *absPn, false, GetOStream(Statistics2), true, true);
66 absD_absPn->setAllToScalar(one);
67
68 // If we rebalanced then Dc lives on a smaller communicator than D.
69 // Since we need to perform matrix-matrix multiplications with Dc, we construct a version of it that lives on the same communicator.
70 auto comm = absD_absPn->getRowMap()->getComm();
71 if (Dc.is_null() || Dc->getRowMap()->getComm()->getSize() < comm->getSize()) {
72 auto lib = absD_absPn->getRowMap()->lib();
73 if (Dc.is_null()) {
74 Kokkos::View<GlobalOrdinal*, typename Node::memory_space> dummy("", 0);
75 auto big_coarse_nodal_map = MapFactory::Build(lib, invalid, dummy, 0, comm);
76 auto big_coarse_edge_map = MapFactory::Build(lib, invalid, dummy, 0, comm);
77 auto big_coarse_nodal_colmap = MapFactory::Build(lib, invalid, dummy, 0, comm);
78
79 typename Matrix::local_matrix_device_type dummyLocalMatrix;
80 Dc = MatrixFactory::Build(dummyLocalMatrix, big_coarse_edge_map, big_coarse_nodal_colmap, big_coarse_nodal_map, big_coarse_edge_map);
81
82 } else {
83 auto big_coarse_nodal_map = MapFactory::Build(lib, invalid, Dc->getDomainMap()->getMyGlobalIndicesDevice(), 0, comm);
84 auto big_coarse_edge_map = MapFactory::Build(lib, invalid, Dc->getRangeMap()->getMyGlobalIndicesDevice(), 0, comm);
85 auto big_coarse_nodal_colmap = MapFactory::Build(lib, invalid, Dc->getColMap()->getMyGlobalIndicesDevice(), 0, comm);
86
87 Dc = MatrixFactory::Build(Dc->getLocalMatrixDevice(), big_coarse_edge_map, big_coarse_nodal_colmap, big_coarse_nodal_map, big_coarse_edge_map);
88 }
89 }
90 absDc = MatrixFactory::BuildCopy(Dc);
91 absDc->setAllToScalar(one);
92
93 absD_absPn_absDcT = MatrixMatrix::Multiply(*absD_absPn, false, *absDc, true, GetOStream(Statistics2), true, true);
94 }
95
96 RCP<Matrix> filtered;
97 {
98 SubFactoryMonitor m2(*this, "Filtering", coarseLevel);
99 using ATS = KokkosKernels::ArithTraits<typename Matrix::impl_scalar_type>;
100 using magnitudeType = typename ATS::magnitudeType;
101 using magATS = KokkosKernels::ArithTraits<magnitudeType>;
102 auto eps = magATS::epsilon();
103
104 RCP<MultiVector> oneVec = MultiVectorFactory::Build(absDc->getDomainMap(), 1);
105 oneVec->putScalar(one);
106 RCP<MultiVector> singleParent = MultiVectorFactory::Build(absDc->getRowMap(), 1);
107 absDc->apply(*oneVec, *singleParent, Teuchos::NO_TRANS);
108 // ghost singleParent
109 RCP<MultiVector> singleParentGhosted;
110 auto importer = absD_absPn_absDcT->getCrsGraph()->getImporter();
111 if (importer.is_null()) {
112 singleParentGhosted = singleParent;
113 } else {
114 singleParentGhosted = MultiVectorFactory::Build(importer->getTargetMap(), 1);
115 singleParentGhosted->doImport(*singleParent, *importer, Xpetra::INSERT);
116 }
117
118 auto lclSingleParent = singleParentGhosted->getLocalViewDevice(Tpetra::Access::ReadOnly);
119
120 // Filter matrix using criterion
121 filtered = Xpetra::applyFilter_LID(
122 absD_absPn_absDcT,
123 KOKKOS_LAMBDA(const LocalOrdinal /*row*/,
124 const LocalOrdinal col,
125 const typename Matrix::impl_scalar_type val) {
126 return ((ATS::magnitude(val - 2.0) < eps) || ((lclSingleParent(col, 0) == 1.0) && (ATS::magnitude(val - 1.0) < eps)));
127 });
128
129 if (IsPrint(Statistics1)) {
130 auto numEntriesBeforeFiltering = absD_absPn_absDcT->getGlobalNumEntries();
131 auto numEntriesAfterFiltering = filtered->getGlobalNumEntries();
132 GetOStream(Statistics1) << "Number of kept entries in filtered pattern for P: " << numEntriesAfterFiltering << "/" << numEntriesBeforeFiltering << std::endl;
133 }
134 }
135
136 auto Ppattern = filtered->getCrsGraph();
137
138 Set(coarseLevel, "Ppattern", Ppattern);
139}
140
141} // namespace MueLu
142
143#endif // MUELU_EDGEPROLONGATORPATTERNFACTORY_DEF_HPP
MueLu::DefaultLocalOrdinal LocalOrdinal
void Build(Level &fineLevel, Level &coarseLevel) const
Build method.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
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.
@ Statistics2
Print even more statistics.
@ Statistics1
Print more statistics.