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

Site Contact