SundanceTriangleMeshReader.cpp
Go to the documentation of this file.
00001 #include "SundanceTriangleMeshReader.hpp"
00002 #include "SundanceOut.hpp"
00003 #include "SundanceExceptions.hpp"
00004 
00005 using namespace Sundance;
00006 using namespace Sundance;
00007 
00008 using namespace Teuchos;
00009 using namespace Sundance;
00010 
00011 
00012 TriangleMeshReader::TriangleMeshReader(const std::string& fname,
00013                                        const MeshType& meshType,
00014                                        const MPIComm& comm)
00015   : MeshReaderBase(fname, meshType, comm),
00016     nodeFilename_(filename()),
00017     elemFilename_(filename()),
00018     parFilename_(filename()),
00019     sideFilename_(filename()),
00020     offset_(0)
00021 {
00022   
00023 
00024   if (nProc() > 1)
00025     {
00026       std::string suffix =  "." + Teuchos::toString(nProc()) 
00027         + "." + Teuchos::toString(myRank());
00028       nodeFilename_ = nodeFilename_ + suffix;
00029       parFilename_ = parFilename_ + suffix;
00030       elemFilename_ = elemFilename_ + suffix;
00031       sideFilename_ = sideFilename_ + suffix;
00032     }
00033   nodeFilename_ = nodeFilename_ + ".node";
00034   elemFilename_ = elemFilename_ + ".ele";
00035   parFilename_ = parFilename_ + ".par";
00036   sideFilename_ = sideFilename_ + ".side";
00037   
00038   setVerbosity (classVerbosity() );
00039   //  verbosity() = 5;
00040   SUNDANCE_OUT(this->verb() > 1,
00041                "node filename = " << nodeFilename_);
00042   
00043   SUNDANCE_OUT(this->verb() > 1,
00044                "elem filename = " << elemFilename_);
00045   
00046 }
00047 TriangleMeshReader::TriangleMeshReader(const ParameterList& params)
00048   : MeshReaderBase(params),
00049     nodeFilename_(filename()),
00050     elemFilename_(filename()),
00051     parFilename_(filename())
00052 {
00053   
00054 
00055   if (nProc() > 1)
00056     {
00057       std::string suffix =  "." + Teuchos::toString(nProc()) 
00058         + "." + Teuchos::toString(myRank());
00059       nodeFilename_ = nodeFilename_ + suffix;
00060       parFilename_ = parFilename_ + suffix;
00061       elemFilename_ = elemFilename_ + suffix;
00062     }
00063   nodeFilename_ = nodeFilename_ + ".node";
00064   elemFilename_ = elemFilename_ + ".ele";
00065   parFilename_ = parFilename_ + ".par";
00066   
00067   setVerbosity( classVerbosity() );
00068   SUNDANCE_OUT(this->verb() > 1,
00069                "node filename = " << nodeFilename_);
00070   
00071   SUNDANCE_OUT(this->verb() > 1,
00072                "elem filename = " << elemFilename_);
00073   
00074 }
00075 
00076 
00077 Mesh TriangleMeshReader::fillMesh() const 
00078 {
00079   Mesh mesh;
00080 
00081   Array<int> ptGID;
00082   Array<int> ptOwner;
00083   Array<int> cellGID;
00084   Array<int> cellOwner;
00085 
00086   readParallelInfo(ptGID, ptOwner, cellGID, cellOwner);
00087 
00088   mesh = readNodes(ptGID, ptOwner);
00089 
00090   readElems(mesh, ptGID, cellGID, cellOwner);
00091 
00092   readSides(mesh);
00093 
00094   //  mesh.assignGlobalIndices();
00095 
00096   return mesh;
00097 }
00098 
00099 void TriangleMeshReader::readParallelInfo(Array<int>& ptGID, 
00100                                           Array<int>& ptOwner,
00101                                           Array<int>& cellGID, 
00102                                           Array<int>& cellOwner) const
00103 {
00104   int nPoints;
00105   int nElems;
00106   std::string line;
00107   Array<string> tokens;
00108   try
00109     {
00110       ptGID.resize(0);
00111       ptOwner.resize(0);
00112       cellGID.resize(0);
00113       cellOwner.resize(0);
00114 
00115       /* if we're running in parallel, read the info on processor 
00116        * distribution */
00117       if (nProc() > 1)
00118         {
00119           RCP<std::ifstream> parStream 
00120             = openFile(parFilename_, "parallel info");
00121      
00122           /* read the number of processors and the processor rank in 
00123            * the file. These must be consistent with the current number of
00124            * processors and the current rank */
00125           getNextLine(*parStream, line, tokens, '#');
00126       
00127           TEST_FOR_EXCEPTION(tokens.length() != 2, RuntimeError,
00128                              "TriangleMeshReader::getMesh() expects 2 entries "
00129                              "on the first line of .par file. In " 
00130                              << parFilename_ << " I found \n[" << line << "]\n");
00131 
00132           int np = atoi(tokens[1]);
00133           int pid = atoi(tokens[0]);
00134 
00135           /* check consistency with the current number of
00136            * processors and the current rank */
00137       
00138           TEST_FOR_EXCEPTION(np != nProc(), RuntimeError,
00139                              "TriangleMeshReader::getMesh() found "
00140                              "a mismatch between the current number of processors="
00141                              << nProc() << 
00142                              "and the number of processors=" << np
00143                              << "in the file " << parFilename_);
00144 
00145           TEST_FOR_EXCEPTION(pid != myRank(), RuntimeError,
00146                              "TriangleMeshReader::getMesh() found "
00147                              "a mismatch between the current processor rank="
00148                              << myRank() << "and the processor rank="
00149                              << pid << " in the file " << parFilename_);
00150 
00151           /* read the number of points */
00152           getNextLine(*parStream, line, tokens, '#');
00153 
00154           TEST_FOR_EXCEPTION(tokens.length() != 1, RuntimeError,
00155                              "TriangleMeshReader::getMesh() requires 1 entry "
00156                              "on the second line of .par file. Found line \n[" 
00157                              << line << "]\n in file " << parFilename_);
00158       
00159           nPoints = StrUtils::atoi(tokens[0]);
00160 
00161           /* read the global ID and the owner PID for each point */
00162           ptGID.resize(nPoints);
00163           ptOwner.resize(nPoints);
00164 
00165           for (int i=0; i<nPoints; i++)
00166             {
00167               getNextLine(*parStream, line, tokens, '#');
00168 
00169               TEST_FOR_EXCEPTION(tokens.length() != 3, RuntimeError,
00170                                  "TriangleMeshReader::getMesh() requires 3 "
00171                                  "entries on each line of the point section in "
00172                                  "the .par file. Found line \n[" << line
00173                                  << "]\n in file " << parFilename_);
00174 
00175               ptGID[i] = StrUtils::atoi(tokens[1]);
00176               ptOwner[i] = StrUtils::atoi(tokens[2]);
00177             }
00178 
00179 
00180           /* Read the number of elements */
00181 
00182           getNextLine(*parStream, line, tokens, '#');
00183 
00184           TEST_FOR_EXCEPTION(tokens.length() != 1, RuntimeError,
00185                              "TriangleMeshReader::getMesh() requires 1 entry "
00186                              "on the cell count line of .par file. Found line \n[" 
00187                              << line << "]\n in file " << parFilename_);
00188 
00189           nElems = StrUtils::atoi(tokens[0]);
00190 
00191           SUNDANCE_OUT(this->verb() > 1,
00192                        "read nElems = " << nElems);
00193 
00194 
00195           /* read the global ID and the owner PID for each element */
00196 
00197           cellGID.resize(nElems);
00198           cellOwner.resize(nElems);
00199           for (int i=0; i<nElems; i++)
00200             {
00201               getNextLine(*parStream, line, tokens, '#');
00202 
00203               TEST_FOR_EXCEPTION(tokens.length() != 3, RuntimeError,
00204                                  "TriangleMeshReader::getMesh() requires 3 "
00205                                  "entries on each line of the element section in "
00206                                  "the .par file. Found line \n[" << line
00207                                  << "]\n in file " << parFilename_);
00208 
00209               cellGID[i] = StrUtils::atoi(tokens[1]);
00210               cellOwner[i] = StrUtils::atoi(tokens[2]);
00211             }
00212         }
00213 
00214       nPoints = ptGID.length();
00215       nElems = cellGID.length();
00216     }
00217   catch(std::exception& e)
00218     {
00219       SUNDANCE_TRACE(e);
00220     }
00221 }
00222 
00223 Mesh TriangleMeshReader::readNodes(Array<int>& ptGID,
00224                                    Array<int>& ptOwner) const 
00225 {
00226   Mesh mesh;
00227   std::string line;
00228   Array<string> tokens;
00229   int nPoints = -1;
00230 
00231   /* Open the node file so we can read in the nodes */
00232   
00233   RCP<std::ifstream> nodeStream = openFile(nodeFilename_, "node info");
00234   
00235   /* read the header line */
00236   getNextLine(*nodeStream, line, tokens, '#');
00237   TEST_FOR_EXCEPTION(tokens.length() != 4, RuntimeError,
00238                      "TriangleMeshReader::getMesh() requires 4 "
00239                      "entries on the header line in "
00240                      "the .node file. Found line \n[" << line
00241                      << "]\n in file " << nodeFilename_);
00242   string headerLine = line;
00243   SUNDANCE_OUT(this->verb() > 2,
00244                "read point header " << line);
00245   
00246   
00247   if (nProc()==1)
00248     {
00249       nPoints = atoi(tokens[0]);
00250       ptGID.resize(nPoints);
00251       ptOwner.resize(nPoints);
00252       for (int i=0; i<nPoints; i++)
00253         {
00254           ptGID[i] = i;
00255           ptOwner[i] = 0;
00256         }
00257     }
00258   else
00259     {
00260       /* If we're running in parallel, we'd better have consistent numbers
00261        * of points in the .node and .par file. */
00262       nPoints = ptGID.length();
00263       TEST_FOR_EXCEPTION(atoi(tokens[0]) != nPoints, RuntimeError,
00264                          "TriangleMeshReader::getMesh() found inconsistent "
00265                          "numbers of points in .node file and par file. Node "
00266                          "file " << nodeFilename_ << " had nPoints=" 
00267                          << atoi(tokens[0]) << " but .par file " 
00268                          << parFilename_ << " had nPoints=" << nPoints);
00269     }
00270 
00271   SUNDANCE_OUT(this->verb() > 3,
00272                "expecting to read " << nPoints << " points");
00273   
00274   int dimension = atoi(tokens[1]);
00275   int nAttributes = atoi(tokens[2]);
00276   int nBdryMarkers = atoi(tokens[3]);
00277 
00278   /* now that we know the dimension, we can build the mesh object */
00279   mesh = createMesh(dimension);
00280 
00281   /* size point-related arrays */
00282   Array<int> ptIndices(nPoints);
00283   Array<bool> usedPoint(nPoints);
00284   nodeAttributes()->resize(nAttributes);
00285   for (int i=0; i<nAttributes; i++)
00286   {
00287     (*nodeAttributes())[i].resize(nPoints);
00288   }
00289   offset_=-1;
00290   bool first = true;
00291 
00292   /* read all the points */
00293   for (int count=0; count<nPoints; count++)
00294     {
00295       getNextLine(*nodeStream, line, tokens, '#');
00296       
00297       TEST_FOR_EXCEPTION(tokens.length() 
00298                          != (1 + dimension + nAttributes + nBdryMarkers),
00299                          RuntimeError,
00300                          "TriangleMeshReader::getMesh() found bad node input "
00301                          "line. Expected " 
00302                          << (1 + dimension + nAttributes + nBdryMarkers)
00303                          << " entries but found line \n[" << 
00304                          line << "]\n in file " << nodeFilename_);
00305       /* Triangle files can use either 0-offset or 1-offset numbering. We'll
00306        * inspect the first node line to decide which numbering to use. */
00307       if (first)
00308         {
00309           offset_ = atoi(tokens[0]);
00310           TEST_FOR_EXCEPTION(offset_ < 0 || offset_ > 1, RuntimeError,
00311                              "TriangleMeshReader::getMesh() expected "
00312                              "either 0-offset or 1-offset numbering. Found an "
00313                              "initial offset of " << offset_ << " in line \n["
00314                              << line << "]\n of file " << nodeFilename_);
00315           first = false;
00316         }
00317       
00318       /* now we can add the point to the mesh */
00319       double x = atof(tokens[1]); 
00320       double y = atof(tokens[2]);
00321       double z = 0.0;
00322       Point pt;
00323       int ptLabel = 0;
00324 
00325       if (dimension==3)
00326         {
00327           z = atof(tokens[3]);
00328           pt = Point(x,y,z);
00329         }
00330       else 
00331         {
00332           pt = Point(x,y);
00333         }
00334 
00335       ptIndices[count] 
00336         = mesh.addVertex(ptGID[count], pt, ptOwner[count], ptLabel);
00337 
00338       for (int i=0; i<nAttributes; i++)
00339         {
00340           (*nodeAttributes())[i][count] = atof(tokens[dimension+1+i]);
00341         }
00342     }
00343   return mesh;
00344 }
00345 
00346 void TriangleMeshReader::readElems(Mesh& mesh,
00347                                    const Array<int>& ptGID,
00348                                    Array<int>& elemGID,
00349                                    Array<int>& elemOwner) const 
00350 {
00351   try
00352     {
00353       std::string line;  
00354       Array<string> tokens;
00355       /* Open the element file */
00356   
00357       RCP<std::ifstream> elemStream = openFile(elemFilename_, "element info");
00358 
00359       getNextLine(*elemStream, line, tokens, '#');
00360 
00361       TEST_FOR_EXCEPTION(tokens.length() != 3, RuntimeError,
00362                          "TriangleMeshReader::getMesh() requires 3 "
00363                          "entries on the header line in "
00364                          "the .ele file. Found line \n[" << line
00365                          << "]\n in file " << elemFilename_);
00366                    
00367       int nElems = -1;
00368 
00369       if (nProc()==1)
00370         {
00371           nElems = atoi(tokens[0]);
00372           elemGID.resize(nElems);
00373           elemOwner.resize(nElems);
00374           for (int i=0; i<nElems; i++)
00375             {
00376               elemGID[i] = i;
00377               elemOwner[i] = 0;
00378             }
00379         }
00380       else
00381         {
00382           /* If we're running in parallel, we'd better have consistent numbers
00383            * of points in the .node and .par file. */
00384           nElems = elemGID.length();
00385           TEST_FOR_EXCEPTION(atoi(tokens[0]) != nElems, RuntimeError,
00386                              "TriangleMeshReader::readElems() found inconsistent "
00387                              "numbers of elements in .ele file and par file. Elem "
00388                              "file " << elemFilename_ << " had nElems=" 
00389                              << atoi(tokens[0]) << " but .par file " 
00390                              << parFilename_ << " had nElems=" << nElems);
00391         }
00392 
00393       int ptsPerElem = atoi(tokens[1]);
00394 
00395       TEST_FOR_EXCEPTION(ptsPerElem != mesh.spatialDim()+1, RuntimeError,
00396                          "TriangleMeshReader::readElems() found inconsistency "
00397                          "between number of points per element=" << ptsPerElem 
00398                          << " and dimension=" << mesh.spatialDim() << ". Number of pts "
00399                          "per element should be dimension + 1");
00400 
00401       int nAttributes = atoi(tokens[2]);
00402       elemAttributes()->resize(nElems);
00403 
00404       int dim = mesh.spatialDim();
00405       Array<int> nodes(dim+1);
00406 
00407       for (int count=0; count<nElems; count++)
00408         {
00409           getNextLine(*elemStream, line, tokens, '#');
00410       
00411           TEST_FOR_EXCEPTION(tokens.length() 
00412                              != (1 + ptsPerElem + nAttributes),
00413                              RuntimeError,
00414                              "TriangleMeshReader::readElems() found bad elem "
00415                              "input line. Expected " 
00416                              << (1 + ptsPerElem + nAttributes)
00417                              << " entries but found line \n[" << 
00418                              line << "]\n in file " << elemFilename_);
00419 
00420           for (int d=0; d<=dim; d++)
00421             {
00422               nodes[d] = ptGID[atoi(tokens[d+1])-offset_];
00423             }
00424 
00425           int elemLabel = 0;
00426           try
00427             {
00428               mesh.addElement(elemGID[count], nodes, elemOwner[count], elemLabel);
00429             }
00430           catch(std::exception& ex1)
00431             {
00432               SUNDANCE_TRACE(ex1);
00433             }
00434       
00435           (*elemAttributes())[count].resize(nAttributes);
00436           for (int i=0; i<nAttributes; i++)
00437             {
00438               (*elemAttributes())[count][i] = atof(tokens[1+ptsPerElem+i]);
00439             }
00440         }
00441     }
00442   catch(std::exception& ex)
00443     {
00444       SUNDANCE_TRACE(ex);
00445     }
00446 }
00447 
00448 
00449 void TriangleMeshReader::readSides(Mesh& mesh) const 
00450 {
00451   try
00452     {
00453       std::string line;  
00454       Array<string> tokens;
00455       /* Open the side file */
00456       RCP<std::ifstream> sideStream;
00457       bool fileOK = false;
00458 
00459       try
00460         {
00461           sideStream = openFile(sideFilename_, "side info");
00462           fileOK = true;
00463         }
00464       catch(std::exception& e) {;}
00465 
00466       /* Not all meshes will have sides files.
00467        * If the sides file doesn't exist, return. */
00468       if (!fileOK)
00469         {
00470           SUNDANCE_VERB_LOW("side file [" << sideFilename_ << "] not found");
00471           return;
00472         }
00473 
00474       getNextLine(*sideStream, line, tokens, '#');
00475 
00476       TEST_FOR_EXCEPTION(tokens.length() != 1, RuntimeError,
00477                          "TriangleMeshReader::readSides() requires 1 "
00478                          "entry on the header line in "
00479                          "the .side file. Found line \n[" << line
00480                          << "]\n in file " << sideFilename_);
00481 
00482       int nSides = atoi(tokens[0]);
00483 
00484       int elemDim = mesh.spatialDim();
00485       int sideDim = elemDim - 1;
00486 
00487       for (int i=0; i<nSides; i++)
00488         {
00489           getNextLine(*sideStream, line, tokens, '#');
00490       
00491           TEST_FOR_EXCEPTION(tokens.length() != 4,
00492                              RuntimeError,
00493                              "TriangleMeshReader::readSides() found bad side "
00494                              "input line. Expected 4 entries but found line \n[" 
00495                              << line << "]\n in file " << sideFilename_);
00496 
00497           int elemGID = atoi(tokens[1]);
00498           int elemFacet = atoi(tokens[2]);
00499           TEST_FOR_EXCEPTION(!mesh.hasGID(elemDim, elemGID), RuntimeError,
00500                              "element GID " << elemGID << " not found");
00501           int elemLID = mesh.mapGIDToLID(elemDim, elemGID);
00502           int o=0; // dummy orientation variable; not needed here
00503           int sideLID = mesh.facetLID(elemDim, elemLID, sideDim, elemFacet, o);
00504           
00505           int sideLabel = atoi(tokens[3]);
00506 
00507           mesh.setLabel(sideDim, sideLID, sideLabel);
00508         }
00509     }
00510   catch(std::exception& ex)
00511     {
00512       SUNDANCE_TRACE(ex);
00513     }
00514 }

Site Contact