SundanceUnfoldPeriodicDF.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 "SundanceMap.hpp"
00032 #include "SundanceTabs.hpp"
00033 #include "SundanceOut.hpp"
00034 #include "SundanceUnfoldPeriodicDF.hpp"
00035 #include "SundancePeriodicMesh1D.hpp"
00036 #include "SundancePartitionedLineMesher.hpp"
00037 #include "SundanceMeshSource.hpp"
00038 #include "SundanceBasicSimplicialMeshType.hpp"
00039 #include "SundanceDOFMapBase.hpp"
00040 #include "Teuchos_MPIContainerComm.hpp"
00041 #include "Teuchos_TimeMonitor.hpp"
00042 
00043 
00044 
00045 namespace Sundance
00046 {
00047 using namespace Teuchos;
00048 using namespace TSFExtended;
00049 
00050 Mesh unfoldPeriodicMesh(const Mesh& mesh)
00051 {
00052   const MeshBase* mb = mesh.ptr().get();
00053   const PeriodicMesh1D* pm = dynamic_cast<const PeriodicMesh1D*>(mb);
00054 
00055   TEST_FOR_EXCEPT(pm==0);
00056 
00057   int numElems = mesh.numCells(1);
00058   double a = mesh.nodePosition(0)[0];
00059   double b = mesh.nodePosition(numElems)[0];
00060 
00061   MeshType meshType = new BasicSimplicialMeshType();
00062   MeshSource mesher = new PartitionedLineMesher(a, b, numElems, meshType,
00063     MPIComm::self());
00064 
00065   Mesh rtn = mesher.getMesh();
00066 
00067   return rtn;
00068 }
00069 
00070 
00071 DiscreteSpace unfoldPeriodicDiscreteSpace(const DiscreteSpace& space)
00072 {
00073   VectorType<double> vecType = space.vecType();
00074   Mesh mesh = unfoldPeriodicMesh(space.mesh());
00075   BasisArray basis = space.basis();
00076 
00077   return DiscreteSpace(mesh, basis, vecType);
00078 }
00079 
00080 Expr unfoldPeriodicDiscreteFunction(const Expr& f)
00081 {
00082   const DiscreteFunction* df = DiscreteFunction::discFunc(f);
00083   TEST_FOR_EXCEPT(df==0);
00084 
00085 
00086   DiscreteSpace perSpace = df->discreteSpace();
00087   DiscreteSpace space = unfoldPeriodicDiscreteSpace(perSpace);
00088   
00089   Mesh oldMesh = perSpace.mesh();
00090   Mesh newMesh = space.mesh();
00091 
00092   Vector<double> oldVec = df->getVector();
00093   Vector<double> newVec = space.createVector();
00094 
00095   const RCP<DOFMapBase>& oldMap = perSpace.map();
00096   const RCP<DOFMapBase>& newMap = space.map();
00097 
00098   /* Copy the element DOFs to the new vector. There are no duplicated
00099    * elements so this map is one-to-one */
00100   Array<int> oldCellLID(oldMesh.numCells(1));
00101   for (int i=0; i<oldMesh.numCells(1); i++)
00102   {
00103     oldCellLID[i] = i;
00104   }
00105   RCP<const Set<int> > funcs = oldMap->allowedFuncsOnCellBatch(1, oldCellLID);
00106 
00107   Array<Array<int> > oldElemDofs;
00108   Array<Array<int> > newElemDofs;
00109   Array<int> oldNNodes;
00110   RCP<const MapStructure> oldMapStruct ;
00111   RCP<const MapStructure> newMapStruct ;
00112 
00113   if (funcs->size())
00114   {
00115     oldMapStruct 
00116       = oldMap->getDOFsForCellBatch(1, oldCellLID, *funcs, oldElemDofs, 
00117         oldNNodes, 0);
00118     
00119     newMapStruct 
00120       = newMap->getDOFsForCellBatch(1, oldCellLID, *funcs, newElemDofs, 
00121         oldNNodes, 0);
00122     
00123     for (int chunk=0; chunk<oldMapStruct->numBasisChunks(); chunk++)
00124     {
00125       int nf = oldMapStruct->numFuncs(chunk);
00126       int nDofsPerCell = oldNNodes[chunk] * nf;
00127       for (int c=0; c<oldCellLID.size(); c++)
00128       {
00129         for (int d=0; d<nDofsPerCell; d++)
00130         {
00131           int oldDof = oldElemDofs[chunk][nDofsPerCell*c + d];
00132           int newDof = newElemDofs[chunk][nDofsPerCell*c + d];
00133           newVec.setElement(newDof, oldVec.getElement(oldDof));
00134         }
00135       }
00136     }
00137   }
00138 
00139   /* Copy the vertex dofs to the new vector. The data at v=0 are duplicated */
00140   Array<int> oldVertLID(oldMesh.numCells(0));
00141   Array<int> newVertLID(newMesh.numCells(0));
00142   for (int i=0; i<oldMesh.numCells(0); i++)
00143   {
00144     oldVertLID[i] = i;
00145   }
00146   for (int i=0; i<newMesh.numCells(0); i++)
00147   {
00148     newVertLID[i] = i;
00149   }
00150   if (funcs->size())
00151   {
00152     funcs = oldMap->allowedFuncsOnCellBatch(0, oldCellLID);
00153     
00154     oldMapStruct = oldMap->getDOFsForCellBatch(0, oldVertLID, *funcs, 
00155       oldElemDofs, 
00156       oldNNodes, 0);
00157     newMapStruct 
00158       = newMap->getDOFsForCellBatch(0, newVertLID, *funcs, newElemDofs, 
00159         oldNNodes, 0);
00160     
00161     for (int chunk=0; chunk<oldMapStruct->numBasisChunks(); chunk++)
00162     {
00163       int nf = oldMapStruct->numFuncs(chunk);
00164       int nDofsPerCell = oldNNodes[chunk] * nf;
00165       for (int c=0; c<newVertLID.size(); c++)
00166       {
00167         if (c < oldVertLID.size())
00168         {
00169           for (int d=0; d<nDofsPerCell; d++)
00170           {
00171             int oldDof = oldElemDofs[chunk][nDofsPerCell*c + d];
00172             int newDof = newElemDofs[chunk][nDofsPerCell*c + d];
00173             newVec.setElement(newDof, oldVec.getElement(oldDof));
00174           }
00175         }
00176         else
00177         {
00178           for (int d=0; d<nDofsPerCell; d++)
00179           {
00180             int oldDof = oldElemDofs[chunk][d];
00181             int newDof = newElemDofs[chunk][nDofsPerCell*c + d];
00182             newVec.setElement(newDof, oldVec.getElement(oldDof));
00183           }
00184         }
00185       }
00186     }
00187   }
00188 
00189   return new DiscreteFunction(space, newVec);
00190 }
00191 
00192 
00193 }
00194 
00195 

Site Contact