p1function.hh

Go to the documentation of this file.
00001 // $Id: p1function.hh 523 2008-11-17 17:52:49Z christi $
00002 
00003 #ifndef DUNE_P1FUNCTION_HH
00004 #define DUNE_P1FUNCTION_HH
00005 
00006 //C++ includes
00007 #include<new>
00008 #include<iostream>
00009 #include<vector>
00010 #include<list>
00011 #include<map>
00012 #include<set>
00013 
00014 // Dune includes
00015 #include<dune/common/fvector.hh>
00016 #include<dune/common/exceptions.hh>
00017 #include<dune/common/tuples.hh>
00018 #include<dune/common/stdstreams.hh>
00019 #include<dune/grid/common/grid.hh>
00020 #include<dune/grid/common/mcmgmapper.hh>
00021 #include<dune/grid/common/universalmapper.hh>
00022 #include<dune/grid/io/file/vtk/vtkwriter.hh>
00023 #include<dune/istl/bvector.hh>
00024 #include<dune/istl/operators.hh>
00025 #include<dune/istl/bcrsmatrix.hh>
00026 #include<dune/istl/owneroverlapcopy.hh>
00027 #include<dune/disc/shapefunctions/lagrangeshapefunctions.hh>
00028 
00029 // same directory includes
00030 #include"functions.hh"
00031 #include"p0function.hh"
00032 
00038 namespace Dune
00039 {
00049   template<class G>
00050   class LeafCommunicate
00051   {
00052   public:
00053         LeafCommunicate (const G& g)
00054           : grid(g)
00055         {}
00056 
00057         template<class DataHandle>
00058         void communicate (DataHandle& data, InterfaceType iftype, CommunicationDirection dir) const
00059         {
00060           grid.template communicate<DataHandle>(data,iftype,dir);
00061         }
00062 
00063   private:
00064         const G& grid;
00065   };
00066 
00067   template<class G>
00068   class LevelCommunicate
00069   {
00070   public:
00071         LevelCommunicate (const G& g, int l)
00072           : grid(g), level(l)
00073         {}
00074 
00075         template<class DataHandle>
00076         void communicate (DataHandle& data, InterfaceType iftype, CommunicationDirection dir) const
00077         {
00078           grid.template communicate<DataHandle>(data,iftype,dir,level);
00079         }
00080 
00081   private:
00082         const G& grid;
00083         int level;
00084   };
00085 
00087   template<class G, class GV, class VM, class LC>
00088   class P1ExtendOverlap {
00089 
00090         // types
00091         typedef typename G::ctype DT;
00092         enum {n=G::dimension};
00093       typedef typename GV::IndexSet IS;
00094         typedef typename G::template Codim<0>::Entity Entity;
00095         typedef typename GV::template Codim<0>::Iterator Iterator;
00096         typedef typename GV::template Codim<n>::Iterator VIterator;
00097         typedef typename G::template Codim<0>::EntityPointer EEntityPointer;
00098         typedef typename G::Traits::GlobalIdSet IDS;
00099         typedef typename IDS::IdType IdType;
00100         typedef std::set<IdType> GIDSet;
00101         typedef std::pair<IdType,int> Pair;
00102         typedef std::set<int> ProcSet;
00103 
00104         // A DataHandle class to exchange border rows
00105         class IdExchange 
00106           : public CommDataHandleIF<IdExchange,Pair> {
00107         public:
00109           typedef Pair DataType;
00110 
00112           bool contains (int dim, int codim) const
00113           {
00114                 return (codim==dim);
00115           }
00116 
00118           bool fixedsize (int dim, int codim) const
00119           {
00120                 return false;
00121           }
00122 
00127           template<class EntityType>
00128           size_t size (EntityType& e) const
00129           {
00130                 return myids[vertexmapper.map(e)].size();
00131           }
00132 
00134           template<class MessageBuffer, class EntityType>
00135           void gather (MessageBuffer& buff, const EntityType& e) const
00136           {
00137                 int alpha=vertexmapper.map(e);
00138                 GIDSet& thisset = myids[alpha];
00139                 for (typename GIDSet::iterator i=thisset.begin(); i!=thisset.end(); ++i)
00140                   {
00141                         buff.write(Pair(*i,grid.comm().rank())); // I have these global ids
00142                         owner[*i] = grid.comm().rank();
00143                   }
00144                 myprocs[alpha].insert(grid.comm().rank());
00145           }
00146 
00151           template<class MessageBuffer, class EntityType>
00152           void scatter (MessageBuffer& buff, const EntityType& e, size_t n)
00153           {
00154                 int alpha=vertexmapper.map(e);
00155                 GIDSet& thisset = myids[alpha];
00156                 int source;
00157                 for (size_t i=0; i<n; i++)
00158                   {
00159                         Pair x;
00160                         buff.read(x);
00161                         thisset.insert(x.first);
00162                         source=x.second;
00163                         if (owner.find(x.first)==owner.end())
00164                           owner[x.first] = source;
00165                         else
00166                           owner[x.first] = std::min(owner[x.first],source);
00167                   }
00168                 myprocs[alpha].insert(source);          
00169           }
00170 
00172           IdExchange (const G& g, const VM& vm, std::map<int,GIDSet>& ids, std::map<int,ProcSet>& procs, 
00173                                   std::map<IdType,int>& o) 
00174                 : grid(g), vertexmapper(vm), myids(ids), myprocs(procs), owner(o)
00175           {}
00176  
00177         private:
00178           const G& grid;
00179           const VM& vertexmapper;
00180           std::map<int,GIDSet>& myids;
00181           std::map<int,ProcSet>& myprocs;
00182           std::map<IdType,int>& owner;
00183         };
00184 
00185         // A DataHandle class to exchange border rows
00186         class BorderLinksExchange 
00187           : public CommDataHandleIF<BorderLinksExchange,IdType>{
00188         public:
00190           typedef IdType DataType;
00191 
00193           bool contains (int dim, int codim) const
00194           {
00195                 return (codim==dim);
00196           }
00197 
00199           bool fixedsize (int dim, int codim) const
00200           {
00201                 return false;
00202           }
00203 
00208           template<class EntityType>
00209           size_t size (EntityType& e) const
00210           {
00211                 return borderlinks[vertexmapper.map(e)].size();
00212           }
00213 
00215           template<class MessageBuffer, class EntityType>
00216           void gather (MessageBuffer& buff, const EntityType& e) const
00217           {
00218                 GIDSet& myset = borderlinks[vertexmapper.map(e)];
00219                 for (typename GIDSet::iterator i=myset.begin(); i!=myset.end(); ++i)
00220                   buff.write(*i); 
00221           }
00222 
00227           template<class MessageBuffer, class EntityType>
00228           void scatter (MessageBuffer& buff, const EntityType& e, size_t n)
00229           {
00230                 GIDSet& myset = borderlinks[vertexmapper.map(e)];
00231                 for (size_t i=0; i<n; i++)
00232                   {
00233                         DataType x;
00234                         buff.read(x);
00235                         myset.insert(x);
00236                   }
00237           }
00238 
00240           BorderLinksExchange (const G& g, std::map<int,GIDSet>& bl, const VM& vm) 
00241                 : grid(g), borderlinks(bl), vertexmapper(vm) 
00242           {}
00243  
00244         private:
00245           const G& grid;        
00246           std::map<int,GIDSet>& borderlinks;
00247           const VM& vertexmapper;
00248         };
00249 
00250   public:
00251 
00252         enum Attributes {slave=OwnerOverlapCopyAttributeSet::copy, 
00253                                          master=OwnerOverlapCopyAttributeSet::owner, 
00254                                          overlap=OwnerOverlapCopyAttributeSet::overlap};
00255 
00256         typedef IndexInfoFromGrid<IdType,int> P1IndexInfoFromGrid;
00257 
00259         void fillIndexInfoFromGrid (const G& grid, const GV& gridview, const VM& vertexmapper, P1IndexInfoFromGrid& info)
00260         {
00261           // build a map of sets where each local index is assigned 
00262           // a set of global ids which are neighbors of this vertex
00263           // At the same time assign to each local index to a set of processors
00264           // and at the same time determine the owner of the gid
00265           std::map<int,GIDSet> myids;
00266           std::map<int,ProcSet> myprocs;
00267           std::map<IdType,int> owner;
00268           Iterator eendit = gridview.template end<0>();
00269           for (Iterator it = gridview.template begin<0>(); it!=eendit; ++it)
00270                 {
00271                   Dune::GeometryType gt = it->type();
00272                   const typename Dune::ReferenceElementContainer<DT,n>::value_type& 
00273                         refelem = ReferenceElements<DT,n>::general(gt);
00274 
00275                   if (it->partitionType()==InteriorEntity)
00276                         for (int i=0; i<refelem.size(n); i++)
00277                           {
00278                                 if (it->template entity<n>(i)->partitionType()==BorderEntity)
00279                                   {
00280                                         int alpha = vertexmapper.template map<n>(*it,i);
00281                                         GIDSet& thisset = myids[alpha];
00282                                         for (int j=0; j<refelem.size(n); j++)
00283                                           {
00284                                                 IdType beta = grid.globalIdSet().template subId<n>(*it,j);
00285                                                 thisset.insert(beta);
00286                                           }
00287                                   }
00288                           }
00289                 }
00290           IdExchange datahandle(grid,vertexmapper,myids,myprocs,owner);
00291           lc.template communicate<IdExchange>(datahandle,InteriorBorder_InteriorBorder_Interface,ForwardCommunication);
00292 
00293           // build map from global id to local index
00294           std::map<IdType,int> gid2index;
00295           for (typename std::map<int,GIDSet>::iterator i=myids.begin(); i!=myids.end(); ++i)
00296                 for (typename GIDSet::iterator j=(i->second).begin(); j!=(i->second).end(); ++j)
00297                   gid2index[*j] = -1; // indicates "not assigned yet"
00298           VIterator vendit = gridview.template end<n>();
00299           for (VIterator it = gridview.template begin<n>(); it!=vendit; ++it)
00300                 {
00301                   IdType beta = grid.globalIdSet().id(*it);
00302                   if (gid2index.find(beta)!=gid2index.end())
00303                         {
00304                           int alpha = vertexmapper.map(*it);
00305                           gid2index[beta] = alpha; // assign existing local index
00306                         }
00307                 }
00308           int extraDOFs = 0;
00309           for (typename std::map<IdType,int>::iterator i=gid2index.begin(); i!=gid2index.end(); ++i)
00310                 if (i->second==-1)
00311                   {
00312                         i->second = vertexmapper.size()+extraDOFs; // assign new local index
00313                         extraDOFs++;
00314                   }
00315 
00316           // build a set of all neighboring processors
00317           ProcSet neighbors;
00318           for (typename std::map<int,ProcSet>::iterator i=myprocs.begin(); i!=myprocs.end(); ++i)
00319                 for (typename ProcSet::iterator j=(i->second).begin(); j!=(i->second).end(); ++j)
00320                   if (*j!=grid.comm().rank())
00321                         neighbors.insert(*j);
00322 
00323           // now all the necessary information is in place
00324 
00325           // application: for all neighbors build a list of global ids
00326           for (typename ProcSet::iterator p=neighbors.begin(); p!=neighbors.end(); ++p)
00327                 {
00328                   GIDSet remote;
00329                   for (typename std::map<int,ProcSet>::iterator i=myprocs.begin(); i!=myprocs.end(); ++i)
00330                         if ((i->second).find(*p)!=(i->second).end())
00331                           {
00332                                 GIDSet& thisset = myids[i->first];
00333                                 for (typename GIDSet::iterator j=thisset.begin(); j!=thisset.end(); ++j)
00334                                   remote.insert(*j);
00335                           }
00336                 }
00337 
00338 
00339           // fill the info object
00340           std::set< Tuple<IdType,int,int> > ownindices;
00341           for (typename std::map<int,GIDSet>::iterator i=myids.begin(); i!=myids.end(); ++i)
00342                 for (typename GIDSet::iterator j=(i->second).begin(); j!=(i->second).end(); ++j)
00343                   {
00344                         int a=slave;
00345                         if (owner[*j]==grid.comm().rank()) a=master;
00346                         info.addLocalIndex(Tuple<IdType,int,int>(*j,gid2index[*j],a));
00347                   }
00348           std::set< Tuple<int,IdType,int> > remoteindices;
00349           for (typename std::map<int,ProcSet>::iterator i=myprocs.begin(); i!=myprocs.end(); ++i)
00350                 {
00351                   GIDSet& thisset = myids[i->first];
00352                   for (typename GIDSet::iterator j=thisset.begin(); j!=thisset.end(); ++j)
00353                         for (typename ProcSet::iterator p=(i->second).begin(); p!=(i->second).end(); ++p)
00354                           {
00355                                 int a=slave;
00356                                 if (owner[*j]==(*p)) a=master;
00357                                 if (*p!=grid.comm().rank()) info.addRemoteIndex(Tuple<int,IdType,int>(*p,*j,a));
00358                           }
00359                 }
00360 
00361           // clear what is not needed anymore to save memory
00362           myids.clear();
00363           gid2index.clear();
00364           myprocs.clear();
00365           owner.clear();
00366           neighbors.clear();
00367 
00368           return;
00369         }
00370 
00371 
00373         void extend (const G& grid, const GV& gridView, const VM& vertexmapper,
00374                                  std::map<int,GIDSet>& borderlinks, int& extraDOFs, std::map<IdType,int>& gid2index)
00375         {
00376           // initialize output parameters
00377           borderlinks.clear();
00378           extraDOFs = 0;
00379           gid2index.clear();
00380 
00381           // build local borderlinks from mesh
00382           Iterator eendit = gridView.template end<0>();
00383           for (Iterator it = gridView.template begin<0>(); it!=eendit; ++it)
00384                 {
00385                   Dune::GeometryType gt = it->type();
00386                   const typename Dune::ReferenceElementContainer<DT,n>::value_type& 
00387                         refelem = ReferenceElements<DT,n>::general(gt);
00388 
00389                   // generate set of neighbors in global ids for border vertices
00390                   if (it->partitionType()==InteriorEntity)
00391                         for (int i=0; i<refelem.size(n); i++)
00392                           if (it->template entity<n>(i)->partitionType()==BorderEntity)
00393                                 {
00394                                   int alpha = vertexmapper.template map<n>(*it,i);
00395                                   GIDSet& myset = borderlinks[alpha];
00396                                   for (int j=0; j<refelem.size(n); j++)
00397                                         if (i!=j)
00398                                           {
00399                                                 IdType beta = grid.globalIdSet().template subId<n>(*it,j);
00400                                                 myset.insert(beta);
00401                                                 //                                                std::cout << g.comm().rank() << ": "
00402                                                 //                                                                      << "borderlink " << alpha
00403                                                 //                                                                      << " " << vertexmapper.template map<n>(*it,j)
00404                                                 //                                                                      << " " << beta
00405                                                 //                                                                      << std::endl;
00406                                           }
00407                                 }
00408                 }
00409 
00410           // exchange neighbor info for border vertices
00411           BorderLinksExchange datahandle(grid,borderlinks,vertexmapper);
00412           lc.template communicate<BorderLinksExchange>(datahandle,
00413                                                                                                          InteriorBorder_InteriorBorder_Interface,
00414                                                                                                          ForwardCommunication);
00415 
00416           // initialize inverse map with ids we have
00417           for (typename std::map<int,GIDSet>::iterator i=borderlinks.begin(); i!=borderlinks.end(); ++i)
00418                 for (typename GIDSet::iterator j=(i->second).begin(); j!=(i->second).end(); ++j)
00419                   gid2index[*j] = -1;
00420 
00421           // check with ids we already have in the grid to find out extra vertices
00422           VIterator vendit = gridView.template end<n>();
00423           for (VIterator it = gridView.template begin<n>(); it!=gridView.template end<n>(); ++it)
00424                 {
00425                   IdType beta = grid.globalIdSet().id(*it);
00426                   if (gid2index.find(beta)!=gid2index.end())
00427                         {
00428                           int alpha = vertexmapper.map(*it);
00429                           gid2index[beta] = alpha;
00430                         }
00431                 }
00432 
00433           // assign index to extra DOFs
00434           extraDOFs = 0;
00435           for (typename std::map<IdType,int>::iterator i=gid2index.begin(); i!=gid2index.end(); ++i)
00436                 if (i->second==-1)
00437                   {
00438                         i->second = vertexmapper.size()+extraDOFs;
00439                         extraDOFs++;
00440                   }
00441 
00442           //              for (typename std::map<int,GIDSet>::iterator i=borderlinks.begin(); i!=borderlinks.end(); ++i)
00443           //                    for (typename GIDSet::iterator j=(i->second).begin(); j!=(i->second).end(); ++j)
00444           //                      std::cout << grid.comm().rank() << ": " << "comm borderlink " << i->first
00445           //                                            << " " << gid2index[*j] << " " << *j << std::endl;
00446         }
00447 
00448         P1ExtendOverlap (LC lcomm)
00449           : lc(lcomm)
00450         {}
00451 
00452   private:
00453         LC lc;
00454   };
00455 
00456   // forward declaration
00457   template<class G, class RT> class P1FunctionManager;
00458 
00459 
00461 
00472   template<class GV, class RT, class LC, int m=1>
00473   class P1Function
00474     : virtual public GridFunctionGlobalEvalDefault<GV,RT,m>
00475     , virtual public FunctionDefault<typename GV::Grid::ctype,RT,GV::Grid::dimension,m>
00476     , virtual public ElementwiseCInfinityFunction<typename GV::Grid,RT,m>
00477     , virtual public H1Function<typename GV::Grid::ctype,RT,GV::Grid::dimension,m>
00478     , virtual public C0GridFunction<typename GV::Grid,RT,m>
00479   {
00481         typedef typename GV::Grid G;
00482 
00484         typedef typename G::ctype DT;
00485 
00487         enum {n=G::dimension};
00488 
00490         typedef typename G::template Codim<0>::Entity Entity;
00491 
00493         template<int dim>
00494         struct P1Layout
00495         {
00496           bool contains (Dune::GeometryType gt)
00497           {
00498               return gt.dim() == 0;
00499           }
00500         }; 
00501 
00503         P1Function (const P1Function&);
00504 
00505         // types
00506         typedef typename G::Traits::GlobalIdSet IDS;
00507         typedef typename IDS::IdType IdType;
00508         typedef std::set<IdType> GIDSet;
00509     typedef typename GV::IndexSet IS;
00510 
00511   public:
00512     typedef GV GridView;
00513     typedef IS IndexSet;
00514     typedef G Grid;
00515         typedef FieldVector<RT,m> BlockType;
00516         typedef BlockVector<BlockType> RepresentationType;
00517     typedef MultipleCodimMultipleGeomTypeMapper<G,IS,P1Layout> VM;
00518         typedef typename P1ExtendOverlap<G,GV,VM,LC>::P1IndexInfoFromGrid P1IndexInfoFromGrid;
00519 
00521         P1Function (const GV& gridView, LC lcomm, bool extendoverlap=false) 
00522           : GridFunctionGlobalEvalDefault<GV,RT,m>(gridView)
00523           , gv(gridView), mapper_(gridView.grid(),gridView.indexSet()), lc(lcomm), oldcoeff(0)
00524         {
00525           // check if overlap extension is possible
00526           if (extendoverlap && gv.grid().overlapSize(0)>0)
00527                 DUNE_THROW(GridError,"P1Function: extending overlap requires nonoverlapping grid");
00528 
00529           // no extra DOFs so far
00530           extraDOFs = 0;
00531           extendOverlap = extendoverlap;
00532 
00533           // overlap extension
00534           if (extendoverlap)
00535                 {
00536                   // set of neighbors in global ids for border vertices
00537                   std::map<int,GIDSet> borderlinks;
00538                   std::map<IdType,int> gid2index;
00539 
00540                   // compute extension
00541                   P1ExtendOverlap<G,GV,VM,LC> extender(lc);
00542                   extender.extend(gv.grid(),gv,mapper_,borderlinks,extraDOFs,gid2index);
00543                 }
00544 
00545           // allocate the vector
00546           oldcoeff = 0;
00547           try {
00548                 coeff = new RepresentationType(mapper_.size()+extraDOFs);
00549           }
00550           catch (std::bad_alloc) {
00551                 std::cerr << "not enough memory in P1Function" << std::endl;
00552                 throw; // rethrow exception
00553           }
00554           dverb << "making FE function with " << mapper_.size()+extraDOFs << " components"
00555                         << "(" << extraDOFs << " extra degrees of freedom)" << std::endl;
00556         }
00557 
00559         ~P1Function ()
00560         {
00561           delete coeff;
00562           if (oldcoeff!=0) delete oldcoeff;
00563         }
00564 
00566 
00573         virtual RT derivative (int comp, const Dune::FieldVector<int,n>& d, const Dune::FieldVector<DT,n>& x) const
00574         {
00575           DUNE_THROW(NotImplemented, "global derivative not implemented yet");
00576         }
00577 
00579 
00582         virtual int order () const
00583         {
00584           return 1; // up to now only one derivative is implemented
00585         }
00586 
00588 
00594         virtual RT evallocal (int comp, const Entity& e, const Dune::FieldVector<DT,n>& xi) const
00595         {
00596           RT value=0;
00597           Dune::GeometryType gt = e.type(); // extract type of element
00598           for (int i=0; i<Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1).size(); ++i)
00599                 value += Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1)[i].evaluateFunction(0,xi)*(*coeff)[mapper_.template map<n>(e,i)][comp];
00600           return value;
00601         }
00602 
00604 
00609         virtual void evalalllocal (const Entity& e, const Dune::FieldVector<DT,G::dimension>& xi, 
00610                                                            Dune::FieldVector<RT,m>& y) const
00611         {
00612           Dune::GeometryType gt = e.type(); // extract type of element
00613           y = 0;
00614           for (int i=0; i<Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1).size(); ++i)
00615                 {
00616                   RT basefuncvalue=Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1)[i].evaluateFunction(0,xi);
00617                   int index = mapper_.template map<n>(e,i);
00618                   for (int c=0; c<m; c++)
00619                         y[c] += basefuncvalue * (*coeff)[index][c];
00620                 }
00621         }
00622 
00624 
00632         virtual RT derivativelocal (int comp, const Dune::FieldVector<int,n>& d, 
00633                                                                 const Entity& e, const Dune::FieldVector<DT,n>& xi) const
00634         {
00635           int dir=-1; 
00636           int order=0;
00637           for (int i=0; i<n; i++)
00638                 {
00639                   order += d[i];
00640                   if (d[i]>0) dir=i;
00641                 }
00642       assert(dir != -1);
00643           if (order!=1) DUNE_THROW(GridError,"can only evaluate one derivative");
00644 
00645           RT value=0;
00646           Dune::GeometryType gt = e.type(); // extract type of element
00647           const typename Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::value_type& 
00648                 sfs=Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1);
00649           Dune::FieldMatrix<DT,n,n> jac = e.geometry().jacobianInverseTransposed(xi);
00650           for (int i=0; i<sfs.size(); ++i)
00651                 {
00652                   Dune::FieldVector<DT,n> grad(0),temp;
00653                   for (int l=0; l<n; l++) 
00654                         temp[l] = sfs[i].evaluateDerivative(0,l,xi);
00655                   jac.umv(temp,grad); // transform gradient to global ooordinates
00656                   value += grad[dir] * (*coeff)[mapper_.template map<n>(e,i)][comp];
00657                 }
00658           return value;
00659         }
00660 
00661 
00663 
00669         void interpolate (const C0GridFunction<G,RT,m>& u)
00670         {
00671       typedef typename GV::template Codim<0>::template Partition<All_Partition>::Iterator Iterator;
00672           std::vector<bool> visited(mapper_.size());
00673           for (int i=0; i<mapper_.size(); i++) visited[i] = false;
00674 
00675           Iterator eendit = gv.template end<0,All_Partition>();
00676           for (Iterator it = gv.template begin<0,All_Partition>(); it!=eendit; ++it)
00677                 {
00678                   Dune::GeometryType gt = it->type();
00679                   for (int i=0; i<Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1).size(); ++i)
00680                         if (!visited[mapper_.template map<n>(*it,i)])
00681                           {
00682                                 for (int c=0; c<m; c++)
00683                                   (*coeff)[mapper_.template map<n>(*it,i)][c] = 
00684                                         u.evallocal(c,*it,Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1)[i].position());
00685                                 visited[mapper_.template map<n>(*it,i)] = true;
00686                           }
00687                 }
00688         }
00689 
00691         void interpolate (const P0Function<GV,RT,m>& u)
00692         {
00693           typedef typename GV::template Codim<0>::Iterator Iterator;
00694           std::vector<char> counter(mapper_.size());
00695           for (int i=0; i<mapper_.size(); i++) counter[i] = 0;
00696 
00697           for (int i=0; i<(*coeff).size(); i++)
00698                 (*coeff)[i] = 0;
00699           Iterator eendit = gv.template end<0>();
00700           for (Iterator it = gv.template begin<0>(); it!=eendit; ++it)
00701                 {
00702                   Dune::GeometryType gt = it->type();
00703                   for (int i=0; i<Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1).size(); ++i)
00704                         {
00705                           for (int c=0; c<m; c++)
00706                                 (*coeff)[mapper_.template map<n>(*it,i)][c] += 
00707                                   u.evallocal(c,*it,Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1)[i].position());
00708                           counter[mapper_.template map<n>(*it,i)] += 1;
00709                         }
00710                 }
00711           for (int i=0; i<counter.size(); i++)
00712                 for (int c=0; c<m; c++)
00713                   (*coeff)[i][c] /= counter[i];
00714         }
00715 
00717 
00721         const RepresentationType& operator* () const
00722         {
00723           return (*coeff);
00724         }
00725 
00727 
00731         RepresentationType& operator* ()
00732         {
00733           return (*coeff);
00734         }
00735 
00736 
00738         void fillIndexInfoFromGrid (P1IndexInfoFromGrid& info)
00739         {
00740           P1ExtendOverlap<G,GV,VM,LC> extender(lc);
00741           extender.fillIndexInfoFromGrid(gv.grid(),gv,mapper_,info);
00742         }
00743 
00744 
00749         void preAdapt ()
00750         {
00751         }
00752 
00761         void postAdapt (P1FunctionManager<G,RT>& manager)
00762         {
00763           typedef typename G::template Codim<n>::LeafIterator VLeafIterator;
00764           typedef typename G::template Codim<0>::LeafIterator ELeafIterator;
00765           typedef typename G::template Codim<n>::LevelIterator VLevelIterator;
00766           typedef typename G::template Codim<0>::LevelIterator ELevelIterator;
00767           typedef typename G::template Codim<0>::EntityPointer EEntityPointer;
00768 
00769           // \todo check that function is only called for data with respect to leafs
00770           // save the current representation
00771           oldcoeff = coeff;
00772 
00773           // allow mapper to recompute its internal sizes
00774           mapper_.update();
00775 
00776           // overlap extension, recompute extra DOFs
00777           if (extendOverlap)
00778                 {
00779                   // set of neighbors in global ids for border vertices
00780                   std::map<int,GIDSet> borderlinks;
00781                   std::map<IdType,int> gid2index;
00782                   extraDOFs = 0;
00783 
00784                   // compute extension
00785                   P1ExtendOverlap<G,GV,VM,LC> extender(lc);
00786                   extender.extend(gv.grid(),gv,mapper_,borderlinks,extraDOFs,gid2index);
00787                 }
00788 
00789           // allocate data with new size (while keeping the old data ...)
00790           try {
00791                 coeff = new RepresentationType(mapper_.size()+extraDOFs); // allocate new representation
00792           }
00793           catch (std::bad_alloc) {
00794                 std::cerr << "not enough memory in P1Function update" << std::endl;
00795                 throw; // rethrow exception
00796           }
00797           std::cout << "P1  function enlarged to " << mapper_.size() << " components" << std::endl;
00798 
00799           // vector of flags to store which vertex has been handled already
00800           std::vector<bool> visited(mapper_.size());
00801           for (int i=0; i<mapper_.size(); i++) visited[i] = false;
00802 
00803           // now loop over the NEW mesh to copy the data that was already in the OLD mesh
00804           VLeafIterator veendit = gv.grid().template leafend<n>();
00805           for (VLeafIterator it = gv.grid().template leafbegin<n>(); it!=veendit; ++it)
00806                 {
00807                   // lookup in mapper
00808                   int i;
00809                   if (manager.savedMap().contains(*it,i))
00810                         {
00811 //                        std::cout << " found vertex=" << it->geometry()[0] 
00812 //                                              << " at i=" << i
00813 //                                              << " oldindex=" << manager.oldIndex()[i]
00814 //                                              << " newindex=" << mapper_.map(*it)
00815 //                                              << std::endl;
00816                           // the vertex existed already in the old mesh, copy data
00817                           for (int c=0; c<m; c++)
00818                                 (*coeff)[mapper_.map(*it)][c] = (*oldcoeff)[manager.oldIndex()[i]][c];
00819                           // ... and mark as visited
00820                           visited[mapper_.map(*it)] = true;
00821                         }
00822                 }
00823 
00824           // now loop the second time to interpolate the new coefficients
00825           // new implementation using interpolation on codim 0
00826           for (int level=1; level<=gv.grid().maxLevel(); ++level)
00827                 {
00828                   ELevelIterator elendit = gv.grid().template lend<0>(level);
00829                   for (ELevelIterator it = gv.grid().template lbegin<0>(level); it!=elendit; ++it)
00830                         {
00831                           GeometryType gte = it->type();
00832                           for (int i=0; i<Dune::LagrangeShapeFunctions<DT,RT,n>::general(gte,1).size(); ++i)
00833                                 {
00834                                   int index = mapper_.template map<n>(*it,i);
00835                                   if (!visited[index])
00836                                         {
00837                                           // OK, this is a new vertex
00838                                           EEntityPointer father=it->father(); // the father element
00839                                           GeometryType gtf = father->type(); // fathers type
00840                                           const FieldVector<DT,n>& cpos=Dune::LagrangeShapeFunctions<DT,RT,n>::general(gte,1)[i].position();
00841                                           FieldVector<DT,n> pos = it->geometryInFather().global(cpos); // map corner to father element
00842                                           for (int c=0; c<m; c++)
00843                                                 (*coeff)[index][c] = 0;
00844                                           for (int j=0; j<Dune::LagrangeShapeFunctions<DT,RT,n>::general(gtf,1).size(); ++j)
00845                                                 {
00846                                                   RT basefuncvalue = Dune::LagrangeShapeFunctions<DT,RT,n>::general(gtf,1)[j].evaluateFunction(0,pos);
00847                                                   for (int c=0; c<m; c++)
00848                                                         (*coeff)[index][c] += basefuncvalue * (*coeff)[mapper_.template map<n>(*father,j)][c];
00849                                                   //                                      std::cout << "  corner=" << i 
00850                                                   //                                                            << " cpos=" << father->geometry()[i]
00851                                                   //                                                            << " u=" << (*coeff)[mapper_.template map<n>(*father,i)]
00852                                                   //                                                            << std::endl;
00853                                                 }
00854                                           //                              std::cout << "index=" << mapper_.map(*it) << " value=" << value << std::endl;
00855                                           visited[index] = true;                                  
00856                                         }
00857                                 }
00858                         }
00859                 }
00860 
00861           // now really delete old representation
00862           if (oldcoeff!=0) delete oldcoeff;
00863           oldcoeff = 0;
00864         }
00865 
00868         const VM& mapper () const
00869         {
00870           return mapper_;
00871         }
00872  
00875         const GV& gridview () const
00876         {
00877           return gv;
00878         }
00879  
00881         void vtkout (VTKWriter<GV>& vtkwriter, std::string s) const
00882         {
00883           typename VTKWriter<GV>::VTKFunction *p = new VTKGridFunctionWrapper<GV,RT,m>(*this,s);
00884           vtkwriter.addVertexData(p);
00885         }
00886 
00887   private:
00888         // The GridView.  Don't use a reference here since Grid::levelView
00889         // returns a temporary
00890         const GV gv;
00891 
00892         // we need a mapper
00893         VM mapper_;
00894 
00895         // level or leafwise communication object
00896         LC lc;
00897 
00898         // extra DOFs from extending nonoverlapping to overlapping grid
00899         int extraDOFs;
00900         bool extendOverlap;
00901 
00902         // and a dynamically allocated vector
00903         RepresentationType* coeff;
00904 
00905         // saved pointer in update phase
00906         RepresentationType* oldcoeff;
00907   };
00908 
00909 
00916   template<class G, class RT, int m=1>
00917   class LeafP1Function : public P1Function<typename G::LeafGridView,RT,LeafCommunicate<G>,m>
00918   {
00919   public:
00923         LeafP1Function (const G& grid, bool extendoverlap=false) 
00924           : GridFunctionGlobalEvalDefault<typename G::LeafGridView,RT,m>(grid.leafView())
00925           , P1Function<typename G::LeafGridView,RT,LeafCommunicate<G>,m>(grid.leafView(),LeafCommunicate<G>(grid),extendoverlap)
00926         {}
00927   };
00928 
00929 
00936   template<class G, class RT, int m=1>
00937   class LevelP1Function : public P1Function<typename G::LevelGridView,RT,LevelCommunicate<G>,m>
00938   {
00939   public:
00943         LevelP1Function (const G& grid, int level, bool extendoverlap=false) 
00944           : GridFunctionGlobalEvalDefault<typename G::LevelGridView,RT,m>(grid.levelView(level))
00945           , P1Function<typename G::LevelGridView,RT,LevelCommunicate<G>,m>(grid.levelView(level),LevelCommunicate<G>(grid,level),extendoverlap)
00946         {}
00947   };
00948 
00949 
00959   template<class G, class RT>
00960   class P1FunctionManager {
00961         enum {dim=G::dimension};
00962         typedef typename G::ctype DT;
00963         typedef typename G::template Codim<dim>::LeafIterator VLeafIterator;
00964         typedef typename G::template Codim<0>::EntityPointer EEntityPointer;
00965 
00966         template<int dim>
00967         struct P1Layout
00968         {
00969           bool contains (Dune::GeometryType gt)
00970           {
00971               return gt.dim() == 0;
00972           }
00973         }; 
00974 
00975   public:
00976 
00978         P1FunctionManager (const G& g) : mapper(g,g.leafIndexSet()), grid(g), savedmap(g)
00979         {       
00980           // allocate index array to correct size (this possible for vertex data)
00981           oldindex.resize(mapper.size());
00982 
00983           // and allocate the universal mapper to acces the old indices
00984           savedmap.clear(); //should be empty already
00985 
00986           // now loop over all vertices and copy the index provided by the mapper
00987           VLeafIterator veendit = grid.template leafend<dim>();
00988           for (VLeafIterator it = grid.template leafbegin<dim>(); it!=veendit; ++it)
00989                 {
00990                   oldindex[savedmap.map(*it)] = mapper.map(*it);
00991                 }
00992         }
00993 
00994         const GlobalUniversalMapper<G>& savedMap ()
00995         {
00996           return savedmap;
00997         }
00998 
00999         const std::vector<int>& oldIndex ()
01000         {
01001           return oldindex;
01002         }
01003 
01004   private:
01005         // we need a mapper
01006         MultipleCodimMultipleGeomTypeMapper<G,typename G::template Codim<0>::LeafIndexSet,P1Layout> mapper;
01007 
01008         // store a reference to the grid that is managed
01009         const G& grid;
01010 
01011         // We need a persistent consecutive enumeration 
01012         GlobalUniversalMapper<G> savedmap;
01013 
01014         // The old leaf indices are stored in a dynamically allocated vector
01015         std::vector<int> oldindex;
01016   };
01017 
01018 
01021 }
01022 #endif

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