1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "searchableSurfaceCollection.H"
28 #include "addToRunTimeSelectionTable.H"
29 #include "SortableList.H"
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 defineTypeNameAndDebug(searchableSurfaceCollection, 0);
39 addToRunTimeSelectionTable
42 searchableSurfaceCollection,
49 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
51 void Foam::searchableSurfaceCollection::findNearest
53 const pointField& samples,
54 scalarField& minDistSqr,
55 List<pointIndexHit>& nearestInfo,
56 labelList& nearestSurf
60 nearestInfo.setSize(samples.size());
61 nearestInfo = pointIndexHit();
62 nearestSurf.setSize(samples.size());
65 List<pointIndexHit> hitInfo(samples.size());
67 const scalarField localMinDistSqr(samples.size(), GREAT);
69 forAll(subGeom_, surfI)
71 subGeom_[surfI].findNearest
73 cmptDivide // Transform then divide
75 transform_[surfI].localPosition(samples),
82 forAll(hitInfo, pointI)
84 if (hitInfo[pointI].hit())
86 // Rework back into global coordinate sys. Multiply then
88 point globalPt = transform_[surfI].globalPosition
92 hitInfo[pointI].rawPoint(),
97 scalar distSqr = magSqr(globalPt - samples[pointI]);
99 if (distSqr < minDistSqr[pointI])
101 minDistSqr[pointI] = distSqr;
102 nearestInfo[pointI].setPoint(globalPt);
103 nearestInfo[pointI].setHit();
104 nearestInfo[pointI].setIndex
106 hitInfo[pointI].index()
107 + indexOffset_[surfI]
109 nearestSurf[pointI] = surfI;
117 // Sort hits into per-surface bins. Misses are rejected. Maintains map back
119 void Foam::searchableSurfaceCollection::sortHits
121 const List<pointIndexHit>& info,
122 List<List<pointIndexHit> >& surfInfo,
123 labelListList& infoMap
126 // Count hits per surface.
127 labelList nHits(subGeom_.size(), 0);
131 if (info[pointI].hit())
133 label index = info[pointI].index();
134 label surfI = findLower(indexOffset_, index+1);
139 // Per surface the hit
140 surfInfo.setSize(subGeom_.size());
141 // Per surface the original position
142 infoMap.setSize(subGeom_.size());
144 forAll(surfInfo, surfI)
146 surfInfo[surfI].setSize(nHits[surfI]);
147 infoMap[surfI].setSize(nHits[surfI]);
153 if (info[pointI].hit())
155 label index = info[pointI].index();
156 label surfI = findLower(indexOffset_, index+1);
158 // Store for correct surface and adapt indices back to local
160 label localI = nHits[surfI]++;
161 surfInfo[surfI][localI] = pointIndexHit
164 info[pointI].rawPoint(),
165 index-indexOffset_[surfI]
167 infoMap[surfI][localI] = pointI;
173 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
175 Foam::searchableSurfaceCollection::searchableSurfaceCollection
178 const dictionary& dict
181 searchableSurface(io),
182 instance_(dict.size()),
184 transform_(dict.size()),
185 subGeom_(dict.size()),
186 mergeSubRegions_(dict.lookup("mergeSubRegions")),
187 indexOffset_(dict.size()+1)
189 Info<< "SearchableCollection : " << name() << endl;
192 label startIndex = 0;
193 forAllConstIter(dictionary, dict, iter)
195 if (dict.isDict(iter().keyword()))
197 instance_[surfI] = iter().keyword();
199 const dictionary& subDict = dict.subDict(instance_[surfI]);
201 scale_[surfI] = subDict.lookup("scale");
205 coordinateSystem::New
208 subDict.subDict("transform")
212 const word subGeomName(subDict.lookup("surface"));
213 //Pout<< "Trying to find " << subGeomName << endl;
215 const searchableSurface& s =
216 io.db().lookupObject<searchableSurface>(subGeomName);
218 // I don't know yet how to handle the globalSize combined with
219 // regionOffset. Would cause non-consecutive indices locally
220 // if all indices offset by globalSize() of the local region...
221 if (s.size() != s.globalSize())
225 "searchableSurfaceCollection::searchableSurfaceCollection"
226 "(const IOobject&, const dictionary&)"
227 ) << "Cannot use a distributed surface in a collection."
231 subGeom_.set(surfI, &const_cast<searchableSurface&>(s));
233 indexOffset_[surfI] = startIndex;
234 startIndex += subGeom_[surfI].size();
236 Info<< " instance : " << instance_[surfI] << endl;
237 Info<< " surface : " << s.name() << endl;
238 Info<< " scale : " << scale_[surfI] << endl;
239 Info<< " coordsys : " << transform_[surfI] << endl;
244 indexOffset_[surfI] = startIndex;
246 instance_.setSize(surfI);
247 scale_.setSize(surfI);
248 transform_.setSize(surfI);
249 subGeom_.setSize(surfI);
250 indexOffset_.setSize(surfI+1);
254 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
256 Foam::searchableSurfaceCollection::~searchableSurfaceCollection()
260 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
262 const Foam::wordList& Foam::searchableSurfaceCollection::regions() const
264 if (regions_.size() == 0)
266 regionOffset_.setSize(subGeom_.size());
268 DynamicList<word> allRegions;
269 forAll(subGeom_, surfI)
271 regionOffset_[surfI] = allRegions.size();
273 if (mergeSubRegions_)
275 // Single name regardless how many regions subsurface has
276 allRegions.append(instance_[surfI] + "_" + Foam::name(surfI));
280 const wordList& subRegions = subGeom_[surfI].regions();
282 forAll(subRegions, i)
284 allRegions.append(instance_[surfI] + "_" + subRegions[i]);
288 regions_.transfer(allRegions.shrink());
294 Foam::label Foam::searchableSurfaceCollection::size() const
296 return indexOffset_[indexOffset_.size()-1];
300 Foam::pointField Foam::searchableSurfaceCollection::coordinates() const
303 pointField coords(size());
305 // Append individual coordinates
308 forAll(subGeom_, surfI)
310 const pointField subCoords = subGeom_[surfI].coordinates();
314 coords[coordI++] = transform_[surfI].globalPosition
329 void Foam::searchableSurfaceCollection::findNearest
331 const pointField& samples,
332 const scalarField& nearestDistSqr,
333 List<pointIndexHit>& nearestInfo
336 // How to scale distance?
337 scalarField minDistSqr(nearestDistSqr);
339 labelList nearestSurf;
350 void Foam::searchableSurfaceCollection::findLine
352 const pointField& start,
353 const pointField& end,
354 List<pointIndexHit>& info
357 info.setSize(start.size());
358 info = pointIndexHit();
360 // Current nearest (to start) intersection
361 pointField nearest(end);
363 List<pointIndexHit> hitInfo(start.size());
365 forAll(subGeom_, surfI)
368 tmp<pointField> e0 = cmptDivide
370 transform_[surfI].localPosition
377 // Current best end point
378 tmp<pointField> e1 = cmptDivide
380 transform_[surfI].localPosition
387 subGeom_[surfI].findLine(e0, e1, hitInfo);
389 forAll(hitInfo, pointI)
391 if (hitInfo[pointI].hit())
393 // Transform back to global coordinate sys.
394 nearest[pointI] = transform_[surfI].globalPosition
398 hitInfo[pointI].rawPoint(),
402 info[pointI] = hitInfo[pointI];
403 info[pointI].rawPoint() = nearest[pointI];
404 info[pointI].setIndex
406 hitInfo[pointI].index()
407 + indexOffset_[surfI]
419 if (info[pointI].hit())
421 vector n(end[pointI] - start[pointI]);
422 scalar magN = mag(n);
428 scalar s = ((info[pointI].rawPoint()-start[pointI])&n);
434 "searchableSurfaceCollection::findLine(..)"
435 ) << "point:" << info[pointI]
437 << " outside vector "
438 << " start:" << start[pointI]
439 << " end:" << end[pointI]
440 << abort(FatalError);
449 void Foam::searchableSurfaceCollection::findLineAny
451 const pointField& start,
452 const pointField& end,
453 List<pointIndexHit>& info
457 findLine(start, end, info);
461 void Foam::searchableSurfaceCollection::findLineAll
463 const pointField& start,
464 const pointField& end,
465 List<List<pointIndexHit> >& info
468 // To be done. Assume for now only one intersection.
469 List<pointIndexHit> nearestInfo;
470 findLine(start, end, nearestInfo);
472 info.setSize(start.size());
475 if (nearestInfo[pointI].hit())
477 info[pointI].setSize(1);
478 info[pointI][0] = nearestInfo[pointI];
482 info[pointI].clear();
488 void Foam::searchableSurfaceCollection::getRegion
490 const List<pointIndexHit>& info,
494 if (subGeom_.size() == 0)
496 else if (subGeom_.size() == 1)
498 if (mergeSubRegions_)
500 region.setSize(info.size());
501 region = regionOffset_[0];
505 subGeom_[0].getRegion(info, region);
510 // Multiple surfaces. Sort by surface.
512 // Per surface the hit
513 List<List<pointIndexHit> > surfInfo;
514 // Per surface the original position
515 List<List<label> > infoMap;
516 sortHits(info, surfInfo, infoMap);
518 region.setSize(info.size());
523 if (mergeSubRegions_)
525 // Actually no need for surfInfo. Just take region for surface.
526 forAll(infoMap, surfI)
528 const labelList& map = infoMap[surfI];
531 region[map[i]] = regionOffset_[surfI];
537 forAll(infoMap, surfI)
539 labelList surfRegion;
540 subGeom_[surfI].getRegion(surfInfo[surfI], surfRegion);
542 const labelList& map = infoMap[surfI];
545 region[map[i]] = regionOffset_[surfI] + surfRegion[i];
553 void Foam::searchableSurfaceCollection::getNormal
555 const List<pointIndexHit>& info,
559 if (subGeom_.size() == 0)
561 else if (subGeom_.size() == 1)
563 subGeom_[0].getNormal(info, normal);
567 // Multiple surfaces. Sort by surface.
569 // Per surface the hit
570 List<List<pointIndexHit> > surfInfo;
571 // Per surface the original position
572 List<List<label> > infoMap;
573 sortHits(info, surfInfo, infoMap);
575 normal.setSize(info.size());
578 forAll(surfInfo, surfI)
580 vectorField surfNormal;
581 subGeom_[surfI].getNormal(surfInfo[surfI], surfNormal);
583 const labelList& map = infoMap[surfI];
586 normal[map[i]] = surfNormal[i];
593 void Foam::searchableSurfaceCollection::getVolumeType
595 const pointField& points,
596 List<volumeType>& volType
601 "searchableSurfaceCollection::getVolumeType(const pointField&"
602 ", List<volumeType>&) const"
603 ) << "Volume type not supported for collection."
608 void Foam::searchableSurfaceCollection::distribute
610 const List<treeBoundBox>& bbs,
611 const bool keepNonLocal,
612 autoPtr<mapDistribute>& faceMap,
613 autoPtr<mapDistribute>& pointMap
616 forAll(subGeom_, surfI)
618 // Note:Tranform the bounding boxes? Something like
619 // pointField bbPoints =
622 // transform_[surfI].localPosition
628 // treeBoundBox newBb(bbPoints);
630 // Note: what to do with faceMap, pointMap from multiple surfaces?
631 subGeom_[surfI].distribute
642 void Foam::searchableSurfaceCollection::setField(const labelList& values)
644 forAll(subGeom_, surfI)
646 subGeom_[surfI].setField
648 static_cast<const labelList&>
653 subGeom_[surfI].size(),
662 void Foam::searchableSurfaceCollection::getField
664 const List<pointIndexHit>& info,
668 if (subGeom_.size() == 0)
670 else if (subGeom_.size() == 1)
672 subGeom_[0].getField(info, values);
676 // Multiple surfaces. Sort by surface.
678 // Per surface the hit
679 List<List<pointIndexHit> > surfInfo;
680 // Per surface the original position
681 List<List<label> > infoMap;
682 sortHits(info, surfInfo, infoMap);
685 forAll(surfInfo, surfI)
687 labelList surfValues;
688 subGeom_[surfI].getField(surfInfo[surfI], surfValues);
690 if (surfValues.size())
692 // Size values only when we have a surface that supports it.
693 values.setSize(info.size());
695 const labelList& map = infoMap[surfI];
698 values[map[i]] = surfValues[i];
706 // ************************************************************************* //