ENH: change UnsortedMeshedSurface -> meshedSurface for sampledTriSurfaceMesh

- all sampled surface types now consistently use the same storage,
  which allows some more simplifications in the future.

- before/after comparison of the sampledTriSurfaceMesh tested with
  motorbike passenger helmet (serial and parallel). Use the newly added
  'keepIds' functionality to retain the original ids, and can also
  compare them to the original obj file with "GenerateIds" in paraview.
This commit is contained in:
Mark Olesen
2016-11-29 22:56:08 +01:00
parent 3c41b80b38
commit 8b75035f29
3 changed files with 224 additions and 101 deletions

View File

@ -78,6 +78,32 @@ namespace Foam
} }
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
void Foam::sampledTriSurfaceMesh::setZoneMap
(
const surfZoneList& zoneLst,
labelList& zoneIds
)
{
label sz = 0;
forAll(zoneLst, zonei)
{
const surfZone& zn = zoneLst[zonei];
sz += zn.size();
}
zoneIds.setSize(sz);
forAll(zoneLst, zonei)
{
const surfZone& zn = zoneLst[zonei];
// Assign sub-zone Ids
SubList<label>(zoneIds, zn.size(), zn.start()) = zonei;
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
const Foam::indexedOctree<Foam::treeDataFace>& const Foam::indexedOctree<Foam::treeDataFace>&
@ -146,16 +172,11 @@ bool Foam::sampledTriSurfaceMesh::update(const meshSearch& meshSearcher)
// Global numbering for cells/faces - only used to uniquely identify local // Global numbering for cells/faces - only used to uniquely identify local
// elements // elements
globalIndex globalCells globalIndex globalCells(onBoundary() ? mesh().nFaces() : mesh().nCells());
(
(sampleSource_ == cells || sampleSource_ == insideCells)
? mesh().nCells()
: mesh().nFaces()
);
forAll(nearest, i) forAll(nearest, i)
{ {
nearest[i].first() = GREAT; nearest[i].first() = GREAT;
nearest[i].second() = labelMax; nearest[i].second() = labelMax;
} }
@ -174,7 +195,7 @@ bool Foam::sampledTriSurfaceMesh::update(const meshSearch& meshSearcher)
); );
if (nearInfo.hit()) if (nearInfo.hit())
{ {
nearest[triI].first() = magSqr(nearInfo.hitPoint()-fc[triI]); nearest[triI].first() = magSqr(nearInfo.hitPoint()-fc[triI]);
nearest[triI].second() = globalCells.toGlobal(nearInfo.index()); nearest[triI].second() = globalCells.toGlobal(nearInfo.index());
} }
} }
@ -192,7 +213,7 @@ bool Foam::sampledTriSurfaceMesh::update(const meshSearch& meshSearcher)
const label index = cellTree.findInside(fc[triI]); const label index = cellTree.findInside(fc[triI]);
if (index != -1) if (index != -1)
{ {
nearest[triI].first() = 0.0; nearest[triI].first() = 0.0;
nearest[triI].second() = globalCells.toGlobal(index); nearest[triI].second() = globalCells.toGlobal(index);
} }
} }
@ -216,7 +237,7 @@ bool Foam::sampledTriSurfaceMesh::update(const meshSearch& meshSearcher)
); );
if (nearInfo.hit()) if (nearInfo.hit())
{ {
nearest[triI].first() = magSqr(nearInfo.hitPoint()-fc[triI]); nearest[triI].first() = magSqr(nearInfo.hitPoint()-fc[triI]);
nearest[triI].second() = globalCells.toGlobal nearest[triI].second() = globalCells.toGlobal
( (
bTree.shapes().faceLabels()[nearInfo.index()] bTree.shapes().faceLabels()[nearInfo.index()]
@ -270,6 +291,37 @@ bool Foam::sampledTriSurfaceMesh::update(const meshSearch& meshSearcher)
// From original point to compact points // From original point to compact points
labelList reversePointMap(s.points().size(), -1); labelList reversePointMap(s.points().size(), -1);
// Handle region-wise sorting (makes things slightly more complicated)
zoneIds_.setSize(s.size(), -1);
// Better not to use triSurface::sortedZones here,
// since we'll sort ourselves
// Get zone/region sizes used, store under the original region Id
Map<label> zoneSizes;
// Recover region names from the input surface
Map<word> zoneNames;
{
const geometricSurfacePatchList& patches = s.patches();
forAll(patches, patchi)
{
zoneNames.set
(
patchi,
(
patches[patchi].name().empty()
? Foam::name("patch%d", patchi)
: patches[patchi].name()
)
);
zoneSizes.set(patchi, 0);
}
}
{ {
label newPointi = 0; label newPointi = 0;
label newFacei = 0; label newFacei = 0;
@ -278,57 +330,139 @@ bool Foam::sampledTriSurfaceMesh::update(const meshSearch& meshSearcher)
{ {
if (cellOrFaceLabels[facei] != -1) if (cellOrFaceLabels[facei] != -1)
{ {
faceMap[newFacei++] = facei;
const triSurface::FaceType& f = s[facei]; const triSurface::FaceType& f = s[facei];
const label regionid = f.region();
Map<label>::iterator fnd = zoneSizes.find(regionid);
if (fnd != zoneSizes.end())
{
fnd()++;
}
else
{
// This shouldn't happen
zoneSizes.insert(regionid, 1);
zoneNames.set
(
regionid,
Foam::name("patch%d", regionid)
);
}
// Store new faces compact
faceMap[newFacei] = facei;
zoneIds_[newFacei] = regionid;
++newFacei;
// Renumber face points
forAll(f, fp) forAll(f, fp)
{ {
if (reversePointMap[f[fp]] == -1) const label labI = f[fp];
if (reversePointMap[labI] == -1)
{ {
pointMap[newPointi] = f[fp]; pointMap[newPointi] = labI;
reversePointMap[f[fp]] = newPointi++; reversePointMap[labI] = newPointi++;
} }
} }
} }
} }
// Trim
faceMap.setSize(newFacei); faceMap.setSize(newFacei);
zoneIds_.setSize(newFacei);
pointMap.setSize(newPointi); pointMap.setSize(newPointi);
} }
// Assign start/size (and name) to the newZones
// re-use the lookup to map (zoneId => zoneI)
surfZoneList zoneLst(zoneSizes.size());
label start = 0;
label zoneI = 0;
forAllIter(Map<label>, zoneSizes, iter)
{
// No negative regionids, so Map<label> sorts properly
const label regionid = iter.key();
word name;
Map<word>::const_iterator fnd = zoneNames.find(regionid);
if (fnd != zoneNames.end())
{
name = fnd();
}
if (name.empty())
{
name = ::Foam::name("patch%d", regionid);
}
zoneLst[zoneI] = surfZone
(
name,
0, // initialize with zero size
start,
zoneI
);
// Adjust start for the next zone and save (zoneId => zoneI) mapping
start += iter();
iter() = zoneI++;
}
// At this stage:
// - faceMap to map the (unsorted) compact to original triangle
// - zoneIds for the next sorting
// - zoneSizes contains region -> count information
// Rebuild the faceMap for the sorted order
labelList sortedFaceMap(faceMap.size());
forAll(zoneIds_, facei)
{
label zonei = zoneIds_[facei];
label sortedFacei = zoneLst[zonei].start() + zoneLst[zonei].size()++;
sortedFaceMap[sortedFacei] = faceMap[facei];
}
// zoneIds are now simply flat values
setZoneMap(zoneLst, zoneIds_);
// Replace the faceMap with the properly sorted face map
faceMap.transfer(sortedFaceMap);
if (keepIds_) if (keepIds_)
{ {
originalIds_ = faceMap; originalIds_ = faceMap;
} }
// Subset cellOrFaceLabels // Subset cellOrFaceLabels (for compact faces)
cellOrFaceLabels = UIndirectList<label>(cellOrFaceLabels, faceMap)(); cellOrFaceLabels = UIndirectList<label>(cellOrFaceLabels, faceMap)();
// Store any face per point (without using pointFaces()) // Store any face per point (without using pointFaces())
labelList pointToFace(pointMap.size()); labelList pointToFace(pointMap.size());
// Create faces and points for subsetted surface // Create faces and points for subsetted surface
faceList& faces = this->storedFaces(); faceList& surfFaces = this->storedFaces();
faces.setSize(faceMap.size()); surfFaces.setSize(faceMap.size());
labelList& zoneIds = this->storedZoneIds(); this->storedZones().transfer(zoneLst);
zoneIds.setSize(faceMap.size());
forAll(faceMap, i) forAll(faceMap, facei)
{ {
const labelledTri& f = s[faceMap[i]]; const labelledTri& origF = s[faceMap[facei]];
triFace newF face& f = surfFaces[facei];
(
reversePointMap[f[0]],
reversePointMap[f[1]],
reversePointMap[f[2]]
);
faces[i] = newF.triFaceFace();
zoneIds[i] = f.region(); // preserve zone information
forAll(newF, fp) f = triFace
(
reversePointMap[origF[0]],
reversePointMap[origF[1]],
reversePointMap[origF[2]]
);
forAll(f, fp)
{ {
pointToFace[newF[fp]] = i; pointToFace[f[fp]] = facei;
} }
} }
@ -418,7 +552,7 @@ bool Foam::sampledTriSurfaceMesh::update(const meshSearch& meshSearcher)
const point& pt = points()[pointi]; const point& pt = points()[pointi];
label facei = cellOrFaceLabels[pointToFace[pointi]]; label facei = cellOrFaceLabels[pointToFace[pointi]];
sampleElements_[pointi] = facei; sampleElements_[pointi] = facei;
samplePoints_[pointi] = mesh().faces()[facei].nearestPoint samplePoints_[pointi] = mesh().faces()[facei].nearestPoint
( (
pt, pt,
mesh().points() mesh().points()
@ -429,16 +563,16 @@ bool Foam::sampledTriSurfaceMesh::update(const meshSearch& meshSearcher)
else else
{ {
// if sampleSource_ == cells: // if sampleSource_ == cells:
// samplePoints_ : n/a
// sampleElements_ : per surface triangle the cell // sampleElements_ : per surface triangle the cell
// samplePoints_ : n/a
// if sampleSource_ == insideCells: // if sampleSource_ == insideCells:
// samplePoints_ : n/a
// sampleElements_ : -1 or per surface triangle the cell // sampleElements_ : -1 or per surface triangle the cell
// else:
// samplePoints_ : n/a // samplePoints_ : n/a
// else:
// sampleElements_ : per surface triangle the boundary face // sampleElements_ : per surface triangle the boundary face
samplePoints_.clear(); // samplePoints_ : n/a
sampleElements_.transfer(cellOrFaceLabels); sampleElements_.transfer(cellOrFaceLabels);
samplePoints_.clear();
} }
@ -448,77 +582,47 @@ bool Foam::sampledTriSurfaceMesh::update(const meshSearch& meshSearcher)
OFstream str(mesh().time().path()/"surfaceToMesh.obj"); OFstream str(mesh().time().path()/"surfaceToMesh.obj");
Info<< "Dumping correspondence from local surface (points or faces)" Info<< "Dumping correspondence from local surface (points or faces)"
<< " to mesh (cells or faces) to " << str.name() << endl; << " to mesh (cells or faces) to " << str.name() << endl;
label vertI = 0;
const vectorField& centres =
(
onBoundary()
? mesh().faceCentres()
: mesh().cellCentres()
);
if (sampledSurface::interpolate()) if (sampledSurface::interpolate())
{ {
if (sampleSource_ == cells || sampleSource_ == insideCells) label vertI = 0;
forAll(samplePoints_, pointi)
{ {
forAll(samplePoints_, pointi) meshTools::writeOBJ(str, points()[pointi]);
{ vertI++;
meshTools::writeOBJ(str, points()[pointi]);
vertI++;
meshTools::writeOBJ(str, samplePoints_[pointi]); meshTools::writeOBJ(str, samplePoints_[pointi]);
vertI++; vertI++;
label celli = sampleElements_[pointi]; label elemi = sampleElements_[pointi];
meshTools::writeOBJ(str, mesh().cellCentres()[celli]); meshTools::writeOBJ(str, centres[elemi]);
vertI++; vertI++;
str << "l " << vertI-2 << ' ' << vertI-1 << ' ' << vertI str << "l " << vertI-2 << ' ' << vertI-1 << ' ' << vertI << nl;
<< nl;
}
}
else
{
forAll(samplePoints_, pointi)
{
meshTools::writeOBJ(str, points()[pointi]);
vertI++;
meshTools::writeOBJ(str, samplePoints_[pointi]);
vertI++;
label facei = sampleElements_[pointi];
meshTools::writeOBJ(str, mesh().faceCentres()[facei]);
vertI++;
str << "l " << vertI-2 << ' ' << vertI-1 << ' ' << vertI
<< nl;
}
} }
} }
else else
{ {
if (sampleSource_ == cells || sampleSource_ == insideCells) label vertI = 0;
forAll(sampleElements_, triI)
{ {
forAll(sampleElements_, triI) meshTools::writeOBJ(str, faceCentres()[triI]);
{ vertI++;
meshTools::writeOBJ(str, faceCentres()[triI]);
vertI++;
label celli = sampleElements_[triI]; label elemi = sampleElements_[triI];
meshTools::writeOBJ(str, mesh().cellCentres()[celli]); meshTools::writeOBJ(str, centres[elemi]);
vertI++; vertI++;
str << "l " << vertI-1 << ' ' << vertI << nl; str << "l " << vertI-1 << ' ' << vertI << nl;
}
}
else
{
forAll(sampleElements_, triI)
{
meshTools::writeOBJ(str, faceCentres()[triI]);
vertI++;
label facei = sampleElements_[triI];
meshTools::writeOBJ(str, mesh().faceCentres()[facei]);
vertI++;
str << "l " << vertI-1 << ' ' << vertI << nl;
}
} }
} }
} }
needsUpdate_ = false; needsUpdate_ = false;
return true; return true;
} }
@ -553,6 +657,7 @@ Foam::sampledTriSurfaceMesh::sampledTriSurfaceMesh
needsUpdate_(true), needsUpdate_(true),
keepIds_(false), keepIds_(false),
originalIds_(), originalIds_(),
zoneIds_(),
sampleElements_(0), sampleElements_(0),
samplePoints_(0) samplePoints_(0)
{} {}
@ -584,6 +689,7 @@ Foam::sampledTriSurfaceMesh::sampledTriSurfaceMesh
needsUpdate_(true), needsUpdate_(true),
keepIds_(dict.lookupOrDefault<Switch>("keepIds", false)), keepIds_(dict.lookupOrDefault<Switch>("keepIds", false)),
originalIds_(), originalIds_(),
zoneIds_(),
sampleElements_(0), sampleElements_(0),
samplePoints_(0) samplePoints_(0)
{} {}
@ -617,6 +723,7 @@ Foam::sampledTriSurfaceMesh::sampledTriSurfaceMesh
needsUpdate_(true), needsUpdate_(true),
keepIds_(false), keepIds_(false),
originalIds_(), originalIds_(),
zoneIds_(),
sampleElements_(0), sampleElements_(0),
samplePoints_(0) samplePoints_(0)
{} {}
@ -646,6 +753,7 @@ bool Foam::sampledTriSurfaceMesh::expire()
sampledSurface::clearGeom(); sampledSurface::clearGeom();
MeshStorage::clear(); MeshStorage::clear();
zoneIds_.clear();
originalIds_.clear(); originalIds_.clear();
boundaryTreePtr_.clear(); boundaryTreePtr_.clear();

View File

@ -62,6 +62,7 @@ Description
SourceFiles SourceFiles
sampledTriSurfaceMesh.C sampledTriSurfaceMesh.C
sampledTriSurfaceMeshTemplates.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -71,6 +72,7 @@ SourceFiles
#include "sampledSurface.H" #include "sampledSurface.H"
#include "triSurfaceMesh.H" #include "triSurfaceMesh.H"
#include "MeshedSurface.H" #include "MeshedSurface.H"
#include "MeshedSurfacesFwd.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -87,7 +89,7 @@ class meshSearch;
class sampledTriSurfaceMesh class sampledTriSurfaceMesh
: :
public sampledSurface, public sampledSurface,
public UnsortedMeshedSurface<face> public meshedSurface
{ {
public: public:
//- Types of communications //- Types of communications
@ -95,13 +97,13 @@ public:
{ {
cells, cells,
insideCells, insideCells,
boundaryFaces, boundaryFaces
}; };
private: private:
//- Private typedefs for convenience //- Private typedefs for convenience
typedef UnsortedMeshedSurface<face> MeshStorage; typedef meshedSurface MeshStorage;
// Private data // Private data
@ -127,6 +129,9 @@ private:
//- Search tree for all non-coupled boundary faces //- Search tree for all non-coupled boundary faces
mutable autoPtr<indexedOctree<treeDataFace>> boundaryTreePtr_; mutable autoPtr<indexedOctree<treeDataFace>> boundaryTreePtr_;
//- For compatibility with the meshSurf interface
labelList zoneIds_;
//- From local surface triangle to mesh cell/face. //- From local surface triangle to mesh cell/face.
labelList sampleElements_; labelList sampleElements_;
@ -194,6 +199,10 @@ public:
// Member Functions // Member Functions
//- Set new zoneIds list based on the surfZoneList information
static void setZoneMap(const surfZoneList&, labelList& zoneIds);
//- Does the surface need an update? //- Does the surface need an update?
virtual bool needsUpdate() const; virtual bool needsUpdate() const;
@ -226,7 +235,7 @@ public:
//- Const access to per-face zone/region information //- Const access to per-face zone/region information
virtual const labelList& zoneIds() const virtual const labelList& zoneIds() const
{ {
return MeshStorage::zoneIds(); return zoneIds_;
} }
//- Face area vectors //- Face area vectors
@ -260,6 +269,12 @@ public:
return originalIds_; return originalIds_;
} }
//- Sampling boundary values instead of cell values
bool onBoundary() const
{
return sampleSource_ == boundaryFaces;
}
//- Sample field on surface //- Sample field on surface
virtual tmp<scalarField> sample virtual tmp<scalarField> sample
@ -323,7 +338,7 @@ public:
const interpolation<tensor>& const interpolation<tensor>&
) const; ) const;
//- Write //- Write information
virtual void print(Ostream&) const; virtual void print(Ostream&) const;
}; };

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -38,7 +38,7 @@ Foam::sampledTriSurfaceMesh::sampleField
tmp<Field<Type>> tvalues(new Field<Type>(sampleElements_.size())); tmp<Field<Type>> tvalues(new Field<Type>(sampleElements_.size()));
Field<Type>& values = tvalues.ref(); Field<Type>& values = tvalues.ref();
if (sampleSource_ == cells || sampleSource_ == insideCells) if (!onBoundary())
{ {
// Sample cells // Sample cells
@ -52,7 +52,7 @@ Foam::sampledTriSurfaceMesh::sampleField
// Sample boundary faces // Sample boundary faces
const polyBoundaryMesh& pbm = mesh().boundaryMesh(); const polyBoundaryMesh& pbm = mesh().boundaryMesh();
label nBnd = mesh().nFaces()-mesh().nInternalFaces(); const label nBnd = mesh().nFaces()-mesh().nInternalFaces();
// Create flat boundary field // Create flat boundary field
@ -94,7 +94,7 @@ Foam::sampledTriSurfaceMesh::interpolateField
tmp<Field<Type>> tvalues(new Field<Type>(sampleElements_.size())); tmp<Field<Type>> tvalues(new Field<Type>(sampleElements_.size()));
Field<Type>& values = tvalues.ref(); Field<Type>& values = tvalues.ref();
if (sampleSource_ == cells || sampleSource_ == insideCells) if (!onBoundary())
{ {
// Sample cells. // Sample cells.