Salome HOME
226267e4b71ec8563e5185913e7fa212ad1a53fa
[modules/multipr.git] / src / MULTIPR / MULTIPR_Elements.cxx
1 // Project MULTIPR, IOLS WP1.2.1 - EDF/CS
2 // Partitioning/decimation module for the SALOME v3.2 platform
3
4 /**
5  * \file    MULTIPR_Elements.cxx
6  *
7  * \brief   see MULTIPR_Elements.hxx
8  *
9  * \author  Olivier LE ROUX - CS, Virtual Reality Dpt
10  * 
11  * \date    01/2007
12  */
13
14 //*****************************************************************************
15 // Includes section
16 //*****************************************************************************
17
18 #include "MULTIPR_Elements.hxx"
19 #include "MULTIPR_Nodes.hxx"
20 #include "MULTIPR_Exceptions.hxx"
21
22 #include <iostream>
23 #include <set>
24 #include <map>
25
26 using namespace std;
27
28
29 namespace multipr
30 {
31
32
33 //*****************************************************************************
34 // Class Elements implementation
35 //*****************************************************************************
36
37 Elements::Elements() 
38 {
39         mId       = NULL;
40         mFamIdent = NULL;
41         mNames    = NULL;
42         mCon      = NULL;
43         
44         reset(); 
45 }
46
47
48 Elements::~Elements()  
49
50         reset();  
51 }
52
53
54 void Elements::reset() 
55
56         mNum           = 0;
57         mEntity        = MED_MAILLE;
58         mGeom          = MED_NONE;
59         mNumNodesByElt = 0;
60         mDim           = 0;
61         
62         if (mId != NULL)       { delete[] mId;       mId       = NULL; }
63         if (mFamIdent != NULL) { delete[] mFamIdent; mFamIdent = NULL; }
64         if (mNames != NULL)    { delete[] mNames;    mNames    = NULL; }
65         if (mCon != NULL)      { delete[] mCon;      mCon      = NULL; }
66
67         mSetOfNodes.clear();
68         
69         mFlagPrintAll = false;
70 }
71
72
73 med_int Elements::getFamilyIdentifier(med_int pIndex) const 
74
75         if ((pIndex < 0) || (pIndex >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__);
76         
77         return mFamIdent[pIndex]; 
78 }
79
80
81 const med_int* Elements::getConnectivity(int pIndex) const
82 {
83         if ((pIndex < 0) || (pIndex >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__);
84         
85         return mCon + mNumNodesByElt * pIndex;
86 }
87
88
89 void Elements::getCoordinates(med_int pIndexElt, const Nodes* pNodes, med_float* pCoo, int pFirst) const
90 {
91         if ((pIndexElt < 0) || (pIndexElt >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__);
92         if (pNodes == NULL) throw NullArgumentException("", __FILE__, __LINE__);
93         if (pCoo == NULL) throw NullArgumentException("", __FILE__, __LINE__);
94         
95         // get the list of nodes of the element
96         const med_int* con = getConnectivity(pIndexElt);
97         
98         med_float* destCoo = pCoo;
99         int size = sizeof(med_float) * mDim;
100         
101         // for each node of the element
102         int n = (mNumNodesByElt < pFirst) ? mNumNodesByElt : pFirst;
103         for (int i = 0 ; i < n ; i++)
104         {
105                 // get index of node (MED index start at 1)
106                 med_int indexNode = con[i] - 1;
107                 
108                 // get coordinates of this node
109                 const med_float* srcCoo = pNodes->getCoordinates(indexNode);
110                 
111                 // copy coordinates to destCoo
112                 memcpy(destCoo, srcCoo, size);
113                 
114                 // prepare next point
115                 destCoo += mDim;
116         }
117 }
118
119
120 Elements* Elements::extractSubSet(const set<med_int>& pSetIndices) const
121 {
122         Elements* subset = new Elements();
123         
124         //---------------------------------------------------------------------
125         // Copy parameters
126         //---------------------------------------------------------------------
127         subset->mNum           = pSetIndices.size();
128         subset->mEntity        = mEntity;
129         subset->mGeom          = mGeom;          // e.g. 310 for a TETRA10
130         subset->mNumNodesByElt = mNumNodesByElt; // e.g. 10 for a TETRA10
131         subset->mDim           = mDim;           // e.g. 3 for a TETRA10
132         
133         //---------------------------------------------------------------------
134         // Allocate arrays
135         //---------------------------------------------------------------------
136         subset->mFamIdent     = new med_int[subset->mNum];
137         subset->mCon          = new med_int[mNumNodesByElt * subset->mNum];
138         
139         //---------------------------------------------------------------------
140         // Copy subset of familys id and connectivity.
141         //---------------------------------------------------------------------
142         med_int* destCon = subset->mCon;
143         set<med_int>::iterator itSet = pSetIndices.begin();
144         for (int itElt = 0 ; itElt < subset->mNum; itElt++)
145         {
146                 med_int srcIndex = (*itSet) - 1; // MED index start at 1
147                 subset->mFamIdent[itElt] = mFamIdent[srcIndex];
148                 
149                 med_int* srcCon = mCon + srcIndex * mNumNodesByElt;
150                 memcpy(destCon, srcCon, sizeof(med_int) * mNumNodesByElt);
151                 
152                 destCon += mNumNodesByElt;
153                 itSet++;
154         }
155         
156         //---------------------------------------------------------------------
157         // Copy subset of identifiers if necessary
158         //---------------------------------------------------------------------
159         if (isIdentifiers())  
160         { 
161                 itSet = pSetIndices.begin();
162                 subset->mId = new med_int[subset->mNum]; 
163                 for (int itElt = 0 ; itElt < subset->mNum; itElt++)
164                 {
165                         med_int srcIndex = (*itSet) - 1; // MED index start at 1
166                         subset->mId[itElt] = mId[srcIndex];
167                         
168                         itSet++;
169                 }
170         }
171         
172         //---------------------------------------------------------------------
173         // Copy subset of names if necessary
174         //---------------------------------------------------------------------
175         if (isNames())       
176         { 
177                 itSet = pSetIndices.begin();
178                 subset->mNames = new char[MED_TAILLE_PNOM * subset->mNum + 1]; 
179                 char* destPtr = subset->mNames;
180                 for (int itElt = 0 ; itElt < subset->mNum; itElt++)
181                 {
182                         med_int srcIndex = (*itSet) - 1; // MED index start at 1
183                         char* srcPtr = mNames + srcIndex * MED_TAILLE_PNOM;
184                         memcpy(destPtr, srcPtr, MED_TAILLE_PNOM);
185                         
186                         destPtr += MED_TAILLE_PNOM;
187                         itSet++;
188                 }
189                 subset->mNames[MED_TAILLE_PNOM * subset->mNum] = '\0';
190         }
191         
192         return subset;
193 }
194
195
196 const set<med_int>& Elements::getSetOfNodes()
197 {       
198         // lazy get: test if mSetOfNodes has already been built
199         if (mSetOfNodes.size() == 0)
200         {
201                 buildSetOfNodes();
202         }
203         
204         return mSetOfNodes;
205 }
206
207
208 set<med_int> Elements::getSetOfFamilies() const
209 {
210         // set of families is empty at the beginning
211         set<med_int> setOfFamilies;
212         
213         // for each element, add its family to the set
214         for (int itElt = 0 ; itElt < mNum ; itElt++)
215         {
216                 setOfFamilies.insert(mFamIdent[itElt]);
217         }
218         
219         return setOfFamilies;
220 }
221
222
223 void Elements::remap()
224 {
225         // build set of nodes if necessary
226         if (mSetOfNodes.size() == 0)
227         {
228                 buildSetOfNodes();
229         }
230         
231         // build the map for indices convertion
232         map<med_int, med_int> mapOldIndexToNewIndex;
233         med_int newIndex = 1; // MED index start at 1
234         for (set<med_int>::iterator itSet = mSetOfNodes.begin(); itSet != mSetOfNodes.end() ; itSet++)
235         {
236                 med_int oldIndex = (*itSet);
237                 mapOldIndexToNewIndex.insert(make_pair(oldIndex, newIndex));
238                 newIndex++;
239         }
240         
241         // for each node referenced by this set of elements
242         for (int itNode = 0, size = mNum * mNumNodesByElt ; itNode < size ; itNode++)
243         {
244                 // convert old index to new index (remap)
245                 mCon[itNode] = mapOldIndexToNewIndex[mCon[itNode]];
246         }
247         
248         buildSetOfNodes();
249 }
250
251
252 void Elements::buildSetOfNodes()
253 {
254         if (mSetOfNodes.size() != 0)
255         {
256                 mSetOfNodes.clear();
257         }
258         
259         // for each node referenced by this set of elements
260         for (int itNode = 0, size = mNum * mNumNodesByElt ; itNode < size ; itNode++)
261         {
262                 // add the node to the set
263                 mSetOfNodes.insert(mCon[itNode]);
264         }
265 }
266
267
268 void Elements::readMED(
269         med_idt               pMEDfile, 
270         char*                 pMeshName, 
271         med_int               pMeshDim, 
272         med_entite_maillage   pEntity, 
273         med_geometrie_element pGeom)
274 {
275         if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__);
276         if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
277         if ((pMeshDim < 1) || (pMeshDim > 3)) throw IllegalArgumentException("", __FILE__, __LINE__);
278         
279         reset();
280         
281         mEntity        = pEntity;
282         mGeom          = pGeom;
283         mNumNodesByElt = mGeom % 100;
284         mDim           = mGeom / 100;
285         
286         mNum = MEDnEntMaa(
287                 pMEDfile, 
288                 pMeshName, 
289                 MED_CONN,  // type of information requested = CONNECTIVITY
290                 pEntity, 
291                 pGeom, 
292                 MED_NOD);  // nodal connectivity
293         
294         if (mNum < 0) throw IOException("i/o error while reading information about elements in MED file", __FILE__, __LINE__);
295         
296         mCon      = new med_int[mNumNodesByElt * mNum];
297         mNames    = new char[MED_TAILLE_PNOM * mNum + 1];
298         mId       = new med_int[mNum];
299         mFamIdent = new med_int[mNum]; 
300         med_booleen isNames;
301         med_booleen isIdentifiers;
302         
303         med_err ret = MEDelementsLire(
304                 pMEDfile, 
305                 pMeshName, 
306                 pMeshDim, 
307                 mCon, 
308                 MED_FULL_INTERLACE,
309                 mNames, 
310                 &isNames,
311                 mId,
312                 &isIdentifiers,
313                 mFamIdent,
314                 mNum, 
315                 mEntity, 
316                 mGeom, 
317                 MED_NOD); // NODAL CONNECTIVITY
318         
319         if (ret != 0) throw IOException("i/o error while reading elements in MED file", __FILE__, __LINE__);
320         
321         if (!isNames)
322         {
323                 delete[] mNames;
324                 mNames = NULL;
325         }
326         
327         if (!isIdentifiers)
328         {
329                 delete[] mId;
330                 mId = NULL;
331         }
332 }
333
334
335 void Elements::writeMED(med_idt pMEDfile, char* pMeshName, med_int pMeshDim)
336 {
337         if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__);
338         if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
339         if (strlen(pMeshName) > MED_TAILLE_NOM) throw IllegalArgumentException("", __FILE__, __LINE__);
340         if ((pMeshDim < 1) || (pMeshDim > 3)) throw IllegalArgumentException("", __FILE__, __LINE__);
341         
342         // special case: if no elements => do nothing
343         if (mNum == 0) return;
344         
345         med_err ret = MEDelementsEcr(
346                 pMEDfile,
347                 pMeshName,
348                 pMeshDim,
349                 mCon,
350                 MED_FULL_INTERLACE,
351                 mNames,
352                 isNames()?MED_VRAI:MED_FAUX,
353                 mId,
354                 isIdentifiers()?MED_VRAI:MED_FAUX,
355                 mFamIdent,
356                 mNum,
357                 mEntity,
358                 mGeom,
359                 MED_NOD); // NODAL CONNECTIVITY
360                 
361         if (ret != 0) throw IOException("i/o error while writing elements in MED file", __FILE__, __LINE__);
362 }
363
364
365 ostream& operator<<(ostream& pOs, Elements& pE)
366 {
367         char strEntity[16];
368         switch (pE.mEntity) 
369         {
370                 case MED_MAILLE: strcpy(strEntity, "MED_MAILLE"); break;
371                 case MED_FACE:   strcpy(strEntity, "MED_FACE"); break;
372                 case MED_ARETE:  strcpy(strEntity, "MED_ARETE"); break;
373                 case MED_NOEUD:  strcpy(strEntity, "MED_NOEUD"); break;
374                 default:         strcpy(strEntity, "UNKNOWN"); break;
375         }
376         
377         pOs << "Elements: " << endl;
378         pOs << "    #number  =" << pE.mNum << endl;
379         pOs << "    Entity   =" << strEntity << endl;
380         pOs << "    Geom     =" << pE.mGeom << endl; 
381         pOs << "    Has names?" << (pE.isNames()?"yes":"no") << endl;
382         pOs << "    Has id   ?" << (pE.isIdentifiers()?"yes":"no") << endl;
383
384         {
385                 set<med_int> setOfFam = pE.getSetOfFamilies();
386                 if (setOfFam.size() == 0)
387                 {
388                         pOs << "    Families: #fam=0" << endl;
389                 }
390                 else
391                 {
392                         set<med_int>::iterator itFam = setOfFam.end();
393                         itFam--;
394                         pOs << "    Families: #fam=" << setOfFam.size() << " id_min=" << (*(setOfFam.begin())) << " id_max=" << (*itFam) << endl;
395                         
396                         if (pE.mFlagPrintAll)
397                         {
398                                 for (int i = 0 ; i < pE.mNum; i++)
399                                 {
400                                         pOs << "        Elt " << (i + 1) << ": " << pE.mFamIdent[i] << endl;
401                                 }
402                         }
403                 }
404         }
405         
406         {
407                 set<med_int> setOfNodes = pE.getSetOfNodes();
408                 if (setOfNodes.size() == 0)
409                 {
410                         pOs << "    Connectivity: #nodes=0" << endl;
411                 }
412                 else
413                 {
414                         set<med_int>::iterator itNode = setOfNodes.end();
415                         itNode--;
416                         pOs << "    Connectivity: #nodes=" << setOfNodes.size() << " id_min=" << (*(setOfNodes.begin())) << " id_max=" << (*itNode) << endl;
417                         
418                         if (pE.mFlagPrintAll)
419                         {
420                                 for (int i = 0 ; i < pE.mNum ; i++)
421                                 {
422                                         pOs << "        Elt " << (i + 1) << ": ";
423                                         for (int j = 0 ; j < pE.mNumNodesByElt ; j++)
424                                         {
425                                                 pOs << pE.mCon[i * pE.mNumNodesByElt + j] << " ";
426                                         }
427                                         pOs << endl;
428                                 }
429                         }
430                 }
431         }
432         
433         if (pE.mFlagPrintAll)
434         {
435                 
436                 if (pE.isIdentifiers())
437                 {
438                         pOs << "    Num (identifier): " << endl;
439                         for (int i = 0 ; i < pE.mNum; i++)
440                         {
441                                 pOs << "        Elt " << (i + 1) << ": " << pE.mId[i] << " " << endl;
442                         }
443                 }
444                 
445                 if (pE.isNames())
446                 {
447                         pE.mNames[MED_TAILLE_PNOM * pE.mNum] = '\0';
448                         pOs << "    Names: |" << pE.mNames << "|" << endl;
449                 }
450                 
451         }
452         
453         return pOs;
454 }
455
456
457 } // namespace  multipr
458
459 // EOF