From 008a4333301fc1000d0424446bdbd204de17ba3b Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Wed, 26 Feb 2020 00:12:14 +0100 Subject: [PATCH] ENH: keep element ids when reading/writing meshed surfaces (#1600) --- .../sampledMeshedSurface.C | 20 ++------ .../sampledMeshedSurface.H | 21 +++----- .../sampledSurface/sampledSurface.H | 7 --- .../sampledSurfaces/sampledSurfaces.C | 7 ++- .../sampledSurfaces/sampledSurfaces.H | 4 +- src/surfMesh/MeshedSurface/MeshedSurface.C | 50 ++++++++++++++++++- src/surfMesh/MeshedSurface/MeshedSurface.H | 20 ++++++++ .../MeshedSurface/MeshedSurfaceCore.C | 12 +++-- .../MeshedSurface/MeshedSurfaceZones.C | 16 ++++++ .../MeshedSurfaceProxy/MeshedSurfaceProxy.C | 6 ++- .../MeshedSurfaceProxy/MeshedSurfaceProxy.H | 23 ++++++++- src/surfMesh/mergedSurf/mergedSurf.C | 7 +++ src/surfMesh/mergedSurf/mergedSurf.H | 8 +++ src/surfMesh/meshedSurf/meshedSurf.H | 6 +++ src/surfMesh/meshedSurf/meshedSurfRef.H | 21 ++++++-- .../surfaceFormats/nas/NASsurfaceFormat.C | 48 ++++++++++++++++-- .../surfaceFormats/obj/OBJsurfaceFormat.C | 4 +- .../starcd/STARCDsurfaceFormat.C | 38 +++++++++++++- .../surfaceFormats/vtk/VTKsurfaceFormat.C | 6 ++- .../writers/nastran/nastranSurfaceWriter.C | 24 +++++++++ .../nastran/nastranSurfaceWriterImpl.C | 22 ++++++++ .../writers/starcd/starcdSurfaceWriter.C | 9 +++- 22 files changed, 318 insertions(+), 61 deletions(-) diff --git a/src/sampling/sampledSurface/sampledMeshedSurface/sampledMeshedSurface.C b/src/sampling/sampledSurface/sampledMeshedSurface/sampledMeshedSurface.C index 3198116b9f0..2373d74acb8 100644 --- a/src/sampling/sampledSurface/sampledMeshedSurface/sampledMeshedSurface.C +++ b/src/sampling/sampledSurface/sampledMeshedSurface/sampledMeshedSurface.C @@ -118,7 +118,7 @@ inline static IOobject selectReadIO(const word& name, const Time& runTime) void Foam::sampledMeshedSurface::setZoneMap() { - // Ensure zoneIds_ are correctly populated + // Populate zoneIds_ based on surfZone information const meshedSurface& s = static_cast<const meshedSurface&>(*this); @@ -279,19 +279,10 @@ bool Foam::sampledMeshedSurface::update(const meshSearch& meshSearcher) s = surface_.subsetMesh(facesToSubset, pointMap, faceMap); + // Ensure zoneIds_ are indeed correct setZoneMap(); - // This is currently only partially useful - if (keepIds_) - { - originalIds_ = faceMap; - } - else - { - originalIds_.clear(); - } - // Subset cellOrFaceLabels (for compact faces) cellOrFaceLabels = labelUIndList(cellOrFaceLabels, faceMap)(); @@ -492,8 +483,7 @@ Foam::sampledMeshedSurface::sampledMeshedSurface ), sampleSource_(sampleSource), needsUpdate_(true), - keepIds_(false), - originalIds_(), + keepIds_(true), zoneIds_(), sampleElements_(), samplePoints_() @@ -524,8 +514,7 @@ Foam::sampledMeshedSurface::sampledMeshedSurface ), sampleSource_(samplingSourceNames_.get("source", dict)), needsUpdate_(true), - keepIds_(dict.lookupOrDefault("keepIds", false)), - originalIds_(), + keepIds_(dict.lookupOrDefault("keepIds", true)), zoneIds_(), sampleElements_(), samplePoints_() @@ -610,7 +599,6 @@ bool Foam::sampledMeshedSurface::expire() MeshStorage::clear(); zoneIds_.clear(); - originalIds_.clear(); sampleElements_.clear(); samplePoints_.clear(); diff --git a/src/sampling/sampledSurface/sampledMeshedSurface/sampledMeshedSurface.H b/src/sampling/sampledSurface/sampledMeshedSurface/sampledMeshedSurface.H index 05da864184a..bec78a6796b 100644 --- a/src/sampling/sampledSurface/sampledMeshedSurface/sampledMeshedSurface.H +++ b/src/sampling/sampledSurface/sampledMeshedSurface/sampledMeshedSurface.H @@ -86,7 +86,7 @@ Usage surface | surface name in triSurface/ | yes | patches | Limit to named surface regions (wordRes) | no | source | cells/insideCells/boundaryFaces | yes | - keepIds | pass through id numbering | no | false + keepIds | pass through id numbering | no | true \endtable SourceFiles @@ -153,10 +153,6 @@ private: //- Retain element ids/order of original surface bool keepIds_; - //- List of element ids/order of the original surface, - //- when keepIds is active. - labelList originalIds_; - //- For compatibility with the meshSurf interface labelList zoneIds_; @@ -255,6 +251,12 @@ public: return zoneIds_; } + //- Per-face identifier (eg, element Id) + virtual const labelList& faceIds() const + { + return MeshStorage::faceIds(); + } + //- Face area vectors virtual const vectorField& Sf() const { @@ -276,14 +278,7 @@ public: //- If element ids/order of the original surface are kept virtual bool hasFaceIds() const { - return keepIds_; - } - - //- List of element ids/order of the original surface, - // when keepIds is active. - virtual const labelList& originalIds() const - { - return originalIds_; + return keepIds_ && !MeshStorage::faceIds().empty(); } //- Sampling boundary values instead of cell values diff --git a/src/sampling/sampledSurface/sampledSurface/sampledSurface.H b/src/sampling/sampledSurface/sampledSurface/sampledSurface.H index 6dc8d28e69a..b21df8349e1 100644 --- a/src/sampling/sampledSurface/sampledSurface/sampledSurface.H +++ b/src/sampling/sampledSurface/sampledSurface/sampledSurface.H @@ -340,13 +340,6 @@ public: return false; } - //- List of element ids/order of the original surface, - //- when hasFaceIds is true. - virtual const labelList& originalIds() const - { - return labelList::null(); - } - // General registry storage (optional) diff --git a/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C b/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C index 0f133b402c0..a87a22d4801 100644 --- a/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C +++ b/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C @@ -558,10 +558,15 @@ bool Foam::sampledSurfaces::performAction(unsigned request) // Write original ids if (s.hasFaceIds() && !s.interpolate()) { + // This is still quite horrible. + + Field<label> ids(s.faceIds()); + ids += label(1); // From 0-based to 1-based + writeSurface ( outWriter, - Field<label>(s.originalIds()), + ids, "Ids" ); } diff --git a/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.H b/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.H index a5dd2fe7a5f..641a7bf2bc3 100644 --- a/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.H +++ b/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.H @@ -69,7 +69,7 @@ Description } surfaces - ( + { f0surf { type meshedSurface; @@ -88,7 +88,7 @@ Description // Optional: registry storage store true } - ); + } } \endverbatim diff --git a/src/surfMesh/MeshedSurface/MeshedSurface.C b/src/surfMesh/MeshedSurface/MeshedSurface.C index 48330fb0a1b..27c762a1e15 100644 --- a/src/surfMesh/MeshedSurface/MeshedSurface.C +++ b/src/surfMesh/MeshedSurface/MeshedSurface.C @@ -167,6 +167,7 @@ template<class Face> Foam::MeshedSurface<Face>::MeshedSurface() : ParentType(List<Face>(), pointField()), + faceIds_(), zones_() {} @@ -178,6 +179,7 @@ Foam::MeshedSurface<Face>::MeshedSurface ) : ParentType(surf.surfFaces(), surf.points()), + faceIds_(surf.faceIds_), zones_(surf.zones_) {} @@ -238,6 +240,7 @@ Foam::MeshedSurface<Face>::MeshedSurface ) : ParentType(faceLst, pointLst), // Copy construct + faceIds_(), zones_(zoneLst) {} @@ -251,6 +254,7 @@ Foam::MeshedSurface<Face>::MeshedSurface ) : ParentType(faceLst, pointLst, true), // Move construct + faceIds_(), zones_(zoneLst) {} @@ -265,6 +269,7 @@ Foam::MeshedSurface<Face>::MeshedSurface ) : ParentType(faceLst, pointLst), // Copy construct + faceIds_(), zones_() { if (zoneSizes.size()) @@ -291,6 +296,7 @@ Foam::MeshedSurface<Face>::MeshedSurface ) : ParentType(faceLst, pointLst, true), // Move construct + faceIds_(), zones_() { if (zoneSizes.size()) @@ -559,6 +565,7 @@ void Foam::MeshedSurface<Face>::clear() storedPoints().clear(); storedFaces().clear(); + storedFaceIds().clear(); storedZones().clear(); } @@ -678,6 +685,17 @@ bool Foam::MeshedSurface<Face>::stitchFaces faceMap.resize(newFacei); faceLst.resize(newFacei); + // The faceMap is a newToOld mapping and only removes elements + if (faceIds_.size()) + { + forAll(faceMap, facei) + { + faceIds_[facei] = faceIds_[faceMap[facei]]; + } + + faceIds_.resize(newFacei); + } + remapFaces(faceMap); } faceMap.clear(); @@ -837,6 +855,17 @@ bool Foam::MeshedSurface<Face>::checkFaces faceMap.resize(newFacei); faceLst.resize(newFacei); + // The faceMap is a newToOld mapping and only removes elements + if (faceIds_.size()) + { + forAll(faceMap, facei) + { + faceIds_[facei] = faceIds_[faceMap[facei]]; + } + + faceIds_.resize(newFacei); + } + remapFaces(faceMap); } faceMap.clear(); @@ -967,6 +996,8 @@ Foam::label Foam::MeshedSurface<Face>::triangulate return 0; } + this->storedFaceIds().clear(); // Invalid or misleading + List<Face> newFaces(nTri); List<label> faceMap; @@ -1106,11 +1137,20 @@ Foam::MeshedSurface<Face>::subsetMeshImpl zone.size() = newFacei - zone.start(); } + + // Subset of faceIds. Can be empty. + labelList newFaceIds; + if (faceIds_.size()) + { + newFaceIds = labelUIndList(faceIds_, faceMap); + } + // Construct the sub-surface MeshedSurface<Face> newSurf; newSurf.storedFaces().transfer(newFaces); newSurf.storedPoints().transfer(newPoints); newSurf.storedZones().transfer(newZones); + newSurf.storedFaceIds().transfer(newFaceIds); return newSurf; } @@ -1212,6 +1252,7 @@ void Foam::MeshedSurface<Face>::swap this->storedPoints().swap(surf.storedPoints()); this->storedFaces().swap(surf.storedFaces()); this->storedZones().swap(surf.storedZones()); + this->storedFaceIds().swap(surf.storedFaceIds()); } @@ -1227,6 +1268,7 @@ void Foam::MeshedSurface<Face>::transfer this->storedPoints().transfer(pointLst); this->storedFaces().transfer(faceLst); this->storedZones().clear(); + this->storedFaceIds().clear(); // Likely to be invalid } @@ -1246,6 +1288,7 @@ void Foam::MeshedSurface<Face>::transfer this->storedPoints().transfer(surf.storedPoints()); this->storedFaces().transfer(surf.storedFaces()); this->storedZones().transfer(surf.storedZones()); + this->storedFaceIds().transfer(surf.storedFaceIds()); surf.clear(); } @@ -1304,6 +1347,8 @@ void Foam::MeshedSurface<Face>::swapFaces(List<Face>& faces) { ParentType::clearOut(); // Topology changes + this->storedFaceIds().clear(); // Likely to be invalid + this->storedFaces().swap(faces); } @@ -1373,6 +1418,7 @@ void Foam::MeshedSurface<Face>::operator=(const MeshedSurface<Face>& surf) this->storedPoints() = surf.points(); this->storedFaces() = surf.surfFaces(); + this->storedFaceIds() = surf.faceIds(); this->storedZones() = surf.surfZones(); } @@ -1391,7 +1437,9 @@ Foam::MeshedSurface<Face>::operator Foam::MeshedSurfaceProxy<Face>() const ( this->points(), this->surfFaces(), - this->surfZones() + this->surfZones(), + labelUList::null(), // faceMap = none + this->faceIds() ); } diff --git a/src/surfMesh/MeshedSurface/MeshedSurface.H b/src/surfMesh/MeshedSurface/MeshedSurface.H index f6b60673831..d132ae34571 100644 --- a/src/surfMesh/MeshedSurface/MeshedSurface.H +++ b/src/surfMesh/MeshedSurface/MeshedSurface.H @@ -120,6 +120,11 @@ private: // Private Data + //- Face ids. + // If these exist, they are typically arise from reading a mesh + // format from another CAE software (eg, NASTRAN, STARCD, ...) + labelList faceIds_; + //- Zone information // (face ordering nFaces/startFace only used during reading/writing) surfZoneList zones_; @@ -169,6 +174,12 @@ protected: return static_cast<List<Face>&>(*this); } + //- Non-const access to face ids + labelList& storedFaceIds() + { + return faceIds_; + } + //- Non-const access to the zones surfZoneList& storedZones() { @@ -180,6 +191,7 @@ protected: ( DynamicList<Face>& unsortedFaces, DynamicList<label>& zoneIds, + DynamicList<label>& elemIds, bool sorted ); @@ -391,6 +403,14 @@ public: return static_cast<const List<Face>&>(*this); } + //- Return const access to faces ids + // If these exist, they are typically arise from reading a mesh + // format from another CAE software (eg, NASTRAN, STARCD, ...) + const labelList& faceIds() const + { + return faceIds_; + } + //- Const access to the surface zones. // If zones are defined, they must be contiguous and cover the // entire surface diff --git a/src/surfMesh/MeshedSurface/MeshedSurfaceCore.C b/src/surfMesh/MeshedSurface/MeshedSurfaceCore.C index 20961c4f9af..b90331b4a2f 100644 --- a/src/surfMesh/MeshedSurface/MeshedSurfaceCore.C +++ b/src/surfMesh/MeshedSurface/MeshedSurfaceCore.C @@ -52,9 +52,11 @@ namespace Foam MeshedSurface<face>& surf ) { - // First triangulate - // - slightly wasteful for space, but adjusts the zones too! + // First triangulate. + // Potentially wasteful of space, but adjusts zones and + // invalidates the faceIds surf.triangulate(); + this->storedPoints().transfer(surf.storedPoints()); this->storedZones().transfer(surf.storedZones()); @@ -83,9 +85,11 @@ namespace Foam MeshedSurface<face>& surf ) { - // First triangulate - // - slightly wasteful for space, but adjusts the zones too! + // First triangulate. + // Potentially wasteful of space, but adjusts zones and + // invalidates the faceIds surf.triangulate(); + this->storedPoints().transfer(surf.storedPoints()); this->storedZones().transfer(surf.storedZones()); diff --git a/src/surfMesh/MeshedSurface/MeshedSurfaceZones.C b/src/surfMesh/MeshedSurface/MeshedSurfaceZones.C index 223c28afcd6..051a413cbec 100644 --- a/src/surfMesh/MeshedSurface/MeshedSurfaceZones.C +++ b/src/surfMesh/MeshedSurface/MeshedSurfaceZones.C @@ -71,6 +71,7 @@ void Foam::MeshedSurface<Face>::sortFacesAndStore ( DynamicList<Face>& unsortedFaces, DynamicList<label>& zoneIds, + DynamicList<label>& elemIds, bool sorted ) { @@ -84,10 +85,16 @@ void Foam::MeshedSurface<Face>::sortFacesAndStore sorted = true; } + if (elemIds.size() != nInputFaces) + { + elemIds.clear(); + } + if (sorted) { // No additional sorting required this->storedFaces().transfer(unsortedFaces); + this->storedFaceIds().transfer(elemIds); return; } @@ -106,6 +113,15 @@ void Foam::MeshedSurface<Face>::sortFacesAndStore // Can use transfer, faceMap is unique newFaces[facei].transfer(unsortedFaces[faceMap[facei]]); } + + auto& newFaceIds = this->storedFaceIds(); + newFaceIds.resize(elemIds.size()); + + // Element ids in sorted order + forAll(newFaceIds, facei) + { + newFaceIds[facei] = elemIds[faceMap[facei]]; + } } diff --git a/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.C b/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.C index c2058125636..bec7309364c 100644 --- a/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.C +++ b/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.C @@ -223,13 +223,15 @@ Foam::MeshedSurfaceProxy<Face>::MeshedSurfaceProxy const pointField& pointLst, const UList<Face>& faceLst, const UList<surfZone>& zoneLst, - const labelUList& faceMap + const labelUList& faceMap, + const labelUList& faceIdsLst ) : points_(pointLst), faces_(faceLst), zones_(zoneLst), - faceMap_(faceMap) + faceMap_(faceMap), + faceIds_(faceIdsLst) {} diff --git a/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.H b/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.H index 12e4891b180..7aeda7f0fca 100644 --- a/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.H +++ b/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.H @@ -31,6 +31,9 @@ Description A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats. + The constructor interface is fat and ugly, but is largely encapsulated + by conversion operators in other classes. + SourceFiles MeshedSurfaceProxy.C MeshedSurfaceProxys.C @@ -73,6 +76,9 @@ class MeshedSurfaceProxy const UList<label>& faceMap_; + const UList<label>& faceIds_; + + public: // Public Typedefs @@ -101,8 +107,9 @@ public: ( const pointField& pointLst, const UList<Face>& faceLst, - const UList<surfZone>& zoneLst = List<surfZone>(), - const labelUList& faceMap = labelUList::null() + const UList<surfZone>& zoneLst = UList<surfZone>::null(), + const labelUList& faceMap = labelUList::null(), + const labelUList& faceIdLst = labelUList::null() ); @@ -183,12 +190,24 @@ public: return faceMap_; } + //- Const access to the faceIds, zero-sized when unused + const labelUList& faceIds() const + { + return faceIds_; + } + //- Can/should use faceMap? bool useFaceMap() const { return faceMap_.size() == faces_.size(); } + //- Possible to use faceIds? + bool useFaceIds() const + { + return faceIds_.size() == faces_.size(); + } + //- Count number of triangles. inline label nTriangles() const; diff --git a/src/surfMesh/mergedSurf/mergedSurf.C b/src/surfMesh/mergedSurf/mergedSurf.C index fc0f2ed500c..2db9ada9b22 100644 --- a/src/surfMesh/mergedSurf/mergedSurf.C +++ b/src/surfMesh/mergedSurf/mergedSurf.C @@ -61,6 +61,7 @@ Foam::mergedSurf::mergedSurf const pointField& unmergedPoints, const faceList& unmergedFaces, const labelList& origZoneIds, + const labelList& origFaceIds, const scalar mergeDim ) : @@ -71,6 +72,7 @@ Foam::mergedSurf::mergedSurf unmergedPoints, unmergedFaces, origZoneIds, + origFaceIds, mergeDim ); } @@ -91,6 +93,7 @@ void Foam::mergedSurf::clear() pointsMap_.clear(); zoneIds_.clear(); + faceIds_.clear(); } @@ -106,6 +109,7 @@ bool Foam::mergedSurf::merge unmergedSurface.points(), unmergedSurface.faces(), unmergedSurface.zoneIds(), + unmergedSurface.faceIds(), mergeDim ); } @@ -124,6 +128,7 @@ bool Foam::mergedSurf::merge unmergedPoints, unmergedFaces, labelList(), + labelList(), mergeDim ); } @@ -134,6 +139,7 @@ bool Foam::mergedSurf::merge const pointField& unmergedPoints, const faceList& unmergedFaces, const labelList& origZoneIds, + const labelList& origFaceIds, const scalar mergeDim ) { @@ -160,6 +166,7 @@ bool Foam::mergedSurf::merge // Now handle per-face information globalIndex::gatherOp(origZoneIds, zoneIds_); + globalIndex::gatherOp(origFaceIds, faceIds_); return true; } diff --git a/src/surfMesh/mergedSurf/mergedSurf.H b/src/surfMesh/mergedSurf/mergedSurf.H index f2adba45295..1b03e8e8743 100644 --- a/src/surfMesh/mergedSurf/mergedSurf.H +++ b/src/surfMesh/mergedSurf/mergedSurf.H @@ -96,6 +96,7 @@ public: const pointField& unmergedPoints, const faceList& unmergedFaces, const labelList& origZoneIds, + const labelList& origFaceIds, const scalar mergeDim ); @@ -133,6 +134,12 @@ public: return zoneIds_; } + //- Per-face identifier (eg, element Id) + virtual const labelList& faceIds() const + { + return faceIds_; + } + //- Map for reordered points (old-to-new) const labelList& pointsMap() const { @@ -166,6 +173,7 @@ public: const pointField& unmergedPoints, const faceList& unmergedFaces, const labelList& origZoneIds, + const labelList& origFaceIds, const scalar mergeDim ); diff --git a/src/surfMesh/meshedSurf/meshedSurf.H b/src/surfMesh/meshedSurf/meshedSurf.H index 36420372e36..6933b5eed21 100644 --- a/src/surfMesh/meshedSurf/meshedSurf.H +++ b/src/surfMesh/meshedSurf/meshedSurf.H @@ -79,6 +79,12 @@ public: { return labelList::null(); } + + //- Per-face identifier (eg, element Id) + virtual const labelList& faceIds() const + { + return labelList::null(); + } }; diff --git a/src/surfMesh/meshedSurf/meshedSurfRef.H b/src/surfMesh/meshedSurf/meshedSurfRef.H index 7ec13c203b8..c52d35363b3 100644 --- a/src/surfMesh/meshedSurf/meshedSurfRef.H +++ b/src/surfMesh/meshedSurf/meshedSurfRef.H @@ -53,6 +53,7 @@ class meshedSurfRef std::reference_wrapper<const pointField> points_; std::reference_wrapper<const faceList> faces_; std::reference_wrapper<const labelList> zoneIds_; + std::reference_wrapper<const labelList> faceIds_; public: @@ -64,7 +65,8 @@ public: : points_(std::cref<pointField>(pointField::null())), faces_(std::cref<faceList>(faceList::null())), - zoneIds_(std::cref<labelList>(labelList::null())) + zoneIds_(std::cref<labelList>(labelList::null())), + faceIds_(std::cref<labelList>(labelList::null())) {} @@ -73,12 +75,14 @@ public: ( const pointField& pointLst, const faceList& faceLst, - const labelList& zoneIdLst = labelList::null() + const labelList& zoneIdLst = labelList::null(), + const labelList& faceIdLst = labelList::null() ) : points_(std::cref<pointField>(pointLst)), faces_(std::cref<faceList>(faceLst)), - zoneIds_(std::cref<labelList>(zoneIdLst)) + zoneIds_(std::cref<labelList>(zoneIdLst)), + faceIds_(std::cref<labelList>(faceIdLst)) {} @@ -106,12 +110,19 @@ public: return zoneIds_.get(); } + //- Per-face identifier (eg, element Id) + virtual const labelList& faceIds() const + { + return faceIds_.get(); + } + //- Remove all references by redirecting to null objects void clear() { points_ = std::cref<pointField>(pointField::null()); faces_ = std::cref<faceList>(faceList::null()); zoneIds_ = std::cref<labelList>(labelList::null()); + faceIds_ = std::cref<labelList>(labelList::null()); } //- Reset components @@ -119,12 +130,14 @@ public: ( const pointField& pointLst, const faceList& faceLst, - const labelList& zoneIdLst = labelList::null() + const labelList& zoneIdLst = labelList::null(), + const labelList& faceIdLst = labelList::null() ) { points_ = std::cref<pointField>(pointLst); faces_ = std::cref<faceList>(faceLst); zoneIds_ = std::cref<labelList>(zoneIdLst); + faceIds_ = std::cref<labelList>(faceIdLst); } }; diff --git a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C index 34632ffa60c..b76b3562e7a 100644 --- a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C +++ b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C @@ -117,6 +117,8 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read DynamicList<label> pointId; // Nastran point id (1-based) DynamicList<point> dynPoints; + + DynamicList<label> dynElemId; // Nastran element id (1-based) DynamicList<Face> dynFaces; DynamicList<label> dynZones; DynamicList<label> dynSizes; @@ -127,6 +129,9 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read label zoneId = 0; bool sorted = true; + // Element id gets trashed with decompose into a triangle! + bool ignoreElemId = false; + // Name for face group Map<word> nameLookup; @@ -222,7 +227,7 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read if (cmd == "CTRIA3") { - (void) nextNasField(line, linei, 8); // 8-16 + label elemId = readLabel(nextNasField(line, linei, 8)); // 8-16 label groupId = readLabel(nextNasField(line, linei, 8)); // 16-24 const auto a = readLabel(nextNasField(line, linei, 8)); // 24-32 const auto b = readLabel(nextNasField(line, linei, 8)); // 32-40 @@ -247,13 +252,15 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read // Info<< "zone" << zoneId << " => group " << groupId <<nl; } + --elemId; // Convert 1-based -> 0-based + dynElemId.append(elemId); dynFaces.append(Face{a, b, c}); dynZones.append(zoneId); dynSizes[zoneId]++; } else if (cmd == "CQUAD4") { - (void) nextNasField(line, linei, 8); // 8-16 + label elemId = readLabel(nextNasField(line, linei, 8)); // 8-16 label groupId = readLabel(nextNasField(line, linei, 8)); // 16-24 const auto a = readLabel(nextNasField(line, linei, 8)); // 24-32 const auto b = readLabel(nextNasField(line, linei, 8)); // 32-40 @@ -281,6 +288,9 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read if (faceTraits<Face>::isTri()) { + ignoreElemId = true; + dynElemId.clear(); + dynFaces.append(Face{a, b, c}); dynFaces.append(Face{c, d, a}); dynZones.append(zoneId); @@ -289,6 +299,9 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read } else { + --elemId; // Convert 1-based -> 0-based + + dynElemId.append(elemId); dynFaces.append(Face{a,b,c,d}); dynZones.append(zoneId); dynSizes[zoneId]++; @@ -358,6 +371,10 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read // << " points:" << dynPoints.size() // << endl; + if (ignoreElemId) + { + dynElemId.clear(); + } // Transfer to normal lists this->storedPoints().transfer(dynPoints); @@ -403,7 +420,7 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read } } - this->sortFacesAndStore(dynFaces, dynZones, sorted); + this->sortFacesAndStore(dynFaces, dynZones, dynElemId, sorted); // Add zones (retaining empty ones) this->addZones(dynSizes, names); @@ -428,6 +445,7 @@ void Foam::fileFormats::NASsurfaceFormat<Face>::write const UList<point>& pointLst = surf.points(); const UList<Face>& faceLst = surf.surfFaces(); const UList<label>& faceMap = surf.faceMap(); + const UList<label>& elemIds = surf.faceIds(); // for no zones, suppress the group name const surfZoneList zones = @@ -439,6 +457,25 @@ void Foam::fileFormats::NASsurfaceFormat<Face>::write const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1); + // Possible to use faceIds? + bool useOrigFaceIds = + (!useFaceMap && elemIds.size() == faceLst.size()); + + if (useOrigFaceIds) + { + // Not possible with on-the-fly face decomposition + + for (const auto& f : faceLst) + { + if (f.size() > 4) + { + useOrigFaceIds = false; + break; + } + } + } + + OFstream os(filename, streamOpt); if (!os.good()) { @@ -489,6 +526,11 @@ void Foam::fileFormats::NASsurfaceFormat<Face>::write const Face& f = faceLst[facei]; + if (useOrigFaceIds) + { + elemId = elemIds[facei]; + } + elemId = writeShell(os, f, elemId, zoneIndex); } diff --git a/src/surfMesh/surfaceFormats/obj/OBJsurfaceFormat.C b/src/surfMesh/surfaceFormats/obj/OBJsurfaceFormat.C index 25928e9732c..a2b43c28ead 100644 --- a/src/surfMesh/surfaceFormats/obj/OBJsurfaceFormat.C +++ b/src/surfMesh/surfaceFormats/obj/OBJsurfaceFormat.C @@ -71,6 +71,8 @@ bool Foam::fileFormats::OBJsurfaceFormat<Face>::read DynamicList<point> dynPoints; DynamicList<label> dynVerts; + + DynamicList<label> dynElemId; // unused DynamicList<Face> dynFaces; DynamicList<word> dynNames; @@ -207,7 +209,7 @@ bool Foam::fileFormats::OBJsurfaceFormat<Face>::read // Transfer to normal lists this->storedPoints().transfer(dynPoints); - this->sortFacesAndStore(dynFaces, dynZones, sorted); + this->sortFacesAndStore(dynFaces, dynZones, dynElemId, sorted); // Add zones (retaining empty ones) this->addZones(dynSizes, dynNames); diff --git a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C index 797cee86520..d1db77d26f7 100644 --- a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C +++ b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C @@ -127,7 +127,9 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read readHeader(is, STARCDCore::HEADER_CEL); + DynamicList<label> dynElemId; // STARCD element id (1-based) DynamicList<Face> dynFaces; + DynamicList<label> dynZones; DynamicList<word> dynNames; DynamicList<label> dynSizes; @@ -137,6 +139,9 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read bool sorted = true; label zoneId = 0; + // Element id gets trashed with decompose into a triangle! + bool ignoreElemId = false; + label ignoredLabel, shapeId, nLabels, cellTableId, typeId; DynamicList<label> vertexLabels(64); @@ -144,7 +149,9 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read while (is.read(tok).good() && tok.isLabel()) { - // const label starCellId = tok.labelToken(); + // First token is the element id (1-based) + label elemId = tok.labelToken(); + is >> shapeId >> nLabels >> cellTableId @@ -203,6 +210,8 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read if (faceTraits<Face>::isTri() && nLabels > 3) { // The face needs triangulation + ignoreElemId = true; + dynElemId.clear(); face f(vertices); @@ -220,6 +229,9 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read } else if (nLabels >= 3) { + --elemId; // Convert 1-based -> 0-based + dynElemId.append(elemId); + dynFaces.append(Face(vertices)); dynZones.append(zoneId); dynSizes[zoneId]++; @@ -228,7 +240,14 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read } mapPointId.clear(); - this->sortFacesAndStore(dynFaces, dynZones, sorted); + + if (ignoreElemId) + { + dynElemId.clear(); + } + + + this->sortFacesAndStore(dynFaces, dynZones, dynElemId, sorted); // Add zones (retaining empty ones) this->addZones(dynSizes, dynNames); @@ -253,6 +272,7 @@ void Foam::fileFormats::STARCDsurfaceFormat<Face>::write const UList<point>& pointLst = surf.points(); const UList<Face>& faceLst = surf.surfFaces(); const UList<label>& faceMap = surf.faceMap(); + const UList<label>& elemIds = surf.faceIds(); const surfZoneList zones = ( @@ -263,6 +283,15 @@ void Foam::fileFormats::STARCDsurfaceFormat<Face>::write const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1); + // Possible to use faceIds? + const bool useOrigFaceIds = + ( + !useFaceMap + && surf.useFaceIds() + && elemIds.size() == faceLst.size() + ); + + fileName baseName = filename.lessExt(); // The .vrt file @@ -287,6 +316,11 @@ void Foam::fileFormats::STARCDsurfaceFormat<Face>::write const Face& f = faceLst[facei]; + if (useOrigFaceIds) + { + elemId = elemIds[facei]; + } + writeShell(os, f, elemId, zoneIndex); ++elemId; } diff --git a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.C b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.C index 068c6c77f23..38f19dc70e8 100644 --- a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.C +++ b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.C @@ -175,6 +175,8 @@ bool Foam::fileFormats::VTKsurfaceFormat<Face>::read } } + DynamicList<label> dynElemId; // unused + if (nTri > faces.size()) { // We are here if the target surface needs triangles and @@ -203,7 +205,7 @@ bool Foam::fileFormats::VTKsurfaceFormat<Face>::read zoneSizes[zonei]++; } - this->sortFacesAndStore(dynFaces, dynZones, sorted); + this->sortFacesAndStore(dynFaces, dynZones, dynElemId, sorted); // Add zones (retaining empty ones) this->addZones(zoneSizes, zoneNames); @@ -225,7 +227,7 @@ bool Foam::fileFormats::VTKsurfaceFormat<Face>::read zoneSizes[zonei]++; } - this->sortFacesAndStore(dynFaces, dynZones, sorted); + this->sortFacesAndStore(dynFaces, dynZones, dynElemId, sorted); // Add zones (retaining empty ones) this->addZones(zoneSizes, zoneNames); diff --git a/src/surfMesh/writers/nastran/nastranSurfaceWriter.C b/src/surfMesh/writers/nastran/nastranSurfaceWriter.C index 9592e5bba92..fcfae7d7607 100644 --- a/src/surfMesh/writers/nastran/nastranSurfaceWriter.C +++ b/src/surfMesh/writers/nastran/nastranSurfaceWriter.C @@ -211,6 +211,24 @@ void Foam::surfaceWriters::nastranWriter::writeGeometry const pointField& points = surf.points(); const faceList& faces = surf.faces(); const labelList& zones = surf.zoneIds(); + const labelList& elemIds = surf.faceIds(); + + // Possible to use faceIds? + bool useOrigFaceIds = (elemIds.size() == faces.size()); + + if (useOrigFaceIds) + { + // Not possible with on-the-fly face decomposition + for (const auto& f : faces) + { + if (f.size() > 4) + { + useOrigFaceIds = false; + break; + } + } + } + // Write points @@ -238,6 +256,12 @@ void Foam::surfaceWriters::nastranWriter::writeGeometry { const face& f = faces[facei]; + if (useOrigFaceIds) + { + // When available and not decomposed + elemId = elemIds[facei]; + } + // 1-offset for PID const label propId = 1 + (facei < zones.size() ? zones[facei] : 0); diff --git a/src/surfMesh/writers/nastran/nastranSurfaceWriterImpl.C b/src/surfMesh/writers/nastran/nastranSurfaceWriterImpl.C index 737240262c9..56fee262501 100644 --- a/src/surfMesh/writers/nastran/nastranSurfaceWriterImpl.C +++ b/src/surfMesh/writers/nastran/nastranSurfaceWriterImpl.C @@ -247,6 +247,16 @@ Foam::fileName Foam::surfaceWriters::nastranWriter::writeTemplate // Regular (undecomposed) faces const faceList& faces = surf.faces(); + const labelList& elemIds = surf.faceIds(); + + // Possible to use faceIds? + // Not possible with on-the-fly face decomposition + const bool useOrigFaceIds = + ( + elemIds.size() == faces.size() + && decompFaces.empty() + ); + label elemId = 0; @@ -254,6 +264,12 @@ Foam::fileName Foam::surfaceWriters::nastranWriter::writeTemplate { forAll(faces, facei) { + if (useOrigFaceIds) + { + // When available and not decomposed + elemId = elemIds[facei]; + } + const label beginElemId = elemId; // Any face decomposition @@ -299,6 +315,12 @@ Foam::fileName Foam::surfaceWriters::nastranWriter::writeTemplate forAll(faces, facei) { + if (useOrigFaceIds) + { + // When available and not decomposed + elemId = elemIds[facei]; + } + const Type v(varScale * *valIter); ++valIter; diff --git a/src/surfMesh/writers/starcd/starcdSurfaceWriter.C b/src/surfMesh/writers/starcd/starcdSurfaceWriter.C index 2f31924bed5..789d7cbb538 100644 --- a/src/surfMesh/writers/starcd/starcdSurfaceWriter.C +++ b/src/surfMesh/writers/starcd/starcdSurfaceWriter.C @@ -145,7 +145,14 @@ Foam::fileName Foam::surfaceWriters::starcdWriter::write() mkDir(outputFile.path()); } - MeshedSurfaceProxy<face>(surf.points(), surf.faces()).write + MeshedSurfaceProxy<face> + ( + surf.points(), + surf.faces(), + UList<surfZone>::null(), // one zone + labelUList::null(), // no faceMap + surf.faceIds() // with face ids (if possible) + ).write ( outputFile, "inp", -- GitLab