SundanceMeshIOUtils.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 "SundanceMeshIOUtils.hpp"
00044 #include "PlayaOut.hpp"
00045 #include "PlayaTabs.hpp"
00046 
00047 
00048 namespace Sundance
00049 {
00050 using namespace Sundance;
00051 using namespace Sundance;
00052 using namespace Sundance;
00053 using namespace Teuchos;
00054   using std::ifstream;
00055   using std::ofstream;
00056 
00057 
00058 Expr readNodalFields(const MeshSource& mesher, const Mesh& mesh,
00059   const VectorType<double>& vecType, int verb)
00060 {
00061   Tabs tab0(0);
00062   PLAYA_ROOT_MSG1(verb, tab0 << "begin readNodalFields()");
00063   Tabs tab1;
00064 
00065   /* Read the attributes */
00066   RCP<Array<Array<double> > > elemAttr;
00067   RCP<Array<Array<double> > > vertAttr;
00068 
00069   PLAYA_ROOT_MSG2(verb, tab1 << "reading attributes");
00070   mesher.getAttributes(vertAttr, elemAttr);
00071   int nAttrs = vertAttr->size();
00072   PLAYA_ROOT_MSG2(verb, tab1 << "found " << nAttrs << " attributes");
00073   const Array<Array<double> >& funcVals = *vertAttr;
00074   
00075   /* create an empty (zero-valued) discrete function */
00076   Array<BasisFamily> bas(nAttrs);
00077   for (int i=0; i<bas.size(); i++) bas[i] = new Lagrange(1);
00078   PLAYA_ROOT_MSG2(verb, tab1 << "forming discrete space");
00079   DiscreteSpace discSpace(mesh, bas, vecType);
00080   PLAYA_ROOT_MSG2(verb, tab1 << "forming discrete function");
00081   Expr u0 = new DiscreteFunction(discSpace, 0.0, "u0");
00082   
00083   /* get from the discrete function a pointer to the underlying
00084    * vector and a pointer to the node-to-dof map. */
00085   Vector<double> vec = DiscreteFunction::discFunc(u0)->getVector();
00086   const RCP<DOFMapBase>& dofMap 
00087     = DiscreteFunction::discFunc(u0)->map();
00088   
00089   /* run through the data, putting each entry into its correct place in
00090    * the vector as indexed by the dof number, NOT the node number. */
00091   PLAYA_ROOT_MSG2(verb, tab1 << "filling discrete function");
00092   Array<int> dofs(1);
00093   for (int i=0; i<mesh.numCells(0); i++)
00094   {
00095     Tabs tab2;
00096     PLAYA_ROOT_MSG3(verb, tab2 << "node i=" << i);
00097     for (int f=0; f<nAttrs; f++)
00098     {
00099       Tabs tab3;
00100       /* look up the dof for the f-th function on this node */
00101       dofMap->getDOFsForCell(0, i, f, dofs);
00102       int dof = dofs[0];
00103       PLAYA_ROOT_MSG3(verb, tab3 << "f=" << f << " dof=" << dof << " val=" 
00104         << funcVals[f][i]);
00105       loadable(vec)->setElement(dof, funcVals[f][i]);
00106     }
00107   }
00108   
00109   /* Reset the vector */
00110   DiscreteFunction::discFunc(u0)->setVector(vec);
00111 
00112   PLAYA_ROOT_MSG1(verb, tab0 << "done readNodalFields()");
00113   return u0;
00114 }
00115 
00116 
00117 
00118 
00119 
00120 Expr readSerialGridField(const std::string& gridFile, 
00121   double ax, double bx,
00122   double ay, double by,
00123   const VectorType<double>& vecType,
00124   const MeshType& meshType,
00125   Mesh& mesh)
00126 {
00127   ifstream is(gridFile.c_str());
00128   int nNodes ;
00129   int nx;
00130   int ny;
00131   int nAttrs;
00132   is >> nx >> ny >> nAttrs;
00133   nNodes = nx*ny;
00134 
00135   Array<Array<double> > funcVals(nAttrs);
00136   for (int i=0; i<nAttrs; i++) funcVals[i].resize(nNodes);
00137   for (int i=0; i<nNodes; i++) 
00138   {
00139     for (int f=0; f<nAttrs; f++) 
00140     {
00141       is >> funcVals[f][i];
00142     }
00143   }
00144   
00145   
00146   MeshSource mesher = new PartitionedRectangleMesher(ax, bx, nx-1, 1,
00147     ay, by, ny-1, 1,
00148     meshType);
00149 
00150   mesh = mesher.getMesh();
00151 
00152   
00153   
00154   /* create an empty (zero-valued) discrete function */
00155   Array<BasisFamily> bas(nAttrs);
00156   for (int i=0; i<bas.size(); i++) bas[i] = new Lagrange(1);
00157   DiscreteSpace discSpace(mesh, bas, vecType);
00158   Expr u0 = new DiscreteFunction(discSpace, 0.0, "u0");
00159 
00160   
00161   /* get from the discrete function a pointer to the underlying
00162    * vector and a pointer to the node-to-dof map. */
00163   Vector<double> vec = DiscreteFunction::discFunc(u0)->getVector();
00164   const RCP<DOFMapBase>& dofMap 
00165     = DiscreteFunction::discFunc(u0)->map();
00166   
00167   /* run through the data, putting each entry into its correct place in
00168    * the vector as indexed by the dof number, NOT the node number. */
00169   Array<int> dofs(1);
00170   for (int i=0; i<mesh.numCells(0); i++)
00171   {
00172     for (int f=0; f<nAttrs; f++)
00173     {
00174       /* look up the dof for the f-th function on this node */
00175       dofMap->getDOFsForCell(0, i, f, dofs);
00176       int dof = dofs[0];
00177       loadable(vec)->setElement(dof, funcVals[f][i]);
00178     }
00179   }
00180   
00181   /* Reset the vector */
00182   DiscreteFunction::discFunc(u0)->setVector(vec);
00183 
00184   return u0;
00185 }
00186 
00187 double readbackTester(const std::string& infile, const MPIComm& comm, int verb) 
00188 {
00189   /* We will do our linear algebra using Epetra */
00190   VectorType<double> vecType = new EpetraVectorType();
00191   
00192   /* Read a mesh */
00193   Out::root() << "starting to read mesh " << std::endl;
00194   MeshType meshType = new BasicSimplicialMeshType();
00195   MeshSource mesher = new ExodusMeshReader(infile, meshType, verb, comm);
00196   Mesh mesh = mesher.getMesh();
00197 
00198   Out::root() << "done reading mesh " << std::endl;
00199   int dim = mesh.spatialDim();
00200   
00201   Expr x = new CoordExpr(0);
00202   Expr y = new CoordExpr(1);
00203   Expr z = new CoordExpr(2);
00204   
00205 
00206   /* Create a discrete function on the mesh */
00207   DiscreteSpace discSpace(mesh, new Lagrange(1), vecType);
00208   Out::root() << "done making discfunc " << std::endl;
00209   Expr u;
00210   if (dim==3)
00211   {
00212     L2Projector proj(discSpace, x*sin(x)*y*y+exp(z)*cos(y));
00213     u = proj.project();
00214   }
00215   else if (dim==2)
00216   {
00217     L2Projector proj(discSpace, x*sin(x)+x*x*cos(y));
00218     u = proj.project();
00219   }
00220   else
00221   {
00222     TEUCHOS_TEST_FOR_EXCEPT(dim != 2 && dim != 3);
00223   }
00224   Out::root() << "done projecting function " << std::endl;
00225   /* Compute some functional using the mesh */
00226   CellFilter interior = new MaximalCellFilter();
00227   QuadratureFamily quad = new GaussianQuadrature(2);
00228   Expr F = Integral(interior, u*u, quad);
00229   double fVal = evaluateIntegral(mesh, F);
00230   Out::root() << "done evaluating functional on original mesh" << std::endl;
00231   
00232   /* write the solution */
00233   FieldWriter w = new ExodusWriter("./readbackTest-out");
00234   w.addMesh(mesh);
00235   w.addField("u", new ExprFieldWrapper(u));
00236   w.write();
00237 
00238   /* Read back the solution */
00239   MeshSource mesher2 = new ExodusMeshReader("./readbackTest-out", meshType, verb, comm);
00240   Mesh mesh2 = mesher2.getMesh();
00241   Expr u2 = readNodalFields(mesher2, mesh2, vecType, verb);
00242   Out::root() << "done readback " << std::endl;
00243   
00244   /* Compute the functional using the second mesh */
00245   Expr F2 = Integral(interior, u2*u2, quad);
00246   double fVal2 = evaluateIntegral(mesh2, F2);
00247     
00248   Out::root() << "functional on original mesh = " << fVal << std::endl;
00249   Out::root() << "functional on readback mesh = " << fVal2 << std::endl;
00250 
00251   double diff = std::fabs(fVal - fVal2);
00252   Out::root() << "diff = " << diff << std::endl;
00253 
00254   return diff;
00255 }
00256 
00257    
00258 
00259 void invertMap(const Map<int,int>& in, Map<int,int>& out)
00260 {
00261   typedef Map<int,int>::const_iterator iter;
00262 
00263   for (iter i=in.begin(); i!=in.end(); i++)
00264   {
00265     out.put(i->second, i->first);
00266   }
00267 }
00268  
00269 void serialPartition(
00270   const RCP<SerialPartitionerBase>& part,
00271   int numProc,
00272   const MeshSource& mesher, 
00273   const std::string& outfile)
00274 {
00275   /* This should only be run on a single-process communicator. If run in 
00276    * parallel, this function should be called only by the "MPI_COMM_SELF" 
00277    * communicator of a single processor. */
00278   TEUCHOS_TEST_FOR_EXCEPTION(mesher.comm().getNProc() > 1, std::runtime_error,
00279     "serialPartition() should only be called from a "
00280     "single-process communicator");
00281 
00282   /* Make the mesh */
00283   Mesh mesh = mesher.getMesh();
00284   int dim = mesh.spatialDim();
00285 
00286   /* */
00287   FieldWriter origWriter = new ExodusWriter("orig-writback");
00288   origWriter.addMesh(mesh);
00289   origWriter.write();
00290 
00291   /* Set up maps between old (unpartitioned) and new (partitioned) element
00292    * and vertex indices. These will be needed to transfer fields, if any,
00293    * to the partitioned mesh */
00294   Array<Sundance::Map<int, int> > oldElemLIDToNewLIDMaps;
00295   Array<Sundance::Map<int, int> > oldVertLIDToNewLIDMaps;
00296 
00297   /* Carry out the partitioning */
00298   Array<Mesh> submesh = part->makeMeshParts(mesh, numProc,
00299     oldElemLIDToNewLIDMaps,
00300     oldVertLIDToNewLIDMaps
00301     );
00302 
00303   /* Read the fields, if any, from the old mesh */
00304   RCP<Array<Array<double> > > oldElemData;
00305   RCP<Array<Array<double> > > oldNodeData;
00306   mesher.getAttributes(oldNodeData, oldElemData);
00307 
00308   /* Find the process IDs that view each vertex */
00309   Array<Set<int> > vertViewers(mesh.numCells(0));
00310   for (int p=0; p<numProc; p++)
00311   {
00312     for (int v=0; v<submesh[p].numCells(0); v++)
00313     {
00314       int gid = submesh[p].mapLIDToGID(0,v);
00315       vertViewers[gid].put(p);
00316     }
00317   }
00318 
00319   /* Now write the submeshes using the specified writer */
00320   for (int p=0; p<numProc; p++)
00321   {
00322     Out::os() << "writing part=" << p << " of " << numProc << std::endl; 
00323     FieldWriter writer = new ExodusWriter(outfile);
00324     /* Set the mesh for writing */
00325     writer.impersonateParallelProc(numProc, p);
00326     writer.addMesh(submesh[p]);
00327 
00328     /* Prepare to map the field data to the new submeshes */
00329     Map<int, int> newElemLIDToOldLIDMap;
00330     Map<int, int> newVertLIDToOldLIDMap;
00331     Out::os() << "preparing maps to submeshes" << std::endl; 
00332     invertMap(oldElemLIDToNewLIDMaps[p], newElemLIDToOldLIDMap);
00333     invertMap(oldVertLIDToNewLIDMaps[p], newVertLIDToOldLIDMap);
00334 
00335     /* Map the element-based field data */
00336     Out::os() << "mapping element data to submeshes" << std::endl; 
00337     RCP<Array<double> > elemData;
00338     int nElemFuncs = oldElemData->size();
00339     int nElems = submesh[p].numCells(dim);
00340     for (int f=0; f<nElemFuncs; f++)
00341     {
00342       elemData = rcp(new Array<double>(nElems));
00343       for (int lid=0; lid<nElems; lid++)
00344       {
00345         int oldLID = newElemLIDToOldLIDMap.get(lid);
00346         (*elemData)[lid] = (*oldElemData)[f][oldLID];
00347       }
00348       /* Write the element-based data */
00349       writer.addField("uElem["+ Teuchos::toString(f)+"]", 
00350         new CellLIDMappedFieldWrapper(dim, 1, elemData));
00351     }
00352 
00353     /* Map the node-based field data */
00354     Out::os() << "mapping node data to submeshes" << std::endl; 
00355     RCP<Array<double> > nodeData;
00356     int nNodeFuncs = oldNodeData->size();
00357     int nNodes = submesh[p].numCells(0);
00358     for (int f=0; f<nNodeFuncs; f++)
00359     {
00360       nodeData = rcp(new Array<double>(nNodes));
00361       for (int lid=0; lid<nNodes; lid++)
00362       {
00363         int oldLID = newVertLIDToOldLIDMap.get(lid);
00364         (*nodeData)[lid] = (*oldNodeData)[f][oldLID];
00365       }
00366       /* Write the node-based data */
00367       writer.addField("uNode["+ Teuchos::toString(f)+"]", 
00368         new CellLIDMappedFieldWrapper(0, 1, nodeData));
00369     }
00370         
00371     /* Complete the write of the p-th segment */
00372     Out::os() << "doing write()" << std::endl; 
00373     writer.write();
00374     Out::os() << "done part=" << p << " of " << numProc << std::endl; 
00375   }
00376 
00377   /* Write the vertex view files */
00378   for (int p=0; p<numProc; p++)
00379   {
00380     Out::os() << "writing part=" << p << " of " << numProc << std::endl; 
00381 
00382     string vvFile = outfile + "-" + Teuchos::toString(numProc)
00383       + "-" + Teuchos::toString(p) + ".pvv";
00384     ofstream of(vvFile.c_str());
00385     of << submesh[p].numCells(0) << endl;
00386     for (int v=0; v<submesh[p].numCells(0); v++)
00387     {
00388       int gid = submesh[p].mapLIDToGID(0, v);
00389       const Set<int>& viewers = vertViewers[gid];
00390       of << v << " " << gid << " " << viewers.size();
00391       for (Set<int>::const_iterator 
00392              i=viewers.begin(); i!=viewers.end(); i++)
00393       {
00394         of << " " << *i;
00395       }
00396       of << endl;
00397     }
00398   }
00399 }
00400 
00401   
00402   
00403 
00404 
00405 }

Site Contact