From b5676cd627c85b4017a53524067b4f8ffed7d5a0 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Mon, 10 Feb 2020 15:21:05 +0100 Subject: [PATCH] ENH: overhaul ensight handling (#1579) - includes restructuring and simplification of low-level ensight part handling and refactor of backends to improve code reuse. foamToEnsight ------------- * new cellZone support. This was previously only possible via a separate foamToEnsightParts utility that was not parallelized. * support for point fields. * `-nearCellValue` option (as per foamToVTK) * support data indexing using values from the time index foamToEnsightParts ------------------ * now redundant and removed. ensightOutputSurface (new class) -------------------------------- * a lightweight wrapper for point/face references that is tailored for the ensightSurfaceWriter. It uses compact face/point information and is serial only, since this is the format requirements from the surfaceWriter class. ensightMesh (revised class) --------------------------- * now only holds a polyMesh reference, which removes its dependency on finiteVolume and allows it to be relocated under fileFormats instead of conversion. Removed classes: ensightParts, ensighPartFaces, ensightPartCells - these were used by foamToEnsightParts, but not needed anymore. --- .../dataConversion/foamToEnsight/Make/options | 2 - .../foamToEnsight/checkMeshMoving.H | 10 +- .../foamToEnsight/convertLagrangian.H | 12 +- .../foamToEnsight/convertVolumeFields.H | 30 +- .../foamToEnsight/foamToEnsight.C | 302 +++++-- .../getTimeIndex.H | 2 +- .../dataConversion/foamToEnsight/readFields.H | 104 ++- .../foamToEnsight/writeDimFields.H | 76 +- .../writePointFields.H} | 71 +- .../foamToEnsight/writeVolFields.H | 68 +- .../foamToEnsightParts/Make/files | 4 - .../foamToEnsightParts/Make/options | 15 - .../foamToEnsightParts/checkMeshMoving.H | 45 - .../foamToEnsightParts/convertLagrangian.H | 138 --- .../foamToEnsightParts/findCloudFields.H | 94 --- .../foamToEnsightParts/foamToEnsightParts.C | 370 -------- .../foamToEnsightParts/moveMesh.H | 19 - .../foamToEnsightParts/readFields.H | 101 --- .../foamToEnsightParts/writeDimFields.H | 125 --- src/conversion/Make/files | 4 - src/conversion/ensight/mesh/ensightMesh.C | 404 --------- src/conversion/ensight/mesh/ensightMesh.H | 503 ----------- src/conversion/ensight/mesh/ensightMeshIO.C | 794 ------------------ .../ensight/mesh/ensightMeshOptions.C | 183 ---- .../ensight/output/ensightOutputVolField.H | 78 +- .../output/ensightOutputVolFieldTemplates.C | 404 ++++----- src/fileFormats/Make/files | 20 +- src/fileFormats/ensight/mesh/ensightMesh.C | 479 +++++++++++ src/fileFormats/ensight/mesh/ensightMesh.H | 342 ++++++++ .../ensight/mesh/ensightMeshI.H | 66 +- .../ensight/mesh/ensightMeshOptions.C | 340 ++++++++ .../ensight/output/ensightOutput.C | 490 +++++++++++ .../ensight/output/ensightOutput.H | 258 +++++- .../ensight/output/ensightOutputTemplates.C | 304 +++---- .../ensight/part/{ => cells}/ensightCells.C | 154 ++-- .../ensight/part/cells/ensightCells.H | 279 ++++++ .../ensight/part/cells/ensightCellsAddr.C | 238 ++++++ .../ensight/part/{ => cells}/ensightCellsI.H | 59 +- .../ensight/part/cells/ensightCellsIO.C | 322 +++++++ src/fileFormats/ensight/part/ensightCells.H | 215 ----- src/fileFormats/ensight/part/ensightFaces.H | 222 ----- src/fileFormats/ensight/part/ensightPart.H | 183 ---- .../ensight/part/ensightPartCells.C | 344 -------- .../ensight/part/ensightPartCells.H | 180 ---- .../ensight/part/ensightPartFaces.C | 302 ------- .../ensight/part/ensightPartFaces.H | 202 ----- src/fileFormats/ensight/part/ensightParts.C | 134 --- src/fileFormats/ensight/part/ensightParts.H | 120 --- .../ensight/part/{ => faces}/ensightFaces.C | 241 +++--- .../ensight/part/faces/ensightFaces.H | 264 ++++++ .../ensight/part/faces/ensightFacesAddr.C | 96 +++ .../ensight/part/{ => faces}/ensightFacesI.H | 68 +- .../ensight/part/faces/ensightFacesIO.C | 138 +++ .../ensight/part/{ => part}/ensightPart.C | 47 +- .../ensight/part/part/ensightPart.H | 214 +++++ .../part/surface/ensightOutputSurface.C | 62 +- .../part/surface/ensightOutputSurface.H | 137 +++ .../surface/ensightOutputSurfaceTemplates.C | 98 ++- .../utilities/ensightWrite/ensightWrite.C | 4 +- .../ensightWrite/ensightWriteTemplates.C | 4 +- .../writers/ensight/ensightSurfaceWriter.C | 2 +- .../ensight/ensightSurfaceWriterCollated.C | 41 +- .../ensight/ensightSurfaceWriterUncollated.C | 44 +- 63 files changed, 4853 insertions(+), 5818 deletions(-) rename applications/utilities/postProcessing/dataConversion/{foamToEnsightParts => foamToEnsight}/getTimeIndex.H (97%) rename applications/utilities/postProcessing/dataConversion/{foamToEnsightParts/writeVolFields.H => foamToEnsight/writePointFields.H} (64%) delete mode 100644 applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/files delete mode 100644 applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/options delete mode 100644 applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkMeshMoving.H delete mode 100644 applications/utilities/postProcessing/dataConversion/foamToEnsightParts/convertLagrangian.H delete mode 100644 applications/utilities/postProcessing/dataConversion/foamToEnsightParts/findCloudFields.H delete mode 100644 applications/utilities/postProcessing/dataConversion/foamToEnsightParts/foamToEnsightParts.C delete mode 100644 applications/utilities/postProcessing/dataConversion/foamToEnsightParts/moveMesh.H delete mode 100644 applications/utilities/postProcessing/dataConversion/foamToEnsightParts/readFields.H delete mode 100644 applications/utilities/postProcessing/dataConversion/foamToEnsightParts/writeDimFields.H delete mode 100644 src/conversion/ensight/mesh/ensightMesh.C delete mode 100644 src/conversion/ensight/mesh/ensightMesh.H delete mode 100644 src/conversion/ensight/mesh/ensightMeshIO.C delete mode 100644 src/conversion/ensight/mesh/ensightMeshOptions.C create mode 100644 src/fileFormats/ensight/mesh/ensightMesh.C create mode 100644 src/fileFormats/ensight/mesh/ensightMesh.H rename src/{conversion => fileFormats}/ensight/mesh/ensightMeshI.H (55%) create mode 100644 src/fileFormats/ensight/mesh/ensightMeshOptions.C create mode 100644 src/fileFormats/ensight/output/ensightOutput.C rename src/fileFormats/ensight/part/{ => cells}/ensightCells.C (68%) create mode 100644 src/fileFormats/ensight/part/cells/ensightCells.H create mode 100644 src/fileFormats/ensight/part/cells/ensightCellsAddr.C rename src/fileFormats/ensight/part/{ => cells}/ensightCellsI.H (54%) create mode 100644 src/fileFormats/ensight/part/cells/ensightCellsIO.C delete mode 100644 src/fileFormats/ensight/part/ensightCells.H delete mode 100644 src/fileFormats/ensight/part/ensightFaces.H delete mode 100644 src/fileFormats/ensight/part/ensightPart.H delete mode 100644 src/fileFormats/ensight/part/ensightPartCells.C delete mode 100644 src/fileFormats/ensight/part/ensightPartCells.H delete mode 100644 src/fileFormats/ensight/part/ensightPartFaces.C delete mode 100644 src/fileFormats/ensight/part/ensightPartFaces.H delete mode 100644 src/fileFormats/ensight/part/ensightParts.C delete mode 100644 src/fileFormats/ensight/part/ensightParts.H rename src/fileFormats/ensight/part/{ => faces}/ensightFaces.C (52%) create mode 100644 src/fileFormats/ensight/part/faces/ensightFaces.H create mode 100644 src/fileFormats/ensight/part/faces/ensightFacesAddr.C rename src/fileFormats/ensight/part/{ => faces}/ensightFacesI.H (52%) create mode 100644 src/fileFormats/ensight/part/faces/ensightFacesIO.C rename src/fileFormats/ensight/part/{ => part}/ensightPart.C (73%) create mode 100644 src/fileFormats/ensight/part/part/ensightPart.H rename applications/utilities/postProcessing/dataConversion/foamToEnsightParts/convertVolumeFields.H => src/fileFormats/ensight/part/surface/ensightOutputSurface.C (59%) create mode 100644 src/fileFormats/ensight/part/surface/ensightOutputSurface.H rename applications/utilities/postProcessing/dataConversion/foamToEnsightParts/readFields.C => src/fileFormats/ensight/part/surface/ensightOutputSurfaceTemplates.C (54%) diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options index 49c30cf7750..2c48a253240 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/options @@ -3,13 +3,11 @@ EXE_INC = \ -I$(LIB_SRC)/fileFormats/lnInclude \ -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/conversion/lnInclude \ - -I$(LIB_SRC)/dynamicMesh/lnInclude \ -I$(LIB_SRC)/lagrangian/intermediate/lnInclude EXE_LIBS = \ -lfiniteVolume \ -lfileFormats \ - -ldynamicMesh \ -lconversion \ -llagrangianIntermediate \ -lgenericPatchFields diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkMeshMoving.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkMeshMoving.H index 4849c951287..bb1b2dd4463 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkMeshMoving.H +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkMeshMoving.H @@ -1,6 +1,6 @@ // Check for "points" in any of the result directories -bool meshMoving = false; +bool hasMovingMesh = false; if (timeDirs.size() > 1 && Pstream::master()) { @@ -12,7 +12,7 @@ if (timeDirs.size() > 1 && Pstream::master()) { const word& timeName = inst.name(); - meshMoving = + hasMovingMesh = ( timeName != mesh.pointsInstance() && IOobject @@ -27,13 +27,13 @@ if (timeDirs.size() > 1 && Pstream::master()) ).typeHeaderOk<pointIOField>(true, false) ); - if (meshMoving) + if (hasMovingMesh) { break; } } - if (meshMoving) + if (hasMovingMesh) { Info<< "found. Writing meshes for every timestep." << endl; } @@ -43,4 +43,4 @@ if (timeDirs.size() > 1 && Pstream::master()) } } -reduce(meshMoving, orOp<bool>()); +reduce(hasMovingMesh, orOp<bool>()); diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertLagrangian.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertLagrangian.H index b0478d844c4..143f9f226f7 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertLagrangian.H +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertLagrangian.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2018-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -31,9 +31,8 @@ Description // Cloud field data output if (doLagrangian) { - forAll(cloudNames, cloudNo) + for (const word& cloudName : cloudNames) { - const word& cloudName = cloudNames[cloudNo]; const HashTable<word>& theseCloudFields = cloudFields[cloudName]; fileNameList currentCloudDirs @@ -48,12 +47,7 @@ if (doLagrangian) Info<< "Write " << cloudName << " ("; const bool cloudExists = - returnReduce - ( - currentCloudDirs.found(cloudName), - orOp<bool>() - ); - + returnReduce(currentCloudDirs.found(cloudName), orOp<bool>()); { autoPtr<ensightFile> os = ensCase.newCloud(cloudName); diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertVolumeFields.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertVolumeFields.H index 5490eec6d7a..a831662117e 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertVolumeFields.H +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/convertVolumeFields.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2018-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -35,25 +35,19 @@ Description { Info<< "Write volume field ("; - writeAllVolFields - ( - ensCase, - ensMesh, - meshProxy, - objects, - nodeValues - ); - - writeAllDimFields - ( - ensCase, - ensMesh, - meshProxy, - objects, - nodeValues - ); + writeAllVolFields(ensCase, ensMesh, objects, nearCellValue); + writeAllDimFields(ensCase, ensMesh, objects); Info<< " )" << nl; + + // PointData + // - only construct pointMesh on request (it constructs edge addressing) + if (!noPointValues) + { + Info<< "Write point field ("; + writeAllPointFields(ensCase, ensMesh, objects); + Info<< " )" << nl; + } } diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C b/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C index c440c358252..27cf45716f7 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2018 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -32,7 +32,11 @@ Group Description Translate OpenFOAM data to EnSight format. - An Ensight part is created for the internalMesh and for each patch. + An Ensight part is created for cellZones (unzoned cells are "internalMesh") + and patches. + + - Handles volume fields, dimensioned fields, point fields + - Handles mesh topology changes. Usage \b foamToEnsight [OPTION] @@ -51,36 +55,66 @@ Usage The quoting is required to avoid shell expansions and to pass the information as a single argument. + - \par -nearCellValue + Use zero-gradient cell values on patches + + - \par -nodeValues + Force interpolation of values to nodes + - \par -no-boundary - Suppress writing any patches. + Suppress output for all boundary patches - \par -no-internal - Suppress writing the internal mesh. + Suppress output for internal (volume) mesh + + - \par -no-cellZones + Suppress cellZone handling - \par -no-lagrangian Suppress writing lagrangian positions and fields. - - \par -patches patch or patch list - Specify particular patches to write. + - \par -no-mesh + Suppress writing the geometry. Can be useful for converting partial + results for a static geometry. - - \par -faceZones zone or zone list - Specify faceZones to write, with wildcards - - - \par -cellZone zoneName - Specify single cellZone to write (not lagrangian) + - \par -no-point-data + Suppress conversion of pointFields. No interpolated PointData. - \par -noZero Exclude the often incomplete initial conditions. + - \par -index \<start\> + Starting index for the Ensight \c data/######## files. + + - \par -index-by-time + Use time index from the uniform/time file. + - \par -name \<subdir\> Define sub-directory name to use for Ensight data (default: "EnSight") - \par -width \<n\> Width of Ensight data subdir (default: 8) -Note - Writes to \a EnSight directory to avoid collisions with - foamToEnsightParts + - \par -cellZones NAME | LIST + Specify single zone or multiple cell zones (name or regex) to write + + - \par -faceZones NAME | LIST + Specify single zone or multiple face zones (name or regex) to write + + - \par -patches NAME | LIST + Specify single patch or multiple patches (name or regex) to write + For example, + \verbatim + -patches top + -patches '( front \".*back\" )' + \endverbatim + + - \par -excludePatches NAME | LIST + Specify single or multiple patches (name or regex) not to convert. + For example, + \verbatim + -excludePatches '( inlet_1 inlet_2 "proc.*" )' + \endverbatim \*---------------------------------------------------------------------------*/ @@ -93,6 +127,7 @@ Note #include "HashOps.H" #include "fvc.H" +#include "fvMesh.H" #include "fieldTypes.H" #include "volFields.H" #include "scalarIOField.H" @@ -104,26 +139,18 @@ Note #include "ensightMesh.H" #include "ensightOutputCloud.H" #include "ensightOutputVolField.H" -#include "fvMeshSubsetProxy.H" // local files #include "readFields.H" #include "writeVolFields.H" #include "writeDimFields.H" +#include "writePointFields.H" #include "memInfo.H" -using namespace Foam; - -//- Get internal field and make it a zero-gradient volume field with subsetting -template<class GeoField> -tmp<GeoField> -getZeroGradInternalField(IOobject& io, const fvMeshSubsetProxy& proxy) -{ - auto tfield = tmp<typename GeoField::Internal>::New(io, proxy.baseMesh()); - return proxy.interpolateInternal(tfield); -} +#undef foamToEnsight_useTimeIndex +using namespace Foam; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -131,8 +158,8 @@ int main(int argc, char *argv[]) { argList::addNote ( - "Translate OpenFOAM data to Ensight format with a part for" - " the internalMesh and for each patch." + "Translate OpenFOAM data to Ensight format with parts for the " + " cellZones, any unzoned cells and patches" ); timeSelector::addOptions(); @@ -147,10 +174,42 @@ int main(int argc, char *argv[]) "ascii", "Write in ASCII format instead of 'C Binary'" ); + argList::addOption + ( + "index", + "start", + "Starting index for Ensight data/ files." + , true // mark as an advanced option + ); + argList::addBoolOption + ( + "index-by-time", + "Use time index from the uniform/time file " + , true // mark as an advanced option + ); + argList::addOption + ( + "name", + "subdir", + "Sub-directory name for Ensight output (default: 'EnSight')" + ); + argList::addOption + ( + "width", + "n", + "Width of Ensight data subdir" + ); + argList::addBoolOption + ( + "nearCellValue", + "Use zero-gradient cell values on patches" + , true // mark as an advanced option + ); argList::addBoolOption ( "nodeValues", - "Write values at nodes" + "Force interpolation of values to nodes" + , true // mark as an advanced option ); argList::addBoolOption ( @@ -165,12 +224,37 @@ int main(int argc, char *argv[]) "Suppress writing the internal mesh" ); argList::addBoolOption + ( + "no-cellZones", + "Suppress writing any cellZones" + ); + argList::addBoolOption ( "no-lagrangian", // noLagrangian "Suppress writing lagrangian positions and fields" ); argList::addOptionCompat("no-lagrangian", {"noLagrangian", 1806}); + argList::addBoolOption + ( + "no-point-data", + "Suppress conversion of pointFields and disables -nodeValues" + ); + argList::addBoolOption + ( + "no-mesh", // noMesh + "Suppress writing the geometry." + " Can be useful for converting partial results for a static geometry" + , true // mark as an advanced option + ); + + // Future? + // argList::addBoolOption + // ( + // "one-boundary", // allPatches + // "Combine all patches into a single part" + // ); + argList::addOption ( "patches", @@ -179,6 +263,14 @@ int main(int argc, char *argv[]) "Eg, 'inlet' or '(outlet \"inlet.*\")'" ); argList::addOption + ( + "excludePatches", + "wordRes", + "Specify single patch or multiple patches to exclude from writing." + " Eg, 'outlet' or '( inlet \".*Wall\" )'" + , true // mark as an advanced option + ); + argList::addOption ( "faceZones", "wordRes", @@ -194,22 +286,13 @@ int main(int argc, char *argv[]) ); argList::addOption ( - "cellZone", - "word", - "Specify cellZone to write" - ); - argList::addOption - ( - "name", - "subdir", - "Sub-directory name for Ensight output (default: 'EnSight')" - ); - argList::addOption - ( - "width", - "n", - "Width of Ensight data subdir" + "cellZones", + "wordRes", + "Specify single or multiple cellZones to write\n" + "Eg, 'cells' or '( slice \"mfp-.*\" )'." ); + argList::addOptionCompat("cellZone", {"cellZones", 1912}); + #include "setRootCase.H" @@ -221,8 +304,6 @@ int main(int argc, char *argv[]) : IOstream::BINARY ); - const bool nodeValues = args.found("nodeValues"); - cpuTime timer; memInfo mem; Info<< "Initial memory " << mem.update().size() << " kB" << endl; @@ -239,12 +320,44 @@ int main(int argc, char *argv[]) regionPrefix = regionName; } + + // + // Configuration + // + const bool doBoundary = !args.found("no-boundary"); + const bool doInternal = !args.found("no-internal"); + const bool doCellZones = !args.found("no-cellZones"); + const bool doLagrangian = !args.found("no-lagrangian"); + const bool noPointValues = args.found("no-point-data"); + const bool nearCellValue = args.found("nearCellValue") && doBoundary; + + // Control for numbering iterations + const bool doConsecutive = !args.found("index-by-time"); + label indexingNumber = args.getOrDefault("index", 0); + + + // Write the geometry, unless otherwise specified + bool doGeometry = !args.found("no-mesh"); + + if (nearCellValue) + { + Info<< "Using neighbouring cell value instead of patch value" + << nl << endl; + } + if (noPointValues) + { + Info<< "Point fields and interpolated point data" + << " disabled with the '-no-point-data' option" + << nl; + } + // // General (case) output options // ensightCase::options caseOpts(format); - caseOpts.nodeValues(args.found("nodeValues")); + // Forced point interpolation? + caseOpts.nodeValues(args.found("nodeValues") && !noPointValues); caseOpts.width(args.get<label>("width", 8)); caseOpts.overwrite(true); // remove existing output directory @@ -262,22 +375,32 @@ int main(int argc, char *argv[]) } - // - // Output configuration (geometry related) - // - ensightMesh::options writeOpts(format); - writeOpts.useBoundaryMesh(!args.found("no-boundary")); - writeOpts.useInternalMesh(!args.found("no-internal")); - const bool doLagrangian = !args.found("no-lagrangian"); + ensightMesh::options writeOpts; + writeOpts.useBoundaryMesh(doBoundary); + writeOpts.useInternalMesh(doInternal); + writeOpts.useCellZones(doCellZones); if (args.found("patches")) { writeOpts.patchSelection(args.getList<wordRe>("patches")); } + if (args.found("excludePatches")) + { + writeOpts.patchExclude(args.getList<wordRe>("excludePatches")); + } + if (args.found("faceZones")) { writeOpts.faceZoneSelection(args.getList<wordRe>("faceZones")); } + if (args.found("cellZones")) + { + writeOpts.cellZoneSelection(args.getList<wordRe>("cellZones")); + } + + // Report the setup + writeOpts.print(Info); + // // Output configuration (field related) @@ -286,22 +409,11 @@ int main(int argc, char *argv[]) wordRes fieldPatterns; args.readListIfPresent<wordRe>("fields", fieldPatterns); - word cellZoneName; - if (args.readIfPresent("cellZone", cellZoneName)) - { - Info<< "Converting cellZone " << cellZoneName - << " only, with new outside faces as \"oldInternalFaces\"." - << nl; - } - - // Ignored (unproxied) if cellZoneName is empty - fvMeshSubsetProxy meshProxy(mesh, fvMeshSubsetProxy::ZONE, cellZoneName); - // New ensight case file, initialize header etc. ensightCase ensCase(outputDir, args.globalCaseName(), caseOpts); - // Construct the Ensight mesh - ensightMesh ensMesh(meshProxy.mesh(), writeOpts); + // Construct ensight mesh + ensightMesh ensMesh(mesh, writeOpts); if (Pstream::master()) { @@ -335,50 +447,64 @@ int main(int argc, char *argv[]) // Remove "*_0" restart fields objects.prune_0(); - // Only retain volume and dimensioned fields. - objects.filterClasses - ( - [](const word& clsName){ - return - ( - fieldTypes::volume.found(clsName) - || fieldTypes::internal.found(clsName) - ); - } - ); + if (noPointValues) + { + // Prune point fields unless specifically requested + objects.filterClasses + ( + [](const word& clsName) + { + return fieldTypes::point.found(clsName); + }, + true // prune + ); + } wordList objectNames(objects.sortedNames()); // Check availability for all times... - checkData(meshProxy.baseMesh(), timeDirs, objectNames); + checkData(mesh, timeDirs, objectNames); testedObjectNames = objectNames; } + if (hasMovingMesh && !doGeometry) + { + Info<< "has moving mesh: ignoring '-no-mesh' option" << endl; + doGeometry = true; + } - forAll(timeDirs, timeIndex) + forAll(timeDirs, timei) { - runTime.setTime(timeDirs[timeIndex], timeIndex); - ensCase.nextTime(timeDirs[timeIndex]); + runTime.setTime(timeDirs[timei], timei); + + // Index for the Ensight case + #include "getTimeIndex.H" + + ensCase.setTime(timeDirs[timei], timeIndex); Info<< "Time [" << timeIndex << "] = " << runTime.timeName() << nl; polyMesh::readUpdateState meshState = mesh.readUpdate(); - if (meshState != polyMesh::UNCHANGED) + const bool moving = (meshState != polyMesh::UNCHANGED); + + if (moving) { - meshProxy.correct(); ensMesh.expire(); ensMesh.correct(); } - if (timeIndex == 0 || meshMoving) + if (timei == 0 || moving) { - autoPtr<ensightGeoFile> os = ensCase.newGeometry(meshMoving); - ensMesh.write(os); + if (doGeometry) + { + autoPtr<ensightGeoFile> os = ensCase.newGeometry(hasMovingMesh); + ensMesh.write(os); + } } // Objects at this time - IOobjectList objects(meshProxy.baseMesh(), runTime.timeName()); + IOobjectList objects(mesh, runTime.timeName()); // Restrict to objects that are available for all times objects.filterObjects(testedObjectNames); @@ -386,7 +512,7 @@ int main(int argc, char *argv[]) // Volume, internal, point fields #include "convertVolumeFields.H" - // Write lagrangian data + // Lagrangian fields #include "convertLagrangian.H" Info<< "Wrote in " diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/getTimeIndex.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/getTimeIndex.H similarity index 97% rename from applications/utilities/postProcessing/dataConversion/foamToEnsightParts/getTimeIndex.H rename to applications/utilities/postProcessing/dataConversion/foamToEnsight/getTimeIndex.H index b83ba15cef6..aeb83110064 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/getTimeIndex.H +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/getTimeIndex.H @@ -3,7 +3,7 @@ label timeIndex = 0; { - if (optIndex) + if (doConsecutive) { timeIndex = indexingNumber++; } diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/readFields.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/readFields.H index d51ce30412d..8f378f9cb92 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/readFields.H +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/readFields.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2018-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -27,7 +27,8 @@ InNamespace Foam Description - Read fields from disk for foamToEnsight + Helper routines for reading a field or fields, + for foamToEnsight SourceFiles readFields.C @@ -39,39 +40,114 @@ SourceFiles #include "instantList.H" #include "IOobjectList.H" -#include "fvMeshSubsetProxy.H" +#include "zeroGradientFvPatchFields.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { -//- Get the field and subset it, or return nullptr +//- Get the field or return nullptr template<class GeoField> -tmp<GeoField> getField(const IOobject* io, const fvMeshSubsetProxy& proxy) +tmp<GeoField> getField +( + const IOobject* io, + const typename GeoField::Mesh& mesh +) { if (io) { - auto tfield = tmp<GeoField>::New(*io, proxy.baseMesh()); - return proxy.interpolate(tfield); + return tmp<GeoField>::New(*io, mesh); } return nullptr; } -//- Get internal field and make it a zero-gradient volume field with subsetting +//- Get the named field from the objects, or return nullptr. template<class GeoField> -tmp<GeoField> -getZeroGradField(const IOobject* io, const fvMeshSubsetProxy& proxy) +tmp<GeoField> getField +( + const typename GeoField::Mesh& mesh, + const IOobjectList& objects, + const word& fieldName +) { - if (io) + // Can do something with syncPar on failure ... + + return getField<GeoField>(objects.findObject(fieldName), mesh); +} + + +//- Convert an internal field to zero-gradient volume field +template<class Type> +tmp<GeometricField<Type, fvPatchField, volMesh>> +makeZeroGradientField +( + const tmp + < + typename GeometricField<Type, fvPatchField, volMesh>::Internal + >& tdf +) +{ + if (tdf.valid()) + { + auto& df = tdf.ref(); + + auto tfield = GeometricField<Type, fvPatchField, volMesh>::New + ( + df.name(), + df.mesh(), + df.dimensions(), + std::move(df.field()), + zeroGradientFvPatchScalarField::typeName + ); + + tfield.ref().oriented() = df.oriented(); + tfield.ref().correctBoundaryConditions(); + + tdf.clear(); + + return tfield; + } + + tdf.clear(); + + return nullptr; +} + + +//- Convert a volume field to zero-gradient volume field +template<class Type> +tmp<GeometricField<Type, fvPatchField, volMesh>> +makeZeroGradientField +( + const tmp<GeometricField<Type, fvPatchField, volMesh>>& tdf +) +{ + if (tdf.valid()) { - auto tfield = - tmp<typename GeoField::Internal>::New(*io, proxy.baseMesh()); - return proxy.interpolateInternal(tfield); + auto& df = tdf.ref(); + + auto tfield = GeometricField<Type, fvPatchField, volMesh>::New + ( + df.name(), + df.mesh(), + df.dimensions(), + std::move(df.primitiveFieldRef(false)), // No update accessTime + zeroGradientFvPatchScalarField::typeName + ); + + tfield.ref().oriented() = df.oriented(); + tfield.ref().correctBoundaryConditions(); + + tdf.clear(); + + return tfield; } + tdf.clear(); + return nullptr; } diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/writeDimFields.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/writeDimFields.H index ae4d9c35506..6d5e335198c 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/writeDimFields.H +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/writeDimFields.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2018-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -30,12 +30,11 @@ Description Read dimensioned fields from disk and write with ensightMesh SourceFiles - writeDimFields.H \*---------------------------------------------------------------------------*/ -#ifndef writeDimFields_H -#define writeDimFields_H +#ifndef ensight_writeDimFields_H +#define ensight_writeDimFields_H #include "writeVolFields.H" @@ -45,39 +44,59 @@ namespace Foam { template<class Type> -label writeDimFields +bool writeDimField ( ensightCase& ensCase, const ensightMesh& ensMesh, - const fvMeshSubsetProxy& proxy, - const IOobjectList& objects, - const bool nodeValues + const tmp<DimensionedField<Type, volMesh>>& tdf ) { - typedef GeometricField<Type, fvPatchField, volMesh> GeoField; + if (!tdf.valid()) + { + return false; + } + + auto tfield = makeZeroGradientField<Type>(tdf); + + // Now a volField with zero-gradient boundaries + + return writeVolField<Type> + ( + ensCase, + ensMesh, + tfield, + false // No nearCellValue, we already have zero-gradient + ); +} + +template<class Type> +label writeDimFields +( + ensightCase& ensCase, + const ensightMesh& ensMesh, + const IOobjectList& objects +) +{ typedef typename GeometricField < Type, fvPatchField, volMesh >::Internal DimField; + const fvMesh& mesh = dynamicCast<const fvMesh>(ensMesh.mesh()); label count = 0; for (const word& fieldName : objects.sortedNames<DimField>()) { - const IOobject* io = objects.findObject(fieldName); - if ( - writeVolField<Type> + writeDimField<Type> ( ensCase, ensMesh, - proxy, - getZeroGradField<GeoField>(io, proxy), - nodeValues + getField<DimField>(objects.findObject(fieldName), mesh) ) ) { @@ -94,29 +113,26 @@ label writeAllDimFields ( ensightCase& ensCase, const ensightMesh& ensMesh, - const fvMeshSubsetProxy& proxy, - const IOobjectList& objects, - const bool nodeValues + const IOobjectList& objects ) { - #undef foamToEnsight_WRITE_FIELD - #define foamToEnsight_WRITE_FIELD(PrimitiveType) \ + #undef ensight_WRITE_FIELD + #define ensight_WRITE_FIELD(PrimitiveType) \ writeDimFields<PrimitiveType> \ ( \ - ensCase, ensMesh, \ - proxy, \ - objects, \ - nodeValues \ + ensCase, \ + ensMesh, \ + objects \ ) label count = 0; - count += foamToEnsight_WRITE_FIELD(scalar); - count += foamToEnsight_WRITE_FIELD(vector); - count += foamToEnsight_WRITE_FIELD(sphericalTensor); - count += foamToEnsight_WRITE_FIELD(symmTensor); - count += foamToEnsight_WRITE_FIELD(tensor); + count += ensight_WRITE_FIELD(scalar); + count += ensight_WRITE_FIELD(vector); + count += ensight_WRITE_FIELD(sphericalTensor); + count += ensight_WRITE_FIELD(symmTensor); + count += ensight_WRITE_FIELD(tensor); - #undef foamToEnsight_WRITE_FIELD + #undef ensight_WRITE_FIELD return count; } diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/writeVolFields.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/writePointFields.H similarity index 64% rename from applications/utilities/postProcessing/dataConversion/foamToEnsightParts/writeVolFields.H rename to applications/utilities/postProcessing/dataConversion/foamToEnsight/writePointFields.H index dbad2846351..450c93611bc 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/writeVolFields.H +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/writePointFields.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -27,17 +27,18 @@ InNamespace Foam Description - Read volume fields from disk and write with ensightParts + Read point fields from disk + and write as ensight data SourceFiles - writeVolFields.H \*---------------------------------------------------------------------------*/ -#ifndef writeVolFields_H -#define writeVolFields_H +#ifndef ensight_writePointFields_H +#define ensight_writePointFields_H #include "readFields.H" +#include "ensightMesh.H" #include "fvMesh.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -46,12 +47,11 @@ namespace Foam { template<class Type> -bool writeVolField +bool writePointField ( ensightCase& ensCase, - const ensightParts& ensParts, - const fvMesh& mesh, - const tmp<GeometricField<Type, fvPatchField, volMesh>>& tfield + const ensightMesh& ensMesh, + const tmp<GeometricField<Type, pointPatchField, pointMesh>>& tfield ) { if (!tfield.valid()) @@ -61,14 +61,14 @@ bool writeVolField const auto& field = tfield(); - autoPtr<ensightFile> os = ensCase.newData<Type>(field.name()); + // PointData = true + autoPtr<ensightFile> os = ensCase.newData<Type>(field.name(), true); - // Currently serial only - bool wrote = ensightOutput::Serial::writeVolField<Type> + bool wrote = ensightOutput::writePointField<Type> ( + os.ref(), field, - ensParts, - os.ref() + ensMesh ); tfield.clear(); @@ -77,15 +77,16 @@ bool writeVolField template<class Type> -label writeVolFields +label writePointFields ( ensightCase& ensCase, - const ensightParts& ensParts, - const fvMesh& mesh, + const ensightMesh& ensMesh, const IOobjectList& objects ) { - typedef GeometricField<Type, fvPatchField, volMesh> GeoField; + typedef GeometricField<Type, pointPatchField, pointMesh> GeoField; + + const pointMesh& ptMesh = pointMesh::New(ensMesh.mesh()); label count = 0; @@ -93,12 +94,11 @@ label writeVolFields { if ( - writeVolField<Type> + writePointField<Type> ( ensCase, - ensParts, - mesh, - getField<GeoField>(objects.findObject(fieldName), mesh) + ensMesh, + getField<GeoField>(ptMesh, objects, fieldName) ) ) { @@ -111,31 +111,30 @@ label writeVolFields } -label writeAllVolFields +label writeAllPointFields ( ensightCase& ensCase, - const ensightParts& ensParts, - const fvMesh& mesh, + const ensightMesh& ensMesh, const IOobjectList& objects ) { - #undef foamToEnsight_WRITE_FIELD - #define foamToEnsight_WRITE_FIELD(PrimitiveType) \ - writeVolFields<PrimitiveType> \ + #undef ensight_WRITE_FIELD + #define ensight_WRITE_FIELD(PrimitiveType) \ + writePointFields<PrimitiveType> \ ( \ - ensCase, ensParts, \ - mesh, \ + ensCase, \ + ensMesh, \ objects \ ) label count = 0; - count += foamToEnsight_WRITE_FIELD(scalar); - count += foamToEnsight_WRITE_FIELD(vector); - count += foamToEnsight_WRITE_FIELD(sphericalTensor); - count += foamToEnsight_WRITE_FIELD(symmTensor); - count += foamToEnsight_WRITE_FIELD(tensor); + count += ensight_WRITE_FIELD(scalar); + count += ensight_WRITE_FIELD(vector); + count += ensight_WRITE_FIELD(sphericalTensor); + count += ensight_WRITE_FIELD(symmTensor); + count += ensight_WRITE_FIELD(tensor); - #undef foamToEnsight_WRITE_FIELD + #undef ensight_WRITE_FIELD return count; } diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/writeVolFields.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/writeVolFields.H index d0b6655c5fe..5415a006c18 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/writeVolFields.H +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/writeVolFields.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2018-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -30,15 +30,14 @@ Description Read volume fields from disk and write with ensightMesh SourceFiles - writeVolFields.H \*---------------------------------------------------------------------------*/ -#ifndef writeVolFields_H -#define writeVolFields_H +#ifndef ensight_writeVolFields_H +#define ensight_writeVolFields_H #include "readFields.H" -#include "fvMeshSubsetProxy.H" +#include "fvMesh.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -50,25 +49,41 @@ bool writeVolField ( ensightCase& ensCase, const ensightMesh& ensMesh, - const fvMeshSubsetProxy& proxy, const tmp<GeometricField<Type, fvPatchField, volMesh>>& tfield, - const bool nodeValues + const bool nearCellValue = false ) { if (!tfield.valid()) { return false; } + else if (nearCellValue) + { + auto tzgrad = makeZeroGradientField<Type>(tfield); + + // Recursive call + return writeVolField + ( + ensCase, + ensMesh, + tzgrad, + false // No nearCellValue, we already have zero-gradient + ); + } const auto& field = tfield(); - autoPtr<ensightFile> os = ensCase.newData<Type>(field.name()); + // Forced use of node values? + const bool nodeValues = ensCase.nodeValues(); + + autoPtr<ensightFile> os = + ensCase.newData<Type>(field.name(), nodeValues); bool wrote = ensightOutput::writeVolField<Type> ( + os.ref(), field, ensMesh, - os.ref(), nodeValues ); @@ -82,13 +97,14 @@ label writeVolFields ( ensightCase& ensCase, const ensightMesh& ensMesh, - const fvMeshSubsetProxy& proxy, const IOobjectList& objects, - const bool nodeValues + const bool nearCellValue = false ) { typedef GeometricField<Type, fvPatchField, volMesh> GeoField; + const fvMesh& mesh = dynamicCast<const fvMesh>(ensMesh.mesh()); + label count = 0; for (const word& fieldName : objects.sortedNames<GeoField>()) @@ -99,9 +115,8 @@ label writeVolFields ( ensCase, ensMesh, - proxy, - getField<GeoField>(objects.findObject(fieldName), proxy), - nodeValues + getField<GeoField>(objects.findObject(fieldName), mesh), + nearCellValue ) ) { @@ -118,29 +133,28 @@ label writeAllVolFields ( ensightCase& ensCase, const ensightMesh& ensMesh, - const fvMeshSubsetProxy& proxy, const IOobjectList& objects, - const bool nodeValues + const bool nearCellValue = false ) { - #undef foamToEnsight_WRITE_FIELD - #define foamToEnsight_WRITE_FIELD(PrimitiveType) \ + #undef ensight_WRITE_FIELD + #define ensight_WRITE_FIELD(PrimitiveType) \ writeVolFields<PrimitiveType> \ ( \ - ensCase, ensMesh, \ - proxy, \ + ensCase, \ + ensMesh, \ objects, \ - nodeValues \ + nearCellValue \ ) label count = 0; - count += foamToEnsight_WRITE_FIELD(scalar); - count += foamToEnsight_WRITE_FIELD(vector); - count += foamToEnsight_WRITE_FIELD(sphericalTensor); - count += foamToEnsight_WRITE_FIELD(symmTensor); - count += foamToEnsight_WRITE_FIELD(tensor); + count += ensight_WRITE_FIELD(scalar); + count += ensight_WRITE_FIELD(vector); + count += ensight_WRITE_FIELD(sphericalTensor); + count += ensight_WRITE_FIELD(symmTensor); + count += ensight_WRITE_FIELD(tensor); - #undef foamToEnsight_WRITE_FIELD + #undef ensight_WRITE_FIELD return count; } diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/files b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/files deleted file mode 100644 index 2dcb81ea73a..00000000000 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/files +++ /dev/null @@ -1,4 +0,0 @@ -foamToEnsightParts.C -readFields.C - -EXE = $(FOAM_APPBIN)/foamToEnsightParts diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/options b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/options deleted file mode 100644 index 91f83bb8b00..00000000000 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/Make/options +++ /dev/null @@ -1,15 +0,0 @@ -EXE_INC = \ - -I$(LIB_SRC)/finiteVolume/lnInclude \ - -I$(LIB_SRC)/fileFormats/lnInclude \ - -I$(LIB_SRC)/meshTools/lnInclude \ - -I$(LIB_SRC)/conversion/lnInclude \ - -I$(LIB_SRC)/dynamicMesh/lnInclude \ - -I$(LIB_SRC)/lagrangian/intermediate/lnInclude - -EXE_LIBS = \ - -lfiniteVolume \ - -lfileFormats \ - -lconversion \ - -ldynamicMesh \ - -llagrangianIntermediate \ - -lgenericPatchFields diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkMeshMoving.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkMeshMoving.H deleted file mode 100644 index 8155d920cbc..00000000000 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/checkMeshMoving.H +++ /dev/null @@ -1,45 +0,0 @@ -// check for "points" in all of the result directories -// - could restrict to the selected times - -bool meshMoving = false; - -if (timeDirs.size() > 1 && Pstream::master()) -{ - // We already loaded a mesh (usually from constant). - // See if any other "polyMesh/points" files exist too. - - Info<< "Search for moving mesh ... " << flush; - forAll(timeDirs, timeI) - { - meshMoving = - ( - IOobject - ( - "points", - timeDirs[timeI].name(), - polyMesh::meshSubDir, - mesh, - IOobject::NO_READ, - IOobject::NO_WRITE, - false // no register - ).typeHeaderOk<pointIOField>(true, false) - ); - - if (meshMoving) - { - break; - } - } - - if (meshMoving) - { - Info<< "found." << nl - << " Writing meshes for every timestep." << endl; - } - else - { - Info<< "none detected." << endl; - } -} - -reduce(meshMoving, orOp<bool>()); diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/convertLagrangian.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/convertLagrangian.H deleted file mode 100644 index 8eb554150e1..00000000000 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/convertLagrangian.H +++ /dev/null @@ -1,138 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -Description - Code chunk for post-processing conversion of cloud(s) to Ensight - -\*---------------------------------------------------------------------------*/ - -// Cloud field data output -if (doLagrangian) -{ - forAll(cloudNames, cloudNo) - { - const word& cloudName = cloudNames[cloudNo]; - const HashTable<word>& theseCloudFields = cloudFields[cloudName]; - - fileNameList currentCloudDirs - ( - readDir - ( - runTime.timePath()/regionPrefix/cloud::prefix, - fileName::DIRECTORY - ) - ); - - Info<< "Write " << cloudName << " ("; - - const bool cloudExists = - returnReduce - ( - currentCloudDirs.found(cloudName), - orOp<bool>() - ); - - { - autoPtr<ensightFile> os = ensCase.newCloud(cloudName); - - ensightOutput::writeCloudPositions - ( - mesh, - cloudName, - cloudExists, - os - ); - - Info<< " positions"; - if (!cloudExists) - { - Info<< "{0}"; // report empty field - } - } - - forAllConstIters(theseCloudFields, fieldIter) - { - const word& fieldName = fieldIter.key(); - const word& fieldType = fieldIter.val(); - - IOobject fieldObject - ( - fieldName, - mesh.time().timeName(), - cloud::prefix/cloudName, - mesh, - IOobject::MUST_READ - ); - - bool fieldExists = cloudExists; // No field without positions - if (cloudExists) - { - // Want MUST_READ (globally) and valid=false (locally), - // but that combination does not work. - // So check the header and sync globally - - fieldExists = - fieldObject.typeHeaderOk<IOField<scalar>>(false); - - reduce(fieldExists, orOp<bool>()); - } - - bool wrote = false; - if (fieldType == scalarIOField::typeName) - { - autoPtr<ensightFile> os = - ensCase.newCloudData<scalar>(cloudName, fieldName); - - wrote = ensightOutput::writeCloudField<scalar> - ( - fieldObject, fieldExists, os - ); - } - else if (fieldType == vectorIOField::typeName) - { - autoPtr<ensightFile> os = - ensCase.newCloudData<vector>(cloudName, fieldName); - - wrote = ensightOutput::writeCloudField<vector> - ( - fieldObject, fieldExists, os - ); - } - - if (wrote) - { - Info<< ' ' << fieldName; - if (!fieldExists) - { - Info<< "{0}"; // report empty field - } - } - } - Info<< " )" << nl; - } -} - - -// ************************************************************************* // diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/findCloudFields.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/findCloudFields.H deleted file mode 100644 index a8a56c33a8a..00000000000 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/findCloudFields.H +++ /dev/null @@ -1,94 +0,0 @@ -// check all time directories for the following: - -// The fields for each cloud: -HashTable<HashTable<word>> cloudFields; - -// Identify if lagrangian data exist at any time step. -if (timeDirs.size() && doLagrangian) -{ - const fileName& baseDir = mesh.time().path(); - const fileName cloudPrefix(regionPrefix/cloud::prefix); - - Info<< "Searching for lagrangian ... " << flush; - - for (const instant& inst : timeDirs) - { - const word& timeName = inst.name(); - - // DO NOT USE -->> runTime.setTime(timeDirs[timeI], timeI); <<-- - // It incurs a large overhead when done so frequently. - - fileNameList cloudDirs - ( - readDir - ( - baseDir/timeName/cloudPrefix, - fileName::DIRECTORY - ) - ); - - for (fileName& cloudDir : cloudDirs) - { - const word cloudName(std::move(cloudDir)); - - IOobjectList cloudObjs - ( - mesh, - timeName, - cloudPrefix/cloudName - ); - - // Clouds require "coordinates". - // The "positions" are for v1706 and lower. - // - detect and remove since these are treated specially - - bool isCloud = false; - if (cloudObjs.erase("coordinates")) - { - isCloud = true; - } - if (cloudObjs.erase("positions")) - { - isCloud = true; - } - - if (isCloud) - { - // Save the cloud fields on a per cloud basis - auto& fieldsPerCloud = cloudFields(cloudName); - - forAllConstIters(cloudObjs, fieldIter) - { - const IOobject* io = *fieldIter; - - // Field name/type - fieldsPerCloud.insert(io->name(), io->headerClassName()); - } - } - } - } - - if (Pstream::parRun()) - { - Pstream::mapCombineGather(cloudFields, HashTableOps::plusEqOp<word>()); - Pstream::mapCombineScatter(cloudFields); - } - - if (cloudFields.empty()) - { - Info<< "none detected." << endl; - } -} - - -// Sorted list of cloud names -const wordList cloudNames(cloudFields.sortedToc()); - -if (cloudNames.size()) -{ - // Complete the echo information - as flatOutput - cloudNames.writeList(Info) << endl; -} - - -// ************************************************************************* // diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/foamToEnsightParts.C b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/foamToEnsightParts.C deleted file mode 100644 index 4b221f34943..00000000000 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/foamToEnsightParts.C +++ /dev/null @@ -1,370 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2018 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -Application - foamToEnsightParts - -Group - grpPostProcessingUtilities - -Description - Translate OpenFOAM data to Ensight format with an Ensight part - for each cellZone and patch. - -Usage - \b foamToEnsightParts [OPTION] - - Options: - - \par -ascii - Write Ensight data in ASCII format instead of "C Binary" - - - \par -fields \<fields\> - Specify single or multiple fields to write (all by default) - For example, - \verbatim - -fields T - -fields '(p T U \"alpha.*\")' - \endverbatim - The quoting is required to avoid shell expansions and to pass the - information as a single argument. - - - \par -noZero - Exclude the often incomplete initial conditions. - - - \par -index \<start\> - Ignore the time index contained in the time file and use a - simple indexing when creating the \c Ensight/data/######## files. - - - \par -no-lagrangian - Suppress writing lagrangian positions and fields. - - - \par -no-mesh - Suppress writing the geometry. Can be useful for converting partial - results for a static geometry. - - - \par -noZero - Exclude the often incomplete initial conditions. - - - \par -name \<subdir\> - Define sub-directory name to use for Ensight data (default: "Ensight") - - - \par -width \<n\> - Width of Ensight data subdir - -Note - - no parallel data. - - writes to \a Ensight directory to avoid collisions with foamToEnsight. - -\*---------------------------------------------------------------------------*/ - -#include "argList.H" -#include "timeSelector.H" -#include "IOobjectList.H" -#include "IOmanip.H" -#include "OFstream.H" -#include "PstreamCombineReduceOps.H" -#include "HashOps.H" - -#include "fieldTypes.H" -#include "volFields.H" -#include "scalarIOField.H" -#include "vectorIOField.H" - -// file-format/conversion -#include "ensightCase.H" -#include "ensightGeoFile.H" -#include "ensightParts.H" -#include "ensightOutputCloud.H" -#include "ensightOutputVolField.H" -#include "fvMeshSubsetProxy.H" - -// local files -#include "readFields.H" -#include "writeVolFields.H" -#include "writeDimFields.H" - -#include "memInfo.H" - -using namespace Foam; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -int main(int argc, char *argv[]) -{ - argList::addNote - ( - "Translate OpenFOAM data to Ensight format with an Ensight part" - " for each cellZone and patch." - ); - - // Enable -constant - // Probably don't need -withZero though, since the fields are vetted - // afterwards anyhow - timeSelector::addOptions(true, false); // constant(true), zero(false) - #include "addRegionOption.H" - - argList::noParallel(); - argList::addBoolOption - ( - "ascii", - "Write in ASCII format instead of 'C Binary'" - ); - argList::addOption - ( - "index", - "start", - "Ignore the time index contained in the uniform/time file" - " and use simple indexing when creating files" - ); - argList::addBoolOption - ( - "no-lagrangian", // noLagrangian - "Suppress writing lagrangian positions and fields" - ); - argList::addOptionCompat("no-lagrangian", {"noLagrangian", 1806}); - - argList::addBoolOption - ( - "no-mesh", // noMesh - "Suppress writing the geometry." - " Can be useful for converting partial results for a static geometry" - ); - argList::addOptionCompat("no-mesh", {"noMesh", 1806}); - - argList::addOption - ( - "fields", - "wordRes", - "Specify single or multiple fields to write (all by default)\n" - "Eg, 'T' or '( \"U.*\" )'" - ); - - argList::addOption - ( - "name", - "subdir", - "Sub-directory name for Ensight output (default: 'Ensight')" - ); - argList::addOption - ( - "width", - "n", - "Width of Ensight data subdir" - ); - - #include "setRootCase.H" - - // Default to binary output, unless otherwise specified - const IOstream::streamFormat format = - ( - args.found("ascii") - ? IOstream::ASCII - : IOstream::BINARY - ); - - cpuTime timer; - memInfo mem; - Info<< "Initial memory " << mem.update().size() << " kB" << endl; - - #include "createTime.H" - - instantList timeDirs = timeSelector::select0(runTime, args); - - #include "createNamedMesh.H" - - fileName regionPrefix; // Mesh instance (region0 gets filtered out) - if (regionName != polyMesh::defaultRegion) - { - regionPrefix = regionName; - } - - // - // general (case) output options - // - ensightCase::options caseOpts(format); - - caseOpts.width(args.get<label>("width", 8)); - caseOpts.overwrite(false); // leave existing output directory - - // Can also have separate directory for lagrangian - // caseOpts.separateCloud(true); - - // Define sub-directory name to use for EnSight data. - // The path to the ensight directory is at case level only - // - For parallel cases, data only written from master - fileName ensightDir = args.get<word>("name", "Ensight"); - if (!ensightDir.isAbsolute()) - { - ensightDir = args.globalPath()/ensightDir; - } - - // - // Open new ensight case file, initialize header etc. - // - ensightCase ensCase - ( - ensightDir, - "Ensight", // args.globalCaseName(), - caseOpts - ); - - - // - // Output configuration - // - - // Control for renumbering iterations - label indexingNumber = 0; - const bool optIndex = args.readIfPresent("index", indexingNumber); - const bool doLagrangian = !args.found("no-lagrangian"); - - // Write the geometry, unless otherwise specified - bool doGeometry = !args.found("no-mesh"); - - // - // Output configuration (field related) - // - - wordRes fieldPatterns; - args.readListIfPresent<wordRe>("fields", fieldPatterns); - - - // Construct the list of ensight parts for the entire mesh - ensightParts ensParts(mesh); - - // Write summary information - if (Pstream::master()) - { - Info<< "Converting " << timeDirs.size() << " time steps" << endl; - - OFstream info(ensCase.path()/"partsInfo"); - - info - << "// summary of ensight parts" << nl << nl; - ensParts.writeSummary(info); - } - - #include "checkMeshMoving.H" - #include "findCloudFields.H" - - Info<< "Startup in " - << timer.cpuTimeIncrement() << " s, " - << mem.update().size() << " kB" << nl << endl; - - - // Initially all possible objects that are available at the final time - wordHashSet testedObjectNames; - { - IOobjectList objects(mesh, timeDirs.last().name()); - - if (!fieldPatterns.empty()) - { - objects.filterObjects(fieldPatterns); - } - - // Remove "*_0" restart fields - objects.prune_0(); - - // Only retain volume and dimensioned fields. - objects.filterClasses - ( - [](const word& clsName){ - return - ( - fieldTypes::volume.found(clsName) - || fieldTypes::internal.found(clsName) - ); - } - ); - - wordList objectNames(objects.sortedNames()); - - // Check availability for all times... - checkData(mesh, timeDirs, objectNames); - - testedObjectNames = objectNames; - } - - if (meshMoving && !doGeometry) - { - Info<< "mesh is moving: ignoring '-no-mesh' option" << endl; - doGeometry = true; - } - - - forAll(timeDirs, timeI) - { - runTime.setTime(timeDirs[timeI], timeI); - - #include "getTimeIndex.H" - #include "moveMesh.H" - - ensCase.setTime(timeDirs[timeI], timeIndex); - - Info<< "Time [" << timeIndex << "] = " << runTime.timeName() << nl; - - if (timeI == 0 || mesh.moving()) - { - if (mesh.moving()) - { - ensParts.recalculate(mesh); - } - - if (doGeometry) - { - autoPtr<ensightGeoFile> os = ensCase.newGeometry(meshMoving); - ensParts.write(os.ref()); - } - } - - // Objects at this time - IOobjectList objects(mesh, runTime.timeName()); - - // Restrict to objects that are available for all times - objects.filterObjects(testedObjectNames); - - // Volume, internal fields - #include "convertVolumeFields.H" - - // Lagrangian fields - #include "convertLagrangian.H" - - Info<< "Wrote in " - << timer.cpuTimeIncrement() << " s, " - << mem.update().size() << " kB" << endl; - } - - ensCase.write(); - - Info<< "\nEnd: " - << timer.elapsedCpuTime() << " s, " - << mem.update().peak() << " kB (peak)\n" << endl; - - return 0; -} - - -// ************************************************************************* // diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/moveMesh.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/moveMesh.H deleted file mode 100644 index 8e3f53ce966..00000000000 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/moveMesh.H +++ /dev/null @@ -1,19 +0,0 @@ -{ - IOobject io - ( - "points", - runTime.timeName(), - polyMesh::meshSubDir, - mesh, - IOobject::NO_READ, - IOobject::NO_WRITE, - false // no register - ); - - if (io.typeHeaderOk<pointIOField>(true, false)) - { - // Read new points - io.readOpt() = IOobject::MUST_READ; - mesh.movePoints(pointIOField(io)); - } -} diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/readFields.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/readFields.H deleted file mode 100644 index fe8288bd1fc..00000000000 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/readFields.H +++ /dev/null @@ -1,101 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -InNamespace - Foam - -Description - Read fields from disk for foamToEnsight - -SourceFiles - readFields.C - -\*---------------------------------------------------------------------------*/ - -#ifndef readFields_H -#define readFields_H - -#include "instantList.H" -#include "IOobjectList.H" -#include "fvMesh.H" -#include "fvMeshSubsetProxy.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -//- Get the field and subset it, or return nullptr -template<class GeoField> -tmp<GeoField> getField(const IOobject* io, const fvMesh& mesh) -{ - if (io) - { - auto tfield = tmp<GeoField>::New(*io, mesh); - return tfield; - } - - return nullptr; -} - - -//- Get internal field and make it a zero-gradient volume field with subsetting -template<class GeoField> -tmp<GeoField> -getZeroGradField(const IOobject* io, const fvMesh& mesh) -{ - if (io) - { - auto tdimfield = - tmp<typename GeoField::Internal>::New(*io, mesh); - - auto tfield = fvMeshSubsetProxy::zeroGradientField(tdimfield()); - tdimfield.clear(); - - return tfield; - } - - return nullptr; -} - - -//- Check if fields are good to use (available at all times) -// ignore special fields (_0 fields), -// ignore fields that are not available for all time-steps -label checkData -( - const fvMesh& mesh, - const instantList& timeDirs, - wordList& objectNames -); - - -} // End namespace Foam - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#endif - -// ************************************************************************* // diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/writeDimFields.H b/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/writeDimFields.H deleted file mode 100644 index cc3fa5f7307..00000000000 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/writeDimFields.H +++ /dev/null @@ -1,125 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -InNamespace - Foam - -Description - Read dimensioned fields from disk and write with ensightParts - -SourceFiles - writeDimFields.H - -\*---------------------------------------------------------------------------*/ - -#ifndef ensightParts_writeDimFields_H -#define ensightParts_writeDimFields_H - -#include "writeVolFields.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -template<class Type> -label writeDimFields -( - ensightCase& ensCase, - const ensightParts& ensParts, - const fvMesh& mesh, - const IOobjectList& objects -) -{ - typedef GeometricField<Type, fvPatchField, volMesh> GeoField; - - typedef typename - GeometricField - < - Type, fvPatchField, volMesh - >::Internal DimField; - - - label count = 0; - - for (const word& fieldName : objects.sortedNames<DimField>()) - { - const IOobject* io = objects.findObject(fieldName); - - if - ( - writeVolField<Type> - ( - ensCase, - ensParts, - mesh, - getZeroGradField<GeoField>(io, mesh) - ) - ) - { - Info<< ' ' << fieldName; - ++count; - } - } - - return count; -} - - -label writeAllDimFields -( - ensightCase& ensCase, - const ensightParts& ensParts, - const fvMesh& mesh, - const IOobjectList& objects -) -{ - #undef foamToEnsight_WRITE_FIELD - #define foamToEnsight_WRITE_FIELD(PrimitiveType) \ - writeDimFields<PrimitiveType> \ - ( \ - ensCase, ensParts, \ - mesh, \ - objects \ - ) - - label count = 0; - count += foamToEnsight_WRITE_FIELD(scalar); - count += foamToEnsight_WRITE_FIELD(vector); - count += foamToEnsight_WRITE_FIELD(sphericalTensor); - count += foamToEnsight_WRITE_FIELD(symmTensor); - count += foamToEnsight_WRITE_FIELD(tensor); - - #undef foamToEnsight_WRITE_FIELD - return count; -} - -} // End namespace Foam - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#endif - -// ************************************************************************* // diff --git a/src/conversion/Make/files b/src/conversion/Make/files index 4cf7b300a08..a00ca056813 100644 --- a/src/conversion/Make/files +++ b/src/conversion/Make/files @@ -7,10 +7,6 @@ common/writer/meshWriter.C common/tables/boundaryRegion.C common/tables/cellTable.C -ensight/mesh/ensightMesh.C -ensight/mesh/ensightMeshIO.C -ensight/mesh/ensightMeshOptions.C - fire/FIREMeshReader.C fire/FIREMeshWriter.C fire/checkFireEdges.C diff --git a/src/conversion/ensight/mesh/ensightMesh.C b/src/conversion/ensight/mesh/ensightMesh.C deleted file mode 100644 index 0b9dd7a4c2f..00000000000 --- a/src/conversion/ensight/mesh/ensightMesh.C +++ /dev/null @@ -1,404 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2019 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -\*---------------------------------------------------------------------------*/ - -#include "ensightMesh.H" -#include "fvMesh.H" -#include "globalMeshData.H" -#include "PstreamCombineReduceOps.H" -#include "emptyPolyPatch.H" -#include "processorPolyPatch.H" -#include "mapDistribute.H" -#include "stringListOps.H" - -#include "ensightFile.H" -#include "ensightGeoFile.H" -#include "demandDrivenData.H" - -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // - -void Foam::ensightMesh::clear() -{ - meshCells_.clear(); - boundaryPatchFaces_.clear(); - faceZoneFaces_.clear(); - patchLookup_.clear(); - globalPointsPtr_.clear(); -} - - -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - -Foam::ensightMesh::ensightMesh -( - const fvMesh& mesh, - const ensightMesh::options& opts -) -: - options_(new options(opts)), - mesh_(mesh), - needsUpdate_(true) -{ - if (!option().lazy()) - { - correct(); - } -} - - -Foam::ensightMesh::ensightMesh(const fvMesh& mesh) -: - ensightMesh(mesh, IOstream::streamFormat::BINARY) -{} - - -Foam::ensightMesh::ensightMesh -( - const fvMesh& mesh, - const IOstream::streamFormat format -) -: - options_(new options(format)), - mesh_(mesh), - needsUpdate_(true) -{ - if (!option().lazy()) - { - correct(); - } -} - - -// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // - -Foam::ensightMesh::~ensightMesh() -{ - deleteDemandDrivenData(options_); -} - - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -bool Foam::ensightMesh::needsUpdate() const -{ - return needsUpdate_; -} - - -bool Foam::ensightMesh::expire() -{ - clear(); - - // Already marked as expired - if (needsUpdate_) - { - return false; - } - - needsUpdate_ = true; - return true; -} - - -void Foam::ensightMesh::correct() -{ - clear(); - - // Part number - label nParts = 0; - - if (useInternalMesh()) - { - meshCells_.index() = nParts++; - meshCells_.classify(mesh_); - - // Determine parallel shared points - globalPointsPtr_ = mesh_.globalData().mergePoints - ( - pointToGlobal_, - uniquePointMap_ - ); - } - meshCells_.reduce(); - - - if (useBoundaryMesh()) - { - // Patches are output. Check that they are synced. - mesh_.boundaryMesh().checkParallelSync(true); - - wordList patchNames = mesh_.boundaryMesh().names(); - if (Pstream::parRun()) - { - // Do not include processor patches in matching - patchNames.resize(mesh_.boundaryMesh().nNonProcessor()); - } - - const wordRes& matcher = option().patchSelection(); - - const labelList patchIds = - ( - matcher.empty() - ? identity(patchNames.size()) // Use all - : findStrings(matcher, patchNames) // Use specified names - ); - - for (const label patchId : patchIds) - { - const word& patchName = patchNames[patchId]; - - // Use fvPatch (not polyPatch) to automatically remove empty patches - const fvPatch& p = mesh_.boundary()[patchId]; - - ensightFaces& ensFaces = boundaryPatchFaces_(patchName); - ensFaces.clear(); - - if (p.size()) - { - // Local face addressing (offset = 0), - // - this is what we'll need later when writing fields - ensFaces.classify(p.patch()); - } - else - { - // The patch is empty (on this processor) - // or the patch is 'empty' (as fvPatch type) - ensFaces.clear(); - } - - // Finalize - ensFaces.reduce(); - - if (ensFaces.total()) - { - patchLookup_.set(patchId, patchName); - ensFaces.index() = nParts++; - } - else - { - boundaryPatchFaces_.erase(patchName); - } - } - - // At this point, - // * patchLookup_ is a map of (patchId, name) - // * boundaryPatchFaces_ is a lookup by name for the faces elements - } - - - if (option().useFaceZones()) - { - // Mark boundary faces to be excluded from export - bitSet excludeFace(mesh_.nFaces()); - - for (const polyPatch& pp : mesh_.boundaryMesh()) - { - const auto* procPatch = isA<processorPolyPatch>(pp); - - if (isA<emptyPolyPatch>(pp)) - { - excludeFace.set(pp.range()); - } - else if (procPatch && !procPatch->owner()) - { - // Exclude neighbour-side, retain owner-side only - excludeFace.set(pp.range()); - } - } - - // Use sorted order for later consistency - const wordList zoneNames = - mesh_.faceZones().sortedNames(option().faceZoneSelection()); - - // Count face types in each selected faceZone - for (const word& zoneName : zoneNames) - { - const label zoneID = mesh_.faceZones().findZoneID(zoneName); - const faceZone& fz = mesh_.faceZones()[zoneID]; - - ensightFaces& ensFaces = faceZoneFaces_(zoneName); - ensFaces.clear(); - - if (fz.size()) - { - ensFaces.classify - ( - mesh_.faces(), - fz, - fz.flipMap(), - excludeFace - ); - } - - // Finalize - ensFaces.reduce(); - - if (ensFaces.total()) - { - ensFaces.index() = nParts++; - } - else - { - faceZoneFaces_.erase(zoneName); - } - } - } - - needsUpdate_ = false; -} - - -void Foam::ensightMesh::write(ensightGeoFile& os) const -{ - // - // Write internalMesh - // - if (useInternalMesh()) - { - const label nPoints = globalPoints().size(); - - const pointField uniquePoints(mesh_.points(), uniquePointMap_); - - // writePartHeader(os, 0, "internalMesh"); - // beginCoordinates(os, nPoints); - writeAllPoints - ( - meshCells_.index(), - "internalMesh", - nPoints, - uniquePoints, - os - ); - - writeCellConnectivity(meshCells_, pointToGlobal_, os); - } - - - // - // Write patches - sorted by Id - // - for (const label patchId : patchLookup_.sortedToc()) - { - const word& patchName = patchLookup_[patchId]; - const ensightFaces& ensFaces = boundaryPatchFaces_[patchName]; - - const polyPatch& pp = mesh_.boundaryMesh()[patchId]; - - // Renumber the patch points/faces into unique points - labelList pointToGlobal; - labelList uniqueMeshPointLabels; - autoPtr<globalIndex> globalPointsPtr = - mesh_.globalData().mergePoints - ( - pp.meshPoints(), - pp.meshPointMap(), - pointToGlobal, // local point to unique global index - uniqueMeshPointLabels // unique global points - ); - - // Renumber the patch faces, - // from local patch indexing to unique global index - faceList patchFaces(pp.localFaces()); - for (face& f : patchFaces) - { - inplaceRenumber(pointToGlobal, f); - } - - writeAllPoints - ( - ensFaces.index(), - patchName, - globalPointsPtr().size(), - pointField(mesh_.points(), uniqueMeshPointLabels), - os - ); - - writeFaceConnectivity(ensFaces, patchFaces, os); - } - - - // - // Write faceZones, if requested - // - for (const word& zoneName : faceZoneFaces_.sortedToc()) - { - const ensightFaces& ensFaces = faceZoneFaces_[zoneName]; - - // Use the properly sorted faceIds (ensightFaces) and do NOT use the - // faceZone directly, otherwise the point-maps will not correspond. - // - perform face-flipping later - - indirectPrimitivePatch pp - ( - IndirectList<face>(mesh_.faces(), ensFaces.faceIds()), - mesh_.points() - ); - - // Renumber the points/faces into unique points - labelList pointToGlobal; - labelList uniqueMeshPointLabels; - autoPtr<globalIndex> globalPointsPtr = - mesh_.globalData().mergePoints - ( - pp.meshPoints(), - pp.meshPointMap(), - pointToGlobal, // local point to unique global index - uniqueMeshPointLabels // unique global points - ); - - // Renumber the faces belonging to the faceZone, - // from local numbering to unique global index. - // Also a good place to perform face flipping - const boolList& flip = ensFaces.flipMap(); - faceList patchFaces(pp.localFaces()); - forAll(patchFaces, facei) - { - face& f = patchFaces[facei]; - - if (flip[facei]) - { - f.flip(); - } - - inplaceRenumber(pointToGlobal, f); - } - - writeAllPoints - ( - ensFaces.index(), - zoneName, - globalPointsPtr().size(), - pointField(mesh_.points(), uniqueMeshPointLabels), - os - ); - - writeFaceConnectivity(ensFaces, patchFaces, os, true); - } -} - - -// ************************************************************************* // diff --git a/src/conversion/ensight/mesh/ensightMesh.H b/src/conversion/ensight/mesh/ensightMesh.H deleted file mode 100644 index fe0b4f25dbd..00000000000 --- a/src/conversion/ensight/mesh/ensightMesh.H +++ /dev/null @@ -1,503 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2018 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -Class - Foam::ensightMesh - -Description - Encapsulation of volume meshes for writing in ensight format. - -SourceFiles - ensightMesh.C - ensightMeshIO.C - ensightMeshOptions.C - -\*---------------------------------------------------------------------------*/ - -#ifndef ensightMesh_H -#define ensightMesh_H - -#include "ensightCells.H" -#include "ensightFaces.H" -#include "ensightGeoFile.H" -#include "cellList.H" -#include "faceList.H" -#include "cellShapeList.H" -#include "HashTable.H" -#include "Map.H" -#include "scalarField.H" -#include "wordRes.H" -#include "globalIndex.H" - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -// Forward declarations -class fvMesh; -class ensightMesh; - -/*---------------------------------------------------------------------------*\ - Class ensightMesh Declaration -\*---------------------------------------------------------------------------*/ - -class ensightMesh -{ -public: - - // Forward declarations - class options; - - -private: - - // Private data - - //- Writer options - const options* options_; - - //- Reference to the OpenFOAM mesh - const fvMesh& mesh_; - - //- The volume cells (internalMesh) - ensightCells meshCells_; - - //- Face elements per patch - HashTable<ensightFaces> boundaryPatchFaces_; - - //- Face elements per faceZone - HashTable<ensightFaces> faceZoneFaces_; - - //- The list of patches to be output - Map<word> patchLookup_; - - //- Track if it needs an update - mutable bool needsUpdate_; - - - // Parallel merged points - - //- Global numbering for merged points - autoPtr<globalIndex> globalPointsPtr_; - - //- From mesh point to global merged point - labelList pointToGlobal_; - - //- Local points that are unique - labelList uniquePointMap_; - - - // Private Member Functions - - //- Clear some storage - void clear(); - - - //- Inplace renumber of cell-shapes - static cellShapeList& renumberShapes - ( - cellShapeList& shapes, - const labelUList& pointToGlobal - ); - - //- Copy and return renumbered cell-shapes - static cellShapeList renumberShapes - ( - const cellShapeList& shapes, - const labelUList& addr, - const labelUList& pointToGlobal - ); - - //- Write list of faces - static void writeFaceList - ( - const faceList& faces, - ensightGeoFile& os - ); - - //- Write list of faces - static void writeFaceList - ( - const UIndirectList<face>& faces, - ensightGeoFile& os - ); - - //- Return sizes of faces in the list - static labelList getFaceSizes - ( - const faceList& faces - ); - - //- Return sizes of faces in the list - static labelList getFaceSizes - ( - const UIndirectList<face>& faces - ); - - //- Write sizes of faces in the list - static void writeFaceSizes - ( - const faceList& faces, - ensightGeoFile& os - ); - - //- Write sizes of faces in the list - static void writeFaceSizes - ( - const UIndirectList<face>& faces, - ensightGeoFile& os - ); - - //- Write cell connectivity via cell shapes - static void writeCellShapes - ( - const cellShapeList& shapes, - ensightGeoFile& os - ); - - //- Return the number of faces per poly element - static labelList getPolysNFaces - ( - const labelUList& polys, - const cellList& cellFaces - ); - - //- Write the number of faces per poly element - static void writePolysNFaces - ( - const labelUList& polys, - const cellList& cellFaces, - ensightGeoFile& os - ); - - //- Return the number of points per poly element - static labelList getPolysNPointsPerFace - ( - const labelUList& polys, - const cellList& cellFaces, - const faceList& faces - ); - - //- Write the number of points per poly element - static void writePolysNPointsPerFace - ( - const labelUList& polys, - const cellList& cellFaces, - const faceList& faces, - ensightGeoFile& os - ); - - //- Write the point ids per poly element - static void writePolysPoints - ( - const labelUList& addr, - const cellList& cellFaces, - const faceList& faces, - const labelList& faceOwner, - ensightGeoFile& os - ); - - //- Write the poly connectivity - void writePolysConnectivity - ( - const labelUList& polys, - const labelList& pointToGlobal, - ensightGeoFile& - ) const; - - //- Write the regular cell connectivity for all types - void writeCellConnectivity - ( - const ensightCells& ensCells, - const labelList& pointToGlobal, - ensightGeoFile& os - ) const; - - //- Write the regular cell connectivity for specified type - void writeCellConnectivity - ( - ensightCells::elemType elemType, - const ensightCells& ensCells, - const labelList& pointToGlobal, - ensightGeoFile& os - ) const; - - //- Write the regular face connectivity for specified type and - //- and specified faces - void writeFaceConnectivity - ( - ensightFaces::elemType elemType, - const label nTotal, - const faceList& faces, - const labelUList& addr, - ensightGeoFile& - ) const; - - //- Write the regular face connectivity for specified type - void writeFaceConnectivity - ( - ensightFaces::elemType elemType, - const label nTotal, - const faceList& faces, - ensightGeoFile& os - ) const; - - - void writeFaceConnectivity - ( - const ensightFaces& ensFaces, - const faceList& faces, - ensightGeoFile& os, - const bool raw = false - ) const; - - - void writeAllPoints - ( - const label partId, - const word& ensightPartName, - const label nTotal, - const pointField& uniquePoints, - ensightGeoFile& - ) const; - - - //- No copy construct - ensightMesh(const ensightMesh&) = delete; - - //- No copy assignment - void operator=(const ensightMesh&) = delete; - - -public: - - // Constructors - - //- Construct from components - ensightMesh(const fvMesh& mesh, const options& opts); - - //- Construct from fvMesh with all default options, binary output - explicit ensightMesh(const fvMesh& mesh); - - //- Construct from fvMesh with all default options and specified format - ensightMesh(const fvMesh& mesh, const IOstream::streamFormat format); - - - //- Destructor - ~ensightMesh(); - - - // Member Functions - - // Access - - //- Reference to the underlying fvMesh - inline const fvMesh& mesh() const; - - //- Reference to the writer/mesh options - inline const ensightMesh::options& option() const; - - //- Ascii/Binary file output - inline IOstream::streamFormat format() const; - - //- Using internal? - inline bool useInternalMesh() const; - - //- Using boundary? - inline bool useBoundaryMesh() const; - - //- The volume cells (internalMesh) - inline const ensightCells& meshCells() const; - - //- The list of patches to be output - inline const Map<word>& patches() const; - - //- Face elements per selected patch - inline const HashTable<ensightFaces>& boundaryPatchFaces() const; - - //- Face elements per selected faceZone. - // To be output in sorted order. - inline const HashTable<ensightFaces>& faceZoneFaces() const; - - - // Parallel point merging - - //- Global numbering for merged points - const globalIndex& globalPoints() const - { - return globalPointsPtr_(); - } - - //- From mesh point to global merged point - const labelList& pointToGlobal() const - { - return pointToGlobal_; - } - - //- Local points that are unique - const labelList& uniquePointMap() const - { - return uniquePointMap_; - } - - - // Other - - //- Does the content need an update? - bool needsUpdate() const; - - //- Mark as needing an update. - // May also free up unneeded data. - // Return false if already marked as expired. - bool expire(); - - //- Update for new mesh - void correct(); - - - // Output - - //- Write to file - inline void write(autoPtr<ensightGeoFile>& os) const; - - //- Write to file - void write(ensightGeoFile& os) const; - -}; - - -//- Configuration options for the ensightMesh -class ensightMesh::options -{ - //- Ascii/Binary file output - IOstream::streamFormat format_; - - //- Create in 'expired' mode - bool lazy_; - - //- Use the internal mesh - bool internal_; - - //- Use the boundary mesh - bool boundary_; - - //- Output of selected patches only - wordRes patchPatterns_; - - //- Output of selected faceZones - wordRes faceZonePatterns_; - - -public: - - // Constructors - - //- Construct for binary output - options(); - - //- Construct for specified format - explicit options(IOstream::streamFormat format); - - - // Member Functions - - // Access - - //- File output format (ascii | binary) - IOstream::streamFormat format() const; - - //- Lazy creation? (ie, ensightMesh starts as needsUpdate) - bool lazy() const; - - //- Using internal? - bool useInternalMesh() const; - - //- Using boundary? - bool useBoundaryMesh() const; - - //- Using faceZones? - bool useFaceZones() const; - - //- Selection of patches. Empty if unspecified. - const wordRes& patchSelection() const; - - //- Selection of faceZones. Empty if unspecified. - const wordRes& faceZoneSelection() const; - - - // Edit - - //- Reset to defaults - void reset(); - - //- Lazy creation - ensightMesh starts as needsUpdate. - void lazy(bool beLazy); - - //- Alter the useBoundaryMesh state - void useInternalMesh(bool on); - - //- Alter the useBoundaryMesh state - void useBoundaryMesh(bool on); - - //- Define patch selection matcher - void patchSelection(const UList<wordRe>& patterns); - - //- Define patch selection matcher - void patchSelection(List<wordRe>&& patterns); - - //- Define faceZone selection matcher - void faceZoneSelection(const UList<wordRe>& patterns); - - //- Define faceZone selection matcher - void faceZoneSelection(List<wordRe>&& patterns); - - - // Housekeeping - - //- Older name for useBoundaryMesh() - // \deprecated OCT-2018 - bool usePatches() const { return useBoundaryMesh(); } - - //- Older name for useBoundaryMesh() - // \deprecated OCT-2018 - void noPatches(bool off) { useBoundaryMesh(!off); } - -}; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#include "ensightMeshI.H" - -#endif - -// ************************************************************************* // diff --git a/src/conversion/ensight/mesh/ensightMeshIO.C b/src/conversion/ensight/mesh/ensightMeshIO.C deleted file mode 100644 index 4e3bc534041..00000000000 --- a/src/conversion/ensight/mesh/ensightMeshIO.C +++ /dev/null @@ -1,794 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2016-2018 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -\*---------------------------------------------------------------------------*/ - -#include "ensightMesh.H" -#include "fvMesh.H" -#include "globalMeshData.H" -#include "PstreamCombineReduceOps.H" -#include "processorPolyPatch.H" -#include "mapDistribute.H" -#include "stringListOps.H" - -#include "ensightFile.H" -#include "ensightGeoFile.H" - -// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // - -Foam::cellShapeList& Foam::ensightMesh::renumberShapes -( - cellShapeList& shapes, - const labelUList& pointToGlobal -) -{ - for (cellShape& shape : shapes) - { - inplaceRenumber(pointToGlobal, shape); - } - - return shapes; -} - - -Foam::cellShapeList Foam::ensightMesh::renumberShapes -( - const cellShapeList& shapes, - const labelUList& addr, - const labelUList& pointToGlobal -) -{ - cellShapeList list(shapes, addr); - - renumberShapes(list, pointToGlobal); - - return list; -} - - -void Foam::ensightMesh::writeFaceList -( - const faceList& faceLst, - ensightGeoFile& os -) -{ - for (const face& f : faceLst) - { - for (const label labi : f) - { - os.write(labi + 1); - } - - os.newline(); - } -} - - -void Foam::ensightMesh::writeFaceList -( - const UIndirectList<face>& faceLst, - ensightGeoFile& os -) -{ - for (const face& f : faceLst) - { - for (const label labi : f) - { - os.write(labi + 1); - } - - os.newline(); - } -} - - -Foam::labelList Foam::ensightMesh::getFaceSizes -( - const faceList& faceLst -) -{ - labelList list(faceLst.size()); - - auto outIter = list.begin(); - - for (const face& f : faceLst) - { - *outIter = f.size(); - ++outIter; - } - - return list; -} - - -Foam::labelList Foam::ensightMesh::getFaceSizes -( - const UIndirectList<face>& faceLst -) -{ - labelList list(faceLst.size()); - - auto outIter = list.begin(); - - for (const face& f : faceLst) - { - *outIter = f.size(); - ++outIter; - } - - return list; -} - - -void Foam::ensightMesh::writeFaceSizes -( - const faceList& faceLst, - ensightGeoFile& os -) -{ - for (const face& f : faceLst) - { - os.write(f.size()); - os.newline(); - } -} - - -void Foam::ensightMesh::writeFaceSizes -( - const UIndirectList<face>& faceLst, - ensightGeoFile& os -) -{ - for (const face& f : faceLst) - { - os.write(f.size()); - os.newline(); - } -} - - -void Foam::ensightMesh::writeCellShapes -( - const cellShapeList& shapes, - ensightGeoFile& os -) -{ - for (const cellShape& cellPoints : shapes) - { - // Convert global -> local index - // (note: Ensight indices start with 1) - - // In ASCII, write one cell per line - for (const label pointi : cellPoints) - { - os.write(pointi + 1); - } - - os.newline(); - } -} - - -Foam::labelList Foam::ensightMesh::getPolysNFaces -( - const labelUList& addr, - const cellList& cellFaces -) -{ - labelList list(addr.size()); - - auto outIter = list.begin(); - - // The number of faces per element - for (const label cellId : addr) - { - const labelUList& cf = cellFaces[cellId]; - - *outIter = cf.size(); - ++outIter; - } - - return list; -} - - -void Foam::ensightMesh::writePolysNFaces -( - const labelUList& addr, - const cellList& cellFaces, - ensightGeoFile& os -) -{ - // Write the number of faces per element (1/line in ASCII) - for (const label cellId : addr) - { - const labelUList& cf = cellFaces[cellId]; - - os.write(cf.size()); - os.newline(); - } -} - - -Foam::labelList Foam::ensightMesh::getPolysNPointsPerFace -( - const labelUList& addr, - const cellList& cellFaces, - const faceList& faces -) -{ - // Count the number of faces per element - - label nTotFaces = 0; - for (const label cellId : addr) - { - const labelUList& cf = cellFaces[cellId]; - - nTotFaces += cf.size(); - } - - labelList list(nTotFaces); - - auto outIter = list.begin(); - - // The number of points per element face - for (const label cellId : addr) - { - const labelUList& cf = cellFaces[cellId]; - - for (const label facei : cf) - { - *outIter = faces[facei].size(); - ++outIter; - } - } - - return list; -} - - -void Foam::ensightMesh::writePolysNPointsPerFace -( - const labelUList& addr, - const cellList& cellFaces, - const faceList& faces, - ensightGeoFile& os -) -{ - // Write the number of points per element face (1/line in ASCII) - for (const label cellId : addr) - { - const labelUList& cf = cellFaces[cellId]; - - for (const label facei : cf) - { - os.write(faces[facei].size()); - os.newline(); - } - } -} - - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -void Foam::ensightMesh::writePolysPoints -( - const labelUList& addr, - const cellList& cellFaces, - const faceList& faces, - const labelList& faceOwner, - ensightGeoFile& os -) -{ - for (const label cellId : addr) - { - const labelUList& cf = cellFaces[cellId]; - - for (const label faceId : cf) - { - const face& f = faces[faceId]; // face points (in global points) - - if (faceId < faceOwner.size() && faceOwner[faceId] != cellId) - { - // internal face, neighbour - // - // as per face::reverseFace(), but without copying - - os.write(f[0] + 1); - for (label pti = f.size()-1; pti > 0; --pti) - { - os.write(f[pti] + 1); - } - } - else - { - for (const label labi : f) - { - os.write(labi + 1); - } - } - - os.newline(); - } - } -} - - -void Foam::ensightMesh::writePolysConnectivity -( - const labelUList& addr, - const labelList& pointToGlobal, - ensightGeoFile& os -) const -{ - const cellList& cellFaces = mesh_.cells(); - const faceList& meshFaces = mesh_.faces(); - const labelList& faceOwner = mesh_.faceOwner(); - - // Number of faces for each poly cell - if (Pstream::master()) - { - // Master - writePolysNFaces(addr, cellFaces, os); - - // Slaves - for (int slave=1; slave<Pstream::nProcs(); ++slave) - { - IPstream fromSlave(Pstream::commsTypes::scheduled, slave); - labelList addr(fromSlave); - cellList cellFaces(fromSlave); - - writePolysNFaces(addr, cellFaces, os); - } - } - else - { - OPstream toMaster(Pstream::commsTypes::scheduled, Pstream::masterNo()); - toMaster - << addr - << cellFaces; - } - - // Number of points for each face of the above list - if (Pstream::master()) - { - // Master - writePolysNPointsPerFace - ( - addr, - cellFaces, - meshFaces, - os - ); - - // Slaves - for (int slave=1; slave<Pstream::nProcs(); ++slave) - { - IPstream fromSlave(Pstream::commsTypes::scheduled, slave); - labelList addr(fromSlave); - cellList cellFaces(fromSlave); - faceList meshFaces(fromSlave); - - writePolysNPointsPerFace - ( - addr, - cellFaces, - meshFaces, - os - ); - } - } - else - { - OPstream toMaster(Pstream::commsTypes::scheduled, Pstream::masterNo()); - toMaster - << addr - << cellFaces - << meshFaces; - } - - - // Renumber faces to use global point numbers - faceList faces(mesh_.faces()); - for (face& f : faces) - { - inplaceRenumber(pointToGlobal, f); - } - - // List of points id for each face of the above list - if (Pstream::master()) - { - // Master - writePolysPoints - ( - addr, - cellFaces, - faces, - faceOwner, - os - ); - - // Slaves - for (int slave=1; slave<Pstream::nProcs(); ++slave) - { - IPstream fromSlave(Pstream::commsTypes::scheduled, slave); - labelList addr(fromSlave); - cellList cellFaces(fromSlave); - faceList faces(fromSlave); - labelList faceOwner(fromSlave); - - writePolysPoints - ( - addr, - cellFaces, - faces, - faceOwner, - os - ); - } - } - else - { - OPstream toMaster(Pstream::commsTypes::scheduled, Pstream::masterNo()); - toMaster - << addr - << cellFaces - << faces - << faceOwner; - } -} - - -void Foam::ensightMesh::writeCellConnectivity -( - const ensightCells::elemType elemType, - const ensightCells& ensCells, - const labelList& pointToGlobal, - ensightGeoFile& os -) const -{ - const label nTotal = ensCells.total(elemType); - - if (nTotal) - { - const labelUList& addr = ensCells.cellIds(elemType); - - if (Pstream::master()) - { - os.writeKeyword(ensightCells::key(elemType)); - os.write(nTotal); - os.newline(); - } - - if (elemType == ensightCells::NFACED) - { - writePolysConnectivity - ( - addr, - pointToGlobal, - os - ); - } - else - { - const cellShapeList shapes - ( - renumberShapes - ( - mesh_.cellShapes(), - addr, - pointToGlobal - ) - ); - - - if (Pstream::master()) - { - writeCellShapes(shapes, os); - - for (int slave=1; slave<Pstream::nProcs(); ++slave) - { - IPstream fromSlave(Pstream::commsTypes::scheduled, slave); - cellShapeList recv(fromSlave); - - writeCellShapes(recv, os); - } - } - else - { - OPstream toMaster - ( - Pstream::commsTypes::scheduled, - Pstream::masterNo() - ); - - toMaster - << shapes; - } - } - } -} - - -void Foam::ensightMesh::writeCellConnectivity -( - const ensightCells& ensCells, - const labelList& pointToGlobal, - ensightGeoFile& os -) const -{ - for (label typei=0; typei < ensightCells::nTypes; ++typei) - { - const ensightCells::elemType what = - ensightCells::elemType(typei); - - writeCellConnectivity(what, ensCells, pointToGlobal, os); - } -} - - -void Foam::ensightMesh::writeFaceConnectivity -( - ensightFaces::elemType elemType, - const label nTotal, - const faceList& faces, - ensightGeoFile& os -) const -{ - if (nTotal) - { - if (Pstream::master()) - { - os.writeKeyword(ensightFaces::key(elemType)); - os.write(nTotal); - os.newline(); - } - - if (elemType == ensightFaces::NSIDED) - { - // Number of points per face - - if (Pstream::master()) - { - writeFaceSizes(faces, os); - - for (int slave=1; slave<Pstream::nProcs(); ++slave) - { - IPstream fromSlave(Pstream::commsTypes::scheduled, slave); - faceList recv(fromSlave); - - writeFaceSizes(recv, os); - } - } - else - { - OPstream toMaster - ( - Pstream::commsTypes::scheduled, - Pstream::masterNo() - ); - - toMaster - << faces; - } - } - - - // List of points id for each face - if (Pstream::master()) - { - writeFaceList(faces, os); - - for (int slave=1; slave<Pstream::nProcs(); ++slave) - { - IPstream fromSlave(Pstream::commsTypes::scheduled, slave); - faceList recv(fromSlave); - - writeFaceList(recv, os); - } - } - else - { - OPstream toMaster - ( - Pstream::commsTypes::scheduled, - Pstream::masterNo() - ); - - toMaster - << faces; - } - } -} - - -void Foam::ensightMesh::writeFaceConnectivity -( - ensightFaces::elemType elemType, - const label nTotal, - const faceList& faceLst, - const labelUList& addr, - ensightGeoFile& os -) const -{ - if (nTotal) - { - if (Pstream::master()) - { - os.writeKeyword(ensightFaces::key(elemType)); - os.write(nTotal); - os.newline(); - } - - const UIndirectList<face> faces(faceLst, addr); - - if (elemType == ensightFaces::NSIDED) - { - // Number of points per face - - if (Pstream::master()) - { - writeFaceSizes(faces, os); - - for (int slave=1; slave<Pstream::nProcs(); ++slave) - { - IPstream fromSlave(Pstream::commsTypes::scheduled, slave); - faceList recv(fromSlave); - - writeFaceSizes(recv, os); - } - } - else - { - OPstream toMaster - ( - Pstream::commsTypes::scheduled, - Pstream::masterNo() - ); - - toMaster - << faces; - } - } - - // List of points id per face - if (Pstream::master()) - { - writeFaceList(faces, os); - - for (int slave=1; slave<Pstream::nProcs(); ++slave) - { - IPstream fromSlave(Pstream::commsTypes::scheduled, slave); - faceList recv(fromSlave); - - writeFaceList(recv, os); - } - } - else - { - OPstream toMaster - ( - Pstream::commsTypes::scheduled, - Pstream::masterNo() - ); - - toMaster - << faces; - } - } -} - - -void Foam::ensightMesh::writeFaceConnectivity -( - const ensightFaces& ensFaces, - const faceList& faceLst, - ensightGeoFile& os, - const bool raw -) const -{ - for (label typei=0; typei < ensightFaces::nTypes; ++typei) - { - const ensightFaces::elemType what = - ensightFaces::elemType(typei); - - if (raw) - { - writeFaceConnectivity - ( - what, - ensFaces.total(what), - SubList<face> - ( - faceLst, - ensFaces.faceIds(what).size(), - ensFaces.offset(what) - ), - os - ); - } - else - { - writeFaceConnectivity - ( - what, - ensFaces.total(what), - faceLst, - ensFaces.faceIds(what), - os - ); - } - } -} - - -void Foam::ensightMesh::writeAllPoints -( - const label partId, - const word& ensightPartName, - const label nPoints, - const pointField& uniquePoints, - ensightGeoFile& os -) const -{ - if (Pstream::master()) - { - os.beginPart(partId, ensightPartName); - - // Write points - os.beginCoordinates(nPoints); - - for (direction cmpt=0; cmpt < point::nComponents; ++cmpt) - { - os.writeList(uniquePoints.component(cmpt)); - - for (int slave=1; slave<Pstream::nProcs(); ++slave) - { - IPstream fromSlave(Pstream::commsTypes::scheduled, slave); - scalarField recv(fromSlave); - os.writeList(recv); - } - } - } - else - { - for (direction cmpt=0; cmpt < point::nComponents; ++cmpt) - { - OPstream toMaster - ( - Pstream::commsTypes::scheduled, - Pstream::masterNo() - ); - - toMaster - << uniquePoints.component(cmpt); - } - } -} - - -// ************************************************************************* // diff --git a/src/conversion/ensight/mesh/ensightMeshOptions.C b/src/conversion/ensight/mesh/ensightMeshOptions.C deleted file mode 100644 index 73ba0bd937e..00000000000 --- a/src/conversion/ensight/mesh/ensightMeshOptions.C +++ /dev/null @@ -1,183 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2016-2018 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -\*---------------------------------------------------------------------------*/ - -#include "ensightMesh.H" - -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - -Foam::ensightMesh::options::options() -: - options(IOstream::streamFormat::BINARY) -{} - - -Foam::ensightMesh::options::options(IOstream::streamFormat format) -: - format_(format), - lazy_(false), - internal_(true), - boundary_(true), - patchPatterns_(), - faceZonePatterns_() -{} - - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -Foam::IOstream::streamFormat Foam::ensightMesh::options::format() const -{ - return format_; -} - - -bool Foam::ensightMesh::options::lazy() const -{ - return lazy_; -} - - -bool Foam::ensightMesh::options::useInternalMesh() const -{ - return internal_; -} - - -bool Foam::ensightMesh::options::useBoundaryMesh() const -{ - return boundary_; -} - - -bool Foam::ensightMesh::options::useFaceZones() const -{ - return faceZonePatterns_.size(); -} - - -void Foam::ensightMesh::options::reset() -{ - internal_ = true; - boundary_ = true; - patchPatterns_.clear(); - faceZonePatterns_.clear(); -} - - -void Foam::ensightMesh::options::lazy(bool beLazy) -{ - lazy_ = beLazy; -} - - -void Foam::ensightMesh::options::useInternalMesh(bool on) -{ - internal_ = on; -} - - -void Foam::ensightMesh::options::useBoundaryMesh(bool on) -{ - boundary_ = on; - - if (!boundary_ && patchPatterns_.size()) - { - patchPatterns_.clear(); - - WarningInFunction - << "Deactivating boundary and removing old patch selection" - << endl; - } -} - - -void Foam::ensightMesh::options::patchSelection -( - const UList<wordRe>& patterns -) -{ - patchPatterns_ = wordRes(patterns); - - if (!boundary_ && patchPatterns_.size()) - { - patchPatterns_.clear(); - - WarningInFunction - << "Ignoring patch selection, boundary is not active" - << endl; - } -} - - -void Foam::ensightMesh::options::patchSelection -( - List<wordRe>&& patterns -) -{ - patchPatterns_ = wordRes(std::move(patterns)); - - if (!boundary_ && patchPatterns_.size()) - { - patchPatterns_.clear(); - - WarningInFunction - << "Ignoring patch selection, boundary is not active" - << endl; - } -} - - -void Foam::ensightMesh::options::faceZoneSelection -( - const UList<wordRe>& patterns -) -{ - faceZonePatterns_ = wordRes(patterns); -} - - -void Foam::ensightMesh::options::faceZoneSelection -( - List<wordRe>&& patterns -) -{ - faceZonePatterns_ = wordRes(std::move(patterns)); -} - - -const Foam::wordRes& Foam::ensightMesh::options::patchSelection() const -{ - return patchPatterns_; -} - - -const Foam::wordRes& Foam::ensightMesh::options::faceZoneSelection() const -{ - return faceZonePatterns_; -} - - -// ************************************************************************* // diff --git a/src/conversion/ensight/output/ensightOutputVolField.H b/src/conversion/ensight/output/ensightOutputVolField.H index 21a570b4954..7309103d4d4 100644 --- a/src/conversion/ensight/output/ensightOutputVolField.H +++ b/src/conversion/ensight/output/ensightOutputVolField.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2019 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -35,10 +35,8 @@ Description #define ensightOutputVolField_H #include "ensightOutput.H" -#include "ensightPart.H" -#include "ensightParts.H" -#include "ensightPartFaces.H" -#include "ensightPartCells.H" +#include "ensightFaces.H" +#include "ensightCells.H" #include "volFields.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -46,40 +44,12 @@ Description namespace Foam { -// Forward declarations +// Forward Declarations class ensightMesh; namespace ensightOutput { -/*---------------------------------------------------------------------------*\ - Namespace ensightOutput::Detail -\*---------------------------------------------------------------------------*/ - -namespace Detail -{ - -//- Write volume field component-wise -template<class Type> -bool writeVolField -( - const GeometricField<Type, fvPatchField, volMesh>& vf, - const ensightMesh& ensMesh, - ensightFile& os -); - -//- Write point field component-wise -template<class Type> -bool writePointField -( - const GeometricField<Type, pointPatchField, pointMesh>& pf, - const ensightMesh& ensMesh, - ensightFile& os -); - -} // End namespace Detail - - /*---------------------------------------------------------------------------*\ Namespace ensightOutput \*---------------------------------------------------------------------------*/ @@ -88,51 +58,31 @@ bool writePointField template<class Type> bool writeVolField ( - const GeometricField<Type, fvPatchField, volMesh>&, - const ensightMesh& ensMesh, ensightFile& os, - const bool nodeValues = false -); - - -/*---------------------------------------------------------------------------*\ - Namespace ensightOutput::Serial -\*---------------------------------------------------------------------------*/ - -namespace Serial -{ - -//- Write volume field component-wise for specified faces -template<class Type> -bool writeVolField -( const GeometricField<Type, fvPatchField, volMesh>& vf, - const ensightPartFaces& part, - ensightFile& os + const ensightMesh& ensMesh ); -//- Write volume field component-wise for specified cells +//- Write volume field component-wise, optionally forcing interpolation template<class Type> bool writeVolField ( + ensightFile& os, const GeometricField<Type, fvPatchField, volMesh>& vf, - const ensightPartCells& part, - ensightFile& os + const ensightMesh& ensMesh, + const bool nodeValues ); - -//- Write volume field component-wise +//- Write point field component-wise template<class Type> -bool writeVolField +bool writePointField ( - const GeometricField<Type, fvPatchField, volMesh>& vf, - const ensightParts& list, - ensightFile& os + ensightFile& os, + const GeometricField<Type, pointPatchField, pointMesh>& pf, + const ensightMesh& ensMesh ); -} // End namespace Serial - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/conversion/ensight/output/ensightOutputVolFieldTemplates.C b/src/conversion/ensight/output/ensightOutputVolFieldTemplates.C index de1238cf54f..f08c0ad0c65 100644 --- a/src/conversion/ensight/output/ensightOutputVolFieldTemplates.C +++ b/src/conversion/ensight/output/ensightOutputVolFieldTemplates.C @@ -5,8 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2019 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -30,132 +29,167 @@ License #include "ensightMesh.H" #include "fvMesh.H" -#include "globalIndex.H" +#include "linear.H" #include "volPointInterpolation.H" #include "interpolation.H" -#include "linear.H" #include "processorFvPatch.H" -#include "uindirectPrimitivePatch.H" +#include "DynamicField.H" // * * * * * * * * * * * * * * * * Detail * * * * * * * * * * * * * * * * * // template<class Type> -bool Foam::ensightOutput::Detail::writeVolField +bool Foam::ensightOutput::writeVolField ( + ensightFile& os, const GeometricField<Type, fvPatchField, volMesh>& vf, - const ensightMesh& ensMesh, - ensightFile& os + const ensightMesh& ensMesh ) { - constexpr bool parallel = true; + bool parallel = Pstream::parRun(); - const fvMesh& mesh = ensMesh.mesh(); - const ensightCells& meshCells = ensMesh.meshCells(); - const Map<word>& patchLookup = ensMesh.patches(); - const HashTable<ensightFaces>& patchFaces = ensMesh.boundaryPatchFaces(); - const HashTable<ensightFaces>& zoneFaces = ensMesh.faceZoneFaces(); + const fvMesh& mesh = vf.mesh(); + const polyBoundaryMesh& bmesh = mesh.boundaryMesh(); - // - // write internalMesh, unless patch-selection was requested - // - if (ensMesh.useInternalMesh()) + const Map<ensightCells>& cellZoneParts = ensMesh.cellZoneParts(); + const Map<ensightFaces>& faceZoneParts = ensMesh.faceZoneParts(); + const Map<ensightFaces>& boundaryParts = ensMesh.boundaryParts(); + + + // Write internalMesh and cellZones - sorted by index + for (const label zoneId : cellZoneParts.sortedToc()) { - Detail::writeCellField(vf, meshCells, os, parallel); + const ensightCells& part = cellZoneParts[zoneId]; + + ensightOutput::writeField(os, vf, part, parallel); } - // - // write patches - // use sortedToc for extra safety - // - const labelList patchIds = patchLookup.sortedToc(); - for (const label patchId : patchIds) + + // Write patches - sorted by index + for (const label patchId : boundaryParts.sortedToc()) { - const word& patchName = patchLookup[patchId]; - const ensightFaces& part = patchFaces[patchName]; + const ensightFaces& part = boundaryParts[patchId]; - writeFaceField + if (patchId < 0 || patchId >= bmesh.size()) + { + // Future handling of combined patches? + continue; + } + + const label patchStart = bmesh[patchId].start(); + + // Either use a flat boundary field for all patches, + // or patch-local face ids + + // Operate on a copy + ensightFaces localPart(part); + + // Change from global faceIds to patch-local + localPart.decrFaceIds(patchStart); + + ensightOutput::writeField ( - vf.boundaryField()[patchId], - part, os, + vf.boundaryField()[patchId], + localPart, parallel ); } - // - // write faceZones, if requested - // use sortedToc for extra safety - // - const wordList zoneNames = zoneFaces.sortedToc(); - if (!zoneNames.empty()) + // No face zones data + if (faceZoneParts.empty()) { - // Interpolates cell values to faces - needed only when exporting - // faceZones... - GeometricField<Type, fvsPatchField, surfaceMesh> sf - ( - Foam::linearInterpolate(vf) - ); + return true; + } - // flat boundary field - // similar to volPointInterpolation::flatBoundaryField() - Field<Type> flat(mesh.nBoundaryFaces(), Zero); + // Flat boundary field + // similar to volPointInterpolation::flatBoundaryField() + + Field<Type> flat(mesh.nBoundaryFaces(), Zero); + + const fvBoundaryMesh& bm = mesh.boundary(); + forAll(vf.boundaryField(), patchi) + { + const polyPatch& pp = bm[patchi].patch(); + const auto& bf = vf.boundaryField()[patchi]; - const fvBoundaryMesh& bm = mesh.boundary(); - forAll(vf.boundaryField(), patchi) + if (isA<processorFvPatch>(bm[patchi])) { - const polyPatch& pp = bm[patchi].patch(); - const auto& bf = vf.boundaryField()[patchi]; - - if (isA<processorFvPatch>(bm[patchi])) - { - // Use average value for processor faces - // own cell value = patchInternalField - // nei cell value = evaluated boundary values - SubList<Type> - ( - flat, - bf.size(), - pp.offset() - ) = (0.5 * (bf.patchInternalField() + bf)); - } - else if (!isA<emptyFvPatch>(bm[patchi])) - { - SubList<Type> - ( - flat, - bf.size(), - pp.offset() - ) = bf; - } + // Use average value for processor faces + // own cell value = patchInternalField + // nei cell value = evaluated boundary values + SubList<Type> + ( + flat, + bf.size(), + pp.offset() + ) = (0.5 * (bf.patchInternalField() + bf)); + } + else if (!isA<emptyFvPatch>(bm[patchi])) + { + SubList<Type> + ( + flat, + bf.size(), + pp.offset() + ) = bf; } + } + + + // Interpolate cell values to faces + // - only needed when exporting faceZones... + + tmp<GeometricField<Type, fvsPatchField, surfaceMesh>> tsfld + = Foam::linearInterpolate(vf); + + const auto& sfld = tsfld(); + + + // Local output buffer + label maxLen = 0; + + forAllConstIters(faceZoneParts, iter) + { + maxLen = max(maxLen, iter.val().size()); + } + + DynamicField<Type> values(maxLen); + - for (const word& zoneName : zoneNames) + // + // Write requested faceZones - sorted by index + // + for (const label zoneId : faceZoneParts.sortedToc()) + { + const ensightFaces& part = faceZoneParts[zoneId]; + + // Loop over face ids to store the needed field values + // - internal faces use linear interpolation + // - boundary faces use the corresponding patch value + + // Local copy of the field + values.resize(part.size()); + values = Zero; + + auto valIter = values.begin(); + + for (const label faceId : part.faceIds()) { - const ensightFaces& part = zoneFaces[zoneName]; - - // Field (local size) - Field<Type> values(part.size()); - - // Loop over face ids to store the needed field values - // - internal faces use linear interpolation - // - boundary faces use the corresponding patch value - forAll(part, i) - { - const label faceId = part[i]; - values[i] = - ( - mesh.isInternalFace(faceId) - ? sf[faceId] - : flat[faceId - mesh.nInternalFaces()] - ); - } - - // The field is already copied in the proper order - // - just need its corresponding sub-fields - Detail::writeFaceSubField(values, part, os, parallel); + *valIter = + ( + mesh.isInternalFace(faceId) + ? sfld[faceId] + : flat[faceId - mesh.nInternalFaces()] + ); + + ++valIter; } + + // The field is already in the proper element order + // - just need its corresponding sub-fields + ensightOutput::Detail::writeFaceSubField(os, values, part, parallel); } return true; @@ -163,118 +197,90 @@ bool Foam::ensightOutput::Detail::writeVolField template<class Type> -bool Foam::ensightOutput::Detail::writePointField +bool Foam::ensightOutput::writePointField ( + ensightFile& os, const GeometricField<Type, pointPatchField, pointMesh>& pf, - const ensightMesh& ensMesh, - ensightFile& os + const ensightMesh& ensMesh ) { - constexpr bool parallel = true; + bool parallel = Pstream::parRun(); - const fvMesh& mesh = ensMesh.mesh(); - const Map<word>& patchLookup = ensMesh.patches(); + const polyMesh& mesh = ensMesh.mesh(); - const HashTable<ensightFaces>& patchFaces = ensMesh.boundaryPatchFaces(); - const HashTable<ensightFaces>& zoneFaces = ensMesh.faceZoneFaces(); + const Map<ensightCells>& cellZoneParts = ensMesh.cellZoneParts(); + const Map<ensightFaces>& faceZoneParts = ensMesh.faceZoneParts(); + const Map<ensightFaces>& boundaryParts = ensMesh.boundaryParts(); // - // write internalMesh, unless patch-selection was requested + // Write internalMesh and cellZones - sorted by index // - if (ensMesh.useInternalMesh()) + for (const label zoneId : cellZoneParts.sortedToc()) { + const ensightCells& part = cellZoneParts[zoneId]; + + labelList uniqueMeshPointLabels; + part.uniqueMeshPoints(mesh, uniqueMeshPointLabels, parallel); + if (Pstream::master()) { - os.beginPart(0); // 0 = internalMesh + os.beginPart(part.index()); } - Detail::writeFieldComponents + ensightOutput::Detail::writeFieldComponents ( - "coordinates", - Field<Type>(pf.internalField(), ensMesh.uniquePointMap()), os, + ensightFile::coordinates, + UIndirectList<Type>(pf.internalField(), uniqueMeshPointLabels), parallel ); } + // - // write patches - // use sortedToc for extra safety + // Write patches - sorted by index // - const labelList patchIds = patchLookup.sortedToc(); - for (const label patchId : patchIds) + for (const label patchId : boundaryParts.sortedToc()) { - const word& patchName = patchLookup[patchId]; - const ensightFaces& part = patchFaces[patchName]; - - const fvPatch& p = mesh.boundary()[patchId]; + const ensightFaces& part = boundaryParts[patchId]; - // Renumber the patch points/faces into unique points - labelList pointToGlobal; labelList uniqueMeshPointLabels; - autoPtr<globalIndex> globalPointsPtr = - mesh.globalData().mergePoints - ( - p.patch().meshPoints(), - p.patch().meshPointMap(), - pointToGlobal, - uniqueMeshPointLabels - ); + part.uniqueMeshPoints(mesh, uniqueMeshPointLabels, parallel); if (Pstream::master()) { os.beginPart(part.index()); } - Detail::writeFieldComponents + ensightOutput::Detail::writeFieldComponents ( - "coordinates", - Field<Type>(pf.internalField(), uniqueMeshPointLabels), os, + ensightFile::coordinates, + UIndirectList<Type>(pf.internalField(), uniqueMeshPointLabels), parallel ); } // - // write faceZones, if requested + // Write requested faceZones - sorted by index // - const wordList zoneNames = zoneFaces.sortedToc(); - for (const word& zoneName : zoneNames) + for (const label zoneId : faceZoneParts.sortedToc()) { - const ensightFaces& part = zoneFaces[zoneName]; - - uindirectPrimitivePatch p - ( - UIndirectList<face> - ( - mesh.faces(), - part.faceIds() - ), - mesh.points() - ); + const ensightFaces& part = faceZoneParts[zoneId]; - // Renumber the patch points/faces into unique points - labelList pointToGlobal; labelList uniqueMeshPointLabels; - autoPtr<globalIndex> globalPointsPtr = - mesh.globalData().mergePoints - ( - p.meshPoints(), - p.meshPointMap(), - pointToGlobal, - uniqueMeshPointLabels - ); + part.uniqueMeshPoints(mesh, uniqueMeshPointLabels, parallel); if (Pstream::master()) { os.beginPart(part.index()); } - Detail::writeFieldComponents + ensightOutput::Detail::writeFieldComponents ( - "coordinates", - Field<Type>(pf.internalField(), uniqueMeshPointLabels), os, + ensightFile::coordinates, + UIndirectList<Type>(pf.internalField(), uniqueMeshPointLabels), parallel ); } @@ -288,9 +294,9 @@ bool Foam::ensightOutput::Detail::writePointField template<class Type> bool Foam::ensightOutput::writeVolField ( + ensightFile& os, const GeometricField<Type, fvPatchField, volMesh>& vf, const ensightMesh& ensMesh, - ensightFile& os, const bool nodeValues ) { @@ -303,90 +309,10 @@ bool Foam::ensightOutput::writeVolField pfld.ref().checkOut(); pfld.ref().rename(vf.name()); - return Detail::writePointField<Type>(pfld, ensMesh, os); + return ensightOutput::writePointField<Type>(os, pfld, ensMesh); } - return Detail::writeVolField<Type>(vf, ensMesh, os); -} - - -// * * * * * * * * * * * * * * * * Serial * * * * * * * * * * * * * * * * * // - -template<class Type> -bool Foam::ensightOutput::Serial::writeVolField -( - const GeometricField<Type, fvPatchField, volMesh>& vf, - const ensightPartFaces& part, - ensightFile& os -) -{ - constexpr bool parallel = false; // serial - - const label patchi = part.patchIndex(); - - if (patchi >= 0 && patchi < vf.boundaryField().size()) - { - return ensightOutput::Detail::writeFaceField - ( - vf.boundaryField()[patchi], - part, - os, - parallel - ); - } - - return false; -} - - -template<class Type> -bool Foam::ensightOutput::Serial::writeVolField -( - const GeometricField<Type, fvPatchField, volMesh>& vf, - const ensightPartCells& part, - ensightFile& os -) -{ - constexpr bool parallel = false; // serial - - return ensightOutput::Detail::writeCellField - ( - vf.internalField(), - part, - os, - parallel - ); -} - - -template<class Type> -bool Foam::ensightOutput::Serial::writeVolField -( - const GeometricField<Type, fvPatchField, volMesh>& vf, - const ensightParts& list, - ensightFile& os -) -{ - for (const ensightPart& part : list) - { - const ensightPartFaces* fptr = isA<ensightPartFaces>(part); - - if (fptr) - { - Serial::writeVolField(vf, *fptr, os); - continue; - } - - const ensightPartCells* cptr = isA<ensightPartCells>(part); - - if (cptr) - { - Serial::writeVolField(vf, *cptr, os); - continue; - } - } - - return true; + return ensightOutput::writeVolField<Type>(os, vf, ensMesh); } diff --git a/src/fileFormats/Make/files b/src/fileFormats/Make/files index 62f54aaba6c..e08ede224e5 100644 --- a/src/fileFormats/Make/files +++ b/src/fileFormats/Make/files @@ -7,12 +7,20 @@ ensight/file/ensightCaseOptions.C ensight/file/ensightFile.C ensight/file/ensightGeoFile.C -ensight/part/ensightCells.C -ensight/part/ensightFaces.C -ensight/part/ensightPart.C -ensight/part/ensightPartCells.C -ensight/part/ensightPartFaces.C -ensight/part/ensightParts.C +ensight/mesh/ensightMesh.C +ensight/mesh/ensightMeshOptions.C + +ensight/output/ensightOutput.C + +part = ensight/part +$(part)/cells/ensightCells.C +$(part)/cells/ensightCellsAddr.C +$(part)/cells/ensightCellsIO.C +$(part)/faces/ensightFaces.C +$(part)/faces/ensightFacesAddr.C +$(part)/faces/ensightFacesIO.C +$(part)/part/ensightPart.C +$(part)/surface/ensightOutputSurface.C ensight/read/ensightReadFile.C ensight/type/ensightPTraits.C diff --git a/src/fileFormats/ensight/mesh/ensightMesh.C b/src/fileFormats/ensight/mesh/ensightMesh.C new file mode 100644 index 00000000000..4dfdf835c37 --- /dev/null +++ b/src/fileFormats/ensight/mesh/ensightMesh.C @@ -0,0 +1,479 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2011-2016 OpenFOAM Foundation + Copyright (C) 2016-2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "ensightMesh.H" +#include "ensightGeoFile.H" +#include "polyMesh.H" +#include "emptyPolyPatch.H" +#include "processorPolyPatch.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const Foam::label Foam::ensightMesh::internalZone = -1; + + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Find matching ids based on whitelist, blacklist +// +// An empty whitelist accepts everything that is not blacklisted. +// A regex match is trumped by a literal match. +// +// Eg, +// input: ( abc apple wall wall1 wall2 ) +// whitelist: ( abc def "wall.*" ) +// blacklist: ( "[ab].*" wall ) +// +// result: (abc wall1 wall2) +// +static labelList getSelected +( + const UList<word>& input, + const wordRes& whitelist, + const wordRes& blacklist +) +{ + const label len = input.size(); + + if (whitelist.empty() && blacklist.empty()) + { + return identity(len); + } + + labelList indices(len); + + label count = 0; + for (label i=0; i < len; ++i) + { + const auto& text = input[i]; + + bool accept = false; + + if (whitelist.size()) + { + const auto result = whitelist.matched(text); + + accept = + ( + result == wordRe::LITERAL + ? true + : (result == wordRe::REGEX && !blacklist.match(text)) + ); + } + else + { + accept = !blacklist.match(text); + } + + if (accept) + { + indices[count] = i; + ++count; + } + } + indices.resize(count); + + return indices; +} + + +// Patch names without processor patches +static wordList nonProcessorPatchNames(const polyBoundaryMesh& bmesh) +{ + #ifdef FULLDEBUG + // Patches are output. Check that they are synced. + bmesh.checkParallelSync(true); + #endif + + wordList patchNames(bmesh.names()); + patchNames.resize(bmesh.nNonProcessor()); + + return patchNames; +} + + +} // End namespace Foam + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::ensightMesh::clear() +{ + cellZoneParts_.clear(); + faceZoneParts_.clear(); + boundaryParts_.clear(); +} + + +void Foam::ensightMesh::renumber() +{ + label partNo = 0; + + for (const label id : cellZoneParts_.sortedToc()) + { + cellZoneParts_[id].index() = partNo++; + } + + for (const label id : boundaryParts_.sortedToc()) + { + boundaryParts_[id].index() = partNo++; + } + + for (const label id : faceZoneParts_.sortedToc()) + { + faceZoneParts_[id].index() = partNo++; + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::ensightMesh::ensightMesh +( + const polyMesh& mesh +) +: + ensightMesh(mesh, ensightMesh::options()) +{} + + +Foam::ensightMesh::ensightMesh +( + const polyMesh& mesh, + const ensightMesh::options& opts +) +: + options_(new options(opts)), + mesh_(mesh), + needsUpdate_(true) +{ + if (!option().lazy()) + { + correct(); + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::ensightMesh::correct() +{ + clear(); + + const wordRes& czMatcher = option().cellZoneSelection(); + const wordRes& fzMatcher = option().faceZoneSelection(); + + // Possible cellZones + const wordList czNames = + ( + ( + option().useCellZones() + && (!czMatcher.empty() || option().useInternalMesh()) + ) + ? mesh_.cellZones().names() + : wordList() + ); + + const labelList czoneIds = + ( + czMatcher.empty() + ? identity(czNames.size()) // All + : czMatcher.matching(czNames) // Selected names + ); + + + // Possible faceZones + const wordList fzNames = + ( + option().useFaceZones() + ? mesh_.faceZones().names() + : wordList() + ); + + const labelList fzoneIds = + ( + fzMatcher.empty() + ? identity(fzNames.size()) // All + : fzMatcher.matching(fzNames) // Selected names + ); + + + // Possible patchNames + const wordList patchNames = + ( + option().useBoundaryMesh() + ? nonProcessorPatchNames(mesh_.boundaryMesh()) + : wordList() + ); + + const labelList patchIds = + ( + option().useBoundaryMesh() + ? getSelected + ( + patchNames, + option().patchSelection(), + option().patchExclude() + ) + : labelList() + ); + + + // Track which cells are in a zone or not + bitSet cellSelection; + + // Faces to be excluded from export + bitSet excludeFace; + + + // cellZones first + for (const label zoneId : czoneIds) + { + const word& zoneName = czNames[zoneId]; + const cellZone& zn = mesh_.cellZones()[zoneId]; + + if (returnReduce(!zn.empty(), orOp<bool>())) + { + cellSelection.set(zn); + + ensightCells& part = cellZoneParts_(zoneId); + + part.clear(); + part.identifier() = zoneId; + part.rename(zoneName); + + part.classify(mesh_, zn); + + // Finalize + part.reduce(); + } + } + + if (option().useInternalMesh() && czMatcher.empty()) + { + // The internal mesh: + // Either the entire mesh (if no zones specified) + // or whatever is leftover as unzoned + + if (cellZoneParts_.empty()) + { + ensightCells& part = cellZoneParts_(internalZone); + + part.clear(); + part.identifier() = internalZone; + part.rename("internalMesh"); + + part.classify(mesh_); + + // Finalize + part.reduce(); + } + else + { + // Unzoned cells - flip selection from zoned to unzoned + cellSelection.flip(); + + if (returnReduce(cellSelection.any(), orOp<bool>())) + { + ensightCells& part = cellZoneParts_(internalZone); + + part.clear(); + part.identifier() = internalZone; + part.rename("internalMesh"); + + part.classify(mesh_, cellSelection); + + // Finalize + part.reduce(); + } + } + + // Handled all cells + cellSelection.clearStorage(); + } + else if (cellSelection.none()) + { + // No internal, no cellZones selected - just ignore + cellSelection.clearStorage(); + } + + + // Face exclusion based on cellZones + + if (returnReduce(!cellSelection.empty(), orOp<bool>())) + { + excludeFace.resize(mesh_.nFaces()); + + const labelList& owner = mesh_.faceOwner(); + + forAll(owner, facei) + { + const label celli = owner[facei]; + + if (!cellSelection.test(celli)) + { + excludeFace.set(facei); + } + } + } + + + // Face exclusion for empty/processor types + // so they are ignored for face zones + + if (fzoneIds.size()) + { + excludeFace.resize(mesh_.nFaces()); + + for (const polyPatch& p : mesh_.boundaryMesh()) + { + const auto* procPatch = isA<processorPolyPatch>(p); + + if (isA<emptyPolyPatch>(p)) + { + excludeFace.set(p.range()); + } + else if (procPatch && !procPatch->owner()) + { + // Exclude neighbour-side, retain owner-side only + excludeFace.set(p.range()); + } + } + } + + + // Patches + for (const label patchId : patchIds) + { + const word& patchName = patchNames[patchId]; + const polyPatch& p = mesh_.boundaryMesh()[patchId]; + + if (isA<emptyPolyPatch>(p)) + { + // Skip empty patch types + continue; + } + else if (isA<processorPolyPatch>(p)) + { + // Only real (non-processor) boundaries. + break; + } + + ensightFaces& part = boundaryParts_(patchId); + + part.clear(); + part.identifier() = patchId; + part.rename(patchName); + + part.classify + ( + mesh_.faces(), + identity(p.size(), p.start()), + boolList(), // no flip map + excludeFace + ); + + // Finalize + part.reduce(); + + if (!part.total()) + { + boundaryParts_.erase(patchId); + } + } + + + // Face zones + + for (const label zoneId : fzoneIds) + { + const word& zoneName = fzNames[zoneId]; + const faceZone& zn = mesh_.faceZones()[zoneId]; + + ensightFaces& part = faceZoneParts_(zoneId); + + part.clear(); + part.identifier() = zoneId; + part.rename(zoneName); + + if (zn.size()) + { + part.classify + ( + mesh_.faces(), + zn, + zn.flipMap(), + excludeFace + ); + } + + // Finalize + part.reduce(); + + if (!part.total()) + { + faceZoneParts_.erase(zoneId); + } + } + + renumber(); + + needsUpdate_ = false; +} + + +void Foam::ensightMesh::write +( + ensightGeoFile& os, + bool parallel +) const +{ + // The internalMesh, cellZones + for (const label id : cellZoneParts_.sortedToc()) + { + cellZoneParts_[id].write(os, mesh_, parallel); + } + + // Patches - sorted by index + for (const label id : boundaryParts_.sortedToc()) + { + boundaryParts_[id].write(os, mesh_, parallel); + } + + // Requested faceZones - sorted by index + for (const label id : faceZoneParts_.sortedToc()) + { + faceZoneParts_[id].write(os, mesh_, parallel); + } +} + + +// ************************************************************************* // diff --git a/src/fileFormats/ensight/mesh/ensightMesh.H b/src/fileFormats/ensight/mesh/ensightMesh.H new file mode 100644 index 00000000000..1db242c65e5 --- /dev/null +++ b/src/fileFormats/ensight/mesh/ensightMesh.H @@ -0,0 +1,342 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2011-2016 OpenFOAM Foundation + Copyright (C) 2016-2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::ensightMesh + +Description + Encapsulation of volume meshes for writing in ensight format. + It manages cellZones, facesZone, patches. + + When cellZones are present (and not disabled), the cells are grouped + in parts according to the zone. + Any remaining \em unzoned cells are placed into the "internalMesh" part, + which is always part 0. If cellZones are missing or disabled, + all cells are placed into the "internalMesh" part. + + If one or more cellZones are explicitly requested, all other cells + (including any unzoned cells) are ignored. + + The converted patch faces are restricted by the volume mesh coverage. + Except when the entire internal mesh has been explicitly suppressed. + +Note + The internal data management uses a Map for cellZones, faceZones and + patches. The internalMesh is treated as cellZone with a special index. + + Since the patches are subsetted by the internal mesh coverage, + they are treated as indirect patches rather than regular poly patches. + +SourceFiles + ensightMesh.C + ensightMeshI.H + ensightMeshOptions.C + +\*---------------------------------------------------------------------------*/ + +#ifndef ensightMesh_H +#define ensightMesh_H + +#include "Map.H" +#include "ensightCells.H" +#include "ensightFaces.H" +#include "wordRes.H" +#include <memory> + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class polyMesh; +class ensightGeoFile; +class ensightMesh; + +/*---------------------------------------------------------------------------*\ + Class ensightMesh Declaration +\*---------------------------------------------------------------------------*/ + +class ensightMesh +{ +public: + + // Forward Declarations + class options; + + //- The zone-id for internal mesh or unzoned cells. + static const label internalZone; + + +private: + + // Private Data + + //- Writer options + const std::unique_ptr<options> options_; + + //- Reference to the OpenFOAM mesh + const polyMesh& mesh_; + + //- Volume elements per cellZone, lookup by zone index. + // The zone -1 is reserved for internal mesh (unzoned cells) + Map<ensightCells> cellZoneParts_; + + //- Face elements per faceZone, lookup by zone index. + Map<ensightFaces> faceZoneParts_; + + //- Face elements per selected patch, lookup by patch index + Map<ensightFaces> boundaryParts_; + + //- Track if it needs an update + mutable bool needsUpdate_; + + + // Private Member Functions + + //- Clear all storage + void clear(); + + //- Enforce consistent index/part numbering + void renumber(); + + //- No copy construct + ensightMesh(const ensightMesh&) = delete; + + //- No copy assignment + void operator=(const ensightMesh&) = delete; + + +public: + + // Constructors + + //- Construct from mesh with all default options + explicit ensightMesh(const polyMesh& mesh); + + //- Construct from components + ensightMesh(const polyMesh& mesh, const options& opts); + + + // Member Functions + + // Access + + //- Reference to the underlying polyMesh + inline const polyMesh& mesh() const; + + //- Reference to the writer/mesh options + inline const ensightMesh::options& option() const; + + //- Face elements per selected patch, lookup by patch index + // Process in sorted order. + // May require special treatment for zone -1 (internal). + inline const Map<ensightCells>& cellZoneParts() const; + + //- Face elements per faceZone, lookup by zone index. + // Process in sorted order. + inline const Map<ensightFaces>& faceZoneParts() const; + + //- Face elements per selected patch, lookup by patch index + // Process in sorted order. + inline const Map<ensightFaces>& boundaryParts() const; + + + // Sizing Information + + //- Any parts? + inline bool empty() const; + + //- Number of parts + inline label size() const; + + + // Other + + //- Does the content need an update? + inline bool needsUpdate() const; + + //- Mark as needing an update. + // May also free up unneeded data. + // Return false if already marked as expired. + inline bool expire(); + + //- Update for new mesh + void correct(); + + + // Output + + //- Write geometry to file. Normally in parallel + inline void write + ( + autoPtr<ensightGeoFile>& os, + bool parallel = Pstream::parRun() + ) const; + + //- Write geometry to file. Normally in parallel + void write + ( + ensightGeoFile& os, + bool parallel = Pstream::parRun() + ) const; +}; + + +/*---------------------------------------------------------------------------*\ + Class ensightMesh::options Declaration +\*---------------------------------------------------------------------------*/ + +//- Configuration options for the ensightMesh +class ensightMesh::options +{ + // Private Data + + //- Create in 'expired' mode + bool lazy_; + + //- Use the internal mesh + bool internal_; + + //- Use the boundary mesh + bool boundary_; + + //- Handle cellZones (if internal_ is true) + bool cellZones_; + + //- Selected patches only + wordRes patchInclude_; + + //- Deselected patches + wordRes patchExclude_; + + //- Selected cellZones + wordRes cellZoneInclude_; + + //- Selected faceZones + wordRes faceZoneInclude_; + + +public: + + // Constructors + + //- Default construct. Non-lazy with internal/boundary/cellZones. + options(); + + + // Member Functions + + // Access + + //- Lazy creation? (ie, ensightMesh starts as needsUpdate) + bool lazy() const; + + //- Using internal? + bool useInternalMesh() const; + + //- Using boundary? + bool useBoundaryMesh() const; + + //- Using faceZones? + bool useFaceZones() const; + + //- Using cellZones? + bool useCellZones() const; + + //- Selection of patches. Empty if unspecified. + const wordRes& patchSelection() const; + + //- Selection of black listed patches. Empty if unspecified. + const wordRes& patchExclude() const; + + //- Selection of faceZones. Empty if unspecified. + const wordRes& faceZoneSelection() const; + + //- Selection of faceZones. Empty if unspecified. + const wordRes& cellZoneSelection() const; + + + // Edit + + //- Reset to defaults + void reset(); + + //- Lazy creation - ensightMesh starts as needsUpdate + void lazy(bool beLazy); + + //- Alter the useBoundaryMesh state + void useInternalMesh(bool on); + + //- Alter the useBoundaryMesh state + void useBoundaryMesh(bool on); + + //- Alter the useCellZones state + void useCellZones(bool on); + + //- Define patch selection matcher + void patchSelection(const UList<wordRe>& patterns); + + //- Define patch selection matcher + void patchSelection(List<wordRe>&& patterns); + + //- Define patch selection blacklist + void patchExclude(const UList<wordRe>& patterns); + + //- Define patch selection blacklist + void patchExclude(List<wordRe>&& patterns); + + //- Define faceZone selection matcher + void faceZoneSelection(const UList<wordRe>& patterns); + + //- Define faceZone selection matcher + void faceZoneSelection(List<wordRe>&& patterns); + + //- Define cellZone selection matcher + void cellZoneSelection(const UList<wordRe>& patterns); + + //- Define cellZone selection matcher + void cellZoneSelection(List<wordRe>&& patterns); + + + // Output + + //- Report values + void print(Ostream& os) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "ensightMeshI.H" + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ensight/mesh/ensightMeshI.H b/src/fileFormats/ensight/mesh/ensightMeshI.H similarity index 55% rename from src/conversion/ensight/mesh/ensightMeshI.H rename to src/fileFormats/ensight/mesh/ensightMeshI.H index 8691435d298..a9cdbfbc730 100644 --- a/src/conversion/ensight/mesh/ensightMeshI.H +++ b/src/fileFormats/ensight/mesh/ensightMeshI.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -25,9 +25,9 @@ License \*---------------------------------------------------------------------------*/ -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -inline const Foam::fvMesh& Foam::ensightMesh::mesh() const +inline const Foam::polyMesh& Foam::ensightMesh::mesh() const { return mesh_; } @@ -39,53 +39,77 @@ inline const Foam::ensightMesh::options& Foam::ensightMesh::option() const } -inline Foam::IOstream::streamFormat Foam::ensightMesh::format() const +inline const Foam::Map<Foam::ensightCells>& +Foam::ensightMesh::cellZoneParts() const { - return options_->format(); + return cellZoneParts_; } -inline bool Foam::ensightMesh::useInternalMesh() const +inline const Foam::Map<Foam::ensightFaces>& +Foam::ensightMesh::faceZoneParts() const { - return options_->useInternalMesh(); + return faceZoneParts_; } -inline bool Foam::ensightMesh::useBoundaryMesh() const +inline const Foam::Map<Foam::ensightFaces>& +Foam::ensightMesh::boundaryParts() const { - return options_->useBoundaryMesh(); + return boundaryParts_; } -inline const Foam::ensightCells& Foam::ensightMesh::meshCells() const +inline bool Foam::ensightMesh::expire() { - return meshCells_; + clear(); + + // Already marked as expired + if (needsUpdate_) + { + return false; + } + + needsUpdate_ = true; + return true; } -inline const Foam::Map<Foam::word>& Foam::ensightMesh::patches() const +inline bool Foam::ensightMesh::needsUpdate() const { - return patchLookup_; + return needsUpdate_; } -inline const Foam::HashTable<Foam::ensightFaces>& -Foam::ensightMesh::boundaryPatchFaces() const +inline bool Foam::ensightMesh::empty() const { - return boundaryPatchFaces_; + return + ( + cellZoneParts_.empty() + && faceZoneParts_.empty() + && boundaryParts_.empty() + ); } -inline const Foam::HashTable<Foam::ensightFaces>& -Foam::ensightMesh::faceZoneFaces() const +inline Foam::label Foam::ensightMesh::size() const { - return faceZoneFaces_; + return + ( + cellZoneParts_.size() + + faceZoneParts_.size() + + boundaryParts_.size() + ); } -inline void Foam::ensightMesh::write(autoPtr<ensightGeoFile>& os) const +inline void Foam::ensightMesh::write +( + autoPtr<ensightGeoFile>& os, + bool parallel +) const { - write(os.ref()); + write(os.ref(), parallel); } diff --git a/src/fileFormats/ensight/mesh/ensightMeshOptions.C b/src/fileFormats/ensight/mesh/ensightMeshOptions.C new file mode 100644 index 00000000000..831d076897f --- /dev/null +++ b/src/fileFormats/ensight/mesh/ensightMeshOptions.C @@ -0,0 +1,340 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016-2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "ensightMesh.H" +#include "Switch.H" + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// DIY flatOutput without a leading size indicator +static Ostream& printPatterns(Ostream& os, const wordRes& list) +{ + os << token::BEGIN_LIST; + + bool sep = false; + + for (const wordRe& item : list) + { + if (sep) os << token::SPACE; + os << item; + + sep = true; + } + os << token::END_LIST; + + return os; +} + +} // End namespace + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::ensightMesh::options::options() +: + lazy_(false), + internal_(true), + boundary_(true), + cellZones_(true), + patchInclude_(), + patchExclude_(), + cellZoneInclude_(), + faceZoneInclude_() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::ensightMesh::options::lazy() const +{ + return lazy_; +} + + +bool Foam::ensightMesh::options::useInternalMesh() const +{ + return internal_; +} + + +bool Foam::ensightMesh::options::useBoundaryMesh() const +{ + return boundary_; +} + + +bool Foam::ensightMesh::options::useCellZones() const +{ + return cellZones_; +} + + +bool Foam::ensightMesh::options::useFaceZones() const +{ + return faceZoneInclude_.size(); +} + + +void Foam::ensightMesh::options::reset() +{ + internal_ = true; + boundary_ = true; + cellZones_ = true; + patchInclude_.clear(); + patchExclude_.clear(); + faceZoneInclude_.clear(); + cellZoneInclude_.clear(); +} + + +void Foam::ensightMesh::options::lazy(bool beLazy) +{ + lazy_ = beLazy; +} + + +void Foam::ensightMesh::options::useInternalMesh(bool on) +{ + internal_ = on; +} + + +void Foam::ensightMesh::options::useBoundaryMesh(bool on) +{ + boundary_ = on; + + if (!boundary_) + { + if (patchInclude_.size()) + { + patchInclude_.clear(); + + WarningInFunction + << "Deactivating boundary, removed old patch selection" + << endl; + } + } +} + + +void Foam::ensightMesh::options::useCellZones(bool on) +{ + cellZones_ = on; + + if (!cellZones_ && cellZoneInclude_.size()) + { + cellZoneInclude_.clear(); + + WarningInFunction + << "Deactivating cellZones, removed old zone selection" + << endl; + } +} + + +void Foam::ensightMesh::options::patchSelection +( + const UList<wordRe>& patterns +) +{ + patchInclude_ = wordRes(patterns); + + if (!boundary_ && patchInclude_.size()) + { + patchInclude_.clear(); + + WarningInFunction + << "Ignoring patch selection, boundary is disabled" + << endl; + } +} + + +void Foam::ensightMesh::options::patchSelection +( + List<wordRe>&& patterns +) +{ + patchInclude_ = wordRes(std::move(patterns)); + + if (!boundary_ && patchInclude_.size()) + { + patchInclude_.clear(); + + WarningInFunction + << "Ignoring patch selection, boundary is disabled" + << endl; + } +} + + +void Foam::ensightMesh::options::patchExclude +( + const UList<wordRe>& patterns +) +{ + patchExclude_ = wordRes(patterns); +} + + +void Foam::ensightMesh::options::patchExclude +( + List<wordRe>&& patterns +) +{ + patchExclude_ = wordRes(std::move(patterns)); +} + + +void Foam::ensightMesh::options::faceZoneSelection +( + const UList<wordRe>& patterns +) +{ + faceZoneInclude_ = wordRes(patterns); +} + + +void Foam::ensightMesh::options::faceZoneSelection +( + List<wordRe>&& patterns +) +{ + faceZoneInclude_ = wordRes(std::move(patterns)); +} + + +void Foam::ensightMesh::options::cellZoneSelection +( + const UList<wordRe>& patterns +) +{ + cellZoneInclude_ = wordRes(patterns); + + if (!cellZones_ && cellZoneInclude_.size()) + { + cellZoneInclude_.clear(); + + WarningInFunction + << "Ignoring cellZone selection, cellZones are disabled" + << endl; + } +} + + +void Foam::ensightMesh::options::cellZoneSelection +( + List<wordRe>&& patterns +) +{ + cellZoneInclude_ = wordRes(std::move(patterns)); + + if (!cellZones_ && cellZoneInclude_.size()) + { + cellZoneInclude_.clear(); + + WarningInFunction + << "Ignoring cellZone selection, cellZones are disabled" + << endl; + } +} + + +const Foam::wordRes& Foam::ensightMesh::options::patchSelection() const +{ + return patchInclude_; +} + + +const Foam::wordRes& Foam::ensightMesh::options::patchExclude() const +{ + return patchExclude_; +} + + +const Foam::wordRes& Foam::ensightMesh::options::faceZoneSelection() const +{ + return faceZoneInclude_; +} + + +const Foam::wordRes& Foam::ensightMesh::options::cellZoneSelection() const +{ + return cellZoneInclude_; +} + + +void Foam::ensightMesh::options::print(Ostream& os) const +{ + os << "internal: " << Switch::name(internal_) << nl; + os << "cellZones: " << Switch::name(cellZones_) << nl; + if (cellZones_) + { + os.incrIndent(); + if (!cellZoneInclude_.empty()) + { + os.writeKeyword("include"); + printPatterns(os, cellZoneInclude_) << nl; + } + os.decrIndent(); + } + + os << "boundary: " << Switch::name(boundary_) << nl; + if (boundary_) + { + os.incrIndent(); + if (!patchInclude_.empty()) + { + os.writeKeyword("include"); + printPatterns(os, patchInclude_) << nl; + } + if (!patchExclude_.empty()) + { + os.writeKeyword("exclude"); + printPatterns(os, patchExclude_) << nl; + } + os.decrIndent(); + } + + os << "faceZones: " << Switch::name(useFaceZones()) << nl; + if (useFaceZones()) + { + os.incrIndent(); + if (!faceZoneInclude_.empty()) + { + os.writeKeyword("include"); + printPatterns(os, faceZoneInclude_) << nl; + } + os.decrIndent(); + } +} + + +// ************************************************************************* // diff --git a/src/fileFormats/ensight/output/ensightOutput.C b/src/fileFormats/ensight/output/ensightOutput.C new file mode 100644 index 00000000000..461f8322355 --- /dev/null +++ b/src/fileFormats/ensight/output/ensightOutput.C @@ -0,0 +1,490 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "ensightOutput.H" + +#include "cell.H" +#include "cellShape.H" +#include "face.H" +#include "polyMesh.H" +#include "ListOps.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Sizes + +Foam::labelList Foam::ensightOutput::Detail::getFaceSizes +( + const UList<face>& faces +) +{ + labelList list(faces.size()); + + auto outIter = list.begin(); + + for (const face& f : faces) + { + *outIter = f.size(); + ++outIter; + } + + return list; +} + + +Foam::labelList Foam::ensightOutput::Detail::getFaceSizes +( + const UIndirectList<face>& faces +) +{ + labelList list(faces.size()); + + auto outIter = list.begin(); + + for (const face& f : faces) + { + *outIter = f.size(); + ++outIter; + } + + return list; +} + + +Foam::labelList Foam::ensightOutput::Detail::getPolysNFaces +( + const polyMesh& mesh, + const labelUList& addr +) +{ + const cellList& meshCells = mesh.cells(); + + labelList list(addr.size()); + + auto outIter = list.begin(); + + // The number of faces per element + for (const label cellId : addr) + { + *outIter = meshCells[cellId].size(); + ++outIter; + } + + return list; +} + + +Foam::labelList Foam::ensightOutput::Detail::getPolysNPointsPerFace +( + const polyMesh& mesh, + const labelUList& addr +) +{ + const cellList& meshCells = mesh.cells(); + const faceList& meshFaces = mesh.faces(); + + // Count the number of faces per element + + label nTotFaces = 0; + for (const label cellId : addr) + { + nTotFaces += meshCells[cellId].size(); + } + + labelList list(nTotFaces); + + auto outIter = list.begin(); + + // The number of points per element face + for (const label cellId : addr) + { + for (const label facei : meshCells[cellId]) + { + *outIter = meshFaces[facei].size(); + ++outIter; + } + } + + return list; +} + + +void Foam::ensightOutput::writeFaceList +( + ensightGeoFile& os, + const UList<face>& faces +) +{ + for (const face& f : faces) + { + for (const label labi : f) + { + os.write(labi + 1); + } + + os.newline(); + } +} + + +void Foam::ensightOutput::writeFaceList +( + ensightGeoFile& os, + const UIndirectList<face>& faces +) +{ + for (const face& f : faces) + { + for (const label labi : f) + { + os.write(labi + 1); + } + + os.newline(); + } +} + + +void Foam::ensightOutput::writeCellShapes +( + ensightGeoFile& os, + const UList<cellShape>& shapes +) +{ + for (const cellShape& cellPoints : shapes) + { + // Convert global -> local index + // (note: Ensight indices start with 1) + + // In ASCII, write one cell per line + for (const label pointi : cellPoints) + { + os.write(pointi + 1); + } + + os.newline(); + } +} + + +void Foam::ensightOutput::writePolysPoints +( + ensightGeoFile& os, + const polyMesh& mesh, + const labelUList& addr, + const labelList& pointMap +) +{ + const cellList& meshCells = mesh.cells(); + const faceList& meshFaces = mesh.faces(); + const labelList& owner = mesh.faceOwner(); + + for (const label cellId : addr) + { + for (const label faceId : meshCells[cellId]) + { + const face& f = meshFaces[faceId]; + + if (faceId < owner.size() && owner[faceId] != cellId) + { + // The neighbour of an internal face + // - write as face::reverseFace() + + os.write(pointMap[f[0]] + 1); + for (label pti = f.size()-1; pti > 0; --pti) + { + os.write(pointMap[f[pti]] + 1); + } + } + else + { + for (const label pointi : f) + { + os.write(pointMap[pointi] + 1); + } + } + + os.newline(); + } + } +} + + +void Foam::ensightOutput::writePolysPoints +( + ensightGeoFile& os, + const cellUList& meshCells, + const labelUList& addr, + const faceUList& meshFaces, + const labelUList& owner +) +{ + for (const label cellId : addr) + { + for (const label faceId : meshCells[cellId]) + { + const face& f = meshFaces[faceId]; + + if (faceId < owner.size() && owner[faceId] != cellId) + { + // The neighbour of an internal face + // - write as face::reverseFace() + + os.write(f[0] + 1); + for (label pti = f.size()-1; pti > 0; --pti) + { + os.write(f[pti] + 1); + } + } + else + { + for (const label pointi : f) + { + os.write(pointi + 1); + } + } + + os.newline(); + } + } +} + + +void Foam::ensightOutput::writeFaceConnectivity +( + ensightGeoFile& os, + const ensightFaces::elemType etype, + const label nTotal, + const faceUList& faces, + bool parallel +) +{ + if (!nTotal) + { + return; + } + + parallel = parallel && Pstream::parRun(); + + const label nSlaves = (parallel ? Pstream::nProcs() : 0); + + if (Pstream::master()) + { + os.writeKeyword(ensightFaces::key(etype)); + os.write(nTotal); + os.newline(); + } + + if (etype == ensightFaces::NSIDED) + { + // Face sizes (number of points per face) + + labelList send(ensightOutput::Detail::getFaceSizes(faces)); + + if (Pstream::master()) + { + os.writeLabels(send); + + for (int slave=1; slave < nSlaves; ++slave) + { + IPstream fromSlave(Pstream::commsTypes::scheduled, slave); + labelList recv(fromSlave); + + os.writeLabels(recv); + } + } + else if (nSlaves) + { + OPstream toMaster + ( + Pstream::commsTypes::scheduled, + Pstream::masterNo() + ); + + toMaster << send; + } + } + + + // List of points id for each face + if (Pstream::master()) + { + writeFaceList(os, faces); + + for (int slave=1; slave < nSlaves; ++slave) + { + IPstream fromSlave(Pstream::commsTypes::scheduled, slave); + List<face> recv(fromSlave); + + writeFaceList(os, recv); + } + } + else if (nSlaves) + { + OPstream toMaster + ( + Pstream::commsTypes::scheduled, + Pstream::masterNo() + ); + + toMaster << faces; + } +} + + +void Foam::ensightOutput::writeFaceConnectivity +( + ensightGeoFile& os, + const ensightFaces::elemType etype, + const label nTotal, + const UIndirectList<face>& faces, + bool parallel +) +{ + if (!nTotal) + { + return; + } + + parallel = parallel && Pstream::parRun(); + + const label nSlaves = (parallel ? Pstream::nProcs() : 0); + + if (Pstream::master()) + { + os.writeKeyword(ensightFaces::key(etype)); + os.write(nTotal); + os.newline(); + } + + if (etype == ensightFaces::NSIDED) + { + // Face sizes (number of points per face) + + labelList send(ensightOutput::Detail::getFaceSizes(faces)); + + if (Pstream::master()) + { + os.writeLabels(send); + + for (int slave=1; slave < nSlaves; ++slave) + { + IPstream fromSlave(Pstream::commsTypes::scheduled, slave); + labelList recv(fromSlave); + + os.writeLabels(recv); + } + } + else if (nSlaves) + { + OPstream toMaster + ( + Pstream::commsTypes::scheduled, + Pstream::masterNo() + ); + + toMaster << send; + } + } + + + // List of points id per face + + if (Pstream::master()) + { + writeFaceList(os, faces); + + for (int slave=1; slave < nSlaves; ++slave) + { + IPstream fromSlave(Pstream::commsTypes::scheduled, slave); + List<face> recv(fromSlave); + + writeFaceList(os, recv); + } + } + else if (nSlaves) + { + OPstream toMaster + ( + Pstream::commsTypes::scheduled, + Pstream::masterNo() + ); + + toMaster << faces; + } +} + + +void Foam::ensightOutput::writeFaceConnectivity +( + ensightGeoFile& os, + const ensightFaces& part, + const faceUList& faces, + bool parallel +) +{ + for (label typei=0; typei < ensightFaces::nTypes; ++typei) + { + const auto etype = ensightFaces::elemType(typei); + + writeFaceConnectivity + ( + os, + etype, + part.total(etype), + UIndirectList<face>(faces, part.faceIds(etype)), + parallel + ); + } +} + + +void Foam::ensightOutput::writeFaceConnectivityPresorted +( + ensightGeoFile& os, + const ensightFaces& part, + const faceUList& faces, + bool parallel +) +{ + for (label typei=0; typei < ensightFaces::nTypes; ++typei) + { + const auto etype = ensightFaces::elemType(typei); + + writeFaceConnectivity + ( + os, + etype, + part.total(etype), + SubList<face>(faces, part.range(etype)), + parallel + ); + } +} + + +// ************************************************************************* // diff --git a/src/fileFormats/ensight/output/ensightOutput.H b/src/fileFormats/ensight/output/ensightOutput.H index 4c6a23fb78c..4a2f77dcbf4 100644 --- a/src/fileFormats/ensight/output/ensightOutput.H +++ b/src/fileFormats/ensight/output/ensightOutput.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2019 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -30,6 +30,7 @@ Description A collection of functions for writing ensight file content. SourceFiles + ensightOutput.C ensightOutputTemplates.C \*---------------------------------------------------------------------------*/ @@ -38,97 +39,276 @@ SourceFiles #define ensightOutput_H #include "ensightFile.H" +#include "ensightGeoFile.H" #include "ensightCells.H" #include "ensightFaces.H" #include "ensightPTraits.H" +#include "faceListFwd.H" +#include "cellListFwd.H" + +#include "ListOps.H" +#include "ListListOps.H" +#include "IndirectList.H" + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Local definitions, could be relocated to ListListOps directly + +namespace Foam +{ +namespace ListListOps +{ + +//- Return the sizes of the sub-lists +template<class T, class Addr, class AccessOp> +labelList subSizes +( + const IndirectListBase<T, Addr>& lists, + AccessOp aop +) +{ + labelList output(lists.size()); + auto out = output.begin(); + + for (const T& sub : lists) + { + *out = aop(sub).size(); + ++out; + } + + return output; +} + + +//- Inplace renumber the values (not the indices) of a list of lists. +// Negative IntListType elements are left untouched. +template<class IntListType> +void inplaceRenumber +( + const labelUList& oldToNew, + IntListType& lists +) +{ + for (auto& sub : lists) + { + for (auto& item : sub) + { + if (item >= 0) + { + item = oldToNew[item]; + } + } + } +} + +} // End namespace ListListOps +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { + +// Forward Declarations +class cellShape; +class polyMesh; + namespace ensightOutput { /*---------------------------------------------------------------------------*\ - Namespace ensightOutput::Detail + Geometry Output \*---------------------------------------------------------------------------*/ -//- \brief Implementation details and output backends that would not normally -//- be called directly by a user. +//- Write list of faces +void writeFaceList +( + ensightGeoFile& os, + const UList<face>& faces +); -namespace Detail -{ +//- Write list of faces +void writeFaceList +( + ensightGeoFile& os, + const UIndirectList<face>& faces +); -//- Write field content (component-wise) for the given ensight element type -template<template<typename> class FieldContainer, class Type> -bool writeFieldComponents +//- Write cell connectivity via cell shapes +void writeCellShapes ( - const char* key, - const FieldContainer<Type>& fld, - ensightFile& os, - bool parallel //!< Collective write? + ensightGeoFile& os, + const UList<cellShape>& shapes ); -//- Write a field of faces values as an indirect list, -//- using the face ids from ensightFaces -template<class Type> -bool writeFaceField +//- Write the point ids per poly element. +// Points have been already renumbered +void writePolysPoints ( - const Field<Type>& fld, + ensightGeoFile& os, + const cellUList& meshCells, + const labelUList& addr, //!< Cell ids to write + const faceUList& meshFaces, + const labelUList& faceOwner +); + +//- Write the point ids per poly element, with point renumbering +void writePolysPoints +( + ensightGeoFile& os, + const polyMesh& mesh, + const labelUList& addr, //!< Cell ids to write + const labelList& pointMap //!< Point map to use +); + + +//- Write the regular face connectivity for specified type and +//- and specified faces +void writeFaceConnectivity +( + ensightGeoFile& os, + const ensightFaces::elemType etype, + const label nTotal, + const UIndirectList<face>& faces, + bool parallel //!< Collective write? +); + + +//- Write the regular face connectivity for specified type +void writeFaceConnectivity +( + ensightGeoFile& os, + const ensightFaces::elemType etype, + const label nTotal, + const faceUList& faces, + bool parallel //!< Collective write? +); + + +//- Write the face connectivity for the part +void writeFaceConnectivity +( + ensightGeoFile& os, const ensightFaces& part, - ensightFile& os, - bool parallel //!< Collective write? + const faceUList& faces, + bool parallel //!< Collective write? ); -//- Write a sub-field of faces values as an indirect list, -//- using the sublist sizing information from ensightFaces -template<class Type> -bool writeFaceSubField +//- Write the \b presorted face connectivity for the part +// This is a special case when the list of faces is already in +// ensight sorted order +void writeFaceConnectivityPresorted ( - const Field<Type>& fld, + ensightGeoFile& os, const ensightFaces& part, - ensightFile& os, - bool parallel //!< Collective write? + const faceUList& faces, + bool parallel //!< Collective write? ); +/*---------------------------------------------------------------------------*\ + Field Output +\*---------------------------------------------------------------------------*/ //- Write a field of cell values as an indirect list, //- using the cell ids from ensightCells template<class Type> -bool writeCellField +bool writeField ( + ensightFile& os, const Field<Type>& fld, const ensightCells& part, - ensightFile& os, - bool parallel //!< Collective write? + bool parallel //!< Collective write? ); -} // End namespace Detail +//- Write a field of faces values as an indirect list, +//- using the face ids from ensightFaces +template<class Type> +bool writeField +( + ensightFile& os, + const Field<Type>& fld, + const ensightFaces& part, + bool parallel //!< Collective write? +); /*---------------------------------------------------------------------------*\ - Namespace ensightOutput::Serial + Namespace ensightOutput::Detail \*---------------------------------------------------------------------------*/ -//- \brief Output routines that are either designed for serial-only, -//- or for which parallelization is pending. -namespace Serial +//- \brief Implementation details and output backends that would not normally +//- be called directly by a user. + +namespace Detail { -//- Write a field of point (node) values (already compacted?) +//- Return sizes of faces in the list +labelList getFaceSizes(const UList<face>& faces); + +//- Return sizes of faces in the list +labelList getFaceSizes(const UIndirectList<face>& faces); + +//- The number of faces per poly element +labelList getPolysNFaces(const polyMesh& mesh, const labelUList& addr); + +//- The number of points for each face of the poly elements +labelList getPolysNPointsPerFace(const polyMesh& mesh, const labelUList& addr); + + +//- Copy specified field component into a scalarField +// works for various lists types +template<template<typename> class FieldContainer, class Type> +void copyComponent +( + scalarField& res, + const FieldContainer<Type>& input, + const direction cmpt +); + + +//- Write coordinates (component-wise) for the given part +template<template<typename> class FieldContainer> +bool writeCoordinates +( + ensightGeoFile& os, + const label partId, + const word& partName, + const label nPoints, + const FieldContainer<Foam::point>& fld, + bool parallel //!< Collective write? +); + + +//- Write field content (component-wise) for the given ensight element type +template<template<typename> class FieldContainer, class Type> +bool writeFieldComponents +( + ensightFile& os, + const char* key, + const FieldContainer<Type>& fld, + bool parallel //!< Collective write? +); + + +//- Write a sub-field of faces values as an indirect list, +//- using the sub-list sizing information from ensightFaces template<class Type> -bool writePointField +bool writeFaceSubField ( + ensightFile& os, const Field<Type>& fld, const ensightFaces& part, - ensightFile& os + bool parallel //!< Collective write? ); -} // End namespace Serial + +} // End namespace Detail + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/fileFormats/ensight/output/ensightOutputTemplates.C b/src/fileFormats/ensight/output/ensightOutputTemplates.C index 13a9eeaa01a..a0985b2cf13 100644 --- a/src/fileFormats/ensight/output/ensightOutputTemplates.C +++ b/src/fileFormats/ensight/output/ensightOutputTemplates.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -31,73 +31,72 @@ License // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // template<template<typename> class FieldContainer, class Type> -bool Foam::ensightOutput::Detail::writeFieldComponents +void Foam::ensightOutput::Detail::copyComponent ( - const char* key, - const FieldContainer<Type>& fld, - ensightFile& os, - bool parallel + scalarField& res, + const FieldContainer<Type>& input, + const direction cmpt ) { - // Preliminary checks - // ~~~~~~~~~~~~~~~~~~ - - parallel = parallel && Pstream::parRun(); + res.resize(input.size()); - bool hasField = !fld.empty(); + auto iter = res.begin(); - if (parallel) + for (const Type& val : input) { - reduce(hasField, orOp<bool>()); + *iter = component(val, cmpt); + ++iter; } +} + - // Nothing to write - if (!hasField) return false; +template<template<typename> class FieldContainer> +bool Foam::ensightOutput::Detail::writeCoordinates +( + ensightGeoFile& os, + const label partId, + const word& partName, + const label nPoints, + const FieldContainer<Foam::point>& fld, + bool parallel +) +{ + parallel = parallel && Pstream::parRun(); - // End preliminary checks - // ~~~~~~~~~~~~~~~~~~~~~~ + const label nSlaves = (parallel ? Pstream::nProcs() : 0); + // Using manual copyComponent(...) instead of fld.component() to support + // indirect lists etc. + + scalarField send(fld.size()); if (Pstream::master()) { - os.writeKeyword(key); + // Serial output, or parallel (master) - if (!parallel) - { - // Serial output - for (direction d=0; d < pTraits<Type>::nComponents; ++d) - { - const label cmpt = ensightPTraits<Type>::componentOrder[d]; + os.beginPart(partId, partName); + os.beginCoordinates(nPoints); - os.writeList(fld.component(cmpt)); - } - } - else + for (direction cmpt=0; cmpt < point::nComponents; ++cmpt) { - // Parallel (master) + copyComponent(send, fld, cmpt); + os.writeList(send); - for (direction d=0; d < pTraits<Type>::nComponents; ++d) + for (int slave=1; slave < nSlaves; ++slave) { - const label cmpt = ensightPTraits<Type>::componentOrder[d]; - - os.writeList(fld.component(cmpt)); - - for (int slave=1; slave<Pstream::nProcs(); ++slave) - { - IPstream fromSlave(Pstream::commsTypes::scheduled, slave); - scalarField received(fromSlave); - os.writeList(received); - } + IPstream fromSlave(Pstream::commsTypes::scheduled, slave); + scalarField recv(fromSlave); + os.writeList(recv); } } } - else if (parallel) + else if (nSlaves) { // Parallel (slaves) - for (direction d=0; d < pTraits<Type>::nComponents; ++d) + for (direction cmpt=0; cmpt < point::nComponents; ++cmpt) { - const label cmpt = ensightPTraits<Type>::componentOrder[d]; + copyComponent(send, fld, cmpt); OPstream toMaster ( @@ -105,8 +104,7 @@ bool Foam::ensightOutput::Detail::writeFieldComponents Pstream::masterNo() ); - toMaster - << fld.component(cmpt); + toMaster << send; } } @@ -114,52 +112,77 @@ bool Foam::ensightOutput::Detail::writeFieldComponents } -template<class Type> -bool Foam::ensightOutput::Detail::writeFaceField +template<template<typename> class FieldContainer, class Type> +bool Foam::ensightOutput::Detail::writeFieldComponents ( - const Field<Type>& fld, - const ensightFaces& part, ensightFile& os, + const char* key, + const FieldContainer<Type>& fld, bool parallel ) { - // Preliminary checks - // ~~~~~~~~~~~~~~~~~~ - parallel = parallel && Pstream::parRun(); - bool hasGeom = (parallel ? part.total() : part.size()); - bool hasField = !fld.empty(); + const label nSlaves = (parallel ? Pstream::nProcs() : 0); - if (parallel) + // Preliminary checks { - // Used 'pre-reduced' information for hasGeom - reduce(hasField, orOp<bool>()); + bool hasField = !fld.empty(); + + if (parallel) + { + reduce(hasField, orOp<bool>()); + } + + // No field + if (!hasField) return false; } - // Nothing to write - if (!hasGeom || !hasField) return false; - // End preliminary checks - // ~~~~~~~~~~~~~~~~~~~~~~ + // Using manual copyComponent(...) instead of fld.component() to support + // indirect lists etc. + scalarField send(fld.size()); if (Pstream::master()) { - os.beginPart(part.index()); - } + // Serial output, or parallel (master) - for (int typei=0; typei < ensightFaces::nTypes; ++typei) + os.writeKeyword(key); + + for (direction d=0; d < pTraits<Type>::nComponents; ++d) + { + const direction cmpt = ensightPTraits<Type>::componentOrder[d]; + + copyComponent(send, fld, cmpt); + os.writeList(send); + + for (label slave=1; slave < nSlaves; ++slave) + { + IPstream fromSlave(Pstream::commsTypes::scheduled, slave); + scalarField recv(fromSlave); + os.writeList(recv); + } + } + } + else if (nSlaves) { - const ensightFaces::elemType what = ensightFaces::elemType(typei); + // Parallel (slaves) - writeFieldComponents - ( - ensightFaces::key(what), - Field<Type>(fld, part.faceIds(what)), - os, - parallel - ); + for (direction d=0; d < pTraits<Type>::nComponents; ++d) + { + const direction cmpt = ensightPTraits<Type>::componentOrder[d]; + + copyComponent(send, fld, cmpt); + + OPstream toMaster + ( + Pstream::commsTypes::scheduled, + Pstream::masterNo() + ); + + toMaster << send; + } } return true; @@ -169,31 +192,29 @@ bool Foam::ensightOutput::Detail::writeFaceField template<class Type> bool Foam::ensightOutput::Detail::writeFaceSubField ( + ensightFile& os, const Field<Type>& fld, const ensightFaces& part, - ensightFile& os, bool parallel ) { - // Preliminary checks - // ~~~~~~~~~~~~~~~~~~ - parallel = parallel && Pstream::parRun(); - bool hasGeom = (parallel ? part.total() : part.size()); - bool hasField = !fld.empty(); - - if (parallel) + // Preliminary checks: total() contains pre-reduced information { - // Used 'pre-reduced' information for hasGeom - reduce(hasField, orOp<bool>()); - } + // No geometry + if (parallel ? !part.total() : !part.size()) return false; - // Nothing to write - if (!hasGeom || !hasField) return false; + bool hasField = !fld.empty(); - // End preliminary checks - // ~~~~~~~~~~~~~~~~~~~~~~ + if (parallel) + { + reduce(hasField, orOp<bool>()); + } + + // No field + if (!hasField) return false; + } if (Pstream::master()) @@ -201,23 +222,19 @@ bool Foam::ensightOutput::Detail::writeFaceSubField os.beginPart(part.index()); } + labelList localAddr; - label start = 0; // The start of the sub-list for (int typei=0; typei < ensightFaces::nTypes; ++typei) { - const ensightFaces::elemType what = ensightFaces::elemType(typei); - - const label size = part.faceIds(what).size(); + const auto etype = ensightFaces::elemType(typei); - writeFieldComponents + ensightOutput::Detail::writeFieldComponents ( - ensightFaces::key(what), - SubField<Type>(fld, size, start), os, + ensightFaces::key(etype), + SubField<Type>(fld, part.range(etype)), parallel ); - - start += size; // Advance the start for next sub-list } return true; @@ -225,79 +242,80 @@ bool Foam::ensightOutput::Detail::writeFaceSubField template<class Type> -bool Foam::ensightOutput::Serial::writePointField +bool Foam::ensightOutput::writeField ( + ensightFile& os, const Field<Type>& fld, - const ensightFaces& part, - ensightFile& os + const ensightCells& part, + bool parallel ) { - // Preliminary checks - // ~~~~~~~~~~~~~~~~~~ - - bool parallel = false && Pstream::parRun(); - - bool hasGeom = (parallel ? part.total() : part.size()); - bool hasField = !fld.empty(); + parallel = parallel && Pstream::parRun(); - if (parallel) + // Preliminary checks: total() contains pre-reduced information { - // Used 'pre-reduced' information for hasGeom - reduce(hasField, orOp<bool>()); - } + // No geometry + if (parallel ? !part.total() : !part.size()) return false; - // Nothing to write - if (!hasGeom || !hasField) return false; + bool hasField = !fld.empty(); - // End preliminary checks - // ~~~~~~~~~~~~~~~~~~~~~~ + if (parallel) + { + reduce(hasField, orOp<bool>()); + } + // No field + if (!hasField) return false; + } if (Pstream::master()) { os.beginPart(part.index()); } - ensightOutput::Detail::writeFieldComponents - ( - "coordinates", - fld, - os, - parallel - ); + for (int typei=0; typei < ensightCells::nTypes; ++typei) + { + const auto etype = ensightCells::elemType(typei); + + ensightOutput::Detail::writeFieldComponents + ( + os, + ensightCells::key(etype), + UIndirectList<Type>(fld, part.cellIds(etype)), + parallel + ); + } return true; } template<class Type> -bool Foam::ensightOutput::Detail::writeCellField +bool Foam::ensightOutput::writeField ( - const Field<Type>& fld, - const ensightCells& part, ensightFile& os, + const Field<Type>& fld, + const ensightFaces& part, bool parallel ) { - // Preliminary checks - // ~~~~~~~~~~~~~~~~~~ - parallel = parallel && Pstream::parRun(); - bool hasGeom = (parallel ? part.total() : part.size()); - bool hasField = !fld.empty(); - - if (parallel) + // Preliminary checks: total() contains pre-reduced information { - // Used 'pre-reduced' information for hasGeom - reduce(hasField, orOp<bool>()); - } + // No geometry + if (parallel ? !part.total() : !part.size()) return false; - // Nothing to write - if (!hasGeom || !hasField) return false; + bool hasField = !fld.empty(); - // End preliminary checks - // ~~~~~~~~~~~~~~~~~~~~~~ + if (parallel) + { + reduce(hasField, orOp<bool>()); + } + + // No field + if (!hasField) return false; + } if (Pstream::master()) @@ -305,15 +323,15 @@ bool Foam::ensightOutput::Detail::writeCellField os.beginPart(part.index()); } - for (int typei=0; typei < ensightCells::nTypes; ++typei) + for (int typei=0; typei < ensightFaces::nTypes; ++typei) { - const ensightCells::elemType what = ensightCells::elemType(typei); + const auto etype = ensightFaces::elemType(typei); - Detail::writeFieldComponents + ensightOutput::Detail::writeFieldComponents ( - ensightCells::key(what), - Field<Type>(fld, part.cellIds(what)), os, + ensightFaces::key(etype), + UIndirectList<Type>(fld, part.faceIds(etype)), parallel ); } diff --git a/src/fileFormats/ensight/part/ensightCells.C b/src/fileFormats/ensight/part/cells/ensightCells.C similarity index 68% rename from src/fileFormats/ensight/part/ensightCells.C rename to src/fileFormats/ensight/part/cells/ensightCells.C index 728366cee1a..625977a99ae 100644 --- a/src/fileFormats/ensight/part/ensightCells.C +++ b/src/fileFormats/ensight/part/cells/ensightCells.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2019 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -33,31 +33,41 @@ License // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // +namespace Foam +{ + defineTypeNameAndDebug(ensightCells, 0); +} + const char* Foam::ensightCells::elemNames[5] = { "tetra4", "pyramid5", "penta6", "hexa8", "nfaced" }; +static_assert +( + Foam::ensightCells::nTypes == 5, + "Support exactly 5 cell types (tetra4, pyramid5, penta6, hexa8, nfaced)" +); + // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // void Foam::ensightCells::resizeAll() { - // overall required size - label n = 0; - forAll(sizes_, typei) - { - n += sizes_[typei]; - } - address_.setSize(n, Zero); + // Assign sub-list offsets, determine overall size - // assign corresponding sub-lists - n = 0; - forAll(sizes_, typei) + label len = 0; + + auto iter = offsets_.begin(); + + *iter = 0; + for (const label n : sizes_) { - slices_[typei].setStart(n); - slices_[typei].setSize(sizes_[typei]); + len += n; - n += sizes_[typei]; + *(++iter) = len; } + + // The addressing space + addressing().resize(len, Zero); } @@ -65,38 +75,17 @@ void Foam::ensightCells::resizeAll() Foam::ensightCells::ensightCells() : - ensightCells(0) -{} - - -Foam::ensightCells::ensightCells(const label partIndex) -: - index_(partIndex), - address_(), - slices_(), + ensightPart(), + offsets_(Zero), sizes_(Zero) -{ - resizeAll(); // adjust allocation/sizing -} +{} -Foam::ensightCells::ensightCells(const ensightCells& obj) +Foam::ensightCells::ensightCells(const string& description) : - index_(obj.index_), - address_(obj.address_), - slices_(), - sizes_() + ensightCells() { - // Save the total (reduced) sizes - FixedList<label, 5> totSizes = obj.sizes_; - - // Need local sizes for the resize operation - this->sizes_ = obj.sizes(); - - resizeAll(); // Adjust allocation/sizing - - // Restore total (reduced) sizes - this->sizes_ = totSizes; + rename(description); } @@ -105,9 +94,10 @@ Foam::ensightCells::ensightCells(const ensightCells& obj) Foam::FixedList<Foam::label, 5> Foam::ensightCells::sizes() const { FixedList<label, 5> count; - forAll(slices_, typei) + + forAll(count, typei) { - count[typei] = slices_[typei].size(); + count[typei] = size(elemType(typei)); } return count; @@ -127,17 +117,25 @@ Foam::label Foam::ensightCells::total() const void Foam::ensightCells::clear() { - sizes_ = Zero; // reset sizes - resizeAll(); + clearOut(); + + ensightPart::clear(); + + sizes_ = Zero; + offsets_ = Zero; } +void Foam::ensightCells::clearOut() +{} + + void Foam::ensightCells::reduce() { // No listCombineGather, listCombineScatter for FixedList forAll(sizes_, typei) { - sizes_[typei] = slices_[typei].size(); + sizes_[typei] = size(elemType(typei)); Foam::reduce(sizes_[typei], sumOp<label>()); } } @@ -145,12 +143,15 @@ void Foam::ensightCells::reduce() void Foam::ensightCells::sort() { - forAll(slices_, typei) + for (int typei=0; typei < nTypes; ++typei) { - if (slices_[typei].size()) + const labelRange sub(range(elemType(typei))); + + if (!sub.empty()) { - SubList<label> idLst(address_, slices_[typei]); - Foam::sort(idLst); + SubList<label> ids(addressing(), sub); + + Foam::sort(ids); } } } @@ -178,59 +179,56 @@ void Foam::ensightCells::classifyImpl { const cellModel& model = shapes[id].model(); - enum elemType what = NFACED; + elemType etype(NFACED); if (model == tet) { - what = TETRA4; + etype = TETRA4; } else if (model == pyr) { - what = PYRAMID5; + etype = PYRAMID5; } else if (model == prism) { - what = PENTA6; + etype = PENTA6; } else if (model == hex) { - what = HEXA8; + etype = HEXA8; } - sizes_[what]++; + ++sizes_[etype]; } resizeAll(); // adjust allocation sizes_ = Zero; // reset sizes - use for local indexing here + // Pass 2: Assign cell-id per shape type for (const label id : cellIds) { const cellModel& model = shapes[id].model(); - enum elemType what = NFACED; + elemType etype(NFACED); if (model == tet) { - what = TETRA4; + etype = TETRA4; } else if (model == pyr) { - what = PYRAMID5; + etype = PYRAMID5; } else if (model == prism) { - what = PENTA6; + etype = PENTA6; } else if (model == hex) { - what = HEXA8; + etype = HEXA8; } - // eg, the processor local cellId - labelUList slice = address_[slices_[what]]; - - slice[sizes_[what]] = id; - sizes_[what]++; + add(etype, id); } } @@ -262,4 +260,28 @@ void Foam::ensightCells::classify } +void Foam::ensightCells::writeDict(Ostream& os, const bool full) const +{ + os.beginBlock(type()); + + os.writeEntry("id", index()+1); // Ensight starts with 1 + os.writeEntry("name", name()); + os.writeEntry("size", size()); + + if (full) + { + for (int typei=0; typei < ensightCells::nTypes; ++typei) + { + const auto etype = ensightCells::elemType(typei); + + os.writeKeyword(ensightCells::key(etype)); + + cellIds(etype).writeList(os, 0) << endEntry; // Flat output + } + } + + os.endBlock(); +} + + // ************************************************************************* // diff --git a/src/fileFormats/ensight/part/cells/ensightCells.H b/src/fileFormats/ensight/part/cells/ensightCells.H new file mode 100644 index 00000000000..d16dcc7a86c --- /dev/null +++ b/src/fileFormats/ensight/part/cells/ensightCells.H @@ -0,0 +1,279 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016-2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::ensightCells + +Description + Sorting/classification of cells (3D) into corresponding ensight element + types. + +\*---------------------------------------------------------------------------*/ + +#ifndef ensightCells_H +#define ensightCells_H + +#include "ensightPart.H" +#include "FixedList.H" +#include "Map.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class bitSet; +class polyMesh; + +/*---------------------------------------------------------------------------*\ + Class ensightCells Declaration +\*---------------------------------------------------------------------------*/ + +class ensightCells +: + public ensightPart +{ +public: + + // Public Data + + //- Supported ensight 'Cell' element types + // Must be zero-based since they are also for internal bookkeeping. + enum elemType + { + TETRA4 = 0, //!< "tetra4" + PYRAMID5, //!< "pyramid5" + PENTA6, //!< "penta6" + HEXA8, //!< "hexa8" + NFACED //!< "nfaced" + }; + + //- Number of 'Cell' element types (5) + static constexpr int nTypes = 5; + + //- The ensight 'Cell' element type names + static const char* elemNames[nTypes]; + + + // Static Functions + + //- The ensight element name for the specified 'Cell' type + inline static const char* key(const elemType etype); + + +private: + + // Private Data + + //- Begin/end offsets for address of each element type + FixedList<label, nTypes+1> offsets_; + + //- List of global sizes for each element type. + // Used temporarily for local sizes when building the element lists. + FixedList<label, nTypes> sizes_; + + + // Private Member Functions + + //- Low-level internal addition routine + inline void add(const elemType etype, label id); + + //- Use temporarily stored sizes to redimension the element lists + void resizeAll(); + + //- Classify cell types, set element lists for selection (implemention) + template<class Addressing> + void classifyImpl(const polyMesh& mesh, const Addressing& cellIds); + + + label meshPointMapppings + ( + const polyMesh& mesh, + labelList& pointToGlobal, // Can also be labelList::null() + labelList& uniqueMeshPointLabels, + bool parallel + ) const; + + + //- Write cell connectivity for polyhedral cells + static void writePolysConnectivity + ( + ensightGeoFile& os, + const polyMesh& mesh, + const ensightCells& part, + const labelList& pointToGlobal, + bool parallel + ); + + //- Write cell connectivity for specified (non-poly) type + static void writeShapeConnectivity + ( + ensightGeoFile& os, + const polyMesh& mesh, + const ensightCells::elemType etype, + const ensightCells& part, + const labelList& pointToGlobal, + bool parallel + ); + + +public: + + //- Declare type-name, virtual type (with debug switch) + TypeName("ensightCells"); + + + // Constructors + + //- Default construct, with part index 0 + ensightCells(); + + //- Default construct, with description/partName + explicit ensightCells(const string& description); + + + //- Destructor + virtual ~ensightCells() = default; + + + + // Member Functions + + // Access + + //- Processor-local size of all elements. + using ensightPart::size; + + //- Processor-local size of the specified element type. + inline label size(const elemType etype) const; + + //- Processor-local offset/size of element type. + inline labelRange range(const elemType etype) const; + + //- The global size of all element types. + // This value is only meaningful after a reduce operation. + label total() const; + + //- The global size of the specified element type. + // This value is only meaningful after a reduce operation. + inline label total(const elemType etype) const; + + //- The global sizes for each element type. + // This value is only meaningful after a reduce operation. + inline const FixedList<label, nTypes>& totals() const; + + //- Processor-local sizes per element type. + FixedList<label, nTypes> sizes() const; + + //- Processor-local cell ids of all elements + inline const labelList& cellIds() const; + + //- Processor-local cell ids of the specified element type + inline const labelUList cellIds(const elemType etype) const; + + + // Addressing + + //- Mesh point map. + // Map mesh point index to local (compact) point index + Map<label> meshPointMap(const polyMesh& mesh) const; + + + // Edit + + //- Classify cell types and set the element lists. + void classify(const polyMesh& mesh); + + //- Classify cell types and set element lists, + //- using a subgroup of cells (eg, from a cellZone etc). + void classify(const polyMesh& mesh, const labelUList& cellIds); + + //- Classify cell types and set element lists, + //- using a subgroup of cells + void classify(const polyMesh& mesh, const bitSet& selection); + + + //- Clear any demand-driven data + void clearOut(); + + //- Set addressable sizes to zero, free up addressing memory. + void clear(); + + //- Sum element counts across all processes. + void reduce(); + + //- Sort element lists numerically. + void sort(); + + + // Advanced (use with caution) + + //- Increase cell ids by specified offset value + // Eg, to change zone local Ids to global Ids + inline void incrCellIds(const label off); + + //- Decrease face ids by specified offset value + // Eg, to change global Ids to zone local Ids + inline void decrCellIds(const label off); + + + + // Output + + //- Globally unique mesh points. Required when writing point fields. + label uniqueMeshPoints + ( + const polyMesh& mesh, + labelList& uniqueMeshPointLabels, + bool parallel + ) const; + + + //- Write information about the object as a dictionary, + //- optionally write all element addresses + virtual void writeDict(Ostream& os, const bool full=false) const; + + //- Write geometry, using a mesh reference (serial only) + virtual void write + ( + ensightGeoFile& os, + const polyMesh& mesh, + bool parallel + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "ensightCellsI.H" + +#endif + +// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/cells/ensightCellsAddr.C b/src/fileFormats/ensight/part/cells/ensightCellsAddr.C new file mode 100644 index 00000000000..09c9f62af90 --- /dev/null +++ b/src/fileFormats/ensight/part/cells/ensightCellsAddr.C @@ -0,0 +1,238 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "ensightCells.H" +#include "polyMesh.H" +#include "globalIndex.H" +#include "globalMeshData.H" +#include "ListOps.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::Map<Foam::label> +Foam::ensightCells::meshPointMap(const polyMesh& mesh) const +{ + const label nEstimate = 8*this->size(); + + Map<label> pointMap(nEstimate); + + // Pass 1: markup used points from cells + + for (const label celli : this->cellIds()) + { + for (const label facei : mesh.cells()[celli]) + { + for (const label pointi : mesh.faces()[facei]) + { + pointMap.insert(pointi, 0); + } + } + } + + // Compact point numbering, preserves the original order + label nPoints = 0; + for (const label pointi : pointMap.sortedToc()) + { + pointMap(pointi) = nPoints++; + } + + return pointMap; +} + + +Foam::label Foam::ensightCells::meshPointMapppings +( + const polyMesh& mesh, + labelList& pointToGlobalRequest, + labelList& uniqueMeshPointLabels, + bool parallel +) const +{ + labelList pointToGlobal; + + const bool rewritePointMap = notNull(pointToGlobalRequest); + + if (notNull(pointToGlobalRequest)) + { + pointToGlobal.transfer(pointToGlobalRequest); + } + + + const ensightCells& part = *this; + + parallel = parallel && Pstream::parRun(); + + // Renumber the points/faces into unique points + label nPoints = 0; // Total number of points + + bool allCells = (part.size() == mesh.nCells()); + + if (parallel) + { + Foam::reduce(allCells, andOp<bool>()); + + if (allCells) + { + // All cells used, and thus all points + + autoPtr<globalIndex> globalPointsPtr = + mesh.globalData().mergePoints + ( + pointToGlobal, + uniqueMeshPointLabels + ); + + nPoints = globalPointsPtr().size(); // nPoints (global) + } + else + { + // Map mesh point index to local (compact) point index + + Map<label> meshPointMap(part.meshPointMap(mesh)); + + labelList meshPoints(meshPointMap.sortedToc()); + + autoPtr<globalIndex> globalPointsPtr = + mesh.globalData().mergePoints + ( + meshPoints, + meshPointMap, + pointToGlobal, + uniqueMeshPointLabels + ); + + nPoints = globalPointsPtr().size(); // nPoints (global) + + meshPointMap.clear(); + + // The mergePoints returns pointToGlobal under the + // assumption of local addressing + // (eg, patch localFaces). + // Recast as original mesh points to new global points + + if (rewritePointMap) + { + labelList oldToNew(mesh.nPoints(), -1); + + forAll(meshPoints, i) + { + const label orig = meshPoints[i]; + const label glob = pointToGlobal[i]; + + oldToNew[orig] = glob; + } + + pointToGlobal.transfer(oldToNew); + } + } + } + else + { + // Non-parallel + + nPoints = mesh.nPoints(); + pointToGlobal.resize(nPoints); + + if (allCells) + { + // All cells used, and thus all points + + uniqueMeshPointLabels.resize(nPoints); + + ListOps::identity(pointToGlobal); + ListOps::identity(uniqueMeshPointLabels); + } + else + { + // Mark up with -1 for unused entries + pointToGlobal = -1; + + nPoints = 0; + + // Pass 1: markup used points from cells + + for (const label celli : this->cellIds()) + { + for (const label facei : mesh.cells()[celli]) + { + for (const label pointi : mesh.faces()[facei]) + { + if (pointToGlobal[pointi] == -1) + { + pointToGlobal[pointi] = nPoints++; + } + } + } + } + + // Pass 2: + // + // Compact point numbering, preserving original point order + uniqueMeshPointLabels.resize(nPoints); + + nPoints = 0; + forAll(pointToGlobal, pointi) + { + if (pointToGlobal[pointi] != -1) + { + pointToGlobal[pointi] = nPoints; + + uniqueMeshPointLabels[nPoints] = pointi; + + ++nPoints; + } + } + } + } + + if (notNull(pointToGlobalRequest)) + { + pointToGlobalRequest.transfer(pointToGlobal); + } + + return nPoints; +} + + +Foam::label Foam::ensightCells::uniqueMeshPoints +( + const polyMesh& mesh, + labelList& uniqueMeshPointLabels, + bool parallel +) const +{ + return meshPointMapppings + ( + mesh, + const_cast<labelList&>(labelList::null()), // Ignore pointToGlobal + uniqueMeshPointLabels, + parallel + ); +} + + +// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/ensightCellsI.H b/src/fileFormats/ensight/part/cells/ensightCellsI.H similarity index 54% rename from src/fileFormats/ensight/part/ensightCellsI.H rename to src/fileFormats/ensight/part/cells/ensightCellsI.H index dcac7ab0030..cfccab8eed4 100644 --- a/src/fileFormats/ensight/part/ensightCellsI.H +++ b/src/fileFormats/ensight/part/cells/ensightCellsI.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -25,76 +25,71 @@ License \*---------------------------------------------------------------------------*/ -#include "error.H" +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -inline const char* Foam::ensightCells::key(const enum elemType what) +inline void Foam::ensightCells::add(const elemType etype, label id) { - return elemNames[what]; -} - + // Linear addressing location + const label index = offsets_[etype] + sizes_[etype]++; -inline Foam::label Foam::ensightCells::index() const -{ - return index_; + addressing()[index] = id; } -inline Foam::label& Foam::ensightCells::index() +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline const char* Foam::ensightCells::key(const elemType etype) { - return index_; + return elemNames[etype]; } -inline Foam::label Foam::ensightCells::size() const +inline const Foam::FixedList<Foam::label,5>& Foam::ensightCells::totals() const { - return address_.size(); + return sizes_; } -inline const Foam::FixedList<Foam::label,5>& Foam::ensightCells::totals() const +inline Foam::label Foam::ensightCells::total(const elemType etype) const { - return sizes_; + return sizes_[etype]; } -inline Foam::label Foam::ensightCells::total(const enum elemType what) const +inline Foam::label Foam::ensightCells::size(const elemType etype) const { - return sizes_[what]; + return (offsets_[etype+1] - offsets_[etype]); } -inline Foam::label Foam::ensightCells::size(const enum elemType what) const +inline Foam::labelRange Foam::ensightCells::range(const elemType etype) const { - return slices_[what].size(); + return labelRange(offsets_[etype], offsets_[etype+1] - offsets_[etype]); } -inline Foam::label Foam::ensightCells::offset(const enum elemType what) const +inline const Foam::labelList& Foam::ensightCells::cellIds() const { - return slices_[what].start(); + return addressing(); } -inline const Foam::labelUList Foam::ensightCells::cellIds -( - const enum elemType what -) const +inline const Foam::labelUList +Foam::ensightCells::cellIds(const elemType etype) const { - return address_[slices_[what]]; + return addressing()[range(etype)]; } -inline const Foam::labelUList& Foam::ensightCells::cellIds() const +inline void Foam::ensightCells::incrCellIds(const label off) { - return address_; + incrAddressing(off); } -inline Foam::label Foam::ensightCells::operator[](const label i) const +inline void Foam::ensightCells::decrCellIds(const label off) { - return address_[i]; + decrAddressing(off); } diff --git a/src/fileFormats/ensight/part/cells/ensightCellsIO.C b/src/fileFormats/ensight/part/cells/ensightCellsIO.C new file mode 100644 index 00000000000..217543b2a19 --- /dev/null +++ b/src/fileFormats/ensight/part/cells/ensightCellsIO.C @@ -0,0 +1,322 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "ensightCells.H" +#include "ensightOutput.H" +#include "polyMesh.H" +#include "globalIndex.H" +#include "globalMeshData.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::ensightCells::writePolysConnectivity +( + ensightGeoFile& os, + const polyMesh& mesh, + const ensightCells& part, + const labelList& pointToGlobal, + const bool parallel +) +{ + constexpr ensightCells::elemType etype(ensightCells::NFACED); + + // Slaves + const label nSlaves = (parallel ? Pstream::nProcs() : 0); + + + const label nTotal = part.total(etype); + const labelUList& addr = part.cellIds(etype); + + if (!nTotal) + { + return; + } + + if (Pstream::master()) + { + os.writeKeyword(ensightCells::key(etype)); + os.write(nTotal); + os.newline(); + } + + // Number of faces per polyhedral (1/line in ASCII) + { + labelList send + ( + ensightOutput::Detail::getPolysNFaces(mesh, addr) + ); + + if (Pstream::master()) + { + // Master + os.writeLabels(send); + + // Slaves + for (int slave=1; slave < nSlaves; ++slave) + { + IPstream fromSlave(Pstream::commsTypes::scheduled, slave); + + labelList recv(fromSlave); + os.writeLabels(recv); + } + } + else if (nSlaves) + { + OPstream toMaster + ( + Pstream::commsTypes::scheduled, + Pstream::masterNo() + ); + + toMaster << send; + } + } + + + // Number of points for each polyhedral face (1/line in ASCII) + { + labelList send + ( + ensightOutput::Detail::getPolysNPointsPerFace(mesh, addr) + ); + + if (Pstream::master()) + { + // Master + os.writeLabels(send); + + // Slaves + for (int slave=1; slave < nSlaves; ++slave) + { + IPstream fromSlave(Pstream::commsTypes::scheduled, slave); + + labelList recv(fromSlave); + os.writeLabels(recv); + } + } + else if (nSlaves) + { + OPstream toMaster + ( + Pstream::commsTypes::scheduled, + Pstream::masterNo() + ); + + toMaster << send; + } + } + + + // List of points id for each face of the above list + if (Pstream::master()) + { + // Master + ensightOutput::writePolysPoints + ( + os, + mesh, + addr, + pointToGlobal + ); + + // Slaves + for (int slave=1; slave < nSlaves; ++slave) + { + IPstream fromSlave(Pstream::commsTypes::scheduled, slave); + + cellList cells(fromSlave); + labelList addr(fromSlave); + faceList faces(fromSlave); + labelList owner(fromSlave); + + ensightOutput::writePolysPoints + ( + os, + cells, + addr, + faces, + owner + ); + } + } + else if (nSlaves) + { + // Renumber faces to use global point numbers + faceList faces(mesh.faces()); + ListListOps::inplaceRenumber(pointToGlobal, faces); + + OPstream toMaster + ( + Pstream::commsTypes::scheduled, + Pstream::masterNo() + ); + + toMaster + << mesh.cells() + << addr + << faces + << mesh.faceOwner(); + } +} + + +void Foam::ensightCells::writeShapeConnectivity +( + ensightGeoFile& os, + const polyMesh& mesh, + const ensightCells::elemType etype, + const ensightCells& part, + const labelList& pointToGlobal, + const bool parallel +) +{ + if (etype == ensightCells::NFACED) + { + FatalErrorInFunction + << "Called for ensight NFACED cell. Programming error\n" + << exit(FatalError); + } + + // Slaves + const label nSlaves = (parallel ? Pstream::nProcs() : 0); + + + const label nTotal = part.total(etype); + const labelUList& addr = part.cellIds(etype); + + if (!nTotal) + { + return; + } + + + if (Pstream::master()) + { + os.writeKeyword(ensightCells::key(etype)); + os.write(nTotal); + os.newline(); + } + + + // Primitive shape - get subset and renumber + cellShapeList shapes(mesh.cellShapes(), addr); + + ListListOps::inplaceRenumber(pointToGlobal, shapes); + + if (Pstream::master()) + { + ensightOutput::writeCellShapes(os, shapes); + + for (int slave=1; slave < nSlaves; ++slave) + { + IPstream fromSlave(Pstream::commsTypes::scheduled, slave); + cellShapeList recv(fromSlave); + + ensightOutput::writeCellShapes(os, recv); + } + } + else if (nSlaves) + { + OPstream toMaster + ( + Pstream::commsTypes::scheduled, + Pstream::masterNo() + ); + + toMaster << shapes; + } +} + + +void Foam::ensightCells::write +( + ensightGeoFile& os, + const polyMesh& mesh, + bool parallel +) const +{ + const ensightCells& part = *this; + + parallel = parallel && Pstream::parRun(); + + // Renumber the points/faces into unique points + + label nPoints = 0; // Total number of points + labelList pointToGlobal; // local point to unique global index + labelList uniqueMeshPointLabels; // unique global points + + nPoints = meshPointMapppings + ( + mesh, + pointToGlobal, + uniqueMeshPointLabels, + parallel + ); + + ensightOutput::Detail::writeCoordinates + ( + os, + part.index(), + part.name(), + nPoints, // nPoints (global) + UIndirectList<point>(mesh.points(), uniqueMeshPointLabels), + parallel //!< Collective write? + ); + + + for (label typei=0; typei < ensightCells::nTypes; ++typei) + { + const auto etype = ensightCells::elemType(typei); + + if (etype == ensightCells::NFACED) + { + writePolysConnectivity + ( + os, + mesh, + part, + pointToGlobal, + parallel + ); + } + else + { + writeShapeConnectivity + ( + os, + mesh, + etype, + part, + pointToGlobal, + parallel + ); + } + } +} + + +// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/ensightCells.H b/src/fileFormats/ensight/part/ensightCells.H deleted file mode 100644 index f2e3f3b9d3d..00000000000 --- a/src/fileFormats/ensight/part/ensightCells.H +++ /dev/null @@ -1,215 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2016-2019 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -Class - Foam::ensightCells - -Description - Sorting/classification of cells (3D) into corresponding ensight element - types. - -\*---------------------------------------------------------------------------*/ - -#ifndef ensightCells_H -#define ensightCells_H - -#include "labelList.H" -#include "FixedList.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -// Forward declarations -class bitSet; -class polyMesh; - -/*---------------------------------------------------------------------------*\ - Class ensightCells Declaration -\*---------------------------------------------------------------------------*/ - -class ensightCells -{ -public: - - // Public data - - //- Addressable ensight element types - enum elemType - { - TETRA4, //!< "tetra4" - PYRAMID5, //!< "pyramid5" - PENTA6, //!< "penta6" - HEXA8, //!< "hexa8" - NFACED //!< "nfaced" - }; - - //- Number of element types (5) - static constexpr int nTypes = 5; - - //- The ensight element type names - static const char* elemNames[5]; - - - // Static Member Functions - - //- Return the ensight element name for the specified type - inline static const char* key(const enum elemType); - - -private: - - // Private Data - - //- Location within a list. - // The ensight part number is typically this value +1. - label index_; - - //- Linear list of ids, sub-sectioned per element type by sub-lists - labelList address_; - - //- Slices (sub-lists) of the address ids for each element type. - FixedList<labelRange, 5> slices_; - - //- List of global sizes for each element type. - // Used temporarily for local sizes when building the element lists. - FixedList<label, 5> sizes_; - - - // Private Member Functions - - //- Use temporarily stored sizes to redimension the element lists - void resizeAll(); - - //- Classify cell types, set element lists for selection (implemention) - template<class Addressing> - void classifyImpl(const polyMesh& mesh, const Addressing& cellIds); - - //- No copy assignment - void operator=(const ensightCells&) = delete; - - -public: - - // Constructors - - //- Construct null, with part index 0 - ensightCells(); - - //- Construct null, with specified part index - explicit ensightCells(const label partIndex); - - //- Copy constructor. Needed for lists etc. - ensightCells(const ensightCells& obj); - - - //- Destructor - ~ensightCells() = default; - - - // Member Functions - - // Access - - //- The index in a list. - inline label index() const; - - //- The index in a list, non-const access. - inline label& index(); - - //- The processor local size of all elements. - inline label size() const; - - //- The processor local size of the specified element type. - inline label size(const enum elemType) const; - - //- The global number of the specified element type. - // This value is only meaningful after a reduce operation. - inline label total(const enum elemType) const; - - //- The global number of all element types. - // This value is only meaningful after a reduce operation. - label total() const; - - //- The global numbers per element type. - // This value is only meaningful after a reduce operation. - inline const FixedList<label, 5>& totals() const; - - //- The processor local sizes per element type. - FixedList<label, 5> sizes() const; - - //- Processor local starting offset of element type. - inline label offset(const enum elemType what) const; - - //- Return the (local) cell ids of the specified element type - inline const labelUList cellIds(const enum elemType) const; - - //- Return the cell ids of all elements - inline const labelUList& cellIds() const; - - - // Edit - - //- Classify cell types and set the element lists. - void classify(const polyMesh& mesh); - - //- Classify cell types and set element lists, - //- using a subgroup of cells (eg, from a cellZone etc). - void classify(const polyMesh& mesh, const labelUList& cellIds); - - //- Classify cell types and set element lists, - //- using a subgroup of cells - void classify(const polyMesh& mesh, const bitSet& selection); - - //- Set addressable sizes to zero, free up addressing memory. - void clear(); - - //- Sum element counts across all processes. - void reduce(); - - //- Sort element lists numerically. - void sort(); - - - // Member Operators - - //- Return id from linear list of addressing. - inline label operator[](const label i) const; - -}; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#include "ensightCellsI.H" - -#endif - -// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/ensightFaces.H b/src/fileFormats/ensight/part/ensightFaces.H deleted file mode 100644 index 307237279a8..00000000000 --- a/src/fileFormats/ensight/part/ensightFaces.H +++ /dev/null @@ -1,222 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2016-2018 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -Class - Foam::ensightFaces - -Description - Sorting/classification of faces (2D) into corresponding ensight types - -\*---------------------------------------------------------------------------*/ - -#ifndef ensightFaces_H -#define ensightFaces_H - -#include "boolList.H" -#include "labelList.H" -#include "faceList.H" -#include "FixedList.H" -#include "bitSet.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -/*---------------------------------------------------------------------------*\ - Class ensightFaces Declaration -\*---------------------------------------------------------------------------*/ - -class ensightFaces -{ -public: - - // Public Data - - //- Addressable ensight element types - enum elemType - { - TRIA3, //!< "tria3" - QUAD4, //!< "quad4" - NSIDED //!< "nsided" - }; - - //- Number of element types (3) - static constexpr int nTypes = 3; - - //- The ensight element type names - static const char* elemNames[3]; - - - // Static Member Functions - - //- Return the ensight element name for the specified type - static inline const char* key(const enum elemType); - - -private: - - // Private data - - //- Location within a list. - // The ensight part number is typically this value +1. - label index_; - - //- Linear list of ids, sub-sectioned per element type by sub-lists - labelList address_; - - //- Linear list of face-flips - boolList flipMap_; - - //- Slices (sub-lists) of the address and flips for each element type. - FixedList<labelRange, 3> slices_; - - //- List of global sizes for each element type. - // Used temporarily for local sizes when building the element lists. - FixedList<label, 3> sizes_; - - - // Private Member Functions - - //- Low-level internal addition routine - inline void add(const face& f, const label id, const bool flip = false); - - //- Use temporarily stored sizes to redimension the element lists - void resizeAll(); - - //- No copy assignment - void operator=(const ensightFaces&) = delete; - - -public: - - // Constructors - - //- Construct null, with part index 0 - ensightFaces(); - - //- Construct null, with specified part index - explicit ensightFaces(const label partIndex); - - //- Copy constructor. Needed for lists etc. - ensightFaces(const ensightFaces& obj); - - - //- Destructor - ~ensightFaces() = default; - - - // Member Functions - - // Access - - //- The index in a list. - inline label index() const; - - //- The index in a list, non-const access. - inline label& index(); - - //- The processor local size of all elements. - inline label size() const; - - //- The processor local size of the specified element type. - inline label size(const enum elemType) const; - - //- The global number of all element types. - // This value is only meaningful after a reduce operation. - label total() const; - - //- The global number of the specified element type. - // This value is only meaningful after a reduce operation. - inline label total(const enum elemType) const; - - //- The global numbers per element type. - // This value is only meaningful after a reduce operation. - inline const FixedList<label, 3>& totals() const; - - //- The processor local sizes per element type. - FixedList<label, 3> sizes() const; - - //- Processor local starting offset of element type. - inline label offset(const enum elemType what) const; - - //- Return the (local) face ids of the specified element type - inline const labelUList faceIds(const enum elemType) const; - - //- Return the processor local face ids of all elements - inline const labelUList& faceIds() const; - - //- Return the processor local flip-map of all elements - inline const boolList& flipMap() const; - - - // Edit - - //- Classify the face types, set element list. - void classify(const faceList& faces); - - - //- Classify the face types, set element list. - // The indirect addressing can be used when classifying groups of - // face (eg, from a faceZone etc) with an optional flipMap. - // The optional exclude marker can be used to skip faces on particular - // boundary types or regions. - void classify - ( - const faceList& faces, - const labelUList& addressing, - const boolList& flipMap = boolList(), - const bitSet& exclude = bitSet() - ); - - - //- Set addressable sizes to zero, free up addressing memory. - void clear(); - - //- Sum element counts across all processes. - void reduce(); - - //- Sort element lists numerically. - void sort(); - - - // Member Operators - - //- Return element from linear-list. - inline label operator[](const label i) const; -}; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#include "ensightFacesI.H" - -#endif - -// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/ensightPart.H b/src/fileFormats/ensight/part/ensightPart.H deleted file mode 100644 index 2b9d3f9d3b9..00000000000 --- a/src/fileFormats/ensight/part/ensightPart.H +++ /dev/null @@ -1,183 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2019 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -Class - Foam::ensightPart - -Description - Base class for ensightPartCells and ensightPartFaces - -SourceFiles - ensightPart.C - -\*---------------------------------------------------------------------------*/ - -#ifndef ensightPart_H -#define ensightPart_H - -#include "ensightGeoFile.H" -#include "typeInfo.H" -#include "labelList.H" -#include "polyMesh.H" -#include "Field.H" -#include "IOstream.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -/*---------------------------------------------------------------------------*\ - Class ensightPart Declaration -\*---------------------------------------------------------------------------*/ - -class ensightPart -{ - // Private Data - - //- Part name (or description) - string name_; - - - // Private Member Functions - - //- No copy construct - ensightPart(const ensightPart&) = delete; - - //- No copy assignment - void operator=(const ensightPart&) = delete; - - -protected: - - // Protected Classes - - //- Track the points used by the part and map global to local indices - struct localPoints - { - //- Number of points used - label nPoints; - - //- Map global to local indices - labelList list; - - //- Null constructor - localPoints() - : - nPoints(0), - list() - {} - - //- Construct for mesh points - localPoints(const pointField& pts) - : - nPoints(0), - list(pts.size(), -1) - {} - }; - -public: - - //- Runtime type information - TypeName("ensightPart"); - - - // Constructors - - //- Construct with description - explicit ensightPart(const string& description); - - - //- Destructor - virtual ~ensightPart() = default; - - - // Access - - //- Part index (0-based) - virtual label index() const = 0; - - //- Number of elements in this part - virtual label size() const - { - return 0; - } - - //- Return the part name or description - const string& name() const - { - return name_; - } - - //- Change the part name or description - void rename(string value) - { - name_ = std::move(value); - } - - - // Output - - //- Write summary information about the object - virtual void writeSummary(Ostream& os) const = 0; - - //- Print various types of debugging information - virtual void dumpInfo(Ostream& os) const = 0; - - //- Write geometry - virtual void write(ensightGeoFile& os) const = 0; - - //- Helper: write geometry with given pointField - virtual void write(ensightGeoFile& os, const pointField&) const = 0; - - - // Housekeeping - - //- Deprecated(2019-12) - use rename() method - // \deprecated(2019-12) - use rename() method - void FOAM_DEPRECATED_FOR(2019-12, "rename() method") - name(string value) - { - name_ = std::move(value); - } -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - - -//- IOstream Operator to write geometry -ensightGeoFile& operator<<(ensightGeoFile& os, const ensightPart& part); - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#endif - -// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/ensightPartCells.C b/src/fileFormats/ensight/part/ensightPartCells.C deleted file mode 100644 index 8a206be91f3..00000000000 --- a/src/fileFormats/ensight/part/ensightPartCells.C +++ /dev/null @@ -1,344 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2019 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -\*---------------------------------------------------------------------------*/ - -#include "ensightPartCells.H" - -// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // - -namespace Foam -{ - defineTypeNameAndDebug(ensightPartCells, 0); -} - - -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // - -Foam::ensightPart::localPoints Foam::ensightPartCells::calcLocalPoints() const -{ - localPoints ptList(mesh_.points()); - labelList& usedPoints = ptList.list; - label nPoints = 0; - - // Add all points from cells - const labelUList& idList = this->cellIds(); - - for (const label id : idList) - { - const labelUList& cFaces = mesh_.cells()[id]; - - forAll(cFaces, cFacei) - { - const face& f = mesh_.faces()[cFaces[cFacei]]; - - forAll(f, fp) - { - if (usedPoints[f[fp]] == -1) - { - usedPoints[f[fp]] = nPoints++; - } - } - } - } - - // this is not absolutely necessary, but renumber anyhow - nPoints = 0; - forAll(usedPoints, ptI) - { - if (usedPoints[ptI] > -1) - { - usedPoints[ptI] = nPoints++; - } - } - - ptList.nPoints = nPoints; - return ptList; -} - - -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - -Foam::ensightPartCells::ensightPartCells -( - label partIndex, - const polyMesh& mesh, - const string& partName -) -: - ensightCells(partIndex), - ensightPart(partName), - mesh_(mesh) -{ - classify(mesh); -} - - -Foam::ensightPartCells::ensightPartCells -( - label partIndex, - const polyMesh& mesh, - const labelUList& cellIds, - const string& partName -) -: - ensightCells(partIndex), - ensightPart(partName), - mesh_(mesh) -{ - classify(mesh, cellIds); -} - - -Foam::ensightPartCells::ensightPartCells -( - label partIndex, - const polyMesh& mesh, - const bitSet& selection, - const string& partName -) -: - ensightCells(partIndex), - ensightPart(partName), - mesh_(mesh) -{ - classify(mesh, selection); -} - - -Foam::ensightPartCells::ensightPartCells -( - label partIndex, - const polyMesh& mesh, - const cellZone& zn, - const string& partName -) -: - ensightPartCells - ( - partIndex, - mesh, - static_cast<const labelList&>(zn), - zn.name() - ) -{ - if (!partName.empty()) - { - rename(partName); - } -} - - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -void Foam::ensightPartCells::writeConnectivity -( - ensightGeoFile& os, - const word& key, - const labelUList& idList, - const labelUList& pointMap -) const -{ - if (idList.empty()) return; - - os.writeKeyword(key); - os.write(idList.size()); - os.newline(); - - // write polyhedral - if (key == "nfaced") - { - const faceList& meshFaces = mesh_.faces(); - const labelUList& owner = mesh_.faceOwner(); - - // write the number of faces per element - forAll(idList, i) - { - const label id = idList[i]; - const labelUList& cFace = mesh_.cells()[id]; - - os.write(cFace.size()); - os.newline(); - } - - // write the number of points per element face - forAll(idList, i) - { - const label id = idList[i]; - const labelUList& cFace = mesh_.cells()[id]; - - forAll(cFace, facei) - { - const face& cf = meshFaces[cFace[facei]]; - - os.write(cf.size()); - os.newline(); - } - } - - // write the points describing each element face - forAll(idList, i) - { - const label id = idList[i]; - const labelUList& cFace = mesh_.cells()[id]; - - forAll(cFace, cFacei) - { - const label faceId = cFace[cFacei]; - const face& cf = meshFaces[faceId]; - - // convert global -> local index - // (note: Ensight indices start with 1) - - // ensight >= 9 needs consistently oriented nfaced cells - if (id == owner[faceId]) - { - forAll(cf, ptI) - { - os.write(pointMap[cf[ptI]] + 1); - } - } - else - { - // as per face::reverseFace(), but without copying - - os.write(pointMap[cf[0]] + 1); - for (label ptI = cf.size()-1; ptI > 0; --ptI) - { - os.write(pointMap[cf[ptI]] + 1); - } - } - - os.newline(); - } - } - } - else - { - // write primitive - const cellShapeList& shapes = mesh_.cellShapes(); - - forAll(idList, i) - { - const label id = idList[i]; - const cellShape& cellPoints = shapes[id]; - - // convert global -> local index - // (note: Ensight indices start with 1) - forAll(cellPoints, ptI) - { - os.write(pointMap[cellPoints[ptI]] + 1); - } - os.newline(); - } - } -} - - -void Foam::ensightPartCells::write -( - ensightGeoFile& os, - const pointField& points -) const -{ - if (size()) - { - const localPoints ptList = calcLocalPoints(); - const labelUList& pointMap = ptList.list; - - os.beginPart(index(), name()); - os.beginCoordinates(ptList.nPoints); - - for (direction cmpt=0; cmpt < point::nComponents; ++cmpt) - { - forAll(pointMap, ptI) - { - if (pointMap[ptI] > -1) - { - os.write(points[ptI].component(cmpt)); - os.newline(); - } - } - } - - // Write each element type - for (int typei=0; typei < ensightCells::nTypes; ++typei) - { - const ensightCells::elemType what = ensightCells::elemType(typei); - - writeConnectivity - ( - os, - ensightCells::key(what), - cellIds(what), - pointMap - ); - } - } -} - - -void Foam::ensightPartCells::write(ensightGeoFile& os) const -{ - this->write(os, mesh_.points()); -} - - -void Foam::ensightPartCells::writeSummary(Ostream& os) const -{ - os.beginBlock(type()); - - os.writeEntry("id", index()+1); // Ensight starts with 1 - os.writeEntry("name", name()); - os.writeEntry("size", size()); - - os.endBlock(); -} - - -void Foam::ensightPartCells::dumpInfo(Ostream& os) const -{ - os.beginBlock(type()); - - os.writeEntry("id", index()+1); // Ensight starts with 1 - os.writeEntry("name", name()); - os.writeEntry("size", size()); - - for (int typei=0; typei < ensightCells::nTypes; ++typei) - { - const ensightCells::elemType what = ensightCells::elemType(typei); - const labelUList& addr = this->cellIds(what); - - os.writeKeyword(ensightCells::key(what)); - - addr.writeList(os, 0) << endEntry; // Flat output - } - - os.endBlock(); -} - - -// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/ensightPartCells.H b/src/fileFormats/ensight/part/ensightPartCells.H deleted file mode 100644 index b0ddad0d4d7..00000000000 --- a/src/fileFormats/ensight/part/ensightPartCells.H +++ /dev/null @@ -1,180 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2016-2019 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -Class - Foam::ensightPartCells - -Description - An implementation of ensightPart to hold volume mesh cells. - -SourceFiles - ensightPartCells.C - -\*---------------------------------------------------------------------------*/ - -#ifndef ensightPartCells_H -#define ensightPartCells_H - -#include "ensightPart.H" -#include "ensightCells.H" -#include "typeInfo.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -/*---------------------------------------------------------------------------*\ - Class ensightPartCells Declaration -\*---------------------------------------------------------------------------*/ - -class ensightPartCells -: - public ensightCells, - public ensightPart -{ - // Private Data - - //- The referenced mesh - const polyMesh& mesh_; - - - // Private Member Functions - - //- Track points used - localPoints calcLocalPoints() const; - - //- Element connectivity - void writeConnectivity - ( - ensightGeoFile&, - const word& key, - const labelUList& idList, - const labelUList& pointMap - ) const; - - - //- No copy construct - ensightPartCells(const ensightPartCells&) = delete; - - //- No copy assignment - void operator=(const ensightPartCells&) = delete; - - -public: - - //- Runtime type information - TypeName("ensightCells"); - - - // Constructors - - //- Construct from entire polyMesh without zones. - //- Part receives the specified name (default: "cells"). - ensightPartCells - ( - label partIndex, - const polyMesh& mesh, - const string& partName = "cells" - ); - - //- Construct a part from polyMesh and list of cells. - //- Part receives the specified name (default: "cells"). - ensightPartCells - ( - label partIndex, - const polyMesh& mesh, - const labelUList& cellIds, - const string& partName = "cells" - ); - - //- Construct a part from polyMesh and selection of cells. - //- Part receives the specified name (default: "cells"). - ensightPartCells - ( - label partIndex, - const polyMesh& mesh, - const bitSet& selection, - const string& partName = "cells" - ); - - //- Construct from polyMesh and cellZone. - //- Part receives the name of the zone unless otherwise specified. - ensightPartCells - ( - label partIndex, - const polyMesh& mesh, - const cellZone& zn, - const string& partName = "" - ); - - - //- Destructor - virtual ~ensightPartCells() = default; - - - // Member Functions - - // Access - - //- Part index (0-based) - virtual label index() const - { - return ensightCells::index(); - } - - //- Number of elements in this part - virtual label size() const - { - return ensightCells::size(); - } - - - // Output - - //- Write summary information about the object - virtual void writeSummary(Ostream& os) const; - - //- Print various types of debugging information - virtual void dumpInfo(Ostream& os) const; - - //- Write geometry - virtual void write(ensightGeoFile& os) const; - - //- Helper: write geometry with given pointField - virtual void write(ensightGeoFile& os, const pointField& points) const; -}; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#endif - -// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/ensightPartFaces.C b/src/fileFormats/ensight/part/ensightPartFaces.C deleted file mode 100644 index 6e9d2747c49..00000000000 --- a/src/fileFormats/ensight/part/ensightPartFaces.C +++ /dev/null @@ -1,302 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2019 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -\*---------------------------------------------------------------------------*/ - -#include "ensightPartFaces.H" - -// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // - -namespace Foam -{ - defineTypeNameAndDebug(ensightPartFaces, 0); -} - - -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // - -Foam::ensightPart::localPoints Foam::ensightPartFaces::calcLocalPoints() const -{ - if (contiguousPoints_) - { - localPoints ptList; - ptList.list = identity(points_.size()); - ptList.nPoints = points_.size(); - return ptList; - } - - localPoints ptList(points_); - labelList& usedPoints = ptList.list; - label nPoints = 0; - - // Add all points from faces - const labelUList& idList = this->faceIds(); - - // Add all points from faces - forAll(idList, i) - { - const label id = idList[i] + start_; - const face& f = faces_[id]; - - forAll(f, fp) - { - if (usedPoints[f[fp]] == -1) - { - usedPoints[f[fp]] = nPoints++; - } - } - } - - - // This is not absolutely necessary, but renumber anyhow - nPoints = 0; - forAll(usedPoints, ptI) - { - if (usedPoints[ptI] > -1) - { - usedPoints[ptI] = nPoints++; - } - } - - ptList.nPoints = nPoints; - return ptList; -} - - -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - -Foam::ensightPartFaces::ensightPartFaces -( - label partIndex, - const string& description, - const pointField& points, - const faceList& faces, - const bool contiguousPoints -) -: - ensightFaces(partIndex), - ensightPart(description), - start_(0), - patchIndex_(-1), - faces_(faces), - points_(points), - contiguousPoints_(contiguousPoints) -{ - // Classify the face shapes - classify(faces); -} - - -Foam::ensightPartFaces::ensightPartFaces -( - label partIndex, - const polyMesh& mesh, - const polyPatch& patch, - const string& partName -) -: - ensightFaces(partIndex), - ensightPart(patch.name()), - start_(patch.start()), - patchIndex_(patch.index()), - faces_(mesh.faces()), - points_(mesh.points()), - contiguousPoints_(false) -{ - if (!partName.empty()) - { - rename(partName); - } - - // Classify the face shapes - classify(patch); -} - - -Foam::ensightPartFaces::ensightPartFaces -( - label partIndex, - const polyPatch& patch, - const string& partName -) -: - ensightPartFaces(partIndex, patch.boundaryMesh().mesh(), patch, partName) -{} - - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -void Foam::ensightPartFaces::writeConnectivity -( - ensightGeoFile& os, - const word& key, - const faceList& faces, - const labelUList& idList, - const labelUList& pointMap -) const -{ - if (idList.empty()) return; - - os.writeKeyword(key); - os.write(idList.size()); - os.newline(); - - // Write (polygon) face sizes - if (key == "nsided") - { - // Write the number of points per face - forAll(idList, i) - { - const label id = idList[i] + start_; - const face& f = faces[id]; - - os.write(f.size()); - os.newline(); - } - } - - // Write the points describing the face - forAll(idList, i) - { - const label id = idList[i] + start_; - const face& f = faces[id]; - - // Convert global -> local index - // (note: Ensight indices start with 1) - forAll(f, fp) - { - os.write(pointMap[f[fp]] + 1); - } - os.newline(); - } -} - - -void Foam::ensightPartFaces::writeConnectivity -( - ensightGeoFile& os, - const word& key, - const labelUList& idList, - const labelUList& pointMap -) const -{ - writeConnectivity - ( - os, - key, - faces_, - idList, - pointMap - ); -} - - -void Foam::ensightPartFaces::write -( - ensightGeoFile& os, - const pointField& points -) const -{ - if (size()) - { - const localPoints ptList = calcLocalPoints(); - const labelUList& pointMap = ptList.list; - - os.beginPart(index(), name()); - os.beginCoordinates(ptList.nPoints); - - for (direction cmpt=0; cmpt < point::nComponents; ++cmpt) - { - forAll(pointMap, ptI) - { - if (pointMap[ptI] > -1) - { - os.write(points[ptI].component(cmpt)); - os.newline(); - } - } - } - - // Write part - for (int typei=0; typei < ensightFaces::nTypes; ++typei) - { - const ensightFaces::elemType what = ensightFaces::elemType(typei); - - writeConnectivity - ( - os, - ensightFaces::key(what), - faceIds(what), - pointMap - ); - } - } -} - - -void Foam::ensightPartFaces::write(ensightGeoFile& os) const -{ - this->write(os, points_); -} - - -void Foam::ensightPartFaces::writeSummary(Ostream& os) const -{ - os.beginBlock(type()); - - os.writeEntry("id", index()+1); // Ensight starts with 1 - os.writeEntry("name", name()); - os.writeEntry("start", start_); - os.writeEntry("size", size()); - - os.endBlock(); -} - - -void Foam::ensightPartFaces::dumpInfo(Ostream& os) const -{ - os.beginBlock(type()); - - os.writeEntry("id", index()+1); // Ensight starts with 1 - os.writeEntry("name", name()); - os.writeEntry("start", start_); - os.writeEntry("size", size()); - - for (int typei=0; typei < ensightFaces::nTypes; ++typei) - { - const ensightFaces::elemType what = ensightFaces::elemType(typei); - const labelUList& addr = this->faceIds(what); - - os.writeKeyword(ensightFaces::key(what)); - - addr.writeList(os, 0) << endEntry; // Flat output - } - - os.endBlock(); -} - - -// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/ensightPartFaces.H b/src/fileFormats/ensight/part/ensightPartFaces.H deleted file mode 100644 index 08fb6af73b7..00000000000 --- a/src/fileFormats/ensight/part/ensightPartFaces.H +++ /dev/null @@ -1,202 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2016-2019 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -Class - Foam::ensightPartFaces - -Description - An implementation of ensightPart to hold mesh faces. - -SourceFiles - ensightPartFaces.C - -\*---------------------------------------------------------------------------*/ - -#ifndef ensightPartFaces_H -#define ensightPartFaces_H - -#include "ensightPart.H" -#include "ensightFaces.H" -#include "typeInfo.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -/*---------------------------------------------------------------------------*\ - Class ensightPartFaces Declaration -\*---------------------------------------------------------------------------*/ - -class ensightPartFaces -: - public ensightFaces, - public ensightPart -{ - // Private data - - //- Start offset for patch - const label start_; - - //- Patch index - const label patchIndex_; - - //- The referenced faces - const faceList& faces_; - - //- The referenced pointField - const pointField& points_; - - //- Can skip local point renumbering when points are contiguous - const bool contiguousPoints_; - - - // Private Member Functions - - //- Track points used - localPoints calcLocalPoints() const; - - //- Element connectivity - void writeConnectivity - ( - ensightGeoFile&, - const word& key, - const labelUList& idList, - const labelUList& pointMap - ) const; - - - //- Helper: write connectivity - void writeConnectivity - ( - ensightGeoFile&, - const word& key, - const faceList&, - const labelUList& idList, - const labelUList& pointMap - ) const; - - - //- No copy construct - ensightPartFaces(const ensightPartFaces&) = delete; - - //- No copy assignment - void operator=(const ensightPartFaces&) = delete; - - -public: - - //- Runtime type information - TypeName("ensightFaces"); - - - // Constructors - - //- Construct part with 0-based index, description, points and faces - // Can skip local point renumbering when points are contiguous - ensightPartFaces - ( - label partIndex, - const string& description, - const pointField& points, - const faceList& faces, - const bool contiguousPoints = false - ); - - //- Construct from polyMesh and polyPatch - //- Part receives the name of the patch unless otherwise specified. - ensightPartFaces - ( - label partIndex, - const polyMesh& mesh, - const polyPatch& patch, - const string& partName = "" - ); - - //- Construct from polyPatch - //- Part receives the name of the patch unless otherwise specified. - ensightPartFaces - ( - label partIndex, - const polyPatch& patch, - const string& partName = "" - ); - - - //- Destructor - virtual ~ensightPartFaces() = default; - - - // Member Functions - - // Access - - //- Part index (0-based) - virtual label index() const - { - return ensightFaces::index(); - } - - - //- Number of elements in this part - virtual label size() const - { - return ensightFaces::size(); - } - - - //- Return the patch index, -1 when not in use. - inline label patchIndex() const - { - return patchIndex_; - } - - - // Output - - //- Write summary information about the object - virtual void writeSummary(Ostream& os) const; - - //- Print various types of debugging information - virtual void dumpInfo(Ostream& os) const; - - //- Write geometry - virtual void write(ensightGeoFile& os) const; - - //- Helper: write geometry given the pointField - virtual void write(ensightGeoFile& os, const pointField& points) const; -}; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#endif - -// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/ensightParts.C b/src/fileFormats/ensight/part/ensightParts.C deleted file mode 100644 index 70baac46477..00000000000 --- a/src/fileFormats/ensight/part/ensightParts.C +++ /dev/null @@ -1,134 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2019 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -\*---------------------------------------------------------------------------*/ - -#include "ensightParts.H" -#include "bitSet.H" -#include "emptyPolyPatch.H" -#include "processorPolyPatch.H" - -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - -Foam::ensightParts::ensightParts(const polyMesh& mesh) -: - StorageType() -{ - recalculate(mesh); -} - - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -void Foam::ensightParts::recalculate(const polyMesh& mesh) -{ - StorageType::clear(); - - label nPart = 0; - - // Track which cells are in a zone or not - bitSet selection(mesh.nCells()); - - // Do all cell zones - for (const cellZone& zn : mesh.cellZones()) - { - if (returnReduce(!zn.empty(), orOp<bool>())) - { - selection.set(zn); - this->append(new ensightPartCells(nPart++, mesh, zn)); - } - } - - if (!nPart) - { - // No zones at all? - do entire mesh. Name as per ensightMesh - this->append(new ensightPartCells(nPart++, mesh, "internalMesh")); - } - else - { - // Flip from zoned to unzoned - selection.flip(); - - if (returnReduce(selection.any(), orOp<bool>())) - { - this->append - ( - new ensightPartCells(nPart++, mesh, selection, "__internal__") - ); - } - } - - - // Do boundaries, skipping empty and processor patches - for (const polyPatch& p : mesh.boundaryMesh()) - { - if (isA<processorPolyPatch>(p)) - { - // No processor patches - break; - } - - if (returnReduce(!p.empty(), orOp<bool>())) - { - this->append(new ensightPartFaces(nPart++, mesh, p)); - } - } -} - - -void Foam::ensightParts::write(ensightGeoFile& os) const -{ - // Some feedback - Info<< "Write geometry part (" << flush; - - for (const ensightPart& part : *this) - { - Info<< ' ' << part.index() << flush; - part.write(os); - } - Info<< " )" << endl; -} - - -void Foam::ensightParts::writeSummary(Ostream& os) const -{ - for (const ensightPart& part : *this) - { - part.writeSummary(os); - } -} - - -void Foam::ensightParts::dumpInfo(Ostream& os) const -{ - for (const ensightPart& part : *this) - { - part.dumpInfo(os); - } -} - - -// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/ensightParts.H b/src/fileFormats/ensight/part/ensightParts.H deleted file mode 100644 index 6ee3b3b1f14..00000000000 --- a/src/fileFormats/ensight/part/ensightParts.H +++ /dev/null @@ -1,120 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2019 OpenCFD Ltd. -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -Class - Foam::ensightParts - -Description - A collection of several ensightPart elements - -SourceFiles - ensightParts.C - -\*---------------------------------------------------------------------------*/ - -#ifndef ensightParts_H -#define ensightParts_H - -#include "SLPtrList.H" -#include "ensightPart.H" -#include "ensightPartFaces.H" -#include "ensightPartCells.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -/*---------------------------------------------------------------------------*\ - Class ensightParts Declaration -\*---------------------------------------------------------------------------*/ - -class ensightParts -: - public SLPtrList<ensightPart> -{ - // Private Member Functions - - //- No copy construct - ensightParts(const ensightParts&) = delete; - - //- No copy assignment - void operator=(const ensightParts&) = delete; - - -public: - - //- Storage type used - typedef SLPtrList<ensightPart> StorageType; - - - // Constructors - - //- Construct from polyMesh - explicit ensightParts(const polyMesh& mesh); - - - //- Destructor - ~ensightParts() = default; - - - // Member Functions - - //- Number of parts - using StorageType::size; - - //- Clear old information and construct anew from polyMesh - void recalculate(const polyMesh& mesh); - - - // Output - - //- Write summary information about the objects - void writeSummary(Ostream& os) const; - - //- Print various types of debugging information - void dumpInfo(Ostream& os) const; - - //- Write the geometry to file - void write(autoPtr<ensightGeoFile>& os) const - { - write(os.ref()); - } - - //- Write the geometry to file - void write(ensightGeoFile& os) const; -}; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#endif - -// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/ensightFaces.C b/src/fileFormats/ensight/part/faces/ensightFaces.C similarity index 52% rename from src/fileFormats/ensight/part/ensightFaces.C rename to src/fileFormats/ensight/part/faces/ensightFaces.C index 425ebc6f968..d818a06536e 100644 --- a/src/fileFormats/ensight/part/ensightFaces.C +++ b/src/fileFormats/ensight/part/faces/ensightFaces.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2018 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -31,16 +31,27 @@ License // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // +namespace Foam +{ + defineTypeNameAndDebug(ensightFaces, 0); +} + const char* Foam::ensightFaces::elemNames[3] = { "tria3", "quad4", "nsided" }; +static_assert +( + Foam::ensightFaces::nTypes == 3, + "Support exactly 3 face types (tria3, quad4, nsided)" +); + // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // namespace { -// Simple shape classifier +// Trivial shape classifier static inline Foam::ensightFaces::elemType whatType(const Foam::face& f) { return @@ -58,48 +69,26 @@ static inline Foam::ensightFaces::elemType whatType(const Foam::face& f) // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -// Only used in this file-scope -inline void Foam::ensightFaces::add -( - const face& f, - const label id, - const bool flip -) +void Foam::ensightFaces::resizeAll() { - const enum elemType what = whatType(f); + // Assign sub-list offsets, determine overall size - // linear addressing: - const label index = offset(what) + sizes_[what]++; - - address_[index] = id; - if (flipMap_.size()) - { - flipMap_[index] = flip; - } -} + label len = 0; + auto iter = offsets_.begin(); -void Foam::ensightFaces::resizeAll() -{ - // overall required size - label n = 0; - forAll(sizes_, typei) + *iter = 0; + for (const label n : sizes_) { - n += sizes_[typei]; - } - address_.setSize(n, Zero); + len += n; - // assign corresponding sub-lists - n = 0; - forAll(sizes_, typei) - { - slices_[typei].setStart(n); - slices_[typei].setSize(sizes_[typei]); - - n += sizes_[typei]; + *(++iter) = len; } - // normally assume no flipMap + // The addressing space + addressing().resize(len, Zero); + + // Normally assume no flipMap flipMap_.clear(); } @@ -108,40 +97,18 @@ void Foam::ensightFaces::resizeAll() Foam::ensightFaces::ensightFaces() : - ensightFaces(0) -{} - - -Foam::ensightFaces::ensightFaces(const label partIndex) -: - index_(partIndex), - address_(), + ensightPart(), flipMap_(), - slices_(), + offsets_(Zero), sizes_(Zero) -{ - resizeAll(); // adjust allocation/sizing -} +{} -Foam::ensightFaces::ensightFaces(const ensightFaces& obj) +Foam::ensightFaces::ensightFaces(const string& description) : - index_(obj.index_), - address_(obj.address_), - flipMap_(obj.flipMap_), - slices_(), - sizes_() + ensightFaces() { - // Save the total (reduced) sizes - FixedList<label, 3> totSizes = obj.sizes_; - - // Need local sizes for the resize operation - this->sizes_ = obj.sizes(); - - resizeAll(); // adjust allocation/sizing - - // Restore total (reduced) sizes - this->sizes_ = totSizes; + rename(description); } @@ -150,9 +117,10 @@ Foam::ensightFaces::ensightFaces(const ensightFaces& obj) Foam::FixedList<Foam::label, 3> Foam::ensightFaces::sizes() const { FixedList<label, 3> count; - forAll(slices_, typei) + + forAll(count, typei) { - count[typei] = slices_[typei].size(); + count[typei] = size(elemType(typei)); } return count; @@ -172,17 +140,26 @@ Foam::label Foam::ensightFaces::total() const void Foam::ensightFaces::clear() { - sizes_ = Zero; // reset sizes - resizeAll(); + clearOut(); + + ensightPart::clear(); + + flipMap_.clear(); + sizes_ = Zero; + offsets_ = Zero; } +void Foam::ensightFaces::clearOut() +{} + + void Foam::ensightFaces::reduce() { // No listCombineGather, listCombineScatter for FixedList forAll(sizes_, typei) { - sizes_[typei] = slices_[typei].size(); + sizes_[typei] = size(elemType(typei)); Foam::reduce(sizes_[typei], sumOp<label>()); } } @@ -190,89 +167,116 @@ void Foam::ensightFaces::reduce() void Foam::ensightFaces::sort() { - if (flipMap_.size() == address_.size()) + const bool useFlip = (size() == flipMap_.size()); + + if (useFlip) { // Must sort flip map as well labelList order; - forAll(slices_, typei) + for (int typei=0; typei < nTypes; ++typei) { - if (slices_[typei].size()) + const labelRange sub(range(elemType(typei))); + + if (!sub.empty()) { - SubList<label> idLst(address_, slices_[typei]); - SubList<bool> flip(flipMap_, slices_[typei]); + SubList<label> ids(addressing(), sub); + SubList<bool> flips(flipMap_, sub); - Foam::sortedOrder(idLst, order); + Foam::sortedOrder(ids, order); - idLst = reorder<labelList>(order, idLst); - flip = reorder<boolList>(order, flip); + ids = reorder<labelList>(order, ids); + flips = reorder<boolList>(order, flips); } } } else { - // no flip-maps, simpler to sort - forAll(slices_, typei) + flipMap_.clear(); // Extra safety + + // No flip-maps, simply sort addresses + for (int typei=0; typei < nTypes; ++typei) { - if (slices_[typei].size()) + const labelRange sub(range(elemType(typei))); + + if (!sub.empty()) { - SubList<label> idLst(address_, slices_[typei]); - Foam::sort(idLst); + SubList<label> ids(addressing(), sub); + Foam::sort(ids); } } - - flipMap_.clear(); // for extra safety } } -void Foam::ensightFaces::classify(const faceList& faces) +void Foam::ensightFaces::classify(const UList<face>& faces) { - const label sz = faces.size(); + const label len = faces.size(); // Pass 1: Count the shapes sizes_ = Zero; // reset sizes - for (label listi = 0; listi < sz; ++listi) + for (label listi = 0; listi < len; ++listi) { - const enum elemType what = whatType(faces[listi]); - sizes_[what]++; + const auto etype = whatType(faces[listi]); + + ++sizes_[etype]; } resizeAll(); // adjust allocation sizes_ = Zero; // reset sizes - use for local indexing here + // Pass 2: Assign face-id per shape type - for (label listi = 0; listi < sz; ++listi) + for (label listi = 0; listi < len; ++listi) { - add(faces[listi], listi); + const auto etype = whatType(faces[listi]); + + add(etype, listi); } } void Foam::ensightFaces::classify ( - const faceList& faces, - const labelUList& addressing, + const UList<face>& faces, + const labelRange& range +) +{ + const labelRange slice(range.subset0(faces.size())); + + // Operate on a local slice + classify(SubList<face>(slice, faces)); + + // Fixup to use the real faceIds instead of the 0-based slice + incrAddressing(slice.start()); +} + + +void Foam::ensightFaces::classify +( + const UList<face>& faces, + const labelUList& addr, const boolList& flipMap, const bitSet& exclude ) { - const label sz = addressing.size(); - const bool useFlip = (addressing.size() == flipMap.size()); + const label len = addr.size(); + const bool useFlip = (len == flipMap.size()); // Pass 1: Count the shapes sizes_ = Zero; // reset sizes - for (label listi = 0; listi < sz; ++listi) + for (label listi = 0; listi < len; ++listi) { - const label faceId = addressing[listi]; + const label faceId = addr[listi]; if (!exclude.test(faceId)) { - const enum elemType what = whatType(faces[faceId]); - sizes_[what]++; + const auto etype = whatType(faces[faceId]); + + ++sizes_[etype]; } } @@ -281,22 +285,53 @@ void Foam::ensightFaces::classify if (useFlip) { - flipMap_.setSize(address_.size(), false); + flipMap_.resize(len); flipMap_ = false; } + else + { + flipMap_.clear(); // Extra safety + } // Pass 2: Assign face-id per shape type - for (label listi = 0; listi < sz; ++listi) + for (label listi = 0; listi < len; ++listi) { - const label faceId = addressing[listi]; + const label faceId = addr[listi]; const bool doFlip = useFlip && flipMap[listi]; if (!exclude.test(faceId)) { - add(faces[faceId], faceId, doFlip); + const auto etype = whatType(faces[faceId]); + + add(etype, faceId, doFlip); } } } + +void Foam::ensightFaces::writeDict(Ostream& os, const bool full) const +{ + os.beginBlock(type()); + + os.writeEntry("id", index()+1); // Ensight starts with 1 + os.writeEntry("name", name()); + os.writeEntry("size", size()); + + if (full) + { + for (int typei=0; typei < ensightFaces::nTypes; ++typei) + { + const auto etype = ensightFaces::elemType(typei); + + os.writeKeyword(ensightFaces::key(etype)); + + faceIds(etype).writeList(os, 0) << endEntry; // Flat output + } + } + + os.endBlock(); +} + + // ************************************************************************* // diff --git a/src/fileFormats/ensight/part/faces/ensightFaces.H b/src/fileFormats/ensight/part/faces/ensightFaces.H new file mode 100644 index 00000000000..0faa6004822 --- /dev/null +++ b/src/fileFormats/ensight/part/faces/ensightFaces.H @@ -0,0 +1,264 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016-2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::ensightFaces + +Description + Sorting/classification of faces (2D) into corresponding ensight types. + + Some caution may be required when handling face addressing into a + boundaryField. Since the face addressing is absolute, it will be + necessary to work on a copy with local ids. For example, + + \code + // Operate on a copy + ensightFaces localPart(part); + + // Change from global faceIds to patch-local faceIds + localPart.decrFaceIds(patchStart); + + // Can now address into boundaryField + \endcode + +\*---------------------------------------------------------------------------*/ + +#ifndef ensightFaces_H +#define ensightFaces_H + +#include "ensightPart.H" +#include "boolList.H" +#include "faceList.H" +#include "FixedList.H" +#include "bitSet.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class polyMesh; + +/*---------------------------------------------------------------------------*\ + Class ensightFaces Declaration +\*---------------------------------------------------------------------------*/ + +class ensightFaces +: + public ensightPart +{ +public: + + // Public Data + + //- Supported ensight 'Face' element types. + // Must be zero-based since they are also for internal bookkeeping. + enum elemType + { + TRIA3 = 0, //!< "tria3" + QUAD4, //!< "quad4" + NSIDED //!< "nsided" + }; + + //- Number of 'Face' element types (3) + static constexpr int nTypes = 3; + + //- The ensight 'Face' element type names + static const char* elemNames[nTypes]; + + + // Static Functions + + //- The ensight element name for the specified 'Face' type + static inline const char* key(const elemType etype); + + +private: + + // Private Data + + //- Linear list of face-flips + boolList flipMap_; + + //- Begin/end offsets for address/flips of each element type + FixedList<label, nTypes+1> offsets_; + + //- List of global sizes for each element type. + // Used temporarily for local sizes when building the element lists. + FixedList<label, nTypes> sizes_; + + + // Private Member Functions + + //- Low-level internal addition routine + inline void add(const elemType etype, label id, bool flip=false); + + //- Use temporarily stored sizes to redimension the element lists + void resizeAll(); + + +public: + + //- Declare type-name, virtual type (with debug switch) + TypeName("ensightFaces"); + + + // Constructors + + //- Default construct, with part index 0 + ensightFaces(); + + //- Default construct, with description/partName + explicit ensightFaces(const string& description); + + + //- Destructor + virtual ~ensightFaces() = default; + + + // Member Functions + + // Access + + //- Processor-local size of all elements. + using ensightPart::size; + + //- Processor-local size of the specified element type. + inline label size(const elemType etype) const; + + //- Processor-local offset/size of element type. + inline labelRange range(const elemType etype) const; + + //- The global size of all element types. + // This value is only meaningful after a reduce operation. + label total() const; + + //- The global size of the specified element type. + // This value is only meaningful after a reduce operation. + inline label total(const elemType etype) const; + + //- The global sizes for each element type. + // This value is only meaningful after a reduce operation. + inline const FixedList<label, nTypes>& totals() const; + + //- Processor-local sizes per element type. + FixedList<label, nTypes> sizes() const; + + //- Processor-local face ids of all elements + inline const labelList& faceIds() const; + + //- Processor-local face ids of the specified element type + inline const labelUList faceIds(const elemType etype) const; + + //- Processor-local flip-map of all elements + inline const boolList& flipMap() const; + + //- True for non-zero flip-map that spans the addresses + inline bool usesFlipMap() const; + + + // Edit + + //- Classify the face types and set the element lists. + void classify(const UList<face>& faces); + + //- Classify face types (for a sublist) and set element lists. + void classify(const UList<face>& faces, const labelRange& range); + + //- Classify the face types and set the element lists. + // The indirect addressing can be used when classifying groups of + // face (eg, from a faceZone etc) with an optional flipMap. + // The optional exclude marker can be used to skip faces on particular + // boundary types or regions. + void classify + ( + const UList<face>& faces, + const labelUList& addr, + const boolList& flipMap = boolList(), + const bitSet& exclude = bitSet() + ); + + + //- Clear any demand-driven data + void clearOut(); + + //- Set addressable sizes to zero, free up addressing memory. + void clear(); + + //- Sum element counts across all processes. + void reduce(); + + //- Sort element lists numerically. + void sort(); + + + // Advanced (use with caution) + + //- Increase face ids by specified offset value + // Eg, to change patch local Ids to global Ids + void incrFaceIds(const label off); + + //- Decrease face ids by specified offset value + // Eg, to change global Ids to patch local Ids + void decrFaceIds(const label off); + + + // Output + + //- Globally unique mesh points. + //- Required when writing point fields. + label uniqueMeshPoints + ( + const polyMesh& mesh, + labelList& uniqueMeshPointLabels, + bool parallel + ) const; + + //- Write information about the object as a dictionary, + //- optionally write all element addresses + virtual void writeDict(Ostream& os, const bool full=false) const; + + //- Write geometry, using a mesh reference (serial only) + virtual void write + ( + ensightGeoFile& os, + const polyMesh& mesh, + bool parallel + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "ensightFacesI.H" + +#endif + +// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/faces/ensightFacesAddr.C b/src/fileFormats/ensight/part/faces/ensightFacesAddr.C new file mode 100644 index 00000000000..bbfb4e21512 --- /dev/null +++ b/src/fileFormats/ensight/part/faces/ensightFacesAddr.C @@ -0,0 +1,96 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "ensightFaces.H" +#include "ensightOutput.H" + +#include "polyMesh.H" +#include "globalIndex.H" +#include "globalMeshData.H" +#include "uindirectPrimitivePatch.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::label Foam::ensightFaces::uniqueMeshPoints +( + const polyMesh& mesh, + labelList& uniqueMeshPointLabels, + bool parallel +) const +{ + const ensightFaces& part = *this; + + parallel = parallel && Pstream::parRun(); + + // Renumber the patch points/faces into unique points + label nPoints = 0; // Total number of points + labelList pointToGlobal; // local point to unique global index + + const pointField& points = mesh.points(); + const faceList& faces = mesh.faces(); + + + // Use the properly sorted faceIds (ensightFaces) and do NOT use + // the faceZone or anything else directly, otherwise the + // point-maps will not correspond. + // - perform face-flipping later + + uindirectPrimitivePatch pp + ( + UIndirectList<face>(faces, part.faceIds()), + points + ); + + if (parallel) + { + autoPtr<globalIndex> globalPointsPtr = + mesh.globalData().mergePoints + ( + pp.meshPoints(), + pp.meshPointMap(), + pointToGlobal, + uniqueMeshPointLabels + ); + + nPoints = globalPointsPtr().size(); // nPoints (global) + } + else + { + // Non-parallel + // - all information already available from PrimitivePatch + + nPoints = pp.meshPoints().size(); + uniqueMeshPointLabels = pp.meshPoints(); + + // Not neaded: pointToGlobal + } + + return nPoints; +} + + +// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/ensightFacesI.H b/src/fileFormats/ensight/part/faces/ensightFacesI.H similarity index 52% rename from src/fileFormats/ensight/part/ensightFacesI.H rename to src/fileFormats/ensight/part/faces/ensightFacesI.H index 15799e5610f..b971115ac8e 100644 --- a/src/fileFormats/ensight/part/ensightFacesI.H +++ b/src/fileFormats/ensight/part/faces/ensightFacesI.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2017 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -25,82 +25,88 @@ License \*---------------------------------------------------------------------------*/ -#include "error.H" +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -inline const char* Foam::ensightFaces::key(const enum elemType what) +inline void Foam::ensightFaces::add(const elemType etype, label id, bool flip) { - return elemNames[what]; + // Linear addressing location + const label index = offsets_[etype] + sizes_[etype]++; + + addressing()[index] = id; + + if (flipMap_.size()) + { + flipMap_[index] = flip; + } } -inline Foam::label Foam::ensightFaces::index() const +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline const char* Foam::ensightFaces::key(const elemType etype) { - return index_; + return elemNames[etype]; } -inline Foam::label& Foam::ensightFaces::index() +inline const Foam::FixedList<Foam::label,3>& Foam::ensightFaces::totals() const { - return index_; + return sizes_; } -inline Foam::label Foam::ensightFaces::size() const +inline Foam::label Foam::ensightFaces::total(const elemType etype) const { - return address_.size(); + return sizes_[etype]; } -inline const Foam::FixedList<Foam::label,3>& Foam::ensightFaces::totals() const +inline Foam::label Foam::ensightFaces::size(const elemType etype) const { - return sizes_; + return (offsets_[etype+1] - offsets_[etype]); } -inline Foam::label Foam::ensightFaces::total(const enum elemType what) const +inline Foam::labelRange Foam::ensightFaces::range(const elemType etype) const { - return sizes_[what]; + return labelRange(offsets_[etype], offsets_[etype+1] - offsets_[etype]); } -inline Foam::label Foam::ensightFaces::size(const enum elemType what) const +inline const Foam::labelList& Foam::ensightFaces::faceIds() const { - return slices_[what].size(); + return addressing(); } -inline Foam::label Foam::ensightFaces::offset(const enum elemType what) const +inline const Foam::labelUList +Foam::ensightFaces::faceIds(const elemType etype) const { - return slices_[what].start(); + return addressing()[range(etype)]; } -inline const Foam::labelUList Foam::ensightFaces::faceIds -( - const enum elemType what -) const +inline const Foam::boolList& Foam::ensightFaces::flipMap() const { - return address_[slices_[what]]; + return flipMap_; } -inline const Foam::labelUList& Foam::ensightFaces::faceIds() const +inline bool Foam::ensightFaces::usesFlipMap() const { - return address_; + return (!flipMap_.empty() && flipMap_.size() == size()); } -inline const Foam::boolList& Foam::ensightFaces::flipMap() const +inline void Foam::ensightFaces::incrFaceIds(const label off) { - return flipMap_; + incrAddressing(off); } -inline Foam::label Foam::ensightFaces::operator[](const label i) const +inline void Foam::ensightFaces::decrFaceIds(const label off) { - return address_[i]; + decrAddressing(off); } diff --git a/src/fileFormats/ensight/part/faces/ensightFacesIO.C b/src/fileFormats/ensight/part/faces/ensightFacesIO.C new file mode 100644 index 00000000000..4ce459eddb6 --- /dev/null +++ b/src/fileFormats/ensight/part/faces/ensightFacesIO.C @@ -0,0 +1,138 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "ensightFaces.H" +#include "ensightOutput.H" + +#include "polyMesh.H" +#include "globalIndex.H" +#include "globalMeshData.H" +#include "uindirectPrimitivePatch.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::ensightFaces::write +( + ensightGeoFile& os, + const polyMesh& mesh, + bool parallel +) const +{ + const ensightFaces& part = *this; + + parallel = parallel && Pstream::parRun(); + + // Renumber the patch points/faces into unique points + label nPoints = 0; // Total number of points + labelList pointToGlobal; // local point to unique global index + labelList uniqueMeshPointLabels; // unique global points + + + const pointField& points = mesh.points(); + const faceList& faces = mesh.faces(); + + + // Use the properly sorted faceIds (ensightFaces) and do NOT use + // the faceZone or anything else directly, otherwise the + // point-maps will not correspond. + // - perform face-flipping later + + uindirectPrimitivePatch pp + ( + UIndirectList<face>(faces, part.faceIds()), + points + ); + + if (parallel) + { + autoPtr<globalIndex> globalPointsPtr = + mesh.globalData().mergePoints + ( + pp.meshPoints(), + pp.meshPointMap(), + pointToGlobal, + uniqueMeshPointLabels + ); + + nPoints = globalPointsPtr().size(); // nPoints (global) + } + else + { + // Non-parallel + // - all information already available from PrimitivePatch + + nPoints = pp.meshPoints().size(); + uniqueMeshPointLabels = pp.meshPoints(); + + pointToGlobal.resize(nPoints); + ListOps::identity(pointToGlobal); + } + + ensightOutput::Detail::writeCoordinates + ( + os, + part.index(), + part.name(), + nPoints, // nPoints (global) + UIndirectList<point>(points, uniqueMeshPointLabels), + parallel //!< Collective write? + ); + + + // Renumber the faces belonging to the faceZone, + // from local numbering to unique global index. + + faceList patchFaces(pp.localFaces()); + ListListOps::inplaceRenumber(pointToGlobal, patchFaces); + + // Also a good place to perform face flipping + if (part.usesFlipMap()) + { + const boolList& flip = part.flipMap(); + + forAll(patchFaces, facei) + { + face& f = patchFaces[facei]; + + if (flip[facei]) + { + f.flip(); + } + } + } + + ensightOutput::writeFaceConnectivityPresorted + ( + os, + part, + patchFaces, + parallel //!< Collective write? + ); +} + + +// ************************************************************************* // diff --git a/src/fileFormats/ensight/part/ensightPart.C b/src/fileFormats/ensight/part/part/ensightPart.C similarity index 73% rename from src/fileFormats/ensight/part/ensightPart.C rename to src/fileFormats/ensight/part/part/ensightPart.C index 2092a33f396..70d7d51e2ea 100644 --- a/src/fileFormats/ensight/part/ensightPart.C +++ b/src/fileFormats/ensight/part/part/ensightPart.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -32,28 +32,49 @@ License namespace Foam { - defineTypeNameAndDebug(ensightPart, 0); + defineTypeName(ensightPart); +} + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +void Foam::ensightPart::incrAddressing(const label off) +{ + for (label& val : address_) + { + val += off; + } +} + + +void Foam::ensightPart::decrAddressing(const label off) +{ + for (label& val : address_) + { + val -= off; + } } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -Foam::ensightPart::ensightPart(const string& description) +Foam::ensightPart::ensightPart() noexcept : - name_(description) + index_(0), + identifier_(-1), + name_(), + address_() {} -// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // - -Foam::ensightGeoFile& Foam::operator<< -( - ensightGeoFile& os, - const ensightPart& part -) +Foam::ensightPart::ensightPart(const string& description) +: + ensightPart() { - part.write(os); - return os; + if (!description.empty()) + { + name_ = description; + } } diff --git a/src/fileFormats/ensight/part/part/ensightPart.H b/src/fileFormats/ensight/part/part/ensightPart.H new file mode 100644 index 00000000000..9bb3d4e250e --- /dev/null +++ b/src/fileFormats/ensight/part/part/ensightPart.H @@ -0,0 +1,214 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2011-2016 OpenFOAM Foundation + Copyright (C) 2016-2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::ensightPart + +Description + Base class for ensightCells, ensightFaces, ensightOutputSurfaces. + +SourceFiles + ensightPart.C + +\*---------------------------------------------------------------------------*/ + +#ifndef ensightPart_H +#define ensightPart_H + +#include "ensightGeoFile.H" +#include "labelList.H" +#include "typeInfo.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class ensightPart Declaration +\*---------------------------------------------------------------------------*/ + +class ensightPart +{ + // Private Data + + //- Part index within a list. + // The ensight part number is typically this value +1. + label index_; + + //- OpenFOAM identifier (patch index, zone index, etc). + // An unused identifier is -1 + label identifier_; + + //- Part name (or description) + string name_; + + //- Linear list of element ids (face/cell) + // Sub-sectioning by element type is done by derived classes + labelList address_; + + +protected: + + //- Element addressing + const labelList& addressing() const + { + return address_; + } + + //- Element addressing + labelList& addressing() + { + return address_; + } + + //- Clear element addressing + void clear() + { + address_.clear(); + } + + //- Increase addressing by specified offset value + // Eg, change local to global id + void incrAddressing(const label off); + + //- Decrease addressing by specified offset value + // Eg, change global to local id + void decrAddressing(const label off); + + +public: + + //- Declare type-name, virtual type (without debug switch) + TypeNameNoDebug("ensightPart"); + + + // Constructors + + //- Default construct. Index=0, identifier = -1 + ensightPart() noexcept; + + //- Default construct, with description/partName + explicit ensightPart(const string& description); + + + //- Destructor + virtual ~ensightPart() = default; + + + // Member Functions + + //- The index in a list (0-based) + label index() const + { + return index_; + } + + //- The index in a list (0-based) + label& index() + { + return index_; + } + + //- OpenFOAM identifier (patch, zone, etc), -1 when not in use. + label identifier() const + { + return identifier_; + } + + //- OpenFOAM identifier (patch, zone, etc), -1 when not in use. + label& identifier() + { + return identifier_; + } + + //- Processor-local test for any elements. + bool empty() const + { + return address_.empty(); + } + + //- Processor-local size of all elements. + label size() const + { + return address_.size(); + } + + //- The part name or description + const string& name() const + { + return name_; + } + + //- Change the part name or description + void rename(const string& value) + { + name_ = value; + } + + //- Change the part name or description + void rename(string&& value) + { + name_ = std::move(value); + } + + + // Output + + //- Write information about the object as a dictionary, + //- optionally write all element addresses + virtual void writeDict(Ostream& os, const bool full=false) const + {} + + + // Member Operators + + //- Processor-local element id from linear-list of addresses. + label operator[](const label i) const + { + return address_[i]; + } +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Housekeeping + +//- Deprecated(2020-02) - use ensightOutput or member write() methods +// \deprecated(2020-02) - use ensightOutput or member write() methods +void operator<<(ensightGeoFile&, const ensightPart&) = delete; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/convertVolumeFields.H b/src/fileFormats/ensight/part/surface/ensightOutputSurface.C similarity index 59% rename from applications/utilities/postProcessing/dataConversion/foamToEnsightParts/convertVolumeFields.H rename to src/fileFormats/ensight/part/surface/ensightOutputSurface.C index b5f39307ddd..fa9d577180e 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/convertVolumeFields.H +++ b/src/fileFormats/ensight/part/surface/ensightOutputSurface.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -23,35 +23,57 @@ License You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. -Description - Code chunk for converting volume and dimensioned fields - included by foamToEnsightParts. - \*---------------------------------------------------------------------------*/ -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +#include "ensightOutputSurface.H" +#include "ensightOutput.H" + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::ensightOutputSurface::ensightOutputSurface +( + const pointField& points, + const faceList& faces, + const string& description +) +: + ensightFaces(description), + points_(points), + faces_(faces) +{ + // Classify face types + classify(faces); +} + -// Cell field data output +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::ensightOutputSurface::write(ensightGeoFile& os) const { - Info<< "Write volume field ("; + if (!total()) + { + return; + } - writeAllVolFields + // Coordinates + ensightOutput::Detail::writeCoordinates ( - ensCase, - ensParts, - mesh, - objects + os, + index(), + name(), + points_.size(), + points_, + false // serial ); - writeAllDimFields + // Faces + ensightOutput::writeFaceConnectivity ( - ensCase, - ensParts, - mesh, - objects + os, + *this, + faces_, + false // serial ); - - Info<< " )" << nl; } diff --git a/src/fileFormats/ensight/part/surface/ensightOutputSurface.H b/src/fileFormats/ensight/part/surface/ensightOutputSurface.H new file mode 100644 index 00000000000..33a34f8eb69 --- /dev/null +++ b/src/fileFormats/ensight/part/surface/ensightOutputSurface.H @@ -0,0 +1,137 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::ensightOutputSurface + +Description + A variant of ensightFaces that holds references to contiguous + points/faces with its own encapsulated write methods. + The surface is assumed to have been merged prior, thus the output is + serial-only. + +Note + The primary use is for the Foam::surfaceWriters::ensightWriter + but can be used independently as well. + +SourceFiles + ensightOutputSurface.C + ensightOutputSurfaceTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef ensightOutputSurface_H +#define ensightOutputSurface_H + +#include "ensightFaces.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class ensightOutputSurface Declaration +\*---------------------------------------------------------------------------*/ + +class ensightOutputSurface +: + public ensightFaces +{ + // Private Data + + //- The referenced pointField + const pointField& points_; + + //- The referenced faces + const faceList& faces_; + + + // Private Member Functions + + //- No copy construct + ensightOutputSurface(const ensightOutputSurface&) = delete; + + //- No copy assignment + void operator=(const ensightOutputSurface&) = delete; + + +public: + + // Constructors + + //- Construct from points and faces. + //- Part receives the specified name (default: "surface"). + ensightOutputSurface + ( + const pointField& points, + const faceList& faces, + const string& description = "surface" + ); + + + //- Destructor + virtual ~ensightOutputSurface() = default; + + + // Member Functions + + //- Write processor-local geometry (serial-only) + void write(ensightGeoFile& os) const; + + //- Write a field of face or point values (serial-only) + template<class Type> + void writeData + ( + ensightFile& os, + const Field<Type>& fld, + const bool isPointData = false + ) const; + + //- Write a field of face values (serial-only) + template<class Type> + void writeFaceData(ensightFile& os, const Field<Type>& fld) const; + + //- Write a field of point values (serial-only) + template<class Type> + void writePointData(ensightFile& os, const Field<Type>& fld) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "ensightOutputSurfaceTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/readFields.C b/src/fileFormats/ensight/part/surface/ensightOutputSurfaceTemplates.C similarity index 54% rename from applications/utilities/postProcessing/dataConversion/foamToEnsightParts/readFields.C rename to src/fileFormats/ensight/part/surface/ensightOutputSurfaceTemplates.C index 10cbaa2c950..0d2296f1172 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsightParts/readFields.C +++ b/src/fileFormats/ensight/part/surface/ensightOutputSurfaceTemplates.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -25,56 +25,72 @@ License \*---------------------------------------------------------------------------*/ -#include "readFields.H" -#include "volFields.H" +#include "ensightOutputSurface.H" +#include "ensightOutput.H" -// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -Foam::label Foam::checkData +template<class Type> +void Foam::ensightOutputSurface::writeData ( - const fvMesh& mesh, - const instantList& timeDirs, - wordList& objectNames -) + ensightFile& os, + const Field<Type>& fld, + const bool isPointData +) const { - // Assume prune_0() was used prior to calling this + if (isPointData) + { + this->writePointData(os, fld); + } + else + { + this->writeFaceData(os, fld); + } +} + + +template<class Type> +void Foam::ensightOutputSurface::writeFaceData +( + ensightFile& os, + const Field<Type>& fld +) const +{ + ensightOutput::writeField + ( + os, + fld, + *this, + false /* serial only! */ + ); +} - wordHashSet goodFields; - for (const word& fieldName : objectNames) +template<class Type> +void Foam::ensightOutputSurface::writePointData +( + ensightFile& os, + const Field<Type>& fld +) const +{ + const ensightOutputSurface& part = *this; + + // No geometry or field + if (part.empty() || fld.empty()) { - bool good = false; - - for (const instant& inst : timeDirs) - { - good = - IOobject - ( - fieldName, - inst.name(), - mesh, - IOobject::NO_READ, - IOobject::NO_WRITE, - false // no register - ).typeHeaderOk<volScalarField>(false, false); - - if (!good) - { - break; - } - } - - reduce(good, andOp<bool>()); - - if (good) - { - goodFields.insert(fieldName); - } + return; } - objectNames = goodFields.sortedToc(); - return objectNames.size(); + os.beginPart(part.index()); + + ensightOutput::Detail::writeFieldComponents + ( + os, + ensightFile::coordinates, + fld, + false /* serial only! */ + ); } diff --git a/src/functionObjects/utilities/ensightWrite/ensightWrite.C b/src/functionObjects/utilities/ensightWrite/ensightWrite.C index e2ca33cf1b5..06bcdacad4c 100644 --- a/src/functionObjects/utilities/ensightWrite/ensightWrite.C +++ b/src/functionObjects/utilities/ensightWrite/ensightWrite.C @@ -77,7 +77,8 @@ Foam::functionObjects::ensightWrite::ensightWrite ) : fvMeshFunctionObject(name, runTime, dict), - writeOpts_ + writeOpts_(), + caseOpts_ ( IOstreamOption::formatNames.lookupOrDefault ( @@ -87,7 +88,6 @@ Foam::functionObjects::ensightWrite::ensightWrite true // Failsafe behaviour ) ), - caseOpts_(writeOpts_.format()), outputDir_(), consecutive_(false), meshState_(polyMesh::TOPO_CHANGE), diff --git a/src/functionObjects/utilities/ensightWrite/ensightWriteTemplates.C b/src/functionObjects/utilities/ensightWrite/ensightWriteTemplates.C index 785aca83107..8156cd0acbd 100644 --- a/src/functionObjects/utilities/ensightWrite/ensightWriteTemplates.C +++ b/src/functionObjects/utilities/ensightWrite/ensightWriteTemplates.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2019 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -58,9 +58,9 @@ Foam::label Foam::functionObjects::ensightWrite::writeVolFields ensightOutput::writeVolField<Type> ( + os.ref(), field, ensMesh(), - os.ref(), caseOpts_.nodeValues() ); diff --git a/src/surfMesh/writers/ensight/ensightSurfaceWriter.C b/src/surfMesh/writers/ensight/ensightSurfaceWriter.C index 615983b1550..19d2aae5c0d 100644 --- a/src/surfMesh/writers/ensight/ensightSurfaceWriter.C +++ b/src/surfMesh/writers/ensight/ensightSurfaceWriter.C @@ -31,8 +31,8 @@ License #include "Fstream.H" #include "OSspecific.H" #include "ensightCase.H" -#include "ensightPartFaces.H" #include "ensightOutput.H" +#include "ensightOutputSurface.H" #include "ensightPTraits.H" #include "surfaceWriterMethods.H" #include "addToRunTimeSelectionTable.H" diff --git a/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C b/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C index a92350dffb3..4dc8fdeeda3 100644 --- a/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C +++ b/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2014 OpenFOAM Foundation - Copyright (C) 2015-2019 OpenCFD Ltd. + Copyright (C) 2015-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -405,29 +405,28 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated const fileName meshFile(baseDir/geometryName); - // Write geometry - ensightPartFaces ensPart + // Ensight Geometry + ensightOutputSurface part ( - 0, - meshFile.name(), surf.points(), surf.faces(), - true // contiguous points + meshFile.name() ); + if (!exists(meshFile)) { if (verbose_) { Info<< "Writing mesh file to " << meshFile.name() << endl; } - // Use two-argument form for path-name to avoid validating base-dir + // Two-argument form for path-name to avoid validating base-dir ensightGeoFile osGeom ( meshFile.path(), meshFile.name(), writeFormat_ ); - osGeom << ensPart; + part.write(osGeom); // serial } // Write field @@ -443,31 +442,11 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated Info<< "Writing field file to " << osField.name() << endl; } - // Write field + // Write field (serial only) osField.writeKeyword(ensightPTraits<Type>::typeName); + part.writeData(osField, tfield(), this->isPointData()); - if (this->isPointData()) - { - ensightOutput::Serial::writePointField - ( - tfield(), - ensPart, - osField - // serial - ); - } - else - { - ensightOutput::Detail::writeFaceField - ( - tfield(), - ensPart, - osField, - false // serial - ); - } - - // Place a timestamp in the directory for future reference + // Timestamp in the directory for future reference { OFstream timeStamp(dataDir/"time"); timeStamp diff --git a/src/surfMesh/writers/ensight/ensightSurfaceWriterUncollated.C b/src/surfMesh/writers/ensight/ensightSurfaceWriterUncollated.C index e5c60b99947..6a129ca0230 100644 --- a/src/surfMesh/writers/ensight/ensightSurfaceWriterUncollated.C +++ b/src/surfMesh/writers/ensight/ensightSurfaceWriterUncollated.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2014 OpenFOAM Foundation - Copyright (C) 2015-2019 OpenCFD Ltd. + Copyright (C) 2015-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -87,15 +87,13 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated() printTimeset(osCase, 1, 0.0); - ensightPartFaces ensPart + ensightOutputSurface part ( - 0, - osGeom.name().name(), surf.points(), surf.faces(), - true // contiguous points + osGeom.name().name() ); - osGeom << ensPart; + part.write(osGeom); // serial } wroteGeom_ = true; @@ -173,6 +171,7 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated osCase.setf(ios_base::scientific, ios_base::floatfield); osCase.precision(5); + // Two-argument form for path-name to avoid validating base-dir ensightGeoFile osGeom ( baseDir, @@ -212,39 +211,18 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated osCase << "# end" << nl; - ensightPartFaces ensPart + // Ensight Geometry + ensightOutputSurface part ( - 0, - osGeom.name().name(), surf.points(), surf.faces(), - true // contiguous points + osGeom.name().name() ); - osGeom << ensPart; + part.write(osGeom); // serial - // Write field + // Write field (serial) osField.writeKeyword(ensightPTraits<Type>::typeName); - - if (this->isPointData()) - { - ensightOutput::Serial::writePointField - ( - tfield(), - ensPart, - osField - // serial - ); - } - else - { - ensightOutput::Detail::writeFaceField - ( - tfield(), - ensPart, - osField, - false // serial - ); - } + part.writeData(osField, tfield(), this->isPointData()); } wroteGeom_ = true; -- GitLab