1 // Project MULTIPR, IOLS WP1.2.1 - EDF/CS
2 // Partitioning/decimation module for the SALOME v3.2 platform
5 * \file MULTIPR_MeshDis.hxx
7 * \brief Class MeshDis: distributed mesh.
8 * = MASTER file (ASCII) -> list of sequential MED file.
10 * \author Olivier LE ROUX - CS, Virtual Reality Dpt
15 #ifndef MULTIPR_MESHDIS_HXX
16 #define MULTIPR_MESHDIS_HXX
18 //*****************************************************************************
20 //*****************************************************************************
30 // include MEDSPLITTER used to split mesh using METIS or SCOTCH
31 #include "MEDMEM_define.hxx"
32 #include "MEDMEM_Mesh.hxx"
33 #include "MEDMEM_Family.hxx"
34 #include "MEDSPLITTER_Graph.hxx"
35 #include "MEDSPLITTER_MESHCollection.hxx"
36 #include "MEDSPLITTER_Topology.hxx"
37 #include "MULTIPR_Globals.hxx"
39 #include <boost/thread/recursive_mutex.hpp>
40 #include <boost/thread/mutex.hpp>
41 #include <boost/shared_ptr.hpp>
46 //*****************************************************************************
48 //*****************************************************************************
54 //*****************************************************************************
55 // Class MeshDisPart = a sub-part of a distributed mesh.
58 // - a sequential MED file representing a Group (scenario 1)
59 // - a sequential MED file representing a part of a Group (scenario 2 -> MEDSPLITTER)
60 // - a lower resolution of a part (decimation)
61 //*****************************************************************************
69 * Action to be done for this part on next writing on disk.
82 * Builds an empty part of a distributed mesh (default constructor).
87 * Destructor. Removes everything.
92 * Resets this object in its state by default (empty). Cleans memory.
97 * Creates a MeshDisPart.
98 * \param pToDoOnNextWrite
103 * \param pMEDFileName file name excluding the path.
104 * \param pMesh can be NULL.
107 OnNextWrite pToDoOnNextWrite,
108 const char* pMeshName,
110 const char* pPartName,
112 const char* pMEDFileName,
115 //---------------------------------------------------------------------
116 // Basic accessors/mutators
117 //---------------------------------------------------------------------
120 * Returns the name of this part.
121 * \return the name of this part.
123 const char* getPartName() const { return mPartName; }
126 * Returns the name of the mesh of this part.
127 * \return the name of the mesh of this part.
129 const char* getMeshName() const { return mMeshName; }
132 * Returns the mesh of this part.
133 * \return the mesh of this part.
135 const Mesh* getMesh() const { return mMesh; }
138 * Returns the MED filename which contain this part.
139 * \return the MED filename which contain this part.
141 const char* getMEDFileName() const { return mMEDFileName; }
144 * Returns the suffix of the related MED filename (without .med extension).
146 * 1. "agregat100grains_12pas_grain97.med" -> "grain97"
147 * 2. "agregat100grains_12pas_grain100_part2.med" -> "grain100_part2"
148 * 3. "aagregat100grains_12pas_grain98_gradmoy-low-25.0-0.3.med" -> "grain98_gradmoy-low-25-0.3"
150 const char* getMEDFileNameSuffix() const;
153 * Returns the action to be performed on this part on next write.
154 * \return the action to be performed on this part on next write.
156 OnNextWrite getOnNextWrite() const { return mToDoOnNextWrite; }
158 //---------------------------------------------------------------------
160 //---------------------------------------------------------------------
163 * Reads the sequentiel MED file corresponding to this part.
164 * \throw IOException if an i/o error occurs.
169 * Dumps any MeshDisPart to the given output stream.
170 * \param pOs any output stream.
171 * \param pM any MeshDisPart.
172 * \return the output stream pOs.
174 friend std::ostream& operator<<(std::ostream& pOs, MeshDisPart& pM);
178 // MeshDisPart can be used:
179 // 1 (KEEP_AS_IT) : To store data read from one line of an ASCII master file (distributed MED file)
180 // 2 (WRITE_MESH) : As a temporary structure to store all infos about a mesh corresponding to a group (before writing on disk).
181 // 3 (WRITE_PARTS) : As a temporary structure to store all infos about splitting using MEDSPLITTER.
183 OnNextWrite mToDoOnNextWrite; /**< See enum OnNextWrite. */
185 //---------------------------------------------------------------------
187 //---------------------------------------------------------------------
188 char mMeshName[MED_TAILLE_NOM + 1]; /**< Name of the mesh. */
189 int mId; /**< Id of this part in [1..n]. */
190 char mPartName[MED_TAILLE_NOM + 1]; /**< Name of this part. */
191 char mPath[256]; /**< Path of the MED file. */
192 char mMEDFileName[256]; /**< Name of the MED file which contain this part. */
194 //---------------------------------------------------------------------
195 // Case 2: mesh of the related sequential MED file (can be NULL if not loaded)
196 //---------------------------------------------------------------------
197 Mesh* mMesh; /**< Mesh associated with this part; can be NULL. */
199 //---------------------------------------------------------------------
200 // Case 3 only: temporary result of MEDSPLITTER
201 //---------------------------------------------------------------------
202 int mSplit; /**< For MEDSPLITTER: number of parts. Temporary. */
203 MEDSPLITTER::MESHCollection* mCollection; /**< New data after splitting. */
204 MEDSPLITTER::MESHCollection* mOldCollection; /**< Data before splitting (we need them when we want to write new data on disk. */
208 // do not allow copy constructor
209 MeshDisPart(const MeshDisPart&);
212 MeshDisPart& operator=(const MeshDisPart&);
214 // do not allow operator ==
215 bool operator==(const MeshDisPart&);
217 //---------------------------------------------------------------------
219 //---------------------------------------------------------------------
220 friend class MeshDis;
222 }; // class MeshDisPart
225 //*****************************************************************************
227 //*****************************************************************************
234 * Builds an empty mesh (default constructor).
239 * Destructor. Removes everything.
244 * Resets this object in its state by default (empty). Clean memory.
248 //---------------------------------------------------------------------
249 // Basic accessors/mutators
250 //---------------------------------------------------------------------
253 * Sets the name of the associated sequential MED file (=original MED file).
254 * \param pFilename name of the associated sequential MED file.
256 void setSequentialMEDFilename(const char* pFilename);
259 * Returns the name of this sequential MED file (=original MED file).
260 * \return the name of this sequential MED file (=original MED file).
262 const char* getSequentialMEDFilename() const { return mSequentialMEDFilename; }
265 * Returns the name of this distributed MED file (=name of the master file).
266 * \return the name of this distributed MED file (=name of the master file).
268 const char* getDistributedMEDFilename() const { return mDistributedMEDFilename; }
271 * Adds a new part to this distributed mesh.
272 * Used by the split process (extract groups).
273 * \param pToDoOnNextWrite
278 * \param pMEDFileName
279 * \param pMesh can be NULL.
282 MeshDisPart::OnNextWrite pToDoOnNextWrite,
283 const char* pMeshName,
285 const char* pPartName,
287 const char* pMEDFileName,
291 * Inserts a new part to this distributed mesh.
292 * Used by the decimation process.
293 * \param pToDoOnNextWrite
298 * \param pMEDFileName
299 * \param pMesh can be NULL.
300 * \param pPosition insert after this position. Start at 1.
303 MeshDisPart::OnNextWrite pToDoOnNextWrite,
304 const char* pMeshName,
306 const char* pPartName,
308 const char* pMEDFileName,
313 * Removes all the part beginning by pPrefixPartName from this distributed mesh.
314 * Example: if pPrefixPartName="PART_4" => remove "PART_4" and all sub-parts "PART_4_*", but not "PART41".
315 * \param pPrefixPartName name of the part.
317 void removeParts(const char* pPrefixPartName);
320 * Returns the current number of parts in this distributed mesh.
321 * \return the current number of parts in this distributed mesh.
323 int getNumParts() const { return mParts.size(); }
326 * Returns the nth part of this distributed mesh.
327 * \param pIndex index of the part (in 0..getNumParts()-1).
328 * \return the nth part of this distributed mesh.
330 MeshDisPart* getPart(int pIndex) const { return mParts[pIndex]; }
333 * Returns the list of meshes contained in this distributed MED file.
334 * \return the list of meshes contained in this distributed MED file.
336 std::vector<std::string> getMeshes() const;
339 * Returns the list of fields contained in this distributed MED file.
340 * \param pPartList The list of parts to get the fields from (separator is '|').
341 * \param pAddNbGaussPoint If set to true, the number of gauss point of each field is added.
342 * \return the list of fields contained in this distributed MED file.
344 std::vector<std::string> getFields(const char* pPartList, bool pAddNbGaussPoint = false) const;
347 * Returns the number of iteration for a given field.
348 * \param pPartList The list of parts to get the fields from (separator is '|').
349 * \param pFieldName field name.
350 * \return the number of iteration for a given field.
352 int getTimeStamps(const char* pPartList, const char* pFieldName) const;
355 * Returns all information about a part.
356 * \param pPartName name of the part.
357 * \return all information about a part.
359 std::string getPartInfo(const char* pPartName);
361 //---------------------------------------------------------------------
363 //---------------------------------------------------------------------
366 * Finds a part of this distributed mesh by its name.
367 * Returns NULL if the part does not exist.
368 * \param pPartName part to be found; must not be NULL.
369 * \return a pointer towards the part if it exists, NULL otherwise.
370 * \throw NullArgumentException if pPartName is NULL.
372 MeshDisPart* findPart(const char* pPartName);
375 * Updates this distributed mesh by splitting one of its part.
376 * This splitting method leans on medsplitter, by V. Bergeaud (CEA).
377 * \param pPartName name of the part to be splitted.
378 * \param pNbParts number of sub-parts.
379 * \param pPartitionner MULTIPR_METIS or MULTIPR_SCOTCH.
380 * \throw RuntimeException if any error occurs.
382 void splitPart(const char* pPartName, int pNbParts, int pPartitionner);
385 * Creates 3 resolution (CURRENT = FULL, MEDIUM and LOW) of a part of this distributed mesh.
386 * Names of new meshes are <original_name>_MED and <original_name>_LOW.
391 * \param pTMed threshold used to generate MEDIUM resolution.
392 * \param pTLow threshold used to generate LOW resolution (must be >= pTMed).
394 * \param pBoxing number of cells along each axis; e.g. if 100 then grid will have 100*100*100 = 10**6 cells; 100 by default.
395 * \return a list of strings, containing names of empty resulting parts, empty list if all resolutions are non-empty.
396 * \throw RuntimeException if any error occurs.
398 std::list<std::string> decimatePart(
399 const char* pPartName,
400 const char* pFieldName,
402 const char* pFilterName,
403 const char* pFilterParams);
406 * Returns useful information to configure decimation parameters.
407 * Depends on part, field and filter: generic operation.
408 * \param pPartName name of the part.
409 * \param pFieldName name of the field used for decimation.
410 * \param pFieldIt iteration (time step) of the field.
411 * \param pFilterName name of the filter to be used.
412 * \param pFilterParams params to be used with the filter (depends on filter; this string will be parsed).
415 std::string evalDecimationParams(
416 const char* pPartName,
417 const char* pFieldName,
419 const char* pFilterName,
420 const char* pFilterParams);
423 * Get the statistics of the last decimation.
424 * The format is : "lowres-compression-rate medres-compression-rate".
426 std::string& getDecimationStatistics() { return mStats; }
428 //---------------------------------------------------------------------
430 //---------------------------------------------------------------------
433 * Reads the master file of a distributed MED file.
434 * \param pMEDfilename
435 * \throw NullArgumentException if pMEDfilename is NULL.
436 * \throw IOException if any i/o error occurs.
438 void readDistributedMED(const char* pMEDfilename);
441 * Works like \a readDistributedMED(), but assumes that the distributed MED file was
442 * moved from the original location and its ASCII master file needs to be updated.
444 * \note This method is mentioned to be used only in persistence.
446 void readPersistentDistributedMED(const char* pMEDfilename);
449 * Writes this distributed MED file (including master file and sub MED files if necessary).
450 * \param pMEDfilenamePrefix
451 * \throw NullArgumentException if pMEDfilename is NULL.
452 * \throw IOException if any i/o error occurs.
454 void writeDistributedMED (const char* pMEDfilenamePrefix,
455 bool pIsPersistence = false);
458 * Update save progress.
459 * \param pPercents current save progress in percents.
461 void setProgress (int pPercents);
464 * Obtain save progress.
465 * \return current save progress in percents.
470 * Read and write the fields for optimized domain split.
471 * \param pMeshName The name of the current mesh.
472 * \param pGroups The groups.
473 * \param pGaussList The list of gauss index.
474 * \param pProfils The profiles of the mesh.
476 void readAndWriteFields (const char* pMeshName, std::vector<Group*>* pGroups,
477 GaussIndexList* pGaussList, std::vector<Profil*>& pProfils);
480 * Dumps any MeshDis to the given output stream.
481 * \param pOs any output stream.
482 * \param pM any MeshDis.
483 * \return the output stream pOs.
485 friend std::ostream& operator<<(std::ostream& pOs, MeshDis& pM);
490 * Recomputes the number of parts in this distributed mesh.
491 * This method is used by writeDistributedMED().
492 * \return the number of parts in this distributed mesh.
494 int computeNumParts();
498 char mSequentialMEDFilename[256]; /**< Name of the original MED file used to build distribyuted MED. */
499 char mDistributedMEDFilename[256]; /**< Name of this distributed MED file (= name of the master file). */
500 std::vector<MeshDisPart*> mParts; /**< Table of sub-parts; a distributed mesh is composed of N sub-part, where N = mParts.size(). */
501 std::string mStats; /**< Statistics of the last decimation */
503 int mWriteProgress; /**< Mesh saving progress in percents */
504 boost::recursive_mutex mWriteMutex; /**< For thread-safe access to mWriteProgress */
508 // do not allow copy constructor
509 MeshDis(const MeshDis&);
512 MeshDis& operator=(const MeshDis&);
514 // do not allow operator ==
515 bool operator==(const MeshDis&);
520 //----------------------------------------------------------------------------
521 //! This class provide thread-safety for MEDWrapper interaction
524 TLockProxy& operator=(const TLockProxy& );
526 boost::shared_ptr<boost::mutex> myMutex;
529 TLockProxy(MeshDis* theMeshDis, boost::shared_ptr<boost::mutex> theMutex);
533 MeshDis * operator-> () const;
536 //----------------------------------------------------------------------------
537 //! To specialize the SharedPtr for MeshDis
539 class SharedPtr: public boost::shared_ptr<T>
543 : myMutex(new boost::mutex())
547 explicit SharedPtr(Y * p)
548 : boost::shared_ptr<T>(p),
549 myMutex(new boost::mutex())
553 SharedPtr(SharedPtr<Y> const & r)
554 : boost::shared_ptr<T>(r,boost::detail::dynamic_cast_tag()),
560 operator=(SharedPtr<Y> const & r)
562 boost::shared_ptr<T>(r,boost::detail::dynamic_cast_tag()).swap(*this);
563 myMutex = r->myMutex;
569 operator()(Y * p) // Y must be complete
571 return operator=<Y>(SharedPtr<Y>(p));
576 operator()(SharedPtr<Y> const & r) // Y must be complete
578 return operator=<Y>(SharedPtr<Y>(r));
581 TLockProxy operator-> () const // never throws
583 return TLockProxy(this->get(), myMutex);
587 void reset (Y * p) // Y must be complete
589 //boost::detail::thread::lock_ops<typename T::TMutex>::lock(p->myMutex);
590 boost::detail::thread::lock_ops<boost::mutex>::lock(*myMutex);
591 if (boost::shared_ptr<T>::get() != NULL) delete (boost::shared_ptr<T>::get());
592 boost::shared_ptr<T>(p).swap(*this);
593 //boost::detail::thread::lock_ops<typename T::TMutex>::unlock(p->myMutex);
594 boost::detail::thread::lock_ops<boost::mutex>::unlock(*myMutex);
598 operator const T& () const;
602 T& operator* () const;
604 T * get() const // never throws
606 return boost::shared_ptr<T>::get();
610 boost::shared_ptr<boost::mutex> myMutex;
614 } // namespace MULTIPR
617 #endif // MULTIPR_MESHDIS_HXX