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