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

Site Contact