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-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 "Matrix.H"
30 #include "Istream.H"
31 #include "Ostream.H"
32 #include "token.H"
33 #include "contiguous.H"
34 #include "ListPolicy.H"
35 
36 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
37 
38 template<class Form, class Type>
40 :
41  mRows_(0),
42  nCols_(0),
43  v_(nullptr)
44 {
45  this->readMatrix(is);
46 }
47 
48 
49 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
50 
51 template<class Form, class Type>
53 {
54  // Anull matrix
55  clear();
56 
58 
59  token firstToken(is);
60 
61  is.fatalCheck("readMatrix : reading first token");
62 
63  if (firstToken.isLabel())
64  {
65  mRows_ = firstToken.labelToken();
66  nCols_ = readLabel(is);
67  doAlloc();
68 
69  // The total size
70  const label len = size();
71 
72  if (is.format() == IOstreamOption::BINARY && is_contiguous<Type>::value)
73  {
74  // Binary and contiguous
75 
76  if (len)
77  {
78  Detail::readContiguous<Type>
79  (
80  is,
81  this->data_bytes(),
82  this->size_bytes()
83  );
84 
85  is.fatalCheck("readMatrix : reading the binary block");
86  }
87  }
88  else
89  {
90  // Begin of contents marker
91  char listDelimiter = is.readBeginList("Matrix");
92 
93  if (len)
94  {
95  if (listDelimiter == token::BEGIN_LIST)
96  {
97  auto iter = this->begin();
98 
99  // Loop over rows
100  for (label i = 0; i < mRows_; ++i)
101  {
102  listDelimiter = is.readBeginList("MatrixRow");
103 
104  for (label j = 0; j < nCols_; ++j, (void)++iter)
105  {
106  is >> *iter;
107  is.fatalCheck("readMatrix : reading entry");
108  }
109 
110  is.readEndList("MatrixRow");
111  }
112  }
113  else // BEGIN_BLOCK
114  {
115  Type elem;
116  is >> elem;
117 
118  is.fatalCheck("readMatrix : reading the single entry");
119 
120  std::fill_n(begin(), size(), elem);
121  }
122  }
123 
124  // End of contents marker
125  is.readEndList("Matrix");
126  }
127 
128  return len;
129  }
130 
132  << "incorrect first token, expected <int>, found "
133  << firstToken.info() << nl
134  << exit(FatalIOError);
136  return 0;
137 }
138 
139 
140 template<class Form, class Type>
142 (
143  Ostream& os,
144  const label shortLen
145 ) const
146 {
147  const Matrix<Form, Type>& mat = *this;
148  const label len = mat.size(); // Total size (rows * cols)
149 
150  auto iter = mat.cbegin(); // element-wise iterator
151 
152  // Rows, columns size
153  os << mat.nRows() << token::SPACE << mat.nCols();
154 
155  if (os.format() == IOstreamOption::BINARY && is_contiguous<Type>::value)
156  {
157  // Binary and contiguous
158 
159  if (len)
160  {
161  // write(...) includes surrounding start/end delimiters
162  os.write(mat.cdata_bytes(), mat.size_bytes());
163  }
164  }
165  else if (is_contiguous<Type>::value && len > 1 && mat.uniform())
166  {
167  // Two or more entries, and all entries have identical values.
168  os << token::BEGIN_BLOCK << *iter << token::END_BLOCK;
169  }
170  else if
171  (
172  (len <= 1 || !shortLen)
173  || (len <= shortLen && is_contiguous<Type>::value)
174  )
175  {
176  // Single-line output (entire matrix)
177 
178  // Begin matrix
179  os << token::BEGIN_LIST;
180 
181  // Loop over rows
182  for (label i = 0; i < mat.nRows(); ++i)
183  {
184  // Begin row
185  os << token::BEGIN_LIST;
186 
187  // Write row
188  for (label j = 0; j < mat.nCols(); ++j, (void)++iter)
189  {
190  if (j) os << token::SPACE;
191  os << *iter;
192  }
193 
194  // End row
195  os << token::END_LIST;
196  }
197 
198  // End matrix
199  os << token::END_LIST;
200  }
201  else if
202  (
203  (mat.nCols() <= 1 || !shortLen)
204  || (mat.nCols() <= shortLen && is_contiguous<Type>::value)
205  )
206  {
207  // Multi-line matrix, single-line rows
208 
209  // Begin matrix
210  os << nl << token::BEGIN_LIST;
211 
212  // Loop over rows
213  for (label i = 0; i < mat.nRows(); ++i)
214  {
215  // Begin row
216  os << nl << token::BEGIN_LIST;
217 
218  // Write row
219  for (label j = 0; j < mat.nCols(); ++j, (void)++iter)
220  {
221  if (j) os << token::SPACE;
222  os << *iter;
223  }
224 
225  // End row
226  os << token::END_LIST;
227  }
228 
229  // End matrix
230  os << nl << token::END_LIST << nl;
231  }
232  else
233  {
234  // Multi-line output
235 
236  // Begin matrix
237  os << nl << token::BEGIN_LIST;
238 
239  // Loop over rows
240  for (label i=0; i < mat.nRows(); ++i)
241  {
242  // Begin row
243  os << nl << token::BEGIN_LIST;
244 
245  // Write row
246  for (label j = 0; j < mat.nCols(); ++j, (void)++iter)
247  {
248  os << nl << *iter;
249  }
250 
251  // End row
252  os << nl << token::END_LIST;
253  }
254 
255  // End matrix
256  os << nl << token::END_LIST << nl;
257  }
258 
259  os.check(FUNCTION_NAME);
260  return os;
261 }
262 
263 
264 // ************************************************************************* //
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
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:65
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:45
label nCols() const noexcept
The number of columns.
Definition: Matrix.H:253
Ostream & writeMatrix(Ostream &os, const label shortLen=0) const
Write Matrix, with line-breaks in ASCII when length exceeds shortLen.
Definition: MatrixIO.C:135
label size() const
The number of elements in Matrix (m*n)
Definition: MatrixI.H:89
label nRows() const noexcept
The number of rows.
Definition: Matrix.H:243
bool uniform() const
True if all entries have identical values, and Matrix is non-empty.
Definition: MatrixI.H:159
patchWriters clear()
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:210
OBJstream os(runTime.globalPath()/outputName)
#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:196
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:627
A template class to specify that a data type can be considered as being contiguous in memory...
Definition: contiguous.H:70
Matrix() noexcept
Default construct (empty matrix)
Definition: MatrixI.H:42
const_iterator cbegin() const noexcept
Return const_iterator to begin traversing a constant Matrix.
Definition: MatrixI.H:531
constexpr auto begin(C &c) -> decltype(c.begin())
Return iterator to the beginning of the container c.
Definition: stdFoam.H:168
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 ...