00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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),
00044 mNextIndex(0u)
00045 {
00046 if (fibreFileType == AXISYM)
00047 {
00048 mNumItemsPerLine = DIM;
00049 }
00050 else
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
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
00108
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
00142 mDataFile.seekg((fibreIndex-mNextIndex)*mNumItemsPerLine*sizeof(double), std::ios::cur);
00143
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
00171 rFibreMatrix = trans(rFibreMatrix);
00172
00173 if (checkOrthogonality)
00174 {
00175
00176 c_matrix<double,DIM,DIM> temp;
00177 temp = prod(trans(rFibreMatrix), rFibreMatrix);
00178
00179
00180 for (unsigned i=0; i<DIM; i++)
00181 {
00182 for (unsigned j=0; j<DIM; j++)
00183 {
00184 double val = (i==j ? 1.0 : 0.0);
00185
00186 if (fabs(temp(i,j)-val) > 1e-4)
00187 {
00188 EXCEPTION("Read fibre-sheet matrix, " << rFibreMatrix << " from file "
00189 << " which is not orthogonal (tolerance 1e-4)");
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
00214 mDataFile.seekg((fibreIndex-mNextIndex)*mNumItemsPerLine*sizeof(double), std::ios::cur);
00215
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
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
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;
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
00313 raw_line = raw_line.substr(0, raw_line.find('#'));
00314
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