1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 Manipulate a cell/face/point set interactively.
28 \*---------------------------------------------------------------------------*/
33 #include "globalMeshData.H"
34 #include "IStringStream.H"
38 #include "topoSetSource.H"
41 #include "demandDrivenData.H"
42 #include "writePatch.H"
43 #include "writePointSet.H"
44 #include "IOobjectList.H"
50 # include <readline/readline.h>
51 # include <readline/history.h>
56 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
60 static const char* historyFile = ".setSet";
63 Istream& selectStream(Istream* is0Ptr, Istream* is1Ptr)
75 FatalErrorIn("selectStream(Istream*, Istream*)")
76 << "No valid stream opened" << abort(FatalError);
87 const topoSet& fromSet,
93 Pout<< " Backing up " << fromName << " into " << toName << endl;
95 topoSet backupSet(mesh, toName, fromSet);
105 const polyMesh& mesh,
106 const word& fromName,
110 topoSet fromSet(mesh, fromName, IOobject::READ_IF_PRESENT);
112 backup(mesh, fromName, fromSet, toName);
116 // Write set to VTK readable files
119 const polyMesh& mesh,
120 const topoSet& currentSet,
121 const fileName& vtkName
124 if (typeid(currentSet) == typeid(faceSet))
126 // Faces of set with OpenFOAM faceID as value
128 faceList setFaces(currentSet.size());
129 labelList faceValues(currentSet.size());
132 forAllConstIter(topoSet, currentSet, iter)
134 setFaces[setFaceI] = mesh.faces()[iter.key()];
135 faceValues[setFaceI] = iter.key();
139 primitiveFacePatch fp(setFaces, mesh.points());
148 mesh.time().path()/vtkName
151 else if (typeid(currentSet) == typeid(cellSet))
153 // External faces of cellset with OpenFOAM cellID as value
155 Map<label> cellFaces(currentSet.size());
157 forAllConstIter(cellSet, currentSet, iter)
159 label cellI = iter.key();
161 const cell& cFaces = mesh.cells()[cellI];
165 label faceI = cFaces[i];
167 if (mesh.isInternalFace(faceI))
169 label otherCellI = mesh.faceOwner()[faceI];
171 if (otherCellI == cellI)
173 otherCellI = mesh.faceNeighbour()[faceI];
176 if (!currentSet.found(otherCellI))
178 cellFaces.insert(faceI, cellI);
183 cellFaces.insert(faceI, cellI);
188 faceList setFaces(cellFaces.size());
189 labelList faceValues(cellFaces.size());
192 forAllConstIter(Map<label>, cellFaces, iter)
194 setFaces[setFaceI] = mesh.faces()[iter.key()];
195 faceValues[setFaceI] = iter(); // Cell ID
199 primitiveFacePatch fp(setFaces, mesh.points());
208 mesh.time().path()/vtkName
211 else if (typeid(currentSet) == typeid(pointSet))
218 mesh.time().path()/vtkName
226 "(const polyMesh& mesh, const topoSet& currentSet,"
227 "const fileName& vtkName)"
228 ) << "Don't know how to handle set of type " << currentSet.type()
234 void printHelp(Ostream& os)
236 os << "Please type 'help', 'list', 'quit', 'time ddd'"
237 << " or a set command after prompt." << endl
238 << "'list' will show all current cell/face/point sets." << endl
239 << "'time ddd' will change the current time." << endl
241 << "A set command should be of the following form" << endl
243 << " cellSet|faceSet|pointSet <setName> <action> <source>"
245 << "The <action> is one of" << endl
246 << " list - prints the contents of the set" << endl
247 << " clear - clears the set" << endl
248 << " invert - inverts the set" << endl
249 << " new <source> - sets to set to the source set" << endl
250 << " add <source> - adds all elements from the source set" << endl
251 << " delete <source> - deletes ,," << endl
252 << " subset <source> - combines current set with the source set"
255 << "The sources come in various forms. Type a wrong source"
256 << " to see all the types available." << endl
258 << "Example: pick up all cells connected by point or face to patch"
259 << " movingWall" << endl
261 << "Pick up all faces of patch:" << endl
262 << " faceSet f0 new patchToFace movingWall" << endl
263 << "Add faces 0,1,2:" << endl
264 << " faceSet f0 add labelToFace (0 1 2)" << endl
265 << "Pick up all points used by faces in faceSet f0:" << endl
266 << " pointSet p0 new faceToPoint f0 all" << endl
267 << "Pick up cell which has any face in f0:" << endl
268 << " cellSet c0 new faceToCell f0 any" << endl
269 << "Add cells which have any point in p0:" << endl
270 << " cellSet c0 add pointToCell p0 any" << endl
271 << "List set:" << endl
272 << " cellSet c0 list" << endl
277 void printAllSets(const polyMesh& mesh, Ostream& os)
282 mesh.pointsInstance(),
283 polyMesh::meshSubDir/"sets"
285 IOobjectList cellSets(objects.lookupClass(cellSet::typeName));
288 os << "cellSets:" << endl;
289 forAllConstIter(IOobjectList, cellSets, iter)
291 cellSet set(*iter());
292 os << '\t' << set.name() << "\tsize:" << set.size() << endl;
295 IOobjectList faceSets(objects.lookupClass(faceSet::typeName));
298 os << "faceSets:" << endl;
299 forAllConstIter(IOobjectList, faceSets, iter)
301 faceSet set(*iter());
302 os << '\t' << set.name() << "\tsize:" << set.size() << endl;
305 IOobjectList pointSets(objects.lookupClass(pointSet::typeName));
306 if (pointSets.size())
308 os << "pointSets:" << endl;
309 forAllConstIter(IOobjectList, pointSets, iter)
311 pointSet set(*iter());
312 os << '\t' << set.name() << "\tsize:" << set.size() << endl;
319 // Read command and execute. Return true if ok, false otherwise.
322 const polyMesh& mesh,
325 const word& actionName,
326 const bool writeVTKFile,
330 // Get some size estimate for set.
331 const globalMeshData& parData = mesh.globalData();
336 parData.nTotalCells(),
339 parData.nTotalFaces(),
340 parData.nTotalPoints()
343 / (10*Pstream::nProcs());
349 autoPtr<topoSet> currentSetPtr;
355 topoSetSource::setAction action =
356 topoSetSource::toAction(actionName);
359 IOobject::readOption r;
363 (action == topoSetSource::NEW)
364 || (action == topoSetSource::CLEAR)
367 r = IOobject::NO_READ;
369 //backup(mesh, setName, setName + "_old");
371 currentSetPtr = topoSet::New(setType, mesh, setName, typSize);
375 r = IOobject::MUST_READ;
377 currentSetPtr = topoSet::New(setType, mesh, setName, r);
379 topoSet& currentSet = currentSetPtr();
381 // Presize it according to current mesh data.
382 currentSet.resize(max(currentSet.size(), typSize));
385 if (currentSetPtr.empty())
387 Pout<< " Cannot construct/load set "
388 << topoSet::localPath(mesh, setName) << endl;
394 topoSet& currentSet = currentSetPtr();
396 Pout<< " Set:" << currentSet.name()
397 << " Size:" << currentSet.size()
398 << " Action:" << actionName
401 //if ((r == IOobject::MUST_READ) && (action != topoSetSource::LIST))
403 // // currentSet has been read so can make copy.
404 // backup(mesh, setName, currentSet, setName + "_old");
409 case topoSetSource::CLEAR:
411 // Already handled above by not reading
414 case topoSetSource::INVERT:
416 currentSet.invert(currentSet.maxSize(mesh));
419 case topoSetSource::LIST:
421 currentSet.writeDebug(Pout, mesh, 100);
425 case topoSetSource::SUBSET:
427 if (is >> sourceType)
429 autoPtr<topoSetSource> setSource
439 // Backup current set.
443 currentSet.name() + "_old2",
448 currentSet.resize(oldSet.size());
449 setSource().applyToSet(topoSetSource::NEW, currentSet);
451 // Combine new value of currentSet with old one.
452 currentSet.subset(oldSet);
458 if (is >> sourceType)
460 autoPtr<topoSetSource> setSource
470 setSource().applyToSet(action, currentSet);
476 if (action != topoSetSource::LIST)
478 // Set will have been modified.
480 // Synchronize for coupled patches.
481 currentSet.sync(mesh);
486 mkDir(mesh.time().path()/"VTK"/currentSet.name());
490 "VTK"/currentSet.name()/currentSet.name()
492 + name(mesh.time().timeIndex())
496 Pout<< " Writing " << currentSet.name()
497 << " (size " << currentSet.size() << ") to "
498 << currentSet.instance()/currentSet.local()
500 << " and to vtk file " << vtkName << endl << endl;
504 writeVTK(mesh, currentSet, vtkName);
508 Pout<< " Writing " << currentSet.name()
509 << " (size " << currentSet.size() << ") to "
510 << currentSet.instance()/currentSet.local()
511 /currentSet.name() << endl << endl;
518 catch (Foam::IOerror& fIOErr)
522 Pout<< fIOErr.message().c_str() << endl;
524 if (sourceType.size())
526 Pout<< topoSetSource::usage(sourceType).c_str();
529 catch (Foam::error& fErr)
533 Pout<< fErr.message().c_str() << endl;
535 if (sourceType.size())
537 Pout<< topoSetSource::usage(sourceType).c_str();
545 // Status returned from parsing the first token of the line
548 QUIT, // quit program
549 INVALID, // token is not a valid set manipulation command
550 VALID // ,, is a valid ,,
554 void printMesh(const Time& runTime, const polyMesh& mesh)
556 Pout<< "Time:" << runTime.timeName()
557 << " cells:" << mesh.nCells()
558 << " faces:" << mesh.nFaces()
559 << " points:" << mesh.nPoints()
560 << " patches:" << mesh.boundaryMesh().size()
561 << " bb:" << mesh.bounds() << nl;
566 commandStatus parseType
576 Pout<< "Type 'help' for usage information" << endl;
580 else if (setType == "help")
586 else if (setType == "list")
588 printAllSets(mesh, Pout);
592 else if (setType == "time")
594 scalar requestedTime = readScalar(is);
595 instantList Times = runTime.times();
597 label nearestIndex = Time::findClosestTimeIndex(Times, requestedTime);
599 Pout<< "Changing time from " << runTime.timeName()
600 << " to " << Times[nearestIndex].name()
603 runTime.setTime(Times[nearestIndex], nearestIndex);
604 polyMesh::readUpdateState stat = mesh.readUpdate();
608 case polyMesh::UNCHANGED:
610 Pout<< " mesh not changed." << endl;
613 case polyMesh::POINTS_MOVED:
615 Pout<< " points moved; topology unchanged." << endl;
618 case polyMesh::TOPO_CHANGE:
620 Pout<< " topology changed; patches unchanged." << nl
622 printMesh(runTime, mesh);
625 case polyMesh::TOPO_PATCH_CHANGE:
627 Pout<< " topology changed and patches changed." << nl
629 printMesh(runTime, mesh);
635 FatalErrorIn("parseType")
636 << "Illegal mesh update state "
637 << stat << abort(FatalError);
644 else if (setType == "quit")
646 Pout<< "Quitting ..." << endl;
653 || setType == "faceSet"
654 || setType == "pointSet"
663 "commandStatus parseType(Time&, polyMesh&, const word&"
665 ) << "Illegal command " << setType << endl
666 << "Should be one of 'help', 'list', 'time' or a set type :"
667 << " 'cellSet', 'faceSet', 'pointSet'"
675 commandStatus parseAction(const word& actionName)
677 commandStatus stat = INVALID;
679 if (actionName.size())
683 (void)topoSetSource::toAction(actionName);
687 catch (Foam::IOerror& fIOErr)
691 catch (Foam::error& fErr)
702 int main(int argc, char *argv[])
704 # include "addRegionOption.H"
705 # include "addTimeOptions.H"
707 argList::validOptions.insert("noVTK", "");
708 argList::validOptions.insert("batch", "file");
710 # include "setRootCase.H"
711 # include "createTime.H"
713 bool writeVTK = !args.optionFound("noVTK");
716 instantList Times = runTime.times();
718 # include "checkTimeOptions.H"
720 runTime.setTime(Times[startTime], startTime);
722 # include "createNamedPolyMesh.H"
724 // Print some mesh info
725 printMesh(runTime, mesh);
728 std::ifstream* fileStreamPtr(NULL);
730 if (args.optionFound("batch"))
732 fileName batchFile(args.option("batch"));
734 Pout<< "Reading commands from file " << batchFile << endl;
736 // we cannot handle .gz files
737 if (!isFile(batchFile, false))
739 FatalErrorIn(args.executable())
740 << "Cannot open file " << batchFile << exit(FatalError);
743 fileStreamPtr = new std::ifstream(batchFile.c_str());
746 else if (!read_history(historyFile))
748 Info<< "Successfully read history from " << historyFile << endl;
753 Pout<< "Please type 'help', 'quit' or a set command after prompt." << endl;
757 FatalError.throwExceptions();
758 FatalIOError.throwExceptions();
764 // Type: cellSet, faceSet, pointSet
766 // Name of destination set.
768 // Action (new, invert etc.)
771 commandStatus stat = INVALID;
775 if (!fileStreamPtr->good())
777 Pout<< "End of batch file" << endl;
781 std::getline(*fileStreamPtr, rawLine);
785 Pout<< "Doing:" << rawLine << endl;
792 char* linePtr = readline("readline>");
794 rawLine = string(linePtr);
798 add_history(linePtr);
799 write_history(historyFile);
802 free(linePtr); // readline uses malloc, not new.
806 Pout<< "Command>" << flush;
807 std::getline(std::cin, rawLine);
812 if (rawLine.empty() || rawLine[0] == '#')
817 IStringStream is(rawLine + ' ');
819 // Type: cellSet, faceSet, pointSet
822 stat = parseType(runTime, mesh, setType, is);
828 if (is >> actionName)
830 stat = parseAction(actionName);
841 else if (stat == VALID)
843 ok = doCommand(mesh, setType, setName, actionName, writeVTK, is);
851 delete fileStreamPtr;
854 Pout<< "\nEnd" << endl;
860 // ************************************************************************* //