1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 
5 #include <dune/istl/matrixmatrix.hh>
6 #include <dune/pdelab.hh>
7 
8 /** Parameter class for the stationary convection-diffusion equation of the following form:
9  *
10  * \f{align*}{
11  *   \nabla\cdot(-A(x) \nabla u + b(x) u) + c(x)u &=& f \mbox{ in } \Omega,  \ \
12  *                                              u &=& g \mbox{ on } \partial\Omega_D (Dirichlet)\ \
13  *                (b(x,u) - A(x)\nabla u) \cdot n &=& j \mbox{ on } \partial\Omega_N (Flux)\ \
14  *                        -(A(x)\nabla u) \cdot n &=& o \mbox{ on } \partial\Omega_O (Outflow)
15  * \f}
16  * Note:
17  *  - This formulation is valid for velocity fields which are non-divergence free.
18  *  - Outflow boundary conditions should only be set on the outflow boundary
19  *
20  * The template parameters are:
21  *  - GV a model of a GridView
22  *  - RF numeric type to represent results
23  */
24 
25 template<typename GV, typename RF>
26 class GenericEllipticProblem
27 {
28   typedef Dune::PDELab::ConvectionDiffusionBoundaryConditions::Type BCType;
29 
30 public:
31   typedef Dune::PDELab::ConvectionDiffusionParameterTraits<GV,RF> Traits;
32 
33   //! tensor diffusion constant per cell? return false if you want more than one evaluation of A per cell.
permeabilityIsConstantPerCell()34   static constexpr bool permeabilityIsConstantPerCell()
35   {
36     return true;
37   }
38 
39   //! tensor diffusion coefficient
40   typename Traits::PermTensorType
A(const typename Traits::ElementType & e,const typename Traits::DomainType & x) const41   A (const typename Traits::ElementType& e, const typename Traits::DomainType& x) const
42   {
43     typename Traits::PermTensorType I;
44     for (std::size_t i=0; i<Traits::dimDomain; i++)
45       for (std::size_t j=0; j<Traits::dimDomain; j++)
46         I[i][j] = (i==j) ? 1 : 0;
47     return I;
48   }
49 
50   //! velocity field
51   typename Traits::RangeType
b(const typename Traits::ElementType & e,const typename Traits::DomainType & x) const52   b (const typename Traits::ElementType& e, const typename Traits::DomainType& x) const
53   {
54     typename Traits::RangeType v(0.0);
55     return v;
56   }
57 
58   //! sink term
59   typename Traits::RangeFieldType
c(const typename Traits::ElementType & e,const typename Traits::DomainType & x) const60   c (const typename Traits::ElementType& e, const typename Traits::DomainType& x) const
61   {
62     return 0.0;
63   }
64 
65   //! source term
66   typename Traits::RangeFieldType
f(const typename Traits::ElementType & e,const typename Traits::DomainType & x) const67   f (const typename Traits::ElementType& e, const typename Traits::DomainType& x) const
68   {
69     return 0.0;
70   }
71 
72   //! boundary condition type function
73   /* return Dune::PDELab::ConvectionDiffusionBoundaryConditions::Dirichlet for Dirichlet boundary conditions
74    * return Dune::PDELab::ConvectionDiffusionBoundaryConditions::Neumann for flux boundary conditions
75    * return Dune::PDELab::ConvectionDiffusionBoundaryConditions::Outflow for outflow boundary conditions
76    */
77   BCType
bctype(const typename Traits::IntersectionType & is,const typename Traits::IntersectionDomainType & x) const78   bctype (const typename Traits::IntersectionType& is, const typename Traits::IntersectionDomainType& x) const
79   {
80     return Dune::PDELab::ConvectionDiffusionBoundaryConditions::Dirichlet;
81   }
82 
83   //! Dirichlet boundary condition value
84   typename Traits::RangeFieldType
g(const typename Traits::ElementType & e,const typename Traits::DomainType & xlocal) const85   g (const typename Traits::ElementType& e, const typename Traits::DomainType& xlocal) const
86   {
87     typename Traits::DomainType x = e.geometry().global(xlocal);
88     return exp(-(x*x));
89   }
90 
91   //! flux boundary condition
92   typename Traits::RangeFieldType
j(const typename Traits::IntersectionType & is,const typename Traits::IntersectionDomainType & x) const93   j (const typename Traits::IntersectionType& is, const typename Traits::IntersectionDomainType& x) const
94   {
95     return 0.0;
96   }
97 
98   //! outflow boundary condition
99   typename Traits::RangeFieldType
o(const typename Traits::IntersectionType & is,const typename Traits::IntersectionDomainType & x) const100   o (const typename Traits::IntersectionType& is, const typename Traits::IntersectionDomainType& x) const
101   {
102     return 0.0;
103   }
104 };
105 
main(int argc,char ** argv)106 int main(int argc, char **argv)
107 {
108   // initialize MPI, finalize is done automatically on exit
109   Dune::MPIHelper::instance(argc,argv);
110 
111   // command line args
112   int cells=16; if (argc>=2) sscanf(argv[1],"%d",&cells);
113   int refinements=0; if (argc>=3) sscanf(argv[2],"%d",&refinements);
114 
115   Dune::Timer watch;
116 
117   // define parameters
118   const unsigned int dim = 2;
119   const unsigned int degree = 1;
120   const Dune::GeometryType::BasicType elemtype = Dune::GeometryType::cube;
121   const Dune::PDELab::MeshType meshtype = Dune::PDELab::MeshType::conforming;
122   const Dune::SolverCategory::Category solvertype = Dune::SolverCategory::overlapping;
123   typedef double NumberType;
124 
125   // make grid
126   typedef Dune::YaspGrid<dim> GM;
127   typedef Dune::PDELab::StructuredGrid<GM> Grid;
128   Grid grid(elemtype,cells,1);
129   grid->loadBalance();
130   grid->refineOptions(false);
131   grid->globalRefine(refinements);
132 
133   // make problem parameters
134   typedef GenericEllipticProblem<GM::LeafGridView,NumberType> Problem;
135   Problem problem;
136   // make dummy constraints parameters, DG has no essential boundary conditions
137   typedef Dune::PDELab::DirichletConstraintsParameters BCType;
138   BCType bctype;
139 
140   // make DG finite element space
141   typedef Dune::PDELab::DGQkSpace<GM,NumberType,degree,elemtype,solvertype> FS;
142   FS fs(grid->leafGridView());
143   fs.assembleConstraints(bctype);
144   //std::cout << "number of constraints is " << fs.getCC().size() << std::endl;
145 
146   // assembler for finite elemenent problem
147   typedef Dune::PDELab::ConvectionDiffusionDG<Problem,typename FS::FEM> LOP;
148   LOP lop(problem,Dune::PDELab::ConvectionDiffusionDGMethod::SIPG,Dune::PDELab::ConvectionDiffusionDGWeights::weightsOn,2.0);
149   typedef Dune::PDELab::GalerkinGlobalAssemblerNewBackend<FS,LOP,solvertype> ASSEMBLER;
150   ASSEMBLER assembler(fs,lop,ASSEMBLER::MBE(5)); // 5 entries per row with cartesian mesh in 2D and blocked DG space
151 
152   // allocate solution vector
153   typedef FS::DOF V;
154   V x(fs.getGFS(),0.0);
155   std::cout << "number of elements is " << Dune::PDELab::Backend::native(x).N() << std::endl;
156 
157   // use purely Neumann-zero boundary conditions
158   // projected matrix from DG space has no essential boundary conditions
159   typedef Dune::PDELab::NoDirichletConstraintsParameters CGBCType;
160   CGBCType cgbctype;
161   // CG space
162   typedef Dune::PDELab::CGSpace<GM,NumberType,1,CGBCType,elemtype,meshtype,solvertype> CGFS;
163   CGFS cgfs(*grid,cgbctype);
164   cgfs.assembleConstraints(cgbctype);
165 
166   // need to set up my own grid operator that does not use P0Constraints
167   typedef typename FS::GFS GFS;
168   typedef typename FS::CC DGCC2;
169   DGCC2 dgcc2; // empty: no constraints!
170   typedef Dune::PDELab::ISTL::BCRSMatrixBackend<> MBE;
171   typedef Dune::PDELab::GridOperator<GFS,GFS,LOP,MBE,NumberType,NumberType,NumberType,DGCC2,DGCC2> DGGO2;
172   DGGO2 dggo2(fs.getGFS(),dgcc2,fs.getGFS(),dgcc2,lop,MBE(5));
173 
174   /////////////////// SEQUENTIAL
175   // make linear solver and solve problem
176   {
177       typedef Dune::PDELab::ISTLBackend_SEQ_AMG_4_DG<ASSEMBLER::GO,CGFS::GFS,
178                                                      Dune::PDELab::CG2DGProlongation,Dune::SeqSSOR,Dune::CGSolver> LS;
179       LS ls(assembler.getGO(),cgfs.getGFS(),1000,3);
180       // set parameters for AMG in CG-subspace
181       Dune::Amg::Parameters params = ls.parameters();
182       params.setCoarsenTarget(2000);
183       params.setMaxLevel(20);
184       params.setProlongationDampingFactor(1.8);
185       params.setNoPreSmoothSteps(2);
186       params.setNoPostSmoothSteps(2);
187       params.setGamma(1);
188       params.setAdditive(false);
189       ls.setParameters(params);
190       typedef Dune::PDELab::StationaryLinearProblemSolver<DGGO2,LS,V> SLP;
191       SLP slp(dggo2,ls,x,1e-8);
192       slp.setHangingNodeModifications(false);
193       slp.apply();
194   }
195 
196   /////////////////// OVERLAPPING
197   // reset initial iterate
198   x = 0.0;
199   // make linear solver and solve problem
200 #if HAVE_MPI
201   {
202       typedef Dune::PDELab::ISTLBackend_OVLP_AMG_4_DG<ASSEMBLER::GO,FS::CC,CGFS::GFS,CGFS::CC,
203                                                       Dune::PDELab::CG2DGProlongation,Dune::SeqSSOR,Dune::CGSolver> LS;
204       LS ls(assembler.getGO(),fs.getCC(),cgfs.getGFS(),cgfs.getCC(),1000,3);
205       // set parameters for AMG in CG-subspace
206       Dune::Amg::Parameters params = ls.parameters();
207       params.setCoarsenTarget(2000);
208       params.setMaxLevel(20);
209       params.setProlongationDampingFactor(1.8);
210       params.setNoPreSmoothSteps(2);
211       params.setNoPostSmoothSteps(2);
212       params.setGamma(1);
213       params.setAdditive(false);
214       ls.setParameters(params);
215       typedef Dune::PDELab::StationaryLinearProblemSolver<DGGO2,LS,V> SLP;
216       SLP slp(dggo2,ls,x,1e-8);
217       slp.setHangingNodeModifications(false);
218       slp.apply();
219   }
220 #endif // HAVE_MPI
221 
222   // done
223   return 0;
224 }
225