FreeFOAM The Cross-Platform CFD Toolkit
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 | Copyright (C) 1991-2010 OpenCFD Ltd.
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 <OpenFOAM/Istream.H>
28 #include <OpenFOAM/Ostream.H>
29 #include <OpenFOAM/token.H>
30 #include <OpenFOAM/contiguous.H>
31 
32 // * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * //
33 
34 template<class Form, class Type>
36 :
37  n_(0),
38  m_(0),
39  v_(NULL)
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("operator>>(Istream&, Matrix<Form, Type>&) : reading first token");
56 
57  if (firstToken.isLabel())
58  {
59  M.n_ = firstToken.labelToken();
60  M.m_ = readLabel(is);
61 
62  label nm = M.n_*M.m_;
63 
64  // Read list contents depending on data format
65  if (is.format() == IOstream::ASCII || !contiguous<Type>())
66  {
67  // Read beginning of contents
68  char listDelimiter = is.readBeginList("Matrix");
69 
70  if (nm)
71  {
72  M.allocate();
73  Type* v = M.v_[0];
74 
75  if (listDelimiter == token::BEGIN_LIST)
76  {
77  label k = 0;
78 
79  // loop over rows
80  for (register label i=0; i<M.n(); i++)
81  {
82  listDelimiter = is.readBeginList("MatrixRow");
83 
84  for (register label j=0; j<M.m(); j++)
85  {
86  is >> v[k++];
87 
88  is.fatalCheck
89  (
90  "operator>>(Istream&, Matrix<Form, Type>&) : "
91  "reading entry"
92  );
93  }
94 
95  is.readEndList("MatrixRow");
96  }
97  }
98  else
99  {
100  Type element;
101  is >> element;
102 
103  is.fatalCheck
104  (
105  "operator>>(Istream&, Matrix<Form, Type>&) : "
106  "reading the single entry"
107  );
108 
109  for (register label i=0; i<nm; i++)
110  {
111  v[i] = element;
112  }
113  }
114  }
115 
116  // Read end of contents
117  is.readEndList("Matrix");
118  }
119  else
120  {
121  if (nm)
122  {
123  M.allocate();
124  Type* v = M.v_[0];
125 
126  is.read(reinterpret_cast<char*>(v), nm*sizeof(Type));
127 
128  is.fatalCheck
129  (
130  "operator>>(Istream&, Matrix<Form, Type>&) : "
131  "reading the binary block"
132  );
133  }
134  }
135  }
136  else
137  {
138  FatalIOErrorIn("operator>>(Istream&, Matrix<Form, Type>&)", is)
139  << "incorrect first token, expected <int>, found "
140  << firstToken.info()
141  << exit(FatalIOError);
142  }
143 
144  return is;
145 }
146 
147 
148 template<class Form, class Type>
149 Foam::Ostream& Foam::operator<<(Ostream& os, const Matrix<Form, Type>& M)
150 {
151  label nm = M.n_*M.m_;
152 
153  os << M.n() << token::SPACE << M.m();
154 
155  // Write list contents depending on data format
156  if (os.format() == IOstream::ASCII || !contiguous<Type>())
157  {
158  if (nm)
159  {
160  bool uniform = false;
161 
162  const Type* v = M.v_[0];
163 
164  if (nm > 1 && contiguous<Type>())
165  {
166  uniform = true;
167 
168  for (register label i=0; i< nm; i++)
169  {
170  if (v[i] != v[0])
171  {
172  uniform = false;
173  break;
174  }
175  }
176  }
177 
178  if (uniform)
179  {
180  // Write size of list and start contents delimiter
181  os << token::BEGIN_BLOCK;
182 
183  // Write list contents
184  os << v[0];
185 
186  // Write end of contents delimiter
187  os << token::END_BLOCK;
188  }
189  else if (nm < 10 && contiguous<Type>())
190  {
191  // Write size of list and start contents delimiter
192  os << token::BEGIN_LIST;
193 
194  label k = 0;
195 
196  // loop over rows
197  for (register label i=0; i< M.n(); i++)
198  {
199  os << token::BEGIN_LIST;
200 
201  // Write row
202  for (register label j=0; j< M.m(); j++)
203  {
204  if (j > 0) os << token::SPACE;
205  os << v[k++];
206  }
207 
208  os << token::END_LIST;
209  }
210 
211  // Write end of contents delimiter
212  os << token::END_LIST;
213  }
214  else
215  {
216  // Write size of list and start contents delimiter
217  os << nl << token::BEGIN_LIST;
218 
219  label k = 0;
220 
221  // loop over rows
222  for (register label i=0; i< M.n(); i++)
223  {
224  os << nl << token::BEGIN_LIST;
225 
226  // Write row
227  for (register label j=0; j< M.m(); j++)
228  {
229  os << nl << v[k++];
230  }
231 
232  os << nl << token::END_LIST;
233  }
234 
235  // Write end of contents delimiter
236  os << nl << token::END_LIST << nl;
237  }
238  }
239  else
240  {
242  }
243  }
244  else
245  {
246  if (nm)
247  {
248  os.write(reinterpret_cast<const char*>(M.v_[0]), nm*sizeof(Type));
249  }
250  }
251 
252  // Check state of IOstream
253  os.check("Ostream& operator<<(Ostream&, const Matrix&)");
254 
255  return os;
256 }
257 
258 
259 // ************************ vim: set sw=4 sts=4 et: ************************ //