1 // -*- tab-width: 4; indent-tabs-mode: nil -*-
2 #ifndef DUNE_PDELAB_TEST_TESTPOISSON_PERIODIC_HH
3 #define DUNE_PDELAB_TEST_TESTPOISSON_PERIODIC_HH
4 
5 
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9 
10 #include <dune/pdelab/boilerplate/pdelab.hh>
11 #include <dune/pdelab/localoperator/convectiondiffusionfem.hh>
12 #include <dune/pdelab/localoperator/convectiondiffusiondg.hh>
13 
14 // Poisson problem definition
15 template<typename GV, typename RF>
16 class GenericEllipticProblem
17 {
18   typedef Dune::PDELab::ConvectionDiffusionBoundaryConditions::Type BCType;
19 
20 public:
21   typedef Dune::PDELab::ConvectionDiffusionParameterTraits<GV,RF> Traits;
22 
23   //! tensor diffusion constant per cell? return false if you want more than one evaluation of A per cell.
permeabilityIsConstantPerCell()24   static constexpr bool permeabilityIsConstantPerCell()
25   {
26     return true;
27   }
28 
29   //! tensor diffusion coefficient
30   typename Traits::PermTensorType
A(const typename Traits::ElementType & e,const typename Traits::DomainType & x) const31   A (const typename Traits::ElementType& e, const typename Traits::DomainType& x) const
32   {
33     typename Traits::PermTensorType I;
34     for (std::size_t i=0; i<Traits::dimDomain; i++)
35       for (std::size_t j=0; j<Traits::dimDomain; j++)
36         I[i][j] = (i==j) ? 1 : 0;
37     return I;
38   }
39 
40   //! velocity field
41   typename Traits::RangeType
b(const typename Traits::ElementType & e,const typename Traits::DomainType & x) const42   b (const typename Traits::ElementType& e, const typename Traits::DomainType& x) const
43   {
44     typename Traits::RangeType v(0.0);
45     return v;
46   }
47 
48   //! sink term
49   typename Traits::RangeFieldType
c(const typename Traits::ElementType & e,const typename Traits::DomainType & x) const50   c (const typename Traits::ElementType& e, const typename Traits::DomainType& x) const
51   {
52     return 0.0;
53   }
54 
55   //! source term
56   typename Traits::RangeFieldType
f(const typename Traits::ElementType & e,const typename Traits::DomainType & xlocal) const57   f (const typename Traits::ElementType& e, const typename Traits::DomainType& xlocal) const
58   {
59     auto x = e.geometry().global(xlocal);
60     return x[0] * std::sin(5.0*M_PI*x[1]) + std::exp(-((x[0]-0.5)*(x[0]-0.5) + (x[1]-0.5)*(x[1]-0.5)) / 0.02);
61   }
62 
63   //! Boundary condition type function. Will not be evaluated on periodic boundary, so we simply set Dirichlet.
64   BCType
bctype(const typename Traits::IntersectionType & is,const typename Traits::IntersectionDomainType & x) const65   bctype (const typename Traits::IntersectionType& is, const typename Traits::IntersectionDomainType& x) const
66   {
67     return Dune::PDELab::ConvectionDiffusionBoundaryConditions::Dirichlet;
68   }
69 
70   //! Dirichlet boundary condition value
71   typename Traits::RangeFieldType
g(const typename Traits::ElementType & e,const typename Traits::DomainType & xlocal) const72   g (const typename Traits::ElementType& e, const typename Traits::DomainType& xlocal) const
73   {
74     return 0.0;
75   }
76 
77   //! flux boundary condition
78   typename Traits::RangeFieldType
j(const typename Traits::IntersectionType & is,const typename Traits::IntersectionDomainType & x) const79   j (const typename Traits::IntersectionType& is, const typename Traits::IntersectionDomainType& x) const
80   {
81     return 0.0;
82   }
83 
84   //! outflow boundary condition
85   typename Traits::RangeFieldType
o(const typename Traits::IntersectionType & is,const typename Traits::IntersectionDomainType & x) const86   o (const typename Traits::IntersectionType& is, const typename Traits::IntersectionDomainType& x) const
87   {
88     return 0.0;
89   }
90 };
91 
92 // Problem solver
93 template<typename GridType, typename NumberType, int dim>
poisson(GridType & grid)94 void poisson (GridType& grid)
95 {
96 #if DG == 0
97     const Dune::PDELab::MeshType meshtype = Dune::PDELab::MeshType::conforming;
98 #endif
99     const Dune::SolverCategory::Category solvertype = Dune::SolverCategory::overlapping;
100     const Dune::GeometryType::BasicType elemtype = Dune::GeometryType::cube;
101 
102     // make problem parameters
103     typedef GenericEllipticProblem<typename GridType::LeafGridView,NumberType> Problem;
104     Problem problem;
105     typedef Dune::PDELab::ConvectionDiffusionBoundaryConditionAdapter<Problem> BCType;
106     BCType bctype(grid.leafGridView(),problem);
107 
108     // make a finite element space
109 #if DG == 0
110     typedef Dune::PDELab::CGSpace<GridType,NumberType,DEGREE,BCType,elemtype,meshtype,solvertype> FS;
111     FS fs(grid,bctype);
112 #else
113     typedef Dune::PDELab::DGQkSpace<GridType,NumberType,DEGREE,elemtype,solvertype> FS;
114     FS fs(grid.leafGridView());
115 #endif
116 
117     // make a degree of freedom vector and initialize it with a function
118     typedef typename FS::DOF V;
119     V x(fs.getGFS(),0.0);
120 
121 #if DG == 0
122     typedef Dune::PDELab::ConvectionDiffusionDirichletExtensionAdapter<Problem> G;
123     G g(grid.leafGridView(),problem);
124     Dune::PDELab::interpolate(g,fs.getGFS(),x);
125 #endif
126 
127     // assemble constraints
128     fs.assembleConstraints(bctype);
129     fs.setNonConstrainedDOFS(x,0.0);
130 
131     // assembler for finite elemenent problem
132 #if DG == 0
133     typedef Dune::PDELab::ConvectionDiffusionFEM<Problem,typename FS::FEM> LOP;
134     LOP lop(problem);
135     typedef Dune::PDELab::GalerkinGlobalAssembler<FS,LOP,solvertype> ASSEMBLER;
136     ASSEMBLER assembler(fs,lop,27);
137 #else
138     typedef Dune::PDELab::ConvectionDiffusionDG<Problem,typename FS::FEM> LOP;
139     LOP lop(problem,Dune::PDELab::ConvectionDiffusionDGMethod::SIPG,Dune::PDELab::ConvectionDiffusionDGWeights::weightsOn,2.0);
140     typedef Dune::PDELab::GalerkinGlobalAssembler<FS,LOP,solvertype> ASSEMBLER;
141     ASSEMBLER assembler(fs,lop,27);
142 #endif
143 
144     // make linear solver and solve problem
145     typedef Dune::PDELab::ISTLSolverBackend_IterativeDefault<FS,ASSEMBLER,solvertype> SBE;
146     SBE sbe(fs,assembler,5000,1);
147 
148     typedef Dune::PDELab::StationaryLinearProblemSolver<typename ASSEMBLER::GO,typename SBE::LS,V> SLP;
149     SLP slp(*assembler,*sbe,x,1e-6);
150     slp.apply();
151 
152     // // print statistics about nonzero values per row
153     // typename ASSEMBLER::MAT m(assembler.getGO());
154     // std::cout << m.patternStatistics() << std::endl;
155 
156     // output grid to VTK file
157     Dune::SubsamplingVTKWriter<typename GridType::LeafGridView> vtkwriter(grid.leafGridView(),Dune::refinementIntervals(DEGREE));
158     typename FS::DGF xdgf(fs.getGFS(),x);
159     vtkwriter.addVertexData(std::make_shared<typename FS::VTKF>(xdgf,"x_h"));
160     auto out_name = "poisson_periodic_" + std::to_string(dim) + "d_q" + std::to_string(DEGREE) + "_dg" + std::to_string(DG);
161     vtkwriter.write(out_name, Dune::VTK::appendedraw);
162 }
163 
164 #endif // DUNE_PDELAB_TEST_TESTPOISSON_PERIODIC_HH
165