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 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 #include <algorithm>
36 
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38 
39 template<class Form, class Type>
41 :
42  mRows_(0),
43  nCols_(0),
44  v_(nullptr)
45 {
46  operator>>(is, *this);
47 }
48 
49 
50 template<class Form, class Type>
52 {
53  // Anull matrix
54  clear();
55 
57 
58  token firstToken(is);
59 
60  is.fatalCheck("readMatrix : reading first token");
61 
62  if (firstToken.isLabel())
63  {
64  mRows_ = firstToken.labelToken();
65  nCols_ = readLabel(is);
66  doAlloc();
67 
68  // The total size
69  const label len = size();
70 
71  // Read list contents depending on data format
72  if (is.format() == IOstream::ASCII || !is_contiguous<Type>::value)
73  {
74  // Read beginning of contents
75  char listDelimiter = is.readBeginList("Matrix");
76 
77  if (len)
78  {
79  if (listDelimiter == token::BEGIN_LIST)
80  {
81  label idx = 0;
82 
83  // Loop over rows
84  for (label i = 0; i < mRows_; ++i)
85  {
86  listDelimiter = is.readBeginList("MatrixRow");
87 
88  for (label j = 0; j < nCols_; ++j)
89  {
90  is >> v_[idx++];
91 
92  is.fatalCheck("readMatrix : reading reading entry");
93  }
94 
95  is.readEndList("MatrixRow");
96  }
97  }
98  else
99  {
100  Type element;
101  is >> element;
102 
103  is.fatalCheck("readMatrix : reading the single entry");
104 
105  std::fill(begin(), end(), element);
106  }
107  }
108 
109  // Read end of contents
110  is.readEndList("Matrix");
111  }
112  else
113  {
114  if (len)
115  {
116  Detail::readContiguous<Type>
117  (
118  is,
119  reinterpret_cast<char*>(v_),
120  len*sizeof(Type)
121  );
122 
123  is.fatalCheck("readMatrix : reading the binary block");
124  }
125  }
126 
127  return len;
128  }
129 
130 
132  << "incorrect first token, expected <int>, found "
133  << firstToken.info()
134  << exit(FatalIOError);
135 
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 
149  // The total size
150  const label len = mat.size();
151 
152  // Rows, columns size
153  os << mat.m() << token::SPACE << mat.n();
154 
155  // Write list contents depending on data format
156  if (os.format() == IOstream::ASCII || !is_contiguous<Type>::value)
157  {
158  if (len)
159  {
160  const Type* v = mat.cdata();
161 
162  // Can the contents be considered 'uniform' (ie, identical)
163  if (len > 1 && is_contiguous<Type>::value && mat.uniform())
164  {
165  // Two or more entries, and all entries have identical values.
166  os << token::BEGIN_BLOCK << v[0] << token::END_BLOCK;
167  }
168  else if (len < shortLen && is_contiguous<Type>::value)
169  {
170  // Write start contents delimiter
171  os << token::BEGIN_LIST;
172 
173  label idx = 0;
174 
175  // Loop over rows
176  for (label i = 0; i < mat.m(); ++i)
177  {
178  os << token::BEGIN_LIST;
179 
180  // Write row
181  for (label j = 0; j < mat.n(); ++j)
182  {
183  if (j) os << token::SPACE;
184  os << v[idx++];
185  }
186 
187  os << token::END_LIST;
188  }
189 
190  // Write end of contents delimiter
191  os << token::END_LIST;
192  }
193  else
194  {
195  // Write start contents delimiter
196  os << nl << token::BEGIN_LIST;
197 
198  label idx = 0;
199 
200  // Loop over rows
201  for (label i=0; i < mat.m(); ++i)
202  {
203  os << nl << token::BEGIN_LIST;
204 
205  // Write row
206  for (label j=0; j < mat.n(); ++j)
207  {
208  os << nl << v[idx++];
209  }
210 
211  os << nl << token::END_LIST;
212  }
213 
214  // Write end of contents delimiter
215  os << nl << token::END_LIST << nl;
216  }
217  }
218  else
219  {
220  os << token::BEGIN_LIST << token::END_LIST << nl;
221  }
222  }
223  else
224  {
225  // Contents are binary and contiguous
226 
227  if (len)
228  {
229  // write(...) includes surrounding start/end delimiters
230  os.write
231  (
232  reinterpret_cast<const char*>(mat.cdata()),
233  len*sizeof(Type)
234  );
235  }
236  }
237 
238  os.check(FUNCTION_NAME);
239  return os;
240 }
241 
242 
243 template<class Form, class Type>
245 {
246  mat.readMatrix(is);
247  return is;
248 }
249 
250 
251 template<class Form, class Type>
252 Foam::Ostream& Foam::operator<<(Ostream& os, const Matrix<Form, Type>& mat)
253 {
254  return mat.writeMatrix(os, Detail::ListPolicy::short_length<Type>::value);
255 }
256 
257 
258 // ************************************************************************* //
token.H
Foam::token::labelToken
label labelToken() const
Return label value.
Definition: tokenI.H:487
Foam::token::isLabel
bool isLabel() const noexcept
Token is LABEL.
Definition: tokenI.H:481
stdFoam::begin
constexpr auto begin(C &c) -> decltype(c.begin())
Return iterator to the beginning of the container c.
Definition: stdFoam.H:97
Foam::Matrix::n
label n() const noexcept
The number of columns.
Definition: MatrixI.H:102
Matrix.H
Foam::Istream::readBeginList
char readBeginList(const char *funcName)
Begin read of list data, starts with '(' or '{'.
Definition: Istream.C:146
Foam::Matrix::writeMatrix
Ostream & writeMatrix(Ostream &os, const label shortLen=0) const
Definition: MatrixIO.C:142
Foam::IOstream::fatalCheck
bool fatalCheck(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:57
Foam::IOstreamOption::format
streamFormat format() const noexcept
Get the current stream format.
Definition: IOstreamOption.H:289
Foam::Istream::readEndList
char readEndList(const char *funcName)
End read of list data, ends with ')' or '}'.
Definition: Istream.C:167
Foam::FatalIOError
IOerror FatalIOError
Foam::operator>>
Istream & operator>>(Istream &, directionInfo &)
Definition: directionInfo.C:230
Foam::token
A token holds an item read from Istream.
Definition: token.H:68
ListPolicy.H
Foam::Matrix
A templated (m x n) matrix of objects of <T>. The layout is (mRows x nCols) - row-major order:
Definition: DiagonalMatrix.H:53
Foam::operator<<
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:83
Foam::token::info
InfoProxy< token > info() const
Return info proxy for printing token information to a stream.
Definition: token.H:551
Foam::Istream
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:61
Istream.H
Foam::Matrix::readMatrix
bool readMatrix(Istream &is)
Read Matrix from Istream, discarding existing contents.
Definition: MatrixIO.C:51
Foam::IOstream::check
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:51
Foam::Matrix::size
label size() const
The number of elements in Matrix (m*n)
Definition: MatrixI.H:109
stdFoam::end
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:121
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Ostream.H
Foam::Matrix::uniform
bool uniform() const
True if all entries have identical values, and Matrix is non-empty.
Definition: MatrixI.H:179
clear
patchWriters clear()
Foam::Matrix::m
label m() const noexcept
The number of rows.
Definition: MatrixI.H:95
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::readLabel
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:66
contiguous.H
Foam::Matrix::cdata
const Type * cdata() const noexcept
Definition: MatrixI.H:201
FUNCTION_NAME
#define FUNCTION_NAME
Definition: messageStream.H:270
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:401
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::Matrix::Matrix
Matrix()
Construct null.
Definition: MatrixI.H:48
Foam::is_contiguous
A template class to specify that a data type can be considered as being contiguous in memory.
Definition: contiguous.H:75