00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "SundanceExodusMeshReader.hpp"
00044 #include "SundanceVertexSort.hpp"
00045 #include "SundanceOut.hpp"
00046 #include "PlayaExceptions.hpp"
00047 #include "SundancePathUtils.hpp"
00048 #include "Teuchos_Time.hpp"
00049 #include "Teuchos_TimeMonitor.hpp"
00050
00051 #ifdef HAVE_SUNDANCE_EXODUS
00052 #include "exodusII.h"
00053 #endif
00054
00055 using namespace Teuchos;
00056 using namespace Sundance;
00057 using namespace std;
00058
00059 static Time& getExoTimer()
00060 {
00061 static RCP<Time> rtn
00062 = TimeMonitor::getNewTimer("raw exodus reader functions");
00063 return *rtn;
00064 }
00065
00066
00067 static Time& getExoFillTimer()
00068 {
00069 static RCP<Time> rtn
00070 = TimeMonitor::getNewTimer("exodus reader fillMesh");
00071 return *rtn;
00072 }
00073
00074
00075 ExodusMeshReader::ExodusMeshReader(const std::string& fname,
00076 const MeshType& meshType,
00077 int verbosity,
00078 const MPIComm& comm)
00079 : MeshReaderBase(fname, meshType, verbosity, comm),
00080 exoFilename_(fname),
00081 parFilename_(fname)
00082 {
00083 Tabs tab0(0);
00084
00085 if (nProc() > 1)
00086 {
00087 std::string suffix = "-" + Teuchos::toString(nProc())
00088 + "-" + Teuchos::toString(myRank());
00089 exoFilename_ = exoFilename_ + suffix;
00090 parFilename_ = parFilename_ + suffix;
00091 }
00092 exoFilename_ = exoFilename_ + ".exo";
00093 parFilename_ = parFilename_ + ".pxo";
00094
00095 PLAYA_MSG1(verb(), "exodus filename = " << exoFilename_);
00096
00097 if (nProc() > 1)
00098 {
00099 SUNDANCE_OUT(this->verb() > 1,
00100 "par filename = " << parFilename_);
00101 }
00102 }
00103
00104
00105
00106
00107
00108 Mesh ExodusMeshReader::fillMesh() const
00109 {
00110 TimeMonitor fillTimer(getExoFillTimer());
00111 Tabs tab0(0);
00112 Tabs tab1;
00113 Mesh mesh;
00114 #ifndef HAVE_SUNDANCE_EXODUS
00115 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00116 "ExodusMeshReader called for a build without ExodusII");
00117 #else
00118 PLAYA_ROOT_MSG1(verb(), tab0 << "in ExodusMeshReader::fillMesh()");
00119
00120 int CPU_word_size = 8;
00121 int IO_word_size = 0;
00122 float version;
00123
00124 Array<int> ptGID;
00125 Array<int> ptOwner;
00126 Array<int> elemGID;
00127 Array<int> elemOwner;
00128
00129 readParallelInfo(ptGID, ptOwner, elemGID, elemOwner);
00130
00131 if (verb() > 2) ex_opts(EX_DEBUG | EX_VERBOSE);
00132
00133 PLAYA_MSG3(verb(), tab1 << "opening file");
00134 std::string resolvedName = searchForFile(exoFilename_);
00135 int exoID = ex_open(resolvedName.c_str(), EX_READ,
00136 &CPU_word_size, &IO_word_size, &version);
00137
00138 TEUCHOS_TEST_FOR_EXCEPTION(exoID < 0, std::runtime_error, "ExodusMeshReader unable to "
00139 "open file: " << exoFilename_);
00140
00141 PLAYA_MSG3(verb(), tab1 << "exoID=" << exoID);
00142
00143 TEUCHOS_TEST_FOR_EXCEPT(IO_word_size != 8 || CPU_word_size != 8);
00144
00145 char title[MAX_LINE_LENGTH+1];
00146
00147 int dim = 0;
00148 int numNodes = 0;
00149 int numElems = 0;
00150 int numElemBlocks = 0;
00151 int numNodeSets = 0;
00152 int numSideSets = 0;
00153
00154 int ierr = ex_get_init(exoID, title, &dim, &numNodes, &numElems,
00155 &numElemBlocks, &numNodeSets, &numSideSets);
00156
00157 TEUCHOS_TEST_FOR_EXCEPTION(numNodes <= 0, std::runtime_error, "invalid numNodes="
00158 << numNodes);
00159 TEUCHOS_TEST_FOR_EXCEPTION(numElems <= 0, std::runtime_error, "invalid numElems="
00160 << numElems);
00161
00162 PLAYA_MSG2(verb(), tab1 << "numNodes=" << numNodes);
00163 PLAYA_MSG2(verb(), tab1 << "numElems=" << numElems);
00164
00165
00166 if (nProc()==1)
00167 {
00168 ptGID.resize(numNodes);
00169 ptOwner.resize(numNodes);
00170 for (int i=0; i<numNodes; i++)
00171 {
00172 ptGID[i] = i;
00173 ptOwner[i] = 0;
00174 }
00175 }
00176 else
00177 {
00178
00179
00180 TEUCHOS_TEST_FOR_EXCEPTION((int)ptGID.size() != numNodes, std::runtime_error,
00181 "ExodusMeshReader::getMesh() found inconsistent "
00182 "numbers of points in .exo file and .pex files. Exo "
00183 "file " << exoFilename_ << " had nPoints="
00184 << numNodes << " but .pex file "
00185 << parFilename_ << " had nPoints=" << ptGID.size());
00186 }
00187
00188
00189 mesh = createMesh(dim);
00190
00191
00192
00193
00194 PLAYA_MSG2(verb(), tab1 << "reading vertices");
00195 Array<double> x(numNodes);
00196 Array<double> y(numNodes);
00197 Array<double> z(numNodes * (dim > 2));
00198
00199 if (dim == 2)
00200 {
00201 ierr = ex_get_coord(exoID, &(x[0]), &(y[0]), (void*) 0);
00202 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00203 TEUCHOS_TEST_FOR_EXCEPT(ierr > 0);
00204 }
00205 else if (dim==3)
00206 {
00207 ierr = ex_get_coord(exoID, (void*) &(x[0]), (void*) &(y[0]), (void*) &(z[0]));
00208 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00209 }
00210 else
00211 {
00212 TEUCHOS_TEST_FOR_EXCEPTION(dim < 2 || dim > 3, std::runtime_error,
00213 "invalid dimension=" << dim << " in ExodusMeshReader");
00214 }
00215
00216
00217
00218 PLAYA_MSG2(verb(), tab1 << "adding vertices to mesh");
00219 for (int n=0; n<numNodes; n++)
00220 {
00221 Point p;
00222 if (dim==2)
00223 {
00224 p = Point(x[n], y[n]);
00225 }
00226 else
00227 {
00228 p = Point(x[n], y[n], z[n]);
00229 }
00230 mesh.addVertex(ptGID[n], p, ptOwner[n], 0);
00231 }
00232
00233
00234
00235 if (nProc()==1)
00236 {
00237 elemGID.resize(numElems);
00238 elemOwner.resize(numElems);
00239 for (int i=0; i<numElems; i++)
00240 {
00241 elemGID[i] = i;
00242 elemOwner[i] = 0;
00243 }
00244 }
00245 else
00246 {
00247
00248
00249 TEUCHOS_TEST_FOR_EXCEPTION((int)elemGID.size() != numElems, std::runtime_error,
00250 "ExodusMeshReader::readElems() found inconsistent "
00251 "numbers of elements in .exo file and .pex files. Exodus "
00252 "file " << exoFilename_ << " had nElems="
00253 << numElems << " but .pex file "
00254 << parFilename_ << " had nElems=" << elemGID.size());
00255 }
00256
00257
00258
00259 PLAYA_MSG2(verb(), tab1 << "reading elements");
00260 Array<int> blockIDs(numElemBlocks);
00261 if (numElemBlocks > 0)
00262 {
00263 TimeMonitor timer(getExoTimer());
00264 ierr = ex_get_elem_blk_ids(exoID, &(blockIDs[0]));
00265 }
00266 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00267 PLAYA_MSG2(verb(), tab1 << "file contains block IDs " << blockIDs);
00268 int count = 0;
00269 Array<int> permKey;
00270 permKey.resize(numElems);
00271
00272 Array<int> blockIsSimplicial(numElemBlocks);
00273 bool allBlocksAreSimplicial = true;
00274
00275 for (int b=0; b<numElemBlocks; b++)
00276 {
00277 Tabs tab2;
00278 char elemType[MAX_LINE_LENGTH+1];
00279 int elsInBlock=0;
00280 int nodesPerEl=0;
00281 int numAttrs=0;
00282 int bid = blockIDs[b];
00283 PLAYA_MSG2(verb(), tab2 << "reading elems for block ID=" << bid);
00284 {
00285 TimeMonitor timer(getExoTimer());
00286 ierr = ex_get_elem_block(exoID, bid, elemType, &elsInBlock,
00287 &nodesPerEl, &numAttrs);
00288 }
00289 TEUCHOS_TEST_FOR_EXCEPTION(ierr < 0, std::runtime_error,
00290 "ex_get_elem_block returned error code ierr=" << ierr);
00291
00292 bool blockIsSimplicial = true;
00293 if (nodesPerEl != dim+1)
00294 {
00295 blockIsSimplicial=false;
00296 allBlocksAreSimplicial=false;
00297 }
00298
00299
00300
00301 PLAYA_MSG2(verb(), tab2 << "reading connectivity for block ID=" << bid);
00302 Array<int> connect(elsInBlock * nodesPerEl);
00303
00304 {
00305 TimeMonitor timer(getExoTimer());
00306 ierr = ex_get_elem_conn(exoID, bid, &(connect[0]));
00307 }
00308 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00309 int n=0;
00310 Array<int> orderedVerts(nodesPerEl);
00311 Array<int> exVerts(nodesPerEl);
00312
00313 for (int e=0; e<elsInBlock; e++, n+=nodesPerEl, count++)
00314 {
00315
00316 for (int v=0; v<nodesPerEl; v++)
00317 {
00318 orderedVerts[v] = ptGID[connect[n+v]-1];
00319 }
00320 exVerts = orderedVerts;
00321 int key = -1;
00322 if (blockIsSimplicial)
00323 {
00324 vertexSort(orderedVerts, &key);
00325
00326 }
00327
00328 int elemLID
00329 = mesh.addElement(elemGID[count], orderedVerts,
00330 elemOwner[count], bid);
00331 if (blockIsSimplicial)
00332 {
00333
00334 permKey[elemLID]=key;
00335 }
00336 }
00337 }
00338
00339
00340
00341 mesh.freezeTopology();
00342
00343
00344
00345 Array<int> nsIDs(numNodeSets);
00346 if (numNodeSets > 0)
00347 {
00348 TimeMonitor timer(getExoTimer());
00349 ierr = ex_get_node_set_ids(exoID, &(nsIDs[0]));
00350 }
00351 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00352 for (int ns=0; ns<numNodeSets; ns++)
00353 {
00354 int nNodes;
00355 int nDist;
00356 int nsID = nsIDs[ns];
00357 {
00358 TimeMonitor timer(getExoTimer());
00359 ierr = ex_get_node_set_param(exoID, nsID, &nNodes, &nDist);
00360 }
00361 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00362 Array<int> nodes(nNodes);
00363 {
00364 TimeMonitor timer(getExoTimer());
00365 ierr = ex_get_node_set(exoID, nsID, &(nodes[0]));
00366 }
00367 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00368 for (int n=0; n<nNodes; n++)
00369 {
00370 mesh.setLabel(0, nodes[n]-1, nsID);
00371 }
00372 }
00373
00374
00375
00376 Array<int> ssIDs(numSideSets);
00377 if (numSideSets > 0)
00378 {
00379 TimeMonitor timer(getExoTimer());
00380 ierr = ex_get_side_set_ids(exoID, &(ssIDs[0]));
00381 }
00382 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00383 for (int ss=0; ss<numSideSets; ss++)
00384 {
00385 int nSides;
00386 int nDist;
00387 int ssID = ssIDs[ss];
00388 {
00389 TimeMonitor timer(getExoTimer());
00390 ierr = ex_get_side_set_param(exoID, ssID, &nSides, &nDist);
00391 }
00392 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00393 Array<int> sides(nSides);
00394 Array<int> elems(nSides);
00395 {
00396 TimeMonitor timer(getExoTimer());
00397 ierr = ex_get_side_set(exoID, ssID, &(elems[0]), &(sides[0]));
00398 }
00399 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00400 for (int n=0; n<nSides; n++)
00401 {
00402 int elemID = elems[n]-1;
00403 int facetNum = sides[n]-1;
00404 int fsign;
00405 if (allBlocksAreSimplicial)
00406 {
00407 int key = permKey[elemID];
00408 facetNum = exFacetIndexToUFCFacetIndex(dim, key, facetNum);
00409 }
00410 int sideLID = mesh.facetLID(dim, elemID, dim-1,
00411 facetNum, fsign);
00412 mesh.setLabel(dim-1, sideLID, ssID);
00413 }
00414 }
00415
00416
00417
00418 int nNodalVars = 0;
00419 {
00420 TimeMonitor timer(getExoTimer());
00421 ierr = ex_get_var_param(exoID, "N", &nNodalVars);
00422 }
00423 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00424
00425 Array<Array<double> >& funcVals = *nodeAttributes();
00426 funcVals.resize(nNodalVars);
00427
00428 for (int i=0; i<nNodalVars; i++)
00429 {
00430 int t = 1;
00431 funcVals[i].resize(mesh.numCells(0));
00432 {
00433 TimeMonitor timer(getExoTimer());
00434 ierr = ex_get_nodal_var(exoID, t, i+1, mesh.numCells(0), &(funcVals[i][0]));
00435 }
00436 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00437 }
00438
00439
00440 int nElemVars = 0;
00441 {
00442 TimeMonitor timer(getExoTimer());
00443 ierr = ex_get_var_param(exoID, "E", &nElemVars);
00444 }
00445 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00446
00447 Array<Array<double> >& eFuncVals = *elemAttributes();
00448 eFuncVals.resize(nElemVars);
00449
00450 for (int i=0; i<nElemVars; i++)
00451 {
00452 int t = 1;
00453 eFuncVals[i].resize(mesh.numCells(mesh.spatialDim()));
00454 {
00455 TimeMonitor timer(getExoTimer());
00456 ierr = ex_get_elem_var(exoID, t, i+1, 1, mesh.numCells(mesh.spatialDim()), &(eFuncVals[i][0]));
00457 }
00458 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00459 }
00460
00461 ierr = ex_close(exoID);
00462 TEUCHOS_TEST_FOR_EXCEPT(ierr < 0);
00463
00464 #endif
00465 return mesh;
00466 }
00467
00468
00469
00470
00471 void ExodusMeshReader::readParallelInfo(Array<int>& ptGID,
00472 Array<int>& ptOwner,
00473 Array<int>& cellGID,
00474 Array<int>& cellOwner) const
00475 {
00476 int nPoints;
00477 int nElems;
00478 std::string line;
00479 Array<string> tokens;
00480 try
00481 {
00482 ptGID.resize(0);
00483 ptOwner.resize(0);
00484 cellGID.resize(0);
00485 cellOwner.resize(0);
00486
00487
00488
00489 if (nProc() > 1)
00490 {
00491 RCP<std::ifstream> parStream
00492 = openFile(parFilename_, "parallel info");
00493
00494
00495
00496
00497 getNextLine(*parStream, line, tokens, '#');
00498
00499 TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 2, std::runtime_error,
00500 "ExodusMeshReader::getMesh() expects 2 entries "
00501 "on the first line of .par file. In "
00502 << parFilename_ << " I found \n[" << line << "]\n");
00503
00504 int np = atoi(tokens[1]);
00505 int pid = atoi(tokens[0]);
00506
00507
00508
00509
00510 TEUCHOS_TEST_FOR_EXCEPTION(np != nProc(), std::runtime_error,
00511 "ExodusMeshReader::getMesh() found "
00512 "a mismatch between the current number of processors="
00513 << nProc() <<
00514 "and the number of processors=" << np
00515 << "in the file " << parFilename_);
00516
00517 TEUCHOS_TEST_FOR_EXCEPTION(pid != myRank(), std::runtime_error,
00518 "ExodusMeshReader::getMesh() found "
00519 "a mismatch between the current processor rank="
00520 << myRank() << "and the processor rank="
00521 << pid << " in the file " << parFilename_);
00522
00523
00524 getNextLine(*parStream, line, tokens, '#');
00525
00526 TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 1, std::runtime_error,
00527 "ExodusMeshReader::getMesh() requires 1 entry "
00528 "on the second line of .pxo file. Found line \n["
00529 << line << "]\n in file " << parFilename_);
00530
00531 nPoints = StrUtils::atoi(tokens[0]);
00532
00533
00534 ptGID.resize(nPoints);
00535 ptOwner.resize(nPoints);
00536
00537 for (int i=0; i<nPoints; i++)
00538 {
00539 getNextLine(*parStream, line, tokens, '#');
00540
00541 TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 3, std::runtime_error,
00542 "ExodusMeshReader::getMesh() requires 3 "
00543 "entries on each line of the point section in "
00544 "the .pxo file. Found line \n[" << line
00545 << "]\n in file " << parFilename_);
00546
00547 ptGID[i] = StrUtils::atoi(tokens[1]);
00548 ptOwner[i] = StrUtils::atoi(tokens[2]);
00549 }
00550
00551
00552
00553
00554 getNextLine(*parStream, line, tokens, '#');
00555
00556 TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 1, std::runtime_error,
00557 "ExodusMeshReader::getMesh() requires 1 entry "
00558 "on the cell count line of .pxo file. Found line \n["
00559 << line << "]\n in file " << parFilename_);
00560
00561 nElems = StrUtils::atoi(tokens[0]);
00562
00563 SUNDANCE_OUT(this->verb() > 1,
00564 "read nElems = " << nElems);
00565
00566
00567
00568
00569 cellGID.resize(nElems);
00570 cellOwner.resize(nElems);
00571 for (int i=0; i<nElems; i++)
00572 {
00573 getNextLine(*parStream, line, tokens, '#');
00574
00575 TEUCHOS_TEST_FOR_EXCEPTION(tokens.length() != 3, std::runtime_error,
00576 "ExodusMeshReader::getMesh() requires 3 "
00577 "entries on each line of the element section in "
00578 "the .pxo file. Found line \n[" << line
00579 << "]\n in file " << parFilename_);
00580
00581 cellGID[i] = StrUtils::atoi(tokens[1]);
00582 cellOwner[i] = StrUtils::atoi(tokens[2]);
00583 }
00584 }
00585
00586 nPoints = ptGID.length();
00587 nElems = cellGID.length();
00588 }
00589 catch(std::exception& e)
00590 {
00591 SUNDANCE_TRACE(e);
00592 }
00593 }