FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

meshRefinementProblemCells.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*----------------------------------------------------------------------------*/
00025 
00026 #include "meshRefinement.H"
00027 #include <finiteVolume/fvMesh.H>
00028 #include <OpenFOAM/syncTools.H>
00029 #include <OpenFOAM/Time.H>
00030 #include <autoMesh/refinementSurfaces.H>
00031 #include <meshTools/pointSet.H>
00032 #include <meshTools/faceSet.H>
00033 #include <OpenFOAM/indirectPrimitivePatch.H>
00034 #include <OpenFOAM/OFstream.H>
00035 #include <meshTools/cellSet.H>
00036 #include <meshTools/searchableSurfaces.H>
00037 #include <dynamicMesh/polyMeshGeometry.H>
00038 #include <OpenFOAM/IOmanip.H>
00039 
00040 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00041 
00042 void Foam::meshRefinement::markBoundaryFace
00043 (
00044     const label faceI,
00045     boolList& isBoundaryFace,
00046     boolList& isBoundaryEdge,
00047     boolList& isBoundaryPoint
00048 ) const
00049 {
00050     isBoundaryFace[faceI] = true;
00051 
00052     const labelList& fEdges = mesh_.faceEdges(faceI);
00053 
00054     forAll(fEdges, fp)
00055     {
00056         isBoundaryEdge[fEdges[fp]] = true;
00057     }
00058 
00059     const face& f = mesh_.faces()[faceI];
00060 
00061     forAll(f, fp)
00062     {
00063         isBoundaryPoint[f[fp]] = true;
00064     }
00065 }
00066 
00067 
00068 void Foam::meshRefinement::findNearest
00069 (
00070     const labelList& meshFaces,
00071     List<pointIndexHit>& nearestInfo,
00072     labelList& nearestSurface,
00073     labelList& nearestRegion,
00074     vectorField& nearestNormal
00075 ) const
00076 {
00077     pointField fc(meshFaces.size());
00078     forAll(meshFaces, i)
00079     {
00080         fc[i] = mesh_.faceCentres()[meshFaces[i]];
00081     }
00082 
00083     const labelList allSurfaces(identity(surfaces_.surfaces().size()));
00084 
00085     surfaces_.findNearest
00086     (
00087         allSurfaces,
00088         fc,
00089         scalarField(fc.size(), sqr(GREAT)),    // sqr of attraction
00090         nearestSurface,
00091         nearestInfo
00092     );
00093 
00094     // Do normal testing per surface.
00095     nearestNormal.setSize(nearestInfo.size());
00096     nearestRegion.setSize(nearestInfo.size());
00097 
00098     forAll(allSurfaces, surfI)
00099     {
00100         DynamicList<pointIndexHit> localHits;
00101 
00102         forAll(nearestSurface, i)
00103         {
00104             if (nearestSurface[i] == surfI)
00105             {
00106                 localHits.append(nearestInfo[i]);
00107             }
00108         }
00109 
00110         label geomI = surfaces_.surfaces()[surfI];
00111 
00112         pointField localNormals;
00113         surfaces_.geometry()[geomI].getNormal(localHits, localNormals);
00114 
00115         labelList localRegion;
00116         surfaces_.geometry()[geomI].getRegion(localHits, localRegion);
00117 
00118         label localI = 0;
00119         forAll(nearestSurface, i)
00120         {
00121             if (nearestSurface[i] == surfI)
00122             {
00123                 nearestNormal[i] = localNormals[localI];
00124                 nearestRegion[i] = localRegion[localI];
00125                 localI++;
00126             }
00127         }
00128     }
00129 }
00130 
00131 
00132 Foam::Map<Foam::label> Foam::meshRefinement::findEdgeConnectedProblemCells
00133 (
00134     const scalarField& perpendicularAngle,
00135     const labelList& globalToPatch
00136 ) const
00137 {
00138     // Construct addressing engine from all patches added for meshing.
00139     autoPtr<indirectPrimitivePatch> ppPtr
00140     (
00141         meshRefinement::makePatch
00142         (
00143             mesh_,
00144             meshedPatches()
00145         )
00146     );
00147     const indirectPrimitivePatch& pp = ppPtr();
00148 
00149 
00150     // 1. Collect faces to test
00151     // ~~~~~~~~~~~~~~~~~~~~~~~~
00152 
00153     DynamicList<label> candidateFaces(pp.size()/20);
00154 
00155     const labelListList& edgeFaces = pp.edgeFaces();
00156 
00157     const labelList& cellLevel = meshCutter_.cellLevel();
00158 
00159     forAll(edgeFaces, edgeI)
00160     {
00161         const labelList& eFaces = edgeFaces[edgeI];
00162 
00163         if (eFaces.size() == 2)
00164         {
00165             label face0 = pp.addressing()[eFaces[0]];
00166             label face1 = pp.addressing()[eFaces[1]];
00167 
00168             label cell0 = mesh_.faceOwner()[face0];
00169             label cell1 = mesh_.faceOwner()[face1];
00170 
00171             if (cellLevel[cell0] > cellLevel[cell1])
00172             {
00173                 // cell0 smaller.
00174                 const vector& n0 = pp.faceNormals()[eFaces[0]];
00175                 const vector& n1 = pp.faceNormals()[eFaces[1]];
00176 
00177                 if (mag(n0 & n1) < 0.1)
00178                 {
00179                     candidateFaces.append(face0);
00180                 }
00181             }
00182             else if (cellLevel[cell1] > cellLevel[cell0])
00183             {
00184                 // cell1 smaller.
00185                 const vector& n0 = pp.faceNormals()[eFaces[0]];
00186                 const vector& n1 = pp.faceNormals()[eFaces[1]];
00187 
00188                 if (mag(n0 & n1) < 0.1)
00189                 {
00190                     candidateFaces.append(face1);
00191                 }
00192             }
00193         }
00194     }
00195     candidateFaces.shrink();
00196 
00197     Info<< "Testing " << returnReduce(candidateFaces.size(), sumOp<label>())
00198         << " faces on edge-connected cells of differing level."
00199         << endl;
00200 
00201     if (debug)
00202     {
00203         faceSet fSet(mesh_, "edgeConnectedFaces", candidateFaces);
00204         Pout<< "Writing " << fSet.size()
00205             << " with problematic topology to faceSet "
00206             << fSet.objectPath() << endl;
00207         fSet.write();
00208     }
00209 
00210 
00211     // 2. Find nearest surface on candidate faces
00212     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00213 
00214     List<pointIndexHit> nearestInfo;
00215     labelList nearestSurface;
00216     labelList nearestRegion;
00217     vectorField nearestNormal;
00218     findNearest
00219     (
00220         candidateFaces,
00221         nearestInfo,
00222         nearestSurface,
00223         nearestRegion,
00224         nearestNormal
00225     );
00226 
00227 
00228     // 3. Test angle to surface
00229     // ~~~~~~~~~~~~~~~~~~~~~~~~
00230 
00231     Map<label> candidateCells(candidateFaces.size());
00232 
00233     faceSet perpFaces(mesh_, "perpendicularFaces", pp.size()/100);
00234 
00235     forAll(candidateFaces, i)
00236     {
00237         label faceI = candidateFaces[i];
00238 
00239         vector n = mesh_.faceAreas()[faceI];
00240         n /= mag(n);
00241 
00242         label region = surfaces_.globalRegion
00243         (
00244             nearestSurface[i],
00245             nearestRegion[i]
00246         );
00247 
00248         scalar angle =
00249             perpendicularAngle[region]
00250           / 180.0
00251           * mathematicalConstant::pi;
00252 
00253         if (angle >= 0)
00254         {
00255             if (mag(n & nearestNormal[i]) < Foam::sin(angle))
00256             {
00257                 perpFaces.insert(faceI);
00258                 candidateCells.insert
00259                 (
00260                     mesh_.faceOwner()[faceI],
00261                     globalToPatch[region]
00262                 );
00263             }
00264         }
00265     }
00266 
00267     if (debug)
00268     {
00269         Pout<< "Writing " << perpFaces.size()
00270             << " faces that are perpendicular to the surface to set "
00271             << perpFaces.objectPath() << endl;
00272         perpFaces.write();
00273     }
00274     return candidateCells;
00275 }
00276 
00277 
00278 // Check if moving face to new points causes a 'collapsed' face.
00279 // Uses new point position only for the face, not the neighbouring
00280 // cell centres
00281 bool Foam::meshRefinement::isCollapsedFace
00282 (
00283     const pointField& points,
00284     const pointField& neiCc,
00285     const scalar minFaceArea,
00286     const scalar maxNonOrtho,
00287     const label faceI
00288 ) const
00289 {
00290     vector s = mesh_.faces()[faceI].normal(points);
00291     scalar magS = mag(s);
00292 
00293     // Check face area
00294     if (magS < minFaceArea)
00295     {
00296         return true;
00297     }
00298 
00299     // Check orthogonality
00300     const point& ownCc = mesh_.cellCentres()[mesh_.faceOwner()[faceI]];
00301 
00302     if (mesh_.isInternalFace(faceI))
00303     {
00304         label nei = mesh_.faceNeighbour()[faceI];
00305         vector d = ownCc - mesh_.cellCentres()[nei];
00306 
00307         scalar dDotS = (d & s)/(mag(d)*magS + VSMALL);
00308 
00309         if (dDotS < maxNonOrtho)
00310         {
00311             return true;
00312         }
00313         else
00314         {
00315             return false;
00316         }
00317     }
00318     else
00319     {
00320         label patchI = mesh_.boundaryMesh().whichPatch(faceI);
00321 
00322         if (mesh_.boundaryMesh()[patchI].coupled())
00323         {
00324             vector d = ownCc - neiCc[faceI-mesh_.nInternalFaces()];
00325 
00326             scalar dDotS = (d & s)/(mag(d)*magS + VSMALL);
00327 
00328             if (dDotS < maxNonOrtho)
00329             {
00330                 return true;
00331             }
00332             else
00333             {
00334                 return false;
00335             }
00336         }
00337         else
00338         {
00339             // Collapsing normal boundary face does not cause problems with
00340             // non-orthogonality
00341             return true;
00342         }
00343     }
00344 }
00345 
00346 
00347 // Check if moving cell to new points causes it to collapse.
00348 bool Foam::meshRefinement::isCollapsedCell
00349 (
00350     const pointField& points,
00351     const scalar volFraction,
00352     const label cellI
00353 ) const
00354 {
00355     scalar vol = mesh_.cells()[cellI].mag(points, mesh_.faces());
00356 
00357     if (vol/mesh_.cellVolumes()[cellI] < volFraction)
00358     {
00359         return true;
00360     }
00361     else
00362     {
00363         return false;
00364     }
00365 }
00366 
00367 
00368 // Returns list with for every internal face -1 or the patch they should
00369 // be baffled into. Gets run after createBaffles so all the unzoned surface
00370 // intersections have already been turned into baffles. (Note: zoned surfaces
00371 // are not baffled at this stage)
00372 // Used to remove cells by baffling all their faces and have the
00373 // splitMeshRegions chuck away non used regions.
00374 Foam::labelList Foam::meshRefinement::markFacesOnProblemCells
00375 (
00376     const dictionary& motionDict,
00377     const bool removeEdgeConnectedCells,
00378     const scalarField& perpendicularAngle,
00379     const labelList& globalToPatch
00380 ) const
00381 {
00382     const labelList& cellLevel = meshCutter_.cellLevel();
00383     const labelList& pointLevel = meshCutter_.pointLevel();
00384     const polyBoundaryMesh& patches = mesh_.boundaryMesh();
00385 
00386     // Per internal face (boundary faces not used) the patch that the
00387     // baffle should get (or -1)
00388     labelList facePatch(mesh_.nFaces(), -1);
00389 
00390     // Mark all points and edges on baffle patches (so not on any inlets,
00391     // outlets etc.)
00392     boolList isBoundaryPoint(mesh_.nPoints(), false);
00393     boolList isBoundaryEdge(mesh_.nEdges(), false);
00394     boolList isBoundaryFace(mesh_.nFaces(), false);
00395 
00396     // Fill boundary data. All elements on meshed patches get marked.
00397     // Get the labels of added patches.
00398     labelList adaptPatchIDs(meshedPatches());
00399 
00400     forAll(adaptPatchIDs, i)
00401     {
00402         label patchI = adaptPatchIDs[i];
00403 
00404         const polyPatch& pp = patches[patchI];
00405 
00406         label faceI = pp.start();
00407 
00408         forAll(pp, j)
00409         {
00410             markBoundaryFace
00411             (
00412                 faceI,
00413                 isBoundaryFace,
00414                 isBoundaryEdge,
00415                 isBoundaryPoint
00416             );
00417 
00418             faceI++;
00419         }
00420     }
00421 
00422     // Swap neighbouring cell centres and cell level
00423     labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
00424     pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
00425     calcNeighbourData(neiLevel, neiCc);
00426 
00427 
00428     // Count of faces marked for baffling
00429     label nBaffleFaces = 0;
00430 
00431     // Count of faces not baffled since would not cause a collapse
00432     label nPrevented = 0;
00433 
00434     if (removeEdgeConnectedCells && max(perpendicularAngle) >= 0)
00435     {
00436         Info<< "markFacesOnProblemCells :"
00437             << " Checking for edge-connected cells of highly differing sizes."
00438             << endl;
00439 
00440         // Pick up the cells that need to be removed and (a guess for)
00441         // the patch they should be patched with.
00442         Map<label> problemCells
00443         (
00444             findEdgeConnectedProblemCells
00445             (
00446                 perpendicularAngle,
00447                 globalToPatch
00448             )
00449         );
00450 
00451         // Baffle all faces of cells that need to be removed
00452         forAllConstIter(Map<label>, problemCells, iter)
00453         {
00454             const cell& cFaces = mesh_.cells()[iter.key()];
00455 
00456             forAll(cFaces, i)
00457             {
00458                 label faceI = cFaces[i];
00459 
00460                 if (facePatch[faceI] == -1 && mesh_.isInternalFace(faceI))
00461                 {
00462                     facePatch[faceI] = getBafflePatch(facePatch, faceI);
00463                     nBaffleFaces++;
00464 
00465                     // Mark face as a 'boundary'
00466                     markBoundaryFace
00467                     (
00468                         faceI,
00469                         isBoundaryFace,
00470                         isBoundaryEdge,
00471                         isBoundaryPoint
00472                     );
00473                 }
00474             }
00475         }
00476         Info<< "markFacesOnProblemCells : Marked "
00477             << returnReduce(nBaffleFaces, sumOp<label>())
00478             << " additional internal faces to be converted into baffles"
00479             << " due to "
00480             << returnReduce(problemCells.size(), sumOp<label>())
00481             << " cells edge-connected to lower level cells." << endl;
00482 
00483         if (debug)
00484         {
00485             cellSet problemCellSet(mesh_, "problemCells", problemCells.toc());
00486             Pout<< "Writing " << problemCellSet.size()
00487                 << " cells that are edge connected to coarser cell to set "
00488                 << problemCellSet.objectPath() << endl;
00489             problemCellSet.write();
00490         }
00491     }
00492 
00493     syncTools::syncPointList
00494     (
00495         mesh_,
00496         isBoundaryPoint,
00497         orEqOp<bool>(),
00498         false,              // null value
00499         false               // no separation
00500     );
00501 
00502     syncTools::syncEdgeList
00503     (
00504         mesh_,
00505         isBoundaryEdge,
00506         orEqOp<bool>(),
00507         false,              // null value
00508         false               // no separation
00509     );
00510 
00511     syncTools::syncFaceList
00512     (
00513         mesh_,
00514         isBoundaryFace,
00515         orEqOp<bool>(),
00516         false               // no separation
00517     );
00518 
00519 
00520     // See if checking for collapse
00521     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00522 
00523     // Collapse checking parameters
00524     scalar volFraction = -1;
00525     if (motionDict.found("minVolCollapseRatio"))
00526     {
00527         volFraction = readScalar(motionDict.lookup("minVolCollapseRatio"));
00528     }
00529     const bool checkCollapse = (volFraction > 0);
00530     scalar minArea = -1;
00531     scalar maxNonOrtho = -1;
00532 
00533 
00534     // Find nearest (non-baffle) surface
00535     pointField newPoints;
00536 
00537     if (checkCollapse)
00538     {
00539         minArea = readScalar(motionDict.lookup("minArea"));
00540         maxNonOrtho = readScalar(motionDict.lookup("maxNonOrtho"));
00541 
00542         Info<< "markFacesOnProblemCells :"
00543             << " Deleting all-anchor surface cells only if"
00544             << "snapping them violates mesh quality constraints:" << nl
00545             << "    snapped/original cell volume < " << volFraction << nl
00546             << "    face area                    < " << minArea << nl
00547             << "    non-orthogonality            > " << maxNonOrtho << nl
00548             << endl;
00549 
00550         // Construct addressing engine.
00551         autoPtr<indirectPrimitivePatch> ppPtr
00552         (
00553             meshRefinement::makePatch
00554             (
00555                 mesh_,
00556                 adaptPatchIDs
00557             )
00558         );
00559         const indirectPrimitivePatch& pp = ppPtr();
00560         const pointField& localPoints = pp.localPoints();
00561         const labelList& meshPoints = pp.meshPoints();
00562 
00563         List<pointIndexHit> hitInfo;
00564         labelList hitSurface;
00565         surfaces_.findNearest
00566         (
00567             surfaces_.getUnnamedSurfaces(),
00568             localPoints,
00569             scalarField(localPoints.size(), sqr(GREAT)),    // sqr of attraction
00570             hitSurface,
00571             hitInfo
00572         );
00573 
00574         // Start of from current points
00575         newPoints = mesh_.points();
00576 
00577         forAll(hitInfo, i)
00578         {
00579             if (hitInfo[i].hit())
00580             {
00581                 newPoints[meshPoints[i]] = hitInfo[i].hitPoint();
00582             }
00583         }
00584     }
00585 
00586 
00587 
00588     // For each cell count the number of anchor points that are on
00589     // the boundary:
00590     // 8 : check the number of (baffle) boundary faces. If 3 or more block
00591     //     off the cell since the cell would get squeezed down to a diamond
00592     //     (probably; if the 3 or more faces are unrefined (only use the
00593     //      anchor points))
00594     // 7 : store. Used to check later on whether there are points with
00595     //     3 or more of these cells. (note that on a flat surface a boundary
00596     //     point will only have 4 cells connected to it)
00597 
00598 
00599     // Does cell have exactly 7 of its 8 anchor points on the boundary?
00600     PackedBoolList hasSevenBoundaryAnchorPoints(mesh_.nCells());
00601     // If so what is the remaining non-boundary anchor point?
00602     labelHashSet nonBoundaryAnchors(mesh_.nCells()/10000);
00603 
00604     // On-the-fly addressing storage.
00605     DynamicList<label> dynFEdges;
00606     DynamicList<label> dynCPoints;
00607 
00608     forAll(cellLevel, cellI)
00609     {
00610         const labelList& cPoints = mesh_.cellPoints(cellI, dynCPoints);
00611 
00612         // Get number of anchor points (pointLevel <= cellLevel)
00613 
00614         label nBoundaryAnchors = 0;
00615         label nNonAnchorBoundary = 0;
00616         label nonBoundaryAnchor = -1;
00617 
00618         forAll(cPoints, i)
00619         {
00620             label pointI = cPoints[i];
00621 
00622             if (pointLevel[pointI] <= cellLevel[cellI])
00623             {
00624                 // Anchor point
00625                 if (isBoundaryPoint[pointI])
00626                 {
00627                     nBoundaryAnchors++;
00628                 }
00629                 else
00630                 {
00631                     // Anchor point which is not on the surface
00632                     nonBoundaryAnchor = pointI;
00633                 }
00634             }
00635             else if (isBoundaryPoint[pointI])
00636             {
00637                 nNonAnchorBoundary++;
00638             }
00639         }
00640 
00641         if (nBoundaryAnchors == 8)
00642         {
00643             const cell& cFaces = mesh_.cells()[cellI];
00644 
00645             // Count boundary faces.
00646             label nBfaces = 0;
00647 
00648             forAll(cFaces, cFaceI)
00649             {
00650                 if (isBoundaryFace[cFaces[cFaceI]])
00651                 {
00652                     nBfaces++;
00653                 }
00654             }
00655 
00656             // If nBfaces > 1 make all non-boundary non-baffle faces baffles.
00657             // We assume that this situation is where there is a single
00658             // cell sticking out which would get flattened.
00659 
00660             // Eugene: delete cell no matter what.
00661             //if (nBfaces > 1)
00662             {
00663                 if
00664                 (
00665                     checkCollapse
00666                 && !isCollapsedCell(newPoints, volFraction, cellI)
00667                 )
00668                 {
00669                     nPrevented++;
00670                     //Pout<< "Preventing collapse of 8 anchor point cell "
00671                     //    << cellI << " at " << mesh_.cellCentres()[cellI]
00672                     //    << " since new volume "
00673                     //    << mesh_.cells()[cellI].mag(newPoints, mesh_.faces())
00674                     //    << " old volume " << mesh_.cellVolumes()[cellI]
00675                     //    << endl;
00676                 }
00677                 else
00678                 {
00679                     // Block all faces of cell
00680                     forAll(cFaces, cf)
00681                     {
00682                         label faceI = cFaces[cf];
00683 
00684                         if
00685                         (
00686                             facePatch[faceI] == -1
00687                          && mesh_.isInternalFace(faceI)
00688                         )
00689                         {
00690                             facePatch[faceI] = getBafflePatch(facePatch, faceI);
00691                             nBaffleFaces++;
00692 
00693                             // Mark face as a 'boundary'
00694                             markBoundaryFace
00695                             (
00696                                 faceI,
00697                                 isBoundaryFace,
00698                                 isBoundaryEdge,
00699                                 isBoundaryPoint
00700                             );
00701                         }
00702                     }
00703                 }
00704             }
00705         }
00706         else if (nBoundaryAnchors == 7)
00707         {
00708             // Mark the cell. Store the (single!) non-boundary anchor point.
00709             hasSevenBoundaryAnchorPoints.set(cellI, 1u);
00710             nonBoundaryAnchors.insert(nonBoundaryAnchor);
00711         }
00712     }
00713 
00714 
00715     // Loop over all points. If a point is connected to 4 or more cells
00716     // with 7 anchor points on the boundary set those cell's non-boundary faces
00717     // to baffles
00718 
00719     DynamicList<label> dynPCells;
00720 
00721     forAllConstIter(labelHashSet, nonBoundaryAnchors, iter)
00722     {
00723         label pointI = iter.key();
00724 
00725         const labelList& pCells = mesh_.pointCells(pointI, dynPCells);
00726 
00727         // Count number of 'hasSevenBoundaryAnchorPoints' cells.
00728         label n = 0;
00729 
00730         forAll(pCells, i)
00731         {
00732             if (hasSevenBoundaryAnchorPoints.get(pCells[i]) == 1u)
00733             {
00734                 n++;
00735             }
00736         }
00737 
00738         if (n > 3)
00739         {
00740             // Point in danger of being what? Remove all 7-cells.
00741             forAll(pCells, i)
00742             {
00743                 label cellI = pCells[i];
00744 
00745                 if (hasSevenBoundaryAnchorPoints.get(cellI) == 1u)
00746                 {
00747                     if
00748                     (
00749                         checkCollapse
00750                     && !isCollapsedCell(newPoints, volFraction, cellI)
00751                     )
00752                     {
00753                         nPrevented++;
00754                         //Pout<< "Preventing collapse of 7 anchor cell "
00755                         //    << cellI
00756                         //    << " at " << mesh_.cellCentres()[cellI]
00757                         //    << " since new volume "
00758                         //    << mesh_.cells()[cellI].mag
00759                         //        (newPoints, mesh_.faces())
00760                         //    << " old volume " << mesh_.cellVolumes()[cellI]
00761                         //    << endl;
00762                     }
00763                     else
00764                     {
00765                         const cell& cFaces = mesh_.cells()[cellI];
00766 
00767                         forAll(cFaces, cf)
00768                         {
00769                             label faceI = cFaces[cf];
00770 
00771                             if
00772                             (
00773                                 facePatch[faceI] == -1
00774                              && mesh_.isInternalFace(faceI)
00775                             )
00776                             {
00777                                 facePatch[faceI] = getBafflePatch
00778                                 (
00779                                     facePatch,
00780                                     faceI
00781                                 );
00782                                 nBaffleFaces++;
00783 
00784                                 // Mark face as a 'boundary'
00785                                 markBoundaryFace
00786                                 (
00787                                     faceI,
00788                                     isBoundaryFace,
00789                                     isBoundaryEdge,
00790                                     isBoundaryPoint
00791                                 );
00792                             }
00793                         }
00794                     }
00795                 }
00796             }
00797         }
00798     }
00799 
00800 
00801     // Sync all. (note that pointdata and facedata not used anymore but sync
00802     // anyway)
00803 
00804     syncTools::syncPointList
00805     (
00806         mesh_,
00807         isBoundaryPoint,
00808         orEqOp<bool>(),
00809         false,              // null value
00810         false               // no separation
00811     );
00812 
00813     syncTools::syncEdgeList
00814     (
00815         mesh_,
00816         isBoundaryEdge,
00817         orEqOp<bool>(),
00818         false,              // null value
00819         false               // no separation
00820     );
00821 
00822     syncTools::syncFaceList
00823     (
00824         mesh_,
00825         isBoundaryFace,
00826         orEqOp<bool>(),
00827         false               // no separation
00828     );
00829 
00830 
00831     // Find faces with all edges on the boundary and make them baffles
00832     for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
00833     {
00834         if (facePatch[faceI] == -1)
00835         {
00836             const labelList& fEdges = mesh_.faceEdges(faceI, dynFEdges);
00837             label nFaceBoundaryEdges = 0;
00838 
00839             forAll(fEdges, fe)
00840             {
00841                 if (isBoundaryEdge[fEdges[fe]])
00842                 {
00843                     nFaceBoundaryEdges++;
00844                 }
00845             }
00846 
00847             if (nFaceBoundaryEdges == fEdges.size())
00848             {
00849                 if
00850                 (
00851                     checkCollapse
00852                 && !isCollapsedFace
00853                     (
00854                         newPoints,
00855                         neiCc,
00856                         minArea,
00857                         maxNonOrtho,
00858                         faceI
00859                     )
00860                 )
00861                 {
00862                     nPrevented++;
00863                     //Pout<< "Preventing collapse of face " << faceI
00864                     //    << " with all boundary edges "
00865                     //    << " at " << mesh_.faceCentres()[faceI]
00866                     //    << endl;
00867                 }
00868                 else
00869                 {
00870                     facePatch[faceI] = getBafflePatch(facePatch, faceI);
00871                     nBaffleFaces++;
00872 
00873                     // Do NOT update boundary data since this would grow blocked
00874                     // faces across gaps.
00875                 }
00876             }
00877         }
00878     }
00879 
00880     forAll(patches, patchI)
00881     {
00882         const polyPatch& pp = patches[patchI];
00883 
00884         if (pp.coupled())
00885         {
00886             label faceI = pp.start();
00887 
00888             forAll(pp, i)
00889             {
00890                 if (facePatch[faceI] == -1)
00891                 {
00892                     const labelList& fEdges = mesh_.faceEdges(faceI, dynFEdges);
00893                     label nFaceBoundaryEdges = 0;
00894 
00895                     forAll(fEdges, fe)
00896                     {
00897                         if (isBoundaryEdge[fEdges[fe]])
00898                         {
00899                             nFaceBoundaryEdges++;
00900                         }
00901                     }
00902 
00903                     if (nFaceBoundaryEdges == fEdges.size())
00904                     {
00905                         if
00906                         (
00907                             checkCollapse
00908                         && !isCollapsedFace
00909                             (
00910                                 newPoints,
00911                                 neiCc,
00912                                 minArea,
00913                                 maxNonOrtho,
00914                                 faceI
00915                             )
00916                         )
00917                         {
00918                             nPrevented++;
00919                             //Pout<< "Preventing collapse of coupled face "
00920                             //    << faceI
00921                             //    << " with all boundary edges "
00922                             //    << " at " << mesh_.faceCentres()[faceI]
00923                             //    << endl;
00924                         }
00925                         else
00926                         {
00927                             facePatch[faceI] = getBafflePatch(facePatch, faceI);
00928                             nBaffleFaces++;
00929 
00930                             // Do NOT update boundary data since this would grow
00931                             // blocked faces across gaps.
00932                         }
00933                     }
00934                 }
00935 
00936                 faceI++;
00937             }
00938         }
00939     }
00940 
00941     Info<< "markFacesOnProblemCells : marked "
00942         << returnReduce(nBaffleFaces, sumOp<label>())
00943         << " additional internal faces to be converted into baffles."
00944         << endl;
00945 
00946     if (checkCollapse)
00947     {
00948         Info<< "markFacesOnProblemCells : prevented "
00949             << returnReduce(nPrevented, sumOp<label>())
00950             << " internal faces fom getting converted into baffles."
00951             << endl;
00952     }
00953 
00954     return facePatch;
00955 }
00956 
00957 
00960 //Foam::labelList Foam::meshRefinement::markFacesOnProblemCellsGeometric
00961 //(
00962 //    const dictionary& motionDict
00963 //) const
00964 //{
00965 //    // Construct addressing engine.
00966 //    autoPtr<indirectPrimitivePatch> ppPtr
00967 //    (
00968 //        meshRefinement::makePatch
00969 //        (
00970 //            mesh_,
00971 //            meshedPatches()
00972 //        )
00973 //    );
00974 //    const indirectPrimitivePatch& pp = ppPtr();
00975 //    const pointField& localPoints = pp.localPoints();
00976 //    const labelList& meshPoints = pp.meshPoints();
00977 //
00978 //    // Find nearest (non-baffle) surface
00979 //    pointField newPoints(mesh_.points());
00980 //    {
00981 //        List<pointIndexHit> hitInfo;
00982 //        labelList hitSurface;
00983 //        surfaces_.findNearest
00984 //        (
00985 //            surfaces_.getUnnamedSurfaces(),
00986 //            localPoints,
00987 //            scalarField(localPoints.size(), sqr(GREAT)),// sqr of attraction
00988 //            hitSurface,
00989 //            hitInfo
00990 //        );
00991 //
00992 //        forAll(hitInfo, i)
00993 //        {
00994 //            if (hitInfo[i].hit())
00995 //            {
00996 //                //label pointI = meshPoints[i];
00997 //                //Pout<< "   " << pointI << " moved from "
00998 //                //    << mesh_.points()[pointI] << " by "
00999 //                //    << mag(hitInfo[i].hitPoint()-mesh_.points()[pointI])
01000 //                //    << endl;
01001 //                newPoints[meshPoints[i]] = hitInfo[i].hitPoint();
01002 //            }
01003 //        }
01004 //    }
01005 //
01006 //    // Per face (internal or coupled!) the patch that the
01007 //    // baffle should get (or -1).
01008 //    labelList facePatch(mesh_.nFaces(), -1);
01009 //    // Count of baffled faces
01010 //    label nBaffleFaces = 0;
01011 //
01012 //    {
01013 //        pointField oldPoints(mesh_.points());
01014 //        mesh_.movePoints(newPoints);
01015 //        faceSet wrongFaces(mesh_, "wrongFaces", 100);
01016 //        {
01017 //            //motionSmoother::checkMesh(false, mesh_, motionDict, wrongFaces);
01018 //
01019 //            // Just check the errors from squashing
01020 //            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
01021 //
01022 //            const labelList allFaces(identity(mesh_.nFaces()));
01023 //            label nWrongFaces = 0;
01024 //
01025 //            scalar minArea(readScalar(motionDict.lookup("minArea")));
01026 //            if (minArea > -SMALL)
01027 //            {
01028 //                polyMeshGeometry::checkFaceArea
01029 //                (
01030 //                    false,
01031 //                    minArea,
01032 //                    mesh_,
01033 //                    mesh_.faceAreas(),
01034 //                    allFaces,
01035 //                    &wrongFaces
01036 //                );
01037 //
01038 //                label nNewWrongFaces = returnReduce
01039 //                (
01040 //                    wrongFaces.size(),
01041 //                    sumOp<label>()
01042 //                );
01043 //
01044 //                Info<< "    faces with area < "
01045 //                    << setw(5) << minArea
01046 //                    << " m^2                            : "
01047 //                    << nNewWrongFaces-nWrongFaces << endl;
01048 //
01049 //                nWrongFaces = nNewWrongFaces;
01050 //            }
01051 //
01053 //            scalar minDet = 0.01;
01054 //            if (minDet > -1)
01055 //            {
01056 //                polyMeshGeometry::checkCellDeterminant
01057 //                (
01058 //                    false,
01059 //                    minDet,
01060 //                    mesh_,
01061 //                    mesh_.faceAreas(),
01062 //                    allFaces,
01063 //                    polyMeshGeometry::affectedCells(mesh_, allFaces),
01064 //                    &wrongFaces
01065 //                );
01066 //
01067 //                label nNewWrongFaces = returnReduce
01068 //                (
01069 //                    wrongFaces.size(),
01070 //                    sumOp<label>()
01071 //                );
01072 //
01073 //                Info<< "    faces on cells with determinant < "
01074 //                    << setw(5) << minDet << "                : "
01075 //                    << nNewWrongFaces-nWrongFaces << endl;
01076 //
01077 //                nWrongFaces = nNewWrongFaces;
01078 //            }
01079 //        }
01080 //
01081 //
01082 //        forAllConstIter(faceSet, wrongFaces, iter)
01083 //        {
01084 //            label patchI = mesh_.boundaryMesh().whichPatch(iter.key());
01085 //
01086 //            if (patchI == -1 || mesh_.boundaryMesh()[patchI].coupled())
01087 //            {
01088 //                facePatch[iter.key()] = getBafflePatch(facePatch, iter.key());
01089 //                nBaffleFaces++;
01090 //
01091 //                //Pout<< "    " << iter.key()
01092 //                //    //<< " on patch " << mesh_.boundaryMesh()[patchI].name()
01093 //                //    << " is destined for patch " << facePatch[iter.key()]
01094 //                //    << endl;
01095 //            }
01096 //        }
01097 //        // Restore points.
01098 //        mesh_.movePoints(oldPoints);
01099 //    }
01100 //
01101 //
01102 //    Info<< "markFacesOnProblemCellsGeometric : marked "
01103 //        << returnReduce(nBaffleFaces, sumOp<label>())
01104 //        << " additional internal and coupled faces"
01105 //        << " to be converted into baffles." << endl;
01106 //
01107 //    syncTools::syncFaceList
01108 //    (
01109 //        mesh_,
01110 //        facePatch,
01111 //        maxEqOp<label>(),
01112 //        false               // no separation
01113 //    );
01114 //
01115 //    return facePatch;
01116 //}
01117 
01118 
01119 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines