SundanceExodusNetCDFMeshReader.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 
00043 #include "SundanceExodusNetCDFMeshReader.hpp"
00044 #include "SundanceOut.hpp"
00045 #include "PlayaExceptions.hpp"
00046 
00047 using namespace Sundance;
00048 using namespace Sundance;
00049 
00050 using namespace Teuchos;
00051 using namespace Sundance;
00052 
00053 
00054 ExodusNetCDFMeshReader::ExodusNetCDFMeshReader(const std::string& fname,
00055   const MeshType& meshType,
00056   int verbosity,
00057   const MPIComm& comm)
00058   : MeshReaderBase(fname, meshType, verbosity, comm)
00059 {
00060   TEUCHOS_TEST_FOR_EXCEPTION(nProc() > 1, std::runtime_error,
00061     "ExodusNetCDFMeshReader not useable with parallel meshes");
00062 }
00063 
00064 ExodusNetCDFMeshReader::ExodusNetCDFMeshReader(const ParameterList& params)
00065   : MeshReaderBase(params)
00066 {
00067   TEUCHOS_TEST_FOR_EXCEPTION(nProc() > 1, std::runtime_error,
00068     "ExodusNetCDFMeshReader not useable with parallel meshes");
00069 }
00070 
00071 
00072 
00073 
00074 Mesh ExodusNetCDFMeshReader::fillMesh() const 
00075 {
00076   Mesh mesh;
00077 
00078   RCP<std::ifstream> is = openFile(filename(), "NetCDF");
00079 
00080   std::string line;
00081   Array<string> tokens;
00082 
00083   /* read the header line */
00084   getNextLine(*is, line, tokens, '#');
00085 
00086   TEUCHOS_TEST_FOR_EXCEPTION(tokens[0] != "netcdf", std::runtime_error,
00087     "ExodusNetCDF reader expected to find [netcdf] as first "
00088     "token, found " << tokens[0]);
00089 
00090   /* read the list of dimensions */
00091   getNextLine(*is, line, tokens, '#');
00092 
00093 
00094   TEUCHOS_TEST_FOR_EXCEPTION(tokens[0] != "dimensions:", std::runtime_error,
00095     "ExodusNetCDF reader expected to find [dimension:] as first "
00096     "token, found " << tokens[0]);
00097   
00098   int nElem = 0;
00099   int nNodes = 0;
00100   int nElemBlocks = 0;
00101   int nSideSets = 0;
00102   int nNodeSets = 0;
00103   int dimension = 0 ;
00104   Array<int> blockSizes;
00105   Array<int> sideSetSizes;
00106   Array<int> nodeSetSizes;
00107   Array<int> nodesPerElem;
00108   while (true)
00109   {
00110     getNextLine(*is, line, tokens, '#');
00111 
00112     if (tokens[0] == "variables:") break;
00113     std::string keyword = tokens[0];
00114     std::string equals = tokens[1];
00115     TEUCHOS_TEST_FOR_EXCEPTION(equals!="=", std::runtime_error, "ExodusNetCDF reader "
00116       "expected [=] as second token, found "
00117       << equals);
00118 
00119     TEUCHOS_TEST_FOR_EXCEPTION(tokens.size() < 4, std::runtime_error,
00120       "ExodusNetCDF reader found a dimension line with "
00121       "fewer than 4 tokens");
00122 
00123     int val = atoi(tokens[2]);
00124     if (keyword=="num_dim")
00125     {
00126       dimension = val;
00127     }
00128     else if (keyword=="num_nodes")
00129     {
00130       nNodes = val;
00131     }
00132     else if (keyword=="num_elem")
00133     {
00134       nElem = val;
00135     } 
00136     else if (keyword=="num_el_blk")
00137     {
00138       nElemBlocks = val;
00139       blockSizes.resize(nElemBlocks);
00140       nodesPerElem.resize(nElemBlocks);
00141     }
00142     else if (keyword=="num_side_sets")
00143     {
00144       nSideSets = val;
00145       sideSetSizes.resize(nSideSets);
00146       std::cerr << "num side sets = " << nSideSets << std::endl;
00147     }
00148     else if (keyword=="num_node_sets")
00149     {
00150       nNodeSets = val;
00151       nodeSetSizes.resize(nNodeSets);
00152       std::cerr << "num node sets = " << nNodeSets << std::endl;
00153     }
00154     else
00155     {
00156       for (int i=0; i<nElemBlocks; i++)
00157       {
00158         if (keyword=="num_el_in_blk" + Teuchos::toString(i+1))
00159         {
00160           blockSizes[i] = val;
00161           break;
00162         }
00163         if (keyword=="num_nod_per_el" + Teuchos::toString(i+1))
00164         {
00165           nodesPerElem[i] = val;
00166           break;
00167         }
00168       }
00169       for (int i=0; i<nSideSets; i++)
00170       {
00171         if (keyword=="num_side_ss" + Teuchos::toString(i+1))
00172         {
00173           sideSetSizes[i] = val;
00174           break;
00175         }
00176       }
00177       for (int i=0; i<nNodeSets; i++)
00178       {
00179         if (keyword=="num_nod_ns" + Teuchos::toString(i+1))
00180         {
00181           nodeSetSizes[i] = val;
00182           break;
00183         }
00184       }
00185     }
00186   }
00187 
00188   
00189 
00190   /* skip until we find [data:] */
00191   while (true)
00192   {
00193     getNextLine(*is, line, tokens, '#');
00194 
00195     if (tokens[0] == "data:") break;
00196   }
00197 
00198   /* read the data */
00199   
00200 
00201   Array<double> coords;
00202   coords.reserve(nNodes*dimension);
00203   Array<Array<int> > connect(nElemBlocks);
00204   Array<Array<int> > sideSetElems(nSideSets);
00205   Array<Array<int> > sideSetFacets(nSideSets);
00206   Array<Array<int> > nodeSetNodes(nNodeSets);
00207 
00208   bool doneWithData = false;
00209   while(!doneWithData)
00210   {
00211     if (!getNextLine(*is, line, tokens, '#')) 
00212     {
00213       doneWithData = true;
00214       break;
00215     }
00216 
00217     if (tokens.size()==0) 
00218     {
00219 
00220       doneWithData=true;
00221       break;
00222     }
00223       
00224     if (tokens[0]=="coord")
00225     {
00226       bool done = false;
00227       for (int i=1; i<tokens.size(); i++)
00228       {
00229         if (tokens[i] == "=") continue;
00230         if (tokens[i] == ";") 
00231         {
00232           done = true;
00233           break;
00234         }
00235         coords.append(atof(StrUtils::before(tokens[i], ",")));
00236       }
00237       while (!done)
00238       {
00239         if (!getNextLine(*is, line, tokens, '#'))
00240         {
00241           doneWithData = true;
00242           break;
00243         }
00244 
00245         for (int i=0; i<tokens.size(); i++)
00246         {
00247           if (tokens[i] == "=") continue;
00248           if (tokens[i] == ";") 
00249           {
00250             done = true;
00251             break;
00252           }
00253           coords.append(atof(StrUtils::before(tokens[i], ",")));
00254         }
00255       }
00256       continue;
00257     }
00258     /* see if the line lists connectivity data for a block */
00259     for (int b=0; b<nElemBlocks; b++)
00260     {
00261       if (tokens[0] == "connect" + Teuchos::toString(b+1))
00262       {
00263         connect[b].reserve(blockSizes[b]);
00264         bool done = false;
00265         for (int i=1; i<tokens.size(); i++)
00266         {
00267           if (tokens[i] == "=") continue;
00268           if (tokens[i] == ";") 
00269           {
00270             done = true;
00271             break;
00272           }
00273           connect[b].append(atoi(StrUtils::before(tokens[i], ",")));
00274         }
00275         while (!done)
00276         {
00277           if (!getNextLine(*is, line, tokens, '#'))
00278           {
00279             doneWithData = true;
00280             break;
00281           }
00282 
00283           for (int i=0; i<tokens.size(); i++)
00284           {
00285             if (tokens[i] == "=") continue;
00286             if (tokens[i] == ";") 
00287             {
00288               done = true;
00289               break;
00290             }
00291             connect[b].append(atoi(StrUtils::before(tokens[i], ",")));
00292           }
00293         }
00294         continue;
00295       }
00296     }
00297 
00298     /* see if the line lists side set element numbers */
00299     for (int s=0; s<nSideSets; s++)
00300     {
00301       if (tokens[0] == "elem_ss" + Teuchos::toString(s+1))
00302       {
00303         sideSetElems[s].reserve(sideSetSizes[s]);
00304         bool done = false;
00305         for (int i=1; i<tokens.size(); i++)
00306         {
00307           if (tokens[i] == "=") continue;
00308           if (tokens[i] == ";") 
00309           {
00310             done = true;
00311             break;
00312           }
00313           sideSetElems[s].append(atoi(StrUtils::before(tokens[i], ",")));
00314         }
00315         while (!done)
00316         {
00317           if (!getNextLine(*is, line, tokens, '#'))
00318           {
00319             doneWithData = true;
00320             break;
00321           }
00322 
00323           for (int i=0; i<tokens.size(); i++)
00324           {
00325             if (tokens[i] == "=") continue;
00326             if (tokens[i] == ";") 
00327             {
00328               done = true;
00329               break;
00330             }
00331             sideSetElems[s].append(atoi(StrUtils::before(tokens[i], ",")));
00332           }
00333         }
00334         continue;
00335       }
00336     }
00337 
00338     /* see if the line lists side set facet numbers */
00339     for (int s=0; s<nSideSets; s++)
00340     {
00341       if (tokens[0] == "side_ss" + Teuchos::toString(s+1))
00342       {
00343         sideSetFacets[s].reserve(sideSetSizes[s]);
00344         bool done = false;
00345         for (int i=1; i<tokens.size(); i++)
00346         {
00347           if (tokens[i] == "=") continue;
00348           if (tokens[i] == ";") 
00349           {
00350             done = true;
00351             break;
00352           }
00353           sideSetFacets[s].append(atoi(StrUtils::before(tokens[i], ",")));
00354         }
00355         while (!done)
00356         {
00357           if (!getNextLine(*is, line, tokens, '#'))
00358           {
00359             doneWithData = true;
00360             break;
00361           }
00362           for (int i=0; i<tokens.size(); i++)
00363           {
00364             if (tokens[i] == "=") continue;
00365             if (tokens[i] == ";") 
00366             {
00367               done = true;
00368               break;
00369             }
00370             sideSetFacets[s].append(atoi(StrUtils::before(tokens[i], ",")));
00371           }
00372         }
00373         continue;
00374       }
00375     }
00376 
00377     /* see if the line lists node set node numbers */
00378     for (int s=0; s<nNodeSets; s++)
00379     {
00380       if (tokens[0] == "node_ns" + Teuchos::toString(s+1))
00381       {
00382         nodeSetNodes[s].reserve(nodeSetSizes[s]);
00383         bool done = false;
00384         for (int i=1; i<tokens.size(); i++)
00385         {
00386           if (tokens[i] == "=") continue;
00387           if (tokens[i] == ";") 
00388           {
00389             done = true;
00390             break;
00391           }
00392           nodeSetNodes[s].append(atoi(StrUtils::before(tokens[i], ",")));
00393         }
00394         while (!done)
00395         {
00396           if (!getNextLine(*is, line, tokens, '#'))
00397           {
00398             doneWithData = true;
00399             break;
00400           }
00401           for (int i=0; i<tokens.size(); i++)
00402           {
00403             if (tokens[i] == "=") continue;
00404             if (tokens[i] == ";") 
00405             {
00406               done = true;
00407               break;
00408             }
00409             nodeSetNodes[s].append(atoi(StrUtils::before(tokens[i], ",")));
00410           }
00411         }
00412         continue;
00413       }
00414     }
00415   }
00416 
00417 
00418 
00419   /* now we can build the mesh */
00420   mesh = createMesh(dimension);
00421 
00422   /* do some consistency checks */
00423   TEUCHOS_TEST_FOR_EXCEPTION(dimension * nNodes != coords.size(), std::runtime_error,
00424     "bad coordinate array in exodus reader");
00425 
00426   for (int b=0; b<nElemBlocks; b++)
00427   {
00428     TEUCHOS_TEST_FOR_EXCEPTION(blockSizes[b]*nodesPerElem[b] != connect[b].size(), std::runtime_error,
00429       "bad connectivity array for block " << b << " in exodus reader");
00430   }
00431 
00432   for (int s=0; s<nSideSets; s++)
00433   {
00434     TEUCHOS_TEST_FOR_EXCEPTION(sideSetElems[s].size() != sideSetFacets[s].size(), std::runtime_error,
00435       "inconsistent side set specification for ss=" << s 
00436       << " in exodus reader ");
00437   }
00438 
00439   /* add the points to the mesh */
00440   for (int n=0; n<nNodes; n++)
00441   {
00442     Point x;
00443     if (dimension==2)
00444     {
00445       x = Point(coords[n], coords[nNodes+n]);
00446     }
00447     else
00448     {
00449       x = Point(coords[n], coords[nNodes+n], coords[2*nNodes+n]);
00450     }
00451     mesh.addVertex(n, x, 0, 0);
00452   }
00453 
00454 
00455   /* add the elements */
00456   int lid=0;
00457   for (int b=0; b<nElemBlocks; b++)
00458   {
00459     int n = 0;
00460     for (int e=0; e<blockSizes[b]; e++, n+=nodesPerElem[b], lid++)
00461     {
00462       if (dimension==2)
00463       {
00464         mesh.addElement(lid, tuple(connect[b][n]-1, connect[b][n+1]-1, connect[b][n+2]-1), 0, b+1);
00465       }
00466       else
00467       {
00468         mesh.addElement(lid, 
00469           tuple(connect[b][n]-1, connect[b][n+1]-1, connect[b][n+2]-1, connect[b][n+3]-1),
00470           0, b+1);
00471       }
00472     }
00473   }
00474 
00475   mesh.freezeTopology();
00476 
00477   /* label the side sets */
00478 
00479   for (int s=0; s<nSideSets; s++)
00480   {
00481     for (int n=0; n<sideSetSizes[s]; n++)
00482     {
00483       int elemID = sideSetElems[s][n];
00484       int facetNum = sideSetFacets[s][n];
00485       int fsign;
00486       int sideLID = mesh.facetLID(dimension, elemID-1, dimension-1, 
00487         facetNum-1,fsign);
00488       mesh.setLabel(dimension-1, sideLID, s+1);
00489     }
00490   }
00491 
00492   /* label the node sets */
00493   for (int s=0; s<nNodeSets; s++)
00494   {
00495     for (int n=0; n<nodeSetSizes[s]; n++)
00496     {
00497       int nodeNum = nodeSetNodes[s][n]-1;
00498       mesh.setLabel(0, nodeNum, s+1);
00499     }
00500   }
00501 
00502   return mesh;
00503 }
00504 

Site Contact