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

uniformSet.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 "uniformSet.H"
00027 #include <meshTools/meshSearch.H>
00028 #include <OpenFOAM/DynamicList.H>
00029 #include <OpenFOAM/polyMesh.H>
00030 
00031 #include <lagrangian/Cloud.H>
00032 #include <lagrangian/passiveParticle.H>
00033 #include <OpenFOAM/IDLList.H>
00034 
00035 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00036 
00037 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00038 
00039 namespace Foam
00040 {
00041     defineTypeNameAndDebug(uniformSet, 0);
00042     addToRunTimeSelectionTable(sampledSet, uniformSet, word);
00043 }
00044 
00045 
00046 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00047 
00048 // Finds along line (samplePt + t * offset) next sample beyond or equal to
00049 // currentPt.
00050 // Updates samplePt, sampleI
00051 bool Foam::uniformSet::nextSample
00052 (
00053     const point& currentPt,
00054     const vector& offset,
00055     const scalar smallDist,
00056     point& samplePt,
00057     label& sampleI
00058 ) const
00059 {
00060     bool pointFound = false;
00061 
00062     const vector normOffset = offset/mag(offset);
00063 
00064     samplePt += offset;
00065     sampleI++;
00066 
00067     for(; sampleI < nPoints_; sampleI++)
00068     {
00069         scalar s = (samplePt - currentPt) & normOffset;
00070 
00071         if (s > -smallDist)
00072         {
00073             // samplePt is close to or beyond currentPt -> use it
00074             pointFound = true;
00075 
00076             break;
00077         }
00078         samplePt += offset;
00079     }
00080 
00081     return pointFound;
00082 }
00083 
00084 
00085 // Sample singly connected segment. Returns false if end_ reached.
00086 bool Foam::uniformSet::trackToBoundary
00087 (
00088     Particle<passiveParticle>& singleParticle,
00089     point& samplePt,
00090     label& sampleI,
00091     DynamicList<point>& samplingPts,
00092     DynamicList<label>& samplingCells,
00093     DynamicList<label>& samplingFaces,
00094     DynamicList<scalar>& samplingCurveDist
00095 ) const
00096 {
00097     // distance vector between sampling points
00098     const vector offset = (end_ - start_)/(nPoints_ - 1);
00099     const vector smallVec = tol*offset;
00100     const scalar smallDist = mag(smallVec);
00101 
00102     // Alias
00103     const point& trackPt = singleParticle.position();
00104 
00105     while(true)
00106     {
00107         // Find next samplePt on/after trackPt. Update samplePt, sampleI
00108         if (!nextSample(trackPt, offset, smallDist, samplePt, sampleI))
00109         {
00110             // no more samples.
00111             if (debug)
00112             {
00113                 Info<< "trackToBoundary : Reached end : samplePt now:"
00114                     << samplePt << "  sampleI now:" << sampleI << endl;
00115             }
00116             return false;
00117         }
00118 
00119         if (mag(samplePt - trackPt) < smallDist)
00120         {
00121             // trackPt corresponds with samplePt. Store and use next samplePt
00122             if (debug)
00123             {
00124                 Info<< "trackToBoundary : samplePt corresponds to trackPt : "
00125                     << "  trackPt:" << trackPt << "  samplePt:" << samplePt
00126                     << endl;
00127             }
00128 
00129             samplingPts.append(trackPt);
00130             samplingCells.append(singleParticle.cell());
00131             samplingFaces.append(-1);
00132             samplingCurveDist.append(mag(trackPt - start_));
00133 
00134             // go to next samplePt
00135             if (!nextSample(trackPt, offset, smallDist, samplePt, sampleI))
00136             {
00137                 // no more samples.
00138                 if (debug)
00139                 {
00140                     Info<< "trackToBoundary : Reached end : "
00141                         << "  samplePt now:" << samplePt
00142                         << "  sampleI now:" << sampleI
00143                         << endl;
00144                 }
00145 
00146                 return false;
00147             }
00148         }
00149 
00150 
00151         if (debug)
00152         {
00153             Info<< "Searching along trajectory from "
00154                 << "  trackPt:" << trackPt
00155                 << "  trackCellI:" << singleParticle.cell()
00156                 << "  to:" << samplePt << endl;
00157         }
00158 
00159         point oldPos = trackPt;
00160         label facei = -1;
00161         do
00162         {
00163             singleParticle.stepFraction() = 0;
00164             singleParticle.track(samplePt);
00165 
00166             if (debug)
00167             {
00168                 Info<< "Result of tracking "
00169                     << "  trackPt:" << trackPt
00170                     << "  trackCellI:" << singleParticle.cell()
00171                     << "  trackFaceI:" << singleParticle.face()
00172                     << "  onBoundary:" << singleParticle.onBoundary()
00173                     << "  samplePt:" << samplePt
00174                     << "  smallDist:" << smallDist
00175                     << endl;
00176             }
00177         }
00178         while
00179         (
00180             !singleParticle.onBoundary()
00181          && (mag(trackPt - oldPos) < smallDist)
00182         );
00183 
00184         if (singleParticle.onBoundary())
00185         {
00186             //Info<< "trackToBoundary : reached boundary" << endl;
00187             if (mag(trackPt - samplePt) < smallDist)
00188             {
00189                 //Info<< "trackToBoundary : boundary is also sampling point"
00190                 //    << endl;
00191                 // Reached samplePt on boundary
00192                 samplingPts.append(trackPt);
00193                 samplingCells.append(singleParticle.cell());
00194                 samplingFaces.append(facei);
00195                 samplingCurveDist.append(mag(trackPt - start_));
00196             }
00197 
00198             return true;
00199         }
00200 
00201         //Info<< "trackToBoundary : reached internal sampling point" << endl;
00202         // Reached samplePt in cell or on internal face
00203         samplingPts.append(trackPt);
00204         samplingCells.append(singleParticle.cell());
00205         samplingFaces.append(-1);
00206         samplingCurveDist.append(mag(trackPt - start_));
00207 
00208         // go to next samplePt
00209     }
00210 }
00211 
00212 
00213 void Foam::uniformSet::calcSamples
00214 (
00215     DynamicList<point>& samplingPts,
00216     DynamicList<label>& samplingCells,
00217     DynamicList<label>& samplingFaces,
00218     DynamicList<label>& samplingSegments,
00219     DynamicList<scalar>& samplingCurveDist
00220 ) const
00221 {
00222     // distance vector between sampling points
00223     if ((nPoints_ < 2) || (mag(end_ - start_) < SMALL))
00224     {
00225         FatalErrorIn("uniformSet::calcSamples()")
00226             << "Incorrect sample specification. Either too few points or"
00227             << " start equals end point." << endl
00228             << "nPoints:" << nPoints_
00229             << "  start:" << start_
00230             << "  end:" << end_
00231             << exit(FatalError);
00232     }
00233 
00234     const vector offset = (end_ - start_)/(nPoints_ - 1);
00235     const vector normOffset = offset/mag(offset);
00236     const vector smallVec = tol*offset;
00237     const scalar smallDist = mag(smallVec);
00238 
00239     // Get all boundary intersections
00240     List<pointIndexHit> bHits = searchEngine().intersections
00241     (
00242         start_ - smallVec,
00243         end_ + smallVec
00244     );
00245 
00246     point bPoint(GREAT, GREAT, GREAT);
00247     label bFaceI = -1;
00248 
00249     if (bHits.size())
00250     {
00251         bPoint = bHits[0].hitPoint();
00252         bFaceI = bHits[0].index();
00253     }
00254 
00255     // Get first tracking point. Use bPoint, bFaceI if provided.
00256 
00257     point trackPt;
00258     label trackCellI = -1;
00259     label trackFaceI = -1;
00260 
00261     bool isSample =
00262         getTrackingPoint
00263         (
00264             offset,
00265             start_,
00266             bPoint,
00267             bFaceI,
00268 
00269             trackPt,
00270             trackCellI,
00271             trackFaceI
00272         );
00273 
00274     if (trackCellI == -1)
00275     {
00276         // Line start_ - end_ does not intersect domain at all.
00277         // (or is along edge)
00278         // Set points and cell/face labels to empty lists
00279 
00280         return;
00281     }
00282 
00283     if (isSample)
00284     {
00285         samplingPts.append(start_);
00286         samplingCells.append(trackCellI);
00287         samplingFaces.append(trackFaceI);
00288         samplingCurveDist.append(0.0);
00289     }
00290 
00291     //
00292     // Track until hit end of all boundary intersections
00293     //
00294 
00295     // current segment number
00296     label segmentI = 0;
00297 
00298     // starting index of current segment in samplePts
00299     label startSegmentI = 0;
00300 
00301     label sampleI = 0;
00302     point samplePt = start_;
00303 
00304     // index in bHits; current boundary intersection
00305     label bHitI = 1;
00306 
00307     while(true)
00308     {
00309         // Initialize tracking starting from trackPt
00310         Cloud<passiveParticle> particles(mesh(), IDLList<passiveParticle>());
00311 
00312         passiveParticle singleParticle
00313         (
00314             particles,
00315             trackPt,
00316             trackCellI
00317         );
00318 
00319         bool reachedBoundary = trackToBoundary
00320         (
00321             singleParticle,
00322             samplePt,
00323             sampleI,
00324             samplingPts,
00325             samplingCells,
00326             samplingFaces,
00327             samplingCurveDist
00328         );
00329 
00330         // fill sampleSegments
00331         for(label i = samplingPts.size() - 1; i >= startSegmentI; --i)
00332         {
00333             samplingSegments.append(segmentI);
00334         }
00335 
00336 
00337         if (!reachedBoundary)
00338         {
00339             if (debug)
00340             {
00341                 Info<< "calcSamples : Reached end of samples: "
00342                     << "  samplePt now:" << samplePt
00343                     << "  sampleI now:" << sampleI
00344                     << endl;
00345             }
00346             break;
00347         }
00348 
00349 
00350         bool foundValidB = false;
00351 
00352         while (bHitI < bHits.size())
00353         {
00354             scalar dist =
00355                 (bHits[bHitI].hitPoint() - singleParticle.position())
00356               & normOffset;
00357 
00358             if (debug)
00359             {
00360                 Info<< "Finding next boundary : "
00361                     << "bPoint:" << bHits[bHitI].hitPoint()
00362                     << "  tracking:" << singleParticle.position()
00363                     << "  dist:" << dist
00364                     << endl;
00365             }
00366 
00367             if (dist > smallDist)
00368             {
00369                 // hitpoint is past tracking position
00370                 foundValidB = true;
00371                 break;
00372             }
00373             else
00374             {
00375                 bHitI++;
00376             }
00377         }
00378 
00379         if (!foundValidB)
00380         {
00381             // No valid boundary intersection found beyond tracking position
00382             break;
00383         }
00384 
00385         // Update starting point for tracking
00386         trackFaceI = bFaceI;
00387         trackPt = pushIn(bPoint, trackFaceI);
00388         trackCellI = getBoundaryCell(trackFaceI);
00389 
00390         segmentI++;
00391 
00392         startSegmentI = samplingPts.size();
00393     }
00394 }
00395 
00396 
00397 void Foam::uniformSet::genSamples()
00398 {
00399     // Storage for sample points
00400     DynamicList<point> samplingPts;
00401     DynamicList<label> samplingCells;
00402     DynamicList<label> samplingFaces;
00403     DynamicList<label> samplingSegments;
00404     DynamicList<scalar> samplingCurveDist;
00405 
00406     calcSamples
00407     (
00408         samplingPts,
00409         samplingCells,
00410         samplingFaces,
00411         samplingSegments,
00412         samplingCurveDist
00413     );
00414 
00415     samplingPts.shrink();
00416     samplingCells.shrink();
00417     samplingFaces.shrink();
00418     samplingSegments.shrink();
00419     samplingCurveDist.shrink();
00420 
00421     setSamples
00422     (
00423         samplingPts,
00424         samplingCells,
00425         samplingFaces,
00426         samplingSegments,
00427         samplingCurveDist
00428     );
00429 }
00430 
00431 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00432 
00433 Foam::uniformSet::uniformSet
00434 (
00435     const word& name,
00436     const polyMesh& mesh,
00437     meshSearch& searchEngine,
00438     const word& axis,
00439     const point& start,
00440     const point& end,
00441     const label nPoints
00442 )
00443 :
00444     sampledSet(name, mesh, searchEngine, axis),
00445     start_(start),
00446     end_(end),
00447     nPoints_(nPoints)
00448 {
00449     genSamples();
00450 
00451     if (debug)
00452     {
00453         write(Info);
00454     }
00455 }
00456 
00457 
00458 Foam::uniformSet::uniformSet
00459 (
00460     const word& name,
00461     const polyMesh& mesh,
00462     meshSearch& searchEngine,
00463     const dictionary& dict
00464 )
00465 :
00466     sampledSet(name, mesh, searchEngine, dict),
00467     start_(dict.lookup("start")),
00468     end_(dict.lookup("end")),
00469     nPoints_(readLabel(dict.lookup("nPoints")))
00470 {
00471     genSamples();
00472 
00473     if (debug)
00474     {
00475         write(Info);
00476     }
00477 }
00478 
00479 
00480 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00481 
00482 Foam::uniformSet::~uniformSet()
00483 {}
00484 
00485 
00486 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00487 
00488 
00489 Foam::point Foam::uniformSet::getRefPoint(const List<point>& pts) const
00490 {
00491     // Use start point as reference for 'distance'
00492     return start_;
00493 }
00494 
00495 
00496 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines