]> 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 void Obj::setMesh(const char* pMeshName)
122 {
123         // setMesh() is only available for sequential MED file (not distributed MED file)
124         if ((mState != MULTIPR_OBJ_STATE_SEQ_INIT) &&
125             (mState != MULTIPR_OBJ_STATE_SEQ)) throw IllegalStateException("expected a sequential MED file", __FILE__, __LINE__);
126         
127         mMeshName = pMeshName;
128         
129         // change state to MULTIPR_OBJ_STATE_SEQ (in case of state=MULTIPR_OBJ_STATE_SEQ_INIT)
130         mState = MULTIPR_OBJ_STATE_SEQ;
131 }
132
133
134 vector<string> Obj::getMeshes() const
135 {
136         // test whether it is a sequential MED file or a distributed MED file
137         if ((mState == MULTIPR_OBJ_STATE_SEQ_INIT) ||
138             (mState == MULTIPR_OBJ_STATE_SEQ))
139         {
140                 // CASE 1: sequential MED file
141                 return multipr::getListMeshes(mMEDfilename.c_str());
142         }
143         else
144         {
145                 // CASE 2: distributed MED file
146                 if (mMeshDis == NULL)
147                 {
148                         throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
149                 }
150                 
151                 return mMeshDis->getMeshes();
152         }
153 }
154
155
156 vector<string> Obj::getFields() const
157 {
158         // test whether it is a sequential MED file or a distributed MED file
159         if ((mState == MULTIPR_OBJ_STATE_SEQ_INIT) ||
160             (mState == MULTIPR_OBJ_STATE_SEQ)) 
161         {
162                 // CASE 1: sequential MED file
163                 vector<pair<string, int> > tmp = multipr::getListFields(mMEDfilename.c_str());
164                 
165                 vector<string> res;
166                 for (int i = 0 ; i < tmp.size() ; i++)
167                 {
168                         res.push_back(tmp[i].first);
169                 }
170                 
171                 return res;
172         }
173         else
174         {
175                 // CASE 2: distributed MED file
176                 if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
177                 
178                 return mMeshDis->getFields();
179         }
180 }
181
182
183 int Obj::getTimeStamps(const char* pFieldName) const
184 {
185         // test whether it is a sequential MED file or a distributed MED file
186         if ((mState == MULTIPR_OBJ_STATE_SEQ_INIT) ||
187             (mState == MULTIPR_OBJ_STATE_SEQ)) 
188         {
189                 // CASE 1: sequential MED file
190                 vector<pair<string, int> > tmp = multipr::getListFields(mMEDfilename.c_str());
191         
192                 for (int i = 0 ; i < tmp.size() ; i++)
193                 {
194                         if (strcmp(tmp[i].first.c_str(), pFieldName) == 0)
195                         {
196                                 return tmp[i].second;
197                         }
198                 }
199                 
200                 // pFieldName not found in the list of fields
201                 return 0;
202         }
203         else
204         {
205                 // CASE 2: distributed MED file
206                 if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
207                 
208                 return mMeshDis->getTimeStamps(pFieldName);
209         }
210 }
211
212
213 vector<string> Obj::getParts() const
214 {
215         // getParts() is only available for distributed MED file (not sequential MED file)
216         if ((mState != MULTIPR_OBJ_STATE_DIS) &&
217             (mState != MULTIPR_OBJ_STATE_DIS_MEM)) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__);
218         
219         return getListParts();
220 }
221
222
223 string Obj::getPartInfo(const char* pPartName) 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         if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
230         
231         return mMeshDis->getPartInfo(pPartName);
232         
233 }
234
235
236 void Obj::removeParts(const char* pPrefixPartName)
237 {
238         // removePart() is only available for distributed MED file (not sequential MED file)
239         if ((mState != MULTIPR_OBJ_STATE_DIS) &&
240             (mState != MULTIPR_OBJ_STATE_DIS_MEM)) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__);
241                 
242         if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
243         
244         mMeshDis->removeParts(pPrefixPartName);
245         mState = MULTIPR_OBJ_STATE_DIS_MEM;
246 }
247
248
249 vector<string> Obj::partitionneDomaine()
250 {
251         if (mState == MULTIPR_OBJ_STATE_SEQ_INIT) throw IllegalStateException("use setMesh() before", __FILE__, __LINE__);
252         
253         // partitionneDomaine() is only available for sequential MED file (not distributed MED file)
254         if (mState != MULTIPR_OBJ_STATE_SEQ) throw IllegalStateException("unexpected operation", __FILE__, __LINE__);
255         
256         //-------------------------------------------------------------
257         // Read the sequential mesh
258         //-------------------------------------------------------------
259         cout << "Read sequential MED file: " << mMEDfilename << ": please wait... " << endl;
260         
261         Mesh mesh;
262         mesh.readSequentialMED(mMEDfilename.c_str(), mMeshName.c_str());
263         cout << mesh << endl;
264         
265         //-------------------------------------------------------------
266         // Build distributed mesh from groups
267         //-------------------------------------------------------------
268         cout << "Build distributed mesh: please wait... " << endl;
269         try
270         {
271                 mMeshDis = mesh.splitGroupsOfElements();
272         }
273         catch (RuntimeException& e)
274         {
275                 delete mMeshDis;
276                 mMeshDis = NULL;
277                 throw e;
278         }
279         
280         mState = MULTIPR_OBJ_STATE_DIS_MEM;
281         
282         return getListParts();
283 }
284
285
286 vector<string> Obj::partitionneGrain(
287         const char* pPartName, 
288         int         pNbParts, 
289         int         pPartitionner)
290 {
291         if (mMeshDis == NULL) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__);
292         if (pPartName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
293         if (pNbParts < 2) throw IllegalArgumentException("", __FILE__, __LINE__);
294         if ((pPartitionner != 0) && (pPartitionner != 1)) throw IllegalArgumentException("partitionner should be 0=METIS or 1=SCOTCH", __FILE__, __LINE__);
295
296         // partitionneGrain() is only available for distributed MED file (not sequential MED file)
297         if ((mState != MULTIPR_OBJ_STATE_DIS_MEM) &&
298             (mState != MULTIPR_OBJ_STATE_DIS)) throw IllegalStateException("unexpected operation", __FILE__, __LINE__);
299         
300         // if distributed MED file is currently in memory, then write to disk before performing partitionneGrain()
301         // (because MEDSPLIITER starts from a file)
302         if (mState == MULTIPR_OBJ_STATE_DIS_MEM)
303         {
304                 //-----------------------------------------------------
305                 // Write distributed mesh
306                 //-----------------------------------------------------
307                 cout << "Write distributed mesh: please wait... " << endl;
308                 string strPrefix = removeExtension(mMEDfilename.c_str(), ".med");
309                 mMeshDis->writeDistributedMED(strPrefix.c_str());
310                 
311                 mMEDfilename = mMeshDis->getFilename();
312                 
313                 delete mMeshDis;
314                 
315                 //---------------------------------------------------------------------
316                 // Read the distributed mesh
317                 //--------------------------------------------------------------------- 
318                 int ret = MEDformatConforme(mMEDfilename.c_str());
319                 if (ret == 0) throw IOException("waiting for a distributed MED file (not a sequential one)", __FILE__, __LINE__);
320         
321                 mMeshDis = new MeshDis();
322                 mMeshDis->readDistributedMED(mMEDfilename.c_str());
323                 
324                 mState = MULTIPR_OBJ_STATE_DIS;
325         }
326
327         //---------------------------------------------------------------------
328         // Split the given part (pGroupName)
329         //---------------------------------------------------------------------
330         mMeshDis->splitPart(pPartName, pNbParts, pPartitionner);
331         cout << mMeshDis << endl;
332
333         //---------------------------------------------------------------------
334         // Write new distributed mesh
335         //---------------------------------------------------------------------
336         string strPrefix = multipr::removeExtension(mMEDfilename.c_str(), ".med");
337         mMeshDis->writeDistributedMED(strPrefix.c_str());
338         
339         //---------------------------------------------------------------------
340         // Read the distributed mesh
341         //---------------------------------------------------------------------
342         delete mMeshDis;
343         mMeshDis = new MeshDis();
344         //cout << "read dis MED file: filename=" << mMEDfilename << endl;
345         mMeshDis->readDistributedMED(mMEDfilename.c_str());
346         
347         return getListParts();
348 }
349
350
351 vector<string> Obj::decimePartition(
352         const char* pPartName,
353         const char* pFieldName,
354         int         pFieldIt,
355         const char* pFilterName,
356         double      pTmed,
357         double      pTlow,
358         double      pRadius,
359         int         pBoxing)
360 {
361         
362         // decimePartition() is only available for distributed MED file (not sequential MED file)
363         if ((mState != MULTIPR_OBJ_STATE_DIS_MEM) &&
364             (mState != MULTIPR_OBJ_STATE_DIS)) throw IllegalStateException("unexpected operation", __FILE__, __LINE__);
365             
366         if (mMeshDis == NULL) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__);
367         
368         //---------------------------------------------------------------------
369         // Decimate
370         //---------------------------------------------------------------------
371         mMeshDis->decimatePart(
372                 pPartName, 
373                 pFieldName,
374                 pFieldIt,
375                 pFilterName,
376                 pTmed,
377                 pTlow,
378                 pRadius,
379                 pBoxing);
380                 
381         mState = MULTIPR_OBJ_STATE_DIS_MEM;
382         
383         return getListParts();
384 }
385
386
387 vector<string> Obj::getListParts() const
388 {
389         if (mMeshDis == NULL) throw IllegalStateException("not a distributed mesh", __FILE__, __LINE__);
390         
391         vector<string> names;
392         
393         int numParts = mMeshDis->getNumParts();
394         for (int i = 0 ; i < numParts ; i++)
395         {
396                 names.push_back( mMeshDis->getPart(i)->getPartName() );
397         }
398         
399         return names;
400 }
401
402
403 void Obj::save()
404 {
405         // only save file if it is a distributed MED file currently in memory
406         if (mState == MULTIPR_OBJ_STATE_DIS_MEM)
407         {
408                 //-------------------------------------------------------------
409                 // Write new distributed mesh
410                 //-------------------------------------------------------------
411                 string strPrefix = multipr::removeExtension(mMEDfilename.c_str(), ".med");
412                 mMeshDis->writeDistributedMED(strPrefix.c_str());               
413                 mMEDfilename = mMeshDis->getFilename();
414                 
415                 cout << "Write MED master file: " << mMEDfilename << ": OK" << endl;
416                 
417                 //-------------------------------------------------------------
418                 // Read the distributed mesh
419                 //-------------------------------------------------------------
420                 delete mMeshDis;
421                 mMeshDis = new MeshDis();
422                 mMeshDis->readDistributedMED(mMEDfilename.c_str());
423                 
424                 mState = MULTIPR_OBJ_STATE_DIS;
425         }
426 }
427
428
429 ostream& operator<<(ostream& pOs, Obj& pO)
430 {
431         pOs << "Obj:" << endl;
432         pOs << "    Name:" << pO.mMEDfilename << endl;
433         
434         return pOs;
435 }
436
437
438 } // namespace multipr
439
440 // EOF