From daa2b76c84adb5ccf3e14702439113fc07ebafe4 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Tue, 8 Sep 2020 09:17:35 +0200 Subject: [PATCH] ENH: suppress surface Face-id field if writer manages that itself (#1600) - for CAE formats such as abaqus, nastran, starcd, etc, the element id is already part of the output format itself. For these cases, there is no use in generating an additional "Ids" field. ENH: add code to ignore negative face ids - these will arise from very special cases, such as when a solid element and side are encoded into a single integer. BUG: starcd surface values output did not use original face ids --- .../sampledSurfaces/sampledSurfaces.C | 38 +++++++++++++------ .../abaqus/ABAQUSsurfaceFormat.C | 12 ++++-- .../surfaceFormats/nas/NASsurfaceFormat.C | 11 ++++-- .../starcd/STARCDsurfaceFormat.C | 3 +- .../writers/nastran/nastranSurfaceWriter.C | 10 +++-- .../writers/nastran/nastranSurfaceWriter.H | 6 +++ .../nastran/nastranSurfaceWriterImpl.C | 7 ++-- .../writers/starcd/starcdSurfaceWriter.C | 37 ++++++++++++++---- .../writers/starcd/starcdSurfaceWriter.H | 6 +++ src/surfMesh/writers/surfaceWriter.H | 8 ++++ 10 files changed, 105 insertions(+), 33 deletions(-) diff --git a/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C b/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C index 3779ff20d3c..48b65330f9e 100644 --- a/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C +++ b/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C @@ -32,6 +32,7 @@ License #include "mapPolyMesh.H" #include "volFields.H" #include "HashOps.H" +#include "ListOps.H" #include "Time.H" #include "UIndirectList.H" #include "addToRunTimeSelectionTable.H" @@ -168,12 +169,18 @@ void Foam::sampledSurfaces::countFields() forAll(*this, surfi) { const sampledSurface& s = (*this)[surfi]; + surfaceWriter& outWriter = writers_[surfi]; - writers_[surfi].nFields() = + outWriter.nFields() = ( nVolumeFields + (s.withSurfaceFields() ? nSurfaceFields : 0) - + ((s.hasFaceIds() && !s.interpolate()) ? 1 : 0) + + + ( + // Face-id field, but not if the writer manages that itself + !s.interpolate() && s.hasFaceIds() && !outWriter.usesFaceIds() + ? 1 : 0 + ) ); } } @@ -319,7 +326,7 @@ bool Foam::sampledSurfaces::read(const dictionary& dict) const dictionary& surfDict = dEntry.dict(); autoPtr<sampledSurface> surf = - sampledSurface::New + sampledSurface::New ( dEntry.keyword(), mesh_, @@ -555,20 +562,29 @@ bool Foam::sampledSurfaces::performAction(unsigned request) outWriter.beginTime(obr_.time()); - // Write original ids - if (s.hasFaceIds() && !s.interpolate()) + // Face-id field, but not if the writer manages that itself + if (!s.interpolate() && s.hasFaceIds() && !outWriter.usesFaceIds()) { // This is still quite horrible. Field<label> ids(s.faceIds()); - ids += label(1); // From 0-based to 1-based - writeSurface + if ( - outWriter, - ids, - "Ids" - ); + returnReduce + ( + !ListOps::found(ids, lessOp1<label>(0)), + andOp<bool>() + ) + ) + { + // From 0-based to 1-based, provided there are no + // negative ids (eg, encoded solid/side) + + ids += label(1); + } + + writeSurface(outWriter, ids, "Ids"); } } } diff --git a/src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormat.C b/src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormat.C index 810fb2c1796..72ebcfc65e2 100644 --- a/src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormat.C +++ b/src/surfMesh/surfaceFormats/abaqus/ABAQUSsurfaceFormat.C @@ -26,10 +26,10 @@ License \*---------------------------------------------------------------------------*/ #include "ABAQUSsurfaceFormat.H" +#include "ListOps.H" #include "IFstream.H" #include "IOmanip.H" #include "faceTraits.H" -#include "stringOps.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -267,13 +267,17 @@ void Foam::fileFormats::ABAQUSsurfaceFormat<Face>::write const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1); // Possible to use faceIds? + // - cannot if there are negative ids (eg, encoded solid/side) bool useOrigFaceIds = - (!useFaceMap && elemIds.size() == faceLst.size()); + ( + !useFaceMap + && elemIds.size() == faceLst.size() + && !ListOps::found(elemIds, lessOp1<label>(0)) + ); + // Not possible with on-the-fly face decomposition if (useOrigFaceIds) { - // Not possible with on-the-fly face decomposition - for (const auto& f : faceLst) { if (f.size() > 4) diff --git a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C index b76b3562e7a..ad4e03eab61 100644 --- a/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C +++ b/src/surfMesh/surfaceFormats/nas/NASsurfaceFormat.C @@ -27,6 +27,7 @@ License \*---------------------------------------------------------------------------*/ #include "NASsurfaceFormat.H" +#include "ListOps.H" #include "IFstream.H" #include "IOmanip.H" #include "faceTraits.H" @@ -458,13 +459,17 @@ void Foam::fileFormats::NASsurfaceFormat<Face>::write const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1); // Possible to use faceIds? + // - cannot if there are negative ids (eg, encoded solid/side) bool useOrigFaceIds = - (!useFaceMap && elemIds.size() == faceLst.size()); + ( + !useFaceMap + && elemIds.size() == faceLst.size() + && !ListOps::found(elemIds, lessOp1<label>(0)) + ); + // Not possible with on-the-fly face decomposition if (useOrigFaceIds) { - // Not possible with on-the-fly face decomposition - for (const auto& f : faceLst) { if (f.size() > 4) diff --git a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C index d1db77d26f7..3914fa32566 100644 --- a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C +++ b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C @@ -284,11 +284,12 @@ void Foam::fileFormats::STARCDsurfaceFormat<Face>::write const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1); // Possible to use faceIds? + // - cannot if there are negative ids (eg, encoded solid/side) const bool useOrigFaceIds = ( !useFaceMap - && surf.useFaceIds() && elemIds.size() == faceLst.size() + && !ListOps::found(elemIds, lessOp1<label>(0)) ); diff --git a/src/surfMesh/writers/nastran/nastranSurfaceWriter.C b/src/surfMesh/writers/nastran/nastranSurfaceWriter.C index c5c4dfbb2d2..5f377ab46b8 100644 --- a/src/surfMesh/writers/nastran/nastranSurfaceWriter.C +++ b/src/surfMesh/writers/nastran/nastranSurfaceWriter.C @@ -29,6 +29,7 @@ License #include "nastranSurfaceWriter.H" #include "Pair.H" #include "IOmanip.H" +#include "ListOps.H" #include "OSspecific.H" #include "surfaceWriterMethods.H" #include "addToRunTimeSelectionTable.H" @@ -214,11 +215,15 @@ void Foam::surfaceWriters::nastranWriter::writeGeometry const labelList& elemIds = surf.faceIds(); // Possible to use faceIds? - bool useOrigFaceIds = (elemIds.size() == faces.size()); + bool useOrigFaceIds = + ( + elemIds.size() == faces.size() + && !ListOps::found(elemIds, lessOp1<label>(0)) + ); + // Not possible with on-the-fly face decomposition if (useOrigFaceIds) { - // Not possible with on-the-fly face decomposition for (const auto& f : faces) { if (f.size() > 4) @@ -258,7 +263,6 @@ void Foam::surfaceWriters::nastranWriter::writeGeometry if (useOrigFaceIds) { - // When available and not decomposed elemId = elemIds[facei]; } diff --git a/src/surfMesh/writers/nastran/nastranSurfaceWriter.H b/src/surfMesh/writers/nastran/nastranSurfaceWriter.H index a56169167be..c22c082cb97 100644 --- a/src/surfMesh/writers/nastran/nastranSurfaceWriter.H +++ b/src/surfMesh/writers/nastran/nastranSurfaceWriter.H @@ -254,6 +254,12 @@ public: // Member Functions + //- Format uses faceIds as part of its output + virtual bool usesFaceIds() const // override + { + return true; + } + //- Write surface geometry to file. virtual fileName write(); // override diff --git a/src/surfMesh/writers/nastran/nastranSurfaceWriterImpl.C b/src/surfMesh/writers/nastran/nastranSurfaceWriterImpl.C index bcffc522e30..a417f374c25 100644 --- a/src/surfMesh/writers/nastran/nastranSurfaceWriterImpl.C +++ b/src/surfMesh/writers/nastran/nastranSurfaceWriterImpl.C @@ -28,6 +28,7 @@ License #include "OFstream.H" #include "IOmanip.H" +#include "ListOps.H" #include "OSspecific.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -254,13 +255,13 @@ Foam::fileName Foam::surfaceWriters::nastranWriter::writeTemplate // Regular (undecomposed) faces const faceList& faces = surf.faces(); - const labelList& elemIds = surf.faceIds(); + const labelUList& elemIds = surf.faceIds(); // Possible to use faceIds? - // Not possible with on-the-fly face decomposition const bool useOrigFaceIds = ( elemIds.size() == faces.size() + && !ListOps::found(elemIds, lessOp1<label>(0)) && decompFaces.empty() ); @@ -273,7 +274,6 @@ Foam::fileName Foam::surfaceWriters::nastranWriter::writeTemplate { if (useOrigFaceIds) { - // When available and not decomposed elemId = elemIds[facei]; } @@ -324,7 +324,6 @@ Foam::fileName Foam::surfaceWriters::nastranWriter::writeTemplate { if (useOrigFaceIds) { - // When available and not decomposed elemId = elemIds[facei]; } diff --git a/src/surfMesh/writers/starcd/starcdSurfaceWriter.C b/src/surfMesh/writers/starcd/starcdSurfaceWriter.C index 0aa30d2a811..b036e14d284 100644 --- a/src/surfMesh/writers/starcd/starcdSurfaceWriter.C +++ b/src/surfMesh/writers/starcd/starcdSurfaceWriter.C @@ -27,6 +27,7 @@ License \*---------------------------------------------------------------------------*/ #include "starcdSurfaceWriter.H" +#include "ListOps.H" #include "OFstream.H" #include "OSspecific.H" #include "MeshedSurfaceProxy.H" @@ -53,7 +54,7 @@ namespace Foam template<class Type> static inline void writeData(Ostream& os, const Type& val) { - for (direction cmpt=0; cmpt < pTraits<Type>::nComponents; ++cmpt) + for (direction cmpt=0; cmpt < pTraits<Type>::nComponents; ++cmpt) { os << ' ' << component(val, cmpt); } @@ -145,13 +146,23 @@ Foam::fileName Foam::surfaceWriters::starcdWriter::write() mkDir(outputFile.path()); } + const labelUList& origFaceIds = surf.faceIds(); + + // Face ids (if possible) + const labelUList& elemIds = + ( + !ListOps::found(origFaceIds, lessOp1<label>(0)) + ? origFaceIds + : labelUList::null() + ); + MeshedSurfaceProxy<face> ( surf.points(), surf.faces(), UList<surfZone>::null(), // one zone labelUList::null(), // no faceMap - surf.faceIds() // with face ids (if possible) + elemIds // face ids ).write ( outputFile, @@ -204,6 +215,8 @@ Foam::fileName Foam::surfaceWriters::starcdWriter::writeTemplate // geometry merge() implicit tmp<Field<Type>> tfield = mergeField(localValues); + const meshedSurf& surf = surface(); + if (Pstream::master() || !parallel_) { const auto& values = tfield(); @@ -215,16 +228,26 @@ Foam::fileName Foam::surfaceWriters::starcdWriter::writeTemplate OFstream os(outputFile, streamOpt_); - // 1-based ids - label elemId = 1; + const labelUList& elemIds = surf.faceIds(); + + // Possible to use faceIds? + const bool useOrigFaceIds = + ( + elemIds.size() == values.size() + && !ListOps::found(elemIds, lessOp1<label>(0)) + ); + + label faceIndex = 0; // No header, just write values for (const Type& val : values) { - os << elemId; - writeData(os, val); + const label elemId = + (useOrigFaceIds ? elemIds[faceIndex] : faceIndex); - ++elemId; + os << (elemId + 1); // 1-based ids + writeData(os, val); + ++faceIndex; } } diff --git a/src/surfMesh/writers/starcd/starcdSurfaceWriter.H b/src/surfMesh/writers/starcd/starcdSurfaceWriter.H index 4e3b5250298..0955d210370 100644 --- a/src/surfMesh/writers/starcd/starcdSurfaceWriter.H +++ b/src/surfMesh/writers/starcd/starcdSurfaceWriter.H @@ -159,6 +159,12 @@ public: return true; } + //- Format uses faceIds as part of its output + virtual bool usesFaceIds() const // override + { + return true; + } + //- Write surface geometry to file. virtual fileName write(); // override diff --git a/src/surfMesh/writers/surfaceWriter.H b/src/surfMesh/writers/surfaceWriter.H index 7813347d3be..c1142e88b86 100644 --- a/src/surfMesh/writers/surfaceWriter.H +++ b/src/surfMesh/writers/surfaceWriter.H @@ -300,6 +300,14 @@ public: return false; } + //- True if the writer format uses faceIds as part of its output. + // Element ids are used by various CAE formats + // (abaqus, nastran, starcd, ...) + virtual bool usesFaceIds() const + { + return false; + } + // Bookkeeping -- GitLab