Chaste Release::3.1
|
00001 /* 00002 00003 Copyright (c) 2005-2012, University of Oxford. 00004 All rights reserved. 00005 00006 University of Oxford means the Chancellor, Masters and Scholars of the 00007 University of Oxford, having an administrative office at Wellington 00008 Square, Oxford OX1 2JD, UK. 00009 00010 This file is part of Chaste. 00011 00012 Redistribution and use in source and binary forms, with or without 00013 modification, are permitted provided that the following conditions are met: 00014 * Redistributions of source code must retain the above copyright notice, 00015 this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright notice, 00017 this list of conditions and the following disclaimer in the documentation 00018 and/or other materials provided with the distribution. 00019 * Neither the name of the University of Oxford nor the names of its 00020 contributors may be used to endorse or promote products derived from this 00021 software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 */ 00035 00036 #include "FibreReader.hpp" 00037 00038 #include <sstream> 00039 #include "Exception.hpp" 00040 00041 template<unsigned DIM> 00042 FibreReader<DIM>::FibreReader(const FileFinder& rFileFinder, FibreFileType fibreFileType) 00043 : mFileIsBinary(false), // overwritten by ReadNumLinesOfDataFromFile() if applicable. 00044 mNextIndex(0u) 00045 { 00046 if (fibreFileType == AXISYM) 00047 { 00048 mNumItemsPerLine = DIM; 00049 } 00050 else //(fibreFileType == ORTHO) 00051 { 00052 mNumItemsPerLine = DIM*DIM; 00053 } 00054 mTokens.resize(mNumItemsPerLine); 00055 00056 mFilePath = rFileFinder.GetAbsolutePath(); 00057 mDataFile.open(mFilePath.c_str()); 00058 if (!mDataFile.is_open()) 00059 { 00060 EXCEPTION("Failed to open fibre file " + rFileFinder.GetAbsolutePath()); 00061 } 00062 00063 // Note: this method will close the file on error 00064 ReadNumLinesOfDataFromFile(); 00065 } 00066 00067 template<unsigned DIM> 00068 FibreReader<DIM>::~FibreReader() 00069 { 00070 mDataFile.close(); 00071 } 00072 00073 template<unsigned DIM> 00074 void FibreReader<DIM>::GetAllAxi(std::vector< c_vector<double, DIM> >& direction) 00075 { 00076 assert(direction.empty()); 00077 if (mNumItemsPerLine != DIM) 00078 { 00079 EXCEPTION("Use GetAllOrtho when reading orthotropic fibres"); 00080 } 00081 direction.reserve(mNumLinesOfData); 00082 for (unsigned i=0; i<mNumLinesOfData; i++) 00083 { 00084 c_vector<double, DIM> temp_vector; 00085 GetFibreVector(i, temp_vector, false); 00086 direction.push_back(temp_vector); 00087 } 00088 } 00089 00090 template<unsigned DIM> 00091 void FibreReader<DIM>::GetAllOrtho(std::vector< c_vector<double, DIM> >& first_direction, 00092 std::vector< c_vector<double, DIM> >& second_direction, 00093 std::vector< c_vector<double, DIM> >& third_direction) 00094 { 00095 assert(first_direction.empty()); 00096 assert(second_direction.empty()); 00097 assert(third_direction.empty()); 00098 if (mNumItemsPerLine != DIM*DIM) 00099 { 00100 EXCEPTION("Use GetAllAxi when reading axisymmetric fibres"); 00101 } 00102 for (unsigned i=0; i<mNumLinesOfData; i++) 00103 { 00104 c_matrix<double, DIM, DIM> temp_matrix; 00105 GetFibreSheetAndNormalMatrix(i, temp_matrix, true); 00106 00107 //Note that although the matrix appears row-wise in the ascii .ortho file, 00108 //for convenience it is stored column-wise. 00109 matrix_column<c_matrix<double, DIM, DIM> > col0(temp_matrix, 0); 00110 first_direction.push_back(col0); 00111 if (DIM>=2) 00112 { 00113 matrix_column<c_matrix<double, DIM, DIM> > col1(temp_matrix, 1); 00114 second_direction.push_back(col1); 00115 } 00116 if (DIM==3) 00117 { 00118 matrix_column<c_matrix<double, DIM, DIM> > col2(temp_matrix, 2); 00119 third_direction.push_back(col2); 00120 } 00121 } 00122 00123 } 00124 template<unsigned DIM> 00125 void FibreReader<DIM>::GetFibreSheetAndNormalMatrix(unsigned fibreIndex, 00126 c_matrix<double,DIM,DIM>& rFibreMatrix, 00127 bool checkOrthogonality) 00128 { 00129 if (mNumItemsPerLine != DIM*DIM) 00130 { 00131 EXCEPTION("Use GetFibreVector when reading axisymmetric fibres"); 00132 } 00133 if (fibreIndex < mNextIndex) 00134 { 00135 EXCEPTION("Fibre reads must be monotonically increasing; " << fibreIndex 00136 << " is before expected next index " << mNextIndex); 00137 } 00138 if (mFileIsBinary) 00139 { 00140 00141 // Skip to the desired index 00142 mDataFile.seekg((fibreIndex-mNextIndex)*mNumItemsPerLine*sizeof(double), std::ios::cur); 00143 // Take mNumItemsPerLine from the ifstream 00144 mDataFile.read((char*)&(rFibreMatrix(0,0)), mNumItemsPerLine*sizeof(double)); 00145 mNextIndex = fibreIndex+1; 00146 } 00147 else 00148 { 00149 unsigned num_entries = 0u; 00150 while (fibreIndex >= mNextIndex) 00151 { 00152 num_entries = GetTokensAtNextLine(); 00153 mNextIndex++; 00154 } 00155 if(num_entries < mNumItemsPerLine) 00156 { 00157 EXCEPTION("A line is incomplete in " << mFilePath 00158 << " - each line should contain " << DIM*DIM << " entries"); 00159 } 00160 for(unsigned i=0; i<DIM; i++) 00161 { 00162 for(unsigned j=0; j<DIM; j++) 00163 { 00164 rFibreMatrix(i,j) = mTokens[DIM*i + j]; 00165 } 00166 } 00167 00168 } 00169 00170 //The binary file and ascii file are row-major. However, we store column major 00171 //matrices 00172 rFibreMatrix = trans(rFibreMatrix); 00173 00174 00175 if(checkOrthogonality) 00176 { 00177 c_matrix<double,DIM,DIM> temp = prod(trans(rFibreMatrix),rFibreMatrix); 00178 // check temp is equal to the identity 00179 for(unsigned i=0; i<DIM; i++) 00180 { 00181 for(unsigned j=0; j<DIM; j++) 00182 { 00183 double val = (i==j ? 1.0 : 0.0); 00184 00185 if(fabs(temp(i,j)-val)>1e-4) 00186 { 00187 EXCEPTION("Read fibre-sheet matrix, " << rFibreMatrix << " from file " 00188 << " which is not orthogonal (tolerance 1e-4)"); 00189 } 00190 } 00191 } 00192 } 00193 00194 } 00195 00196 template<unsigned DIM> 00197 void FibreReader<DIM>::GetFibreVector(unsigned fibreIndex, 00198 c_vector<double,DIM>& rFibreVector, 00199 bool checkNormalised) 00200 { 00201 if (mNumItemsPerLine != DIM) 00202 { 00203 EXCEPTION("Use GetFibreSheetAndNormalMatrix when reading orthotropic fibres"); 00204 } 00205 if (fibreIndex < mNextIndex) 00206 { 00207 EXCEPTION("Fibre reads must be monotonically increasing; " << fibreIndex 00208 << " is before expected next index " << mNextIndex); 00209 } 00210 00211 if (mFileIsBinary) 00212 { 00213 // Skip to the desired index 00214 mDataFile.seekg((fibreIndex-mNextIndex)*mNumItemsPerLine*sizeof(double), std::ios::cur); 00215 // Take mNumItemsPerLine from the ifstream 00216 mDataFile.read((char*)&rFibreVector[0], mNumItemsPerLine*sizeof(double)); 00217 mNextIndex = fibreIndex+1; 00218 } 00219 else 00220 { 00221 unsigned num_entries = 0u; 00222 while (fibreIndex >= mNextIndex) 00223 { 00224 num_entries = GetTokensAtNextLine(); 00225 mNextIndex++; 00226 } 00227 if (num_entries < mNumItemsPerLine) 00228 { 00229 EXCEPTION("A line is incomplete in " << mFilePath 00230 << " - each line should contain " << DIM << " entries"); 00231 } 00232 for (unsigned i=0; i<DIM; i++) 00233 { 00234 rFibreVector(i) = mTokens[i]; 00235 } 00236 } 00237 00238 00239 if (checkNormalised && fabs(norm_2(rFibreVector)-1)>1e-4) 00240 { 00241 EXCEPTION("Read vector " << rFibreVector << " from file " 00242 << mFilePath << " which is not normalised (tolerance 1e-4)"); 00243 } 00244 } 00245 00246 00247 template<unsigned DIM> 00248 unsigned FibreReader<DIM>::GetTokensAtNextLine() 00249 { 00250 assert(mTokens.size() == mNumItemsPerLine); 00251 00252 std::string line; 00253 bool blank_line; 00254 00255 do 00256 { 00257 getline(mDataFile, line); 00258 00259 if (line.empty() && mDataFile.eof()) 00260 { 00261 mDataFile.close(); 00262 std::string error = "End of file " + mFilePath + " reached. Either file contains fewer " 00263 + "definitions than defined in header, or one of the GetNext[..] methods " 00264 + "has been called too often"; 00265 EXCEPTION(error); 00266 } 00267 00268 // get rid of any comments 00269 line = line.substr(0, line.find('#')); 00270 00271 blank_line = (line.find_first_not_of(" \t",0) == std::string::npos); 00272 } 00273 while(blank_line); 00274 00275 // get rid of any trailing whitespace 00276 std::string::iterator iter = line.end(); 00277 iter--; 00278 unsigned nchars2delete = 0; 00279 while(*iter == ' ' || *iter == '\t') 00280 { 00281 nchars2delete++; 00282 iter--; 00283 } 00284 line.erase(line.length()-nchars2delete); 00285 00286 std::stringstream line_stream(line); 00287 00288 unsigned index = 0; 00289 while (!line_stream.eof()) 00290 { 00291 double item; 00292 line_stream >> item; 00293 if(index >= mNumItemsPerLine) 00294 { 00295 EXCEPTION("Too many entries in a line in " + mFilePath); 00296 } 00297 mTokens[index++] = item; 00298 } 00299 00300 return index; // the number of entries put into mTokens 00301 } 00302 00303 00304 template<unsigned DIM> 00305 void FibreReader<DIM>::ReadNumLinesOfDataFromFile() 00306 { 00307 std::string raw_line; 00308 bool blank_line = false; 00309 do 00310 { 00311 getline(mDataFile, raw_line); 00312 //Strip comments following a hash 00313 raw_line = raw_line.substr(0, raw_line.find('#')); 00314 //Check for blank line 00315 blank_line = (raw_line.find_first_not_of(" \t",0) == std::string::npos); 00316 } 00317 while (blank_line); 00318 00319 std::stringstream header_line(raw_line); 00320 00321 header_line >> mNumLinesOfData; 00322 00323 std::string extras; 00324 header_line >> extras; 00325 00326 if (extras=="BIN") 00327 { 00328 mFileIsBinary = true; 00329 } 00330 else if (extras!="") 00331 { 00332 mDataFile.close(); 00333 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"); 00334 } 00335 } 00336 00337 00338 00339 template class FibreReader<1>; 00340 template class FibreReader<2>; 00341 template class FibreReader<3>; 00342 00343 00344 00345 00346