TrianglesMeshReader.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
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 "TrianglesMeshReader.hpp"
00030 #include "Exception.hpp"
00031 #include <cassert>
00032 #include <sstream>
00033 
00034 const static char* NODES_FILE_EXTENSION = ".node";
00035 const static char* ELEMENTS_FILE_EXTENSION = ".ele";
00036 const static char* FACES_FILE_EXTENSION = ".face";
00037 const static char* EDGES_FILE_EXTENSION = ".edge";
00038 
00040 // Implementation
00042 
00043 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00044 TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::TrianglesMeshReader(std::string pathBaseName, unsigned orderOfElements, unsigned orderOfBoundaryElements)
00045     : mFilesBaseName(pathBaseName),
00046       mNumNodes(0),
00047       mNumElements(0),
00048       mNumFaces(0),
00049       mNodesRead(0),
00050       mElementsRead(0),
00051       mFacesRead(0),
00052       mBoundaryFacesRead(0),
00053       mNumElementAttributes(0),
00054       mNumFaceAttributes(0),
00055       mOrderOfElements(orderOfElements),
00056       mOrderOfBoundaryElements(orderOfBoundaryElements)
00057 {
00058     // Only linear and quadratic elements
00059     assert(orderOfElements==1 || orderOfElements==2);
00060     if (mOrderOfElements==1)
00061     {
00062         mNodesPerElement = ELEMENT_DIM+1;
00063     }
00064     else
00065     {
00066         #define COVERAGE_IGNORE
00067         assert(SPACE_DIM==ELEMENT_DIM);
00068         #undef COVERAGE_IGNORE
00069         mNodesPerElement = (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2;
00070     }
00071 
00072     if (mOrderOfBoundaryElements==1)
00073     {
00074         mNodesPerBoundaryElement = ELEMENT_DIM;
00075     }
00076     else
00077     {
00078         #define COVERAGE_IGNORE
00079         assert(SPACE_DIM==ELEMENT_DIM);
00080         #undef COVERAGE_IGNORE
00081         mNodesPerBoundaryElement = ELEMENT_DIM*(ELEMENT_DIM+1)/2;
00082     }
00083 
00084     mIndexFromZero = false; // Initially assume that nodes are not numbered from zero
00085 
00086     OpenFiles();
00087     ReadHeaders();
00088 }
00089 
00090 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00091 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumElements() const
00092 {
00093     return mNumElements;
00094 }
00095 
00096 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00097 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumNodes() const
00098 {
00099     return mNumNodes;
00100 }
00101 
00102 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00103 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumFaces() const
00104 {
00105     return mNumFaces;
00106 }
00107 
00108 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00109 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumEdges() const
00110 {
00111     return mNumFaces;
00112 }
00113 
00114 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00115 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumElementAttributes() const
00116 {
00117     return mNumElementAttributes;
00118 }
00119 
00120 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00121 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumFaceAttributes() const
00122 {
00123     return mNumFaceAttributes;
00124 }
00125 
00126 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00127 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::Reset()
00128 {
00129     CloseFiles();
00130     OpenFiles();
00131     ReadHeaders();
00132 
00133     mNodesRead = 0;
00134     mElementsRead = 0;
00135     mFacesRead = 0;
00136     mBoundaryFacesRead = 0;
00137 }
00138 
00139 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00140 std::vector<double> TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextNode()
00141 {
00142     std::vector<double> ret_coords;
00143 
00144     std::string buffer;
00145     GetNextLineFromStream(mNodesFile, buffer);
00146 
00147     std::stringstream buffer_stream(buffer);
00148 
00149     unsigned index;
00150     buffer_stream >> index;
00151 
00152     unsigned offset = mIndexFromZero ? 0 : 1;
00153     if (index != mNodesRead+offset)
00154     {
00155         std::stringstream error;
00156         error << "Data for node " << mNodesRead << " missing";
00157         EXCEPTION(error.str());
00158     }
00159 
00160     double coord;
00161 
00162     for (unsigned i=0; i<SPACE_DIM; i++)
00163     {
00164         buffer_stream >> coord;
00165         ret_coords.push_back(coord);
00166     }
00167 
00168     mNodesRead++;
00169 
00170     return ret_coords;
00171 }
00172 
00173 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00174 ElementData TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextElementData()
00175 {
00176     ElementData element_data;
00177 
00178     std::string buffer;
00179     GetNextLineFromStream(mElementsFile, buffer);
00180 
00181     std::stringstream buffer_stream(buffer);
00182 
00183     unsigned element_index;
00184     buffer_stream >> element_index;
00185 
00186     unsigned offset = mIndexFromZero ? 0 : 1;
00187     if (element_index != mElementsRead+offset)
00188     {
00189         std::stringstream error;
00190         error << "Data for element " << mElementsRead << " missing";
00191         EXCEPTION(error.str());
00192     }
00193 
00194     unsigned node_index;
00195     for (unsigned i=0; i<mNodesPerElement; i++)
00196     {
00197         buffer_stream >> node_index;
00198         element_data.NodeIndices.push_back(node_index - offset);
00199     }
00200 
00201     if (mNumElementAttributes > 0)
00202     {
00203         assert(mNumElementAttributes==1);
00204 
00205         unsigned attribute_value;
00206         buffer_stream >> attribute_value;
00207         element_data.AttributeValue = attribute_value;
00208     }
00209     else
00210     {
00211         element_data.AttributeValue = 0;
00212     }
00213 
00214     mElementsRead++;
00215     return element_data;
00216 }
00217 
00218 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00219 ElementData TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextFaceData()
00220 {
00221     ElementData face_data;
00222     std::vector<unsigned> ret_indices;
00223 
00224     // In the first three cases there's no file, all the nodes are set as faces
00225     if (SPACE_DIM == 1)
00226     {
00227         ret_indices.push_back(mBoundaryFacesRead);
00228     }
00229     else if (SPACE_DIM == 2 && ELEMENT_DIM == 1)
00230     {
00231         ret_indices.push_back(mBoundaryFacesRead);
00232     }
00233     else if (SPACE_DIM == 3 && ELEMENT_DIM == 1)
00234     {
00235         ret_indices.push_back(mBoundaryFacesRead);
00236     }    
00237     else
00238     {
00239         unsigned offset = mIndexFromZero ? 0 : 1;
00240 
00241         assert(ELEMENT_DIM != 0); //Covered in earlier exception, but needed in loop guard here.
00242         do
00243         {
00244             ret_indices.clear();
00245 
00246             std::string buffer;
00247             GetNextLineFromStream(mFacesFile, buffer);
00248 
00249             std::stringstream buffer_stream(buffer);
00250 
00251             unsigned face_index;
00252             buffer_stream >> face_index;
00253 
00254             if (face_index != mFacesRead+offset)
00255             {
00256                 std::stringstream error;
00257                 error << "Data for face " << mFacesRead << " missing";
00258                 EXCEPTION(error.str());
00259             }
00260 
00261             unsigned node_index;
00262             for (unsigned i=0; i<mNodesPerBoundaryElement; i++)
00263             {
00264                 buffer_stream >> node_index;
00265                 ret_indices.push_back(node_index-offset);
00266             }
00267 
00268             if (mNumFaceAttributes>0)
00269             {
00270                 assert(mNumFaceAttributes==1);
00271 
00272                 unsigned attribute_value;
00273                 buffer_stream >> attribute_value;
00274                 face_data.AttributeValue = attribute_value;
00275             }
00276             else
00277             {
00278                 face_data.AttributeValue = 0u;
00279             }
00280 
00281             mFacesRead++;
00282         }
00283         while ((mNumFaceAttributes==1) && (face_data.AttributeValue==0));
00284     }
00285 
00286     mBoundaryFacesRead++;
00287     face_data.NodeIndices = ret_indices;
00288     return face_data;
00289 }
00290 
00291 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00292 ElementData TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextEdgeData()
00293 {
00294     return GetNextFaceData();
00295 }
00296 
00297 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00298 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenFiles()
00299 {
00300     OpenNodeFile();
00301     OpenElementsFile();
00302     OpenFacesFile();
00303 }
00304 
00305 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00306 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenNodeFile()
00307 {
00308     // Nodes definition
00309     std::string file_name = mFilesBaseName + NODES_FILE_EXTENSION;
00310     mNodesFile.open(file_name.c_str());
00311     if (!mNodesFile.is_open())
00312     {
00313         EXCEPTION("Could not open data file: " + file_name);
00314     }
00315 }
00316 
00317 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00318 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenElementsFile()
00319 {
00320     // Elements definition
00321     std::string file_name;
00322     if (ELEMENT_DIM == SPACE_DIM)
00323     {
00324         file_name = mFilesBaseName + ELEMENTS_FILE_EXTENSION;
00325     }
00326     else
00327     {
00328         if (SPACE_DIM == 2 && ELEMENT_DIM == 1)
00329         {
00330             file_name = mFilesBaseName + EDGES_FILE_EXTENSION;
00331         }
00332         else if (SPACE_DIM == 3 && ELEMENT_DIM == 1)
00333         {
00334             file_name = mFilesBaseName + EDGES_FILE_EXTENSION;   
00335         }
00336         else if (SPACE_DIM == 3 && ELEMENT_DIM == 2)
00337         {
00338             file_name = mFilesBaseName + FACES_FILE_EXTENSION;
00339         }
00340         else
00341         {
00342             EXCEPTION("Can't have a zero-dimensional mesh in a one-dimensional space");
00343         }
00344     }
00345 
00346     mElementsFile.open(file_name.c_str());
00347     if (!mElementsFile.is_open())
00348     {
00349         EXCEPTION("Could not open data file: " + file_name);
00350     }
00351 }
00352 
00353 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00354 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenFacesFile()
00355 {  
00356     // Faces/edges definition
00357     std::string file_name;
00358     if (SPACE_DIM == 3)
00359     {
00360         if (SPACE_DIM == ELEMENT_DIM)
00361         {
00362             file_name = mFilesBaseName + FACES_FILE_EXTENSION;
00363         }
00364         else
00365         {
00366             file_name = mFilesBaseName + EDGES_FILE_EXTENSION;
00367         }
00368     }
00369     else if (SPACE_DIM == 2)
00370     {
00371         file_name = mFilesBaseName + EDGES_FILE_EXTENSION;
00372     }
00373     else if (SPACE_DIM == 1)
00374     {
00375         // There is no file, data will be generated instead of read
00376         return;
00377     }
00378 
00379     mFacesFile.open(file_name.c_str());
00380     if (!mFacesFile.is_open())
00381     {
00382         EXCEPTION("Could not open data file: " + file_name);
00383     }
00384 }
00385 
00386 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00387 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::ReadHeaders()
00388 {
00389     std::string buffer;
00390 
00391     GetNextLineFromStream(mNodesFile, buffer);
00392     std::stringstream buffer_stream(buffer);
00393     unsigned dimension;
00394     buffer_stream >> mNumNodes >> dimension >> mNumNodeAttributes >> mMaxNodeBdyMarker;
00395     if (SPACE_DIM != dimension)
00396     {
00397         EXCEPTION("SPACE_DIM  != dimension read from file ");
00398     }
00399 
00400     // Get the next line to see if it is indexed from zero or not
00401     GetNextLineFromStream(mNodesFile, buffer);
00402     std::stringstream buffer_stream_ii(buffer);
00403 
00404     unsigned first_index;
00405     buffer_stream_ii >> first_index;
00406     assert(first_index == 0 || first_index == 1);
00407     mIndexFromZero = (first_index == 0);
00408 
00409     // Close, reopen, skip header
00410     mNodesFile.close();
00411     OpenNodeFile();
00412     GetNextLineFromStream(mNodesFile, buffer);
00413 
00415     GetNextLineFromStream(mElementsFile, buffer);
00416     std::stringstream buffer_stream2(buffer);
00417 
00418     if (ELEMENT_DIM == SPACE_DIM)
00419     {
00420         buffer_stream2 >> mNumElements >> mNumElementNodes >> mNumElementAttributes;
00421 
00422         if ( mNumElementNodes != mNodesPerElement )
00423         {
00424             std::stringstream error;
00425             error << "Number of nodes per elem, " << mNumElementNodes << ", does not match "
00426                   << "expected number, " << mNodesPerElement << " (which is calculated given "
00427                   << "the order of elements chosen, " << mOrderOfElements << " (1=linear, 2=quadratics)";
00428             EXCEPTION(error.str());
00429         }
00430     }
00431     else
00432     {
00433         buffer_stream2 >> mNumElements >> mNumFaceAttributes;
00434 
00435         mNodesPerElement = ELEMENT_DIM+1;
00436     }
00437 
00438     if (SPACE_DIM == 1)
00439     {
00440         mNumFaces = mNumNodes;
00441     }
00442     else if (SPACE_DIM == 2 && ELEMENT_DIM == 1)
00443     {
00444         mNumFaces = mNumNodes;
00445     }
00446     else if (SPACE_DIM == 3 && ELEMENT_DIM == 1)
00447     {
00448         mNumFaces = mNumNodes;   
00449     }
00450     else
00451     {
00452         GetNextLineFromStream(mFacesFile, buffer);
00453         std::stringstream buffer_stream3(buffer);
00454 
00455         buffer_stream3 >> mNumFaces >> mNumFaceAttributes;
00456         assert(mNumFaceAttributes==0 || mNumFaceAttributes==1);
00457 
00458         // if mNumFaceAttributes=1 then loop over and set mNumFaces to be
00459         // the number of faces which are marked as boundary faces
00460         if ((mNumFaceAttributes==1) && (SPACE_DIM!=1))
00461         {
00462             unsigned num_boundary_faces = 0;
00463             bool end_of_file=false;
00464             while (!end_of_file)
00465             {
00466                 try
00467                 {
00468                     GetNextFaceData();
00469                     num_boundary_faces++;
00470                 }
00471                 catch(Exception& e)
00472                 {
00473                     end_of_file = true;
00474                 }
00475             }
00476             mNumFaces = num_boundary_faces;
00477 
00478             // close the file, reopen, and skip the header again
00479             mFacesFile.close();
00480             mFacesFile.clear(); // Older versions of gcc don't explicitly reset "fail" and "eof" flags in std::ifstream after calling close()
00481             OpenFacesFile();
00482             GetNextLineFromStream(mFacesFile, buffer);
00483             mFacesRead = 0;
00484             mBoundaryFacesRead = 0;
00485         }
00486     }
00487 }
00488 
00489 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00490 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::CloseFiles()
00491 {
00492     mNodesFile.close();
00493     mElementsFile.close();
00494     mFacesFile.close();
00495 }
00496 
00497 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00498 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextLineFromStream(std::ifstream& fileStream, std::string& rRawLine)
00499 {
00500     bool line_is_blank;
00501 
00502     do
00503     {
00504         getline(fileStream, rRawLine);
00505 
00506         if (fileStream.eof())
00507         {
00509             EXCEPTION("File contains incomplete data");
00510         }
00511 
00512         // Get rid of any comment
00513         rRawLine = rRawLine.substr(0, rRawLine.find('#',0));
00514 
00515         line_is_blank = (rRawLine.find_first_not_of(" \t",0) == std::string::npos);
00516     }
00517     while (line_is_blank);
00518 }
00519 
00520 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00521 std::string TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetMeshFileBaseName()
00522 {
00523     return mFilesBaseName;
00524 }
00525 
00526 
00528 // Explicit instantiation
00530 
00531 template class TrianglesMeshReader<0,1>;
00532 template class TrianglesMeshReader<1,1>;
00533 template class TrianglesMeshReader<1,2>;
00534 template class TrianglesMeshReader<1,3>;
00535 template class TrianglesMeshReader<2,2>;
00536 template class TrianglesMeshReader<2,3>;
00537 template class TrianglesMeshReader<3,3>;

Generated on Tue Aug 4 16:10:22 2009 for Chaste by  doxygen 1.5.5