31 Projection(RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >& Nullspace) {
32 localMap_ = Xpetra::MapFactory<LocalOrdinal, GlobalOrdinal, Node>::Build(Nullspace->getMap()->lib(),
33 Nullspace->getNumVectors(),
34 Nullspace->getMap()->getIndexBase(),
35 Nullspace->getMap()->getComm(),
36 Xpetra::LocallyReplicated);
38 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tempMV = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(
localMap_, Nullspace->getNumVectors());
39 const Scalar ONE = Teuchos::ScalarTraits<Scalar>::one();
40 const Scalar ZERO = Teuchos::ScalarTraits<Scalar>::zero();
41 tempMV->multiply(Teuchos::CONJ_TRANS, Teuchos::NO_TRANS, ONE, *Nullspace, *Nullspace, ZERO);
43 Kokkos::View<Scalar**, Kokkos::LayoutLeft, Kokkos::HostSpace> Q(
"Q", Nullspace->getNumVectors(), Nullspace->getNumVectors());
46 auto dots = tempMV->getLocalViewHost(Tpetra::Access::ReadOnly);
47 Kokkos::deep_copy(Q, dots);
51 Teuchos::LAPACK<LocalOrdinal, Scalar> lapack;
53 lapack.POTRF(
'L', Nullspace->getNumVectors(), Q.data(), LDQ, &info);
54 TEUCHOS_ASSERT(info == 0);
55 lapack.TRTRI(
'L',
'N', Nullspace->getNumVectors(), Q.data(), LDQ, &info);
56 TEUCHOS_ASSERT(info == 0);
58 Nullspace_ = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(Nullspace->getMap(), Nullspace->getNumVectors());
60 for (
size_t i = 0; i < Nullspace->getNumVectors(); i++) {
61 for (
size_t j = 0; j <= i; j++) {
62 Nullspace_->getVectorNonConst(i)->update(Q(i, j), *Nullspace->getVector(j), ONE);
69 projectOut(Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& X) {
70 const Scalar ONE = Teuchos::ScalarTraits<Scalar>::one();
71 const Scalar ZERO = Teuchos::ScalarTraits<Scalar>::zero();
75 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tempMV = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(
localMap_, X.getNumVectors());
76 tempMV->multiply(Teuchos::CONJ_TRANS, Teuchos::NO_TRANS, ONE, *
Nullspace_, X, ZERO);
77 auto dots = tempMV->getLocalViewHost(Tpetra::Access::ReadOnly);
78 bool doProject =
true;
79 for (
size_t i = 0; i < X.getNumVectors(); i++) {
80 for (
size_t j = 0; j <
Nullspace_->getNumVectors(); j++) {
81 doProject = doProject || (Teuchos::ScalarTraits<Scalar>::magnitude(dots(j, i)) > 100 * Teuchos::ScalarTraits<Scalar>::eps());
85 for (
size_t i = 0; i < X.getNumVectors(); i++) {
86 for (
size_t j = 0; j <
Nullspace_->getNumVectors(); j++) {
87 X.getVectorNonConst(i)->update(-dots(j, i), *
Nullspace_->getVector(j), ONE);
166 this->
GetOStream(
Warnings0) <<
"MueLu::Amesos2Smoother::Setup(): Setup() has already been called" << std::endl;
171 RCP<const Map> rowMap = A->getRowMap();
175 if (pL.get<
bool>(
"fix nullspace")) {
176 this->
GetOStream(
Runtime1) <<
"MueLu::Amesos2Smoother::Setup(): fixing nullspace" << std::endl;
178 rowMap = A->getRowMap();
179 size_t gblNumCols = rowMap->getGlobalNumElements();
184 RCP<MultiVector> Nullspace =
projection_->Nullspace_;
186 RCP<MultiVector> ghostedNullspace;
187 RCP<const Map> colMap;
188 RCP<const Import> importer;
189 if (rowMap->getComm()->getSize() > 1) {
190 this->
GetOStream(
Warnings0) <<
"MueLu::Amesos2Smoother::Setup(): Applying nullspace fix on distributed matrix. Try rebalancing to single rank!" << std::endl;
191 ArrayRCP<GO> elements_RCP;
192 elements_RCP.resize(gblNumCols);
193 ArrayView<GO> elements = elements_RCP();
194 for (
size_t k = 0; k < gblNumCols; k++)
195 elements[k] = Teuchos::as<GO>(k);
196 colMap = MapFactory::Build(rowMap->lib(), gblNumCols * rowMap->getComm()->getSize(), elements, Teuchos::ScalarTraits<GO>::zero(), rowMap->getComm());
197 importer = ImportFactory::Build(rowMap, colMap);
198 ghostedNullspace = MultiVectorFactory::Build(colMap, Nullspace->getNumVectors());
199 ghostedNullspace->doImport(*Nullspace, *importer, Xpetra::INSERT);
201 ghostedNullspace = Nullspace;
205#if KOKKOS_VERSION >= 40799
206 using ATS = KokkosKernels::ArithTraits<SC>;
208 using ATS = Kokkos::ArithTraits<SC>;
210 using impl_Scalar =
typename ATS::val_type;
211#if KOKKOS_VERSION >= 40799
212 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
214 using impl_ATS = Kokkos::ArithTraits<impl_Scalar>;
216 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
218 typedef typename Matrix::local_matrix_device_type KCRS;
219 typedef typename KCRS::StaticCrsGraphType graph_t;
220 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
221 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
222 typedef typename KCRS::values_type::non_const_type scalar_view_t;
224 const impl_Scalar impl_SC_ZERO = impl_ATS::zero();
226 size_t lclNumRows = rowMap->getLocalNumElements();
227 LocalOrdinal lclNumCols = Teuchos::as<LocalOrdinal>(gblNumCols);
228 lno_view_t newRowPointers(
"newRowPointers", lclNumRows + 1);
229 lno_nnz_view_t newColIndices(
"newColIndices", lclNumRows * gblNumCols);
230 scalar_view_t newValues(
"newValues", lclNumRows * gblNumCols);
234 RCP<Vector> diag = VectorFactory::Build(A->getRowMap());
235 A->getLocalDiagCopy(*diag);
236 shift = diag->normInf();
241 auto lclNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
242 auto lclGhostedNullspace = ghostedNullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
243 Kokkos::parallel_for(
244 "MueLu:Amesos2Smoother::fixNullspace_1", range_type(0, lclNumRows + 1),
245 KOKKOS_LAMBDA(
const size_t i) {
246 if (i < lclNumRows) {
247 newRowPointers(i) = i * gblNumCols;
249 newColIndices(i * gblNumCols + j) = j;
250 newValues(i * gblNumCols + j) = impl_SC_ZERO;
251 for (
size_t I = 0;
I < lclNullspace.extent(1);
I++)
252 for (
size_t J = 0; J < lclGhostedNullspace.extent(1); J++)
253 newValues(i * gblNumCols + j) += shift * lclNullspace(i,
I) * impl_ATS::conjugate(lclGhostedNullspace(j, J));
256 newRowPointers(lclNumRows) = lclNumRows * gblNumCols;
261 if (colMap->lib() == Xpetra::UseTpetra) {
262 auto lclA = A->getLocalMatrixDevice();
263 auto lclColMapA = A->getColMap()->getLocalMap();
264 auto lclColMapANew = colMap->getLocalMap();
265 Kokkos::parallel_for(
266 "MueLu:Amesos2Smoother::fixNullspace_2", range_type(0, lclNumRows),
267 KOKKOS_LAMBDA(
const size_t i) {
268 for (
size_t jj = lclA.graph.row_map(i); jj < lclA.graph.row_map(i + 1); jj++) {
269 LO j = lclColMapANew.getLocalElement(lclColMapA.getGlobalElement(lclA.graph.entries(jj)));
270 impl_Scalar v = lclA.values(jj);
271 newValues(i * gblNumCols + j) += v;
275 auto lclA = A->getLocalMatrixHost();
276 for (
size_t i = 0; i < lclNumRows; i++) {
277 for (
size_t jj = lclA.graph.row_map(i); jj < lclA.graph.row_map(i + 1); jj++) {
278 LO j = colMap->getLocalElement(A->getColMap()->getGlobalElement(lclA.graph.entries(jj)));
279 SC v = lclA.values(jj);
280 newValues(i * gblNumCols + j) += v;
285 RCP<Matrix> newA = rcp(
new CrsMatrixWrap(rowMap, colMap, 0));
286 RCP<CrsMatrix> newAcrs = toCrsMatrix(newA);
287 newAcrs->setAllValues(newRowPointers, newColIndices, newValues);
288 newAcrs->expertStaticFillComplete(A->getDomainMap(), A->getRangeMap(),
289 importer, A->getCrsGraph()->getExporter());
292 rowMap = factorA->getRowMap();
297 RCP<const Tpetra_CrsMatrix> tA = toTpetra(factorA);
299 prec_ = Amesos2::create<Tpetra_CrsMatrix, Tpetra_MultiVector>(
type_, tA);
301 RCP<Teuchos::ParameterList> amesos2_params = Teuchos::rcpFromRef(pL.sublist(
"Amesos2"));
302 amesos2_params->setName(
"Amesos2");
303 if ((rowMap->getGlobalNumElements() != as<size_t>((rowMap->getMaxAllGlobalIndex() - rowMap->getMinAllGlobalIndex()) + 1)) ||
304 (!rowMap->isContiguous() && (rowMap->getComm()->getSize() == 1))) {
305 if (((
type_ !=
"Cusolver") && (
type_ !=
"Tacho")) && !(amesos2_params->sublist(
prec_->name()).template isType<bool>(
"IsContiguous")))
306 amesos2_params->sublist(
prec_->name()).set(
"IsContiguous",
false,
"Are GIDs Contiguous");
308 prec_->setParameters(amesos2_params);
310 prec_->numericFactorization();