diff --git a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockAMGCycle.C b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockAMGCycle.C index 101d1b9e6..1a6d28e94 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockAMGCycle.C +++ b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockAMGCycle.C @@ -107,6 +107,22 @@ void Foam::BlockAMGCycle::makeCoarseLevels(const label nMaxLevels) } +template +Foam::BlockLduMatrix& Foam::BlockAMGCycle::coarseMatrix() +{ + if (!coarseLevelPtr_) + { + FatalErrorIn + ( + "BlockLduMatrix& BlockAMGCycle::coarseMatrix()" + ) << "Coarse level not available" + << abort(FatalError); + } + + return coarseLevelPtr_->matrix(); +} + + template void Foam::BlockAMGCycle::fixedCycle ( @@ -193,7 +209,21 @@ void Foam::BlockAMGCycle::fixedCycle else { // Call direct solver - levelPtr_->solve(x, b, 1e-9, 0); + levelPtr_->solve(x, b, 1e-7, 0); + } +} + + +template +void Foam::BlockAMGCycle::initMatrix() +{ + // Update current level + levelPtr_->initLevel(coarseLevelPtr_); + + // If present, update coarse levels recursively + if (coarseLevelPtr_) + { + coarseLevelPtr_->initMatrix(); } } diff --git a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockAMGCycle.H b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockAMGCycle.H index 56da581f5..517d7f90c 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockAMGCycle.H +++ b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockAMGCycle.H @@ -143,6 +143,9 @@ public: return nLevels_; } + //- Return coarse matrix + BlockLduMatrix& coarseMatrix(); + //- Calculate residual void residual ( @@ -166,6 +169,9 @@ public: const label nPostSweeps, const bool scale ) const; + + //- Re-initialise preconditioner after matrix coefficient update + void initMatrix(); }; diff --git a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockAMGLevel.H b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockAMGLevel.H index 9db62dc0e..b1a119fcd 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockAMGLevel.H +++ b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockAMGLevel.H @@ -86,6 +86,9 @@ public: // Member Functions + //- Return reference to matrix + virtual BlockLduMatrix& matrix() = 0; + //- Return reference to x virtual Field& x() = 0; @@ -144,6 +147,12 @@ public: //- Create next level from current level virtual autoPtr makeNextLevel() const = 0; + + //- Re-initialise AMG level after matrix coefficient update + virtual void initLevel + ( + autoPtr >& coarseLevelPtr + ) = 0; }; diff --git a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixAgglomeration/BlockMatrixAgglomeration.H b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixAgglomeration/BlockMatrixAgglomeration.H index e75d523b3..779c528ab 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixAgglomeration/BlockMatrixAgglomeration.H +++ b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixAgglomeration/BlockMatrixAgglomeration.H @@ -192,6 +192,9 @@ public: Field& x, const Field& coarseX ) const; + + //- Update coarse matrix using same coefficients + virtual void updateMatrix(BlockLduMatrix& coarseMatrix) const; }; diff --git a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixClustering/BlockMatrixClustering.C b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixClustering/BlockMatrixClustering.C index c5752bba9..4cffd8dc5 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixClustering/BlockMatrixClustering.C +++ b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixClustering/BlockMatrixClustering.C @@ -495,6 +495,163 @@ void Foam::BlockMatrixClustering::calcClustering() reduce(coarsen_, andOp()); + // If the matrix will be coarsened, create off-diagonal agglomeration + // Does the matrix have solo equations + bool soloEqns = nSolo_ > 0; + + // Storage for block neighbours and coefficients + + // Guess initial maximum number of neighbours in block + label maxNnbrs = 10; + + // Number of neighbours per block + labelList blockNnbrs(nCoarseEqns_, 0); + + // Setup initial packed storage for neighbours and coefficients + labelList blockNbrsData(maxNnbrs*nCoarseEqns_); + + const label nFineCoeffs = upperAddr.size(); + + // Create face-restriction addressing + coeffRestrictAddr_.setSize(nFineCoeffs); + + // Initial neighbour array (not in upper-triangle order) + labelList initCoarseNeighb(nFineCoeffs); + + // Counter for coarse coeffs + label nCoarseCoeffs = 0; + + // Loop through all fine coeffs + forAll (upperAddr, fineCoeffi) + { + label rmUpperAddr = agglomIndex_[upperAddr[fineCoeffi]]; + label rmLowerAddr = agglomIndex_[lowerAddr[fineCoeffi]]; + + // If the coefficient touches block zero and solo equations are + // present, skip it + if (soloEqns && (rmUpperAddr == 0 || rmLowerAddr == 0)) + { + continue; + } + + if (rmUpperAddr == rmLowerAddr) + { + // For each fine coeff inside of a coarse cluster keep the address + // of the cluster corresponding to the coeff in the + // coeffRestrictAddr_ as a negative index + coeffRestrictAddr_[fineCoeffi] = -(rmUpperAddr + 1); + } + else + { + // This coeff is a part of a coarse coeff + + label cOwn = rmUpperAddr; + label cNei = rmLowerAddr; + + // Get coarse owner and neighbour + if (rmUpperAddr > rmLowerAddr) + { + cOwn = rmLowerAddr; + cNei = rmUpperAddr; + } + + // Check the neighbour to see if this coeff has already been found + bool nbrFound = false; + label& ccnCoeffs = blockNnbrs[cOwn]; + + for (int i = 0; i < ccnCoeffs; i++) + { + if (initCoarseNeighb[blockNbrsData[maxNnbrs*cOwn + i]] == cNei) + { + nbrFound = true; + coeffRestrictAddr_[fineCoeffi] = + blockNbrsData[maxNnbrs*cOwn + i]; + break; + } + } + + if (!nbrFound) + { + if (ccnCoeffs >= maxNnbrs) + { + // Double the size of list and copy data + label oldMaxNnbrs = maxNnbrs; + maxNnbrs *= 2; + + // Resize and copy list + const labelList oldBlockNbrsData = blockNbrsData; + blockNbrsData.setSize(maxNnbrs*nCoarseEqns_); + + forAll (blockNnbrs, i) + { + for (int j = 0; j < blockNnbrs[i]; j++) + { + blockNbrsData[maxNnbrs*i + j] = + oldBlockNbrsData[oldMaxNnbrs*i + j]; + } + } + } + + blockNbrsData[maxNnbrs*cOwn + ccnCoeffs] = nCoarseCoeffs; + initCoarseNeighb[nCoarseCoeffs] = cNei; + coeffRestrictAddr_[fineCoeffi] = nCoarseCoeffs; + ccnCoeffs++; + + // New coarse coeff created + nCoarseCoeffs++; + } + } + } // End for all fine coeffs + + + // Renumber into upper-triangular order + + // All coarse owner-neighbour storage + labelList coarseOwner(nCoarseCoeffs); + labelList coarseNeighbour(nCoarseCoeffs); + labelList coarseCoeffMap(nCoarseCoeffs); + + label coarseCoeffi = 0; + + forAll (blockNnbrs, cci) + { + label* cCoeffs = &blockNbrsData[maxNnbrs*cci]; + label ccnCoeffs = blockNnbrs[cci]; + + for (int i = 0; i < ccnCoeffs; i++) + { + coarseOwner[coarseCoeffi] = cci; + coarseNeighbour[coarseCoeffi] = initCoarseNeighb[cCoeffs[i]]; + coarseCoeffMap[cCoeffs[i]] = coarseCoeffi; + coarseCoeffi++; + } + } + + forAll(coeffRestrictAddr_, fineCoeffi) + { + label rmUpperAddr = agglomIndex_[upperAddr[fineCoeffi]]; + label rmLowerAddr = agglomIndex_[lowerAddr[fineCoeffi]]; + + // If the coefficient touches block zero and solo equations are + // present, skip it + if (soloEqns && (rmUpperAddr == 0 || rmLowerAddr == 0)) + { + continue; + } + + if (coeffRestrictAddr_[fineCoeffi] >= 0) + { + coeffRestrictAddr_[fineCoeffi] = + coarseCoeffMap[coeffRestrictAddr_[fineCoeffi]]; + } + } + + // Clear the temporary storage for the coarse matrix data + blockNnbrs.setSize(0); + blockNbrsData.setSize(0); + initCoarseNeighb.setSize(0); + coarseCoeffMap.setSize(0); + if (blockLduMatrix::debug >= 3) { // Count singleton clusters @@ -555,10 +712,8 @@ void Foam::BlockMatrixClustering::restrictDiag squareTypeField& activeCoarseCoeff = coarseCoeff.asSquare(); const squareTypeField& activeCoeff = Coeff.asSquare(); - forAll (coarseCoeff, i) - { - activeCoarseCoeff[i] = pTraits::zero; - } + // Reset coefficients to zero + activeCoarseCoeff = pTraits::zero; forAll (Coeff, i) { @@ -577,10 +732,8 @@ void Foam::BlockMatrixClustering::restrictDiag linearTypeField& activeCoarseCoeff = coarseCoeff.asLinear(); const linearTypeField& activeCoeff = Coeff.asLinear(); - forAll (coarseCoeff, i) - { - activeCoarseCoeff[i] = pTraits::zero; - } + // Reset coefficients to zero + activeCoarseCoeff = pTraits::zero; forAll (Coeff, i) { @@ -599,10 +752,8 @@ void Foam::BlockMatrixClustering::restrictDiag scalarTypeField& activeCoarseCoeff = coarseCoeff.asScalar(); const scalarTypeField& activeCoeff = Coeff.asScalar(); - forAll (coarseCoeff, i) - { - activeCoarseCoeff[i] = pTraits::zero; - } + // Reset coefficients to zero + activeCoarseCoeff = pTraits::zero; forAll (Coeff, i) { @@ -624,7 +775,6 @@ template template void Foam::BlockMatrixClustering::agglomerateCoeffs ( - const labelList& coeffRestrictAddr, Field& activeCoarseDiag, Field& activeCoarseUpper, const Field& activeFineUpper, @@ -638,7 +788,10 @@ void Foam::BlockMatrixClustering::agglomerateCoeffs const unallocLabelList& upperAddr = matrix_.lduAddr().upperAddr(); const unallocLabelList& lowerAddr = matrix_.lduAddr().lowerAddr(); - forAll(coeffRestrictAddr, fineCoeffI) + // Reset coefficients to zero. Cannot touch the diagonal + activeCoarseUpper = pTraits::zero; + + forAll(coeffRestrictAddr_, fineCoeffI) { label rmUpperAddr = agglomIndex_[upperAddr[fineCoeffI]]; label rmLowerAddr = agglomIndex_[lowerAddr[fineCoeffI]]; @@ -650,7 +803,7 @@ void Foam::BlockMatrixClustering::agglomerateCoeffs continue; } - label cCoeff = coeffRestrictAddr[fineCoeffI]; + label cCoeff = coeffRestrictAddr_[fineCoeffI]; if (cCoeff >= 0) { @@ -673,7 +826,6 @@ template template void Foam::BlockMatrixClustering::agglomerateCoeffs ( - const labelList& coeffRestrictAddr, Field& activeCoarseDiag, Field& activeCoarseUpper, const Field& activeFineUpper, @@ -688,7 +840,11 @@ void Foam::BlockMatrixClustering::agglomerateCoeffs const unallocLabelList& upperAddr = matrix_.lduAddr().upperAddr(); const unallocLabelList& lowerAddr = matrix_.lduAddr().lowerAddr(); - forAll(coeffRestrictAddr, fineCoeffI) + // Reset coefficients to zero. Cannot touch the diagonal + activeCoarseUpper = pTraits::zero; + activeCoarseLower = pTraits::zero; + + forAll(coeffRestrictAddr_, fineCoeffI) { label rmUpperAddr = agglomIndex_[upperAddr[fineCoeffI]]; label rmLowerAddr = agglomIndex_[lowerAddr[fineCoeffI]]; @@ -700,7 +856,7 @@ void Foam::BlockMatrixClustering::agglomerateCoeffs continue; } - label cCoeff = coeffRestrictAddr[fineCoeffI]; + label cCoeff = coeffRestrictAddr_[fineCoeffI]; if (cCoeff >= 0) { @@ -739,10 +895,8 @@ void Foam::BlockMatrixClustering::restrictDiagDecoupled linearTypeField& activeCoarseCoeff = coarseCoeff.asLinear(); const linearTypeField& activeCoeff = Coeff.asLinear(); - forAll (coarseCoeff, i) - { - activeCoarseCoeff[i] = pTraits::zero; - } + // Reset coefficients to zero + activeCoarseCoeff = pTraits::zero; forAll (Coeff, i) { @@ -761,10 +915,8 @@ void Foam::BlockMatrixClustering::restrictDiagDecoupled scalarTypeField& activeCoarseCoeff = coarseCoeff.asScalar(); const scalarTypeField& activeCoeff = Coeff.asScalar(); - forAll (coarseCoeff, i) - { - activeCoarseCoeff[i] = pTraits::zero; - } + // Reset coefficients to zero + activeCoarseCoeff = pTraits::zero; forAll (Coeff, i) { @@ -800,6 +952,7 @@ Foam::BlockMatrixClustering::BlockMatrixClustering maxGroupSize_(readLabel(dict.lookup("maxGroupSize"))), normPtr_(BlockCoeffNorm::New(dict)), agglomIndex_(matrix_.lduAddr().size()), + coeffRestrictAddr_(), groupSize_(groupSize), nSolo_(0), nCoarseEqns_(0), @@ -850,8 +1003,6 @@ Foam::BlockMatrixClustering::restrictMatrix() const const unallocLabelList& upperAddr = matrix_.lduAddr().upperAddr(); const unallocLabelList& lowerAddr = matrix_.lduAddr().lowerAddr(); - const label nFineCoeffs = upperAddr.size(); - # ifdef FULLDEBUG if (agglomIndex_.size() != matrix_.lduAddr().size()) { @@ -866,161 +1017,6 @@ Foam::BlockMatrixClustering::restrictMatrix() const } # endif - // Does the matrix have solo equations - bool soloEqns = nSolo_ > 0; - - // Storage for block neighbours and coefficients - - // Guess initial maximum number of neighbours in block - label maxNnbrs = 10; - - // Number of neighbours per block - labelList blockNnbrs(nCoarseEqns_, 0); - - // Setup initial packed storage for neighbours and coefficients - labelList blockNbrsData(maxNnbrs*nCoarseEqns_); - - // Create face-restriction addressing - labelList coeffRestrictAddr(nFineCoeffs); - - // Initial neighbour array (not in upper-triangle order) - labelList initCoarseNeighb(nFineCoeffs); - - // Counter for coarse coeffs - label nCoarseCoeffs = 0; - - // Loop through all fine coeffs - forAll (upperAddr, fineCoeffi) - { - label rmUpperAddr = agglomIndex_[upperAddr[fineCoeffi]]; - label rmLowerAddr = agglomIndex_[lowerAddr[fineCoeffi]]; - - // If the coefficient touches block zero and solo equations are - // present, skip it - if (soloEqns && (rmUpperAddr == 0 || rmLowerAddr == 0)) - { - continue; - } - - if (rmUpperAddr == rmLowerAddr) - { - // For each fine coeff inside of a coarse cluster keep the address - // of the cluster corresponding to the coeff in the - // coeffRestrictAddr as a negative index - coeffRestrictAddr[fineCoeffi] = -(rmUpperAddr + 1); - } - else - { - // This coeff is a part of a coarse coeff - - label cOwn = rmUpperAddr; - label cNei = rmLowerAddr; - - // Get coarse owner and neighbour - if (rmUpperAddr > rmLowerAddr) - { - cOwn = rmLowerAddr; - cNei = rmUpperAddr; - } - - // Check the neighbour to see if this coeff has already been found - bool nbrFound = false; - label& ccnCoeffs = blockNnbrs[cOwn]; - - for (int i = 0; i < ccnCoeffs; i++) - { - if (initCoarseNeighb[blockNbrsData[maxNnbrs*cOwn + i]] == cNei) - { - nbrFound = true; - coeffRestrictAddr[fineCoeffi] = - blockNbrsData[maxNnbrs*cOwn + i]; - break; - } - } - - if (!nbrFound) - { - if (ccnCoeffs >= maxNnbrs) - { - // Double the size of list and copy data - label oldMaxNnbrs = maxNnbrs; - maxNnbrs *= 2; - - // Resize and copy list - const labelList oldBlockNbrsData = blockNbrsData; - blockNbrsData.setSize(maxNnbrs*nCoarseEqns_); - - forAll (blockNnbrs, i) - { - for (int j = 0; j < blockNnbrs[i]; j++) - { - blockNbrsData[maxNnbrs*i + j] = - oldBlockNbrsData[oldMaxNnbrs*i + j]; - } - } - } - - blockNbrsData[maxNnbrs*cOwn + ccnCoeffs] = nCoarseCoeffs; - initCoarseNeighb[nCoarseCoeffs] = cNei; - coeffRestrictAddr[fineCoeffi] = nCoarseCoeffs; - ccnCoeffs++; - - // New coarse coeff created - nCoarseCoeffs++; - } - } - } // End for all fine coeffs - - - // Renumber into upper-triangular order - - // All coarse owner-neighbour storage - labelList coarseOwner(nCoarseCoeffs); - labelList coarseNeighbour(nCoarseCoeffs); - labelList coarseCoeffMap(nCoarseCoeffs); - - label coarseCoeffi = 0; - - forAll (blockNnbrs, cci) - { - label* cCoeffs = &blockNbrsData[maxNnbrs*cci]; - label ccnCoeffs = blockNnbrs[cci]; - - for (int i = 0; i < ccnCoeffs; i++) - { - coarseOwner[coarseCoeffi] = cci; - coarseNeighbour[coarseCoeffi] = initCoarseNeighb[cCoeffs[i]]; - coarseCoeffMap[cCoeffs[i]] = coarseCoeffi; - coarseCoeffi++; - } - } - - forAll(coeffRestrictAddr, fineCoeffi) - { - label rmUpperAddr = agglomIndex_[upperAddr[fineCoeffi]]; - label rmLowerAddr = agglomIndex_[lowerAddr[fineCoeffi]]; - - // If the coefficient touches block zero and solo equations are - // present, skip it - if (soloEqns && (rmUpperAddr == 0 || rmLowerAddr == 0)) - { - continue; - } - - if (coeffRestrictAddr[fineCoeffi] >= 0) - { - coeffRestrictAddr[fineCoeffi] = - coarseCoeffMap[coeffRestrictAddr[fineCoeffi]]; - } - } - - // Clear the temporary storage for the coarse matrix data - blockNnbrs.setSize(0); - blockNbrsData.setSize(0); - initCoarseNeighb.setSize(0); - coarseCoeffMap.setSize(0); - - // Create coarse-level coupled interfaces // Create coarse interfaces, addressing and coefficients @@ -1028,8 +1024,7 @@ Foam::BlockMatrixClustering::restrictMatrix() const const_cast& >(matrix_).interfaces().size(); const typename BlockLduInterfaceFieldPtrsList::Type& - interfaceFields = - const_cast&>(matrix_).interfaces(); + interfaceFields = matrix_.interfaces(); // Set the coarse interfaces and coefficients lduInterfacePtrsList coarseInterfaces(interfaceSize); @@ -1046,7 +1041,7 @@ Foam::BlockMatrixClustering::restrictMatrix() const nCoarseEqns_, coarseOwner, coarseNeighbour, - Pstream::worldComm, //HJ, AMG Comm fineMesh.comm(), + Pstream::worldComm, true ) ); @@ -1140,7 +1135,39 @@ Foam::BlockMatrixClustering::restrictMatrix() const ); BlockLduMatrix& coarseMatrix = coarseMatrixPtr(); + // Build matrix coefficients + this->updateMatrix(coarseMatrix); + + // Create and return BlockAMGLevel + return autoPtr > + ( + new coarseBlockAMGLevel + ( + coarseAddrPtr, + coarseMatrixPtr, + this->dict(), + this->type(), + this->groupSize(), + this->minCoarseEqns() + ) + ); +} + + +template +void Foam::BlockMatrixClustering::updateMatrix +( + BlockLduMatrix& coarseMatrix +) const +{ + // Get interfaces from fine matrix + const typename BlockLduInterfaceFieldPtrsList::Type& + interfaceFields = matrix_.interfaces(); + // Get interfaces from coarse matrix + lduInterfacePtrsList coarseInterfaces = coarseMatrix.mesh().interfaces(); + + // Get interfaces fields from coarse matrix typename BlockLduInterfaceFieldPtrsList::Type& coarseInterfaceFieldsTransfer = coarseMatrix.interfaces(); @@ -1242,7 +1269,6 @@ Foam::BlockMatrixClustering::restrictMatrix() const agglomerateCoeffs ( - coeffRestrictAddr, activeCoarseDiag, activeCoarseUpper, activeFineUpper, @@ -1264,7 +1290,6 @@ Foam::BlockMatrixClustering::restrictMatrix() const agglomerateCoeffs ( - coeffRestrictAddr, activeCoarseDiag, activeCoarseUpper, activeFineUpper, @@ -1286,7 +1311,6 @@ Foam::BlockMatrixClustering::restrictMatrix() const agglomerateCoeffs ( - coeffRestrictAddr, activeCoarseDiag, activeCoarseUpper, activeFineUpper, @@ -1326,7 +1350,6 @@ Foam::BlockMatrixClustering::restrictMatrix() const agglomerateCoeffs ( - coeffRestrictAddr, activeCoarseDiag, activeCoarseUpper, activeFineUpper, @@ -1352,7 +1375,6 @@ Foam::BlockMatrixClustering::restrictMatrix() const agglomerateCoeffs ( - coeffRestrictAddr, activeCoarseDiag, activeCoarseUpper, activeFineUpper, @@ -1378,7 +1400,6 @@ Foam::BlockMatrixClustering::restrictMatrix() const agglomerateCoeffs ( - coeffRestrictAddr, activeCoarseDiag, activeCoarseUpper, activeFineUpper, @@ -1396,20 +1417,6 @@ Foam::BlockMatrixClustering::restrictMatrix() const << abort(FatalError); } } - - // Create and return BlockAMGLevel - return autoPtr > - ( - new coarseBlockAMGLevel - ( - coarseAddrPtr, - coarseMatrixPtr, - this->dict(), - this->type(), - this->groupSize(), - this->minCoarseEqns() - ) - ); } diff --git a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixClustering/BlockMatrixClustering.H b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixClustering/BlockMatrixClustering.H index 804d323c2..8b1081e75 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixClustering/BlockMatrixClustering.H +++ b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixClustering/BlockMatrixClustering.H @@ -76,7 +76,10 @@ class BlockMatrixClustering autoPtr > normPtr_; //- Child array: for each fine equation give a clustering index - labelField agglomIndex_; + labelList agglomIndex_; + + //- Face-restriction addressing + labelList coeffRestrictAddr_; //- Group size label groupSize_; @@ -116,7 +119,6 @@ class BlockMatrixClustering template void agglomerateCoeffs ( - const labelList& coeffRestrictAddr, Field& activeCoarseDiag, Field& activeCoarseUpper, const Field& activeFineUpper, @@ -127,7 +129,6 @@ class BlockMatrixClustering template void agglomerateCoeffs ( - const labelList& coeffRestrictAddr, Field& activeCoarseDiag, Field& activeCoarseUpper, const Field& activeFineUpper, @@ -197,6 +198,9 @@ public: Field& x, const Field& coarseX ) const; + + //- Update coarse matrix using same coefficients + virtual void updateMatrix(BlockLduMatrix& coarseMatrix) const; }; diff --git a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixCoarsening/BlockMatrixCoarsening.H b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixCoarsening/BlockMatrixCoarsening.H index 74b11a148..e957bec1b 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixCoarsening/BlockMatrixCoarsening.H +++ b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixCoarsening/BlockMatrixCoarsening.H @@ -172,8 +172,7 @@ public: virtual bool coarsen() const = 0; //- Restrict matrix - virtual autoPtr > restrictMatrix - () const = 0; + virtual autoPtr > restrictMatrix() const = 0; //- Restrict residual virtual void restrictResidual @@ -189,6 +188,8 @@ public: const Field& coarseX ) const = 0; + //- Update coarse matrix using same coefficients + virtual void updateMatrix(BlockLduMatrix& coarseMatrix) const = 0; }; @@ -203,15 +204,15 @@ public: #endif #define makeBlockMatrixCoarsening(BlockMatrixCoarseningType, typeBlockMatrixCoarseningType) \ - \ -defineNamedTemplateTypeNameAndDebug(typeBlockMatrixCoarseningType, 0); \ - \ + \ +defineNamedTemplateTypeNameAndDebug(typeBlockMatrixCoarseningType, 0); \ + \ addToRunTimeSelectionTable(BlockMatrixCoarseningType, typeBlockMatrixCoarseningType, matrix); -#define makeBlockMatrixCoarsenings(blockAmgCoarseningType) \ - \ -makeBlockMatrixCoarsening(blockScalarMatrixCoarsening, blockAmgCoarseningType##Scalar); \ -makeBlockMatrixCoarsening(blockVectorMatrixCoarsening, blockAmgCoarseningType##Vector); \ +#define makeBlockMatrixCoarsenings(blockAmgCoarseningType) \ + \ +makeBlockMatrixCoarsening(blockScalarMatrixCoarsening, blockAmgCoarseningType##Scalar); \ +makeBlockMatrixCoarsening(blockVectorMatrixCoarsening, blockAmgCoarseningType##Vector); \ makeBlockMatrixCoarsening(blockTensorMatrixCoarsening, blockAmgCoarseningType##Tensor); // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixSelection/BlockMatrixSelection.C b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixSelection/BlockMatrixSelection.C index e151d4e75..510a07060 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixSelection/BlockMatrixSelection.C +++ b/src/foam/matrices/blockLduMatrix/BlockAMG/BlockMatrixCoarsening/BlockMatrixSelection/BlockMatrixSelection.C @@ -989,8 +989,7 @@ Foam::BlockMatrixSelection::restrictMatrix() const nCoarseEqns_, coarseOwner, coarseNeighbour, - // true - false // DO NOT REUSE STORAGE! HJ, HERE + false // DO NOT REUSE STORAGE! ) ); diff --git a/src/foam/matrices/blockLduMatrix/BlockAMG/coarseBlockAMGLevel.C b/src/foam/matrices/blockLduMatrix/BlockAMG/coarseBlockAMGLevel.C index bafb06dc4..694f2a152 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAMG/coarseBlockAMGLevel.C +++ b/src/foam/matrices/blockLduMatrix/BlockAMG/coarseBlockAMGLevel.C @@ -104,6 +104,13 @@ Foam::coarseBlockAMGLevel::~coarseBlockAMGLevel() // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +template +Foam::BlockLduMatrix& Foam::coarseBlockAMGLevel::matrix() +{ + return matrixPtr_(); +} + + template Foam::Field& Foam::coarseBlockAMGLevel::x() { @@ -334,4 +341,23 @@ Foam::coarseBlockAMGLevel::makeNextLevel() const } +template +void Foam::coarseBlockAMGLevel::initLevel +( + autoPtr >& coarseLevelPtr +) +{ + // Update matrix by repeating coarsening + + // Update smoother for new matrix + smootherPtr_->initMatrix(); + + // Update coarse matrix if it exists + if (coarseLevelPtr.valid()) + { + coarseningPtr_->updateMatrix(coarseLevelPtr->matrix()); + } +} + + // ************************************************************************* // diff --git a/src/foam/matrices/blockLduMatrix/BlockAMG/coarseBlockAMGLevel.H b/src/foam/matrices/blockLduMatrix/BlockAMG/coarseBlockAMGLevel.H index fbeb70d75..ade3cc715 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAMG/coarseBlockAMGLevel.H +++ b/src/foam/matrices/blockLduMatrix/BlockAMG/coarseBlockAMGLevel.H @@ -125,6 +125,9 @@ public: return dict_; } + //- Return reference to matrix + virtual BlockLduMatrix& matrix(); + //- Return reference to x virtual Field& x(); @@ -184,6 +187,13 @@ public: //- Create next level from current level virtual autoPtr > makeNextLevel() const; + + //- Re-initialise AMG level after matrix coefficient update + // and update matrix coefficients on coarse level using same coarsening + virtual void initLevel + ( + autoPtr >& coarseLevelPtr + ); }; diff --git a/src/foam/matrices/blockLduMatrix/BlockAMG/fineBlockAMGLevel.C b/src/foam/matrices/blockLduMatrix/BlockAMG/fineBlockAMGLevel.C index fc22a49f6..de915e45b 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAMG/fineBlockAMGLevel.C +++ b/src/foam/matrices/blockLduMatrix/BlockAMG/fineBlockAMGLevel.C @@ -81,11 +81,23 @@ Foam::fineBlockAMGLevel::fineBlockAMGLevel // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +template +Foam::BlockLduMatrix& Foam::fineBlockAMGLevel::matrix() +{ + FatalErrorIn("Field& Foam::fineBlockAMGLevel::matrix()") + << "Access to matrix is not available on fine level." + << abort(FatalError); + + // Dummy return + return const_cast&>(matrix_); +} + + template Foam::Field& Foam::fineBlockAMGLevel::x() { FatalErrorIn("Field& Foam::fineBlockAMGLevel::x()") - << "x is not available." + << "x is not available on fine level." << abort(FatalError); // Dummy return @@ -97,7 +109,7 @@ template Foam::Field& Foam::fineBlockAMGLevel::b() { FatalErrorIn("Field& Foam::fineBlockAMGLevel::b()") - << "b is not available." + << "b is not available on fine level." << abort(FatalError); // Dummy return @@ -279,4 +291,23 @@ Foam::fineBlockAMGLevel::makeNextLevel() const } +template +void Foam::fineBlockAMGLevel::initLevel +( + autoPtr >& coarseLevelPtr +) +{ + // Fine matrix has been updated externally + + // Update smoother for new matrix + smootherPtr_->initMatrix(); + + // Update coarse matrix if it exists + if (coarseLevelPtr.valid()) + { + coarseningPtr_->updateMatrix(coarseLevelPtr->matrix()); + } +} + + // ************************************************************************* // diff --git a/src/foam/matrices/blockLduMatrix/BlockAMG/fineBlockAMGLevel.H b/src/foam/matrices/blockLduMatrix/BlockAMG/fineBlockAMGLevel.H index 2ce5b4638..fa78b44ef 100644 --- a/src/foam/matrices/blockLduMatrix/BlockAMG/fineBlockAMGLevel.H +++ b/src/foam/matrices/blockLduMatrix/BlockAMG/fineBlockAMGLevel.H @@ -125,6 +125,9 @@ public: return dict_; } + //- Return reference to matrix + virtual BlockLduMatrix& matrix(); + //- Return reference to x virtual Field& x(); @@ -183,6 +186,13 @@ public: //- Create next level from current level virtual autoPtr > makeNextLevel() const; + + //- Re-initialise AMG level after matrix coefficient update + // and update matrix coefficients on coarse level using same coarsening + virtual void initLevel + ( + autoPtr >& coarseLevelPtr + ); }; diff --git a/src/foam/matrices/blockLduMatrix/BlockLduMatrix/BlockLduMatrix.C b/src/foam/matrices/blockLduMatrix/BlockLduMatrix/BlockLduMatrix.C index d764f1738..9aa243faf 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduMatrix/BlockLduMatrix.C +++ b/src/foam/matrices/blockLduMatrix/BlockLduMatrix/BlockLduMatrix.C @@ -67,7 +67,6 @@ Foam::BlockLduMatrix::BlockLduMatrix(const lduMesh& ldu) coupleUpper_.set(i, new CoeffField(addr.patchAddr(i).size())); coupleLower_.set(i, new CoeffField(addr.patchAddr(i).size())); } - } diff --git a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockAMGPrecon/BlockAMGPrecon.C b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockAMGPrecon/BlockAMGPrecon.C index b56392cc1..6457d8a10 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockAMGPrecon/BlockAMGPrecon.C +++ b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockAMGPrecon/BlockAMGPrecon.C @@ -141,4 +141,11 @@ void Foam::BlockAMGPrecon::precondition } +template +void Foam::BlockAMGPrecon::initMatrix() +{ + amgPtr_->initMatrix(); +} + + // ************************************************************************* // diff --git a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockAMGPrecon/BlockAMGPrecon.H b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockAMGPrecon/BlockAMGPrecon.H index 9ab026a3e..f93762632 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockAMGPrecon/BlockAMGPrecon.H +++ b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockAMGPrecon/BlockAMGPrecon.H @@ -25,7 +25,7 @@ Class BlockAMGPrecon Description - AMG preconditioning + Algebraic Multigrid preconditioning for block matrices Author Klas Jareteg, 2012-12-13 @@ -55,7 +55,7 @@ template class BlockAMGCycle; /*---------------------------------------------------------------------------*\ - Class BlockAMGPrecon Declaration + Class BlockAMGPrecon Declaration \*---------------------------------------------------------------------------*/ template @@ -141,6 +141,9 @@ public: Field& x, const Field& b ) const; + + //- Re-initialise preconditioner after matrix coefficient update + virtual void initMatrix(); }; diff --git a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockCholeskyPrecon/BlockCholeskyPrecon.C b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockCholeskyPrecon/BlockCholeskyPrecon.C index ea48e7475..4495c0556 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockCholeskyPrecon/BlockCholeskyPrecon.C +++ b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockCholeskyPrecon/BlockCholeskyPrecon.C @@ -914,7 +914,7 @@ Foam::BlockCholeskyPrecon::BlockCholeskyPrecon BlockLduPrecon(matrix), preconDiag_(matrix.diag()) { - calcPreconDiag(); + this->calcPreconDiag(); } @@ -1301,4 +1301,12 @@ void Foam::BlockCholeskyPrecon::preconditionT } +template +void Foam::BlockCholeskyPrecon::initMatrix() +{ + preconDiag_.clear(); + this->calcPreconDiag(); +} + + // ************************************************************************* // diff --git a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockCholeskyPrecon/BlockCholeskyPrecon.H b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockCholeskyPrecon/BlockCholeskyPrecon.H index 035f5bf75..0e2b91c97 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockCholeskyPrecon/BlockCholeskyPrecon.H +++ b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockCholeskyPrecon/BlockCholeskyPrecon.H @@ -25,7 +25,7 @@ Class BlockCholeskyPrecon Description - Incomplete Cholesky preconditioning with no fill-in. + Incomplete Cholesky preconditioning with no fill-in for block matrices. Author Hrvoje Jasak, Wikki Ltd. All rights reserved. @@ -215,6 +215,9 @@ public: Field& xT, const Field& bT ) const; + + //- Re-initialise preconditioner after matrix coefficient update + virtual void initMatrix(); }; diff --git a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockDiagonalPrecon/BlockDiagonalPrecon.H b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockDiagonalPrecon/BlockDiagonalPrecon.H index 3071824a0..baf8384de 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockDiagonalPrecon/BlockDiagonalPrecon.H +++ b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockDiagonalPrecon/BlockDiagonalPrecon.H @@ -107,6 +107,10 @@ public: { return precondition(xT, bT); } + + //- Re-initialise preconditioner after matrix coefficient update + virtual void initMatrix() + {} }; diff --git a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockGaussSeidelPrecon/BlockGaussSeidelPrecon.C b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockGaussSeidelPrecon/BlockGaussSeidelPrecon.C index 3ea12a25a..62c6bbfff 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockGaussSeidelPrecon/BlockGaussSeidelPrecon.C +++ b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockGaussSeidelPrecon/BlockGaussSeidelPrecon.C @@ -946,4 +946,14 @@ void Foam::BlockGaussSeidelPrecon::preconditionT } +template +void Foam::BlockGaussSeidelPrecon::initMatrix() +{ + invDiag_.clear(); + LUDiag_.clear(); + + this->calcInvDiag(); +} + + // ************************************************************************* // diff --git a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockGaussSeidelPrecon/BlockGaussSeidelPrecon.H b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockGaussSeidelPrecon/BlockGaussSeidelPrecon.H index df85068b3..dd7657998 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockGaussSeidelPrecon/BlockGaussSeidelPrecon.H +++ b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockGaussSeidelPrecon/BlockGaussSeidelPrecon.H @@ -172,6 +172,9 @@ public: Field& xT, const Field& bT ) const; + + //- Re-initialise preconditioner after matrix coefficient update + virtual void initMatrix(); }; diff --git a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockILUCpPrecon/BlockILUCpPrecon.C b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockILUCpPrecon/BlockILUCpPrecon.C index bb15a2df4..4e12661c1 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockILUCpPrecon/BlockILUCpPrecon.C +++ b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockILUCpPrecon/BlockILUCpPrecon.C @@ -840,4 +840,17 @@ void Foam::BlockILUCpPrecon::preconditionT } +template +void Foam::BlockILUCpPrecon::initMatrix() +{ + // Clear extended matrix + extBlockMatrix_.extendedLower().clear(); + extBlockMatrix_.extendedLower().clear(); + + preconDiag_.clear(); + + this->calcFactorization(); +} + + // ************************************************************************* // diff --git a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockILUCpPrecon/BlockILUCpPrecon.H b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockILUCpPrecon/BlockILUCpPrecon.H index 1b318a087..508ced666 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockILUCpPrecon/BlockILUCpPrecon.H +++ b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockILUCpPrecon/BlockILUCpPrecon.H @@ -168,6 +168,9 @@ public: Field& xT, const Field& bT ) const; + + //- Re-initialise preconditioner after matrix coefficient update + virtual void initMatrix(); }; diff --git a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockLduPrecon/BlockLduPrecon.H b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockLduPrecon/BlockLduPrecon.H index 0c42df87b..aca2beb19 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockLduPrecon/BlockLduPrecon.H +++ b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockLduPrecon/BlockLduPrecon.H @@ -140,6 +140,9 @@ public: "(Field& xT, const Field& bT) const" ); } + + //- Re-initialise preconditioner after matrix coefficient update + virtual void initMatrix() = 0; }; diff --git a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockNoPrecon/BlockNoPrecon.H b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockNoPrecon/BlockNoPrecon.H index 0f7646867..df53588aa 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockNoPrecon/BlockNoPrecon.H +++ b/src/foam/matrices/blockLduMatrix/BlockLduPrecons/BlockNoPrecon/BlockNoPrecon.H @@ -109,6 +109,10 @@ public: { precondition(xT, bT); } + + //- Re-initialise preconditioner after matrix coefficient update + virtual void initMatrix() + {} }; diff --git a/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockGaussSeidelSmoother/BlockGaussSeidelSmoother.H b/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockGaussSeidelSmoother/BlockGaussSeidelSmoother.H index 903c00b1e..ac1f7e22e 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockGaussSeidelSmoother/BlockGaussSeidelSmoother.H +++ b/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockGaussSeidelSmoother/BlockGaussSeidelSmoother.H @@ -111,6 +111,12 @@ public: gs_.precondition(x, b); } } + + //- Re-initialise preconditioner after matrix coefficient update + virtual void initMatrix() + { + gs_.initMatrix(); + } }; diff --git a/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockILUCpSmoother/BlockILUCpSmoother.H b/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockILUCpSmoother/BlockILUCpSmoother.H index 1de496dd1..7721fc5f9 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockILUCpSmoother/BlockILUCpSmoother.H +++ b/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockILUCpSmoother/BlockILUCpSmoother.H @@ -127,6 +127,12 @@ public: x += xCorr_; } } + + //- Re-initialise preconditioner after matrix coefficient update + virtual void initMatrix() + { + precon_.initMatrix(); + } }; diff --git a/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockILUSmoother/BlockILUSmoother.H b/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockILUSmoother/BlockILUSmoother.H index 49abb4d4e..9d7cdebd9 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockILUSmoother/BlockILUSmoother.H +++ b/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockILUSmoother/BlockILUSmoother.H @@ -133,6 +133,12 @@ public: x += xCorr_; } } + + //- Re-initialise preconditioner after matrix coefficient update + virtual void initMatrix() + { + precon_.initMatrix(); + } }; diff --git a/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockLduSmoother/BlockLduSmoother.H b/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockLduSmoother/BlockLduSmoother.H index 8fa047bd4..c8c687fe1 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockLduSmoother/BlockLduSmoother.H +++ b/src/foam/matrices/blockLduMatrix/BlockLduSmoothers/BlockLduSmoother/BlockLduSmoother.H @@ -125,6 +125,9 @@ public: const Field& b, const label nSweeps ) const = 0; + + //- Re-initialise preconditioner after matrix coefficient update + virtual void initMatrix() = 0; }; diff --git a/src/foam/matrices/blockLduMatrix/BlockLduSolvers/BlockAMGSolver/BlockAMGSolver.H b/src/foam/matrices/blockLduMatrix/BlockLduSolvers/BlockAMGSolver/BlockAMGSolver.H index cc20a27c0..583983dd1 100644 --- a/src/foam/matrices/blockLduMatrix/BlockLduSolvers/BlockAMGSolver/BlockAMGSolver.H +++ b/src/foam/matrices/blockLduMatrix/BlockLduSolvers/BlockAMGSolver/BlockAMGSolver.H @@ -51,7 +51,7 @@ namespace Foam { /*---------------------------------------------------------------------------*\ - Class BlockAMGSolver Declaration + Class BlockAMGSolver Declaration \*---------------------------------------------------------------------------*/ template @@ -93,10 +93,9 @@ public: ); - // Destructor - - virtual ~BlockAMGSolver() - {} + //- Destructor + virtual ~BlockAMGSolver() + {} // Member Functions