76 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> > tempMV = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(localMap_, X.getNumVectors());
77 tempMV->multiply(Teuchos::CONJ_TRANS, Teuchos::NO_TRANS, ONE, *Nullspace_, X, ZERO);
78 auto dots = tempMV->getHostLocalView(Xpetra::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);
94template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
100 if (!
type_.empty()) {
103 std::transform(
type_.begin(), ++
type_.begin(),
type_.begin(), ::toupper);
105 if (
type_ ==
"Superlu_dist")
106 type_ =
"Superludist";
111 if (
type_ ==
"" || Amesos2::query(
type_) ==
false) {
112 std::string oldtype =
type_;
113#if defined(HAVE_AMESOS2_KLU2)
115#elif defined(HAVE_AMESOS2_SUPERLU)
117#elif defined(HAVE_AMESOS2_SUPERLUDIST)
118 type_ =
"Superludist";
119#elif defined(HAVE_AMESOS2_BASKER)
122 this->
declareConstructionOutcome(
true, std::string(
"Amesos2 has been compiled without SuperLU_DIST, SuperLU, Klu, or Basker. By default, MueLu tries") +
123 "to use one of these libraries. Amesos2 must be compiled with one of these solvers, " +
124 "or a valid Amesos2 solver has to be specified explicitly.");
128 this->
GetOStream(
Warnings0) <<
"MueLu::Amesos2Smoother: \"" << oldtype <<
"\" is not available. Using \"" <<
type_ <<
"\" instead" << std::endl;
135 "Amesos2 has been compiled without the support of this solver, or the solver name is misspelled.");
138template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
141template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
143 RCP<ParameterList> validParamList = rcp(
new ParameterList());
144 validParamList->set<RCP<const FactoryBase> >(
"A", null,
"Factory of the coarse matrix");
145 validParamList->set<RCP<const FactoryBase> >(
"Nullspace", null,
"Factory of the nullspace");
146 validParamList->set<
bool>(
"fix nullspace",
false,
"Remove zero eigenvalue by adding rank one correction.");
147 ParameterList norecurse;
148 norecurse.disableRecursiveValidation();
149 validParamList->set<ParameterList>(
"Amesos2", norecurse,
"Parameters that are passed to Amesos2");
150 return validParamList;
167 this->
GetOStream(
Warnings0) <<
"MueLu::Amesos2Smoother::Setup(): Setup() has already been called" << std::endl;
172 RCP<const Map> rowMap = A->getRowMap();
176 if (pL.get<
bool>(
"fix nullspace")) {
177 this->
GetOStream(
Runtime1) <<
"MueLu::Amesos2Smoother::Setup(): fixing nullspace" << std::endl;
179 rowMap = A->getRowMap();
180 size_t gblNumCols = rowMap->getGlobalNumElements();
185 RCP<MultiVector> Nullspace =
projection_->Nullspace_;
187 RCP<MultiVector> ghostedNullspace;
188 RCP<const Map> colMap;
189 RCP<const Import> importer;
190 if (rowMap->getComm()->getSize() > 1) {
191 this->
GetOStream(
Warnings0) <<
"MueLu::Amesos2Smoother::Setup(): Applying nullspace fix on distributed matrix. Try rebalancing to single rank!" << std::endl;
192 ArrayRCP<GO> elements_RCP;
193 elements_RCP.resize(gblNumCols);
194 ArrayView<GO> elements = elements_RCP();
195 for (
size_t k = 0; k < gblNumCols; k++)
196 elements[k] = Teuchos::as<GO>(k);
197 colMap = MapFactory::Build(rowMap->lib(), gblNumCols * rowMap->getComm()->getSize(), elements, Teuchos::ScalarTraits<GO>::zero(), rowMap->getComm());
198 importer = ImportFactory::Build(rowMap, colMap);
199 ghostedNullspace = MultiVectorFactory::Build(colMap, Nullspace->getNumVectors());
200 ghostedNullspace->doImport(*Nullspace, *importer, Xpetra::INSERT);
202 ghostedNullspace = Nullspace;
206 using ATS = Kokkos::ArithTraits<SC>;
207 using impl_Scalar =
typename ATS::val_type;
208 using impl_ATS = Kokkos::ArithTraits<impl_Scalar>;
209 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
211 typedef typename Matrix::local_matrix_type KCRS;
212 typedef typename KCRS::StaticCrsGraphType graph_t;
213 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
214 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
215 typedef typename KCRS::values_type::non_const_type scalar_view_t;
217 const impl_Scalar impl_SC_ZERO = impl_ATS::zero();
219 size_t lclNumRows = rowMap->getLocalNumElements();
220 LocalOrdinal lclNumCols = Teuchos::as<LocalOrdinal>(gblNumCols);
221 lno_view_t newRowPointers(
"newRowPointers", lclNumRows + 1);
222 lno_nnz_view_t newColIndices(
"newColIndices", lclNumRows * gblNumCols);
223 scalar_view_t newValues(
"newValues", lclNumRows * gblNumCols);
227 RCP<Vector> diag = VectorFactory::Build(A->getRowMap());
228 A->getLocalDiagCopy(*diag);
229 shift = diag->normInf();
234 auto lclNullspace = Nullspace->getDeviceLocalView(Xpetra::Access::ReadOnly);
235 auto lclGhostedNullspace = ghostedNullspace->getDeviceLocalView(Xpetra::Access::ReadOnly);
236 Kokkos::parallel_for(
237 "MueLu:Amesos2Smoother::fixNullspace_1", range_type(0, lclNumRows + 1),
238 KOKKOS_LAMBDA(
const size_t i) {
239 if (i < lclNumRows) {
240 newRowPointers(i) = i * gblNumCols;
242 newColIndices(i * gblNumCols + j) = j;
243 newValues(i * gblNumCols + j) = impl_SC_ZERO;
244 for (
size_t I = 0;
I < lclNullspace.extent(1);
I++)
245 for (
size_t J = 0; J < lclGhostedNullspace.extent(1); J++)
246 newValues(i * gblNumCols + j) += shift * lclNullspace(i,
I) * impl_ATS::conjugate(lclGhostedNullspace(j, J));
249 newRowPointers(lclNumRows) = lclNumRows * gblNumCols;
254 if (colMap->lib() == Xpetra::UseTpetra) {
255 auto lclA = A->getLocalMatrixDevice();
256 auto lclColMapA = A->getColMap()->getLocalMap();
257 auto lclColMapANew = colMap->getLocalMap();
258 Kokkos::parallel_for(
259 "MueLu:Amesos2Smoother::fixNullspace_2", range_type(0, lclNumRows),
260 KOKKOS_LAMBDA(
const size_t i) {
261 for (
size_t jj = lclA.graph.row_map(i); jj < lclA.graph.row_map(i + 1); jj++) {
262 LO j = lclColMapANew.getLocalElement(lclColMapA.getGlobalElement(lclA.graph.entries(jj)));
263 impl_Scalar v = lclA.values(jj);
264 newValues(i * gblNumCols + j) += v;
268 auto lclA = A->getLocalMatrixHost();
269 for (
size_t i = 0; i < lclNumRows; i++) {
270 for (
size_t jj = lclA.graph.row_map(i); jj < lclA.graph.row_map(i + 1); jj++) {
271 LO j = colMap->getLocalElement(A->getColMap()->getGlobalElement(lclA.graph.entries(jj)));
272 SC v = lclA.values(jj);
273 newValues(i * gblNumCols + j) += v;
278 RCP<Matrix> newA = rcp(
new CrsMatrixWrap(rowMap, colMap, 0));
279 RCP<CrsMatrix> newAcrs = toCrsMatrix(newA);
280 newAcrs->setAllValues(newRowPointers, newColIndices, newValues);
281 newAcrs->expertStaticFillComplete(A->getDomainMap(), A->getRangeMap(),
282 importer, A->getCrsGraph()->getExporter());
285 rowMap = factorA->getRowMap();
290 RCP<const Tpetra_CrsMatrix> tA = toTpetra(factorA);
292 prec_ = Amesos2::create<Tpetra_CrsMatrix, Tpetra_MultiVector>(
type_, tA);
294 RCP<Teuchos::ParameterList> amesos2_params = Teuchos::rcpFromRef(pL.sublist(
"Amesos2"));
295 amesos2_params->setName(
"Amesos2");
296 if ((rowMap->getGlobalNumElements() != as<size_t>((rowMap->getMaxAllGlobalIndex() - rowMap->getMinAllGlobalIndex()) + 1)) ||
297 (!rowMap->isContiguous() && (rowMap->getComm()->getSize() == 1))) {
298 if (((
type_ !=
"Cusolver") && (
type_ !=
"Tacho")) && !(amesos2_params->sublist(
prec_->name()).template isType<bool>(
"IsContiguous")))
299 amesos2_params->sublist(
prec_->name()).set(
"IsContiguous",
false,
"Are GIDs Contiguous");
301 prec_->setParameters(amesos2_params);
303 prec_->numericFactorization();