Salome HOME
Merge from BR_V5_DEV 16Feb09
[modules/med.git] / src / MULTIPR / MULTIPR_Utils.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_Utils.cxx
23  *
24  * \brief   see MULTIPR_Utils.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_Utils.hxx"
36 #include "MULTIPR_Exceptions.hxx"
37 #include "MULTIPR_Mesh.hxx"
38
39 #include <iostream>
40
41 using namespace std;
42
43 //*****************************************************************************
44 // Implementation
45 //*****************************************************************************
46
47 void multipr::trim(char* pStr, char pChar)
48 {
49     int len = strlen(pStr) - 1;
50     int p = len;
51     while (pStr[p] == pChar)
52     {
53         p--;
54     }
55     if (p != len)
56     {
57         pStr[p + 1] = '\0';
58     }
59 }
60
61
62 bool multipr::startsWith(const char* pStr, const char* pStrPrefix)
63 {
64     int i = 0;
65     while ((pStr[i] != '\0') && (pStrPrefix[i] != '\0') && (pStr[i] == pStrPrefix[i]))
66     {
67         i++;
68     }
69     return (pStrPrefix[i] == '\0');
70 }
71
72
73 string multipr::removeExtension(const char* pFilename, const char* pExtension)
74 {
75     string strPrefix(pFilename); 
76     strPrefix.erase(strPrefix.rfind(pExtension), strlen(pExtension));
77     
78     return strPrefix;
79 }
80
81
82 string multipr::getFilenameWithoutPath(const char* pFilename)
83 {
84     char* res = strrchr(pFilename, '/');
85     if (res == NULL)
86     {
87         return pFilename;
88     }
89     else
90     {
91         char* name = res + 1;
92         return name;
93     }
94 }
95
96
97 string multipr::getPath(const char* pFilename)
98 {
99   // find (reverse) the first occurrence of '/' in the given string
100   std::string aFilename(pFilename);
101   std::string::size_type aPos = aFilename.rfind('/');
102
103   if ( aPos == std::string::npos )
104     return "";
105
106   aFilename = aFilename.substr( 0, aPos + 1 );
107   while ( true ) {
108     aPos = aFilename.find( "//" );
109
110     if ( aPos == std::string::npos )
111       break;
112
113     aFilename.replace( aPos, 2, "/" );
114   }
115
116   return aFilename;
117 }
118
119
120 void multipr::copyFile(const char* pFilename, const char* pDestDir)
121 {
122     std::string srcDir = multipr::getPath(pFilename);
123     if (strcmp(srcDir.c_str(), pDestDir) == 0) return;
124
125     std::string filenameWithoutPath = multipr::getFilenameWithoutPath(pFilename);
126     std::string pDstFilename (pDestDir);
127     pDstFilename += filenameWithoutPath;
128
129     // open binary source file
130     FILE* src = fopen(pFilename, "rb");
131     if (src == NULL) return;
132
133     // open (create) binary destination file
134     FILE* dst = fopen(pDstFilename.c_str(), "wb");
135     if (dst == NULL) return;
136
137     const int size = 65536; // size of buffer is 64Kb
138     char* buf = new char[size];
139     int ret;
140     ret = fread(buf, 1, size, src);
141     while (ret != 0)
142     {
143         fwrite(buf, 1, ret, dst); // write to destination
144         ret = fread(buf, 1, size, src); // read from source
145     }
146
147     delete[] buf;
148     fclose(src);
149     fclose(dst);
150 }
151
152
153 void multipr::printArray2D(
154      const med_float* pData, 
155     const int        pNumElt,
156     const int        pDimElt,
157     const char*      pPrefix)
158 {
159     for (int itElt = 0 ; itElt < pNumElt ; itElt++)
160     {
161         cout << pPrefix << " " << (itElt + 1) << ": ";
162         for (int itDim = 0 ; itDim < pDimElt ; itDim++)
163         {
164             cout << pData[itElt * pDimElt + itDim] << " ";
165         }
166         cout << endl;
167     }
168 }
169
170
171 string multipr::realToString(med_float mV)
172 {
173     char str[32];
174     sprintf(str, "%lf", mV);
175     trim(str, '0');
176     int len = strlen(str);
177     if (str[len - 1] == '.')
178     {
179         str[len] = '0';
180         str[len + 1] = '\0';
181     }
182     return string(str);
183 }
184
185
186 vector<string> multipr::getListMeshes(const char* pMEDfilename)
187 {
188     if (pMEDfilename == NULL) throw multipr::NullArgumentException("", __FILE__, __LINE__);
189     
190     vector<string> res;
191     med_err ret;
192     
193     //---------------------------------------------------------------------
194     // Open MED file (READ_ONLY)
195     //---------------------------------------------------------------------
196     med_idt file = MEDouvrir(const_cast<char*>(pMEDfilename), MED_LECTURE); // open MED file for reading
197     if (file <= 0) throw multipr::IOException("MED file not found or not a sequential MED file", __FILE__, __LINE__);
198     
199     //---------------------------------------------------------------------
200     // Read name of meshes
201     //---------------------------------------------------------------------
202     med_int nbMeshes = MEDnMaa(file);
203     if (nbMeshes <= 0) throw multipr::IOException("i/o error while reading number of meshes in MED file", __FILE__, __LINE__);    
204     
205     // for each mesh in the file (warning: first mesh is number 1)
206     for (int itMesh = 1 ; itMesh <= nbMeshes ; itMesh++)
207     {
208         char meshName[MED_TAILLE_NOM + 1];
209         
210         med_int meshDim;
211         med_maillage meshType;
212         char meshDesc[MED_TAILLE_DESC + 1]; 
213         
214         ret = MEDmaaInfo(
215             file, 
216             itMesh, 
217             meshName, 
218             &meshDim, 
219             &meshType, 
220             meshDesc);
221             
222         if (ret != 0) throw multipr::IOException("i/o error while reading mesh information in MED file", __FILE__, __LINE__);
223         
224         res.push_back(meshName);
225     }
226     
227     //---------------------------------------------------------------------
228     // Close the MED file
229     //---------------------------------------------------------------------
230     ret = MEDfermer(file);
231     if (ret != 0) throw multipr::IOException("i/o error while closing MED file", __FILE__, __LINE__);
232     
233     return res;
234 }
235
236
237 void multipr::getListScalarFields(const char* pMEDfilename, vector<pair<string, int> >& pFields, bool pAddNbGaussPoint, const char *pMeshName)
238 {
239     if (pMEDfilename == NULL) throw multipr::NullArgumentException("", __FILE__, __LINE__);
240     med_err ret;
241     med_int ngauss = 0;
242     bool    isOnNodes = true;
243     //---------------------------------------------------------------------
244     // Open MED file (READ_ONLY)
245     //---------------------------------------------------------------------
246     med_idt file = MEDouvrir(const_cast<char*>(pMEDfilename), MED_LECTURE); // open MED file for reading
247     if (file <= 0) throw multipr::IOException("MED file not found or not a sequential MED file", __FILE__, __LINE__);
248
249     //---------------------------------------------------------------------
250     // Read number of fields
251     //---------------------------------------------------------------------
252     med_int numFields = MEDnChamp(file, 0);
253     if (numFields < 0) throw IOException("Can't read number of fields.", __FILE__, __LINE__);
254     if (numFields == 0)
255     {
256         return ;
257     }
258
259     //---------------------------------------------------------------------
260     // For each field, read its name
261     //---------------------------------------------------------------------
262     for (int itField = 1 ; itField <= numFields ; itField++)
263     {
264         char*           name = new char[MED_TAILLE_NOM + 1024];
265         med_type_champ  type;
266         med_int         numComponents = MEDnChamp(file, itField);
267         
268         if (numComponents < 0) throw IOException("Number of component less than zero.", __FILE__, __LINE__);
269         
270         // collect scalar field only (not vectorial fields)
271         if (numComponents != 1)
272         {
273             continue;
274         }
275         // temporary buffers
276         char* strComponent = new char[numComponents * MED_TAILLE_PNOM + 1];
277         char* strUnit      = new char[numComponents * MED_TAILLE_PNOM + 1];
278         strComponent[0] = '\0';
279         strUnit[0] = '\0';
280         
281         // Get field info.
282         med_err ret = MEDchampInfo(
283             file, 
284             itField, 
285             name, 
286             &(type), 
287             strComponent, 
288             strUnit, 
289             numComponents);
290         delete[] strUnit;
291         delete[] strComponent;
292         if (ret != 0) throw IOException("Can't get information on a field.", __FILE__, __LINE__);
293         
294         // Get number of time step on nodes.
295         med_int numTimeStamps = MEDnPasdetemps(
296             file, 
297             name, 
298             MED_NOEUD, 
299             (med_geometrie_element) 0);
300         if (numTimeStamps < 0) throw IOException("Can't get number of time steps on nodes", __FILE__, __LINE__);
301         
302         // Get the number of time step on elements.
303         if (numTimeStamps == 0)
304         {
305             for (int i = 0; i < eMaxMedMesh; ++i)
306             {
307                 numTimeStamps = MEDnPasdetemps(
308                     file, 
309                     name, 
310                     MED_MAILLE, 
311                     CELL_TYPES[i]);
312                 if (numTimeStamps > 0)
313                 {
314                     isOnNodes = false;
315                     break;
316                 }
317             }
318         }
319
320         if (numTimeStamps  < 0) throw IOException("Can't get number of time steps on elements", __FILE__, __LINE__);    
321         // For GUI only : add the nomber of gauss points to the string.
322         if (pAddNbGaussPoint == true && pMeshName != NULL)
323         {
324             char*       tmp = new char[1024];
325             char*       tmp2 = new char[1024];
326             med_booleen local;
327             med_int     numdt, numo, nmaa;
328             med_float   dt;
329             med_int     nb_values = -1;
330
331             if (isOnNodes)
332             {
333                 // Get number of gauss points on nodes.
334                 ret = MEDpasdetempsInfo(file, name, MED_NOEUD, (med_geometrie_element) 0, 1, &ngauss, &numdt, &numo, tmp2, &dt, tmp, &local, &nmaa);
335                 nb_values = MEDnVal(file, name, MED_NOEUD,(med_geometrie_element) 0, numdt, numo, const_cast<char*>(pMeshName), MED_COMPACT);
336             }
337             else
338             {
339                 // Get number of gauss points on elements.
340                 // For each geometry type.
341                 for (int itCell = 0 ; itCell < eMaxMedMesh ; ++itCell)
342                 {
343                     tmp[0] = '\0';
344                     // For each time step.
345                     for (int j = 1; j <= numTimeStamps; ++j)
346                     {
347                         ret = MEDpasdetempsInfo(file, name, MED_MAILLE, const_cast<med_geometrie_element*>(CELL_TYPES)[itCell], j, &ngauss, &numdt, &numo, tmp2, &dt, tmp, &local, &nmaa);
348                         // If we can get info on this field, it must exist.
349                         if (ret == 0)
350                         {
351                             nb_values = MEDnVal(file, name, MED_MAILLE,const_cast<med_geometrie_element*>(CELL_TYPES)[itCell], numdt, numo, const_cast<char*>(pMeshName), MED_COMPACT);
352                             if (nb_values > 0)
353                             {
354                                 break;
355                             }
356                         }
357                     }
358                     // We got what we need : don't need to go further.
359                     if (ret == 0)
360                     {
361                         break;
362                     }
363                     
364                 }
365             }
366             tmp[0] = '\0';
367             sprintf(tmp, "%s : %d gauss points", name, nb_values);
368             sprintf(name, "%s", tmp);
369         }
370
371         // add the pair(name, #time stamps) to the result
372         pFields.push_back(make_pair(name, numTimeStamps));
373     }
374         
375     //---------------------------------------------------------------------
376     // Close the MED file
377     //---------------------------------------------------------------------
378     ret = MEDfermer(file);
379     if (ret != 0) throw multipr::IOException("i/o error while closing MED file", __FILE__, __LINE__);
380 }
381
382
383 // EOF