185 const SC SCALAR_ONE = Teuchos::ScalarTraits<SC>::one();
186 const SC SCALAR_TWO = SCALAR_ONE + SCALAR_ONE;
188 const LO LO_ZERO = Teuchos::OrdinalTraits<LO>::zero();
189 const LO LO_ONE = Teuchos::OrdinalTraits<LO>::one();
192 const MT MT_ZERO = Teuchos::ScalarTraits<MT>::zero();
193 const MT MT_ONE = Teuchos::ScalarTraits<MT>::one();
196 RCP<const Matrix> AT = A;
199 std::string algostr = pL.get<std::string>(
"aggregate qualities: algorithm");
200 MT zeroThreshold = Teuchos::as<MT>(pL.get<
double>(
"aggregate qualities: zero threshold"));
201 enum AggAlgo {ALG_FORWARD=0, ALG_REVERSE};
203 if(algostr ==
"forward") {algo = ALG_FORWARD;
GetOStream(
Statistics1) <<
"AggregateQuality: Using 'forward' algorithm" << std::endl;}
204 else if(algostr ==
"reverse") {algo = ALG_REVERSE;
GetOStream(
Statistics1) <<
"AggregateQuality: Using 'reverse' algorithm" << std::endl;}
209 bool check_symmetry = pL.get<
bool>(
"aggregate qualities: check symmetry");
210 if (check_symmetry) {
212 RCP<MultiVector> x = MultiVectorFactory::Build(A->getMap(), 1,
false);
213 x->Xpetra_randomize();
215 RCP<MultiVector> tmp = MultiVectorFactory::Build(A->getMap(), 1,
false);
217 A->apply(*x, *tmp, Teuchos::NO_TRANS);
218 A->apply(*x, *tmp, Teuchos::TRANS, -SCALAR_ONE, SCALAR_ONE);
220 Array<magnitudeType> tmp_norm(1);
221 tmp->norm2(tmp_norm());
223 Array<magnitudeType> x_norm(1);
224 tmp->norm2(x_norm());
226 if (tmp_norm[0] > 1e-10*x_norm[0]) {
227 std::string transpose_string =
"transpose";
228 RCP<ParameterList> whatever;
231 assert(A->getMap()->isSameAs( *(AT->getMap()) ));
244 ArrayRCP<LO> aggSortedVertices, aggsToIndices, aggSizes;
247 LO numAggs = aggs->GetNumAggregates();
251 typedef Teuchos::SerialDenseMatrix<LO,MT> DenseMatrix;
252 typedef Teuchos::SerialDenseVector<LO,MT> DenseVector;
254 ArrayView<const LO> rowIndices;
255 ArrayView<const SC> rowValues;
256 ArrayView<const SC> colValues;
257 Teuchos::LAPACK<LO,MT> myLapack;
260 for (LO aggId=LO_ZERO; aggId<numAggs; ++aggId) {
262 LO aggSize = aggSizes[aggId];
263 DenseMatrix A_aggPart(aggSize, aggSize,
true);
264 DenseVector offDiagonalAbsoluteSums(aggSize,
true);
267 for (LO idx=LO_ZERO; idx<aggSize; ++idx) {
269 LO nodeId = aggSortedVertices[idx+aggsToIndices[aggId]];
270 A->getLocalRowView(nodeId, rowIndices, rowValues);
271 AT->getLocalRowView(nodeId, rowIndices, colValues);
274 for (LO elem=LO_ZERO; elem<rowIndices.size();++elem) {
276 LO nodeId2 = rowIndices[elem];
277 SC val = (rowValues[elem]+colValues[elem])/SCALAR_TWO;
279 LO idxInAgg = -LO_ONE;
284 for (LO idx2=LO_ZERO; idx2<aggSize; ++idx2) {
286 if (aggSortedVertices[idx2+aggsToIndices[aggId]] == nodeId2) {
296 if (idxInAgg == -LO_ONE) {
298 offDiagonalAbsoluteSums[idx] += Teuchos::ScalarTraits<SC>::magnitude(val);
302 A_aggPart(idx,idxInAgg) = Teuchos::ScalarTraits<SC>::real(val);
312 DenseMatrix A_aggPartDiagonal(aggSize, aggSize,
true);
313 MT diag_sum = MT_ZERO;
314 for (
int i=0;i<aggSize;++i) {
315 A_aggPartDiagonal(i,i) = Teuchos::ScalarTraits<SC>::real(A_aggPart(i,i));
316 diag_sum += Teuchos::ScalarTraits<SC>::real(A_aggPart(i,i));
319 DenseMatrix ones(aggSize, aggSize,
false);
320 ones.putScalar(MT_ONE);
324 DenseMatrix tmp(aggSize, aggSize,
false);
325 DenseMatrix topMatrix(A_aggPartDiagonal);
327 tmp.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, MT_ONE, ones, A_aggPartDiagonal, MT_ZERO);
328 topMatrix.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, -MT_ONE/diag_sum, A_aggPartDiagonal, tmp, MT_ONE);
331 DenseMatrix bottomMatrix(A_aggPart);
332 MT matrixNorm = A_aggPart.normInf();
335 const MT boost = (algo == ALG_FORWARD) ? (-1e4*Teuchos::ScalarTraits<MT>::eps()*matrixNorm) : MT_ZERO;
337 for (
int i=0;i<aggSize;++i){
338 bottomMatrix(i,i) -= offDiagonalAbsoluteSums(i) + boost;
343 DenseVector alpha_real(aggSize,
false);
344 DenseVector alpha_imag(aggSize,
false);
345 DenseVector beta(aggSize,
false);
347 DenseVector workArray(14*(aggSize+1),
false);
349 LO (*ptr2func)(MT*, MT*, MT*);
355 const char compute_flag =
'N';
356 if(algo == ALG_FORWARD) {
358 myLapack.GGES(compute_flag,compute_flag,compute_flag,ptr2func,aggSize,
359 topMatrix.values(),aggSize,bottomMatrix.values(),aggSize,&sdim,
360 alpha_real.values(),alpha_imag.values(),beta.values(),vl,aggSize,
361 vr,aggSize,workArray.values(),workArray.length(),bwork,
363 TEUCHOS_ASSERT(info == LO_ZERO);
365 MT maxEigenVal = MT_ZERO;
366 for (
int i=LO_ZERO;i<aggSize;++i) {
369 maxEigenVal = std::max(maxEigenVal, alpha_real[i]/beta[i]);
372 (agg_qualities->getDataNonConst(0))[aggId] = (MT_ONE+MT_ONE)*maxEigenVal;
377 myLapack.GGES(compute_flag,compute_flag,compute_flag,ptr2func,aggSize,
378 bottomMatrix.values(),aggSize,topMatrix.values(),aggSize,&sdim,
379 alpha_real.values(),alpha_imag.values(),beta.values(),vl,aggSize,
380 vr,aggSize,workArray.values(),workArray.length(),bwork,
383 TEUCHOS_ASSERT(info == LO_ZERO);
385 MT minEigenVal = MT_ZERO;
387 for (
int i=LO_ZERO;i<aggSize;++i) {
388 MT ev = alpha_real[i] / beta[i];
389 if(ev > zeroThreshold) {
390 if (minEigenVal == MT_ZERO) minEigenVal = ev;
391 else minEigenVal = std::min(minEigenVal,ev);
394 if(minEigenVal == MT_ZERO) (agg_qualities->getDataNonConst(0))[aggId] = Teuchos::ScalarTraits<MT>::rmax();
395 else (agg_qualities->getDataNonConst(0))[aggId] = (MT_ONE+MT_ONE) / minEigenVal;