FaceDoFPackInfo.hpp 14.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * Copyright (c) 2017-2019 Daniel Drzisga, Dominik Thoennes, Marcus Mohr, Nils Kohl.
 *
 * This file is part of HyTeG
 * (see https://i10git.cs.fau.de/hyteg/hyteg).
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
Dominik Test2's avatar
Dominik Test2 committed
20
21
#pragma once

Dominik Thoennes's avatar
Dominik Thoennes committed
22
23
#include "hyteg/communication/DoFSpacePackInfo.hpp"
#include "hyteg/facedofspace/FaceDoFIndexing.hpp"
24
#include "hyteg/memory/FunctionMemory.hpp"
Dominik Test2's avatar
Dominik Test2 committed
25

26
namespace hyteg {
Dominik Test2's avatar
Dominik Test2 committed
27

28
29
using facedof::macroface::CELL_BLUE;
using facedof::macroface::CELL_GRAY;
30
using walberla::uint_t;
Dominik Test2's avatar
Dominik Test2 committed
31

32
33
34
35
template < typename ValueType >
class FaceDoFPackInfo : public communication::DoFSpacePackInfo< ValueType >
{
 public:
36
37
38
39
40
41
42
   FaceDoFPackInfo( uint_t                                                 level,
                    PrimitiveDataID< FunctionMemory< ValueType >, Vertex > dataIDVertex,
                    PrimitiveDataID< FunctionMemory< ValueType >, Edge >   dataIDEdge,
                    PrimitiveDataID< FunctionMemory< ValueType >, Face >   dataIDFace,
                    std::weak_ptr< PrimitiveStorage >                      storage )
   : communication::DoFSpacePackInfo< ValueType >( level, dataIDVertex, dataIDEdge, dataIDFace, storage )
   {}
Dominik Test2's avatar
Dominik Test2 committed
43

44
   void packVertexForEdge( const Vertex* sender, const PrimitiveID& receiver, walberla::mpi::SendBuffer& buffer ) const override;
Dominik Test2's avatar
Dominik Test2 committed
45

46
   void unpackEdgeFromVertex( Edge* receiver, const PrimitiveID& sender, walberla::mpi::RecvBuffer& buffer ) const override;
Dominik Test2's avatar
Dominik Test2 committed
47

48
   void communicateLocalVertexToEdge( const Vertex* sender, Edge* receiver ) const override;
Dominik Test2's avatar
Dominik Test2 committed
49

50
   void packEdgeForVertex( const Edge* sender, const PrimitiveID& receiver, walberla::mpi::SendBuffer& buffer ) const override;
Dominik Test2's avatar
Dominik Test2 committed
51

52
   void unpackVertexFromEdge( Vertex* receiver, const PrimitiveID& sender, walberla::mpi::RecvBuffer& buffer ) const override;
Dominik Test2's avatar
Dominik Test2 committed
53

54
   void communicateLocalEdgeToVertex( const Edge* sender, Vertex* receiver ) const override;
Dominik Test2's avatar
Dominik Test2 committed
55

56
   void packEdgeForFace( const Edge* sender, const PrimitiveID& receiver, walberla::mpi::SendBuffer& buffer ) const override;
Dominik Test2's avatar
Dominik Test2 committed
57

58
   void unpackFaceFromEdge( Face* receiver, const PrimitiveID& sender, walberla::mpi::RecvBuffer& buffer ) const override;
Dominik Test2's avatar
Dominik Test2 committed
59

60
   void communicateLocalEdgeToFace( const Edge* sender, Face* receiver ) const override;
Dominik Test2's avatar
Dominik Test2 committed
61

62
   void packFaceForEdge( const Face* sender, const PrimitiveID& receiver, walberla::mpi::SendBuffer& buffer ) const override;
Dominik Test2's avatar
Dominik Test2 committed
63

64
   void unpackEdgeFromFace( Edge* receiver, const PrimitiveID& sender, walberla::mpi::RecvBuffer& buffer ) const override;
Dominik Test2's avatar
Dominik Test2 committed
65

66
   void communicateLocalFaceToEdge( const Face* sender, Edge* receiver ) const override;
67

68
69
70
71
72
73
 private:
   using communication::DoFSpacePackInfo< ValueType >::level_;
   using communication::DoFSpacePackInfo< ValueType >::dataIDVertex_;
   using communication::DoFSpacePackInfo< ValueType >::dataIDEdge_;
   using communication::DoFSpacePackInfo< ValueType >::dataIDFace_;
   using communication::DoFSpacePackInfo< ValueType >::storage_;
Dominik Test2's avatar
Dominik Test2 committed
74
75
};

76
77
78
79
80
81
82
83
84
85
86
template < typename ValueType >
void FaceDoFPackInfo< ValueType >::packVertexForEdge( const Vertex*              sender,
                                                      const PrimitiveID&         receiver,
                                                      walberla::mpi::SendBuffer& buffer ) const
{
   /// see DGMemory.hpp for a description of the Vertex Memory
   ValueType* vertexData = sender->getData( dataIDVertex_ )->getPointer( level_ );
   for ( const PrimitiveID& faceID : storage_.lock()->getEdge( receiver )->neighborFaces() )
   {
      buffer << vertexData[sender->face_index( faceID ) * 2];
   }
Dominik Thoennes's avatar
Dominik Thoennes committed
87
88
}

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
template < typename ValueType >
void FaceDoFPackInfo< ValueType >::unpackEdgeFromVertex( Edge*                      receiver,
                                                         const PrimitiveID&         sender,
                                                         walberla::mpi::RecvBuffer& buffer ) const
{
   typedef stencilDirection sD;
   ValueType*               edgeData = receiver->getData( dataIDEdge_ )->getPointer( level_ );
   uint_t                   pos      = std::numeric_limits< uint_t >::max();
   if ( receiver->vertex_index( sender ) == 0 )
   {
      pos = 0;
   }
   else if ( receiver->vertex_index( sender ) == 1 )
   {
      pos = levelinfo::num_microvertices_per_edge( level_ ) - 2;
   }
   else
   {
      WALBERLA_LOG_WARNING( "Vertex with ID: " << sender.getID() << " is not in Edge: " << receiver )
   }
   buffer >> edgeData[facedof::macroedge::indexFaceFromVertex( level_, pos, sD::CELL_GRAY_SE )];
   if ( receiver->getNumNeighborFaces() == 2 )
   {
      buffer >> edgeData[facedof::macroedge::indexFaceFromVertex( level_, pos, sD::CELL_GRAY_NE )];
   }
Dominik Thoennes's avatar
Dominik Thoennes committed
114
115
}

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
template < typename ValueType >
void FaceDoFPackInfo< ValueType >::communicateLocalVertexToEdge( const Vertex* sender, Edge* receiver ) const
{
   typedef stencilDirection sD;
   ValueType*               vertexData = sender->getData( dataIDVertex_ )->getPointer( level_ );
   ValueType*               edgeData   = receiver->getData( dataIDEdge_ )->getPointer( level_ );
   uint_t                   pos        = std::numeric_limits< uint_t >::max();
   if ( receiver->vertex_index( sender->getID() ) == 0 )
   {
      pos = 0;
   }
   else if ( receiver->vertex_index( sender->getID() ) == 1 )
   {
      pos = levelinfo::num_microvertices_per_edge( level_ ) - 2;
   }
   else
   {
      WALBERLA_LOG_WARNING( "Vertex with ID: " << sender << " is not in Edge: " << receiver )
   }
   edgeData[facedof::macroedge::indexFaceFromVertex( level_, pos, sD::CELL_GRAY_SE )] =
       vertexData[sender->face_index( receiver->neighborFaces()[0] ) * 2];
   if ( receiver->getNumNeighborFaces() == 2 )
   {
      edgeData[facedof::macroedge::indexFaceFromVertex( level_, pos, sD::CELL_GRAY_NE )] =
          vertexData[sender->face_index( receiver->neighborFaces()[1] ) * 2];
   }
Dominik Thoennes's avatar
Dominik Thoennes committed
142
143
}

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
template < typename ValueType >
void FaceDoFPackInfo< ValueType >::packEdgeForVertex( const Edge*                sender,
                                                      const PrimitiveID&         receiver,
                                                      walberla::mpi::SendBuffer& buffer ) const
{
   ///the blue face DoF which are owned by the face need to communicated to the vertex
   typedef stencilDirection sD;
   ValueType*               edgeData = sender->getData( dataIDEdge_ )->getPointer( level_ );
   uint_t                   pos      = std::numeric_limits< uint_t >::max();
   if ( sender->vertex_index( receiver ) == 0 )
   {
      pos = 1;
   }
   else if ( sender->vertex_index( receiver ) == 1 )
   {
      pos = levelinfo::num_microvertices_per_edge( level_ ) - 2;
   }
   else
   {
      WALBERLA_LOG_WARNING( "Vertex with ID: " << receiver.getID() << " is not in Edge: " << sender )
   }
   buffer << edgeData[facedof::macroedge::indexFaceFromVertex( level_, pos, sD::CELL_BLUE_SE )];
   if ( sender->getNumNeighborFaces() == 2 )
   {
      buffer << edgeData[facedof::macroedge::indexFaceFromVertex( level_, pos, sD::CELL_BLUE_NW )];
   }
Dominik Thoennes's avatar
Dominik Thoennes committed
170
171
}

172
173
174
175
176
177
178
179
180
181
template < typename ValueType >
void FaceDoFPackInfo< ValueType >::unpackVertexFromEdge( Vertex*                    receiver,
                                                         const PrimitiveID&         sender,
                                                         walberla::mpi::RecvBuffer& buffer ) const
{
   ValueType* vertexData = receiver->getData( dataIDVertex_ )->getPointer( level_ );
   for ( const PrimitiveID& faceID : storage_.lock()->getEdge( sender )->neighborFaces() )
   {
      buffer >> vertexData[receiver->face_index( faceID ) * 2 + 1];
   }
Dominik Thoennes's avatar
Dominik Thoennes committed
182
183
}

184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
template < typename ValueType >
void FaceDoFPackInfo< ValueType >::communicateLocalEdgeToVertex( const Edge* sender, Vertex* receiver ) const
{
   ValueType* edgeData = sender->getData( dataIDEdge_ )->getPointer( level_ );
   uint_t     pos      = std::numeric_limits< uint_t >::max();
   if ( sender->vertex_index( receiver->getID() ) == 0 )
   {
      pos = 1;
   }
   else if ( sender->vertex_index( receiver->getID() ) == 1 )
   {
      pos = levelinfo::num_microvertices_per_edge( level_ ) - 2;
   }
   else
   {
      WALBERLA_LOG_WARNING( "Vertex with ID: " << receiver << " is not in Edge: " << sender )
   }
   ValueType* vertexData = receiver->getData( dataIDVertex_ )->getPointer( level_ );
   vertexData[receiver->face_index( sender->neighborFaces()[0] ) * 2 + 1] =
       edgeData[facedof::macroedge::indexFaceFromVertex( level_, pos, stencilDirection::CELL_BLUE_SE )];
   ;
   if ( sender->getNumNeighborFaces() == 2 )
   {
      vertexData[receiver->face_index( sender->neighborFaces()[1] ) * 2 + 1] =
          edgeData[facedof::macroedge::indexFaceFromVertex( level_, pos, stencilDirection::CELL_BLUE_NW )];
   }
Dominik Thoennes's avatar
Dominik Thoennes committed
210
211
}

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
template < typename ValueType >
void FaceDoFPackInfo< ValueType >::packEdgeForFace( const Edge*                sender,
                                                    const PrimitiveID&         receiver,
                                                    walberla::mpi::SendBuffer& buffer ) const
{
   ValueType*       edgeData     = sender->getData( dataIDEdge_ )->getPointer( level_ );
   uint_t           vPerEdge     = levelinfo::num_microvertices_per_edge( level_ );
   uint_t           faceIdOnEdge = sender->face_index( receiver );
   stencilDirection dirCellGray;
   //the first face is the south face and the second the north face
   if ( faceIdOnEdge == 0 )
   {
      dirCellGray = stencilDirection::CELL_GRAY_SE;
   }
   else
   {
      WALBERLA_ASSERT_EQUAL( faceIdOnEdge, 1 );
      dirCellGray = stencilDirection::CELL_GRAY_NE;
   }
   for ( uint_t i = 0; i < vPerEdge - 1; ++i )
   {
      buffer << edgeData[facedof::macroedge::indexFaceFromVertex( level_, i, dirCellGray )];
   }
Dominik Thoennes's avatar
Dominik Thoennes committed
235
236
}

237
238
239
240
241
242
243
244
245
246
247
248
249
250
template < typename ValueType >
void FaceDoFPackInfo< ValueType >::unpackFaceFromEdge( Face*                      receiver,
                                                       const PrimitiveID&         sender,
                                                       walberla::mpi::RecvBuffer& buffer ) const
{
   ValueType* faceData        = receiver->getData( dataIDFace_ )->getPointer( level_ );
   uint_t     edgeIndexOnFace = receiver->edge_index( sender );
   for ( auto it =
             facedof::macroface::indexIterator( edgeIndexOnFace, receiver->edge_orientation[edgeIndexOnFace], CELL_GRAY, level_ );
         it != facedof::macroface::indexIterator();
         ++it )
   {
      buffer >> faceData[*it];
   }
Dominik Thoennes's avatar
Dominik Thoennes committed
251
252
}

253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
template < typename ValueType >
void FaceDoFPackInfo< ValueType >::communicateLocalEdgeToFace( const Edge* sender, Face* receiver ) const
{
   ValueType*       edgeData        = sender->getData( dataIDEdge_ )->getPointer( level_ );
   ValueType*       faceData        = receiver->getData( dataIDFace_ )->getPointer( level_ );
   uint_t           faceIdOnEdge    = sender->face_index( receiver->getID() );
   uint_t           edgeIndexOnFace = receiver->edge_index( sender->getID() );
   stencilDirection dirCellGray;
   //the first face is the south face and the second the north face
   if ( faceIdOnEdge == 0 )
   {
      dirCellGray = stencilDirection::CELL_GRAY_SE;
   }
   else
   {
      WALBERLA_ASSERT_EQUAL( faceIdOnEdge, 1 );
      dirCellGray = stencilDirection::CELL_GRAY_NE;
   }
   uint_t pos = 0;
   for ( auto it =
             facedof::macroface::indexIterator( edgeIndexOnFace, receiver->edge_orientation[edgeIndexOnFace], CELL_GRAY, level_ );
         it != facedof::macroface::indexIterator();
         ++it )
   {
      faceData[*it] = edgeData[facedof::macroedge::indexFaceFromVertex( level_, pos, dirCellGray )];
      pos++;
   }
Dominik Thoennes's avatar
Dominik Thoennes committed
280
281
}

282
283
284
285
286
287
288
289
290
291
292
293
294
295
template < typename ValueType >
void FaceDoFPackInfo< ValueType >::packFaceForEdge( const Face*                sender,
                                                    const PrimitiveID&         receiver,
                                                    walberla::mpi::SendBuffer& buffer ) const
{
   ValueType* faceData        = sender->getData( dataIDFace_ )->getPointer( level_ );
   uint_t     edgeIndexOnFace = sender->edge_index( receiver );
   for ( auto it =
             facedof::macroface::indexIterator( edgeIndexOnFace, sender->edge_orientation[edgeIndexOnFace], CELL_BLUE, level_ );
         it != facedof::macroface::indexIterator();
         ++it )
   {
      buffer << faceData[*it];
   }
Dominik Thoennes's avatar
Dominik Thoennes committed
296
297
}

298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
template < typename ValueType >
void FaceDoFPackInfo< ValueType >::unpackEdgeFromFace( Edge*                      receiver,
                                                       const PrimitiveID&         sender,
                                                       walberla::mpi::RecvBuffer& buffer ) const
{
   ValueType*       edgeData     = receiver->getData( dataIDEdge_ )->getPointer( level_ );
   uint_t           vPerEdge     = levelinfo::num_microvertices_per_edge( level_ );
   uint_t           faceIdOnEdge = receiver->face_index( sender );
   stencilDirection dirCellBlue;
   //the first face is the south face and the second the north face
   if ( faceIdOnEdge == 0 )
   {
      dirCellBlue = stencilDirection::CELL_BLUE_SE;
   }
   else
   {
      WALBERLA_ASSERT_EQUAL( faceIdOnEdge, 1 );
      dirCellBlue = stencilDirection::CELL_BLUE_NW;
   }
   //unpack Blue Cell
   for ( uint_t i = 1; i < vPerEdge - 1; ++i )
   {
      buffer >> edgeData[facedof::macroedge::indexFaceFromVertex( level_, i, dirCellBlue )];
   }
Dominik Thoennes's avatar
Dominik Thoennes committed
322
323
}

324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
template < typename ValueType >
void FaceDoFPackInfo< ValueType >::communicateLocalFaceToEdge( const Face* sender, Edge* receiver ) const
{
   ValueType*       edgeData        = receiver->getData( dataIDEdge_ )->getPointer( level_ );
   ValueType*       faceData        = sender->getData( dataIDFace_ )->getPointer( level_ );
   const uint_t     faceIdOnEdge    = receiver->face_index( sender->getID() );
   const uint_t     edgeIndexOnFace = sender->edge_index( receiver->getID() );
   uint_t           pos             = 1;
   stencilDirection dirCellBlue;
   //the first face is the south face and the second the north face
   if ( faceIdOnEdge == 0 )
   {
      dirCellBlue = stencilDirection::CELL_BLUE_SE;
   }
   else
   {
      WALBERLA_ASSERT_EQUAL( faceIdOnEdge, 1 );
      dirCellBlue = stencilDirection::CELL_BLUE_NW;
   }
   for ( auto it =
             facedof::macroface::indexIterator( edgeIndexOnFace, sender->edge_orientation[edgeIndexOnFace], CELL_BLUE, level_ );
         it != facedof::macroface::indexIterator();
         ++it )
   {
      edgeData[facedof::macroedge::indexFaceFromVertex( level_, pos, dirCellBlue )] = faceData[*it];
      pos++;
   }
Dominik Thoennes's avatar
Dominik Thoennes committed
351
}
Dominik Test2's avatar
Dominik Test2 committed
352

353
} //namespace hyteg