decomposedBlockData.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) 2017-2018 OpenFOAM Foundation
9  Copyright (C) 2020-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "decomposedBlockData.H"
30 #include "OPstream.H"
31 #include "IPstream.H"
32 #include "PstreamBuffers.H"
33 #include "Fstream.H"
34 #include "dictionary.H"
35 #include "objectRegistry.H"
36 #include "SubList.H"
37 #include "charList.H"
38 #include "labelPair.H"
40 #include "SpanStream.H"
41 #include "StringStream.H"
42 
43 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 
45 namespace Foam
46 {
48 }
49 
50 
51 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
52 
54 (
55  const word& objectType
56 )
57 {
58  return
59  (
60  objectType == decomposedBlockData::typeName
61  );
62 }
63 
64 
66 (
67  const IOobject& io
68 )
69 {
71 }
72 
73 
74 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
75 
77 (
78  const label comm,
79  const IOobject& io,
80  const UPstream::commsTypes commsType
81 )
82 :
83  regIOobject(io),
84  commsType_(commsType),
85  comm_(comm),
86  contentData_()
87 {
88  // Temporary warning
90  {
92  << "decomposedBlockData " << name()
93  << " constructed with READ_MODIFIED"
94  " but decomposedBlockData does not support automatic rereading."
95  << endl;
96  }
97  if (isReadRequired() || (isReadOptional() && headerOk()))
98  {
99  read();
100  }
101 }
102 
103 
104 // * * * * * * * * * * * * * * * Members Functions * * * * * * * * * * * * * //
105 
107 (
108  OSstream& os,
109  const label blocki,
110  const char* str,
111  const size_t len
112 )
113 {
114  // Offset to the beginning of this output
115  // This should generally be OK for non-compressed streams
116  // (eg, std::ofstream)
117 
118  std::streamoff blockOffset = os.stdStream().tellp();
119 
120  const word procName("processor" + Foam::name(blocki));
121 
122  // Write as commented content
123  // ----------------
124  // // processorN
125  // NCHARS
126  // (...)
127  // ----------------
128  {
129  os << nl << "// " << procName << nl;
130 
131  if (str && len > 0)
132  {
133  // Special treatment for char data (binary I/O only)
134  const auto oldFmt = os.format(IOstreamOption::BINARY);
135 
136  os << label(len) << nl;
137  os.write(str, len);
138  os << nl;
139 
140  os.format(oldFmt);
141  }
142  else
143  {
144  os << label(0) << nl;
145  }
146  }
147 
148  // Write as primitiveEntry
149  // {
150  // // Like writeKeyword()
151  // os << nl << procName << nl;
152  //
153  // if (str && len > 0)
154  // {
155  // // Special treatment for char data (binary I/O only)
156  // const auto oldFmt = os.format(IOstreamOption::BINARY);
157  //
158  // os << label(len) << nl;
159  // os.write(str, len);
160  // os << nl;
161  //
162  // os.format(oldFmt);
163  // }
164  // else
165  // {
166  // os << label(0) << nl;
167  // }
168  //
169  // os.endEntry();
170  // }
171 
172  return blockOffset;
173 }
174 
175 
177 (
178  Istream& is,
179  List<char>& charData
180 )
181 {
182  // Handle any of these:
183 
184  // 0. NCHARS (...)
185  // 1. List<char> NCHARS (...)
186  // 2. processorN List<char> NCHARS (...) ;
187  // 3. processorN NCHARS (...) ;
188 
190  token tok(is);
192 
193  // Dictionary format has primitiveEntry keyword:
194  const bool isDictFormat = (tok.isWord() && !tok.isCompound());
195 
196  if (!isDictFormat && tok.good())
197  {
198  is.putBack(tok);
199  }
200  charData.readList(is);
201 
202  if (isDictFormat)
203  {
205  is >> tok;
207 
208  // Swallow trailing ';'
209  if (tok.good() && !tok.isPunctuation(token::END_STATEMENT))
210  {
211  is.putBack(tok);
212  }
213  }
214 
215  return true;
216 }
217 
218 
220 {
221  // As per readBlockEntry but seeks instead of reading.
222  // Internals like charList::readList - ie, always binary
223 
224  // Handle any of these:
225  // 0. NCHARS (...)
226  // 1. List<char> NCHARS (...)
227  // 2. processorN List<char> NCHARS (...) ;
228  // 3. processorN NCHARS (...) ;
229 
230  if (!is.good()) return false;
231  token tok(is);
232  if (!is.good()) return false;
233 
234  // Dictionary format has primitiveEntry keyword:
235  const bool isDictFormat = (tok.isWord() && !tok.isCompound());
236 
237  if (isDictFormat)
238  {
239  is >> tok;
240  if (!is.good()) return false;
241  }
242 
243 
244  bool handled = false;
245 
246  // Like charList::readList
247  if (tok.isCompound())
248  {
249  handled = true;
250  }
251  else if (tok.isLabel())
252  {
253  // Label: could be int(..) or just a plain '0'
254 
255  const label len = tok.labelToken();
256 
257  // Special treatment for char data (binary I/O only)
258  const auto oldFmt = is.format(IOstreamOption::BINARY);
259 
260  if (len)
261  {
262  // read(...) includes surrounding start/end delimiters.
263 
264  // Note: nullptr to ignore instead of reading
265  is.read(nullptr, std::streamsize(len));
266  }
267  is.format(oldFmt);
268 
269  handled = true;
270  }
271  else
272  {
273  // Incorrect token
274  return false;
275  }
276 
277  if (isDictFormat)
278  {
279  is.fatalCheck(FUNCTION_NAME);
280  is >> tok;
281  is.fatalCheck(FUNCTION_NAME);
282 
283  // Swallow trailing ';'
284  if (tok.good() && !tok.isPunctuation(token::END_STATEMENT))
285  {
286  is.putBack(tok);
287  }
288  }
289 
290  return handled;
291 }
292 
293 
295 (
296  Istream& is,
297  const label maxNumBlocks
298 )
299 {
300  label nBlocks = 0;
301 
302  // Handle OpenFOAM header if it is the first entry
303  if (is.good())
304  {
305  token tok(is);
306 
307  if (is.good() && tok.isWord("FoamFile"))
308  {
309  dictionary headerDict(is); // Read sub-dictionary content
310 
311  if (headerDict.readIfPresent("version", tok))
312  {
313  is.version(tok);
314  }
315 
316  word formatName;
317  if (headerDict.readIfPresent("format", formatName))
318  {
319  is.format(formatName);
320  }
321 
324  //if (headerDict.readIfPresent("blocks", nBlocks))
325  //{
326  // return nBlocks;
327  //}
328  }
329  else if (tok.good())
330  {
331  is.putBack(tok);
332  }
333  }
334 
335  while (is.good() && skipBlockEntry(is))
336  {
337  ++nBlocks;
338 
339  if (maxNumBlocks == nBlocks)
340  {
341  break;
342  }
343  }
344 
345  return nBlocks;
346 }
347 
348 
349 bool Foam::decomposedBlockData::hasBlock(Istream& is, const label blockNumber)
350 {
351  return
352  (
353  blockNumber >= 0
354  && (blockNumber < getNumBlocks(is, blockNumber+1))
355  );
356 }
357 
358 
360 (
361  OSstream& os,
362  IOstreamOption streamOptData,
363  const regIOobject& io,
364  const label blocki,
365  const bool withLocalHeader
366 )
367 {
368  // String of all data to write
369  string contentChars;
370  {
371  OStringStream buf(streamOptData);
372 
373  bool ok = true;
374 
375  // Generate FoamFile header on master, without comment banner
376  if (withLocalHeader)
377  {
378  const bool old = IOobject::bannerEnabled(false);
379 
380  ok = io.writeHeader(buf);
381 
383  }
384 
385  // Write the data to the Ostream
386  ok = ok && io.writeData(buf);
387 
388  if (!ok)
389  {
390  return std::streamoff(-1);
391  }
392 
393  contentChars = buf.str();
394  }
396  return decomposedBlockData::writeBlockEntry(os, blocki, contentChars);
397 }
398 
399 
402 (
403  const label blocki,
404  ISstream& is,
405  IOobject& headerIO
406 )
407 {
408  if (debug)
409  {
410  Pout<< "decomposedBlockData::readBlock:"
411  << " stream:" << is.name() << " attempt to read block " << blocki
412  << endl;
413  }
414 
415  // Extracted header information
416  IOstreamOption streamOptData;
417  unsigned labelWidth = is.labelByteSize();
418  unsigned scalarWidth = is.scalarByteSize();
419 
420  autoPtr<ISstream> realIsPtr;
421 
422  // Read master for header
423  List<char> data;
425 
426  if (blocki == 0)
427  {
428  realIsPtr.reset(new ICharStream(std::move(data)));
429  realIsPtr->name() = is.name();
430 
431  {
432  // Read header from first block,
433  // advancing the stream position
434  if (!headerIO.readHeader(*realIsPtr))
435  {
436  FatalIOErrorInFunction(*realIsPtr)
437  << "Problem while reading object header "
438  << is.relativeName() << nl
439  << exit(FatalIOError);
440  }
441  }
442  }
443  else
444  {
445  {
446  // Read header from first block
447  ISpanStream headerStream(data);
448  if (!headerIO.readHeader(headerStream))
449  {
450  FatalIOErrorInFunction(headerStream)
451  << "Problem while reading object header "
452  << is.relativeName() << nl
453  << exit(FatalIOError);
454  }
455  streamOptData = static_cast<IOstreamOption>(headerStream);
456  labelWidth = headerStream.labelByteSize();
457  scalarWidth = headerStream.scalarByteSize();
458  }
459 
460  for (label i = 1; i < blocki+1; i++)
461  {
462  // Read and discard data, only retain the last one
464  }
465  realIsPtr.reset(new ICharStream(std::move(data)));
466  realIsPtr->name() = is.name();
467 
468  // Apply stream settings
469  realIsPtr().format(streamOptData.format());
470  realIsPtr().version(streamOptData.version());
471  realIsPtr().setLabelByteSize(labelWidth);
472  realIsPtr().setScalarByteSize(scalarWidth);
473  }
474 
475  return realIsPtr;
476 }
477 
478 
480 (
481  const label comm,
482  autoPtr<ISstream>& isPtr,
483  List<char>& data,
484  const UPstream::commsTypes commsType
485 )
486 {
487  if (debug)
488  {
489  Pout<< "decomposedBlockData::readBlocks:"
490  << " stream:" << (isPtr ? isPtr->name() : "invalid")
491  << " commsType:" << Pstream::commsTypeNames[commsType]
492  << " comm:" << comm << endl;
493  }
494 
495  bool ok = false;
496 
497  if (UPstream::master(comm))
498  {
499  auto& is = *isPtr;
501 
502  // Read master data
504  }
505 
506  if (commsType == UPstream::commsTypes::scheduled)
507  {
508  if (UPstream::master(comm))
509  {
510  // Master data already read ...
511  auto& is = *isPtr;
513 
514  // Read and transmit slave data
515  for (const int proci : UPstream::subProcs(comm))
516  {
517  List<char> elems;
519 
520  OPstream os
521  (
523  proci,
524  0,
526  comm
527  );
528  os << elems;
529  }
530 
531  ok = is.good();
532  }
533  else
534  {
535  IPstream is
536  (
539  0,
541  comm
542  );
543  is >> data;
544  }
545  }
546  else
547  {
548  PstreamBuffers pBufs(comm, UPstream::commsTypes::nonBlocking);
549 
550  if (UPstream::master(comm))
551  {
552  // Master data already read ...
553  auto& is = *isPtr;
555 
556  // Read and transmit slave data
557  for (const int proci : UPstream::subProcs(comm))
558  {
559  List<char> elems;
561 
562  UOPstream os(proci, pBufs);
563  os << elems;
564  }
565  }
566 
567  pBufs.finishedScatters();
568 
569  if (!UPstream::master(comm))
570  {
571  UIPstream is(UPstream::masterNo(), pBufs);
572  is >> data;
573  }
574  }
575 
577 
578  return ok;
579 }
580 
581 
583 (
584  const label comm,
585  const fileName& fName,
586  autoPtr<ISstream>& isPtr,
587  IOobject& headerIO,
588  const UPstream::commsTypes commsType
589 )
590 {
591  if (debug)
592  {
593  Pout<< "decomposedBlockData::readBlocks:"
594  << " stream:" << (isPtr ? isPtr->name() : "invalid")
595  << " commsType:" << Pstream::commsTypeNames[commsType] << endl;
596  }
597 
598  bool ok = false;
599  List<char> data;
600  autoPtr<ISstream> realIsPtr;
601 
602  if (UPstream::master(comm))
603  {
604  auto& is = *isPtr;
606 
607  // Read master data
609 
610  realIsPtr.reset(new ICharStream(std::move(data)));
611  realIsPtr->name() = fName;
612 
613  {
614  // Read header from first block,
615  // advancing the stream position
616  if (!headerIO.readHeader(*realIsPtr))
617  {
618  FatalIOErrorInFunction(*realIsPtr)
619  << "Problem while reading object header "
620  << is.relativeName() << nl
621  << exit(FatalIOError);
622  }
623  }
624  }
625 
626  if (commsType == UPstream::commsTypes::scheduled)
627  {
628  if (UPstream::master(comm))
629  {
630  // Master data already read ...
631  auto& is = *isPtr;
633 
634  // Read and transmit slave data
635  for (const int proci : UPstream::subProcs(comm))
636  {
638 
639  OPstream os
640  (
642  proci,
643  0,
645  comm
646  );
647  os << data;
648  }
649 
650  ok = is.good();
651  }
652  else
653  {
654  IPstream is
655  (
658  0,
660  comm
661  );
662  is >> data;
663 
664  realIsPtr.reset(new ICharStream(std::move(data)));
665  realIsPtr->name() = fName;
666  }
667  }
668  else
669  {
670  PstreamBuffers pBufs(comm, UPstream::commsTypes::nonBlocking);
671 
672  if (UPstream::master(comm))
673  {
674  // Master data already read ...
675  auto& is = *isPtr;
677 
678  // Read and transmit slave data
679  for (const int proci : UPstream::subProcs(comm))
680  {
681  List<char> elems;
683 
684  UOPstream os(proci, pBufs);
685  os << elems;
686  }
687 
688  ok = is.good();
689  }
690 
691  pBufs.finishedScatters();
692 
693  if (!UPstream::master(comm))
694  {
695  UIPstream is(UPstream::masterNo(), pBufs);
696  is >> data;
697 
698  realIsPtr.reset(new ICharStream(std::move(data)));
699  realIsPtr->name() = fName;
700  }
701  }
702 
703  Pstream::broadcast(ok, comm);
704 
705  // Broadcast master header info,
706  // set stream properties from realIsPtr on master
707 
708  int verValue;
709  int fmtValue;
710  unsigned labelWidth;
711  unsigned scalarWidth;
712  word headerName(headerIO.name());
713 
714  if (UPstream::master(comm))
715  {
716  verValue = realIsPtr().version().canonical();
717  fmtValue = static_cast<int>(realIsPtr().format());
718  labelWidth = realIsPtr().labelByteSize();
719  scalarWidth = realIsPtr().scalarByteSize();
720  }
721 
723  (
724  UPstream::worldComm, // Future? comm,
725  verValue,
726  fmtValue,
727  labelWidth,
728  scalarWidth,
729  headerName,
730  headerIO.headerClassName(),
731  headerIO.note()
732  // Unneeded: headerIO.instance()
733  // Unneeded: headerIO.local()
734  );
735 
736  realIsPtr().version(IOstreamOption::versionNumber::canonical(verValue));
737  realIsPtr().format(IOstreamOption::streamFormat(fmtValue));
738  realIsPtr().setLabelByteSize(labelWidth);
739  realIsPtr().setScalarByteSize(scalarWidth);
740 
741  headerIO.rename(headerName);
742 
743  return realIsPtr;
744 }
745 
746 
748 (
749  const label comm,
750  const label data,
751  labelList& datas
752 )
753 {
754  const label nProcs = UPstream::nProcs(comm);
755  datas.resize(nProcs);
756 
757  char* data0Ptr = datas.data_bytes();
758 
759  List<int> recvOffsets;
760  List<int> recvSizes;
761  if (UPstream::master(comm))
762  {
763  recvOffsets.setSize(nProcs);
764  forAll(recvOffsets, proci)
765  {
766  // Note: truncating long int to int since UPstream::gather limited
767  // to ints
768  recvOffsets[proci] =
769  int(reinterpret_cast<char*>(&datas[proci]) - data0Ptr);
770  }
771  recvSizes.setSize(nProcs, sizeof(label));
772  }
773 
775  (
776  reinterpret_cast<const char*>(&data),
777  sizeof(label),
778  data0Ptr,
779  recvSizes,
780  recvOffsets,
781  comm
782  );
783 }
784 
785 
787 (
788  const label comm,
789  const UList<char>& data,
790  const labelUList& recvSizes,
791 
792  const labelRange& fromProcs,
793 
794  List<int>& sliceOffsets,
795  DynamicList<char>& recvData
796 )
797 {
798  const label myProci = UPstream::myProcNo(comm);
799  const label numProcs = UPstream::nProcs(comm);
800 
801  int nSendBytes = 0;
802  recvData.clear();
803 
804  // Calculate master data
805  List<int> sliceSizes;
806  if (UPstream::master(comm))
807  {
808  sliceSizes.resize(numProcs, 0);
809  sliceOffsets.resize(numProcs+1, 0);
810 
811  // Offset 1 beyond the end of the range
812  const label endProci = fromProcs.end_value();
813 
814  int totalSize = 0;
815  for (const label proci : fromProcs)
816  {
817  sliceSizes[proci] = int(recvSizes[proci]);
818  sliceOffsets[proci] = totalSize;
819  totalSize += sliceSizes[proci];
820  }
821 
822  sliceOffsets[endProci] = totalSize;
823  recvData.resize(totalSize);
824  }
825  else if (fromProcs.contains(myProci))
826  {
827  // Note: UPstream::gather limited to int
828  nSendBytes = int(data.size_bytes());
829  }
830 
832  (
833  data.cdata(),
834  nSendBytes,
835 
836  recvData.data(),
837  sliceSizes,
838  sliceOffsets,
839  comm
840  );
841 }
842 
843 
845 (
846  const label comm,
847  const off_t maxBufferSize,
848  const labelUList& recvSizes,
849  const label startProci
850 )
851 {
852  const label nProcs = UPstream::nProcs(comm);
853 
854  label nSendProcs = 0;
855  if (UPstream::master(comm))
856  {
857  off_t totalSize = recvSizes[startProci];
858  label proci = startProci+1;
859  while (proci < nProcs && (totalSize+recvSizes[proci] < maxBufferSize))
860  {
861  totalSize += recvSizes[proci];
862  proci++;
863  }
864 
865  nSendProcs = proci-startProci;
866  }
867 
868  Pstream::broadcast(nSendProcs, comm);
869 
870  return nSendProcs;
871 }
872 
873 
875 (
876  const label comm,
877  autoPtr<OSstream>& osPtr,
878  List<std::streamoff>& blockOffset,
879  const UList<char>& masterData,
880 
881  const labelUList& recvSizes,
882  const UPtrList<SubList<char>>& slaveData,
883 
884  const UPstream::commsTypes commsType,
885  const bool syncReturnState
886 )
887 {
888  if (debug)
889  {
890  Pout<< "decomposedBlockData::writeBlocks:"
891  << " stream:" << (osPtr ? osPtr->name() : "none")
892  << " data:" << masterData.size()
893  << " (master only) slaveData:" << slaveData.size()
894  << " commsType:" << Pstream::commsTypeNames[commsType] << endl;
895  }
896 
897  const label nProcs = UPstream::nProcs(comm);
898 
899  bool ok = true;
900 
901  // Write master data
902  if (UPstream::master(comm))
903  {
904  blockOffset.resize(nProcs);
905 
906  OSstream& os = osPtr();
907 
908  blockOffset[UPstream::masterNo()] =
910  (
911  os,
913  masterData
914  );
915 
916  ok = os.good();
917  }
918 
919  if (slaveData.size())
920  {
921  // Already have gathered the slave data.
922 
923  if (UPstream::master(comm))
924  {
925  // Master data already written ...
926  OSstream& os = osPtr();
927 
928  // Write slaves
929  for (label proci = 1; proci < nProcs; ++proci)
930  {
931  blockOffset[proci] =
933  (
934  os,
935  proci,
936  slaveData[proci]
937  );
938  }
939 
940  ok = os.good();
941  }
942  }
943  else if (commsType == UPstream::commsTypes::scheduled)
944  {
945  if (UPstream::master(comm))
946  {
947  // Master data already written ...
948  OSstream& os = osPtr();
949 
950  // Receive and write slaves
951  label maxNonLocalSize = 0;
952  for (label proci = 1; proci < nProcs; ++proci)
953  {
954  maxNonLocalSize = max(maxNonLocalSize, recvSizes[proci]);
955  }
956 
957  DynamicList<char> elems(maxNonLocalSize);
958  for (label proci = 1; proci < nProcs; ++proci)
959  {
960  elems.resize_nocopy(recvSizes[proci]);
962  (
964  proci,
965  elems.data(),
966  elems.size_bytes(),
968  comm
969  );
970 
971  blockOffset[proci] =
973  (
974  os,
975  proci,
976  elems
977  );
978  }
979 
980  ok = os.good();
981  }
982  else
983  {
985  (
988  masterData.cdata(),
989  masterData.size_bytes(),
991  comm
992  );
993  }
994  }
995  else
996  {
997  // Master data already written ...
998 
999  // Find out how many processor can be received into
1000  // maxMasterFileBufferSize
1001 
1002  // Starting slave processor and number of processors
1003  label startProc = 1;
1004  label nSendProcs = nProcs-1;
1005 
1006  DynamicList<char> recvData;
1007 
1008  while (nSendProcs > 0 && startProc < nProcs)
1009  {
1010  nSendProcs = calcNumProcs
1011  (
1012  comm,
1013  off_t
1014  (
1015  fileOperations::masterUncollatedFileOperation::
1016  maxMasterFileBufferSize
1017  ),
1018  recvSizes,
1019  startProc
1020  );
1021 
1022  if (nSendProcs == 0)
1023  {
1024  break;
1025  }
1026 
1027 
1028  // Gather data from (a slice of) the slaves
1029  labelRange fromProcs(startProc, nSendProcs);
1030 
1031  List<int> sliceOffsets;
1032  gatherSlaveData
1033  (
1034  comm,
1035  masterData,
1036  recvSizes,
1037 
1038  fromProcs,
1039 
1040  sliceOffsets,
1041  recvData
1042  );
1043 
1044  if (UPstream::master(comm))
1045  {
1046  OSstream& os = osPtr();
1047 
1048  // Write received data
1049  for (const label proci : fromProcs)
1050  {
1051  SubList<char> dataSlice
1052  (
1053  recvData,
1054  sliceOffsets[proci+1]-sliceOffsets[proci],
1055  sliceOffsets[proci]
1056  );
1057 
1058  blockOffset[proci] =
1060  (
1061  os,
1062  proci,
1063  dataSlice
1064  );
1065  }
1066  }
1067 
1068  startProc += nSendProcs;
1069  }
1070 
1071  if (UPstream::master(comm))
1072  {
1073  ok = osPtr->good();
1074  }
1075  }
1076 
1077  if (syncReturnState)
1078  {
1079  //- Enable to get synchronised error checking. Is the one that keeps
1080  // slaves as slow as the master (which does all the writing)
1081  Pstream::broadcast(ok, comm);
1082  }
1083 
1084  return ok;
1085 }
1086 
1087 
1089 {
1090  autoPtr<ISstream> isPtr;
1091  fileName objPath(fileHandler().filePath(false, *this, word::null));
1092  if (UPstream::master(comm_))
1093  {
1094  isPtr.reset(new IFstream(objPath));
1095  IOobject::readHeader(*isPtr);
1096  }
1097 
1098  return readBlocks(comm_, isPtr, contentData_, commsType_);
1099 }
1100 
1101 
1103 {
1104  IOobject io(*this);
1105  IOstreamOption streamOpt(os);
1106 
1107  int verValue;
1108  int fmtValue;
1109  // Unneeded: word masterName(name());
1110  fileName masterLocation(instance()/db().dbDir()/local());
1111 
1112  // Re-read my own data to find out the header information
1113  if (Pstream::master(comm_))
1114  {
1115  ISpanStream headerStream(contentData_);
1116  io.readHeader(headerStream);
1117 
1118  verValue = headerStream.version().canonical();
1119  fmtValue = static_cast<int>(headerStream.format());
1120  }
1121 
1122  // Broadcast header information
1124  (
1125  comm_,
1126  verValue,
1127  fmtValue,
1128  // Unneeded: masterName
1129  io.headerClassName(),
1130  io.note(),
1131  // Unneeded: io.instance()
1132  // Unneeded: io.local()
1133  masterLocation
1134  );
1135 
1137  streamOpt.format(IOstreamOption::streamFormat(fmtValue));
1138 
1139  if (!Pstream::master(comm_))
1140  {
1142  (
1143  os,
1144  streamOpt, // streamOpt for data
1145  io.headerClassName(),
1146  io.note(),
1147  masterLocation,
1148  name(),
1149  dictionary()
1150  );
1151  }
1152 
1153  // Write the character data
1154  if (isA<OFstream>(os))
1155  {
1156  // Serial file output - can use writeRaw()
1157  os.writeRaw(contentData_.cdata(), contentData_.size_bytes());
1158  }
1159  else
1160  {
1161  // Other cases are less fortunate, and no std::string_view
1162  std::string str(contentData_.cdata(), contentData_.size_bytes());
1163  os.writeQuoted(str, false);
1164  }
1165 
1166  if (!Pstream::master(comm_))
1167  {
1169  }
1170 
1171  return os.good();
1173 
1174 
1176 (
1177  IOstreamOption streamOpt,
1178  const bool writeOnProc
1179 ) const
1180 {
1181  autoPtr<OSstream> osPtr;
1182  if (UPstream::master(comm_))
1183  {
1184  // Note: always write binary. These are strings so readable anyway.
1185  // They have already be tokenised on the sending side.
1186 
1187  osPtr.reset(new OFstream(objectPath(), IOstreamOption::BINARY));
1188 
1189  // Update meta-data for current state
1190  const_cast<regIOobject&>
1191  (
1192  static_cast<const regIOobject&>(*this)
1193  ).updateMetaData();
1194 
1196  (
1197  *osPtr,
1198  streamOpt, // streamOpt for data
1199  static_cast<const IOobject&>(*this)
1200  );
1201  }
1202 
1203  labelList recvSizes;
1204  gather(comm_, label(contentData_.size_bytes()), recvSizes);
1205 
1206  List<std::streamoff> blockOffsets;
1207  PtrList<SubList<char>> slaveData; // dummy slave data
1208  return writeBlocks
1209  (
1210  comm_,
1211  osPtr,
1212  blockOffsets,
1213  contentData_,
1214  recvSizes,
1215  slaveData,
1216  commsType_
1217  );
1218 }
1219 
1220 
1221 // ************************************************************************* //
bool good() const noexcept
True if token is not UNDEFINED or ERROR.
Definition: tokenI.H:507
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:50
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
fileName relativeName() const
Return the name of the stream relative to the current case.
Definition: IOstream.C:39
bool isWord() const noexcept
Token is word-variant (WORD, DIRECTIVE)
Definition: tokenI.H:711
virtual bool read()
Read object.
Input/output streams with (internal or external) character storage.
A class for handling file names.
Definition: fileName.H:72
readOption readOpt() const noexcept
Get the read option.
static const Enum< commsTypes > commsTypeNames
Enumerated names for the communication types.
Definition: UPstream.H:82
static label read(const UPstream::commsTypes commsType, const int fromProcNo, char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, UPstream::Request *req=nullptr)
Read buffer contents from given processor.
Definition: UIPstreamRead.C:35
static void gatherSlaveData(const label comm, const UList< char > &data, const labelUList &recvSizes, const labelRange &fromProcs, List< int > &recvOffsets, DynamicList< char > &recvData)
Helper: gather data from (subset of) slaves.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
static bool writeBlocks(const label comm, autoPtr< OSstream > &osPtr, List< std::streamoff > &blockOffset, const UList< char > &masterData, const labelUList &recvSizes, const UPtrList< SubList< char >> &slaveData, const UPstream::commsTypes commsType, const bool syncReturnState=true)
Write *this. Ostream only valid on master.
virtual Ostream & write(const char c) override
Write character.
Definition: OBJstream.C:69
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:160
commsTypes
Communications types.
Definition: UPstream.H:72
Foam::string str() const
Get the string - as Foam::string rather than std::string.
Definition: StringStream.H:96
Input/output from string buffers.
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
bool isCompound() const noexcept
Token is COMPOUND.
Definition: tokenI.H:803
static autoPtr< ISstream > readBlock(const label blocki, ISstream &is, IOobject &headerIO)
Read selected block (non-seeking) + header information.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
Output to file stream, using an OSstream.
Definition: OFstream.H:49
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:52
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
virtual void rename(const word &newName)
Rename the object.
Definition: IOobject.H:677
A token holds an item read from Istream.
Definition: token.H:65
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:272
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content...
Definition: DynamicListI.H:353
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
bool headerOk()
Read and check header info. Does not check the headerClassName.
Definition: regIOobject.C:505
const string & note() const noexcept
Return the optional note.
Definition: IOobjectI.H:225
refPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler - forwards to fileOperation::handler()
static bool readBlocks(const label comm, autoPtr< ISstream > &isPtr, List< char > &contentChars, const UPstream::commsTypes commsType)
Read data into *this. ISstream is only valid on master.
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1229
A simple container for options an IOstream can normally have.
End entry [isseparator].
Definition: token.H:160
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1074
virtual Ostream & writeRaw(const char *data, std::streamsize count) override
Low-level raw binary output.
Definition: OSstream.C:271
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:409
unsigned scalarByteSize() const noexcept
The sizeof (scalar) in bytes associated with the stream.
Definition: IOstream.H:340
virtual const fileName & name() const override
Get the name of the output serial stream. (eg, the name of the Fstream file name) ...
Definition: OSstream.H:128
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write using stream options.
bool writeHeader(Ostream &os) const
Write header with current type()
bool isReadOptional() const noexcept
True if (LAZY_READ) bits are set [same as READ_IF_PRESENT].
char * data_bytes() noexcept
Return pointer to the underlying array serving as data storage,.
Definition: UListI.H:286
IntType end_value() const noexcept
The value 1 beyond the end of the range.
Definition: IntRangeI.H:64
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...
void gather(const Type *sendData, Type *recvData, int count, MPI_Datatype datatype, const label comm, UPstream::Request *req=nullptr, label *requestID=nullptr)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
int canonical() const noexcept
From version to canonical integer value.
virtual const std::ostream & stdStream() const override
Const access to underlying std::ostream.
Definition: OFstream.C:125
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:37
static std::streamoff writeBlockEntry(OSstream &os, const label blocki, const char *str, const size_t len)
Helper: write block of (binary) character data.
void putBack(const token &tok)
Put back a token (copy). Only a single put back is permitted.
Definition: Istream.C:71
A List obtained as a section of another List.
Definition: SubList.H:50
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1065
void setSize(const label n)
Alias for resize()
Definition: List.H:316
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
"scheduled" : (MPI_Send, MPI_Recv)
static bool hasBlock(Istream &is, const label blockNumber)
True if the given block number (starts at 0) has a corresponding decomposedBlockData block entry...
A class for handling words, derived from Foam::string.
Definition: word.H:63
static bool readBlockEntry(Istream &is, List< char > &charData)
Helper: read block of (binary) character data.
static void gather(const char *sendData, int sendCount, char *recvData, const UList< int > &recvCounts, const UList< int > &recvOffsets, const label communicator=worldComm)
Receive variable length char data from all ranks.
virtual Ostream & writeQuoted(const char *str, std::streamsize len, const bool quoted=true) override
Write character/string content, with/without surrounding quotes.
Definition: OBJstream.C:78
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition: UPstream.H:1059
The decomposedBlockData comprise a List<char> for each output processor, typically with IO on the mas...
static const word null
An empty word.
Definition: word.H:84
bool local
Definition: EEqn.H:20
static bool isCollatedType(const word &objectType)
True if object type is a known collated type.
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition: HashTable.H:106
virtual const fileName & name() const override
The name of the input serial stream. (eg, the name of the Fstream file name)
Definition: ISstream.H:141
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:105
static Ostream & writeEndDivider(Ostream &os)
Write the standard end file divider.
Istream & readList(Istream &is)
Read List from Istream, discarding contents of existing List.
Definition: ListIO.C:169
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
int debug
Static debugging option.
OBJstream os(runTime.globalPath()/outputName)
#define FUNCTION_NAME
defineTypeNameAndDebug(combustionModel, 0)
Input from file stream, using an ISstream.
Definition: IFstream.H:49
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:405
bool isReadRequired() const noexcept
True if (MUST_READ | READ_MODIFIED) bits are set.
static bool bannerEnabled() noexcept
Status of output file banner.
Definition: IOobject.H:361
static void broadcasts(const label comm, Type &arg1, Args &&... args)
Broadcast multiple items to all communicator ranks. Does nothing in non-parallel. ...
static label getNumBlocks(Istream &is, const label maxNumBlocks=-1)
Extract number of decomposedBlockData block entries, optionally with an upper limit. The input stream should be in a rewound state (or only have read the header) before calling.
decomposedBlockData(const label comm, const IOobject &io, const UPstream::commsTypes=UPstream::commsTypes::scheduled)
Construct given an IOobject.
static label calcNumProcs(const label comm, const off_t maxBufferSize, const labelUList &recvSizes, const label startProci)
Helper: determine number of processors whose recvSizes fits into maxBufferSize.
const word & headerClassName() const noexcept
Return name of the class name read from header.
Definition: IOobjectI.H:213
Generic input stream using a standard (STL) stream.
Definition: ISstream.H:51
bool fatalCheck(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:51
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:281
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
versionNumber version() const noexcept
Get the stream version.
static bool write(const UPstream::commsTypes commsType, const int toProcNo, const char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, UPstream::Request *req=nullptr, const UPstream::sendModes sendMode=UPstream::sendModes::normal)
Write buffer contents to given processor.
streamFormat
Data format (ascii | binary)
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:66
"nonBlocking" : (MPI_Isend, MPI_Irecv)
const T * cdata() const noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:265
List< label > labelList
A List of labels.
Definition: List.H:62
static rangeType subProcs(const label communicator=worldComm)
Range of process indices for sub-processes.
Definition: UPstream.H:1185
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
bool readHeader(Istream &is)
Read header (&#39;FoamFile&#39; dictionary) and set the IOobject and stream characteristics.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
virtual bool writeData(Ostream &os) const
Write separated content (assumes content is the serialised data)
unsigned labelByteSize() const noexcept
The sizeof (label) in bytes associated with the stream.
Definition: IOstream.H:332
Similar to IStringStream but using an externally managed buffer for its input. This allows the input ...
Definition: ISpanStream.H:286
Output to string buffer, using a OSstream. Always UNCOMPRESSED.
Definition: StringStream.H:256
streamFormat format() const noexcept
Get the current stream format.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
std::streamsize size_bytes() const noexcept
Number of contiguous bytes for the List data.
Definition: UListI.H:293
static bool skipBlockEntry(Istream &is)
Helper: skip a block of (binary) character data.
static void writeHeader(Ostream &os, IOstreamOption streamOptContainer, const word &objectType, const string &note, const fileName &location, const word &objectName, const dictionary &extraEntries)
Helper: write FoamFile IOobject header.
Namespace for OpenFOAM.
static void gather(const label comm, const label data, labelList &datas)
Helper: gather single label. Note: using native Pstream.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...