46 #ifndef MUELU_AGGREGATEQUALITYESTIMATEFACTORY_DEF_HPP
47 #define MUELU_AGGREGATEQUALITYESTIMATEFACTORY_DEF_HPP
57 #include <Xpetra_IO.hpp>
60 #include "MueLu_FactoryManager.hpp"
61 #include "MueLu_Utilities.hpp"
67 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
71 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
74 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
77 Input(currentLevel,
"A");
78 Input(currentLevel,
"Aggregates");
79 Input(currentLevel,
"CoarseMap");
83 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
87 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
95 #undef SET_VALID_ENTRY
101 return validParamList;
105 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
110 RCP<Matrix> A = Get<RCP<Matrix>>(currentLevel,
"A");
111 RCP<Aggregates> aggregates = Get<RCP<Aggregates>>(currentLevel,
"Aggregates");
113 RCP<const Map> map = Get< RCP<const Map> >(currentLevel,
"CoarseMap");
116 assert(!aggregates->AggregatesCrossProcessors());
117 ComputeAggregateQualities(A, aggregates, aggregate_qualities);
119 Set(currentLevel,
"AggregateQualities", aggregate_qualities);
121 OutputAggQualities(currentLevel, aggregate_qualities);
125 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
144 for (LO i=0;i<numAggs;++i) {
145 aggsToIndices[i+LO_ONE] = aggsToIndices[i] + aggSizes[i];
151 LO numNodes = vertex2AggId->getLocalLength();
153 std::vector<LO> vertexInsertionIndexByAgg(numNodes,LO_ZERO);
155 for (LO i=0;i<numNodes;++i) {
157 LO aggId = vertex2AggIdData[i];
158 if (aggId<0 || aggId>=numAggs)
continue;
160 aggSortedVertices[aggsToIndices[aggId]+vertexInsertionIndexByAgg[aggId]] = i;
161 vertexInsertionIndexByAgg[aggId]++;
168 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
172 const SC SCALAR_TWO = SCALAR_ONE + SCALAR_ONE;
185 std::string algostr = pL.
get<std::string>(
"aggregate qualities: algorithm");
186 MT zeroThreshold = Teuchos::as<MT>(pL.
get<
double>(
"aggregate qualities: zero threshold"));
187 enum AggAlgo {ALG_FORWARD=0, ALG_REVERSE};
189 if(algostr ==
"forward") {algo = ALG_FORWARD; GetOStream(
Statistics1) <<
"AggregateQuality: Using 'forward' algorithm" << std::endl;}
190 else if(algostr ==
"reverse") {algo = ALG_REVERSE; GetOStream(
Statistics1) <<
"AggregateQuality: Using 'reverse' algorithm" << std::endl;}
195 bool check_symmetry = pL.
get<
bool>(
"aggregate qualities: check symmetry");
196 if (check_symmetry) {
199 x->Xpetra_randomize();
207 tmp->norm2(tmp_norm());
210 tmp->norm2(x_norm());
212 if (tmp_norm[0] > 1e-10*x_norm[0]) {
213 std::string transpose_string =
"transpose";
217 assert(A->getMap()->isSameAs( *(AT->getMap()) ));
230 ArrayRCP<LO> aggSortedVertices, aggsToIndices, aggSizes;
231 ConvertAggregatesData(aggs, aggSortedVertices, aggsToIndices, aggSizes);
246 for (LO aggId=LO_ZERO; aggId<numAggs; ++aggId) {
248 LO aggSize = aggSizes[aggId];
249 DenseMatrix A_aggPart(aggSize, aggSize,
true);
250 DenseVector offDiagonalAbsoluteSums(aggSize,
true);
253 for (LO idx=LO_ZERO; idx<aggSize; ++idx) {
255 LO nodeId = aggSortedVertices[idx+aggsToIndices[aggId]];
256 A->getLocalRowView(nodeId, rowIndices, rowValues);
257 AT->getLocalRowView(nodeId, rowIndices, colValues);
260 for (LO elem=LO_ZERO; elem<rowIndices.
size();++elem) {
262 LO nodeId2 = rowIndices[elem];
263 SC val = (rowValues[elem]+colValues[elem])/SCALAR_TWO;
265 LO idxInAgg = -LO_ONE;
270 for (LO idx2=LO_ZERO; idx2<aggSize; ++idx2) {
272 if (aggSortedVertices[idx2+aggsToIndices[aggId]] == nodeId2) {
282 if (idxInAgg == -LO_ONE) {
298 DenseMatrix A_aggPartDiagonal(aggSize, aggSize,
true);
299 MT diag_sum = MT_ZERO;
300 for (
int i=0;i<aggSize;++i) {
305 DenseMatrix ones(aggSize, aggSize,
false);
306 ones.putScalar(MT_ONE);
310 DenseMatrix tmp(aggSize, aggSize,
false);
311 DenseMatrix topMatrix(A_aggPartDiagonal);
317 DenseMatrix bottomMatrix(A_aggPart);
318 MT matrixNorm = A_aggPart.normInf();
323 for (
int i=0;i<aggSize;++i){
324 bottomMatrix(i,i) -= offDiagonalAbsoluteSums(i) + boost;
329 DenseVector alpha_real(aggSize,
false);
330 DenseVector alpha_imag(aggSize,
false);
331 DenseVector beta(aggSize,
false);
333 DenseVector workArray(14*(aggSize+1),
false);
335 LO (*ptr2func)(MT*, MT*, MT*);
341 const char compute_flag =
'N';
342 if(algo == ALG_FORWARD) {
344 myLapack.
GGES(compute_flag,compute_flag,compute_flag,ptr2func,aggSize,
345 topMatrix.values(),aggSize,bottomMatrix.values(),aggSize,&sdim,
346 alpha_real.values(),alpha_imag.values(),beta.values(),vl,aggSize,
347 vr,aggSize,workArray.values(),workArray.length(),bwork,
351 MT maxEigenVal = MT_ZERO;
352 for (
int i=LO_ZERO;i<aggSize;++i) {
355 maxEigenVal = std::max(maxEigenVal, alpha_real[i]/beta[i]);
358 (agg_qualities->getDataNonConst(0))[aggId] = (MT_ONE+MT_ONE)*maxEigenVal;
363 myLapack.
GGES(compute_flag,compute_flag,compute_flag,ptr2func,aggSize,
364 bottomMatrix.values(),aggSize,topMatrix.values(),aggSize,&sdim,
365 alpha_real.values(),alpha_imag.values(),beta.values(),vl,aggSize,
366 vr,aggSize,workArray.values(),workArray.length(),bwork,
371 MT minEigenVal = MT_ZERO;
373 for (
int i=LO_ZERO;i<aggSize;++i) {
374 MT ev = alpha_real[i] / beta[i];
375 if(ev > zeroThreshold) {
376 if (minEigenVal == MT_ZERO) minEigenVal = ev;
377 else minEigenVal = std::min(minEigenVal,ev);
381 else (agg_qualities->getDataNonConst(0))[aggId] = (MT_ONE+MT_ONE) / minEigenVal;
386 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
391 magnitudeType good_agg_thresh = Teuchos::as<magnitudeType>(pL.
get<
double>(
"aggregate qualities: good aggregate threshold"));
399 MT mean_bad_agg = 0.0;
400 MT mean_good_agg = 0.0;
403 for (
size_t i=0;i<agg_qualities->getLocalLength();++i) {
405 if (data[i] > good_agg_thresh) {
407 mean_bad_agg += data[i];
410 mean_good_agg += data[i];
412 worst_agg = std::max(worst_agg, data[i]);
416 if (num_bad_aggs > 0) mean_bad_agg /= num_bad_aggs;
417 mean_good_agg /= agg_qualities->getLocalLength() - num_bad_aggs;
419 if (num_bad_aggs == 0) {
420 GetOStream(
Statistics1) <<
"All aggregates passed the quality measure. Worst aggregate had quality " << worst_agg <<
". Mean aggregate quality " << mean_good_agg <<
"." << std::endl;
422 GetOStream(
Statistics1) << num_bad_aggs <<
" out of " << agg_qualities->getLocalLength() <<
" did not pass the quality measure. Worst aggregate had quality " << worst_agg <<
". "
423 <<
"Mean bad aggregate quality " << mean_bad_agg <<
". Mean good aggregate quality " << mean_good_agg <<
"." << std::endl;
426 if (pL.
get<
bool>(
"aggregate qualities: file output")) {
427 std::string filename = pL.
get<std::string>(
"aggregate qualities: file base")+
"."+std::to_string(level.
GetLevelID());
428 Xpetra::IO<magnitudeType,LO,GO,Node>::Write(filename, *agg_qualities);
432 const auto n = size_t(agg_qualities->getLocalLength());
437 for (
size_t i=0; i<n; ++i) {
438 tmp.push_back(data[i]);
441 std::sort(tmp.begin(), tmp.end());
445 GetOStream(
Statistics1) <<
"AGG QUALITY HEADER : | LEVEL | TOTAL |";
446 for (
auto percent : percents) {
447 GetOStream(
Statistics1) << std::fixed << std::setprecision(4) <<100.0*percent <<
"% |";
452 for (
auto percent : percents) {
453 size_t i = size_t(n*percent);
454 i = i < n ? i : n-1u;
456 GetOStream(
Statistics1) << std::fixed <<std::setprecision(4) << tmp[i] <<
" |";
465 #endif // MUELU_AGGREGATEQUALITYESTIMATE_DEF_HPP
void OutputAggQualities(const Level &level, RCP< const Xpetra::MultiVector< magnitudeType, LO, GO, Node >> agg_qualities) const
virtual ~AggregateQualityEstimateFactory()
Destructor.
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
static magnitudeType real(T a)
#define SET_VALID_ENTRY(name)
Teuchos::ArrayRCP< LO > ComputeAggregateSizes(bool forceRecompute=false) const
Compute sizes of aggregates.
void DeclareInput(Level ¤tLevel) const
Specifies the data that this class needs, and the factories that generate that data.
void GGES(const char &JOBVL, const char &JOBVR, const char &SORT, OrdinalType &(*ptr2func)(ScalarType *, ScalarType *, ScalarType *), const OrdinalType &n, ScalarType *A, const OrdinalType &lda, ScalarType *B, const OrdinalType &ldb, OrdinalType *sdim, MagnitudeType *ALPHAR, MagnitudeType *ALPHAI, MagnitudeType *BETA, ScalarType *VL, const OrdinalType &ldvl, ScalarType *VR, const OrdinalType &ldvr, ScalarType *WORK, const OrdinalType &lwork, OrdinalType *BWORK, OrdinalType *info) const
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
LO GetNumAggregates() const
returns the number of aggregates of the current processor. Note: could/should be renamed to GetNumLoc...
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Transpose(Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, bool optimizeTranspose=false, const std::string &label=std::string(), const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
void ComputeAggregateQualities(RCP< const Matrix > A, RCP< const Aggregates > aggs, RCP< Xpetra::MultiVector< magnitudeType, LO, GO, Node >> agg_qualities) const
const RCP< LOMultiVector > & GetVertex2AggId() const
Returns constant vector that maps local node IDs to local aggregates IDs.
static magnitudeType magnitude(T a)
void Build(Level ¤tLevel) const
Build aggregate quality esimates with this factory.
static void ConvertAggregatesData(RCP< const Aggregates > aggs, ArrayRCP< LO > &aggSortedVertices, ArrayRCP< LO > &aggsToIndices, ArrayRCP< LO > &aggSizes)
Build aggregate quality esimates with this factory.
int GetLevelID() const
Return level number.
Exception throws to report errors in the internal logical of the program.
#define TEUCHOS_ASSERT(assertion_test)
Teuchos::ScalarTraits< Scalar >::magnitudeType magnitudeType
AggregateQualityEstimateFactory()
Constructor.