void Foam::GAMGAgglomeration::agglomerateLduAddressing ( const label fineLevelIndex ) { const lduMesh& fineMesh = meshLevel(fineLevelIndex); const lduAddressing& fineMeshAddr = fineMesh.lduAddr(); const labelUList& upperAddr = fineMeshAddr.upperAddr(); const labelUList& lowerAddr = fineMeshAddr.lowerAddr(); label nFineFaces = upperAddr.size(); // Get restriction map for current level const labelField& restrictMap = restrictAddressing(fineLevelIndex); if (min(restrictMap) == -1) { FatalErrorInFunction << "min(restrictMap) == -1" << exit(FatalError); } if (restrictMap.size() != fineMeshAddr.size()) { FatalErrorInFunction << "restrict map does not correspond to fine level. " << endl << " Sizes: restrictMap: " << restrictMap.size() << " nEqns: " << fineMeshAddr.size() << abort(FatalError); } // Get the number of coarse cells const label nCoarseCells = nCells_[fineLevelIndex]; // Storage for coarse cell neighbours and coefficients // Guess initial maximum number of neighbours in coarse cell label maxNnbrs = 10; // Number of faces for each coarse-cell labelList cCellnFaces(nCoarseCells, 0); // Setup initial packed storage for coarse-cell faces labelList cCellFaces(maxNnbrs*nCoarseCells); // Create face-restriction addressing faceRestrictAddressing_.set(fineLevelIndex, new labelList(nFineFaces)); labelList& faceRestrictAddr = faceRestrictAddressing_[fineLevelIndex]; // Initial neighbour array (not in upper-triangle order) labelList initCoarseNeighb(nFineFaces); // Counter for coarse faces label& nCoarseFaces = nFaces_[fineLevelIndex]; nCoarseFaces = 0; // Loop through all fine faces forAll(upperAddr, fineFacei) { label rmUpperAddr = restrictMap[upperAddr[fineFacei]]; label rmLowerAddr = restrictMap[lowerAddr[fineFacei]]; if (rmUpperAddr == rmLowerAddr) { // For each fine face inside of a coarse cell keep the address // of the cell corresponding to the face in the faceRestrictAddr // as a negative index faceRestrictAddr[fineFacei] = -(rmUpperAddr + 1); } else { // this face is a part of a coarse face 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 face has already been found label* ccFaces = &cCellFaces[maxNnbrs*cOwn]; bool nbrFound = false; label& ccnFaces = cCellnFaces[cOwn]; for (int i=0; i<ccnFaces; i++) { if (initCoarseNeighb[ccFaces[i]] == cNei) { nbrFound = true; faceRestrictAddr[fineFacei] = ccFaces[i]; break; } } if (!nbrFound) { if (ccnFaces >= maxNnbrs) { label oldMaxNnbrs = maxNnbrs; maxNnbrs *= 2; cCellFaces.setSize(maxNnbrs*nCoarseCells); forAllReverse(cCellnFaces, i) { label* oldCcNbrs = &cCellFaces[oldMaxNnbrs*i]; label* newCcNbrs = &cCellFaces[maxNnbrs*i]; for (int j=0; j<cCellnFaces[i]; j++) { newCcNbrs[j] = oldCcNbrs[j]; } } ccFaces = &cCellFaces[maxNnbrs*cOwn]; } ccFaces[ccnFaces] = nCoarseFaces; initCoarseNeighb[nCoarseFaces] = cNei; faceRestrictAddr[fineFacei] = nCoarseFaces; ccnFaces++; // new coarse face created nCoarseFaces++; }
Foam::MGridGenGAMGAgglomeration::MGridGenGAMGAgglomeration ( const lduMesh& mesh, const dictionary& dict ) : GAMGAgglomeration(mesh, dict), fvMesh_(refCast<const fvMesh>(mesh)) { // Min, max size of agglomerated cells label minSize(readLabel(dict.lookup("minSize"))); label maxSize(readLabel(dict.lookup("maxSize"))); // Get the finest-level interfaces from the mesh interfaceLevels_.set ( 0, new lduInterfacePtrsList(fvMesh_.boundary().interfaces()) ); // Start geometric agglomeration from the cell volumes and areas of the mesh scalarField* VPtr = const_cast<scalarField*>(&fvMesh_.cellVolumes()); vectorField* SfPtr = const_cast<vectorField*>(&fvMesh_.faceAreas()); // Create the boundary area cell field scalarField* SbPtr(new scalarField(fvMesh_.nCells(), 0)); { scalarField& Sb = *SbPtr; const labelList& own = fvMesh_.faceOwner(); const vectorField& Sf = fvMesh_.faceAreas(); forAll(Sf, facei) { if (!fvMesh_.isInternalFace(facei)) { Sb[own[facei]] += mag(Sf[facei]); } } } // Agglomerate until the required number of cells in the coarsest level // is reached label nCreatedLevels = 0; while (nCreatedLevels < maxLevels_ - 1) { label nCoarseCells = -1; tmp<labelField> finalAgglomPtr = agglomerate ( nCoarseCells, minSize, maxSize, meshLevel(nCreatedLevels).lduAddr(), *VPtr, *SfPtr, *SbPtr ); if (continueAgglomerating(nCoarseCells)) { nCells_[nCreatedLevels] = nCoarseCells; restrictAddressing_.set(nCreatedLevels, finalAgglomPtr); } else { break; } agglomerateLduAddressing(nCreatedLevels); // Agglomerate the cell volumes field for the next level { scalarField* aggVPtr ( new scalarField(meshLevels_[nCreatedLevels].size()) ); restrictField(*aggVPtr, *VPtr, nCreatedLevels); if (nCreatedLevels) { delete VPtr; } VPtr = aggVPtr; } // Agglomerate the face areas field for the next level { vectorField* aggSfPtr ( new vectorField ( meshLevels_[nCreatedLevels].upperAddr().size(), vector::zero ) ); restrictFaceField(*aggSfPtr, *SfPtr, nCreatedLevels); if (nCreatedLevels) { delete SfPtr; } SfPtr = aggSfPtr; } // Agglomerate the cell boundary areas field for the next level { scalarField* aggSbPtr ( new scalarField(meshLevels_[nCreatedLevels].size()) ); restrictField(*aggSbPtr, *SbPtr, nCreatedLevels); delete SbPtr; SbPtr = aggSbPtr; } nCreatedLevels++; } // Shrink the storage of the levels to those created compactLevels(nCreatedLevels); // Delete temporary geometry storage if (nCreatedLevels) { delete VPtr; delete SfPtr; } delete SbPtr; }
void Foam::GAMGAgglomeration::compactLevels(const label nCreatedLevels) { nCells_.setSize(nCreatedLevels); restrictAddressing_.setSize(nCreatedLevels); nFaces_.setSize(nCreatedLevels); faceRestrictAddressing_.setSize(nCreatedLevels); faceFlipMap_.setSize(nCreatedLevels); nPatchFaces_.setSize(nCreatedLevels); patchFaceRestrictAddressing_.setSize(nCreatedLevels); meshLevels_.setSize(nCreatedLevels); // Have procCommunicator_ always, even if not procAgglomerating procCommunicator_.setSize(nCreatedLevels + 1); if (processorAgglomerate()) { procAgglomMap_.setSize(nCreatedLevels); agglomProcIDs_.setSize(nCreatedLevels); procCellOffsets_.setSize(nCreatedLevels); procFaceMap_.setSize(nCreatedLevels); procBoundaryMap_.setSize(nCreatedLevels); procBoundaryFaceMap_.setSize(nCreatedLevels); procAgglomeratorPtr_().agglomerate(); } // Print a bit if (processorAgglomerate() && debug) { Info<< "GAMGAgglomeration:" << nl << " local agglomerator : " << type() << nl; if (processorAgglomerate()) { Info<< " processor agglomerator : " << procAgglomeratorPtr_().type() << nl << nl; } Info<< setw(36) << "nCells" << setw(20) << "nFaces/nCells" << setw(20) << "nInterfaces" << setw(20) << "nIntFaces/nCells" << setw(12) << "profile" << nl << setw(8) << "Level" << setw(8) << "nProcs" << " " << setw(8) << "avg" << setw(8) << "max" << " " << setw(8) << "avg" << setw(8) << "max" << " " << setw(8) << "avg" << setw(8) << "max" << " " << setw(8) << "avg" << setw(8) << "max" //<< " " << setw(12) << "avg" << nl << setw(8) << "-----" << setw(8) << "------" << " " << setw(8) << "---" << setw(8) << "---" << " " << setw(8) << "---" << setw(8) << "---" << " " << setw(8) << "---" << setw(8) << "---" << " " << setw(8) << "---" << setw(8) << "---" //<< " " << setw(12) << "---" //<< " " << nl; for (label levelI = 0; levelI <= size(); levelI++) { label nProcs = 0; label nCells = 0; scalar faceCellRatio = 0; label nInterfaces = 0; label nIntFaces = 0; scalar ratio = 0.0; scalar profile = 0.0; if (hasMeshLevel(levelI)) { nProcs = 1; const lduMesh& fineMesh = meshLevel(levelI); nCells = fineMesh.lduAddr().size(); faceCellRatio = scalar(fineMesh.lduAddr().lowerAddr().size())/nCells; const lduInterfacePtrsList interfaces = fineMesh.interfaces(); forAll(interfaces, i) { if (interfaces.set(i)) { nInterfaces++; nIntFaces += interfaces[i].faceCells().size(); } } ratio = scalar(nIntFaces)/nCells; profile = fineMesh.lduAddr().band().second(); } label totNprocs = returnReduce(nProcs, sumOp<label>()); label maxNCells = returnReduce(nCells, maxOp<label>()); label totNCells = returnReduce(nCells, sumOp<label>()); scalar maxFaceCellRatio = returnReduce(faceCellRatio, maxOp<scalar>()); scalar totFaceCellRatio = returnReduce(faceCellRatio, sumOp<scalar>()); label maxNInt = returnReduce(nInterfaces, maxOp<label>()); label totNInt = returnReduce(nInterfaces, sumOp<label>()); scalar maxRatio = returnReduce(ratio, maxOp<scalar>()); scalar totRatio = returnReduce(ratio, sumOp<scalar>()); scalar totProfile = returnReduce(profile, sumOp<scalar>()); int oldPrecision = Info().precision(4); Info<< setw(8) << levelI << setw(8) << totNprocs << " " << setw(8) << totNCells/totNprocs << setw(8) << maxNCells << " " << setw(8) << totFaceCellRatio/totNprocs << setw(8) << maxFaceCellRatio << " " << setw(8) << scalar(totNInt)/totNprocs << setw(8) << maxNInt << " " << setw(8) << totRatio/totNprocs << setw(8) << maxRatio << setw(12) << totProfile/totNprocs << nl; Info().precision(oldPrecision); } Info<< endl; }