1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Partitioning/decimation module for the SALOME v3.2 platform
22 * \file MULTIPR_MeshDis.hxx
24 * \brief Class MeshDis: distributed mesh.
25 * = MASTER file (ASCII) -> list of sequential MED file.
27 * \author Olivier LE ROUX - CS, Virtual Reality Dpt
32 #ifndef MULTIPR_MESHDIS_HXX
33 #define MULTIPR_MESHDIS_HXX
35 //*****************************************************************************
37 //*****************************************************************************
47 // include MEDSPLITTER used to split mesh using METIS or SCOTCH
48 #include "MEDMEM_define.hxx"
49 #include "MEDMEM_Mesh.hxx"
50 #include "MEDMEM_Family.hxx"
51 #include "MEDSPLITTER_Graph.hxx"
52 #include "MEDSPLITTER_MESHCollection.hxx"
53 #include "MEDSPLITTER_Topology.hxx"
54 #include "MULTIPR_Globals.hxx"
56 #include <boost/thread/recursive_mutex.hpp>
57 #include <boost/thread/mutex.hpp>
58 #include <boost/shared_ptr.hpp>
63 //*****************************************************************************
65 //*****************************************************************************
71 //*****************************************************************************
72 // Class MeshDisPart = a sub-part of a distributed mesh.
75 // - a sequential MED file representing a Group (scenario 1)
76 // - a sequential MED file representing a part of a Group (scenario 2 -> MEDSPLITTER)
77 // - a lower resolution of a part (decimation)
78 //*****************************************************************************
86 * Action to be done for this part on next writing on disk.
99 * Builds an empty part of a distributed mesh (default constructor).
104 * Destructor. Removes everything.
109 * Resets this object in its state by default (empty). Cleans memory.
114 * Creates a MeshDisPart.
115 * \param pToDoOnNextWrite
120 * \param pMEDFileName file name excluding the path.
121 * \param pMesh can be NULL.
124 OnNextWrite pToDoOnNextWrite,
125 const char* pMeshName,
127 const char* pPartName,
129 const char* pMEDFileName,
132 //---------------------------------------------------------------------
133 // Basic accessors/mutators
134 //---------------------------------------------------------------------
137 * Returns the name of this part.
138 * \return the name of this part.
140 const char* getPartName() const { return mPartName; }
143 * Returns the name of the mesh of this part.
144 * \return the name of the mesh of this part.
146 const char* getMeshName() const { return mMeshName; }
149 * Returns the mesh of this part.
150 * \return the mesh of this part.
152 const Mesh* getMesh() const { return mMesh; }
155 * Returns the MED filename which contain this part.
156 * \return the MED filename which contain this part.
158 const char* getMEDFileName() const { return mMEDFileName; }
161 * Returns the suffix of the related MED filename (without .med extension).
163 * 1. "agregat100grains_12pas_grain97.med" -> "grain97"
164 * 2. "agregat100grains_12pas_grain100_part2.med" -> "grain100_part2"
165 * 3. "aagregat100grains_12pas_grain98_gradmoy-low-25.0-0.3.med" -> "grain98_gradmoy-low-25-0.3"
167 const char* getMEDFileNameSuffix() const;
170 * Returns the action to be performed on this part on next write.
171 * \return the action to be performed on this part on next write.
173 OnNextWrite getOnNextWrite() const { return mToDoOnNextWrite; }
175 //---------------------------------------------------------------------
177 //---------------------------------------------------------------------
180 * Reads the sequentiel MED file corresponding to this part.
181 * \throw IOException if an i/o error occurs.
186 * Dumps any MeshDisPart to the given output stream.
187 * \param pOs any output stream.
188 * \param pM any MeshDisPart.
189 * \return the output stream pOs.
191 friend std::ostream& operator<<(std::ostream& pOs, MeshDisPart& pM);
195 // MeshDisPart can be used:
196 // 1 (KEEP_AS_IT) : To store data read from one line of an ASCII master file (distributed MED file)
197 // 2 (WRITE_MESH) : As a temporary structure to store all infos about a mesh corresponding to a group (before writing on disk).
198 // 3 (WRITE_PARTS) : As a temporary structure to store all infos about splitting using MEDSPLITTER.
200 OnNextWrite mToDoOnNextWrite; /**< See enum OnNextWrite. */
202 //---------------------------------------------------------------------
204 //---------------------------------------------------------------------
205 char mMeshName[MED_TAILLE_NOM + 1]; /**< Name of the mesh. */
206 int mId; /**< Id of this part in [1..n]. */
207 char mPartName[MED_TAILLE_NOM + 1]; /**< Name of this part. */
208 char mPath[256]; /**< Path of the MED file. */
209 char mMEDFileName[256]; /**< Name of the MED file which contain this part. */
211 //---------------------------------------------------------------------
212 // Case 2: mesh of the related sequential MED file (can be NULL if not loaded)
213 //---------------------------------------------------------------------
214 Mesh* mMesh; /**< Mesh associated with this part; can be NULL. */
216 //---------------------------------------------------------------------
217 // Case 3 only: temporary result of MEDSPLITTER
218 //---------------------------------------------------------------------
219 int mSplit; /**< For MEDSPLITTER: number of parts. Temporary. */
220 MEDSPLITTER::MESHCollection* mCollection; /**< New data after splitting. */
221 MEDSPLITTER::MESHCollection* mOldCollection; /**< Data before splitting (we need them when we want to write new data on disk. */
225 // do not allow copy constructor
226 MeshDisPart(const MeshDisPart&);
229 MeshDisPart& operator=(const MeshDisPart&);
231 // do not allow operator ==
232 bool operator==(const MeshDisPart&);
234 //---------------------------------------------------------------------
236 //---------------------------------------------------------------------
237 friend class MeshDis;
239 }; // class MeshDisPart
242 //*****************************************************************************
244 //*****************************************************************************
251 * Builds an empty mesh (default constructor).
256 * Destructor. Removes everything.
261 * Resets this object in its state by default (empty). Clean memory.
265 //---------------------------------------------------------------------
266 // Basic accessors/mutators
267 //---------------------------------------------------------------------
270 * Sets the name of the associated sequential MED file (=original MED file).
271 * \param pFilename name of the associated sequential MED file.
273 void setSequentialMEDFilename(const char* pFilename);
276 * Returns the name of this sequential MED file (=original MED file).
277 * \return the name of this sequential MED file (=original MED file).
279 const char* getSequentialMEDFilename() const { return mSequentialMEDFilename; }
282 * Returns the name of this distributed MED file (=name of the master file).
283 * \return the name of this distributed MED file (=name of the master file).
285 const char* getDistributedMEDFilename() const { return mDistributedMEDFilename; }
288 * Adds a new part to this distributed mesh.
289 * Used by the split process (extract groups).
290 * \param pToDoOnNextWrite
295 * \param pMEDFileName
296 * \param pMesh can be NULL.
299 MeshDisPart::OnNextWrite pToDoOnNextWrite,
300 const char* pMeshName,
302 const char* pPartName,
304 const char* pMEDFileName,
308 * Inserts a new part to this distributed mesh.
309 * Used by the decimation process.
310 * \param pToDoOnNextWrite
315 * \param pMEDFileName
316 * \param pMesh can be NULL.
317 * \param pPosition insert after this position. Start at 1.
320 MeshDisPart::OnNextWrite pToDoOnNextWrite,
321 const char* pMeshName,
323 const char* pPartName,
325 const char* pMEDFileName,
330 * Removes all the part beginning by pPrefixPartName from this distributed mesh.
331 * Example: if pPrefixPartName="PART_4" => remove "PART_4" and all sub-parts "PART_4_*", but not "PART41".
332 * \param pPrefixPartName name of the part.
334 void removeParts(const char* pPrefixPartName);
337 * Returns the current number of parts in this distributed mesh.
338 * \return the current number of parts in this distributed mesh.
340 int getNumParts() const { return mParts.size(); }
343 * Returns the nth part of this distributed mesh.
344 * \param pIndex index of the part (in 0..getNumParts()-1).
345 * \return the nth part of this distributed mesh.
347 MeshDisPart* getPart(int pIndex) const { return mParts[pIndex]; }
350 * Returns the list of meshes contained in this distributed MED file.
351 * \return the list of meshes contained in this distributed MED file.
353 std::vector<std::string> getMeshes() const;
356 * Returns the list of fields contained in this distributed MED file.
357 * \param pPartList The list of parts to get the fields from (separator is '|').
358 * \param pAddNbGaussPoint If set to true, the number of gauss point of each field is added.
359 * \return the list of fields contained in this distributed MED file.
361 std::vector<std::string> getFields(const char* pPartList, bool pAddNbGaussPoint = false) const;
364 * Returns the number of iteration for a given field.
365 * \param pPartList The list of parts to get the fields from (separator is '|').
366 * \param pFieldName field name.
367 * \return the number of iteration for a given field.
369 int getTimeStamps(const char* pPartList, const char* pFieldName) const;
372 * Returns all information about a part.
373 * \param pPartName name of the part.
374 * \return all information about a part.
376 std::string getPartInfo(const char* pPartName);
378 //---------------------------------------------------------------------
380 //---------------------------------------------------------------------
383 * Finds a part of this distributed mesh by its name.
384 * Returns NULL if the part does not exist.
385 * \param pPartName part to be found; must not be NULL.
386 * \return a pointer towards the part if it exists, NULL otherwise.
387 * \throw NullArgumentException if pPartName is NULL.
389 MeshDisPart* findPart(const char* pPartName);
392 * Updates this distributed mesh by splitting one of its part.
393 * This splitting method leans on medsplitter, by V. Bergeaud (CEA).
394 * \param pPartName name of the part to be splitted.
395 * \param pNbParts number of sub-parts.
396 * \param pPartitionner MULTIPR_METIS or MULTIPR_SCOTCH.
397 * \throw RuntimeException if any error occurs.
399 void splitPart(const char* pPartName, int pNbParts, int pPartitionner);
402 * Creates 3 resolution (CURRENT = FULL, MEDIUM and LOW) of a part of this distributed mesh.
403 * Names of new meshes are <original_name>_MED and <original_name>_LOW.
408 * \param pTMed threshold used to generate MEDIUM resolution.
409 * \param pTLow threshold used to generate LOW resolution (must be >= pTMed).
411 * \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.
412 * \return a list of strings, containing names of empty resulting parts, empty list if all resolutions are non-empty.
413 * \throw RuntimeException if any error occurs.
415 std::list<std::string> decimatePart(
416 const char* pPartName,
417 const char* pFieldName,
419 const char* pFilterName,
420 const char* pFilterParams);
423 * Returns useful information to configure decimation parameters.
424 * Depends on part, field and filter: generic operation.
425 * \param pPartName name of the part.
426 * \param pFieldName name of the field used for decimation.
427 * \param pFieldIt iteration (time step) of the field.
428 * \param pFilterName name of the filter to be used.
429 * \param pFilterParams params to be used with the filter (depends on filter; this string will be parsed).
432 std::string evalDecimationParams(
433 const char* pPartName,
434 const char* pFieldName,
436 const char* pFilterName,
437 const char* pFilterParams);
440 * Get the statistics of the last decimation.
441 * The format is : "lowres-compression-rate medres-compression-rate".
443 std::string& getDecimationStatistics() { return mStats; }
445 //---------------------------------------------------------------------
447 //---------------------------------------------------------------------
450 * Reads the master file of a distributed MED file.
451 * \param pMEDfilename
452 * \throw NullArgumentException if pMEDfilename is NULL.
453 * \throw IOException if any i/o error occurs.
455 void readDistributedMED(const char* pMEDfilename);
458 * Works like \a readDistributedMED(), but assumes that the distributed MED file was
459 * moved from the original location and its ASCII master file needs to be updated.
461 * \note This method is mentioned to be used only in persistence.
463 void readPersistentDistributedMED(const char* pMEDfilename);
466 * Writes this distributed MED file (including master file and sub MED files if necessary).
467 * \param pMEDfilenamePrefix
468 * \throw NullArgumentException if pMEDfilename is NULL.
469 * \throw IOException if any i/o error occurs.
471 void writeDistributedMED (const char* pMEDfilenamePrefix,
472 bool pIsPersistence = false);
475 * Update save progress.
476 * \param pPercents current save progress in percents.
478 void setProgress (int pPercents);
481 * Obtain save progress.
482 * \return current save progress in percents.
487 * Read and write the fields for optimized domain split.
488 * \param pMeshName The name of the current mesh.
489 * \param pGroups The groups.
490 * \param pGaussList The list of gauss index.
491 * \param pProfils The profiles of the mesh.
493 void readAndWriteFields (const char* pMeshName, std::vector<Group*>* pGroups,
494 GaussIndexList* pGaussList, std::vector<Profil*>& pProfils);
497 * Dumps any MeshDis to the given output stream.
498 * \param pOs any output stream.
499 * \param pM any MeshDis.
500 * \return the output stream pOs.
502 friend std::ostream& operator<<(std::ostream& pOs, MeshDis& pM);
507 * Recomputes the number of parts in this distributed mesh.
508 * This method is used by writeDistributedMED().
509 * \return the number of parts in this distributed mesh.
511 int computeNumParts();
515 char mSequentialMEDFilename[256]; /**< Name of the original MED file used to build distribyuted MED. */
516 char mDistributedMEDFilename[256]; /**< Name of this distributed MED file (= name of the master file). */
517 std::vector<MeshDisPart*> mParts; /**< Table of sub-parts; a distributed mesh is composed of N sub-part, where N = mParts.size(). */
518 std::string mStats; /**< Statistics of the last decimation */
520 int mWriteProgress; /**< Mesh saving progress in percents */
521 boost::recursive_mutex mWriteMutex; /**< For thread-safe access to mWriteProgress */
525 // do not allow copy constructor
526 MeshDis(const MeshDis&);
529 MeshDis& operator=(const MeshDis&);
531 // do not allow operator ==
532 bool operator==(const MeshDis&);
537 //----------------------------------------------------------------------------
538 //! This class provide thread-safety for MEDWrapper interaction
541 TLockProxy& operator=(const TLockProxy& );
543 boost::shared_ptr<boost::mutex> myMutex;
546 TLockProxy(MeshDis* theMeshDis, boost::shared_ptr<boost::mutex> theMutex);
550 MeshDis * operator-> () const;
553 //----------------------------------------------------------------------------
554 //! To specialize the SharedPtr for MeshDis
556 class SharedPtr: public boost::shared_ptr<T>
560 : myMutex(new boost::mutex())
564 explicit SharedPtr(Y * p)
565 : boost::shared_ptr<T>(p),
566 myMutex(new boost::mutex())
570 SharedPtr(SharedPtr<Y> const & r)
571 : boost::shared_ptr<T>(r,boost::detail::dynamic_cast_tag()),
577 operator=(SharedPtr<Y> const & r)
579 boost::shared_ptr<T>(r,boost::detail::dynamic_cast_tag()).swap(*this);
580 myMutex = r->myMutex;
586 operator()(Y * p) // Y must be complete
588 return operator=<Y>(SharedPtr<Y>(p));
593 operator()(SharedPtr<Y> const & r) // Y must be complete
595 return operator=<Y>(SharedPtr<Y>(r));
598 TLockProxy operator-> () const // never throws
600 return TLockProxy(this->get(), myMutex);
604 void reset (Y * p) // Y must be complete
606 //boost::detail::thread::lock_ops<typename T::TMutex>::lock(p->myMutex);
607 boost::detail::thread::lock_ops<boost::mutex>::lock(*myMutex);
608 if (boost::shared_ptr<T>::get() != NULL) delete (boost::shared_ptr<T>::get());
609 boost::shared_ptr<T>(p).swap(*this);
610 //boost::detail::thread::lock_ops<typename T::TMutex>::unlock(p->myMutex);
611 boost::detail::thread::lock_ops<boost::mutex>::unlock(*myMutex);
615 operator const T& () const;
619 T& operator* () const;
621 T * get() const // never throws
623 return boost::shared_ptr<T>::get();
627 boost::shared_ptr<boost::mutex> myMutex;
631 } // namespace MULTIPR
634 #endif // MULTIPR_MESHDIS_HXX