ensightSurfaceReader.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) 2015-2024 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 "ensightSurfaceReader.H"
29 #include "ensightCase.H"
30 #include "stringOps.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37  defineTypeNameAndDebug(ensightSurfaceReader, 0);
38  addToRunTimeSelectionTable(surfaceReader, ensightSurfaceReader, fileName);
39 }
40 
41 
42 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
43 
44 namespace Foam
45 {
46 
47 // Extract timeset and fileset from split line information
48 // when the minElements has been satisfied.
49 // For example,
50 // ----
51 // model: 1 some-geometry
52 // model: 1 1 some-geometry
53 // ----
54 // would be split *after* the 'model:' resulting in these sub-strings:
55 //
56 // ("1" "some-geometry")
57 // ("1" "1" some-geometry")
58 //
59 // thus call extractTimeset with minElements == 2
60 //
61 template<class StringType>
62 static inline labelPair extractTimeset
63 (
65  const std::size_t minElements
66 )
67 {
68  ISpanStream is;
69 
70  labelPair result(-1, -1);
71  if (split.size() >= minElements)
72  {
73  is.reset(split[0]);
74  is >> result.first();
75 
76  if (split.size() > minElements)
77  {
78  is.reset(split[1]);
79  is >> result.second();
80  }
81  }
82 
83  return result;
84 }
85 
86 } // End namespace Foam
87 
88 
89 // * * * * * * * * * * Protected Static Member Functions * * * * * * * * * * //
90 
91 bool Foam::ensightSurfaceReader::readLine(ISstream& is, std::string& line)
92 {
93  do
94  {
95  is.getLine(line);
96 
97  // Trim out any '#' comments (trailing or otherwise)
98  const auto pos = line.find('#');
99  if (pos != std::string::npos)
100  {
101  line.erase(pos);
102  }
104  }
105  while (line.empty() && is.good());
106 
107  return !line.empty();
108 }
109 
110 
112 (
113  const word& expected,
114  const string& buffer,
115  const ISstream& is
116 )
117 {
118  // Be more generous with our expectations.
119  // Eg, ensight specifies the "VARIABLE" entry,
120  // but accepts "VARIABLES" as well.
121 
122  if (!expected.empty() && !buffer.starts_with(expected))
123  {
125  << "Expected section header '" << expected
126  << "' but read " << buffer << nl
127  << exit(FatalIOError);
128  }
130  DebugInfo
131  << "Read section header: " << buffer.c_str() << nl;
132 }
133 
134 
136 (
137  const word& expected,
138  ISstream& is
139 )
140 {
141  string buffer;
142  readLine(is, buffer);
143 
144  checkSection(expected, buffer, is);
145 }
146 
147 
148 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
149 
152 (
153  ensightReadFile& is
154 ) const
155 {
156  string buffer;
157 
158  Pair<idTypes> idHandling(idTypes::NONE, idTypes::NONE);
159 
160  // Ensight Geometry File
161  is.read(buffer);
162  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
163 
164  // Description - 1
165  is.read(buffer);
166  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
167 
168  // "node id (off|assign|given|ignore)" - "given" is not actually supported
169  is.read(buffer);
170  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
171 
172  if (buffer.contains("ignore"))
173  {
174  idHandling.first() = idTypes::IGNORE;
175  }
176  else if (buffer.contains("given"))
177  {
178  idHandling.first() = idTypes::GIVEN;
179  }
180 
181  // "element id (off|assign|given|ignore)"
182  is.read(buffer);
183  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
184 
185  if (buffer.contains("ignore"))
186  {
187  idHandling.second() = idTypes::IGNORE;
188  }
189  else if (buffer.contains("given"))
190  {
191  idHandling.second() = idTypes::GIVEN;
192  }
193 
194 
195  // "part" - but could also be an optional "extents"
196  is.read(buffer);
197  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
198 
199  if (buffer.contains("extents"))
200  {
201  // Optional extents - read and discard 6 floats
202  // (xmin, xmax, ymin, ymax, zmin, zmax)
203 
204  is.skip<scalar>(6);
205 
206  // "part"
207  is.read(buffer);
208  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
209  }
210 
211  // The part number
212  label intValue;
213  is.read(intValue);
214  DebugInfo<< "part number: " << intValue << nl;
215 
216  // Part description / name
217  is.read(buffer);
218  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
219 
220  // "coordinates"
221  is.read(buffer);
222  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
223 
224  return idHandling;
225 }
226 
227 
229 {
231 
232  enum ParseSection { UNKNOWN, FORMAT, GEOMETRY, VARIABLE, TIME, FILE };
233 
234  if (!is.good())
235  {
237  << "Cannot read file " << is.name()
238  << exit(FatalError);
239  }
240 
241  string buffer;
242  SubStrings<string> split;
243 
244  ParseSection parseState = ParseSection::UNKNOWN;
245 
246  // FORMAT
247  // ~~~~~~
248 
249  debugSection("FORMAT", is);
250  readLine(is, buffer); // type: ensight gold
251  parseState = ParseSection::FORMAT;
252 
253  // GEOMETRY
254  // ~~~~~~~~
255  debugSection("GEOMETRY", is);
256  parseState = ParseSection::GEOMETRY;
257 
258  do
259  {
260  readLine(is, buffer);
261 
262  if (buffer.starts_with("VARIABLE"))
263  {
264  parseState = ParseSection::VARIABLE;
265  break;
266  }
267 
268  if (buffer.contains("change_coords_only"))
269  {
271  << "No support for moving points, only topology change" << nl
272  << exit(FatalIOError);
273  }
274 
275  // Extract filename from GEOMETRY section
276  // ====
277  // model: [ts] [fs] filename [change_coords_only [cstep]]
278  //
279  // ====
280 
281  // TBD:
282  // check for "model:" vs "measured:" ?
283 
284  const auto pos_colon = buffer.find(':');
285 
286  if
287  (
288  (pos_colon == std::string::npos)
289  )
290  {
292  << "Error reading geometry 'model:'" << nl
293  << exit(FatalIOError);
294  }
295 
296  split = stringOps::splitSpace(buffer, pos_colon+1);
297 
298  if (split.empty())
299  {
301  << "Error reading geometry 'model:'" << nl
302  << exit(FatalIOError);
303  }
304 
305  // With timeset? - need at least 2 entries
306  meshTimeset_ = extractTimeset(split, 2);
307  meshFileName_ = split[split.size()-1].str();
308 
309  DebugInfo << "mesh file:" << meshFileName_ << endl;
310  }
311  while (false);
312 
313 
314  if (parseState != ParseSection::VARIABLE)
315  {
316  debugSection("VARIABLE", is);
317  parseState = ParseSection::VARIABLE;
318  }
319 
320  // Read the field description
321  DynamicList<labelPair> dynFieldTimesets(16);
322  DynamicList<word> dynFieldNames(16);
323  DynamicList<string> dynFieldFileNames(16);
324 
325  // VARIABLE
326  // ~~~~~~~~
327 
328  while (is.good())
329  {
330  readLine(is, buffer);
331 
332  if (buffer.starts_with("TIME"))
333  {
334  parseState = ParseSection::TIME;
335  break;
336  }
337 
338  // Read the field name and associated file name.
339  // Eg,
340  // scalar per element: [ts] [fs] p data/********/p
341  // but ignore
342  // scalar per node: [ts] [fs] other data/********/other
343 
344  const auto pos_colon = buffer.find(':');
345 
346  if (pos_colon == std::string::npos)
347  {
348  DebugInfo<< "ignore variable line: " << buffer << nl;
349  continue;
350  }
351 
352  // TODO? handle variable descriptions with spaces (they are quoted)
353 
354  split = stringOps::splitSpace(buffer, pos_colon+1);
355 
356  if (split.size() < 2)
357  {
359  << "Error reading field file name, variable line: "
360  << buffer << endl;
361  continue;
362  }
363 
364  auto pos_key = buffer.find("element");
365  if ((pos_key == std::string::npos) || (pos_colon < pos_key))
366  {
367  DebugInfo<< "ignore variable line: " << buffer << nl;
368  continue;
369  }
370 
371  DebugInfo<< "variable line: " << buffer << nl;
372 
373  // With timeset? - need at least 3 entries
374  dynFieldTimesets.push_back(extractTimeset(split, 3));
375 
376  dynFieldNames.push_back(split[split.size()-2].str());
377  dynFieldFileNames.push_back(split[split.size()-1].str());
378  }
379  fieldTimesets_.transfer(dynFieldTimesets);
380  fieldNames_.transfer(dynFieldNames);
381  fieldFileNames_.transfer(dynFieldFileNames);
382 
383  DebugInfo
384  << "fieldNames: " << fieldNames_ << nl
385  << "fieldFileNames: " << fieldFileNames_ << nl;
386 
387 
388  if (parseState != ParseSection::TIME)
389  {
391  << "Did not find section header 'TIME'" << nl
392  << exit(FatalIOError);
393  }
394 
395 
396  // Determine which unique timeset or fileset to expect
397 
398  labelHashSet expectTimeset;
399  labelHashSet expectFileset;
400 
401  expectTimeset.insert(meshTimeset_.first());
402  expectFileset.insert(meshTimeset_.second());
403 
404  for (const auto& tup : fieldTimesets_)
405  {
406  expectTimeset.insert(tup.first());
407  expectFileset.insert(tup.second());
408  }
409 
410  // Remove placeholders
411  expectTimeset.erase(-1);
412  expectFileset.erase(-1);
413 
414 
415  DebugInfo
416  << "expect timesets: " << flatOutput(expectTimeset) << nl
417  << "expect filesets: " << flatOutput(expectFileset) << nl;
418 
419 
420  // TIME
421  // ~~~~
422  // style 1:
423  // ====
424  // time set: <int> [description]
425  // number of steps: <int>
426  // filename start number: <int>
427  // filename increment: <int>
428  // time values: time_1 .. time_N
429  // ====
430  //
431  // style 2:
432  // ====
433  // time set: <int> [description]
434  // number of steps: <int>
435  // filename numbers: int_1 .. int_N
436  // time values: time_1 .. time_N
437  // ====
438  //
439  // style 3:
440  // ====
441  // time set: <int> [description]
442  // number of steps: <int>
443  // filename numbers file: <filename>
444  // time values file: <filename>
445  // ====
446 
447 
448  // Currently only handling style 1, style 2
449  // and only a single time set
450 
451  // time set = 1
452  {
453  // time set: <int>
454  {
455  readLine(is, buffer);
456  }
457 
458  // number of steps: <int>
459  label nTimes = 0;
460  {
461  readLine(is, buffer);
462  split = stringOps::splitSpace(buffer);
463  readFrom(split.back(), nTimes);
464  }
465 
466  // filename start number: <int>
467  // filename increment: <int>
468  //
469  // OR:
470  // filename numbers: ...
471 
472  readLine(is, buffer);
473  auto pos_colon = buffer.find(':');
474 
475  if (buffer.contains("numbers:"))
476  {
477  // Split out trailing values...
478  split = stringOps::splitSpace(buffer, pos_colon+1);
479 
480  fileNumbers_.resize_nocopy(nTimes);
481 
482  label numRead = 0;
483  while (numRead < nTimes)
484  {
485  for (const auto& chunk : split)
486  {
487  std::string str(chunk.str());
488 
489  if (!Foam::readLabel(str, fileNumbers_[numRead]))
490  {
492  << "Could not parse label: " << str << nl
493  << exit(FatalIOError);
494  }
495  ++numRead;
496 
497  if (numRead == nTimes)
498  {
499  break;
500  }
501  }
502 
503  // Get more input
504  if (numRead < nTimes)
505  {
506  readLine(is, buffer);
507  split = stringOps::splitSpace(buffer);
508  }
509  }
510 
511  timeStartIndex_ = 0;
512  timeIncrement_ = 0;
513  fileNumbers_.resize(numRead);
514  }
515  else
516  {
517  // filename start number: <int>
518  split = stringOps::splitSpace(buffer);
519  readFrom(split.back(), timeStartIndex_);
520 
521  // filename increment: <int>
522  readLine(is, buffer);
523  split = stringOps::splitSpace(buffer);
524  readFrom(split.back(), timeIncrement_);
525 
526  fileNumbers_.clear();
527  }
528 
529  DebugInfo
530  << "nTimes: " << nTimes
531  << " start-index: " << timeStartIndex_
532  << " increment: " << timeIncrement_
533  << " file numbers: " << flatOutput(fileNumbers_) << nl;
534 
535 
536  // time values: time_1 .. time_N
537  readLine(is, buffer);
538 
539  // Split out trailing values...
540  {
541  const auto pos_colon = buffer.find(':');
542  const auto pos_key = buffer.find("values");
543 
544  if
545  (
546  (pos_colon == std::string::npos)
547  || (pos_key == std::string::npos) || (pos_colon < pos_key)
548  )
549  {
550  split.clear();
551  }
552  else
553  {
554  split = stringOps::splitSpace(buffer, pos_colon+1);
555  }
556  }
557 
558  timeValues_.resize_nocopy(nTimes);
559 
560  label numRead = 0;
561  while (numRead < nTimes)
562  {
563  for (const auto& chunk : split)
564  {
565  auto& inst = timeValues_[numRead];
566 
567  // Retain character representation
568  inst.name() = word(chunk.str());
569 
570  if (!Foam::readScalar(inst.name(), inst.value()))
571  {
573  << "Could not parse scalar: " << inst.name() << nl
574  << exit(FatalIOError);
575  }
576  ++numRead;
577 
578  if (numRead == nTimes)
579  {
580  break;
581  }
582  }
583 
584  // Get more input
585  if (numRead < nTimes)
586  {
587  readLine(is, buffer);
588  split = stringOps::splitSpace(buffer);
589  }
590  }
591 
592  timeValues_.resize(numRead);
593  }
594 
595  // Not yet:
596 
597  // FILE
598  // ~~~~
599  // file set: <int>
600  // filename index: <int> - file index number in the file name
601  // number of steps: <int>
602 }
603 
604 
605 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
606 
608 (
609  const fileName& fName,
610  const dictionary& options
611 )
612 :
613  surfaceReader(fName, options),
614  masterOnly_
615  (
616  UPstream::parRun()
617  && options.getOrDefault("masterOnly", false)
618  ),
619  readFormat_(IOstreamOption::ASCII), // Placeholder value
620  baseDir_(fName.path()),
621  meshTimeset_(-1,-1),
622  timeStartIndex_(0),
623  timeIncrement_(1)
624 {
625  if (options.getOrDefault("debug", false))
626  {
627  debug |= 1;
628  }
629 
631  {
632  IFstream is(fName);
633  readCase(is);
634  }
635 
636  if (masterOnly_ && UPstream::parRun())
637  {
639  (
641  meshTimeset_,
644  fieldNames_,
648  fileNumbers_,
650  );
651  }
652 }
653 
654 
655 // * * * * * * * * * * * * * Public Member Functions * * * * * * * * * * * //
656 
658 (
659  const fileName& geometryFile,
660  const label timeIndex
661 )
662 {
664 
665  {
666  // Auto-detect ascii/binary format
667  ensightReadFile is(geometryFile);
668 
669  // Format detected from the geometry
670  readFormat_ = is.format();
671 
672  // For transient single-file
673  is.seekTime(timeIndex);
674 
675  DebugInfo
676  << "File: " << is.name()
677  << " format: "
678  << IOstreamOption::formatNames[readFormat_] << endl;
679 
680  Pair<idTypes> idHandling = readGeometryHeader(is);
681 
682  label nPoints;
683  is.read(nPoints);
684 
685  DebugInfo
686  << "nPoints: " << nPoints << nl;
687 
688  if (idHandling.first() == idTypes::GIVEN)
689  {
691  << "Treating node id 'given' as being 'ignore'" << nl
692  << "If something fails, this could be the reason" << nl
693  << endl;
694 
695  idHandling.first() = idTypes::IGNORE;
696  }
697 
698  if (idHandling.first() == idTypes::IGNORE)
699  {
700  DebugInfo
701  << "Ignore " << nPoints << " node ids" << nl;
702 
703  // Read and discard labels
704  is.skip<label>(nPoints);
705  }
706 
708  is.readPoints(nPoints, points);
709 
710 
711  // Read faces - may be a mix of tria3, quad4, nsided
712  DynamicList<face> dynFaces(nPoints/3);
713  DynamicList<faceInfoTuple> faceTypeInfo(16);
714 
715  string buffer;
716 
717  while (is.good())
718  {
719  // The element type
720  is.read(buffer);
721 
722  if (!is.good())
723  {
724  break;
725  }
726  else if (buffer.contains("BEGIN TIME STEP"))
727  {
728  // Graciously handle a miscued start
729  continue;
730  }
731  else if (buffer.contains("END TIME STEP"))
732  {
733  // END TIME STEP is a valid means to terminate input
734  break;
735  }
736 
737  if
738  (
739  buffer
740  == ensightFaces::elemNames[ensightFaces::elemType::TRIA3]
741  )
742  {
743  label elemCount;
744  is.read(elemCount);
745 
746  faceTypeInfo.emplace_back
747  (
748  ensightFaces::elemType::TRIA3,
749  elemCount
750  );
751 
752  DebugInfo
753  << "faceType <"
754  << ensightFaces::elemNames[ensightFaces::elemType::TRIA3]
755  << "> count: "
756  << elemCount << nl;
757 
758  if
759  (
760  idHandling.second() == idTypes::IGNORE
761  || idHandling.second() == idTypes::GIVEN
762  )
763  {
764  DebugInfo
765  << "Ignore " << elemCount << " element ids" << nl;
766 
767  // Read and discard labels
768  is.skip<label>(elemCount);
769  }
770 
771  // Extend and fill the new trailing portion
772  const label startElemi = dynFaces.size();
773  dynFaces.resize(startElemi+elemCount, face(3)); // tria3
774  faceList::subList myElements = dynFaces.slice(startElemi);
775 
776  for (auto& f : myElements)
777  {
778  for (label& fp : f)
779  {
780  is.read(fp);
781  }
782  }
783  }
784  else if
785  (
786  buffer
787  == ensightFaces::elemNames[ensightFaces::elemType::QUAD4]
788  )
789  {
790  label elemCount;
791  is.read(elemCount);
792 
793  faceTypeInfo.emplace_back
794  (
795  ensightFaces::elemType::QUAD4,
796  elemCount
797  );
798 
799  DebugInfo
800  << "faceType <"
801  << ensightFaces::elemNames[ensightFaces::elemType::QUAD4]
802  << "> count: "
803  << elemCount << nl;
804 
805  if
806  (
807  idHandling.second() == idTypes::IGNORE
808  || idHandling.second() == idTypes::GIVEN
809  )
810  {
811  DebugInfo
812  << "Ignore " << elemCount << " element ids" << nl;
813 
814  // Read and discard labels
815  is.skip<label>(elemCount);
816  }
817 
818  // Extend and fill the new trailing portion
819  const label startElemi = dynFaces.size();
820  dynFaces.resize(startElemi + elemCount, face(4)); // quad4
821  faceList::subList myElements = dynFaces.slice(startElemi);
822 
823  for (auto& f : myElements)
824  {
825  for (label& fp : f)
826  {
827  is.read(fp);
828  }
829  }
830  }
831  else if
832  (
833  buffer
834  == ensightFaces::elemNames[ensightFaces::elemType::NSIDED]
835  )
836  {
837  label elemCount;
838  is.read(elemCount);
839 
840  faceTypeInfo.emplace_back
841  (
842  ensightFaces::elemType::NSIDED,
843  elemCount
844  );
845 
846  DebugInfo
847  << "faceType <"
848  << ensightFaces::elemNames[ensightFaces::elemType::NSIDED]
849  << "> count: " << elemCount << nl;
850 
851  if
852  (
853  idHandling.second() == idTypes::IGNORE
854  || idHandling.second() == idTypes::GIVEN
855  )
856  {
857  DebugInfo
858  << "Ignore " << elemCount << " element ids" << nl;
859 
860  // Read and discard labels
861  is.skip<label>(elemCount);
862  }
863 
864  // Extend and fill the new trailing portion
865  const label startElemi = dynFaces.size();
866  dynFaces.resize(startElemi + elemCount);
867  faceList::subList myElements = dynFaces.slice(startElemi);
868 
869  for (auto& f : myElements)
870  {
871  label nVerts;
872  is.read(nVerts);
873 
874  f.resize(nVerts);
875  }
876 
877  for (auto& f : myElements)
878  {
879  for (label& fp : f)
880  {
881  is.read(fp);
882  }
883  }
884  }
885  else
886  {
887  if (debug)
888  {
890  << "Unknown face type: <" << buffer.c_str()
891  << ">. Stopping read and continuing with current "
892  << "elements only" << endl;
893  }
894  break;
895  }
896  }
897 
898  // From 1-based Ensight addressing to 0-based OF addressing
899  for (auto& f : dynFaces)
900  {
901  for (label& fp : f)
902  {
903  --fp;
904  }
905  }
906 
907  faceTypeInfo_.transfer(faceTypeInfo);
908  faceList faces(std::move(dynFaces));
909 
910  DebugInfo
911  << "read nFaces: " << faces.size() << nl
912  << "file schema: " << faceTypeInfo_ << nl;
914  return meshedSurface(std::move(points), std::move(faces));
915  }
916 }
917 
918 
920 (
921  const label timeIndex
922 )
923 {
925 
926  if (!surfPtr_)
927  {
928  surfPtr_.reset(new meshedSurface);
929  auto& surf = *surfPtr_;
930 
931  fileName geomFile
932  (
933  baseDir_
934  / ensightCase::expand_mask(meshFileName_, timeIndex)
935  );
936 
937  if (!masterOnly_ || UPstream::master(UPstream::worldComm))
938  {
939  surf = readGeometry(geomFile, timeIndex);
940  }
941 
942  if (masterOnly_ && UPstream::parRun())
943  {
944  // Note: don't need faceTypeInfo_ on (non-reading) ranks
946  }
947  }
948 
949  return *surfPtr_;
950 }
951 
952 
954 {
955  return timeValues_;
956 }
957 
958 
960 (
961  const label timeIndex
962 ) const
963 {
964  return fieldNames_;
965 }
966 
967 
969 (
970  const label timeIndex,
971  const label fieldIndex,
972  const scalar& refValue
973 ) const
974 {
975  return readField<scalar>(timeIndex, fieldIndex);
976 }
977 
978 
980 (
981  const label timeIndex,
982  const label fieldIndex,
983  const vector& refValue
984 ) const
985 {
986  return readField<vector>(timeIndex, fieldIndex);
987 }
988 
989 
992 (
993  const label timeIndex,
994  const label fieldIndex,
995  const sphericalTensor& refValue
996 ) const
997 {
998  return readField<sphericalTensor>(timeIndex, fieldIndex);
999 }
1000 
1001 
1003 (
1004  const label timeIndex,
1005  const label fieldIndex,
1006  const symmTensor& refValue
1007 ) const
1008 {
1009  return readField<symmTensor>(timeIndex, fieldIndex);
1010 }
1011 
1012 
1014 (
1015  const label timeIndex,
1016  const label fieldIndex,
1017  const tensor& refValue
1018 ) const
1019 {
1020  return readField<tensor>(timeIndex, fieldIndex);
1021 }
1022 
1023 
1024 // ************************************************************************* //
const T & first() const noexcept
Access the first element.
Definition: Pair.H:137
virtual wordList fieldNames(const label timeIndex) const
Return a list of the available fields at a given time.
virtual Istream & read(char *buf, std::streamsize count) override
Binary read.
static std::string::size_type length(const char *s)
Length of the character sequence (with nullptr protection)
Definition: string.H:258
A line primitive.
Definition: line.H:52
A class for handling file names.
Definition: fileName.H:72
bool contains(char c) const noexcept
True if string contains given character (cf. C++23)
Definition: string.H:411
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
static const char * elemNames[nTypes]
The ensight &#39;Face&#39; element type names.
Definition: ensightFaces.H:94
static labelPair extractTimeset(const SubStrings< StringType > &split, const std::size_t minElements)
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:153
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
static StringType expand_mask(const StringType &input, const label index)
Replace the &#39;*&#39; mask chars with zero-padded integer value.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:608
static bool readLine(ISstream &is, std::string &line)
Helper function to read an ascii line from file, skipping blank lines and comments.
virtual tmp< Field< scalar > > field(const label timeIndex, const label fieldIndex, const scalar &refValue=pTraits< scalar >::zero) const
Return a scalar field at a given time.
void reset(const char *buffer, size_t nbytes)
Reset input area, position to buffer start and clear errors.
Definition: ISpanStream.H:412
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
static const Enum< streamFormat > formatNames
Stream format names (ascii, binary)
void skip(label n=1)
Read and discard specified number of elements.
List< string > fieldFileNames_
Field file names.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1061
bool masterOnly_
Read on master and broadcast (in parallel)
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:63
List< word > fieldNames_
Field names.
A simple container for options an IOstream can normally have.
SubList< face > subList
Declare type of subList.
Definition: List.H:144
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:421
static void debugSection(const word &expected, ISstream &is)
Read and check a section header.
Sub-ranges of a string with a structure similar to std::match_results, but without the underlying reg...
Definition: CStringList.H:60
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:232
Macros for easy insertion into run-time selection tables.
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
fileName meshFileName_
Name of mesh file, including any subdirectory.
static void checkSection(const word &expected, const string &buffer, const ISstream &is)
Check a section header.
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
dimensionedScalar pos(const dimensionedScalar &ds)
void inplaceTrimRight(std::string &s)
Trim trailing whitespace inplace.
Definition: stringOps.C:979
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
const pointField & points
A class for handling words, derived from Foam::string.
Definition: word.H:63
label nPoints
MeshedSurface< face > meshedSurface
#define DebugInFunction
Report an information message using Foam::Info.
A variant of IFstream with specialised handling for Ensight reading of strings, integers and floats (...
virtual const fileName & name() const override
The name of the input serial stream. (eg, the name of the Fstream file name)
Definition: ISstream.H:147
#define DebugInfo
Report an information message using Foam::Info.
label timeStartIndex_
Start time index.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
int debug
Static debugging option.
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
label timeIncrement_
Time increment.
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
static void broadcasts(const label comm, Type &arg1, Args &&... args)
Broadcast multiple items to all communicator ranks. Does nothing in non-parallel. ...
List< labelPair > fieldTimesets_
The timeset/fileset (if any) associated with fields.
virtual instantList times() const
Return a list of the available times.
static bool split(const std::string &line, std::string &key, std::string &val)
Definition: cpuInfo.C:32
bool starts_with(char c) const
True if string starts with given character (cf. C++20)
Definition: string.H:435
Generic input stream using a standard (STL) stream.
Definition: ISstream.H:51
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:637
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:281
virtual const meshedSurface & geometry(const label timeIndex)
Return a reference to the surface geometry.
Pair< idTypes > readGeometryHeader(ensightReadFile &is) const
Read (and discard) geometry file header.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1094
labelList fileNumbers_
Numbers for files.
void readCase(ISstream &is)
Read the case file.
labelPair meshTimeset_
The timeset/fileset (if any) associated with the mesh.
ensightSurfaceReader(const ensightSurfaceReader &)=delete
No copy construct.
Foam::SubStrings< StringType > splitSpace(const StringType &str, std::string::size_type pos=0)
Split string into sub-strings at whitespace (TAB, NL, VT, FF, CR, SPC)
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
A class for managing temporary objects.
Definition: HashPtrTable.H:50
const T & second() const noexcept
Access the second element.
Definition: Pair.H:147
Tensor of scalars, i.e. Tensor<scalar>.
Abstract base class for surface readers with fields.
Definition: surfaceReader.H:67
Similar to IStringStream but using an externally managed buffer for its input. This allows the input ...
Definition: ISpanStream.H:251
Inter-processor communications stream.
Definition: UPstream.H:65
meshedSurface readGeometry(const fileName &geometryFile, const label timeIndex=0)
Read and return surface geometry. Updates faceTypeInfo_.
Namespace for OpenFOAM.
label timeIndex
Definition: getTimeIndex.H:24
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...