TrianglesMeshReader.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 "TrianglesMeshReader.hpp"
00030 #include "Exception.hpp"
00031 #include <cassert>
00032 #include <sstream>
00033 #include <iostream>
00034 
00035 static const char* NODES_FILE_EXTENSION = ".node";
00036 static const char* ELEMENTS_FILE_EXTENSION = ".ele";
00037 static const char* FACES_FILE_EXTENSION = ".face";
00038 static const char* EDGES_FILE_EXTENSION = ".edge";
00039 static const char* NCL_FILE_EXTENSION = ".ncl";
00040 
00042 // Implementation
00044 
00045 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00046 TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::TrianglesMeshReader(std::string pathBaseName,
00047                                                                  unsigned orderOfElements,
00048                                                                  unsigned orderOfBoundaryElements,
00049                                                                  bool readContainingElementForBoundaryElements)
00050     : mFilesBaseName(pathBaseName),
00051       mNodeItemWidth(0),
00052       mElementItemWidth(0),
00053       mFaceItemWidth(0),
00054       mNumNodes(0),
00055       mNumElements(0),
00056       mNumFaces(0),
00057       mNodesRead(0),
00058       mElementsRead(0),
00059       mFacesRead(0),
00060       mBoundaryFacesRead(0),
00061       mNumNodeAttributes(0),
00062       mNumElementAttributes(0),
00063       mNumFaceAttributes(0),
00064       mOrderOfElements(orderOfElements),
00065       mOrderOfBoundaryElements(orderOfBoundaryElements),
00066       mEofException(false),
00067       mReadContainingElementOfBoundaryElement(readContainingElementForBoundaryElements),
00068       mFilesAreBinary(false),
00069       mMeshIsHexahedral(false),
00070       mNodeFileReadBuffer(NULL),
00071       mElementFileReadBuffer(NULL),
00072       mFaceFileReadBuffer(NULL),
00073       mNodePermutationDefined(false)
00074 {
00075     // Only linear and quadratic elements
00076     assert(orderOfElements==1 || orderOfElements==2);
00077     if ( mOrderOfBoundaryElements == 2 &&  mReadContainingElementOfBoundaryElement)
00078     {
00079         EXCEPTION("Boundary element file should not have containing element info if it is quadratic");
00080     }
00081     if (mOrderOfElements==1)
00082     {
00083         mNodesPerElement = ELEMENT_DIM+1;
00084     }
00085     else
00086     {
00087         #define COVERAGE_IGNORE
00088         assert(SPACE_DIM==ELEMENT_DIM);
00089         #undef COVERAGE_IGNORE
00090         mNodesPerElement = (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2;
00091     }
00092 
00093     if (mOrderOfBoundaryElements==1)
00094     {
00095         mNodesPerBoundaryElement = ELEMENT_DIM;
00096     }
00097     else
00098     {
00099         #define COVERAGE_IGNORE
00100         assert(SPACE_DIM==ELEMENT_DIM);
00101         #undef COVERAGE_IGNORE
00102         mNodesPerBoundaryElement = ELEMENT_DIM*(ELEMENT_DIM+1)/2;
00103     }
00104 
00105     mIndexFromZero = false; // Initially assume that nodes are not numbered from zero
00106 
00107     OpenFiles();
00108     ReadHeaders();
00109 }
00110 
00111 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00112 TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::~TrianglesMeshReader()
00113 {
00114     delete[] mNodeFileReadBuffer;
00115     delete[] mElementFileReadBuffer;
00116     delete[] mFaceFileReadBuffer;
00117 }
00118 
00119 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00120 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumElements() const
00121 {
00122     return mNumElements;
00123 }
00124 
00125 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00126 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumNodes() const
00127 {
00128     return mNumNodes;
00129 }
00130 
00131 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00132 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumFaces() const
00133 {
00134     return mNumFaces;
00135 }
00136 
00137 
00138 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00139 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumElementAttributes() const
00140 {
00141     return mNumElementAttributes;
00142 }
00143 
00144 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00145 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumFaceAttributes() const
00146 {
00147     return mNumFaceAttributes;
00148 }
00149 
00150 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00151 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::Reset()
00152 {
00153     CloseFiles();
00154 
00155     mNodesRead = 0;
00156     mElementsRead = 0;
00157     mFacesRead = 0;
00158     mBoundaryFacesRead = 0;
00159     mEofException = false;
00160 
00161     OpenFiles();
00162     ReadHeaders();
00163 }
00164 
00165 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00166 std::vector<double> TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextNode()
00167 {
00168     std::vector<double> ret_coords(SPACE_DIM);
00169 
00170     mNodeAttributes.clear();//clear attributes for this node
00171     GetNextItemFromStream(mNodesFile, mNodesRead, ret_coords, mNumNodeAttributes, mNodeAttributes);
00172 
00173     mNodesRead++;
00174     return ret_coords;
00175 }
00176 
00177 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00178 ElementData TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextElementData()
00179 {
00180     ElementData element_data;
00181     element_data.NodeIndices.resize(mNodesPerElement);
00182     element_data.AttributeValue = 0; // If an attribute is not read this stays as zero, otherwise overwritten.
00183 
00184     std::vector<unsigned> element_attributes;
00185     GetNextItemFromStream(mElementsFile, mElementsRead, element_data.NodeIndices, mNumElementAttributes, element_attributes);
00186     if (mNumElementAttributes > 0)
00187     {
00188         element_data.AttributeValue = (unsigned) element_attributes[0];
00189     }
00190 
00191     EnsureIndexingFromZero(element_data.NodeIndices);
00192 
00193     mElementsRead++;
00194     
00195     if (mNodePermutationDefined)
00196     {    
00197         for (std::vector<unsigned>::iterator node_it = element_data.NodeIndices.begin();
00198              node_it != element_data.NodeIndices.end();
00199              ++ node_it)
00200         {
00201             assert(*node_it < mPermutationVector.size());            
00202             *node_it =  mPermutationVector[*node_it];
00203         }
00204     }
00205         
00206     return element_data;
00207 }
00208 
00209 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00210 ElementData TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextFaceData()
00211 {
00212     ElementData face_data;
00213     std::vector<unsigned> ret_indices;
00214 
00215     // In the first case there's no file, all the nodes are set as faces
00216     if (ELEMENT_DIM == 1)
00217     {
00218         ret_indices.push_back( mOneDimBoundary[mBoundaryFacesRead] );
00219     }
00220     else
00221     {
00222         ret_indices.resize(mNodesPerBoundaryElement);
00223 
00224         assert(ELEMENT_DIM != 0); //Covered in earlier exception, but needed in loop guard here.
00225         do
00226         {
00227             face_data.AttributeValue = 1u; // If an attribute is not read this stays as one, otherwise overwritten.
00228 
00229             std::vector<unsigned> face_attributes;//will store face attributes, if any
00230             if (mReadContainingElementOfBoundaryElement)
00231             {
00232                 assert(mNumFaceAttributes == 0);
00233                 GetNextItemFromStream(mFacesFile, mFacesRead, ret_indices, 1,
00234                                         face_attributes);
00235 
00236                 if (face_attributes.size() > 0)
00237                 {
00238                     face_data.ContainingElement = (unsigned) face_attributes[0];// only one face attribute registered for the moment
00239                 }
00240 
00241             }
00242             else
00243             {
00244                 GetNextItemFromStream(mFacesFile, mFacesRead, ret_indices, mNumFaceAttributes,
00245                                         face_attributes);
00246 
00247                 if (mNumFaceAttributes > 0)
00248                 {
00249                     face_data.AttributeValue = (unsigned) face_attributes[0];//only one face attribute registered for the moment
00250                 }
00251             }
00252 
00253             EnsureIndexingFromZero(ret_indices);
00254 
00255             mFacesRead++;
00256         }
00257         while (ELEMENT_DIM==2 && face_data.AttributeValue==0); //In triangles format we ignore internal edges (which are marked with attribute 0)
00258     }
00259 
00260     mBoundaryFacesRead++;
00261     
00262     if (mNodePermutationDefined)
00263     {    
00264         for (std::vector<unsigned>::iterator node_it = ret_indices.begin();
00265              node_it != ret_indices.end();
00266              ++ node_it)
00267         {
00268             assert(*node_it < mPermutationVector.size());
00269             *node_it =  mPermutationVector[*node_it];
00270         }
00271     }
00272 
00273     face_data.NodeIndices = ret_indices;
00274         
00275     return face_data;
00276 }
00277 
00278 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00279 std::vector<double> TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNode(unsigned index)
00280 {
00281     if (!mFilesAreBinary)
00282     {
00283         EXCEPTION("Random access is only implemented in mesh readers for binary mesh files.");
00284     }
00285     if (index >= mNumNodes)
00286     {
00287         EXCEPTION("Node does not exist - not enough nodes.");
00288     }
00289     
00290     if (mNodePermutationDefined)
00291     {
00292         assert(index<mInversePermutationVector.size());
00293         index = mInversePermutationVector[index];
00294     }
00295     
00296     // Put the file stream pointer to the right location
00297     mNodesFile.seekg(mNodeFileDataStart + mNodeItemWidth*index, std::ios_base::beg);
00298     // Read the next item.
00299     return GetNextNode();
00300 }
00301 
00302 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00303 ElementData TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetElementData(unsigned index)
00304 {
00305     if (!mFilesAreBinary)
00306     {
00307         EXCEPTION("Random access is only implemented in mesh readers for binary mesh files.");
00308     }
00309     if (index >=mNumElements)
00310     {
00311         EXCEPTION("Element does not exist - not enough elements.");
00312     }
00313 
00314     // Put the file stream pointer to the right location
00315     mElementsFile.seekg(mElementFileDataStart + mElementItemWidth*index, std::ios_base::beg);
00316     // Read the next item.
00317     return GetNextElementData();
00318 }
00319 
00320 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00321 ElementData TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetFaceData(unsigned index)
00322 {
00323     if (!mFilesAreBinary)
00324     {
00325         EXCEPTION("Random access is only implemented in mesh readers for binary mesh files.");
00326     }
00327     if (index >=mNumFaces)
00328     {
00329         EXCEPTION("Face does not exist - not enough faces.");
00330     }
00331     // Put the file stream pointer to the right location
00332     mFacesFile.seekg(mFaceFileDataStart + mFaceItemWidth*index, std::ios_base::beg);
00333     // Read the next item.
00334     return GetNextFaceData();
00335 }
00336 
00337 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00338 std::vector<unsigned> TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetContainingElementIndices(unsigned index)
00339 {
00340     if (!mFilesAreBinary)
00341     {
00342         EXCEPTION("NCL file functionality is only implemented in mesh readers for binary mesh files.");
00343     }
00344 
00345     if (!mNclFileAvailable)
00346     {
00347         EXCEPTION("No NCL file available for this mesh.");
00348     }
00349     if (index >=mNumNodes)
00350     {
00351         EXCEPTION("Connectivity list does not exist - not enough nodes.");
00352     }
00353 
00354     if (mNodePermutationDefined)
00355     {
00356         assert(index<mInversePermutationVector.size());
00357         index = mInversePermutationVector[index];
00358     }
00359 
00360     // Put the file stream pointer to the right location
00361     mNclFile.seekg(mNclFileDataStart + mNclItemWidth*index, std::ios_base::beg);
00362     // Read the next item.
00363     std::vector<unsigned> containing_element_indices;
00364     containing_element_indices.resize(mMaxContainingElements);
00365 
00366     std::vector<unsigned>  dummy;//unused here
00367     GetNextItemFromStream(mNclFile, index, containing_element_indices, 0, dummy);
00368 
00369     EnsureIndexingFromZero(containing_element_indices);
00370 
00371     unsigned num_containing_elements = mMaxContainingElements;
00372     while ( containing_element_indices[num_containing_elements-1] == UINT_MAX )
00373     {
00374         num_containing_elements--;
00375     }
00376 
00377     containing_element_indices.resize(num_containing_elements);
00378 
00379     return containing_element_indices;
00380 }
00381 
00382 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00383 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenFiles()
00384 {
00385     OpenNodeFile();
00386     OpenElementsFile();
00387     OpenFacesFile();
00388     OpenNclFile();
00389 }
00390 
00391 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00392 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenNodeFile()
00393 {
00394     // Nodes definition
00395     std::string file_name = mFilesBaseName + NODES_FILE_EXTENSION;
00396     mNodesFile.open(file_name.c_str());
00397     if (!mNodesFile.is_open())
00398     {
00399         EXCEPTION("Could not open data file: " + file_name);
00400     }
00401 }
00402 
00403 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00404 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenElementsFile()
00405 {
00406     // Elements definition
00407     std::string file_name;
00408     if (ELEMENT_DIM == SPACE_DIM)
00409     {
00410         file_name = mFilesBaseName + ELEMENTS_FILE_EXTENSION;
00411     }
00412     else
00413     {
00414         if (ELEMENT_DIM == 1)
00415         {
00416             file_name = mFilesBaseName + EDGES_FILE_EXTENSION;
00417         }
00418         else if (ELEMENT_DIM == 2)
00419         {
00420             file_name = mFilesBaseName + FACES_FILE_EXTENSION;
00421         }
00422         else
00423         {
00424             EXCEPTION("Can't have a zero-dimensional mesh in a one-dimensional space");
00425         }
00426     }
00427 
00428     mElementsFile.open(file_name.c_str());
00429     if (!mElementsFile.is_open())
00430     {
00431         EXCEPTION("Could not open data file: " + file_name);
00432     }
00433 }
00434 
00435 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00436 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenFacesFile()
00437 {
00438     // Faces/edges definition
00439     std::string file_name;
00440     if (ELEMENT_DIM == 3)
00441     {
00442         file_name = mFilesBaseName + FACES_FILE_EXTENSION;
00443     }
00444     else if (ELEMENT_DIM == 2)
00445     {
00446         file_name = mFilesBaseName + EDGES_FILE_EXTENSION;
00447     }
00448     else //if (ELEMENT_DIM == 1)
00449     {
00450         // There is no file, data will be read from the node file (with boundaries marked)
00451         return;
00452     }
00453 
00454     mFacesFile.open(file_name.c_str());
00455     if (!mFacesFile.is_open())
00456     {
00457         EXCEPTION("Could not open data file: " + file_name);
00458     }
00459 }
00460 
00461 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00462 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenNclFile()
00463 {
00464     // Nodes definition
00465     std::string file_name = mFilesBaseName + NCL_FILE_EXTENSION;
00466     mNclFile.open(file_name.c_str());
00467 
00468     mNclFileAvailable = mNclFile.is_open();
00469 }
00470 
00471 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00472 std::vector<double> TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNodeAttributes()
00473 {
00474     return mNodeAttributes;
00475 }
00476 
00477 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00478 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::ReadHeaders()
00479 {
00480     /*
00481      *  Reading node file header
00482      */
00483     std::string buffer;
00484     GetNextLineFromStream(mNodesFile, buffer);
00485     std::stringstream node_header_line(buffer);
00486     unsigned dimension;
00487     node_header_line >> mNumNodes >> dimension >> mNumNodeAttributes >> mMaxNodeBdyMarker;
00488     if (SPACE_DIM != dimension)
00489     {
00490         EXCEPTION("SPACE_DIM  != dimension read from file ");
00491     }
00492     //Is there anything else on the header line?
00493     std::string extras;
00494     node_header_line >> extras;
00495     if (extras == "BIN")
00496     {
00497         mFilesAreBinary = true;
00498         mNodeFileDataStart = mNodesFile.tellg(); // Record the position of the first byte after the header.
00499         mNodeItemWidth = SPACE_DIM * sizeof(double);
00500         //We enforce that all binary files (written by Chaste) are indexed from zero
00501         mIndexFromZero = true;
00502     }
00503     else
00504     {
00505         // #1621 - ncl files are only supported in binary read mode.
00506         assert(!mNclFileAvailable);
00507 
00508         // Get the next line to see if it is indexed from zero or not
00509         GetNextLineFromStream(mNodesFile, buffer);
00510         std::stringstream node_first_line(buffer);
00511         unsigned first_index;
00512         node_first_line >> first_index;
00513         assert(first_index == 0 || first_index == 1);
00514         mIndexFromZero = (first_index == 0);
00515         // Close, reopen, skip header
00516         mNodesFile.close();
00517         OpenNodeFile();
00518         GetNextLineFromStream(mNodesFile, buffer);
00519     }
00520 
00521     /*
00522      *  Reading element file header
00523      */
00524     GetNextLineFromStream(mElementsFile, buffer);
00525     std::stringstream element_header_line(buffer);
00526 
00527     unsigned extra_attributes = 0;
00528 
00529     if (ELEMENT_DIM == SPACE_DIM)
00530     {
00531         element_header_line >> mNumElements >> mNumElementNodes >> mNumElementAttributes;
00532 
00533         extra_attributes = mNumElementAttributes;
00534 
00535         //Is there anything else on the header line?
00536         std::string element_extras;
00537         element_header_line >> element_extras;
00538         if (element_extras == "BIN")
00539         {
00540             //Double check for binaryness
00541             assert (mFilesAreBinary);
00542         }
00543         else if (element_extras == "HEX")
00544         {
00545             mMeshIsHexahedral = true;
00546             if ( ELEMENT_DIM == 2 )
00547             {
00548                 mNodesPerElement = 4;
00549                 mNodesPerBoundaryElement = 2;
00550             }
00551             if ( ELEMENT_DIM == 3 )
00552             {
00553                 mNodesPerElement = 8;
00554                 mNodesPerBoundaryElement = 4;
00555             }
00556         }
00557         else
00558         {
00559             assert (element_extras == "");
00560         }
00561 
00562         if ( mNumElementNodes != mNodesPerElement )
00563         {
00564             std::stringstream error;
00565             error << "Number of nodes per elem, " << mNumElementNodes << ", does not match "
00566                   << "expected number, " << mNodesPerElement << " (which is calculated given "
00567                   << "the order of elements chosen, " << mOrderOfElements << " (1=linear, 2=quadratics)";
00568             EXCEPTION(error.str());
00569         }
00570     }
00571     else
00572     {
00573         element_header_line >> mNumElements >> mNumFaceAttributes;
00574 
00575         extra_attributes = mNumFaceAttributes;
00576 
00577         //Is there anything else on the header line?
00578         std::string element_extras;
00579         element_header_line >> element_extras;
00580         if (element_extras == "BIN")
00581         {
00582             //Double check for binaryness
00583             assert (mFilesAreBinary);
00584         }
00585 
00586         mNodesPerElement = ELEMENT_DIM+1;
00587     }
00588 
00589 
00590     if (mFilesAreBinary)
00591     {
00592         mElementFileDataStart = mElementsFile.tellg(); // Record the position of the first byte after the header.
00593         mElementItemWidth = (mNodesPerElement + extra_attributes) * sizeof(unsigned);
00594     }
00595 
00596     /*
00597      *  Reading face/edge file header
00598      */
00599     if (ELEMENT_DIM == 1)
00600     {
00601        GetOneDimBoundary();
00602        mNumFaces = mOneDimBoundary.size();
00603     }
00604     else
00605     {
00606         GetNextLineFromStream(mFacesFile, buffer);
00607         std::stringstream face_header_line(buffer);
00608 
00609         face_header_line >> mNumFaces >> mNumFaceAttributes;
00610         assert(mNumFaceAttributes==0 || mNumFaceAttributes==1);
00611         // if mNumFaceAttributes=1 then loop over and set mNumFaces to be
00612         // the number of faces which are marked as boundary faces
00613         //Double check for binaryness
00614         std::string face_extras;
00615         face_header_line >> face_extras;
00616         assert (mFilesAreBinary == (face_extras == "BIN"));
00617         if ((mNumFaceAttributes==1))
00618         {
00619             unsigned num_boundary_faces = 0;
00620             bool end_of_file=false;
00621             while (!end_of_file)
00622             {
00623                 try
00624                 {
00625                     GetNextFaceData();
00626                     num_boundary_faces++;
00627                 }
00628                 catch(Exception& e)
00629                 {
00630                     if(mEofException)
00631                     {
00632                         end_of_file = true;
00633                     }
00634                     else
00635                     {
00636                         throw e;
00637                     }
00638                 }
00639             }
00640             mNumFaces = num_boundary_faces;
00641 
00644 //            if(mNumFaces==0)
00645 //            {
00646 //                EXCEPTION("No boundary elements found. NOTE: elements in face/edge file with an attribute value of 0 are considered to be internal (non-boundary) elements");
00647 //            }
00648 
00649             // close the file, reopen, and skip the header again
00650             mFacesFile.close();
00651             mFacesFile.clear(); // Older versions of gcc don't explicitly reset "fail" and "eof" flags in std::ifstream after calling close()
00652             OpenFacesFile();
00653             GetNextLineFromStream(mFacesFile, buffer);
00654             mFacesRead = 0;
00655             mBoundaryFacesRead = 0;
00656         }
00657     }
00658 
00659     if (mFilesAreBinary)
00660     {
00661         mFaceFileDataStart = mFacesFile.tellg(); // Record the position of the first byte after the header.
00662         mFaceItemWidth = (ELEMENT_DIM + mNumFaceAttributes) * sizeof(unsigned);
00663     }
00664 
00665     /*
00666      * Read NCL file (if one is available)
00667      */
00668     if (mNclFileAvailable)
00669     {
00670         GetNextLineFromStream(mNclFile, buffer);
00671         std::stringstream ncl_header_line(buffer);
00672         unsigned num_nodes_in_file;
00673         ncl_header_line >> num_nodes_in_file >> mMaxContainingElements;
00674 
00675         if ( mNumNodes != num_nodes_in_file )
00676         {
00677             EXCEPTION("NCL file does not contain the correct number of nodes for mesh");
00678         }
00679 
00680         mNclFileDataStart = mNclFile.tellg(); // Record the position of the first byte after the header.
00681         mNclItemWidth = mMaxContainingElements * sizeof(unsigned);
00682     }
00683 
00684 }
00685 
00686 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00687 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::CloseFiles()
00688 {
00689     mNodesFile.close();
00690     mElementsFile.close();
00691     mFacesFile.close();
00692     mNclFile.close();
00693 }
00694 
00695 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00696 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextLineFromStream(std::ifstream& rFileStream, std::string& rRawLine)
00697 {
00698     bool line_is_blank;
00699     mEofException = false;
00700     do
00701     {
00702         getline(rFileStream, rRawLine);
00703         if (rFileStream.eof())
00704         {
00705             mEofException = true;
00706             EXCEPTION("File contains incomplete data: unexpected end of file.");
00707         }
00708 
00709         // Get rid of any comment
00710         rRawLine = rRawLine.substr(0, rRawLine.find('#',0));
00711 
00712         line_is_blank = (rRawLine.find_first_not_of(" \t",0) == std::string::npos);
00713     }
00714     while (line_is_blank);
00715 }
00716 
00717 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00718 template<class T>
00719 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextItemFromStream(std::ifstream& rFileStream, unsigned expectedItemNumber,
00720                                std::vector<T>& rDataPacket, const unsigned& rNumAttributes, std::vector<T>& rAttributes)
00721 {
00722     if (mFilesAreBinary)
00723     {
00724         rFileStream.read((char*)&rDataPacket[0], rDataPacket.size()*sizeof(T));
00725         if (rNumAttributes>0)
00726         {
00727             for (unsigned i = 0; i < rNumAttributes; i++)
00728             {
00729                 T attribute;
00730                 rFileStream.read((char*) &attribute, sizeof(T));
00731                 rAttributes.push_back(attribute);
00732             }
00733         }
00734     }
00735     else
00736     {
00737         std::string buffer;
00738         GetNextLineFromStream(rFileStream,buffer);
00739         std::stringstream buffer_stream(buffer);
00740 
00741         unsigned item_index;
00742         buffer_stream >> item_index;
00743 
00744         // If we are indexing from zero our expected item number is one larger.
00745         expectedItemNumber += mIndexFromZero ? 0 : 1;
00746 
00747         if (item_index != expectedItemNumber)
00748         {
00749             std::stringstream error;
00750             if (!mIndexFromZero)
00751             { // To fix the exception message to agree with file format.
00752                 expectedItemNumber--;
00753             }
00754             error << "Data for item " << expectedItemNumber << " missing";
00755             EXCEPTION(error.str());
00756         }
00757 
00758         for (unsigned i=0; i<rDataPacket.size(); i++)
00759         {
00760             buffer_stream >> rDataPacket[i];
00761         }
00762 
00763         if (rNumAttributes>0)
00764         {
00765             for (unsigned i = 0; i < rNumAttributes; i++)
00766             {
00767                 T attribute;
00768                 buffer_stream >> attribute;
00769                 rAttributes.push_back(attribute);
00770             }
00771         }
00772     }
00773 }
00774 
00775 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00776 std::string TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetMeshFileBaseName()
00777 {
00778     return mFilesBaseName;
00779 }
00780 
00781 
00782 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00783 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetOneDimBoundary()
00784 {
00785     assert(ELEMENT_DIM == 1);
00786     if (!mOneDimBoundary.empty())
00787     {
00788         //We have already read this and have reset the reader (probably from the mesh class)...
00789         return;
00790     }
00791 
00792     std::vector<unsigned> node_indices(2);
00793     std::vector<unsigned>  dummy_attribute;//unused
00794     //Count how many times we see each node
00795     std::vector<unsigned> node_count(mNumNodes);//Covers the case if it's indexed from 1
00796     for (unsigned element_index=0; element_index<mNumElements;element_index++)
00797     {
00798         GetNextItemFromStream(mElementsFile, element_index, node_indices, mNumElementAttributes, dummy_attribute);
00799         if (!mIndexFromZero)
00800         {
00801             //Adjust so we are indexing from zero
00802             node_indices[0]--;
00803             node_indices[1]--;
00804         }
00805         node_count[node_indices[0]]++;
00806         node_count[node_indices[1]]++;
00807     }
00808     //Find the ones which are terminals (only one mention)
00809     for (unsigned node_index=0; node_index<mNumNodes;node_index++)
00810     {
00811         if (node_count[node_index] == 1u)
00812         {
00813             mOneDimBoundary.push_back(node_index);
00814         }
00815     }
00816 
00817     // close the file, reopen, and skip the header again
00818     mElementsFile.close();
00819     mElementsFile.clear(); // Older versions of gcc don't explicitly reset "fail" and "eof" flags in std::ifstream after calling close()
00820     OpenElementsFile();
00821     std::string buffer;
00822     GetNextLineFromStream(mElementsFile, buffer);
00823 }
00824 
00825 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00826 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::EnsureIndexingFromZero(std::vector<unsigned>& rNodeIndices)
00827 {
00828 
00829     if (!mIndexFromZero) // If node indices do not start at zero move them all down one so they do
00830     {
00831         for (unsigned i=0; i<rNodeIndices.size(); i++)
00832         {
00833             rNodeIndices[i]--;
00834         }
00835     }
00836 
00837 }
00838 
00839 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00840 bool TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::IsFileFormatBinary()
00841 {
00842     return mFilesAreBinary;
00843 }
00844 
00845 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00846 bool TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::HasNclFile()
00847 {
00848     return mNclFileAvailable;
00849 }
00850 
00851 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00852 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::SetReadBufferSize(unsigned bufferSize)
00853 {
00854     mNodeFileReadBuffer =  new char[bufferSize];
00855     mElementFileReadBuffer =  new char[bufferSize];
00856     mFaceFileReadBuffer =  new char[bufferSize];
00857 
00858     mNodesFile.rdbuf()->pubsetbuf(mNodeFileReadBuffer, bufferSize);
00859     mElementsFile.rdbuf()->pubsetbuf(mElementFileReadBuffer, bufferSize);
00860     mFacesFile.rdbuf()->pubsetbuf(mFaceFileReadBuffer, bufferSize);
00861 
00862 }
00863 
00864 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00865 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::SetNodePermutation(std::vector<unsigned>& rPermutationVector)
00866 {
00867     if ( !mFilesAreBinary )
00868     {
00869         // It would be too inefficient otherwise...
00870         EXCEPTION("Permuted read can only be used with binary files since it requires random access to the node file.");
00871     }
00872     
00873     mNodePermutationDefined = true;    
00874     mPermutationVector = rPermutationVector;    
00875     mInversePermutationVector.resize(mPermutationVector.size());
00876     for (unsigned index=0; index<mPermutationVector.size(); index++)
00877     {
00878         mInversePermutationVector[mPermutationVector[index]]=index;
00879     }
00880 }
00881 
00883 // Explicit instantiation
00885 
00886 template class TrianglesMeshReader<0,1>;
00887 template class TrianglesMeshReader<1,1>;
00888 template class TrianglesMeshReader<1,2>;
00889 template class TrianglesMeshReader<1,3>;
00890 template class TrianglesMeshReader<2,2>;
00891 template class TrianglesMeshReader<2,3>;
00892 template class TrianglesMeshReader<3,3>;
00893 
00894 
00899 template void TrianglesMeshReader<0,1>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&);
00900 template void TrianglesMeshReader<0,1>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double>  &, const unsigned&, std::vector<double>&);
00901 template void TrianglesMeshReader<1,1>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&);
00902 template void TrianglesMeshReader<1,1>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double>  &, const unsigned&, std::vector<double>&);
00903 template void TrianglesMeshReader<1,2>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&);
00904 template void TrianglesMeshReader<1,2>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double>  &, const unsigned&, std::vector<double>&);
00905 template void TrianglesMeshReader<1,3>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&);
00906 template void TrianglesMeshReader<1,3>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double>  &, const unsigned&, std::vector<double>&);
00907 template void TrianglesMeshReader<2,2>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&);
00908 template void TrianglesMeshReader<2,2>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double>  &, const unsigned&, std::vector<double>&);
00909 template void TrianglesMeshReader<2,3>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&);
00910 template void TrianglesMeshReader<2,3>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double>  &, const unsigned&, std::vector<double>&);
00911 template void TrianglesMeshReader<3,3>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&);
00912 template void TrianglesMeshReader<3,3>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double>  &, const unsigned&, std::vector<double>&);

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