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

refinementSurfaces.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 "refinementSurfaces.H"
00027 #include <OpenFOAM/Time.H>
00028 #include <meshTools/searchableSurfaces.H>
00029 #include <autoMesh/shellSurfaces.H>
00030 #include <meshTools/triSurfaceMesh.H>
00031 #include <OpenFOAM/labelPair.H>
00032 #include <meshTools/searchableSurfacesQueries.H>
00033 #include <OpenFOAM/UPtrList.H>
00034 
00035 
00036 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00037 
00038 // Construct from components
00039 Foam::refinementSurfaces::refinementSurfaces
00040 (
00041     const searchableSurfaces& allGeometry,
00042     const PtrList<dictionary>& surfaceDicts
00043 )
00044 :
00045     allGeometry_(allGeometry),
00046     surfaces_(surfaceDicts.size()),
00047     names_(surfaceDicts.size()),
00048     faceZoneNames_(surfaceDicts.size()),
00049     cellZoneNames_(surfaceDicts.size()),
00050     zoneInside_(surfaceDicts.size()),
00051     regionOffset_(surfaceDicts.size())
00052 {
00053     labelList globalMinLevel(surfaceDicts.size(), 0);
00054     labelList globalMaxLevel(surfaceDicts.size(), 0);
00055     scalarField globalAngle(surfaceDicts.size(), -GREAT);
00056     List<Map<label> > regionMinLevel(surfaceDicts.size());
00057     List<Map<label> > regionMaxLevel(surfaceDicts.size());
00058     List<Map<scalar> > regionAngle(surfaceDicts.size());
00059 
00060     //wordList globalPatchType(surfaceDicts.size());
00061     //List<HashTable<word> > regionPatchType(surfaceDicts.size());
00062     //List<HashTable<word> > regionPatchName(surfaceDicts.size());
00063 
00064     forAll(surfaceDicts, surfI)
00065     {
00066         const dictionary& dict = surfaceDicts[surfI];
00067 
00068         dict.lookup("name") >> names_[surfI];
00069 
00070         surfaces_[surfI] = allGeometry_.findSurfaceID(names_[surfI]);
00071 
00072         // Global refinement level
00073         globalMinLevel[surfI] = readLabel(dict.lookup("minRefinementLevel"));
00074         globalMaxLevel[surfI] = readLabel(dict.lookup("maxRefinementLevel"));
00075 
00076         // Global zone names per surface
00077         if (dict.found("faceZone"))
00078         {
00079             dict.lookup("faceZone") >> faceZoneNames_[surfI];
00080             dict.lookup("cellZone") >> cellZoneNames_[surfI];
00081             dict.lookup("zoneInside") >> zoneInside_[surfI];
00082         }
00083 
00084         // Global perpendicular angle
00085         if (dict.found("perpendicularAngle"))
00086         {
00087             globalAngle[surfI] = readScalar(dict.lookup("perpendicularAngle"));
00088         }
00089 
00091         //if (dict.found("patchType"))
00092         //{
00093         //    dict.lookup("patchType") >> globalPatchType[surfI];
00094         //}
00095 
00096 
00097         if (dict.found("regions"))
00098         {
00099             PtrList<dictionary> regionDicts(dict.lookup("regions"));
00100 
00101             const wordList& regionNames =
00102                 allGeometry_[surfaces_[surfI]].regions();
00103 
00104             forAll(regionDicts, dictI)
00105             {
00106                 const dictionary& regionDict = regionDicts[dictI];
00107 
00108                 const word regionName(regionDict.lookup("name"));
00109 
00110                 label regionI = findIndex(regionNames, regionName);
00111 
00112                 if (regionI == -1)
00113                 {
00114                     FatalErrorIn
00115                     (
00116                         "refinementSurfaces::refinementSurfaces"
00117                         "(const IOobject&, const PtrList<dictionary>&)"
00118                     )   << "No region called " << regionName << " on surface "
00119                         << allGeometry_[surfaces_[surfI]].name() << endl
00120                         << "Valid regions are " << regionNames
00121                         << exit(FatalError);
00122                 }
00123 
00124 
00125                 label min = readLabel(regionDict.lookup("minRefinementLevel"));
00126                 label max = readLabel(regionDict.lookup("maxRefinementLevel"));
00127 
00128                 bool hasInserted = regionMinLevel[surfI].insert(regionI, min);
00129                 if (!hasInserted)
00130                 {
00131                     FatalErrorIn
00132                     (
00133                         "refinementSurfaces::refinementSurfaces"
00134                         "(const IOobject&, const PtrList<dictionary>&)"
00135                     )   << "Duplicate region name " << regionName
00136                         << " on surface " << names_[surfI]
00137                         << exit(FatalError);
00138                 }
00139                 regionMaxLevel[surfI].insert(regionI, max);
00140 
00141                 if (regionDict.found("perpendicularAngle"))
00142                 {
00143                     regionAngle[surfI].insert
00144                     (
00145                         regionI,
00146                         readScalar(regionDict.lookup("perpendicularAngle"))
00147                     );
00148                 }
00149             }
00150         }
00151     }
00152 
00153 
00154     // Check for duplicate surface names
00155     {
00156         HashTable<label> surfaceNames(names_.size());
00157 
00158         forAll(names_, surfI)
00159         {
00160             if (!surfaceNames.insert(names_[surfI], surfI))
00161             {
00162                 FatalErrorIn
00163                 (
00164                     "refinementSurfaces::refinementSurfaces"
00165                     "(const IOobject&, const PtrList<dictionary>&)"
00166                 )   << "Duplicate surface name " << names_[surfI] << endl
00167                     << "Previous occurrence of name at surface "
00168                     << surfaceNames[names_[surfI]]
00169                     << exit(FatalError);
00170             }
00171         }
00172     }
00173 
00174     // Calculate local to global region offset
00175     label nRegions = 0;
00176 
00177     forAll(surfaceDicts, surfI)
00178     {
00179         regionOffset_[surfI] = nRegions;
00180 
00181         nRegions += allGeometry_[surfaces_[surfI]].regions().size();
00182     }
00183 
00184     // Rework surface specific information into information per global region
00185     minLevel_.setSize(nRegions);
00186     minLevel_ = 0;
00187     maxLevel_.setSize(nRegions);
00188     maxLevel_ = 0;
00189     perpendicularAngle_.setSize(nRegions);
00190     perpendicularAngle_ = -GREAT;
00191     //patchName_.setSize(nRegions);
00192     //patchType_.setSize(nRegions);
00193 
00194     forAll(surfaceDicts, surfI)
00195     {
00196         label nRegions = allGeometry_[surfaces_[surfI]].regions().size();
00197 
00198         // Initialise to global (i.e. per surface)
00199         for (label i = 0; i < nRegions; i++)
00200         {
00201             minLevel_[regionOffset_[surfI] + i] = globalMinLevel[surfI];
00202             maxLevel_[regionOffset_[surfI] + i] = globalMaxLevel[surfI];
00203             perpendicularAngle_[regionOffset_[surfI] + i] = globalAngle[surfI];
00204         }
00205 
00206         // Overwrite with region specific information
00207         forAllConstIter(Map<label>, regionMinLevel[surfI], iter)
00208         {
00209             label globalRegionI = regionOffset_[surfI] + iter.key();
00210 
00211             minLevel_[globalRegionI] = iter();
00212             maxLevel_[globalRegionI] = regionMaxLevel[surfI][iter.key()];
00213 
00214             // Check validity
00215             if
00216             (
00217                 minLevel_[globalRegionI] < 0
00218              || maxLevel_[globalRegionI] < minLevel_[globalRegionI]
00219             )
00220             {
00221                 FatalErrorIn
00222                 (
00223                     "refinementSurfaces::refinementSurfaces"
00224                     "(const IOobject&, const PtrList<dictionary>&)"
00225                 )   << "Illegal level or layer specification for surface "
00226                     << names_[surfI]
00227                     << " : minLevel:" << minLevel_[globalRegionI]
00228                     << " maxLevel:" << maxLevel_[globalRegionI]
00229                     << exit(FatalError);
00230             }
00231         }
00232         forAllConstIter(Map<scalar>, regionAngle[surfI], iter)
00233         {
00234             label globalRegionI = regionOffset_[surfI] + iter.key();
00235 
00236             perpendicularAngle_[globalRegionI] = regionAngle[surfI][iter.key()];
00237         }
00238 
00239 
00241         //forAllConstIter(HashTable<word>, regionPatchName[surfI], iter)
00242         //{
00243         //    label regionI = findIndex(regionNames, iter.key());
00244         //    label globalRegionI = regionOffset_[surfI] + regionI;
00245         //
00246         //    patchName_[globalRegionI] = iter();
00247         //    patchType_[globalRegionI] = regionPatchType[surfI][iter.key()];
00248         //}
00249     }
00250 }
00251 
00252 
00253 Foam::refinementSurfaces::refinementSurfaces
00254 (
00255     const searchableSurfaces& allGeometry,
00256     const dictionary& surfacesDict
00257 )
00258 :
00259     allGeometry_(allGeometry),
00260     surfaces_(surfacesDict.size()),
00261     names_(surfacesDict.size()),
00262     faceZoneNames_(surfacesDict.size()),
00263     cellZoneNames_(surfacesDict.size()),
00264     zoneInside_(surfacesDict.size()),
00265     regionOffset_(surfacesDict.size())
00266 {
00267     // Wilcard specification : loop over all surface, all regions
00268     // and try to find a match.
00269 
00270     // Count number of surfaces.
00271     label surfI = 0;
00272     forAll(allGeometry.names(), geomI)
00273     {
00274         const word& geomName = allGeometry_.names()[geomI];
00275 
00276         if (surfacesDict.found(geomName))
00277         {
00278             surfI++;
00279         }
00280     }
00281 
00282     // Size lists
00283     surfaces_.setSize(surfI);
00284     names_.setSize(surfI);
00285     faceZoneNames_.setSize(surfI);
00286     cellZoneNames_.setSize(surfI);
00287     zoneInside_.setSize(surfI);
00288     regionOffset_.setSize(surfI);
00289 
00290     labelList globalMinLevel(surfI, 0);
00291     labelList globalMaxLevel(surfI, 0);
00292     scalarField globalAngle(surfI, -GREAT);
00293     List<Map<label> > regionMinLevel(surfI);
00294     List<Map<label> > regionMaxLevel(surfI);
00295     List<Map<scalar> > regionAngle(surfI);
00296 
00297     surfI = 0;
00298     forAll(allGeometry.names(), geomI)
00299     {
00300         const word& geomName = allGeometry_.names()[geomI];
00301 
00302         if (surfacesDict.found(geomName))
00303         {
00304             const dictionary& dict = surfacesDict.subDict(geomName);
00305 
00306             names_[surfI] = geomName;
00307             surfaces_[surfI] = geomI;
00308 
00309             const labelPair refLevel(dict.lookup("level"));
00310             globalMinLevel[surfI] = refLevel[0];
00311             globalMaxLevel[surfI] = refLevel[1];
00312 
00313             // Global zone names per surface
00314             if (dict.found("faceZone"))
00315             {
00316                 dict.lookup("faceZone") >> faceZoneNames_[surfI];
00317                 dict.lookup("cellZone") >> cellZoneNames_[surfI];
00318                 dict.lookup("zoneInside") >> zoneInside_[surfI];
00319             }
00320 
00321             // Global perpendicular angle
00322             if (dict.found("perpendicularAngle"))
00323             {
00324                 globalAngle[surfI] = readScalar
00325                 (
00326                     dict.lookup("perpendicularAngle")
00327                 );
00328             }
00329 
00330             if (dict.found("regions"))
00331             {
00332                 const dictionary& regionsDict = dict.subDict("regions");
00333                 const wordList& regionNames =
00334                     allGeometry_[surfaces_[surfI]].regions();
00335 
00336                 forAll(regionNames, regionI)
00337                 {
00338                     if (regionsDict.found(regionNames[regionI]))
00339                     {
00340                         // Get the dictionary for region
00341                         const dictionary& regionDict = regionsDict.subDict
00342                         (
00343                             regionNames[regionI]
00344                         );
00345 
00346                         const labelPair refLevel(regionDict.lookup("level"));
00347 
00348                         regionMinLevel[surfI].insert(regionI, refLevel[0]);
00349                         regionMaxLevel[surfI].insert(regionI, refLevel[1]);
00350 
00351                         if (regionDict.found("perpendicularAngle"))
00352                         {
00353                             regionAngle[surfI].insert
00354                             (
00355                                 regionI,
00356                                 readScalar
00357                                 (
00358                                     regionDict.lookup("perpendicularAngle")
00359                                 )
00360                             );
00361                         }
00362                     }
00363                 }
00364             }
00365             surfI++;
00366         }
00367     }
00368 
00369     // Calculate local to global region offset
00370     label nRegions = 0;
00371 
00372     forAll(surfaces_, surfI)
00373     {
00374         regionOffset_[surfI] = nRegions;
00375         nRegions += allGeometry_[surfaces_[surfI]].regions().size();
00376     }
00377 
00378     // Rework surface specific information into information per global region
00379     minLevel_.setSize(nRegions);
00380     minLevel_ = 0;
00381     maxLevel_.setSize(nRegions);
00382     maxLevel_ = 0;
00383     perpendicularAngle_.setSize(nRegions);
00384     perpendicularAngle_ = -GREAT;
00385 
00386 
00387     forAll(globalMinLevel, surfI)
00388     {
00389         label nRegions = allGeometry_[surfaces_[surfI]].regions().size();
00390 
00391         // Initialise to global (i.e. per surface)
00392         for (label i = 0; i < nRegions; i++)
00393         {
00394             minLevel_[regionOffset_[surfI] + i] = globalMinLevel[surfI];
00395             maxLevel_[regionOffset_[surfI] + i] = globalMaxLevel[surfI];
00396             perpendicularAngle_[regionOffset_[surfI] + i] = globalAngle[surfI];
00397         }
00398 
00399         // Overwrite with region specific information
00400         forAllConstIter(Map<label>, regionMinLevel[surfI], iter)
00401         {
00402             label globalRegionI = regionOffset_[surfI] + iter.key();
00403 
00404             minLevel_[globalRegionI] = iter();
00405             maxLevel_[globalRegionI] = regionMaxLevel[surfI][iter.key()];
00406 
00407             // Check validity
00408             if
00409             (
00410                 minLevel_[globalRegionI] < 0
00411              || maxLevel_[globalRegionI] < minLevel_[globalRegionI]
00412             )
00413             {
00414                 FatalErrorIn
00415                 (
00416                     "refinementSurfaces::refinementSurfaces"
00417                     "(const searchableSurfaces&, const dictionary>&"
00418                 )   << "Illegal level or layer specification for surface "
00419                     << names_[surfI]
00420                     << " : minLevel:" << minLevel_[globalRegionI]
00421                     << " maxLevel:" << maxLevel_[globalRegionI]
00422                     << exit(FatalError);
00423             }
00424         }
00425         forAllConstIter(Map<scalar>, regionAngle[surfI], iter)
00426         {
00427             label globalRegionI = regionOffset_[surfI] + iter.key();
00428 
00429             perpendicularAngle_[globalRegionI] = regionAngle[surfI][iter.key()];
00430         }
00431     }
00432 }
00433 
00434 
00435 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00436 
00437 // Get indices of unnamed surfaces (surfaces without faceZoneName)
00438 Foam::labelList Foam::refinementSurfaces::getUnnamedSurfaces() const
00439 {
00440     labelList anonymousSurfaces(faceZoneNames_.size());
00441 
00442     label i = 0;
00443     forAll(faceZoneNames_, surfI)
00444     {
00445         if (faceZoneNames_[surfI].empty())
00446         {
00447             anonymousSurfaces[i++] = surfI;
00448         }
00449     }
00450     anonymousSurfaces.setSize(i);
00451 
00452     return anonymousSurfaces;
00453 }
00454 
00455 
00456 // Get indices of named surfaces (surfaces with faceZoneName)
00457 Foam::labelList Foam::refinementSurfaces::getNamedSurfaces() const
00458 {
00459    labelList namedSurfaces(faceZoneNames_.size());
00460 
00461     label namedI = 0;
00462     forAll(faceZoneNames_, surfI)
00463     {
00464         if (faceZoneNames_[surfI].size())
00465         {
00466             namedSurfaces[namedI++] = surfI;
00467         }
00468     }
00469     namedSurfaces.setSize(namedI);
00470 
00471     return namedSurfaces;
00472 }
00473 
00474 
00475 // Get indices of closed named surfaces
00476 Foam::labelList Foam::refinementSurfaces::getClosedNamedSurfaces() const
00477 {
00478     labelList named(getNamedSurfaces());
00479 
00480     labelList closed(named.size());
00481     label closedI = 0;
00482 
00483     forAll(named, i)
00484     {
00485         label surfI = named[i];
00486 
00487         if (allGeometry_[surfaces_[surfI]].hasVolumeType())
00488         {
00489             closed[closedI++] = surfI;
00490         }
00491     }
00492     closed.setSize(closedI);
00493 
00494     return closed;
00495 }
00496 
00497 
00498 // // Count number of triangles per surface region
00499 // Foam::labelList Foam::refinementSurfaces::countRegions(const triSurface& s)
00500 // {
00501 //     const geometricSurfacePatchList& regions = s.patches();
00502 // 
00503 //     labelList nTris(regions.size(), 0);
00504 // 
00505 //     forAll(s, triI)
00506 //     {
00507 //         nTris[s[triI].region()]++;
00508 //     }
00509 //     return nTris;
00510 // }
00511 
00512 
00513 // // Pre-calculate the refinement level for every element
00514 // void Foam::refinementSurfaces::wantedRefinementLevel
00515 // (
00516 //     const shellSurfaces& shells,
00517 //     const label surfI,
00518 //     const List<pointIndexHit>& info,    // Indices
00519 //     const pointField& ctrs,             // Representative coordinate
00520 //     labelList& minLevelField
00521 // ) const
00522 // {
00523 //     const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
00524 // 
00525 //     // Get per element the region
00526 //     labelList region;
00527 //     geom.getRegion(info, region);
00528 // 
00529 //     // Initialise fields to region wise minLevel
00530 //     minLevelField.setSize(ctrs.size());
00531 //     minLevelField = -1;
00532 // 
00533 //     forAll(minLevelField, i)
00534 //     {
00535 //         if (info[i].hit())
00536 //         {
00537 //             minLevelField[i] = minLevel(surfI, region[i]);
00538 //         }
00539 //     }
00540 // 
00541 //     // Find out if triangle inside shell with higher level
00542 //     // What level does shell want to refine fc to?
00543 //     labelList shellLevel;
00544 //     shells.findHigherLevel(ctrs, minLevelField, shellLevel);
00545 // 
00546 //     forAll(minLevelField, i)
00547 //     {
00548 //         minLevelField[i] = max(minLevelField[i], shellLevel[i]);
00549 //     }
00550 // }
00551 
00552 
00553 // Precalculate the refinement level for every element of the searchable
00554 // surface.
00555 void Foam::refinementSurfaces::setMinLevelFields
00556 (
00557     const shellSurfaces& shells
00558 )
00559 {
00560     forAll(surfaces_, surfI)
00561     {
00562         const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
00563 
00564         // Precalculation only makes sense if there are different regions
00565         // (so different refinement levels possible) and there are some
00566         // elements. Possibly should have 'enough' elements to have fine
00567         // enough resolution but for now just make sure we don't catch e.g.
00568         // searchableBox (size=6)
00569         if (geom.regions().size() > 1 && geom.globalSize() > 10)
00570         {
00571             // Representative local coordinates
00572             const pointField ctrs = geom.coordinates();
00573 
00574             labelList minLevelField(ctrs.size(), -1);
00575             {
00576                 // Get the element index in a roundabout way. Problem is e.g.
00577                 // distributed surface where local indices differ from global
00578                 // ones (needed for getRegion call)
00579                 List<pointIndexHit> info;
00580                 geom.findNearest
00581                 (
00582                     ctrs,
00583                     scalarField(ctrs.size(), sqr(GREAT)),
00584                     info
00585                 );
00586 
00587                 // Get per element the region
00588                 labelList region;
00589                 geom.getRegion(info, region);
00590 
00591                 // From the region get the surface-wise refinement level
00592                 forAll(minLevelField, i)
00593                 {
00594                     if (info[i].hit())
00595                     {
00596                         minLevelField[i] = minLevel(surfI, region[i]);
00597                     }
00598                 }
00599             }
00600 
00601             // Find out if triangle inside shell with higher level
00602             // What level does shell want to refine fc to?
00603             labelList shellLevel;
00604             shells.findHigherLevel(ctrs, minLevelField, shellLevel);
00605 
00606             forAll(minLevelField, i)
00607             {
00608                 minLevelField[i] = max(minLevelField[i], shellLevel[i]);
00609             }
00610 
00611             // Store minLevelField on surface
00612             const_cast<searchableSurface&>(geom).setField(minLevelField);
00613         }
00614     }
00615 }
00616 
00617 
00618 // Find intersections of edge. Return -1 or first surface with higher minLevel
00619 // number.
00620 void Foam::refinementSurfaces::findHigherIntersection
00621 (
00622     const pointField& start,
00623     const pointField& end,
00624     const labelList& currentLevel,   // current cell refinement level
00625 
00626     labelList& surfaces,
00627     labelList& surfaceLevel
00628 ) const
00629 {
00630     surfaces.setSize(start.size());
00631     surfaces = -1;
00632     surfaceLevel.setSize(start.size());
00633     surfaceLevel = -1;
00634 
00635     if (surfaces_.empty())
00636     {
00637         return;
00638     }
00639 
00640     if (surfaces_.size() == 1)
00641     {
00642         // Optimisation: single segmented surface. No need to duplicate
00643         // point storage.
00644 
00645         label surfI = 0;
00646 
00647         const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
00648 
00649         // Do intersection test
00650         List<pointIndexHit> intersectionInfo(start.size());
00651         geom.findLineAny(start, end, intersectionInfo);
00652 
00653         // See if a cached level field available
00654         labelList minLevelField;
00655         geom.getField(intersectionInfo, minLevelField);
00656         bool haveLevelField =
00657         (
00658             returnReduce(minLevelField.size(), sumOp<label>())
00659           > 0
00660         );
00661 
00662         if (!haveLevelField && geom.regions().size() == 1)
00663         {
00664             minLevelField = labelList
00665             (
00666                 intersectionInfo.size(),
00667                 minLevel(surfI, 0)
00668             );
00669             haveLevelField = true;
00670         }
00671 
00672         if (haveLevelField)
00673         {
00674             forAll(intersectionInfo, i)
00675             {
00676                 if
00677                 (
00678                     intersectionInfo[i].hit()
00679                  && minLevelField[i] > currentLevel[i]
00680                 )
00681                 {
00682                     surfaces[i] = surfI;    // index of surface
00683                     surfaceLevel[i] = minLevelField[i];
00684                 }
00685             }
00686             return;
00687         }
00688     }
00689 
00690 
00691 
00692     // Work arrays
00693     pointField p0(start);
00694     pointField p1(end);
00695     labelList intersectionToPoint(identity(start.size()));
00696     List<pointIndexHit> intersectionInfo(start.size());
00697 
00698     forAll(surfaces_, surfI)
00699     {
00700         const searchableSurface& geom = allGeometry_[surfaces_[surfI]];
00701 
00702         // Do intersection test
00703         geom.findLineAny(p0, p1, intersectionInfo);
00704 
00705         // See if a cached level field available
00706         labelList minLevelField;
00707         geom.getField(intersectionInfo, minLevelField);
00708 
00709         // Copy all hits into arguments, In-place compact misses.
00710         label missI = 0;
00711         forAll(intersectionInfo, i)
00712         {
00713             // Get the minLevel for the point
00714             label minLocalLevel = -1;
00715 
00716             if (intersectionInfo[i].hit())
00717             {
00718                 // Check if minLevelField for this surface.
00719                 if (minLevelField.size())
00720                 {
00721                     minLocalLevel = minLevelField[i];
00722                 }
00723                 else
00724                 {
00725                     // Use the min level for the surface instead. Assume
00726                     // single region 0.
00727                     minLocalLevel = minLevel(surfI, 0);
00728                 }
00729             }
00730 
00731 
00732             label pointI = intersectionToPoint[i];
00733 
00734             if (minLocalLevel > currentLevel[pointI])
00735             {
00736                 // Mark point for refinement
00737                 surfaces[pointI] = surfI;
00738                 surfaceLevel[pointI] = minLocalLevel;
00739             }
00740             else
00741             {
00742                 p0[missI] = start[pointI];
00743                 p1[missI] = end[pointI];
00744                 intersectionToPoint[missI] = pointI;
00745                 missI++;
00746             }
00747         }
00748 
00749         // All done? Note that this decision should be synchronised
00750         if (returnReduce(missI, sumOp<label>()) == 0)
00751         {
00752             break;
00753         }
00754 
00755         // Trim misses
00756         p0.setSize(missI);
00757         p1.setSize(missI);
00758         intersectionToPoint.setSize(missI);
00759         intersectionInfo.setSize(missI);
00760     }
00761 }
00762 
00763 
00764 void Foam::refinementSurfaces::findAllHigherIntersections
00765 (
00766     const pointField& start,
00767     const pointField& end,
00768     const labelList& currentLevel,   // current cell refinement level
00769 
00770     List<vectorList>& surfaceNormal,
00771     labelListList& surfaceLevel
00772 ) const
00773 {
00774     surfaceLevel.setSize(start.size());
00775     surfaceNormal.setSize(start.size());
00776 
00777     if (surfaces_.empty())
00778     {
00779         return;
00780     }
00781 
00782     // Work arrays
00783     List<List<pointIndexHit> > hitInfo;
00784     labelList pRegions;
00785     vectorField pNormals;
00786 
00787     forAll(surfaces_, surfI)
00788     {
00789         allGeometry_[surfaces_[surfI]].findLineAll(start, end, hitInfo);
00790 
00791         // Repack hits for surface into flat list
00792         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00793         // To avoid overhead of calling getRegion for every point
00794 
00795         label n = 0;
00796         forAll(hitInfo, pointI)
00797         {
00798             n += hitInfo[pointI].size();
00799         }
00800 
00801         List<pointIndexHit> surfInfo(n);
00802         labelList pointMap(n);
00803         n = 0;
00804 
00805         forAll(hitInfo, pointI)
00806         {
00807             const List<pointIndexHit>& pHits = hitInfo[pointI];
00808 
00809             forAll(pHits, i)
00810             {
00811                 surfInfo[n] = pHits[i];
00812                 pointMap[n] = pointI;
00813                 n++;
00814             }
00815         }
00816 
00817         labelList surfRegion(n);
00818         vectorField surfNormal(n);
00819         allGeometry_[surfaces_[surfI]].getRegion(surfInfo, surfRegion);
00820         allGeometry_[surfaces_[surfI]].getNormal(surfInfo, surfNormal);
00821 
00822         surfInfo.clear();
00823 
00824 
00825         // Extract back into pointwise
00826         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
00827 
00828         forAll(surfRegion, i)
00829         {
00830             label region = globalRegion(surfI, surfRegion[i]);
00831             label pointI = pointMap[i];
00832 
00833             if (maxLevel_[region] > currentLevel[pointI])
00834             {
00835                 // Append to pointI info
00836                 label sz = surfaceNormal[pointI].size();
00837                 surfaceNormal[pointI].setSize(sz+1);
00838                 surfaceNormal[pointI][sz] = surfNormal[i];
00839 
00840                 surfaceLevel[pointI].setSize(sz+1);
00841                 surfaceLevel[pointI][sz] = maxLevel_[region];
00842             }
00843         }
00844     }
00845 }
00846 
00847 
00848 void Foam::refinementSurfaces::findNearestIntersection
00849 (
00850     const labelList& surfacesToTest,
00851     const pointField& start,
00852     const pointField& end,
00853 
00854     labelList& surface1,
00855     List<pointIndexHit>& hit1,
00856     labelList& region1,
00857     labelList& surface2,
00858     List<pointIndexHit>& hit2,
00859     labelList& region2
00860 ) const
00861 {
00862     // 1. intersection from start to end
00863     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00864 
00865     // Initialize arguments
00866     surface1.setSize(start.size());
00867     surface1 = -1;
00868     hit1.setSize(start.size());
00869     region1.setSize(start.size());
00870 
00871     // Current end of segment to test.
00872     pointField nearest(end);
00873     // Work array
00874     List<pointIndexHit> nearestInfo(start.size());
00875     labelList region;
00876 
00877     forAll(surfacesToTest, testI)
00878     {
00879         label surfI = surfacesToTest[testI];
00880 
00881         // See if any intersection between start and current nearest
00882         allGeometry_[surfaces_[surfI]].findLine
00883         (
00884             start,
00885             nearest,
00886             nearestInfo
00887         );
00888         allGeometry_[surfaces_[surfI]].getRegion
00889         (
00890             nearestInfo,
00891             region
00892         );
00893 
00894         forAll(nearestInfo, pointI)
00895         {
00896             if (nearestInfo[pointI].hit())
00897             {
00898                 hit1[pointI] = nearestInfo[pointI];
00899                 surface1[pointI] = surfI;
00900                 region1[pointI] = region[pointI];
00901                 nearest[pointI] = hit1[pointI].hitPoint();
00902             }
00903         }
00904     }
00905 
00906 
00907     // 2. intersection from end to last intersection
00908     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00909 
00910     // Find the nearest intersection from end to start. Note that we initialize
00911     // to the first intersection (if any).
00912     surface2 = surface1;
00913     hit2 = hit1;
00914     region2 = region1;
00915 
00916     // Set current end of segment to test.
00917     forAll(nearest, pointI)
00918     {
00919         if (hit1[pointI].hit())
00920         {
00921             nearest[pointI] = hit1[pointI].hitPoint();
00922         }
00923         else
00924         {
00925             // Disable testing by setting to end.
00926             nearest[pointI] = end[pointI];
00927         }
00928     }
00929 
00930     forAll(surfacesToTest, testI)
00931     {
00932         label surfI = surfacesToTest[testI];
00933 
00934         // See if any intersection between end and current nearest
00935         allGeometry_[surfaces_[surfI]].findLine
00936         (
00937             end,
00938             nearest,
00939             nearestInfo
00940         );
00941         allGeometry_[surfaces_[surfI]].getRegion
00942         (
00943             nearestInfo,
00944             region
00945         );
00946 
00947         forAll(nearestInfo, pointI)
00948         {
00949             if (nearestInfo[pointI].hit())
00950             {
00951                 hit2[pointI] = nearestInfo[pointI];
00952                 surface2[pointI] = surfI;
00953                 region2[pointI] = region[pointI];
00954                 nearest[pointI] = hit2[pointI].hitPoint();
00955             }
00956         }
00957     }
00958 
00959 
00960     // Make sure that if hit1 has hit something, hit2 will have at least the
00961     // same point (due to tolerances it might miss its end point)
00962     forAll(hit1, pointI)
00963     {
00964         if (hit1[pointI].hit() && !hit2[pointI].hit())
00965         {
00966             hit2[pointI] = hit1[pointI];
00967             surface2[pointI] = surface1[pointI];
00968             region2[pointI] = region1[pointI];
00969         }
00970     }
00971 }
00972 
00973 
00974 void Foam::refinementSurfaces::findAnyIntersection
00975 (
00976     const pointField& start,
00977     const pointField& end,
00978 
00979     labelList& hitSurface,
00980     List<pointIndexHit>& hitInfo
00981 ) const
00982 {
00983     searchableSurfacesQueries::findAnyIntersection
00984     (
00985         allGeometry_,
00986         surfaces_,
00987         start,
00988         end,
00989         hitSurface,
00990         hitInfo
00991     );
00992 }
00993 
00994 
00995 void Foam::refinementSurfaces::findNearest
00996 (
00997     const labelList& surfacesToTest,
00998     const pointField& samples,
00999     const  scalarField& nearestDistSqr,
01000     labelList& hitSurface,
01001     List<pointIndexHit>& hitInfo
01002 ) const
01003 {
01004     labelList geometries(UIndirectList<label>(surfaces_, surfacesToTest));
01005 
01006     // Do the tests. Note that findNearest returns index in geometries.
01007     searchableSurfacesQueries::findNearest
01008     (
01009         allGeometry_,
01010         geometries,
01011         samples,
01012         nearestDistSqr,
01013         hitSurface,
01014         hitInfo
01015     );
01016 
01017     // Rework the hitSurface to be surface (i.e. index into surfaces_)
01018     forAll(hitSurface, pointI)
01019     {
01020         if (hitSurface[pointI] != -1)
01021         {
01022             hitSurface[pointI] = surfacesToTest[hitSurface[pointI]];
01023         }
01024     }
01025 }
01026 
01027 
01028 void Foam::refinementSurfaces::findNearestRegion
01029 (
01030     const labelList& surfacesToTest,
01031     const pointField& samples,
01032     const  scalarField& nearestDistSqr,
01033     labelList& hitSurface,
01034     labelList& hitRegion
01035 ) const
01036 {
01037     labelList geometries(UIndirectList<label>(surfaces_, surfacesToTest));
01038 
01039     // Do the tests. Note that findNearest returns index in geometries.
01040     List<pointIndexHit> hitInfo;
01041     searchableSurfacesQueries::findNearest
01042     (
01043         allGeometry_,
01044         geometries,
01045         samples,
01046         nearestDistSqr,
01047         hitSurface,
01048         hitInfo
01049     );
01050 
01051     // Rework the hitSurface to be surface (i.e. index into surfaces_)
01052     forAll(hitSurface, pointI)
01053     {
01054         if (hitSurface[pointI] != -1)
01055         {
01056             hitSurface[pointI] = surfacesToTest[hitSurface[pointI]];
01057         }
01058     }
01059 
01060     // Collect the region
01061     hitRegion.setSize(hitSurface.size());
01062     hitRegion = -1;
01063 
01064     forAll(surfacesToTest, i)
01065     {
01066         label surfI = surfacesToTest[i];
01067 
01068         // Collect hits for surfI
01069         const labelList localIndices(findIndices(hitSurface, surfI));
01070 
01071         List<pointIndexHit> localHits
01072         (
01073             UIndirectList<pointIndexHit>
01074             (
01075                 hitInfo,
01076                 localIndices
01077             )
01078         );
01079 
01080         labelList localRegion;
01081         allGeometry_[surfaces_[surfI]].getRegion(localHits, localRegion);
01082 
01083         forAll(localIndices, i)
01084         {
01085             hitRegion[localIndices[i]] = localRegion[i];
01086         }
01087     }
01088 }
01089 
01090 
01093 //Foam::label Foam::refinementSurfaces::findHighestIntersection
01094 //(
01095 //    const point& start,
01096 //    const point& end,
01097 //    const label currentLevel,   // current cell refinement level
01098 //
01099 //    pointIndexHit& maxHit
01100 //) const
01101 //{
01102 //    // surface with highest maxlevel
01103 //    label maxSurface = -1;
01104 //    // maxLevel of maxSurface
01105 //    label maxLevel = currentLevel;
01106 //
01107 //    forAll(*this, surfI)
01108 //    {
01109 //        pointIndexHit hit = operator[](surfI).findLineAny(start, end);
01110 //
01111 //        if (hit.hit())
01112 //        {
01113 //            const triSurface& s = operator[](surfI);
01114 //
01115 //            label region = globalRegion(surfI, s[hit.index()].region());
01116 //
01117 //            if (maxLevel_[region] > maxLevel)
01118 //            {
01119 //                maxSurface = surfI;
01120 //                maxLevel = maxLevel_[region];
01121 //                maxHit = hit;
01122 //            }
01123 //        }
01124 //    }
01125 //
01126 //    if (maxSurface == -1)
01127 //    {
01128 //        // maxLevel unchanged. No interesting surface hit.
01129 //        maxHit.setMiss();
01130 //    }
01131 //
01132 //    return maxSurface;
01133 //}
01134 
01135 
01136 void Foam::refinementSurfaces::findInside
01137 (
01138     const labelList& testSurfaces,
01139     const pointField& pt,
01140     labelList& insideSurfaces
01141 ) const
01142 {
01143     insideSurfaces.setSize(pt.size());
01144     insideSurfaces = -1;
01145 
01146     forAll(testSurfaces, i)
01147     {
01148         label surfI = testSurfaces[i];
01149 
01150         if (allGeometry_[surfaces_[surfI]].hasVolumeType())
01151         {
01152             List<searchableSurface::volumeType> volType;
01153             allGeometry_[surfaces_[surfI]].getVolumeType(pt, volType);
01154 
01155             forAll(volType, pointI)
01156             {
01157                 if (insideSurfaces[pointI] == -1)
01158                 {
01159                     if
01160                     (
01161                         (
01162                             volType[pointI] == triSurfaceMesh::INSIDE
01163                          && zoneInside_[surfI]
01164                         )
01165                      || (
01166                             volType[pointI] == triSurfaceMesh::OUTSIDE
01167                          && !zoneInside_[surfI]
01168                         )
01169                     )
01170                     {
01171                         insideSurfaces[pointI] = surfI;
01172                     }
01173                 }
01174             }
01175         }
01176     }
01177 }
01178 
01179 
01180 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines