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
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
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)
00086 {
00087 const Dune::FieldVector<DT,n>& local = Dune::QuadratureRules<DT,n>::rule(gt,p)[g].position();
00088 Dune::FieldVector<DT,n> global = e.geometry().global(local);
00089 double weight = Dune::QuadratureRules<DT,n>::rule(gt,p)[g].weight();
00090 DT detjac = e.geometry().integrationElement(local);
00091 RT q = problem.q(global,e,local);
00092 integralq += q*q*weight*detjac;
00093 }
00094 integralq *= h_K*h_K;
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
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
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
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
00135 if (first || !gt.isSimplex())
00136 {
00137 jac = e.geometry().jacobianInverseTransposed(local);
00138 Kjac = problem.K(center,e,local);
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]);
00147 }
00148 }
00149
00150
00151 if (it.neighbor())
00152 {
00153
00154 facebctype = BoundaryConditions::process;
00155
00156
00157 for (int i=0; i<sfs.size(); i++)
00158 {
00159 facefluxK[i] = -(cache[i]*unitOuterNormal);
00160 }
00161
00162
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);
00179 facefluxN[i] = -(Kgradphi*unitOuterNormal);
00180 }
00181 return;
00182 }
00183
00184
00185 if (it.boundary())
00186 {
00187
00188 facebctype = problem.bctype(global,e,local);
00189 if (facebctype!=BoundaryConditions::neumann)
00190 return;
00191
00192
00193 facefluxN[0] = problem.J(global,e,local);
00194
00195
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
00233 *eta2 = 0;
00234
00235
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
00241 assert(it->isLeaf());
00242
00243
00244 Dune::GeometryType gt = it->type();
00245
00246
00247 RT elementpart;
00248 loc.estimate(*it,elementpart);
00249 (*eta2)[eta2.mapper().map(*it)] += elementpart;
00250
00251
00252
00253 IntersectionIterator iendit = it->ileafend();
00254 bool first=true;
00255 for (IntersectionIterator iit = it->ileafbegin(); iit!=iendit; ++iit)
00256 {
00257
00258 if (iit->neighbor())
00259 {
00260
00261
00262 const EEntityPointer outside = iit->outside();
00263
00264
00265 if (!outside->isLeaf())
00266 continue;
00267
00268
00269 if (outside->level()==it->level() && eta2.mapper().map(*it)<eta2.mapper().map(*outside))
00270 continue;
00271
00272
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
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
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
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
00299 if (iit->boundary())
00300 {
00301
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
00310 if (facebctype!=BoundaryConditions::neumann)
00311 continue;
00312
00313
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
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