/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017 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 "demandDrivenData.H"
#include "foamVtkWriteCellSetFaces.H"
#include "foamVtkWriteFaceSet.H"
#include "foamVtkWritePointSet.H"
#include "IOobjectList.H"
#include "cellZoneSet.H"
#include "faceZoneSet.H"
#include "pointZoneSet.H"
#include "timeSelector.H"
#include "collatedFileOperation.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& currentSet,
const fileName& vtkBaseName
)
{
if (isA(currentSet))
{
// Faces of set with OpenFOAM faceID as value
vtk::writeFaceSet
(
mesh,
dynamicCast(currentSet),
mesh.time().path()/vtkBaseName,
vtk::formatType::LEGACY_BINARY
);
}
else if (isA(currentSet))
{
// External faces of cellset with OpenFOAM cellID as value
vtk::writeCellSetFaces
(
mesh,
dynamicCast(currentSet),
mesh.time().path()/vtkBaseName,
vtk::formatType::LEGACY_BINARY
);
}
else if (isA(currentSet))
{
vtk::writePointSet
(
mesh,
dynamicCast(currentSet),
mesh.time().path()/vtkBaseName,
vtk::formatType::LEGACY_BINARY
);
}
else
{
WarningInFunction
<< "Don't know how to handle set of type " << currentSet.type()
<< endl;
}
}
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 - sets to set to the source set" << nl
<< " add - adds all elements from the source set" << nl
<< " delete - deletes ,," << 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;
}
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"
);
IOobjectList cellSets(objects.lookupClass(cellSet::typeName));
if (cellSets.size())
{
os << "cellSets:" << endl;
forAllConstIter(IOobjectList, cellSets, iter)
{
cellSet set(*iter());
os << '\t' << set.name() << "\tsize:" << set.size() << endl;
}
}
IOobjectList faceSets(objects.lookupClass(faceSet::typeName));
if (faceSets.size())
{
os << "faceSets:" << endl;
forAllConstIter(IOobjectList, faceSets, iter)
{
faceSet set(*iter());
os << '\t' << set.name() << "\tsize:" << set.size() << endl;
}
}
IOobjectList pointSets(objects.lookupClass(pointSet::typeName));
if (pointSets.size())
{
os << "pointSets:" << endl;
forAllConstIter(IOobjectList, pointSets, iter)
{
pointSet set(*iter());
os << '\t' << set.name() << "\tsize:" << set.size() << endl;
}
}
const cellZoneMesh& cellZones = mesh.cellZones();
if (cellZones.size())
{
os << "cellZones:" << endl;
forAll(cellZones, i)
{
const cellZone& zone = cellZones[i];
os << '\t' << zone.name() << "\tsize:" << zone.size() << endl;
}
}
const faceZoneMesh& faceZones = mesh.faceZones();
if (faceZones.size())
{
os << "faceZones:" << endl;
forAll(faceZones, i)
{
const faceZone& zone = faceZones[i];
os << '\t' << zone.name() << "\tsize:" << zone.size() << endl;
}
}
const pointZoneMesh& pointZones = mesh.pointZones();
if (pointZones.size())
{
os << "pointZones:" << endl;
forAll(pointZones, i)
{
const pointZone& zone = pointZones[i];
os << '\t' << zone.name() << "\tsize:" << zone.size() << endl;
}
}
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();
zones.write();
}
}
// 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 =
max
(
parData.nTotalCells(),
max
(
parData.nTotalFaces(),
parData.nTotalPoints()
)
)
/ (10*Pstream::nProcs());
bool ok = true;
// Set to work on
autoPtr currentSetPtr;
word sourceType;
try
{
topoSetSource::setAction action =
topoSetSource::toAction(actionName);
IOobject::readOption r;
if (action == topoSetSource::REMOVE)
{
removeSet(mesh, setType, setName);
}
else if
(
(action == topoSetSource::NEW)
|| (action == topoSetSource::CLEAR)
)
{
r = IOobject::NO_READ;
currentSetPtr = topoSet::New(setType, mesh, setName, typSize);
}
else
{
r = IOobject::MUST_READ;
currentSetPtr = topoSet::New(setType, mesh, setName, r);
topoSet& currentSet = currentSetPtr();
// Presize it according to current mesh data.
currentSet.resize(max(currentSet.size(), typSize));
}
if (currentSetPtr.valid())
{
topoSet& currentSet = currentSetPtr();
Info<< " Set:" << currentSet.name()
<< " Size:" << returnReduce(currentSet.size(), sumOp