1 // Project MULTIPR, IOLS WP1.2.1 - EDF/CS
2 // Partitioning/decimation module for the SALOME v3.2 platform
5 * \file MULTIPR_Obj.cxx
7 * \brief see MULTIPR_Obj.hxx
9 * \author Olivier LE ROUX - CS, Virtual Reality Dpt
14 //*****************************************************************************
16 //*****************************************************************************
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"
34 //*****************************************************************************
35 // Class Obj implementation
36 //*****************************************************************************
56 mState = MULTIPR_OBJ_STATE_RESET;
58 if (mMeshDis != NULL) { delete mMeshDis; mMeshDis = NULL; }
62 void Obj::create(const char* pMEDfilename)
64 if (pMEDfilename == NULL) throw multipr::NullArgumentException("file name must not be NULL", __FILE__, __LINE__);
66 // reset everything before associating a new MED file to this object
69 mMEDfilename = pMEDfilename;
71 // check if file exists
72 FILE* f = fopen(pMEDfilename, "rb");
75 // file does not exist
76 mState = MULTIPR_OBJ_STATE_ERROR;
77 throw FileNotFoundException("file not found", __FILE__, __LINE__);
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
85 // sequential MED file has been sucessfuly openened
87 // CASE 1: sequential MED file
88 med_int ret = MEDfermer(file);
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__);
97 mState = MULTIPR_OBJ_STATE_SEQ_INIT;
98 cout << "Sequential MED file " << pMEDfilename << " has been successfuly opened" << endl;
102 // CASE 2: distributed MED file?
105 mMeshDis = new multipr::MeshDis();
106 mMeshDis->readDistributedMED(pMEDfilename);
108 mState = MULTIPR_OBJ_STATE_DIS;
109 cout << "Distributed MED file " << pMEDfilename << " has been successfuly opened" << endl;
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__);
121 void Obj::setMesh(const char* pMeshName)
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__);
127 mMeshName = pMeshName;
129 // change state to MULTIPR_OBJ_STATE_SEQ (in case of state=MULTIPR_OBJ_STATE_SEQ_INIT)
130 mState = MULTIPR_OBJ_STATE_SEQ;
134 vector<string> Obj::getMeshes() const
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))
140 // CASE 1: sequential MED file
141 return multipr::getListMeshes(mMEDfilename.c_str());
145 // CASE 2: distributed MED file
146 if (mMeshDis == NULL)
148 throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
151 return mMeshDis->getMeshes();
156 vector<string> Obj::getFields() const
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))
162 // CASE 1: sequential MED file
163 vector<pair<string, int> > tmp = multipr::getListFields(mMEDfilename.c_str());
166 for (int i = 0 ; i < tmp.size() ; i++)
168 res.push_back(tmp[i].first);
175 // CASE 2: distributed MED file
176 if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
178 return mMeshDis->getFields();
183 int Obj::getTimeStamps(const char* pFieldName) const
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))
189 // CASE 1: sequential MED file
190 vector<pair<string, int> > tmp = multipr::getListFields(mMEDfilename.c_str());
192 for (int i = 0 ; i < tmp.size() ; i++)
194 if (strcmp(tmp[i].first.c_str(), pFieldName) == 0)
196 return tmp[i].second;
200 // pFieldName not found in the list of fields
205 // CASE 2: distributed MED file
206 if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
208 return mMeshDis->getTimeStamps(pFieldName);
213 vector<string> Obj::getParts() const
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__);
219 return getListParts();
223 string Obj::getPartInfo(const char* pPartName) const
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__);
229 if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
231 return mMeshDis->getPartInfo(pPartName);
236 void Obj::removeParts(const char* pPrefixPartName)
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__);
242 if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
244 mMeshDis->removeParts(pPrefixPartName);
245 mState = MULTIPR_OBJ_STATE_DIS_MEM;
249 vector<string> Obj::partitionneDomaine()
251 if (mState == MULTIPR_OBJ_STATE_SEQ_INIT) throw IllegalStateException("use setMesh() before", __FILE__, __LINE__);
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__);
256 //-------------------------------------------------------------
257 // Read the sequential mesh
258 //-------------------------------------------------------------
259 cout << "Read sequential MED file: " << mMEDfilename << ": please wait... " << endl;
262 mesh.readSequentialMED(mMEDfilename.c_str(), mMeshName.c_str());
263 cout << mesh << endl;
265 //-------------------------------------------------------------
266 // Build distributed mesh from groups
267 //-------------------------------------------------------------
268 cout << "Build distributed mesh: please wait... " << endl;
271 mMeshDis = mesh.splitGroupsOfElements();
273 catch (RuntimeException& e)
280 mState = MULTIPR_OBJ_STATE_DIS_MEM;
282 return getListParts();
286 vector<string> Obj::partitionneGrain(
287 const char* pPartName,
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__);
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__);
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)
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());
311 mMEDfilename = mMeshDis->getFilename();
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__);
321 mMeshDis = new MeshDis();
322 mMeshDis->readDistributedMED(mMEDfilename.c_str());
324 mState = MULTIPR_OBJ_STATE_DIS;
327 //---------------------------------------------------------------------
328 // Split the given part (pGroupName)
329 //---------------------------------------------------------------------
330 mMeshDis->splitPart(pPartName, pNbParts, pPartitionner);
331 cout << mMeshDis << endl;
333 //---------------------------------------------------------------------
334 // Write new distributed mesh
335 //---------------------------------------------------------------------
336 string strPrefix = multipr::removeExtension(mMEDfilename.c_str(), ".med");
337 mMeshDis->writeDistributedMED(strPrefix.c_str());
339 //---------------------------------------------------------------------
340 // Read the distributed mesh
341 //---------------------------------------------------------------------
343 mMeshDis = new MeshDis();
344 //cout << "read dis MED file: filename=" << mMEDfilename << endl;
345 mMeshDis->readDistributedMED(mMEDfilename.c_str());
347 return getListParts();
351 vector<string> Obj::decimePartition(
352 const char* pPartName,
353 const char* pFieldName,
355 const char* pFilterName,
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__);
366 if (mMeshDis == NULL) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__);
368 //---------------------------------------------------------------------
370 //---------------------------------------------------------------------
371 mMeshDis->decimatePart(
381 mState = MULTIPR_OBJ_STATE_DIS_MEM;
383 return getListParts();
387 vector<string> Obj::getListParts() const
389 if (mMeshDis == NULL) throw IllegalStateException("not a distributed mesh", __FILE__, __LINE__);
391 vector<string> names;
393 int numParts = mMeshDis->getNumParts();
394 for (int i = 0 ; i < numParts ; i++)
396 names.push_back( mMeshDis->getPart(i)->getPartName() );
405 // only save file if it is a distributed MED file currently in memory
406 if (mState == MULTIPR_OBJ_STATE_DIS_MEM)
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();
415 cout << "Write MED master file: " << mMEDfilename << ": OK" << endl;
417 //-------------------------------------------------------------
418 // Read the distributed mesh
419 //-------------------------------------------------------------
421 mMeshDis = new MeshDis();
422 mMeshDis->readDistributedMED(mMEDfilename.c_str());
424 mState = MULTIPR_OBJ_STATE_DIS;
429 ostream& operator<<(ostream& pOs, Obj& pO)
431 pOs << "Obj:" << endl;
432 pOs << " Name:" << pO.mMEDfilename << endl;
438 } // namespace multipr