DUNE-FEM (unstable)

checklinearoperator.hh
1#ifndef DUNE_FEM_OPERATOR_LINEAR_TEST_CHECKLINEAROPERATOR_HH
2#define DUNE_FEM_OPERATOR_LINEAR_TEST_CHECKLINEAROPERATOR_HH
3
4#include <cstddef>
5#include <cmath>
6
7#include <algorithm>
8#include <utility>
9#include <vector>
10
15
16#include <dune/fem/common/hybrid.hh>
17#include <dune/fem/operator/common/stencil.hh>
18#include <dune/fem/operator/common/temporarylocalmatrix.hh>
19
20namespace Dune
21{
22
23 namespace Fem
24 {
25
26 // DiagonalRange
27 // -------------
28
29 template< class DomainSpace, class RangeSpace >
30 struct DiagonalRange
31 {
32 struct Iterator
33 {
34 typedef typename DomainSpace::IteratorType Iterator1;
35 typedef typename DomainSpace::EntityType Entity1;
36 typedef typename RangeSpace::IteratorType Iterator2;
37 typedef typename RangeSpace::EntityType Entity2;
38
39 Iterator () = default;
40
41 Iterator ( Iterator1 it1, Iterator2 it2 ) : it_( it1, it2 ) {}
42
43 Iterator &operator++ () { ++it_.first; ++it_.second; return *this; }
44
45 std::pair< Entity1, Entity2 > operator* () const { return std::make_pair( *it_.first, *it_.second ); }
46
47 bool operator!= ( const Iterator &other ) const { return (it_ != other.it_); }
48 bool operator== ( const Iterator &other ) const { return (it_ == other.it_); }
49
50 private:
51 std::pair< Iterator1, Iterator2 > it_;
52 };
53
54 DiagonalRange ( const DomainSpace &dSpace, const RangeSpace &rSpace )
55 : dSpace_( dSpace ), rSpace_( rSpace )
56 {}
57
58 Iterator begin () const { return Iterator( dSpace_.begin(), rSpace_.begin() ); }
59 Iterator end () const { return Iterator( dSpace_.end(), rSpace_.end() ); }
60
61 protected:
62 const DomainSpace &dSpace_;
63 const RangeSpace &rSpace_;
64 };
65
66
67
68 // diagonalRange
69 // -------------
70
71 template< class Space1, class Space2 >
72 DiagonalRange< Space1, Space2 > diagonalRange ( const Space1 &space1, const Space2 &space2 )
73 {
74 return DiagonalRange< Space1, Space2 >( space1, space2 );
75 }
76
77
78
79 // RangeStencil
80 // ------------
81
82 template< class DomainSpace, class RangeSpace >
83 struct RangeStencil
84 : public Dune::Fem::Stencil< DomainSpace, RangeSpace >
85 {
86 typedef RangeStencil< DomainSpace, RangeSpace > ThisType;
88
89 template< class Range >
90 RangeStencil ( const DomainSpace &dSpace, const RangeSpace &rSpace, const Range &range )
91 : BaseType( dSpace, rSpace )
92 {
93 for( const auto &entry : range )
94 BaseType::fill( entry.first, entry.second );
95 }
96
97 virtual void setupStencil() const
98 {
99 DUNE_THROW(NotImplemented,"This is done in the constructor");
100 }
101 };
102
103
104
105 namespace CheckLinearOperator
106 {
107
108 template< class LocalMatrix >
109 inline void verifyPermutation ( const LocalMatrix &localMatrix, const std::vector< std::pair< int, int > > &permutation )
110 {
111 for( const auto &p : permutation )
112 {
113 if( localMatrix.get( p.first, p.second ) != 1.0 )
114 DUNE_THROW( Dune::NotImplemented, "LocalMatrix not set correctly" );
115 }
116 }
117
118 template< class LinearOperator, class DomainEntity, class RangeEntity >
119 inline void_t< typename LinearOperator::LocalMatrixType >
120 verifyLocalMatrixPermutation ( const LinearOperator &linOp, const DomainEntity &domainEntity, const RangeEntity &rangeEntity,
121 const std::vector< std::pair< int, int > > &permutation, PriorityTag< 1 > )
122 {
124 localMat( linOp.domainSpace(), linOp.rangeSpace() );
125 localMat.bind( domainEntity, rangeEntity );
126 linOp.getLocalMatrix( domainEntity, rangeEntity, localMat );
127 verifyPermutation( localMat, permutation );
128 localMat.unbind();
129 }
130
131 template< class LinearOperator, class DomainEntity, class RangeEntity >
132 inline void verifyLocalMatrixPermutation ( const LinearOperator &linOp, const DomainEntity &domainEntity, const RangeEntity &rangeEntity,
133 const std::vector< std::pair< int, int > > &permutation, PriorityTag< 0 > )
134 {
135 static bool warn = true;
136 if( warn )
137 std::cout << "Note: " << className( linOp ) << " does not support old-style local matrix interface." << std::endl;
138 warn = false;
139 }
140
141 template< class LinearOperator, class DomainEntity, class RangeEntity >
142 inline void verifyLocalMatrixPermutation ( const LinearOperator &linOp, const DomainEntity &domainEntity, const RangeEntity &rangeEntity,
143 const std::vector< std::pair< int, int > > &permutation )
144 {
145 verifyLocalMatrixPermutation( linOp, domainEntity, rangeEntity, permutation, PriorityTag< 42 >() );
146 }
147
148 } // namespace CheckLinearOperator
149
150
151
152 // checkLinearOperator
153 // -------------------
154
155 template< class LinearOperator, class Range >
156 inline void checkLinearOperator ( LinearOperator &linOp, const Range &range, const std::vector< std::pair< int, int > > &permutation )
157 {
158 typedef typename LinearOperator::DomainFunctionType DomainFunctionType;
159 typedef typename LinearOperator::RangeFunctionType RangeFunctionType;
160
161 // get type of domain and range function
162 typedef typename DomainFunctionType::DiscreteFunctionSpaceType DomainSpaceType;
163 typedef typename RangeFunctionType::DiscreteFunctionSpaceType RangeSpaceType;
164
165 // get spaces
166 const DomainSpaceType &dSpace = linOp.domainSpace();
167 const RangeSpaceType &rSpace = linOp.rangeSpace();
168
169 // construct some domain and range functions
170 DomainFunctionType domainFunction( "domain Function", dSpace );
171 RangeFunctionType rangeFunction1( "range Function1", rSpace );
172 RangeFunctionType rangeFunction2( "range Function2", rSpace );
173
174 // first test initialization
175 RangeStencil< DomainSpaceType, RangeSpaceType > stencil( dSpace, rSpace, range );
176
177 for( int k=0; k<4; ++k )
178 {
179 // check setting operator entries to zero
180 linOp.reserve( stencil );
181 linOp.clear();
182
184
185 // test assemble
186 // check {add,addScaled}LocalMatrix
187 for( const auto &entry : range )
188 {
189 auto domainEntity = entry.first;
190 auto rangeEntity = entry.second;
191
192 {
193 temp.init( domainEntity, rangeEntity );
194 temp.clear();
195 for( const auto &p : permutation )
196 temp.set( p.first, p.second, 1.0 );
197
198 linOp.addLocalMatrix( domainEntity, rangeEntity, temp );
199 linOp.addScaledLocalMatrix( domainEntity, rangeEntity, temp, -1.0 );
200 }
201 }
202
203 linOp.flushAssembly();
204
205 // check {set}LocalMatrix
206 for( const auto &entry : range )
207 {
208 auto domainEntity = entry.first;
209 auto rangeEntity = entry.second;
210
211 {
212 // check {add,set,addScaled}LocalMatrix
213 temp.init( domainEntity, rangeEntity );
214 temp.clear();
215 for( const auto &p : permutation )
216 temp.set( p.first, p.second, 1.0 );
217
218 linOp.setLocalMatrix( domainEntity, rangeEntity, temp );
219 }
220 }
221
222 linOp.flushAssembly();
223 if (k>=2) // just for checking 'clearRow' and reassembly so don't check content of matrix
224 {
225 try
226 {
227 linOp.unitRow(0);
228 linOp.finalize();
229 }
230 catch( const Dune::NotImplemented &exception )
231 {
232 std::cout << "operator does not implement unitRow method\n";
233 }
234 continue;
235 }
236
237 // test getLocalMatrix
238 for( const auto &entry : range )
239 {
240 auto domainEntity = entry.first;
241 auto rangeEntity = entry.second;
242
243 temp.init( domainEntity, rangeEntity );
244 temp.clear();
245 linOp.getLocalMatrix( domainEntity, rangeEntity, temp );
246 CheckLinearOperator::verifyPermutation( temp, permutation );
247
248 // check old localMatrix implementation
249 CheckLinearOperator::verifyLocalMatrixPermutation( linOp, domainEntity, rangeEntity, permutation );
250 }
251
252 // test application
253 domainFunction.clear();
254 std::size_t minNumDofs = std::min( domainFunction.blocks(), rangeFunction1.blocks() );
255 for( std::size_t i = 0; i < minNumDofs; ++i )
256 {
257 auto block = domainFunction.dofVector()[ i ];
258 Hybrid::forEach( typename DomainSpaceType::LocalBlockIndices(), [ &block, i ] ( auto &&j ) { block[ j ] = i; } );
259 }
260 linOp( domainFunction, rangeFunction1 );
261
262 // mimic operator apply manually
263 rangeFunction2.clear();
265 std::vector< double > values;
266 for( const auto &entry : range )
267 {
268 auto domainEntity = entry.first;
269 auto rangeEntity = entry.second;
270
271 tmp.resize( dSpace.blockMapper().numDofs( domainEntity ) * DomainSpaceType::localBlockSize );
272 domainFunction.getLocalDofs( domainEntity, tmp );
273
274 values.clear();
275 values.resize( rSpace.blockMapper().numDofs( rangeEntity ) * RangeSpaceType::localBlockSize, 0.0 );
276
277 for( const auto &p : permutation )
278 values[ p.first ] = tmp[ p.second ];
279 rangeFunction2.setLocalDofs( rangeEntity, values );
280 }
281 rangeFunction2.communicate();
282
283 rangeFunction1.dofVector() -= rangeFunction2.dofVector();
284
285 double diff = rangeFunction1.scalarProductDofs( rangeFunction1 );
286 if( std::abs( diff ) > 1e-8 )
287 DUNE_THROW( Dune::NotImplemented, "Id Operator not assembled correctly" );
288 }
289 }
290
291 } // namespace Fem
292
293} // namespace Dune
294
295#endif // #ifndef DUNE_FEM_OPERATOR_LINEAR_TEST_CHECKLINEAROPERATOR_HH
default implementation for a general operator stencil
Definition: stencil.hh:35
void fill(const DomainEntityType &dEntity, const RangeEntityType &rEntity, bool fillGhost=true) const
Create stencil entries for (dEntity,rEntity) pair.
Definition: stencil.hh:93
A local matrix with a small array as storage.
Definition: temporarylocalmatrix.hh:100
Default exception for dummy implementations.
Definition: exceptions.hh:263
A free function to provide the demangled class name of a given object or type as a string.
This file implements a dense vector with a dynamic size.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:256
EnableIfInterOperable< T1, T2, bool >::type operator==(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for equality.
Definition: iteratorfacades.hh:238
EnableIfInterOperable< T1, T2, bool >::type operator!=(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for inequality.
Definition: iteratorfacades.hh:260
Dune namespace.
Definition: alignedallocator.hh:13
std::string className()
Provide the demangled class name of a type T as a string.
Definition: classname.hh:47
DomainFunction DomainFunctionType
type of discrete function in the operator's domain
Definition: operator.hh:36
DomainFunction RangeFunctionType
type of discrete function in the operator's range
Definition: operator.hh:38
Traits for type conversions and type information.
Utilities for type computations, constraining overloads, ...
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 21, 23:30, 2024)