10 #ifndef MUELU_AMESOS2SMOOTHER_DEF_HPP
11 #define MUELU_AMESOS2SMOOTHER_DEF_HPP
16 #if defined(HAVE_MUELU_AMESOS2)
20 #include <Amesos2_config.h>
21 #include <Amesos2.hpp>
25 #include "MueLu_Utilities.hpp"
30 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
34 Nullspace->getNumVectors(),
35 Nullspace->getMap()->getIndexBase(),
36 Nullspace->getMap()->getComm(),
44 Kokkos::View<Scalar**, Kokkos::LayoutLeft, Kokkos::HostSpace> Q(
"Q", Nullspace->getNumVectors(), Nullspace->getNumVectors());
47 auto dots = tempMV->getLocalViewHost(Xpetra::Access::ReadOnly);
48 Kokkos::deep_copy(Q, dots);
54 lapack.
POTRF(
'L', Nullspace->getNumVectors(), Q.data(), LDQ, &info);
56 lapack.
TRTRI(
'L',
'N', Nullspace->getNumVectors(), Q.data(), LDQ, &info);
61 for (
size_t i = 0; i < Nullspace->getNumVectors(); i++) {
62 for (
size_t j = 0; j <= i; j++) {
63 Nullspace_->getVectorNonConst(i)->update(Q(i, j), *Nullspace->getVector(j), ONE);
68 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
78 auto dots = tempMV->getLocalViewHost(Xpetra::Access::ReadOnly);
79 bool doProject =
true;
81 for (
size_t j = 0; j < Nullspace_->getNumVectors(); j++) {
87 for (
size_t j = 0; j < Nullspace_->getNumVectors(); j++) {
94 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
97 , useTransformation_(false) {
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.");
138 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
141 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
146 validParamList->
set<
bool>(
"fix nullspace",
false,
"Remove zero eigenvalue by adding rank one correction.");
149 validParamList->
set<
ParameterList>(
"Amesos2", norecurse,
"Parameters that are passed to Amesos2");
150 return validParamList;
153 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
157 this->Input(currentLevel,
"A");
158 if (pL.
get<
bool>(
"fix nullspace"))
159 this->Input(currentLevel,
"Nullspace");
162 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
167 this->GetOStream(
Warnings0) <<
"MueLu::Amesos2Smoother::Setup(): Setup() has already been called" << std::endl;
169 RCP<Matrix> A = Factory::Get<RCP<Matrix> >(currentLevel,
"A");
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();
182 RCP<MultiVector> NullspaceOrig = Factory::Get<RCP<MultiVector> >(currentLevel,
"Nullspace");
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;
193 elements_RCP.
resize(gblNumCols);
195 for (
size_t k = 0; k < gblNumCols; k++)
196 elements[k] = Teuchos::as<GO>(k);
198 importer = ImportFactory::Build(rowMap, colMap);
199 ghostedNullspace = MultiVectorFactory::Build(colMap, Nullspace->getNumVectors());
200 ghostedNullspace->doImport(*Nullspace, *importer,
Xpetra::INSERT);
202 ghostedNullspace = Nullspace;
206 #if KOKKOS_VERSION >= 40799
207 using ATS = KokkosKernels::ArithTraits<SC>;
209 using ATS = Kokkos::ArithTraits<SC>;
211 using impl_Scalar =
typename ATS::val_type;
212 #if KOKKOS_VERSION >= 40799
213 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
215 using impl_ATS = Kokkos::ArithTraits<impl_Scalar>;
217 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
219 typedef typename Matrix::local_matrix_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(Xpetra::Access::ReadOnly);
243 auto lclGhostedNullspace = ghostedNullspace->getLocalViewDevice(Xpetra::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;
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;
288 newAcrs->setAllValues(newRowPointers, newColIndices, newValues);
289 newAcrs->expertStaticFillComplete(A->getDomainMap(), A->getRangeMap(),
290 importer, A->getCrsGraph()->getExporter());
293 rowMap = factorA->getRowMap();
300 prec_ = Amesos2::create<Tpetra_CrsMatrix, Tpetra_MultiVector>(type_, tA);
303 amesos2_params->
setName(
"Amesos2");
304 if ((rowMap->getGlobalNumElements() != as<size_t>((rowMap->getMaxAllGlobalIndex() - rowMap->getMinAllGlobalIndex()) + 1)) ||
305 (!rowMap->isContiguous() && (rowMap->getComm()->getSize() == 1))) {
306 if (((type_ !=
"Cusolver") && (type_ !=
"Tacho")) && !(amesos2_params->
sublist(prec_->name()).
template isType<bool>(
"IsContiguous")))
307 amesos2_params->
sublist(prec_->name()).set(
"IsContiguous",
false,
"Are GIDs Contiguous");
311 prec_->numericFactorization();
316 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
321 if (!useTransformation_) {
322 tX =
toTpetra(Teuchos::rcpFromRef(X));
323 tB =
toTpetra(Teuchos::rcpFromRef(const_cast<MultiVector&>(B)));
326 size_t numVectors = X.getNumVectors();
327 size_t length = X.getLocalLength();
330 "MueLu::Amesos2Smoother::Apply: Fixing coarse matrix for Amesos2 for multivectors has not been implemented yet.");
332 ArrayRCP<SC> X_data = X_->getDataNonConst(0), B_data = B_->getDataNonConst(0);
334 for (
size_t i = 0; i < length; i++) {
335 X_data[i] = Xdata[i];
336 B_data[i] = Bdata[i];
348 prec_->setX(Teuchos::null);
349 prec_->setB(Teuchos::null);
351 if (useTransformation_) {
353 size_t length = X.getLocalLength();
358 for (
size_t i = 0; i < length; i++)
359 Xdata[i] = X_data[i];
364 if (pL.
get<
bool>(
"fix nullspace")) {
365 projection_->projectOut(X);
370 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
377 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
379 std::ostringstream out;
382 out << prec_->description();
386 out <<
"{type = " << type_ <<
"}";
391 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
396 out0 <<
"Prec. type: " << type_ << std::endl;
399 out0 <<
"Parameter list: " << std::endl;
401 out << this->GetParameterList();
404 if ((verbLevel &
External) && prec_ != Teuchos::null) {
406 out << *prec_ << std::endl;
409 if (verbLevel &
Debug)
412 <<
"RCP<prec_>: " << prec_ << std::endl;
415 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
417 if (!prec_.is_null())
418 return prec_->getStatus().getNnzLU();
424 #endif // HAVE_MUELU_AMESOS2
425 #endif // MUELU_AMESOS2SMOOTHER_DEF_HPP
Important warning messages (one line)
MueLu::DefaultLocalOrdinal LocalOrdinal
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
static Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node >> &map, size_t NumVectors, bool zeroOut=true)
ParameterList & disableRecursiveValidation()
static magnitudeType eps()
Print external lib objects.
T & get(const std::string &name, T def_value)
std::string type_
amesos2-specific key phrase that denote smoother type
void Apply(MultiVector &X, const MultiVector &B, bool InitialGuessIsZero=false) const
Apply the direct solver. Solves the linear system AX=B using the constructed solver.
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Print additional debugging information.
std::string tolower(const std::string &str)
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Amesos2Smoother(const std::string &type="", const Teuchos::ParameterList ¶mList=Teuchos::ParameterList())
Constructor Creates a MueLu interface to the direct solvers in the Amesos2 package. If you are using type=="", then either SuperLU or KLU2 are used by default.
std::string description() const
Return a simple one-line description of this object.
void resize(const size_type n, const T &val=T())
RCP< SmootherPrototype > Copy() const
virtual void SetParameterList(const Teuchos::ParameterList ¶mList)
Set parameters from a parameter list and return with default values.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
MueLu::DefaultScalar Scalar
void declareConstructionOutcome(bool fail, std::string msg)
Class that holds all level-specific information.
static Teuchos::RCP< Map< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, const Teuchos::RCP< const Teuchos::Comm< int >> &comm, LocalGlobal lg=Xpetra::GloballyDistributed)
Class that encapsulates Amesos2 direct solvers.
void POTRF(const char &UPLO, const OrdinalType &n, ScalarType *A, const OrdinalType &lda, OrdinalType *info) const
bool IsSetup() const
Get the state of a smoother prototype.
void DeclareInput(Level ¤tLevel) const
Input.
#define MUELU_DESCRIBE
Helper macro for implementing Describable::describe() for BaseClass objects.
ParameterList & setParameters(const ParameterList &source)
static magnitudeType magnitude(T a)
RCP< const Tpetra::CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > toTpetra(const RCP< const CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > &graph)
virtual ~Amesos2Smoother()
Destructor.
void Setup(Level ¤tLevel)
Set up the direct solver. This creates the underlying Amesos2 solver object according to the paramete...
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
ParameterList & setName(const std::string &name)
Print class parameters (more parameters, more verbose)
virtual Teuchos::RCP< Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > getVectorNonConst(size_t j)=0
Exception throws to report errors in the internal logical of the program.
#define TEUCHOS_ASSERT(assertion_test)
Description of what is happening (more verbose)
virtual size_t getNumVectors() const =0
void TRTRI(const char &UPLO, const char &DIAG, const OrdinalType &n, ScalarType *A, const OrdinalType &lda, OrdinalType *info) const
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
void print(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the object with some verbosity level to an FancyOStream object.
virtual std::string description() const
Return a simple one-line description of this object.
Projection(RCP< Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &Nullspace)
std::string toString(const T &t)
void projectOut(Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X)