Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/med.git] / src / MEDMEM / MEDMEM_Support.cxx
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/ or email : webmaster.salome@opencascade.com
19 //
20 /*
21  File Support.cxx
22  $Header$
23 */
24
25 #include <set>
26 #include <algorithm>
27 #include <list>
28
29 #include "MEDMEM_Support.hxx"
30 #include "MEDMEM_DriversDef.hxx"
31 #include "MEDMEM_Mesh.hxx"
32
33 using namespace std;
34 using namespace MED_EN;
35 using namespace MEDMEM;
36
37 #define MED_NBR_GEOMETRIE_MAILLE 15
38
39 /* This class is a generic class for family and group */
40
41 /*!
42   Constructor.
43 */
44 //--------------------------------------------------------------------------
45 SUPPORT::SUPPORT(): _name(""),  _description("None"), _mesh((MESH*)NULL),
46                     _entity(MED_CELL), _numberOfGeometricType(0),
47                     _isOnAllElts(false),
48                     _totalNumberOfElements(0),
49                     _number((MEDSKYLINEARRAY*)NULL)
50 //--------------------------------------------------------------------------
51 {
52     MESSAGE("SUPPORT::SUPPORT()");
53 };
54
55 /*!
56   Constructor.
57 */
58 //--------------------------------------------------------------------------
59 SUPPORT::SUPPORT(MESH* Mesh, string Name/*=""*/, medEntityMesh Entity/*=MED_CELL*/):
60                 _name(Name), _description("None"), _mesh(Mesh), _entity(Entity),
61                 _numberOfGeometricType(0), _isOnAllElts(true),
62                 _totalNumberOfElements(0), _number((MEDSKYLINEARRAY*)NULL)
63 //--------------------------------------------------------------------------
64 {
65   MESSAGE("SUPPORT::SUPPORT(MESH*Mesh,string Name,medEntityMesh Entity)");
66   update() ;
67 };
68
69 /*!
70   Copy constructor.
71 */
72 //--------------------------------------------------------------------------
73 SUPPORT::SUPPORT(const SUPPORT & m)
74 //--------------------------------------------------------------------------
75 {
76   const char * LOC = "SUPPORT::SUPPORT(SUPPORT & m) : " ;
77   BEGIN_OF(LOC) ;
78
79   _name = m._name ;
80   _description = m._description ;
81   _mesh = m._mesh ; // on recopie uniquement l'adresse
82   _entity = m._entity;
83   _numberOfGeometricType = m._numberOfGeometricType;
84
85   if (m._geometricType)
86     _geometricType.set(_numberOfGeometricType,m._geometricType);
87
88   _isOnAllElts = m._isOnAllElts;
89
90   if (m._numberOfElements)
91     _numberOfElements.set(_numberOfGeometricType,m._numberOfElements);
92
93   _totalNumberOfElements = m._totalNumberOfElements;
94
95   if (m._isOnAllElts == false && m._number ) // m may be not filled SUPPORTClient
96     _number = new MEDSKYLINEARRAY(* m._number);
97   else
98     _number = (MEDSKYLINEARRAY *) NULL;
99
100   _profilNames=m._profilNames;
101
102   END_OF(LOC) ;
103 };
104 /*!
105   Affectation operator. operator = perform et deep copy except for attribute _mesh
106 */
107 //--------------------------------------------------------------------------
108 SUPPORT & SUPPORT::operator=(const SUPPORT & m)
109 //--------------------------------------------------------------------------
110 {
111   const char * LOC = "SUPPORT::operator=(const SUPPORT & m) : " ;
112   BEGIN_OF(LOC) ;
113
114   if ( this == &m ) return *this;
115
116   _name = m._name;
117   _description = m._description;
118   _mesh = m._mesh ; // on recopie uniquement l'adresse
119   _entity = m._entity;
120   _numberOfGeometricType = m._numberOfGeometricType;
121   if (m._geometricType)
122     _geometricType.set(_numberOfGeometricType,m._geometricType);
123   _isOnAllElts = m._isOnAllElts;
124   if (m._numberOfElements)
125     _numberOfElements.set(_numberOfGeometricType,m._numberOfElements);
126   _totalNumberOfElements = m._totalNumberOfElements;
127   if (m._isOnAllElts == false) {
128     if (_number) delete _number;
129     if  ( m._number ) // m may be not filled SUPPORTClient
130       _number = new MEDSKYLINEARRAY(* m._number);
131     else
132       _number = (MEDSKYLINEARRAY *) NULL;
133   } else
134     _number = (MEDSKYLINEARRAY *) NULL;
135   _profilNames=m._profilNames;
136
137   END_OF(LOC) ;
138   return *this;
139 }
140
141 /*!
142   Destructor.
143 */
144 //-----------------
145 SUPPORT::~SUPPORT()
146 //-----------------
147 {
148   MESSAGE("Destructeur ~SUPPORT()");
149   clearDataOnNumbers();
150 }
151
152 /*!
153   operator <<.
154 */
155 //--------------------------------------------------
156 ostream & MEDMEM::operator<<(ostream &os, const SUPPORT &my)
157 //--------------------------------------------------
158 {
159   os << "Name : "<< my.getName() << endl ;
160   os << "Description : "<< my.getDescription() << endl ;
161   os << "Mesh ptr : ";
162   if (my.getMesh() == NULL)
163     os << " Mesh not defined." << endl ;
164   else
165     os << " Mesh defined." << endl;
166   os << "MeshName : ";
167   os << my.getMeshName() << endl ;
168   os << "Entity : "<<MED_EN::entNames[my._entity] << endl;
169   os << "Entity list : "<< endl;
170   if ( my._isOnAllElts )
171     os << "Is on all entities."<< endl;
172   else {
173     os << "Is not on all entities. "<< endl;
174     if ( my._number )  // m may be not filled SUPPORTClient
175       os << *my.getNumber(MED_ALL_ELEMENTS);
176   }
177   int numberoftypes = my._numberOfGeometricType ;
178   os << "NumberOfTypes : "<<numberoftypes<<endl;
179   PointerOf<medGeometryElement> types = my._geometricType;
180   for (int j=0;j<numberoftypes;j++) {
181     int numberOfElements = my._numberOfElements[j];
182     os << "    On Type "<<MED_EN::geoNames[types[j]]
183        <<" : there is(are) "<<numberOfElements<<" element(s) and " <<endl;
184   }
185   return os ;
186 }
187
188 /*!
189   Updade the SUPPORT attributs with rigth MESH information.
190
191   It has an effect only if SUPPORT is on all elements.
192
193   No more need in future release.
194 */
195 //-------------------
196 void SUPPORT::update()
197 //-------------------
198 {
199   const char * LOC = "SUPPORT::update() : " ;
200   BEGIN_OF(LOC) ;
201
202   if (_isOnAllElts)
203     {
204       if (_entity == MED_NODE)
205         {
206           _numberOfGeometricType=1 ;
207           _geometricType.set(1);
208           _geometricType[0]=MED_POINT1;
209           _numberOfElements.set(1);
210           _numberOfElements[0]=_mesh->getNumberOfNodes(); // Vérifier le pointeur !
211           _totalNumberOfElements=_numberOfElements[0];
212         }
213       else
214         { // we duplicate information from _mesh\ 1
215           _numberOfGeometricType=_mesh->getNumberOfTypesWithPoly(_entity);
216           SCRUTE(_numberOfGeometricType);
217           medGeometryElement *  allType = _mesh->getTypesWithPoly(_entity);
218           _geometricType.set(_numberOfGeometricType,allType );
219           _numberOfElements.set(_numberOfGeometricType);
220           _totalNumberOfElements=0;
221           for (int i=0;i<_numberOfGeometricType;i++)
222             {
223               _numberOfElements[i]=_mesh->getNumberOfElementsWithPoly(_entity,_geometricType[i]) ;
224               _totalNumberOfElements+=_numberOfElements[i];
225             }
226           delete [] allType;
227         }
228
229       SCRUTE(_name);
230       SCRUTE(_numberOfGeometricType);
231     }
232   END_OF(LOC);
233 };
234 /*!
235   Get the field value index (in fortran mode) from the support global number.
236   Becareful, it doesn't take care of the field number of components
237 */
238 //-------------------
239 int SUPPORT::getValIndFromGlobalNumber(const int number) const throw (MEDEXCEPTION)
240 //-------------------
241 {
242   const char * LOC="getValIndFromGlobalNumber(const int number) : ";
243   //BEGIN_OF(LOC);
244
245   if (_isOnAllElts) return number;
246
247   int nbOfEltsThis    = getNumberOfElements(MED_ALL_ELEMENTS);
248
249   const int *eltsThis = _number->getValue();
250
251   int iThis;
252   bool found=false;
253
254   for(iThis=0;iThis<nbOfEltsThis && !found;)
255     if(eltsThis[iThis]==number)
256       {
257         found = true;
258         int valInd = iThis+1;
259         return valInd;
260       }
261     else
262       iThis++;
263
264   //if (!_isOnAllElts)
265   cout << "----Contenu du skyline : ---------------------" << *_number << endl;
266
267   if(!found)
268     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Can't find the global number |"
269                                  << number << "| in Support |"
270                                  << getName() << "|" ));
271  
272   // It should never arrive here !!
273   return 0;
274
275   //END_OF(LOC);
276 }
277
278 /*!
279   Blend the given SUPPORT mySupport into the calling object SUPPORT.
280 */
281 //-------------------
282 void SUPPORT::blending(SUPPORT * mySupport) throw (MEDEXCEPTION)
283 //-------------------
284 {
285   const char * LOC="SUPPORT::blending(SUPPORT *) : ";
286   BEGIN_OF(LOC);
287   if (_entity!=mySupport->getEntity())
288     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Entities are different !"));
289   if(!(*_mesh == *mySupport->getMesh()))
290     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Mesh are different !"));
291   if(_isOnAllElts)
292     return;
293   if(mySupport->isOnAllElements())
294     {
295       *this=*mySupport;
296       return;
297     }
298   if(mySupport->_totalNumberOfElements==0)
299     return;
300   const int *ids=getNumber(MED_ALL_ELEMENTS);
301   set<int> idsSet(ids,ids+getNumberOfElements(MED_ALL_ELEMENTS));
302   const int *idsMySupport=mySupport->getNumber(MED_ALL_ELEMENTS);
303   int mySupportSize=mySupport->getNumberOfElements(MED_ALL_ELEMENTS);
304   set<int>::iterator iter;
305   for(int i=0;i<mySupportSize;i++)
306     idsSet.insert(idsMySupport[i]);
307   int size=idsSet.size();
308
309   if(size!=0)
310     {
311       list<int> idsList;
312       for(iter=idsSet.begin();iter!=idsSet.end();iter++)
313         idsList.push_back(*iter);
314
315       MESSAGE(LOC << " size Set " << idsSet.size() << " size List " << idsList.size());
316
317       if(_entity==MED_NODE)
318         fillFromNodeList(idsList);
319       else
320         fillFromElementList(idsList);
321     }
322   else
323     clearDataOnNumbers();
324   END_OF(LOC);
325 }
326
327 /*!
328     This function allows the user to set a support not on all entities Entity,
329     it should be used after an initialisation with the constructor
330     SUPPORT(MESH* Mesh, string Name="", medEntityMesh Entity=MED_CELL) and
331     after the call to the function setAll(false).
332     It allocates and initialises all the attributs of the class SUPPORT.
333  */
334
335 //-------------------
336 void SUPPORT::setpartial(string Description, int NumberOfGeometricType,
337                          int TotalNumberOfElements,
338                          medGeometryElement *GeometricType,
339                          int *NumberOfElements, int *NumberValue)
340 //-------------------
341 {
342   const char * LOC = "SUPPORT::setpartial(string , int , int , medGeometryElement * , int * , int *) : " ;
343   BEGIN_OF(LOC) ;
344
345   _isOnAllElts = false ;
346
347   _description=Description;
348
349   _numberOfGeometricType=NumberOfGeometricType;
350   _geometricType.set(NumberOfGeometricType);
351   _numberOfElements.set(NumberOfGeometricType);
352   _totalNumberOfElements = TotalNumberOfElements;
353
354   int * index = new int[_numberOfGeometricType+1];
355   index[0]=1;
356   int elemDim = -1;
357   for (int i=0;i<_numberOfGeometricType;i++) {
358     if(GeometricType[i]/100 != elemDim)
359       if(i==0)
360         elemDim=GeometricType[i]/100;
361       else
362         throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"unhomogeneous geometric types (dimension) !"));
363     _geometricType[i] = GeometricType[i] ;
364     _numberOfElements[i] = NumberOfElements[i] ;
365     index[i+1] = index[i]+NumberOfElements[i] ;
366   }
367
368   if (_number!=NULL) delete _number ;
369   _number = new MEDSKYLINEARRAY(_numberOfGeometricType,_totalNumberOfElements,index,NumberValue);
370
371   delete[] index ;
372
373   // PAL16854(Partial support on nodes):
374   // giving a default value to profile names
375   vector<string> prof_names( NumberOfGeometricType);
376   for (int itype=0; itype < NumberOfGeometricType; itype++)
377   {
378     ostringstream typestr;
379     typestr<<_name<<"_type"<<itype;
380     prof_names[itype]=typestr.str();
381   }
382   setProfilNames(prof_names);
383   
384   END_OF(LOC);
385 };
386
387
388 /*!
389     This function allows the user to set a support not on all entities Entity,
390     it should be used after an initialisation of :
391     SUPPORT(MESH* Mesh, string Name="", medEntityMesh Entity=MED_CELL) and
392     after calling  at least setGeometricType and perharps setEntity.
393     It allocates and initialises all the attributs of the class SUPPORT but
394     doesn't set a description, a SUPPORT name, a meshName and an associated MESH.
395  */
396
397 //-------------------
398 void SUPPORT::setpartial(MEDSKYLINEARRAY * number, bool shallowCopy) throw (MEDEXCEPTION)
399 //-------------------
400 {
401   const char * LOC = "SUPPORT::setpartial(MEDSKYLINEARRAY * number) : " ;
402   BEGIN_OF(LOC) ;
403
404   if ( ! _geometricType )
405     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"SUPPORT must contains"
406                                  << " a geometric type list" )) ;
407
408   _numberOfGeometricType = number->getNumberOf();
409
410   _numberOfElements.set(_numberOfGeometricType);
411
412   for (int i=0; i< _numberOfGeometricType; i++)
413     _numberOfElements[i] =  number->getNumberOfI(i+1);
414
415   _totalNumberOfElements = number->getLength();
416
417   _isOnAllElts = false ;
418
419   if (_number!=NULL) delete _number ;
420
421   if ( shallowCopy )
422     _number = number;
423   else
424     _number = new MEDSKYLINEARRAY(*number);
425
426   // cout << *_number << endl;
427
428   END_OF(LOC);
429 };
430
431 void SUPPORT::setpartial_fromfile(MEDSKYLINEARRAY * number, bool shallowCopy) throw (MEDEXCEPTION)
432 //-------------------
433 {
434   const char * LOC = "SUPPORT::setpartial_fromfile(MEDSKYLINEARRAY * number) : " ;
435   BEGIN_OF(LOC) ;
436
437   if ( shallowCopy )
438     _number_fromfile = number;
439   else
440     _number_fromfile = new MEDSKYLINEARRAY(*number);
441
442   END_OF(LOC);
443 };
444
445 void SUPPORT::setProfilNames(vector<string> profilNames) throw (MEDEXCEPTION){
446
447   const char * LOC = "SUPPORT::setProfilNames(vector<string> profilNames) : " ;
448   BEGIN_OF(LOC) ;
449
450   if ( _isOnAllElts )
451     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"SUPPORT shouldn't be on all elements"
452                                  << " while setting profil name list" )) ;
453
454   if ( ! _geometricType || _numberOfGeometricType==0 )
455     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"SUPPORT must contains"
456                                  << " a least one geometric type" )) ;
457
458   if ( ! _number )
459     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"SUPPORT must contains"
460                                  << " a profil number list before setting"
461                                  << " the associated profil name list" )) ;
462
463   if ( ( profilNames.size() != _number->getNumberOf() ) &&
464        ( profilNames.size() !=_numberOfGeometricType ) ) {
465     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"The profil name list size : "<< profilNames.size()
466                                  << " must be equal to the number of geometric type : " 
467                                  <<  _numberOfGeometricType << " (_number->getNumberOf() : "
468                                  << _number->getNumberOf() << " )"
469                                  )) ;
470
471   }
472
473   _profilNames = profilNames;
474
475   END_OF(LOC);
476
477 };
478
479 vector<string> SUPPORT::getProfilNames() const throw (MEDEXCEPTION)
480 {
481   return _profilNames;
482 };
483
484
485 /*!
486   This method gets the boundary elements of the mesh. The support has to be
487   build using the constructor SUPPORT(MESH *,string, medEntityMesh) or
488   SUPPORT() followed by setMesh(MESH*) setName(string) and
489   setEntity(medEntityMesh) before using this method.
490 */
491 //-------------------
492 void SUPPORT::getBoundaryElements() throw (MEDEXCEPTION)
493 //-------------------
494 {
495   const char * LOC = "SUPPORT::getBoundaryElements() : " ;
496   BEGIN_OF(LOC) ;
497
498   if (_mesh == (MESH*)NULL) throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"You shlould use the appropriate SUPPORT Constructor before calling this method"));
499
500   int spaceDimension = _mesh->getSpaceDimension();
501
502   if (spaceDimension == 3)
503     if (_entity != MED_FACE)
504       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Not defined in 3D mesh for entity "<<_entity<<" !"));
505   if (spaceDimension == 2)
506     if (_entity != MED_EDGE)
507       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Not defined in 2D mesh for entity "<<_entity<<" !"));
508
509   setAll(false);
510
511   const int * myConnectivityValue = _mesh->getReverseConnectivity(MED_DESCENDING) ;
512   const int * myConnectivityIndex = _mesh->getReverseConnectivityIndex(MED_DESCENDING) ;
513   int numberOf = _mesh->getNumberOfElements(_entity,MED_ALL_ELEMENTS) ;
514   list<int> myElementsList ;
515   int size = 0 ;
516   SCRUTE(numberOf) ;
517   for (int i=0 ; i<numberOf; i++)
518     if (myConnectivityValue[myConnectivityIndex[i]] == 0) {
519       SCRUTE(i+1) ;
520       myElementsList.push_back(i+1) ;
521       size++ ;
522     }
523   SCRUTE(size) ;
524   // Well, we must know how many geometric type we have found
525   int * myListArray = new int[size] ;
526   int id = 0 ;
527   list<int>::iterator myElementsListIt ;
528   for (myElementsListIt=myElementsList.begin();myElementsListIt!=myElementsList.end();myElementsListIt++) {
529     myListArray[id]=(*myElementsListIt) ;
530     SCRUTE(id);
531     SCRUTE(myListArray[id]);
532     id ++ ;
533   }
534
535   int numberOfGeometricType ;
536   medGeometryElement* geometricType ;
537   int * geometricTypeNumber ;
538   int * numberOfElements ;
539   //MEDSKYLINEARRAY * mySkyLineArray = new MEDSKYLINEARRAY() ;
540   int * mySkyLineArrayIndex ;
541
542   int numberOfType = _mesh->getNumberOfTypes(_entity) ;
543   if (numberOfType == 1) { // wonderfull : it's easy !
544     numberOfGeometricType = 1 ;
545     geometricType = new medGeometryElement[1] ;
546     const medGeometryElement *  allType = _mesh->getTypes(_entity);
547     geometricType[0] = allType[0] ;
548     geometricTypeNumber = new int[1] ; // not use, but initialized to nothing
549     geometricTypeNumber[0] = 0 ;
550     numberOfElements = new int[1] ;
551     numberOfElements[0] = size ;
552     mySkyLineArrayIndex = new int[2] ;
553     mySkyLineArrayIndex[0]=1 ;
554     mySkyLineArrayIndex[1]=1+size ;
555   }
556   else {// hemmm
557     map<medGeometryElement,int> theType ;
558     for (myElementsListIt=myElementsList.begin();myElementsListIt!=myElementsList.end();myElementsListIt++) {
559       medGeometryElement myType = _mesh->getElementType(_entity,*myElementsListIt) ;
560       if (theType.find(myType) != theType.end() )
561         theType[myType]+=1 ;
562       else
563         theType[myType]=1 ;
564     }
565     numberOfGeometricType = theType.size() ;
566     geometricType = new medGeometryElement[numberOfGeometricType] ;
567     //const medGeometryElement *  allType = _mesh->getTypes(_entity); !! UNUSED VARIABLE !!
568     geometricTypeNumber = new int[numberOfGeometricType] ; // not use, but initialized to nothing
569     numberOfElements = new int[numberOfGeometricType] ;
570     mySkyLineArrayIndex = new int[numberOfGeometricType+1] ;
571     int index = 0 ;
572     mySkyLineArrayIndex[0]=1 ;
573     map<medGeometryElement,int>::iterator theTypeIt ;
574     for (theTypeIt=theType.begin();theTypeIt!=theType.end();theTypeIt++) {
575       geometricType[index] = (*theTypeIt).first ;
576          geometricTypeNumber[index] = 0 ;
577       numberOfElements[index] = (*theTypeIt).second ;
578       mySkyLineArrayIndex[index+1]=mySkyLineArrayIndex[index]+numberOfElements[index] ;
579       index++ ;
580     }
581   }
582   //mySkyLineArray->setMEDSKYLINEARRAY(numberOfGeometricType,size,mySkyLineArrayIndex,myListArray) ;
583   MEDSKYLINEARRAY * mySkyLineArray = new MEDSKYLINEARRAY(numberOfGeometricType,size,mySkyLineArrayIndex,myListArray) ;
584
585   setNumberOfGeometricType(numberOfGeometricType) ;
586   //  setGeometricType(geometricType) ;
587  for (int i=0;i<numberOfGeometricType;i++)
588     {
589       _geometricType[i] = geometricType[i];
590     }
591
592   setNumberOfElements(numberOfElements) ;
593   setTotalNumberOfElements(size) ;
594   //  setNumber(mySkyLineArray) ;
595
596   _number = new MEDSKYLINEARRAY(numberOfGeometricType,size);
597
598   _number->setIndex(mySkyLineArrayIndex);
599
600   for (int i=0;i<size;i++)
601     {
602       _number->setIndexValue(i+1,myListArray[i]);
603     }
604
605   delete[] numberOfElements;
606   delete[] geometricTypeNumber;
607   delete[] geometricType;
608   delete[] mySkyLineArrayIndex;
609   delete[] myListArray;
610   delete mySkyLineArray;
611
612   END_OF(LOC) ;
613 }
614
615 /*!
616   intersect the given SUPPORT mySupport into the calling SUPPORT object.
617 */
618 //-------------------
619 void SUPPORT::intersecting(SUPPORT * mySupport) throw (MEDEXCEPTION)
620 {
621   const char * LOC="SUPPORT::intersecting(SUPPORT *) : ";
622   BEGIN_OF(LOC);
623   if (_entity!=mySupport->getEntity())
624     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Entities are different !"));
625   if(!(*_mesh == *mySupport->getMesh()))
626     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Mesh are different !"));
627   if(mySupport->isOnAllElements())
628     return;
629   if(_isOnAllElts)
630     {
631       *this=*mySupport;
632       return;
633     }
634   if(_totalNumberOfElements==0)
635     return;
636   const int *ids=getNumber(MED_ALL_ELEMENTS);
637   set<int> idsSet(ids,ids+getNumberOfElements(MED_ALL_ELEMENTS));
638   const int *idsMySupport=mySupport->getNumber(MED_ALL_ELEMENTS);
639   int mySupportSize=mySupport->getNumberOfElements(MED_ALL_ELEMENTS);
640   set<int> idsSetMySupport(idsMySupport,idsMySupport+mySupportSize);
641   set<int>::iterator iter;
642   list<int> idsList;
643   for(iter=idsSet.begin();iter!=idsSet.end();iter++)
644     if(idsSetMySupport.find(*iter)!=idsSetMySupport.end())
645       idsList.push_back(*iter);
646   int size=idsSet.size();
647   int sizeList = idsList.size();
648
649   MESSAGE(LOC << " size Set " << idsSet.size() << " size List " << idsList.size());
650
651   if(size!=0 && sizeList != 0)
652     {
653       if(_entity==MED_NODE)
654         fillFromNodeList(idsList);
655       else
656         fillFromElementList(idsList);
657     }
658   else
659     {
660       clearDataOnNumbers();
661     }
662   END_OF(LOC);
663 };
664
665 /*!
666   Method that cleans up all the fields related to _numbers. Defined for code factorization.
667  */
668 //--------------------------------------------------
669 void MEDMEM::SUPPORT::clearDataOnNumbers()
670 //--------------------------------------------------
671 {
672   _numberOfGeometricType=0;
673   _totalNumberOfElements=0;
674
675   if(_number)
676     {
677       delete _number;
678       _number=(MEDSKYLINEARRAY *) NULL;
679     }
680 }
681
682 /*!
683   operator == This operator does not compare attributs _name and _description.
684 */
685 //--------------------------------------------------
686 bool MEDMEM::SUPPORT::operator == (const SUPPORT &support) const
687 //--------------------------------------------------
688 {
689   const char * LOC = "bool SUPPORT::operator ==(const SUPPORT &support) const : ";
690
691   BEGIN_OF(LOC);
692
693   bool operatorReturn = false;
694
695   operatorReturn = (*_mesh == *support._mesh) && (_entity == support._entity) &&
696     (_numberOfGeometricType == support._numberOfGeometricType) &&
697     ((_isOnAllElts && support._isOnAllElts) || (!_isOnAllElts && !support._isOnAllElts)) &&
698     (_totalNumberOfElements == support._totalNumberOfElements);
699
700   if (operatorReturn)
701     {
702       if (!_isOnAllElts)
703         {
704           for (int i=0; i<_numberOfGeometricType; i++)
705             {
706               operatorReturn = operatorReturn &&
707                 (_geometricType[i] == support._geometricType[i]) &&
708                 (_numberOfElements[i] == support._numberOfElements[i]);
709
710               if (operatorReturn)
711                 {
712                   for (int j=0; j<_numberOfElements[i]; j++)
713                     {
714                       operatorReturn = operatorReturn &&
715                         (getNumber(_geometricType[i])[j] ==
716                          support.getNumber(_geometricType[i])[j]);
717                     }
718                 }
719             }
720         }
721     }
722
723   END_OF(LOC);
724
725   return operatorReturn;
726 };
727
728 void SUPPORT::changeElementsNbs(MED_EN::medEntityMesh entity, const int *renumberingFromOldToNew, int limitNbClassicPoly, const int *renumberingFromOldToNewPoly)
729 {
730   if(entity != _entity)
731     throw MEDEXCEPTION("SUPPORT::changeElementsNbs : Renumbering on a mismatch entity");
732   list<int> newNbs;
733   if(!_isOnAllElts)
734     {
735       const int *oldNbs=_number->getValue();
736       for(int i=0;i<_totalNumberOfElements;i++)
737         {
738           int globNb=oldNbs[i];
739           if(globNb<=limitNbClassicPoly)
740             newNbs.push_back(renumberingFromOldToNew[globNb-1]);
741           else
742             newNbs.push_back(renumberingFromOldToNewPoly[globNb-limitNbClassicPoly-1]);
743         }
744       newNbs.sort();
745       fillFromElementList(newNbs);
746     }
747   else
748     update();
749 }
750
751 /*!
752   operator == + in case false a test if coordinates and connectivity of _mesh and support->_mesh are the same
753 */
754 bool MEDMEM::SUPPORT::deepCompare(const SUPPORT &support) const
755 {
756   bool operatorReturn =(_entity == support._entity) &&
757     (_numberOfGeometricType == support._numberOfGeometricType) &&
758     ( (_isOnAllElts && support._isOnAllElts) || (!_isOnAllElts  && !support._isOnAllElts) ) &&
759     (_totalNumberOfElements == support._totalNumberOfElements);
760   if (operatorReturn)
761     {
762       if (!_isOnAllElts)
763         {
764           for (int i=0; i<_numberOfGeometricType && operatorReturn; i++)
765             {
766               operatorReturn = (_geometricType[i] == support._geometricType[i]) &&
767                 (_numberOfElements[i] == support._numberOfElements[i]);
768               if (operatorReturn)
769                 {
770                   for (int j=0; j<_numberOfElements[i]; j++)
771                     {
772                       operatorReturn = (getNumber(_geometricType[i])[j] ==
773                          support.getNumber(_geometricType[i])[j]);
774                     }
775                 }
776             }
777         }
778     }
779   if(operatorReturn)
780     {
781       if(!(*_mesh == *support._mesh))
782         {
783           return _mesh->deepCompare(*support._mesh);
784         }
785     }
786   return operatorReturn;
787 }
788
789 /*!
790  States if this is included in other.
791  */
792 bool MEDMEM::SUPPORT::belongsTo(const SUPPORT& other, bool deepCompare) const
793 {
794   if(!(*_mesh == *other._mesh))
795     {
796       if(!deepCompare)
797         return false;
798       if(!_mesh->deepCompare(*other._mesh))
799         return false;
800     }
801   if(_entity!=other._entity)
802     return false;
803   if(other._isOnAllElts)
804     return true;
805   if(_isOnAllElts && !other._isOnAllElts)
806     return false;
807   if(_numberOfGeometricType>other._numberOfGeometricType)
808     return false;
809   for(int i=0; i<_numberOfGeometricType; i++)
810     {
811       MED_EN::medGeometryElement curGeomType=_geometricType[i];
812       int iOther=-1;
813       for(int j=0; j<other._numberOfGeometricType; j++)
814           if(other._geometricType[j]==curGeomType)
815               iOther=j;
816       if(iOther==-1)
817         return false;
818       if(_numberOfElements[i]>other._numberOfElements[iOther])
819         return false;
820       const int *numbers1=_number->getI(i+1);
821       const int *numbers2=other._number->getI(iOther+1);
822       for (int k=0; k<_numberOfElements[i]; k++)
823         {
824           bool found=false;
825           for(int l=0;l<other._numberOfElements[iOther] && !found;l++)
826             {
827               if(numbers1[k]==numbers2[l])
828                 found=true;
829             }
830           if(!found)
831             return false;
832         }
833     }
834   return true;
835 }
836 /*!
837   Method used to sort array of id.
838  */
839 int compareId(const void *x, const void *y)
840 {
841   const int *x1=(const int *)x;
842   const int *y1=(const int *)y;
843   if(*x1<*y1)
844     return -1;
845   else if(*x1>*y1)
846     return 1;
847   else
848     return 0;
849 }
850
851 /*!
852   performs a common operation : Sub builds a sorted int array that is obtained by supression of all ids contained
853   in array defined by (idsToSuppress,lgthIdsToSuppress) from array [start ... end]
854   Example sub(0,7,{1,2,5},3) => {0,3,4,6,7} - WARNING returned list should be deallocated !
855  */
856 list<int> *MEDMEM::SUPPORT::sub(int start,int end,const int *idsToSuppress,int lgthIdsToSuppress)
857 {
858   int size=end-start+1;
859   int sizeRet=size-lgthIdsToSuppress;
860   list<int> *ret;
861   if(sizeRet<0)
862     throw MEDEXCEPTION("MEDMEM::SUPPORT::sub");
863   else if(sizeRet==0)
864     {
865       return 0;
866     }
867   if(idsToSuppress==0)
868     {
869       ret=new list<int>;
870       for(int l=0;l<size;l++)
871         ret->push_back(start+l);
872       return ret;
873     }
874   ret=new list<int>;
875   int *temp=new int[lgthIdsToSuppress];
876   memcpy(temp,idsToSuppress,sizeof(int)*lgthIdsToSuppress);
877   qsort(temp,lgthIdsToSuppress,sizeof(int),compareId);
878   int k=0;
879   for(int i=start;i<=end;i++)
880     if(temp[k]!=i)
881       ret->push_back(i);
882     else
883       k++;
884   delete [] temp;
885   return ret;
886 }
887
888 /*!
889   performs a common operation : Sub builds a sorted int array that is obtained by supression of all ids contained
890   in array defined by (idsToSuppress,lgthIdsToSuppress) from array [start ... end]
891   Example sub({1,3,4,5,6,7,9},7,{1,2,5},3) => {3,4,6,7,9}  - WARNING returned list should be deallocated !
892  */
893 list<int> *MEDMEM::SUPPORT::sub(const int *ids,int lgthIds,const int *idsToSuppress,int lgthIdsToSuppress)
894 {
895   list<int> *ret;
896   int i,j=0;
897   if(lgthIds<0)
898     throw MEDEXCEPTION("MEDMEM::SUPPORT::sub");
899   else if(lgthIds==0)
900     return 0;
901   ret=new list<int>;
902   int *temp1=new int[lgthIds];
903   memcpy(temp1,ids,sizeof(int)*lgthIds);
904   qsort(temp1,lgthIds,sizeof(int),compareId);
905   int *temp2=new int[lgthIdsToSuppress];
906   memcpy(temp2,idsToSuppress,sizeof(int)*lgthIdsToSuppress);
907   qsort(temp2,lgthIdsToSuppress,sizeof(int),compareId);
908   for(i=0;i<lgthIds;)
909     {
910       if(j>=lgthIdsToSuppress)
911           ret->push_back(temp1[i++]);
912       else if(temp1[i]>temp2[j])
913         j++;
914       else if(temp1[i]<temp2[j])
915         ret->push_back(temp1[i++]);
916       else
917         i++;
918     }
919   delete [] temp1;
920   delete [] temp2;
921   return ret;
922 }
923
924 /*!
925   returns a new SUPPORT (responsability to caller to destroy it)
926   that is the complement to "this", lying on the same entity than "this".
927  */
928 SUPPORT *MEDMEM::SUPPORT::getComplement() const
929 {
930   SUPPORT *ret;
931   const int nbOfElt=_mesh->getNumberOfElements(_entity,MED_EN::MED_ALL_ELEMENTS);
932   int nbOfEltInSupp=getNumberOfElements(MED_EN::MED_ALL_ELEMENTS);
933   if(_isOnAllElts || nbOfElt==nbOfEltInSupp)
934     {
935       ret=new SUPPORT;
936       ret->setMesh(_mesh);
937       ret->setEntity(_entity);
938       string name="Complement of ";
939       name+=_name;
940       ret->setName(name);
941       return ret;
942     }
943   const int *nbs=_number->getValue();
944   list<int> *ids=sub(1,nbOfElt,nbs,nbOfEltInSupp);
945   if(_entity==MED_EN::MED_NODE)
946     ret=_mesh->buildSupportOnNodeFromElementList(*ids,_entity);
947   else
948     ret=_mesh->buildSupportOnElementsFromElementList(*ids,_entity);
949   delete ids;
950   return ret;
951 }
952
953 /*!
954   returns a new support the user should delete.
955  */
956 SUPPORT *MEDMEM::SUPPORT::substract(const SUPPORT& other) const throw (MEDEXCEPTION)
957 {
958   const char * LOC = "SUPPORT *MEDMEM::subtract(const SUPPORT * other) : ";
959   BEGIN_OF(LOC);
960   SUPPORT *ret;
961   if (_entity!=other.getEntity())
962     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Entities are different !"));
963   if(!(*_mesh == *other.getMesh()))
964     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Mesh are different !"));
965   if(other._isOnAllElts)
966     {
967       ret=new SUPPORT;
968       ret->setMesh(_mesh);
969       ret->setEntity(_entity);
970       return ret;
971     }
972   if(_isOnAllElts)
973     return other.getComplement();
974   int nbOfEltInThis=getNumberOfElements(MED_EN::MED_ALL_ELEMENTS);
975   const int *nbsThis=_number->getValue();
976   int nbOfEltInOther=other.getNumberOfElements(MED_EN::MED_ALL_ELEMENTS);
977   const int *nbsOther=other._number->getValue();
978   list<int> *ids=sub(nbsThis,nbOfEltInThis,nbsOther,nbOfEltInOther);
979   if(_entity==MED_EN::MED_NODE)
980     ret=_mesh->buildSupportOnNodeFromElementList(*ids,_entity);
981   else
982     ret=_mesh->buildSupportOnElementsFromElementList(*ids,_entity);
983   delete ids;
984   return ret;
985   END_OF(LOC);
986 }
987
988 /*!
989   returns a new support the user has to delete. Entity is either MED_NODE to obtain node elements lying on boundary of "this"
990   or MED_FACE,MED_EDGE (depends on the this->_mesh dimension).
991  */
992 SUPPORT *MEDMEM::SUPPORT::getBoundaryElements(MED_EN::medEntityMesh Entity) const throw (MEDEXCEPTION)
993 {
994   const char * LOC = "SUPPORT *MEDMEM::SUPPORT::getBoundaryElements(MED_EN::medEntityMesh Entity) : ";
995   BEGIN_OF(LOC);
996   int spaceDimension=_mesh->getSpaceDimension();
997   MED_EN::medEntityMesh baseEntity=Entity;
998   if (spaceDimension == 3)
999     if (Entity!=MED_FACE)
1000       if(Entity==MED_NODE)
1001         baseEntity=MED_FACE;
1002       else
1003         throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Not defined in 3D mesh for entity "<<Entity<<" !"));
1004   if (spaceDimension == 2)
1005     if (Entity!=MED_EDGE)
1006       if(Entity==MED_NODE)
1007         baseEntity=MED_EDGE;
1008       else
1009         throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Not defined in 2D mesh for entity "<<Entity<<" !"));
1010   if(_isOnAllElts)
1011     return _mesh->getBoundaryElements(Entity);
1012
1013   const int * myConnectivityValue=_mesh->getReverseConnectivity(MED_DESCENDING);
1014   const int * myConnectivityIndex=_mesh->getReverseConnectivityIndex(MED_DESCENDING);
1015   int numberOf=_mesh->getNumberOfElements(baseEntity,MED_ALL_ELEMENTS);
1016   const int *ids=_number->getValue();
1017   set<int> idsSet(ids,ids+_totalNumberOfElements);
1018   list<int> myElementsList;
1019   for (int i=0;i<numberOf;i++)
1020     {
1021       int nbOfDP1EntitySharing=0;
1022       if(idsSet.find(myConnectivityValue[myConnectivityIndex[i]-1])!=idsSet.end())
1023         nbOfDP1EntitySharing++;
1024       if(idsSet.find(myConnectivityValue[myConnectivityIndex[i]])!=idsSet.end())
1025         nbOfDP1EntitySharing++;
1026       if(nbOfDP1EntitySharing==1)
1027         myElementsList.push_back(i+1);
1028     }
1029   if(Entity==MED_NODE)
1030     {
1031       return _mesh->buildSupportOnNodeFromElementList(myElementsList,baseEntity);
1032     }
1033   else
1034     {
1035       return _mesh->buildSupportOnElementsFromElementList(myElementsList,baseEntity);
1036     }
1037 }
1038
1039 /*!
1040   Method that fills this and updates all its attributes in order to lye on the the listOfNode.
1041  */
1042 void MEDMEM::SUPPORT::fillFromNodeList(const list<int>& listOfNode) throw (MEDEXCEPTION)
1043 {
1044   setEntity(MED_EN::MED_NODE);
1045   clearDataOnNumbers();
1046   int size=listOfNode.size();
1047   int totalNbInMesh=_mesh->getNumberOfElements(_entity,MED_ALL_ELEMENTS);
1048   if(totalNbInMesh==size)
1049     {
1050     _isOnAllElts=true;
1051     update();
1052     return;
1053     }
1054   else
1055     _isOnAllElts=false;
1056   int numberOfGeometricType=1;
1057   medGeometryElement* geometricType=new medGeometryElement[1];
1058   geometricType[0]=MED_NONE;
1059   int *numberOfElements=new int[1];
1060   numberOfElements[0]=size;
1061   int *mySkyLineArrayIndex=new int[2];
1062   mySkyLineArrayIndex[0]=1;
1063   mySkyLineArrayIndex[1]=1+numberOfElements[0];
1064   int *tab=new int[numberOfElements[0]];
1065   int i=0;
1066   for(list<int>::const_iterator iter2=listOfNode.begin();iter2!=listOfNode.end();iter2++)
1067     tab[i++]=*iter2;
1068   MEDSKYLINEARRAY * mySkyLineArray = new MEDSKYLINEARRAY(1,numberOfElements[0],mySkyLineArrayIndex,tab,true);
1069   setNumberOfGeometricType(numberOfGeometricType);
1070   setGeometricType(geometricType);
1071   setNumberOfElements(numberOfElements);
1072   setTotalNumberOfElements(numberOfElements[0]);
1073   setNumber(mySkyLineArray);
1074
1075   delete[] numberOfElements;
1076   delete[] geometricType;
1077 }
1078
1079 /*
1080   Method created to factorize code. This method fills the current SUPPORT on entity 'entity' containing all the entities contained in
1081   elements 'listOfElt' of entity 'entity'. Warning this method should be called after both the attributes this->_mesh and this->_entity are correctly set.
1082  */
1083 void MEDMEM::SUPPORT::fillFromElementList(const list<int>& listOfElt) throw (MEDEXCEPTION)
1084 {
1085   clearDataOnNumbers();
1086   int size=listOfElt.size();
1087   int totalNbInMesh=_mesh->getNumberOfElementsWithPoly(_entity,MED_ALL_ELEMENTS);
1088   if(totalNbInMesh==size){
1089     _isOnAllElts=true;
1090     update();
1091     return;
1092   }
1093   else
1094   _isOnAllElts=false;
1095   // Well, we must know how many geometric type we have found
1096   int * myListArray = new int[size] ;
1097   int id = 0 ;
1098   list<int>::const_iterator myElementsListIt ;
1099   for (myElementsListIt=listOfElt.begin();myElementsListIt!=listOfElt.end();myElementsListIt++)
1100     myListArray[id++]=(*myElementsListIt) ;
1101   int numberOfGeometricType ;
1102   medGeometryElement* geometricType ;
1103   int * numberOfElements ;
1104   int * mySkyLineArrayIndex ;
1105
1106   int numberOfType = _mesh->getNumberOfTypesWithPoly(_entity) ;
1107   if (numberOfType == 1) {
1108     numberOfGeometricType = 1 ;
1109     geometricType = new medGeometryElement[1] ;
1110     medGeometryElement *  allType = _mesh->getTypesWithPoly(_entity);
1111     geometricType[0] = allType[0] ;
1112     numberOfElements = new int[1] ;
1113     numberOfElements[0] = size ;
1114     mySkyLineArrayIndex = new int[2] ;
1115     mySkyLineArrayIndex[0]=1 ;
1116     mySkyLineArrayIndex[1]=1+size ;
1117     delete [] allType;
1118   }
1119   else {// hemmm
1120     map<medGeometryElement,int> theType ;
1121     for (myElementsListIt=listOfElt.begin();myElementsListIt!=listOfElt.end();myElementsListIt++) {
1122       medGeometryElement myType = _mesh->getElementTypeWithPoly(_entity,*myElementsListIt) ;
1123       if (theType.find(myType) != theType.end() )
1124         theType[myType]+=1 ;
1125       else
1126         theType[myType]=1 ;
1127     }
1128     numberOfGeometricType = theType.size() ;
1129     geometricType = new medGeometryElement[numberOfGeometricType] ;
1130     numberOfElements = new int[numberOfGeometricType] ;
1131     mySkyLineArrayIndex = new int[numberOfGeometricType+1] ;
1132     int index = 0 ;
1133     mySkyLineArrayIndex[0]=1 ;
1134     map<medGeometryElement,int>::iterator theTypeIt ;
1135     for (theTypeIt=theType.begin();theTypeIt!=theType.end();theTypeIt++) {
1136       geometricType[index] = (*theTypeIt).first ;
1137       numberOfElements[index] = (*theTypeIt).second ;
1138       mySkyLineArrayIndex[index+1]=mySkyLineArrayIndex[index]+numberOfElements[index] ;
1139       index++ ;
1140     }
1141   }
1142   MEDSKYLINEARRAY * mySkyLineArray = new MEDSKYLINEARRAY(numberOfGeometricType,size,mySkyLineArrayIndex,myListArray,true) ;
1143   setNumberOfGeometricType(numberOfGeometricType) ;
1144   setGeometricType(geometricType) ;
1145    setNumberOfElements(numberOfElements) ;
1146   setTotalNumberOfElements(size) ;
1147   setNumber(mySkyLineArray) ;
1148
1149   delete[] numberOfElements;
1150   delete[] geometricType;
1151 }
1152
1153 /*! set the reference _mesh to Mesh */
1154 //--------------------------------------
1155 void SUPPORT::setMesh(MESH *Mesh) const
1156 //--------------------------------------
1157 {
1158   if(_mesh)
1159     _mesh->removeReference();
1160   _mesh=Mesh;
1161   _meshName = "";
1162   if(_mesh)
1163     _mesh->addReference();
1164 }
1165
1166 /*! returns the mesh name  */
1167 //------------------------------------
1168 string SUPPORT::getMeshName() const
1169 //------------------------------------
1170 {
1171   if (_mesh)
1172     return _mesh->getName();
1173   else
1174     return _meshName;
1175 }
1176
1177 /*!
1178   addReference : reference counter presently disconnected in C++ -> just connected for client.
1179 */
1180 void MEDMEM::SUPPORT::addReference() const
1181 {
1182 }
1183
1184 /*!
1185   removeReference : reference counter presently disconnected in C++ -> just connected for client.
1186 */
1187 void MEDMEM::SUPPORT::removeReference() const
1188 {
1189 }