FibreReader.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
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>::GetNextFibreSheetAndNormalMatrix(c_matrix<double,DIM,DIM>& rFibreMatrix,
00066                                                         bool checkOrthogonality)
00067 {
00068     if (mNumItemsPerLine != DIM*DIM)
00069     {
00070         EXCEPTION("Use GetNextFibreVector when reading axisymmetric fibres.");
00071     }
00072 
00073     unsigned num_entries = GetTokensAtNextLine();
00074     if(num_entries < mNumItemsPerLine)
00075     {
00076         std::stringstream string_stream;
00077         string_stream << "A line is incomplete in " << mFilePath
00078                       << " - each line should contain " << DIM*DIM << " entries";
00079         EXCEPTION(string_stream.str());
00080     }
00081 
00082     for(unsigned i=0; i<DIM; i++)
00083     {
00084         for(unsigned j=0; j<DIM; j++)
00085         {
00086             rFibreMatrix(j,i) = mTokens[DIM*i + j];
00087         }
00088     }
00089 
00090     if(checkOrthogonality)
00091     {
00092         c_matrix<double,DIM,DIM>  temp = prod(trans(rFibreMatrix),rFibreMatrix);
00093         // check temp is equal to the identity
00094         for(unsigned i=0; i<DIM; i++)
00095         {   
00096             for(unsigned j=0; j<DIM; j++)
00097             {
00098                 double val = (i==j ? 1.0 : 0.0);
00099 
00100                 if(fabs(temp(i,j)-val)>1e-4)
00101                 {
00102                     std::stringstream string_stream;
00103                     string_stream << "Read fibre-sheet matrix, " << rFibreMatrix << " from file " 
00104                                   << " which is not orthogonal (tolerance 1e-4)"; 
00105                     EXCEPTION(string_stream.str());
00106                 }
00107             }
00108         }
00109     }
00110 
00111 }
00112 
00113 template<unsigned DIM>
00114 void FibreReader<DIM>::GetNextFibreVector(c_vector<double,DIM>& rFibreVector, 
00115                                           bool checkNormalised)
00116 {
00117     if (mNumItemsPerLine != DIM)
00118     {
00119         EXCEPTION("Use GetNextFibreSheetAndNormalMatrix when reading orthotropic fibres.");
00120     }
00121 
00122     unsigned num_entries = GetTokensAtNextLine();
00123     if(num_entries < mNumItemsPerLine)
00124     {
00125         std::stringstream string_stream;
00126         string_stream << "A line is incomplete in " << mFilePath
00127                       << " - each line should contain " << DIM << " entries";
00128         EXCEPTION(string_stream.str());
00129     }
00130 
00131     for(unsigned i=0; i<DIM; i++)
00132     {
00133         rFibreVector(i) = mTokens[i];
00134     }
00135     
00136     if(checkNormalised && fabs(norm_2(rFibreVector)-1)>1e-4)
00137     {
00138         std::stringstream string_stream;
00139         string_stream << "Read vector " << rFibreVector << " from file " 
00140                       << mFilePath << " which is not normalised (tolerance 1e-4)";
00141         EXCEPTION(string_stream.str());
00142     }
00143 }
00144 
00145 
00146 template<unsigned DIM>
00147 unsigned FibreReader<DIM>::GetTokensAtNextLine()
00148 {
00149     assert(mTokens.size() == mNumItemsPerLine);
00150 
00151     std::string line;
00152     bool blank_line;
00153 
00154     do
00155     {
00156         getline(mDataFile, line);
00157 
00158         if (line.empty() && mDataFile.eof())
00159         {
00160             mDataFile.close();
00161             std::string error =   "End of file " + mFilePath + " reached. Either file contains less "
00162                                 + "definitions than defined in header, or one of the GetNext[..] methods "
00163                                 + "has been called too often";
00164             EXCEPTION(error);
00165         }
00166 
00167         // get rid of any comments
00168         line = line.substr(0, line.find('#'));
00169 
00170         blank_line = (line.find_first_not_of(" \t",0) == std::string::npos);
00171     }
00172     while(blank_line);
00173 
00174     // get rid of any trailing whitespace
00175     std::string::iterator iter = line.end();
00176     iter--;
00177     unsigned nchars2delete = 0;
00178     while(*iter == ' ')
00179     {
00180         nchars2delete++;
00181         iter--;
00182     }
00183     line.erase(line.length()-nchars2delete);
00184 
00185     std::stringstream line_stream(line);
00186 
00187     unsigned index = 0;
00188     while (!line_stream.eof())
00189     {
00190         double item;
00191         line_stream >> item;
00192         if(index >= mNumItemsPerLine)
00193         {
00194             EXCEPTION("Too many entries in a line in " + mFilePath);
00195         }
00196         mTokens[index++] = item;
00197     }
00198 
00199     return index; // the number of entries put into mTokens
00200 }
00201 
00202 
00203 template<unsigned DIM>
00204 void FibreReader<DIM>::ReadNumLinesOfDataFromFile()
00205 {
00206     if (GetTokensAtNextLine() != 1)
00207     {
00208         mDataFile.close();
00209         EXCEPTION("First (non comment) line of the fibre orientation file should contain the number of lines of data in the file (and nothing else)");
00210     }
00211 
00212     mNumLinesOfData = (unsigned) mTokens[0];
00213 }
00214 
00215 
00216 
00217 template class FibreReader<1>;
00218 template class FibreReader<2>;
00219 template class FibreReader<3>;
00220 
00221 
00222 
00223 
00224 

Generated on Mon Nov 1 12:35:16 2010 for Chaste by  doxygen 1.5.5