46 #ifndef MUELU_AMESOS2SMOOTHER_DEF_HPP
47 #define MUELU_AMESOS2SMOOTHER_DEF_HPP
52 #if defined (HAVE_MUELU_TPETRA) && defined(HAVE_MUELU_AMESOS2)
53 #include <Xpetra_Matrix.hpp>
55 #include <Amesos2_config.h>
56 #include <Amesos2.hpp>
60 #include "MueLu_Utilities.hpp"
65 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
67 : type_(type), useTransformation_(false) {
73 std::transform(
type_.begin(), ++
type_.begin(),
type_.begin(), ::toupper);
75 if (
type_ ==
"Superlu_dist")
76 type_ =
"Superludist";
81 if (
type_ ==
"" || Amesos2::query(
type_) ==
false) {
83 #if defined(HAVE_AMESOS2_SUPERLU)
85 #elif defined(HAVE_AMESOS2_KLU2)
87 #elif defined(HAVE_AMESOS2_SUPERLUDIST)
88 type_ =
"Superludist";
89 #elif defined(HAVE_AMESOS2_BASKER)
92 throw Exceptions::RuntimeError(
"Amesos2 has been compiled without SuperLU_DIST, SuperLU, Klu, or Basker. By default, MueLu tries"
93 "to use one of these libraries. Amesos2 must be compiled with one of these solvers, "
94 "or a valid Amesos2 solver has to be specified explicitly.");
97 this->
GetOStream(
Warnings0) <<
"MueLu::Amesos2Smoother: \"" << oldtype <<
"\" is not available. Using \"" <<
type_ <<
"\" instead" << std::endl;
103 TEUCHOS_TEST_FOR_EXCEPTION(Amesos2::query(
type_) ==
false,
Exceptions::RuntimeError,
"The Amesos2 library reported that the solver '" <<
type_ <<
"' is not available. "
104 "Amesos2 has been compiled without the support of this solver, or the solver name is misspelled.");
107 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
110 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
112 RCP<ParameterList> validParamList = rcp(
new ParameterList());
113 validParamList->set< RCP<const FactoryBase> >(
"A",
null,
"Factory of the coarse matrix");
114 validParamList->set< RCP<const FactoryBase> >(
"Nullspace",
null,
"Factory of the nullspace");
115 validParamList->set<
bool>(
"fix nullspace",
false,
"Remove zero eigenvalue by adding rank one correction.");
116 return validParamList;
119 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
121 ParameterList pL = this->GetParameterList();
123 this->Input(currentLevel,
"A");
124 if (pL.get<
bool>(
"fix nullspace"))
125 this->Input(currentLevel,
"Nullspace");
128 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
133 this->GetOStream(
Warnings0) <<
"MueLu::Amesos2Smoother::Setup(): Setup() has already been called" << std::endl;
135 RCP<Matrix> A = Factory::Get< RCP<Matrix> >(currentLevel,
"A");
138 RCP<const Map> rowMap = A->getRowMap();
139 if (rowMap->getGlobalNumElements() != as<size_t>((rowMap->getMaxAllGlobalIndex() - rowMap->getMinAllGlobalIndex())+1)) {
148 this->GetOStream(
Runtime1) <<
"MueLu::Amesos2Smoother::Setup(): using system transformation" << std::endl;
151 "MueLu::Amesos2Smoother::Setup Fixing coarse matrix for Amesos2 for multiple processors has not been implemented yet.");
153 "MueLu::Amesos2Smoother::Setup Fixing coarse matrix for Amesos2 when row map is different from column map has not been implemented yet.");
155 RCP<CrsMatrixWrap> Acrs = rcp_dynamic_cast<CrsMatrixWrap>(A);
157 "MueLu::Amesos2Smoother::Setup Fixing coarse matrix for Amesos2 when matrix is not a Crs matrix has not been implemented yet.");
159 useTransformation_ =
true;
161 ArrayRCP<const size_t> rowPointers;
162 ArrayRCP<const LO> colIndices;
163 ArrayRCP<const SC> values;
164 Acrs->getCrsMatrix()->getAllValues(rowPointers, colIndices, values);
167 RCP<Map> map = MapFactory::Build(rowMap->lib(), rowMap->getGlobalNumElements(), 0, rowMap->getComm());
168 RCP<Matrix> newA = rcp(
new CrsMatrixWrap(map, map, 0, Xpetra::StaticProfile));
169 RCP<CrsMatrix> newAcrs = rcp_dynamic_cast<CrsMatrixWrap>(newA)->getCrsMatrix();
171 using Teuchos::arcp_const_cast;
172 newAcrs->setAllValues(arcp_const_cast<size_t>(rowPointers), arcp_const_cast<LO>(colIndices), arcp_const_cast<SC>(values));
173 newAcrs->expertStaticFillComplete(map, map);
177 X_ = MultiVectorFactory::Build(map, 1);
178 B_ = MultiVectorFactory::Build(map, 1);
182 Teuchos::ParameterList pL = this->GetParameterList();
183 if (pL.get<
bool>(
"fix nullspace")) {
184 this->GetOStream(
Runtime1) <<
"MueLu::Amesos2Smoother::Setup(): fixing nullspace" << std::endl;
186 rowMap = A->getRowMap();
187 size_t M = rowMap->getGlobalNumElements();
189 RCP<MultiVector> Nullspace = Factory::Get< RCP<MultiVector> >(currentLevel,
"Nullspace");
192 "MueLu::Amesos2Smoother::Setup Fixing nullspace for coarse matrix for Amesos2 for nullspace of dim > 1 has not been implemented yet.");
194 RCP<MultiVector> NullspaceImp;
195 RCP<const Map> colMap;
196 RCP<const Import> importer;
197 if (rowMap->getComm()->getSize() > 1) {
198 this->GetOStream(
Warnings0) <<
"MueLu::Amesos2Smoother::Setup(): Applying nullspace fix on distributed matrix. Try rebalancing to single rank!" << std::endl;
199 ArrayRCP<GO> elements_RCP;
200 elements_RCP.resize(M);
201 ArrayView<GO> elements = elements_RCP();
202 for (
size_t k = 0; k<M; k++)
203 elements[k] = Teuchos::as<GO>(k);
204 colMap = MapFactory::Build(rowMap->lib(),M*rowMap->getComm()->getSize(),elements,Teuchos::ScalarTraits<GO>::zero(),rowMap->getComm());
205 importer = ImportFactory::Build(rowMap,colMap);
206 NullspaceImp = MultiVectorFactory::Build(colMap, Nullspace->getNumVectors());
207 NullspaceImp->doImport(*Nullspace,*importer,Xpetra::INSERT);
209 NullspaceImp = Nullspace;
213 ArrayRCP<const SC> nullspaceRCP, nullspaceImpRCP;
214 ArrayView<const SC> nullspace, nullspaceImp;
215 nullspaceRCP = Nullspace->getData(0);
216 nullspace = nullspaceRCP();
217 nullspaceImpRCP = NullspaceImp->getData(0);
218 nullspaceImp = nullspaceImpRCP();
220 RCP<CrsMatrixWrap> Acrs = rcp_dynamic_cast<CrsMatrixWrap>(A);
223 "MueLu::Amesos2Smoother::Setup Fixing nullspace for coarse matrix for Amesos2 when matrix is not a Crs matrix has not been implemented yet.");
225 ArrayRCP<const size_t> rowPointers;
226 ArrayRCP<const LO> colIndices;
227 ArrayRCP<const SC> values;
228 Acrs->getCrsMatrix()->getAllValues(rowPointers, colIndices, values);
230 ArrayRCP<size_t> newRowPointers_RCP;
231 ArrayRCP<LO> newColIndices_RCP;
232 ArrayRCP<SC> newValues_RCP;
234 size_t N = rowMap->getNodeNumElements();
235 newRowPointers_RCP.resize(N+1);
236 newColIndices_RCP.resize(N*M);
237 newValues_RCP.resize(N*M);
239 ArrayView<size_t> newRowPointers = newRowPointers_RCP();
240 ArrayView<LO> newColIndices = newColIndices_RCP();
241 ArrayView<SC> newValues = newValues_RCP();
243 SC normalization = Nullspace->getVector(0)->norm2();
244 normalization = Teuchos::ScalarTraits<Scalar>::one()/(normalization*normalization);
247 for (
size_t i = 0; i < N; i++) {
248 newRowPointers[i] = i*M;
249 for (
size_t j = 0; j < M; j++) {
250 newColIndices[i*M+j] = Teuchos::as<LO>(j);
251 newValues[i*M+j] = normalization * nullspace[i]*Teuchos::ScalarTraits<Scalar>::conjugate(nullspaceImp[j]);
254 newRowPointers[N] = N*M;
257 for (
size_t i = 0; i < N; i++) {
258 for (
size_t jj = rowPointers[i]; jj < rowPointers[i+1]; jj++) {
259 LO j = colMap->getLocalElement(A->getColMap()->getGlobalElement(colIndices[jj]));
261 newValues[i*M+j] += v;
265 RCP<Matrix> newA = rcp(
new CrsMatrixWrap(rowMap, colMap, 0, Xpetra::StaticProfile));
266 RCP<CrsMatrix> newAcrs = rcp_dynamic_cast<CrsMatrixWrap>(newA)->getCrsMatrix();
268 using Teuchos::arcp_const_cast;
269 newAcrs->setAllValues(arcp_const_cast<size_t>(newRowPointers_RCP), arcp_const_cast<LO>(newColIndices_RCP), arcp_const_cast<SC>(newValues_RCP));
270 newAcrs->expertStaticFillComplete(A->getDomainMap(), A->getRangeMap(),
271 importer, A->getCrsGraph()->getExporter());
280 prec_ = Amesos2::create<Tpetra_CrsMatrix,Tpetra_MultiVector>(type_, tA);
281 TEUCHOS_TEST_FOR_EXCEPTION(prec_ == Teuchos::null,
Exceptions::RuntimeError,
"Amesos2::create returns Teuchos::null");
286 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
290 RCP<Tpetra_MultiVector> tX, tB;
291 if (!useTransformation_) {
296 size_t numVectors = X.getNumVectors();
297 size_t length = X.getLocalLength();
300 "MueLu::Amesos2Smoother::Apply: Fixing coarse matrix for Amesos2 for multivectors has not been implemented yet.");
301 ArrayRCP<const SC> Xdata = X. getData(0), Bdata = B. getData(0);
302 ArrayRCP<SC> X_data = X_->getDataNonConst(0), B_data = B_->getDataNonConst(0);
304 for (
size_t i = 0; i < length; i++) {
305 X_data[i] = Xdata[i];
306 B_data[i] = Bdata[i];
318 prec_->setX(Teuchos::null);
319 prec_->setB(Teuchos::null);
321 if (useTransformation_) {
323 size_t length = X.getLocalLength();
325 ArrayRCP<SC> Xdata = X. getDataNonConst(0);
326 ArrayRCP<const SC> X_data = X_->getData(0);
328 for (
size_t i = 0; i < length; i++)
329 Xdata[i] = X_data[i];
333 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
334 RCP<MueLu::SmootherPrototype<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
341 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
343 std::ostringstream out;
346 out << prec_->description();
350 out <<
"{type = " << type_ <<
"}";
355 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
360 out0 <<
"Prec. type: " << type_ << std::endl;
363 out0 <<
"Parameter list: " << std::endl;
364 Teuchos::OSTab tab2(out);
365 out << this->GetParameterList();
368 if ((verbLevel &
External) && prec_ != Teuchos::null) {
369 Teuchos::OSTab tab2(out);
370 out << *prec_ << std::endl;
373 if (verbLevel &
Debug)
376 <<
"RCP<prec_>: " << prec_ << std::endl;
379 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
382 return prec_->getStatus().getNnzLU();
389 #endif // HAVE_MUELU_TPETRA && HAVE_MUELU_AMESOS2
390 #endif // MUELU_AMESOS2SMOOTHER_DEF_HPP