FreeFOAM The Cross-Platform CFD Toolkit
setSet.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
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
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Application
25  setSet
26 
27 Description
28  Manipulate a cell/face/point/ set or zone interactively.
29 
30 Usage
31 
32  - setSet [OPTIONS]
33 
34  @param -batch <batch file>\n
35  Read commands from batch file.
36 
37  @param -noVTK \n
38  Do not export to VTK.
39 
40  @param -noZero \n
41  Ignore timestep 0.
42 
43  @param -constant \n
44  Include the constant directory.
45 
46  @param -time <time>\n
47  Apply only to specific time.
48 
49  @param -latestTime \n
50  Only apply to latest time step.
51 
52  @param -case <dir>\n
53  Case directory.
54 
55  @param -parallel \n
56  Run in parallel.
57 
58  @param -help \n
59  Display help message.
60 
61  @param -doc \n
62  Display Doxygen API documentation page for this application.
63 
64  @param -srcDoc \n
65  Display Doxygen source documentation page for this application.
66 
67 \*---------------------------------------------------------------------------*/
68 
69 #include <OpenFOAM/argList.H>
70 #include <OpenFOAM/Time.H>
71 #include <OpenFOAM/polyMesh.H>
73 #include <OpenFOAM/IStringStream.H>
74 #include <meshTools/cellSet.H>
75 #include <meshTools/faceSet.H>
76 #include <meshTools/pointSet.H>
78 #include <OpenFOAM/OFstream.H>
79 #include <OpenFOAM/IFstream.H>
81 #include "writePatch.H"
82 #include "writePointSet.H"
83 #include <OpenFOAM/IOobjectList.H>
84 #include <meshTools/cellZoneSet.H>
85 #include <meshTools/faceZoneSet.H>
86 #include <meshTools/pointZoneSet.H>
87 
88 #include <stdio.h>
89 
90 
91 #if READLINE != 0
92 # include <readline/readline.h>
93 # include <readline/history.h>
94 #endif
95 
96 using namespace Foam;
97 
98 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
99 
100 
101 #if READLINE != 0
102 static const char* historyFile = ".setSet";
103 #endif
104 
105 Istream& selectStream(Istream* is0Ptr, Istream* is1Ptr)
106 {
107  if (is0Ptr)
108  {
109  return *is0Ptr;
110  }
111  else if (is1Ptr)
112  {
113  return *is1Ptr;
114  }
115  else
116  {
117  FatalErrorIn("selectStream(Istream*, Istream*)")
118  << "No valid stream opened" << abort(FatalError);
119 
120  return *is0Ptr;
121  }
122 }
123 
124 // Copy set
125 void backup
126 (
127  const word& setType,
128  const polyMesh& mesh,
129  const word& fromName,
130  const topoSet& fromSet,
131  const word& toName
132 )
133 {
134  if (fromSet.size())
135  {
136  Info<< " Backing up " << fromName << " into " << toName << endl;
137 
138  topoSet::New(setType, mesh, toName, fromSet)().write();
139  }
140 }
141 
142 
143 // Read and copy set
144 void backup
145 (
146  const word& setType,
147  const polyMesh& mesh,
148  const word& fromName,
149  const word& toName
150 )
151 {
153  (
154  setType,
155  mesh,
156  fromName,
158  );
159 
160  backup(setType, mesh, fromName, fromSet(), toName);
161 }
162 
163 
164 // Write set to VTK readable files
165 void writeVTK
166 (
167  const polyMesh& mesh,
168  const topoSet& currentSet,
169  const fileName& vtkName
170 )
171 {
172  if (isA<faceSet>(currentSet))
173  {
174  // Faces of set with OpenFOAM faceID as value
175 
176  faceList setFaces(currentSet.size());
177  labelList faceValues(currentSet.size());
178  label setFaceI = 0;
179 
180  forAllConstIter(topoSet, currentSet, iter)
181  {
182  setFaces[setFaceI] = mesh.faces()[iter.key()];
183  faceValues[setFaceI] = iter.key();
184  setFaceI++;
185  }
186 
187  primitiveFacePatch fp(setFaces, mesh.points());
188 
189  writePatch
190  (
191  true,
192  currentSet.name(),
193  fp,
194  "faceID",
195  faceValues,
196  mesh.time().path()/vtkName
197  );
198  }
199  else if (isA<cellSet>(currentSet))
200  {
201  // External faces of cellset with OpenFOAM cellID as value
202 
203  Map<label> cellFaces(currentSet.size());
204 
205  forAllConstIter(cellSet, currentSet, iter)
206  {
207  label cellI = iter.key();
208 
209  const cell& cFaces = mesh.cells()[cellI];
210 
211  forAll(cFaces, i)
212  {
213  label faceI = cFaces[i];
214 
215  if (mesh.isInternalFace(faceI))
216  {
217  label otherCellI = mesh.faceOwner()[faceI];
218 
219  if (otherCellI == cellI)
220  {
221  otherCellI = mesh.faceNeighbour()[faceI];
222  }
223 
224  if (!currentSet.found(otherCellI))
225  {
226  cellFaces.insert(faceI, cellI);
227  }
228  }
229  else
230  {
231  cellFaces.insert(faceI, cellI);
232  }
233  }
234  }
235 
236  faceList setFaces(cellFaces.size());
237  labelList faceValues(cellFaces.size());
238  label setFaceI = 0;
239 
240  forAllConstIter(Map<label>, cellFaces, iter)
241  {
242  setFaces[setFaceI] = mesh.faces()[iter.key()];
243  faceValues[setFaceI] = iter(); // Cell ID
244  setFaceI++;
245  }
246 
247  primitiveFacePatch fp(setFaces, mesh.points());
248 
249  writePatch
250  (
251  true,
252  currentSet.name(),
253  fp,
254  "cellID",
255  faceValues,
256  mesh.time().path()/vtkName
257  );
258  }
259  else if (isA<pointSet>(currentSet))
260  {
262  (
263  true,
264  mesh,
265  currentSet,
266  mesh.time().path()/vtkName
267  );
268  }
269  else
270  {
271  WarningIn
272  (
273  "void writeVTK"
274  "(const polyMesh& mesh, const topoSet& currentSet,"
275  "const fileName& vtkName)"
276  ) << "Don't know how to handle set of type " << currentSet.type()
277  << endl;
278  }
279 }
280 
281 
282 void printHelp(Ostream& os)
283 {
284  os << "Please type 'help', 'list', 'quit', 'time ddd'"
285  << " or a set command after prompt." << endl
286  << "'list' will show all current cell/face/point sets." << endl
287  << "'time ddd' will change the current time." << endl
288  << endl
289  << "A set command should be of the following form" << endl
290  << endl
291  << " cellSet|faceSet|pointSet <setName> <action> <source>"
292  << endl
293  << endl
294  << "The <action> is one of" << endl
295  << " list - prints the contents of the set" << endl
296  << " clear - clears the set" << endl
297  << " invert - inverts the set" << endl
298  << " remove - remove the set" << endl
299  << " new <source> - sets to set to the source set" << endl
300  << " add <source> - adds all elements from the source set" << endl
301  << " delete <source> - deletes ,," << endl
302  << " subset <source> - combines current set with the source set"
303  << endl
304  << endl
305  << "The sources come in various forms. Type a wrong source"
306  << " to see all the types available." << endl
307  << endl
308  << "Example: pick up all cells connected by point or face to patch"
309  << " movingWall" << endl
310  << endl
311  << "Pick up all faces of patch:" << endl
312  << " faceSet f0 new patchToFace movingWall" << endl
313  << "Add faces 0,1,2:" << endl
314  << " faceSet f0 add labelToFace (0 1 2)" << endl
315  << "Pick up all points used by faces in faceSet f0:" << endl
316  << " pointSet p0 new faceToPoint f0 all" << endl
317  << "Pick up cell which has any face in f0:" << endl
318  << " cellSet c0 new faceToCell f0 any" << endl
319  << "Add cells which have any point in p0:" << endl
320  << " cellSet c0 add pointToCell p0 any" << endl
321  << "List set:" << endl
322  << " cellSet c0 list" << endl
323  << endl
324  << "Zones can be set using zoneSets from corresponding sets:" << endl
325  << " cellZoneSet c0Zone new setToCellZone c0" << endl
326  << " faceZoneSet f0Zone new setToFaceZone f0" << endl
327  << endl
328  << "or if orientation is important:" << endl
329  << " faceZoneSet f0Zone new setsToFaceZone f0 c0" << endl
330  << endl
331  << "ZoneSets can be manipulated using the general actions:" << endl
332  << " list - prints the contents of the set" << endl
333  << " clear - clears the set" << endl
334  << " invert - inverts the set (undefined orientation)"
335  << endl
336  << " remove - remove the set" << endl
337  << endl;
338 }
339 
340 
341 void printAllSets(const polyMesh& mesh, Ostream& os)
342 {
343  IOobjectList objects
344  (
345  mesh,
346  mesh.pointsInstance(),
347  polyMesh::meshSubDir/"sets"
348  );
349  IOobjectList cellSets(objects.lookupClass(cellSet::typeName));
350  if (cellSets.size())
351  {
352  os << "cellSets:" << endl;
354  {
355  cellSet set(*iter());
356  os << '\t' << set.name() << "\tsize:" << set.size() << endl;
357  }
358  }
359  IOobjectList faceSets(objects.lookupClass(faceSet::typeName));
360  if (faceSets.size())
361  {
362  os << "faceSets:" << endl;
364  {
365  faceSet set(*iter());
366  os << '\t' << set.name() << "\tsize:" << set.size() << endl;
367  }
368  }
369  IOobjectList pointSets(objects.lookupClass(pointSet::typeName));
370  if (pointSets.size())
371  {
372  os << "pointSets:" << endl;
373  forAllConstIter(IOobjectList, pointSets, iter)
374  {
375  pointSet set(*iter());
376  os << '\t' << set.name() << "\tsize:" << set.size() << endl;
377  }
378  }
379 
380  const cellZoneMesh& cellZones = mesh.cellZones();
381  if (cellZones.size())
382  {
383  os << "cellZones:" << endl;
384  forAll(cellZones, i)
385  {
386  const cellZone& zone = cellZones[i];
387  os << '\t' << zone.name() << "\tsize:" << zone.size() << endl;
388  }
389  }
390  const faceZoneMesh& faceZones = mesh.faceZones();
391  if (faceZones.size())
392  {
393  os << "faceZones:" << endl;
394  forAll(faceZones, i)
395  {
396  const faceZone& zone = faceZones[i];
397  os << '\t' << zone.name() << "\tsize:" << zone.size() << endl;
398  }
399  }
400  const pointZoneMesh& pointZones = mesh.pointZones();
401  if (pointZones.size())
402  {
403  os << "pointZones:" << endl;
404  forAll(pointZones, i)
405  {
406  const pointZone& zone = pointZones[i];
407  os << '\t' << zone.name() << "\tsize:" << zone.size() << endl;
408  }
409  }
410 
411  os << endl;
412 }
413 
414 
415 template<class ZoneType>
416 void removeZone
417 (
419  const word& setName
420 )
421 {
422  label zoneID = zones.findZoneID(setName);
423 
424  if (zoneID != -1)
425  {
426  Info<< "Removing zone " << setName << " at index " << zoneID << endl;
427  // Shuffle to last position
428  labelList oldToNew(zones.size());
429  label newI = 0;
430  forAll(oldToNew, i)
431  {
432  if (i != zoneID)
433  {
434  oldToNew[i] = newI++;
435  }
436  }
437  oldToNew[zoneID] = newI;
438  zones.reorder(oldToNew);
439  // Remove last element
440  zones.setSize(zones.size()-1);
441  zones.clearAddressing();
442  zones.write();
443  }
444 }
445 
446 
447 // Physically remove a set
448 void removeSet
449 (
450  const polyMesh& mesh,
451  const word& setType,
452  const word& setName
453 )
454 {
455  // Remove the file
456  IOobjectList objects
457  (
458  mesh,
459  mesh.pointsInstance(),
460  polyMesh::meshSubDir/"sets"
461  );
462 
463  if (objects.found(setName))
464  {
465  // Remove file
466  fileName object = objects[setName]->objectPath();
467  Info<< "Removing file " << object << endl;
468  rm(object);
469  }
470 
471  // See if zone
472  if (setType == cellZoneSet::typeName)
473  {
474  removeZone
475  (
476  const_cast<cellZoneMesh&>(mesh.cellZones()),
477  setName
478  );
479  }
480  else if (setType == faceZoneSet::typeName)
481  {
482  removeZone
483  (
484  const_cast<faceZoneMesh&>(mesh.faceZones()),
485  setName
486  );
487  }
488  else if (setType == pointZoneSet::typeName)
489  {
490  removeZone
491  (
492  const_cast<pointZoneMesh&>(mesh.pointZones()),
493  setName
494  );
495  }
496 }
497 
498 
499 // Read command and execute. Return true if ok, false otherwise.
500 bool doCommand
501 (
502  const polyMesh& mesh,
503  const word& setType,
504  const word& setName,
505  const word& actionName,
506  const bool writeVTKFile,
507  Istream& is
508 )
509 {
510  // Get some size estimate for set.
511  const globalMeshData& parData = mesh.globalData();
512 
513  label typSize =
514  max
515  (
516  parData.nTotalCells(),
517  max
518  (
519  parData.nTotalFaces(),
520  parData.nTotalPoints()
521  )
522  )
523  / (10*Pstream::nProcs());
524 
525 
526  bool ok = true;
527 
528  // Set to work on
529  autoPtr<topoSet> currentSetPtr;
530 
531  word sourceType;
532 
533  try
534  {
535  topoSetSource::setAction action =
536  topoSetSource::toAction(actionName);
537 
538 
540 
541  if (action == topoSetSource::REMOVE)
542  {
543  removeSet(mesh, setType, setName);
544  }
545  else if
546  (
547  (action == topoSetSource::NEW)
548  || (action == topoSetSource::CLEAR)
549  )
550  {
551  r = IOobject::NO_READ;
552  currentSetPtr = topoSet::New(setType, mesh, setName, typSize);
553  }
554  else
555  {
557  currentSetPtr = topoSet::New(setType, mesh, setName, r);
558  topoSet& currentSet = currentSetPtr();
559  // Presize it according to current mesh data.
560  currentSet.resize(max(currentSet.size(), typSize));
561  }
562 
563  if (currentSetPtr.valid())
564  {
565  topoSet& currentSet = currentSetPtr();
566 
567  Info<< " Set:" << currentSet.name()
568  << " Size:" << currentSet.size()
569  << " Action:" << actionName
570  << endl;
571 
572  switch (action)
573  {
575  {
576  // Already handled above by not reading
577  break;
578  }
580  {
581  currentSet.invert(currentSet.maxSize(mesh));
582  break;
583  }
584  case topoSetSource::LIST:
585  {
586  currentSet.writeDebug(Pout, mesh, 100);
587  Pout<< endl;
588  break;
589  }
591  {
592  if (is >> sourceType)
593  {
594  autoPtr<topoSetSource> setSource
595  (
597  (
598  sourceType,
599  mesh,
600  is
601  )
602  );
603 
604  // Backup current set.
605  autoPtr<topoSet> oldSet
606  (
608  (
609  setType,
610  mesh,
611  currentSet.name() + "_old2",
612  currentSet
613  )
614  );
615 
616  currentSet.clear();
617  setSource().applyToSet(topoSetSource::NEW, currentSet);
618 
619  // Combine new value of currentSet with old one.
620  currentSet.subset(oldSet);
621  }
622  break;
623  }
624  default:
625  {
626  if (is >> sourceType)
627  {
628  autoPtr<topoSetSource> setSource
629  (
631  (
632  sourceType,
633  mesh,
634  is
635  )
636  );
637 
638  setSource().applyToSet(action, currentSet);
639  }
640  }
641  }
642 
643 
644  if (action != topoSetSource::LIST)
645  {
646  // Set will have been modified.
647 
648  // Synchronize for coupled patches.
649  currentSet.sync(mesh);
650 
651  // Write
652  if (writeVTKFile)
653  {
654  mkDir(mesh.time().path()/"VTK"/currentSet.name());
655 
656  fileName vtkName
657  (
658  "VTK"/currentSet.name()/currentSet.name()
659  + "_"
660  + name(mesh.time().timeIndex())
661  + ".vtk"
662  );
663 
664  Info<< " Writing " << currentSet.name()
665  << " (size " << currentSet.size() << ") to "
666  << currentSet.instance()/currentSet.local()
667  /currentSet.name()
668  << " and to vtk file " << vtkName << endl << endl;
669 
670  currentSet.write();
671 
672  writeVTK(mesh, currentSet, vtkName);
673  }
674  else
675  {
676  Info<< " Writing " << currentSet.name()
677  << " (size " << currentSet.size() << ") to "
678  << currentSet.instance()/currentSet.local()
679  /currentSet.name() << endl << endl;
680 
681  currentSet.write();
682  }
683  }
684  }
685  }
686  catch (Foam::IOerror& fIOErr)
687  {
688  ok = false;
689 
690  Pout<< fIOErr.message().c_str() << endl;
691 
692  if (sourceType.size())
693  {
694  Pout<< topoSetSource::usage(sourceType).c_str();
695  }
696  }
697  catch (Foam::error& fErr)
698  {
699  ok = false;
700 
701  Pout<< fErr.message().c_str() << endl;
702 
703  if (sourceType.size())
704  {
705  Pout<< topoSetSource::usage(sourceType).c_str();
706  }
707  }
708 
709  return ok;
710 }
711 
712 
713 // Status returned from parsing the first token of the line
714 enum commandStatus
715 {
716  QUIT, // quit program
717  INVALID, // token is not a valid set manipulation command
718  VALIDSETCMD, // ,, is a valid ,,
719  VALIDZONECMD // ,, is a valid zone ,,
720 };
721 
722 
723 void printMesh(const Time& runTime, const polyMesh& mesh)
724 {
725  Info<< "Time:" << runTime.timeName()
726  << " cells:" << mesh.nCells()
727  << " faces:" << mesh.nFaces()
728  << " points:" << mesh.nPoints()
729  << " patches:" << mesh.boundaryMesh().size()
730  << " bb:" << mesh.bounds() << nl;
731 }
732 
733 
734 
735 commandStatus parseType
736 (
737  Time& runTime,
738  polyMesh& mesh,
739  const word& setType,
740  IStringStream& is
741 )
742 {
743  if (setType.empty())
744  {
745  Info<< "Type 'help' for usage information" << endl;
746 
747  return INVALID;
748  }
749  else if (setType == "help")
750  {
751  printHelp(Info);
752 
753  return INVALID;
754  }
755  else if (setType == "list")
756  {
757  printAllSets(mesh, Info);
758 
759  return INVALID;
760  }
761  else if (setType == "time")
762  {
763  scalar requestedTime = readScalar(is);
764  instantList Times = runTime.times();
765 
766  label nearestIndex = Time::findClosestTimeIndex(Times, requestedTime);
767 
768  Info<< "Changing time from " << runTime.timeName()
769  << " to " << Times[nearestIndex].name()
770  << endl;
771 
772  runTime.setTime(Times[nearestIndex], nearestIndex);
774 
775  switch(stat)
776  {
777  case polyMesh::UNCHANGED:
778  {
779  Info<< " mesh not changed." << endl;
780  break;
781  }
783  {
784  Info<< " points moved; topology unchanged." << endl;
785  break;
786  }
788  {
789  Info<< " topology changed; patches unchanged." << nl
790  << " ";
791  printMesh(runTime, mesh);
792  break;
793  }
795  {
796  Info<< " topology changed and patches changed." << nl
797  << " ";
798  printMesh(runTime, mesh);
799 
800  break;
801  }
802  default:
803  {
804  FatalErrorIn("parseType")
805  << "Illegal mesh update state "
806  << stat << abort(FatalError);
807  break;
808  }
809  }
810 
811  return INVALID;
812  }
813  else if (setType == "quit")
814  {
815  Info<< "Quitting ..." << endl;
816 
817  return QUIT;
818  }
819  else if
820  (
821  setType == "cellSet"
822  || setType == "faceSet"
823  || setType == "pointSet"
824  )
825  {
826  return VALIDSETCMD;
827  }
828  else if
829  (
830  setType == "cellZoneSet"
831  || setType == "faceZoneSet"
832  || setType == "pointZoneSet"
833  )
834  {
835  return VALIDZONECMD;
836  }
837  else
838  {
840  (
841  "commandStatus parseType(Time&, polyMesh&, const word&"
842  ", IStringStream&)"
843  ) << "Illegal command " << setType << endl
844  << "Should be one of 'help', 'list', 'time' or a set type :"
845  << " 'cellSet', 'faceSet', 'pointSet', 'faceZoneSet'"
846  << endl;
847 
848  return INVALID;
849  }
850 }
851 
852 
853 commandStatus parseAction(const word& actionName)
854 {
855  commandStatus stat = INVALID;
856 
857  if (actionName.size())
858  {
859  try
860  {
861  (void)topoSetSource::toAction(actionName);
862 
863  stat = VALIDSETCMD;
864  }
865  catch (Foam::IOerror& fIOErr)
866  {
867  stat = INVALID;
868  }
869  catch (Foam::error& fErr)
870  {
871  stat = INVALID;
872  }
873  }
874  return stat;
875 }
876 
877 
878 // Main program:
879 
880 int main(int argc, char *argv[])
881 {
882 # include <OpenFOAM/addRegionOption.H>
883 # include <OpenFOAM/addTimeOptions.H>
884 
885  argList::validOptions.insert("noVTK", "");
886  argList::validOptions.insert("batch", "file");
887 
888 # include <OpenFOAM/setRootCase.H>
889 # include <OpenFOAM/createTime.H>
890 
891  bool writeVTK = !args.optionFound("noVTK");
892 
893  // Get times list
894  instantList Times = runTime.times();
895 
896 # include <OpenFOAM/checkTimeOptions.H>
897 
898  runTime.setTime(Times[startTime], startTime);
899 
901 
902  // Print some mesh info
903  printMesh(runTime, mesh);
904 
905  // Print current sets
906  printAllSets(mesh, Info);
907 
908 
909 
910  std::ifstream* fileStreamPtr(NULL);
911 
912  if (args.optionFound("batch"))
913  {
914  fileName batchFile(args.option("batch"));
915 
916  Info<< "Reading commands from file " << batchFile << endl;
917 
918  // we cannot handle .gz files
919  if (!isFile(batchFile, false))
920  {
922  << "Cannot open file " << batchFile << exit(FatalError);
923  }
924 
925  fileStreamPtr = new std::ifstream(batchFile.c_str());
926  }
927 #if READLINE != 0
928  else if (!read_history(historyFile))
929  {
930  Info<< "Successfully read history from " << historyFile << endl;
931  }
932 #endif
933 
934  Info<< "Please type 'help', 'quit' or a set command after prompt." << endl;
935 
936  bool ok = true;
937 
940 
941  do
942  {
943  string rawLine;
944 
945  // Type: cellSet, faceSet, pointSet
946  word setType;
947  // Name of destination set.
948  word setName;
949  // Action (new, invert etc.)
950  word actionName;
951 
952  commandStatus stat = INVALID;
953 
954  if (fileStreamPtr)
955  {
956  if (!fileStreamPtr->good())
957  {
958  Info<< "End of batch file" << endl;
959  break;
960  }
961 
962  std::getline(*fileStreamPtr, rawLine);
963 
964  if (rawLine.size())
965  {
966  Info<< "Doing:" << rawLine << endl;
967  }
968  }
969  else
970  {
971 # if READLINE != 0
972  {
973  char* linePtr = readline("readline>");
974 
975  rawLine = string(linePtr);
976 
977  if (*linePtr)
978  {
979  add_history(linePtr);
980  write_history(historyFile);
981  }
982 
983  free(linePtr); // readline uses malloc, not new.
984  }
985 # else
986  {
987  Info<< "Command>" << flush;
988  std::getline(std::cin, rawLine);
989  }
990 # endif
991  }
992 
993  if (rawLine.empty() || rawLine[0] == '#')
994  {
995  continue;
996  }
997 
998  IStringStream is(rawLine + ' ');
999 
1000  // Type: cellSet, faceSet, pointSet, faceZoneSet
1001  is >> setType;
1002 
1003  stat = parseType(runTime, mesh, setType, is);
1004 
1005  if (stat == VALIDSETCMD || stat == VALIDZONECMD)
1006  {
1007  if (is >> setName)
1008  {
1009  if (is >> actionName)
1010  {
1011  stat = parseAction(actionName);
1012  }
1013  }
1014  }
1015  ok = true;
1016 
1017  if (stat == QUIT)
1018  {
1019  break;
1020  }
1021  else if (stat == VALIDSETCMD || stat == VALIDZONECMD)
1022  {
1023  ok = doCommand(mesh, setType, setName, actionName, writeVTK, is);
1024  }
1025 
1026  } while (ok);
1027 
1028 
1029  if (fileStreamPtr)
1030  {
1031  delete fileStreamPtr;
1032  }
1033 
1034  Info<< "\nEnd\n" << endl;
1035 
1036  return 0;
1037 }
1038 
1039 
1040 // ************************ vim: set sw=4 sts=4 et: ************************ //