Skip to content
Snippets Groups Projects
Commit 45f4a8b9 authored by Mark OLESEN's avatar Mark OLESEN
Browse files

ENH: bounding box clipping for ensightWrite function object (issue #973)

- for larger problems with a smaller region of interest, can apply a
  bounding to limit the size of the ensight geometry and fields created.

  Since the implementation uses a fvMeshSubset, there is an additional
  per-process memory overhead.

  A high output frequency should be avoided with moving meshes, since
  this indirectly forces a frequent update of the submesh.
parent 62b83a76
Branches
Tags
No related merge requests found
...@@ -4,6 +4,7 @@ EXE_INC = \ ...@@ -4,6 +4,7 @@ EXE_INC = \
-I$(LIB_SRC)/fileFormats/lnInclude \ -I$(LIB_SRC)/fileFormats/lnInclude \
-I$(LIB_SRC)/conversion/lnInclude \ -I$(LIB_SRC)/conversion/lnInclude \
-I$(LIB_SRC)/sampling/lnInclude \ -I$(LIB_SRC)/sampling/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/ODE/lnInclude \ -I$(LIB_SRC)/ODE/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \ -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
-I$(LIB_SRC)/transportModels/compressible/lnInclude -I$(LIB_SRC)/transportModels/compressible/lnInclude
...@@ -13,6 +14,7 @@ LIB_LIBS = \ ...@@ -13,6 +14,7 @@ LIB_LIBS = \
-lfiniteArea \ -lfiniteArea \
-lconversion \ -lconversion \
-lsampling \ -lsampling \
-ldynamicMesh \
-lfluidThermophysicalModels \ -lfluidThermophysicalModels \
-lcompressibleTransportModels \ -lcompressibleTransportModels \
-lODE -lODE
...@@ -47,6 +47,39 @@ namespace functionObjects ...@@ -47,6 +47,39 @@ namespace functionObjects
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::bitSet Foam::functionObjects::ensightWrite::cellSelection() const
{
bitSet cellsToSelect;
// Could also deal with cellZones here, as required
if (bounds_.empty())
{
return cellsToSelect;
}
const auto& cellCentres = static_cast<const fvMesh&>(mesh_).C();
const label len = mesh_.nCells();
cellsToSelect.resize(len);
for (label celli=0; celli < len; ++celli)
{
const point& cc = cellCentres[celli];
if (bounds_.contains(cc))
{
cellsToSelect.set(celli);
}
}
return cellsToSelect;
}
int Foam::functionObjects::ensightWrite::process(const word& fieldName) int Foam::functionObjects::ensightWrite::process(const word& fieldName)
{ {
int state = 0; int state = 0;
...@@ -83,7 +116,8 @@ Foam::functionObjects::ensightWrite::ensightWrite ...@@ -83,7 +116,8 @@ Foam::functionObjects::ensightWrite::ensightWrite
caseOpts_(writeOpts_.format()), caseOpts_(writeOpts_.format()),
selectFields_(), selectFields_(),
dirName_("ensightWrite"), dirName_("ensightWrite"),
consecutive_(false) consecutive_(false),
bounds_()
{ {
if (postProcess) if (postProcess)
{ {
...@@ -104,6 +138,12 @@ bool Foam::functionObjects::ensightWrite::read(const dictionary& dict) ...@@ -104,6 +138,12 @@ bool Foam::functionObjects::ensightWrite::read(const dictionary& dict)
{ {
fvMeshFunctionObject::read(dict); fvMeshFunctionObject::read(dict);
// Ensure consistency
meshSubset_.clear();
ensMesh_.clear();
// //
// writer options // writer options
// //
...@@ -123,6 +163,10 @@ bool Foam::functionObjects::ensightWrite::read(const dictionary& dict) ...@@ -123,6 +163,10 @@ bool Foam::functionObjects::ensightWrite::read(const dictionary& dict)
} }
bounds_.clear();
dict.readIfPresent("bounds", bounds_);
// //
// case options // case options
// //
...@@ -197,7 +241,25 @@ bool Foam::functionObjects::ensightWrite::write() ...@@ -197,7 +241,25 @@ bool Foam::functionObjects::ensightWrite::write()
if (!ensMesh_.valid()) if (!ensMesh_.valid())
{ {
writeGeom = true; writeGeom = true;
ensMesh_.reset(new ensightMesh(mesh_, writeOpts_));
bitSet selection = this->cellSelection();
if (returnReduce(!selection.empty(), orOp<bool>()))
{
meshSubset_.clear();
meshSubset_.reset(new fvMeshSubset(mesh_, selection));
ensMesh_.reset
(
new ensightMesh(meshSubset_->subMesh(), writeOpts_)
);
}
else
{
ensMesh_.reset
(
new ensightMesh(mesh_, writeOpts_)
);
}
} }
if (ensMesh_().needsUpdate()) if (ensMesh_().needsUpdate())
{ {
...@@ -219,12 +281,12 @@ bool Foam::functionObjects::ensightWrite::write() ...@@ -219,12 +281,12 @@ bool Foam::functionObjects::ensightWrite::write()
DynamicList<word> missing(selectFields_.size()); DynamicList<word> missing(selectFields_.size());
DynamicList<word> ignored(selectFields_.size()); DynamicList<word> ignored(selectFields_.size());
// check exact matches first // Check exact matches first
for (const wordRe& select : selectFields_) for (const wordRe& select : selectFields_)
{ {
if (!select.isPattern()) if (!select.isPattern())
{ {
const word& fieldName = static_cast<const word&>(select); const word& fieldName = select;
if (!candidates.erase(fieldName)) if (!candidates.erase(fieldName))
{ {
...@@ -271,7 +333,14 @@ void Foam::functionObjects::ensightWrite::updateMesh(const mapPolyMesh& mpm) ...@@ -271,7 +333,14 @@ void Foam::functionObjects::ensightWrite::updateMesh(const mapPolyMesh& mpm)
{ {
// fvMeshFunctionObject::updateMesh(mpm); // fvMeshFunctionObject::updateMesh(mpm);
if (ensMesh_.valid()) // This is heavy-handed, but with a bounding-box limited sub-mesh,
// we don't readily know if the updates affect the subsetted mesh.
if (!bounds_.empty())
{
ensMesh_.clear();
meshSubset_.clear();
}
else if (ensMesh_.valid())
{ {
ensMesh_->expire(); ensMesh_->expire();
} }
...@@ -282,7 +351,14 @@ void Foam::functionObjects::ensightWrite::movePoints(const polyMesh& mpm) ...@@ -282,7 +351,14 @@ void Foam::functionObjects::ensightWrite::movePoints(const polyMesh& mpm)
{ {
// fvMeshFunctionObject::updateMesh(mpm); // fvMeshFunctionObject::updateMesh(mpm);
if (ensMesh_.valid()) // This is heavy-handed, but with a bounding-box limited sub-mesh,
// we don't readily know if the updates affect the subsetted mesh.
if (!bounds_.empty())
{
ensMesh_.clear();
meshSubset_.clear();
}
else if (ensMesh_.valid())
{ {
ensMesh_->expire(); ensMesh_->expire();
} }
......
...@@ -67,6 +67,7 @@ Description ...@@ -67,6 +67,7 @@ Description
faceZones | Select faceZones to write | no | faceZones | Select faceZones to write | no |
consecutive | Consecutive output numbering | no | false consecutive | Consecutive output numbering | no | false
nodeValues | Write values at nodes | no | false nodeValues | Write values at nodes | no | false
bounds | Limit with a bounding box | no |
\endtable \endtable
Note that if the \c patches entry is an empty list, this will select all Note that if the \c patches entry is an empty list, this will select all
...@@ -93,6 +94,7 @@ SourceFiles ...@@ -93,6 +94,7 @@ SourceFiles
#include "interpolation.H" #include "interpolation.H"
#include "volFields.H" #include "volFields.H"
#include "fvMeshSubset.H"
#include "surfaceFields.H" #include "surfaceFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
...@@ -129,6 +131,12 @@ class ensightWrite ...@@ -129,6 +131,12 @@ class ensightWrite
//- Consecutive output numbering //- Consecutive output numbering
bool consecutive_; bool consecutive_;
//- Restrict to bounding box
boundBox bounds_;
//- Mesh subset handler
autoPtr<fvMeshSubset> meshSubset_;
//- Ensight case handler //- Ensight case handler
autoPtr<ensightCase> ensCase_; autoPtr<ensightCase> ensCase_;
...@@ -150,6 +158,9 @@ class ensightWrite ...@@ -150,6 +158,9 @@ class ensightWrite
return *ensMesh_; return *ensMesh_;
} }
//- Define cell selection from bounding box.
// An empty set if no bounding box is specified.
bitSet cellSelection() const;
//- Apply for the volume field type //- Apply for the volume field type
template<class Type> template<class Type>
......
...@@ -38,20 +38,39 @@ int Foam::functionObjects::ensightWrite::writeVolField ...@@ -38,20 +38,39 @@ int Foam::functionObjects::ensightWrite::writeVolField
// State: return 0 (not-processed), -1 (skip), +1 ok // State: return 0 (not-processed), -1 (skip), +1 ok
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType; typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
const VolFieldType* fldPtr;
// Already done, or not available // Already done, or not available
if (state || !foundObject<VolFieldType>(inputName)) if (state || !(fldPtr = lookupObjectPtr<VolFieldType>(inputName)))
{ {
return state; return state;
} }
autoPtr<ensightFile> os = ensCase().newData<Type>(inputName); autoPtr<ensightFile> os = ensCase().newData<Type>(inputName);
ensightOutput::writeField<Type>
(
lookupObject<VolFieldType>(inputName), if (meshSubset_.valid())
ensMesh(), {
os, tmp<VolFieldType> tfield = meshSubset_->interpolate(*fldPtr);
caseOpts_.nodeValues()
); ensightOutput::writeField<Type>
(
tfield(),
ensMesh(),
os,
caseOpts_.nodeValues()
);
}
else
{
ensightOutput::writeField<Type>
(
*fldPtr,
ensMesh(),
os,
caseOpts_.nodeValues()
);
}
Log << " " << inputName; Log << " " << inputName;
......
#!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
. $WM_PROJECT_DIR/bin/tools/RunFunctions # Tutorial run functions
runApplication surfaceFeatureExtract
runApplication blockMesh
runApplication snappyHexMesh -overwrite
runApplication decomposePar
runParallel $(getApplication)
runApplication reconstructPar
#------------------------------------------------------------------------------
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1806 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object decomposeParDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
numberOfSubdomains 6;
// method kahip;
method scotch;
// ************************************************************************* //
...@@ -12,6 +12,9 @@ ensightWrite ...@@ -12,6 +12,9 @@ ensightWrite
// Fields to output (words or regex) // Fields to output (words or regex)
fields (U p "(k|epsilon|omega)"); fields (U p "(k|epsilon|omega)");
// Limit output region
bounds (0 0 0) (245 180 80);
//- Write more frequent than fields //- Write more frequent than fields
writeControl timeStep; writeControl timeStep;
writeInterval 5; writeInterval 5;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment