FibreReader.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 #include "FibreReader.hpp"
00030 
00031 #include <sstream>
00032 #include "Exception.hpp"
00033 
00034 template<unsigned DIM>
00035 FibreReader<DIM>::FibreReader(FileFinder& rFileFinder, FibreFileType fibreFileType)
00036    : mFileIsBinary(false) // overwritten by ReadNumLinesOfDataFromFile() if applicable.
00037 {
00038     if (fibreFileType == AXISYM)
00039     {
00040         mNumItemsPerLine = DIM;
00041     }
00042     else //(fibreFileType == ORTHO)
00043     {
00044         mNumItemsPerLine = DIM*DIM;
00045     }
00046     mTokens.resize(mNumItemsPerLine);
00047 
00048     mFilePath = rFileFinder.GetAbsolutePath();
00049     mDataFile.open(mFilePath.c_str());
00050     if (!mDataFile.is_open())
00051     {
00052         EXCEPTION("Failed to open fibre file " + rFileFinder.GetAbsolutePath());
00053     }
00054 
00055     // Note: this method will close the file on error
00056     ReadNumLinesOfDataFromFile();
00057 }
00058 
00059 template<unsigned DIM>
00060 FibreReader<DIM>::~FibreReader()
00061 {
00062     mDataFile.close();
00063 }
00064 
00065 template<unsigned DIM>
00066 void FibreReader<DIM>::GetAllAxi(std::vector< c_vector<double, DIM> >& direction)
00067 {
00068     assert(direction.empty());
00069     if (mNumItemsPerLine != DIM)
00070     {
00071         EXCEPTION("Use GetAllOrtho when reading orthotropic fibres");
00072     }
00073     for (unsigned i=0; i<mNumLinesOfData; i++)
00074     {
00075         c_vector<double, DIM> temp_vector;
00076         GetNextFibreVector(temp_vector, false);
00077         direction.push_back(temp_vector);
00078     }
00079 }
00080 
00081 template<unsigned DIM>
00082 void FibreReader<DIM>::GetAllOrtho(std::vector< c_vector<double, DIM> >& first_direction,
00083                                    std::vector< c_vector<double, DIM> >& second_direction,
00084                                    std::vector< c_vector<double, DIM> >& third_direction)
00085 {
00086     assert(first_direction.empty());
00087     assert(second_direction.empty());
00088     assert(third_direction.empty());
00089     if (mNumItemsPerLine != DIM*DIM)
00090     {
00091         EXCEPTION("Use GetAllAxi when reading axisymmetric fibres");
00092     }
00093     for (unsigned i=0; i<mNumLinesOfData; i++)
00094     {
00095         c_matrix<double, DIM, DIM> temp_matrix;
00096         GetNextFibreSheetAndNormalMatrix(temp_matrix, true);
00097 
00098         //Note that although the matrix appears row-wise in the ascii .ortho file,
00099         //for convenience it is stored column-wise.
00100         matrix_column<c_matrix<double, DIM, DIM> > col0(temp_matrix, 0);
00101         first_direction.push_back(col0);
00102         if (DIM>=2)
00103         {
00104             matrix_column<c_matrix<double, DIM, DIM> > col1(temp_matrix, 1);
00105             second_direction.push_back(col1);
00106         }
00107         if (DIM==3)
00108         {
00109             matrix_column<c_matrix<double, DIM, DIM> > col2(temp_matrix, 2);
00110             third_direction.push_back(col2);
00111         }
00112     }
00113 
00114 }
00115 template<unsigned DIM>
00116 void FibreReader<DIM>::GetNextFibreSheetAndNormalMatrix(c_matrix<double,DIM,DIM>& rFibreMatrix,
00117                                                         bool checkOrthogonality)
00118 {
00119     if (mNumItemsPerLine != DIM*DIM)
00120     {
00121         EXCEPTION("Use GetNextFibreVector when reading axisymmetric fibres");
00122     }
00123 
00124     if (mFileIsBinary)
00125     {
00126         //Take mNumItemsPerLine from the ifstream
00127         mDataFile.read((char*)&(rFibreMatrix(0,0)), mNumItemsPerLine*sizeof(double));
00128     }
00129     else
00130     {
00131         unsigned num_entries = GetTokensAtNextLine();
00132         if(num_entries < mNumItemsPerLine)
00133         {
00134             EXCEPTION("A line is incomplete in " << mFilePath
00135                           << " - each line should contain " << DIM*DIM << " entries");
00136         }
00137         for(unsigned i=0; i<DIM; i++)
00138         {
00139             for(unsigned j=0; j<DIM; j++)
00140             {
00141                 rFibreMatrix(i,j) = mTokens[DIM*i + j];
00142             }
00143         }
00144 
00145     }
00146 
00147     //The binary file and ascii file are row-major.  However, we store column major
00148     //matrices
00149     rFibreMatrix = trans(rFibreMatrix);
00150 
00151 
00152     if(checkOrthogonality)
00153     {
00154         c_matrix<double,DIM,DIM>  temp = prod(trans(rFibreMatrix),rFibreMatrix);
00155         // check temp is equal to the identity
00156         for(unsigned i=0; i<DIM; i++)
00157         {
00158             for(unsigned j=0; j<DIM; j++)
00159             {
00160                 double val = (i==j ? 1.0 : 0.0);
00161 
00162                 if(fabs(temp(i,j)-val)>1e-4)
00163                 {
00164                     EXCEPTION("Read fibre-sheet matrix, " << rFibreMatrix << " from file "
00165                                   << " which is not orthogonal (tolerance 1e-4)");
00166                 }
00167             }
00168         }
00169     }
00170 
00171 }
00172 
00173 template<unsigned DIM>
00174 void FibreReader<DIM>::GetNextFibreVector(c_vector<double,DIM>& rFibreVector,
00175                                           bool checkNormalised)
00176 {
00177     if (mNumItemsPerLine != DIM)
00178     {
00179         EXCEPTION("Use GetNextFibreSheetAndNormalMatrix when reading orthotropic fibres");
00180     }
00181 
00182     if (mFileIsBinary)
00183     {
00184         //Take mNumItemsPerLine from the ifstream
00185         mDataFile.read((char*)&rFibreVector[0], mNumItemsPerLine*sizeof(double));
00186     }
00187     else
00188     {
00189         unsigned num_entries = GetTokensAtNextLine();
00190         if(num_entries < mNumItemsPerLine)
00191         {
00192             EXCEPTION("A line is incomplete in " << mFilePath
00193                           << " - each line should contain " << DIM << " entries");
00194         }
00195         for(unsigned i=0; i<DIM; i++)
00196         {
00197             rFibreVector(i) = mTokens[i];
00198         }
00199     }
00200 
00201 
00202     if(checkNormalised && fabs(norm_2(rFibreVector)-1)>1e-4)
00203     {
00204         EXCEPTION("Read vector " << rFibreVector << " from file "
00205                       << mFilePath << " which is not normalised (tolerance 1e-4)");
00206     }
00207 }
00208 
00209 
00210 template<unsigned DIM>
00211 unsigned FibreReader<DIM>::GetTokensAtNextLine()
00212 {
00213     assert(mTokens.size() == mNumItemsPerLine);
00214 
00215     std::string line;
00216     bool blank_line;
00217 
00218     do
00219     {
00220         getline(mDataFile, line);
00221 
00222         if (line.empty() && mDataFile.eof())
00223         {
00224             mDataFile.close();
00225             std::string error =   "End of file " + mFilePath + " reached. Either file contains less "
00226                                 + "definitions than defined in header, or one of the GetNext[..] methods "
00227                                 + "has been called too often";
00228             EXCEPTION(error);
00229         }
00230 
00231         // get rid of any comments
00232         line = line.substr(0, line.find('#'));
00233 
00234         blank_line = (line.find_first_not_of(" \t",0) == std::string::npos);
00235     }
00236     while(blank_line);
00237 
00238     // get rid of any trailing whitespace
00239     std::string::iterator iter = line.end();
00240     iter--;
00241     unsigned nchars2delete = 0;
00242     while(*iter == ' ' || *iter == '\t')
00243     {
00244         nchars2delete++;
00245         iter--;
00246     }
00247     line.erase(line.length()-nchars2delete);
00248 
00249     std::stringstream line_stream(line);
00250 
00251     unsigned index = 0;
00252     while (!line_stream.eof())
00253     {
00254         double item;
00255         line_stream >> item;
00256         if(index >= mNumItemsPerLine)
00257         {
00258             EXCEPTION("Too many entries in a line in " + mFilePath);
00259         }
00260         mTokens[index++] = item;
00261     }
00262 
00263     return index; // the number of entries put into mTokens
00264 }
00265 
00266 
00267 template<unsigned DIM>
00268 void FibreReader<DIM>::ReadNumLinesOfDataFromFile()
00269 {
00270     std::string raw_line;
00271     bool blank_line = false;
00272     do
00273     {
00274         getline(mDataFile, raw_line);
00275         //Strip comments following a hash
00276         raw_line = raw_line.substr(0, raw_line.find('#'));
00277         //Check for blank line
00278         blank_line = (raw_line.find_first_not_of(" \t",0) == std::string::npos);
00279     }
00280     while (blank_line);
00281 
00282     std::stringstream header_line(raw_line);
00283 
00284     header_line >> mNumLinesOfData;
00285 
00286     std::string extras;
00287     header_line >> extras;
00288 
00289     if (extras=="BIN")
00290     {
00291         mFileIsBinary = true;
00292     }
00293     else if (extras!="")
00294     {
00295         mDataFile.close();
00296         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");
00297     }
00298 }
00299 
00300 
00301 
00302 template class FibreReader<1>;
00303 template class FibreReader<2>;
00304 template class FibreReader<3>;
00305 
00306 
00307 
00308 
00309 
Generated on Thu Dec 22 13:00:06 2011 for Chaste by  doxygen 1.6.3