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-2020 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  if (token::compound::isCompound(Form::typeName()))
49  {
50  os << Form::typeName() << " ";
51  }
52 
53  os << M;
54 }
55 
56 
57 template<class Form, class Type>
58 Foam::Istream& Foam::operator>>(Istream& is, Matrix<Form, Type>& M)
59 {
60  // Anull matrix
61  M.clear();
62 
63  is.fatalCheck("operator>>(Istream&, Matrix<Form, Type>&)");
64 
65  token firstToken(is);
66 
67  is.fatalCheck
68  (
69  "operator>>(Istream&, Matrix<Form, Type>&) : reading first token"
70  );
71 
72  if (firstToken.isCompound())
73  {
74  M.transfer
75  (
76  dynamicCast<token::Compound<Form>>
77  (
78  firstToken.transferCompoundToken(is)
79  )
80  );
81  }
82  else if (firstToken.isLabel())
83  {
84  M.mRows_ = firstToken.labelToken();
85  M.nCols_ = readLabel(is);
86 
87  label mn = M.mRows_*M.nCols_;
88 
89  // Read list contents depending on data format
90  if (is.format() == IOstream::ASCII || !contiguous<Type>())
91  {
92  // Read beginning of contents
93  char listDelimiter = is.readBeginList("Matrix");
94 
95  if (mn)
96  {
97  M.allocate();
98  Type* v = M.v_;
99 
100  if (listDelimiter == token::BEGIN_LIST)
101  {
102  label k = 0;
103 
104  // loop over rows
105  for (label i=0; i<M.m(); i++)
106  {
107  listDelimiter = is.readBeginList("MatrixRow");
108 
109  for (label j=0; j<M.n(); j++)
110  {
111  is >> v[k++];
112 
113  is.fatalCheck
114  (
115  "operator>>(Istream&, Matrix<Form, Type>&) : "
116  "reading entry"
117  );
118  }
119 
120  is.readEndList("MatrixRow");
121  }
122  }
123  else
124  {
125  Type element;
126  is >> element;
127 
128  is.fatalCheck
129  (
130  "operator>>(Istream&, Matrix<Form, Type>&) : "
131  "reading the single entry"
132  );
133 
134  for (label i=0; i<mn; i++)
135  {
136  v[i] = element;
137  }
138  }
139  }
140 
141  // Read end of contents
142  is.readEndList("Matrix");
143  }
144  else
145  {
146  if (mn)
147  {
148  M.allocate();
149  Type* v = M.v_;
150 
151  is.read(reinterpret_cast<char*>(v), mn*sizeof(Type));
152 
153  is.fatalCheck
154  (
155  "operator>>(Istream&, Matrix<Form, Type>&) : "
156  "reading the binary block"
157  );
158  }
159  }
160  }
161  else
162  {
164  << "incorrect first token, expected <int>, found "
165  << firstToken.info()
166  << exit(FatalIOError);
167  }
168 
169  return is;
170 }
171 
172 
173 template<class Form, class Type>
174 Foam::Ostream& Foam::operator<<(Ostream& os, const Matrix<Form, Type>& M)
175 {
176  label mn = M.mRows_*M.nCols_;
177 
178  os << M.m() << token::SPACE << M.n();
179 
180  // Write list contents depending on data format
181  if (os.format() == IOstream::ASCII || !contiguous<Type>())
182  {
183  if (mn)
184  {
185  bool uniform = false;
186 
187  const Type* v = M.v_;
188 
189  if (mn > 1 && contiguous<Type>())
190  {
191  uniform = true;
192 
193  for (label i=0; i<mn; i++)
194  {
195  if (v[i] != v[0])
196  {
197  uniform = false;
198  break;
199  }
200  }
201  }
202 
203  if (uniform)
204  {
205  // Write size of list and start contents delimiter
206  os << token::BEGIN_BLOCK;
207 
208  // Write list contents
209  os << v[0];
210 
211  // Write end of contents delimiter
212  os << token::END_BLOCK;
213  }
214  else if (mn < 10 && contiguous<Type>())
215  {
216  // Write size of list and start contents delimiter
217  os << token::BEGIN_LIST;
218 
219  label k = 0;
220 
221  // loop over rows
222  for (label i=0; i<M.m(); i++)
223  {
224  os << token::BEGIN_LIST;
225 
226  // Write row
227  for (label j=0; j< M.n(); j++)
228  {
229  if (j > 0) os << token::SPACE;
230  os << v[k++];
231  }
232 
233  os << token::END_LIST;
234  }
235 
236  // Write end of contents delimiter
237  os << token::END_LIST;
238  }
239  else
240  {
241  // Write size of list and start contents delimiter
242  os << nl << token::BEGIN_LIST;
243 
244  label k = 0;
245 
246  // loop over rows
247  for (label i=0; i<M.m(); i++)
248  {
249  os << nl << token::BEGIN_LIST;
250 
251  // Write row
252  for (label j=0; j< M.n(); j++)
253  {
254  os << nl << v[k++];
255  }
256 
257  os << nl << token::END_LIST;
258  }
259 
260  // Write end of contents delimiter
261  os << nl << token::END_LIST << nl;
262  }
263  }
264  else
265  {
267  }
268  }
269  else
270  {
271  if (mn)
272  {
273  os.write(reinterpret_cast<const char*>(M.v_), mn*sizeof(Type));
274  }
275  }
276 
277  // Check state of IOstream
278  os.check("Ostream& operator<<(Ostream&, const Matrix&)");
279 
280  return os;
281 }
282 
283 
284 // ************************************************************************* //
label k
#define M(I)
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
A templated (m x n) matrix of objects of <T>.
Definition: Matrix.H:80
Matrix()
Null constructor.
Definition: MatrixI.H:31
friend Istream & operator>>(Istream &, mType &)
Read Matrix from Istream, discarding contents of existing Matrix.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
static bool isCompound(const word &name)
Return true if name is a compound type.
Definition: token.C:82
@ BEGIN_BLOCK
Definition: token.H:110
@ END_BLOCK
Definition: token.H:111
@ BEGIN_LIST
Definition: token.H:106
@ END_LIST
Definition: token.H:107
Template function to specify if the data of a type are contiguous.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:318
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
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
To & dynamicCast(From &r)
Reference type cast template function,.
Definition: typeInfo.H:90
void writeEntry(Ostream &os, const HashTable< T, Key, Hash > &ht)
Definition: HashTableIO.C:96
Istream & operator>>(Istream &, directionInfo &)
IOerror FatalIOError
label readLabel(Istream &is)
Definition: label.H:64
Ostream & operator<<(Ostream &, const ensightPart &)
static const char nl
Definition: Ostream.H:260