Salome HOME
adding a new test for makeMesh method.
[modules/med.git] / src / MULTIPR / MULTIPR_Elements.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D
2 //
3 //  This library is free software; you can redistribute it and/or
4 //  modify it under the terms of the GNU Lesser General Public
5 //  License as published by the Free Software Foundation; either
6 //  version 2.1 of the License.
7 //
8 //  This library is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 //  Lesser General Public License for more details.
12 //
13 //  You should have received a copy of the GNU Lesser General Public
14 //  License along with this library; if not, write to the Free Software
15 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Partitioning/decimation module for the SALOME v3.2 platform
20 //
21 /**
22  * \file    MULTIPR_Elements.cxx
23  *
24  * \brief   see MULTIPR_Elements.hxx
25  *
26  * \author  Olivier LE ROUX - CS, Virtual Reality Dpt
27  * 
28  * \date    01/2007
29  */
30
31 //*****************************************************************************
32 // Includes section
33 //*****************************************************************************
34
35 #include "MULTIPR_Elements.hxx"
36 #include "MULTIPR_Nodes.hxx"
37 #include "MULTIPR_Exceptions.hxx"
38
39 #include <iostream>
40 #include <set>
41 #include <map>
42
43 using namespace std;
44
45
46 namespace multipr
47 {
48
49
50 //*****************************************************************************
51 // Class Elements implementation
52 //*****************************************************************************
53
54 Elements::Elements() 
55 {
56     mId       = NULL;
57     mFamIdent = NULL;
58     mNames    = NULL;
59     mCon      = NULL;
60     mFlagPrintAll = false;
61     reset(); 
62 }
63
64 Elements::Elements(med_geometrie_element pGeomType) 
65 {
66     mId       = NULL;
67     mFamIdent = NULL;
68     mNames    = NULL;
69     mCon      = NULL;
70     mNum      = 0;
71     mGeom          = pGeomType;
72     mNumNodesByElt = mGeom % 100;
73     mDim           = mGeom / 100;
74     mEntity        = MED_MAILLE;
75     mFlagPrintAll  = false;
76 }
77
78 Elements::~Elements()  
79
80     reset();  
81 }
82
83
84 void Elements::reset() 
85
86     mNum           = 0;
87     mEntity        = MED_MAILLE;
88     mGeom          = MED_NONE;
89     mNumNodesByElt = 0;
90     mDim           = 0;
91     
92     if (mId != NULL)       { delete[] mId;       mId       = NULL; }
93     if (mFamIdent != NULL) { delete[] mFamIdent; mFamIdent = NULL; }
94     if (mNames != NULL)    { delete[] mNames;    mNames    = NULL; }
95     if (mCon != NULL)      { delete[] mCon;      mCon      = NULL; }
96
97     mSetOfNodes.clear();
98     
99     mFlagPrintAll = false;
100 }
101
102
103 med_int Elements::getFamilyIdentifier(med_int pIndex) const 
104
105     if ((pIndex < 0) || (pIndex >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__);
106     
107     return mFamIdent[pIndex]; 
108 }
109
110
111 const med_int* Elements::getConnectivity(int pIndex) const
112 {
113     if ((pIndex < 0) || (pIndex >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__);
114     
115     return mCon + mNumNodesByElt * pIndex;
116 }
117
118
119 void Elements::getCoordinates(med_int pIndexElt, const Nodes* pNodes, med_float* pCoo, int pFirst) const
120 {
121     if ((pIndexElt < 0) || (pIndexElt >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__);
122     if (pNodes == NULL) throw NullArgumentException("", __FILE__, __LINE__);
123     if (pCoo == NULL) throw NullArgumentException("", __FILE__, __LINE__);
124     
125     // get the list of nodes of the element
126     const med_int* con = getConnectivity(pIndexElt);
127     
128     med_float* destCoo = pCoo;
129     int size = sizeof(med_float) * mDim;
130     
131     // for each node of the element
132     int n = (mNumNodesByElt < pFirst) ? mNumNodesByElt : pFirst;
133     for (int i = 0 ; i < n ; i++)
134     {
135         // get index of node (MED index start at 1)
136         med_int indexNode = con[i] - 1;
137         
138         // get coordinates of this node
139         const med_float* srcCoo = pNodes->getCoordinates(indexNode);
140         
141         // copy coordinates to destCoo
142         memcpy(destCoo, srcCoo, size);
143         
144         // prepare next point
145         destCoo += mDim;
146     }
147 }
148
149
150 Elements* Elements::extractSubSet(const set<med_int>& pSetIndices) const
151 {
152     Elements* subset = new Elements();
153     
154     //---------------------------------------------------------------------
155     // Copy parameters
156     //---------------------------------------------------------------------
157     subset->mNum           = pSetIndices.size();
158     subset->mEntity        = mEntity;
159     subset->mGeom          = mGeom;          // e.g. 310 for a TETRA10
160     subset->mNumNodesByElt = mNumNodesByElt; // e.g. 10 for a TETRA10
161     subset->mDim           = mDim;           // e.g. 3 for a TETRA10
162     
163     //---------------------------------------------------------------------
164     // Allocate arrays
165     //---------------------------------------------------------------------
166     subset->mFamIdent     = new med_int[subset->mNum];
167     subset->mCon          = new med_int[mNumNodesByElt * subset->mNum];
168     
169     //---------------------------------------------------------------------
170     // Copy subset of familys id and connectivity.
171     //---------------------------------------------------------------------
172     med_int* destCon = subset->mCon;
173     set<med_int>::iterator itSet = pSetIndices.begin();
174     for (int itElt = 0 ; itElt < subset->mNum && itSet != pSetIndices.end(); itElt++)
175     {
176         med_int srcIndex = (*itSet) - 1; // MED index start at 1
177                 subset->mFamIdent[itElt] = mFamIdent[srcIndex]; 
178
179         med_int* srcCon = mCon + srcIndex * mNumNodesByElt;
180         memcpy(destCon, srcCon, sizeof(med_int) * mNumNodesByElt);
181         
182         destCon += mNumNodesByElt;
183         itSet++;
184     }
185     //---------------------------------------------------------------------
186     // Copy subset of identifiers if necessary
187     //---------------------------------------------------------------------
188     if (isIdentifiers())  
189     { 
190         itSet = pSetIndices.begin();
191         subset->mId = new med_int[subset->mNum]; 
192         for (int itElt = 0 ; itElt < subset->mNum && itSet != pSetIndices.end(); itElt++)
193         {
194             med_int srcIndex = (*itSet) - 1; // MED index start at 1
195             subset->mId[itElt] = mId[srcIndex];
196             
197             itSet++;
198         }
199     }
200     
201     //---------------------------------------------------------------------
202     // Copy subset of names if necessary
203     //---------------------------------------------------------------------
204     if (isNames())       
205     { 
206         itSet = pSetIndices.begin();
207         subset->mNames = new char[MED_TAILLE_PNOM * subset->mNum + 1]; 
208         char* destPtr = subset->mNames;
209         for (int itElt = 0 ; itElt < subset->mNum && itSet != pSetIndices.end(); itElt++)
210         {
211             med_int srcIndex = (*itSet) - 1; // MED index start at 1
212             char* srcPtr = mNames + srcIndex * MED_TAILLE_PNOM; 
213             memcpy(destPtr, srcPtr, MED_TAILLE_PNOM);
214             
215             destPtr += MED_TAILLE_PNOM;
216             itSet++;
217         }
218         subset->mNames[MED_TAILLE_PNOM * subset->mNum] = '\0';
219     }
220     
221     return subset;
222 }
223
224 void        Elements::extractSubSetFromNodes(const std::set<med_int>& pSetOfNodes, 
225                                    std::set<med_int>& pSubSetOfElements) const
226 {
227     if (&pSetOfNodes == &pSubSetOfElements) throw IllegalStateException("pSetOfNodes and pSubSetOfElements must be different !", __FILE__, __LINE__);
228     
229     int     numOfNodes = pSetOfNodes.size();
230     bool    keepElt = false;
231     for (int itElt = 0; itElt < mNum; ++itElt)
232     {
233         keepElt = false;
234         for (std::set<med_int>::iterator itNode = pSetOfNodes.begin();
235              itNode != pSetOfNodes.end() && keepElt == false; ++itNode)
236         {
237             for (int itCon = 0; itCon < mNumNodesByElt && keepElt == false; ++itCon)
238             {
239                 if ((*itNode) == mCon[itElt * mNumNodesByElt + itCon])
240                 {
241                     keepElt = true;
242                 }
243             }
244         }
245         if (keepElt)
246         {
247             pSubSetOfElements.insert(itElt + 1);
248         }
249     }
250 }
251
252 const set<med_int>& Elements::getSetOfNodes()
253 {    
254     // lazy get: test if mSetOfNodes has already been built
255     if (mSetOfNodes.size() == 0)
256     {
257         buildSetOfNodes();
258     }
259     
260     return mSetOfNodes;
261 }
262
263
264 set<med_int> Elements::getSetOfFamilies() const
265 {
266     // set of families is empty at the beginning
267     set<med_int> setOfFamilies;
268     
269     // for each element, add its family to the set
270     for (int itElt = 0 ; itElt < mNum ; itElt++)
271     {
272         setOfFamilies.insert(mFamIdent[itElt]);
273     }
274     
275     return setOfFamilies;
276 }
277
278
279 void Elements::remap() 
280 {
281         int itNode, size;
282     // build set of nodes if necessary
283     if (mSetOfNodes.size() == 0)
284     {
285         buildSetOfNodes();
286     }
287     
288     // build the map for indices convertion
289     map<med_int, med_int> mapOldIndexToNewIndex;
290     med_int newIndex = 1; // MED index start at 1
291     for (set<med_int>::iterator itSet = mSetOfNodes.begin(); itSet != mSetOfNodes.end() ; itSet++)
292     {
293         med_int oldIndex = (*itSet);
294         mapOldIndexToNewIndex.insert(make_pair(oldIndex, newIndex));
295         newIndex++;
296     }
297     
298     // for each node referenced by this set of elements
299     for (itNode = 0, size = mNum * mNumNodesByElt ; itNode < size ; itNode++)
300     {
301         // convert old index to new index (remap)
302         mCon[itNode] = mapOldIndexToNewIndex[mCon[itNode]];
303     }
304     
305     buildSetOfNodes();
306 }
307
308 void Elements::remap(std::set<med_int>& pSetOfNodes)
309 {
310         int itNode, size;
311         
312         // build the map for indices convertion
313     map<med_int, med_int> mapOldIndexToNewIndex;
314     med_int newIndex = 1; // MED index start at 1
315         itNode = 1;
316     for (std::set<med_int>::iterator it = pSetOfNodes.begin(); it != pSetOfNodes.end(); ++it)
317     {
318         med_int oldIndex = *it;
319         mapOldIndexToNewIndex.insert(make_pair(oldIndex, itNode));
320                 ++itNode;
321     }
322         // for each node referenced by this set of elements
323     for (itNode = 0, size = mNum * mNumNodesByElt ; itNode < size ; itNode++)
324     {
325         // convert old index to new index (remap).
326         mCon[itNode] = mapOldIndexToNewIndex[mCon[itNode]];;
327     }
328     buildSetOfNodes();
329
330 }
331
332 Elements* Elements::mergePartial(Elements* pElements, int pOffset)
333 {
334     Elements* elements = new Elements();
335     
336     //---------------------------------------------------------------------
337     // Copy parameters
338     //---------------------------------------------------------------------
339     elements->mNum           = mNum + pElements->mNum;
340     
341     if (mEntity != pElements->mEntity) throw IllegalStateException("entity should be the same", __FILE__, __LINE__);
342     elements->mEntity        = mEntity;
343     
344     elements->mGeom          = mGeom;          // e.g. 310 for a TETRA10
345     elements->mNumNodesByElt = mNumNodesByElt; // e.g. 10 for a TETRA10
346     if (mDim != pElements->mDim) throw IllegalStateException("dimension should be the same", __FILE__, __LINE__);
347     elements->mDim           = mDim;           // e.g. 3 for a TETRA10
348     
349     elements->mId            = NULL;
350     elements->mNames         = NULL;
351     
352     //---------------------------------------------------------------------
353     // Allocate arrays
354     //---------------------------------------------------------------------
355     elements->mFamIdent     = new med_int[elements->mNum];
356     elements->mCon          = new med_int[mNumNodesByElt * elements->mNum];
357     
358     //---------------------------------------------------------------------
359     // Copy familys id and connectivity.
360     //---------------------------------------------------------------------
361     memcpy(elements->mFamIdent, mFamIdent, mNum * sizeof(med_int));
362     memcpy(elements->mFamIdent + mNum, pElements->mFamIdent, pElements->mNum * sizeof(med_int));
363     
364     memcpy(elements->mCon, mCon, mNum * mNumNodesByElt * sizeof(med_int));
365     
366     med_int* dst = elements->mCon + mNum * mNumNodesByElt;
367     for (int i = 0, n = pElements->mNum * mNumNodesByElt ; i < n ; i++)
368     {
369         dst[i] = pElements->mCon[i] + pOffset;
370     }    
371     
372     //cout << "WARNING: do no build set of nodes" << endl;
373     //elements->buildSetOfNodes();
374     
375     return elements;
376 }
377
378
379 Elements* Elements::mergePartial(vector<Elements*> pElements, vector<int>& pOffsets)
380 {
381     if (pElements.size() == 0) throw IllegalArgumentException("pElements should contain at least 1 element", __FILE__, __LINE__);
382     
383     Elements* elements = new Elements();
384     
385     //---------------------------------------------------------------------
386     // Copy parameters
387     //---------------------------------------------------------------------
388     elements->mNum = mNum;
389     for (unsigned i = 0 ; i < pElements.size() ; i++)
390     {
391         elements->mNum += pElements[i]->mNum;
392     
393         if (mEntity != pElements[i]->mEntity) throw IllegalStateException("entity should be the same", __FILE__, __LINE__);
394         if (mDim != pElements[i]->mDim) throw IllegalStateException("dimension should be the same", __FILE__, __LINE__);
395     }
396         
397     elements->mEntity        = mEntity;    
398     elements->mGeom          = mGeom;          // e.g. 310 for a TETRA10
399     elements->mNumNodesByElt = mNumNodesByElt; // e.g. 10 for a TETRA10    
400     elements->mDim           = mDim;           // e.g. 3 for a TETRA10
401     
402     elements->mId            = NULL;
403     elements->mNames         = NULL;
404     
405     //---------------------------------------------------------------------
406     // Allocate arrays
407     //---------------------------------------------------------------------
408     elements->mFamIdent     = new med_int[elements->mNum];
409     elements->mCon          = new med_int[mNumNodesByElt * elements->mNum];
410     
411     //---------------------------------------------------------------------
412     // Copy familys id and connectivity.
413     //---------------------------------------------------------------------
414     memcpy(elements->mFamIdent, mFamIdent, mNum * sizeof(med_int));
415     memcpy(elements->mCon, mCon, mNum * mNumNodesByElt * sizeof(med_int));
416     
417     int offsetFamIdent = mNum;
418     int offsetCon      = mNum;
419     for (unsigned j = 0 ; j < pElements.size() ; j++)
420     {            
421         memcpy(elements->mFamIdent + offsetFamIdent, pElements[j]->mFamIdent, pElements[j]->mNum * sizeof(med_int));  offsetFamIdent += pElements[j]->mNum;
422         
423         med_int* dst = elements->mCon + offsetCon * mNumNodesByElt;
424         for (int i = 0, n = pElements[j]->mNum * mNumNodesByElt ; i < n ; i++)
425         {
426             dst[i] = pElements[j]->mCon[i] + pOffsets[j];
427         }    
428         offsetCon += pElements[j]->mNum;
429     }
430     
431     //cout << "WARNING: do no build set of nodes" << endl;
432     //elements->buildSetOfNodes();
433
434     return elements;
435 }
436
437
438 void Elements::buildSetOfNodes()
439 {
440     if (mSetOfNodes.size() != 0)
441     {
442         mSetOfNodes.clear();
443     }
444     
445     // for each node referenced by this set of elements
446     for (int itNode = 0, size = mNum * mNumNodesByElt ; itNode < size ; itNode++)
447     {
448         // add the node to the set
449         mSetOfNodes.insert(mCon[itNode]);
450     }
451 }
452
453
454 void Elements::readMED(
455     med_idt               pMEDfile, 
456     char*                 pMeshName, 
457     med_int               pMeshDim, 
458     med_entite_maillage   pEntity, 
459     med_geometrie_element pGeom)
460 {
461     if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__);
462     if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
463     if ((pMeshDim < 1) || (pMeshDim > 3)) throw IllegalArgumentException("", __FILE__, __LINE__);
464     
465     reset();
466     
467     mEntity        = pEntity;
468     mGeom          = pGeom;
469     mNumNodesByElt = mGeom % 100;
470     mDim           = mGeom / 100;
471     
472     mNum = MEDnEntMaa(
473         pMEDfile, 
474         pMeshName, 
475         MED_CONN,  // type of information requested = CONNECTIVITY
476         pEntity, 
477         pGeom, 
478         MED_NOD);  // nodal connectivity
479     
480     if (mNum < 0) throw IOException("i/o error while reading information about elements in MED file", __FILE__, __LINE__);
481     
482     if (mNum == 0)
483     {
484         // empty mesh
485         return;
486     }
487     
488     mCon      = new med_int[mNumNodesByElt * mNum];
489     mNames    = new char[MED_TAILLE_PNOM * mNum + 1];
490     mId       = new med_int[mNum];
491     mFamIdent = new med_int[mNum]; 
492     med_booleen isNames;
493     med_booleen isIdentifiers;
494     
495     med_err ret = MEDelementsLire(
496         pMEDfile, 
497         pMeshName, 
498         pMeshDim, 
499         mCon, 
500         MED_FULL_INTERLACE,
501         mNames, 
502         &isNames,
503         mId,
504         &isIdentifiers,
505         mFamIdent,
506         mNum, 
507         mEntity, 
508         mGeom, 
509         MED_NOD); // NODAL CONNECTIVITY
510     
511     if (ret != 0) throw IOException("i/o error while reading elements in MED file", __FILE__, __LINE__);
512     
513     if (!isNames)
514     {
515         delete[] mNames;
516         mNames = NULL;
517     }
518     
519     if (!isIdentifiers)
520     {
521         delete[] mId;
522         mId = NULL;
523     }
524 }
525
526
527 void Elements::writeMED(med_idt pMEDfile, char* pMeshName, med_int pMeshDim)
528 {
529     if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__);
530     if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
531     if (strlen(pMeshName) > MED_TAILLE_NOM) throw IllegalArgumentException("", __FILE__, __LINE__);
532     if ((pMeshDim < 1) || (pMeshDim > 3)) throw IllegalArgumentException("", __FILE__, __LINE__);
533     
534     // special case: if no elements => do nothing
535     if (mNum == 0) return;
536     
537     med_err ret = MEDelementsEcr(
538         pMEDfile,
539         pMeshName,
540         pMeshDim,
541         mCon,
542         MED_FULL_INTERLACE,
543         mNames,
544         isNames()?MED_VRAI:MED_FAUX,
545         mId,
546         isIdentifiers()?MED_VRAI:MED_FAUX,
547         mFamIdent,
548         mNum,
549         mEntity,
550         mGeom,
551         MED_NOD); // NODAL CONNECTIVITY
552         
553     if (ret != 0) throw IOException("i/o error while writing elements in MED file", __FILE__, __LINE__);
554 }
555
556
557 ostream& operator<<(ostream& pOs, Elements& pE)
558 {
559     char strEntity[16];
560     switch (pE.mEntity) 
561     {
562         case MED_MAILLE: strcpy(strEntity, "MED_MAILLE"); break;
563         case MED_FACE:   strcpy(strEntity, "MED_FACE"); break;
564         case MED_ARETE:  strcpy(strEntity, "MED_ARETE"); break;
565         case MED_NOEUD:  strcpy(strEntity, "MED_NOEUD"); break;
566         default:         strcpy(strEntity, "UNKNOWN"); break;
567     }
568     
569     pOs << "Elements: " << endl;
570     pOs << "    #number  =" << pE.mNum << endl;
571     pOs << "    Entity   =" << strEntity << endl;
572     pOs << "    Geom     =" << pE.mGeom << endl; 
573     pOs << "    Has names?" << (pE.isNames()?"yes":"no") << endl;
574     pOs << "    Has id   ?" << (pE.isIdentifiers()?"yes":"no") << endl;
575
576     {
577         set<med_int> setOfFam = pE.getSetOfFamilies();
578         if (setOfFam.size() == 0)
579         {
580             pOs << "    Families: #fam=0" << endl;
581         }
582         else
583         {
584             set<med_int>::iterator itFam = setOfFam.end();
585             itFam--;
586             pOs << "    Families: #fam=" << setOfFam.size() << " id_min=" << (*(setOfFam.begin())) << " id_max=" << (*itFam) << endl;
587             
588             if (pE.mFlagPrintAll)
589             {
590                 for (int i = 0 ; i < pE.mNum; i++)
591                 {
592                     pOs << "        Elt " << (i + 1) << ": " << pE.mFamIdent[i] << endl;
593                 }
594             }
595         }
596     }
597     
598     {
599         set<med_int> setOfNodes = pE.getSetOfNodes();
600         if (setOfNodes.size() == 0)
601         {
602             pOs << "    Connectivity: #nodes=0" << endl;
603         }
604         else
605         {
606             set<med_int>::iterator itNode = setOfNodes.end();
607             itNode--;
608             pOs << "    Connectivity: #nodes=" << setOfNodes.size() << " id_min=" << (*(setOfNodes.begin())) << " id_max=" << (*itNode) << endl;
609             
610             if (pE.mFlagPrintAll)
611             {
612                 for (int i = 0 ; i < pE.mNum ; i++)
613                 {
614                     pOs << "        Elt " << (i + 1) << ": ";
615                     for (int j = 0 ; j < pE.mNumNodesByElt ; j++)
616                     {
617                         pOs << pE.mCon[i * pE.mNumNodesByElt + j] << " ";
618                     }
619                     pOs << endl;
620                 }
621             }
622         }
623     }
624     
625     if (pE.mFlagPrintAll)
626     {
627         
628         if (pE.isIdentifiers())
629         {
630             pOs << "    Num (identifier): " << endl;
631             for (int i = 0 ; i < pE.mNum; i++)
632             {
633                 pOs << "        Elt " << (i + 1) << ": " << pE.mId[i] << " " << endl;
634             }
635         }
636         
637         if (pE.isNames())
638         {
639             pE.mNames[MED_TAILLE_PNOM * pE.mNum] = '\0';
640             pOs << "    Names: |" << pE.mNames << "|" << endl;
641         }
642         
643     }
644     
645     return pOs;
646 }
647
648
649 } // namespace  multipr
650
651 // EOF