diff --git a/src/foam/matrices/blockLduMatrix/BlockAmg/BlockAmgCycle.C b/src/foam/matrices/blockLduMatrix/BlockAmg/BlockAmgCycle.C index 1607b4670..d325fa3a3 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAmg/BlockAmgCycle.C +++ b/src/foam/matrices/blockLduMatrix/BlockAmg/BlockAmgCycle.C @@ -133,10 +133,7 @@ void Foam::BlockAmgCycle::fixedCycle Field& bCoarse = coarseLevelPtr_->levelPtr_->b(); // Zero out coarse x - forAll (xCoarse,i) - { - xCoarse[i] *= 0.0; - } + xCoarse = pTraits::zero; // Restrict residual: optimisation on number of pre-sweeps levelPtr_->restrictResidual diff --git a/src/foam/matrices/blockLduMatrix/BlockAmg/BlockMatrixCoarsening/BlockMatrixAgglomeration.C b/src/foam/matrices/blockLduMatrix/BlockAmg/BlockMatrixCoarsening/BlockMatrixAgglomeration.C index 1d3b08de5..728c87c0e 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAmg/BlockMatrixCoarsening/BlockMatrixAgglomeration.C +++ b/src/foam/matrices/blockLduMatrix/BlockAmg/BlockMatrixCoarsening/BlockMatrixAgglomeration.C @@ -25,7 +25,7 @@ Class BlockMatrixAgglomeration Description - Agglomerative block matrix AMG corsening, adjusted for BlockLduMatrix + Agglomerative block matrix AMG corsening Author Klas Jareteg, 2012-12-13 @@ -33,6 +33,7 @@ Author \*---------------------------------------------------------------------------*/ #include "BlockMatrixAgglomeration.H" +#include "boolList.H" #include "coeffFields.H" #include "addToRunTimeSelectionTable.H" #include "BlockGAMGInterfaceField.H" @@ -40,6 +41,12 @@ Author // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // +template +const Foam::scalar Foam::BlockMatrixAgglomeration::diagFactor_ +( + debug::tolerances("aamgDiagFactor", 1e-8) +); + template const Foam::scalar Foam::BlockMatrixAgglomeration::weightFactor_ = 0.65; @@ -47,7 +54,7 @@ const Foam::scalar Foam::BlockMatrixAgglomeration::weightFactor_ = 0.65; // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // template -void Foam::BlockMatrixAgglomeration::calcChild() +void Foam::BlockMatrixAgglomeration::calcAgglomeration() { // Algorithm: // 1) Create temporary equation addressing using a double-pass algorithm. @@ -96,9 +103,9 @@ void Foam::BlockMatrixAgglomeration::calcChild() // Create column and coefficient index array { - // Use child array to count number of entries per row. + // Use agglomIndex to count number of entries per row. // Reset the list for counting - labelList& nPerRow = child_; + labelList& nPerRow = agglomIndex_; nPerRow = 0; forAll (upperAddr, coeffI) @@ -123,8 +130,8 @@ void Foam::BlockMatrixAgglomeration::calcChild() nPerRow[lowerAddr[coeffI]]++; } - // Reset child array - child_ = -1; + // Reset agglomeration index array + agglomIndex_ = -1; } @@ -132,43 +139,122 @@ void Foam::BlockMatrixAgglomeration::calcChild() // Get matrix coefficients const CoeffField& diag = matrix_.diag(); - const CoeffField& upper = matrix_.upper(); + + // Coefficient magnitudes are pre-calculated + scalarField magDiag(diag.size()); + scalarField magOffDiag(upperAddr.size()); + + normPtr_->coeffMag(diag, magDiag); + + if (matrix_.asymmetric()) + { + scalarField magUpper(upperAddr.size()); + scalarField magLower(upperAddr.size()); + + normPtr_->coeffMag(matrix_.upper(), magUpper); + normPtr_->coeffMag(matrix_.lower(), magLower); + + magOffDiag = Foam::max(magUpper, magLower); + } + else if (matrix_.symmetric()) + { + normPtr_->coeffMag(matrix_.upper(), magOffDiag); + } + else + { + // Diag only matrix. Reset and return + agglomIndex_ = 0; + nCoarseEqns_ = 1; + + return; + } labelList sizeOfGroups(nRows, 0); nCoarseEqns_ = 0; - label indexU, indexG, colI, curEqn, nextEqn, groupPassI; + // Gather disconnected and weakly connected equations into cluster zero + // Weak connection is assumed to be the one where the off-diagonal + // coefficient is smaller than diagFactor_*diag + { + // Algorithm + // Mark all cells to belong to zero cluster + // Go through all upper and lower coefficients and for the ones + // larger than threshold mark the equations out of cluster zero - scalar magRowDiag, magColDiag, weight, weightU, weightG; + scalarField magScaledDiag = diagFactor_*magDiag; - // Magnitudes pre-calculated - Field magDiag(diag.size()); - Field magUpper(upper.size()); + boolList zeroCluster(diag.size(), true); - normPtr_->coeffMag(diag,magDiag); - normPtr_->coeffMag(upper,magUpper); + forAll (magOffDiag, coeffI) + { + if (magOffDiag[coeffI] > magScaledDiag[upperAddr[coeffI]]) + { + zeroCluster[upperAddr[coeffI]] = false; + } + + if (magOffDiag[coeffI] > magScaledDiag[lowerAddr[coeffI]]) + { + zeroCluster[lowerAddr[coeffI]] = false; + } + } + + // Collect solo equations + label nSolo = 0; + + forAll (zeroCluster, eqnI) + { + if (zeroCluster[eqnI]) + { + // Found solo equation + nSolo++; + + agglomIndex_[eqnI] = nCoarseEqns_; + } + } + + reduce(nSolo, sumOp