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-2019 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 "stringOps.H"
30 
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32 
33 namespace Foam
34 {
35  defineTypeNameAndDebug(ensightSurfaceReader, 0);
36  addToRunTimeSelectionTable(surfaceReader, ensightSurfaceReader, fileName);
37 }
38 
39 
40 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
44 
45 // Read and discard specified number of elements
46 template<class Type>
47 static inline void discard(label n, ensightReadFile& is)
48 {
49  Type val;
50 
51  while (n > 0)
52  {
53  is.read(val);
54  --n;
55  }
56 }
57 
58 } // End namespace Foam
59 
60 
61 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
62 
64 {
65  label i = 0;
66  token tok;
67  while (is.good() && (i < n))
68  {
69  is >> tok;
70  ++i;
71 
72  DebugInfo
73  << "Skipping token " << tok << nl;
74  }
75 
76  if (i != n)
77  {
79  << "Requested to skip " << n << " tokens, but stream exited after "
80  << i << " tokens. Last token read: " << tok
81  << nl;
82  }
83 }
84 
85 
87 {
88  do
89  {
90  is.getLine(line);
91 
92  // Trim out any '#' comments
93  const auto pos = line.find('#');
94  if (pos != std::string::npos)
95  {
96  line.erase(pos);
97  }
99  }
100  while (line.empty() && is.good());
101 }
102 
103 
105 (
106  const word& expected,
107  IFstream& is
108 ) const
109 {
110  string actual;
111  readLine(is, actual);
112 
113  if (expected != actual)
114  {
116  << "Expected section header '" << expected
117  << "' but read " << actual << nl
118  << exit(FatalIOError);
119  }
120 
121  DebugInfo
122  << "Read section header: " << expected << nl;
123 }
124 
125 
128 {
129  // Binary flag string if applicable
130  is.readBinaryHeader();
131 
132  string buffer;
133 
134  Pair<idTypes> idHandling(idTypes::NONE, idTypes::NONE);
135 
136  // Ensight Geometry File
137  is.read(buffer);
138  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
139 
140  // Description - 1
141  is.read(buffer);
142  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
143 
144  // "node id (off|assign|given|ignore)" - "given" is not actually supported
145  is.read(buffer);
146  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
147 
148  if (buffer.find("ignore") != std::string::npos)
149  {
150  idHandling.first() = idTypes::IGNORE;
151  }
152  else if (buffer.find("given") != std::string::npos)
153  {
154  idHandling.first() = idTypes::GIVEN;
155  }
156 
157  // "element id (off|assign|given|ignore)"
158  is.read(buffer);
159  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
160 
161  if (buffer.find("ignore") != std::string::npos)
162  {
163  idHandling.second() = idTypes::IGNORE;
164  }
165  else if (buffer.find("given") != std::string::npos)
166  {
167  idHandling.second() = idTypes::GIVEN;
168  }
169 
170 
171  // "part" - but could also be an optional "extents"
172  is.read(buffer);
173  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
174 
175  if (buffer.find("extents") != std::string::npos)
176  {
177  // Optional extents - read and discard 6 floats
178  // (xmin, xmax, ymin, ymax, zmin, zmax)
179 
180  discard<scalar>(6, is);
181 
182  // Part
183  is.read(buffer);
184  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
185  }
186 
187  // The part number
188  label ivalue;
189  is.read(ivalue);
190  DebugInfo<< "ivalue: " << ivalue << nl;
191 
192  // Part description / name
193  is.read(buffer);
194  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
195 
196  // "coordinates"
197  is.read(buffer);
198  DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
199 
200  return idHandling;
201 }
202 
203 
205 {
207 
208  if (!is.good())
209  {
211  << "Cannot read file " << is.name()
212  << exit(FatalError);
213  }
214 
215  string buffer;
216 
217  // Read the file
218 
219  debugSection("FORMAT", is);
220  readLine(is, buffer); // type: ensight gold
221 
222  debugSection("GEOMETRY", is);
223  readLine(is, buffer);
224 
225  // GEOMETRY with any of these
226  // model: 1 xxx.0000.mesh
227  // model: xxx.0000.mesh
228  // model: data/directory/geometry
229  //
230  // - use the last entry
231  meshFileName_ = stringOps::splitSpace(buffer).last().str();
232 
233  debugSection("VARIABLE", is);
234 
235  // Read the field description
236  DynamicList<word> fieldNames(16);
237  DynamicList<string> fieldFileNames(16);
238 
239  while (is.good())
240  {
241  readLine(is, buffer);
242 
243  if (buffer == "TIME")
244  {
245  break;
246  }
247 
248  // Read the field name and associated file name. Eg,
249  // scalar per element: 1 p data/********/p
250 
251  const auto parsed = stringOps::splitSpace(buffer);
252 
253  if (buffer.find(':') == string::npos || parsed.size() < 4)
254  {
256  << "Error reading field file name. Current buffer: "
257  << buffer << endl;
258  continue;
259  }
260  else if (debug)
261  {
262  Info<<"variable line: " << parsed.size();
263  for (const auto& s : parsed)
264  {
265  Info<<" " << s.str();
266  }
267  Info<<nl;
268  }
269 
270  fieldNames.append(parsed[parsed.size()-2].str());
271  fieldFileNames.append(parsed.last().str());
272  }
273  fieldNames_.transfer(fieldNames);
274  fieldFileNames_.transfer(fieldFileNames);
275 
276  DebugInfo
277  << "fieldNames: " << fieldNames_ << nl
278  << "fieldFileNames: " << fieldFileNames_ << nl;
279 
280  // Start reading time information
281  readLine(is, buffer); // time set: <int>
282 
283  readLine(is, buffer);
284  readFromLine(3, buffer, nTimeSteps_); // number of steps: <int>
285  readLine(is, buffer);
286  readFromLine(3, buffer, timeStartIndex_); // filename start number: <int>
287  readLine(is, buffer);
288  readFromLine(2, buffer, timeIncrement_); // filename increment: <int>
289 
290  DebugInfo
291  << "nTimeSteps: " << nTimeSteps_ << nl
292  << "timeStartIndex: " << timeStartIndex_ << nl
293  << "timeIncrement: " << timeIncrement_ << nl;
294 
295  // Read the time values
296  readLine(is, buffer); // time values:
297  timeValues_.setSize(nTimeSteps_);
298  for (label i = 0; i < nTimeSteps_; ++i)
299  {
300  scalar t(readScalar(is));
301 
302  timeValues_[i].value() = t;
303  // TODO: use character representation of t directly instead of
304  // regenerating from scalar value
305  timeValues_[i].name() = Foam::name(t);
306  }
307 }
308 
309 
310 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
311 
313 :
314  surfaceReader(fName),
315  streamFormat_(IOstream::ASCII),
316  baseDir_(fName.path()),
317  meshFileName_(),
318  fieldNames_(),
319  fieldFileNames_(),
320  nTimeSteps_(0),
321  timeStartIndex_(0),
322  timeIncrement_(1),
323  timeValues_(),
324  surfPtr_(nullptr)
325 {
326  IFstream is(fName);
327  readCase(is);
328 }
329 
330 
331 // * * * * * * * * * * * * * Public Member Functions * * * * * * * * * * * //
332 
334 {
336 
337  if (!surfPtr_.valid())
338  {
339  IFstream isBinary(baseDir_/meshFileName_, IOstream::BINARY);
340 
341  if (!isBinary.good())
342  {
344  << "Cannot read file " << isBinary.name()
345  << exit(FatalError);
346  }
347 
348  streamFormat_ = IOstream::BINARY;
349  {
350  istream& iss = isBinary.stdStream();
351 
352  // Binary string is *exactly* 80 characters
353  string buf(size_t(80), '\0');
354  iss.read(&buf[0], 80);
355 
356  if (!iss)
357  {
358  // Truncated?
359  buf.erase(iss.gcount());
360  }
361 
362  // Truncate at the first embedded '\0'
363  const auto endp = buf.find('\0');
364  if (endp != std::string::npos)
365  {
366  buf.erase(endp);
367  }
368 
369  // Contains "C Binary" ?
370  if
371  (
372  (buf.find("binary") == std::string::npos)
373  && (buf.find("Binary") == std::string::npos)
374  )
375  {
376  streamFormat_ = IOstream::ASCII;
377  }
378  }
379 
380  if (debug)
381  {
382  Info<< "stream format: ";
383  if (streamFormat_ == IOstream::ASCII)
384  {
385  Info<< "ascii" << endl;
386  }
387  else
388  {
389  Info<< "binary" << endl;
390  }
391  }
392 
393 
394  ensightReadFile is(baseDir_/meshFileName_, streamFormat_);
395 
396  DebugInfo
397  << "File: " << is.name() << nl;
398 
399  Pair<idTypes> idHandling = readGeometryHeader(is);
400 
401  label nPoints;
402  is.read(nPoints);
403 
404  DebugInfo
405  << "nPoints: " << nPoints << nl;
406 
407  if (idHandling.first() == idTypes::GIVEN)
408  {
410  << "Treating node id 'given' as being 'ignore'" << nl
411  << "If something fails, this could be the reason" << nl
412  << endl;
413 
414  idHandling.first() = idTypes::IGNORE;
415  }
416 
417  if (idHandling.first() == idTypes::IGNORE)
418  {
419  DebugInfo
420  << "Ignore " << nPoints << " node ids" << nl;
421 
422  // Read and discard labels
423  discard<label>(nPoints, is);
424  }
425 
427  for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
428  {
429  for (point& pt : points)
430  {
431  is.read(pt[cmpt]);
432  }
433  }
434 
435 
436  // Read faces - may be a mix of tris, quads and polys
437  DynamicList<face> faces(ceil(nPoints/3));
438  DynamicList<Tuple2<string, label>> schema(faces.size());
439  string faceType;
440  while (is.good()) // (is.peek() != EOF)
441  {
442  is.read(faceType);
443 
444  if (!is.good())
445  {
446  break;
447  }
448 
449  label nFace = 0;
450 
451  if (faceType == "tria3")
452  {
453  is.read(nFace);
454 
455  DebugInfo
456  << "faceType <" << faceType.c_str() << "> count: "
457  << nFace << nl;
458 
459  if
460  (
461  idHandling.second() == idTypes::IGNORE
462  || idHandling.second() == idTypes::GIVEN
463  )
464  {
465  DebugInfo
466  << "Ignore " << nFace << " element ids" << nl;
467 
468  // Read and discard labels
469  discard<label>(nFace, is);
470  }
471 
472  face f(3);
473  for (label facei = 0; facei < nFace; ++facei)
474  {
475  for (label& fp : f)
476  {
477  is.read(fp);
478  }
479 
480  faces.append(f);
481  }
482  }
483  else if (faceType == "quad4")
484  {
485  is.read(nFace);
486 
487  DebugInfo
488  << "faceType <" << faceType.c_str() << "> count: "
489  << nFace << nl;
490 
491  if
492  (
493  idHandling.second() == idTypes::IGNORE
494  || idHandling.second() == idTypes::GIVEN
495  )
496  {
497  DebugInfo
498  << "Ignore " << nFace << " element ids" << nl;
499 
500  // Read and discard labels
501  discard<label>(nFace, is);
502  }
503 
504  face f(4);
505  for (label facei = 0; facei < nFace; ++facei)
506  {
507  for (label& fp : f)
508  {
509  is.read(fp);
510  }
511 
512  faces.append(f);
513  }
514  }
515  else if (faceType == "nsided")
516  {
517  is.read(nFace);
518 
519  DebugInfo
520  << "faceType <" << faceType.c_str() << "> count: "
521  << nFace << nl;
522 
523  if
524  (
525  idHandling.second() == idTypes::IGNORE
526  || idHandling.second() == idTypes::GIVEN
527  )
528  {
529  DebugInfo
530  << "Ignore " << nFace << " element ids" << nl;
531 
532  // Read and discard labels
533  discard<label>(nFace, is);
534  }
535 
536  labelList np(nFace);
537  for (label facei = 0; facei < nFace; ++facei)
538  {
539  is.read(np[facei]);
540  }
541  for (label facei = 0; facei < nFace; ++facei)
542  {
543  face f(np[facei]);
544  for (label& fp : f)
545  {
546  is.read(fp);
547  }
548 
549  faces.append(f);
550  }
551  }
552  else
553  {
554  if (debug)
555  {
557  << "Unknown face type: <" << faceType.c_str()
558  << ">. Stopping read and continuing with current "
559  << "elements only" << endl;
560  }
561  break;
562  }
563  schema.append(Tuple2<string, label>(faceType, nFace));
564  }
565 
566  schema_.transfer(schema);
567 
568  DebugInfo
569  << "read nFaces: " << faces.size() << nl
570  << "file schema: " << schema_ << nl;
571 
572  // Convert from 1-based Ensight addressing to 0-based OF addressing
573  for (face& f : faces)
574  {
575  for (label& pointi : f)
576  {
577  --pointi;
578  }
579  }
580 
581  surfPtr_.reset(new meshedSurface(std::move(points), std::move(faces)));
582  }
583 
584  return *surfPtr_;
585 }
586 
587 
589 {
590  return timeValues_;
591 }
592 
593 
595 (
596  const label timeIndex
597 ) const
598 {
599  return fieldNames_;
600 }
601 
602 
604 (
605  const label timeIndex,
606  const label fieldIndex,
607  const scalar& refValue
608 ) const
609 {
610  return readField<scalar>(timeIndex, fieldIndex);
611 }
612 
613 
615 (
616  const label timeIndex,
617  const label fieldIndex,
618  const vector& refValue
619 ) const
620 {
621  return readField<vector>(timeIndex, fieldIndex);
622 }
623 
624 
627 (
628  const label timeIndex,
629  const label fieldIndex,
630  const sphericalTensor& refValue
631 ) const
632 {
633  return readField<sphericalTensor>(timeIndex, fieldIndex);
634 }
635 
636 
638 (
639  const label timeIndex,
640  const label fieldIndex,
641  const symmTensor& refValue
642 ) const
643 {
644  return readField<symmTensor>(timeIndex, fieldIndex);
645 }
646 
647 
649 (
650  const label timeIndex,
651  const label fieldIndex,
652  const tensor& refValue
653 ) const
654 {
655  return readField<tensor>(timeIndex, fieldIndex);
656 }
657 
658 
659 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
Foam::Pair::second
const T & second() const noexcept
Return second element, which is also the last element.
Definition: PairI.H:122
Foam::Tensor< scalar >
Foam::val
label ListType::const_reference val
Definition: ListOps.H:407
Foam::SymmTensor< scalar >
Foam::surfaceReader
Base class for surface readers.
Definition: surfaceReader.H:53
Foam::stringOps::inplaceTrimRight
void inplaceTrimRight(std::string &s)
Trim trailing whitespace inplace.
Definition: stringOps.C:1013
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::ISstream::getLine
ISstream & getLine(std::string &str, char delim='\n')
Raw, low-level getline into a string function.
Definition: ISstreamI.H:78
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
s
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputSpray.H:25
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:59
Foam::IFstream
Input from file stream, using an ISstream.
Definition: IFstream.H:97
Foam::DynamicList< word >
Foam::IFstream::name
virtual const fileName & name() const
Read/write access to the name of the stream.
Definition: ISstream.H:111
Foam::ensightSurfaceReader::skip
void skip(const label n, Istream &is) const
Helper function to skip forward n steps in stream.
Definition: ensightSurfaceReader.C:63
Foam::ensightSurfaceReader::readLine
void readLine(IFstream &is, string &buffer) const
Helper function to read an ascii line from file.
Definition: ensightSurfaceReader.C:86
Foam::IOstream
An IOstream is an abstract base class for all input/output systems; be they streams,...
Definition: IOstream.H:75
Foam::ensightSurfaceReader::readCase
void readCase(IFstream &is)
Read the case file.
Definition: ensightSurfaceReader.C:204
Foam::FatalIOError
IOerror FatalIOError
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::token
A token holds an item read from Istream.
Definition: token.H:69
Foam::stringOps::splitSpace
Foam::SubStrings< StringType > splitSpace(const StringType &str)
Split string into sub-strings at whitespace (TAB, NL, VT, FF, CR, SPC)
Definition: stringOpsTemplates.C:180
Foam::ensightSurfaceReader::fieldNames
virtual wordList fieldNames(const label timeIndex) const
Return a list of the available fields at a given time.
Definition: ensightSurfaceReader.C:595
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
n
label n
Definition: TABSMDCalcMethod2.H:31
ensightSurfaceReader.H
Foam::ensightSurfaceReader::ensightSurfaceReader
ensightSurfaceReader(const fileName &fName)
Construct from fileName.
Definition: ensightSurfaceReader.C:312
Foam::ensightSurfaceReader::times
virtual instantList times() const
Return a list of the available times.
Definition: ensightSurfaceReader.C:588
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::ensightReadFile
Ensight output with specialized read() for strings, integers and floats. Correctly handles binary rea...
Definition: ensightReadFile.H:49
Foam::Field< vector >
Foam::Istream
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:61
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
DebugInFunction
#define DebugInFunction
Report an information message using Foam::Info.
Definition: messageStream.H:356
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:472
Foam::ensightSurfaceReader::readGeometryHeader
Pair< idTypes > readGeometryHeader(ensightReadFile &is) const
Read (and discard) geometry file header.
Definition: ensightSurfaceReader.C:127
timeIndex
label timeIndex
Definition: getTimeIndex.H:4
Foam::ensightSurfaceReader::debugSection
void debugSection(const word &expected, IFstream &is) const
Read and check a section header.
Definition: ensightSurfaceReader.C:105
Foam::FatalError
error FatalError
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::SphericalTensor< scalar >
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::ensightReadFile::readBinaryHeader
Istream & readBinaryHeader()
Read "C Binary" for binary files (eg, geometry/measured)
Definition: ensightReadFile.C:152
Foam::IFstream::stdStream
virtual std::istream & stdStream()
Access to underlying std::istream.
Definition: IFstream.C:144
Foam::discard
static void discard(label n, ensightReadFile &is)
Definition: ensightSurfaceReader.C:47
Foam::IOstreamOption::BINARY
"binary"
Definition: IOstreamOption.H:67
Foam::IOstreamOption::ASCII
"ascii"
Definition: IOstreamOption.H:66
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
DebugInfo
#define DebugInfo
Report an information message using Foam::Info.
Definition: messageStream.H:350
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::Pair
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: Pair.H:54
Foam::meshedSurface
MeshedSurface< face > meshedSurface
Definition: MeshedSurfacesFwd.H:41
f
labelList f(nPoints)
Foam::Vector< scalar >
Foam::List< label >
points
const pointField & points
Definition: gmvOutputHeader.H:1
path
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
Foam::direction
uint8_t direction
Definition: direction.H:47
Foam::line
A line primitive.
Definition: line.H:59
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:74
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:375
Foam::ensightSurfaceReader::geometry
virtual const meshedSurface & geometry()
Return a reference to the surface geometry.
Definition: ensightSurfaceReader.C:333
Foam::Tuple2
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: Tuple2.H:57
Foam::ensightSurfaceReader::field
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.
Definition: ensightSurfaceReader.C:604
Foam::IOstream::good
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:216
Foam::MeshedSurface< face >
stringOps.H
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:294
Foam::ensightReadFile::read
virtual Istream & read(char *buf, std::streamsize count)
Binary read.
Definition: ensightReadFile.C:45
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::nComponents
static constexpr direction nComponents
Number of components in this vector space.
Definition: VectorSpace.H:101
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:177