]> SALOME platform Git repositories - modules/med.git/blob - src/MEDMEM/MEDMEM_DriverTools.cxx
Salome HOME
update from the MedMemory V1.0.1
[modules/med.git] / src / MEDMEM / MEDMEM_DriverTools.cxx
1 using namespace std;
2 #include "MEDMEM_DriverTools.hxx"
3 #include "MEDMEM_STRING.hxx"
4 #include "MEDMEM_Exception.hxx"
5 #include "MEDMEM_Mesh.hxx"
6 #include "MEDMEM_Group.hxx"
7 #include <algorithm>
8
9
10 // Cet opérateur permet d'ordonner les mailles dans un set suivant l'ordre requis par MED
11 bool _maille::operator < (const _maille& ma) const
12 {
13     // si le type géométrique differe, la comparaison est basée dessus
14     // sinon on se base sur une comparaison des numéros de sommets 
15     if(geometricType==ma.geometricType)
16     {
17         // construction de deux vecteur temporaire contenant les numeros de sommets
18         // pour faire le tri et les comparaisons
19         size_t l=sommets.size();
20         std::vector<int> v1(l);
21         std::vector<int> v2(l);
22         for (unsigned int i=0; i!=l; ++i)
23           {
24             v1[i]=sommets[i]->second.number;
25             v2[i]=ma.sommets[i]->second.number;
26           }
27         std::sort(v1.begin(), v1.end());
28         std::sort(v2.begin(), v2.end());
29         for(std::vector<int>::const_iterator i1=v1.begin(), i2=v2.begin(); i1!=v1.end(); ++i1, ++i2)
30             if(*i1 != *i2)
31                 return *i1 < *i2;
32         return false; // cas d'égalité
33     }
34     else
35         return geometricType<ma.geometricType;
36 };
37
38
39 // retourne l'entité d'une maille en fonction de la dimension du maillage.
40 MED_EN::medEntityMesh _maille::getEntity(const int meshDimension) const throw (MEDEXCEPTION)
41 {
42   const char * LOC = "_maille::getEntity(const int meshDimension)" ;
43   BEGIN_OF(LOC);
44
45   int mailleDimension = this->dimension();
46   medEntityMesh entity;
47   if (mailleDimension == meshDimension)
48     entity = MED_CELL;
49   else
50     switch (mailleDimension)
51       {
52       case 0 :
53         entity = MED_NODE;
54         break;
55       case 1 :
56         entity = MED_EDGE;
57         break;
58       case 2 :
59         entity = MED_FACE;
60         break;
61       default :
62         throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "Impossible de determiner l'entite de la maille."));
63       }
64 return entity;
65
66 END_OF(LOC);
67 };
68
69 std::ostream& operator << (std::ostream& os, const _maille& ma)
70 {
71     os << "maille " << ma.ordre << " (" << ma.geometricType << ") : < ";
72     std::vector< std::map<int,_noeud>::iterator >::const_iterator i=ma.sommets.begin();
73     os << (*i++)->second.number ;
74     for( ; i!=ma.sommets.end(); ++i)
75         os << ", " << (*i)->second.number;
76     os << " >";
77     return os;
78 }
79
80 std::ostream& operator << (std::ostream& os, const _groupe& gr)
81 {
82     os << "--- Groupe " << gr.nom << " --- " << std::endl ;
83     os << " -> liste des sous-groupes : ";
84     for( std::list<int>::const_iterator i=gr.groupes.begin(); i!=gr.groupes.end(); ++i)
85         os << *i << " ";
86     os << std::endl << " -> liste des mailles : " << std::endl;
87     for( _groupe::mailleIter i=gr.mailles.begin(); i!=gr.mailles.end(); i++)
88         os << "    " << *(*i) << std::endl;
89     return os;
90 }
91
92 std::ostream& operator << (std::ostream& os, const _noeud& no)
93 {
94     os << "noeud " << no.number << " : < ";
95     std::vector<double>::const_iterator i=no.coord.begin();
96     os << *i++ ;
97     for( ; i!=no.coord.end(); ++i)
98         os << ", " << *i;
99     os << " >";
100     return os;
101 }
102
103 std::ostream& operator << (std::ostream& os, const _intermediateMED& mi)
104 {
105     os << "Set des mailles : " << std::endl;
106     for( std::set<_maille>::const_iterator i=mi.maillage.begin(); i!=mi.maillage.end(); ++i)
107         os << *i << std::endl;
108     
109     os << std::endl << "Vector des groupes : " << std::endl;
110    // for( std::vector<_groupe>::const_iterator i=mi.groupes.begin(); i!=mi.groupes.end(); ++i)
111     for (unsigned int i=0; i!=mi.groupes.size(); i++)
112       os << std::setw(3) << i << " " << mi.groupes[i] << std::endl;
113     
114     os << std::endl << "map des noeuds : " << std::endl;
115     for( std::map<int,_noeud>::const_iterator i=mi.points.begin(); i!=mi.points.end(); ++i)
116         os << i->second << std::endl;
117     return os;
118 }
119
120 void _intermediateMED::numerotationMaillage()
121 {
122     // numerotation des mailles par entité
123     int i_maille=0;
124     std::set<_maille>::iterator i=maillage.begin();
125     int dimension=i->dimension();
126     for( ; i!=maillage.end(); ++i)
127     {
128         if ( dimension!=i->dimension() ) // on change d'entite
129         {
130             dimension=i->dimension();
131             i_maille=0;
132         }
133         (*i).ordre=++i_maille;
134     }
135 }
136
137 void _intermediateMED::numerotationPoints()
138 {
139     // Fonction de renumerotation des noeuds (necessaire quand il y a des trous dans la numerotation.
140     int i_noeud=0;
141     for( std::map<int,_noeud>::const_iterator i=points.begin(); i!=points.end(); ++i)
142         i->second.number = ++i_noeud ;
143 }
144     
145
146 /*!
147  * \if developper
148  * create a MED COORDINATE from the intermediate structure.
149  * \endif
150  */
151 COORDINATE *
152 _intermediateMED::getCoordinate()
153 {
154     const medModeSwitch mode=MED_FULL_INTERLACE;
155     const string coordinateSystem="CARTESIAN";
156
157     int spaceDimension=points.begin()->second.coord.size();
158     int numberOfNodes=points.size();
159
160
161     // creation du tableau des coordonnees en mode MED_FULL_INTERLACE
162     double * coord = new double[spaceDimension*numberOfNodes];
163     int k=0;
164     for( std::map<int,_noeud>::const_iterator i=points.begin(); i!=points.end(); ++i, ++k)
165         std::copy(i->second.coord.begin(), i->second.coord.end(), coord+k*spaceDimension);
166
167     // creation de l'objet COORDINATE
168     COORDINATE * coordinate = new COORDINATE(spaceDimension, numberOfNodes, mode);
169     coordinate->setCoordinates(mode,coord);
170     delete [] coord;
171     coordinate->setCoordinatesSystem(coordinateSystem);
172     return coordinate;
173 }
174
175
176   /*!
177    * \if developper
178    * create a MED CONNECTIVITY from the intermediate structure.
179    * for memory optimisation, clear the intermediate structure (the "maillage" set )
180    * \endif
181    */
182 CONNECTIVITY * 
183 _intermediateMED::getConnectivity()
184 {
185     const char * LOC = "_intermediateMED::getConnectivity() : ";
186     BEGIN_OF(LOC);
187     int numberOfNodes=points.size(); // number of nodes in the mesh
188     int numberOfTypes=0;
189     medEntityMesh entity;
190     medGeometryElement * types=NULL; // pointeurs pour allouer les structures MED
191     int * count=NULL;
192     int * connectivity=NULL;
193     CONNECTIVITY *Connectivity, *Constituent;
194
195     medGeometryElement type=0; // variables de travail
196     int nbtype=0;
197     int dimension=0;
198     bool first = true;
199
200     std::vector<medGeometryElement> vtype; // tableau de travail : stockage des types geometriques pour UNE entite
201     std::vector<int> vcount; // tableau de travail : nombre d'elements pour chaque type geometrique de vtype
202
203     std::set<_maille>::const_iterator i=maillage.begin(); // iterateurs sur les mailles
204     std::set<_maille>::const_iterator j=maillage.begin();
205
206     // renumerote les points de 1 a n (pour le cas ou certains points ne sont pas presents dans le maillage d'origine) 
207     numerotationPoints(); 
208
209     do 
210     {
211         // boucle sur les entites de la structure maillage :
212         //   - on parcourt une premiere fois avec i les mailles d'une entite pour récupérer 
213         //     des infos sur les types geometriques, leur nombre et le nombre d'elements.
214         //   - on alloue la connectivite
215         //   - on parcourt une deuxieme fois avec j pour lire les noeuds.
216
217
218         type=i->geometricType; // init boucle for
219         dimension=i->dimension();
220         nbtype=0;
221         vtype.push_back(type);
222         // Boucle sur i de parcours des mailles d'une entite
223         // Une entite se termine lorsqu'on atteint la fin de maillage ou lorsque la dimension des mailles change
224         for( ; i!=maillage.end() && dimension==i->dimension() ; ++i)
225         {
226             if (type != i->geometricType) // si changement de type geometrique
227             {
228                 vcount.push_back(nbtype); // stocke le nombre d'elements de type nbtype
229                 nbtype=0;
230                 type=i->geometricType;
231                 vtype.push_back(type); // stocke le nouveau type geometrique rencontre
232             }
233
234             ++nbtype;
235         }
236         vcount.push_back(nbtype); // n'a pas été stocké dans la boucle
237
238         
239         // Pour l'entite qu'on vient de parcourir, allocation des tableau et creation de la connectivite
240 //      cout << "Dimension = " << dimension << endl;
241 //      cout << "Nombre de type geometriques : " << vtype.size() << endl;
242 //      for (unsigned k=0; k!=vtype.size(); ++k )
243 //          cout << "  -> " << vtype[k] << " : " << vcount[k] << endl;
244
245         numberOfTypes=vtype.size(); // nombre de types de l'entite
246         
247         if ( i==maillage.end() ) // cas de l'entite de plus haut niveau
248             entity=MED_CELL;
249         else if (dimension==2 )
250             entity=MED_FACE;
251         else if (dimension==1 )
252             entity=MED_EDGE;
253         else if (dimension==0 )
254             entity=MED_NODE;
255
256         Connectivity = new CONNECTIVITY(numberOfTypes,entity);
257         Connectivity->setEntityDimension(dimension);
258         Connectivity->setNumberOfNodes(numberOfNodes);
259         
260         types = new medGeometryElement[numberOfTypes];
261         std::copy(vtype.begin(),vtype.end(),types);
262         Connectivity->setGeometricTypes(types,entity);
263         delete [] types;
264
265         count = new int[numberOfTypes+1];
266         count[0]=1;
267         for (unsigned int k=0; k!=vcount.size(); ++k )
268           count[k+1]=count[k]+vcount[k];
269         Connectivity->setCount (count, entity);
270         delete [] count;
271
272         for (int k=0; k!=numberOfTypes; ++k )
273           {
274             // pour chaque type geometrique k, copie des sommets dans connectivity et set dans Connectivity
275             int nbSommetsParMaille = j->sommets.size();
276             int nbSommets = vcount[k] * j->sommets.size();
277             connectivity = new int[ nbSommets ];
278             for (int l=0; l!=vcount[k]; ++l, ++j)
279             {
280                 for ( unsigned n=0; n != j->sommets.size(); ++n)
281                     connectivity[nbSommetsParMaille*l+n] = j->sommets[n]->second.number;
282                 maillage.erase(j);    ; // dangereux, mais optimise la mémoire consommée!
283             }
284
285             Connectivity->setNodal  (connectivity, entity, vtype[k]);
286             delete [] connectivity;
287           }
288                 
289         if (i!=j)
290             throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "Erreur de lecture des mailles ."));
291
292         if ( ! first)
293             Connectivity->setConstituent (Constituent);
294         else
295             first = false;
296         Constituent = Connectivity; // stocke Connectivity pour utilisation dans setConstituent lors de la boucle suivante
297
298         vtype.clear();
299         vcount.clear();
300
301     }
302     while ( i != maillage.end() );
303
304     END_OF(LOC);
305     return Connectivity;
306 }
307
308
309   /*!
310    * \if developper
311    * fill the arguments vector of groups from the intermediate structure.
312    * This function must be called before getConnectivity()
313    * \endif
314    */
315 void
316 _intermediateMED::getGroups(std::vector<GROUP *> & _groupCell, std::vector<GROUP *> & _groupFace, std::vector<GROUP *> & _groupEdge, std::vector<GROUP *> & _groupNode, MESH * _ptrMesh)
317 {
318     const char * LOC = "_intermediateMED::getGroups() : ";
319     BEGIN_OF(LOC);
320     if (maillage.size() == 0)
321         throw MEDEXCEPTION(LOCALIZED(STRING(LOC) << "Erreur : il n'y a plus de mailles (appeler getConnectivity apres getGroups!)."));
322
323     int dimension_maillage=maillage.rbegin()->dimension();
324
325     numerotationMaillage(); // Renumerotation des mailles par entite
326
327     for (unsigned int i=0; i!=this->groupes.size(); ++i)
328     {
329         if (groupes[i].mailles.size()==0)
330             continue; // si le groupe est vide, on passe au suivant
331
332         int nb_geometric_types=1;
333         _groupe::mailleIter j=groupes[i].mailles.begin(); 
334         // initialise groupe_entity a l'entite de la premiere maille du groupe
335         medEntityMesh groupe_entity = (**j).getEntity(dimension_maillage);
336         medGeometryElement geometrictype=(**j).geometricType;
337
338         //Parcours des mailles (a partir de la deuxieme) pour compter les types geometriques
339         for ( ++j ; j!=groupes[i].mailles.end(); ++j )
340         {
341             //Compte nombre de types geometriques
342             if ( (**j).geometricType != geometrictype ) // si on change de type geometrique
343             {
344                 nb_geometric_types++;
345                 geometrictype=(**j).geometricType;
346             }
347
348             //Test si groupe valide : le groupe doit pointer vers des entites de meme dimension
349             if ((**j).dimension() != dimension_maillage)
350                 continue;
351         }
352
353         // le groupe est valide -> on le traite
354         MED_EN::medGeometryElement * tab_types_geometriques = new MED_EN::medGeometryElement[nb_geometric_types];
355         int * tab_index_types_geometriques = new int[nb_geometric_types+1];
356         int * tab_numeros_elements = new int[groupes[i].mailles.size()];
357         int * tab_nombres_elements = new int[nb_geometric_types];
358
359         //Remplit tableaux entree des methodes set
360         int indice_mailles=0;
361         j=groupes[i].mailles.begin();
362         geometrictype=(**j).geometricType;
363         tab_index_types_geometriques[0]=1;
364         int indice_types_geometriques=1;
365         tab_types_geometriques[0]=geometrictype;
366         //parcours des mailles du groupe
367         for (  ; j!=groupes[i].mailles.end(); ++j , ++indice_mailles)
368         {
369             tab_numeros_elements[indice_mailles]=((**j).ordre);
370             if ((**j).geometricType != geometrictype)
371             {
372                 tab_index_types_geometriques[indice_types_geometriques]=indice_mailles+1;
373                 geometrictype=(**j).geometricType;
374                 tab_types_geometriques[indice_types_geometriques]=geometrictype;
375                 ++indice_types_geometriques;
376             }
377         }
378         tab_index_types_geometriques[indice_types_geometriques]=indice_mailles+1;
379         for (int k=0; k != nb_geometric_types; ++k)
380         {
381             tab_nombres_elements[k] = tab_index_types_geometriques[k+1]-tab_index_types_geometriques[k];
382         }
383
384         //Determination type entite du groupe
385         vector <GROUP *> * vect_group;
386         switch ( groupe_entity )
387         {
388             case MED_CELL :
389                 vect_group= & _groupCell;
390                 break;
391             case MED_FACE :
392                 vect_group= & _groupFace;
393                 break;
394             case MED_EDGE :
395                 vect_group= & _groupEdge;
396                 break;
397             case MED_NODE :
398                 vect_group= & _groupNode;
399                 break;
400         }
401         //Creation nouveau groupe MED
402         GROUP * new_group = new GROUP();
403         //Appel methodes set
404         new_group->setTotalNumberOfElements(groupes[i].mailles.size());
405         new_group->setName(groupes[i].nom);
406         new_group->setMesh(_ptrMesh);
407         new_group->setNumberOfGeometricType(nb_geometric_types);
408         new_group->setGeometricType(tab_types_geometriques);
409         new_group->setNumberOfElements(tab_nombres_elements);
410         new_group->setNumber(tab_index_types_geometriques,tab_numeros_elements);
411         new_group->setEntity(groupe_entity);
412         new_group->setAll(groupes[i].mailles.size() == maillage.size());
413         vect_group->push_back(new_group);
414         delete [] tab_types_geometriques;
415         delete [] tab_index_types_geometriques;
416         delete [] tab_numeros_elements;
417         delete [] tab_nombres_elements;
418     }
419
420     END_OF(LOC);
421 }
422
423 /////