Chaste  Release::3.4
FibreReader.cpp
1 /*
2 
3 Copyright (c) 2005-2016, University of Oxford.
4 All rights reserved.
5 
6 University of Oxford means the Chancellor, Masters and Scholars of the
7 University of Oxford, having an administrative office at Wellington
8 Square, Oxford OX1 2JD, UK.
9 
10 This file is part of Chaste.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14  * Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16  * Redistributions in binary form must reproduce the above copyright notice,
17  this list of conditions and the following disclaimer in the documentation
18  and/or other materials provided with the distribution.
19  * Neither the name of the University of Oxford nor the names of its
20  contributors may be used to endorse or promote products derived from this
21  software without specific prior written permission.
22 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34 */
35 
36 #include "FibreReader.hpp"
37 
38 #include <sstream>
39 #include "Exception.hpp"
40 
41 template<unsigned DIM>
42 FibreReader<DIM>::FibreReader(const FileFinder& rFileFinder, FibreFileType fibreFileType)
43  : mFileIsBinary(false), // overwritten by ReadNumLinesOfDataFromFile() if applicable.
44  mNextIndex(0u)
45 {
46  if (fibreFileType == AXISYM)
47  {
48  mNumItemsPerLine = DIM;
49  }
50  else //(fibreFileType == ORTHO)
51  {
52  mNumItemsPerLine = DIM*DIM;
53  }
54  mTokens.resize(mNumItemsPerLine);
55 
56  mFilePath = rFileFinder.GetAbsolutePath();
57  mDataFile.open(mFilePath.c_str());
58  if (!mDataFile.is_open())
59  {
60  EXCEPTION("Failed to open fibre file " + rFileFinder.GetAbsolutePath());
61  }
62 
63  // Note: this method will close the file on error
65 }
66 
67 template<unsigned DIM>
69 {
70  mDataFile.close();
71 }
72 
73 template<unsigned DIM>
74 void FibreReader<DIM>::GetAllAxi(std::vector< c_vector<double, DIM> >& direction)
75 {
76  assert(direction.empty());
77  if (mNumItemsPerLine != DIM)
78  {
79  EXCEPTION("Use GetAllOrtho when reading orthotropic fibres");
80  }
81  direction.reserve(mNumLinesOfData);
82  for (unsigned i=0; i<mNumLinesOfData; i++)
83  {
84  c_vector<double, DIM> temp_vector;
85  GetFibreVector(i, temp_vector, false);
86  direction.push_back(temp_vector);
87  }
88 }
89 
90 template<unsigned DIM>
91 void FibreReader<DIM>::GetAllOrtho(std::vector< c_vector<double, DIM> >& first_direction,
92  std::vector< c_vector<double, DIM> >& second_direction,
93  std::vector< c_vector<double, DIM> >& third_direction)
94 {
95  assert(first_direction.empty());
96  assert(second_direction.empty());
97  assert(third_direction.empty());
98  if (mNumItemsPerLine != DIM*DIM)
99  {
100  EXCEPTION("Use GetAllAxi when reading axisymmetric fibres");
101  }
102  for (unsigned i=0; i<mNumLinesOfData; i++)
103  {
104  c_matrix<double, DIM, DIM> temp_matrix;
105  GetFibreSheetAndNormalMatrix(i, temp_matrix, true);
106 
107  //Note that although the matrix appears row-wise in the ascii .ortho file,
108  //for convenience it is stored column-wise.
109  matrix_column<c_matrix<double, DIM, DIM> > col0(temp_matrix, 0);
110  first_direction.push_back(col0);
111  if (DIM>=2)
112  {
113  matrix_column<c_matrix<double, DIM, DIM> > col1(temp_matrix, 1);
114  second_direction.push_back(col1);
115  }
116  if (DIM==3)
117  {
118  matrix_column<c_matrix<double, DIM, DIM> > col2(temp_matrix, 2);
119  third_direction.push_back(col2);
120  }
121  }
122 
123 }
124 template<unsigned DIM>
126  c_matrix<double,DIM,DIM>& rFibreMatrix,
127  bool checkOrthogonality)
128 {
129  if (mNumItemsPerLine != DIM*DIM)
130  {
131  EXCEPTION("Use GetFibreVector when reading axisymmetric fibres");
132  }
133  if (fibreIndex < mNextIndex)
134  {
135  EXCEPTION("Fibre reads must be monotonically increasing; " << fibreIndex
136  << " is before expected next index " << mNextIndex);
137  }
138  if (mFileIsBinary)
139  {
140 
141  // Skip to the desired index
142  mDataFile.seekg((fibreIndex-mNextIndex)*mNumItemsPerLine*sizeof(double), std::ios::cur);
143  // Take mNumItemsPerLine from the ifstream
144  mDataFile.read((char*)&(rFibreMatrix(0,0)), mNumItemsPerLine*sizeof(double));
145  mNextIndex = fibreIndex+1;
146  }
147  else
148  {
149  unsigned num_entries = 0u;
150  while (fibreIndex >= mNextIndex)
151  {
152  num_entries = GetTokensAtNextLine();
153  mNextIndex++;
154  }
155  if(num_entries < mNumItemsPerLine)
156  {
157  EXCEPTION("A line is incomplete in " << mFilePath
158  << " - each line should contain " << DIM*DIM << " entries");
159  }
160  for(unsigned i=0; i<DIM; i++)
161  {
162  for(unsigned j=0; j<DIM; j++)
163  {
164  rFibreMatrix(i,j) = mTokens[DIM*i + j];
165  }
166  }
167 
168  }
169 
170  // The binary file and ascii file are row-major. However, we store column major matrices.
171  rFibreMatrix = trans(rFibreMatrix);
172 
173  if (checkOrthogonality)
174  {
175  // Note that we define this matrix before setting it as otherwise the profiling build will break (see #2367)
176  c_matrix<double,DIM,DIM> temp;
177  temp = prod(trans(rFibreMatrix), rFibreMatrix);
178 
179  // Check temp is equal to the identity
180  for (unsigned i=0; i<DIM; i++)
181  {
182  for (unsigned j=0; j<DIM; j++)
183  {
184  double val = (i==j ? 1.0 : 0.0);
185 
186  if (fabs(temp(i,j)-val) > 1e-4)
187  {
188  EXCEPTION("Read fibre-sheet matrix, " << rFibreMatrix << " from file "
189  << " which is not orthogonal (tolerance 1e-4)");
190  }
191  }
192  }
193  }
194 }
195 
196 template<unsigned DIM>
197 void FibreReader<DIM>::GetFibreVector(unsigned fibreIndex,
198  c_vector<double,DIM>& rFibreVector,
199  bool checkNormalised)
200 {
201  if (mNumItemsPerLine != DIM)
202  {
203  EXCEPTION("Use GetFibreSheetAndNormalMatrix when reading orthotropic fibres");
204  }
205  if (fibreIndex < mNextIndex)
206  {
207  EXCEPTION("Fibre reads must be monotonically increasing; " << fibreIndex
208  << " is before expected next index " << mNextIndex);
209  }
210 
211  if (mFileIsBinary)
212  {
213  // Skip to the desired index
214  mDataFile.seekg((fibreIndex-mNextIndex)*mNumItemsPerLine*sizeof(double), std::ios::cur);
215  // Take mNumItemsPerLine from the ifstream
216  mDataFile.read((char*)&rFibreVector[0], mNumItemsPerLine*sizeof(double));
217  mNextIndex = fibreIndex+1;
218  }
219  else
220  {
221  unsigned num_entries = 0u;
222  while (fibreIndex >= mNextIndex)
223  {
224  num_entries = GetTokensAtNextLine();
225  mNextIndex++;
226  }
227  if (num_entries < mNumItemsPerLine)
228  {
229  EXCEPTION("A line is incomplete in " << mFilePath
230  << " - each line should contain " << DIM << " entries");
231  }
232  for (unsigned i=0; i<DIM; i++)
233  {
234  rFibreVector(i) = mTokens[i];
235  }
236  }
237 
238 
239  if (checkNormalised && fabs(norm_2(rFibreVector)-1)>1e-4)
240  {
241  EXCEPTION("Read vector " << rFibreVector << " from file "
242  << mFilePath << " which is not normalised (tolerance 1e-4)");
243  }
244 }
245 
246 
247 template<unsigned DIM>
249 {
250  assert(mTokens.size() == mNumItemsPerLine);
251 
252  std::string line;
253  bool blank_line;
254 
255  do
256  {
257  getline(mDataFile, line);
258 
259  if (line.empty() && mDataFile.eof())
260  {
261  mDataFile.close();
262  std::string error = "End of file " + mFilePath + " reached. Either file contains fewer "
263  + "definitions than defined in header, or one of the GetNext[..] methods "
264  + "has been called too often";
265  EXCEPTION(error);
266  }
267 
268  // get rid of any comments
269  line = line.substr(0, line.find('#'));
270 
271  blank_line = (line.find_first_not_of(" \t",0) == std::string::npos);
272  }
273  while(blank_line);
274 
275  // get rid of any trailing whitespace
276  std::string::iterator iter = line.end();
277  iter--;
278  unsigned nchars2delete = 0;
279  while(*iter == ' ' || *iter == '\t')
280  {
281  nchars2delete++;
282  iter--;
283  }
284  line.erase(line.length()-nchars2delete);
285 
286  std::stringstream line_stream(line);
287 
288  unsigned index = 0;
289  while (!line_stream.eof())
290  {
291  double item;
292  line_stream >> item;
293  if(index >= mNumItemsPerLine)
294  {
295  EXCEPTION("Too many entries in a line in " + mFilePath);
296  }
297  mTokens[index++] = item;
298  }
299 
300  return index; // the number of entries put into mTokens
301 }
302 
303 
304 template<unsigned DIM>
306 {
307  std::string raw_line;
308  bool blank_line = false;
309  do
310  {
311  getline(mDataFile, raw_line);
312  //Strip comments following a hash
313  raw_line = raw_line.substr(0, raw_line.find('#'));
314  //Check for blank line
315  blank_line = (raw_line.find_first_not_of(" \t",0) == std::string::npos);
316  }
317  while (blank_line);
318 
319  std::stringstream header_line(raw_line);
320 
321  header_line >> mNumLinesOfData;
322 
323  std::string extras;
324  header_line >> extras;
325 
326  if (extras=="BIN")
327  {
328  mFileIsBinary = true;
329  }
330  else if (extras!="")
331  {
332  mDataFile.close();
333  EXCEPTION("First (non comment) line of the fibre orientation file should contain the number of lines of data in the file (and possibly a BIN tag) at most");
334  }
335 }
336 
337 
338 
339 template class FibreReader<1>;
340 template class FibreReader<2>;
341 template class FibreReader<3>;
342 
343 
344 
345 
346 
FibreReader(const FileFinder &rFileFinder, FibreFileType fibreFileType)
Definition: FibreReader.cpp:42
std::ifstream mDataFile
Definition: FibreReader.hpp:65
std::string GetAbsolutePath() const
Definition: FileFinder.cpp:221
#define EXCEPTION(message)
Definition: Exception.hpp:143
void ReadNumLinesOfDataFromFile()
unsigned GetTokensAtNextLine()
std::string mFilePath
Definition: FibreReader.hpp:68
std::vector< double > mTokens
Definition: FibreReader.hpp:82
unsigned mNumItemsPerLine
Definition: FibreReader.hpp:76
void GetFibreVector(unsigned fibreIndex, c_vector< double, DIM > &rFibreVector, bool checkNormalised=true)
void GetAllAxi(std::vector< c_vector< double, DIM > > &direction)
Definition: FibreReader.cpp:74
void GetAllOrtho(std::vector< c_vector< double, DIM > > &first_direction, std::vector< c_vector< double, DIM > > &second_direction, std::vector< c_vector< double, DIM > > &third_direction)
Definition: FibreReader.cpp:91
void GetFibreSheetAndNormalMatrix(unsigned fibreIndex, c_matrix< double, DIM, DIM > &rFibreMatrix, bool checkOrthogonality=true)