From 7fc943c178a36fcebdff05479d420239c32271c2 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Tue, 12 Oct 2021 08:47:18 +0200 Subject: [PATCH] ENH: improvements for makeFaMesh, checkFaMesh - added -dry-run, -write-vtk options. Additional mesh information after creation. - add parallel reductions and more information for checkFaMesh ENH: minor cleanup of faPatch internals - align pointLabels and pointEdges creation more closely with coding patterns used in PrimitivePatch - use fileHandler when loading "S0" field. --- .../finiteArea/checkFaMesh/Make/options | 8 +- .../finiteArea/checkFaMesh/checkFaMesh.C | 60 ++++---- .../finiteArea/checkFaMesh/faMeshWriteVTK.H | 47 ++++++ .../finiteArea/checkFaMesh/printMeshSummary.H | 134 ++++++++++++++++++ .../finiteArea/makeFaMesh/Make/options | 2 + .../finiteArea/makeFaMesh/decomposeFaFields.H | 49 +++++-- .../makeFaMesh/faMeshWriteEdgesOBJ.H | 11 +- .../finiteArea/makeFaMesh/faMeshWriteVTK.H | 47 ++++++ .../finiteArea/makeFaMesh/makeFaMesh.C | 53 ++++--- .../finiteArea/makeFaMesh/printMeshSummary.H | 99 +++++++++++++ .../faMesh/faBoundaryMesh/faBoundaryMesh.C | 9 +- src/finiteArea/faMesh/faMesh.C | 4 +- .../constraint/cyclic/cyclicFaPatch.C | 37 +++-- .../constraint/processor/processorFaPatch.C | 7 +- .../constraint/processor/processorFaPatch.H | 19 +-- .../faMesh/faPatches/faPatch/faPatch.C | 132 +++++++++-------- .../faMesh/faPatches/faPatch/faPatch.H | 15 +- 17 files changed, 561 insertions(+), 172 deletions(-) create mode 100644 applications/utilities/finiteArea/checkFaMesh/faMeshWriteVTK.H create mode 100644 applications/utilities/finiteArea/checkFaMesh/printMeshSummary.H create mode 100644 applications/utilities/finiteArea/makeFaMesh/faMeshWriteVTK.H create mode 100644 applications/utilities/finiteArea/makeFaMesh/printMeshSummary.H diff --git a/applications/utilities/finiteArea/checkFaMesh/Make/options b/applications/utilities/finiteArea/checkFaMesh/Make/options index b69f32d758c..2a0d2e96cef 100644 --- a/applications/utilities/finiteArea/checkFaMesh/Make/options +++ b/applications/utilities/finiteArea/checkFaMesh/Make/options @@ -1,9 +1,11 @@ EXE_INC = \ -I$(LIB_SRC)/finiteArea/lnInclude \ - -I$(LIB_SRC)/finiteVolume/lnInclude \ - -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/fileFormats/lnInclude \ + -I$(LIB_SRC)/surfMesh/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude EXE_LIBS = \ -lfiniteArea \ - -lfiniteVolume \ + -lfileFormats \ + -lsurfMesh \ -lmeshTools diff --git a/applications/utilities/finiteArea/checkFaMesh/checkFaMesh.C b/applications/utilities/finiteArea/checkFaMesh/checkFaMesh.C index d83aaeb7f2e..e15b830083c 100644 --- a/applications/utilities/finiteArea/checkFaMesh/checkFaMesh.C +++ b/applications/utilities/finiteArea/checkFaMesh/checkFaMesh.C @@ -6,6 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2016-2017 Wikki Ltd + Copyright (C) 2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -29,14 +30,22 @@ Application Description Check a finiteArea mesh -Author +Original Authors Zeljko Tukovic, FAMENA Hrvoje Jasak, Wikki Ltd. \*---------------------------------------------------------------------------*/ -#include "fvCFD.H" -#include "faCFD.H" +#include "Time.H" +#include "argList.H" +#include "faMesh.H" +#include "polyMesh.H" +#include "areaFaMesh.H" +#include "edgeFaMesh.H" +#include "areaFields.H" +#include "edgeFields.H" +#include "processorFaPatch.H" +#include "foamVtkUIndPatchWriter.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -51,37 +60,32 @@ int main(int argc, char *argv[]) "Check a finiteArea mesh" ); - #include "addRegionOption.H" + argList::addBoolOption + ( + "write-vtk", + "Write mesh as a vtp (vtk) file for display or debugging" + ); + #include "addRegionOption.H" #include "setRootCase.H" #include "createTime.H" - #include "createNamedMesh.H" - #include "createFaMesh.H" + #include "createNamedPolyMesh.H" + + + // Create + faMesh aMesh(mesh); Info<< "Time = " << runTime.timeName() << nl << endl; - // General mesh statistics - Info<< "Number of points: " << aMesh.nPoints() << nl - << "Number of internal edges: " << aMesh.nInternalEdges() << nl - << "Number of edges: " << aMesh.nEdges() << nl - << "Number of faces: " << aMesh.nFaces() << nl - << endl; - - // Check geometry - Info<< "Face area: min = " << min(aMesh.S().field()) - << " max = " << max(aMesh.S().field()) << nl - << "Internal edge length: min = " - << min(aMesh.magLe().internalField()) << nl - << " max = " << max(aMesh.magLe().internalField()) << nl - << "Edge length: min = " - << min(aMesh.magLe()).value() << nl - << " max = " << max(aMesh.magLe()).value() << nl - << "Face area normals: min = " << min(aMesh.faceAreaNormals().field()) - << " max = " << max(aMesh.faceAreaNormals().field()) << nl - << endl; - - - Info << "\nEnd" << endl; + #include "printMeshSummary.H" + + if (args.found("write-vtk")) + { + #include "faMeshWriteVTK.H" + } + + Info<< "\nEnd\n" << endl; + return 0; } diff --git a/applications/utilities/finiteArea/checkFaMesh/faMeshWriteVTK.H b/applications/utilities/finiteArea/checkFaMesh/faMeshWriteVTK.H new file mode 100644 index 00000000000..1df8b4d3125 --- /dev/null +++ b/applications/utilities/finiteArea/checkFaMesh/faMeshWriteVTK.H @@ -0,0 +1,47 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM, distributed under GPL-3.0-or-later. + +Description + VTK output of faMesh with some geometric or debug fields + +\*---------------------------------------------------------------------------*/ + +{ + // finiteArea + vtk::uindirectPatchWriter writer + ( + aMesh.patch(), + // vtk::formatType::INLINE_ASCII, + fileName + ( + aMesh.mesh().time().globalPath() / "finiteArea" + ) + ); + + writer.writeGeometry(); + + // CellData + writer.beginCellData(3); + writer.writeProcIDs(); + writer.write("area", aMesh.S().field()); + writer.write("normal", aMesh.faceAreaNormals()); + + // PointData + writer.beginPointData(1); + writer.write("normal", aMesh.pointAreaNormals()); + + Info<< nl + << "Wrote faMesh in vtk format: " << writer.output().name() << nl; +} + + +// ************************************************************************* // diff --git a/applications/utilities/finiteArea/checkFaMesh/printMeshSummary.H b/applications/utilities/finiteArea/checkFaMesh/printMeshSummary.H new file mode 100644 index 00000000000..256d2b1371f --- /dev/null +++ b/applications/utilities/finiteArea/checkFaMesh/printMeshSummary.H @@ -0,0 +1,134 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM, distributed under GPL-3.0-or-later. + +Description + Summary of faMesh information + +\*---------------------------------------------------------------------------*/ + +{ + const faBoundaryMesh& patches = aMesh.boundary(); + const label nNonProcessor = patches.nNonProcessor(); + const label nPatches = patches.size(); + + Info<< "----------------" << nl + << "Mesh Information" << nl + << "----------------" << nl + << " " << "boundingBox: " << boundBox(aMesh.points()) << nl; + + Info<< " Number of points: " + << returnReduce(aMesh.nPoints(), sumOp<label>()) << nl + << " Number of faces: " + << returnReduce(aMesh.nFaces(), sumOp<label>()) << nl; + + Info<< " Number of edges: " + << returnReduce(aMesh.nEdges(), sumOp<label>()) << nl + << " Number of internal edges: " + << returnReduce(aMesh.nInternalEdges(), sumOp<label>()) << nl; + + + label nProcEdges = 0; + + if (Pstream::parRun()) + { + for (const faPatch& fap : patches) + { + const auto* cpp = isA<processorFaPatch>(fap); + + if (cpp) + { + nProcEdges += fap.nEdges(); + } + } + } + + const label nBoundEdges = aMesh.nBoundaryEdges() - nProcEdges; + + Info<< " Number of boundary edges: " + << returnReduce(nBoundEdges - nProcEdges, sumOp<label>()) << nl; + + if (Pstream::parRun()) + { + Info<< " Number of processor edges: " + << returnReduce(nProcEdges, sumOp<label>()) << nl; + } + + + Info<< "----------------" << nl + << "Patches" << nl + << "----------------" << nl; + + for (label patchi = 0; patchi < nNonProcessor; ++patchi) + { + const faPatch& p = patches[patchi]; + + Info<< " " << "patch " << p.index() + << " (size: " << returnReduce(p.size(), sumOp<label>()) + << ") name: " << p.name() + << nl; + } + + + // Geometry information + Info<< nl; + { + scalarMinMax limit(gMinMax(aMesh.S().field())); + Info<< "Face area:" << nl + << " min = " << limit.min() << " max = " << limit.max() << nl; + } + + { + scalarMinMax limit(minMax(aMesh.magLe().primitiveField())); + + // Include processor boundaries into 'internal' edges + if (Pstream::parRun()) + { + for (label patchi = nNonProcessor; patchi < nPatches; ++patchi) + { + limit.add(minMax(aMesh.magLe().boundaryField()[patchi])); + } + + reduce(limit, minMaxOp<scalar>()); + } + + Info<< "Edge length (internal):" << nl + << " min = " << limit.min() << " max = " << limit.max() << nl; + + + // Include (non-processor) boundaries + for (label patchi = 0; patchi < nNonProcessor; ++patchi) + { + limit.add(minMax(aMesh.magLe().boundaryField()[patchi])); + } + + if (Pstream::parRun()) + { + reduce(limit, minMaxOp<scalar>()); + } + + Info<< "Edge length:" << nl + << " min = " << limit.min() << " max = " << limit.max() << nl; + } + + // Not particularly meaningful + #if 0 + { + MinMax<vector> limit(gMinMax(aMesh.faceAreaNormals().field())); + + Info<< "Face area normals:" << nl + << " min = " << limit.min() << " max = " << limit.max() << nl; + } + #endif +} + + +// ************************************************************************* // diff --git a/applications/utilities/finiteArea/makeFaMesh/Make/options b/applications/utilities/finiteArea/makeFaMesh/Make/options index 7a28b2c4b67..3f949d53443 100644 --- a/applications/utilities/finiteArea/makeFaMesh/Make/options +++ b/applications/utilities/finiteArea/makeFaMesh/Make/options @@ -1,6 +1,7 @@ EXE_INC = \ -I$(LIB_SRC)/finiteArea/lnInclude \ -I$(LIB_SRC)/fileFormats/lnInclude \ + -I$(LIB_SRC)/surfMesh/lnInclude \ -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/parallel/decompose/faDecompose/lnInclude \ -I$(LIB_SRC)/parallel/reconstruct/faReconstruct/lnInclude @@ -8,6 +9,7 @@ EXE_INC = \ EXE_LIBS = \ -lfiniteArea \ -lfileFormats \ + -lsurfMesh \ -lmeshTools \ -lfaDecompose \ -lfaReconstruct diff --git a/applications/utilities/finiteArea/makeFaMesh/decomposeFaFields.H b/applications/utilities/finiteArea/makeFaMesh/decomposeFaFields.H index 5c38c9b4f13..3b91b260ca3 100644 --- a/applications/utilities/finiteArea/makeFaMesh/decomposeFaFields.H +++ b/applications/utilities/finiteArea/makeFaMesh/decomposeFaFields.H @@ -17,9 +17,11 @@ Description if (Pstream::parRun()) { - faMeshReconstructor reconstructor(areaMesh); + faMeshReconstructor reconstructor(aMesh); reconstructor.writeAddressing(); + Info<< "Wrote proc-addressing" << nl << endl; + // Handle area fields // ------------------ @@ -72,22 +74,53 @@ if (Pstream::parRun()) if (nAreaFields) { - Info<< "Decomposing " << nAreaFields << " area fields" << nl << endl; + Info<< "Decomposing " << nAreaFields << " area fields" << nl; faFieldDecomposer fieldDecomposer ( fullMesh, - areaMesh, + aMesh, reconstructor.edgeProcAddressing(), reconstructor.faceProcAddressing(), reconstructor.boundaryProcAddressing() ); - fieldDecomposer.decomposeFields(areaScalarFields); - fieldDecomposer.decomposeFields(areaVectorFields); - fieldDecomposer.decomposeFields(areaSphTensorFields); - fieldDecomposer.decomposeFields(areaSymmTensorFields); - fieldDecomposer.decomposeFields(areaTensorFields); + if (areaScalarFields.size()) + { + Info<< " scalars: " + << flatOutput(PtrListOps::names(areaScalarFields)) << nl; + fieldDecomposer.decomposeFields(areaScalarFields); + } + + if (areaVectorFields.size()) + { + Info<< " vectors: " + << flatOutput(PtrListOps::names(areaVectorFields)) << nl; + fieldDecomposer.decomposeFields(areaVectorFields); + } + + if (areaSphTensorFields.size()) + { + Info<< " sphTensors: " + << flatOutput(PtrListOps::names(areaSphTensorFields)) << nl; + fieldDecomposer.decomposeFields(areaSphTensorFields); + } + + if (areaSymmTensorFields.size()) + { + Info<< " symmTensors: " + << flatOutput(PtrListOps::names(areaSymmTensorFields)) << nl; + fieldDecomposer.decomposeFields(areaSymmTensorFields); + } + + if (areaTensorFields.size()) + { + Info<< " tensors: " + << flatOutput(PtrListOps::names(areaTensorFields)) << nl; + fieldDecomposer.decomposeFields(areaTensorFields); + } + + Info<< endl; } } diff --git a/applications/utilities/finiteArea/makeFaMesh/faMeshWriteEdgesOBJ.H b/applications/utilities/finiteArea/makeFaMesh/faMeshWriteEdgesOBJ.H index a50d18df3c3..a5f4192d392 100644 --- a/applications/utilities/finiteArea/makeFaMesh/faMeshWriteEdgesOBJ.H +++ b/applications/utilities/finiteArea/makeFaMesh/faMeshWriteEdgesOBJ.H @@ -16,15 +16,18 @@ Description \*---------------------------------------------------------------------------*/ { - Info<< "Writing edges in obj format" << endl; + Info<< nl + << "Writing edges in obj format" << endl; - word outputName("faMesh-edges.obj"); + word outputName("finiteArea-edges.obj"); if (Pstream::parRun()) { outputName = word ( - "faMesh-edges-" + Foam::name(Pstream::myProcNo()) + ".obj" + "finiteArea-edges-proc" + + Foam::name(Pstream::myProcNo()) + + ".obj" ); } @@ -36,7 +39,7 @@ Description false ); - os.write(areaMesh.patch().edges(), areaMesh.patch().localPoints()); + os.write(aMesh.patch().edges(), aMesh.patch().localPoints()); } diff --git a/applications/utilities/finiteArea/makeFaMesh/faMeshWriteVTK.H b/applications/utilities/finiteArea/makeFaMesh/faMeshWriteVTK.H new file mode 100644 index 00000000000..1df8b4d3125 --- /dev/null +++ b/applications/utilities/finiteArea/makeFaMesh/faMeshWriteVTK.H @@ -0,0 +1,47 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM, distributed under GPL-3.0-or-later. + +Description + VTK output of faMesh with some geometric or debug fields + +\*---------------------------------------------------------------------------*/ + +{ + // finiteArea + vtk::uindirectPatchWriter writer + ( + aMesh.patch(), + // vtk::formatType::INLINE_ASCII, + fileName + ( + aMesh.mesh().time().globalPath() / "finiteArea" + ) + ); + + writer.writeGeometry(); + + // CellData + writer.beginCellData(3); + writer.writeProcIDs(); + writer.write("area", aMesh.S().field()); + writer.write("normal", aMesh.faceAreaNormals()); + + // PointData + writer.beginPointData(1); + writer.write("normal", aMesh.pointAreaNormals()); + + Info<< nl + << "Wrote faMesh in vtk format: " << writer.output().name() << nl; +} + + +// ************************************************************************* // diff --git a/applications/utilities/finiteArea/makeFaMesh/makeFaMesh.C b/applications/utilities/finiteArea/makeFaMesh/makeFaMesh.C index e80ed303d9f..f93685ea48d 100644 --- a/applications/utilities/finiteArea/makeFaMesh/makeFaMesh.C +++ b/applications/utilities/finiteArea/makeFaMesh/makeFaMesh.C @@ -32,7 +32,7 @@ Description When called in parallel, it will also try to act like decomposePar, create procAddressing and decompose serial finite-area fields. -Author +Original Authors Zeljko Tukovic, FAMENA Hrvoje Jasak, Wikki Ltd. @@ -48,6 +48,8 @@ Author #include "areaFields.H" #include "faFieldDecomposer.H" #include "faMeshReconstructor.H" +#include "PtrListOps.H" +#include "foamVtkUIndPatchWriter.H" #include "OBJstream.H" using namespace Foam; @@ -69,11 +71,21 @@ int main(int argc, char *argv[]) ); argList::addOption("dict", "file", "Alternative faMeshDefinition"); + argList::addBoolOption + ( + "dry-run", + "Create but do not write" + ); + argList::addBoolOption + ( + "write-vtk", + "Write mesh as a vtp (vtk) file for display or debugging" + ); argList::addBoolOption ( "write-edges-obj", - "Write mesh edges as obj files and exit", - false // could make an advanced option + "Write mesh edges as obj files (one per processor)", + true // advanced option (debugging only) ); #include "addRegionOption.H" @@ -81,6 +93,8 @@ int main(int argc, char *argv[]) #include "createTime.H" #include "createNamedPolyMesh.H" + const bool dryrun = args.found("dry-run"); + // Reading faMeshDefinition dictionary #include "findMeshDefinitionDict.H" @@ -91,33 +105,40 @@ int main(int argc, char *argv[]) meshDefDict.add("emptyPatch", patchName, true); } + // Create - faMesh areaMesh(mesh, meshDefDict); + faMesh aMesh(mesh, meshDefDict); - bool quickExit = false; + // Mesh information + #include "printMeshSummary.H" if (args.found("write-edges-obj")) { - quickExit = true; #include "faMeshWriteEdgesOBJ.H" } - if (quickExit) + if (args.found("write-vtk")) { - Info<< "\nEnd\n" << endl; - return 0; + #include "faMeshWriteVTK.H" } - // Set the precision of the points data to 10 - IOstream::defaultPrecision(10); + if (dryrun) + { + Info<< "\ndry-run: not writing mesh or decomposing fields\n" << nl; + } + else + { + // Set the precision of the points data to 10 + IOstream::defaultPrecision(10); - Info<< nl << "Write finite area mesh." << nl; - areaMesh.write(); - Info<< endl; + Info<< nl << "Write finite area mesh." << nl; + aMesh.write(); - #include "decomposeFaFields.H" + Info<< endl; + #include "decomposeFaFields.H" + } - Info << "\nEnd\n" << endl; + Info<< "\nEnd\n" << endl; return 0; } diff --git a/applications/utilities/finiteArea/makeFaMesh/printMeshSummary.H b/applications/utilities/finiteArea/makeFaMesh/printMeshSummary.H new file mode 100644 index 00000000000..5dd75c8804d --- /dev/null +++ b/applications/utilities/finiteArea/makeFaMesh/printMeshSummary.H @@ -0,0 +1,99 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM, distributed under GPL-3.0-or-later. + +Description + Summary of faMesh information + +\*---------------------------------------------------------------------------*/ + +{ + const faBoundaryMesh& patches = aMesh.boundary(); + const label nNonProcessor = patches.nNonProcessor(); + const label nPatches = patches.size(); + + Info<< "----------------" << nl + << "Mesh Information" << nl + << "----------------" << nl + << " " << "boundingBox: " << boundBox(aMesh.points()) << nl + << " " << "nFaces: " << returnReduce(aMesh.nFaces(), sumOp<label>()) + << nl; + + + Info<< "----------------" << nl + << "Patches" << nl + << "----------------" << nl; + + for (label patchi = 0; patchi < nNonProcessor; ++patchi) + { + const faPatch& p = patches[patchi]; + + Info<< " " << "patch " << p.index() + << " (size: " << returnReduce(p.size(), sumOp<label>()) + << ") name: " << p.name() + << nl; + } + + // Geometry information + Info<< nl; + { + scalarMinMax limit(gMinMax(aMesh.S().field())); + Info<< "Face area:" << nl + << " min = " << limit.min() << " max = " << limit.max() << nl; + } + + { + scalarMinMax limit(minMax(aMesh.magLe().primitiveField())); + + // Include processor boundaries into 'internal' edges + if (Pstream::parRun()) + { + for (label patchi = nNonProcessor; patchi < nPatches; ++patchi) + { + limit.add(minMax(aMesh.magLe().boundaryField()[patchi])); + } + + reduce(limit, minMaxOp<scalar>()); + } + + Info<< "Edge length (internal):" << nl + << " min = " << limit.min() << " max = " << limit.max() << nl; + + + // Include (non-processor) boundaries + for (label patchi = 0; patchi < nNonProcessor; ++patchi) + { + limit.add(minMax(aMesh.magLe().boundaryField()[patchi])); + } + + if (Pstream::parRun()) + { + reduce(limit, minMaxOp<scalar>()); + } + + Info<< "Edge length:" << nl + << " min = " << limit.min() + << " max = " << limit.max() << nl; + } + + // Not particularly meaningful + #if 0 + { + MinMax<vector> limit(gMinMax(aMesh.faceAreaNormals().field())); + + Info<< "Face area normals:" << nl + << " min = " << limit.min() << " max = " << limit.max() << nl; + } + #endif +} + + +// ************************************************************************* // diff --git a/src/finiteArea/faMesh/faBoundaryMesh/faBoundaryMesh.C b/src/finiteArea/faMesh/faBoundaryMesh/faBoundaryMesh.C index c40ff59d4e6..cd4eee3537a 100644 --- a/src/finiteArea/faMesh/faBoundaryMesh/faBoundaryMesh.C +++ b/src/finiteArea/faMesh/faBoundaryMesh/faBoundaryMesh.C @@ -75,8 +75,15 @@ Foam::faBoundaryMesh::faBoundaryMesh regIOobject(io), mesh_(mesh) { - if (readOpt() == IOobject::MUST_READ) + if + ( + readOpt() == IOobject::MUST_READ + || readOpt() == IOobject::MUST_READ_IF_MODIFIED + ) { + // Warn for MUST_READ_IF_MODIFIED + warnNoRereading<faBoundaryMesh>(); + faPatchList& patches = *this; // Read faPatch list diff --git a/src/finiteArea/faMesh/faMesh.C b/src/finiteArea/faMesh/faMesh.C index fea1ea36e86..a98c49060d4 100644 --- a/src/finiteArea/faMesh/faMesh.C +++ b/src/finiteArea/faMesh/faMesh.C @@ -343,7 +343,7 @@ Foam::faMesh::faMesh(const polyMesh& pMesh) // Calculate the geometry for the patches (transformation tensors etc.) boundary_.calcGeometry(); - if (isFile(pMesh.time().timePath()/mesh().dbDir()/"S0")) + if (fileHandler().isFile(pMesh.time().timePath()/"S0")) { S0Ptr_ = new DimensionedField<scalar, areaMesh> ( @@ -508,7 +508,7 @@ Foam::faMesh::faMesh // Calculate the geometry for the patches (transformation tensors etc.) boundary_.calcGeometry(); - if (isFile(mesh().time().timePath()/"S0")) + if (fileHandler().isFile(pMesh.time().timePath()/"S0")) { S0Ptr_ = new DimensionedField<scalar, areaMesh> ( diff --git a/src/finiteArea/faMesh/faPatches/constraint/cyclic/cyclicFaPatch.C b/src/finiteArea/faMesh/faPatches/constraint/cyclic/cyclicFaPatch.C index 0bee133c300..32f3e4ca5ce 100644 --- a/src/finiteArea/faMesh/faPatches/constraint/cyclic/cyclicFaPatch.C +++ b/src/finiteArea/faMesh/faPatches/constraint/cyclic/cyclicFaPatch.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2016-2017 Wikki Ltd - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -47,34 +47,33 @@ const Foam::scalar Foam::cyclicFaPatch::matchTol_ = 1e-3; void Foam::cyclicFaPatch::calcTransforms() { + const label sizeby2 = this->size()/2; if (size() > 0) { - // const label sizeby2 = this->size()/2; - pointField half0Ctrs(size()/2); - pointField half1Ctrs(size()/2); - for (label i=0; i<size()/2; ++i) + pointField half0Ctrs(sizeby2); + pointField half1Ctrs(sizeby2); + for (label edgei=0; edgei < sizeby2; ++edgei) { - half0Ctrs[i] = this->edgeCentres()[i]; - half1Ctrs[i] = this->edgeCentres()[i+size()/2]; + half0Ctrs[edgei] = this->edgeCentres()[edgei]; + half1Ctrs[edgei] = this->edgeCentres()[edgei + sizeby2]; } - vectorField half0Normals(size()/2); - vectorField half1Normals(size()/2); + vectorField half0Normals(sizeby2); + vectorField half1Normals(sizeby2); const vectorField eN(edgeNormals()*magEdgeLengths()); scalar maxMatchError = 0; label errorEdge = -1; - for (label edgei = 0; edgei < size()/2; ++edgei) + for (label edgei = 0; edgei < sizeby2; ++edgei) { half0Normals[edgei] = eN[edgei]; - label nbrEdgei = edgei + size()/2; - half1Normals[edgei] = eN[nbrEdgei]; + half1Normals[edgei] = eN[edgei + sizeby2]; scalar magLe = mag(half0Normals[edgei]); scalar nbrMagLe = mag(half1Normals[edgei]); - scalar avLe = (magLe + nbrMagLe)/2.0; + scalar avLe = 0.5*(magLe + nbrMagLe); if (magLe < ROOTVSMALL && nbrMagLe < ROOTVSMALL) { @@ -101,10 +100,10 @@ void Foam::cyclicFaPatch::calcTransforms() // Check for error in edge matching if (maxMatchError > matchTol_) { - label nbrEdgei = errorEdge + size()/2; + label nbrEdgei = errorEdge + sizeby2; scalar magLe = mag(half0Normals[errorEdge]); scalar nbrMagLe = mag(half1Normals[errorEdge]); - scalar avLe = (magLe + nbrMagLe)/2.0; + scalar avLe = 0.5*(magLe + nbrMagLe); FatalErrorInFunction << "edge " << errorEdge @@ -162,7 +161,7 @@ void Foam::cyclicFaPatch::makeWeights(scalarField& w) const for (label edgei = 0; edgei < sizeby2; ++edgei) { - scalar avL = (magL[edgei] + magL[edgei + sizeby2])/2.0; + scalar avL = 0.5*(magL[edgei] + magL[edgei + sizeby2]); if ( @@ -191,7 +190,7 @@ void Foam::cyclicFaPatch::makeWeights(scalarField& w) const // Check for error in matching if (maxMatchError > matchTol_) { - scalar avL = (magL[errorEdge] + magL[errorEdge + sizeby2])/2.0; + scalar avL = 0.5*(magL[errorEdge] + magL[errorEdge + sizeby2]); FatalErrorInFunction << "edge " << errorEdge << " and " << errorEdge + sizeby2 @@ -313,7 +312,7 @@ Foam::tmp<Foam::labelField> Foam::cyclicFaPatch::transfer const label sizeby2 = this->size()/2; - for (label edgei=0; edgei<sizeby2; ++edgei) + for (label edgei=0; edgei < sizeby2; ++edgei) { pnf[edgei] = interfaceData[edgei + sizeby2]; pnf[edgei + sizeby2] = interfaceData[edgei]; @@ -345,7 +344,7 @@ Foam::tmp<Foam::labelField> Foam::cyclicFaPatch::internalFieldTransfer const label sizeby2 = this->size()/2; - for (label edgei=0; edgei<sizeby2; ++edgei) + for (label edgei=0; edgei < sizeby2; ++edgei) { pnf[edgei] = iF[edgeCells[edgei + sizeby2]]; pnf[edgei + sizeby2] = iF[edgeCells[edgei]]; diff --git a/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.C b/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.C index d257e4a199c..4ac1c79f227 100644 --- a/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.C +++ b/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.C @@ -80,12 +80,7 @@ void Foam::processorFaPatch::makeNonGlobalPatchPoints() const || !boundaryMesh().mesh()().globalData().nGlobalPoints() ) { - nonGlobalPatchPointsPtr_ = new labelList(nPoints()); - labelList& ngpp = *nonGlobalPatchPointsPtr_; - forAll(ngpp, i) - { - ngpp[i] = i; - } + nonGlobalPatchPointsPtr_ = new labelList(identity(nPoints())); } else { diff --git a/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.H b/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.H index 5924eaae017..b21be3af932 100644 --- a/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.H +++ b/src/finiteArea/faMesh/faPatches/constraint/processor/processorFaPatch.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2016-2017 Wikki Ltd - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -177,19 +177,19 @@ public: // Member Functions //- Return interface size - virtual label interfaceSize() const + virtual label interfaceSize() const noexcept { return size(); } //- Return processor number - int myProcNo() const + int myProcNo() const noexcept { return myProcNo_; } //- Return neighbour processor number - int neighbProcNo() const + int neighbProcNo() const noexcept { return neighbProcNo_; } @@ -197,18 +197,11 @@ public: //- Return true if running parallel virtual bool coupled() const { - if (Pstream::parRun()) - { - return true; - } - else - { - return false; - } + return Pstream::parRun(); } //- Is this the master side? - virtual bool master() const + virtual bool master() const noexcept { return (myProcNo_ < neighbProcNo_); } diff --git a/src/finiteArea/faMesh/faPatches/faPatch/faPatch.C b/src/finiteArea/faMesh/faPatches/faPatch/faPatch.C index 81ddba7ee6d..f6e8b98aae9 100644 --- a/src/finiteArea/faMesh/faPatches/faPatch/faPatch.C +++ b/src/finiteArea/faMesh/faPatches/faPatch/faPatch.C @@ -210,96 +210,102 @@ const Foam::labelList& Foam::faPatch::pointLabels() const } -void Foam::faPatch::calcPointLabels() const +const Foam::labelListList& Foam::faPatch::pointEdges() const { - SLList<label> labels; + if (!pointEdgesPtr_) + { + calcPointEdges(); + } + + return *pointEdgesPtr_; +} + +void Foam::faPatch::calcPointLabels() const +{ const edgeList::subList edges = patchSlice(boundaryMesh().mesh().edges()); - forAll(edges, edgeI) - { - bool existStart = false; - bool existEnd = false; + // Walk boundary edges. + // The edge orientation corresponds to the face orientation + // (outwards normal). - forAllIters(labels, iter) - { - if (*iter == edges[edgeI].start()) - { - existStart = true; - } - - if (*iter == edges[edgeI].end()) - { - existEnd = true; - } - } + // Note: could combine this with calcPointEdges for more efficiency + + // Map<label> markedPoints(4*edges.size()); + labelHashSet markedPoints(4*edges.size()); + DynamicList<label> dynEdgePoints(2*edges.size()); - if (!existStart) + for (const edge& e : edges) + { + // if (markedPoints.insert(e.first(), markedPoints.size())) + if (markedPoints.insert(e.first())) { - labels.append(edges[edgeI].start()); + dynEdgePoints.append(e.first()); } - - if (!existEnd) + // if (markedPoints.insert(e.second(), markedPoints.size())) + if (markedPoints.insert(e.second())) { - labels.append(edges[edgeI].end()); + dynEdgePoints.append(e.second()); } } - pointLabelsPtr_ = new labelList(labels); + // Transfer to plain list (reuse storage) + pointLabelsPtr_ = new labelList(std::move(dynEdgePoints)); + /// const labelList& edgePoints = *pointLabelsPtr_; + /// + /// // Cannot use invertManyToMany - we have non-local edge numbering + /// + /// // Intermediate storage for pointEdges. + /// // Points on the boundary will normally connect 1 or 2 edges only. + /// List<DynamicList<label,2>> dynPointEdges(edgePoints.size()); + /// + /// forAll(edges, edgei) + /// { + /// const edge& e = edges[edgei]; + /// + /// dynPointEdges[markedPoints[e.first()]].append(edgei); + /// dynPointEdges[markedPoints[e.second()]].append(edgei); + /// } + /// + /// // Flatten to regular list + /// pointEdgesPtr_ = new labelListList(edgePoints.size()); + /// auto& pEdges = *pointEdgesPtr_; + /// + /// forAll(pEdges, pointi) + /// { + /// pEdges[pointi] = std::move(dynPointEdges[pointi]); + /// } } void Foam::faPatch::calcPointEdges() const { - const labelList& points = pointLabels(); + const edgeList::subList edges = patchSlice(boundaryMesh().mesh().edges()); - const edgeList::subList e = patchSlice(boundaryMesh().mesh().edges()); + const labelList& edgePoints = pointLabels(); - // set up storage for pointEdges - List<SLList<label>> pointEdgs(points.size()); + // Cannot use invertManyToMany - we have non-local edge numbering - forAll(e, edgeI) - { - const edge& curPoints = e[edgeI]; + // Intermediate storage for pointEdges. + // Points on the boundary will normally connect 1 or 2 edges only. + List<DynamicList<label,2>> dynPointEdges(edgePoints.size()); - forAll(curPoints, pointI) - { - const label localPointIndex = points.find(curPoints[pointI]); - - pointEdgs[localPointIndex].append(edgeI); - } - } - - // sort out the list - pointEdgesPtr_ = new labelListList(pointEdgs.size()); - labelListList& pEdges = *pointEdgesPtr_; - - forAll(pointEdgs, pointI) + forAll(edges, edgei) { - pEdges[pointI].setSize(pointEdgs[pointI].size()); + const edge& e = edges[edgei]; - label i = 0; - for - ( - SLList<label>::iterator curEdgesIter = pointEdgs[pointI].begin(); - curEdgesIter != pointEdgs[pointI].end(); - ++curEdgesIter, ++i - ) - { - pEdges[pointI][i] = curEdgesIter(); - } + dynPointEdges[edgePoints.find(e.first())].append(edgei); + dynPointEdges[edgePoints.find(e.second())].append(edgei); } -} + // Flatten to regular list + pointEdgesPtr_ = new labelListList(edgePoints.size()); + auto& pEdges = *pointEdgesPtr_; -const Foam::labelListList& Foam::faPatch::pointEdges() const -{ - if (!pointEdgesPtr_) + forAll(pEdges, pointi) { - calcPointEdges(); + pEdges[pointi] = std::move(dynPointEdges[pointi]); } - - return *pointEdgesPtr_; } @@ -383,7 +389,7 @@ const Foam::scalarField& Foam::faPatch::magEdgeLengths() const Foam::tmp<Foam::vectorField> Foam::faPatch::edgeNormals() const { - tmp<vectorField> tedgeNorm(edgeLengths()); + auto tedgeNorm = tmp<vectorField>::New(edgeLengths()); for (vector& n : tedgeNorm.ref()) { diff --git a/src/finiteArea/faMesh/faPatches/faPatch/faPatch.H b/src/finiteArea/faMesh/faPatches/faPatch/faPatch.H index e2529421185..71df3aa5004 100644 --- a/src/finiteArea/faMesh/faPatches/faPatch/faPatch.H +++ b/src/finiteArea/faMesh/faPatches/faPatch/faPatch.H @@ -80,17 +80,14 @@ class faPatch //- Reference to boundary mesh const faBoundaryMesh& boundaryMesh_; + //- Demand-driven: edge-face addressing + mutable labelList::subList* edgeFacesPtr_; - // Demand-driven private data + //- Demand-driven: local points labels + mutable labelList* pointLabelsPtr_; - //- Edge-face addressing - mutable labelList::subList* edgeFacesPtr_; - - //- Local points labels - mutable labelList* pointLabelsPtr_; - - //- Point-edge addressing - mutable labelListList* pointEdgesPtr_; + //- Demand-driven: point-edge addressing + mutable labelListList* pointEdgesPtr_; // Private Member Functions -- GitLab