GmshMeshReader.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 #include <cassert>
00036 #include <sstream>
00037 #include <iostream>
00038 
00039 #include "GmshMeshReader.hpp"
00040 #include "Exception.hpp"
00041 
00042 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00043 GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GmshMeshReader(std::string pathBaseName,
00044                                                        unsigned orderOfElements,
00045                                                        unsigned orderOfBoundaryElements) :
00046        mFileName(pathBaseName),
00047        mOrderOfElements(orderOfElements),
00048        mOrderOfBoundaryElements(orderOfBoundaryElements)
00049 {
00050     assert(SPACE_DIM==ELEMENT_DIM); //There is no fundamental reason for this, but full testing of SPACE_DIM != ELEMENT_DIM would be required.
00051 
00052     // Only linear and quadratic elements
00053     assert(mOrderOfElements==1 || mOrderOfElements==2);
00054 
00055     if (mOrderOfElements==1)
00056     {
00057         mNodesPerElement = ELEMENT_DIM+1;
00058     }
00059     else
00060     {
00061         mNodesPerElement = (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2;
00062     }
00063 
00064     if (mOrderOfBoundaryElements==1)
00065     {
00066         mNodesPerBoundaryElement = ELEMENT_DIM;
00067     }
00068     else
00069     {
00070         mNodesPerBoundaryElement = ELEMENT_DIM*(ELEMENT_DIM+1)/2;
00071     }
00072 
00073     OpenFiles();
00074     ReadHeaders();
00075 }
00076 
00077 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00078 GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::~GmshMeshReader()
00079 {
00080     CloseFiles();
00081 }
00082 
00083 template<unsigned  ELEMENT_DIM, unsigned  SPACE_DIM>
00084 void GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenFiles()
00085 {
00086     // Open mesh file
00087     mNodeFile.open(mFileName.c_str());
00088     mElementFile.open(mFileName.c_str());
00089     mFaceFile.open(mFileName.c_str());
00090     if (!mNodeFile.is_open() || !mElementFile.is_open() || !mFaceFile.is_open() )
00091     {
00092         EXCEPTION("Could not open data file: " + mFileName);
00093     }
00094 }
00095 
00096 template<unsigned  ELEMENT_DIM, unsigned  SPACE_DIM>
00097 void GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::CloseFiles()
00098 {
00099     mNodeFile.close();
00100     mElementFile.close();
00101     mFaceFile.close();
00102 }
00103 
00104 
00105 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00106 void GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::ReadHeaders()
00107 {
00108     /*
00109      * Read mesh format information from the file header
00110      */
00111     std::string this_line;
00112     getline(mNodeFile, this_line);
00113 
00114     assert(this_line == "$MeshFormat");
00115 
00116     //Read the version no.
00117     getline(mNodeFile, this_line);
00118     std::stringstream line(this_line);
00119 
00120     line >> mVersionNumber >> mFileType >> mDataSize;
00121 
00122     if(mVersionNumber != 2.2)
00123     {
00124         EXCEPTION("Only .msh version 2.2 files are supported.");
00125     }
00126     assert(mFileType == 0);
00127 
00128     //Check mesh format close string
00129     getline(mNodeFile, this_line);
00130     assert(this_line == "$EndMeshFormat");
00131 
00132     ReadNodeHeader();
00133     ReadElementHeader();
00134     ReadFaceHeader();
00135 }
00136 
00137 
00138 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00139 void GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::ReadNodeHeader()
00140 {
00141     //search for the start of the node section
00142     std::string this_line;
00143     std::stringstream line(this_line);
00144 
00145     while(this_line != "$Nodes")
00146     {
00147         getline(mNodeFile, this_line);
00148     }
00149     getline(mNodeFile, this_line);
00150 
00151     line.clear();
00152     line.str(this_line);
00153     line >> mNumNodes; //mNodesFile should now be pointing at the start of the node lines in the file.
00154 }
00155 
00156 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00157 void GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::ReadElementHeader()
00158 {
00159     //Search for the start of the elements section
00160     std::string this_line;
00161     std::stringstream line(this_line);
00162 
00163     getline(mElementFile, this_line);
00164     while(this_line != "$Elements")
00165     {
00166         getline(mElementFile, this_line);
00167     }
00168     getline(mElementFile, this_line); //Throw away the number of elements specified in the file
00169     int ele_start = mElementFile.tellg(); //Pointer to the start of the element block.
00170 
00171     mNumElements = 0u;
00172     getline(mElementFile, this_line);
00173 
00174     while(this_line != "$EndElements")
00175     {
00176         line.clear();
00177         line.str(this_line);
00178 
00179         unsigned ele_index;
00180         unsigned ele_type;
00181         line >> ele_index >> ele_type;
00182 
00183         if(ELEMENT_DIM == 2 && (ele_type == GmshTypes::TRIANGLE || ele_type == GmshTypes::QUADRATIC_TRIANGLE))
00184         {
00185             mNumElements++;
00186         }
00187         else if(ELEMENT_DIM == 3 && (ele_type == GmshTypes::TETRAHEDRON || ele_type == GmshTypes::QUADRATIC_TETRAHEDRON))
00188         {
00189             mNumElements++;
00190         }
00191 
00192         getline(mElementFile, this_line);
00193     }
00194 
00195     mElementFile.seekg(ele_start); //mElementFile should now be pointing at the start of the node lines in the file.
00196 }
00197 
00198 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00199 void GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::ReadFaceHeader()
00200 {
00201     //Search for the start of the elements section
00202     std::string this_line;
00203     std::stringstream line(this_line);
00204 
00205     getline(mFaceFile, this_line);
00206     while(this_line != "$Elements")
00207     {
00208         getline(mFaceFile, this_line);
00209     }
00210     getline(mFaceFile, this_line); //Throw away the number of elements specified in the file
00211     int face_start = mFaceFile.tellg(); //Pointer to the start of the element block.
00212 
00213     mNumFaces = 0u;
00214     getline(mFaceFile, this_line);
00215 
00216     while(this_line != "$EndElements")
00217     {
00218         line.clear();
00219         line.str(this_line);
00220 
00221         unsigned ele_index;
00222         unsigned ele_type;
00223         line >> ele_index >> ele_type;
00224 
00225         if(ELEMENT_DIM == 2 && (ele_type == GmshTypes::LINE || ele_type == GmshTypes::QUADRATIC_LINE))
00226         {
00227             mNumFaces++;
00228         }
00229         else if(ELEMENT_DIM == 3 && (ele_type == GmshTypes::TRIANGLE || ele_type == GmshTypes::QUADRATIC_TRIANGLE))
00230         {
00231             mNumFaces++;
00232         }
00233 
00234         getline(mFaceFile, this_line);
00235     }
00236 
00237     mFaceFile.seekg(face_start); //mFacesFile should now be pointing at the start of the node lines in the file.
00238 }
00239 
00240 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00241 unsigned GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumElements() const
00242 {
00243     return mNumElements;
00244 }
00245 
00246 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00247 unsigned GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumNodes() const
00248 {
00249     return mNumNodes;
00250 }
00251 
00252 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00253 unsigned GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumFaces() const
00254 {
00255     return mNumFaces;
00256 }
00257 
00258 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00259 unsigned GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumCableElements() const
00260 {
00261     NEVER_REACHED;
00262     //return mNumCableElements;
00263 }
00264 
00265 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00266 unsigned GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetOrderOfElements()
00267 {
00268     return mOrderOfElements;
00269 }
00270 
00271 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00272 unsigned GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetOrderOfBoundaryElements()
00273 {
00274     return mOrderOfBoundaryElements;
00275 }
00276 
00277 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00278 unsigned GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumElementAttributes() const
00279 {
00280     return mNumElementAttributes;
00281 }
00282 
00283 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00284 unsigned GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumFaceAttributes() const
00285 {
00286     return mNumFaceAttributes;
00287 }
00288 
00289 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00290 unsigned GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumCableElementAttributes() const
00291 {
00292     NEVER_REACHED;
00293     //return mNumCableElementAttributes;
00294 }
00295 
00296 
00297 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00298 void GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::Reset()
00299 {
00300     CloseFiles();
00301 
00302     OpenFiles();
00303     ReadHeaders();
00304 }
00305 
00306 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00307 std::vector<double> GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextNode()
00308 {
00309     std::vector<double> ret_coords(SPACE_DIM);
00310 
00311     std::string this_line;
00312     getline(mNodeFile, this_line);
00313 
00314     std::stringstream line(this_line);
00315 
00316     unsigned node_index;
00317     line >> node_index >> ret_coords[0] >> ret_coords[1];
00318 
00319     if(ELEMENT_DIM == 3)
00320     {
00321         line >> ret_coords[2];
00322     }
00323 
00324     return ret_coords;
00325 }
00326 
00327 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00328 std::vector<double> GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNodeAttributes()
00329 {
00330     return std::vector<double>(0);
00331 }
00332 
00333 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00334 ElementData GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextElementData()
00335 {
00336     ElementData element_data;
00337     element_data.NodeIndices.resize(mNodesPerElement);
00338     element_data.AttributeValue = 0.0; // If an attribute is not read this stays as zero, otherwise overwritten.
00339 
00340     std::string this_line;
00341     std::stringstream line(this_line);
00342 
00343     unsigned ele_index;
00344     unsigned ele_type;
00345     unsigned ele_attributes=0;
00346     bool volume_element_found = false;
00347 
00348     while(!volume_element_found)
00349     {
00350         getline(mElementFile, this_line);
00351         line.clear();
00352         line.str(this_line);
00353 
00354         line >> ele_index >> ele_type >> ele_attributes;
00355 
00356         if((ELEMENT_DIM == 2 && (ele_type == GmshTypes::TRIANGLE || ele_type == GmshTypes::QUADRATIC_TRIANGLE) ) ||
00357            (ELEMENT_DIM == 3 && (ele_type == GmshTypes::TETRAHEDRON || ele_type == GmshTypes::QUADRATIC_TETRAHEDRON)))
00358         {
00359             volume_element_found = true;
00360         }
00361     }
00362 
00363     //Gmsh can have arbitrary numbers of element attributes, but Chaste only handles one. We pick the first attribute and throw
00364     //away the remainder.
00365     if(ele_attributes > 0)
00366     {
00367         mNumElementAttributes = 1u;
00368         line >> element_data.AttributeValue;
00369     }
00370     unsigned unused_attr;
00371     for(unsigned attr_index = 0; attr_index < (ele_attributes-1); ++attr_index)
00372     {
00373         line >> unused_attr;
00374     }
00375 
00376     //Read the node indices
00377     for(unsigned node_index = 0; node_index < mNodesPerElement; ++node_index)
00378     {
00379         line >> element_data.NodeIndices[node_index];
00380 
00381         element_data.NodeIndices[node_index]--; //Gmsh *always* indexes from 1, we index from 0
00382     }
00383 
00384     return element_data;
00385 }
00386 
00387 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00388 ElementData GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextCableElementData()
00389 {
00390     NEVER_REACHED;
00391 }
00392 
00393 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00394 ElementData GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextFaceData()
00395 {
00396     ElementData face_data;
00397     face_data.NodeIndices.resize(mNodesPerBoundaryElement);
00398     face_data.AttributeValue = 0.0; // If an attribute is not read this stays as zero, otherwise overwritten.
00399 
00400     std::string this_line;
00401     std::stringstream line(this_line);
00402 
00403     unsigned face_index;
00404     unsigned face_type;
00405     unsigned face_attributes=0;
00406     bool surface_element_found = false;
00407 
00408     while(!surface_element_found)
00409     {
00410         getline(mFaceFile, this_line);
00411         line.clear();
00412         line.str(this_line);
00413 
00414         line >> face_index >> face_type >> face_attributes;
00415 
00416         if((ELEMENT_DIM == 2 && (face_type == GmshTypes::LINE || face_type == GmshTypes::QUADRATIC_LINE) ) ||
00417            (ELEMENT_DIM == 3 && (face_type == GmshTypes::TRIANGLE || face_type == GmshTypes::QUADRATIC_TRIANGLE)))
00418         {
00419             surface_element_found = true;
00420         }
00421     }
00422 
00423     //Gmsh can have arbitrary numbers of element attributes, but Chaste only handles one. We pick the first attribute and throw
00424     //away the remainder.
00425     if(face_attributes > 0)
00426     {
00427         mNumFaceAttributes = 1u;
00428         line >> face_data.AttributeValue;
00429     }
00430     unsigned unused_attr;
00431     for(unsigned attr_index = 0; attr_index < (face_attributes-1); ++attr_index)
00432     {
00433         line >> unused_attr;
00434     }
00435 
00436     //Read the node indices
00437     for(unsigned node_index = 0; node_index < mNodesPerBoundaryElement; ++node_index)
00438     {
00439         line >> face_data.NodeIndices[node_index];
00440 
00441         face_data.NodeIndices[node_index]--; //Gmsh *always* indexes from 1, we index from 0
00442     }
00443 
00444     return face_data;
00445 }
00446 
00447 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00448 std::vector<double> GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNode(unsigned index)
00449 {
00450     NEVER_REACHED;
00451 }
00452 
00453 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00454 ElementData GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetElementData(unsigned index)
00455 {
00456     NEVER_REACHED;
00457 }
00458 
00459 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00460 ElementData GmshMeshReader<ELEMENT_DIM, SPACE_DIM>::GetFaceData(unsigned index)
00461 {
00462     NEVER_REACHED;
00463 }
00464 
00466 // Explicit instantiation
00468 
00469 template class GmshMeshReader<0,1>;
00470 template class GmshMeshReader<1,1>;
00471 template class GmshMeshReader<1,2>;
00472 template class GmshMeshReader<1,3>;
00473 template class GmshMeshReader<2,2>;
00474 template class GmshMeshReader<2,3>;
00475 template class GmshMeshReader<3,3>;

Generated by  doxygen 1.6.2