35 Projection(RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >& Nullspace) {
36 localMap_ = Xpetra::MapFactory<LocalOrdinal, GlobalOrdinal, Node>::Build(Nullspace->getMap()->lib(),
37 Nullspace->getNumVectors(),
38 Nullspace->getMap()->getIndexBase(),
39 Nullspace->getMap()->getComm(),
40 Xpetra::LocallyReplicated);
42 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tempMV = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(localMap_, Nullspace->getNumVectors(),
false);
43 const Scalar ONE = Teuchos::ScalarTraits<Scalar>::one();
44 const Scalar ZERO = Teuchos::ScalarTraits<Scalar>::zero();
45 tempMV->multiply(Teuchos::CONJ_TRANS, Teuchos::NO_TRANS, ONE, *Nullspace, *Nullspace, ZERO);
47 Kokkos::View<typename Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::impl_scalar_type**, Kokkos::LayoutLeft, Kokkos::HostSpace> Q(
"Q", Nullspace->getNumVectors(), Nullspace->getNumVectors());
49 auto dots = tempMV->getLocalViewHost(Tpetra::Access::ReadOnly);
50 Kokkos::deep_copy(Q, dots);
53 KokkosLapack::potrf(
"L", Q);
54 int ret = KokkosLapack::trtri(
"L",
"N", Q);
55 TEUCHOS_ASSERT(ret == 0);
57 Nullspace_ = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(Nullspace->getMap(), Nullspace->getNumVectors());
59 for (
size_t i = 0; i < Nullspace->getNumVectors(); i++) {
60 for (
size_t j = 0; j <= i; j++) {
61 Nullspace_->getVectorNonConst(i)->update(Q(i, j), *Nullspace->getVector(j), ONE);
68 projectOut(Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& X) {
69 const Scalar ONE = Teuchos::ScalarTraits<Scalar>::one();
70 const Scalar ZERO = Teuchos::ScalarTraits<Scalar>::zero();
74 if (tempMV_.is_null() || tempMV_->getNumVectors() != X.getNumVectors())
75 tempMV_ = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(localMap_, X.getNumVectors());
76 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >& tempMV = tempMV_;
77 tempMV->multiply(Teuchos::CONJ_TRANS, Teuchos::NO_TRANS, ONE, *Nullspace_, X, ZERO);
78 auto dots = tempMV->getLocalViewHost(Tpetra::Access::ReadOnly);
79 bool doProject =
true;
80 for (
size_t i = 0; i < X.getNumVectors(); i++) {
81 for (
size_t j = 0; j < Nullspace_->getNumVectors(); j++) {
82 doProject = doProject || (Teuchos::ScalarTraits<Scalar>::magnitude(dots(j, i)) > 100 * Teuchos::ScalarTraits<Scalar>::eps());
86 for (
size_t i = 0; i < X.getNumVectors(); i++) {
87 for (
size_t j = 0; j < Nullspace_->getNumVectors(); j++) {
88 X.getVectorNonConst(i)->update(-dots(j, i), *Nullspace_->getVector(j), ONE);
167 this->GetOStream(
Warnings0) <<
"MueLu::Amesos2Smoother::Setup(): Setup() has already been called" << std::endl;
169 RCP<Matrix> A = Factory::Get<RCP<Matrix> >(currentLevel,
"A");
170 auto A_block = rcp_dynamic_cast<BlockedCrsMatrix>(A);
172 A = A_block->Merge();
176 RCP<const Map> rowMap = A->getRowMap();
178 Teuchos::ParameterList pL = this->GetParameterList();
180 if (pL.get<
bool>(
"fix nullspace")) {
181 this->GetOStream(
Runtime1) <<
"MueLu::Amesos2Smoother::Setup(): fixing nullspace" << std::endl;
183 rowMap = A->getRowMap();
184 auto tpRowMap = Xpetra::toTpetra(rowMap);
185 if (!tpRowMap->haveGlobalConstants()) {
186 Teuchos::rcp_const_cast<Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> >(tpRowMap)->computeGlobalConstants();
188 size_t gblNumCols = rowMap->getGlobalNumElements();
190 RCP<MultiVector> NullspaceOrig = Factory::Get<RCP<MultiVector> >(currentLevel,
"Nullspace");
193 RCP<MultiVector> Nullspace = projection_->Nullspace_;
195 RCP<MultiVector> ghostedNullspace;
196 RCP<const Map> colMap;
197 RCP<const Import> importer;
198 if (rowMap->getComm()->getSize() > 1) {
199 this->GetOStream(
Warnings0) <<
"MueLu::Amesos2Smoother::Setup(): Applying nullspace fix on distributed matrix. Try rebalancing to single rank!" << std::endl;
200 ArrayRCP<GO> elements_RCP;
201 elements_RCP.resize(gblNumCols);
202 ArrayView<GO> elements = elements_RCP();
203 for (
size_t k = 0; k < gblNumCols; k++)
204 elements[k] = Teuchos::as<GO>(k);
205 colMap = MapFactory::Build(rowMap->lib(), gblNumCols * rowMap->getComm()->getSize(), elements, Teuchos::ScalarTraits<GO>::zero(), rowMap->getComm());
206 importer = ImportFactory::Build(rowMap, colMap);
207 ghostedNullspace = MultiVectorFactory::Build(colMap, Nullspace->getNumVectors(),
false);
208 ghostedNullspace->doImport(*Nullspace, *importer, Xpetra::INSERT);
210 ghostedNullspace = Nullspace;
214 using ATS = KokkosKernels::ArithTraits<SC>;
215 using impl_Scalar =
typename ATS::val_type;
216 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
217 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
219 typedef typename Matrix::local_matrix_device_type KCRS;
220 typedef typename KCRS::StaticCrsGraphType graph_t;
221 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
222 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
223 typedef typename KCRS::values_type::non_const_type scalar_view_t;
225 const impl_Scalar impl_SC_ZERO = impl_ATS::zero();
227 size_t lclNumRows = rowMap->getLocalNumElements();
228 LocalOrdinal lclNumCols = Teuchos::as<LocalOrdinal>(gblNumCols);
229 lno_view_t newRowPointers(
"newRowPointers", lclNumRows + 1);
230 lno_nnz_view_t newColIndices(
"newColIndices", lclNumRows * gblNumCols);
231 scalar_view_t newValues(
"newValues", lclNumRows * gblNumCols);
235 RCP<Vector> diag = VectorFactory::Build(A->getRowMap());
236 A->getLocalDiagCopy(*diag);
237 shift = diag->normInf();
242 auto lclNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
243 auto lclGhostedNullspace = ghostedNullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
244 Kokkos::parallel_for(
245 "MueLu:Amesos2Smoother::fixNullspace_1", range_type(0, lclNumRows + 1),
246 KOKKOS_LAMBDA(
const size_t i) {
247 if (i < lclNumRows) {
248 newRowPointers(i) = i * gblNumCols;
250 newColIndices(i * gblNumCols + j) = j;
251 newValues(i * gblNumCols + j) = impl_SC_ZERO;
252 for (
size_t I = 0; I < lclNullspace.extent(1); I++)
253 for (
size_t J = 0; J < lclGhostedNullspace.extent(1); J++)
254 newValues(i * gblNumCols + j) += shift * lclNullspace(i, I) * impl_ATS::conjugate(lclGhostedNullspace(j, J));
257 newRowPointers(lclNumRows) = lclNumRows * gblNumCols;
262 if (colMap->lib() == Xpetra::UseTpetra) {
263 auto lclA = A->getLocalMatrixDevice();
264 auto lclColMapA = A->getColMap()->getLocalMap();
265 auto lclColMapANew = colMap->getLocalMap();
266 Kokkos::parallel_for(
267 "MueLu:Amesos2Smoother::fixNullspace_2", range_type(0, lclNumRows),
268 KOKKOS_LAMBDA(
const size_t i) {
269 for (
size_t jj = lclA.graph.row_map(i); jj < lclA.graph.row_map(i + 1); jj++) {
270 LO j = lclColMapANew.getLocalElement(lclColMapA.getGlobalElement(lclA.graph.entries(jj)));
271 impl_Scalar v = lclA.values(jj);
272 newValues(i * gblNumCols + j) += v;
276 auto lclA = A->getLocalMatrixHost();
277 for (
size_t i = 0; i < lclNumRows; i++) {
278 for (
size_t jj = lclA.graph.row_map(i); jj < lclA.graph.row_map(i + 1); jj++) {
279 LO j = colMap->getLocalElement(A->getColMap()->getGlobalElement(lclA.graph.entries(jj)));
280 SC v = lclA.values(jj);
281 newValues(i * gblNumCols + j) += v;
286 RCP<Matrix> newA = rcp(
new CrsMatrixWrap(rowMap, colMap, 0));
287 RCP<CrsMatrix> newAcrs = toCrsMatrix(newA);
288 newAcrs->setAllValues(newRowPointers, newColIndices, newValues);
289 newAcrs->expertStaticFillComplete(A->getDomainMap(), A->getRangeMap(),
290 importer, A->getCrsGraph()->getExporter());
293 rowMap = factorA->getRowMap();
298 RCP<Tpetra_CrsMatrix> tA = toTpetra(factorA);
299 if (!tA->haveGlobalConstants())
300 Teuchos::rcp_const_cast<typename Tpetra_CrsMatrix::crs_graph_type>(tA->getCrsGraph())->computeGlobalConstants();
302 prec_ = Amesos2::create<Tpetra_CrsMatrix, Tpetra_MultiVector>(type_, tA);
303 TEUCHOS_TEST_FOR_EXCEPTION(prec_ == Teuchos::null,
Exceptions::RuntimeError,
"Amesos2::create returns Teuchos::null");
304 RCP<Teuchos::ParameterList> amesos2_params = Teuchos::rcpFromRef(pL.sublist(
"Amesos2"));
305 amesos2_params->setName(
"Amesos2");
306 if ((rowMap->getGlobalNumElements() != as<size_t>((rowMap->getMaxAllGlobalIndex() - rowMap->getMinAllGlobalIndex()) + 1)) ||
307 (!rowMap->isContiguous() && (rowMap->getComm()->getSize() == 1))) {
308 if (((type_ !=
"Cusolver") && (type_ !=
"Tacho")) && !(amesos2_params->sublist(prec_->name()).template isType<bool>(
"IsContiguous")))
309 amesos2_params->sublist(prec_->name()).set(
"IsContiguous",
false,
"Are GIDs Contiguous");
311 prec_->setParameters(amesos2_params);
313 prec_->numericFactorization();
322 RCP<BlockedMultiVector> blockedX = rcp_dynamic_cast<BlockedMultiVector>(rcpFromRef(X));
323 bool blocked = blockedX != Teuchos::null;
325 this->ApplyBlocked(X, B);
329 RCP<Tpetra_MultiVector> tX, tB;
330 if (!useTransformation_) {
331 tX = toTpetra(Teuchos::rcpFromRef(X));
332 tB = toTpetra(Teuchos::rcpFromRef(
const_cast<MultiVector&
>(B)));
335 size_t numVectors = X.getNumVectors();
336 size_t length = X.getLocalLength();
339 "MueLu::Amesos2Smoother::Apply: Fixing coarse matrix for Amesos2 for multivectors has not been implemented yet.");
340 ArrayRCP<const SC> Xdata = X.getData(0), Bdata = B.getData(0);
341 ArrayRCP<SC> X_data = X_->getDataNonConst(0), B_data = B_->getDataNonConst(0);
343 for (
size_t i = 0; i < length; i++) {
344 X_data[i] = Xdata[i];
345 B_data[i] = Bdata[i];
357 prec_->setX(Teuchos::null);
358 prec_->setB(Teuchos::null);
360 if (useTransformation_) {
362 size_t length = X.getLocalLength();
364 ArrayRCP<SC> Xdata = X.getDataNonConst(0);
365 ArrayRCP<const SC> X_data = X_->getData(0);
367 for (
size_t i = 0; i < length; i++)
368 Xdata[i] = X_data[i];
372 Teuchos::ParameterList pL = this->GetParameterList();
373 if (pL.get<
bool>(
"fix nullspace")) {
374 projection_->projectOut(X);
382 "MueLu::Amesos2Smoother::ApplyBlocked: useTransformation_ == true is not supported");
384 Teuchos::ParameterList pL = this->GetParameterList();
385 const auto fixNullspace = pL.get<
bool>(
"fix nullspace");
387 "MueLu::Amesos2Smoother::ApplyBlocked: \"fix nullspace\" == true is not supported");
389 RCP<BlockedMultiVector> blockedX = rcp_dynamic_cast<BlockedMultiVector>(rcpFromRef(X));
390 RCP<const BlockedMultiVector> blockedB = rcp_dynamic_cast<const BlockedMultiVector>(rcpFromRef(B));
392 "MueLu::Amesos2Smoother::ApplyBlocked: Input and/or output vector are not BlockedMultiVector!");
394 RCP<MultiVector> mergedX = blockedX->Merge();
395 RCP<MultiVector> mergedB = blockedB->Merge();
397 RCP<Tpetra_MultiVector> tX, tB;
398 tX = toTpetra(mergedX);
399 tB = toTpetra(mergedB);
406 prec_->setX(Teuchos::null);
407 prec_->setB(Teuchos::null);
409 RCP<MultiVector> xx = Teuchos::rcp(
new BlockedMultiVector(blockedX->getBlockedMap(), mergedX));
410 SC zero = Teuchos::ScalarTraits<SC>::zero(), one = Teuchos::ScalarTraits<SC>::one();
411 X.update(one, *xx, zero);