Salome HOME
merging the main trunk with the BrForComp branch to build a pre V3_0_1
[modules/med.git] / src / MEDMEM / MEDMEM_Connectivity.hxx
1 #ifndef CONNECTIVITY_HXX
2 #define CONNECTIVITY_HXX
3
4 #include <vector>
5
6 #include "utilities.h"
7 #include "MEDMEM_Exception.hxx"
8 #include "MEDMEM_define.hxx"
9 #include "MEDMEM_PolyhedronArray.hxx"
10
11 namespace MEDMEM {
12 class MEDSKYLINEARRAY;
13 class CELLMODEL;
14 class FAMILY;
15 class GROUP;
16
17 /*!
18         This class deals with all type of connectivity .\n
19         it a recursive class. 
20 */
21
22 /* ------------------------------------------- */
23 class CONNECTIVITY
24 /* ------------------------------------------- */
25 {
26   /* ---------------------- */
27   /*    Class Attributs     */
28   /* ---------------------- */
29
30 protected:
31                                          /*! contains MED_CELL MED_FACE or MED_EDGE */
32   MED_EN::medEntityMesh           _entity;      
33                                          /*! contains MED_NODAL or MED_DESCEND */
34   MED_EN::medConnectivity         _typeConnectivity;
35                                          /*! count of differents cells types 
36                                             used by the mesh */  
37   int                 _numberOfTypes; 
38                                         /*! array of all med_geometric_type used by MESH. */
39   MED_EN::medGeometryElement*     _geometricTypes;
40
41                                         /*! map indexed by med_geometric_type 
42                                             which contains the different 
43                                             'CellModel' used by MESH. */
44   CELLMODEL *             _type;       
45                                         /*! contains the dimension of the entity */
46   int                 _entityDimension;
47
48                                         /*! needed by calculateReverseNodalConnectivity */
49   int                 _numberOfNodes;
50
51                                          /*! array of size _numberOfTypes+1 which 
52                                          gives for each cell type the first 
53                                          cell number in _nodal or _descending
54                                          array (depends on _typeConnectivity) 
55                                          To get cells count for one type, we 
56                                          must minus _count[i+1] and _count[i]
57                                          ( 0 <= i < _numberOfTypes ). 
58                                          Note that _count[_numberOfTypes] returns
59                                          total cells count + 1 */
60   int *               _count;
61
62                                         /*! pointer to an array which stores the nodal connectivity */
63   MEDSKYLINEARRAY* _nodal;
64                                         /*! pointer to an array which stores the nodal connectivity only for polygons */
65   MEDSKYLINEARRAY* _polygonsNodal;
66                                         /*! pointer to an array which stores the nodal connectivity only for polyhedron */
67   POLYHEDRONARRAY* _polyhedronNodal;
68                                         /*! pointer to an array which stores 
69                                             the descending connectivity */
70   MEDSKYLINEARRAY* _descending;
71                                         /*!  pointer to an array which stores the descending connectivity only for polygons */
72   MEDSKYLINEARRAY* _polygonsDescending;
73                                         /*!  pointer to an array which stores the descending connectivity only for polyhedron */
74   MEDSKYLINEARRAY* _polyhedronDescending;
75                                         /*! pointer to an array which stores 
76                                             the reverse nodal connectivity */
77   MEDSKYLINEARRAY* _reverseNodalConnectivity;
78                                         /*! pointer to an array which stores 
79                                             the reverse descending connectivity */
80   MEDSKYLINEARRAY* _reverseDescendingConnectivity;
81                                         /*! if face or edge, list of 2 cells or 
82                                             2 faces it belongs to.
83                                             If 2nd number equals 0, we have a 
84                                             boundary entity. We could use 
85                                             MEDSKYLINEARRAY, but we suppose we have
86                                             always only 2 (or 1) entities. */
87   MEDSKYLINEARRAY* _neighbourhood;
88                                         /*! connectivity of sub cell if 
89                                             descendant connectivity is calculated */
90   CONNECTIVITY * _constituent;  
91
92   /* -------------------- */
93   /*    Class Methods     */
94   /* -------------------- */
95
96 private:
97                                         /*! private method :\n
98                                             does nothing if already exists, else 
99                                             evaluates _nodal from _descending */
100   void  calculateNodalConnectivity();   
101                                         /*! private method :\n
102                                             does nothing if already exists, else
103                                             evaluates from _nodal */  
104   void calculateReverseNodalConnectivity(); 
105                                         /*! private method :\n
106                                             does nothing if already exists, else
107                                             evaluates _descending from _nodal */ 
108   void calculateDescendingConnectivity(); 
109                                         /*! private method :\n
110                                             does nothing if already exists, else
111                                             evaluates from _descending */
112   //  void calculateReverseDescendingConnectivity(CONNECTIVITY *myConnectivity);
113
114   const int*      getReverseNodalConnectivity           ();
115   const int*      getReverseNodalConnectivityIndex      ();
116   const int*      getReverseDescendingConnectivity      ();
117   const int*      getReverseDescendingConnectivityIndex ();
118
119                                         /*! private method :\n
120                                             does nothing if already exists, else
121                                             evaluates _neighbourhood from _descending */
122   void calculateNeighbourhood(CONNECTIVITY &myConnectivity);
123
124   int getIndexOfEndClassicElementInReverseNodal(const int *reverseNodalValue, const int *reverseNodalIndex, int rk)  const;
125
126 public:
127
128   friend class IMED_MESH_RDONLY_DRIVER;
129   friend class MED_MESH_RDONLY_DRIVER21;
130   friend class IMED_MESH_WRONLY_DRIVER;
131   friend class MED_MESH_WRONLY_DRIVER21;
132   friend class MED_MESH_RDONLY_DRIVER22;
133   friend class MED_MESH_WRONLY_DRIVER22;
134
135
136   friend ostream & operator<<(ostream &os, CONNECTIVITY &connectivity);
137
138   // in order to fill CONNECTIVITY of MESH
139   friend class GRID;
140
141   CONNECTIVITY  (MED_EN::medEntityMesh Entity=MED_EN::MED_CELL);
142   CONNECTIVITY  (int numberOfTypes, MED_EN::medEntityMesh Entity=MED_EN::MED_CELL);
143   CONNECTIVITY  (const CONNECTIVITY & m);
144   virtual ~CONNECTIVITY ();
145
146   void setConstituent (CONNECTIVITY * Constituent)
147                                         throw (MEDEXCEPTION);
148
149   void setGeometricTypes (const MED_EN::medGeometryElement * Types,
150                            const MED_EN::medEntityMesh Entity)
151                                         throw (MEDEXCEPTION);
152
153   void setCount (const int * Count, const MED_EN::medEntityMesh Entity)
154                                         throw (MEDEXCEPTION);
155
156   void setNodal (const int * Connectivity,
157                  const MED_EN::medEntityMesh Entity,
158                  const MED_EN::medGeometryElement Type)
159                                         throw (MEDEXCEPTION);
160
161   inline void setNumberOfNodes(int NumberOfNodes);
162   
163   inline int getEntityDimension() const;
164
165   inline void setEntityDimension(int EntityDimension);
166
167   void setPolygonsConnectivity(MED_EN::medConnectivity ConnectivityType,
168                                MED_EN::medEntityMesh Entity,
169                                const int* PolygonsConnectivity,
170                                const int* PolygonsConnectivityIndex,
171                                int ConnectivitySize, int NumberOfPolygons);
172
173   void setPolyhedronConnectivity(MED_EN::medConnectivity ConnectivityType,
174                                  const int* PolyhedronConnectivity,
175                                  const int* PolyhedronIndex, int ConnectivitySize,
176                                  int NumberOfPolyhedron,
177                                  const int* PolyhedronFacesIndex= (int*) NULL,
178                                  int NumberOfFaces=0);
179
180   inline bool   existConnectivity     (MED_EN::medConnectivity connectivityType, MED_EN::medEntityMesh Entity) const;
181   
182   inline bool existPolygonsConnectivity(MED_EN::medConnectivity connectivityType,
183                                         MED_EN::medEntityMesh Entity) const;
184
185   inline bool existPolyhedronConnectivity(MED_EN::medConnectivity connectivityType,
186                                           MED_EN::medEntityMesh Entity) const;
187
188   virtual void          calculateConnectivity (MED_EN::medConnectivity connectivityType, MED_EN::medEntityMesh Entity);
189
190   virtual void          updateFamily (const vector<FAMILY*>& myFamilies);
191
192   inline MED_EN::medEntityMesh              getEntity               ()                     const;
193   inline int                    getNumberOfTypes        (MED_EN::medEntityMesh Entity) const;
194   int                    getNumberOfTypesWithPoly(MED_EN::medEntityMesh Entity) const;
195   const int * getConnectivityOfAnElementWithPoly(MED_EN::medConnectivity ConnectivityType,
196                                                  MED_EN::medEntityMesh Entity,
197                                                  int Number, int &lgth);
198   int getNumberOfPolyType()  const;
199   int getNumberOfElementsWithPoly(MED_EN::medEntityMesh Entity, MED_EN::medGeometryElement Type) const;
200   int getNumberOfElementOfPolyType(MED_EN::medEntityMesh Entity)  const;
201   inline const MED_EN::medGeometryElement * getGeometricTypes       (MED_EN::medEntityMesh Entity) const
202                                                              throw (MEDEXCEPTION);
203   MED_EN::medGeometryElement * getGeometricTypesWithPoly       (MED_EN::medEntityMesh Entity) const
204                                                              throw (MEDEXCEPTION);
205   MED_EN::medGeometryElement                getElementType          (MED_EN::medEntityMesh Entity,
206                                                              int Number)           const;
207   MED_EN::medGeometryElement                getElementTypeWithPoly          (MED_EN::medEntityMesh Entity,
208                                                              int Number)           const;
209   inline MED_EN::medGeometryElement                getPolyTypeRelativeTo() const;
210   virtual inline const int *                getGlobalNumberingIndex (MED_EN::medEntityMesh Entity) const
211                                                              throw (MEDEXCEPTION);
212
213   virtual const int *     getConnectivity      (MED_EN::medConnectivity ConnectivityType, 
214                                             MED_EN::medEntityMesh Entity,
215                                             MED_EN::medGeometryElement Type);
216   virtual int getConnectivityLength        (MED_EN::medConnectivity ConnectivityType, 
217                                             MED_EN::medEntityMesh Entity,
218                                             MED_EN::medGeometryElement Type);
219   virtual const int *     getConnectivityIndex (MED_EN::medConnectivity ConnectivityType,
220                                             MED_EN::medEntityMesh Entity);
221
222   const int* getPolygonsConnectivity(MED_EN::medConnectivity ConnectivityType,
223                                      MED_EN::medEntityMesh Entity);
224   const int* getPolygonsConnectivityIndex(MED_EN::medConnectivity ConnectivityType,
225                                           MED_EN::medEntityMesh Entity);
226   int getNumberOfPolygons() const;
227   const int* getPolyhedronConnectivity(MED_EN::medConnectivity ConnectivityType) const;
228   const int* getPolyhedronFacesIndex() const;
229   const int* getPolyhedronIndex(MED_EN::medConnectivity ConnectivityType) const;
230   int getNumberOfPolyhedronFaces() const;
231   int getNumberOfPolyhedron() const;
232   int *getNodesOfPolyhedron(int polyhedronId, int& lgthOfTab) const;
233   int **getNodesPerFaceOfPolyhedron(int polyhedronId, int& nbOfFaces, int* & nbOfNodesPerFaces) const;
234   const CELLMODEL &   getType              (MED_EN::medGeometryElement Type) const; 
235   const CELLMODEL *   getCellsTypes        (MED_EN::medEntityMesh Entity)    const 
236                                             throw (MEDEXCEPTION);
237  
238   int       getNumberOfNodesInType     (MED_EN::medGeometryElement Type) const; 
239   int       getNumberOfSubCellInType   (MED_EN::medGeometryElement Type) const; 
240   virtual int   getNumberOf                (MED_EN::medEntityMesh Entity, 
241                                             MED_EN::medGeometryElement Type) const;
242   virtual const int*      getValue             (MED_EN::medConnectivity TypeConnectivity, 
243                                             MED_EN::medGeometryElement Type); 
244   virtual const int*      getValueIndex        (MED_EN::medConnectivity TypeConnectivity);
245
246   virtual inline const int* getReverseConnectivity (MED_EN::medConnectivity ConnectivityType, 
247                                                 MED_EN::medEntityMesh Entity=MED_EN::MED_CELL)
248                                                 throw (MEDEXCEPTION);
249   virtual inline const int* getReverseConnectivityIndex (MED_EN::medConnectivity ConnectivityType, 
250                                                      MED_EN::medEntityMesh Entity=MED_EN::MED_CELL)
251                                                      throw (MEDEXCEPTION);
252
253   const int*      getNeighbourhood() const;
254   void invertConnectivityForAFace(int faceId, const int *nodalConnForFace, bool polygonFace=false);
255   bool deepCompare(const CONNECTIVITY& other) const;
256 };
257 /*----------------------*/
258 /* Methodes Inline      */
259 /*----------------------*/
260
261 /*! Returns the  medEntityMesh */
262 //--------------------------------------------------//
263 inline MED_EN::medEntityMesh CONNECTIVITY::getEntity() const 
264 //--------------------------------------------------//
265
266         return _entity; 
267 }
268
269 /*!  Returns the number of different %medGeometryElement types 
270      existing in the specified entity. \n
271      Note : Not implemented for MED_ALL_ENTITIES. */
272 //-----------------------------------------------------------------------//
273 inline int CONNECTIVITY::getNumberOfTypes(MED_EN::medEntityMesh Entity) const
274 //-----------------------------------------------------------------------//
275 {
276   MESSAGE("CONNECTIVITY::getNumberOfTypes : Entity = "<<Entity<<", _entity = "<<_entity);
277   if (_entity==Entity)
278     return _numberOfTypes; 
279   else if (_constituent!=NULL)
280     return _constituent->getNumberOfTypes(Entity);
281   else if (_constituent == NULL)
282     {
283       MESSAGE("CONNECTIVITY::getNumberOfTypes : _constituent == NULL");
284       try
285         {
286           (const_cast <CONNECTIVITY *> (this))->calculateDescendingConnectivity();
287         }
288       catch (MEDEXCEPTION & ex)
289         {
290           return 0 ;
291         }
292
293       SCRUTE(_entityDimension);
294
295       if (_entityDimension != 2 && _entityDimension != 3) return 0;
296
297       try
298         {
299           _constituent->calculateConnectivity(MED_EN::MED_NODAL,Entity);
300         }
301       catch (MEDEXCEPTION & ex)
302         {
303           return 0 ;
304         }
305
306       return _constituent->getNumberOfTypes(Entity);
307     }
308   else
309         return 0; // because it is the right information (no exception needed)!
310 }
311
312 /*!  Returns an array of all %medGeometryElement types existing in the mesh 
313      for the given %medEntityMesh.
314      Note : Not implemented for MED_ALL_ENTITIES.
315      Throws an exception if Entity is unknown */
316 //------------------------------------------------------------------------------------------//
317 inline const MED_EN::medGeometryElement* CONNECTIVITY::getGeometricTypes(MED_EN::medEntityMesh Entity) const 
318                                                 throw (MEDEXCEPTION)
319 //------------------------------------------------------------------------------------------//
320 {
321   if (_entity==Entity)
322         return _geometricTypes;
323   else if (_constituent!=NULL)
324         return _constituent->getGeometricTypes(Entity);
325   else
326         throw MEDEXCEPTION("CONNECTIVITY::getGeometricTypes : Entity not defined !");
327 }
328
329 /*!   Returns an array containing the accumulated number of entities sorted by the geometric type.\n
330
331       Exemple :\n
332
333       In case of a CONNECTIVITY containing 3*MED_TRIA3 et 2*MED_QUAD4 : \n
334             int * count = getGlobalNumberingIndex(MED_CELL)\n
335       count[0] is always set to 1\n
336       count[1] is set to 1+3=4\n
337       count[2] is set to 4+2=6 = total number of cells + 1\n
338
339       Note : Not implemented for MED_ALL_ENTITIES. \n
340       Note : The geometric type order is given by the typedef enum medGeometryElement.
341                       
342 */
343 //----------------------------------------------------------------------------------//
344 inline const int * CONNECTIVITY::getGlobalNumberingIndex(MED_EN::medEntityMesh Entity) const 
345                                                 throw (MEDEXCEPTION)
346 //----------------------------------------------------------------------------------//
347 {
348   if (_entity==Entity)
349         return _count;
350   else if (_constituent!=NULL)
351         return _constituent->getGlobalNumberingIndex(Entity);
352   else
353         throw MEDEXCEPTION("CONNECTIVITY::getGlobalNumberingIndex : Entity not defined !");
354 }
355
356 /*!  Returns true if a connectivity exists on elements of type "Entity" */
357 //-----------------------------------------------------------------------------//
358 inline bool CONNECTIVITY::existConnectivity( MED_EN::medConnectivity ConnectivityType, 
359                                              MED_EN::medEntityMesh Entity) const
360 //-----------------------------------------------------------------------------//
361 {
362   if (_entity==Entity) { 
363     if ((ConnectivityType==MED_EN::MED_NODAL)&(_nodal!=(MEDSKYLINEARRAY*)NULL))
364       return true;
365     if ((ConnectivityType==MED_EN::MED_DESCENDING)&(_descending!=(MEDSKYLINEARRAY*)NULL))
366       return true;
367   } else if (_constituent!=NULL)
368     return _constituent->existConnectivity(ConnectivityType,Entity);
369   return false;
370 }
371
372 /*! Returns true if a polygons connectivity exists on elements of type "Entity" */
373 //-----------------------------------------------------------------------------//
374 inline bool CONNECTIVITY::existPolygonsConnectivity(MED_EN::medConnectivity ConnectivityType,
375                                                     MED_EN::medEntityMesh Entity) const
376 //-----------------------------------------------------------------------------//
377 {
378   if (_entity == Entity)
379     {
380       MESSAGE("existPolygonsConnectivity : _entity == Entity = "<<Entity);
381       if (ConnectivityType == MED_EN::MED_NODAL && _polygonsNodal != (MEDSKYLINEARRAY*) NULL)
382         return true;
383       if (ConnectivityType == MED_EN::MED_DESCENDING && _polygonsDescending != (MEDSKYLINEARRAY*) NULL)
384         return true;
385     }
386   else if (_constituent != (CONNECTIVITY*) NULL)
387     return _constituent->existPolygonsConnectivity(ConnectivityType,Entity);
388   return false;
389 }
390
391 /*! Returns true if a polyhedron connectivity exists on elements of type "Entity" */
392 //-----------------------------------------------------------------------------//
393 inline bool CONNECTIVITY::existPolyhedronConnectivity(MED_EN::medConnectivity ConnectivityType,
394                                                       MED_EN::medEntityMesh Entity) const
395 //-----------------------------------------------------------------------------//
396 {
397   if (_entity == Entity)
398     {
399       MESSAGE("existPolyhedronConnectivity : _entity == Entity = "<<Entity);
400       if (ConnectivityType == MED_EN::MED_NODAL && _polyhedronNodal != (POLYHEDRONARRAY*) NULL)
401         return true;
402       if (ConnectivityType == MED_EN::MED_DESCENDING && _polyhedronDescending != (MEDSKYLINEARRAY*) NULL)
403         return true;
404     }
405   else if (_constituent != (CONNECTIVITY*) NULL)
406     return _constituent->existPolyhedronConnectivity(ConnectivityType,Entity);
407   return false;
408 }
409
410 /*! 
411 Returns an array containing CELLMODEL foreach element type present 
412 in connectivity for given medEntityMesh (similar as getGeometricTypes).\n
413 Throw an execption if the given entity is not defined or if the array is not defined.
414 */
415 //-----------------------------------------------------------------------------//
416 inline const CELLMODEL * CONNECTIVITY::getCellsTypes(MED_EN::medEntityMesh Entity) const
417                                                 throw (MEDEXCEPTION)
418 //-----------------------------------------------------------------------------//
419 {
420   if (Entity == _entity)
421     if (_type!=NULL)
422       return _type;
423     else
424       throw MEDEXCEPTION("CONNECTIVITY::getCellsTypes(medEntityMesh) :"
425                          " CELLMODEL array is not defined !");
426   else
427     if (_constituent != NULL)
428       return _constituent->getCellsTypes(Entity);
429     else
430       throw MEDEXCEPTION("CONNECTIVITY::getCellsTypes(medEntityMesh) : Not found Entity !");
431 }
432
433 /*! A DOCUMENTER */
434 //------------------------------------------------------------------------------------------//
435 inline const int* CONNECTIVITY::getReverseConnectivity( MED_EN::medConnectivity ConnectivityType, 
436                                                             MED_EN::medEntityMesh Entity) 
437                                                             throw (MEDEXCEPTION)
438 //------------------------------------------------------------------------------------------//
439 {
440   if(_entity==Entity)
441     if (ConnectivityType==MED_EN::MED_NODAL)
442       return getReverseNodalConnectivity();
443     else if (ConnectivityType==MED_EN::MED_DESCENDING)
444       return getReverseDescendingConnectivity();
445     else
446       throw MEDEXCEPTION("MESH::getReverseConnectivity : connectivity mode not supported !");
447
448   // other entity :
449   if (NULL==_constituent)
450     calculateDescendingConnectivity();
451   return _constituent->getReverseConnectivity(ConnectivityType,Entity);
452 }
453
454 /*! A DOCUMENTER */
455 //-----------------------------------------------------------------------------------------------//
456 inline const int* CONNECTIVITY::getReverseConnectivityIndex(MED_EN::medConnectivity ConnectivityType, 
457                                                                 MED_EN::medEntityMesh Entity) 
458                                                                 throw (MEDEXCEPTION)
459 //-----------------------------------------------------------------------------------------------//
460 {
461   if(_entity==Entity)
462     if (ConnectivityType==MED_EN::MED_NODAL)
463       return getReverseNodalConnectivityIndex();
464     else if (ConnectivityType==MED_EN::MED_DESCENDING)
465       return getReverseDescendingConnectivityIndex();
466     else
467       throw MEDEXCEPTION("MESH::getReverseConnectivityIndex : connectivity mode not supported !");
468   
469   // other entity :
470   if (NULL==_constituent)
471     calculateDescendingConnectivity();
472   return _constituent->getReverseConnectivityIndex(ConnectivityType,Entity);
473 }
474
475
476 inline void CONNECTIVITY::setNumberOfNodes(int NumberOfNodes)
477 {
478     _numberOfNodes=NumberOfNodes;
479 }
480   
481 inline void CONNECTIVITY::setEntityDimension(int EntityDimension)
482 {
483     _entityDimension=EntityDimension;
484 }
485
486 int CONNECTIVITY::getEntityDimension() const
487 {
488   return _entityDimension;
489 }
490
491 MED_EN::medGeometryElement CONNECTIVITY::getPolyTypeRelativeTo() const
492 {
493   if(_entity==MED_EN::MED_CELL && _entityDimension==3)
494     return MED_EN::MED_POLYHEDRA;
495   else if((_entity==MED_EN::MED_CELL && _entityDimension==2) || (_entity==MED_EN::MED_FACE && _entityDimension==2))
496     return MED_EN::MED_POLYGON;
497   else
498     throw MEDEXCEPTION("getPolyTypeRelativeTo : ");
499 }
500
501 }//End namespace MEDMEM
502
503 #endif /* CONNECTIVITY_HXX */
504