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 "ListStream.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 IOobject::MUST_READ_IF_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  Istream& is,
109  List<char>& charData
110 )
111 {
112  // Handle any of these:
113 
114  // 0. NCHARS (...)
115  // 1. List<char> NCHARS (...)
116  // 2. processorN List<char> NCHARS (...) ;
117  // 3. processorN NCHARS (...) ;
118 
119  is.fatalCheck(FUNCTION_NAME);
120  token tok(is);
121  is.fatalCheck(FUNCTION_NAME);
122 
123  // Dictionary format has primitiveEntry keyword:
124  const bool isDictFormat = (tok.isWord() && !tok.isCompound());
125 
126  if (!isDictFormat && tok.good())
127  {
128  is.putBack(tok);
129  }
130  charData.readList(is);
131 
132  if (isDictFormat)
133  {
134  is.fatalCheck(FUNCTION_NAME);
135  is >> tok;
136  is.fatalCheck(FUNCTION_NAME);
137 
138  // Swallow trailing ';'
139  if (tok.good() && !tok.isPunctuation(token::END_STATEMENT))
140  {
141  is.putBack(tok);
142  }
143  }
144 
145  return true;
146 }
147 
148 
150 {
151  // As per readBlockEntry but seeks instead of reading.
152  // Internals like charList::readList
153 
154  // Handle any of these:
155  // 0. NCHARS (...)
156  // 1. List<char> NCHARS (...)
157  // 2. processorN List<char> NCHARS (...) ;
158  // 3. processorN NCHARS (...) ;
159 
160  if (!is.good()) return false;
161  token tok(is);
162  if (!is.good()) return false;
163 
164  // Dictionary format has primitiveEntry keyword:
165  const bool isDictFormat = (tok.isWord() && !tok.isCompound());
166 
167  if (isDictFormat)
168  {
169  is >> tok;
170  if (!is.good()) return false;
171  }
172 
173 
174  bool handled = false;
175 
176  // Like charList::readList
177  if (tok.isCompound())
178  {
179  handled = true;
180  }
181  else if (tok.isLabel())
182  {
183  // Label: could be int(..) or just a plain '0'
184 
185  const label len = tok.labelToken();
186 
187  // Binary, always contiguous
188 
189  if (len)
190  {
191  const auto oldFmt = is.format(IOstreamOption::BINARY);
192 
193  // read(...) includes surrounding start/end delimiters.
194 
195  // Note: nullptr to seek instead of reading
196  is.read(nullptr, std::streamsize(len));
197 
198  is.format(oldFmt);
199  }
200 
201  handled = true;
202  }
203  else
204  {
205  // Incorrect token
206  return false;
207  }
208 
209  if (isDictFormat)
210  {
211  is.fatalCheck(FUNCTION_NAME);
212  is >> tok;
213  is.fatalCheck(FUNCTION_NAME);
214 
215  // Swallow trailing ';'
216  if (tok.good() && !tok.isPunctuation(token::END_STATEMENT))
217  {
218  is.putBack(tok);
219  }
220  }
221 
222  return handled;
223 }
224 
225 
227 (
228  Istream& is,
229  const bool readHeader
230 )
231 {
232  label nBlocks = 0;
233 
234  if (readHeader)
235  {
236  token tok(is);
237 
238  if (is.good() && tok.isWord("FoamFile"))
239  {
240  dictionary headerDict(is); // Read sub-dictionary content
241 
242  if (headerDict.readIfPresent("version", tok))
243  {
244  is.version(tok);
245  }
246  is.format(headerDict.get<word>("format"));
248  // headerDict.readIfPresent("blocks", nBlocks);
249  //{
250  // return nBlocks;
251  //}
252  }
253  else if (tok.good())
254  {
255  is.putBack(tok);
256  }
257  }
258 
259  while (is.good() && skipBlockEntry(is))
260  {
261  ++nBlocks;
262  }
263 
264  return nBlocks;
265 }
266 
267 
269 (
270  OSstream& os,
271  const label blocki,
272  const UList<char>& charData
273 )
274 {
275  // Offset to the beginning of this output
276 
277  std::streamoff blockOffset = os.stdStream().tellp();
278 
279  const word procName("processor" + Foam::name(blocki));
280 
281  // Write as commented content
282  {
283  os << nl << "// " << procName << nl;
284  charData.writeList(os) << nl;
285  }
286  // Write as primitiveEntry
287  // {
288  // os << nl << procName << nl;
289  // charData.writeList(os);
290  // os.endEntry();
291  // }
292 
293  return blockOffset;
294 }
295 
296 
298 (
299  OSstream& os,
300  const label blocki,
301  const std::string& content
302 )
303 {
304  UList<char> charData
305  (
306  const_cast<char*>(content.data()),
307  label(content.size())
308  );
309 
310  return decomposedBlockData::writeBlockEntry(os, blocki, charData);
311 }
312 
313 
315 (
316  OSstream& os,
317  IOstreamOption streamOptData,
318  const regIOobject& io,
319  const label blocki,
320  const bool withLocalHeader
321 )
322 {
323  // String of all data to write
324  string contentChars;
325  {
326  OStringStream buf(streamOptData);
327 
328  bool ok = true;
329 
330  // Generate FoamFile header on master, without comment banner
331  if (withLocalHeader)
332  {
333  const bool old = IOobject::bannerEnabled(false);
334 
335  ok = io.writeHeader(buf);
336 
338  }
339 
340  // Write the data to the Ostream
341  ok = ok && io.writeData(buf);
342 
343  if (!ok)
344  {
345  return std::streamoff(-1);
346  }
347 
348  contentChars = buf.str();
349  }
351  return decomposedBlockData::writeBlockEntry(os, blocki, contentChars);
352 }
353 
354 
357 (
358  const label blocki,
359  ISstream& is,
360  IOobject& headerIO
361 )
362 {
363  if (debug)
364  {
365  Pout<< "decomposedBlockData::readBlock:"
366  << " stream:" << is.name() << " attempt to read block " << blocki
367  << endl;
368  }
369 
370  // Extracted header information
371  IOstreamOption streamOptData;
372  unsigned labelWidth = is.labelByteSize();
373  unsigned scalarWidth = is.scalarByteSize();
374 
375  autoPtr<ISstream> realIsPtr;
376 
377  // Read master for header
378  List<char> data;
380 
381  if (blocki == 0)
382  {
383  realIsPtr.reset(new IListStream(std::move(data)));
384  realIsPtr->name() = is.name();
385 
386  {
387  // Read header from first block,
388  // advancing the stream position
389  if (!headerIO.readHeader(*realIsPtr))
390  {
391  FatalIOErrorInFunction(*realIsPtr)
392  << "Problem while reading object header "
393  << is.relativeName() << nl
394  << exit(FatalIOError);
395  }
396  }
397  }
398  else
399  {
400  {
401  // Read header from first block
402  UIListStream headerStream(data);
403  if (!headerIO.readHeader(headerStream))
404  {
405  FatalIOErrorInFunction(headerStream)
406  << "Problem while reading object header "
407  << is.relativeName() << nl
408  << exit(FatalIOError);
409  }
410  streamOptData = static_cast<IOstreamOption>(headerStream);
411  labelWidth = headerStream.labelByteSize();
412  scalarWidth = headerStream.scalarByteSize();
413  }
414 
415  for (label i = 1; i < blocki+1; i++)
416  {
417  // Read and discard data, only retain the last one
419  }
420  realIsPtr.reset(new IListStream(std::move(data)));
421  realIsPtr->name() = is.name();
422 
423  // Apply stream settings
424  realIsPtr().format(streamOptData.format());
425  realIsPtr().version(streamOptData.version());
426  realIsPtr().setLabelByteSize(labelWidth);
427  realIsPtr().setScalarByteSize(scalarWidth);
428  }
429 
430  return realIsPtr;
431 }
432 
433 
435 (
436  const label comm,
437  autoPtr<ISstream>& isPtr,
438  List<char>& data,
439  const UPstream::commsTypes commsType
440 )
441 {
442  if (debug)
443  {
444  Pout<< "decomposedBlockData::readBlocks:"
445  << " stream:" << (isPtr ? isPtr->name() : "invalid")
446  << " commsType:" << Pstream::commsTypeNames[commsType]
447  << " comm:" << comm << endl;
448  }
449 
450  bool ok = false;
451 
452  if (UPstream::master(comm))
453  {
454  auto& is = *isPtr;
456 
457  // Read master data
459  }
460 
461  if (commsType == UPstream::commsTypes::scheduled)
462  {
463  if (UPstream::master(comm))
464  {
465  // Master data already read ...
466  auto& is = *isPtr;
468 
469  // Read and transmit slave data
470  for (const int proci : UPstream::subProcs(comm))
471  {
472  List<char> elems;
474 
475  OPstream os
476  (
478  proci,
479  0,
481  comm
482  );
483  os << elems;
484  }
485 
486  ok = is.good();
487  }
488  else
489  {
490  IPstream is
491  (
494  0,
496  comm
497  );
498  is >> data;
499  }
500  }
501  else
502  {
503  PstreamBuffers pBufs(comm, UPstream::commsTypes::nonBlocking);
504 
505  if (UPstream::master(comm))
506  {
507  // Master data already read ...
508  auto& is = *isPtr;
510 
511  // Read and transmit slave data
512  for (const int proci : UPstream::subProcs(comm))
513  {
514  List<char> elems;
516 
517  UOPstream os(proci, pBufs);
518  os << elems;
519  }
520  }
521 
522  pBufs.finishedScatters();
523 
524  if (!UPstream::master(comm))
525  {
526  UIPstream is(UPstream::masterNo(), pBufs);
527  is >> data;
528  }
529  }
530 
532 
533  return ok;
534 }
535 
536 
538 (
539  const label comm,
540  const fileName& fName,
541  autoPtr<ISstream>& isPtr,
542  IOobject& headerIO,
543  const UPstream::commsTypes commsType
544 )
545 {
546  if (debug)
547  {
548  Pout<< "decomposedBlockData::readBlocks:"
549  << " stream:" << (isPtr ? isPtr->name() : "invalid")
550  << " commsType:" << Pstream::commsTypeNames[commsType] << endl;
551  }
552 
553  bool ok = false;
554  List<char> data;
555  autoPtr<ISstream> realIsPtr;
556 
557  if (UPstream::master(comm))
558  {
559  auto& is = *isPtr;
561 
562  // Read master data
564 
565  realIsPtr.reset(new IListStream(std::move(data)));
566  realIsPtr->name() = fName;
567 
568  {
569  // Read header from first block,
570  // advancing the stream position
571  if (!headerIO.readHeader(*realIsPtr))
572  {
573  FatalIOErrorInFunction(*realIsPtr)
574  << "Problem while reading object header "
575  << is.relativeName() << nl
576  << exit(FatalIOError);
577  }
578  }
579  }
580 
581  if (commsType == UPstream::commsTypes::scheduled)
582  {
583  if (UPstream::master(comm))
584  {
585  // Master data already read ...
586  auto& is = *isPtr;
588 
589  // Read and transmit slave data
590  for (const int proci : UPstream::subProcs(comm))
591  {
593 
594  OPstream os
595  (
597  proci,
598  0,
600  comm
601  );
602  os << data;
603  }
604 
605  ok = is.good();
606  }
607  else
608  {
609  IPstream is
610  (
613  0,
615  comm
616  );
617  is >> data;
618 
619  realIsPtr.reset(new IListStream(std::move(data)));
620  realIsPtr->name() = fName;
621  }
622  }
623  else
624  {
625  PstreamBuffers pBufs(comm, UPstream::commsTypes::nonBlocking);
626 
627  if (UPstream::master(comm))
628  {
629  // Master data already read ...
630  auto& is = *isPtr;
632 
633  // Read and transmit slave data
634  for (const int proci : UPstream::subProcs(comm))
635  {
636  List<char> elems;
638 
639  UOPstream os(proci, pBufs);
640  os << elems;
641  }
642 
643  ok = is.good();
644  }
645 
646  pBufs.finishedScatters();
647 
648  if (!UPstream::master(comm))
649  {
650  UIPstream is(UPstream::masterNo(), pBufs);
651  is >> data;
652 
653  realIsPtr.reset(new IListStream(std::move(data)));
654  realIsPtr->name() = fName;
655  }
656  }
657 
658  Pstream::broadcast(ok, comm);
659 
660  // Broadcast master header info,
661  // set stream properties from realIsPtr on master
662 
663  int verValue;
664  int fmtValue;
665  unsigned labelWidth;
666  unsigned scalarWidth;
667  word headerName(headerIO.name());
668 
669  if (UPstream::master(comm))
670  {
671  verValue = realIsPtr().version().canonical();
672  fmtValue = static_cast<int>(realIsPtr().format());
673  labelWidth = realIsPtr().labelByteSize();
674  scalarWidth = realIsPtr().scalarByteSize();
675  }
676 
678  (
679  UPstream::worldComm, // Future? comm,
680  verValue,
681  fmtValue,
682  labelWidth,
683  scalarWidth,
684  headerName,
685  headerIO.headerClassName(),
686  headerIO.note()
687  // Unneeded: headerIO.instance()
688  // Unneeded: headerIO.local()
689  );
690 
691  realIsPtr().version(IOstreamOption::versionNumber::canonical(verValue));
692  realIsPtr().format(IOstreamOption::streamFormat(fmtValue));
693  realIsPtr().setLabelByteSize(labelWidth);
694  realIsPtr().setScalarByteSize(scalarWidth);
695 
696  headerIO.rename(headerName);
697 
698  return realIsPtr;
699 }
700 
701 
703 (
704  const label comm,
705  const label data,
706  labelList& datas
707 )
708 {
709  const label nProcs = UPstream::nProcs(comm);
710  datas.resize(nProcs);
711 
712  char* data0Ptr = datas.data_bytes();
713 
714  List<int> recvOffsets;
715  List<int> recvSizes;
716  if (UPstream::master(comm))
717  {
718  recvOffsets.setSize(nProcs);
719  forAll(recvOffsets, proci)
720  {
721  // Note: truncating long int to int since UPstream::gather limited
722  // to ints
723  recvOffsets[proci] =
724  int(reinterpret_cast<char*>(&datas[proci]) - data0Ptr);
725  }
726  recvSizes.setSize(nProcs, sizeof(label));
727  }
728 
730  (
731  reinterpret_cast<const char*>(&data),
732  sizeof(label),
733  data0Ptr,
734  recvSizes,
735  recvOffsets,
736  comm
737  );
738 }
739 
740 
742 (
743  const label comm,
744  const UList<char>& data,
745  const labelUList& recvSizes,
746 
747  const labelRange& fromProcs,
748 
749  List<int>& sliceOffsets,
750  DynamicList<char>& recvData
751 )
752 {
753  const label myProci = UPstream::myProcNo(comm);
754  const label numProcs = UPstream::nProcs(comm);
755 
756  int nSendBytes = 0;
757  recvData.clear();
758 
759  // Calculate master data
760  List<int> sliceSizes;
761  if (UPstream::master(comm))
762  {
763  sliceSizes.resize(numProcs, 0);
764  sliceOffsets.resize(numProcs+1, 0);
765 
766  // Offset 1 beyond the end of the range
767  const label endProci = fromProcs.end_value();
768 
769  int totalSize = 0;
770  for (const label proci : fromProcs)
771  {
772  sliceSizes[proci] = int(recvSizes[proci]);
773  sliceOffsets[proci] = totalSize;
774  totalSize += sliceSizes[proci];
775  }
776 
777  sliceOffsets[endProci] = totalSize;
778  recvData.resize(totalSize);
779  }
780  else if (fromProcs.contains(myProci))
781  {
782  // Note: UPstream::gather limited to int
783  nSendBytes = int(data.size_bytes());
784  }
785 
787  (
788  data.cdata(),
789  nSendBytes,
790 
791  recvData.data(),
792  sliceSizes,
793  sliceOffsets,
794  comm
795  );
796 }
797 
798 
800 (
801  const label comm,
802  const off_t maxBufferSize,
803  const labelUList& recvSizes,
804  const label startProci
805 )
806 {
807  const label nProcs = UPstream::nProcs(comm);
808 
809  label nSendProcs = 0;
810  if (UPstream::master(comm))
811  {
812  off_t totalSize = recvSizes[startProci];
813  label proci = startProci+1;
814  while (proci < nProcs && (totalSize+recvSizes[proci] < maxBufferSize))
815  {
816  totalSize += recvSizes[proci];
817  proci++;
818  }
819 
820  nSendProcs = proci-startProci;
821  }
822 
823  Pstream::broadcast(nSendProcs, comm);
824 
825  return nSendProcs;
826 }
827 
828 
830 (
831  const label comm,
832  autoPtr<OSstream>& osPtr,
833  List<std::streamoff>& blockOffset,
834  const UList<char>& masterData,
835 
836  const labelUList& recvSizes,
837  const UPtrList<SubList<char>>& slaveData,
838 
839  const UPstream::commsTypes commsType,
840  const bool syncReturnState
841 )
842 {
843  if (debug)
844  {
845  Pout<< "decomposedBlockData::writeBlocks:"
846  << " stream:" << (osPtr ? osPtr->name() : "none")
847  << " data:" << masterData.size()
848  << " (master only) slaveData:" << slaveData.size()
849  << " commsType:" << Pstream::commsTypeNames[commsType] << endl;
850  }
851 
852  const label nProcs = UPstream::nProcs(comm);
853 
854  bool ok = true;
855 
856  // Write master data
857  if (UPstream::master(comm))
858  {
859  blockOffset.resize(nProcs);
860 
861  OSstream& os = osPtr();
862 
863  blockOffset[UPstream::masterNo()] =
865  (
866  os,
868  masterData
869  );
870 
871  ok = os.good();
872  }
873 
874  if (slaveData.size())
875  {
876  // Already have gathered the slave data.
877 
878  if (UPstream::master(comm))
879  {
880  // Master data already written ...
881  OSstream& os = osPtr();
882 
883  // Write slaves
884  for (label proci = 1; proci < nProcs; ++proci)
885  {
886  blockOffset[proci] =
888  (
889  os,
890  proci,
891  slaveData[proci]
892  );
893  }
894 
895  ok = os.good();
896  }
897  }
898  else if (commsType == UPstream::commsTypes::scheduled)
899  {
900  if (UPstream::master(comm))
901  {
902  // Master data already written ...
903  OSstream& os = osPtr();
904 
905  // Receive and write slaves
906  label maxNonLocalSize = 0;
907  for (label proci = 1; proci < nProcs; ++proci)
908  {
909  maxNonLocalSize = max(maxNonLocalSize, recvSizes[proci]);
910  }
911 
912  DynamicList<char> elems(maxNonLocalSize);
913  for (label proci = 1; proci < nProcs; ++proci)
914  {
915  elems.resize_nocopy(recvSizes[proci]);
917  (
919  proci,
920  elems.data(),
921  elems.size_bytes(),
923  comm
924  );
925 
926  blockOffset[proci] =
928  (
929  os,
930  proci,
931  elems
932  );
933  }
934 
935  ok = os.good();
936  }
937  else
938  {
940  (
943  masterData.cdata(),
944  masterData.size_bytes(),
946  comm
947  );
948  }
949  }
950  else
951  {
952  // Master data already written ...
953 
954  // Find out how many processor can be received into
955  // maxMasterFileBufferSize
956 
957  // Starting slave processor and number of processors
958  label startProc = 1;
959  label nSendProcs = nProcs-1;
960 
961  DynamicList<char> recvData;
962 
963  while (nSendProcs > 0 && startProc < nProcs)
964  {
965  nSendProcs = calcNumProcs
966  (
967  comm,
968  off_t
969  (
970  fileOperations::masterUncollatedFileOperation::
971  maxMasterFileBufferSize
972  ),
973  recvSizes,
974  startProc
975  );
976 
977  if (nSendProcs == 0)
978  {
979  break;
980  }
981 
982 
983  // Gather data from (a slice of) the slaves
984  labelRange fromProcs(startProc, nSendProcs);
985 
986  List<int> sliceOffsets;
987  gatherSlaveData
988  (
989  comm,
990  masterData,
991  recvSizes,
992 
993  fromProcs,
994 
995  sliceOffsets,
996  recvData
997  );
998 
999  if (UPstream::master(comm))
1000  {
1001  OSstream& os = osPtr();
1002 
1003  // Write received data
1004  for (const label proci : fromProcs)
1005  {
1006  SubList<char> dataSlice
1007  (
1008  recvData,
1009  sliceOffsets[proci+1]-sliceOffsets[proci],
1010  sliceOffsets[proci]
1011  );
1012 
1013  blockOffset[proci] =
1015  (
1016  os,
1017  proci,
1018  dataSlice
1019  );
1020  }
1021  }
1022 
1023  startProc += nSendProcs;
1024  }
1025 
1026  if (UPstream::master(comm))
1027  {
1028  ok = osPtr->good();
1029  }
1030  }
1031 
1032  if (syncReturnState)
1033  {
1034  //- Enable to get synchronised error checking. Is the one that keeps
1035  // slaves as slow as the master (which does all the writing)
1036  Pstream::broadcast(ok, comm);
1037  }
1038 
1039  return ok;
1040 }
1041 
1042 
1044 {
1045  autoPtr<ISstream> isPtr;
1046  fileName objPath(fileHandler().filePath(false, *this, word::null));
1047  if (UPstream::master(comm_))
1048  {
1049  isPtr.reset(new IFstream(objPath));
1050  IOobject::readHeader(*isPtr);
1051  }
1052 
1053  return readBlocks(comm_, isPtr, contentData_, commsType_);
1054 }
1055 
1056 
1058 {
1059  IOobject io(*this);
1060  IOstreamOption streamOpt(os);
1061 
1062  int verValue;
1063  int fmtValue;
1064  // Unneeded: word masterName(name());
1065  fileName masterLocation(instance()/db().dbDir()/local());
1066 
1067  // Re-read my own data to find out the header information
1068  if (Pstream::master(comm_))
1069  {
1070  UIListStream headerStream(contentData_);
1071  io.readHeader(headerStream);
1072 
1073  verValue = headerStream.version().canonical();
1074  fmtValue = static_cast<int>(headerStream.format());
1075  }
1076 
1077  // Broadcast header information
1079  (
1080  comm_,
1081  verValue,
1082  fmtValue,
1083  // Unneeded: masterName
1084  io.headerClassName(),
1085  io.note(),
1086  // Unneeded: io.instance()
1087  // Unneeded: io.local()
1088  masterLocation
1089  );
1090 
1092  streamOpt.format(IOstreamOption::streamFormat(fmtValue));
1093 
1094  if (!Pstream::master(comm_))
1095  {
1097  (
1098  os,
1099  streamOpt, // streamOpt for data
1100  io.headerClassName(),
1101  io.note(),
1102  masterLocation,
1103  name(),
1104  dictionary()
1105  );
1106  }
1107 
1108  // Write the character data
1109  if (isA<OFstream>(os))
1110  {
1111  // Serial file output - can use writeRaw()
1112  os.writeRaw(contentData_.cdata(), contentData_.size_bytes());
1113  }
1114  else
1115  {
1116  // Other cases are less fortunate, and no std::string_view
1117  std::string str(contentData_.cdata(), contentData_.size_bytes());
1118  os.writeQuoted(str, false);
1119  }
1120 
1121  if (!Pstream::master(comm_))
1122  {
1124  }
1125 
1126  return os.good();
1128 
1129 
1131 (
1132  IOstreamOption streamOpt,
1133  const bool writeOnProc
1134 ) const
1135 {
1136  autoPtr<OSstream> osPtr;
1137  if (UPstream::master(comm_))
1138  {
1139  // Note: always write binary. These are strings so readable anyway.
1140  // They have already be tokenised on the sending side.
1141 
1142  osPtr.reset(new OFstream(objectPath(), IOstreamOption::BINARY));
1143 
1144  // Update meta-data for current state
1145  const_cast<regIOobject&>
1146  (
1147  static_cast<const regIOobject&>(*this)
1148  ).updateMetaData();
1149 
1151  (
1152  *osPtr,
1153  streamOpt, // streamOpt for data
1154  static_cast<const IOobject&>(*this)
1155  );
1156  }
1157 
1158  labelList recvSizes;
1159  gather(comm_, label(contentData_.size_bytes()), recvSizes);
1160 
1161  List<std::streamoff> blockOffsets;
1162  PtrList<SubList<char>> slaveData; // dummy slave data
1163  return writeBlocks
1164  (
1165  comm_,
1166  osPtr,
1167  blockOffsets,
1168  contentData_,
1169  recvSizes,
1170  slaveData,
1171  commsType_
1172  );
1173 }
1174 
1175 
1176 // ************************************************************************* //
virtual const fileName & name() const
Get the name of the output serial stream. (eg, the name of the Fstream file name) ...
Definition: OSstream.H:128
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
virtual bool read()
Read object.
A class for handling file names.
Definition: fileName.H:71
readOption readOpt() const noexcept
Get the read option.
static const Enum< commsTypes > commsTypeNames
Enumerated names for the communication types.
Definition: UPstream.H:84
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
virtual const fileName & name() const
The name of the input serial stream. (eg, the name of the Fstream file name)
Definition: ISstream.H:136
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.
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:132
commsTypes
Communications types.
Definition: UPstream.H:74
Input/output from string buffers.
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:162
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:51
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
virtual void rename(const word &newName)
Rename the object.
Definition: IOobject.H:648
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:229
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content...
Definition: DynamicListI.H:351
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
bool headerOk()
Read and check header info. Does not check the headerClassName.
Definition: regIOobject.C:437
const string & note() const noexcept
Return the optional note.
Definition: IOobjectI.H:192
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:1184
A simple container for options an IOstream can normally have.
virtual std::ostream & stdStream()
Access to underlying std::ostream.
Definition: OFstream.C:110
End entry [isseparator].
Definition: token.H:157
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:1029
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:411
unsigned scalarByteSize() const noexcept
The sizeof (scalar) in bytes associated with the stream.
Definition: IOstream.H:340
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write using stream options.
bool writeHeader(Ostream &os) const
Write header with current type()
virtual Ostream & writeQuoted(const std::string &str, const bool quoted=true)
Write std::string surrounded by quotes.
Definition: OBJstream.C:101
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:243
IntType end_value() const noexcept
The value 1 beyond the end of the range.
Definition: IntRangeI.H:64
static label getNumBlocks(Istream &is, const bool readHeader)
Extract number of blocks from decomposedBlockData file stream.
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all processes in communicator.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:414
void gather(const Type *sendData, Type *recvData, int count, MPI_Datatype datatype, const label comm, UPstream::Request *req=nullptr, label *requestID=nullptr)
int canonical() const noexcept
From version to canonical integer value.
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:37
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:1020
void setSize(const label n)
Alias for resize()
Definition: List.H:289
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
"scheduled" : (MPI_Send, MPI_Recv)
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.
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition: UPstream.H:1014
The decomposedBlockData comprise a List<char> for each output processor, typically with IO on the mas...
static std::streamoff writeBlockEntry(OSstream &os, const label blocki, const UList< char > &charData)
Helper: write block of (binary) character data.
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:100
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:99
Similar to IStringStream but using an externally managed buffer for its input. This allows the input ...
Definition: UIListStream.H:224
static Ostream & writeEndDivider(Ostream &os)
Write the standard end file divider.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:55
int debug
Static debugging option.
OBJstream os(runTime.globalPath()/outputName)
#define FUNCTION_NAME
defineTypeNameAndDebug(combustionModel, 0)
Database for solution data, solver performance and other reduced data.
Definition: data.H:52
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:389
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:344
static void broadcasts(const label comm, Type &arg1, Args &&... args)
Broadcast multiple items to all processes in communicator.
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:180
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:607
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:1037
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:65
"nonBlocking" : (MPI_Isend, MPI_Irecv)
const T * cdata() const noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:222
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:1140
Input/output streams with managed List storage.
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
virtual Ostream & writeRaw(const char *data, std::streamsize count)
Low-level raw binary output.
Definition: OSstream.C:242
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:171
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
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:250
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 ...