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