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