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

Generated on Tue May 31 14:31:48 2011 for Chaste by  doxygen 1.5.5