SundanceExodusMeshReader.cpp
Go to the documentation of this file.
00001 #include "SundanceExodusMeshReader.hpp"
00002 #include "SundanceOut.hpp"
00003 #include "SundanceExceptions.hpp"
00004 #include "SundancePathUtils.hpp"
00005 
00006 #ifdef HAVE_SUNDANCE_EXODUS
00007 #include "exodusII.h"
00008 #endif 
00009 
00010 using namespace Sundance;
00011 using namespace Sundance;
00012 
00013 using namespace Teuchos;
00014 using namespace Sundance;
00015 using namespace std;
00016 
00017 ExodusMeshReader::ExodusMeshReader(const std::string& fname,
00018   const MeshType& meshType,
00019   const MPIComm& comm)
00020   : MeshReaderBase(fname, meshType, comm), 
00021     exoFilename_(fname),
00022     parFilename_(fname)
00023 {
00024   if (nProc() > 1)
00025     {
00026       std::string suffix =  "-" + Teuchos::toString(nProc()) 
00027         + "-" + Teuchos::toString(myRank());
00028       exoFilename_ = exoFilename_ + suffix;
00029       parFilename_ = parFilename_ + suffix;
00030     }
00031   exoFilename_ = exoFilename_ + ".exo";
00032   parFilename_ = parFilename_ + ".pxo";
00033   
00034   setVerbosity( classVerbosity() );
00035 
00036   SUNDANCE_OUT(this->verb() > 1,
00037                "exodus filename = " << exoFilename_);
00038   
00039   if (nProc() > 1)
00040   {
00041     SUNDANCE_OUT(this->verb() > 1,
00042       "par filename = " << parFilename_);
00043   }
00044 }
00045 
00046 
00047 
00048 
00049 
00050 Mesh ExodusMeshReader::fillMesh() const 
00051 {
00052   Mesh mesh;
00053 #ifndef HAVE_SUNDANCE_EXODUS
00054   TEST_FOR_EXCEPTION(true, RuntimeError, 
00055     "ExodusMeshReader called for a build without ExodusII");
00056 #else
00057 
00058   int CPU_word_size = 8;
00059   int IO_word_size = 0;
00060   float version;
00061 
00062   Array<int> ptGID;
00063   Array<int> ptOwner;
00064   Array<int> elemGID;
00065   Array<int> elemOwner;
00066 
00067   readParallelInfo(ptGID, ptOwner, elemGID, elemOwner);
00068 
00069   if (verb() > 2) ex_opts(EX_DEBUG | EX_VERBOSE);
00070 
00071   std::string resolvedName = searchForFile(exoFilename_);
00072   int exoID = ex_open(resolvedName.c_str(), EX_READ, 
00073     &CPU_word_size, &IO_word_size, &version);
00074 
00075   TEST_FOR_EXCEPTION(exoID < 0, RuntimeError, "ExodusMeshReader unable to "
00076     "open file: " << exoFilename_);
00077 
00078   TEST_FOR_EXCEPT(IO_word_size != 8 || CPU_word_size != 8);
00079 
00080   char title[MAX_LINE_LENGTH+1];
00081 
00082   int dim = 0;
00083   int numNodes = 0;
00084   int numElems = 0;
00085   int numElemBlocks = 0;
00086   int numNodeSets = 0;
00087   int numSideSets = 0;
00088 
00089   int ierr = ex_get_init(exoID, title, &dim, &numNodes, &numElems,
00090     &numElemBlocks, &numNodeSets, &numSideSets);
00091 
00092   TEST_FOR_EXCEPTION(numNodes <= 0, RuntimeError, "invalid numNodes=" 
00093     << numNodes);
00094   TEST_FOR_EXCEPTION(numElems <= 0, RuntimeError, "invalid numElems=" 
00095     << numElems);
00096 
00097   /* */
00098   if (nProc()==1)
00099   {
00100     ptGID.resize(numNodes);
00101     ptOwner.resize(numNodes);
00102     for (int i=0; i<numNodes; i++)
00103     {
00104       ptGID[i] = i;
00105       ptOwner[i] = 0;
00106     }
00107   }
00108   else
00109   {
00110     /* If we're running in parallel, we'd better have consistent numbers
00111      * of points in the .exo and .pex files. */
00112     TEST_FOR_EXCEPTION((int)ptGID.size() != numNodes, RuntimeError,
00113       "ExodusMeshReader::getMesh() found inconsistent "
00114       "numbers of points in .exo file and .pex files. Exo "
00115       "file " << exoFilename_ << " had nPoints=" 
00116       << numNodes << " but .pex file " 
00117       << parFilename_ << " had nPoints=" << ptGID.size());
00118   }
00119 
00120   /* now we can build the mesh */
00121   mesh = createMesh(dim);
00122 
00123 
00124   /* Read the points */
00125   Array<double> x(numNodes);
00126   Array<double> y(numNodes);
00127   Array<double> z(numNodes * (dim > 2));
00128 
00129   if (dim == 2)
00130   {
00131     ierr = ex_get_coord(exoID, &(x[0]), &(y[0]), (void*) 0);
00132     TEST_FOR_EXCEPT(ierr < 0);
00133     TEST_FOR_EXCEPT(ierr > 0);
00134   }
00135   else if (dim==3)
00136   {
00137     ierr = ex_get_coord(exoID, (void*) &(x[0]), (void*) &(y[0]), (void*) &(z[0]));
00138     TEST_FOR_EXCEPT(ierr < 0);
00139   }
00140   else 
00141   {
00142     TEST_FOR_EXCEPTION(dim < 2 || dim > 3, RuntimeError, 
00143       "invalid dimension=" << dim << " in ExodusMeshReader");
00144   }
00145 
00146   /* add the points to the mesh */
00147   for (int n=0; n<numNodes; n++)
00148   {
00149     Point p;
00150     if (dim==2)
00151     {
00152       p = Point(x[n], y[n]);
00153     }
00154     else
00155     {
00156       p = Point(x[n], y[n], z[n]);
00157     }
00158     mesh.addVertex(ptGID[n], p, ptOwner[n], 0);
00159   }
00160 
00161 
00162   /* Set up the element numbering */
00163   if (nProc()==1)
00164   {
00165     elemGID.resize(numElems);
00166     elemOwner.resize(numElems);
00167     for (int i=0; i<numElems; i++)
00168     {
00169       elemGID[i] = i;
00170       elemOwner[i] = 0;
00171     }
00172   }
00173   else
00174   {
00175     /* If we're running in parallel, we'd better have consistent numbers
00176      * of elements in the .exo and .pex files. */
00177     TEST_FOR_EXCEPTION((int)elemGID.size() != numElems, RuntimeError,
00178       "ExodusMeshReader::readElems() found inconsistent "
00179       "numbers of elements in .exo file and .pex files. Exodus "
00180       "file " << exoFilename_ << " had nElems=" 
00181       << numElems << " but .pex file " 
00182       << parFilename_ << " had nElems=" << elemGID.size());
00183   }
00184 
00185   /* Read the elements for each block */
00186 
00187   Array<int> blockIDs(numElemBlocks);
00188   if (numElemBlocks > 0)
00189   {
00190     ierr = ex_get_elem_blk_ids(exoID, &(blockIDs[0]));
00191   }
00192   TEST_FOR_EXCEPT(ierr < 0);
00193   int count = 0;
00194   for (int b=0; b<numElemBlocks; b++)
00195   {
00196     char elemType[MAX_LINE_LENGTH+1];
00197     int elsInBlock;
00198     int nodesPerEl;
00199     int numAttrs;
00200     int bid = blockIDs[b];
00201 
00202     ierr = ex_get_elem_block(exoID, bid, elemType, &elsInBlock,
00203       &nodesPerEl, &numAttrs);
00204     TEST_FOR_EXCEPT(ierr < 0);
00205 
00206     Array<int> connect(elsInBlock * nodesPerEl);
00207 
00208     ierr = ex_get_elem_conn(exoID, bid, &(connect[0]));
00209     TEST_FOR_EXCEPT(ierr < 0);
00210     int n=0;
00211 
00212     for (int e=0; e<elsInBlock; e++, n+=nodesPerEl, count++)
00213     {
00214       if (dim==2)
00215       {
00216         mesh.addElement(elemGID[count], tuple(ptGID[connect[n]-1], ptGID[connect[n+1]-1], ptGID[connect[n+2]-1]), elemOwner[count], bid);
00217         SUNDANCE_VERB_HIGH("adding element=("
00218           << connect[n]-1 << ", " << connect[n+1]-1
00219           << ", " << connect[n+2]-1 << ")");
00220       }
00221       else
00222       {
00223         mesh.addElement(elemGID[count], 
00224           tuple(ptGID[connect[n]-1], ptGID[connect[n+1]-1], ptGID[connect[n+2]-1], ptGID[connect[n+3]-1]),
00225           elemOwner[count], bid);
00226       }
00227     }
00228   }
00229 
00230 
00231   /* Read the node sets */
00232   Array<int> nsIDs(numNodeSets);
00233   if (numNodeSets > 0)
00234   {
00235     ierr = ex_get_node_set_ids(exoID, &(nsIDs[0]));
00236   }
00237   TEST_FOR_EXCEPT(ierr < 0);
00238   for (int ns=0; ns<numNodeSets; ns++)
00239   {
00240     int nNodes;
00241     int nDist;
00242     int nsID = nsIDs[ns];
00243     ierr = ex_get_node_set_param(exoID, nsID, &nNodes, &nDist);
00244     TEST_FOR_EXCEPT(ierr < 0);
00245     Array<int> nodes(nNodes);
00246     ierr = ex_get_node_set(exoID, nsID, &(nodes[0]));
00247     TEST_FOR_EXCEPT(ierr < 0);
00248     for (int n=0; n<nNodes; n++)
00249     {
00250       mesh.setLabel(0, nodes[n]-1, nsID);
00251     }
00252   }
00253 
00254     
00255   /* Read the side sets */
00256   Array<int> ssIDs(numSideSets);
00257   if (numSideSets > 0)
00258   {
00259     ierr = ex_get_side_set_ids(exoID, &(ssIDs[0]));
00260   }
00261   TEST_FOR_EXCEPT(ierr < 0);
00262   for (int ss=0; ss<numSideSets; ss++)
00263   {
00264     int nSides;
00265     int nDist;
00266     int ssID = ssIDs[ss];
00267     ierr = ex_get_side_set_param(exoID, ssID, &nSides, &nDist);
00268     TEST_FOR_EXCEPT(ierr < 0);
00269     Array<int> sides(nSides);
00270     Array<int> elems(nSides);
00271     ierr = ex_get_side_set(exoID, ssID, &(elems[0]), &(sides[0]));
00272     TEST_FOR_EXCEPT(ierr < 0);
00273     for (int n=0; n<nSides; n++)
00274     {
00275       int elemID = elems[n];
00276       int facetNum = sides[n];
00277       int fsign;
00278       int sideLID = mesh.facetLID(dim, elemID-1, dim-1, facetNum-1,fsign);
00279       mesh.setLabel(dim-1, sideLID, ssID);
00280     }
00281   }
00282 
00283 
00284   /* Read the nodal attributes */
00285   int nNodalVars = 0;
00286   ierr = ex_get_var_param(exoID, "N", &nNodalVars);
00287   TEST_FOR_EXCEPT(ierr < 0);
00288 
00289   Array<Array<double> >& funcVals = *nodeAttributes();
00290   funcVals.resize(nNodalVars);
00291 
00292   for (int i=0; i<nNodalVars; i++)
00293   {
00294     int t = 1;
00295     funcVals[i].resize(mesh.numCells(0));
00296     ierr = ex_get_nodal_var(exoID, t, i+1, mesh.numCells(0), &(funcVals[i][0]));
00297     TEST_FOR_EXCEPT(ierr < 0);
00298   }
00299 
00300   /* Read the element attributes */
00301   int nElemVars = 0;
00302   ierr = ex_get_var_param(exoID, "E", &nElemVars);
00303   TEST_FOR_EXCEPT(ierr < 0);
00304 
00305   Array<Array<double> >& eFuncVals = *elemAttributes();
00306   eFuncVals.resize(nElemVars);
00307 
00308   for (int i=0; i<nElemVars; i++)
00309   {
00310     int t = 1;
00311     eFuncVals[i].resize(mesh.numCells(mesh.spatialDim()));
00312     ierr = ex_get_elem_var(exoID, t, i+1, 1, mesh.numCells(mesh.spatialDim()), &(eFuncVals[i][0]));
00313     TEST_FOR_EXCEPT(ierr < 0);
00314   }
00315 
00316   ierr = ex_close(exoID);
00317   TEST_FOR_EXCEPT(ierr < 0);
00318 
00319 #endif
00320   return mesh;
00321 }
00322 
00323 
00324 
00325 
00326 void ExodusMeshReader::readParallelInfo(Array<int>& ptGID, 
00327   Array<int>& ptOwner,
00328   Array<int>& cellGID, 
00329   Array<int>& cellOwner) const
00330 {
00331   int nPoints;
00332   int nElems;
00333   std::string line;
00334   Array<string> tokens;
00335   try
00336   {
00337     ptGID.resize(0);
00338     ptOwner.resize(0);
00339     cellGID.resize(0);
00340     cellOwner.resize(0);
00341 
00342     /* if we're running in parallel, read the info on processor 
00343      * distribution */
00344     if (nProc() > 1)
00345     {
00346       RCP<std::ifstream> parStream 
00347         = openFile(parFilename_, "parallel info");
00348      
00349       /* read the number of processors and the processor rank in 
00350        * the file. These must be consistent with the current number of
00351        * processors and the current rank */
00352       getNextLine(*parStream, line, tokens, '#');
00353       
00354       TEST_FOR_EXCEPTION(tokens.length() != 2, RuntimeError,
00355         "ExodusMeshReader::getMesh() expects 2 entries "
00356         "on the first line of .par file. In " 
00357         << parFilename_ << " I found \n[" << line << "]\n");
00358 
00359       int np = atoi(tokens[1]);
00360       int pid = atoi(tokens[0]);
00361 
00362       /* check consistency with the current number of
00363        * processors and the current rank */
00364       
00365       TEST_FOR_EXCEPTION(np != nProc(), RuntimeError,
00366         "ExodusMeshReader::getMesh() found "
00367         "a mismatch between the current number of processors="
00368         << nProc() << 
00369         "and the number of processors=" << np
00370         << "in the file " << parFilename_);
00371 
00372       TEST_FOR_EXCEPTION(pid != myRank(), RuntimeError,
00373         "ExodusMeshReader::getMesh() found "
00374         "a mismatch between the current processor rank="
00375         << myRank() << "and the processor rank="
00376         << pid << " in the file " << parFilename_);
00377 
00378       /* read the number of points */
00379       getNextLine(*parStream, line, tokens, '#');
00380 
00381       TEST_FOR_EXCEPTION(tokens.length() != 1, RuntimeError,
00382         "ExodusMeshReader::getMesh() requires 1 entry "
00383         "on the second line of .pxo file. Found line \n[" 
00384         << line << "]\n in file " << parFilename_);
00385       
00386       nPoints = StrUtils::atoi(tokens[0]);
00387 
00388       /* read the global ID and the owner PID for each point */
00389       ptGID.resize(nPoints);
00390       ptOwner.resize(nPoints);
00391 
00392       for (int i=0; i<nPoints; i++)
00393       {
00394         getNextLine(*parStream, line, tokens, '#');
00395 
00396         TEST_FOR_EXCEPTION(tokens.length() != 3, RuntimeError,
00397           "ExodusMeshReader::getMesh() requires 3 "
00398           "entries on each line of the point section in "
00399           "the .pxo file. Found line \n[" << line
00400           << "]\n in file " << parFilename_);
00401 
00402         ptGID[i] = StrUtils::atoi(tokens[1]);
00403         ptOwner[i] = StrUtils::atoi(tokens[2]);
00404       }
00405 
00406 
00407       /* Read the number of elements */
00408 
00409       getNextLine(*parStream, line, tokens, '#');
00410 
00411       TEST_FOR_EXCEPTION(tokens.length() != 1, RuntimeError,
00412         "ExodusMeshReader::getMesh() requires 1 entry "
00413         "on the cell count line of .pxo file. Found line \n[" 
00414         << line << "]\n in file " << parFilename_);
00415 
00416       nElems = StrUtils::atoi(tokens[0]);
00417 
00418       SUNDANCE_OUT(this->verb() > 1,
00419         "read nElems = " << nElems);
00420 
00421 
00422       /* read the global ID and the owner PID for each element */
00423 
00424       cellGID.resize(nElems);
00425       cellOwner.resize(nElems);
00426       for (int i=0; i<nElems; i++)
00427       {
00428         getNextLine(*parStream, line, tokens, '#');
00429 
00430         TEST_FOR_EXCEPTION(tokens.length() != 3, RuntimeError,
00431           "ExodusMeshReader::getMesh() requires 3 "
00432           "entries on each line of the element section in "
00433           "the .pxo file. Found line \n[" << line
00434           << "]\n in file " << parFilename_);
00435 
00436         cellGID[i] = StrUtils::atoi(tokens[1]);
00437         cellOwner[i] = StrUtils::atoi(tokens[2]);
00438       }
00439     }
00440 
00441     nPoints = ptGID.length();
00442     nElems = cellGID.length();
00443   }
00444   catch(std::exception& e)
00445   {
00446     SUNDANCE_TRACE(e);
00447   }
00448 }

Site Contact