MatrixIO.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2019-2025 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 "Matrix.H"
30 #include "Istream.H"
31 #include "Ostream.H"
32 #include "token.H"
33 
34 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
35 
36 template<class Form, class Type>
38 :
39  Matrix<Form, Type>()
40 {
41  this->readMatrix(is);
42 }
43 
44 
45 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
46 
47 template<class Form, class Type>
49 {
50  // Anull matrix
51  clear();
52 
54 
55  token firstToken(is);
56 
57  is.fatalCheck("readMatrix : reading first token");
58 
59  if (firstToken.isLabel())
60  {
61  mRows_ = firstToken.labelToken();
62  nCols_ = readLabel(is);
63  doAlloc();
64 
65  // The total size
66  const label len = size();
67 
68  if (is.format() == IOstreamOption::BINARY && is_contiguous_v<Type>)
69  {
70  // Binary and contiguous
71 
72  if (len)
73  {
74  Detail::readContiguous<Type>
75  (
76  is,
77  this->data_bytes(),
78  this->size_bytes()
79  );
80 
81  is.fatalCheck("readMatrix : reading the binary block");
82  }
83  }
84  else
85  {
86  // Begin of contents marker
87  char listDelimiter = is.readBeginList("Matrix");
88 
89  if (len)
90  {
91  if (listDelimiter == token::BEGIN_LIST)
92  {
93  auto iter = this->begin();
94 
95  // Loop over rows
96  for (label i = 0; i < mRows_; ++i)
97  {
98  listDelimiter = is.readBeginList("MatrixRow");
99 
100  for (label j = 0; j < nCols_; ++j, (void)++iter)
101  {
102  is >> *iter;
103  is.fatalCheck("readMatrix : reading entry");
104  }
105 
106  is.readEndList("MatrixRow");
107  }
108  }
109  else // BEGIN_BLOCK
110  {
111  Type elem;
112  is >> elem;
113 
114  is.fatalCheck("readMatrix : reading the single entry");
115 
116  std::fill_n(begin(), size(), elem);
117  }
118  }
119 
120  // End of contents marker
121  is.readEndList("Matrix");
122  }
123 
124  return len;
125  }
126 
128  << "incorrect first token, expected <int>, found "
129  << firstToken.info() << nl
130  << exit(FatalIOError);
132  return 0;
133 }
134 
135 
136 template<class Form, class Type>
138 (
139  Ostream& os,
140  const label shortLen
141 ) const
142 {
143  const Matrix<Form, Type>& mat = *this;
144  const label len = mat.size(); // Total size (rows * cols)
145 
146  auto iter = mat.cbegin(); // element-wise iterator
147 
148  // Rows, columns size
149  os << mat.nRows() << token::SPACE << mat.nCols();
150 
151  if (os.format() == IOstreamOption::BINARY && is_contiguous_v<Type>)
152  {
153  // Binary and contiguous
154 
155  if (len)
156  {
157  // write(...) includes surrounding start/end delimiters
158  os.write(mat.cdata_bytes(), mat.size_bytes());
159  }
160  }
161  else if (is_contiguous_v<Type> && len > 1 && mat.uniform())
162  {
163  // Two or more entries, and all entries have identical values.
164  os << token::BEGIN_BLOCK << *iter << token::END_BLOCK;
165  }
166  else if
167  (
168  (len <= 1 || !shortLen)
169  || (len <= shortLen && is_contiguous_v<Type>)
170  )
171  {
172  // Single-line output (entire matrix)
173 
174  // Begin matrix
175  os << token::BEGIN_LIST;
176 
177  // Loop over rows
178  for (label i = 0; i < mat.nRows(); ++i)
179  {
180  // Begin row
181  os << token::BEGIN_LIST;
182 
183  // Write row
184  for (label j = 0; j < mat.nCols(); ++j, (void)++iter)
185  {
186  if (j) os << token::SPACE;
187  os << *iter;
188  }
189 
190  // End row
191  os << token::END_LIST;
192  }
193 
194  // End matrix
195  os << token::END_LIST;
196  }
197  else if
198  (
199  (mat.nCols() <= 1 || !shortLen)
200  || (mat.nCols() <= shortLen && is_contiguous_v<Type>)
201  )
202  {
203  // Multi-line matrix, single-line rows
204 
205  // Begin matrix
206  os << nl << token::BEGIN_LIST;
207 
208  // Loop over rows
209  for (label i = 0; i < mat.nRows(); ++i)
210  {
211  // Begin row
212  os << nl << token::BEGIN_LIST;
213 
214  // Write row
215  for (label j = 0; j < mat.nCols(); ++j, (void)++iter)
216  {
217  if (j) os << token::SPACE;
218  os << *iter;
219  }
220 
221  // End row
222  os << token::END_LIST;
223  }
224 
225  // End matrix
226  os << nl << token::END_LIST << nl;
227  }
228  else
229  {
230  // Multi-line output
231 
232  // Begin matrix
233  os << nl << token::BEGIN_LIST;
234 
235  // Loop over rows
236  for (label i=0; i < mat.nRows(); ++i)
237  {
238  // Begin row
239  os << nl << token::BEGIN_LIST;
240 
241  // Write row
242  for (label j = 0; j < mat.nCols(); ++j, (void)++iter)
243  {
244  os << nl << *iter;
245  }
246 
247  // End row
248  os << nl << token::END_LIST;
249  }
250 
251  // End matrix
252  os << nl << token::END_LIST << nl;
253  }
254 
255  os.check(FUNCTION_NAME);
256  return os;
257 }
258 
259 
260 // ************************************************************************* //
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
constexpr Matrix() noexcept
Default construct (empty matrix)
Definition: MatrixI.H:43
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:45
char readEndList(const char *funcName)
End read of list data, ends with &#39;)&#39; or &#39;}&#39;.
Definition: Istream.C:192
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
A token holds an item read from Istream.
Definition: token.H:69
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:63
bool readMatrix(Istream &is)
Read Matrix from Istream, discarding existing contents.
Definition: MatrixIO.C:41
label nCols() const noexcept
The number of columns.
Definition: Matrix.H:266
Ostream & writeMatrix(Ostream &os, const label shortLen=0) const
Write Matrix, with line-breaks in ASCII when length exceeds shortLen.
Definition: MatrixIO.C:131
label nRows() const noexcept
The number of rows.
Definition: Matrix.H:256
bool uniform() const
True if all entries have identical values, and Matrix is non-empty.
Definition: MatrixI.H:153
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
label size() const noexcept
The number of elements in Matrix (m*n)
Definition: MatrixI.H:83
char readBeginList(const char *funcName)
Begin read of list data, starts with &#39;(&#39; or &#39;{&#39;.
Definition: Istream.C:171
A templated (m x n) matrix of objects of <T>. The layout is (mRows x nCols) - row-major order: ...
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
std::streamsize size_bytes() const noexcept
Number of contiguous bytes for the Matrix data, no runtime check that the type is actually contiguous...
Definition: MatrixI.H:193
#define FUNCTION_NAME
const char * cdata_bytes() const noexcept
Return pointer to the underlying array serving as data storage, reinterpreted as byte data...
Definition: MatrixI.H:179
bool fatalCheck(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:51
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:681
surface1 clear()
const_iterator cbegin() const noexcept
Return const_iterator to begin traversing a constant Matrix.
Definition: MatrixI.H:514
streamFormat format() const noexcept
Get the current stream format.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...