/*---------------------------------------------------------------------------*\ ========= | \\ / 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