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
00111
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
00121 mesh = createMesh(dim);
00122
00123
00124
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
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
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
00176
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
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
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
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
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
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
00343
00344 if (nProc() > 1)
00345 {
00346 RCP<std::ifstream> parStream
00347 = openFile(parFilename_, "parallel info");
00348
00349
00350
00351
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
00363
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
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
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
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
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 }