1 #ifndef DUNE_FEM_COMMON_EXPLICITFIELDVECTOR_HH
2 #define DUNE_FEM_COMMON_EXPLICITFIELDVECTOR_HH
3 
4 #include <type_traits>
5 #include <utility>
6 
7 #include <dune/common/fmatrix.hh>
8 #include <dune/common/fvector.hh>
9 #include <dune/common/typeutilities.hh>
10 
11 namespace Dune
12 {
13 
14   namespace Fem
15   {
16     /**A variant of FieldVector which does not allow for implicit
17      * type-conversion from an to everything.
18      */
19     template<class T, int N>
20     class ExplicitFieldVector;
21   }
22 
23   template<class T, int N>
24   struct DenseMatVecTraits< Fem::ExplicitFieldVector<T, N> >
25     : DenseMatVecTraits<FieldVector<T, N> >
26   {
27     typedef Fem::ExplicitFieldVector<T, N> derived_type;
28   };
29 
30   template<class T, int N>
31   struct FieldTraits<Fem::ExplicitFieldVector<T, N> >
32     : FieldTraits<FieldVector<T, N> >
33   {};
34 
35   template<typename T, int N, int M>
36   struct IsFieldVectorSizeCorrect<Fem::ExplicitFieldVector<T, N>, M>
37     : IsFieldVectorSizeCorrect<FieldVector<T, N>, M>
38   {};
39 
40   namespace Fem {
41 
42     /**std::true_type for containers containing field elements.*/
43     template<class T>
44     struct IsFieldType
45       : std::is_same<typename FieldTraits<T>::field_type, T>
46     {};
47 
48     /**Accept implicit type conversion from any DenseVector to a field
49      * vector only if both vectors contain field elements of some type
50      * or both vectors do NOT contain field elements of some kind and
51      * the elements of the DenseVector are convertible to the field
52      * vector's elements.
53      *
54      * This inhibits the initialization of a FieldVector of complex
55      * objects like matrices from a field vector of scalars.
56      */
57     template<class C, class T, class SFINAE = void>
58     struct AcceptElementImplicitConstruction
59       : IsFieldType<C>
60     {};
61 
62     template<class C, class T>
63     struct AcceptElementImplicitConstruction<
64       C, T,
65       std::enable_if_t<((IsFieldType<typename DenseMatVecTraits<C>::value_type>::value
66                          ==
67                          IsFieldType<T>::value)
68         )> >
69       : std::true_type
70     {};
71 
72     template<class T, int N>
73     class ExplicitFieldVector
74       : public Dune::FieldVector<T, N>
75     {
76       typedef ExplicitFieldVector< T, N > ThisType;
77       typedef Dune::FieldVector<T, N> BaseType;
78      public:
79       //! Constructor making default-initialized vector
ExplicitFieldVector()80       constexpr ExplicitFieldVector()
81         : BaseType()
82       {}
83 
84       /**Redirect any general construction to the base class during
85        * explicit conversion
86        */
87       template< class... Args, disableCopyMove< ThisType, Args... > = 0, std::enable_if_t< std::is_constructible< BaseType, Args &&... >::value, int > = 0 >
ExplicitFieldVector(Args &&...args)88       explicit ExplicitFieldVector ( Args &&... args )
89         : BaseType( std::forward< Args >( args )... )
90       {}
91 
ExplicitFieldVector(const std::initializer_list<T> & values)92       ExplicitFieldVector ( const std::initializer_list< T > &values )
93         : BaseType( values )
94       {}
95 
96       /**Allow implicit conversion if both vectors are either
97        * composed of field-elements of some fields which can be
98        * converted into each other or if both vectors are composed of
99        * more complicated elements (which can be converted into each
100        * other), but do not allow implicit conversion of a FieldVector
101        * of scalars into a FieldVector composed of more complicated
102        * stuff. In particalar, FunctionSpace::RangeType cannot be
103        * implicitly converted to FunctionSpace::HessianRangeType.
104        */
105       template<class C>
ExplicitFieldVector(const DenseVector<C> & x,typename std::enable_if<(IsFieldVectorSizeCorrect<C,N>::value && AcceptElementImplicitConstruction<C,T>::value)>::type * dummy=0)106       ExplicitFieldVector(const DenseVector<C>& x,
107                           typename std::enable_if<(
108                             IsFieldVectorSizeCorrect<C, N>::value
109                             &&
110                             AcceptElementImplicitConstruction<C, T>::value)
111                           >::type* dummy=0 )
112         : BaseType(x)
113       {}
114 
115       //! Assignment operator for scalar
116       template<typename C,
117                std::enable_if_t<(
118                  N == 1 &&
119                  AcceptElementImplicitConstruction<C, T>::value &&
120                  std::is_assignable<T, C>::value &&
121                  ! std::is_base_of<DenseVector<typename FieldTraits<T>::field_type>, T
122                                    >::value
123                  ), int> = 0
124                >
operator =(const C & c)125       ExplicitFieldVector& operator=(const C& c)
126       {
127         (*this)[0] = c;
128         return *this;
129       }
130 
131       //! Inherit assignment
132       // using BaseType::operator=; <- give ambiguous overloads
133       using DenseVector<FieldVector<T, N> >::operator=;
134 
135       //! copy assignment operator
operator =(const ExplicitFieldVector & other)136       ExplicitFieldVector& operator=(const ExplicitFieldVector& other)
137       {
138         static_cast<BaseType&>(*this) = static_cast<const BaseType&>(other);
139         return *this;
140       }
141 
142       template <typename C, std::enable_if_t<std::is_assignable<T, C>::value, int> = 0>
operator =(const FieldVector<C,N> & other)143       ExplicitFieldVector& operator=(const FieldVector<C, N>& other)
144       {
145         static_cast<BaseType&>(*this) = other;
146         return *this;
147       }
148 
149       template <typename C, std::enable_if_t<std::is_assignable<T, C>::value, int> = 0>
operator =(const ExplicitFieldVector<C,N> & other)150       ExplicitFieldVector& operator=(const ExplicitFieldVector<C, N>& other)
151       {
152         static_cast<BaseType&>(*this) = other;
153         return *this;
154       }
155 
156     };
157 
158     template<class FV>
159     struct MakeExplicit
160     {
161       using Type = FV;
162     };
163 
164     template<class Field, int Size>
165     struct MakeExplicit<FieldVector<Field, Size> >
166     {
167       using Type = ExplicitFieldVector<Field, Size>;
168     };
169 
170     template<class FV>
171     using Explicit = typename MakeExplicit<FV>::Type;
172 
173   } // Fem
174 
175 } // Dune
176 
177 
178 #endif // DUNE_FEM_COMMON_EXPLICITFIELDVECTOR_HH
179