1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "searchableSurfaceCollection.H"
27 #include "addToRunTimeSelectionTable.H"
28 #include "SortableList.H"
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 defineTypeNameAndDebug(searchableSurfaceCollection, 0);
38 addToRunTimeSelectionTable
41 searchableSurfaceCollection,
48 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
50 void Foam::searchableSurfaceCollection::findNearest
52 const pointField& samples,
53 scalarField& minDistSqr,
54 List<pointIndexHit>& nearestInfo,
55 labelList& nearestSurf
59 nearestInfo.setSize(samples.size());
60 nearestInfo = pointIndexHit();
61 nearestSurf.setSize(samples.size());
64 List<pointIndexHit> hitInfo(samples.size());
66 const scalarField localMinDistSqr(samples.size(), GREAT);
68 forAll(subGeom_, surfI)
70 subGeom_[surfI].findNearest
72 cmptDivide // Transform then divide
74 transform_[surfI].localPosition(samples),
81 forAll(hitInfo, pointI)
83 if (hitInfo[pointI].hit())
85 // Rework back into global coordinate sys. Multiply then
87 point globalPt = transform_[surfI].globalPosition
91 hitInfo[pointI].rawPoint(),
96 scalar distSqr = magSqr(globalPt - samples[pointI]);
98 if (distSqr < minDistSqr[pointI])
100 minDistSqr[pointI] = distSqr;
101 nearestInfo[pointI].setPoint(globalPt);
102 nearestInfo[pointI].setHit();
103 nearestInfo[pointI].setIndex
105 hitInfo[pointI].index()
106 + indexOffset_[surfI]
108 nearestSurf[pointI] = surfI;
116 // Sort hits into per-surface bins. Misses are rejected. Maintains map back
118 void Foam::searchableSurfaceCollection::sortHits
120 const List<pointIndexHit>& info,
121 List<List<pointIndexHit> >& surfInfo,
122 labelListList& infoMap
125 // Count hits per surface.
126 labelList nHits(subGeom_.size(), 0);
130 if (info[pointI].hit())
132 label index = info[pointI].index();
133 label surfI = findLower(indexOffset_, index+1);
138 // Per surface the hit
139 surfInfo.setSize(subGeom_.size());
140 // Per surface the original position
141 infoMap.setSize(subGeom_.size());
143 forAll(surfInfo, surfI)
145 surfInfo[surfI].setSize(nHits[surfI]);
146 infoMap[surfI].setSize(nHits[surfI]);
152 if (info[pointI].hit())
154 label index = info[pointI].index();
155 label surfI = findLower(indexOffset_, index+1);
157 // Store for correct surface and adapt indices back to local
159 label localI = nHits[surfI]++;
160 surfInfo[surfI][localI] = pointIndexHit
163 info[pointI].rawPoint(),
164 index-indexOffset_[surfI]
166 infoMap[surfI][localI] = pointI;
172 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
174 Foam::searchableSurfaceCollection::searchableSurfaceCollection
177 const dictionary& dict
180 searchableSurface(io),
181 instance_(dict.size()),
183 transform_(dict.size()),
184 subGeom_(dict.size()),
185 mergeSubRegions_(dict.lookup("mergeSubRegions")),
186 indexOffset_(dict.size()+1)
188 Info<< "SearchableCollection : " << name() << endl;
191 label startIndex = 0;
192 forAllConstIter(dictionary, dict, iter)
194 if (dict.isDict(iter().keyword()))
196 instance_[surfI] = iter().keyword();
198 const dictionary& subDict = dict.subDict(instance_[surfI]);
200 scale_[surfI] = subDict.lookup("scale");
204 coordinateSystem::New
207 subDict.subDict("transform")
211 const word subGeomName(subDict.lookup("surface"));
212 //Pout<< "Trying to find " << subGeomName << endl;
214 const searchableSurface& s =
215 io.db().lookupObject<searchableSurface>(subGeomName);
217 // I don't know yet how to handle the globalSize combined with
218 // regionOffset. Would cause non-consecutive indices locally
219 // if all indices offset by globalSize() of the local region...
220 if (s.size() != s.globalSize())
224 "searchableSurfaceCollection::searchableSurfaceCollection"
225 "(const IOobject&, const dictionary&)"
226 ) << "Cannot use a distributed surface in a collection."
230 subGeom_.set(surfI, &const_cast<searchableSurface&>(s));
232 indexOffset_[surfI] = startIndex;
233 startIndex += subGeom_[surfI].size();
235 Info<< " instance : " << instance_[surfI] << endl;
236 Info<< " surface : " << s.name() << endl;
237 Info<< " scale : " << scale_[surfI] << endl;
238 Info<< " coordsys : " << transform_[surfI] << endl;
243 indexOffset_[surfI] = startIndex;
245 instance_.setSize(surfI);
246 scale_.setSize(surfI);
247 transform_.setSize(surfI);
248 subGeom_.setSize(surfI);
249 indexOffset_.setSize(surfI+1);
253 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
255 Foam::searchableSurfaceCollection::~searchableSurfaceCollection()
259 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
261 const Foam::wordList& Foam::searchableSurfaceCollection::regions() const
263 if (regions_.size() == 0)
265 regionOffset_.setSize(subGeom_.size());
267 DynamicList<word> allRegions;
268 forAll(subGeom_, surfI)
270 regionOffset_[surfI] = allRegions.size();
272 if (mergeSubRegions_)
274 // Single name regardless how many regions subsurface has
275 allRegions.append(instance_[surfI] + "_" + Foam::name(surfI));
279 const wordList& subRegions = subGeom_[surfI].regions();
281 forAll(subRegions, i)
283 allRegions.append(instance_[surfI] + "_" + subRegions[i]);
287 regions_.transfer(allRegions.shrink());
293 Foam::label Foam::searchableSurfaceCollection::size() const
295 return indexOffset_.last();
299 Foam::pointField Foam::searchableSurfaceCollection::coordinates() const
302 pointField coords(size());
304 // Append individual coordinates
307 forAll(subGeom_, surfI)
309 const pointField subCoords = subGeom_[surfI].coordinates();
313 coords[coordI++] = transform_[surfI].globalPosition
328 void Foam::searchableSurfaceCollection::findNearest
330 const pointField& samples,
331 const scalarField& nearestDistSqr,
332 List<pointIndexHit>& nearestInfo
335 // How to scale distance?
336 scalarField minDistSqr(nearestDistSqr);
338 labelList nearestSurf;
349 void Foam::searchableSurfaceCollection::findLine
351 const pointField& start,
352 const pointField& end,
353 List<pointIndexHit>& info
356 info.setSize(start.size());
357 info = pointIndexHit();
359 // Current nearest (to start) intersection
360 pointField nearest(end);
362 List<pointIndexHit> hitInfo(start.size());
364 forAll(subGeom_, surfI)
367 tmp<pointField> e0 = cmptDivide
369 transform_[surfI].localPosition
376 // Current best end point
377 tmp<pointField> e1 = cmptDivide
379 transform_[surfI].localPosition
386 subGeom_[surfI].findLine(e0, e1, hitInfo);
388 forAll(hitInfo, pointI)
390 if (hitInfo[pointI].hit())
392 // Transform back to global coordinate sys.
393 nearest[pointI] = transform_[surfI].globalPosition
397 hitInfo[pointI].rawPoint(),
401 info[pointI] = hitInfo[pointI];
402 info[pointI].rawPoint() = nearest[pointI];
403 info[pointI].setIndex
405 hitInfo[pointI].index()
406 + indexOffset_[surfI]
418 if (info[pointI].hit())
420 vector n(end[pointI] - start[pointI]);
421 scalar magN = mag(n);
427 scalar s = ((info[pointI].rawPoint()-start[pointI])&n);
433 "searchableSurfaceCollection::findLine(..)"
434 ) << "point:" << info[pointI]
436 << " outside vector "
437 << " start:" << start[pointI]
438 << " end:" << end[pointI]
439 << abort(FatalError);
448 void Foam::searchableSurfaceCollection::findLineAny
450 const pointField& start,
451 const pointField& end,
452 List<pointIndexHit>& info
456 findLine(start, end, info);
460 void Foam::searchableSurfaceCollection::findLineAll
462 const pointField& start,
463 const pointField& end,
464 List<List<pointIndexHit> >& info
467 // To be done. Assume for now only one intersection.
468 List<pointIndexHit> nearestInfo;
469 findLine(start, end, nearestInfo);
471 info.setSize(start.size());
474 if (nearestInfo[pointI].hit())
476 info[pointI].setSize(1);
477 info[pointI][0] = nearestInfo[pointI];
481 info[pointI].clear();
487 void Foam::searchableSurfaceCollection::getRegion
489 const List<pointIndexHit>& info,
493 if (subGeom_.size() == 0)
495 else if (subGeom_.size() == 1)
497 if (mergeSubRegions_)
499 region.setSize(info.size());
500 region = regionOffset_[0];
504 subGeom_[0].getRegion(info, region);
509 // Multiple surfaces. Sort by surface.
511 // Per surface the hit
512 List<List<pointIndexHit> > surfInfo;
513 // Per surface the original position
514 List<List<label> > infoMap;
515 sortHits(info, surfInfo, infoMap);
517 region.setSize(info.size());
522 if (mergeSubRegions_)
524 // Actually no need for surfInfo. Just take region for surface.
525 forAll(infoMap, surfI)
527 const labelList& map = infoMap[surfI];
530 region[map[i]] = regionOffset_[surfI];
536 forAll(infoMap, surfI)
538 labelList surfRegion;
539 subGeom_[surfI].getRegion(surfInfo[surfI], surfRegion);
541 const labelList& map = infoMap[surfI];
544 region[map[i]] = regionOffset_[surfI] + surfRegion[i];
552 void Foam::searchableSurfaceCollection::getNormal
554 const List<pointIndexHit>& info,
558 if (subGeom_.size() == 0)
560 else if (subGeom_.size() == 1)
562 subGeom_[0].getNormal(info, normal);
566 // Multiple surfaces. Sort by surface.
568 // Per surface the hit
569 List<List<pointIndexHit> > surfInfo;
570 // Per surface the original position
571 List<List<label> > infoMap;
572 sortHits(info, surfInfo, infoMap);
574 normal.setSize(info.size());
577 forAll(surfInfo, surfI)
579 vectorField surfNormal;
580 subGeom_[surfI].getNormal(surfInfo[surfI], surfNormal);
582 const labelList& map = infoMap[surfI];
585 normal[map[i]] = surfNormal[i];
592 void Foam::searchableSurfaceCollection::getVolumeType
594 const pointField& points,
595 List<volumeType>& volType
600 "searchableSurfaceCollection::getVolumeType(const pointField&"
601 ", List<volumeType>&) const"
602 ) << "Volume type not supported for collection."
607 void Foam::searchableSurfaceCollection::distribute
609 const List<treeBoundBox>& bbs,
610 const bool keepNonLocal,
611 autoPtr<mapDistribute>& faceMap,
612 autoPtr<mapDistribute>& pointMap
615 forAll(subGeom_, surfI)
617 // Note:Tranform the bounding boxes? Something like
618 // pointField bbPoints =
621 // transform_[surfI].localPosition
627 // treeBoundBox newBb(bbPoints);
629 // Note: what to do with faceMap, pointMap from multiple surfaces?
630 subGeom_[surfI].distribute
641 void Foam::searchableSurfaceCollection::setField(const labelList& values)
643 forAll(subGeom_, surfI)
645 subGeom_[surfI].setField
647 static_cast<const labelList&>
652 subGeom_[surfI].size(),
661 void Foam::searchableSurfaceCollection::getField
663 const List<pointIndexHit>& info,
667 if (subGeom_.size() == 0)
669 else if (subGeom_.size() == 1)
671 subGeom_[0].getField(info, values);
675 // Multiple surfaces. Sort by surface.
677 // Per surface the hit
678 List<List<pointIndexHit> > surfInfo;
679 // Per surface the original position
680 List<List<label> > infoMap;
681 sortHits(info, surfInfo, infoMap);
684 forAll(surfInfo, surfI)
686 labelList surfValues;
687 subGeom_[surfI].getField(surfInfo[surfI], surfValues);
689 if (surfValues.size())
691 // Size values only when we have a surface that supports it.
692 values.setSize(info.size());
694 const labelList& map = infoMap[surfI];
697 values[map[i]] = surfValues[i];
705 // ************************************************************************* //