From a7ef33da6b93708e2891d5ba674583ae59978530 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Fri, 23 Sep 2022 19:20:57 +0200 Subject: [PATCH] ENH: add finite-area support to setFields (#2591) - for example, defaultFieldValues ( areaScalarFieldValue h 0.00014 ); regions ( clipPlaneToFace { point (0 0 0); normal (1 0 0); fieldValues ( areaScalarFieldValue h 0.00015 ); } ); ENH: additional clipPlaneTo{Cell,Face,Point} topo sets - less cumbersome than defining a semi-infinite bounding box --- .../preProcessing/setFields/Make/options | 2 + .../preProcessing/setFields/setFields.C | 734 +++++++++++++----- src/meshTools/Make/files | 3 + .../clipPlaneToCell/clipPlaneToCell.C | 157 ++++ .../clipPlaneToCell/clipPlaneToCell.H | 172 ++++ .../clipPlaneToFace/clipPlaneToFace.C | 157 ++++ .../clipPlaneToFace/clipPlaneToFace.H | 172 ++++ .../clipPlaneToPoint/clipPlaneToPoint.C | 157 ++++ .../clipPlaneToPoint/clipPlaneToPoint.H | 172 ++++ .../finiteArea/liquidFilmFoam/cylinder/Allrun | 2 + .../liquidFilmFoam/cylinder/Allrun-parallel | 2 + .../cylinder/system/setFieldsDict | 37 + .../laminar/fluidisedBed/system/setFieldsDict | 1 + 13 files changed, 1571 insertions(+), 197 deletions(-) create mode 100644 src/meshTools/topoSet/cellSources/clipPlaneToCell/clipPlaneToCell.C create mode 100644 src/meshTools/topoSet/cellSources/clipPlaneToCell/clipPlaneToCell.H create mode 100644 src/meshTools/topoSet/faceSources/clipPlaneToFace/clipPlaneToFace.C create mode 100644 src/meshTools/topoSet/faceSources/clipPlaneToFace/clipPlaneToFace.H create mode 100644 src/meshTools/topoSet/pointSources/clipPlaneToPoint/clipPlaneToPoint.C create mode 100644 src/meshTools/topoSet/pointSources/clipPlaneToPoint/clipPlaneToPoint.H create mode 100644 tutorials/finiteArea/liquidFilmFoam/cylinder/system/setFieldsDict diff --git a/applications/utilities/preProcessing/setFields/Make/options b/applications/utilities/preProcessing/setFields/Make/options index 969020c4af..b5844533a1 100644 --- a/applications/utilities/preProcessing/setFields/Make/options +++ b/applications/utilities/preProcessing/setFields/Make/options @@ -1,8 +1,10 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/finiteArea/lnInclude \ -I$(LIB_SRC)/meshTools/lnInclude EXE_LIBS = \ -lfiniteVolume \ + -lfiniteArea \ -lmeshTools \ -lgenericPatchFields diff --git a/applications/utilities/preProcessing/setFields/setFields.C b/applications/utilities/preProcessing/setFields/setFields.C index 0af8c05ec0..a5c984cfad 100644 --- a/applications/utilities/preProcessing/setFields/setFields.C +++ b/applications/utilities/preProcessing/setFields/setFields.C @@ -6,6 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation + Copyright (C) 2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -37,214 +38,311 @@ Description #include "argList.H" #include "Time.H" #include "fvMesh.H" +#include "faMesh.H" #include "topoSetSource.H" #include "cellSet.H" #include "faceSet.H" #include "volFields.H" +#include "areaFields.H" using namespace Foam; +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//- Simple tuple of field type and name (read from stream) +class fieldDescription +{ + word type_; + word name_; + +public: + + const word& type() const noexcept { return type_; } + const word& name() const noexcept { return name_; } + + explicit fieldDescription(Istream& is) + { + is >> type_; + is >> name_; + + // Eg, read as "volScalarFieldValue", but change to "volScalarField" + if (type_.ends_with("Value")) + { + type_.erase(type_.size()-5); + } + } +}; + + +// Consume unused field information +template +bool consumeUnusedType(const fieldDescription& fieldDesc, Istream& is) +{ + typedef GeometricField fieldType1; + typedef GeometricField fieldType2; + //? typedef GeometricField fieldType3; + //? typedef GeometricField fieldType4; + + if + ( + fieldDesc.type() == fieldType1::typeName + || fieldDesc.type() == fieldType2::typeName + ) + { + (void) pTraits(is); + return true; + } + + return false; +} + + +// Consume unused field information +static bool consumeUnused(const fieldDescription& fieldDesc, Istream& is) +{ + return + ( + consumeUnusedType(fieldDesc, is) + || consumeUnusedType(fieldDesc, is) + || consumeUnusedType(fieldDesc, is) + || consumeUnusedType(fieldDesc, is) + || consumeUnusedType(fieldDesc, is) + ); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Setting volume fields template bool setCellFieldType ( - const word& fieldTypeDesc, + const fieldDescription& fieldDesc, const fvMesh& mesh, const labelList& selectedCells, - Istream& fieldValueStream + Istream& is ) { typedef GeometricField fieldType; - if (fieldTypeDesc != fieldType::typeName + "Value") + if (fieldDesc.type() != fieldType::typeName) { return false; } - word fieldName(fieldValueStream); + // Get value from stream + const Type fieldValue = pTraits(is); + // Check the current time directory IOobject fieldHeader ( - fieldName, - mesh.time().timeName(), - mesh, + fieldDesc.name(), + mesh.thisDb().time().timeName(), + mesh.thisDb(), IOobject::MUST_READ ); - // Check the "constant" directory - if (!fieldHeader.typeHeaderOk(true)) + bool found = fieldHeader.typeHeaderOk(true); + + if (!found) { + // Fallback to "constant" directory fieldHeader = IOobject ( - fieldName, - mesh.time().constant(), - mesh, + fieldDesc.name(), + mesh.thisDb().time().constant(), + mesh.thisDb(), IOobject::MUST_READ ); + found = fieldHeader.typeHeaderOk(true); } - // Check field exists - if (fieldHeader.typeHeaderOk(true)) + // Field exists + if (found) { - Info<< " Setting internal values of " + Info<< " - set internal values of " << fieldHeader.headerClassName() - << " " << fieldName << endl; + << ": " << fieldDesc.name() + << " = " << fieldValue << endl; fieldType field(fieldHeader, mesh, false); - const Type value = pTraits(fieldValueStream); - - if (selectedCells.size() == field.size()) + if (isNull(selectedCells) || selectedCells.size() == field.size()) { - field.primitiveFieldRef() = value; + field.primitiveFieldRef() = fieldValue; } else { - forAll(selectedCells, celli) + for (const label celli : selectedCells) { - field[selectedCells[celli]] = value; + field[celli] = fieldValue; } } - typename GeometricField:: - Boundary& fieldBf = field.boundaryFieldRef(); - - forAll(field.boundaryField(), patchi) + // Make boundary fields consistent - treat like zeroGradient + for (auto& pfld : field.boundaryFieldRef()) { - fieldBf[patchi] = fieldBf[patchi].patchInternalField(); + pfld = pfld.patchInternalField(); } if (!field.write()) { FatalErrorInFunction - << "Failed writing field " << fieldName << endl; + << "Failed writing field " << field.name() << endl; } } else { - WarningInFunction - << "Field " << fieldName << " not found" << endl; - - // Consume value - (void)pTraits(fieldValueStream); + Warning + << "Field " << fieldDesc.name() << " not found" << endl; } return true; } -class setCellField -{ - -public: - - setCellField() - {} - - autoPtr clone() const - { - return autoPtr::New(); - } - - class iNew - { - const fvMesh& mesh_; - const labelList& selectedCells_; - - public: - - iNew(const fvMesh& mesh, const labelList& selectedCells) - : - mesh_(mesh), - selectedCells_(selectedCells) - {} - - iNew(const fvMesh& mesh, labelList&& selectedCells) - : - mesh_(mesh), - selectedCells_(std::move(selectedCells)) - {} - - autoPtr operator()(Istream& fieldValues) const - { - word fieldType(fieldValues); - - if - ( - !( - setCellFieldType - (fieldType, mesh_, selectedCells_, fieldValues) - || setCellFieldType - (fieldType, mesh_, selectedCells_, fieldValues) - || setCellFieldType - (fieldType, mesh_, selectedCells_, fieldValues) - || setCellFieldType - (fieldType, mesh_, selectedCells_, fieldValues) - || setCellFieldType - (fieldType, mesh_, selectedCells_, fieldValues) - ) - ) - { - WarningInFunction - << "field type " << fieldType << " not currently supported" - << endl; - } - - return autoPtr::New(); - } - }; -}; - +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Setting finite-area face fields template -bool setFaceFieldType +bool setAreaFieldType ( - const word& fieldTypeDesc, - const fvMesh& mesh, + const fieldDescription& fieldDesc, + const faMesh& mesh, const labelList& selectedFaces, - Istream& fieldValueStream + Istream& is ) { - typedef GeometricField fieldType; + typedef GeometricField fieldType; - if (fieldTypeDesc != fieldType::typeName + "Value") + if (fieldDesc.type() != fieldType::typeName) { return false; } - word fieldName(fieldValueStream); + // Get value from stream + const Type fieldValue = pTraits(is); + // Check the current time directory IOobject fieldHeader ( - fieldName, - mesh.time().timeName(), - mesh, + fieldDesc.name(), + mesh.thisDb().time().timeName(), + mesh.thisDb(), IOobject::MUST_READ ); - // Check the "constant" directory - if (!fieldHeader.typeHeaderOk(true)) + bool found = fieldHeader.typeHeaderOk(true); + + if (!found) { + // Fallback to "constant" directory fieldHeader = IOobject ( - fieldName, - mesh.time().constant(), - mesh, + fieldDesc.name(), + mesh.thisDb().time().constant(), + mesh.thisDb(), IOobject::MUST_READ ); + found = fieldHeader.typeHeaderOk(true); } - // Check field exists - if (fieldHeader.typeHeaderOk(true)) + // Field exists + if (found) { - Info<< " Setting patchField values of " + Info<< " - set internal values of " << fieldHeader.headerClassName() - << " " << fieldName << endl; + << ": " << fieldDesc.name() + << " = " << fieldValue << endl; fieldType field(fieldHeader, mesh); - const Type value = pTraits(fieldValueStream); + if (isNull(selectedFaces) || selectedFaces.size() == field.size()) + { + field.primitiveFieldRef() = fieldValue; + } + else + { + for (const label facei : selectedFaces) + { + field[facei] = fieldValue; + } + } + + if (!field.write()) + { + FatalErrorInFunction + << "Failed writing field " << field.name() << endl; + } + } + else + { + Warning + << "Field " << fieldDesc.name() << " not found" << endl; + } + + return true; +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Setting volume boundary fields +template +bool setFaceFieldType +( + const fieldDescription& fieldDesc, + const fvMesh& mesh, + const labelList& selectedFaces, + Istream& is +) +{ + typedef GeometricField fieldType; + + if (fieldDesc.type() != fieldType::typeName) + { + return false; + } + + // Get value from stream + const Type fieldValue = pTraits(is); + + + // Check the current time directory + IOobject fieldHeader + ( + fieldDesc.name(), + mesh.thisDb().time().timeName(), + mesh.thisDb(), + IOobject::MUST_READ + ); + + bool found = fieldHeader.typeHeaderOk(true); + + if (!found) + { + // Fallback to "constant" directory + fieldHeader = IOobject + ( + fieldDesc.name(), + mesh.thisDb().time().constant(), + mesh.thisDb(), + IOobject::MUST_READ + ); + found = fieldHeader.typeHeaderOk(true); + } + + // Field exists + if (found) + { + Info<< " - set boundary values of " + << fieldHeader.headerClassName() + << ": " << fieldDesc.name() + << " = " << fieldValue << endl; + + fieldType field(fieldHeader, mesh); // Create flat list of selected faces and their value. Field allBoundaryValues(mesh.nBoundaryFaces()); @@ -260,34 +358,47 @@ bool setFaceFieldType } // Override - bool hasWarned = false; + unsigned hasWarned = 0; labelList nChanged ( returnReduce(field.boundaryField().size(), maxOp