1 #ifndef PARALLEL_H_INCLUDED
2 #define PARALLEL_H_INCLUDED
3 
4 #include <map>
5 #include <vector>
6 
7 #include "myalloc.h"
8 #include "serialize.h"
9 #include "key.h"
10 
11 namespace ALUGrid
12 {
13 
14   struct GatherScatter;
15   typedef GatherScatter GatherScatterType;
16 
17   // ParallelException
18   // -----------------
19 
20   struct ParallelException
21   {
22     class AccessPllException : public ALUGridException
23     {
24     public:
whatParallelException25       virtual std::string what () const { return "AccessPllException"; }
26     };
27   };
28 
29 
30   //////////////////////////////////////////////////////////////////////////////
31   //
32   //
33   //  Interfaces for elements, faces, edges, and vertices for parallel computations
34   //
35   //
36   //////////////////////////////////////////////////////////////////////////////
37 
38     // Das 'MacroGridMoverIF' mu"s von den Parallelerweiterungen der
39     // Knoten, Kanten, Fl"achen und Elemente des Grobgitters implementiert
40     // werden, damit der Lastverteiler diese Objekte zuweisen, einpacken
41     // und rekonstruieren kann.
42 
43   class MacroGridMoverIF
44   {
45     protected :
MacroGridMoverIF()46       MacroGridMoverIF () {}
~MacroGridMoverIF()47       virtual ~MacroGridMoverIF () {}
48 
49     private:
50       // type of move to map, derive from MyAlloc
51       class MoveTo
52       : public MyAlloc,
53         public std::map< int, int >
54       {};
55 
56     public :
57       typedef MoveTo moveto_t ;
58 
59       enum { VERTEX = 1, EDGE1, FACE3, FACE4,
60              HEXA, TETRA, PERIODIC3, PERIODIC4=-65,
61              HBND3EXT, HBND4EXT, HBND3INT, HBND4INT = -22 ,
62              ENDMARKER , ENDSTREAM } ;
63 
64       static constexpr signed char NO_POINT=-111;
65       static constexpr signed char POINTTRANSMITTED=-112;
66 
67       virtual void attach2   (int) = 0 ;
68       virtual void unattach2 (int) = 0 ;
69 
70       virtual bool packAll  ( std::vector< ObjectStream > & ) = 0;
71       virtual moveto_t* moveToMap () = 0 ;
72       virtual bool dunePackAll ( std::vector< ObjectStream > &, GatherScatterType & ) = 0;
73       virtual void unpackSelf ( ObjectStream &, bool ) = 0;
74       virtual void duneUnpackSelf ( ObjectStream &, bool, GatherScatterType * ) = 0;
75       virtual void computeBaryCenter( double (&center)[3] ) const = 0;
76   };
77 
78   class MacroGridMoverDefault : public MacroGridMoverIF {
79     protected :
MacroGridMoverDefault()80       MacroGridMoverDefault () {}
~MacroGridMoverDefault()81       virtual ~MacroGridMoverDefault () {}
82     public :
83       typedef MacroGridMoverIF :: moveto_t moveto_t ;
84 
attach2(int)85       virtual void attach2   (int) { alugrid_assert (false);abort(); }
unattach2(int)86       virtual void unattach2 (int) { alugrid_assert (false);abort(); }
87 
packAll(std::vector<ObjectStream> &)88       virtual bool packAll ( std::vector< ObjectStream > &) { alugrid_assert (false); abort(); }
moveToMap()89       virtual moveto_t* moveToMap () { alugrid_assert (false); abort(); return ((moveto_t *) 0); }
dunePackAll(std::vector<ObjectStream> &,GatherScatterType &)90       virtual bool dunePackAll ( std::vector< ObjectStream > &, GatherScatterType & ) { alugrid_assert (false); return false; }
unpackSelf(ObjectStream &,bool)91       virtual void unpackSelf ( ObjectStream &, bool ) { alugrid_assert (false); abort(); }
duneUnpackSelf(ObjectStream &,const bool,GatherScatterType *)92       virtual void duneUnpackSelf (ObjectStream &, const bool, GatherScatterType *) {alugrid_assert (false);}
computeBaryCenter(double (& center)[3])93       virtual void computeBaryCenter( double (&center)[3] ) const { center[ 0 ] = center[ 1 ] = center[ 2 ] = 0; }
94   } ;
95 
96     // LinkedObjekt ist die Schnittstelle, die im parallelen Gitter zur
97     // Identifikation ben"otigt wird. Das Identifikationsmodul wendet
98     // sich an diese Schnittstelle, um die Schl"ussel f"ur die Objekte
99     // des Gitters und eine obere Absch"atzung f"ur deren Verbindungsstern
100     // zu erhalten. Diese Abschh"atzung kann auch die globale Verbindung
101     // sein, d.h. der Vektor enth"alt alle Gebietsnummern, dann wird aber
102     // die Effizienz des Identifikationsmoduls schlecht.
103 
104     // Note: The derivation from MacroGridMoverIF is artificial. Since all
105     //       implementations of LinkedObject also derive from MacroGridMoverIf,
106     //       this saves the additional pointer to the vtbl of MacroGridMoverIf.
107 
108   class LinkedObject
109   : public MacroGridMoverDefault
110   {
111   public:
112     // Der Identifier wird f"ur alle Gitterobjekte einheitlich verwendet.
113     // Er ist der Schl"ussel f"ur die Identifikation der mehrdeutigen
114     // Gitterobjekte. Kanten benutzen eine Schl"ussell"ange von zwei,
115     // Fl"achen eine von drei und Elemente eine von vier. Wird nicht der
116     // gesamte Schl"ussel benutzt, werden die "ubrigen Eintr"age mit
117     // -1 gepaddet.
118     // Die Schnittstelle wird von den Parallelerweiterungen der Knoten
119     // Kanten, Fl"achen und (sp"ater auch) Elemente implementiert.
120 
121     template <int size>
122     class IdentifierImpl
123     {
124       typedef IdentifierImpl< size > This;
125       template <int xsize>
126       void assign( const IdentifierImpl< xsize >& );
127 
128       template <int k, int s>
129       struct Spec
130       {
lessSpec131         static bool less( const int (&a)[ size ], const int (&b)[ size ] )
132         {
133           if( a[ k ]  < b[ k ] ) return true;
134           else if( a[ k ] > b[ k ] ) return false ;
135           else return Spec<k+1,s>::less( a, b );
136         }
137       };
138 
139       template <int k>
140       struct Spec< k, k >
141       {
142         static bool less( const int (&a)[ size ], const int (&b)[ size ] )
143         {
144           return  a[ k ]  < b[ k ];
145         }
146       };
147 
148     public:
149       int _i[ size ];
150       static const int _endOfStream = -128 ; // must be a negative value
151     public :
152       inline IdentifierImpl (int = -1, int = -1, int = -1, int = -1) ;
153       template <int xsize>
154       inline IdentifierImpl (const IdentifierImpl< xsize > &) ;
155       template <int xsize>
156       inline const IdentifierImpl & operator = (const IdentifierImpl< xsize >&) ;
157       inline bool operator < (const This &) const ;
158       inline bool operator == (const This &) const ;
159       // read identifier from stream and return true if successful
160       bool read ( ObjectStream& );
161       void write ( ObjectStream& ) const ;
162       inline bool isValid () const ;
163       // read stream termination marker
164       static void endOfStream( ObjectStream& os )
165       {
166         os.writeObject( _endOfStream );
167       }
168 
169     } ;
170 
171     // the identifier need at most 4 entries
172     typedef IdentifierImpl< 4 > Identifier ;
173 
174   public :
175     virtual ~LinkedObject () {}
176 
177     virtual Identifier getIdentifier () const = 0 ;
178     virtual std::vector< int > estimateLinkage () const = 0;
179     virtual void checkAndAddLinkage ( const int ) = 0;
180   };
181 
182   class LinkedObjectDefault
183   : public LinkedObject
184   {
185     public :
186       virtual ~LinkedObjectDefault () {}
187       virtual Identifier getIdentifier () const { alugrid_assert (false);abort(); return Identifier(); }
188       virtual std::vector< int > estimateLinkage () const { alugrid_assert (false); abort(); return std::vector< int >(); }
189       virtual void checkAndAddLinkage ( const int ) { alugrid_assert (false); abort(); }
190   } ;
191 
192   // Die Schnittstelle 'RefineableObject' ist diejenige, an die sich
193   // der parallele Verfeinerer wendet, um z.B. die Requests heraus-
194   // zufinden und zu setzen. Die Requests werden einfach auf den Strom
195   // geschrieben, und sollten beim einlesen auf ihre G"ultigkeit
196   // getestet werden. Die Schnittstelle wird von den Parallelerweiterungen
197   // der Kanten und der Fl"achen implementiert.
198 
199   // Note: The derivation from LinkedObject is artificial. Since all
200   //       implementations of RefineableObject also derive from LinkedObject,
201   //       this saves the additional pointer to the vtbl of LinkedObject.
202 
203   class RefineableObject : public LinkedObjectDefault
204   {
205     protected :
206       RefineableObject () {}
207       virtual ~RefineableObject () {}
208     public :
209       virtual void getRefinementRequest (ObjectStream &) const = 0 ;
210       virtual bool setRefinementRequest (ObjectStream &) = 0 ;
211   } ;
212 
213 
214   class RefineableObjectDefault : public RefineableObject
215   {
216     protected :
217       RefineableObjectDefault () {}
218       virtual ~RefineableObjectDefault () {}
219     public :
220       virtual void getRefinementRequest (ObjectStream &) const { alugrid_assert (false);abort(); }
221       virtual bool setRefinementRequest (ObjectStream &) { alugrid_assert (false);abort(); return false ;}
222   } ;
223 
224     //
225     //    #    #    #  #          #    #    #  ######
226     //    #    ##   #  #          #    ##   #  #
227     //    #    # #  #  #          #    # #  #  #####
228     //    #    #  # #  #          #    #  # #  #
229     //    #    #   ##  #          #    #   ##  #
230     //    #    #    #  ######     #    #    #  ######
231     //
232   ///////////////////////////////////////////////////////////////////
233   //
234   //  --LinkedObject
235   //
236   ///////////////////////////////////////////////////////////////////
237 
238   template <int size>
239   inline bool LinkedObject :: IdentifierImpl< size > :: isValid () const
240   {
241     return _i[ 0 ] == -1 ? false : true ;
242   }
243 
244   template <int size>
245   inline LinkedObject :: IdentifierImpl< size > :: IdentifierImpl (int a, int b, int c, int d)
246   {
247     _i[ 0 ] = a;
248     if( size > 1 )
249       _i[ 1 ] = b;
250     if( size > 2 )
251       _i[ 2 ] = c;
252     if( size > 3 )
253       _i[ 3 ] = d;
254   }
255 
256   template <int size>
257   template <int xsize>
258   inline void LinkedObject :: IdentifierImpl< size > ::
259   assign (const IdentifierImpl< xsize >& x)
260   {
261     alugrid_assert( size <= xsize );
262     alugrid_assert (x.isValid ()) ;
263     for( int i=0; i<size; ++i ) _i[ i ] = x._i[ i ];
264   }
265 
266   template <int size>
267   template <int xsize>
268   inline LinkedObject :: IdentifierImpl< size > ::
269   IdentifierImpl (const IdentifierImpl< xsize > & x)
270   {
271     assign( x );
272   }
273 
274   template <int size>
275   template <int xsize>
276   inline const LinkedObject :: IdentifierImpl< size > &
277   LinkedObject :: IdentifierImpl< size > :: operator = (const IdentifierImpl< xsize >& x)
278   {
279     assign( x );
280     return * this ;
281   }
282 
283   template <int size>
284   inline bool LinkedObject :: IdentifierImpl< size > :: operator < (const This & x) const
285   {
286     return Spec< 0, size-1 > :: less( _i, x._i );
287   }
288 
289   template <int size>
290   inline bool LinkedObject :: IdentifierImpl< size > :: operator == (const This & x) const
291   {
292     bool equal = _i[ 0 ] == x._i[ 0 ];
293     for( int k=1; k<size; ++k )
294       equal &= (_i[ k ] == x._i[ k ]);
295     return equal ;
296   }
297 
298   // read identifier and return true if successful
299   template <int size>
300   inline bool LinkedObject::IdentifierImpl< size >::read ( ObjectStream& os )
301   {
302     // if the next entry is end of stream do nothing more
303     os.readObject( _i[ 0 ] );
304     if( _i[ 0 ] == _endOfStream )
305       return false ;
306 
307     for( int k=1; k<size; ++k )
308       os.readObject( _i[ k ] );
309 
310     return true ;
311   }
312 
313   template <int size>
314   inline void LinkedObject::IdentifierImpl< size >::write ( ObjectStream& os ) const
315   {
316     // write object to stream
317     for( int k=0; k<size; ++k )
318       os.writeObject( _i[ k ] );
319   }
320 
321 } // namespace ALUGrid
322 
323 #endif // #ifndef PARALLEL_H_INCLUDED
324