135 const SC SCALAR_ONE = Teuchos::ScalarTraits<SC>::one();
136 const SC SCALAR_TWO = SCALAR_ONE + SCALAR_ONE;
138 const LO LO_ZERO = Teuchos::OrdinalTraits<LO>::zero();
139 const LO LO_ONE = Teuchos::OrdinalTraits<LO>::one();
142 const MT MT_ZERO = Teuchos::ScalarTraits<MT>::zero();
143 const MT MT_ONE = Teuchos::ScalarTraits<MT>::one();
144 ParameterList pL = GetParameterList();
146 RCP<const Matrix> AT = A;
149 std::string algostr = pL.get<std::string>(
"aggregate qualities: algorithm");
150 MT zeroThreshold = Teuchos::as<MT>(pL.get<
double>(
"aggregate qualities: zero threshold"));
151 enum AggAlgo { ALG_FORWARD = 0,
154 if (algostr ==
"forward") {
156 GetOStream(
Statistics1) <<
"AggregateQuality: Using 'forward' algorithm" << std::endl;
157 }
else if (algostr ==
"reverse") {
159 GetOStream(
Statistics1) <<
"AggregateQuality: Using 'reverse' algorithm" << std::endl;
164 bool check_symmetry = pL.get<
bool>(
"aggregate qualities: check symmetry");
165 if (check_symmetry) {
166 RCP<MultiVector> x = MultiVectorFactory::Build(A->getMap(), 1,
false);
167 x->Xpetra_randomize();
169 RCP<MultiVector> tmp = MultiVectorFactory::Build(A->getMap(), 1,
false);
171 A->apply(*x, *tmp, Teuchos::NO_TRANS);
172 A->apply(*x, *tmp, Teuchos::TRANS, -SCALAR_ONE, SCALAR_ONE);
174 Array<magnitudeType> tmp_norm(1);
175 tmp->norm2(tmp_norm());
177 Array<magnitudeType> x_norm(1);
178 tmp->norm2(x_norm());
180 if (tmp_norm[0] > 1e-10 * x_norm[0]) {
181 std::string transpose_string =
"transpose";
182 RCP<ParameterList> whatever;
185 assert(A->getMap()->isSameAs(*(AT->getMap())));
197 ArrayRCP<LO> aggSortedVertices, aggsToIndices, aggSizes;
198 ConvertAggregatesData(aggs, aggSortedVertices, aggsToIndices, aggSizes);
200 LO numAggs = aggs->GetNumAggregates();
204 typedef Teuchos::SerialDenseMatrix<LO, MT> DenseMatrix;
205 typedef Teuchos::SerialDenseVector<LO, MT> DenseVector;
207 ArrayView<const LO> rowIndices;
208 ArrayView<const SC> rowValues;
209 ArrayView<const SC> colValues;
210 Teuchos::LAPACK<LO, MT> myLapack;
213 for (LO aggId = LO_ZERO; aggId < numAggs; ++aggId) {
214 LO aggSize = aggSizes[aggId];
215 DenseMatrix A_aggPart(aggSize, aggSize,
true);
216 DenseVector offDiagonalAbsoluteSums(aggSize,
true);
219 for (LO idx = LO_ZERO; idx < aggSize; ++idx) {
220 LO nodeId = aggSortedVertices[idx + aggsToIndices[aggId]];
221 A->getLocalRowView(nodeId, rowIndices, rowValues);
222 AT->getLocalRowView(nodeId, rowIndices, colValues);
225 for (LO elem = LO_ZERO; elem < rowIndices.size(); ++elem) {
226 LO nodeId2 = rowIndices[elem];
227 SC val = (rowValues[elem] + colValues[elem]) / SCALAR_TWO;
229 LO idxInAgg = -LO_ONE;
234 for (LO idx2 = LO_ZERO; idx2 < aggSize; ++idx2) {
235 if (aggSortedVertices[idx2 + aggsToIndices[aggId]] == nodeId2) {
242 if (idxInAgg == -LO_ONE) {
244 offDiagonalAbsoluteSums[idx] += Teuchos::ScalarTraits<SC>::magnitude(val);
248 A_aggPart(idx, idxInAgg) = Teuchos::ScalarTraits<SC>::real(val);
255 DenseMatrix A_aggPartDiagonal(aggSize, aggSize,
true);
256 MT diag_sum = MT_ZERO;
257 for (
int i = 0; i < aggSize; ++i) {
258 A_aggPartDiagonal(i, i) = Teuchos::ScalarTraits<SC>::real(A_aggPart(i, i));
259 diag_sum += Teuchos::ScalarTraits<SC>::real(A_aggPart(i, i));
262 DenseMatrix ones(aggSize, aggSize,
false);
263 ones.putScalar(MT_ONE);
267 DenseMatrix tmp(aggSize, aggSize,
false);
268 DenseMatrix topMatrix(A_aggPartDiagonal);
270 tmp.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, MT_ONE, ones, A_aggPartDiagonal, MT_ZERO);
271 topMatrix.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, -MT_ONE / diag_sum, A_aggPartDiagonal, tmp, MT_ONE);
274 DenseMatrix bottomMatrix(A_aggPart);
275 MT matrixNorm = A_aggPart.normInf();
278 const MT boost = (algo == ALG_FORWARD) ? (-1e4 * Teuchos::ScalarTraits<MT>::eps() * matrixNorm) : MT_ZERO;
280 for (
int i = 0; i < aggSize; ++i) {
281 bottomMatrix(i, i) -= offDiagonalAbsoluteSums(i) + boost;
286 DenseVector alpha_real(aggSize,
false);
287 DenseVector alpha_imag(aggSize,
false);
288 DenseVector beta(aggSize,
false);
290 DenseVector workArray(14 * (aggSize + 1),
false);
299 const char compute_flag =
'N';
300 if (algo == ALG_FORWARD) {
302 myLapack.GGES(compute_flag, compute_flag, compute_flag, ptr2func, aggSize,
303 topMatrix.values(), aggSize, bottomMatrix.values(), aggSize, &sdim,
304 alpha_real.values(), alpha_imag.values(), beta.values(), vl, aggSize,
305 vr, aggSize, workArray.values(), workArray.length(), bwork,
307 TEUCHOS_ASSERT(info == LO_ZERO);
309 MT maxEigenVal = MT_ZERO;
310 for (
int i = LO_ZERO; i < aggSize; ++i) {
313 maxEigenVal = std::max(maxEigenVal, alpha_real[i] / beta[i]);
316 (agg_qualities->getDataNonConst(0))[aggId] = (MT_ONE + MT_ONE) * maxEigenVal;
320 myLapack.GGES(compute_flag, compute_flag, compute_flag, ptr2func, aggSize,
321 bottomMatrix.values(), aggSize, topMatrix.values(), aggSize, &sdim,
322 alpha_real.values(), alpha_imag.values(), beta.values(), vl, aggSize,
323 vr, aggSize, workArray.values(), workArray.length(), bwork,
326 TEUCHOS_ASSERT(info == LO_ZERO);
328 MT minEigenVal = MT_ZERO;
330 for (
int i = LO_ZERO; i < aggSize; ++i) {
331 MT ev = alpha_real[i] / beta[i];
332 if (ev > zeroThreshold) {
333 if (minEigenVal == MT_ZERO)
336 minEigenVal = std::min(minEigenVal, ev);
339 if (minEigenVal == MT_ZERO)
340 (agg_qualities->getDataNonConst(0))[aggId] = Teuchos::ScalarTraits<MT>::rmax();
342 (agg_qualities->getDataNonConst(0))[aggId] = (MT_ONE + MT_ONE) / minEigenVal;