]> SALOME platform Git repositories - modules/multipr.git/blob - src/MULTIPR/MULTIPR_Obj.cxx
Salome HOME
*** empty log message ***
[modules/multipr.git] / src / MULTIPR / MULTIPR_Obj.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_Obj.cxx
6  *
7  * \brief   see MULTIPR_Obj.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_Obj.hxx"
19 #include "MULTIPR_Exceptions.hxx"
20 #include "MULTIPR_Mesh.hxx"
21 #include "MULTIPR_MeshDis.hxx"
22 #include "MULTIPR_Utils.hxx"
23
24 #include <stdio.h>
25 #include <iostream>
26
27 using namespace std;
28
29
30 namespace multipr
31 {
32
33
34 //*****************************************************************************
35 // Class Obj implementation
36 //*****************************************************************************
37
38 Obj::Obj() 
39 {
40     mMeshDis = NULL;
41     
42     reset(); 
43 }
44
45
46 Obj::~Obj()  
47
48     reset();  
49 }
50
51
52 void Obj::reset() 
53
54     mMEDfilename     = "";
55     mMeshName        = "";
56     mState           = MULTIPR_OBJ_STATE_RESET;
57     
58     if (mMeshDis != NULL) { delete mMeshDis; mMeshDis = NULL; }
59 }
60
61
62 void Obj::create(const char* pMEDfilename)
63 {
64     if (pMEDfilename == NULL) throw multipr::NullArgumentException("file name must not be NULL", __FILE__, __LINE__);
65     
66     // reset everything before associating a new MED file to this object
67     reset();
68     
69     mMEDfilename = pMEDfilename;
70     
71     // check if file exists
72     FILE* f = fopen(pMEDfilename, "rb");
73     if (f == 0) 
74     {
75         // file does not exist
76         mState = MULTIPR_OBJ_STATE_ERROR;
77         throw FileNotFoundException("file not found", __FILE__, __LINE__);
78     }
79     fclose(f);
80     
81     // test whether it is a sequential MED file or a distributed MED file
82     med_idt file = MEDouvrir(const_cast<char*>(pMEDfilename), MED_LECTURE); // open sequential MED file for reading
83     if (file > 0)
84     {
85         // sequential MED file has been sucessfuly openened
86         
87         // CASE 1: sequential MED file
88         med_int ret = MEDfermer(file);
89         
90         if (ret != 0) 
91         {
92             // error while closing sequential MED file
93             mState = MULTIPR_OBJ_STATE_ERROR;
94             throw multipr::IOException("i/o error while closing MED file", __FILE__, __LINE__);
95         }
96         
97         mState = MULTIPR_OBJ_STATE_SEQ_INIT;
98         cout << "Sequential MED file " << pMEDfilename << " has been successfuly opened" << endl;
99     }
100     else
101     {
102         // CASE 2: distributed MED file?
103         try
104         {
105             mMeshDis = new multipr::MeshDis();
106             mMeshDis->readDistributedMED(pMEDfilename);
107         
108             mState = MULTIPR_OBJ_STATE_DIS;
109             cout << "Distributed MED file " << pMEDfilename << " has been successfuly opened" << endl;
110         }
111         catch (...)
112         {
113             // neither a sequential MED file, nor a distributed MED file => error
114             mState = MULTIPR_OBJ_STATE_ERROR;
115             throw IOException("file is nor a sequential MED file, neither a distributed MED file", __FILE__, __LINE__);
116         }
117     }
118 }
119
120
121 std::string Obj::getSequentialMEDFilename() const
122 {
123     // partitionneGrain() is only available for distributed MED file (not sequential MED file)
124     if ((mState != MULTIPR_OBJ_STATE_DIS_MEM) &&
125         (mState != MULTIPR_OBJ_STATE_DIS)) throw IllegalStateException("unexpected operation", __FILE__, __LINE__);
126     
127         return mMeshDis->getSequentialMEDFilename();
128 }
129
130
131 void Obj::setMesh(const char* pMeshName)
132 {
133     // setMesh() is only available for sequential MED file (not distributed MED file)
134     if ((mState != MULTIPR_OBJ_STATE_SEQ_INIT) &&
135         (mState != MULTIPR_OBJ_STATE_SEQ)) throw IllegalStateException("expected a sequential MED file", __FILE__, __LINE__);
136     
137     mMeshName = pMeshName;
138     
139     // change state to MULTIPR_OBJ_STATE_SEQ (in case of state=MULTIPR_OBJ_STATE_SEQ_INIT)
140     mState = MULTIPR_OBJ_STATE_SEQ;
141 }
142
143
144 vector<string> Obj::getMeshes() const
145 {
146     // test whether it is a sequential MED file or a distributed MED file
147     if ((mState == MULTIPR_OBJ_STATE_SEQ_INIT) ||
148         (mState == MULTIPR_OBJ_STATE_SEQ))
149     {
150         // CASE 1: sequential MED file
151         return multipr::getListMeshes(mMEDfilename.c_str());
152     }
153     else
154     {
155         // CASE 2: distributed MED file
156         if (mMeshDis == NULL)
157         {
158             throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
159         }
160         
161         return mMeshDis->getMeshes();
162     }
163 }
164
165
166 vector<string> Obj::getFields() const
167 {
168     // test whether it is a sequential MED file or a distributed MED file
169     if ((mState == MULTIPR_OBJ_STATE_SEQ_INIT) ||
170         (mState == MULTIPR_OBJ_STATE_SEQ)) 
171     {
172         // CASE 1: sequential MED file
173         vector<pair<string, int> > tmp = multipr::getListScalarFields(mMEDfilename.c_str());
174         
175         vector<string> res;
176         for (int i = 0 ; i < tmp.size() ; i++)
177         {
178             res.push_back(tmp[i].first);
179         }
180         
181         return res;
182     }
183     else
184     {
185         // CASE 2: distributed MED file
186         if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
187         
188         return mMeshDis->getFields();
189     }
190 }
191
192
193 int Obj::getTimeStamps(const char* pFieldName) const
194 {
195     // test whether it is a sequential MED file or a distributed MED file
196     if ((mState == MULTIPR_OBJ_STATE_SEQ_INIT) ||
197         (mState == MULTIPR_OBJ_STATE_SEQ)) 
198     {
199         // CASE 1: sequential MED file
200         vector<pair<string, int> > tmp = multipr::getListScalarFields(mMEDfilename.c_str());
201     
202         for (int i = 0 ; i < tmp.size() ; i++)
203         {
204             if (strcmp(tmp[i].first.c_str(), pFieldName) == 0)
205             {
206                 return tmp[i].second;
207             }
208         }
209         
210         // pFieldName not found in the list of fields
211         return 0;
212     }
213     else
214     {
215         // CASE 2: distributed MED file
216         if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
217         
218         return mMeshDis->getTimeStamps(pFieldName);
219     }
220 }
221
222
223 vector<string> Obj::getParts() const
224 {
225     // getParts() is only available for distributed MED file (not sequential MED file)
226     if ((mState != MULTIPR_OBJ_STATE_DIS) &&
227         (mState != MULTIPR_OBJ_STATE_DIS_MEM)) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__);
228     
229     return getListParts();
230 }
231
232
233 string Obj::getPartInfo(const char* pPartName) const
234 {
235     // getParts() is only available for distributed MED file (not sequential MED file)
236     if ((mState != MULTIPR_OBJ_STATE_DIS) &&
237         (mState != MULTIPR_OBJ_STATE_DIS_MEM)) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__);
238     
239     if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
240     
241     return mMeshDis->getPartInfo(pPartName);
242     
243 }
244
245
246 void Obj::removeParts(const char* pPrefixPartName)
247 {
248     // removePart() is only available for distributed MED file (not sequential MED file)
249     if ((mState != MULTIPR_OBJ_STATE_DIS) &&
250         (mState != MULTIPR_OBJ_STATE_DIS_MEM)) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__);
251         
252     if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
253     
254     mMeshDis->removeParts(pPrefixPartName);
255     mState = MULTIPR_OBJ_STATE_DIS_MEM;
256 }
257
258
259 vector<string> Obj::partitionneDomaine()
260 {
261     if (mState == MULTIPR_OBJ_STATE_SEQ_INIT) throw IllegalStateException("use setMesh() before", __FILE__, __LINE__);
262     
263     // partitionneDomaine() is only available for sequential MED file (not distributed MED file)
264     if (mState != MULTIPR_OBJ_STATE_SEQ) throw IllegalStateException("unexpected operation", __FILE__, __LINE__);
265     
266     //-------------------------------------------------------------
267     // Read the sequential mesh
268     //-------------------------------------------------------------
269     cout << "Read sequential MED file: " << mMEDfilename << ": please wait... " << endl;
270     
271     Mesh mesh;
272     mesh.readSequentialMED(mMEDfilename.c_str(), mMeshName.c_str());
273     cout << mesh << endl;
274     
275     //-------------------------------------------------------------
276     // Build distributed mesh from groups
277     //-------------------------------------------------------------
278     cout << "Build distributed mesh: please wait... " << endl;
279     try
280     {
281         mMeshDis = mesh.splitGroupsOfElements();
282     }
283     catch (RuntimeException& e)
284     {
285         delete mMeshDis;
286         mMeshDis = NULL;
287         throw e;
288     }
289     
290     mState = MULTIPR_OBJ_STATE_DIS_MEM;
291     
292     return getListParts();
293 }
294
295
296 vector<string> Obj::partitionneGrain(
297     const char* pPartName, 
298     int         pNbParts, 
299     int         pPartitionner)
300 {
301     if (mMeshDis == NULL) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__);
302     if (pPartName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
303     if (pNbParts < 2) throw IllegalArgumentException("", __FILE__, __LINE__);
304     if ((pPartitionner != 0) && (pPartitionner != 1)) throw IllegalArgumentException("partitionner should be 0=METIS or 1=SCOTCH", __FILE__, __LINE__);
305
306     // partitionneGrain() is only available for distributed MED file (not sequential MED file)
307     if ((mState != MULTIPR_OBJ_STATE_DIS_MEM) &&
308         (mState != MULTIPR_OBJ_STATE_DIS)) throw IllegalStateException("unexpected operation", __FILE__, __LINE__);
309     
310     // if distributed MED file is currently in memory, then write to disk before performing partitionneGrain()
311     // (because MEDSPLIITER starts from a file)
312     if (mState == MULTIPR_OBJ_STATE_DIS_MEM)
313     {
314         //-----------------------------------------------------
315         // Write distributed mesh
316         //-----------------------------------------------------
317         cout << "Write distributed mesh: please wait... " << endl;
318         string strPrefix = removeExtension(mMEDfilename.c_str(), ".med");
319         mMeshDis->writeDistributedMED(strPrefix.c_str());
320         
321         mMEDfilename = mMeshDis->getDistributedMEDFilename();
322         
323         delete mMeshDis;
324         
325         //---------------------------------------------------------------------
326         // Read the distributed mesh
327         //---------------------------------------------------------------------    
328         int ret = MEDformatConforme(mMEDfilename.c_str());
329         if (ret == 0) throw IOException("waiting for a distributed MED file (not a sequential one)", __FILE__, __LINE__);
330     
331         mMeshDis = new MeshDis();
332         mMeshDis->readDistributedMED(mMEDfilename.c_str());
333         
334         mState = MULTIPR_OBJ_STATE_DIS;
335     }
336
337     //---------------------------------------------------------------------
338     // Split the given part (pGroupName)
339     //---------------------------------------------------------------------
340     mMeshDis->splitPart(pPartName, pNbParts, pPartitionner);
341     cout << mMeshDis << endl;
342
343     //---------------------------------------------------------------------
344     // Write new distributed mesh
345     //---------------------------------------------------------------------
346     string strPrefix = multipr::removeExtension(mMEDfilename.c_str(), ".med");
347     mMeshDis->writeDistributedMED(strPrefix.c_str());
348     
349     //---------------------------------------------------------------------
350     // Read the distributed mesh
351     //---------------------------------------------------------------------
352     delete mMeshDis;
353     mMeshDis = new MeshDis();
354     //cout << "read dis MED file: filename=" << mMEDfilename << endl;
355     mMeshDis->readDistributedMED(mMEDfilename.c_str());
356     
357     return getListParts();
358 }
359
360
361 vector<string> Obj::decimePartition(
362     const char* pPartName,
363     const char* pFieldName,
364     int         pFieldIt,
365     const char* pFilterName,
366     double      pTmed,
367     double      pTlow,
368     double      pRadius,
369     int         pBoxing)
370 {
371     
372     // decimePartition() is only available for distributed MED file (not sequential MED file)
373     if ((mState != MULTIPR_OBJ_STATE_DIS_MEM) &&
374         (mState != MULTIPR_OBJ_STATE_DIS)) throw IllegalStateException("unexpected operation", __FILE__, __LINE__);
375         
376     if (mMeshDis == NULL) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__);
377     
378     //---------------------------------------------------------------------
379     // Decimate
380     //---------------------------------------------------------------------
381     mMeshDis->decimatePart(
382         pPartName, 
383         pFieldName,
384         pFieldIt,
385         pFilterName,
386         pTmed,
387         pTlow,
388         pRadius,
389         pBoxing);
390         
391     mState = MULTIPR_OBJ_STATE_DIS_MEM;
392     
393     return getListParts();
394 }
395
396
397 string Obj::evalDecimationParams(
398     const char* pPartName, 
399     const char* pFieldName, 
400     int         pFieldIt, 
401     const char* pFilterName,
402     const char* pFilterParams)
403 {
404     // decimePartition() is only available for distributed MED file (not sequential MED file)
405     if ((mState != MULTIPR_OBJ_STATE_DIS_MEM) &&
406         (mState != MULTIPR_OBJ_STATE_DIS)) throw IllegalStateException("unexpected operation", __FILE__, __LINE__);
407         
408     if (mMeshDis == NULL) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__);
409     
410     string res = mMeshDis->evalDecimationParams(
411         pPartName,
412         pFieldName,
413         pFieldIt,
414         pFilterName,
415         pFilterParams);
416     
417     return res;
418 }
419
420
421 vector<string> Obj::getListParts() const
422 {
423     if (mMeshDis == NULL) throw IllegalStateException("not a distributed mesh", __FILE__, __LINE__);
424     
425     vector<string> names;
426     
427     int numParts = mMeshDis->getNumParts();
428     for (int i = 0 ; i < numParts ; i++)
429     {
430         names.push_back( mMeshDis->getPart(i)->getPartName() );
431     }
432     
433     return names;
434 }
435
436
437 void Obj::save(const char* pPath)
438 {
439     static string prevPath = "";
440     
441     // only save file if it is a distributed MED file currently in memory or path has changed
442     if ((mState == MULTIPR_OBJ_STATE_DIS_MEM) || (strcmp(pPath, prevPath.c_str()) != 0))
443     {
444         prevPath = pPath;
445         
446         //-------------------------------------------------------------
447         // Write new distributed mesh
448         //-------------------------------------------------------------
449         string filename;
450         if (strlen(pPath) == 0)
451         {
452             filename = multipr::removeExtension(mMEDfilename.c_str(), ".med");
453         }
454         else
455         {
456             filename = string(pPath) + string("/") + multipr::getFilenameWithoutPath(mMEDfilename.c_str());
457         }
458         string strPrefix = multipr::removeExtension(filename.c_str(), ".med");
459         mMeshDis->writeDistributedMED(strPrefix.c_str());
460         mMEDfilename = mMeshDis->getDistributedMEDFilename();
461         
462         cout << "Write MED master file: " << mMEDfilename << ": OK" << endl;
463         
464         //-------------------------------------------------------------
465         // Read the distributed mesh
466         //-------------------------------------------------------------
467         delete mMeshDis;
468         mMeshDis = new MeshDis();
469         mMeshDis->readDistributedMED(mMEDfilename.c_str());
470         
471         mState = MULTIPR_OBJ_STATE_DIS;
472     }
473 }
474
475
476 ostream& operator<<(ostream& pOs, Obj& pO)
477 {
478     pOs << "Obj:" << endl;
479     pOs << "    Name:" << pO.mMEDfilename << endl;
480     
481     return pOs;
482 }
483
484
485 } // namespace multipr
486
487 // EOF