p1groundwaterestimator.hh

Go to the documentation of this file.
00001 #ifndef DUNE_P1GROUNDWATERESTIMATOR_HH
00002 #define DUNE_P1GROUNDWATERESTIMATOR_HH
00003 
00004 #include<map>
00005 #include<iostream>
00006 #include<iomanip>
00007 #include<fstream>
00008 #include<vector>
00009 #include<sstream>
00010 
00011 #include<dune/common/fvector.hh>
00012 #include<dune/common/fmatrix.hh>
00013 #include<dune/common/exceptions.hh>
00014 
00015 #include<dune/grid/common/grid.hh>
00016 #include<dune/grid/common/referenceelements.hh>
00017 #include<dune/grid/common/quadraturerules.hh>
00018 
00019 #include<dune/istl/operators.hh>
00020 #include<dune/istl/bvector.hh>
00021 #include<dune/istl/bcrsmatrix.hh>
00022 
00023 #include<dune/disc/shapefunctions/lagrangeshapefunctions.hh>
00024 #include<dune/disc/operators/boundaryconditions.hh>
00025 #include<dune/disc/functions/p0function.hh>
00026 #include<dune/disc/functions/p1function.hh>
00027 
00028 #include"groundwater.hh"
00029 
00037 namespace Dune
00038 {
00048   template<class G, class RT>
00049   class ElementGroundwaterEstimator {
00050         typedef typename G::ctype DT;
00051         enum {n=G::dimension, m=1};
00052         typedef typename G::Traits::template Codim<0>::Entity Entity;
00053         typedef typename G::template Codim<0>::EntityPointer EEntityPointer;
00054         typedef typename G::Traits::LeafIntersectionIterator IntersectionIterator;
00055         enum {SIZE=Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::maxsize, SIZEF=SIZE};
00056 
00057   public:
00059         ElementGroundwaterEstimator (const GroundwaterEquationParameters<G,RT>& params)
00060           : problem(params)
00061         {
00062         }
00063 
00064 
00074         void estimate (const Entity& e, RT& elementpart)
00075         {
00076           // extract some important parameters
00077           Dune::GeometryType gt = e.type();
00078           Dune::FieldVector<DT,n> center = e.geometry().global(Dune::ReferenceElements<DT,n>::general(gt).position(0,0));
00079           
00080           // integral over right hand side, div(K grad u_h) = 0 for P1 elements
00081           int p=1;
00082           RT volume = e.geometry().integrationElement(Dune::ReferenceElements<DT,n>::general(gt).position(0,0));
00083           RT h_K = pow(volume,1.0/((double)n));
00084           RT integralq = 0;
00085           for (std::size_t g=0; g<Dune::QuadratureRules<DT,n>::rule(gt,p).size(); ++g) // run through all quadrature points
00086                 {
00087                   const Dune::FieldVector<DT,n>& local = Dune::QuadratureRules<DT,n>::rule(gt,p)[g].position(); // pos of integration point
00088                   Dune::FieldVector<DT,n> global = e.geometry().global(local);                                  // ip in global coordinates
00089                   double weight = Dune::QuadratureRules<DT,n>::rule(gt,p)[g].weight();                          // weight of quadrature point
00090                   DT detjac = e.geometry().integrationElement(local);                                           // determinant of jacobian
00091                   RT q = problem.q(global,e,local); // source term
00092                   integralq += q*q*weight*detjac;
00093                 }
00094           integralq *= h_K*h_K; // scaling by h_K^2
00095           elementpart = integralq;
00096         }
00097 
00110         void estimate (const Entity& e, const IntersectionIterator& it, const EEntityPointer& outside, 
00111                                    RT facefluxK[], RT facefluxN[], RT& facefactor, 
00112                                    typename BoundaryConditions::Flags& facebctype, bool first)
00113         {
00114 
00115           // extract some important parameters
00116           GeometryType gt = e.type();
00117           const typename Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::value_type& sfs=Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1);
00118           Dune::FieldVector<DT,n> center = e.geometry().global(Dune::ReferenceElements<DT,n>::general(gt).position(0,0));
00119 
00120           // the edge term
00121           GeometryType gtface = it->intersectionSelfLocal().type();
00122           const Dune::FieldVector<DT,n-1>& facelocal = Dune::ReferenceElements<DT,n-1>::general(gtface).position(0,0);
00123           FieldVector<DT,n> local = it->intersectionSelfLocal().global(facelocal);
00124           FieldVector<DT,n> global = it->intersectionGlobal().global(facelocal);
00125           FieldVector<DT,n> unitOuterNormal = it->unitOuterNormal(facelocal);
00126 
00127           // compute face factor
00128           FieldMatrix<DT,n,n> jac;
00129           FieldMatrix<DT,n,n> Kjac;
00130           DT detjacface = it.intersectionGlobal().integrationElement(facelocal);
00131           DT h_e = pow(detjacface,1.0/((double)n-1));
00132           facefactor = detjacface*h_e*Dune::ReferenceElements<DT,n-1>::general(gtface).volume();
00133 
00134           // compute Kgradphi
00135           if (first || !gt.isSimplex())
00136                 {
00137                   jac = e.geometry().jacobianInverseTransposed(local); // eval jacobian inverse at face center
00138                   Kjac = problem.K(center,e,local);             // eval diffusion tensor at face center
00139                   Kjac.rightmultiply(jac);
00140                   for (int i=0; i<sfs.size(); i++)
00141                         {
00142                           FieldVector<DT,n> temp;
00143                           for (int l=0; l<n; l++) 
00144                                 temp[l] = sfs[i].evaluateDerivative(0,l,local);
00145                           cache[i] = 0;
00146                           Kjac.umv(temp,cache[i]); // multiply with diffusion tensor
00147                         }
00148                 }
00149 
00150           // handle interior edge
00151           if (it.neighbor())
00152                 {
00153                   // no neumann condition
00154                   facebctype = BoundaryConditions::process;
00155 
00156                   // compute coefficients of flux evaluation in self
00157                   for (int i=0; i<sfs.size(); i++)
00158                         {
00159                           facefluxK[i] = -(cache[i]*unitOuterNormal);
00160                         }
00161 
00162                   // compute coefficients of flux evaluation in neighbor
00163                   GeometryType nbgt = outside->type();
00164                   FieldVector<DT,n> nbcenter = outside->geometry().global(ReferenceElements<DT,n>::general(nbgt).position(0,0));
00165                   const typename LagrangeShapeFunctionSetContainer<DT,RT,n>::value_type& nbsfs=LagrangeShapeFunctions<DT,RT,n>::general(nbgt,1);
00166                   GeometryType nbgtface = it.intersectionNeighborLocal().type();
00167                   const FieldVector<DT,n-1>& nbfacelocal = ReferenceElements<DT,n-1>::general(nbgtface).position(0,0);
00168                   FieldVector<DT,n> nblocal = it.intersectionNeighborLocal().global(nbfacelocal);
00169                   FieldMatrix<DT,n,n> nbjac = outside->geometry().jacobianInverseTransposed(nblocal);
00170                   FieldMatrix<DT,n,n> nbKjac = problem.K(nbcenter,*outside,nblocal);
00171                   nbKjac.rightmultiply(nbjac);
00172                   for (int i=0; i<nbsfs.size(); i++)
00173                         {
00174                           FieldVector<DT,n> temp;
00175                           for (int l=0; l<n; l++) 
00176                                 temp[l] = nbsfs[i].evaluateDerivative(0,l,nblocal);
00177                           FieldVector<DT,n> Kgradphi(0);
00178                           nbKjac.umv(temp,Kgradphi); // multiply with diffusion tensor
00179                           facefluxN[i] = -(Kgradphi*unitOuterNormal);
00180                         }
00181                   return;
00182                 }
00183 
00184           // handle face on exterior boundary Neumann boundary
00185           if (it.boundary())
00186                 {
00187                   // evaluate boundary condition type
00188                   facebctype = problem.bctype(global,e,local);
00189                   if (facebctype!=BoundaryConditions::neumann)
00190                         return; // only Neumann conditions require further work
00191 
00192                   // evaluate Neumann boundary
00193                   facefluxN[0] = problem.J(global,e,local);
00194 
00195                   // compute coefficients of flux evaluation in self
00196                   for (int i=0; i<sfs.size(); i++)
00197                         {
00198                           facefluxK[i] = -(cache[i]*unitOuterNormal);
00199                         }
00200                   return;
00201                 }
00202         }
00203 
00204   private:
00205         const GroundwaterEquationParameters<G,RT>& problem;
00206         FieldVector<DT,n> cache[SIZEF];
00207 
00208   };
00209 
00210 
00212   template<class G, class RT>
00213   class GroundwaterEstimator
00214   {
00215         typedef typename G::Traits::LeafIndexSet IS;
00216         typedef typename G::ctype DT;
00217         enum {n=G::dimension};
00218     typedef typename G::template Partition< All_Partition>::LeafGridView GV;
00219         typedef typename GV::template Codim<0>::Entity Entity;
00220         typedef typename GV::IntersectionIterator IntersectionIterator;
00221         typedef typename GV::template Codim<0>::EntityPointer EEntityPointer;
00222 
00223   public:
00224         GroundwaterEstimator (const G& grid, const GroundwaterEquationParameters<G,RT>& params)
00225           :     loc(params),gv(grid.leafView())
00226         {}
00227 
00230         void estimate (const LeafP1Function<G,RT,1>& u, LeafP0Function<G,RT,1>& eta2)
00231         {
00232           // clear estimator values
00233           *eta2 = 0;
00234 
00235           // run over all leaf elements
00236           typedef typename GV::template Codim<0>::Iterator Iterator;
00237           Iterator eendit =  gv.template end<0>();
00238           for (Iterator it =  gv.template begin<0>(); it!=eendit; ++it)
00239                 {
00240                   // in case someone calls it with a level index set
00241                   assert(it->isLeaf());
00242 
00243                   // get access to shape functions for P1 elements
00244                   Dune::GeometryType gt = it->type();
00245                   
00246                   // evaluate element part of estimator
00247                   RT elementpart;
00248                   loc.estimate(*it,elementpart);
00249                   (*eta2)[eta2.mapper().map(*it)] += elementpart;
00250 
00251 
00252                   // loop over all neighbors
00253                   IntersectionIterator iendit = it->ileafend(); 
00254                   bool first=true;
00255                   for (IntersectionIterator iit = it->ileafbegin(); iit!=iendit; ++iit)
00256                         {
00257                           // handle face with neighbor
00258                           if (iit->neighbor())
00259                                 {
00260                                   // Avoid calling the outside() method often
00261                                   // it is extremely expensive !
00262                                   const EEntityPointer outside = iit->outside();
00263 
00264                                   // if neighbor is not leaf then it is evaluated on the neighbor
00265                                   if (!outside->isLeaf()) 
00266                                         continue;
00267 
00268                                   // check if face is handled from other side
00269                                   if (outside->level()==it->level() && eta2.mapper().map(*it)<eta2.mapper().map(*outside))
00270                                         continue;
00271 
00272                                   // evaluate coefficients for this face
00273                                   RT facefluxK[Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::maxsize];
00274                                   RT facefluxN[Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::maxsize];
00275                                   RT facefactor;
00276                                   BoundaryConditions::Flags facebctype;
00277                                   loc.estimate(*it,iit,outside,facefluxK,facefluxN,facefactor,facebctype,first);
00278                                   first=false;
00279 
00280                                   // compute contribution of myself
00281                                   RT self=0;
00282                                   for (int i=0; i<it->template count<n>(); i++)
00283                                         self += facefluxK[i]*(*u)[u.mapper().template map<n>(*it,i)];
00284 
00285                                   // compute contribution of nb
00286                                   RT nb=0;
00287                                   for (int i=0; i<outside->template count<n>(); i++)
00288                                         nb += facefluxN[i]*(*u)[u.mapper().template map<n>(*outside,i)];
00289 
00290 
00291                                   // accumulate contribution to both elements
00292                                   (*eta2)[eta2.mapper().map(*it)] += 0.5*facefactor*(self-nb)*(self-nb);
00293                                   (*eta2)[eta2.mapper().map(*outside)] += 0.5*facefactor*(self-nb)*(self-nb);
00294 
00295                                   continue;
00296                                 }
00297 
00298                           // handle face on boundary
00299                           if (iit->boundary())
00300                                 {
00301                                   // evaluate coefficients for this face
00302                                   RT facefluxK[Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::maxsize];
00303                                   RT facefluxN[Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::maxsize];
00304                                   RT facefactor;
00305                                   BoundaryConditions::Flags facebctype;
00306                                   loc.estimate(*it,iit,iit->inside(),facefluxK,facefluxN,facefactor,facebctype,first);
00307                                   first=false;
00308 
00309                                   // check bc type
00310                                   if (facebctype!=BoundaryConditions::neumann)
00311                                         continue;
00312 
00313                                   // compute contribution of myself
00314                                   RT self=0;
00315                                   for (int i=0; i<it->template count<n>(); i++)
00316                                         self += facefluxK[i]*(*u)[u.mapper().template map<n>(*it,i)];
00317 
00318                                   // accumulate contribution
00319                                   (*eta2)[eta2.mapper().map(*it)] += facefactor*(facefluxN[0]-self)*(facefluxN[0]-self);
00320 
00321                                   continue;
00322                                 }
00323                         }
00324 
00325                 }
00326         }
00327 
00328   private:
00329         ElementGroundwaterEstimator<G,RT> loc;
00330         GV gv;
00331   };
00332   
00334 }
00335 #endif

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