p1mgtransfer.hh

00001 // $Id: p1mgtransfer.hh 519 2008-09-30 18:52:38Z mblatt $
00002 
00003 #ifndef DUNE_P1MGTRANSFER_HH
00004 #define DUNE_P1MGTRANSFER_HH
00005 
00006 #include<set>
00007 #include<map>
00008 
00009 #include<dune/common/exceptions.hh>
00010 #include<dune/common/fvector.hh>
00011 #include<dune/common/fmatrix.hh>
00012 #include<dune/common/geometrytype.hh>
00013 
00014 #include<dune/grid/common/grid.hh>
00015 #include<dune/grid/common/mcmgmapper.hh>
00016 #include<dune/grid/utility/intersectiongetter.hh>
00017 
00018 #include<dune/istl/bvector.hh>
00019 #include<dune/istl/bcrsmatrix.hh>
00020 
00021 #include<dune/disc/shapefunctions/lagrangeshapefunctions.hh>
00022 #include<dune/disc/operators/localstiffness.hh>
00023 
00030 namespace Dune
00031 {
00046   template<class G, class RT, int m=1>
00047   class P1MGTransfer
00048   {
00049   public:
00050         // export type used to store the matrix
00051         typedef FieldMatrix<RT,m,m> BlockType; 
00052         typedef BCRSMatrix<BlockType> RepresentationType;
00053         typedef typename RepresentationType::RowIterator rowiterator;
00054         typedef typename RepresentationType::ColIterator coliterator;
00055 
00056         // mapper: one data element per vertex
00057         template<int dim>
00058         struct P1Layout
00059         {
00060           bool contains (Dune::GeometryType gt)
00061           {
00062               return gt.dim() == 0;
00063           }
00064         }; 
00065 
00066         typedef typename G::ctype DT;
00067         typedef typename G::LevelGridView GridView;
00068         enum {n=G::dimension};
00069         typedef typename G::template Codim<0>::Entity Entity;
00070         typedef typename GridView::template Codim<0>::Iterator ElementLevelIterator;
00071         typedef typename GridView::template Codim<n>::Iterator VertexLevelIterator;
00072         typedef typename GridView::template Codim<0>::EntityPointer EntityPointer;
00073         typedef typename GridView::IndexSet IS;
00074         typedef MultipleCodimMultipleGeomTypeMapper<G,IS,P1Layout> VM;
00075 
00076         typedef std::set<int> IntSet;
00077         typedef std::map<int,IntSet> Graph;
00078 
00082         P1MGTransfer (const G& grid_, int level_)
00083           : grid(grid_), coarseview(grid.levelView(level_-1)),
00084             fineview(grid.levelView(level_)), level(level_)
00085         {
00086           // check that coarse grid exists
00087           if (level==0)
00088                 DUNE_THROW(Exception,"P1MGTransfer: level greater 0 required");
00089 
00090           // allocate vertex mappers for the fine and coarse grid
00091           VM finemapper(grid,grid.levelIndexSet(level));
00092           VM coarsemapper(grid,grid.levelIndexSet(level-1));
00093 
00094           // allocate a graph structure for the sparsity pattern (yes we are lazy here)
00095           Graph graph;
00096 
00097           // allocate a flag vector to handle each vertex exactly once
00098           std::vector<bool> treated(finemapper.size(),false);
00099 
00100 
00101           // build the graph structure from the mesh
00102           for (ElementLevelIterator it = fineview.template begin<0>(); 
00103                    it!=fineview.template end<0>(); ++it)
00104                 {
00105                   // get geometry type of entity 
00106                   GeometryType gt = it->type();
00107 
00108                   // get father entity
00109                   const EntityPointer father = it->father();
00110 
00111                   // get geometry type of father
00112                   GeometryType gtf = father->type();
00113 
00114                   // connect every vertex of the fine grid element with 
00115                   // with every vertex of the coarse grid element
00116                   for (int i=0; i<it->template count<n>(); i++)
00117                         {
00118                           // get index of fine grid vertex
00119                           int indexi = finemapper.template map<n>(*it,i);
00120 
00121                           // skip vertices that have already been treated
00122                           if (treated[indexi]) continue;
00123 
00124                           // get position of fine grid vertex in local coordinate system of father
00125                           const FieldVector<DT,n>& cpos=Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1)[i].position();
00126                           FieldVector<DT,n> pos = it->geometryInFather().global(cpos);
00127 
00128                           // determine interpolation weights
00129                           for (int j=0; j<father-> template count<n>(); j++)
00130                                 {
00131                                   // get value of j th basis function in father element 
00132                                   RT phi = Dune::LagrangeShapeFunctions<DT,RT,n>::general(gtf,1)[j].evaluateFunction(0,pos);
00133 
00134                                   // get global index of that basis function
00135                                   int indexj = coarsemapper.template map<n>(*father,j);
00136 
00137                                   // insert only if non-zero
00138                                   if (std::abs(phi)>1E-6) graph[indexi].insert(indexj);
00139                                 }
00140                           treated[indexi] = true;
00141                         }
00142                 }
00143 
00144           // compute number of nonzeroes
00145           int nnz=0;
00146           for (Graph::iterator i=graph.begin(); i!=graph.end(); ++i)
00147                 nnz += i->second.size();
00148 
00149           // allocate the matrix
00150           std::cout << grid.comm().rank() << ": making " << finemapper.size() << "x"
00151                                 << coarsemapper.size() << " transfer matrix with " << nnz 
00152                                 << " nonzeroes" << std::endl;
00153           A = new RepresentationType(finemapper.size(),coarsemapper.size(),nnz,RepresentationType::random);
00154 
00155           // set row sizes
00156           for (Graph::iterator i=graph.begin(); i!=graph.end(); ++i)
00157                 A->setrowsize(i->first,i->second.size());
00158           A->endrowsizes();
00159 
00160           // set the structure
00161           for (Graph::iterator i=graph.begin(); i!=graph.end(); ++i)
00162                 for (IntSet::iterator j=i->second.begin(); j!=i->second.end(); ++j)
00163                   A->addindex(i->first,*j);
00164           A->endindices();
00165 
00166           // deallocate the map
00167           graph.clear();
00168 
00169           // allocate skip flag vectors
00170           for (int compi=0; compi<m; compi++)
00171                 skipflag[compi] = new std::vector<bool>(finemapper.size(),false);
00172           for (int compi=0; compi<m; compi++)
00173                 coarseskipflag[compi] = new std::vector<bool>(coarsemapper.size(),false);
00174         }
00175 
00176 
00180         void assemble (LocalStiffness<GridView,RT,m>& loc)
00181         {
00182           // allocate vertex mappers for the fine and coarse grid
00183           VM finemapper(grid,grid.levelIndexSet(level));
00184           VM coarsemapper(grid,grid.levelIndexSet(level-1));
00185 
00186           // clear data
00187           (*A) = 0;
00188           for (int compi=0; compi<m; compi++)
00189                 for (int i=0; i<finemapper.size(); i++)
00190                   (*skipflag[compi])[i] = false;
00191           for (int compi=0; compi<m; compi++)
00192                 for (int i=0; i<coarsemapper.size(); i++)
00193                   (*coarseskipflag[compi])[i] = false;
00194 
00195           // determine coarse grid skip flags !
00196           for (ElementLevelIterator it = coarseview.template begin<0>(); 
00197                    it!=coarseview.template end<0>(); ++it)
00198                 {
00199                   // get geometry type of entity 
00200                   GeometryType gt = it->type();
00201 
00202                   // assemble boundary conditions for the given element
00203                   loc.assembleBoundaryCondition(*it);
00204 
00205                   // connect every vertex of the fine grid element with 
00206                   // with every vertex of the coarse grid element
00207                   for (int i=0; i<it->template count<n>(); i++)
00208                         {
00209                           // get index of fine grid vertex
00210                           int indexi = coarsemapper.template map<n>(*it,i);
00211 
00212                           // set skipflag if essential boundary condition is encountered
00213                           for (int compi=0; compi<m; compi++)
00214                                 if (loc.bc(i)[compi]==BoundaryConditions::process || 
00215                                         loc.bc(i)[compi]==BoundaryConditions::dirichlet)
00216                                   (*coarseskipflag[compi])[indexi] = true;
00217                         }
00218                 }
00219 
00220           // allocate a flag vector to handle each vertex exactly once
00221           std::vector<bool> treated(finemapper.size(),false);
00222 
00223           // assemble the entries; needs to consider Dirichlet boundary conditions later
00224           for (ElementLevelIterator it = fineview.template begin<0>(); 
00225                    it!=fineview.template end<0>(); ++it)
00226                 {
00227                   // get geometry type of entity 
00228                   GeometryType gt = it->type();
00229 
00230                   // get father entity
00231                   const EntityPointer father = it->father();
00232 
00233                   // get geometry type of father
00234                   GeometryType gtf = father->type();
00235 
00236                   // assemble boundary conditions for the given element
00237                   loc.assembleBoundaryCondition(*it);
00238 
00239                   // connect every vertex of the fine grid element with 
00240                   // with every vertex of the coarse grid element
00241                   for (int i=0; i<it->template count<n>(); i++)
00242                         {
00243                           // get index of fine grid vertex
00244                           int indexi = finemapper.template map<n>(*it,i);
00245 
00246                           // set skipflag if essential boundary condition is encountered
00247                           for (int compi=0; compi<m; compi++)
00248                                 if (loc.bc(i)[compi]==BoundaryConditions::process || 
00249                                         loc.bc(i)[compi]==BoundaryConditions::dirichlet)
00250                                   (*skipflag[compi])[indexi] = true;
00251 
00252                           // skip vertices that have already been treated
00253                           if (treated[indexi]) continue;
00254 
00255                           // get position of fine grid vertex in local coordinate system of father
00256                           const FieldVector<DT,n>& cpos=Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1)[i].position();
00257                           FieldVector<DT,n> pos = it->geometryInFather().global(cpos);
00258 
00259                           // compute and set matrix values
00260                           for (int j=0; j<father->template count<n>(); ++j)
00261                                 {
00262                                   // get value of j th basis function in father element 
00263                                   RT phi = Dune::LagrangeShapeFunctions<DT,RT,n>::general(gtf,1)[j].evaluateFunction(0,pos);
00264 
00265                                   // insert entry if large enough
00266                                   if (std::abs(phi)>1E-6)
00267                                         {
00268                                           // get global index of that basis function
00269                                           int indexj = coarsemapper.template map<n>(*father,j);
00270 
00271                                           // fill diagonal matrix block; consider coarse skip flags
00272                                           BlockType D;
00273                                           for (int compi=0; compi<m; compi++)
00274                                                 {
00275                                                   double scale=1.0;
00276                                                   if ((*coarseskipflag[compi])[indexj]) scale=0;
00277                                                   for (int compj=0; compj<m; compj++)
00278                                                         if (compi==compj) 
00279                                                           D[compi][compj] = phi*scale; 
00280                                                         else 
00281                                                           D[compi][compj] = 0.0;
00282                                                 }
00283 
00284                                           // set entry
00285                                           (*A)[indexi][indexj] = D;
00286                                         }
00287                                 }
00288 
00289                           // mark this vertex as done
00290                           treated[indexi] = true;
00291                         }
00292                 }
00293         }
00294 
00295         // return the skip flag
00296         bool skipFlag (int compi, int indexi) const
00297         {
00298           return (*skipflag[compi])[indexi];
00299         }
00300 
00301         // return the skip flag
00302         bool coarseSkipFlag (int compi, int indexi) const
00303         {
00304           return (*coarseskipflag[compi])[indexi];
00305         }
00306 
00308         const RepresentationType& operator* () const
00309         {
00310           return *A;
00311         }
00312 
00314         RepresentationType& operator* ()
00315         {
00316           return *A;
00317         }
00318 
00320 
00321         // destructor
00322         ~P1MGTransfer ()
00323         {
00324           delete A;
00325           for (int compi=0; compi<m; compi++)
00326                 delete skipflag[compi];
00327           for (int compi=0; compi<m; compi++)
00328                 delete coarseskipflag[compi];
00329         }
00330 
00331   private:
00332 
00333         // make copy constructor and assignment private
00334         P1MGTransfer (const P1MGTransfer&) {}
00335         P1MGTransfer& operator= (const P1MGTransfer&) {}
00336 
00337         // data members
00338         const G& grid;
00339         const GridView& fineview;
00340         const GridView& coarseview;
00341         int level;
00342         RepresentationType* A;
00343         std::vector<bool>* skipflag[m];
00344         std::vector<bool>* coarseskipflag[m];
00345   };
00346 
00347 
00348 
00350 }
00351 #endif

Generated on 6 Jan 2009 with Doxygen (ver 1.5.1) [logfile].