00001
00002
00003 #ifndef DUNE_P1OPERATOR_HH
00004 #define DUNE_P1OPERATOR_HH
00005
00006 #include<iostream>
00007 #include<vector>
00008 #include<set>
00009 #include<map>
00010 #include<stdio.h>
00011 #include<stdlib.h>
00012
00013 #include<dune/common/timer.hh>
00014 #include<dune/common/fvector.hh>
00015 #include<dune/common/fmatrix.hh>
00016 #include<dune/common/exceptions.hh>
00017 #include<dune/common/geometrytype.hh>
00018 #include<dune/grid/common/grid.hh>
00019 #include<dune/grid/common/mcmgmapper.hh>
00020
00021 #include<dune/istl/bvector.hh>
00022 #include<dune/istl/operators.hh>
00023 #include<dune/istl/bcrsmatrix.hh>
00024 #include<dune/disc/functions/p1function.hh>
00025 #include<dune/disc/shapefunctions/lagrangeshapefunctions.hh>
00026 #include"boundaryconditions.hh"
00027 #include"localstiffness.hh"
00028
00045 namespace Dune
00046 {
00056
00057 typedef std::pair<int,int> P1OperatorLink;
00058
00059
00060 template<int n, int c>
00061 struct P1Operator_meta {
00062 template<class Entity, class VMapper, class AMapper, class Refelem, class Matrix>
00063 static void addrowscube (const Entity& e, const VMapper& vertexmapper, const AMapper& allmapper,
00064 const Refelem& refelem, Matrix& A, std::vector<bool>& visited,
00065 int hangingnodes, std::set<P1OperatorLink>& links)
00066 {
00067 if (refelem.type(0,0).isCube())
00068 {
00069 for (int i=0; i<refelem.size(c); i++)
00070 {
00071 int index = allmapper.template map<c>(e,i);
00072 if (!visited[index])
00073 {
00074 int corners = refelem.size(i,c,n);
00075 for (int j=0; j<corners/2; j++)
00076 {
00077 int alpha = vertexmapper.template map<n>(e,refelem.subEntity(i,c,j,n));
00078 int beta = vertexmapper.template map<n>(e,refelem.subEntity(i,c,corners-1-j,n));
00079 A.incrementrowsize(alpha);
00080 A.incrementrowsize(beta);
00081 if (hangingnodes>0)
00082 {
00083 links.erase(P1OperatorLink(alpha,beta));
00084 links.erase(P1OperatorLink(beta,alpha));
00085 }
00086 }
00087 visited[index] = true;
00088 }
00089 }
00090 }
00091 if (refelem.type(0,0).isPyramid() && c==1)
00092 {
00093 int index = allmapper.template map<c>(e,0);
00094 if (!visited[index])
00095 {
00096 int alpha = vertexmapper.template map<n>(e,0);
00097 int beta = vertexmapper.template map<n>(e,2);
00098 A.incrementrowsize(alpha);
00099 A.incrementrowsize(beta);
00100 if (hangingnodes>0)
00101 {
00102 links.erase(P1OperatorLink(alpha,beta));
00103 links.erase(P1OperatorLink(beta,alpha));
00104 }
00105 alpha = vertexmapper.template map<n>(e,1);
00106 beta = vertexmapper.template map<n>(e,3);
00107 A.incrementrowsize(alpha);
00108 A.incrementrowsize(beta);
00109 if (hangingnodes>0)
00110 {
00111 links.erase(P1OperatorLink(alpha,beta));
00112 links.erase(P1OperatorLink(beta,alpha));
00113 }
00114 visited[index] = true;
00115 }
00116 }
00117 if (refelem.type(0,0).isPrism() && c==1)
00118 {
00119 int index = allmapper.template map<c>(e,1);
00120 if (!visited[index])
00121 {
00122 int alpha = vertexmapper.template map<n>(e,0);
00123 int beta = vertexmapper.template map<n>(e,4);
00124 A.incrementrowsize(alpha);
00125 A.incrementrowsize(beta);
00126 if (hangingnodes>0)
00127 {
00128 links.erase(P1OperatorLink(alpha,beta));
00129 links.erase(P1OperatorLink(beta,alpha));
00130 }
00131 alpha = vertexmapper.template map<n>(e,1);
00132 beta = vertexmapper.template map<n>(e,3);
00133 A.incrementrowsize(alpha);
00134 A.incrementrowsize(beta);
00135 if (hangingnodes>0)
00136 {
00137 links.erase(P1OperatorLink(alpha,beta));
00138 links.erase(P1OperatorLink(beta,alpha));
00139 }
00140 visited[index] = true;
00141 }
00142 index = allmapper.template map<c>(e,2);
00143 if (!visited[index])
00144 {
00145 int alpha = vertexmapper.template map<n>(e,1);
00146 int beta = vertexmapper.template map<n>(e,5);
00147 A.incrementrowsize(alpha);
00148 A.incrementrowsize(beta);
00149 if (hangingnodes>0)
00150 {
00151 links.erase(P1OperatorLink(alpha,beta));
00152 links.erase(P1OperatorLink(beta,alpha));
00153 }
00154 alpha = vertexmapper.template map<n>(e,2);
00155 beta = vertexmapper.template map<n>(e,4);
00156 A.incrementrowsize(alpha);
00157 A.incrementrowsize(beta);
00158 if (hangingnodes>0)
00159 {
00160 links.erase(P1OperatorLink(alpha,beta));
00161 links.erase(P1OperatorLink(beta,alpha));
00162 }
00163 visited[index] = true;
00164 }
00165 index = allmapper.template map<c>(e,3);
00166 if (!visited[index])
00167 {
00168 int alpha = vertexmapper.template map<n>(e,0);
00169 int beta = vertexmapper.template map<n>(e,5);
00170 A.incrementrowsize(alpha);
00171 A.incrementrowsize(beta);
00172 if (hangingnodes>0)
00173 {
00174 links.erase(P1OperatorLink(alpha,beta));
00175 links.erase(P1OperatorLink(beta,alpha));
00176 }
00177 alpha = vertexmapper.template map<n>(e,2);
00178 beta = vertexmapper.template map<n>(e,3);
00179 A.incrementrowsize(alpha);
00180 A.incrementrowsize(beta);
00181 if (hangingnodes>0)
00182 {
00183 links.erase(P1OperatorLink(alpha,beta));
00184 links.erase(P1OperatorLink(beta,alpha));
00185 }
00186 visited[index] = true;
00187 }
00188 }
00189 P1Operator_meta<n,c-1>::addrowscube(e,vertexmapper,allmapper,refelem,A,visited,hangingnodes,links);
00190 return;
00191 }
00192 template<class Entity, class VMapper, class AMapper, class Refelem, class Matrix>
00193 static void addindicescube (const Entity& e, const VMapper& vertexmapper, const AMapper& allmapper,
00194 const Refelem& refelem, Matrix& A, std::vector<bool>& visited)
00195 {
00196 if (refelem.type(0,0).isCube())
00197 {
00198 for (int i=0; i<refelem.size(c); i++)
00199 {
00200 int index = allmapper.template map<c>(e,i);
00201 if (!visited[index])
00202 {
00203 int corners = refelem.size(i,c,n);
00204 for (int j=0; j<corners/2; j++)
00205 {
00206 int alpha = vertexmapper.template map<n>(e,refelem.subEntity(i,c,j,n));
00207 int beta = vertexmapper.template map<n>(e,refelem.subEntity(i,c,corners-1-j,n));
00208 A.addindex(alpha,beta);
00209 A.addindex(beta,alpha);
00210 }
00211 visited[index] = true;
00212 }
00213 }
00214 }
00215 if (refelem.type(0,0).isPyramid() && c==1)
00216 {
00217 int index = allmapper.template map<c>(e,0);
00218 if (!visited[index])
00219 {
00220 int alpha = vertexmapper.template map<n>(e,0);
00221 int beta = vertexmapper.template map<n>(e,2);
00222 A.addindex(alpha,beta);
00223 A.addindex(beta,alpha);
00224 alpha = vertexmapper.template map<n>(e,1);
00225 beta = vertexmapper.template map<n>(e,3);
00226 A.addindex(alpha,beta);
00227 A.addindex(beta,alpha);
00228 visited[index] = true;
00229 }
00230 }
00231 if (refelem.type(0,0).isPrism() && c==1)
00232 {
00233 int index = allmapper.template map<c>(e,1);
00234 if (!visited[index])
00235 {
00236 int alpha = vertexmapper.template map<n>(e,0);
00237 int beta = vertexmapper.template map<n>(e,4);
00238 A.addindex(alpha,beta);
00239 A.addindex(beta,alpha);
00240 alpha = vertexmapper.template map<n>(e,1);
00241 beta = vertexmapper.template map<n>(e,3);
00242 A.addindex(alpha,beta);
00243 A.addindex(beta,alpha);
00244 visited[index] = true;
00245 }
00246 index = allmapper.template map<c>(e,2);
00247 if (!visited[index])
00248 {
00249 int alpha = vertexmapper.template map<n>(e,1);
00250 int beta = vertexmapper.template map<n>(e,5);
00251 A.addindex(alpha,beta);
00252 A.addindex(beta,alpha);
00253 alpha = vertexmapper.template map<n>(e,2);
00254 beta = vertexmapper.template map<n>(e,4);
00255 A.addindex(alpha,beta);
00256 A.addindex(beta,alpha);
00257 visited[index] = true;
00258 }
00259 index = allmapper.template map<c>(e,3);
00260 if (!visited[index])
00261 {
00262 int alpha = vertexmapper.template map<n>(e,0);
00263 int beta = vertexmapper.template map<n>(e,5);
00264 A.addindex(alpha,beta);
00265 A.addindex(beta,alpha);
00266 alpha = vertexmapper.template map<n>(e,2);
00267 beta = vertexmapper.template map<n>(e,3);
00268 A.addindex(alpha,beta);
00269 A.addindex(beta,alpha);
00270 visited[index] = true;
00271 }
00272 }
00273 P1Operator_meta<n,c-1>::addindicescube(e,vertexmapper,allmapper,refelem,A,visited);
00274 return;
00275 }
00276 };
00277 template<int n>
00278 struct P1Operator_meta<n,0> {
00279 template<class Entity, class VMapper, class AMapper, class Refelem, class Matrix>
00280 static void addrowscube (const Entity& e, const VMapper& vertexmapper, const AMapper& allmapper,
00281 const Refelem& refelem, Matrix& A, std::vector<bool>& visited,
00282 int hangingnodes, std::set<P1OperatorLink>& links)
00283 {
00284 if (!refelem.type(0,0).isCube()) return;
00285 int corners = refelem.size(n);
00286 for (int j=0; j<corners/2; j++)
00287 {
00288 int alpha = vertexmapper.template map<n>(e,refelem.subEntity(0,0,j,n));
00289 int beta = vertexmapper.template map<n>(e,refelem.subEntity(0,0,corners-1-j,n));
00290 A.incrementrowsize(alpha);
00291 A.incrementrowsize(beta);
00292 if (hangingnodes>0)
00293 {
00294 links.erase(P1OperatorLink(alpha,beta));
00295 links.erase(P1OperatorLink(beta,alpha));
00296 }
00297 }
00298 return;
00299 }
00300 template<class Entity, class VMapper, class AMapper, class Refelem, class Matrix>
00301 static void addindicescube (const Entity& e, const VMapper& vertexmapper, const AMapper& allmapper,
00302 const Refelem& refelem, Matrix& A, std::vector<bool>& visited)
00303 {
00304 if (!refelem.type(0,0).isCube()) return;
00305 int corners = refelem.size(n);
00306 for (int j=0; j<corners/2; j++)
00307 {
00308 int alpha = vertexmapper.template map<n>(e,refelem.subEntity(0,0,j,n));
00309 int beta = vertexmapper.template map<n>(e,refelem.subEntity(0,0,corners-1-j,n));
00310 A.addindex(alpha,beta);
00311 A.addindex(beta,alpha);
00312 }
00313 return;
00314 }
00315 };
00316
00317
00318 template<int n>
00319 struct P1Operator_meta<n,-1> {
00320 template<class Entity, class VMapper, class AMapper, class Refelem, class Matrix>
00321 static void addrowscube (const Entity& e, const VMapper& vertexmapper, const AMapper& allmapper,
00322 const Refelem& refelem, Matrix& A, std::vector<bool>& visited,
00323 int hangingnodes, std::set<P1OperatorLink>& links)
00324 {
00325 return;
00326 }
00327 template<class Entity, class VMapper, class AMapper, class Refelem, class Matrix>
00328 static void addindicescube (const Entity& e, const VMapper& vertexmapper, const AMapper& allmapper,
00329 const Refelem& refelem, Matrix& A, std::vector<bool>& visited)
00330 {
00331 return;
00332 }
00333 };
00334
00335 template<typename Grid, typename RT, bool hasHangingNodes>
00336 struct HangingNodesIdentifier
00337 {};
00338
00339 template<typename Grid,typename RT>
00340 struct HangingNodesIdentifier<Grid,RT,false>
00341 {
00342 template<typename IndexSet, typename VM>
00343 inline void process(std::vector<unsigned char> S, std::vector<bool>& hanging, std::set<P1OperatorLink>& links, IndexSet& indexset, VM& vertexmapper) const
00344 {}
00345
00346 inline std::size_t count() const
00347 {
00348 return 0;
00349 }
00350 };
00351
00352 template<typename Grid,typename RT>
00353 class HangingNodesIdentifier<Grid,RT,true>
00354 {
00355 public:
00356 typedef typename Grid::ctype DT;
00357 enum {n=Grid::dimension};
00358 typedef typename Grid::template Codim<0>::EntityPointer EEntityPointer;
00359
00360 template<typename GridView, typename VM>
00361 void process(std::vector<unsigned char> S, std::vector<bool>& hanging, std::set<P1OperatorLink>& links, GridView& gridView, VM& vertexmapper)
00362 {
00363
00364 typedef typename GridView::template Codim<0>::Iterator Iterator;
00365
00366 Iterator eendit = gridView.template end<0>();
00367 for (Iterator it = gridView.template begin<0>(); it!=eendit; ++it)
00368 {
00369 Dune::GeometryType gt = it->type();
00370 const typename Dune::ReferenceElementContainer<DT,n>::value_type&
00371 refelem = ReferenceElements<DT,n>::general(gt);
00372
00373
00374 for (int i=0; i<refelem.size(n); i++)
00375 {
00376 int alpha = vertexmapper.template map<n>(*it,i);
00377 if (S[alpha]>it->level()) S[alpha] = it->level();
00378 }
00379 }
00380
00381
00382 for (Iterator it = gridView.template begin<0>(); it!=eendit; ++it)
00383 {
00384 Dune::GeometryType gt = it->type();
00385 const typename Dune::ReferenceElementContainer<DT,n>::value_type&
00386 refelem = ReferenceElements<DT,n>::general(gt);
00387
00388
00389 typename GridView::IntersectionIterator endiit = gridView.iend(*it);
00390 for (typename GridView::IntersectionIterator iit = gridView.ibegin(*it); iit!=endiit; ++iit)
00391 if (iit->neighbor())
00392 {
00393
00394 const EEntityPointer outside = iit->outside();
00395 if (it->level()<=outside->level()) continue;
00396
00397
00398 for (int j=0; j<refelem.size(iit->numberInSelf(),1,n); j++)
00399 {
00400 int alpha = vertexmapper.template map<n>(*it,refelem.subEntity(iit->numberInSelf(),1,j,n));
00401 if (S[alpha]==it->level())
00402 hanging[alpha] = true;
00403 }
00404 }
00405 }
00406
00407
00408 int l2g[Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::maxsize];
00409 int fl2g[Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::maxsize];
00410
00411
00412 for (Iterator it = gridView.template begin<0>(); it!=eendit; ++it)
00413 {
00414 Dune::GeometryType gt = it->type();
00415 const typename Dune::ReferenceElementContainer<DT,n>::value_type&
00416 refelem = ReferenceElements<DT,n>::general(gt);
00417
00418
00419 bool hasHangingNodes = false;
00420 for (int i=0; i<refelem.size(n); i++)
00421 {
00422 l2g[i] = vertexmapper.template map<n>(*it,i);
00423 if (hanging[l2g[i]]) hasHangingNodes=true;
00424 }
00425 if (!hasHangingNodes) continue;
00426
00427
00428
00429 const EEntityPointer father = it->father();
00430
00431
00432 for (int i=0; i<refelem.size(n); i++)
00433 fl2g[i] = vertexmapper.template map<n>(*father,i);
00434
00435
00436 std::map<int,int> g2l;
00437 for (int i=0; i<refelem.size(n); i++)
00438 g2l[l2g[i]] = i;
00439
00440
00441 for (int i=0; i<refelem.size(n); i++)
00442 for (int j=0; j<refelem.size(n); j++)
00443 if (g2l.find(fl2g[j])==g2l.end())
00444 {
00445 links.insert(P1OperatorLink(l2g[i],fl2g[j]));
00446 links.insert(P1OperatorLink(fl2g[j],l2g[i]));
00447 }
00448 }
00449
00450 hangingnodes = 0;
00451 for (int i=0; i<vertexmapper.size(); i++)
00452 if (hanging[i]) hangingnodes++;
00453
00454 }
00455 inline std::size_t count() const
00456 {
00457 return hangingnodes;
00458 }
00459 private:
00460 std::size_t hangingnodes;
00461 };
00462
00463
00464
00475 template<class G, class RT, class GV, class LC, int m=1>
00476 class P1OperatorBase
00477 {
00478 public:
00479
00480 typedef FieldMatrix<RT,m,m> BlockType;
00481 typedef BCRSMatrix<BlockType> RepresentationType;
00482
00483
00484 template<int dim>
00485 struct P1Layout
00486 {
00487 bool contains (Dune::GeometryType gt)
00488 {
00489 return gt.dim() == 0;
00490 }
00491 };
00492
00493
00494 template<int dim>
00495 struct AllLayout
00496 {
00497 bool contains (Dune::GeometryType gt)
00498 {
00499 return true;
00500 }
00501 };
00502
00503 typedef typename G::ctype DT;
00504 enum {n=G::dimension};
00505 typedef typename GV::IndexSet IS;
00506 typedef typename G::template Codim<0>::Entity Entity;
00507 typedef typename GV::template Codim<0>::Iterator Iterator;
00508 typedef typename GV::template Codim<n>::Iterator VIterator;
00509 typedef typename G::template Codim<0>::EntityPointer EEntityPointer;
00510 typedef typename G::Traits::GlobalIdSet IDS;
00511 typedef typename IDS::IdType IdType;
00512 typedef std::set<IdType> GIDSet;
00513 typedef MultipleCodimMultipleGeomTypeMapper<G,IS,P1Layout> VM;
00514 typedef MultipleCodimMultipleGeomTypeMapper<G,IS,AllLayout> AM;
00515
00516 private:
00517
00518
00519
00520 int nnz (const IS& is)
00521 {
00522 int s = 0;
00523 s += is.size(n);
00524 s += 2*is.size(n-1);
00525
00526 for (int c=0; c<n-1; c++)
00527 {
00528 s += 2*is.size(GeometryType(GeometryType::cube,G::dimension-c))*(1<<(n-c-1));
00529 }
00530
00531
00532 s += links.size();
00533
00534 return s;
00535 }
00536
00537
00538
00539
00540
00541
00542
00543 bool init (const G& g, const GV& gridView, LC lc, bool extendoverlap)
00544 {
00545
00546 if (extendoverlap && g.overlapSize(0)>0)
00547 DUNE_THROW(GridError,"P1OperatorBase: extending overlap requires nonoverlapping grid");
00548 extendOverlap = extendoverlap;
00549 extraDOFs = 0;
00550
00551
00552 watch.reset();
00553
00554 hanging.resize(vertexmapper.size(), false);
00555
00556 std::vector<unsigned char> S(vertexmapper.size(), 100);
00557
00558
00559 typedef HangingNodesIdentifier<G,RT,Dune::Capabilities::template hasHangingNodes<G>::v>
00560 HangingNodesIdentifier;
00561 HangingNodesIdentifier hangingNodes;
00562 hangingNodes.process(S,hanging,links,gridView,vertexmapper);
00563
00564
00565 hangingnodes = hangingNodes.count();
00566
00567
00568
00569
00570 watch.reset();
00571 if (extendOverlap)
00572 {
00573
00574 std::map<int,GIDSet> borderlinks;
00575
00576
00577 P1ExtendOverlap<G,GV,VM,LC> extender(lc);
00578 extender.extend(g,gv,vertexmapper,borderlinks,extraDOFs,gid2index);
00579
00580
00581
00582 for (typename std::map<int,GIDSet>::iterator i=borderlinks.begin(); i!=borderlinks.end(); ++i)
00583 for (typename GIDSet::iterator j=(i->second).begin(); j!=(i->second).end(); ++j)
00584 links.insert(P1OperatorLink(i->first,gid2index[*j]));
00585
00586
00587 for (int i=0; i<extraDOFs; i++)
00588 links.insert(P1OperatorLink(vertexmapper.size()+i,vertexmapper.size()+i));
00589 }
00590
00591
00592
00593
00594
00595 return true;
00596 }
00597
00598
00599
00600 int size () const
00601 {
00602 return vertexmapper.size()+extraDOFs;
00603 }
00604
00605 struct MatEntry
00606 {
00607 IdType first;
00608 BlockType second;
00609 MatEntry (const IdType& f, const BlockType& s) : first(f),second(s) {}
00610 MatEntry () {}
00611 };
00612
00613
00614 class MatEntryExchange :
00615 public CommDataHandleIF<MatEntryExchange,MatEntry> {
00616 typedef typename RepresentationType::RowIterator rowiterator;
00617 typedef typename RepresentationType::ColIterator coliterator;
00618 public:
00620 typedef MatEntry DataType;
00621
00623 bool contains (int dim, int codim) const
00624 {
00625 return (codim==dim);
00626 }
00627
00629 bool fixedsize (int dim, int codim) const
00630 {
00631 return false;
00632 }
00633
00638 template<class EntityType>
00639 size_t size (EntityType& e) const
00640 {
00641 int i=vertexmapper.map(e);
00642 int n=0;
00643 for (coliterator j=A[i].begin(); j!=A[i].end(); ++j)
00644 n++;
00645 return n;
00646 }
00647
00649 template<class MessageBuffer, class EntityType>
00650 void gather (MessageBuffer& buff, const EntityType& e) const
00651 {
00652 int i=vertexmapper.map(e);
00653 for (coliterator j=A[i].begin(); j!=A[i].end(); ++j)
00654 {
00655 typename std::map<int,IdType>::const_iterator it=index2gid.find(j.index());
00656 if (it==index2gid.end())
00657 DUNE_THROW(GridError,"MatEntryExchange::gather(): index not in map");
00658 buff.write(MatEntry(it->second,*j));
00659 }
00660 }
00661
00666 template<class MessageBuffer, class EntityType>
00667 void scatter (MessageBuffer& buff, const EntityType& e, size_t n)
00668 {
00669 int i=vertexmapper.map(e);
00670 for (size_t k=0; k<n; k++)
00671 {
00672 MatEntry m;
00673 buff.read(m);
00674 typename std::map<IdType,int>::const_iterator it=gid2index.find(m.first);
00675 if (it==gid2index.end())
00676 DUNE_THROW(GridError,"MatEntryExchange::scatter(): gid not in map");
00677 A[i][it->second] += m.second;
00678 }
00679 }
00680
00682 MatEntryExchange (const G& g, const std::map<IdType,int>& g2i,
00683 const std::map<int,IdType>& i2g,
00684 const VM& vm,
00685 RepresentationType& a)
00686 : grid(g), gid2index(g2i), index2gid(i2g), vertexmapper(vm), A(a)
00687 {}
00688
00689 private:
00690 const G& grid;
00691 const std::map<IdType,int>& gid2index;
00692 const std::map<int,IdType>& index2gid;
00693 const VM& vertexmapper;
00694 RepresentationType& A;
00695 };
00696
00697 public:
00698
00699 P1OperatorBase (const G& g, const GV& gridView, LC lcomm, bool extendoverlap=false)
00700 : grid(g),gv(gridView),lc(lcomm),vertexmapper(g,gridView.indexSet()),allmapper(g,gridView.indexSet()),links(),
00701 initialized(init(g,gridView,lc,extendoverlap)),A(size(),size(),nnz(gridView.indexSet()),RepresentationType::random)
00702
00703 {
00704
00705
00706 std::cout << g.comm().rank() << ": " << "making " << size() << "x"
00707 << size() << " matrix with " << nnz(gv.indexSet()) << " nonzeros" << std::endl;
00708
00709
00710
00711
00712
00713 for (size_t i=0; i<gv.indexSet().size(n); i++)
00714 A.setrowsize(i,0);
00715
00716
00717 std::vector<bool> visited(allmapper.size());
00718 for (int i=0; i<allmapper.size(); i++) visited[i] = false;
00719
00720
00721 watch.reset();
00722 Iterator eendit = gv.template end<0>();
00723 for (Iterator it = gv.template begin<0>(); it!=eendit; ++it)
00724 {
00725 Dune::GeometryType gt = it->type();
00726 const typename Dune::ReferenceElementContainer<DT,n>::value_type&
00727 refelem = ReferenceElements<DT,n>::general(gt);
00728
00729
00730 for (int i=0; i<refelem.size(n); i++)
00731 {
00732 int index = allmapper.template map<n>(*it,i);
00733 int alpha = vertexmapper.template map<n>(*it,i);
00734
00735 if (!visited[index])
00736 {
00737 A.incrementrowsize(alpha);
00738 visited[index] = true;
00739
00740 }
00741 }
00742
00743
00744 for (int i=0; i<refelem.size(n-1); i++)
00745 {
00746 int index = allmapper.template map<n-1>(*it,i);
00747 int alpha = vertexmapper.template map<n>(*it,refelem.subEntity(i,n-1,0,n));
00748 int beta = vertexmapper.template map<n>(*it,refelem.subEntity(i,n-1,1,n));
00749 if (!visited[index])
00750 {
00751 A.incrementrowsize(alpha);
00752 A.incrementrowsize(beta);
00753 visited[index] = true;
00754 if (hangingnodes>0 || extendOverlap)
00755 {
00756 links.erase(P1OperatorLink(alpha,beta));
00757 links.erase(P1OperatorLink(beta,alpha));
00758 }
00759 }
00760 }
00761
00762
00763 if (!gt.isSimplex())
00764 P1Operator_meta<n,n-2>::addrowscube(*it,vertexmapper,allmapper,refelem,A,visited,hangingnodes+(extendOverlap),links);
00765 }
00766
00767
00768 for (typename std::set<P1OperatorLink>::iterator i=links.begin(); i!=links.end(); ++i)
00769 A.incrementrowsize(i->first);
00770
00771
00772 A.endrowsizes();
00773
00774
00775
00776 for (int i=0; i<allmapper.size(); i++) visited[i] = false;
00777
00778
00779 watch.reset();
00780 for (Iterator it = gv.template begin<0>(); it!=eendit; ++it)
00781 {
00782 Dune::GeometryType gt = it->type();
00783 const typename Dune::ReferenceElementContainer<DT,n>::value_type&
00784 refelem = ReferenceElements<DT,n>::general(gt);
00785
00786
00787
00788 for (int i=0; i<refelem.size(n); i++)
00789 {
00790 int index = allmapper.template map<n>(*it,i);
00791 int alpha = vertexmapper.template map<n>(*it,i);
00792
00793 if (!visited[index])
00794 {
00795 A.addindex(alpha,alpha);
00796 visited[index] = true;
00797 }
00798 }
00799
00800
00801 for (int i=0; i<refelem.size(n-1); i++)
00802 {
00803 int index = allmapper.template map<n-1>(*it,i);
00804
00805 if (!visited[index])
00806 {
00807 int alpha = vertexmapper.template map<n>(*it,refelem.subEntity(i,n-1,0,n));
00808 int beta = vertexmapper.template map<n>(*it,refelem.subEntity(i,n-1,1,n));
00809 A.addindex(alpha,beta);
00810 A.addindex(beta,alpha);
00811 visited[index] = true;
00812
00813
00814 }
00815 }
00816
00817
00818 if (!gt.isSimplex())
00819 P1Operator_meta<n,n-2>::addindicescube(*it,vertexmapper,allmapper,refelem,A,visited);
00820 }
00821
00822
00823 for (typename std::set<P1OperatorLink>::iterator i=links.begin(); i!=links.end(); ++i)
00824 A.addindex(i->first,i->second);
00825
00826
00827 A.endindices();
00828
00829
00830
00831 links.clear();
00832
00833
00834 }
00835
00837 const RepresentationType& operator* () const
00838 {
00839 return A;
00840 }
00841
00843 RepresentationType& operator* ()
00844 {
00845 return A;
00846 }
00847
00849 void sumEntries ()
00850 {
00851 if (!extendOverlap) return;
00852
00853
00854 std::map<int,IdType> index2gid;
00855 for (typename std::map<IdType,int>::iterator i=gid2index.begin(); i!=gid2index.end(); ++i)
00856 index2gid[i->second] = i->first;
00857
00858
00859 MatEntryExchange datahandle(grid,gid2index,index2gid,vertexmapper,A);
00860 lc.template communicate<MatEntryExchange>(datahandle,
00861 InteriorBorder_InteriorBorder_Interface,
00862 ForwardCommunication);
00863 }
00864
00865 protected:
00866 Timer watch;
00867 const G& grid;
00868 const GV gv;
00869 LC lc;
00870 VM vertexmapper;
00871 AM allmapper;
00872 std::vector<bool> hanging;
00873 std::set<P1OperatorLink> links;
00874 int hangingnodes;
00875 bool extendOverlap;
00876 int extraDOFs;
00877 std::map<IdType,int> gid2index;
00878 bool initialized;
00879 RepresentationType A;
00880 };
00881
00882
00883
00884
00888 template<class G, class RT, class GV, class LC, int m>
00889 class P1OperatorAssembler : public P1OperatorBase<G,RT,GV,LC,m>
00890 {
00891 typedef typename G::ctype DT;
00892 enum {n=G::dimension};
00893 typedef typename GV::IndexSet IS;
00894 typedef typename G::template Codim<0>::Entity Entity;
00895 typedef typename GV::template Codim<0>::Iterator Iterator;
00896 typedef typename GV::template Codim<n>::Iterator VIterator;
00897 typedef typename G::template Codim<0>::HierarchicIterator HierarchicIterator;
00898 typedef typename G::template Codim<0>::EntityPointer EEntityPointer;
00899 typedef typename P1Function<GV,RT,LC,m>::RepresentationType VectorType;
00900 typedef typename VectorType::block_type VBlockType;
00901 typedef typename P1OperatorBase<G,RT,GV,LC,m>::RepresentationType MatrixType;
00902 typedef typename MatrixType::field_type MFieldType;
00903 typedef typename MatrixType::block_type MBlockType;
00904 typedef typename MatrixType::RowIterator rowiterator;
00905 typedef typename MatrixType::ColIterator coliterator;
00906 typedef typename P1OperatorBase<G,RT,GV,LC,m>::VM VM;
00907 typedef array<BoundaryConditions::Flags,m> BCBlockType;
00908
00909
00910
00911 class AccumulateBCFlags :
00912 public CommDataHandleIF<AccumulateBCFlags,std::pair<BCBlockType,VBlockType> > {
00913 public:
00915 typedef std::pair<BCBlockType,VBlockType> DataType;
00916
00918 bool contains (int dim, int codim) const
00919 {
00920 return (codim==dim);
00921 }
00922
00924 bool fixedsize (int dim, int codim) const
00925 {
00926 return true;
00927 }
00928
00933 template<class EntityType>
00934 size_t size (EntityType& e) const
00935 {
00936 return 1;
00937 }
00938
00940 template<class MessageBuffer, class EntityType>
00941 void gather (MessageBuffer& buff, const EntityType& e) const
00942 {
00943 int alpha = vertexmapper.map(e);
00944 buff.write(DataType(essential[alpha],f[alpha]));
00945 }
00946
00951 template<class MessageBuffer, class EntityType>
00952 void scatter (MessageBuffer& buff, const EntityType& e, size_t n)
00953 {
00954 DataType x;
00955 buff.read(x);
00956 int alpha = vertexmapper.map(e);
00957 for (int i=0; i<m; i++)
00958 if (x.first[i]>essential[alpha][i])
00959 {
00960 essential[alpha][i] = x.first[i];
00961 f[alpha][i] = x.second[i];
00962 }
00963 }
00964
00966 AccumulateBCFlags (const G& g, const VM& vm, std::vector<BCBlockType>& e, VectorType& _f)
00967 : grid(g), essential(e), vertexmapper(vm), f(_f)
00968 {}
00969
00970 private:
00971 const G& grid;
00972 std::vector<BCBlockType>& essential;
00973 const VM& vertexmapper;
00974 VectorType& f;
00975 };
00976
00977
00978
00979 public:
00980 P1OperatorAssembler (const G& g, const GV& gridView, LC lcomm, bool extendoverlap=false)
00981 : P1OperatorBase<G,RT,GV,LC,m>(g,gridView,lcomm,extendoverlap)
00982 { }
00983
00984
01005 void assemble (LocalStiffness<GV,RT,m>& loc, P1Function<GV,RT,LC,m>& u, P1Function<GV,RT,LC,m>& f)
01006 {
01007
01008 if ((*u).N()!=this->A.M() || (*f).N()!=this->A.N())
01009 DUNE_THROW(MathError,"P1OperatorAssembler::assemble(): size mismatch");
01010
01011
01012 this->watch.reset();
01013 this->A = 0;
01014 *f = 0;
01015
01016
01017
01018 std::vector<BCBlockType> essential(this->vertexmapper.size());
01019 for (typename std::vector<BCBlockType>::size_type i=0; i<essential.size(); i++)
01020 essential[i].assign(BoundaryConditions::neumann);
01021
01022
01023 std::vector<unsigned char> treated(this->vertexmapper.size());
01024 for (std::vector<unsigned char>::size_type
01025 i=0; i<treated.size(); i++) treated[i] = false;
01026
01027
01028 RT alpha[Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::maxsize][Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::maxsize];
01029
01030
01031 int l2g[Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::maxsize];
01032 int fl2g[Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::maxsize];
01033
01034
01035 Iterator eendit = this->gv.template end<0>();
01036 for (Iterator it = this->gv.template begin<0>(); it!=eendit; ++it)
01037 {
01038
01039 if (it->partitionType()==GhostEntity)
01040 continue;
01041
01042
01043 Dune::GeometryType gt = it->type();
01044 const typename Dune::LagrangeShapeFunctionSetContainer<DT,RT,n>::value_type&
01045 sfs=Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1);
01046
01047
01048 for (int k=0; k<sfs.size(); k++)
01049 {
01050 if (sfs[k].codim()!=n) DUNE_THROW(MathError,"expected codim==dim");
01051 int alpha = this->vertexmapper.template map<n>(*it,sfs[k].entity());
01052 l2g[k] = alpha;
01053 }
01054
01055
01056
01057 loc.template assemble(*it);
01058
01059
01060
01061 bool hasHangingNodes = false;
01062 for (int k=0; k<sfs.size(); k++)
01063 {
01064
01065 if (!this->hanging[l2g[k]]) continue;
01066 hasHangingNodes = true;
01067
01068
01069 EEntityPointer father=it->father();
01070 GeometryType gtf = father->type();
01071 assert(gtf==gt);
01072 const FieldVector<DT,n>& cpos=Dune::LagrangeShapeFunctions<DT,RT,n>::general(gt,1)[k].position();
01073 FieldVector<DT,n> pos = it->geometryInFather().global(cpos);
01074
01075
01076 for (int i=0; i<Dune::LagrangeShapeFunctions<DT,RT,n>::general(gtf,1).size(); ++i)
01077 {
01078 alpha[i][k] = Dune::LagrangeShapeFunctions<DT,RT,n>::general(gtf,1)[i].evaluateFunction(0,pos);
01079 fl2g[i] = this->vertexmapper.template map<n>(*father,i);
01080 }
01081
01082
01083 if (!treated[l2g[k]])
01084 {
01085 bool throwflag=false;
01086 int cnt=0;
01087 for (int i=0; i<Dune::LagrangeShapeFunctions<DT,RT,n>::general(gtf,1).size(); ++i)
01088 if (std::abs(alpha[i][k])>1E-4)
01089 {
01090 if (this->hanging[fl2g[i]])
01091 {
01092 std::cout << "X i=" << father->geometry().corner(i)
01093 << " k=" << it->geometry().corner(k)
01094 << " alpha=" << alpha[i][k]
01095 << " cnt=" << ++cnt
01096 << std::endl;
01097 throwflag = true;
01098 }
01099 this->A[l2g[k]][fl2g[i]] = MFieldType();
01100 }
01101 if (throwflag)
01102 DUNE_THROW(GridError,"hanging node interpolated from hanging node");
01103 for (int comp=0; comp<m; comp++)
01104 this->A[l2g[k]][l2g[k]][comp][comp] = static_cast<MFieldType>(1);
01105 (*f)[l2g[k]] = 0;
01106 (*u)[l2g[k]] = 0;
01107 treated[l2g[k]] = true;
01108 }
01109 }
01110
01111
01112 for (int i=0; i<sfs.size(); i++)
01113 {
01114
01115 if (this->hanging[l2g[i]]) continue;
01116
01117
01118 for (int j=0; j<sfs.size(); j++)
01119 {
01120
01121 if (this->hanging[l2g[j]]) continue;
01122
01123
01124 this->A[l2g[i]][l2g[j]] += loc.mat(i,j);
01125 }
01126
01127
01128 for (int comp=0; comp<m; comp++)
01129 {
01130 if (loc.bc(i)[comp]>essential[l2g[i]][comp])
01131 {
01132 essential[l2g[i]][comp] = loc.bc(i)[comp];
01133 (*f)[l2g[i]][comp] = loc.rhs(i)[comp];
01134 }
01135 if (essential[l2g[i]][comp]==BoundaryConditions::neumann)
01136 (*f)[l2g[i]][comp] += loc.rhs(i)[comp];
01137 }
01138 }
01139
01140
01141 if (hasHangingNodes)
01142 {
01143
01144 std::map<int,int> g2l;
01145 for (int i=0; i<sfs.size(); i++)
01146 g2l[l2g[i]] = i;
01147
01148
01149 std::map<int,int> fg2l;
01150 for (int i=0; i<sfs.size(); i++)
01151 fg2l[fl2g[i]] = i;
01152
01153 EEntityPointer father=it->father();
01154
01155
01156 for (int i=0; i<sfs.size(); ++i)
01157 {
01158
01159
01160 for (int j=0; j<sfs.size(); ++j)
01161 {
01162
01163 for (int k=0; k<sfs.size(); k++)
01164 {
01165
01166 if (!this->hanging[l2g[k]]) continue;
01167
01168
01169 if ( std::abs(alpha[j][k])>1E-4 && g2l.find(fl2g[i])!=g2l.end() )
01170 {
01171 accumulate(this->A[fl2g[i]][fl2g[j]],alpha[j][k],loc.mat(g2l[fl2g[i]],k));
01172 }
01173
01174
01175 if ( std::abs(alpha[j][k])>1E-4 && fg2l.find(l2g[i])==fg2l.end() && !this->hanging[l2g[i]])
01176 {
01177 accumulate(this->A[l2g[i]][fl2g[j]],alpha[j][k],loc.mat(i,k));
01178 }
01179
01180
01181 if ( std::abs(alpha[i][k])>1E-4 && g2l.find(fl2g[j])!=g2l.end() )
01182 {
01183 accumulate(this->A[fl2g[i]][fl2g[j]],alpha[i][k],loc.mat(k,g2l[fl2g[j]]));
01184 }
01185
01186
01187 if ( std::abs(alpha[i][k])>1E-4 && fg2l.find(l2g[j])==fg2l.end() && !this->hanging[l2g[j]])
01188 {
01189 accumulate(this->A[fl2g[i]][l2g[j]],alpha[i][k],loc.mat(k,j));
01190 }
01191
01192
01193 for (int l=0; l<sfs.size(); l++)
01194 {
01195
01196 if (!this->hanging[l2g[l]]) continue;
01197
01198 if ( std::abs(alpha[i][k])>1E-4 && std::abs(alpha[j][l])>1E-4 )
01199 {
01200 accumulate(this->A[fl2g[i]][fl2g[j]],alpha[i][k]*alpha[j][l],loc.mat(k,l));
01201 }
01202 }
01203 }
01204 }
01205
01206
01207 for (int comp=0; comp<m; comp++)
01208 if (essential[fl2g[i]][comp]==BoundaryConditions::neumann)
01209 for (int k=0; k<sfs.size(); k++)
01210 {
01211
01212 if (!this->hanging[l2g[k]]) continue;
01213
01214 if ( std::abs(alpha[i][k])>1E-4 && loc.bc(k)[comp]==BoundaryConditions::neumann )
01215 (*f)[fl2g[i]][comp] += alpha[i][k]*loc.rhs(k)[comp];
01216 }
01217 }
01218 }
01219 }
01220
01221
01222 if (this->extendOverlap)
01223 this->sumEntries();
01224
01225
01226 if (this->extendOverlap)
01227 {
01228 AccumulateBCFlags datahandle(this->grid,this->vertexmapper,essential,*f);
01229 this->lc.template communicate<AccumulateBCFlags>(datahandle,InteriorBorder_InteriorBorder_Interface,ForwardCommunication);
01230
01231 }
01232
01233
01234
01235 VIterator vendit = this->gv.template end<n>();
01236 for (VIterator it = this->gv.template begin<n>(); it!=vendit; ++it)
01237 if (it->partitionType()==GhostEntity)
01238 {
01239
01240 int i=this->vertexmapper.map(*it);
01241
01242
01243 coliterator endj=this->A[i].end();
01244 for (coliterator j=this->A[i].begin(); j!=endj; ++j)
01245 {
01246 (*j) = MFieldType();
01247 if (j.index()==i)
01248 for (int comp=0; comp<m; comp++)
01249 (*j)[comp][comp] = static_cast<MFieldType>(1);
01250 }
01251 (*f)[i] = 0;
01252 }
01253
01254
01255 rowiterator endi=this->A.end();
01256 for (rowiterator i=this->A.begin(); i!=endi; ++i)
01257 {
01258
01259 if (i.index()>=this->vertexmapper.size())
01260 {
01261 coliterator endj=(*i).end();
01262 for (coliterator j=(*i).begin(); j!=endj; ++j)
01263 {
01264 (*j) = MFieldType();
01265 if (j.index()==i.index())
01266 for (int comp=0; comp<m; comp++)
01267 (*j)[comp][comp] = static_cast<MFieldType>(1);
01268 }
01269 (*f)[i.index()] = 0;
01270 continue;
01271 }
01272
01273
01274 if (!this->hanging[i.index()])
01275 {
01276 for (int icomp=0; icomp<m; icomp++)
01277 if (essential[i.index()][icomp]!=BoundaryConditions::neumann)
01278 {
01279 coliterator endj=(*i).end();
01280 for (coliterator j=(*i).begin(); j!=endj; ++j)
01281 if (j.index()==i.index())
01282 {
01283 for (int jcomp=0; jcomp<m; jcomp++)
01284 if (icomp==jcomp)
01285 (*j)[icomp][jcomp] = static_cast<MFieldType>(1);
01286 else
01287 (*j)[icomp][jcomp] = MFieldType();
01288 }
01289 else
01290 {
01291 for (int jcomp=0; jcomp<m; jcomp++)
01292 (*j)[icomp][jcomp] = MFieldType();
01293 }
01294 (*u)[i.index()][icomp] = (*f)[i.index()][icomp];
01295 }
01296 }
01297 }
01298 }
01299
01301 void interpolateHangingNodes (P1Function<GV,RT,LC,m>& u)
01302 {
01303
01304 std::vector<unsigned char> treated(this->vertexmapper.size());
01305 for (std::size_t i=0; i<treated.size(); i++) treated[i] = false;
01306
01307
01308 Iterator eendit = this->gv.template end<0>();
01309 for (Iterator it = this->gv.template begin<0>(); it!=eendit; ++it)
01310 {
01311
01312 Dune::GeometryType gt = it->type();
01313 const