SundanceTriangleMeshReader.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 
00043 #include "SundanceTriangleMeshReader.hpp"
00044 #include "SundanceOut.hpp"
00045 #include "SundanceGeomUtils.hpp"
00046 #include "PlayaExceptions.hpp"
00047 
00048 using namespace Sundance;
00049 using namespace Sundance;
00050 
00051 using namespace Teuchos;
00052 using namespace Sundance;
00053 
00054 
00055 TriangleMeshReader::TriangleMeshReader(const std::string& fname,
00056                const MeshType& meshType,
00057                int verbosity,
00058                const MPIComm& comm)
00059   : MeshReaderBase(fname, meshType, verbosity, comm),
00060     nodeFilename_(filename()),
00061     elemFilename_(filename()),
00062     parFilename_(filename()),
00063     sideFilename_(filename()),
00064     edgeFilename_(filename()),
00065     offset_(0)
00066 {
00067   
00068 
00069   if (nProc() > 1)
00070     {
00071       std::string suffix =  "." + Teuchos::toString(nProc()) 
00072         + "." + Teuchos::toString(myRank());
00073       nodeFilename_ = nodeFilename_ + suffix;
00074       parFilename_ = parFilename_ + suffix;
00075       elemFilename_ = elemFilename_ + suffix;
00076       sideFilename_ = sideFilename_ + suffix;
00077       edgeFilename_ = edgeFilename_ + suffix;
00078     }
00079   nodeFilename_ = nodeFilename_ + ".node";
00080   elemFilename_ = elemFilename_ + ".ele";
00081   parFilename_ = parFilename_ + ".par";
00082   sideFilename_ = sideFilename_ + ".side";
00083   edgeFilename_ = edgeFilename_ + ".edge";
00084   
00085   //  verbosity() = 5;
00086   SUNDANCE_OUT(this->verb() > 1,
00087                "node filename = " << nodeFilename_);
00088   
00089   SUNDANCE_OUT(this->verb() > 1,
00090                "elem filename = " << elemFilename_);
00091   
00092 }
00093 TriangleMeshReader::TriangleMeshReader(const ParameterList& params)
00094   : MeshReaderBase(params),
00095     nodeFilename_(filename()),
00096     elemFilename_(filename()),
00097     parFilename_(filename()),
00098     sideFilename_(filename()),
00099     edgeFilename_(filename()),
00100     offset_(0)
00101 {
00102   
00103 
00104   if (nProc() > 1)
00105     {
00106       std::string suffix =  "." + Teuchos::toString(nProc()) 
00107         + "." + Teuchos::toString(myRank());
00108       nodeFilename_ = nodeFilename_ + suffix;
00109       parFilename_ = parFilename_ + suffix;
00110       elemFilename_ = elemFilename_ + suffix;
00111       sideFilename_ = sideFilename_ + suffix;
00112       edgeFilename_ = edgeFilename_ + suffix;
00113     }
00114   nodeFilename_ = nodeFilename_ + ".node";
00115   elemFilename_ = elemFilename_ + ".ele";
00116   sideFilename_ = sideFilename_ + ".side";
00117   edgeFilename_ = edgeFilename_ + ".edge";
00118   parFilename_ = parFilename_ + ".par";
00119   
00120   SUNDANCE_OUT(this->verb() > 1,
00121                "node filename = " << nodeFilename_);
00122   
00123   SUNDANCE_OUT(this->verb() > 1,
00124                "elem filename = " << elemFilename_);
00125   
00126 }
00127 
00128 
00129 Mesh TriangleMeshReader::fillMesh() const 
00130 {
00131   Mesh mesh;
00132 
00133   Array<int> ptGID;
00134   Array<int> ptOwner;
00135   Array<int> cellGID;
00136   Array<int> cellOwner;
00137 
00138   readParallelInfo(ptGID, ptOwner, cellGID, cellOwner);
00139 
00140   mesh = readNodes(ptGID, ptOwner);
00141 
00142   readElems(mesh, ptGID, cellGID, cellOwner);
00143 
00144   mesh.freezeTopology();
00145 
00146   readSides(mesh);
00147 
00148   readEdges(mesh);
00149 
00150   return mesh;
00151 }
00152 
00153 void TriangleMeshReader::readParallelInfo(Array<int>& ptGID, 
00154                                           Array<int>& ptOwner,
00155                                           Array<int>& cellGID, 
00156                                           Array<int>& cellOwner) const
00157 {
00158   int nPoints;
00159   int nElems;
00160   std::string line;
00161   Array<string> tokens;
00162   try
00163     {
00164       ptGID.resize(0);
00165       ptOwner.resize(0);
00166       cellGID.resize(0);
00167       cellOwner.resize(0);
00168 
00169       /* if we're running in parallel, read the info on processor 
00170        * distribution */
00171       if (nProc() > 1)
00172         {
00173           RCP<std::ifstream> parStream 
00174             = openFile(parFilename_, "parallel info");
00175      
00176           /* read the number of processors and the processor rank in 
00177            * the file. These must be consistent with the current number of
00178            * processors and the current rank */
00179           getNextLine(*parStream, line, tokens, '#');
00180       
00181           TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 2, std::runtime_error,
00182              "TriangleMeshReader::getMesh() expects 2 entries "
00183              "on the first line of .par file. In " 
00184              << parFilename_ << " I found \n[" << line << "]\n");
00185 
00186           int np = atoi(tokens[1]);
00187           int pid = atoi(tokens[0]);
00188 
00189           /* check consistency with the current number of
00190            * processors and the current rank */
00191       
00192           TEUCHOS_TEST_FOR_EXCEPTION(np != nProc(), std::runtime_error,
00193              "TriangleMeshReader::getMesh() found "
00194              "a mismatch between the current number of processors="
00195              << nProc() << 
00196              "and the number of processors=" << np
00197              << "in the file " << parFilename_);
00198 
00199           TEUCHOS_TEST_FOR_EXCEPTION(pid != myRank(), std::runtime_error,
00200              "TriangleMeshReader::getMesh() found "
00201              "a mismatch between the current processor rank="
00202              << myRank() << "and the processor rank="
00203              << pid << " in the file " << parFilename_);
00204 
00205           /* read the number of points */
00206           getNextLine(*parStream, line, tokens, '#');
00207 
00208           TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 1, std::runtime_error,
00209              "TriangleMeshReader::getMesh() requires 1 entry "
00210              "on the second line of .par file. Found line \n[" 
00211              << line << "]\n in file " << parFilename_);
00212       
00213           nPoints = StrUtils::atoi(tokens[0]);
00214 
00215           /* read the global ID and the owner PID for each point */
00216           ptGID.resize(nPoints);
00217           ptOwner.resize(nPoints);
00218 
00219           for (int i=0; i<nPoints; i++)
00220             {
00221               getNextLine(*parStream, line, tokens, '#');
00222 
00223               TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 3, std::runtime_error,
00224            "TriangleMeshReader::getMesh() requires 3 "
00225            "entries on each line of the point section in "
00226            "the .par file. Found line \n[" << line
00227            << "]\n in file " << parFilename_);
00228 
00229               ptGID[i] = StrUtils::atoi(tokens[1]);
00230               ptOwner[i] = StrUtils::atoi(tokens[2]);
00231             }
00232 
00233 
00234           /* Read the number of elements */
00235 
00236           getNextLine(*parStream, line, tokens, '#');
00237 
00238           TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 1, std::runtime_error,
00239              "TriangleMeshReader::getMesh() requires 1 entry "
00240              "on the cell count line of .par file. Found line \n[" 
00241              << line << "]\n in file " << parFilename_);
00242 
00243           nElems = StrUtils::atoi(tokens[0]);
00244 
00245           SUNDANCE_OUT(this->verb() > 1,
00246                        "read nElems = " << nElems);
00247 
00248 
00249           /* read the global ID and the owner PID for each element */
00250 
00251           cellGID.resize(nElems);
00252           cellOwner.resize(nElems);
00253           for (int i=0; i<nElems; i++)
00254             {
00255               getNextLine(*parStream, line, tokens, '#');
00256 
00257               TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 3, std::runtime_error,
00258            "TriangleMeshReader::getMesh() requires 3 "
00259            "entries on each line of the element section in "
00260            "the .par file. Found line \n[" << line
00261            << "]\n in file " << parFilename_);
00262 
00263               cellGID[i] = StrUtils::atoi(tokens[1]);
00264               cellOwner[i] = StrUtils::atoi(tokens[2]);
00265             }
00266         }
00267 
00268       nPoints = ptGID.length();
00269       nElems = cellGID.length();
00270     }
00271   catch(std::exception& e)
00272     {
00273       SUNDANCE_TRACE(e);
00274     }
00275 }
00276 
00277 Mesh TriangleMeshReader::readNodes(Array<int>& ptGID,
00278                                    Array<int>& ptOwner) const 
00279 {
00280   Mesh mesh;
00281   std::string line;
00282   Array<string> tokens;
00283   int nPoints = -1;
00284 
00285   /* Open the node file so we can read in the nodes */
00286   
00287   RCP<std::ifstream> nodeStream = openFile(nodeFilename_, "node info");
00288   
00289   /* read the header line */
00290   getNextLine(*nodeStream, line, tokens, '#');
00291   TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 4, std::runtime_error,
00292            "TriangleMeshReader::getMesh() requires 4 "
00293            "entries on the header line in "
00294            "the .node file. Found line \n[" << line
00295            << "]\n in file " << nodeFilename_);
00296   string headerLine = line;
00297   SUNDANCE_OUT(this->verb() > 2,
00298                "read point header " << line);
00299   
00300   
00301   if (nProc()==1)
00302     {
00303       nPoints = atoi(tokens[0]);
00304       ptGID.resize(nPoints);
00305       ptOwner.resize(nPoints);
00306       for (int i=0; i<nPoints; i++)
00307         {
00308           ptGID[i] = i;
00309           ptOwner[i] = 0;
00310         }
00311     }
00312   else
00313     {
00314       /* If we're running in parallel, we'd better have consistent numbers
00315        * of points in the .node and .par file. */
00316       nPoints = ptGID.length();
00317       TEUCHOS_TEST_FOR_EXCEPTION(atoi(tokens[0]) != nPoints, std::runtime_error,
00318          "TriangleMeshReader::getMesh() found inconsistent "
00319          "numbers of points in .node file and par file. Node "
00320          "file " << nodeFilename_ << " had nPoints=" 
00321          << atoi(tokens[0]) << " but .par file " 
00322          << parFilename_ << " had nPoints=" << nPoints);
00323     }
00324 
00325   SUNDANCE_OUT(this->verb() > 3,
00326                "expecting to read " << nPoints << " points");
00327   
00328   int dimension = atoi(tokens[1]);
00329   int nAttributes = atoi(tokens[2]);
00330   int nBdryMarkers = atoi(tokens[3]);
00331 
00332   /* now that we know the dimension, we can build the mesh object */
00333   mesh = createMesh(dimension);
00334 
00335   /* size point-related arrays */
00336   Array<int> ptIndices(nPoints);
00337   Array<bool> usedPoint(nPoints);
00338   nodeAttributes()->resize(nAttributes);
00339   for (int i=0; i<nAttributes; i++)
00340     {
00341       (*nodeAttributes())[i].resize(nPoints);
00342     }
00343   offset_=-1;
00344   bool first = true;
00345 
00346   /* read all the points */
00347   for (int count=0; count<nPoints; count++)
00348     {
00349       getNextLine(*nodeStream, line, tokens, '#');
00350       
00351       TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() 
00352          != (1 + dimension + nAttributes + nBdryMarkers),
00353          std::runtime_error,
00354          "TriangleMeshReader::getMesh() found bad node input "
00355          "line. Expected " 
00356          << (1 + dimension + nAttributes + nBdryMarkers)
00357          << " entries but found line \n[" << 
00358          line << "]\n in file " << nodeFilename_);
00359       /* Triangle files can use either 0-offset or 1-offset numbering. We'll
00360        * inspect the first node line to decide which numbering to use. */
00361       if (first)
00362         {
00363           offset_ = atoi(tokens[0]);
00364           TEUCHOS_TEST_FOR_EXCEPTION(offset_ < 0 || offset_ > 1, std::runtime_error,
00365              "TriangleMeshReader::getMesh() expected "
00366              "either 0-offset or 1-offset numbering. Found an "
00367              "initial offset of " << offset_ << " in line \n["
00368              << line << "]\n of file " << nodeFilename_);
00369           first = false;
00370         }
00371       
00372       /* now we can add the point to the mesh */
00373       double x = atof(tokens[1]); 
00374       double y = atof(tokens[2]);
00375       double z = 0.0;
00376       Point pt;
00377       int ptLabel = 0;
00378 
00379       if (dimension==3)
00380   {
00381     z = atof(tokens[3]);
00382           pt = Point(x,y,z);
00383   }
00384       else 
00385   {
00386           pt = Point(x,y);
00387   }
00388 
00389       ptIndices[count] 
00390         = mesh.addVertex(ptGID[count], pt, ptOwner[count], ptLabel);
00391 
00392       for (int i=0; i<nAttributes; i++)
00393   {
00394     (*nodeAttributes())[i][count] = atof(tokens[dimension+1+i]);
00395   }
00396     }
00397   return mesh;
00398 }
00399 
00400 void TriangleMeshReader::readElems(Mesh& mesh,
00401                                    const Array<int>& ptGID,
00402                                    Array<int>& elemGID,
00403                                    Array<int>& elemOwner) const 
00404 {
00405   try
00406     {
00407       std::string line;  
00408       Array<string> tokens;
00409       /* Open the element file */
00410   
00411       RCP<std::ifstream> elemStream = openFile(elemFilename_, "element info");
00412 
00413       getNextLine(*elemStream, line, tokens, '#');
00414 
00415       TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 3, std::runtime_error,
00416          "TriangleMeshReader::getMesh() requires 3 "
00417          "entries on the header line in "
00418          "the .ele file. Found line \n[" << line
00419          << "]\n in file " << elemFilename_);
00420                    
00421       int nElems = -1;
00422 
00423       if (nProc()==1)
00424         {
00425           nElems = atoi(tokens[0]);
00426           elemGID.resize(nElems);
00427           elemOwner.resize(nElems);
00428           for (int i=0; i<nElems; i++)
00429             {
00430               elemGID[i] = i;
00431               elemOwner[i] = 0;
00432             }
00433         }
00434       else
00435         {
00436           /* If we're running in parallel, we'd better have consistent numbers
00437            * of points in the .node and .par file. */
00438           nElems = elemGID.length();
00439           TEUCHOS_TEST_FOR_EXCEPTION(atoi(tokens[0]) != nElems, std::runtime_error,
00440              "TriangleMeshReader::readElems() found inconsistent "
00441              "numbers of elements in .ele file and par file. Elem "
00442              "file " << elemFilename_ << " had nElems=" 
00443              << atoi(tokens[0]) << " but .par file " 
00444              << parFilename_ << " had nElems=" << nElems);
00445         }
00446 
00447       int ptsPerElem = atoi(tokens[1]);
00448 
00449       TEUCHOS_TEST_FOR_EXCEPTION(ptsPerElem != mesh.spatialDim()+1, std::runtime_error,
00450          "TriangleMeshReader::readElems() found inconsistency "
00451          "between number of points per element=" << ptsPerElem 
00452          << " and dimension=" << mesh.spatialDim() << ". Number of pts "
00453          "per element should be dimension + 1");
00454 
00455       int nAttributes = atoi(tokens[2]);
00456       elemAttributes()->resize(nElems);
00457 
00458       int dim = mesh.spatialDim();
00459       Array<int> nodes(dim+1);
00460 
00461       for (int count=0; count<nElems; count++)
00462         {
00463           getNextLine(*elemStream, line, tokens, '#');
00464       
00465           TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() 
00466              != (1 + ptsPerElem + nAttributes),
00467              std::runtime_error,
00468              "TriangleMeshReader::readElems() found bad elem "
00469              "input line. Expected " 
00470              << (1 + ptsPerElem + nAttributes)
00471              << " entries but found line \n[" << 
00472              line << "]\n in file " << elemFilename_);
00473 
00474           for (int d=0; d<=dim; d++)
00475             {
00476               nodes[d] = ptGID[atoi(tokens[d+1])-offset_];
00477             }
00478 
00479           int elemLabel = 0;
00480           try
00481             {
00482               mesh.addElement(elemGID[count], nodes, elemOwner[count], elemLabel);
00483             }
00484           catch(std::exception& ex1)
00485             {
00486               SUNDANCE_TRACE(ex1);
00487             }
00488       
00489           (*elemAttributes())[count].resize(nAttributes);
00490           for (int i=0; i<nAttributes; i++)
00491             {
00492               (*elemAttributes())[count][i] = atof(tokens[1+ptsPerElem+i]);
00493             }
00494         }
00495     }
00496   catch(std::exception& ex)
00497     {
00498       SUNDANCE_TRACE(ex);
00499     }
00500 }
00501 
00502 
00503 void TriangleMeshReader::readSides(Mesh& mesh) const 
00504 {
00505   try
00506     {
00507       std::string line;  
00508       Array<string> tokens;
00509       /* Open the side file */
00510       RCP<std::ifstream> sideStream;
00511       bool fileOK = false;
00512 
00513       try
00514         {
00515           sideStream = openFile(sideFilename_, "side info");
00516           fileOK = true;
00517         }
00518       catch(std::exception& e) {;}
00519 
00520       /* Not all meshes will have sides files.
00521        * If the sides file doesn't exist, return. */
00522       if (!fileOK)
00523         {
00524           SUNDANCE_VERB_LOW("side file [" << sideFilename_ << "] not found");
00525           return;
00526         }
00527 
00528       getNextLine(*sideStream, line, tokens, '#');
00529 
00530       TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 1, std::runtime_error,
00531          "TriangleMeshReader::readSides() requires 1 "
00532          "entry on the header line in "
00533          "the .side file. Found line \n[" << line
00534          << "]\n in file " << sideFilename_);
00535 
00536       int nSides = atoi(tokens[0]);
00537 
00538       int elemDim = mesh.spatialDim();
00539       int sideDim = elemDim - 1;
00540 
00541       for (int i=0; i<nSides; i++)
00542         {
00543           getNextLine(*sideStream, line, tokens, '#');
00544       
00545           TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 4,
00546              std::runtime_error,
00547              "TriangleMeshReader::readSides() found bad side "
00548              "input line. Expected 4 entries but found line \n[" 
00549              << line << "]\n in file " << sideFilename_);
00550 
00551           int elemGID = atoi(tokens[1]);
00552           int elemFacet = atoi(tokens[2]);
00553           TEUCHOS_TEST_FOR_EXCEPTION(!mesh.hasGID(elemDim, elemGID), std::runtime_error,
00554              "element GID " << elemGID << " not found");
00555           int elemLID = mesh.mapGIDToLID(elemDim, elemGID);
00556           int o=0; // dummy orientation variable; not needed here
00557           int sideLID = mesh.facetLID(elemDim, elemLID, sideDim, 
00558               elemFacet, o);
00559           
00560           int sideLabel = atoi(tokens[3]);
00561 
00562           mesh.setLabel(sideDim, sideLID, sideLabel);
00563         }
00564     }
00565   catch(std::exception& ex)
00566     {
00567       SUNDANCE_TRACE(ex);
00568     }
00569 }
00570 
00571 
00572 
00573 void TriangleMeshReader::readEdges(Mesh& mesh) const 
00574 {
00575   try
00576     {
00577       std::string line;  
00578       Array<string> tokens;
00579       /* Open the edge file */
00580       RCP<std::ifstream> edgeStream;
00581       bool fileOK = false;
00582 
00583       try
00584         {
00585           edgeStream = openFile(edgeFilename_, "edge info");
00586           fileOK = true;
00587         }
00588       catch(std::exception& e) {;}
00589 
00590       /* Not all meshes will have edges files.
00591        * If the edges file doesn't exist, return. */
00592       if (!fileOK)
00593         {
00594           SUNDANCE_VERB_LOW("edge file [" << edgeFilename_ << "] not found");
00595           return;
00596         }
00597 
00598       getNextLine(*edgeStream, line, tokens, '#');
00599 
00600       TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 2, std::runtime_error,
00601          "TriangleMeshReader::readEdges() requires 2 "
00602          "entries on the header line in "
00603          "the .edge file. Found line \n[" << line
00604          << "]\n in file " << edgeFilename_);
00605 
00606       int nEdges = atoi(tokens[0]);
00607 
00608       for (int i=0; i<nEdges; i++)
00609         {
00610           getNextLine(*edgeStream, line, tokens, '#');
00611       
00612           TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 4,
00613              std::runtime_error,
00614              "TriangleMeshReader::readEdges() found bad edge "
00615              "input line. Expected 4 entries but found line \n[" 
00616              << line << "]\n in file " << edgeFilename_);
00617 
00618           int v1 = atoi(tokens[1])-offset_;
00619           int v2 = atoi(tokens[2])-offset_;
00620           int label = atoi(tokens[3]);
00621     if (label==0) continue;
00622 
00623     int edgeLID = lookupEdgeLIDFromVerts(mesh, v1, v2);
00624 
00625           TEUCHOS_TEST_FOR_EXCEPTION(edgeLID < 0, std::runtime_error,
00626              "edge(" << v1 << ", " << v2 <<") not found");
00627           mesh.setLabel(1, edgeLID, label);
00628         }
00629     }
00630   catch(std::exception& ex)
00631     {
00632       SUNDANCE_TRACE(ex);
00633     }
00634 }

Site Contact