/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . \*---------------------------------------------------------------------------*/ #include "GAMGSolver.H" #include "GAMGInterfaceField.H" #include "processorLduInterfaceField.H" #include "processorGAMGInterfaceField.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // 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(fineInterfaces.size()) ); PtrList& coarsePrimInterfaces = primitiveInterfaceLevels_[fineLevelIndex]; interfaceLevels_.set ( fineLevelIndex, new lduInterfaceFieldPtrsList(fineInterfaces.size()) ); lduInterfaceFieldPtrsList& coarseInterfaces = interfaceLevels_[fineLevelIndex]; // Set coarse-level boundary coefficients interfaceLevelsBouCoeffs_.set ( fineLevelIndex, new FieldField(fineInterfaces.size()) ); FieldField& coarseInterfaceBouCoeffs = interfaceLevelsBouCoeffs_[fineLevelIndex]; // Set coarse-level internal coefficients interfaceLevelsIntCoeffs_.set ( fineLevelIndex, new FieldField(fineInterfaces.size()) ); FieldField& 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 { // Get off-diagonal matrix coefficients const scalarField& fineUpper = fineMatrix.upper(); // Coarse matrix upper coefficients scalarField& coarseUpper = coarseMatrix.upper(nCoarseFaces); forAll(faceRestrictAddr, fineFacei) { label cFace = faceRestrictAddr[fineFacei]; if (cFace >= 0) { coarseUpper[cFace] += fineUpper[fineFacei]; } else { // Add the fine face coefficient into the diagonal. coarseDiag[-1 - cFace] += 2*fineUpper[fineFacei]; } } } } } void Foam::GAMGSolver::agglomerateInterfaceCoefficients ( const label fineLevelIndex, const lduInterfacePtrsList& coarseMeshInterfaces, PtrList& coarsePrimInterfaces, lduInterfaceFieldPtrsList& coarseInterfaces, FieldField& coarseInterfaceBouCoeffs, FieldField& coarseInterfaceIntCoeffs ) const { // Get reference to fine-level interfaces const lduInterfaceFieldPtrsList& fineInterfaces = interfaceLevel(fineLevelIndex); // Get reference to fine-level boundary coefficients const FieldField& fineInterfaceBouCoeffs = interfaceBouCoeffsLevel(fineLevelIndex); // Get reference to fine-level internal coefficients const FieldField& fineInterfaceIntCoeffs = interfaceIntCoeffsLevel(fineLevelIndex); const labelListList& patchFineToCoarse = agglomeration_.patchFaceRestrictAddressing(fineLevelIndex); const labelList& nPatchFaces = agglomeration_.nPatchFaces(fineLevelIndex); // Add the coarse level forAll(fineInterfaces, inti) { if (fineInterfaces.set(inti)) { const GAMGInterface& coarseInterface = refCast ( coarseMeshInterfaces[inti] ); coarsePrimInterfaces.set ( inti, GAMGInterfaceField::New ( coarseInterface, fineInterfaces[inti] ).ptr() ); coarseInterfaces.set ( inti, &coarsePrimInterfaces[inti] ); const labelList& faceRestrictAddressing = patchFineToCoarse[inti]; coarseInterfaceBouCoeffs.set ( inti, new scalarField(nPatchFaces[inti], 0.0) ); agglomeration_.restrictField ( coarseInterfaceBouCoeffs[inti], fineInterfaceBouCoeffs[inti], faceRestrictAddressing ); coarseInterfaceIntCoeffs.set ( inti, new scalarField(nPatchFaces[inti], 0.0) ); agglomeration_.restrictField ( coarseInterfaceIntCoeffs[inti], fineInterfaceIntCoeffs[inti], faceRestrictAddressing ); } } } void Foam::GAMGSolver::gatherMatrices ( const labelList& procIDs, const lduMesh& dummyMesh, const label meshComm, const lduMatrix& mat, const FieldField& interfaceBouCoeffs, const FieldField& interfaceIntCoeffs, const lduInterfaceFieldPtrsList& interfaces, PtrList& otherMats, PtrList>& otherBouCoeffs, PtrList>& otherIntCoeffs, List& otherTransforms, List>& otherRanks ) const { if (debug) { Pout<< "GAMGSolver::gatherMatrices :" << " collecting matrices from procs:" << procIDs << " using comm:" << meshComm << endl; } if (Pstream::myProcNo(meshComm) == procIDs[0]) { // Master. otherMats.setSize(procIDs.size()-1); otherBouCoeffs.setSize(procIDs.size()-1); otherIntCoeffs.setSize(procIDs.size()-1); otherTransforms.setSize(procIDs.size()-1); otherRanks.setSize(procIDs.size()-1); for (label proci = 1; proci < procIDs.size(); proci++) { label otherI = proci-1; IPstream fromSlave ( Pstream::commsTypes::scheduled, procIDs[proci], 0, // bufSize Pstream::msgType(), meshComm ); otherMats.set(otherI, new lduMatrix(dummyMesh, fromSlave)); // Receive number of/valid interfaces boolList& procTransforms = otherTransforms[otherI]; List