MatrixIO.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "Matrix.H"
27 #include "Istream.H"
28 #include "Ostream.H"
29 #include "token.H"
30 #include "contiguous.H"
31 
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
33 
34 template<class Form, class Type>
36 :
37  mRows_(0),
38  nCols_(0),
39  v_(nullptr)
40 {
41  operator>>(is, *this);
42 }
43 
44 
45 template<class Form, class Type>
47 {
48  // Anull matrix
49  M.clear();
50 
51  is.fatalCheck("operator>>(Istream&, Matrix<Form, Type>&)");
52 
53  token firstToken(is);
54 
55  is.fatalCheck
56  (
57  "operator>>(Istream&, Matrix<Form, Type>&) : reading first token"
58  );
59 
60  if (firstToken.isLabel())
61  {
62  M.mRows_ = firstToken.labelToken();
63  M.nCols_ = readLabel(is);
64 
65  label mn = M.mRows_*M.nCols_;
66 
67  // Read list contents depending on data format
68  if (is.format() == IOstream::ASCII || !contiguous<Type>())
69  {
70  // Read beginning of contents
71  char listDelimiter = is.readBeginList("Matrix");
72 
73  if (mn)
74  {
75  M.allocate();
76  Type* v = M.v_;
77 
78  if (listDelimiter == token::BEGIN_LIST)
79  {
80  label k = 0;
81 
82  // loop over rows
83  for (label i=0; i<M.m(); i++)
84  {
85  listDelimiter = is.readBeginList("MatrixRow");
86 
87  for (label j=0; j<M.n(); j++)
88  {
89  is >> v[k++];
90 
91  is.fatalCheck
92  (
93  "operator>>(Istream&, Matrix<Form, Type>&) : "
94  "reading entry"
95  );
96  }
97 
98  is.readEndList("MatrixRow");
99  }
100  }
101  else
102  {
103  Type element;
104  is >> element;
105 
106  is.fatalCheck
107  (
108  "operator>>(Istream&, Matrix<Form, Type>&) : "
109  "reading the single entry"
110  );
111 
112  for (label i=0; i<mn; i++)
113  {
114  v[i] = element;
115  }
116  }
117  }
118 
119  // Read end of contents
120  is.readEndList("Matrix");
121  }
122  else
123  {
124  if (mn)
125  {
126  M.allocate();
127  Type* v = M.v_;
128 
129  is.read(reinterpret_cast<char*>(v), mn*sizeof(Type));
130 
131  is.fatalCheck
132  (
133  "operator>>(Istream&, Matrix<Form, Type>&) : "
134  "reading the binary block"
135  );
136  }
137  }
138  }
139  else
140  {
142  << "incorrect first token, expected <int>, found "
143  << firstToken.info()
144  << exit(FatalIOError);
145  }
146 
147  return is;
148 }
149 
150 
151 template<class Form, class Type>
152 Foam::Ostream& Foam::operator<<(Ostream& os, const Matrix<Form, Type>& M)
153 {
154  label mn = M.mRows_*M.nCols_;
155 
156  os << M.m() << token::SPACE << M.n();
157 
158  // Write list contents depending on data format
159  if (os.format() == IOstream::ASCII || !contiguous<Type>())
160  {
161  if (mn)
162  {
163  bool uniform = false;
164 
165  const Type* v = M.v_;
166 
167  if (mn > 1 && contiguous<Type>())
168  {
169  uniform = true;
170 
171  for (label i=0; i<mn; i++)
172  {
173  if (v[i] != v[0])
174  {
175  uniform = false;
176  break;
177  }
178  }
179  }
180 
181  if (uniform)
182  {
183  // Write size of list and start contents delimiter
184  os << token::BEGIN_BLOCK;
185 
186  // Write list contents
187  os << v[0];
188 
189  // Write end of contents delimiter
190  os << token::END_BLOCK;
191  }
192  else if (mn < 10 && contiguous<Type>())
193  {
194  // Write size of list and start contents delimiter
195  os << token::BEGIN_LIST;
196 
197  label k = 0;
198 
199  // loop over rows
200  for (label i=0; i<M.m(); i++)
201  {
202  os << token::BEGIN_LIST;
203 
204  // Write row
205  for (label j=0; j< M.n(); j++)
206  {
207  if (j > 0) os << token::SPACE;
208  os << v[k++];
209  }
210 
211  os << token::END_LIST;
212  }
213 
214  // Write end of contents delimiter
215  os << token::END_LIST;
216  }
217  else
218  {
219  // Write size of list and start contents delimiter
220  os << nl << token::BEGIN_LIST;
221 
222  label k = 0;
223 
224  // loop over rows
225  for (label i=0; i<M.m(); i++)
226  {
227  os << nl << token::BEGIN_LIST;
228 
229  // Write row
230  for (label j=0; j< M.n(); j++)
231  {
232  os << nl << v[k++];
233  }
234 
235  os << nl << token::END_LIST;
236  }
237 
238  // Write end of contents delimiter
239  os << nl << token::END_LIST << nl;
240  }
241  }
242  else
243  {
244  os << token::BEGIN_LIST << token::END_LIST << nl;
245  }
246  }
247  else
248  {
249  if (mn)
250  {
251  os.write(reinterpret_cast<const char*>(M.v_), mn*sizeof(Type));
252  }
253  }
254 
255  // Check state of IOstream
256  os.check("Ostream& operator<<(Ostream&, const Matrix&)");
257 
258  return os;
259 }
260 
261 
262 // ************************************************************************* //
bool isLabel() const
Definition: tokenI.H:271
label n() const
Return the number of columns.
Definition: MatrixI.H:64
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
char readEndList(const char *funcName)
Definition: Istream.C:148
InfoProxy< token > info() const
Return info proxy.
Definition: token.H:380
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
A token holds items read from Istream.
Definition: token.H:69
Template function to specify if the data of a type are contiguous.
label k
Boltzmann constant.
Matrix()
Null constructor.
Definition: MatrixI.H:31
virtual Istream & read(token &)=0
Return next token from stream.
Istream & operator>>(Istream &, directionInfo &)
streamFormat format() const
Return current stream format.
Definition: IOstream.H:377
char readBeginList(const char *funcName)
Definition: Istream.C:127
void clear()
Clear the Matrix, i.e. set sizes to zero.
Definition: Matrix.C:214
label readLabel(Istream &is)
Definition: label.H:64
void fatalCheck(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:105
A templated (m x n) matrix of objects of <T>.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
static const char nl
Definition: Ostream.H:265
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:331
label labelToken() const
Definition: tokenI.H:276
label m() const
Return the number of rows.
Definition: MatrixI.H:57
#define M(I)
IOerror FatalIOError