00001 #include "SundanceExodusNetCDFMeshReader.hpp"
00002 #include "SundanceOut.hpp"
00003 #include "PlayaExceptions.hpp"
00004
00005 using namespace Sundance;
00006 using namespace Sundance;
00007
00008 using namespace Teuchos;
00009 using namespace Sundance;
00010
00011
00012 ExodusNetCDFMeshReader::ExodusNetCDFMeshReader(const std::string& fname,
00013 const MeshType& meshType,
00014 const MPIComm& comm)
00015 : MeshReaderBase(fname, meshType, comm)
00016 {
00017 TEUCHOS_TEST_FOR_EXCEPTION(nProc() > 1, std::runtime_error,
00018 "ExodusNetCDFMeshReader not useable with parallel meshes");
00019 }
00020
00021 ExodusNetCDFMeshReader::ExodusNetCDFMeshReader(const ParameterList& params)
00022 : MeshReaderBase(params)
00023 {
00024 TEUCHOS_TEST_FOR_EXCEPTION(nProc() > 1, std::runtime_error,
00025 "ExodusNetCDFMeshReader not useable with parallel meshes");
00026 }
00027
00028
00029
00030
00031 Mesh ExodusNetCDFMeshReader::fillMesh() const
00032 {
00033 Mesh mesh;
00034
00035 RCP<std::ifstream> is = openFile(filename(), "NetCDF");
00036
00037 std::string line;
00038 Array<string> tokens;
00039
00040
00041 getNextLine(*is, line, tokens, '#');
00042
00043 TEUCHOS_TEST_FOR_EXCEPTION(tokens[0] != "netcdf", std::runtime_error,
00044 "ExodusNetCDF reader expected to find [netcdf] as first "
00045 "token, found " << tokens[0]);
00046
00047
00048 getNextLine(*is, line, tokens, '#');
00049
00050
00051 TEUCHOS_TEST_FOR_EXCEPTION(tokens[0] != "dimensions:", std::runtime_error,
00052 "ExodusNetCDF reader expected to find [dimension:] as first "
00053 "token, found " << tokens[0]);
00054
00055 int nElem = 0;
00056 int nNodes = 0;
00057 int nElemBlocks = 0;
00058 int nSideSets = 0;
00059 int nNodeSets = 0;
00060 int dimension = 0 ;
00061 Array<int> blockSizes;
00062 Array<int> sideSetSizes;
00063 Array<int> nodeSetSizes;
00064 Array<int> nodesPerElem;
00065 while (true)
00066 {
00067 getNextLine(*is, line, tokens, '#');
00068
00069 if (tokens[0] == "variables:") break;
00070 std::string keyword = tokens[0];
00071 std::string equals = tokens[1];
00072 TEUCHOS_TEST_FOR_EXCEPTION(equals!="=", std::runtime_error, "ExodusNetCDF reader "
00073 "expected [=] as second token, found "
00074 << equals);
00075
00076 TEUCHOS_TEST_FOR_EXCEPTION(tokens.size() < 4, std::runtime_error,
00077 "ExodusNetCDF reader found a dimension line with "
00078 "fewer than 4 tokens");
00079
00080 int val = atoi(tokens[2]);
00081 if (keyword=="num_dim")
00082 {
00083 dimension = val;
00084 }
00085 else if (keyword=="num_nodes")
00086 {
00087 nNodes = val;
00088 }
00089 else if (keyword=="num_elem")
00090 {
00091 nElem = val;
00092 }
00093 else if (keyword=="num_el_blk")
00094 {
00095 nElemBlocks = val;
00096 blockSizes.resize(nElemBlocks);
00097 nodesPerElem.resize(nElemBlocks);
00098 }
00099 else if (keyword=="num_side_sets")
00100 {
00101 nSideSets = val;
00102 sideSetSizes.resize(nSideSets);
00103 std::cerr << "num side sets = " << nSideSets << std::endl;
00104 }
00105 else if (keyword=="num_node_sets")
00106 {
00107 nNodeSets = val;
00108 nodeSetSizes.resize(nNodeSets);
00109 std::cerr << "num node sets = " << nNodeSets << std::endl;
00110 }
00111 else
00112 {
00113 for (int i=0; i<nElemBlocks; i++)
00114 {
00115 if (keyword=="num_el_in_blk" + Teuchos::toString(i+1))
00116 {
00117 blockSizes[i] = val;
00118 break;
00119 }
00120 if (keyword=="num_nod_per_el" + Teuchos::toString(i+1))
00121 {
00122 nodesPerElem[i] = val;
00123 break;
00124 }
00125 }
00126 for (int i=0; i<nSideSets; i++)
00127 {
00128 if (keyword=="num_side_ss" + Teuchos::toString(i+1))
00129 {
00130 sideSetSizes[i] = val;
00131 break;
00132 }
00133 }
00134 for (int i=0; i<nNodeSets; i++)
00135 {
00136 if (keyword=="num_nod_ns" + Teuchos::toString(i+1))
00137 {
00138 nodeSetSizes[i] = val;
00139 break;
00140 }
00141 }
00142 }
00143 }
00144
00145
00146
00147
00148 while (true)
00149 {
00150 getNextLine(*is, line, tokens, '#');
00151
00152 if (tokens[0] == "data:") break;
00153 }
00154
00155
00156
00157
00158 Array<double> coords;
00159 coords.reserve(nNodes*dimension);
00160 Array<Array<int> > connect(nElemBlocks);
00161 Array<Array<int> > sideSetElems(nSideSets);
00162 Array<Array<int> > sideSetFacets(nSideSets);
00163 Array<Array<int> > nodeSetNodes(nNodeSets);
00164
00165 bool doneWithData = false;
00166 while(!doneWithData)
00167 {
00168 if (!getNextLine(*is, line, tokens, '#'))
00169 {
00170 doneWithData = true;
00171 break;
00172 }
00173
00174 if (tokens.size()==0)
00175 {
00176
00177 doneWithData=true;
00178 break;
00179 }
00180
00181 if (tokens[0]=="coord")
00182 {
00183 bool done = false;
00184 for (int i=1; i<tokens.size(); i++)
00185 {
00186 if (tokens[i] == "=") continue;
00187 if (tokens[i] == ";")
00188 {
00189 done = true;
00190 break;
00191 }
00192 coords.append(atof(StrUtils::before(tokens[i], ",")));
00193 }
00194 while (!done)
00195 {
00196 if (!getNextLine(*is, line, tokens, '#'))
00197 {
00198 doneWithData = true;
00199 break;
00200 }
00201
00202 for (int i=0; i<tokens.size(); i++)
00203 {
00204 if (tokens[i] == "=") continue;
00205 if (tokens[i] == ";")
00206 {
00207 done = true;
00208 break;
00209 }
00210 coords.append(atof(StrUtils::before(tokens[i], ",")));
00211 }
00212 }
00213 continue;
00214 }
00215
00216 for (int b=0; b<nElemBlocks; b++)
00217 {
00218 if (tokens[0] == "connect" + Teuchos::toString(b+1))
00219 {
00220 connect[b].reserve(blockSizes[b]);
00221 bool done = false;
00222 for (int i=1; i<tokens.size(); i++)
00223 {
00224 if (tokens[i] == "=") continue;
00225 if (tokens[i] == ";")
00226 {
00227 done = true;
00228 break;
00229 }
00230 connect[b].append(atoi(StrUtils::before(tokens[i], ",")));
00231 }
00232 while (!done)
00233 {
00234 if (!getNextLine(*is, line, tokens, '#'))
00235 {
00236 doneWithData = true;
00237 break;
00238 }
00239
00240 for (int i=0; i<tokens.size(); i++)
00241 {
00242 if (tokens[i] == "=") continue;
00243 if (tokens[i] == ";")
00244 {
00245 done = true;
00246 break;
00247 }
00248 connect[b].append(atoi(StrUtils::before(tokens[i], ",")));
00249 }
00250 }
00251 continue;
00252 }
00253 }
00254
00255
00256 for (int s=0; s<nSideSets; s++)
00257 {
00258 if (tokens[0] == "elem_ss" + Teuchos::toString(s+1))
00259 {
00260 sideSetElems[s].reserve(sideSetSizes[s]);
00261 bool done = false;
00262 for (int i=1; i<tokens.size(); i++)
00263 {
00264 if (tokens[i] == "=") continue;
00265 if (tokens[i] == ";")
00266 {
00267 done = true;
00268 break;
00269 }
00270 sideSetElems[s].append(atoi(StrUtils::before(tokens[i], ",")));
00271 }
00272 while (!done)
00273 {
00274 if (!getNextLine(*is, line, tokens, '#'))
00275 {
00276 doneWithData = true;
00277 break;
00278 }
00279
00280 for (int i=0; i<tokens.size(); i++)
00281 {
00282 if (tokens[i] == "=") continue;
00283 if (tokens[i] == ";")
00284 {
00285 done = true;
00286 break;
00287 }
00288 sideSetElems[s].append(atoi(StrUtils::before(tokens[i], ",")));
00289 }
00290 }
00291 continue;
00292 }
00293 }
00294
00295
00296 for (int s=0; s<nSideSets; s++)
00297 {
00298 if (tokens[0] == "side_ss" + Teuchos::toString(s+1))
00299 {
00300 sideSetFacets[s].reserve(sideSetSizes[s]);
00301 bool done = false;
00302 for (int i=1; i<tokens.size(); i++)
00303 {
00304 if (tokens[i] == "=") continue;
00305 if (tokens[i] == ";")
00306 {
00307 done = true;
00308 break;
00309 }
00310 sideSetFacets[s].append(atoi(StrUtils::before(tokens[i], ",")));
00311 }
00312 while (!done)
00313 {
00314 if (!getNextLine(*is, line, tokens, '#'))
00315 {
00316 doneWithData = true;
00317 break;
00318 }
00319 for (int i=0; i<tokens.size(); i++)
00320 {
00321 if (tokens[i] == "=") continue;
00322 if (tokens[i] == ";")
00323 {
00324 done = true;
00325 break;
00326 }
00327 sideSetFacets[s].append(atoi(StrUtils::before(tokens[i], ",")));
00328 }
00329 }
00330 continue;
00331 }
00332 }
00333
00334
00335 for (int s=0; s<nNodeSets; s++)
00336 {
00337 if (tokens[0] == "node_ns" + Teuchos::toString(s+1))
00338 {
00339 nodeSetNodes[s].reserve(nodeSetSizes[s]);
00340 bool done = false;
00341 for (int i=1; i<tokens.size(); i++)
00342 {
00343 if (tokens[i] == "=") continue;
00344 if (tokens[i] == ";")
00345 {
00346 done = true;
00347 break;
00348 }
00349 nodeSetNodes[s].append(atoi(StrUtils::before(tokens[i], ",")));
00350 }
00351 while (!done)
00352 {
00353 if (!getNextLine(*is, line, tokens, '#'))
00354 {
00355 doneWithData = true;
00356 break;
00357 }
00358 for (int i=0; i<tokens.size(); i++)
00359 {
00360 if (tokens[i] == "=") continue;
00361 if (tokens[i] == ";")
00362 {
00363 done = true;
00364 break;
00365 }
00366 nodeSetNodes[s].append(atoi(StrUtils::before(tokens[i], ",")));
00367 }
00368 }
00369 continue;
00370 }
00371 }
00372 }
00373
00374
00375
00376
00377 mesh = createMesh(dimension);
00378
00379
00380 TEUCHOS_TEST_FOR_EXCEPTION(dimension * nNodes != coords.size(), std::runtime_error,
00381 "bad coordinate array in exodus reader");
00382
00383 for (int b=0; b<nElemBlocks; b++)
00384 {
00385 TEUCHOS_TEST_FOR_EXCEPTION(blockSizes[b]*nodesPerElem[b] != connect[b].size(), std::runtime_error,
00386 "bad connectivity array for block " << b << " in exodus reader");
00387 }
00388
00389 for (int s=0; s<nSideSets; s++)
00390 {
00391 TEUCHOS_TEST_FOR_EXCEPTION(sideSetElems[s].size() != sideSetFacets[s].size(), std::runtime_error,
00392 "inconsistent side set specification for ss=" << s
00393 << " in exodus reader ");
00394 }
00395
00396
00397 for (int n=0; n<nNodes; n++)
00398 {
00399 Point x;
00400 if (dimension==2)
00401 {
00402 x = Point(coords[n], coords[nNodes+n]);
00403 }
00404 else
00405 {
00406 x = Point(coords[n], coords[nNodes+n], coords[2*nNodes+n]);
00407 }
00408 mesh.addVertex(n, x, 0, 0);
00409 }
00410
00411
00412
00413 int lid=0;
00414 for (int b=0; b<nElemBlocks; b++)
00415 {
00416 int n = 0;
00417 for (int e=0; e<blockSizes[b]; e++, n+=nodesPerElem[b], lid++)
00418 {
00419 if (dimension==2)
00420 {
00421 mesh.addElement(lid, tuple(connect[b][n]-1, connect[b][n+1]-1, connect[b][n+2]-1), 0, b+1);
00422 }
00423 else
00424 {
00425 mesh.addElement(lid,
00426 tuple(connect[b][n]-1, connect[b][n+1]-1, connect[b][n+2]-1, connect[b][n+3]-1),
00427 0, b+1);
00428 }
00429 }
00430 }
00431
00432
00433
00434 for (int s=0; s<nSideSets; s++)
00435 {
00436 for (int n=0; n<sideSetSizes[s]; n++)
00437 {
00438 int elemID = sideSetElems[s][n];
00439 int facetNum = sideSetFacets[s][n];
00440 int fsign;
00441 int sideLID = mesh.facetLID(dimension, elemID-1, dimension-1,
00442 facetNum-1,fsign);
00443 mesh.setLabel(dimension-1, sideLID, s+1);
00444 }
00445 }
00446
00447
00448 for (int s=0; s<nNodeSets; s++)
00449 {
00450 for (int n=0; n<nodeSetSizes[s]; n++)
00451 {
00452 int nodeNum = nodeSetNodes[s][n]-1;
00453 mesh.setLabel(0, nodeNum, s+1);
00454 }
00455 }
00456
00457 return mesh;
00458 }
00459