1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
7 
8 #include <iostream>
9 
10 #include <dune/common/filledarray.hh>
11 #include <dune/common/parallel/mpihelper.hh>
12 
13 #include <dune/grid/yaspgrid.hh>
14 
15 #include <dune/pdelab.hh>
16 
17 // Wrapped Qk local basis which can have a zero size on some elements
18 template <class T, int k, int d> struct WrappedBasis {
19   using Basis = Dune::QkStuff::QkLocalBasis<T, T, k, d>;
20 
21   Basis basis;
22   bool setZero;
23 
WrappedBasisWrappedBasis24   WrappedBasis() : setZero(false) {}
25 
sizeWrappedBasis26   unsigned int size() const { return setZero ? 0 : basis.size(); }
27 
28   inline void
evaluateFunctionWrappedBasis29   evaluateFunction(const typename Basis::Traits::DomainType &in,
30                    std::vector<typename Basis::Traits::RangeType> &out) const {
31     if (setZero)
32       out.clear();
33     else
34       basis.evaluateFunction(in, out);
35   }
36 
evaluateJacobianWrappedBasis37   void evaluateJacobian(
38       const typename Basis::Traits::DomainType &in,
39       std::vector<typename Basis::Traits::JacobianType> &out) const {
40     if (setZero)
41       out.clear();
42     else
43       basis.evaluateFunction(in, out);
44   }
45 
orderWrappedBasis46   unsigned int order() const { return setZero ? 0 : basis.order(); }
47 };
48 
49 // wrapped QkDG local coefficients which can have a zero size on some elements
50 template <int k, int d> struct WrappedCoefficients {
51   using Coefficients = Dune::QkStuff::QkDGLocalCoefficients<k, d>;
52 
53   Coefficients coeffs;
54   bool setZero;
55 
WrappedCoefficientsWrappedCoefficients56   WrappedCoefficients() : setZero(false) {}
57 
sizeWrappedCoefficients58   std::size_t size() const { return setZero ? 0 : coeffs.size(); }
59 
localKeyWrappedCoefficients60   const Dune::LocalKey &localKey(std::size_t i) const {
61     if (setZero) {
62       DUNE_THROW(Dune::Exception, "set zero");
63     } else {
64       return coeffs.localKey(i);
65     }
66   }
67 };
68 
69 // wrapped Qk local interpolation which can have a zero size on some elements
70 template <class T, int k, int d> struct WrappedInterpolation {
71   using Interpolation = Dune::QkStuff::QkLocalInterpolation<
72       k, d, Dune::QkStuff::QkLocalBasis<T, T, k, d>>;
73 
74   Interpolation interpolation;
75   bool setZero;
76 
WrappedInterpolationWrappedInterpolation77   WrappedInterpolation() : setZero(false) {}
78 
79   template <typename F, typename C>
interpolateWrappedInterpolation80   void interpolate(const F &f, std::vector<C> &out) const {
81     if (setZero)
82       out.clear();
83     else
84       interpolation.interpolate(f, out);
85   }
86 };
87 
88 // wrapped Qk local finite element which can have a zero size on some elements
89 template <class T, int k, int d> class WrappedFiniteElement {
90   using Basis = WrappedBasis<T, k, d>;
91   using Coefficients = WrappedCoefficients<k, d>;
92   using Interpolation = WrappedInterpolation<T, k, d>;
93 
94 public:
95   typedef Dune::LocalFiniteElementTraits<Basis, Coefficients, Interpolation>
96       Traits;
97 
WrappedFiniteElement()98   WrappedFiniteElement()
99     : gt(Dune::GeometryTypes::cube(d))
100   {}
101 
localBasis() const102   const typename Traits::LocalBasisType &localBasis() const { return basis; }
103 
localCoefficients() const104   const typename Traits::LocalCoefficientsType &localCoefficients() const {
105     return coefficients;
106   }
107 
localInterpolation() const108   const typename Traits::LocalInterpolationType &localInterpolation() const {
109     return interpolation;
110   }
111 
type() const112   Dune::GeometryType type() const { return gt; }
113 
clone() const114   WrappedFiniteElement *clone() const {
115     return new WrappedFiniteElement(*this);
116   }
117 
setZero(bool value)118   void setZero(bool value) {
119     basis.setZero = value;
120     coefficients.setZero = value;
121     interpolation.setZero = value;
122   }
123 
124 private:
125   Basis basis;
126   Coefficients coefficients;
127   Interpolation interpolation;
128   Dune::GeometryType gt;
129 };
130 
131 // wrapped QkDG local finite element map which has no local basis functions on
132 // elements with an even
133 // index
134 template <class GV, class T, int k, int d>
135 class WrappedFiniteElementMap
136     : public Dune::PDELab::LocalFiniteElementMapInterface<
137           Dune::PDELab::LocalFiniteElementMapTraits<
138               WrappedFiniteElement<T, k, d>>,
139           WrappedFiniteElementMap<GV, T, k, d>> {
140 
141 public:
142   using Traits =
143       Dune::PDELab::LocalFiniteElementMapTraits<WrappedFiniteElement<T, k, d>>;
144 
WrappedFiniteElementMap(const GV & gv_,unsigned int rank_)145   WrappedFiniteElementMap(const GV &gv_, unsigned int rank_)
146       : gv(gv_), rank(rank_) {}
147 
fixedSize() const148   bool fixedSize() const { return false; }
149 
hasDOFs(int codim) const150   bool hasDOFs(int codim) const { return codim == 0; }
151 
size(Dune::GeometryType gt) const152   std::size_t size(Dune::GeometryType gt) const {
153     DUNE_THROW(Dune::PDELab::VariableElementSize,
154                "the fem has variable element size");
155   }
156 
maxLocalSize() const157   std::size_t maxLocalSize() const {
158     return Dune::QkStuff::QkSize<k, d>::value;
159   }
160 
161   template <class EntityType>
find(const EntityType & e) const162   const typename Traits::FiniteElementType &find(const EntityType &e) const {
163     fe.setZero(gv.indexSet().index(e) % rank != 0);
164     return fe;
165   }
166 
167 private:
168   mutable WrappedFiniteElement<T, k, d> fe;
169   GV gv;
170   unsigned int rank;
171 };
172 
main(int argc,char ** argv)173 int main(int argc, char **argv) {
174   try {
175     // Maybe initialize Mpi
176     Dune::MPIHelper::instance(argc, argv);
177 
178     const int dim = 2;
179 
180     Dune::FieldVector<double, dim> L(1.0);
181     Dune::YaspGrid<dim> grid(L, Dune::filledArray<dim, int>(2));
182 
183     const int degree = 1;
184     const int blockSize = Dune::QkStuff::QkSize<degree, dim>::value;
185 
186     using GV = Dune::YaspGrid<dim>::LeafGridView;
187     using ES = Dune::PDELab::AllEntitySet<GV>;
188     using FEM = WrappedFiniteElementMap<GV, double, degree, dim>;
189     using VBE =
190         Dune::PDELab::ISTL::VectorBackend<Dune::PDELab::ISTL::Blocking::fixed,
191                                           blockSize>;
192     using GFS =
193         Dune::PDELab::GridFunctionSpace<ES, FEM, Dune::PDELab::NoConstraints,
194                                         VBE>;
195     using PVBE = Dune::PDELab::ISTL::VectorBackend<>;
196     using POT =
197         Dune::PDELab::ordering::Chunked<Dune::PDELab::EntityBlockedOrderingTag>;
198     using PGFS = Dune::PDELab::PowerGridFunctionSpace<
199         GFS, 2, Dune::PDELab::ISTL::VectorBackend<>, POT>;
200 
201     GV gv = grid.leafGridView();
202     FEM fem0(gv, 2);
203     FEM fem1(gv, 3);
204     ES es{gv};
205     auto gfs0 = std::make_shared<GFS>(es, fem0);
206     auto gfs1 = std::make_shared<GFS>(es, fem1);
207 
208     {
209       PGFS pgfs(*gfs0, *gfs1, PVBE(), POT(blockSize));
210       pgfs.ordering();
211     }
212 
213     {
214       std::array<std::shared_ptr<GFS>,2> containter{gfs0,gfs1};
215       PGFS pgfs(containter, PVBE(), POT(blockSize));
216       pgfs.ordering();
217     }
218 
219     return 0;
220   } catch (Dune::Exception &e) {
221     std::cerr << "Dune reported error: " << e << std::endl;
222     return 1;
223   } catch (...) {
224     std::cerr << "Unknown exception thrown!" << std::endl;
225     return 1;
226   }
227 }
228