diff --git a/src/meshTools/searchableSurface/distributedTriSurfaceMesh.C b/src/meshTools/searchableSurface/distributedTriSurfaceMesh.C index 60ad087b70a3d68239124c8a3960f79b3a4b5eec..40ad36bbc3a4e5b185388fbd006c220853d1694b 100644 --- a/src/meshTools/searchableSurface/distributedTriSurfaceMesh.C +++ b/src/meshTools/searchableSurface/distributedTriSurfaceMesh.C @@ -912,41 +912,6 @@ Foam::distributedTriSurfaceMesh::independentlyDistributedBbs } -void Foam::distributedTriSurfaceMesh::calcBounds -( - boundBox& bb, - label& nPoints -) const -{ - // Unfortunately nPoints constructs meshPoints() so do compact version - // ourselves - - PackedBoolList pointIsUsed(points().size()); - - nPoints = 0; - bb.min() = point(VGREAT, VGREAT, VGREAT); - bb.max() = point(-VGREAT, -VGREAT, -VGREAT); - - const triSurface& s = static_cast<const triSurface&>(*this); - - forAll(s, triI) - { - const labelledTri& f = s[triI]; - - forAll(f, fp) - { - label pointI = f[fp]; - if (pointIsUsed.set(pointI, 1u)) - { - bb.min() = ::Foam::min(bb.min(), points()[pointI]); - bb.max() = ::Foam::max(bb.max(), points()[pointI]); - nPoints++; - } - } - } -} - - // Does any part of triangle overlap bb. bool Foam::distributedTriSurfaceMesh::overlaps ( @@ -1935,20 +1900,7 @@ void Foam::distributedTriSurfaceMesh::getNormal { if (!Pstream::parRun()) { - normal.setSize(info.size()); - - forAll(info, i) - { - if (info[i].hit()) - { - normal[i] = faceNormals()[info[i].index()]; - } - else - { - // Set to what? - normal[i] = vector::zero; - } - } + triSurfaceMesh::getNormal(info, normal); return; } @@ -2006,70 +1958,64 @@ void Foam::distributedTriSurfaceMesh::getNormal void Foam::distributedTriSurfaceMesh::getField ( - const word& fieldName, const List<pointIndexHit>& info, labelList& values ) const { - const triSurfaceLabelField& fld = lookupObject<triSurfaceLabelField> - ( - fieldName - ); - - if (!Pstream::parRun()) { - values.setSize(info.size()); - forAll(info, i) - { - if (info[i].hit()) - { - values[i] = fld[info[i].index()]; - } - } + triSurfaceMesh::getField(info, values); return; } + if (foundObject<triSurfaceLabelField>("values")) + { + const triSurfaceLabelField& fld = lookupObject<triSurfaceLabelField> + ( + "values" + ); - // Get query data (= local index of triangle) - // ~~~~~~~~~~~~~~ - labelList triangleIndex(info.size()); - autoPtr<mapDistribute> mapPtr - ( - calcLocalQueries + // Get query data (= local index of triangle) + // ~~~~~~~~~~~~~~ + + labelList triangleIndex(info.size()); + autoPtr<mapDistribute> mapPtr ( - info, - triangleIndex - ) - ); - const mapDistribute& map = mapPtr(); + calcLocalQueries + ( + info, + triangleIndex + ) + ); + const mapDistribute& map = mapPtr(); - // Do my tests - // ~~~~~~~~~~~ + // Do my tests + // ~~~~~~~~~~~ - values.setSize(triangleIndex.size()); + values.setSize(triangleIndex.size()); - forAll(triangleIndex, i) - { - label triI = triangleIndex[i]; - values[i] = fld[triI]; - } + forAll(triangleIndex, i) + { + label triI = triangleIndex[i]; + values[i] = fld[triI]; + } - // Send back results - // ~~~~~~~~~~~~~~~~~ + // Send back results + // ~~~~~~~~~~~~~~~~~ - map.distribute - ( - Pstream::nonBlocking, - List<labelPair>(0), - info.size(), - map.constructMap(), // what to send - map.subMap(), // what to receive - values - ); + map.distribute + ( + Pstream::nonBlocking, + List<labelPair>(0), + info.size(), + map.constructMap(), // what to send + map.subMap(), // what to receive + values + ); + } } diff --git a/src/meshTools/searchableSurface/distributedTriSurfaceMesh.H b/src/meshTools/searchableSurface/distributedTriSurfaceMesh.H index dba72d2abf4b1491be861f6e5dc825533d9b1427..577d12e4c3544fad2b73e8b4343d5c2f80682262 100644 --- a/src/meshTools/searchableSurface/distributedTriSurfaceMesh.H +++ b/src/meshTools/searchableSurface/distributedTriSurfaceMesh.H @@ -217,9 +217,6 @@ private: const triSurface& ); - //- Calculate surface bounding box - void calcBounds(boundBox& bb, label& nPoints) const; - //- Does any part of triangle overlap bb. static bool overlaps ( @@ -418,7 +415,7 @@ public: // Should really be split into a routine to determine decomposition // and one that does actual distribution but determining // decomposition with duplicate triangle merging requires - // same amoun as work as actual distribution. + // same amount as work as actual distribution. virtual void distribute ( const List<treeBoundBox>&, @@ -430,14 +427,9 @@ public: // Other - //- Specific to triSurfaceMesh: from a set of hits (points and + //- WIP. From a set of hits (points and // indices) get the specified field. Misses do not get set. - virtual void getField - ( - const word& fieldName, - const List<pointIndexHit>&, - labelList& values - ) const; + virtual void getField(const List<pointIndexHit>&, labelList&) const; //- Subset the part of surface that is overlapping bounds. static triSurface overlappingSurface diff --git a/src/meshTools/searchableSurface/searchableBox.C b/src/meshTools/searchableSurface/searchableBox.C index a4cc593562a6460ac80f4998d7dc570c4651da71..cb854c3772552b9602a50531321c80a07268beac 100644 --- a/src/meshTools/searchableSurface/searchableBox.C +++ b/src/meshTools/searchableSurface/searchableBox.C @@ -229,6 +229,21 @@ const Foam::wordList& Foam::searchableBox::regions() const } +Foam::pointField Foam::searchableBox::coordinates() const +{ + pointField ctrs(6); + + const pointField pts = treeBoundBox::points(); + const faceList& fcs = treeBoundBox::faces; + + forAll(fcs, i) + { + ctrs[i] = fcs[i].centre(pts); + } + return ctrs; +} + + Foam::pointIndexHit Foam::searchableBox::findNearest ( const point& sample, diff --git a/src/meshTools/searchableSurface/searchableBox.H b/src/meshTools/searchableSurface/searchableBox.H index 9d1f2e8217ef3db841ebf9d1c8b4f5796c34b866..77e0ecd98d8c33b06a2d710eee10f47b1f8de70c 100644 --- a/src/meshTools/searchableSurface/searchableBox.H +++ b/src/meshTools/searchableSurface/searchableBox.H @@ -127,6 +127,9 @@ public: return 6; } + //- Get representative set of element coordinates + // Usually the element centres (should be of length size()). + virtual pointField coordinates() const; // Single point queries. diff --git a/src/meshTools/searchableSurface/searchableCylinder.C b/src/meshTools/searchableSurface/searchableCylinder.C index fcaa42194aab42ce1f06f9e199f215548b92c627..0df222ccb0fc929bb882c8c9b1fafa1535097ec2 100644 --- a/src/meshTools/searchableSurface/searchableCylinder.C +++ b/src/meshTools/searchableSurface/searchableCylinder.C @@ -40,6 +40,14 @@ addToRunTimeSelectionTable(searchableSurface, searchableCylinder, dict); // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // +Foam::pointField Foam::searchableCylinder::coordinates() const +{ + pointField ctrs(1, 0.5*(point1_ + point2_)); + + return ctrs; +} + + Foam::pointIndexHit Foam::searchableCylinder::findNearest ( const point& sample, diff --git a/src/meshTools/searchableSurface/searchableCylinder.H b/src/meshTools/searchableSurface/searchableCylinder.H index cae0f058db2863db95ff479381d207c8ad9e57cf..98b4d91e4117eceb782b45a976928820a211c759 100644 --- a/src/meshTools/searchableSurface/searchableCylinder.H +++ b/src/meshTools/searchableSurface/searchableCylinder.H @@ -150,6 +150,10 @@ public: return 1; } + //- Get representative set of element coordinates + // Usually the element centres (should be of length size()). + virtual pointField coordinates() const; + // Multiple point queries. diff --git a/src/meshTools/searchableSurface/searchablePlane.H b/src/meshTools/searchableSurface/searchablePlane.H index 87777e3209bc6763b1e8cd155eb55ce4f3f7c4e1..c0b58cc8ac2d0c086deca4a4dda306756a295623 100644 --- a/src/meshTools/searchableSurface/searchablePlane.H +++ b/src/meshTools/searchableSurface/searchablePlane.H @@ -26,7 +26,7 @@ Class Foam::searchablePlane Description - Searching on plane. See plane.H + Searching on (infinite) plane. See plane.H SourceFiles searchablePlane.C @@ -122,6 +122,14 @@ public: return 1; } + //- Get representative set of element coordinates + // Usually the element centres (should be of length size()). + virtual pointField coordinates() const + { + //notImplemented("searchablePlane::coordinates()") + return pointField(1, refPoint()); + } + // Multiple point queries. diff --git a/src/meshTools/searchableSurface/searchablePlate.H b/src/meshTools/searchableSurface/searchablePlate.H index 7bc900f554bd3dc7a281873cf4b850077d5cf695..b05414bb6cb0e2dd764b732ff0e34f97a59539db 100644 --- a/src/meshTools/searchableSurface/searchablePlate.H +++ b/src/meshTools/searchableSurface/searchablePlate.H @@ -145,6 +145,13 @@ public: return 1; } + //- Get representative set of element coordinates + // Usually the element centres (should be of length size()). + virtual pointField coordinates() const + { + return pointField(1, origin_); + } + // Multiple point queries. diff --git a/src/meshTools/searchableSurface/searchableSphere.H b/src/meshTools/searchableSurface/searchableSphere.H index 297890b9db1b6e4568db5a65ca6d2055fd25777e..fb4aeb22f81c9d3c37afc69da4c549880af66362 100644 --- a/src/meshTools/searchableSurface/searchableSphere.H +++ b/src/meshTools/searchableSurface/searchableSphere.H @@ -133,6 +133,13 @@ public: return 1; } + //- Get representative set of element coordinates + // Usually the element centres (should be of length size()). + virtual pointField coordinates() const + { + return pointField(1, centre_); + } + // Multiple point queries. diff --git a/src/meshTools/searchableSurface/searchableSurface.H b/src/meshTools/searchableSurface/searchableSurface.H index 35b9dc9fb5a1ff9f3ba054492f7130ab2beee4a2..daf8b76daa7131344ef19d86263cda4883c1d6c9 100644 --- a/src/meshTools/searchableSurface/searchableSurface.H +++ b/src/meshTools/searchableSurface/searchableSurface.H @@ -190,6 +190,10 @@ public: return size(); } + //- Get representative set of element coordinates + // Usually the element centres (should be of length size()). + virtual pointField coordinates() const = 0; + // Single point queries. @@ -319,6 +323,18 @@ public: ) {} + //- WIP. Store element-wise field. + virtual void setField(const labelList& values) + {} + + //- WIP. From a set of hits (points and + // indices) get the specified field. Misses do not get set. Return + // empty field if not supported. + virtual void getField(const List<pointIndexHit>&, labelList& values) + const + { + values.clear(); + } }; diff --git a/src/meshTools/searchableSurface/searchableSurfaceCollection.C b/src/meshTools/searchableSurface/searchableSurfaceCollection.C index ba1dd32988e47a2aa53eb001e1014ad1686f83d2..9279087c1908b2298e61c15b71215646104ced6e 100644 --- a/src/meshTools/searchableSurface/searchableSurfaceCollection.C +++ b/src/meshTools/searchableSurface/searchableSurfaceCollection.C @@ -101,7 +101,11 @@ void Foam::searchableSurfaceCollection::findNearest minDistSqr[pointI] = distSqr; nearestInfo[pointI].setPoint(globalPt); nearestInfo[pointI].setHit(); - nearestInfo[pointI].setIndex(hitInfo[pointI].index()); + nearestInfo[pointI].setIndex + ( + hitInfo[pointI].index() + + indexOffset_[surfI] + ); nearestSurf[pointI] = surfI; } } @@ -110,6 +114,62 @@ void Foam::searchableSurfaceCollection::findNearest } +// Sort hits into per-surface bins. Misses are rejected. Maintains map back +// to position +void Foam::searchableSurfaceCollection::sortHits +( + const List<pointIndexHit>& info, + List<List<pointIndexHit> >& surfInfo, + labelListList& infoMap +) const +{ + // Count hits per surface. + labelList nHits(subGeom_.size(), 0); + + forAll(info, pointI) + { + if (info[pointI].hit()) + { + label index = info[pointI].index(); + label surfI = findLower(indexOffset_, index+1); + nHits[surfI]++; + } + } + + // Per surface the hit + surfInfo.setSize(subGeom_.size()); + // Per surface the original position + infoMap.setSize(subGeom_.size()); + + forAll(surfInfo, surfI) + { + surfInfo[surfI].setSize(nHits[surfI]); + infoMap[surfI].setSize(nHits[surfI]); + } + nHits = 0; + + forAll(info, pointI) + { + if (info[pointI].hit()) + { + label index = info[pointI].index(); + label surfI = findLower(indexOffset_, index+1); + + // Store for correct surface and adapt indices back to local + // ones + label localI = nHits[surfI]++; + surfInfo[surfI][localI] = pointIndexHit + ( + info[pointI].hit(), + info[pointI].rawPoint(), + index-indexOffset_[surfI] + ); + infoMap[surfI][localI] = pointI; + } + } +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::searchableSurfaceCollection::searchableSurfaceCollection @@ -123,11 +183,13 @@ Foam::searchableSurfaceCollection::searchableSurfaceCollection scale_(dict.size()), transform_(dict.size()), subGeom_(dict.size()), - mergeSubRegions_(dict.lookup("mergeSubRegions")) + mergeSubRegions_(dict.lookup("mergeSubRegions")), + indexOffset_(dict.size()+1) { Info<< "SearchableCollection : " << name() << endl; label surfI = 0; + label startIndex = 0; forAllConstIter(dictionary, dict, iter) { if (dict.isDict(iter().keyword())) @@ -153,8 +215,24 @@ Foam::searchableSurfaceCollection::searchableSurfaceCollection const searchableSurface& s = io.db().lookupObject<searchableSurface>(subGeomName); + // I don't know yet how to handle the globalSize combined with + // regionOffset. Would cause non-consecutive indices locally + // if all indices offset by globalSize() of the local region... + if (s.size() != s.globalSize()) + { + FatalErrorIn + ( + "searchableSurfaceCollection::searchableSurfaceCollection" + "(const IOobject&, const dictionary&)" + ) << "Cannot use a distributed surface in a collection." + << exit(FatalError); + } + subGeom_.set(surfI, &const_cast<searchableSurface&>(s)); + indexOffset_[surfI] = startIndex; + startIndex += subGeom_[surfI].size(); + Info<< " instance : " << instance_[surfI] << endl; Info<< " surface : " << s.name() << endl; Info<< " scale : " << scale_[surfI] << endl; @@ -163,10 +241,13 @@ Foam::searchableSurfaceCollection::searchableSurfaceCollection surfI++; } } + indexOffset_[surfI] = startIndex; + instance_.setSize(surfI); scale_.setSize(surfI); transform_.setSize(surfI); subGeom_.setSize(surfI); + indexOffset_.setSize(surfI+1); } @@ -212,12 +293,36 @@ const Foam::wordList& Foam::searchableSurfaceCollection::regions() const Foam::label Foam::searchableSurfaceCollection::size() const { - label n = 0; + return indexOffset_[indexOffset_.size()-1]; +} + + +Foam::pointField Foam::searchableSurfaceCollection::coordinates() const +{ + // Get overall size + pointField coords(size()); + + // Append individual coordinates + label coordI = 0; + forAll(subGeom_, surfI) { - n += subGeom_[surfI].size(); + const pointField subCoords = subGeom_[surfI].coordinates(); + + forAll(subCoords, i) + { + coords[coordI++] = transform_[surfI].globalPosition + ( + cmptMultiply + ( + subCoords[i], + scale_[surfI] + ) + ); + } } - return n; + + return coords; } @@ -296,6 +401,11 @@ void Foam::searchableSurfaceCollection::findLine ); info[pointI] = hitInfo[pointI]; info[pointI].rawPoint() = nearest[pointI]; + info[pointI].setIndex + ( + hitInfo[pointI].index() + + indexOffset_[surfI] + ); } } } @@ -397,82 +507,42 @@ void Foam::searchableSurfaceCollection::getRegion } else { - region.setSize(info.size()); - region = -1; + // Multiple surfaces. Sort by surface. - // Which region did point come from. Retest for now to see which - // surface it originates from - crap solution! Should use global indices - // in index inside pointIndexHit to do this better. + // Per surface the hit + List<List<pointIndexHit> > surfInfo; + // Per surface the original position + List<List<label> > infoMap; + sortHits(info, surfInfo, infoMap); - pointField samples(info.size()); - forAll(info, pointI) - { - if (info[pointI].hit()) - { - samples[pointI] = info[pointI].hitPoint(); - } - else - { - samples[pointI] = vector::zero; - } - } - //scalarField minDistSqr(info.size(), SMALL); - scalarField minDistSqr(info.size(), GREAT); + region.setSize(info.size()); + region = -1; - labelList nearestSurf; - List<pointIndexHit> nearestInfo; - findNearest - ( - samples, - minDistSqr, - nearestInfo, - nearestSurf - ); + // Do region tests - // Check + if (mergeSubRegions_) { - forAll(info, pointI) + // Actually no need for surfInfo. Just take region for surface. + forAll(infoMap, surfI) { - if (info[pointI].hit() && nearestSurf[pointI] == -1) + const labelList& map = infoMap[surfI]; + forAll(map, i) { - FatalErrorIn - ( - "searchableSurfaceCollection::getRegion(..)" - ) << "pointI:" << pointI - << " sample:" << samples[pointI] - << " nearest:" << nearestInfo[pointI] - << " nearestsurf:" << nearestSurf[pointI] - << abort(FatalError); + region[map[i]] = regionOffset_[surfI]; } } } - - forAll(subGeom_, surfI) + else { - // Collect points from my surface - labelList indices(findIndices(nearestSurf, surfI)); - - if (mergeSubRegions_) - { - forAll(indices, i) - { - region[indices[i]] = regionOffset_[surfI]; - } - } - else + forAll(infoMap, surfI) { labelList surfRegion; - subGeom_[surfI].getRegion - ( - List<pointIndexHit> - ( - UIndirectList<pointIndexHit>(info, indices) - ), - surfRegion - ); - forAll(indices, i) + subGeom_[surfI].getRegion(surfInfo[surfI], surfRegion); + + const labelList& map = infoMap[surfI]; + forAll(map, i) { - region[indices[i]] = regionOffset_[surfI] + surfRegion[i]; + region[map[i]] = regionOffset_[surfI] + surfRegion[i]; } } } @@ -494,52 +564,26 @@ void Foam::searchableSurfaceCollection::getNormal } else { - normal.setSize(info.size()); + // Multiple surfaces. Sort by surface. - // See above - crap retest to find surface point originates from. - pointField samples(info.size()); - forAll(info, pointI) - { - if (info[pointI].hit()) - { - samples[pointI] = info[pointI].hitPoint(); - } - else - { - samples[pointI] = vector::zero; - } - } - //scalarField minDistSqr(info.size(), SMALL); - scalarField minDistSqr(info.size(), GREAT); - - labelList nearestSurf; - List<pointIndexHit> nearestInfo; - findNearest - ( - samples, - minDistSqr, - nearestInfo, - nearestSurf - ); + // Per surface the hit + List<List<pointIndexHit> > surfInfo; + // Per surface the original position + List<List<label> > infoMap; + sortHits(info, surfInfo, infoMap); + normal.setSize(info.size()); - forAll(subGeom_, surfI) + // Do region tests + forAll(surfInfo, surfI) { - // Collect points from my surface - labelList indices(findIndices(nearestSurf, surfI)); - vectorField surfNormal; - subGeom_[surfI].getNormal - ( - List<pointIndexHit> - ( - UIndirectList<pointIndexHit>(info, indices) - ), - surfNormal - ); - forAll(indices, i) + subGeom_[surfI].getNormal(surfInfo[surfI], surfNormal); + + const labelList& map = infoMap[surfI]; + forAll(map, i) { - normal[indices[i]] = surfNormal[i]; + normal[map[i]] = surfNormal[i]; } } } @@ -561,4 +605,99 @@ void Foam::searchableSurfaceCollection::getVolumeType } +void Foam::searchableSurfaceCollection::distribute +( + const List<treeBoundBox>& bbs, + const bool keepNonLocal, + autoPtr<mapDistribute>& faceMap, + autoPtr<mapDistribute>& pointMap +) +{ + forAll(subGeom_, surfI) + { + // Note:Tranform the bounding boxes? Something like + // pointField bbPoints = + // cmptDivide + // ( + // transform_[surfI].localPosition + // ( + // bbs[i].points() + // ), + // scale_[surfI] + // ); + // treeBoundBox newBb(bbPoints); + + // Note: what to do with faceMap, pointMap from multiple surfaces? + subGeom_[surfI].distribute + ( + bbs, + keepNonLocal, + faceMap, + pointMap + ); + } +} + + +void Foam::searchableSurfaceCollection::setField(const labelList& values) +{ + forAll(subGeom_, surfI) + { + subGeom_[surfI].setField + ( + static_cast<const labelList&> + ( + SubList<label> + ( + values, + subGeom_[surfI].size(), + indexOffset_[surfI] + ) + ) + ); + } +} + + +void Foam::searchableSurfaceCollection::getField +( + const List<pointIndexHit>& info, + labelList& values +) const +{ + if (subGeom_.size() == 0) + {} + else if (subGeom_.size() == 1) + { + subGeom_[0].getField(info, values); + } + else + { + // Multiple surfaces. Sort by surface. + + // Per surface the hit + List<List<pointIndexHit> > surfInfo; + // Per surface the original position + List<List<label> > infoMap; + sortHits(info, surfInfo, infoMap); + + values.setSize(info.size()); + //?Misses do not get set? values = 0; + + // Do surface tests + forAll(surfInfo, surfI) + { + labelList surfValues; + subGeom_[surfI].getField(surfInfo[surfI], surfValues); + + const labelList& map = infoMap[surfI]; + forAll(map, i) + { + values[map[i]] = surfValues[i]; + } + } + } +} + + // ************************************************************************* // diff --git a/src/meshTools/searchableSurface/searchableSurfaceCollection.H b/src/meshTools/searchableSurface/searchableSurfaceCollection.H index 3f7ee84baa4012d2482007fa75434a8d1dbc4ca2..e0de60827831f51f04c4cdb232fe5c18c9659d02 100644 --- a/src/meshTools/searchableSurface/searchableSurfaceCollection.H +++ b/src/meshTools/searchableSurface/searchableSurfaceCollection.H @@ -77,6 +77,10 @@ private: Switch mergeSubRegions_; + //- offsets for indices coming from different surfaces + // (sized with size() of each surface) + labelList indexOffset_; + //- Region names mutable wordList regions_; //- From individual regions to collection regions @@ -95,6 +99,15 @@ private: labelList& nearestSurf ) const; + //- Sort hits into per-surface bins. Misses are rejected. + // Maintains map back to position + void sortHits + ( + const List<pointIndexHit>& info, + List<List<pointIndexHit> >& surfInfo, + labelListList& infoMap + ) const; + //- Disallow default bitwise copy construct searchableSurfaceCollection(const searchableSurfaceCollection&); @@ -161,6 +174,10 @@ public: //- Range of local indices that can be returned. virtual label size() const; + //- Get representative set of element coordinates + // Usually the element centres (should be of length size()). + virtual pointField coordinates() const; + // Multiple point queries. @@ -215,6 +232,27 @@ public: List<volumeType>& ) const; + // Other + + //- Set bounds of surface. Bounds currently set as list of + // bounding boxes. The bounds are hints to the surface as for + // the range of queries it can expect. faceMap/pointMap can be + // set if the surface has done any redistribution. + virtual void distribute + ( + const List<treeBoundBox>&, + const bool keepNonLocal, + autoPtr<mapDistribute>& faceMap, + autoPtr<mapDistribute>& pointMap + ); + + //- WIP. Store element-wise field. + virtual void setField(const labelList& values); + + //- WIP. From a set of hits (points and + // indices) get the specified field. Misses do not get set. Return + // empty field if not supported. + virtual void getField(const List<pointIndexHit>&, labelList&) const; // regIOobject implementation diff --git a/src/meshTools/searchableSurface/searchableSurfaceWithGaps.H b/src/meshTools/searchableSurface/searchableSurfaceWithGaps.H index 312c74b1d77b66ce6cb4bff37b6ccbac15068b2e..64db7ee91ceabb0343e6be0d68c6f40814fc96d2 100644 --- a/src/meshTools/searchableSurface/searchableSurfaceWithGaps.H +++ b/src/meshTools/searchableSurface/searchableSurfaceWithGaps.H @@ -151,6 +151,13 @@ public: return surface().size(); } + //- Get representative set of element coordinates + // Usually the element centres (should be of length size()). + virtual pointField coordinates() const + { + return surface().coordinates(); + } + // Multiple point queries. @@ -225,6 +232,41 @@ public: } + // Other + + //- Set bounds of surface. Bounds currently set as list of + // bounding boxes. The bounds are hints to the surface as for + // the range of queries it can expect. faceMap/pointMap can be + // set if the surface has done any redistribution. + virtual void distribute + ( + const List<treeBoundBox>& bbs, + const bool keepNonLocal, + autoPtr<mapDistribute>& faceMap, + autoPtr<mapDistribute>& pointMap + ) + { + subGeom_[0].distribute(bbs, keepNonLocal, faceMap, pointMap); + } + + //- WIP. Store element-wise field. + virtual void setField(const labelList& values) + { + subGeom_[0].setField(values); + } + + //- WIP. From a set of hits (points and + // indices) get the specified field. Misses do not get set. Return + // empty field if not supported. + virtual void getField + ( + const List<pointIndexHit>& info, + labelList& values + ) const + { + surface().getField(info, values); + } + // regIOobject implementation bool writeData(Ostream& os) const diff --git a/src/meshTools/searchableSurface/triSurfaceMesh.C b/src/meshTools/searchableSurface/triSurfaceMesh.C index 11d687aa8b6f75d86f4b191d89d9f681f8382ea9..08d367e9746252451c5ddd9cb95e3c663235e3b9 100644 --- a/src/meshTools/searchableSurface/triSurfaceMesh.C +++ b/src/meshTools/searchableSurface/triSurfaceMesh.C @@ -30,6 +30,7 @@ License #include "EdgeMap.H" #include "triSurfaceFields.H" #include "Time.H" +#include "PackedBoolList.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -281,6 +282,36 @@ void Foam::triSurfaceMesh::getNextIntersections } +void Foam::triSurfaceMesh::calcBounds(boundBox& bb, label& nPoints) const +{ + // Unfortunately nPoints constructs meshPoints() so do compact version + // ourselves + + const triSurface& s = static_cast<const triSurface&>(*this); + + PackedBoolList pointIsUsed(points().size()); + + nPoints = 0; + bb = boundBox::invertedBox; + + forAll(s, triI) + { + const labelledTri& f = s[triI]; + + forAll(f, fp) + { + label pointI = f[fp]; + if (pointIsUsed.set(pointI, 1u)) + { + bb.min() = ::Foam::min(bb.min(), points()[pointI]); + bb.max() = ::Foam::max(bb.max(), points()[pointI]); + nPoints++; + } + } + } +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s) @@ -301,6 +332,7 @@ Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s) ), triSurface(s), tolerance_(indexedOctree<treeDataTriSurface>::perturbTol()), + maxTreeDepth_(10), surfaceClosed_(-1) {} @@ -344,6 +376,7 @@ Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io) ) ), tolerance_(indexedOctree<treeDataTriSurface>::perturbTol()), + maxTreeDepth_(10), surfaceClosed_(-1) {} @@ -390,6 +423,7 @@ Foam::triSurfaceMesh::triSurfaceMesh ) ), tolerance_(indexedOctree<treeDataTriSurface>::perturbTol()), + maxTreeDepth_(10), surfaceClosed_(-1) { scalar scaleFactor = 0; @@ -410,6 +444,14 @@ Foam::triSurfaceMesh::triSurfaceMesh Info<< searchableSurface::name() << " : using intersection tolerance " << tolerance_ << endl; } + + + // Have optional non-standard tree-depth to limit storage. + if (dict.readIfPresent("maxTreeDepth", maxTreeDepth_) && maxTreeDepth_ > 0) + { + Info<< searchableSurface::name() << " : using maximum tree depth " + << maxTreeDepth_ << endl; + } } @@ -431,6 +473,17 @@ void Foam::triSurfaceMesh::clearOut() // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +Foam::pointField Foam::triSurfaceMesh::coordinates() const +{ + // Use copy to calculate face centres so they don't get stored + return PrimitivePatch<labelledTri, SubList, const pointField&> + ( + SubList<labelledTri>(*this, triSurface::size()), + triSurface::points() + ).faceCentres(); +} + + void Foam::triSurfaceMesh::movePoints(const pointField& newPoints) { tree_.clear(); @@ -444,15 +497,28 @@ const Foam::indexedOctree<Foam::treeDataTriSurface>& { if (tree_.empty()) { + // Calculate bb without constructing local point numbering. + treeBoundBox bb; + label nPoints; + calcBounds(bb, nPoints); + + if (nPoints != points().size()) + { + WarningIn("triSurfaceMesh::tree() const") + << "Surface " << searchableSurface::name() + << " does not have compact point numbering." + << " Of " << points().size() << " only " << nPoints + << " are used. This might give problems in some routines." + << endl; + } + + // Random number generator. Bit dodgy since not exactly random ;-) Random rndGen(65431); // Slightly extended bb. Slightly off-centred just so on symmetric // geometry there are less face/edge aligned items. - treeBoundBox bb - ( - treeBoundBox(points(), meshPoints()).extend(rndGen, 1E-4) - ); + bb = bb.extend(rndGen, 1E-4); bb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL); bb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL); @@ -465,9 +531,9 @@ const Foam::indexedOctree<Foam::treeDataTriSurface>& ( treeDataTriSurface(*this), bb, - 10, // maxLevel - 10, // leafsize - 3.0 // duplicity + maxTreeDepth_, // maxLevel + 10, // leafsize + 3.0 // duplicity ) ); @@ -494,15 +560,17 @@ const Foam::indexedOctree<Foam::treeDataEdge>& + nInternalEdges() ); + treeBoundBox bb; + label nPoints; + calcBounds(bb, nPoints); + // Random number generator. Bit dodgy since not exactly random ;-) Random rndGen(65431); // Slightly extended bb. Slightly off-centred just so on symmetric // geometry there are less face/edge aligned items. - treeBoundBox bb - ( - treeBoundBox(points(), meshPoints()).extend(rndGen, 1E-4) - ); + + bb = bb.extend(rndGen, 1E-4); bb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL); bb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL); @@ -517,10 +585,10 @@ const Foam::indexedOctree<Foam::treeDataEdge>& localPoints(), // points bEdges // selected edges ), - bb, // bb - 8, // maxLevel - 10, // leafsize - 3.0 // duplicity + bb, // bb + maxTreeDepth_, // maxLevel + 10, // leafsize + 3.0 // duplicity ) ); } @@ -754,24 +822,53 @@ void Foam::triSurfaceMesh::getNormal } +void Foam::triSurfaceMesh::setField(const labelList& values) +{ + autoPtr<triSurfaceLabelField> fldPtr + ( + new triSurfaceLabelField + ( + IOobject + ( + "values", + objectRegistry::time().timeName(), // instance + "triSurface", // local + *this, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + *this, + dimless, + labelField(values) + ) + ); + + // Store field on triMesh + fldPtr.ptr()->store(); +} + + void Foam::triSurfaceMesh::getField ( - const word& fieldName, const List<pointIndexHit>& info, labelList& values ) const { - const triSurfaceLabelField& fld = lookupObject<triSurfaceLabelField> - ( - fieldName - ); - - values.setSize(info.size()); - forAll(info, i) + if (foundObject<triSurfaceLabelField>("values")) { - if (info[i].hit()) + values.setSize(info.size()); + + const triSurfaceLabelField& fld = lookupObject<triSurfaceLabelField> + ( + "values" + ); + + forAll(info, i) { - values[i] = fld[info[i].index()]; + if (info[i].hit()) + { + values[i] = fld[info[i].index()]; + } } } } diff --git a/src/meshTools/searchableSurface/triSurfaceMesh.H b/src/meshTools/searchableSurface/triSurfaceMesh.H index e93b83ecdbb9a04046639c79b666edef979e0c72..dea7c642b896ab21f8670c2e6218b3a491e79c63 100644 --- a/src/meshTools/searchableSurface/triSurfaceMesh.H +++ b/src/meshTools/searchableSurface/triSurfaceMesh.H @@ -71,6 +71,9 @@ private: //- Optional tolerance to use in searches scalar tolerance_; + //- Optional max tree depth of octree + label maxTreeDepth_; + //- Search tree (triangles) mutable autoPtr<indexedOctree<treeDataTriSurface> > tree_; @@ -129,6 +132,11 @@ private: void operator=(const triSurfaceMesh&); +protected: + + //- Calculate (number of)used points and their bounding box + void calcBounds(boundBox& bb, label& nPoints) const; + public: //- Runtime type information @@ -185,6 +193,10 @@ public: return triSurface::size(); } + //- Get representative set of element coordinates + // Usually the element centres (should be of length size()). + virtual pointField coordinates() const; + virtual void findNearest ( const pointField& sample, @@ -236,6 +248,8 @@ public: List<volumeType>& ) const; + // Other + //- Set bounds of surface. Bounds currently set as list of // bounding boxes. The bounds are hints to the surface as for // the range of queries it can expect. faceMap/pointMap can be @@ -249,16 +263,12 @@ public: ) {} - // Other + //- WIP. Store element-wise field. + virtual void setField(const labelList& values); - //- Specific to triSurfaceMesh: from a set of hits (points and + //- WIP. From a set of hits (points and // indices) get the specified field. Misses do not get set. - virtual void getField - ( - const word& fieldName, - const List<pointIndexHit>&, - labelList& values - ) const; + virtual void getField(const List<pointIndexHit>&, labelList&) const; // regIOobject implementation