/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2018 OpenFOAM Foundation
Copyright (C) 2017-2023 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 .
Application
setSet
Group
grpMeshManipulationUtilities
Description
Manipulate a cell/face/point Set or Zone interactively.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "polyMesh.H"
#include "globalMeshData.H"
#include "StringStream.H"
#include "cellSet.H"
#include "faceSet.H"
#include "pointSet.H"
#include "topoSetSource.H"
#include "Fstream.H"
#include "foamVtkWriteTopoSet.H"
#include "IOobjectList.H"
#include "cellZoneSet.H"
#include "faceZoneSet.H"
#include "pointZoneSet.H"
#include "timeSelector.H"
#include
#ifdef HAVE_LIBREADLINE
#include
#include
static const char* historyFile = ".setSet";
#endif
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Write set to VTK readable files
void writeVTK
(
const polyMesh& mesh,
const topoSet& currSet,
const fileName& outputName
)
{
if
(
!vtk::writeTopoSet
(
mesh,
currSet,
vtk::formatType::INLINE_BASE64, // XML-binary
// vtk::formatType::LEGACY_BINARY,
outputName,
false // Not parallel
)
)
{
WarningInFunction
<< "Don't know how to handle set of type "
<< currSet.type() << nl;
}
}
void printHelp(Ostream& os)
{
os << "Please type 'help', 'list', 'quit', 'time ddd'"
<< " or a set command after prompt." << nl
<< "'list' will show all current cell/face/point sets." << nl
<< "'time ddd' will change the current time." << nl
<< nl
<< "A set command should be of the following form" << nl
<< nl
<< " cellSet|faceSet|pointSet "
<< nl
<< nl
<< "The is one of" << nl
<< " list - prints the contents of the set" << nl
<< " clear - clears the set" << nl
<< " invert - inverts the set" << nl
<< " remove - remove the set" << nl
<< " new - use all elements from the source set" << nl
<< " add - adds all elements from the source set" << nl
<< " subtract - subtract the source set elements" << nl
<< " subset - combines current set with the source set"
<< nl
<< nl
<< "The sources come in various forms. Type a wrong source"
<< " to see all the types available." << nl
<< nl
<< "Example: pick up all cells connected by point or face to patch"
<< " movingWall" << nl
<< nl
<< "Pick up all faces of patch:" << nl
<< " faceSet f0 new patchToFace movingWall" << nl
<< "Add faces 0,1,2:" << nl
<< " faceSet f0 add labelToFace (0 1 2)" << nl
<< "Pick up all points used by faces in faceSet f0:" << nl
<< " pointSet p0 new faceToPoint f0 all" << nl
<< "Pick up cell which has any face in f0:" << nl
<< " cellSet c0 new faceToCell f0 any" << nl
<< "Add cells which have any point in p0:" << nl
<< " cellSet c0 add pointToCell p0 any" << nl
<< "List set:" << nl
<< " cellSet c0 list" << nl
<< nl
<< "Zones can be set using zoneSets from corresponding sets:" << nl
<< " cellZoneSet c0Zone new setToCellZone c0" << nl
<< " faceZoneSet f0Zone new setToFaceZone f0" << nl
<< nl
<< "or if orientation is important:" << nl
<< " faceZoneSet f0Zone new setsToFaceZone f0 c0" << nl
<< nl
<< "ZoneSets can be manipulated using the general actions:" << nl
<< " list - prints the contents of the set" << nl
<< " clear - clears the set" << nl
<< " invert - inverts the set (undefined orientation)"
<< nl
<< " remove - remove the set" << nl
<< endl;
}
template
void printSets(Ostream& os, const IOobjectList& objects)
{
label n = 0;
for (const IOobject& io : objects.csorted())
{
SetType set(io);
if (!n++) os << SetType::typeName << "s:" << nl;
os << '\t' << set.name() << "\tsize:" << set.size() << endl;
}
}
template
void printZones(Ostream& os, const ZoneMesh& zones)
{
label n = 0;
for (const ZoneType& zn : zones)
{
if (!n++) os << ZoneType::typeName << "s:" << nl;
os << '\t' << zn.name() << "\tsize:" << zn.size() << endl;
}
}
void printAllSets(const polyMesh& mesh, Ostream& os)
{
IOobjectList objects
(
mesh,
mesh.time().findInstance
(
polyMesh::meshSubDir/"sets",
word::null,
IOobject::READ_IF_PRESENT,
mesh.facesInstance()
),
polyMesh::meshSubDir/"sets"
);
printSets(os, objects);
printSets(os, objects);
printSets(os, objects);
printZones(os, mesh.cellZones());
printZones(os, mesh.faceZones());
printZones(os, mesh.pointZones());
os << endl;
}
template
void removeZone
(
ZoneMesh& zones,
const word& setName
)
{
label zoneID = zones.findZoneID(setName);
if (zoneID != -1)
{
Info<< "Removing zone " << setName << " at index " << zoneID << endl;
// Shuffle to last position
labelList oldToNew(zones.size());
label newI = 0;
forAll(oldToNew, i)
{
if (i != zoneID)
{
oldToNew[i] = newI++;
}
}
oldToNew[zoneID] = newI;
zones.reorder(oldToNew);
// Remove last element
zones.setSize(zones.size()-1);
zones.clearAddressing();
if (!zones.write())
{
WarningInFunction << "Failed writing zone " << setName << endl;
}
zones.write();
// Force flushing so we know it has finished writing
fileHandler().flush();
}
}
// Physically remove a set
void removeSet
(
const polyMesh& mesh,
const word& setType,
const word& setName
)
{
// Remove the file
IOobjectList objects
(
mesh,
mesh.time().findInstance
(
polyMesh::meshSubDir/"sets",
word::null,
IOobject::READ_IF_PRESENT,
mesh.facesInstance()
),
polyMesh::meshSubDir/"sets"
);
if (objects.found(setName))
{
// Remove file
fileName object = objects[setName]->objectPath();
Info<< "Removing file " << object << endl;
rm(object);
}
// See if zone
if (setType == cellZoneSet::typeName)
{
removeZone
(
const_cast(mesh.cellZones()),
setName
);
}
else if (setType == faceZoneSet::typeName)
{
removeZone
(
const_cast(mesh.faceZones()),
setName
);
}
else if (setType == pointZoneSet::typeName)
{
removeZone
(
const_cast(mesh.pointZones()),
setName
);
}
}
// Read command and execute. Return true if ok, false otherwise.
bool doCommand
(
const polyMesh& mesh,
const word& setType,
const word& setName,
const word& actionName,
const bool writeVTKFile,
const bool writeCurrentTime,
const bool noSync,
Istream& is
)
{
// Get some size estimate for set.
const globalMeshData& parData = mesh.globalData();
label typSize =
Foam::max
(
parData.nTotalCells(),
Foam::max
(
parData.nTotalFaces(),
parData.nTotalPoints()
)
)
/ (10*Pstream::nProcs());
bool ok = true;
// Set to work on
autoPtr currentSetPtr;
word sourceType;
try
{
topoSetSource::setAction action =
topoSetSource::actionNames[actionName];
switch (action)
{
case topoSetSource::REMOVE :
{
removeSet(mesh, setType, setName);
break;
}
case topoSetSource::NEW :
case topoSetSource::CLEAR :
{
currentSetPtr = topoSet::New(setType, mesh, setName, typSize);
break;
}
case topoSetSource::IGNORE :
// Nothing to do
break;
default:
{
currentSetPtr = topoSet::New
(
setType,
mesh,
setName,
IOobject::MUST_READ
);
topoSet& currentSet = currentSetPtr();
// Presize it according to current mesh data.
currentSet.reserve(Foam::max(currentSet.size(), typSize));
}
}
if (currentSetPtr)
{
topoSet& currentSet = *currentSetPtr;
Info<< " Set:" << currentSet.name()
<< " Size:" << returnReduce(currentSet.size(), sumOp