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

searchableSurfaceCollection.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 "searchableSurfaceCollection.H"
00027 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00028 #include <OpenFOAM/SortableList.H>
00029 #include <OpenFOAM/Time.H>
00030 #include <OpenFOAM/ListOps.H>
00031 
00032 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00033 
00034 namespace Foam
00035 {
00036 
00037 defineTypeNameAndDebug(searchableSurfaceCollection, 0);
00038 addToRunTimeSelectionTable
00039 (
00040     searchableSurface,
00041     searchableSurfaceCollection,
00042     dict
00043 );
00044 
00045 }
00046 
00047 
00048 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00049 
00050 void Foam::searchableSurfaceCollection::findNearest
00051 (
00052     const pointField& samples,
00053     scalarField& minDistSqr,
00054     List<pointIndexHit>& nearestInfo,
00055     labelList& nearestSurf
00056 ) const
00057 {
00058     // Initialise
00059     nearestInfo.setSize(samples.size());
00060     nearestInfo = pointIndexHit();
00061     nearestSurf.setSize(samples.size());
00062     nearestSurf = -1;
00063 
00064     List<pointIndexHit> hitInfo(samples.size());
00065 
00066     const scalarField localMinDistSqr(samples.size(), GREAT);
00067 
00068     forAll(subGeom_, surfI)
00069     {
00070         subGeom_[surfI].findNearest
00071         (
00072             cmptDivide  // Transform then divide
00073             (
00074                 transform_[surfI].localPosition(samples),
00075                 scale_[surfI]
00076             ),
00077             localMinDistSqr,
00078             hitInfo
00079         );
00080 
00081         forAll(hitInfo, pointI)
00082         {
00083             if (hitInfo[pointI].hit())
00084             {
00085                 // Rework back into global coordinate sys. Multiply then
00086                 // transform
00087                 point globalPt = transform_[surfI].globalPosition
00088                 (
00089                     cmptMultiply
00090                     (
00091                         hitInfo[pointI].rawPoint(),
00092                         scale_[surfI]
00093                     )
00094                 );
00095 
00096                 scalar distSqr = magSqr(globalPt - samples[pointI]);
00097 
00098                 if (distSqr < minDistSqr[pointI])
00099                 {
00100                     minDistSqr[pointI] = distSqr;
00101                     nearestInfo[pointI].setPoint(globalPt);
00102                     nearestInfo[pointI].setHit();
00103                     nearestInfo[pointI].setIndex
00104                     (
00105                         hitInfo[pointI].index()
00106                       + indexOffset_[surfI]
00107                     );
00108                     nearestSurf[pointI] = surfI;
00109                 }
00110             }
00111         }
00112     }
00113 }
00114 
00115 
00116 // Sort hits into per-surface bins. Misses are rejected. Maintains map back
00117 // to position
00118 void Foam::searchableSurfaceCollection::sortHits
00119 (
00120     const List<pointIndexHit>& info,
00121     List<List<pointIndexHit> >& surfInfo,
00122     labelListList& infoMap
00123 ) const
00124 {
00125     // Count hits per surface.
00126     labelList nHits(subGeom_.size(), 0);
00127 
00128     forAll(info, pointI)
00129     {
00130         if (info[pointI].hit())
00131         {
00132             label index = info[pointI].index();
00133             label surfI = findLower(indexOffset_, index+1);
00134             nHits[surfI]++;
00135         }
00136     }
00137 
00138     // Per surface the hit
00139     surfInfo.setSize(subGeom_.size());
00140     // Per surface the original position
00141     infoMap.setSize(subGeom_.size());
00142 
00143     forAll(surfInfo, surfI)
00144     {
00145         surfInfo[surfI].setSize(nHits[surfI]);
00146         infoMap[surfI].setSize(nHits[surfI]);
00147     }
00148     nHits = 0;
00149 
00150     forAll(info, pointI)
00151     {
00152         if (info[pointI].hit())
00153         {
00154             label index = info[pointI].index();
00155             label surfI = findLower(indexOffset_, index+1);
00156 
00157             // Store for correct surface and adapt indices back to local
00158             // ones
00159             label localI = nHits[surfI]++;
00160             surfInfo[surfI][localI] = pointIndexHit
00161             (
00162                 info[pointI].hit(),
00163                 info[pointI].rawPoint(),
00164                 index-indexOffset_[surfI]
00165             );
00166             infoMap[surfI][localI] = pointI;
00167         }
00168     }
00169 }
00170 
00171 
00172 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00173 
00174 Foam::searchableSurfaceCollection::searchableSurfaceCollection
00175 (
00176     const IOobject& io,
00177     const dictionary& dict
00178 )
00179 :
00180     searchableSurface(io),
00181     instance_(dict.size()),
00182     scale_(dict.size()),
00183     transform_(dict.size()),
00184     subGeom_(dict.size()),
00185     mergeSubRegions_(dict.lookup("mergeSubRegions")),
00186     indexOffset_(dict.size()+1)
00187 {
00188     Info<< "SearchableCollection : " << name() << endl;
00189 
00190     label surfI = 0;
00191     label startIndex = 0;
00192     forAllConstIter(dictionary, dict, iter)
00193     {
00194         if (dict.isDict(iter().keyword()))
00195         {
00196             instance_[surfI] = iter().keyword();
00197 
00198             const dictionary& subDict = dict.subDict(instance_[surfI]);
00199 
00200             scale_[surfI] = subDict.lookup("scale");
00201             transform_.set
00202             (
00203                 surfI,
00204                 coordinateSystem::New
00205                 (
00206                     "",
00207                     subDict.subDict("transform")
00208                 )
00209             );
00210 
00211             const word subGeomName(subDict.lookup("surface"));
00212             //Pout<< "Trying to find " << subGeomName << endl;
00213 
00214             const searchableSurface& s =
00215                 io.db().lookupObject<searchableSurface>(subGeomName);
00216 
00217             // I don't know yet how to handle the globalSize combined with
00218             // regionOffset. Would cause non-consecutive indices locally
00219             // if all indices offset by globalSize() of the local region...
00220             if (s.size() != s.globalSize())
00221             {
00222                 FatalErrorIn
00223                 (
00224                     "searchableSurfaceCollection::searchableSurfaceCollection"
00225                     "(const IOobject&, const dictionary&)"
00226                 )   << "Cannot use a distributed surface in a collection."
00227                     << exit(FatalError);
00228             }
00229 
00230             subGeom_.set(surfI, &const_cast<searchableSurface&>(s));
00231 
00232             indexOffset_[surfI] = startIndex;
00233             startIndex += subGeom_[surfI].size();
00234 
00235             Info<< "    instance : " << instance_[surfI] << endl;
00236             Info<< "    surface  : " << s.name() << endl;
00237             Info<< "    scale    : " << scale_[surfI] << endl;
00238             Info<< "    coordsys : " << transform_[surfI] << endl;
00239 
00240             surfI++;
00241         }
00242     }
00243     indexOffset_[surfI] = startIndex;
00244 
00245     instance_.setSize(surfI);
00246     scale_.setSize(surfI);
00247     transform_.setSize(surfI);
00248     subGeom_.setSize(surfI);
00249     indexOffset_.setSize(surfI+1);
00250 }
00251 
00252 
00253 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00254 
00255 Foam::searchableSurfaceCollection::~searchableSurfaceCollection()
00256 {}
00257 
00258 
00259 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00260 
00261 const Foam::wordList& Foam::searchableSurfaceCollection::regions() const
00262 {
00263     if (regions_.size() == 0)
00264     {
00265         regionOffset_.setSize(subGeom_.size());
00266 
00267         DynamicList<word> allRegions;
00268         forAll(subGeom_, surfI)
00269         {
00270             regionOffset_[surfI] = allRegions.size();
00271 
00272             if (mergeSubRegions_)
00273             {
00274                 // Single name regardless how many regions subsurface has
00275                 allRegions.append(instance_[surfI] + "_" + Foam::name(surfI));
00276             }
00277             else
00278             {
00279                 const wordList& subRegions = subGeom_[surfI].regions();
00280 
00281                 forAll(subRegions, i)
00282                 {
00283                     allRegions.append(instance_[surfI] + "_" + subRegions[i]);
00284                 }
00285             }
00286         }
00287         regions_.transfer(allRegions.shrink());
00288     }
00289     return regions_;
00290 }
00291 
00292 
00293 Foam::label Foam::searchableSurfaceCollection::size() const
00294 {
00295     return indexOffset_[indexOffset_.size()-1];
00296 }
00297 
00298 
00299 Foam::pointField Foam::searchableSurfaceCollection::coordinates() const
00300 {
00301     // Get overall size
00302     pointField coords(size());
00303 
00304     // Append individual coordinates
00305     label coordI = 0;
00306 
00307     forAll(subGeom_, surfI)
00308     {
00309         const pointField subCoords = subGeom_[surfI].coordinates();
00310 
00311         forAll(subCoords, i)
00312         {
00313             coords[coordI++] = transform_[surfI].globalPosition
00314             (
00315                 cmptMultiply
00316                 (
00317                     subCoords[i],
00318                     scale_[surfI]
00319                 )
00320             );
00321         }
00322     }
00323 
00324     return coords;
00325 }
00326 
00327 
00328 void Foam::searchableSurfaceCollection::findNearest
00329 (
00330     const pointField& samples,
00331     const scalarField& nearestDistSqr,
00332     List<pointIndexHit>& nearestInfo
00333 ) const
00334 {
00335     // How to scale distance?
00336     scalarField minDistSqr(nearestDistSqr);
00337 
00338     labelList nearestSurf;
00339     findNearest
00340     (
00341         samples,
00342         minDistSqr,
00343         nearestInfo,
00344         nearestSurf
00345     );
00346 }
00347 
00348 
00349 void Foam::searchableSurfaceCollection::findLine
00350 (
00351     const pointField& start,
00352     const pointField& end,
00353     List<pointIndexHit>& info
00354 ) const
00355 {
00356     info.setSize(start.size());
00357     info = pointIndexHit();
00358 
00359     // Current nearest (to start) intersection
00360     pointField nearest(end);
00361 
00362     List<pointIndexHit> hitInfo(start.size());
00363 
00364     forAll(subGeom_, surfI)
00365     {
00366         // Starting point
00367         tmp<pointField> e0 = cmptDivide
00368         (
00369             transform_[surfI].localPosition
00370             (
00371                 start
00372             ),
00373             scale_[surfI]
00374         );
00375 
00376         // Current best end point
00377         tmp<pointField> e1 = cmptDivide
00378         (
00379             transform_[surfI].localPosition
00380             (
00381                 nearest
00382             ),
00383             scale_[surfI]
00384         );
00385 
00386         subGeom_[surfI].findLine(e0, e1, hitInfo);
00387 
00388         forAll(hitInfo, pointI)
00389         {
00390             if (hitInfo[pointI].hit())
00391             {
00392                 // Transform back to global coordinate sys.
00393                 nearest[pointI] = transform_[surfI].globalPosition
00394                 (
00395                     cmptMultiply
00396                     (
00397                         hitInfo[pointI].rawPoint(),
00398                         scale_[surfI]
00399                     )
00400                 );
00401                 info[pointI] = hitInfo[pointI];
00402                 info[pointI].rawPoint() = nearest[pointI];
00403                 info[pointI].setIndex
00404                 (
00405                     hitInfo[pointI].index()
00406                   + indexOffset_[surfI]
00407                 );
00408             }
00409         }
00410     }
00411 
00412 
00413     // Debug check
00414     if (false)
00415     {
00416         forAll(info, pointI)
00417         {
00418             if (info[pointI].hit())
00419             {
00420                 vector n(end[pointI] - start[pointI]);
00421                 scalar magN = mag(n);
00422 
00423                 if (magN > SMALL)
00424                 {
00425                     n /= mag(n);
00426 
00427                     scalar s = ((info[pointI].rawPoint()-start[pointI])&n);
00428 
00429                     if (s < 0 || s > 1)
00430                     {
00431                         FatalErrorIn
00432                         (
00433                             "searchableSurfaceCollection::findLine(..)"
00434                         )   << "point:" << info[pointI]
00435                             << " s:" << s
00436                             << " outside vector "
00437                             << " start:" << start[pointI]
00438                             << " end:" << end[pointI]
00439                             << abort(FatalError);
00440                     }
00441                 }
00442             }
00443         }
00444     }
00445 }
00446 
00447 
00448 void Foam::searchableSurfaceCollection::findLineAny
00449 (
00450     const pointField& start,
00451     const pointField& end,
00452     List<pointIndexHit>& info
00453 ) const
00454 {
00455     // To be done ...
00456     findLine(start, end, info);
00457 }
00458 
00459 
00460 void Foam::searchableSurfaceCollection::findLineAll
00461 (
00462     const pointField& start,
00463     const pointField& end,
00464     List<List<pointIndexHit> >& info
00465 ) const
00466 {
00467     // To be done. Assume for now only one intersection.
00468     List<pointIndexHit> nearestInfo;
00469     findLine(start, end, nearestInfo);
00470 
00471     info.setSize(start.size());
00472     forAll(info, pointI)
00473     {
00474         if (nearestInfo[pointI].hit())
00475         {
00476             info[pointI].setSize(1);
00477             info[pointI][0] = nearestInfo[pointI];
00478         }
00479         else
00480         {
00481             info[pointI].clear();
00482         }
00483     }
00484 }
00485 
00486 
00487 void Foam::searchableSurfaceCollection::getRegion
00488 (
00489     const List<pointIndexHit>& info,
00490     labelList& region
00491 ) const
00492 {
00493     if (subGeom_.size() == 0)
00494     {}
00495     else if (subGeom_.size() == 1)
00496     {
00497         if (mergeSubRegions_)
00498         {
00499             region.setSize(info.size());
00500             region = regionOffset_[0];
00501         }
00502         else
00503         {
00504             subGeom_[0].getRegion(info, region);
00505         }
00506     }
00507     else
00508     {
00509         // Multiple surfaces. Sort by surface.
00510 
00511         // Per surface the hit
00512         List<List<pointIndexHit> > surfInfo;
00513         // Per surface the original position
00514         List<List<label> > infoMap;
00515         sortHits(info, surfInfo, infoMap);
00516 
00517         region.setSize(info.size());
00518         region = -1;
00519 
00520         // Do region tests
00521 
00522         if (mergeSubRegions_)
00523         {
00524             // Actually no need for surfInfo. Just take region for surface.
00525             forAll(infoMap, surfI)
00526             {
00527                 const labelList& map = infoMap[surfI];
00528                 forAll(map, i)
00529                 {
00530                     region[map[i]] = regionOffset_[surfI];
00531                 }
00532             }
00533         }
00534         else
00535         {
00536             forAll(infoMap, surfI)
00537             {
00538                 labelList surfRegion;
00539                 subGeom_[surfI].getRegion(surfInfo[surfI], surfRegion);
00540 
00541                 const labelList& map = infoMap[surfI];
00542                 forAll(map, i)
00543                 {
00544                     region[map[i]] = regionOffset_[surfI] + surfRegion[i];
00545                 }
00546             }
00547         }
00548     }
00549 }
00550 
00551 
00552 void Foam::searchableSurfaceCollection::getNormal
00553 (
00554     const List<pointIndexHit>& info,
00555     vectorField& normal
00556 ) const
00557 {
00558     if (subGeom_.size() == 0)
00559     {}
00560     else if (subGeom_.size() == 1)
00561     {
00562         subGeom_[0].getNormal(info, normal);
00563     }
00564     else
00565     {
00566         // Multiple surfaces. Sort by surface.
00567 
00568         // Per surface the hit
00569         List<List<pointIndexHit> > surfInfo;
00570         // Per surface the original position
00571         List<List<label> > infoMap;
00572         sortHits(info, surfInfo, infoMap);
00573 
00574         normal.setSize(info.size());
00575 
00576         // Do region tests
00577         forAll(surfInfo, surfI)
00578         {
00579             vectorField surfNormal;
00580             subGeom_[surfI].getNormal(surfInfo[surfI], surfNormal);
00581 
00582             const labelList& map = infoMap[surfI];
00583             forAll(map, i)
00584             {
00585                 normal[map[i]] = surfNormal[i];
00586             }
00587         }
00588     }
00589 }
00590 
00591 
00592 void Foam::searchableSurfaceCollection::getVolumeType
00593 (
00594     const pointField& points,
00595     List<volumeType>& volType
00596 ) const
00597 {
00598     FatalErrorIn
00599     (
00600         "searchableSurfaceCollection::getVolumeType(const pointField&"
00601         ", List<volumeType>&) const"
00602     )   << "Volume type not supported for collection."
00603         << exit(FatalError);
00604 }
00605 
00606 
00607 void Foam::searchableSurfaceCollection::distribute
00608 (
00609     const List<treeBoundBox>& bbs,
00610     const bool keepNonLocal,
00611     autoPtr<mapDistribute>& faceMap,
00612     autoPtr<mapDistribute>& pointMap
00613 )
00614 {
00615     forAll(subGeom_, surfI)
00616     {
00617         // Note:Tranform the bounding boxes? Something like
00618         // pointField bbPoints =
00619         // cmptDivide
00620         // (
00621         //     transform_[surfI].localPosition
00622         //     (
00623         //         bbs[i].points()
00624         //     ),
00625         //     scale_[surfI]
00626         // );
00627         // treeBoundBox newBb(bbPoints);
00628 
00629         // Note: what to do with faceMap, pointMap from multiple surfaces?
00630         subGeom_[surfI].distribute
00631         (
00632             bbs,
00633             keepNonLocal,
00634             faceMap,
00635             pointMap
00636         );
00637     }
00638 }
00639 
00640 
00641 void Foam::searchableSurfaceCollection::setField(const labelList& values)
00642 {
00643     forAll(subGeom_, surfI)
00644     {
00645         subGeom_[surfI].setField
00646         (
00647             static_cast<const labelList&>
00648             (
00649                 SubList<label>
00650                 (
00651                     values,
00652                     subGeom_[surfI].size(),
00653                     indexOffset_[surfI]
00654                 )
00655             )
00656         );
00657     }
00658 }
00659 
00660 
00661 void Foam::searchableSurfaceCollection::getField
00662 (
00663     const List<pointIndexHit>& info,
00664     labelList& values
00665 ) const
00666 {
00667     if (subGeom_.size() == 0)
00668     {}
00669     else if (subGeom_.size() == 1)
00670     {
00671         subGeom_[0].getField(info, values);
00672     }
00673     else
00674     {
00675         // Multiple surfaces. Sort by surface.
00676 
00677         // Per surface the hit
00678         List<List<pointIndexHit> > surfInfo;
00679         // Per surface the original position
00680         List<List<label> > infoMap;
00681         sortHits(info, surfInfo, infoMap);
00682 
00683         // Do surface tests
00684         forAll(surfInfo, surfI)
00685         {
00686             labelList surfValues;
00687             subGeom_[surfI].getField(surfInfo[surfI], surfValues);
00688 
00689             if (surfValues.size())
00690             {
00691                 // Size values only when we have a surface that supports it.
00692                 values.setSize(info.size());
00693 
00694                 const labelList& map = infoMap[surfI];
00695                 forAll(map, i)
00696                 {
00697                     values[map[i]] = surfValues[i];
00698                 }
00699             }
00700         }
00701     }
00702 }
00703 
00704 
00705 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines