SundanceVTKWriter.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                              Sundance
00005 //                 Copyright (2005) Sandia Corporation
00006 // 
00007 // Copyright (year first published) Sandia Corporation.  Under the terms 
00008 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 
00009 // retains certain rights in this software.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //                                                                                 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA                                                                                
00025 // Questions? Contact Kevin Long (krlong@sandia.gov), 
00026 // Sandia National Laboratories, Livermore, California, USA
00027 // 
00028 // ************************************************************************
00029 /* @HEADER@ */
00030 
00031 #include "SundanceVTKWriter.hpp"
00032 #include "PlayaExceptions.hpp"
00033 #include "SundanceOut.hpp"
00034 #include "PlayaTabs.hpp"
00035 #include "Teuchos_XMLObject.hpp"
00036 
00037 
00038 
00039 using namespace Sundance;
00040 using namespace Sundance;
00041 using namespace Sundance;
00042 using namespace Teuchos;
00043 
00044 
00045 
00046 
00047 void VTKWriter::write() const 
00048 {
00049   lowLevelWrite(filename(), false);
00050   if (nProc() > 1 && myRank()==0) lowLevelWrite(filename(), true);
00051 }
00052 
00053 void VTKWriter::lowLevelWrite(const std::string& filename, bool isPHeader) const 
00054 {
00055   std::string PHeader = "";
00056   if (isPHeader) PHeader="P";
00057 
00058   std::string f = filename;
00059   
00060   if (isPHeader) f = f + ".pvtu";
00061   else if (nProc() > 1) 
00062     {
00063       f = f + Teuchos::toString(myRank()) + ".vtu";
00064     }
00065   else
00066     {
00067       f = f + ".vtu";
00068     }
00069   
00070   SUNDANCE_VERB_MEDIUM("writing VTK file " << f);
00071 
00072   std::ofstream os(f.c_str());
00073 
00074   XMLObject head("VTKFile");
00075   head.addAttribute("type", PHeader + "UnstructuredGrid");
00076   head.addAttribute("version", "0.1");
00077   
00078   os << head.header() << std::endl;
00079 
00080   for (int i=0; i<comments().length(); i++)
00081     {
00082       os << "<!-- " << comments()[i] << " -->" << std::endl;
00083     }
00084 
00085   XMLObject ug(PHeader + "UnstructuredGrid");
00086   os << ug.header() << std::endl;
00087 
00088   if (isPHeader)
00089     {
00090       writePoints(os, isPHeader);
00091       writePointData(os, isPHeader);
00092       writeCellData(os, isPHeader);
00093       for (int p=0; p<nProc(); p++)
00094         {
00095           XMLObject pc("Piece");
00096           std::string pfile = filename + Teuchos::toString(p) + ".vtu";
00097           size_t pos = pfile.find_last_of("/");
00098           if (pos != std::string::npos)
00099           {
00100             pfile = pfile.substr(pos+1);
00101           }
00102           pc.addAttribute("Source", pfile);
00103           os << pc << std::endl;
00104         }
00105     }
00106   else
00107     {
00108       XMLObject pc("Piece");
00109       pc.addAttribute("NumberOfPoints", Teuchos::toString(mesh().numCells(0)));
00110       pc.addAttribute("NumberOfCells", Teuchos::toString(mesh().numCells(mesh().spatialDim())));
00111 
00112       os << pc.header() << std::endl;
00113 
00114       writePoints(os, false);
00115       writeCells(os);
00116       writePointData(os, false);
00117       writeCellData(os, false);
00118 
00119       os << pc.footer() << std::endl;
00120     }
00121 
00122   os << ug.footer() << std::endl;
00123   os << head.footer() << std::endl;
00124 }
00125 
00126 void VTKWriter::writePoints(std::ostream& os, bool isPHeader) const 
00127 {
00128   std::string PHeader = "";
00129   if (isPHeader) PHeader="P";
00130   XMLObject pts(PHeader + "Points");
00131 
00132   os << pts.header() << std::endl;
00133 
00134   XMLObject xml(PHeader + "DataArray");
00135   xml.addAttribute("NumberOfComponents", "3");
00136   xml.addAttribute("type", "Float32");
00137   xml.addAttribute("format", "ascii");
00138 
00139   os << xml.header() << std::endl;
00140 
00141   /* write the points, unless this call is for the dummy header on the root proc */
00142   if (!isPHeader)
00143     {
00144       int np = mesh().numCells(0);
00145       int dim = mesh().spatialDim();
00146       
00147       for (int i=0; i<np; i++)
00148         {
00149           const Point& x = mesh().nodePosition(i);
00150           
00151           for (int d=0; d<dim; d++)
00152             {
00153               os << x[d] << " ";
00154             }
00155           for (int d=dim; d<3; d++)
00156             {
00157               os << "0.0 ";
00158             }
00159           os << std::endl;
00160         }
00161     }
00162 
00163   os << xml.footer() << std::endl;
00164 
00165   os << pts.footer() << std::endl;
00166 }
00167 
00168 
00169 void VTKWriter::writeCells(std::ostream& os) const 
00170 {
00171   XMLObject cells("Cells");
00172   os << cells.header() << std::endl;
00173 
00174   XMLObject conn("DataArray");
00175   conn.addAttribute("type", "Int32");
00176   conn.addAttribute("Name", "connectivity");
00177   conn.addAttribute("format", "ascii");
00178 
00179   int dim = mesh().spatialDim();
00180   int nc = mesh().numCells(dim);
00181   int dummySign;
00182 
00183   os << conn.header() << std::endl;
00184   CellType cellType = mesh().cellType(dim);
00185   
00186   for (int c=0; c<nc; c++)
00187     {
00188       int nNodes = mesh().numFacets( dim , c , 0 );
00189 
00190     switch(cellType)
00191       {
00192       case TriangleCell: case LineCell: case TetCell:
00193             for (int i=0; i<nNodes; i++)
00194               {
00195                 os << " " << mesh().facetLID(dim,c,0,i,dummySign);
00196               }
00197             os << std::endl;
00198         break;
00199       case QuadCell:  // for quads we have different order
00200               os << " " << mesh().facetLID(dim,c,0,0,dummySign);
00201               os << " " << mesh().facetLID(dim,c,0,1,dummySign);
00202               os << " " << mesh().facetLID(dim,c,0,3,dummySign);
00203               os << " " << mesh().facetLID(dim,c,0,2,dummySign);
00204               os << std::endl;
00205         break;
00206       case BrickCell:  // for quads we have different order
00207               os << " " << mesh().facetLID(dim,c,0,0,dummySign);
00208               os << " " << mesh().facetLID(dim,c,0,1,dummySign);
00209               os << " " << mesh().facetLID(dim,c,0,2,dummySign);
00210               os << " " << mesh().facetLID(dim,c,0,3,dummySign);
00211               os << " " << mesh().facetLID(dim,c,0,4,dummySign);
00212               os << " " << mesh().facetLID(dim,c,0,5,dummySign);
00213               os << " " << mesh().facetLID(dim,c,0,6,dummySign);
00214               os << " " << mesh().facetLID(dim,c,0,7,dummySign);
00215               os << std::endl;
00216         break;
00217             default:
00218                TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "call type " << cellType <<
00219                    " not handled in VTKWriter::writeCells()");
00220       }
00221     }
00222   
00223   os << conn.footer() << std::endl;
00224 
00225 
00226   XMLObject offsets("DataArray");
00227   offsets.addAttribute("type", "Int32");
00228   offsets.addAttribute("Name", "offsets");
00229   offsets.addAttribute("format", "ascii");
00230   
00231   os << offsets.header() << std::endl;
00232 
00233   int count = 0;
00234   for (int c=0; c<nc; c++)
00235     {
00236       count += mesh().numFacets(dim, c, 0);
00237       os << count << std::endl;
00238     }
00239 
00240   os << offsets.footer() << std::endl;
00241 
00242   XMLObject types("DataArray");
00243   types.addAttribute("type", "UInt8");
00244   types.addAttribute("Name", "types");
00245   types.addAttribute("format", "ascii");
00246 
00247   os << types.header() << std::endl;
00248 
00249   for (int c=0; c<nc; c++)
00250     {
00251 
00252       int vtkCode = 0;
00253       switch(cellType)
00254         {
00255         case TriangleCell:
00256           vtkCode = 5;
00257           break;
00258         case QuadCell:
00259           vtkCode = 9;
00260           break;
00261         case TetCell:
00262           vtkCode = 10;
00263           break;
00264         case BrickCell:
00265           vtkCode = 11;
00266           break;
00267         default:
00268           TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00269                              "call type " << cellType << " not handled "
00270                              "in VTKWriter::writeCells()");
00271         }
00272       os << vtkCode << std::endl;
00273     }
00274 
00275   os << types.footer() << std::endl;
00276 
00277   os << cells.footer() << std::endl;
00278 }
00279 
00280 void VTKWriter::writePointData(std::ostream& os, bool isPHeader) const 
00281 {
00282   std::string PHeader = "";
00283   if (isPHeader) PHeader="P";
00284 
00285   XMLObject xml(PHeader + "PointData");
00286 
00287   if (pointVectorNames().length() > 0) xml.addAttribute("Vectors", pointVectorNames()[0]);
00288   if (pointScalarNames().length() > 0) xml.addAttribute("Scalars", pointScalarNames()[0]);
00289 
00290   os << xml.header() << std::endl;
00291 
00292   for (int i=0; i<pointScalarNames().length(); i++)
00293     {
00294       writeDataArray(os, pointScalarNames()[i], pointScalarFields()[i], isPHeader, true);
00295     }
00296 
00297   for (int i=0; i<pointVectorNames().length(); i++)
00298     {
00299       writeDataArray(os, pointVectorNames()[i], pointVectorFields()[i], isPHeader, true);
00300     }
00301 
00302   os << xml.footer() << std::endl;
00303 }
00304 
00305 void VTKWriter::writeCellData(std::ostream& os, bool isPHeader) const 
00306 {
00307   std::string PHeader = "";
00308   if (isPHeader) PHeader="P";
00309 
00310   XMLObject xml(PHeader + "CellData");
00311 
00312   if (cellVectorNames().length() > 0) xml.addAttribute("Vectors", cellVectorNames()[0]);
00313   if (cellScalarNames().length() > 0) xml.addAttribute("Scalars", cellScalarNames()[0]);
00314 
00315   os << xml.header() << std::endl;
00316 
00317   for (int i=0; i<cellScalarNames().length(); i++)
00318     {
00319       writeDataArray(os, cellScalarNames()[i], cellScalarFields()[i], isPHeader, false);
00320     }
00321 
00322   /* ---- vector plot works intermeadaty for VTK's */
00323   for (int i=0; i<cellVectorNames().length(); i++)
00324     {
00325       writeDataArray(os, cellVectorNames()[i], cellVectorFields()[i], isPHeader, false);
00326     }
00327 
00328   os << xml.footer() << std::endl;
00329 }
00330 
00331 
00332 void VTKWriter::writeDataArray(std::ostream& os, const std::string& name, 
00333                                const RCP<FieldBase>& expr, bool isPHeader, bool isPointData) const 
00334 {
00335   std::string PHeader = "";
00336   if (isPHeader) PHeader="P";
00337 
00338   XMLObject xml(PHeader + "DataArray");
00339   xml.addAttribute("type", "Float32");
00340   xml.addAttribute("Name", name);
00341   xml.addAttribute("format", "ascii");
00342   
00343   if (expr->numElems() > 1)
00344     {
00345     // Since we are plotting always in 3D the vector components have 3 component and not "expr->numElems()"
00346       xml.addAttribute("NumberOfComponents", "3" );
00347     }
00348   
00349   os << xml.header() << std::endl;
00350 
00351   /* write the point|cell data, unless this is a parallel header */
00352   if (!isPHeader)
00353     {
00354 
00355       if (isPointData)
00356         {
00357           int numNodes = mesh().numCells(0);
00358 
00359           for (int i=0; i<numNodes; i++)
00360             {
00361               for (int j=0; j < expr->numElems(); j++)
00362                 {
00363                   if (expr->isDefined(0,i,j)){
00364                   double val = expr->getData(0, i, j);
00365                     val = (fabs(val) > 1e-16) ? val : 0.0;
00366                     os << (float) val << std::endl;
00367                   }else
00368                     os << undefinedValue() << std::endl;
00369                 }
00370               // write the rest with 0.0 if it is a zero component
00371               if (expr->numElems() > 1)
00372                 for (int j= expr->numElems(); j < 3 ; j++)
00373                   os << "0.0 " << std::endl;
00374             }
00375         }
00376       else
00377         {
00378           int dim = mesh().spatialDim();
00379           int nc = mesh().numCells(dim);
00380           
00381           for (int c=0; c<nc; c++)
00382             {
00383               for (int j=0; j < expr->numElems(); j++)
00384                 {
00385                   if (expr->isDefined(dim,c,j)){
00386                     double val = expr->getData(dim, c, j);
00387                     val = (fabs(val) > 1e-16) ? val : 0.0;
00388                     os << (float) val << std::endl;
00389                   }else
00390                     os << undefinedValue() << std::endl;
00391                 }
00392               // write the rest with 0.0 if it is a zero component
00393               if (expr->numElems() > 1)
00394                 for (int j= expr->numElems(); j < 3 ; j++)
00395                   os << "0.0 " << std::endl;
00396             }
00397         }
00398     }
00399 
00400   os << xml.footer() << std::endl;
00401 }
00402 

Site Contact