SundanceVTKWriter.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 #include "SundanceVTKWriter.hpp"
00043 #include "PlayaExceptions.hpp"
00044 #include "SundanceOut.hpp"
00045 #include "PlayaTabs.hpp"
00046 #include "Teuchos_XMLObject.hpp"
00047 
00048 
00049 
00050 using namespace Sundance;
00051 using namespace Sundance;
00052 using namespace Sundance;
00053 using namespace Teuchos;
00054 
00055 
00056 
00057 
00058 void VTKWriter::write() const 
00059 {
00060   lowLevelWrite(filename(), false);
00061   if (nProc() > 1 && myRank()==0) lowLevelWrite(filename(), true);
00062 }
00063 
00064 void VTKWriter::lowLevelWrite(const std::string& filename, bool isPHeader) const 
00065 {
00066   std::string PHeader = "";
00067   if (isPHeader) PHeader="P";
00068 
00069   std::string f = filename;
00070   
00071   if (isPHeader) f = f + ".pvtu";
00072   else if (nProc() > 1) 
00073     {
00074       f = f + Teuchos::toString(myRank()) + ".vtu";
00075     }
00076   else
00077     {
00078       f = f + ".vtu";
00079     }
00080   
00081   SUNDANCE_VERB_MEDIUM("writing VTK file " << f);
00082 
00083   std::ofstream os(f.c_str());
00084 
00085   XMLObject head("VTKFile");
00086   head.addAttribute("type", PHeader + "UnstructuredGrid");
00087   head.addAttribute("version", "0.1");
00088   
00089   os << head.header() << std::endl;
00090 
00091   for (int i=0; i<comments().length(); i++)
00092     {
00093       os << "<!-- " << comments()[i] << " -->" << std::endl;
00094     }
00095 
00096   XMLObject ug(PHeader + "UnstructuredGrid");
00097   os << ug.header() << std::endl;
00098 
00099   if (isPHeader)
00100     {
00101       writePoints(os, isPHeader);
00102       writePointData(os, isPHeader);
00103       writeCellData(os, isPHeader);
00104       for (int p=0; p<nProc(); p++)
00105         {
00106           XMLObject pc("Piece");
00107           std::string pfile = filename + Teuchos::toString(p) + ".vtu";
00108           size_t pos = pfile.find_last_of("/");
00109           if (pos != std::string::npos)
00110           {
00111             pfile = pfile.substr(pos+1);
00112           }
00113           pc.addAttribute("Source", pfile);
00114           os << pc << std::endl;
00115         }
00116     }
00117   else
00118     {
00119       XMLObject pc("Piece");
00120       pc.addAttribute("NumberOfPoints", Teuchos::toString(mesh().numCells(0)));
00121       pc.addAttribute("NumberOfCells", Teuchos::toString(mesh().numCells(mesh().spatialDim())));
00122 
00123       os << pc.header() << std::endl;
00124 
00125       writePoints(os, false);
00126       writeCells(os);
00127       writePointData(os, false);
00128       writeCellData(os, false);
00129 
00130       os << pc.footer() << std::endl;
00131     }
00132 
00133   os << ug.footer() << std::endl;
00134   os << head.footer() << std::endl;
00135 }
00136 
00137 void VTKWriter::writePoints(std::ostream& os, bool isPHeader) const 
00138 {
00139   std::string PHeader = "";
00140   if (isPHeader) PHeader="P";
00141   XMLObject pts(PHeader + "Points");
00142 
00143   os << pts.header() << std::endl;
00144 
00145   XMLObject xml(PHeader + "DataArray");
00146   xml.addAttribute("NumberOfComponents", "3");
00147   xml.addAttribute("type", "Float32");
00148   xml.addAttribute("format", "ascii");
00149 
00150   os << xml.header() << std::endl;
00151 
00152   /* write the points, unless this call is for the dummy header on the root proc */
00153   if (!isPHeader)
00154     {
00155       int np = mesh().numCells(0);
00156       int dim = mesh().spatialDim();
00157       
00158       for (int i=0; i<np; i++)
00159         {
00160           const Point& x = mesh().nodePosition(i);
00161           
00162           for (int d=0; d<dim; d++)
00163             {
00164               os << x[d] << " ";
00165             }
00166           for (int d=dim; d<3; d++)
00167             {
00168               os << "0.0 ";
00169             }
00170           os << std::endl;
00171         }
00172     }
00173 
00174   os << xml.footer() << std::endl;
00175 
00176   os << pts.footer() << std::endl;
00177 }
00178 
00179 
00180 void VTKWriter::writeCells(std::ostream& os) const 
00181 {
00182   XMLObject cells("Cells");
00183   os << cells.header() << std::endl;
00184 
00185   XMLObject conn("DataArray");
00186   conn.addAttribute("type", "Int32");
00187   conn.addAttribute("Name", "connectivity");
00188   conn.addAttribute("format", "ascii");
00189 
00190   int dim = mesh().spatialDim();
00191   int nc = mesh().numCells(dim);
00192   int dummySign;
00193 
00194   os << conn.header() << std::endl;
00195   CellType cellType = mesh().cellType(dim);
00196   
00197   for (int c=0; c<nc; c++)
00198     {
00199       int nNodes = mesh().numFacets( dim , c , 0 );
00200 
00201     switch(cellType)
00202       {
00203       case TriangleCell: case LineCell: case TetCell:
00204             for (int i=0; i<nNodes; i++)
00205               {
00206                 os << " " << mesh().facetLID(dim,c,0,i,dummySign);
00207               }
00208             os << std::endl;
00209         break;
00210       case QuadCell:  // for quads we have different order
00211               os << " " << mesh().facetLID(dim,c,0,0,dummySign);
00212               os << " " << mesh().facetLID(dim,c,0,1,dummySign);
00213               os << " " << mesh().facetLID(dim,c,0,3,dummySign);
00214               os << " " << mesh().facetLID(dim,c,0,2,dummySign);
00215               os << std::endl;
00216         break;
00217       case BrickCell:  // for quads we have different order
00218               os << " " << mesh().facetLID(dim,c,0,0,dummySign);
00219               os << " " << mesh().facetLID(dim,c,0,1,dummySign);
00220               os << " " << mesh().facetLID(dim,c,0,2,dummySign);
00221               os << " " << mesh().facetLID(dim,c,0,3,dummySign);
00222               os << " " << mesh().facetLID(dim,c,0,4,dummySign);
00223               os << " " << mesh().facetLID(dim,c,0,5,dummySign);
00224               os << " " << mesh().facetLID(dim,c,0,6,dummySign);
00225               os << " " << mesh().facetLID(dim,c,0,7,dummySign);
00226               os << std::endl;
00227         break;
00228             default:
00229                TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "call type " << cellType <<
00230                    " not handled in VTKWriter::writeCells()");
00231       }
00232     }
00233   
00234   os << conn.footer() << std::endl;
00235 
00236 
00237   XMLObject offsets("DataArray");
00238   offsets.addAttribute("type", "Int32");
00239   offsets.addAttribute("Name", "offsets");
00240   offsets.addAttribute("format", "ascii");
00241   
00242   os << offsets.header() << std::endl;
00243 
00244   int count = 0;
00245   for (int c=0; c<nc; c++)
00246     {
00247       count += mesh().numFacets(dim, c, 0);
00248       os << count << std::endl;
00249     }
00250 
00251   os << offsets.footer() << std::endl;
00252 
00253   XMLObject types("DataArray");
00254   types.addAttribute("type", "UInt8");
00255   types.addAttribute("Name", "types");
00256   types.addAttribute("format", "ascii");
00257 
00258   os << types.header() << std::endl;
00259 
00260   for (int c=0; c<nc; c++)
00261     {
00262 
00263       int vtkCode = 0;
00264       switch(cellType)
00265         {
00266         case TriangleCell:
00267           vtkCode = 5;
00268           break;
00269         case QuadCell:
00270           vtkCode = 9;
00271           break;
00272         case TetCell:
00273           vtkCode = 10;
00274           break;
00275         case BrickCell:
00276           vtkCode = 11;
00277           break;
00278         default:
00279           TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00280                              "call type " << cellType << " not handled "
00281                              "in VTKWriter::writeCells()");
00282         }
00283       os << vtkCode << std::endl;
00284     }
00285 
00286   os << types.footer() << std::endl;
00287 
00288   os << cells.footer() << std::endl;
00289 }
00290 
00291 void VTKWriter::writePointData(std::ostream& os, bool isPHeader) const 
00292 {
00293   std::string PHeader = "";
00294   if (isPHeader) PHeader="P";
00295 
00296   XMLObject xml(PHeader + "PointData");
00297 
00298   if (pointVectorNames().length() > 0) xml.addAttribute("Vectors", pointVectorNames()[0]);
00299   if (pointScalarNames().length() > 0) xml.addAttribute("Scalars", pointScalarNames()[0]);
00300 
00301   os << xml.header() << std::endl;
00302 
00303   for (int i=0; i<pointScalarNames().length(); i++)
00304     {
00305       writeDataArray(os, pointScalarNames()[i], pointScalarFields()[i], isPHeader, true);
00306     }
00307 
00308   for (int i=0; i<pointVectorNames().length(); i++)
00309     {
00310       writeDataArray(os, pointVectorNames()[i], pointVectorFields()[i], isPHeader, true);
00311     }
00312 
00313   os << xml.footer() << std::endl;
00314 }
00315 
00316 void VTKWriter::writeCellData(std::ostream& os, bool isPHeader) const 
00317 {
00318   std::string PHeader = "";
00319   if (isPHeader) PHeader="P";
00320 
00321   XMLObject xml(PHeader + "CellData");
00322 
00323   if (cellVectorNames().length() > 0) xml.addAttribute("Vectors", cellVectorNames()[0]);
00324   if (cellScalarNames().length() > 0) xml.addAttribute("Scalars", cellScalarNames()[0]);
00325 
00326   os << xml.header() << std::endl;
00327 
00328   for (int i=0; i<cellScalarNames().length(); i++)
00329     {
00330       writeDataArray(os, cellScalarNames()[i], cellScalarFields()[i], isPHeader, false);
00331     }
00332 
00333   /* ---- vector plot works intermeadaty for VTK's */
00334   for (int i=0; i<cellVectorNames().length(); i++)
00335     {
00336       writeDataArray(os, cellVectorNames()[i], cellVectorFields()[i], isPHeader, false);
00337     }
00338 
00339   os << xml.footer() << std::endl;
00340 }
00341 
00342 
00343 void VTKWriter::writeDataArray(std::ostream& os, const std::string& name, 
00344                                const RCP<FieldBase>& expr, bool isPHeader, bool isPointData) const 
00345 {
00346   std::string PHeader = "";
00347   if (isPHeader) PHeader="P";
00348 
00349   XMLObject xml(PHeader + "DataArray");
00350   xml.addAttribute("type", "Float32");
00351   xml.addAttribute("Name", name);
00352   xml.addAttribute("format", "ascii");
00353   
00354   if (expr->numElems() > 1)
00355     {
00356     // Since we are plotting always in 3D the vector components have 3 component and not "expr->numElems()"
00357       xml.addAttribute("NumberOfComponents", "3" );
00358     }
00359   
00360   os << xml.header() << std::endl;
00361 
00362   /* write the point|cell data, unless this is a parallel header */
00363   if (!isPHeader)
00364     {
00365 
00366       if (isPointData)
00367         {
00368           int numNodes = mesh().numCells(0);
00369 
00370           for (int i=0; i<numNodes; i++)
00371             {
00372               for (int j=0; j < expr->numElems(); j++)
00373                 {
00374                   if (expr->isDefined(0,i,j)){
00375                   double val = expr->getData(0, i, j);
00376                     val = (fabs(val) > 1e-16) ? val : 0.0;
00377                     os << (float) val << std::endl;
00378                   }else
00379                     os << undefinedValue() << std::endl;
00380                 }
00381               // write the rest with 0.0 if it is a zero component
00382               if (expr->numElems() > 1)
00383                 for (int j= expr->numElems(); j < 3 ; j++)
00384                   os << "0.0 " << std::endl;
00385             }
00386         }
00387       else
00388         {
00389           int dim = mesh().spatialDim();
00390           int nc = mesh().numCells(dim);
00391           
00392           for (int c=0; c<nc; c++)
00393             {
00394               for (int j=0; j < expr->numElems(); j++)
00395                 {
00396                   if (expr->isDefined(dim,c,j)){
00397                     double val = expr->getData(dim, c, j);
00398                     val = (fabs(val) > 1e-16) ? val : 0.0;
00399                     os << (float) val << std::endl;
00400                   }else
00401                     os << undefinedValue() << std::endl;
00402                 }
00403               // write the rest with 0.0 if it is a zero component
00404               if (expr->numElems() > 1)
00405                 for (int j= expr->numElems(); j < 3 ; j++)
00406                   os << "0.0 " << std::endl;
00407             }
00408         }
00409     }
00410 
00411   os << xml.footer() << std::endl;
00412 }
00413 

Site Contact