ensightCase.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2016-2018 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "ensightCase.H"
29 #include "stringListOps.H"
30 #include "Time.H"
31 #include "cloud.H"
32 #include "IOmanip.H"
33 #include "globalIndex.H"
34 
35 #include "ensightFile.H"
36 #include "ensightGeoFile.H"
37 #include "demandDrivenData.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 const char* Foam::ensightCase::dataDirName = "data";
42 const char* Foam::ensightCase::geometryName = "geometry";
43 
44 
45 // * * * * * * * * * * * * * Private Functions * * * * * * * * * * * * * * //
46 
47 Foam::fileName Foam::ensightCase::dataDir() const
48 {
49  return ensightDir_/dataDirName;
50 }
51 
52 
53 void Foam::ensightCase::initialize()
54 {
55  if (Pstream::master())
56  {
57  // EnSight and EnSight/data directories must exist
58 
59  // We may wish to retain old data
60  // eg, convert new results or a particular time interval
61  // OR remove everything
62 
63  if (isDir(ensightDir_))
64  {
65  if (options_->overwrite())
66  {
67  Foam::rmDir(ensightDir_);
68  }
69  else
70  {
72  <<"Warning: re-using existing directory" << nl
73  << " " << ensightDir_ << endl;
74  }
75  }
76 
77  // Create ensight and data directories
78  mkDir(dataDir());
79 
80  // The case file is always ASCII
81  os_ = new OFstream(ensightDir_/caseName_, IOstream::ASCII);
82 
83  // Format options
84  os_->setf(ios_base::left);
85  os_->setf(ios_base::scientific, ios_base::floatfield);
86  os_->precision(5);
87 
88  writeHeader();
89  }
90 }
91 
92 
93 Foam::label Foam::ensightCase::checkTimeset(const labelHashSet& lookup) const
94 {
95  // assume the worst
96  label ts = -1;
97 
98  // work on a copy
99  labelHashSet tsTimes(lookup);
100  tsTimes.erase(-1);
101 
102  if (tsTimes.empty())
103  {
104  // no times needed
105  ts = 0;
106  }
107  else if (tsTimes.size() == timesUsed_.size())
108  {
109  forAllConstIters(timesUsed_, iter)
110  {
111  tsTimes.erase(iter.key());
112  }
113 
114  // OR
115  // tsTimes.unset(timesUsed_.toc());
116 
117  if (tsTimes.empty())
118  {
119  ts = 1; // can use timeset 1
120  }
121  }
122 
123  return ts;
124 }
125 
126 
127 void Foam::ensightCase::writeHeader() const
128 {
129  if (os_) // master only
130  {
131  this->rewind();
132  *os_
133  << "FORMAT" << nl
134  << "type: ensight gold" << nl;
135  }
136 }
137 
138 
139 Foam::scalar Foam::ensightCase::writeTimeset() const
140 {
141  const label ts = 1;
142 
143  const labelList indices(timesUsed_.sortedToc());
144  label count = indices.size();
145 
146  // correct for negative starting values
147  scalar timeCorrection = timesUsed_[indices[0]];
148  if (timeCorrection < 0)
149  {
150  timeCorrection = -timeCorrection;
151  Info<< "Correcting time values. Adding " << timeCorrection << endl;
152  }
153  else
154  {
155  timeCorrection = 0;
156  }
157 
158 
159  *os_
160  << "time set: " << ts << nl
161  << "number of steps: " << count << nl;
162 
163  if (indices[0] == 0 && indices[count-1] == count-1)
164  {
165  // looks to be contiguous numbering
166  *os_
167  << "filename start number: " << 0 << nl
168  << "filename increment: " << 1 << nl;
169  }
170  else
171  {
172  *os_
173  << "filename numbers:" << nl;
174 
175  count = 0;
176  for (const label idx : indices)
177  {
178  *os_ << ' ' << setw(12) << idx;
179 
180  if (++count % 6 == 0)
181  {
182  *os_ << nl;
183  }
184  }
185 
186  if (count)
187  {
188  *os_ << nl;
189  }
190  }
191 
192 
193  *os_ << "time values:" << nl;
194 
195  count = 0;
196  for (const label idx : indices)
197  {
198  *os_ << ' ' << setw(12) << timesUsed_[idx] + timeCorrection;
199 
200  if (++count % 6 == 0)
201  {
202  *os_ << nl;
203  }
204  }
205  if (count)
206  {
207  *os_ << nl;
208  }
209 
210  return timeCorrection;
211 }
212 
213 
214 void Foam::ensightCase::writeTimeset
215 (
216  const label ts,
217  const labelHashSet& lookup,
218  const scalar timeCorrection
219 ) const
220 {
221  // make a copy
222  labelHashSet hashed(lookup);
223  hashed.erase(-1);
224 
225  const labelList indices(hashed.sortedToc());
226  label count = indices.size();
227 
228  *os_
229  << "time set: " << ts << nl
230  << "number of steps: " << count << nl
231  << "filename numbers:" << nl;
232 
233  count = 0;
234  for (const label idx : indices)
235  {
236  *os_ << ' ' << setw(12) << idx;
237 
238  if (++count % 6 == 0)
239  {
240  *os_ << nl;
241  }
242  }
243 
244  if (count)
245  {
246  *os_ << nl;
247  }
248 
249  *os_ << "time values:" << nl;
250 
251  count = 0;
252  for (const label idx : indices)
253  {
254  *os_ << ' ' << setw(12) << timesUsed_[idx] + timeCorrection;
255 
256  if (++count % 6 == 0)
257  {
258  *os_ << nl;
259  }
260  }
261  if (count)
262  {
263  *os_ << nl;
264  }
265 }
266 
267 
268 void Foam::ensightCase::noteGeometry(const bool moving) const
269 {
270  if (moving)
271  {
272  geomTimes_.insert(timeIndex_);
273  }
274  else
275  {
276  geomTimes_.insert(-1);
277  }
278 
279  changed_ = true;
280 }
281 
282 
283 void Foam::ensightCase::noteCloud(const word& cloudName) const
284 {
285  if (!cloudVars_.found(cloudName))
286  {
287  cloudVars_.insert(cloudName, HashTable<string>());
288  }
289  cloudTimes_.insert(timeIndex_);
290 
291  changed_ = true;
292 }
293 
294 
295 void Foam::ensightCase::noteCloud
296 (
297  const word& cloudName,
298  const word& varName,
299  const char* ensightType
300 ) const
301 {
302  if (cloudVars_.found(cloudName))
303  {
304  if (cloudVars_[cloudName].insert(varName, ensightType))
305  {
306  changed_ = true;
307  }
308  }
309  else
310  {
312  << "Tried to add a cloud variable for writing"
313  << " - without having added a cloud"
314  << abort(FatalError);
315  }
316 }
317 
318 
319 void Foam::ensightCase::noteVariable
320 (
321  const word& varName,
322  const char* ensightType
323 ) const
324 {
325  if (variables_.insert(varName, ensightType))
326  {
327  changed_ = true;
328  }
329 }
330 
331 
333 Foam::ensightCase::createDataFile
334 (
335  const word& name
336 ) const
337 {
338  if (Pstream::master())
339  {
340  // The data/ITER subdirectory must exist
341  // Note that data/ITER is indeed a valid ensight::FileName
342  const fileName outdir = dataDir()/padded(timeIndex_);
343  mkDir(outdir);
344 
345  return autoPtr<ensightFile>::New(outdir, name, format());
346  }
347 
348  return nullptr;
349 }
350 
351 
353 Foam::ensightCase::createCloudFile
354 (
355  const word& cloudName,
356  const word& name
357 ) const
358 {
359  if (Pstream::master())
360  {
361  // Write
362  // eg -> "data/********/lagrangian/<cloudName>/positions"
363  // or -> "lagrangian/<cloudName>/********/positions"
364  // TODO? check that cloudName is a valid ensight filename
365  const fileName outdir =
366  (
367  separateCloud()
368  ? (ensightDir_ / cloud::prefix / cloudName / padded(timeIndex_))
369  : (dataDir() / padded(timeIndex_) / cloud::prefix / cloudName)
370  );
371 
372  mkDir(outdir); // should be unnecessary after newCloud()
373 
374  return autoPtr<ensightFile>::New(outdir, name, format());
375  }
376 
377  return nullptr;
378 }
379 
380 
381 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
382 
383 Foam::ensightCase::ensightCase
384 (
385  const fileName& ensightDir,
386  const word& caseName,
387  const ensightCase::options& opts
388 )
389 :
390  options_(new options(opts)),
391  ensightDir_(ensightDir),
392  caseName_(caseName + ".case"),
393  os_(nullptr),
394  changed_(false),
395  timeIndex_(0),
396  timeValue_(0),
397  timesUsed_(),
398  geomTimes_(),
399  cloudTimes_(),
400  variables_(),
401  cloudVars_()
402 {
403  initialize();
404 }
405 
406 
407 Foam::ensightCase::ensightCase
408 (
409  const fileName& ensightDir,
410  const word& caseName,
412 )
413 :
414  options_(new options(format)),
415  ensightDir_(ensightDir),
416  caseName_(caseName + ".case"),
417  os_(nullptr),
418  changed_(false),
419  timeIndex_(0),
420  timeValue_(0),
421  timesUsed_(),
422  geomTimes_(),
423  cloudTimes_(),
424  variables_(),
425  cloudVars_()
426 {
427  initialize();
428 }
429 
430 
431 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
432 
434 {
435  deleteDemandDrivenData(options_);
437 }
438 
439 
440 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
441 
442 void Foam::ensightCase::nextTime(const scalar value)
443 {
444  // use next available index
445  setTime(value, timesUsed_.size());
446 }
447 
448 
450 {
451  nextTime(t.value());
452 }
453 
454 
455 void Foam::ensightCase::setTime(const scalar value, const label index)
456 {
457  timeIndex_ = index;
458  timeValue_ = value;
459 
460  if (Pstream::master())
461  {
462  // The data/ITER subdirectory must exist
463  // Note that data/ITER is indeed a valid ensight::FileName
464 
465  const fileName outdir = dataDir()/padded(timeIndex_);
466  mkDir(outdir);
467 
468  // place a timestamp in the directory for future reference
469  OFstream timeStamp(outdir/"time");
470  timeStamp
471  << "# index time" << nl
472  << outdir.name() << ' ' << timeValue_ << nl;
473  }
474 
475  // Record of time index/value used
476  timesUsed_.set(index, value);
477 }
478 
479 
480 void Foam::ensightCase::setTime(const instant& t, const label index)
481 {
482  setTime(t.value(), index);
483 }
484 
485 
487 {
488  if (!os_) return; // master only
489 
490  // geometry timeset
491  const bool staticGeom = (geomTimes_.size() == 1 && geomTimes_.found(-1));
492  label tsGeom = staticGeom ? 0 : checkTimeset(geomTimes_);
493 
494  // geometry index, when mesh is not moving but stored under data/XXX/
495  label meshIndex = -1;
496 
497  // cloud timeset
498  label tsCloud = checkTimeset(cloudTimes_);
499 
500  // Increment time-sets to the correct indices
501  if (tsGeom < 0)
502  {
503  tsGeom = 2; // Next available timeset
504 
505  // Saved under data/XXX/geometry, but not actually moving
506  if (geomTimes_.size() == 1)
507  {
508  tsGeom = 0;
509  meshIndex = *(geomTimes_.begin());
510  }
511  }
512  if (tsCloud < 0)
513  {
514  tsCloud = 1 + std::max(label(1), tsGeom); // Next available timeset
515  }
516 
517  writeHeader();
518 
519 
520  // data mask: eg "data/******"
521  const fileName dataMask = (dataDirName/mask());
522 
523  //
524  // GEOMETRY
525  //
526  if (!geomTimes_.empty() || !cloudTimes_.empty())
527  {
528  // start of variables
529  *os_
530  << nl
531  << "GEOMETRY" << nl;
532  }
533 
534  if (staticGeom)
535  {
536  // Steady
537  *os_
538  << setw(16) << "model:"
539  << geometryName
540  << nl;
541  }
542  else if (meshIndex >= 0)
543  {
544  // Not really moving, but stored under data/XXXX/geometry
545  *os_
546  << setw(16) << "model:"
547  << (dataDirName/padded(meshIndex)/geometryName).c_str()
548  << nl;
549  }
550  else if (!geomTimes_.empty())
551  {
552  // Moving
553  *os_
554  << word::printf("model: %-9d", tsGeom) // width 16 (no quotes)
555  << (dataMask/geometryName).c_str()
556  << nl;
557  }
558 
559  // Clouds and cloud variables
560  const wordList cloudNames(cloudVars_.sortedToc());
561 
562  for (const word& cloudName : cloudNames)
563  {
564  const fileName masked =
565  (
566  separateCloud()
567  ? (cloud::prefix / cloudName / mask())
568  : (dataMask / cloud::prefix / cloudName)
569  );
570 
571  *os_
572  << word::printf("measured: %-6d", tsCloud) // width 16 (no quotes)
573  << (masked/"positions").c_str()
574  << nl;
575  }
576 
577 
578  //
579  // VARIABLE
580  //
581  if (variables_.size() || cloudVars_.size())
582  {
583  // start of variables
584  *os_
585  << nl
586  << "VARIABLE" << nl;
587  }
588 
589 
590  // Field variables (always use timeset 1)
591  const wordList varNames(variables_.sortedToc());
592 
593  for (const word& varName : varNames)
594  {
595  const string& ensType = variables_[varName];
596 
597  *os_
598  << ensType.c_str()
599  <<
600  (
601  nodeValues()
602  ? " per node: 1 " // time-set 1
603  : " per element: 1 " // time-set 1
604  )
605  << setw(15) << varName << ' '
606  << (dataMask/varName).c_str() << nl;
607  }
608 
609 
610  // Clouds and cloud variables (using cloud timeset)
611  // Write
612  // as -> "data/********/lagrangian/<cloudName>/positions"
613  // or -> "lagrangian/<cloudName>/********/positions"
614 
615  label cloudNo = 0;
616  for (const word& cloudName : cloudNames)
617  {
618  const fileName masked =
619  (
620  separateCloud()
621  ? (cloud::prefix / cloudName / mask())
622  : (dataMask / cloud::prefix / cloudName)
623  );
624 
625  const HashTable<string>& vars = cloudVars_[cloudName];
626 
627  for (const word& varName : vars.sortedToc())
628  {
629  const string& ensType = vars[varName];
630 
631  // prefix variables with 'c' (cloud) and cloud index
632  *os_
633  << ensType.c_str() << " per "
634  << word::printf("measured node: %-5d", tsCloud) // width 20
635  << setw(15)
636  << ("c" + Foam::name(cloudNo) + varName).c_str() << ' '
637  << (masked/varName).c_str()
638  << nl;
639  }
640 
641  ++cloudNo;
642  }
643 
644 
645  //
646  // TIME
647  //
648 
649  if (!timesUsed_.empty())
650  {
651  *os_
652  << nl << "TIME" << nl;
653 
654  // timeset 1
655  const scalar timeCorrection = writeTimeset();
656 
657  // timeset geometry
658  if (tsGeom > 1)
659  {
660  writeTimeset(tsGeom, geomTimes_, timeCorrection);
661  }
662 
663  // timeset cloud
664  if (tsCloud > 1)
665  {
666  writeTimeset(tsCloud, cloudTimes_, timeCorrection);
667  }
668 
669  *os_
670  << "# end" << nl;
671  }
672 
673  *os_ << flush;
674  changed_ = false;
675 }
676 
677 
680 (
681  const bool moving
682 ) const
683 {
685 
686  if (Pstream::master())
687  {
688  // Set the path of the ensight file
689  fileName path;
690 
691  if (moving)
692  {
693  // Moving mesh: write as "data/********/geometry"
694  path = dataDir()/padded(timeIndex_);
695  mkDir(path);
696  }
697  else
698  {
699  // Static mesh: write as "geometry"
700  path = ensightDir_;
701  }
702 
703  noteGeometry(moving); // note for later use
704 
705  return autoPtr<ensightGeoFile>::New(path, geometryName, format());
706  }
707 
708  return nullptr;
709 }
710 
711 
714 (
715  const word& cloudName
716 ) const
717 {
719 
720  if (Pstream::master())
721  {
722  output = createCloudFile(cloudName, "positions");
723 
724  // Tag binary format (just like geometry files)
725  output().writeBinaryHeader();
726 
727  // Description
728  output().write(cloud::prefix/cloudName);
729  output().newline();
730 
731  noteCloud(cloudName); // note for later use
732  }
733 
734  return output;
735 }
736 
737 
739 {
740  if (os_) // master only
741  {
742  os_->stdStream().seekp(0, std::ios_base::beg);
743  }
744 }
745 
746 
748 {
749  os << "Ensight case:" << nl
750  << " path: " << ensightDir_ << nl
751  << " name: " << caseName_ << nl
752  << " format: " << format() << nl
753  << " values per " << (nodeValues() ? "node" : "element") << nl;
754 
755  return os;
756 }
757 
758 
759 // ************************************************************************* //
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
Construct autoPtr of T with forwarding arguments.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
insert
srcOptions insert("case", fileName(rootDirSource/caseDirSource))
Foam::cloud::prefix
static const word prefix
The prefix to local: lagrangian.
Definition: cloud.H:87
Foam::ensightCase::~ensightCase
~ensightCase()
Destructor.
Definition: ensightCase.C:433
Foam::ensightCase::nextTime
void nextTime(const scalar t)
Set time for time-set 1, using next available index.
Definition: ensightCase.C:442
ensightCase.H
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
cloudName
const word cloudName(propsDict.get< word >("cloud"))
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::ensightCase::setTime
void setTime(const scalar t, const label index)
Set current index and time for time-set 1.
Definition: ensightCase.C:455
Foam::ensightCase::printInfo
Ostream & printInfo(Ostream &os) const
Print some general information.
Definition: ensightCase.C:747
Foam::ensightCase::write
void write() const
Write the case file.
Definition: ensightCase.C:486
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
globalIndex.H
Foam::fileName::name
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Definition: fileNameI.H:209
cloud.H
Foam::ensightCase::rewind
void rewind() const
Rewind the output stream (master only).
Definition: ensightCase.C:738
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::writeHeader
static void writeHeader(Ostream &os, const word &fieldName)
Definition: rawSurfaceWriterImpl.C:49
setTime
runTimeSource setTime(sourceTimes[sourceTimeIndex], sourceTimeIndex)
Foam::deleteDemandDrivenData
void deleteDemandDrivenData(DataPtr &dataPtr)
Definition: demandDrivenData.H:42
Foam::flush
Ostream & flush(Ostream &os)
Flush stream.
Definition: Ostream.H:329
format
word format(conversionProperties.get< word >("format"))
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:62
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
ensightFile.H
Foam::cellModeller::lookup
const cellModel * lookup(const word &modelName)
Deprecated(2017-11) equivalent to cellModel::ptr static method.
Definition: cellModeller.H:46
Foam::ensightCase::dataDirName
static const char * dataDirName
The name for "data" subdirectory.
Definition: ensightCase.H:68
IOmanip.H
Istream and Ostream manipulators taking arguments.
DetailInfo
#define DetailInfo
Definition: evalEntry.C:36
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::IOstreamOption::streamFormat
streamFormat
Data format (ascii | binary)
Definition: IOstreamOption.H:64
Foam::FatalError
error FatalError
cloudNames
const wordList cloudNames(cloudFields.sortedToc())
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::setw
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
Foam::HashTable::sortedToc
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition: HashTable.C:136
Foam::scientific
IOstream & scientific(IOstream &io)
Definition: IOstream.H:447
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:99
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:438
Foam::HashTable
A HashTable similar to std::unordered_map.
Definition: HashTable.H:105
Time.H
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
ensightGeoFile.H
Foam::IOstreamOption::ASCII
"ascii"
Definition: IOstreamOption.H:66
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::nl
constexpr char nl
Definition: Ostream.H:372
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
Foam::rmDir
bool rmDir(const fileName &directory, const bool silent=false)
Remove a dirctory and its contents (optionally silencing warnings)
Definition: MSwindows.C:1018
Foam::BitOps::count
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition: BitOps.H:74
Foam::List< word >
Foam::Instant::value
scalar value() const
The value (const access)
Definition: Instant.H:99
path
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
Foam::ensightCase::options
Configuration options for the ensightCase.
Definition: ensightCase.H:313
Foam::ensightCase::newGeometry
autoPtr< ensightGeoFile > newGeometry(const bool moving=false) const
Open stream for new geometry file (on master).
Definition: ensightCase.C:680
Foam::word::printf
static word printf(const char *fmt, const PrimitiveType &val)
Use a printf-style formatter for a primitive.
stringListOps.H
Operations on lists of strings.
Foam::ensightCase::newCloud
autoPtr< ensightFile > newCloud(const word &cloudName) const
Open stream for new cloud positions (on master).
Definition: ensightCase.C:714
Foam::instant
An instant of time. Contains the time value and name.
Definition: instant.H:52
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::labelHashSet
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys and label hasher.
Definition: HashSet.H:415
Foam::mkDir
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:507
Foam::ensightCase::geometryName
static const char * geometryName
The name for geometry files.
Definition: ensightCase.H:76
Foam::isDir
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: MSwindows.C:643