void Foam::GAMGSolver::agglomerateMatrix ( const label fineLevelIndex, const lduMesh& coarseMesh, const lduInterfacePtrsList& coarseMeshInterfaces ) { // Get fine matrix const lduMatrix& fineMatrix = matrixLevel(fineLevelIndex); if (UPstream::myProcNo(fineMatrix.mesh().comm()) != -1) { const label nCoarseFaces = agglomeration_.nFaces(fineLevelIndex); const label nCoarseCells = agglomeration_.nCells(fineLevelIndex); // Set the coarse level matrix matrixLevels_.set ( fineLevelIndex, new lduMatrix(coarseMesh) ); lduMatrix& coarseMatrix = matrixLevels_[fineLevelIndex]; // Coarse matrix diagonal initialised by restricting the finer mesh // diagonal. Note that we size with the cached coarse nCells and not // the actual coarseMesh size since this might be dummy when processor // agglomerating. scalarField& coarseDiag = coarseMatrix.diag(nCoarseCells); agglomeration_.restrictField ( coarseDiag, fineMatrix.diag(), fineLevelIndex, false // no processor agglomeration ); // Get reference to fine-level interfaces const lduInterfaceFieldPtrsList& fineInterfaces = interfaceLevel(fineLevelIndex); // Create coarse-level interfaces primitiveInterfaceLevels_.set ( fineLevelIndex, new PtrList<lduInterfaceField>(fineInterfaces.size()) ); PtrList<lduInterfaceField>& coarsePrimInterfaces = primitiveInterfaceLevels_[fineLevelIndex]; interfaceLevels_.set ( fineLevelIndex, new lduInterfaceFieldPtrsList(fineInterfaces.size()) ); lduInterfaceFieldPtrsList& coarseInterfaces = interfaceLevels_[fineLevelIndex]; // Set coarse-level boundary coefficients interfaceLevelsBouCoeffs_.set ( fineLevelIndex, new FieldField<Field, scalar>(fineInterfaces.size()) ); FieldField<Field, scalar>& coarseInterfaceBouCoeffs = interfaceLevelsBouCoeffs_[fineLevelIndex]; // Set coarse-level internal coefficients interfaceLevelsIntCoeffs_.set ( fineLevelIndex, new FieldField<Field, scalar>(fineInterfaces.size()) ); FieldField<Field, scalar>& coarseInterfaceIntCoeffs = interfaceLevelsIntCoeffs_[fineLevelIndex]; // Add the coarse level agglomerateInterfaceCoefficients ( fineLevelIndex, coarseMeshInterfaces, coarsePrimInterfaces, coarseInterfaces, coarseInterfaceBouCoeffs, coarseInterfaceIntCoeffs ); // Get face restriction map for current level const labelList& faceRestrictAddr = agglomeration_.faceRestrictAddressing(fineLevelIndex); const boolList& faceFlipMap = agglomeration_.faceFlipMap(fineLevelIndex); // Check if matrix is asymetric and if so agglomerate both upper // and lower coefficients ... if (fineMatrix.hasLower()) { // Get off-diagonal matrix coefficients const scalarField& fineUpper = fineMatrix.upper(); const scalarField& fineLower = fineMatrix.lower(); // Coarse matrix upper coefficients. Note passed in size scalarField& coarseUpper = coarseMatrix.upper(nCoarseFaces); scalarField& coarseLower = coarseMatrix.lower(nCoarseFaces); forAll(faceRestrictAddr, fineFacei) { label cFace = faceRestrictAddr[fineFacei]; if (cFace >= 0) { // Check the orientation of the fine-face relative to the // coarse face it is being agglomerated into if (!faceFlipMap[fineFacei]) { coarseUpper[cFace] += fineUpper[fineFacei]; coarseLower[cFace] += fineLower[fineFacei]; } else { coarseUpper[cFace] += fineLower[fineFacei]; coarseLower[cFace] += fineUpper[fineFacei]; } } else { // Add the fine face coefficients into the diagonal. coarseDiag[-1 - cFace] += fineUpper[fineFacei] + fineLower[fineFacei]; } } } else // ... Otherwise it is symmetric so agglomerate just the upper {
void Foam::GAMGSolver::agglomerateMatrix(const label fineLevelIndex) { // Get fine matrix const lduMatrix& fineMatrix = matrixLevel(fineLevelIndex); // Set the coarse level matrix matrixLevels_.set ( fineLevelIndex, new lduMatrix(agglomeration_.meshLevel(fineLevelIndex + 1)) ); lduMatrix& coarseMatrix = matrixLevels_[fineLevelIndex]; // Get face restriction map for current level const labelList& faceRestrictAddr = agglomeration_.faceRestrictAddressing(fineLevelIndex); // Coarse matrix diagonal initialised by restricting the fine mesh diagonal scalarField& coarseDiag = coarseMatrix.diag(); agglomeration_.restrictField ( coarseDiag, fineMatrix.diag(), fineLevelIndex ); // Get reference to fine-level interfaces const lduInterfaceFieldPtrsList& fineInterfaces = interfaceLevel(fineLevelIndex); // Get reference to fine-level boundary coefficients const FieldField<Field, scalar>& fineInterfaceBouCoeffs = coupleBouCoeffsLevel(fineLevelIndex); // Get reference to fine-level internal coefficients const FieldField<Field, scalar>& fineInterfaceIntCoeffs = coupleIntCoeffsLevel(fineLevelIndex); // Create coarse-level interfaces interfaceLevels_.set ( fineLevelIndex, new lduInterfaceFieldPtrsList(fineInterfaces.size()) ); lduInterfaceFieldPtrsList& coarseInterfaces = interfaceLevels_[fineLevelIndex]; // Set coarse-level boundary coefficients coupleLevelsBouCoeffs_.set ( fineLevelIndex, new FieldField<Field, scalar>(fineInterfaces.size()) ); FieldField<Field, scalar>& coarseInterfaceBouCoeffs = coupleLevelsBouCoeffs_[fineLevelIndex]; // Set coarse-level internal coefficients coupleLevelsIntCoeffs_.set ( fineLevelIndex, new FieldField<Field, scalar>(fineInterfaces.size()) ); FieldField<Field, scalar>& coarseInterfaceIntCoeffs = coupleLevelsIntCoeffs_[fineLevelIndex]; // Add the coarse level forAll (fineInterfaces, inti) { if (fineInterfaces.set(inti)) { const GAMGInterface& coarseInterface = refCast<const GAMGInterface> ( agglomeration_.interfaceLevel(fineLevelIndex + 1)[inti] ); coarseInterfaces.set ( inti, GAMGInterfaceField::New ( coarseInterface, fineInterfaces[inti] ).ptr() ); coarseInterfaceBouCoeffs.set ( inti, coarseInterface.agglomerateCoeffs(fineInterfaceBouCoeffs[inti]) ); coarseInterfaceIntCoeffs.set ( inti, coarseInterface.agglomerateCoeffs(fineInterfaceIntCoeffs[inti]) ); } } // Check if matrix is assymetric and if so agglomerate both upper and lower // coefficients ... if (fineMatrix.hasLower()) { // Get off-diagonal matrix coefficients const scalarField& fineUpper = fineMatrix.upper(); const scalarField& fineLower = fineMatrix.lower(); // Coarse matrix upper coefficients scalarField& coarseUpper = coarseMatrix.upper(); scalarField& coarseLower = coarseMatrix.lower(); const labelList& restrictAddr = agglomeration_.restrictAddressing(fineLevelIndex); const unallocLabelList& l = fineMatrix.lduAddr().lowerAddr(); const unallocLabelList& cl = coarseMatrix.lduAddr().lowerAddr(); const unallocLabelList& cu = coarseMatrix.lduAddr().upperAddr(); forAll(faceRestrictAddr, fineFacei) { label cFace = faceRestrictAddr[fineFacei]; if (cFace >= 0) { // Check the orientation of the fine-face relative to the // coarse face it is being agglomerated into if (cl[cFace] == restrictAddr[l[fineFacei]]) { coarseUpper[cFace] += fineUpper[fineFacei]; coarseLower[cFace] += fineLower[fineFacei]; } else if (cu[cFace] == restrictAddr[l[fineFacei]]) { coarseUpper[cFace] += fineLower[fineFacei]; coarseLower[cFace] += fineUpper[fineFacei]; } else { FatalErrorIn ( "GAMGSolver::agglomerateMatrix(const label)" ) << "Inconsistent addressing between " "fine and coarse grids" << exit(FatalError); } } else { // Add the fine face coefficients into the diagonal. coarseDiag[-1 - cFace] += fineUpper[fineFacei] + fineLower[fineFacei]; } } }