Salome HOME
DCQ : Merge with Ecole Ete a6.
[modules/visu.git] / src / CONVERTOR / VISU_MedConvertor.cxx
1 //  VISU OBJECT : interactive object for VISU entities implementation
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //  File   : VISU_MedConvertor.cxx
24 //  Author : Alexey PETROV
25 //  Module : VISU
26
27
28 #include "VISU_MedConvertor.hxx"
29 #include "VISU_ConvertorUtils.hxx"
30
31 #include <valarray>     
32 #include <vtkCellType.h>
33
34 #define USER_INTERLACE MED_FULL_INTERLACE
35
36 using namespace std;
37
38 #ifdef _DEBUG_
39 static int MYDEBUG = 0;
40 #else
41 static int MYDEBUG = 0;
42 #endif
43
44
45 static med_err ret = 0;
46
47 typedef map<VISU::TEntity,med_entite_maillage> TVisu2MedEntity;
48
49 static TVisu2MedEntity aVisu2MedEntity;
50
51 static int INIT = (
52                    aVisu2MedEntity[VISU::NODE_ENTITY] = MED_NOEUD,
53                    aVisu2MedEntity[VISU::EDGE_ENTITY] = MED_ARETE,
54                    aVisu2MedEntity[VISU::FACE_ENTITY] = MED_FACE,
55                    aVisu2MedEntity[VISU::CELL_ENTITY] = MED_MAILLE,
56                    1);
57
58 static med_geometrie_element NODEGEOM[1] = {MED_POINT1};
59
60 static med_geometrie_element EDGEGEOM[MED_NBR_GEOMETRIE_ARETE] = {
61   MED_SEG2, MED_SEG3
62   };
63
64 static med_geometrie_element FACEGEOM[MED_NBR_GEOMETRIE_FACE] = {
65   MED_TRIA3, MED_QUAD4, MED_TRIA6, MED_QUAD8
66   };
67
68 static med_geometrie_element  CELLGEOM[MED_NBR_GEOMETRIE_MAILLE] = {
69   MED_POINT1, MED_SEG2, MED_SEG3, MED_TRIA3,
70   MED_QUAD4, MED_TRIA6, MED_QUAD8, MED_TETRA4,
71   MED_PYRA5, MED_PENTA6, MED_HEXA8, MED_TETRA10, 
72   MED_PYRA13, MED_PENTA15, MED_HEXA20
73   };
74
75 void GetEntity2Geom(const VISU::TEntity& theEntity, med_geometrie_element*& theVector, int* theEnd) 
76 {
77   switch(theEntity){
78   case VISU::CELL_ENTITY: theVector = CELLGEOM; *theEnd = MED_NBR_GEOMETRIE_MAILLE; break;
79   case VISU::FACE_ENTITY: theVector = FACEGEOM; *theEnd = MED_NBR_GEOMETRIE_FACE; break;
80   case VISU::EDGE_ENTITY: theVector = EDGEGEOM; *theEnd = MED_NBR_GEOMETRIE_ARETE; break;
81   case VISU::NODE_ENTITY: theVector = NODEGEOM; *theEnd = 1; break;
82   default:
83     throw std::runtime_error("GetEntity2Geom >> theEntity is uncorrect");
84   }
85 }
86
87 extern "C"
88 VISU_Convertor* CreateMedConvertor(const string& theFileName) {
89   return new VISU_MedConvertor(theFileName);
90 }
91
92 class MedFile{
93   char* myFileName;
94   med_idt myFid;
95   MedFile();
96   MedFile(const MedFile&);
97 public:
98   MedFile(const char* theFileName)  :
99     myFileName(strdup(theFileName))
100   {
101     myFid = MEDouvrir(myFileName,MED_LECT);
102     if(myFid < 0){
103       free(myFileName);
104       throw std::runtime_error(string("MedFile::MedFile >> MEDouvrir(...) - ") + theFileName);
105     }
106   }
107   ~MedFile(){
108     free(myFileName);
109     if(myFid >= 0) 
110       MEDfermer(myFid);
111   }
112   const med_idt& GetFid() const { return myFid;};
113 };
114
115 VISU_MedConvertor::VISU_MedConvertor(const string& theFileName)  {
116   myFileInfo.setFile(QString(theFileName.c_str()));
117   myName = myFileInfo.baseName().latin1();
118 }
119
120 VISU_Convertor* VISU_MedConvertor::Build()  {
121   MedFile aMedFile(myFileInfo.absFilePath());
122   med_idt fid = aMedFile.GetFid();
123   med_int iMeshEnd = MEDnMaa(fid);  //Get number of meshes
124   if (iMeshEnd < 0) throw std::runtime_error(EXCEPTION("ImportInfo >> MEDnMaa(...)"));
125   if(MYDEBUG) MESSAGE("ImportInfo - MEDnMaa = "<<iMeshEnd<<"; myFileInfo = "<<myFileInfo.filePath());
126   for(int iMesh = 1; iMesh <= iMeshEnd; iMesh++){
127     med_int aMeshDim;
128     char aMeshName[MED_TAILLE_NOM+1] = "";
129     MEDmaaInfo(fid,iMesh,aMeshName,&aMeshDim);
130     if(MYDEBUG) MESSAGE("ImportInfo - aMeshName = '"<<aMeshName<<"'; aMeshDim = "<<aMeshDim);
131     VISU::TMesh &aMesh = myMeshMap[aMeshName];
132     aMesh.myDim = aMeshDim;
133     aMesh.myName = aMeshName;
134     typedef map<med_int,VISU::TEntity> TFamily2EntityMap;
135     TFamily2EntityMap aFamily2EntityMap;
136     typedef map<med_int,med_int> TFamilyCounterMap;
137     TFamilyCounterMap aFamilyNbCellsCounterMap, aFamilyCellsSizeCounterMap;
138     TVisu2MedEntity::const_iterator aVisu2MedEntityIter = aVisu2MedEntity.begin();
139     for(; aVisu2MedEntityIter != aVisu2MedEntity.end(); aVisu2MedEntityIter++) {
140       VISU::TEntity anEntity = aVisu2MedEntityIter->first;
141       int iGeomElemEnd;
142       med_geometrie_element* aGeomElemVector;
143       GetEntity2Geom(anEntity,aGeomElemVector,&iGeomElemEnd);
144       med_entite_maillage& aMedEntity = aVisu2MedEntity[anEntity];
145       for (int iGeomElem = 0; iGeomElem < iGeomElemEnd; iGeomElem++) {
146         int medId = getIdMedType(aGeomElemVector[iGeomElem]);
147         int aVtkType = med2vtk[medId].vtkType;
148         med_geometrie_element aMedType = med2vtk[medId].medType;
149         if(aMedEntity == MED_NOEUD){
150           med_geometrie_element typgeo = (med_geometrie_element)0;
151           med_connectivite typco = (med_connectivite)0;
152           med_int iNumElemEnd = MEDnEntMaa(fid,aMeshName,MED_COOR,MED_NOEUD,typgeo,typco);
153           if(iNumElemEnd > 0){
154             VISU::TMeshOnEntity& aMeshOnEntity = aMesh.myMeshOnEntityMap[anEntity];
155             aMeshOnEntity.myEntity = anEntity;
156             aMeshOnEntity.myMeshName = aMeshName;
157             aMeshOnEntity.myNbCells = iNumElemEnd;
158             aMeshOnEntity.myCellsSize = 2*iNumElemEnd;
159             aMesh.myNbPoints = iNumElemEnd;
160             if(MYDEBUG) 
161               MESSAGE("ImportInfo -\t anEntity = "<<anEntity<<
162                       "; medName = "<<med2vtk[medId].medName<<
163                       "; myNbCells = "<<aMeshOnEntity.myNbCells<<
164                       "; myCellsSize = "<<aMeshOnEntity.myCellsSize);
165             med_booleen iname_elem, inum_elem;
166             valarray<med_int> num_elem(iNumElemEnd), num_fam_elem(iNumElemEnd);
167             valarray<char> name_elem('\0',iNumElemEnd*MED_TAILLE_PNOM+1);
168             med_repere rep;
169             valarray<char> name_coord('\0',aMesh.myDim*MED_TAILLE_PNOM+1);
170             valarray<char> unit_coord('\0',aMesh.myDim*MED_TAILLE_PNOM+1);
171             valarray<med_float> coord(aMesh.myDim*iNumElemEnd);
172             ret = MEDnoeudsLire(fid,aMeshName,aMesh.myDim,&coord[0],MED_FULL_INTERLACE,&rep,
173                                 &name_coord[0],&unit_coord[0],&name_elem[0],&iname_elem,
174                                 &num_elem[0],&inum_elem,&num_fam_elem[0],iNumElemEnd);
175             if(ret < 0) throw std::runtime_error(EXCEPTION("ImportInfo >> MEDnoeudsLire(...)"));
176             for (int iNumElem = 0; iNumElem < iNumElemEnd; iNumElem++)
177               if(num_fam_elem[iNumElem] != 0){
178                 aFamily2EntityMap[num_fam_elem[iNumElem]] = anEntity;
179                 aFamilyNbCellsCounterMap[num_fam_elem[iNumElem]] += 1;
180                 aFamilyCellsSizeCounterMap[num_fam_elem[iNumElem]] += 2;
181               }
182           }
183         }
184         //Get number of connectivities
185         med_int iNumElemEnd = MEDnEntMaa(fid,aMeshName,MED_CONN,aMedEntity,aMedType,MED_NOD); 
186         if (iNumElemEnd > 0) {
187           VISU::TMeshOnEntity& aMeshOnEntity = aMesh.myMeshOnEntityMap[anEntity];
188           aMeshOnEntity.myEntity = anEntity;
189           aMeshOnEntity.myMeshName = aMeshName;
190           med_booleen iname_elem, inum_elem;
191           valarray<med_int> num_elem(iNumElemEnd), num_fam_elem(iNumElemEnd);
192           valarray<char> name_elem('\0',iNumElemEnd*MED_TAILLE_PNOM+1);
193           med_int aNbConnForElem = getNbMedConnect(aMedType,anEntity,aMesh.myDim);
194           aMeshOnEntity.myNbCells += iNumElemEnd;
195           aMeshOnEntity.myCellsSize += iNumElemEnd*(med2vtk[medId].vtkNbNodes + 1);
196           if(MYDEBUG) 
197             MESSAGE("ImportInfo -\t anEntity = "<<anEntity<<
198                     "; medName = "<<med2vtk[medId].medName<<
199                     "; aNbConnForElem = "<<aNbConnForElem<<
200                     "; myNbCells = "<<aMeshOnEntity.myNbCells<<
201                     "; myCellsSize = "<<aMeshOnEntity.myCellsSize);
202           valarray<med_int> conn(0,aNbConnForElem*iNumElemEnd);
203           ret = MEDelementsLire(fid,aMeshName,aMesh.myDim,&conn[0],MED_FULL_INTERLACE,
204                                 &name_elem[0],&iname_elem,&num_elem[0],&inum_elem,
205                                 &num_fam_elem[0],iNumElemEnd,aMedEntity,aMedType,MED_NOD);
206           if (ret < 0) throw std::runtime_error(EXCEPTION("ImportInfo >> MEDelementsLire(...)"));
207           for (int iNumElem = 0; iNumElem < iNumElemEnd; iNumElem++)
208             if(num_fam_elem[iNumElem] != 0){
209               aFamily2EntityMap[num_fam_elem[iNumElem]] = anEntity;
210               aFamilyNbCellsCounterMap[num_fam_elem[iNumElem]] += 1;
211               aFamilyCellsSizeCounterMap[num_fam_elem[iNumElem]] += med2vtk[medId].vtkNbNodes + 1;
212             } 
213         }
214       }
215     }
216     med_int aNbFamily = MEDnFam(fid,aMeshName,0,MED_FAMILLE);
217     if(MYDEBUG) MESSAGE("ImportInfo - aNbFamily = "<<aNbFamily);
218     for(int aFamInd = 1; aFamInd <= aNbFamily; aFamInd++){
219       med_int aNbAttrib = MEDnFam(fid,aMeshName,aFamInd,MED_ATTR);
220       valarray<med_int> anAttId(aNbAttrib), anAttVal(aNbAttrib);
221       valarray<char> anAttDesc('\0',aNbAttrib*MED_TAILLE_DESC+1);
222       med_int aNbGroup = MEDnFam(fid,aMeshName,aFamInd,MED_GROUPE);
223       if(0 && MYDEBUG) 
224         MESSAGE("ImportInfo - aFamInd = "<<aFamInd<<"; aNbAttrib = "<<aNbAttrib<<"; aNbGroup = "<<aNbGroup);
225       valarray<char> aGroupNames('\0',aNbGroup*MED_TAILLE_LNOM+1);
226       char aFamilyName[MED_TAILLE_NOM+1] = "";
227       med_int aFamilyNum;
228       ret = MEDfamInfo(fid,aMeshName,aFamInd,aFamilyName,&aFamilyNum,
229                        &anAttId[0],&anAttVal[0],&anAttDesc[0],&aNbAttrib,
230                        &aGroupNames[0],&aNbGroup);
231       if(ret < 0) throw std::runtime_error(EXCEPTION("ImportInfo >> MEDfamInfo"));
232       if(0 && MYDEBUG) 
233         MESSAGE("ImportInfo - aFamilyNum = "<<aFamilyNum<<"; aNbGroup = "<<aNbGroup);
234       if(aFamily2EntityMap.find(aFamilyNum) == aFamily2EntityMap.end()) {
235         if(MYDEBUG) MESSAGE("ImportInfo - a Family with name '"<<aFamilyName<<"' are empty !!!");
236         continue;
237       }
238       VISU::TEntity anEntity = aFamily2EntityMap[aFamilyNum];
239       VISU::TMeshOnEntity& aMeshOnEntity = aMesh.myMeshOnEntityMap[anEntity];
240       VISU::TFamily& aFamily = aMeshOnEntity.myFamilyMap[aFamilyName];
241       aFamily.myName = aFamilyName;
242       aFamily.myEntity = anEntity;
243       aFamily.myId = aFamilyNum;
244       aFamily.myNbCells = aFamilyNbCellsCounterMap[aFamilyNum];
245       aFamily.myCellsSize = aFamilyCellsSizeCounterMap[aFamilyNum];
246       if(MYDEBUG) 
247         MESSAGE("ImportInfo - aFamily.myEntity = "<<anEntity<<
248                 "; myName = '"<<aFamilyName<<
249                 "'; myId = "<<aFamilyNum<<
250                 "; myNbCells = "<<aFamily.myNbCells<<
251                 "; myCellsSize = "<<aFamily.myCellsSize);
252       VISU::TBindGroups& aBindGroups = aFamily.myGroups;
253       for(int iGroup = 0, iPos = 0; iGroup < aNbGroup; iGroup++, iPos += MED_TAILLE_LNOM){
254         char aGroupName[MED_TAILLE_LNOM+1];
255         strncpy(aGroupName,&aGroupNames[iPos],MED_TAILLE_LNOM);
256         aGroupName[MED_TAILLE_LNOM] = '\0';
257         if(MYDEBUG) MESSAGE("ImportInfo - aGroupName["<<iGroup<<"] = '"<<aGroupName<<"'");
258         aBindGroups.insert(aGroupName);
259       }
260     }
261     //Calculation of TMesh.TGroupMap
262     const VISU::TMeshOnEntityMap& aMeshOnEntityMap = aMesh.myMeshOnEntityMap;
263     if(aMeshOnEntityMap.empty()) continue;
264     VISU::TGroupMap& aGroupMap = aMesh.myGroupMap;
265     VISU::TMeshOnEntityMap::const_iterator aMeshOnEntityMapIter = aMeshOnEntityMap.begin();
266     for(; aMeshOnEntityMapIter != aMeshOnEntityMap.end(); aMeshOnEntityMapIter++){
267       const VISU::TMeshOnEntity& aMeshOnEntity = aMeshOnEntityMapIter->second;
268       const VISU::TFamilyMap& aFamilyMap = aMeshOnEntity.myFamilyMap;
269       if(aFamilyMap.empty()) continue;
270       VISU::TFamilyMap::const_iterator aFamilyMapIter = aFamilyMap.begin();
271       for(; aFamilyMapIter != aFamilyMap.end(); aFamilyMapIter++){
272         const VISU::TFamily& aFamily = aFamilyMapIter->second;
273         const VISU::TBindGroups& aBindGroups = aFamily.myGroups;
274         if(aBindGroups.empty()) continue;
275         VISU::TBindGroups::const_iterator aBindGroupsIter = aBindGroups.begin();
276         for(; aBindGroupsIter != aBindGroups.end(); aBindGroupsIter++){
277           const string& aGroupName = *aBindGroupsIter;
278           VISU::TGroup& aGroup = aGroupMap[aGroupName];
279           aGroup.myName = aGroupName;
280           aGroup.myMeshName = aMesh.myName;
281           VISU::TFamilyAndEntity aFamilyAndEntity(aFamily.myName,aFamily.myEntity);
282           aGroup.myFamilyAndEntitySet.insert(aFamilyAndEntity);
283           aGroup.myNbCells += aFamily.myNbCells;
284           aGroup.myCellsSize += aFamily.myCellsSize;
285         }
286       }
287     }
288     //Displaing information for the TMesh.TGroupMap
289     VISU::TGroupMap::const_iterator aGroupMapIter = aGroupMap.begin();
290     if(MYDEBUG) MESSAGE("ImportInfo - aGroupMap.size() = "<<aGroupMap.size());
291     for(; aGroupMapIter != aGroupMap.end(); aGroupMapIter++){
292       const VISU::TGroup& aCGroup = aGroupMapIter->second;
293       const string& aGroupName = aGroupMapIter->first;
294       if(MYDEBUG) MESSAGE("ImportInfo - aGroupName = '"<<aGroupName<<
295                 "'; myNbCells = "<<aCGroup.myNbCells<<
296                 "; myCellsSize = "<<aCGroup.myCellsSize);
297       const VISU::TGroup& aGroup = aGroupMapIter->second;
298       const VISU::TFamilyAndEntitySet& aFamilyAndEntitySet = aGroup.myFamilyAndEntitySet;
299       VISU::TFamilyAndEntitySet::const_iterator aFamilyAndEntitySetIter = aFamilyAndEntitySet.begin();
300       for(; aFamilyAndEntitySetIter != aFamilyAndEntitySet.end(); aFamilyAndEntitySetIter++){
301         const string& aFamilyName = aFamilyAndEntitySetIter->first;
302         if(MYDEBUG) MESSAGE("ImportInfo - \t aFamilyName = '"<<aFamilyName<<"'");
303       }
304     }
305   }
306   //Reading information about fields
307   med_int iFieldEnd = MEDnChamp(fid,0);
308   if (iFieldEnd < 0) throw std::runtime_error(EXCEPTION("ImportChamps >> MEDnChamp(fid,0)"));
309   if(MYDEBUG) MESSAGE("ImportInfo - iFieldEnd = "<<iFieldEnd);
310   for(med_int iField = 1; iField <= iFieldEnd; iField++){
311     med_int ncomp = MEDnChamp(fid,iField);
312     if(ncomp < 0) throw std::runtime_error(EXCEPTION("ImportChamps >> MEDnChamp(fid,i)"));
313     valarray<char> aCompNames('\0',ncomp*MED_TAILLE_PNOM + 1);
314     valarray<char> aUnitNames('\0',ncomp*MED_TAILLE_PNOM + 1);
315     char name_field[MED_TAILLE_NOM + 1] = "";
316     med_type_champ type_field;
317     if(MEDchampInfo(fid,iField,name_field,&type_field,&aCompNames[0],&aUnitNames[0],ncomp) < 0)
318       throw std::runtime_error(EXCEPTION("ImportInfo >> MEDchampInfo(...)"));
319     //if(type_field != MED_REEL64) continue; //There is some problem in reading INTXX values
320     TVisu2MedEntity::const_iterator aVisu2MedEntityIter = aVisu2MedEntity.begin();
321     for(; aVisu2MedEntityIter != aVisu2MedEntity.end(); aVisu2MedEntityIter++) {
322       VISU::TEntity anEntity = aVisu2MedEntityIter->first;
323       int iGeomElemEnd;
324       med_geometrie_element* aGeomElemVector;
325       GetEntity2Geom(anEntity,aGeomElemVector,&iGeomElemEnd);
326       med_entite_maillage& aMedEntity = aVisu2MedEntity[anEntity];
327       for (int iGeomElem = 0; iGeomElem < iGeomElemEnd; iGeomElem++) {
328         med_geometrie_element& aGeom = aGeomElemVector[iGeomElem];
329         med_int iTimeStampEnd = MEDnPasdetemps(fid,name_field,aMedEntity,aGeom);
330         if(iTimeStampEnd < 0) throw std::runtime_error(EXCEPTION("ImportInfo >> MEDnPasdetemps(...)"));
331         if(iTimeStampEnd > 0) {
332           for(med_int iTimeStamp = 1; iTimeStamp <= iTimeStampEnd; iTimeStamp++) {
333             char aMeshName[MED_TAILLE_NOM+1] = "";
334             med_int ngauss = 0, numdt = 0, numo = 0;
335             char dt_unit[MED_TAILLE_PNOM+1] = "";
336             med_float dt = 0;
337             ret = MEDpasdetempsInfo(fid,name_field,aMedEntity,aGeom,iTimeStamp,
338                                     aMeshName,&ngauss,&numdt,dt_unit,&dt,&numo);
339             if(ret < 0) throw std::runtime_error(EXCEPTION("ImportInfo >> MEDpasdetempsInfo(...) < 0"));
340             if(myMeshMap.find(aMeshName) == myMeshMap.end())
341               throw std::runtime_error(EXCEPTION("ImportInfo >> MEDpasdetempsInfo(...)"));
342             VISU::TMesh &aMesh = myMeshMap[aMeshName];
343             VISU::TMeshOnEntity& aMeshOnEntity = aMesh.myMeshOnEntityMap[anEntity];
344             VISU::TFieldMap::iterator aFieldMapIter = aMeshOnEntity.myFieldMap.find(name_field);
345             //if(MYDEBUG && aFieldMapIter == aMeshOnEntity.myFieldMap.end()){
346             VISU::TField& aField = aMeshOnEntity.myFieldMap[name_field];
347             if(iTimeStamp == 1){
348               aField.myId = iField;
349               aField.myName = name_field;
350               aField.myEntity = anEntity;
351               aField.myMeshName = aMeshName;
352               aField.myNbComp = ncomp;
353               aField.myNbValField = iTimeStampEnd;
354               aField.myDataSize = aMeshOnEntity.myNbCells * ncomp;
355               aField.myCompNames.resize(ncomp);
356               aField.myUnitNames.resize(ncomp);
357               if(MYDEBUG)
358                 MESSAGE("ImportInfo - aField.myName = '"<<name_field<<
359                         "'; myMeshName = '"<<aMeshName<<
360                         "'; myEntity = "<<anEntity<<
361                         "; myNbComp = "<<ncomp<<
362                         "; myDataSize = "<<aField.myDataSize);
363               for(int iComp = 0, iPos = 0; iComp < ncomp; iComp++, iPos += MED_TAILLE_PNOM){
364                 char aCompName[MED_TAILLE_PNOM+1], aUnitName[MED_TAILLE_PNOM+1];
365                 strncpy(aCompName,&aCompNames[iPos],MED_TAILLE_PNOM);
366                 aCompName[MED_TAILLE_PNOM] = '\0';
367                 aField.myCompNames[iComp] = aCompName;
368                 strncpy(aUnitName,&aUnitNames[iPos],MED_TAILLE_PNOM);
369                 aUnitName[MED_TAILLE_PNOM] = '\0';
370                 aField.myUnitNames[iComp] = aUnitName;
371                 if(MYDEBUG)
372                   MESSAGE("ImportInfo - aCompName = '"<<aCompName<<"'; aUnitName = '"<<aUnitName<<"'");
373               }
374               
375             }
376             VISU::TField::TValForTime& aValForTime = aField.myValField[iTimeStamp];
377             aValForTime.myId = iTimeStamp;
378             aValForTime.myFieldName = aField.myName;
379             aValForTime.myEntity = aField.myEntity;
380             aValForTime.myMeshName = aField.myMeshName;
381             aValForTime.myNbComp = aField.myNbComp;
382             aValForTime.myTime = VISU::TField::TTime(dt,dt_unit);
383             if(MYDEBUG) 
384               MESSAGE("ImportInfo -\t aValForTime.myTime = "<<dt<<", "<<dt_unit);
385           }
386         }
387       }
388     }
389   }
390   return this; 
391 }
392
393 int VISU_MedConvertor::LoadMeshOnEntity(VISU::TMeshOnEntity& theMeshOnEntity, 
394                                         const string& theFamilyName)
395 {
396   //Open the med file (it will be closed by call of destructor)
397   MedFile aMedFile(myFileInfo.absFilePath());
398   med_idt fid = aMedFile.GetFid();
399   //Main part of code
400   const string& aMeshName = theMeshOnEntity.myMeshName;
401   const VISU::TEntity& anEntity = theMeshOnEntity.myEntity;
402   VISU::TMesh& aMesh = myMeshMap[aMeshName];
403   int isPointsUpdated;
404   if(anEntity == VISU::NODE_ENTITY) 
405     isPointsUpdated = LoadPoints(fid,aMesh,theFamilyName);
406   else 
407     isPointsUpdated = LoadPoints(fid,aMesh);
408   int isCellsOnEntityUpdated = LoadCellsOnEntity(fid,theMeshOnEntity,theFamilyName);
409
410   return (isPointsUpdated || isCellsOnEntityUpdated);
411 }
412
413 int VISU_MedConvertor::LoadMeshOnGroup(VISU::TMesh& theMesh, 
414                                        const VISU::TFamilyAndEntitySet& theFamilyAndEntitySet)
415 {
416   //Open the med file (it will be closed by call of destructor)
417   MedFile aMedFile(myFileInfo.absFilePath());
418   med_idt fid = aMedFile.GetFid();
419   //Main part of code
420   int isPointsUpdated = 0;
421   int isCellsOnEntityUpdated = 0;
422   VISU::TFamilyAndEntitySet::const_iterator aFamilyAndEntitySetIter = theFamilyAndEntitySet.begin();
423   for(; aFamilyAndEntitySetIter != theFamilyAndEntitySet.end(); aFamilyAndEntitySetIter++){
424     const string& aFamilyName = aFamilyAndEntitySetIter->first;
425     const VISU::TEntity& anEntity = aFamilyAndEntitySetIter->second;
426     VISU::TMeshOnEntity& aMeshOnEntity = theMesh.myMeshOnEntityMap[anEntity];
427     if(anEntity == VISU::NODE_ENTITY){
428       isPointsUpdated += LoadPoints(fid,theMesh,aFamilyName);
429       isCellsOnEntityUpdated += LoadCellsOnEntity(fid,aMeshOnEntity);
430     }else{
431       isPointsUpdated += LoadPoints(fid,theMesh);
432       isCellsOnEntityUpdated += LoadCellsOnEntity(fid,aMeshOnEntity,aFamilyName);
433     }
434   }
435
436   return (isPointsUpdated || isCellsOnEntityUpdated);
437 }
438
439 int VISU_MedConvertor::LoadFieldOnMesh(VISU::TMesh& theMesh, 
440                                        VISU::TMeshOnEntity& theMeshOnEntity, 
441                                        VISU::TField& theField, 
442                                        VISU::TField::TValForTime& theValForTime)
443 {
444   //Open the med file (it will be closed by call of destructor)
445   MedFile aMedFile(myFileInfo.absFilePath());
446   med_idt fid = aMedFile.GetFid();
447   //Main part of code
448   int isPointsUpdated = LoadPoints(fid,theMesh);
449   int isCellsOnEntityUpdated = LoadCellsOnEntity(fid,theMeshOnEntity);
450   int isFieldUpdated = LoadField(fid,theMeshOnEntity,theField,theValForTime);
451   
452   return (isPointsUpdated || isCellsOnEntityUpdated || isFieldUpdated);
453 }
454
455 int VISU_MedConvertor::LoadPoints(const med_idt& fid, VISU::TMesh& theMesh, const string& theFamilyName) 
456 {
457   try{
458     //Check on existing family
459     VISU::TMeshOnEntity& aMeshOnEntity = theMesh.myMeshOnEntityMap[VISU::NODE_ENTITY];
460     aMeshOnEntity.myEntity = VISU::NODE_ENTITY;
461     aMeshOnEntity.myMeshName = theMesh.myName;
462     VISU::TFamily* pFamily = VISU::GetFamily(aMeshOnEntity,theFamilyName);
463     bool isFamilyPresent = (pFamily != NULL);
464     VISU::TFamily& aFamily = *pFamily;
465     //Check on loading already done
466     bool isPointsLoaded = !theMesh.myPointsCoord.empty();
467     if(isPointsLoaded) 
468       if(!isFamilyPresent) return 0;
469       else if(!aFamily.mySubMesh.empty()) return 0;
470     if(MYDEBUG) 
471       MESSAGE("LoadPoints - isPointsLoaded = "<<isPointsLoaded<<"; theFamilyName = '"<<theFamilyName<<"'");
472     //Main part of code
473     char aMeshName[MED_TAILLE_NOM+1] = "";
474     strcpy(aMeshName,theMesh.myName.c_str());
475     med_geometrie_element typgeo = (med_geometrie_element)0; //MED_POINT1
476     med_connectivite typco = (med_connectivite)0; //MED_NOD
477     med_int iNumElemEnd = MEDnEntMaa(fid,aMeshName,MED_COOR,MED_NOEUD,typgeo,typco);
478     if (iNumElemEnd <= 0) throw std::runtime_error(EXCEPTION("LoadPoints >> MEDnEntMaa(...)"));
479     if(MYDEBUG) MESSAGE("LoadPoints - iNumElemEnd = "<<iNumElemEnd);
480     med_repere rep;
481     med_booleen iname_elem, inum_elem;
482     valarray<med_int> num_elem(iNumElemEnd), num_fam_elem(iNumElemEnd);
483     valarray<char> name_elem('\0',iNumElemEnd*MED_TAILLE_PNOM+1);
484     valarray<char> name_coord('\0',theMesh.myDim*MED_TAILLE_PNOM+1);
485     valarray<char> unit_coord('\0',theMesh.myDim*MED_TAILLE_PNOM+1);
486     valarray<med_float> coord(theMesh.myDim*iNumElemEnd);
487     ret = MEDnoeudsLire(fid,aMeshName,theMesh.myDim,&coord[0],MED_FULL_INTERLACE,&rep,
488                         &name_coord[0],&unit_coord[0],&name_elem[0],&iname_elem,
489                         &num_elem[0],&inum_elem,&num_fam_elem[0],iNumElemEnd);
490     if(ret < 0) throw std::runtime_error(EXCEPTION("LoadPoints >> MEDnoeudsLire(...)"));
491     if(!isPointsLoaded){
492       VISU::TMesh::TPointsCoord& aPointsCoord = theMesh.myPointsCoord;
493       aPointsCoord.resize(iNumElemEnd*theMesh.myDim);
494       if(MYDEBUG) MESSAGE("LoadPoints - Filling coordinates of the mesh - inum_elem = "<<inum_elem);
495       inum_elem = MED_FAUX; // It is workaround 
496       if(inum_elem == MED_FAUX)
497         for (int iNumElem = 0; iNumElem < iNumElemEnd; iNumElem++) 
498           for(int iDim = 0, iNumElem2Dim = iNumElem*theMesh.myDim; iDim < theMesh.myDim; iDim++, iNumElem2Dim++)
499             aPointsCoord[iNumElem2Dim] = coord[iNumElem2Dim];
500       else
501         for (int iNumElem = 0; iNumElem < iNumElemEnd; iNumElem++)
502           for(int iDim = 0, iNumElem2Dim = iNumElem*theMesh.myDim; iDim < theMesh.myDim; iDim++, iNumElem2Dim++)
503             aPointsCoord[num_elem[iNumElem2Dim]] = coord[iNumElem2Dim];
504       if(MYDEBUG) MESSAGE("LoadPoints - Filling aMeshOnEntity with type NODE_ENTITY");
505       VISU::TMeshOnEntity::TConnForCellType& aConnForCellType = aMeshOnEntity.myCellsConn[VTK_VERTEX];
506       aConnForCellType.resize(iNumElemEnd);
507       for (int iNumElem = 0; iNumElem < iNumElemEnd; iNumElem++)
508         aConnForCellType[iNumElem] = VISU::TMeshOnEntity::TConnect(1,iNumElem);
509     }
510     if(isFamilyPresent && iNumElemEnd > 0){
511       if(MYDEBUG) MESSAGE("LoadPoints - Filling aFamily SubMesh");
512       VISU::TFamily::TSubMeshOnCellType& aSubMeshOnCellType = aFamily.mySubMesh[VTK_VERTEX];
513       for (int iNumElem = 0; iNumElem < iNumElemEnd; iNumElem++) 
514         if(num_fam_elem[iNumElem] == aFamily.myId)
515           aSubMeshOnCellType.insert(iNumElem);
516     }
517     return 1;
518   }catch(std::runtime_error& exc){
519     theMesh.myPointsCoord.clear();
520     throw std::runtime_error(exc.what());
521   }catch(...){
522     theMesh.myPointsCoord.clear();
523     throw std::runtime_error(EXCEPTION("Unknown exception !!!"));
524   }
525   return 0;
526 }
527
528 int VISU_MedConvertor::LoadCellsOnEntity(const med_idt& fid, VISU::TMeshOnEntity& theMeshOnEntity,
529                                          const string& theFamilyName)
530 {
531   try{
532     //Check on existing family
533     VISU::TFamily* pFamily = VISU::GetFamily(theMeshOnEntity,theFamilyName);
534     bool isFamilyPresent = (pFamily != NULL);
535     VISU::TFamily& aFamily = *pFamily;
536     //Check on loading already done
537     bool isCellsLoaded = !theMeshOnEntity.myCellsConn.empty();
538     if(isCellsLoaded) 
539       if(!isFamilyPresent) return 0;
540       else if(!aFamily.mySubMesh.empty()) return 0;
541     if(MYDEBUG) {
542       MESSAGE("LoadCellsOnEntity - theFamilyName = '"<<theFamilyName<<"'");
543       MESSAGE("LoadCellsOnEntity - isCellsLoaded = "<<isCellsLoaded<<"; isFamilyPresent = "<<isFamilyPresent);
544     }
545     //Main part of code
546     int iGeomElemEnd;
547     med_geometrie_element* aGeomElemVector;
548     const VISU::TEntity& anEntity = theMeshOnEntity.myEntity;
549     GetEntity2Geom(anEntity,aGeomElemVector,&iGeomElemEnd);
550     const med_entite_maillage& aMedEntity = aVisu2MedEntity[anEntity];
551     char aMeshName[MED_TAILLE_NOM+1] = "";
552     strcpy(aMeshName,theMeshOnEntity.myMeshName.c_str());
553     if(MYDEBUG) 
554       MESSAGE("LoadCellsOnEntity - theMeshOnEntity.myEntity = "<<theMeshOnEntity.myEntity<<
555               "; iGeomElemEnd = "<<iGeomElemEnd<<"; theFamilyName = '"<<theFamilyName<<"'");
556     VISU::TMesh &aMesh = myMeshMap[theMeshOnEntity.myMeshName];
557     int aNbPoints = aMesh.myPointsCoord.size()/aMesh.myDim;
558     valarray<med_int>  num_node(aNbPoints);
559     med_booleen inum_node = 
560       med_booleen(MEDnumLire(fid,aMeshName,&num_node[0],aNbPoints,MED_NOEUD,med_geometrie_element(0)) >= 0);
561     if(MYDEBUG) MESSAGE("LoadCellsOnEntity - inum_node = "<<inum_node);
562     inum_node = MED_FAUX;
563     map<med_int,med_int> node_map;
564     if(inum_node) 
565       for(int i = 0; i < aNbPoints; i++) 
566         node_map[num_node[i]-1] = i;
567     for (int iGeomElem = 0; iGeomElem < iGeomElemEnd; iGeomElem++) {
568       int medId = getIdMedType(aGeomElemVector[iGeomElem]);
569       int nbMedNodes = med2vtk[medId].medNbNodes;
570       int nbVtkNodes = med2vtk[medId].vtkNbNodes;
571       int aVtkType = med2vtk[medId].vtkType;
572       med_geometrie_element aMedType = med2vtk[medId].medType;
573       med_int iNumElemEnd = MEDnEntMaa(fid,aMeshName,MED_CONN,aMedEntity,aMedType,MED_NOD);
574       if (iNumElemEnd > 0) {
575         med_booleen iname_elem, inum_elem;
576         valarray<med_int> num_elem(iNumElemEnd), num_fam_elem(iNumElemEnd);
577         valarray<char> name_elem('\0',iNumElemEnd*MED_TAILLE_PNOM+1);
578         med_int aNbConnForElem = getNbMedConnect(aMedType,anEntity,aMesh.myDim);
579         if(MYDEBUG) MESSAGE("LoadCellsOnEntity - medName = "<<med2vtk[medId].medName<<
580                             "; iNumElemEnd = "<<iNumElemEnd<<"; aNbConnForElem = "<<aNbConnForElem);
581         valarray<med_int> conn(aNbConnForElem*iNumElemEnd);
582         ret = MEDelementsLire(fid,aMeshName,aMesh.myDim,&conn[0],MED_FULL_INTERLACE,
583                               &name_elem[0],&iname_elem,&num_elem[0],&inum_elem,
584                               &num_fam_elem[0],iNumElemEnd,aMedEntity,aMedType,MED_NOD);
585         if (ret < 0) throw std::runtime_error(EXCEPTION("LoadCellsOnEntity >> MEDelementsLire(...)"));
586         if(!isCellsLoaded){
587           VISU::TMeshOnEntity::TConnForCellType& aConnForCellType = theMeshOnEntity.myCellsConn[aVtkType];
588           aConnForCellType.resize(iNumElemEnd);
589           valarray<med_int> aConnect(nbMedNodes);
590           for (int iNumElem = 0; iNumElem < iNumElemEnd; iNumElem++) {
591             VISU::TMeshOnEntity::TConnect& anArray = aConnForCellType[iNumElem];
592             anArray.resize(nbVtkNodes);
593             if(inum_node)
594               for (int k = 0, kj = iNumElem*aNbConnForElem; k < nbMedNodes; k++)
595                 aConnect[k] = node_map[conn[kj+k]-1];
596             else
597               for (int k = 0, kj = iNumElem*aNbConnForElem; k < nbMedNodes; k++)
598                 aConnect[k] = conn[kj+k] - 1;
599             switch(aMedType){
600             case MED_TETRA4 :
601             case MED_TETRA10 :
602               anArray[0] = aConnect[0];
603               anArray[1] = aConnect[1];
604               anArray[2] = aConnect[3];  
605               anArray[3] = aConnect[2];  
606               break;
607             case MED_PYRA5 :
608             case MED_PYRA13 :
609               anArray[0] = aConnect[0];
610               anArray[1] = aConnect[3];  
611               anArray[2] = aConnect[2];
612               anArray[3] = aConnect[1];  
613               anArray[4] = aConnect[4];
614               break;
615             default:
616               for (int k = 0; k < nbVtkNodes; k++) 
617                 anArray[k] = aConnect[k];
618             }
619             for (int k = 0; k < nbVtkNodes; k++) 
620               if(anArray[k] < 0 || aNbPoints <= anArray[k])
621                 throw std::runtime_error(EXCEPT("ImportCells >> aNbPoints(%1) <= anArray[%2][%3](%4) < 0").
622                                          arg(aNbPoints).arg(iNumElem).arg(k).arg(anArray[k]).latin1());
623           }
624         }
625         //Filling aFamily SubMesh
626         if(isFamilyPresent){
627           VISU::TFamily::TSubMeshOnCellType& aSubMeshOnCellType = aFamily.mySubMesh[aVtkType];
628           for (int iNumElem = 0; iNumElem < iNumElemEnd; iNumElem++) 
629             if(num_fam_elem[iNumElem] == aFamily.myId)
630               aSubMeshOnCellType.insert(iNumElem);
631         }
632       }
633     }
634     return 1;
635   }catch(std::runtime_error& exc){
636     theMeshOnEntity.myCellsConn.clear();
637     throw std::runtime_error(exc.what());
638   }catch(...){
639     theMeshOnEntity.myCellsConn.clear();
640     throw std::runtime_error(EXCEPTION("Unknown exception !!!"));
641   }
642   return 0;
643 }
644
645 int VISU_MedConvertor::LoadField(const med_idt& fid, const VISU::TMeshOnEntity& theMeshOnEntity,
646                                  VISU::TField& theField, VISU::TField::TValForTime& theValForTime)
647 {
648   //Check on loading already done
649   if(!theValForTime.myValForCells.empty()) return 0;
650   //Main part of code
651   med_int ncomp = MEDnChamp(fid,theField.myId);
652   if(ncomp < 0) throw std::runtime_error(EXCEPTION("LoadField >> MEDnChamp(fid,i)"));
653   valarray<char> comp('\0',ncomp*MED_TAILLE_PNOM + 1);
654   valarray<char> unit('\0',ncomp*MED_TAILLE_PNOM + 1);
655   char aFieldName[MED_TAILLE_NOM + 1] = "";
656   char aMeshName[MED_TAILLE_NOM+1] = "";
657   strcpy(aMeshName,theValForTime.myMeshName.c_str());
658   med_type_champ type_field;
659   if(MEDchampInfo(fid,theField.myId,aFieldName,&type_field,&comp[0],&unit[0],ncomp) < 0)
660     throw std::runtime_error(EXCEPTION("LoadField >> MEDchampInfo(...)"));
661   int iGeomElemEnd;
662   med_geometrie_element* aGeomElemVector;
663   const VISU::TEntity& anEntity = theField.myEntity;
664   GetEntity2Geom(anEntity,aGeomElemVector,&iGeomElemEnd);
665   med_entite_maillage& aMedEntity = aVisu2MedEntity[anEntity];
666   const VISU::TMeshOnEntity::TCellsConn& aCellsConn = theMeshOnEntity.myCellsConn;
667   if(MYDEBUG){
668     MESSAGE("LoadField - aMeshName = '"<<aMeshName<<"' aFieldName = '"<<aFieldName<<"'; anEntity = "<<anEntity);
669     MESSAGE("LoadField - iGeomElemEnd = "<<iGeomElemEnd<<"; ncomp = "<<ncomp<<"; type_field = "<<type_field);
670   }
671   for (int iGeomElem = 0; iGeomElem < iGeomElemEnd; iGeomElem++) {
672     const med_geometrie_element& aGeom = aGeomElemVector[iGeomElem];
673     med_int iTimeStampEnd = MEDnPasdetemps(fid,aFieldName,aMedEntity,aGeom);
674     //Checking for accordance between the mesh and the field data
675     med_int iNumElemEnd = 0;
676     if(aMedEntity == MED_NOEUD)
677       iNumElemEnd = MEDnEntMaa(fid,aMeshName,MED_COOR,MED_NOEUD,med_geometrie_element(0),med_connectivite(0));
678     else
679       iNumElemEnd = MEDnEntMaa(fid,aMeshName,MED_CONN,aMedEntity,aGeom,MED_NOD);
680     int medId = getIdMedType(aGeomElemVector[iGeomElem]);
681     int aVtkType = med2vtk[medId].vtkType;
682     if(iTimeStampEnd <= 0){
683       if(iNumElemEnd > 0){
684         if(!theField.myIsTrimmed){
685           theField.myIsTrimmed = true;
686           theField.myDataSize -= iNumElemEnd*theField.myNbComp;
687         }
688         //throw std::runtime_error(EXCEPT("VISU_MedConvertor::LoadField - There is no the data "
689         //                              "for cells with type %1 of the mesh !!!").
690         //                       arg(med2vtk[medId].medName).latin1());
691       }
692     }else{
693       med_int ngauss = 0, numdt = 0, numo = 0;
694       char dt_unit[MED_TAILLE_PNOM+1] = "";
695       med_float dt = 0;
696       ret = MEDpasdetempsInfo(fid,aFieldName,aMedEntity,aGeom,theValForTime.myId,
697                               aMeshName,&ngauss,&numdt,dt_unit,&dt,&numo);
698       if(ret < 0) throw std::runtime_error(EXCEPTION("LoadField >> MEDpasdetempsInfo(...)"));
699       med_int nval = MEDnVal(fid,aFieldName,aMedEntity,aGeom,numdt,numo);
700       if(nval <= 0) throw std::runtime_error(EXCEPTION("LoadField >> MEDnVal(...) - nval <= 0"));
701       else{
702         //Checking for accordance between the mesh and the field data
703         if(iNumElemEnd <= 0) 
704           throw std::runtime_error(EXCEPTION("LoadField - There is no the geom. elem. on the mesh !!!"));
705         static int aMaxNbGaussPts = 52;  // the workaround for broken files
706         if(ngauss > aMaxNbGaussPts) ngauss = 1;
707         if(iNumElemEnd*ngauss != nval) 
708           throw std::runtime_error(EXCEPT("LoadField - Size of values (%1) and size of mesh (%2) not equal !!!").
709                                    arg(nval).arg(iNumElemEnd*ngauss).latin1());
710         VISU::TField::TValForCellsWithType &anArray = theValForTime.myValForCells[aVtkType];
711         int jEnd = theField.myNbComp*nval;
712         int kEnd = jEnd/ngauss;
713         anArray.resize(kEnd);
714         char pflname[MED_TAILLE_NOM + 1] = "";
715         switch(type_field){
716         case MED_REEL64 : {
717           valarray<med_float> valr(jEnd);
718           ret = MEDchampLire(fid,aMeshName,aFieldName,(unsigned char*)&valr[0],MED_FULL_INTERLACE,MED_ALL,
719                              pflname,aMedEntity,aGeom,numdt,numo);
720           if(ret < 0) throw std::runtime_error(EXCEPTION("LoadField >> MEDchampLire(...)"));
721           for (med_int k = 0, j = 0; k < kEnd; k++, j += ngauss){
722             for (med_int iGauss = 0; iGauss < ngauss; iGauss++)
723               anArray[k] = valr[j+iGauss];
724             anArray[k] /= ngauss;
725           }
726           break;
727         }
728         //case MED_INT64 : //valarray<long long> valr(jEnd);
729         case MED_INT32 : //valarray<long int> valr(jEnd);
730         case MED_INT : {
731           valarray<med_int> valr(jEnd);
732           ret = MEDchampLire(fid,aMeshName,aFieldName,(unsigned char*)&valr[0],MED_FULL_INTERLACE,MED_ALL,
733                              pflname,aMedEntity,aGeom,numdt,numo);
734           if(ret < 0) throw std::runtime_error(EXCEPTION("LoadField >> MEDchampLire(...)"));
735           for (med_int k = 0, j = 0; k < kEnd; k++, j += ngauss){
736             for (med_int iGauss = 0; iGauss < ngauss; iGauss++)
737               anArray[k] = valr[j+iGauss];
738             anArray[k] /= ngauss;
739           }
740           break;
741         }
742         default :
743           throw std::runtime_error(EXCEPTION("LoadField >> Value of med_type_champ for the field is wrong !!!"));
744         }
745         if(MYDEBUG) MESSAGE("LoadField - aGeom = "<<aGeom<<"; nval = "<<nval<<"; ngauss = "<<ngauss
746                             <<"; iTimeStampEnd = "<<iTimeStampEnd<<"; pflname = '"<<pflname<<"'");
747       }
748     }
749   }
750   return 1; 
751 }