DUNE-FEM (unstable)

petscdofblock.hh
1#ifndef DUNE_FEM_PETSCDOFBLOCK_HH
2#define DUNE_FEM_PETSCDOFBLOCK_HH
3
4#include <algorithm>
5#include <memory>
6
7#include <dune/fem/storage/envelope.hh>
8
9#if HAVE_PETSC
10
11#include <dune/fem/misc/petsc/petsccommon.hh>
12#include <dune/fem/misc/petsc/petscvector.hh>
13
14#include <dune/fem/io/streams/streams.hh>
15
16namespace Dune
17{
18
19 namespace Fem
20 {
21 template < class PVector >
22 class PetscDofBlock;
23
24 /* ========================================
25 * class PetscDofBlock::DofProxy
26 * =======================================
27 */
28 template< class PVector >
29 class PetscDofProxy
30 {
31 public:
32 typedef PVector PetscVectorType;
33 typedef typename PetscDofBlock< PetscVectorType >::DofProxy ThisType;
34 typedef typename PetscDofBlock< PetscVectorType >::IndexType IndexType;
35
36 static const unsigned int blockSize = PetscVectorType::blockSize;
37
38 // This is needed to put DofProxies in STL (or STL-like) containers...
39 PetscDofProxy () = default;
40
41 // ???
42 PetscDofProxy ( PetscScalar s ) {}
43
44 // this is called by a friend
45 PetscDofProxy ( PetscVectorType &petscVector, IndexType blockIndex, PetscInt indexInBlock )
46 : petscVector_( &petscVector ),
47 blockIndex_( blockIndex ),
48 indexInBlock_( indexInBlock )
49 {}
50
51 // Does not change the value of the DoF which this proxy, but it assigns this proxy instance...
52 void assign ( const ThisType &other )
53 {
54 petscVector_ = other.petscVector_;
55 blockIndex_ = other.blockIndex_;
56 indexInBlock_ = other.indexInBlock_;
57 }
58
59 const ThisType& operator= ( ThisType &other )
60 {
61 setValue( other.getValue() );
62 return *this;
63 }
64
65 const ThisType& operator= ( PetscScalar val )
66 {
67 setValue( val );
68 return *this;
69 }
70
71 const ThisType& operator*= ( const ThisType& other )
72 {
73 PetscScalar value = getValue() * other.getValue();
74 setValue( value );
75 return *this;
76 }
77
78 const ThisType& operator*= ( const PetscScalar scalar )
79 {
80 PetscScalar value = getValue() * scalar ;
81 setValue( value );
82 return *this;
83 }
84
85 const ThisType& operator+= ( const ThisType &other )
86 {
87 setValue( other.getValue(), ADD_VALUES );
88 return *this;
89 }
90
91 const ThisType& operator+= ( const PetscScalar scalar )
92 {
93 setValue( scalar, ADD_VALUES );
94 return *this;
95 }
96
97 const ThisType& operator-= ( const ThisType &other )
98 {
99 setValue( -other.getValue(), ADD_VALUES );
100 return *this;
101 }
102
103 const ThisType& operator-= ( const PetscScalar scalar )
104 {
105 setValue( -scalar, ADD_VALUES );
106 return *this;
107 }
108
109 // conversion operators
110 operator PetscScalar () const
111 {
112 return valid() ? getValue() : PetscScalar( 0 );
113 }
114
115 bool valid() const { return bool( petscVector_ ); }
116
117 protected:
118 PetscScalar getValue () const
119 {
120 assert( valid() );
121 PetscInt index = blockSize * petscVector().mappers().ghostIndex( blockIndex_ ) + indexInBlock_;
122 PetscScalar ret;
123 ::Dune::Petsc::VecGetValues( *petscVector().getGhostedVector(), 1, &index, &ret );
124 return ret;
125 }
126
127 void setValue ( const PetscScalar &val, InsertMode mode = INSERT_VALUES )
128 {
129 PetscInt index = blockSize * petscVector().mappers().ghostIndex( blockIndex_ ) + indexInBlock_;
130 ::Dune::Petsc::VecSetValue( *( petscVector().getGhostedVector() ), index, val, mode );
131 petscVector().hasBeenModified();
132 }
133
134 PetscVectorType& petscVector ()
135 {
136 assert( petscVector_ );
137 return *petscVector_;
138 }
139
140 const PetscVectorType& petscVector () const
141 {
142 assert( petscVector_ );
143 return *petscVector_;
144 }
145
146 // data fields
147 PetscVectorType *petscVector_ = nullptr;
148 IndexType blockIndex_ = 0;
149 PetscInt indexInBlock_ = 0;
150 };
151
152 template< class Scalar, class PVector >
153 void axpy ( const Scalar &a, const Scalar &x, PetscDofProxy< PVector > proxy )
154 {
155 proxy += a*x;
156 }
157
158
159
160
161 /* ========================================
162 * class PetscDofBlock
163 * =======================================
164 */
165 template< class PVector >
166 class PetscDofBlock
167 {
168 typedef PetscDofBlock< PVector > ThisType;
169
170 public:
171 typedef PVector PetscVectorType;
172 typedef PetscInt IndexType;
173
174 static const unsigned int blockSize = PetscVectorType::blockSize;
175
176 typedef PetscDofProxy< PVector > DofProxy;
177 class DofIterator;
178
179 // Needed so that we can put this class in a Dune::Envelope
180 typedef std::pair< PetscVectorType&, IndexType > UnaryConstructorParamType;
181
182 // this is the ctor to be used
183 PetscDofBlock ( PetscVectorType &petscVector, IndexType blockIndex )
184 : petscVector_( petscVector ),
185 blockIndex_( blockIndex )
186 {}
187
188 // this is the ctor to be used
189 PetscDofBlock ( const PetscDofBlock& other )
190 : petscVector_( other.petscVector_ ),
191 blockIndex_( other.blockIndex_ )
192 {}
193
194 // ..or this one, which is semantically equivalent to the above ctor
195 explicit PetscDofBlock ( UnaryConstructorParamType arg )
196 : petscVector_( arg.first ),
197 blockIndex_( arg.second )
198 {}
199
200 const PetscDofBlock& operator*= ( const PetscScalar value )
201 {
202 for( unsigned int i=0; i<blockSize; ++i )
203 (*this)[ i ] *= value ;
204 return *this;
205 }
206
207 PetscDofBlock () = delete;
208
209 IndexType size() const { return blockSize; }
210
211 DofProxy operator [] ( unsigned int index )
212 {
213 assert( index < blockSize );
214 return DofProxy( petscVector_, blockIndex_, index );
215 }
216
217 const DofProxy operator [] ( unsigned int index ) const
218 {
219 assert( index < blockSize );
220 return DofProxy( petscVector_, blockIndex_, index );
221 }
222
223 private:
224 PetscVectorType &petscVector_;
225 IndexType blockIndex_;
226 };
227
229 //template< class Traits, class PVector >
230 template< class Traits, class PVector >
231 inline OutStreamInterface< Traits >&
232 operator<< ( OutStreamInterface< Traits > &out,
233 const PetscDofProxy< PVector >& value )
234 {
235 // write to stream
236 out << PetscScalar( value );
237 return out;
238 }
239
241 //template< class Traits, class PVector >
242 template< class Traits, class PVector >
243 inline InStreamInterface< Traits >&
244 operator>> ( InStreamInterface< Traits > &in,
245 PetscDofProxy< PVector > value )
246 {
247 PetscScalar val;
248 // get value from stream
249 in >> val;
250 // write value to discrete function
251 value = val;
252 return in;
253 }
254
255
256 /*
257 * This is almost a bidirectional iterator but does not completely satisfy the required
258 * interface (see the C++2003 standard, 24.1.4) [no default ctor, no operator->].
259 */
260
261 /* ========================================
262 * class PetscDofBlock::DofIterator
263 * =======================================
264 */
265 template< class PVector >
266 class PetscDofBlock< PVector >::DofIterator
267 {
268 typedef typename PetscDofBlock< PVector >::DofIterator ThisType;
269 typedef PetscDofBlock< PVector > DofBlockType;
270
271 // TODO: get rid of this! we don't like shared pointers. Own a real instance instead!
272 typedef std::shared_ptr< DofBlockType > DofBlockSharedPointer;
273
274 public:
275 typedef std::input_iterator_tag iterator_category;
276 typedef typename DofBlockType::DofProxy value_type;
277 typedef std::ptrdiff_t difference_type;
278 typedef PetscScalar* pointer;
279 typedef PetscScalar& reference;
280
281 typedef PVector PetscVectorType;
282
283 // standard ctor
284 DofIterator ( PetscVectorType &petscVector, unsigned int blockIndex, PetscInt indexInBlock = 0 )
285 : petscVector_( petscVector ),
286 blockIndex_( blockIndex ),
287 indexInBlock_( indexInBlock )
288 {
289 // blockIndex == size denotes the end iterator
290 assert( static_cast< std::size_t >( blockIndex ) <= petscVector_.mappers().size() );
291
292 // Is this not the end iterator?
293 if( static_cast< std::size_t >( blockIndex ) < petscVector_.mappers().size() )
294 {
295 resetBlockPtr();
296 }
297 }
298
299 bool operator== ( const ThisType &other ) const
300 {
301 return (blockIndex_ == other.blockIndex_) && (indexInBlock_ == other.indexInBlock_);
302 }
303
304 bool operator!= ( const ThisType &other ) const { return !this->operator==( other ); };
305
306 value_type operator* () { return block()[ indexInBlock_]; }
307 const value_type operator* () const { return block()[ indexInBlock_ ]; }
308
309 // prefix increment
310 ThisType& operator++ () { increment(); return *this; }
311
312 // prefix decrement
313 ThisType& operator-- () { decrement(); return *this; }
314
315 DofIterator () = delete;
316
317 private:
318 PetscVectorType& petscVector () { return petscVector_; }
319
320 void increment ()
321 {
322 ++indexInBlock_;
323 if( static_cast< std::size_t >( indexInBlock_ ) >= DofBlockType::blockSize )
324 {
325 ++blockIndex_;
326 indexInBlock_ = 0;
327 if( static_cast< std::size_t >( blockIndex_ ) < petscVector().mappers().size() )
328 resetBlockPtr();
329 }
330 }
331
332 void decrement ()
333 {
334 assert( blockIndex_ > 0 );
335 if( indexInBlock_ == 0 )
336 {
337 indexInBlock_ = DofBlockType::blockSize - 1;
338 --blockIndex_;
339 resetBlockPtr();
340 }
341 else
342 {
343 --blockIndex_;
344 }
345 }
346
347 // TODO: iterator should own the block - _no_ new...
348 void resetBlockPtr () { blockPtr_.reset( new DofBlockType( *petscVector().block( blockIndex_ ) ) ); }
349
350 DofBlockType& block () const { return *blockPtr_.get(); }
351
352 PetscVectorType &petscVector_;
353 unsigned int blockIndex_;
354 PetscInt indexInBlock_;
355 DofBlockSharedPointer blockPtr_;
356 };
357
358 } // namespace Fem
359
360} // namespace Dune
361
362#endif // #if HAVE_PETSC
363
364#endif // DUNE_FEM_PETSCDOFBLOCK_HH
Stream & operator>>(Stream &stream, std::tuple< Ts... > &t)
Read a std::tuple.
Definition: streamoperators.hh:43
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
typename Overloads::ScalarType< std::decay_t< V > >::type Scalar
Element type of some SIMD type.
Definition: interface.hh:235
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
void assign(T &dst, const T &src, bool mask)
masked Simd assignment (scalar version)
Definition: simd.hh:447
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 21, 23:30, 2024)