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 {
00037     if (fibreFileType == AXISYM)
00038     {
00039         mNumItemsPerLine = DIM;
00040     }
00041     else //(fibreFileType == ORTHO)
00042     {
00043         mNumItemsPerLine = DIM*DIM;
00044     }
00045     mTokens.resize(mNumItemsPerLine);
00046 
00047     mFilePath = rFileFinder.GetAbsolutePath();
00048     mDataFile.open(mFilePath.c_str());
00049     if (!mDataFile.is_open())
00050     {
00051         EXCEPTION("Failed to open fibre file " + rFileFinder.GetAbsolutePath());
00052     }
00053 
00054     // Note: this method will close the file on error
00055     ReadNumLinesOfDataFromFile();
00056 }
00057 
00058 template<unsigned DIM>
00059 FibreReader<DIM>::~FibreReader()
00060 {
00061     mDataFile.close();
00062 }
00063 
00064 template<unsigned DIM>
00065 void FibreReader<DIM>::GetAllAxi(std::vector< c_vector<double, DIM> >& direction)
00066 {
00067     assert(direction.empty());                                       
00068     if (mNumItemsPerLine != DIM)
00069     {
00070         EXCEPTION("Use GetAllOrtho when reading orthotropic fibres");
00071     }   
00072     for (unsigned i=0; i<mNumLinesOfData; i++)
00073     {
00074         c_vector<double, DIM> temp_vector;
00075         GetNextFibreVector(temp_vector, false);
00076         direction.push_back(temp_vector);
00077     }
00078 }    
00079 
00080 template<unsigned DIM>
00081 void FibreReader<DIM>::GetAllOrtho(std::vector< c_vector<double, DIM> >& first_direction, 
00082                                    std::vector< c_vector<double, DIM> >& second_direction,
00083                                    std::vector< c_vector<double, DIM> >& third_direction)
00084 {
00085     assert(first_direction.empty());                                       
00086     assert(second_direction.empty());                                       
00087     assert(third_direction.empty());                                       
00088     if (mNumItemsPerLine != DIM*DIM)
00089     {
00090         EXCEPTION("Use GetAllAxi when reading axisymmetric fibres");
00091     }   
00092     for (unsigned i=0; i<mNumLinesOfData; i++)
00093     {
00094         c_matrix<double, DIM, DIM> temp_matrix;
00095         GetNextFibreSheetAndNormalMatrix(temp_matrix, false);
00096         matrix_row<c_matrix<double, DIM, DIM> > row0(temp_matrix, 0);
00097         first_direction.push_back(row0);
00098         if (DIM>=2)
00099         {
00100             matrix_row<c_matrix<double, DIM, DIM> > row1(temp_matrix, 1);
00101             second_direction.push_back(row1);
00102         }
00103         if (DIM==3)
00104         {
00105             matrix_row<c_matrix<double, DIM, DIM> > row2(temp_matrix, 2);
00106             third_direction.push_back(row2);
00107         }
00108     }
00109  
00110 }                        
00111 template<unsigned DIM>
00112 void FibreReader<DIM>::GetNextFibreSheetAndNormalMatrix(c_matrix<double,DIM,DIM>& rFibreMatrix,
00113                                                         bool checkOrthogonality)
00114 {
00115     if (mNumItemsPerLine != DIM*DIM)
00116     {
00117         EXCEPTION("Use GetNextFibreVector when reading axisymmetric fibres");
00118     }
00119 
00120     unsigned num_entries = GetTokensAtNextLine();
00121     if(num_entries < mNumItemsPerLine)
00122     {
00123         std::stringstream string_stream;
00124         string_stream << "A line is incomplete in " << mFilePath
00125                       << " - each line should contain " << DIM*DIM << " entries";
00126         EXCEPTION(string_stream.str());
00127     }
00128 
00129     for(unsigned i=0; i<DIM; i++)
00130     {
00131         for(unsigned j=0; j<DIM; j++)
00132         {
00133             rFibreMatrix(j,i) = mTokens[DIM*i + j];
00134         }
00135     }
00136 
00137     if(checkOrthogonality)
00138     {
00139         c_matrix<double,DIM,DIM>  temp = prod(trans(rFibreMatrix),rFibreMatrix);
00140         // check temp is equal to the identity
00141         for(unsigned i=0; i<DIM; i++)
00142         {   
00143             for(unsigned j=0; j<DIM; j++)
00144             {
00145                 double val = (i==j ? 1.0 : 0.0);
00146 
00147                 if(fabs(temp(i,j)-val)>1e-4)
00148                 {
00149                     std::stringstream string_stream;
00150                     string_stream << "Read fibre-sheet matrix, " << rFibreMatrix << " from file " 
00151                                   << " which is not orthogonal (tolerance 1e-4)"; 
00152                     EXCEPTION(string_stream.str());
00153                 }
00154             }
00155         }
00156     }
00157 
00158 }
00159 
00160 template<unsigned DIM>
00161 void FibreReader<DIM>::GetNextFibreVector(c_vector<double,DIM>& rFibreVector, 
00162                                           bool checkNormalised)
00163 {
00164     if (mNumItemsPerLine != DIM)
00165     {
00166         EXCEPTION("Use GetNextFibreSheetAndNormalMatrix when reading orthotropic fibres");
00167     }
00168 
00169     unsigned num_entries = GetTokensAtNextLine();
00170     if(num_entries < mNumItemsPerLine)
00171     {
00172         std::stringstream string_stream;
00173         string_stream << "A line is incomplete in " << mFilePath
00174                       << " - each line should contain " << DIM << " entries";
00175         EXCEPTION(string_stream.str());
00176     }
00177 
00178     for(unsigned i=0; i<DIM; i++)
00179     {
00180         rFibreVector(i) = mTokens[i];
00181     }
00182     
00183     if(checkNormalised && fabs(norm_2(rFibreVector)-1)>1e-4)
00184     {
00185         std::stringstream string_stream;
00186         string_stream << "Read vector " << rFibreVector << " from file " 
00187                       << mFilePath << " which is not normalised (tolerance 1e-4)";
00188         EXCEPTION(string_stream.str());
00189     }
00190 }
00191 
00192 
00193 template<unsigned DIM>
00194 unsigned FibreReader<DIM>::GetTokensAtNextLine()
00195 {
00196     assert(mTokens.size() == mNumItemsPerLine);
00197 
00198     std::string line;
00199     bool blank_line;
00200 
00201     do
00202     {
00203         getline(mDataFile, line);
00204 
00205         if (line.empty() && mDataFile.eof())
00206         {
00207             mDataFile.close();
00208             std::string error =   "End of file " + mFilePath + " reached. Either file contains less "
00209                                 + "definitions than defined in header, or one of the GetNext[..] methods "
00210                                 + "has been called too often";
00211             EXCEPTION(error);
00212         }
00213 
00214         // get rid of any comments
00215         line = line.substr(0, line.find('#'));
00216 
00217         blank_line = (line.find_first_not_of(" \t",0) == std::string::npos);
00218     }
00219     while(blank_line);
00220 
00221     // get rid of any trailing whitespace
00222     std::string::iterator iter = line.end();
00223     iter--;
00224     unsigned nchars2delete = 0;
00225     while(*iter == ' ')
00226     {
00227         nchars2delete++;
00228         iter--;
00229     }
00230     line.erase(line.length()-nchars2delete);
00231 
00232     std::stringstream line_stream(line);
00233 
00234     unsigned index = 0;
00235     while (!line_stream.eof())
00236     {
00237         double item;
00238         line_stream >> item;
00239         if(index >= mNumItemsPerLine)
00240         {
00241             EXCEPTION("Too many entries in a line in " + mFilePath);
00242         }
00243         mTokens[index++] = item;
00244     }
00245 
00246     return index; // the number of entries put into mTokens
00247 }
00248 
00249 
00250 template<unsigned DIM>
00251 void FibreReader<DIM>::ReadNumLinesOfDataFromFile()
00252 {
00253     if (GetTokensAtNextLine() != 1)
00254     {
00255         mDataFile.close();
00256         EXCEPTION("First (non comment) line of the fibre orientation file should contain the number of lines of data in the file (and nothing else)");
00257     }
00258 
00259     mNumLinesOfData = (unsigned) mTokens[0];
00260 }
00261 
00262 
00263 
00264 template class FibreReader<1>;
00265 template class FibreReader<2>;
00266 template class FibreReader<3>;
00267 
00268 
00269 
00270 
00271 

Generated on Mon Apr 18 11:35:28 2011 for Chaste by  doxygen 1.5.5