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 std::string Obj::getSequentialMEDFilename() const
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__);
127 return mMeshDis->getSequentialMEDFilename();
131 void Obj::setMesh(const char* pMeshName)
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__);
137 mMeshName = pMeshName;
139 // change state to MULTIPR_OBJ_STATE_SEQ (in case of state=MULTIPR_OBJ_STATE_SEQ_INIT)
140 mState = MULTIPR_OBJ_STATE_SEQ;
144 vector<string> Obj::getMeshes() const
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))
150 // CASE 1: sequential MED file
151 return multipr::getListMeshes(mMEDfilename.c_str());
155 // CASE 2: distributed MED file
156 if (mMeshDis == NULL)
158 throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
161 return mMeshDis->getMeshes();
166 vector<string> Obj::getFields() const
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))
172 // CASE 1: sequential MED file
173 vector<pair<string, int> > tmp = multipr::getListScalarFields(mMEDfilename.c_str());
176 for (int i = 0 ; i < tmp.size() ; i++)
178 res.push_back(tmp[i].first);
185 // CASE 2: distributed MED file
186 if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
188 return mMeshDis->getFields();
193 int Obj::getTimeStamps(const char* pFieldName) const
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))
199 // CASE 1: sequential MED file
200 vector<pair<string, int> > tmp = multipr::getListScalarFields(mMEDfilename.c_str());
202 for (int i = 0 ; i < tmp.size() ; i++)
204 if (strcmp(tmp[i].first.c_str(), pFieldName) == 0)
206 return tmp[i].second;
210 // pFieldName not found in the list of fields
215 // CASE 2: distributed MED file
216 if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
218 return mMeshDis->getTimeStamps(pFieldName);
223 vector<string> Obj::getParts() 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 return getListParts();
233 string Obj::getPartInfo(const char* pPartName) const
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__);
239 if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
241 return mMeshDis->getPartInfo(pPartName);
246 void Obj::removeParts(const char* pPrefixPartName)
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__);
252 if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__);
254 mMeshDis->removeParts(pPrefixPartName);
255 mState = MULTIPR_OBJ_STATE_DIS_MEM;
259 vector<string> Obj::partitionneDomaine()
261 if (mState == MULTIPR_OBJ_STATE_SEQ_INIT) throw IllegalStateException("use setMesh() before", __FILE__, __LINE__);
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__);
266 //-------------------------------------------------------------
267 // Read the sequential mesh
268 //-------------------------------------------------------------
269 cout << "Read sequential MED file: " << mMEDfilename << ": please wait... " << endl;
272 mesh.readSequentialMED(mMEDfilename.c_str(), mMeshName.c_str());
273 cout << mesh << endl;
275 //-------------------------------------------------------------
276 // Build distributed mesh from groups
277 //-------------------------------------------------------------
278 cout << "Build distributed mesh: please wait... " << endl;
281 mMeshDis = mesh.splitGroupsOfElements();
283 catch (RuntimeException& e)
290 mState = MULTIPR_OBJ_STATE_DIS_MEM;
292 return getListParts();
296 vector<string> Obj::partitionneGrain(
297 const char* pPartName,
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__);
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__);
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)
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());
321 mMEDfilename = mMeshDis->getDistributedMEDFilename();
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__);
331 mMeshDis = new MeshDis();
332 mMeshDis->readDistributedMED(mMEDfilename.c_str());
334 mState = MULTIPR_OBJ_STATE_DIS;
337 //---------------------------------------------------------------------
338 // Split the given part (pGroupName)
339 //---------------------------------------------------------------------
340 mMeshDis->splitPart(pPartName, pNbParts, pPartitionner);
341 cout << mMeshDis << endl;
343 //---------------------------------------------------------------------
344 // Write new distributed mesh
345 //---------------------------------------------------------------------
346 string strPrefix = multipr::removeExtension(mMEDfilename.c_str(), ".med");
347 mMeshDis->writeDistributedMED(strPrefix.c_str());
349 //---------------------------------------------------------------------
350 // Read the distributed mesh
351 //---------------------------------------------------------------------
353 mMeshDis = new MeshDis();
354 //cout << "read dis MED file: filename=" << mMEDfilename << endl;
355 mMeshDis->readDistributedMED(mMEDfilename.c_str());
357 return getListParts();
361 vector<string> Obj::decimePartition(
362 const char* pPartName,
363 const char* pFieldName,
365 const char* pFilterName,
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__);
376 if (mMeshDis == NULL) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__);
378 //---------------------------------------------------------------------
380 //---------------------------------------------------------------------
381 mMeshDis->decimatePart(
391 mState = MULTIPR_OBJ_STATE_DIS_MEM;
393 return getListParts();
397 string Obj::evalDecimationParams(
398 const char* pPartName,
399 const char* pFieldName,
401 const char* pFilterName,
402 const char* pFilterParams)
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__);
408 if (mMeshDis == NULL) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__);
410 string res = mMeshDis->evalDecimationParams(
421 vector<string> Obj::getListParts() const
423 if (mMeshDis == NULL) throw IllegalStateException("not a distributed mesh", __FILE__, __LINE__);
425 vector<string> names;
427 int numParts = mMeshDis->getNumParts();
428 for (int i = 0 ; i < numParts ; i++)
430 names.push_back( mMeshDis->getPart(i)->getPartName() );
437 void Obj::save(const char* pPath)
439 static string prevPath = "";
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))
446 //-------------------------------------------------------------
447 // Write new distributed mesh
448 //-------------------------------------------------------------
450 if (strlen(pPath) == 0)
452 filename = multipr::removeExtension(mMEDfilename.c_str(), ".med");
456 filename = string(pPath) + string("/") + multipr::getFilenameWithoutPath(mMEDfilename.c_str());
458 string strPrefix = multipr::removeExtension(filename.c_str(), ".med");
459 mMeshDis->writeDistributedMED(strPrefix.c_str());
460 mMEDfilename = mMeshDis->getDistributedMEDFilename();
462 cout << "Write MED master file: " << mMEDfilename << ": OK" << endl;
464 //-------------------------------------------------------------
465 // Read the distributed mesh
466 //-------------------------------------------------------------
468 mMeshDis = new MeshDis();
469 mMeshDis->readDistributedMED(mMEDfilename.c_str());
471 mState = MULTIPR_OBJ_STATE_DIS;
476 ostream& operator<<(ostream& pOs, Obj& pO)
478 pOs << "Obj:" << endl;
479 pOs << " Name:" << pO.mMEDfilename << endl;
485 } // namespace multipr