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-2025 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 static inline labelPair extractTimeset
62 (
63  const SubStrings& split,
64  const std::size_t minElements
65 )
66 {
67  ISpanStream is;
68 
69  labelPair result(-1, -1);
70  if (split.size() >= minElements)
71  {
72  is.reset(split[0]);
73  is >> result.first();
74 
75  if (split.size() > minElements)
76  {
77  is.reset(split[1]);
78  is >> result.second();
79  }
80  }
81 
82  return result;
83 }
84 
85 } // End namespace Foam
86 
87 
88 // * * * * * * * * * * Protected Static Member Functions * * * * * * * * * * //
89 
90 bool Foam::ensightSurfaceReader::readLine(ISstream& is, std::string& line)
91 {
92  do
93  {
94  is.getLine(line);
95 
96  // Trim out any '#' comments (trailing or otherwise)
97  const auto pos = line.find('#');
98  if (pos != std::string::npos)
99  {
100  line.erase(pos);
101  }
103  }
104  while (line.empty() && is.good());
105 
106  return !line.empty();
107 }
108 
109 
111 (
112  const word& expected,
113  const string& buffer,
114  const ISstream& is
115 )
116 {
117  // Be more generous with our expectations.
118  // Eg, ensight specifies the "VARIABLE" entry,
119  // but accepts "VARIABLES" as well.
120 
121  if (!expected.empty() && !buffer.starts_with(expected))
122  {
124  << "Expected section header '" << expected
125  << "' but read " << buffer << nl
126  << exit(FatalIOError);
127  }
129  DebugInfo
130  << "Read section header: " << buffer.c_str() << nl;
131 }
132 
133 
135 (
136  const word& expected,
137  ISstream& is
138 )
139 {
140  string buffer;
141  readLine(is, buffer);
142 
143  checkSection(expected, buffer, is);
144 }
145 
146 
147 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
148 
151 (
152  ensightReadFile& is
153 ) const
154 {
155  string buffer;
156 
157  Pair<idTypes> idHandling(idTypes::NONE, idTypes::NONE);
158 
159  // Ensight Geometry File
160  is.read(buffer);
161  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
162 
163  // Description - 1
164  is.read(buffer);
165  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
166 
167  // "node id (off|assign|given|ignore)" - "given" is not actually supported
168  is.read(buffer);
169  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
170 
171  if (buffer.contains("ignore"))
172  {
173  idHandling.first() = idTypes::IGNORE;
174  }
175  else if (buffer.contains("given"))
176  {
177  idHandling.first() = idTypes::GIVEN;
178  }
179 
180  // "element id (off|assign|given|ignore)"
181  is.read(buffer);
182  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
183 
184  if (buffer.contains("ignore"))
185  {
186  idHandling.second() = idTypes::IGNORE;
187  }
188  else if (buffer.contains("given"))
189  {
190  idHandling.second() = idTypes::GIVEN;
191  }
192 
193 
194  // "part" - but could also be an optional "extents"
195  is.read(buffer);
196  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
197 
198  if (buffer.contains("extents"))
199  {
200  // Optional extents - read and discard 6 floats
201  // (xmin, xmax, ymin, ymax, zmin, zmax)
202 
203  is.skip<scalar>(6);
204 
205  // "part"
206  is.read(buffer);
207  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
208  }
209 
210  // The part number
211  label intValue;
212  is.read(intValue);
213  DebugInfo<< "part number: " << intValue << nl;
214 
215  // Part description / name
216  is.read(buffer);
217  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
218 
219  // "coordinates"
220  is.read(buffer);
221  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
222 
223  return idHandling;
224 }
225 
226 
228 {
230 
231  enum ParseSection { UNKNOWN, FORMAT, GEOMETRY, VARIABLE, TIME, FILE };
232 
233  if (!is.good())
234  {
236  << "Cannot read file " << is.name()
237  << exit(FatalError);
238  }
239 
240  string buffer;
241  SubStrings split;
242 
243  ParseSection parseState = ParseSection::UNKNOWN;
244 
245  // FORMAT
246  // ~~~~~~
247 
248  debugSection("FORMAT", is);
249  readLine(is, buffer); // type: ensight gold
250  parseState = ParseSection::FORMAT;
251 
252  // GEOMETRY
253  // ~~~~~~~~
254  debugSection("GEOMETRY", is);
255  parseState = ParseSection::GEOMETRY;
256 
257  do
258  {
259  readLine(is, buffer);
260 
261  if (buffer.starts_with("VARIABLE"))
262  {
263  parseState = ParseSection::VARIABLE;
264  break;
265  }
266 
267  if (buffer.contains("change_coords_only"))
268  {
270  << "No support for moving points, only topology change" << nl
271  << exit(FatalIOError);
272  }
273 
274  // Extract filename from GEOMETRY section
275  // ====
276  // model: [ts] [fs] filename [change_coords_only [cstep]]
277  //
278  // ====
279 
280  // TBD:
281  // check for "model:" vs "measured:" ?
282 
283  const auto pos_colon = buffer.find(':');
284 
285  if
286  (
287  (pos_colon == std::string::npos)
288  )
289  {
291  << "Error reading geometry 'model:'" << nl
292  << exit(FatalIOError);
293  }
294 
295  split = stringOps::splitSpace(buffer, pos_colon+1);
296 
297  if (split.empty())
298  {
300  << "Error reading geometry 'model:'" << nl
301  << exit(FatalIOError);
302  }
303 
304  // With timeset? - need at least 2 entries
305  meshTimeset_ = extractTimeset(split, 2);
306  meshFileName_ = split[split.size()-1].str();
307 
308  DebugInfo << "mesh file:" << meshFileName_ << endl;
309  }
310  while (false);
311 
312 
313  if (parseState != ParseSection::VARIABLE)
314  {
315  debugSection("VARIABLE", is);
316  parseState = ParseSection::VARIABLE;
317  }
318 
319  // Read the field description
320  DynamicList<labelPair> dynFieldTimesets(16);
321  DynamicList<word> dynFieldNames(16);
322  DynamicList<string> dynFieldFileNames(16);
323 
324  // VARIABLE
325  // ~~~~~~~~
326 
327  while (is.good())
328  {
329  readLine(is, buffer);
330 
331  if (buffer.starts_with("TIME"))
332  {
333  parseState = ParseSection::TIME;
334  break;
335  }
336 
337  // Read the field name and associated file name.
338  // Eg,
339  // scalar per element: [ts] [fs] p data/********/p
340  // but ignore
341  // scalar per node: [ts] [fs] other data/********/other
342 
343  const auto pos_colon = buffer.find(':');
344 
345  if (pos_colon == std::string::npos)
346  {
347  DebugInfo<< "ignore variable line: " << buffer << nl;
348  continue;
349  }
350 
351  // TODO? handle variable descriptions with spaces (they are quoted)
352 
353  split = stringOps::splitSpace(buffer, pos_colon+1);
354 
355  if (split.size() < 2)
356  {
358  << "Error reading field file name, variable line: "
359  << buffer << endl;
360  continue;
361  }
362 
363  auto pos_key = buffer.find("element");
364  if ((pos_key == std::string::npos) || (pos_colon < pos_key))
365  {
366  DebugInfo<< "ignore variable line: " << buffer << nl;
367  continue;
368  }
369 
370  DebugInfo<< "variable line: " << buffer << nl;
371 
372  // With timeset? - need at least 3 entries
373  dynFieldTimesets.push_back(extractTimeset(split, 3));
374 
375  dynFieldNames.push_back(split[split.size()-2].str());
376  dynFieldFileNames.push_back(split[split.size()-1].str());
377  }
378  fieldTimesets_.transfer(dynFieldTimesets);
379  fieldNames_.transfer(dynFieldNames);
380  fieldFileNames_.transfer(dynFieldFileNames);
381 
382  DebugInfo
383  << "fieldNames: " << fieldNames_ << nl
384  << "fieldFileNames: " << fieldFileNames_ << nl;
385 
386 
387  if (parseState != ParseSection::TIME)
388  {
390  << "Did not find section header 'TIME'" << nl
391  << exit(FatalIOError);
392  }
393 
394 
395  // Determine which unique timeset or fileset to expect
396 
397  labelHashSet expectTimeset;
398  labelHashSet expectFileset;
399 
400  expectTimeset.insert(meshTimeset_.first());
401  expectFileset.insert(meshTimeset_.second());
402 
403  for (const auto& tup : fieldTimesets_)
404  {
405  expectTimeset.insert(tup.first());
406  expectFileset.insert(tup.second());
407  }
408 
409  // Remove placeholders
410  expectTimeset.erase(-1);
411  expectFileset.erase(-1);
412 
413 
414  DebugInfo
415  << "expect timesets: " << flatOutput(expectTimeset) << nl
416  << "expect filesets: " << flatOutput(expectFileset) << nl;
417 
418 
419  // TIME
420  // ~~~~
421  // style 1:
422  // ====
423  // time set: <int> [description]
424  // number of steps: <int>
425  // filename start number: <int>
426  // filename increment: <int>
427  // time values: time_1 .. time_N
428  // ====
429  //
430  // style 2:
431  // ====
432  // time set: <int> [description]
433  // number of steps: <int>
434  // filename numbers: int_1 .. int_N
435  // time values: time_1 .. time_N
436  // ====
437  //
438  // style 3:
439  // ====
440  // time set: <int> [description]
441  // number of steps: <int>
442  // filename numbers file: <filename>
443  // time values file: <filename>
444  // ====
445 
446 
447  // Currently only handling style 1, style 2
448  // and only a single time set
449 
450  // time set = 1
451  {
452  // time set: <int>
453  {
454  readLine(is, buffer);
455  }
456 
457  // number of steps: <int>
458  label nTimes = 0;
459  {
460  readLine(is, buffer);
461  split = stringOps::splitSpace(buffer);
462  readFrom(split.back(), nTimes);
463  }
464 
465  // filename start number: <int>
466  // filename increment: <int>
467  //
468  // OR:
469  // filename numbers: ...
470 
471  readLine(is, buffer);
472  auto pos_colon = buffer.find(':');
473 
474  if (buffer.contains("numbers:"))
475  {
476  // Split out trailing values...
477  split = stringOps::splitSpace(buffer, pos_colon+1);
478 
479  fileNumbers_.resize_nocopy(nTimes);
480 
481  label numRead = 0;
482  while (numRead < nTimes)
483  {
484  for (const auto& chunk : split)
485  {
486  std::string str(chunk.str());
487 
488  if (!Foam::readLabel(str, fileNumbers_[numRead]))
489  {
491  << "Could not parse label: " << str << nl
492  << exit(FatalIOError);
493  }
494  ++numRead;
495 
496  if (numRead == nTimes)
497  {
498  break;
499  }
500  }
501 
502  // Get more input
503  if (numRead < nTimes)
504  {
505  readLine(is, buffer);
506  split = stringOps::splitSpace(buffer);
507  }
508  }
509 
510  timeStartIndex_ = 0;
511  timeIncrement_ = 0;
512  fileNumbers_.resize(numRead);
513  }
514  else
515  {
516  // filename start number: <int>
517  split = stringOps::splitSpace(buffer);
518  readFrom(split.back(), timeStartIndex_);
519 
520  // filename increment: <int>
521  readLine(is, buffer);
522  split = stringOps::splitSpace(buffer);
523  readFrom(split.back(), timeIncrement_);
524 
525  fileNumbers_.clear();
526  }
527 
528  DebugInfo
529  << "nTimes: " << nTimes
530  << " start-index: " << timeStartIndex_
531  << " increment: " << timeIncrement_
532  << " file numbers: " << flatOutput(fileNumbers_) << nl;
533 
534 
535  // time values: time_1 .. time_N
536  readLine(is, buffer);
537 
538  // Split out trailing values...
539  {
540  const auto pos_colon = buffer.find(':');
541  const auto pos_key = buffer.find("values");
542 
543  if
544  (
545  (pos_colon == std::string::npos)
546  || (pos_key == std::string::npos) || (pos_colon < pos_key)
547  )
548  {
549  split.clear();
550  }
551  else
552  {
553  split = stringOps::splitSpace(buffer, pos_colon+1);
554  }
555  }
556 
557  timeValues_.resize_nocopy(nTimes);
558 
559  label numRead = 0;
560  while (numRead < nTimes)
561  {
562  for (const auto& chunk : split)
563  {
564  auto& inst = timeValues_[numRead];
565 
566  // Retain character representation
567  inst.name() = word(chunk.str());
568 
569  if (!Foam::readScalar(inst.name(), inst.value()))
570  {
572  << "Could not parse scalar: " << inst.name() << nl
573  << exit(FatalIOError);
574  }
575  ++numRead;
576 
577  if (numRead == nTimes)
578  {
579  break;
580  }
581  }
582 
583  // Get more input
584  if (numRead < nTimes)
585  {
586  readLine(is, buffer);
587  split = stringOps::splitSpace(buffer);
588  }
589  }
590 
591  timeValues_.resize(numRead);
592  }
593 
594  // Not yet:
595 
596  // FILE
597  // ~~~~
598  // file set: <int>
599  // filename index: <int> - file index number in the file name
600  // number of steps: <int>
601 }
602 
603 
604 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
605 
607 (
608  const fileName& fName,
609  const dictionary& options
610 )
611 :
612  surfaceReader(fName, options),
613  masterOnly_
614  (
615  UPstream::parRun()
616  && options.getOrDefault("masterOnly", false)
617  ),
618  readFormat_(IOstreamOption::ASCII), // Placeholder value
619  baseDir_(fName.path()),
620  meshTimeset_(-1,-1),
621  timeStartIndex_(0),
622  timeIncrement_(1)
623 {
624  if (options.getOrDefault("debug", false))
625  {
626  debug |= 1;
627  }
628 
630  {
631  IFstream is(fName);
632  readCase(is);
633  }
634 
635  if (masterOnly_ && UPstream::parRun())
636  {
638  (
640  meshTimeset_,
643  fieldNames_,
647  fileNumbers_,
649  );
650  }
651 }
652 
653 
654 // * * * * * * * * * * * * * Public Member Functions * * * * * * * * * * * //
655 
657 (
658  const fileName& geometryFile,
659  const label timeIndex
660 )
661 {
663 
664  {
665  // Auto-detect ascii/binary format
666  ensightReadFile is(geometryFile);
667 
668  // Format detected from the geometry
669  readFormat_ = is.format();
670 
671  // For transient single-file
672  is.seekTime(timeIndex);
673 
674  DebugInfo
675  << "File: " << is.name()
676  << " format: "
677  << IOstreamOption::formatNames[readFormat_] << endl;
678 
679  Pair<idTypes> idHandling = readGeometryHeader(is);
680 
681  label nPoints;
682  is.read(nPoints);
683 
684  DebugInfo
685  << "nPoints: " << nPoints << nl;
686 
687  if (idHandling.first() == idTypes::GIVEN)
688  {
690  << "Treating node id 'given' as being 'ignore'" << nl
691  << "If something fails, this could be the reason" << nl
692  << endl;
693 
694  idHandling.first() = idTypes::IGNORE;
695  }
696 
697  if (idHandling.first() == idTypes::IGNORE)
698  {
699  DebugInfo
700  << "Ignore " << nPoints << " node ids" << nl;
701 
702  // Read and discard labels
703  is.skip<label>(nPoints);
704  }
705 
707  is.readPoints(nPoints, points);
708 
709 
710  // Read faces - may be a mix of tria3, quad4, nsided
711  DynamicList<face> dynFaces(nPoints/3);
712  DynamicList<faceInfoTuple> faceTypeInfo(16);
713 
714  string buffer;
715 
716  while (is.good())
717  {
718  // The element type
719  is.read(buffer);
720 
721  if (!is.good())
722  {
723  break;
724  }
725  else if (buffer.contains("BEGIN TIME STEP"))
726  {
727  // Graciously handle a miscued start
728  continue;
729  }
730  else if (buffer.contains("END TIME STEP"))
731  {
732  // END TIME STEP is a valid means to terminate input
733  break;
734  }
735 
736  if
737  (
738  buffer
739  == ensightFaces::elemNames[ensightFaces::elemType::TRIA3]
740  )
741  {
742  label elemCount;
743  is.read(elemCount);
744 
745  faceTypeInfo.emplace_back
746  (
747  ensightFaces::elemType::TRIA3,
748  elemCount
749  );
750 
751  DebugInfo
752  << "faceType <"
753  << ensightFaces::elemNames[ensightFaces::elemType::TRIA3]
754  << "> count: "
755  << elemCount << nl;
756 
757  if
758  (
759  idHandling.second() == idTypes::IGNORE
760  || idHandling.second() == idTypes::GIVEN
761  )
762  {
763  DebugInfo
764  << "Ignore " << elemCount << " element ids" << nl;
765 
766  // Read and discard labels
767  is.skip<label>(elemCount);
768  }
769 
770  // Extend and fill the new trailing portion
771  const label startElemi = dynFaces.size();
772  dynFaces.resize(startElemi+elemCount, face(3)); // tria3
773  faceList::subList myElements = dynFaces.slice(startElemi);
774 
775  for (auto& f : myElements)
776  {
777  for (label& fp : f)
778  {
779  is.read(fp);
780  }
781  }
782  }
783  else if
784  (
785  buffer
786  == ensightFaces::elemNames[ensightFaces::elemType::QUAD4]
787  )
788  {
789  label elemCount;
790  is.read(elemCount);
791 
792  faceTypeInfo.emplace_back
793  (
794  ensightFaces::elemType::QUAD4,
795  elemCount
796  );
797 
798  DebugInfo
799  << "faceType <"
800  << ensightFaces::elemNames[ensightFaces::elemType::QUAD4]
801  << "> count: "
802  << elemCount << nl;
803 
804  if
805  (
806  idHandling.second() == idTypes::IGNORE
807  || idHandling.second() == idTypes::GIVEN
808  )
809  {
810  DebugInfo
811  << "Ignore " << elemCount << " element ids" << nl;
812 
813  // Read and discard labels
814  is.skip<label>(elemCount);
815  }
816 
817  // Extend and fill the new trailing portion
818  const label startElemi = dynFaces.size();
819  dynFaces.resize(startElemi + elemCount, face(4)); // quad4
820  faceList::subList myElements = dynFaces.slice(startElemi);
821 
822  for (auto& f : myElements)
823  {
824  for (label& fp : f)
825  {
826  is.read(fp);
827  }
828  }
829  }
830  else if
831  (
832  buffer
833  == ensightFaces::elemNames[ensightFaces::elemType::NSIDED]
834  )
835  {
836  label elemCount;
837  is.read(elemCount);
838 
839  faceTypeInfo.emplace_back
840  (
841  ensightFaces::elemType::NSIDED,
842  elemCount
843  );
844 
845  DebugInfo
846  << "faceType <"
847  << ensightFaces::elemNames[ensightFaces::elemType::NSIDED]
848  << "> count: " << elemCount << nl;
849 
850  if
851  (
852  idHandling.second() == idTypes::IGNORE
853  || idHandling.second() == idTypes::GIVEN
854  )
855  {
856  DebugInfo
857  << "Ignore " << elemCount << " element ids" << nl;
858 
859  // Read and discard labels
860  is.skip<label>(elemCount);
861  }
862 
863  // Extend and fill the new trailing portion
864  const label startElemi = dynFaces.size();
865  dynFaces.resize(startElemi + elemCount);
866  faceList::subList myElements = dynFaces.slice(startElemi);
867 
868  for (auto& f : myElements)
869  {
870  label nVerts;
871  is.read(nVerts);
872 
873  f.resize(nVerts);
874  }
875 
876  for (auto& f : myElements)
877  {
878  for (label& fp : f)
879  {
880  is.read(fp);
881  }
882  }
883  }
884  else
885  {
886  if (debug)
887  {
889  << "Unknown face type: <" << buffer.c_str()
890  << ">. Stopping read and continuing with current "
891  << "elements only" << endl;
892  }
893  break;
894  }
895  }
896 
897  // From 1-based Ensight addressing to 0-based OF addressing
898  for (auto& f : dynFaces)
899  {
900  for (label& fp : f)
901  {
902  --fp;
903  }
904  }
905 
906  faceTypeInfo_.transfer(faceTypeInfo);
907  faceList faces(std::move(dynFaces));
908 
909  DebugInfo
910  << "read nFaces: " << faces.size() << nl
911  << "file schema: " << faceTypeInfo_ << nl;
913  return meshedSurface(std::move(points), std::move(faces));
914  }
915 }
916 
917 
919 (
920  const label timeIndex
921 )
922 {
924 
925  if (!surfPtr_)
926  {
927  surfPtr_.reset(new meshedSurface);
928  auto& surf = *surfPtr_;
929 
930  fileName geomFile
931  (
932  baseDir_
933  / ensightCase::expand_mask(meshFileName_, timeIndex)
934  );
935 
936  if (!masterOnly_ || UPstream::master(UPstream::worldComm))
937  {
938  surf = readGeometry(geomFile, timeIndex);
939  }
940 
941  if (masterOnly_ && UPstream::parRun())
942  {
943  // Note: don't need faceTypeInfo_ on (non-reading) ranks
945  }
946  }
947 
948  return *surfPtr_;
949 }
950 
951 
953 {
954  return timeValues_;
955 }
956 
957 
959 (
960  const label timeIndex
961 ) const
962 {
963  return fieldNames_;
964 }
965 
966 
968 (
969  const label timeIndex,
970  const label fieldIndex,
971  const scalar& refValue
972 ) const
973 {
974  return readField<scalar>(timeIndex, fieldIndex);
975 }
976 
977 
979 (
980  const label timeIndex,
981  const label fieldIndex,
982  const vector& refValue
983 ) const
984 {
985  return readField<vector>(timeIndex, fieldIndex);
986 }
987 
988 
991 (
992  const label timeIndex,
993  const label fieldIndex,
994  const sphericalTensor& refValue
995 ) const
996 {
997  return readField<sphericalTensor>(timeIndex, fieldIndex);
998 }
999 
1000 
1002 (
1003  const label timeIndex,
1004  const label fieldIndex,
1005  const symmTensor& refValue
1006 ) const
1007 {
1008  return readField<symmTensor>(timeIndex, fieldIndex);
1009 }
1010 
1011 
1013 (
1014  const label timeIndex,
1015  const label fieldIndex,
1016  const tensor& refValue
1017 ) const
1018 {
1019  return readField<tensor>(timeIndex, fieldIndex);
1020 }
1021 
1022 
1023 // ************************************************************************* //
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
Foam::SubStrings splitSpace(const std::string &str, std::string::size_type pos=0)
Split string into sub-strings at whitespace (TAB, NL, VT, FF, CR, SPC)
static const char * elemNames[nTypes]
The ensight &#39;Face&#39; element type names.
Definition: ensightFaces.H:94
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:150
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 void broadcasts(const int communicator, Type &value, Args &&... values)
Broadcast multiple items to all communicator ranks. Does nothing in non-parallel. ...
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:600
static bool readLine(ISstream &is, std::string &line)
Helper function to read an ascii line from file, skipping blank lines and comments.
static labelPair extractTimeset(const SubStrings &split, const std::size_t minElements)
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:435
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:529
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1586
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:149
void inplaceTrimRight(std::string &s)
Trim trailing whitespace inplace.
static void broadcast(Type &value, const int communicator=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:987
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: SubStrings.H:45
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:229
Macros for easy insertion into run-time selection tables.
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)
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)
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:629
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:1619
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.
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:266
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 ...