Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/med.git] / src / MULTIPR / MULTIPR_MeshDis.hxx
1 // Project MULTIPR, IOLS WP1.2.1 - EDF/CS
2 // Partitioning/decimation module for the SALOME v3.2 platform
3
4 /**
5  * \file    MULTIPR_MeshDis.hxx
6  *
7  * \brief   Class MeshDis: distributed mesh.
8  *          = MASTER file (ASCII) -> list of sequential MED file.
9  *
10  * \author  Olivier LE ROUX - CS, Virtual Reality Dpt
11  * 
12  * \date    01/2007
13  */
14
15 #ifndef MULTIPR_MESHDIS_HXX
16 #define MULTIPR_MESHDIS_HXX
17
18 //*****************************************************************************
19 // Includes section
20 //*****************************************************************************
21
22 extern "C"
23 {
24     #include "med.h"
25 }
26
27 #include <iostream>
28 #include <vector>
29
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"
38
39 #include <boost/thread/recursive_mutex.hpp>
40 #include <boost/thread/mutex.hpp>
41 #include <boost/shared_ptr.hpp>
42
43 namespace multipr
44 {
45
46 //*****************************************************************************
47 // Pre-declaration
48 //*****************************************************************************
49
50 class Mesh;
51 class Group;
52 class Profil;
53
54 //*****************************************************************************
55 // Class MeshDisPart = a sub-part of a distributed mesh.
56 //
57 // It can be :
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 //*****************************************************************************
62
63 class MeshDisPart
64 {
65
66 public:
67
68     /**
69      * Action to be done for this part on next writing on disk.
70      */
71     enum OnNextWrite
72     {
73         MULTIPR_UNDEFINED,
74         MULTIPR_KEEP_AS_IT,
75         MULTIPR_WRITE_MESH,
76         MULTIPR_WRITE_PARTS
77     };
78     
79 public:
80
81     /**
82      * Builds an empty part of a distributed mesh (default constructor).
83      */
84     MeshDisPart();
85     
86     /**
87      * Destructor. Removes everything.
88      */
89     ~MeshDisPart();
90     
91     /**
92      * Resets this object in its state by default (empty). Cleans memory.
93      */
94     void reset();
95     
96     /**
97      * Creates a MeshDisPart.
98      * \param  pToDoOnNextWrite
99      * \param  pMeshName
100      * \param  pId
101      * \param  pPartName
102      * \param  pPath
103      * \param  pMEDFileName file name excluding the path.
104      * \param  pMesh can be NULL.
105      */
106     void create(
107         OnNextWrite pToDoOnNextWrite,
108         const char* pMeshName, 
109         int         pId,
110         const char* pPartName,
111         const char* pPath,
112         const char* pMEDFileName,
113         Mesh*       pMesh);
114     
115     //---------------------------------------------------------------------
116     // Basic accessors/mutators
117     //---------------------------------------------------------------------
118     
119     /**
120      * Returns the name of this part.
121      * \return the name of this part.
122      */
123     const char* getPartName() const { return mPartName; }
124     
125     /**
126      * Returns the name of the mesh of this part.
127      * \return the name of the mesh of this part.
128      */
129     const char* getMeshName() const { return mMeshName; }
130     
131     /**
132      * Returns the mesh of this part.
133      * \return the mesh of this part.
134      */
135     const Mesh* getMesh() const { return mMesh; }
136         
137     /**
138      * Returns the MED filename which contain this part.
139      * \return the MED filename which contain this part.
140      */
141     const char* getMEDFileName() const { return mMEDFileName; }
142     
143     /**
144      * Returns the suffix of the related MED filename (without .med extension).
145      * For examples:
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"
149      */
150     const char* getMEDFileNameSuffix() const;
151     
152     /**
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.
155      */
156     OnNextWrite getOnNextWrite() const { return mToDoOnNextWrite; }
157      
158     //---------------------------------------------------------------------
159     // I/O
160     //---------------------------------------------------------------------
161     
162     /**
163      * Reads the sequentiel MED file corresponding to this part.
164      * \throw  IOException if an i/o error occurs.
165      */
166     void readMED();
167      
168     /**
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.
173      */
174     friend std::ostream& operator<<(std::ostream& pOs, MeshDisPart& pM);
175     
176 private:
177
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.
182     
183     OnNextWrite  mToDoOnNextWrite;               /**< See enum OnNextWrite. */
184     
185     //---------------------------------------------------------------------
186     // Case 1, 2, and 3
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. */
193     
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. */
198     
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. */
205     
206 private:
207
208     // do not allow copy constructor
209     MeshDisPart(const MeshDisPart&);
210     
211     // do not allow copy
212     MeshDisPart& operator=(const MeshDisPart&);
213     
214     // do not allow operator ==
215     bool operator==(const MeshDisPart&); 
216     
217     //---------------------------------------------------------------------
218     // Friends
219     //---------------------------------------------------------------------    
220     friend class MeshDis;
221     
222 }; // class MeshDisPart
223
224
225 //*****************************************************************************
226 // Class MeshDis
227 //*****************************************************************************
228
229 class MeshDis
230 {
231 public:
232
233     /**
234      * Builds an empty mesh (default constructor).
235      */
236     MeshDis();
237      
238     /**
239      * Destructor. Removes everything.
240      */
241     ~MeshDis();
242      
243     /**
244      * Resets this object in its state by default (empty). Clean memory.
245      */
246     void reset();
247     
248     //---------------------------------------------------------------------
249     // Basic accessors/mutators
250     //---------------------------------------------------------------------
251
252     /**
253      * Sets the name of the associated sequential MED file (=original MED file).
254      * \param  pFilename name of the associated sequential MED file.
255      */
256     void setSequentialMEDFilename(const char* pFilename);
257     
258     /**
259      * Returns the name of this sequential MED file (=original MED file).
260      * \return the name of this sequential MED file (=original MED file).
261      */
262     const char* getSequentialMEDFilename() const { return mSequentialMEDFilename; }
263        
264     /**
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).
267      */
268     const char* getDistributedMEDFilename() const { return mDistributedMEDFilename; }
269      
270     /**
271      * Adds a new part to this distributed mesh.
272      * Used by the split process (extract groups).
273      * \param  pToDoOnNextWrite
274      * \param  pMeshName
275      * \param  pId
276      * \param  pPartName
277      * \param  pPath
278      * \param  pMEDFileName
279      * \param  pMesh can be NULL.
280      */
281     void addMesh(
282         MeshDisPart::OnNextWrite pToDoOnNextWrite,
283         const char* pMeshName, 
284         int         pId,
285         const char* pPartName,
286         const char* pPath,
287         const char* pMEDFileName,
288         Mesh*       pMesh);
289     
290     /**
291      * Inserts a new part to this distributed mesh.
292      * Used by the decimation process.
293      * \param  pToDoOnNextWrite
294      * \param  pMeshName
295      * \param  pId
296      * \param  pPartName
297      * \param  pPath
298      * \param  pMEDFileName
299      * \param  pMesh can be NULL.
300      * \param  pPosition insert after this position. Start at 1.
301      */
302     void insertMesh(
303         MeshDisPart::OnNextWrite pToDoOnNextWrite,
304         const char* pMeshName, 
305         int         pId,
306         const char* pPartName,
307         const char* pPath,
308         const char* pMEDFileName,
309         Mesh*       pMesh,
310         int         pPosition);
311     
312     /**
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.
316      */
317     void removeParts(const char* pPrefixPartName);
318     
319     /**
320      * Returns the current number of parts in this distributed mesh.
321      * \return the current number of parts in this distributed mesh.
322      */
323     int getNumParts() const { return mParts.size(); }
324     
325     /**
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.
329      */
330     MeshDisPart* getPart(int pIndex) const { return mParts[pIndex]; }
331     
332     /**
333      * Returns the list of meshes contained in this distributed MED file.
334      * \return the list of meshes contained in this distributed MED file.
335      */
336     std::vector<std::string> getMeshes() const; 
337     
338     /**
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.
343      */
344     std::vector<std::string> getFields(const char* pPartList, bool pAddNbGaussPoint = false) const; 
345     
346     /**
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.
351      */
352     int getTimeStamps(const char* pPartList, const char* pFieldName) const; 
353     
354     /**
355      * Returns all information about a part.
356      * \param  pPartName name of the part.
357      * \return all information about a part.
358      */
359     std::string getPartInfo(const char* pPartName);
360      
361     //---------------------------------------------------------------------
362     // Algorithms
363     //---------------------------------------------------------------------
364     
365     /**
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.
371      */
372     MeshDisPart* findPart(const char* pPartName);
373     
374     /**
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.
381      */
382     void splitPart(const char* pPartName, int pNbParts, int pPartitionner);
383     
384     /**
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.
387      * \param  pPartName
388      * \param  pFielName
389      * \param  pFieldIt
390      * \param  pFilterName
391      * \param  pTMed        threshold used to generate MEDIUM resolution.
392      * \param  pTLow        threshold used to generate LOW resolution (must be >= pTMed).
393      * \param  pRadius
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.
397      */
398     std::list<std::string> decimatePart(
399         const char* pPartName, 
400         const char* pFieldName,
401         med_int     pFieldIt,
402         const char* pFilterName,
403         const char* pFilterParams);
404         
405     /**
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).
413      * \return 
414      */
415     std::string evalDecimationParams(
416         const char* pPartName, 
417         const char* pFieldName, 
418         int         pFieldIt, 
419         const char* pFilterName,
420         const char* pFilterParams);
421     
422         /**
423          * Get the statistics of the last decimation.
424          * The format is : "lowres-compression-rate medres-compression-rate".
425          */
426         std::string& getDecimationStatistics() { return mStats; }
427                 
428     //---------------------------------------------------------------------
429     // I/O
430     //---------------------------------------------------------------------
431     
432     /**
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.
437      */
438     void readDistributedMED(const char* pMEDfilename);
439
440     /**
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.
443      *
444      * \note This method is mentioned to be used only in persistence.
445      */
446     void readPersistentDistributedMED(const char* pMEDfilename);
447
448     /**
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.
453      */
454     void writeDistributedMED (const char* pMEDfilenamePrefix,
455                               bool        pIsPersistence = false);
456
457     /**
458      * Update save progress.
459      * \param pPercents current save progress in percents.
460      */
461     void setProgress (int pPercents);
462
463     /**
464      * Obtain save progress.
465      * \return current save progress in percents.
466      */
467     int getProgress();
468     
469     /**
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.
475      */
476     void readAndWriteFields (const char* pMeshName, std::vector<Group*>* pGroups,
477                              GaussIndexList* pGaussList, std::vector<Profil*>& pProfils);
478
479     /**
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.
484      */
485     friend std::ostream& operator<<(std::ostream& pOs, MeshDis& pM);
486     
487 private:
488
489     /**
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.
493      */
494     int computeNumParts();
495     
496 private:
497
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 */
502
503     int                       mWriteProgress;               /**< Mesh saving progress in percents */
504     boost::recursive_mutex    mWriteMutex;                  /**< For thread-safe access to mWriteProgress */
505
506 private:
507
508     // do not allow copy constructor
509     MeshDis(const MeshDis&);
510     
511     // do not allow copy
512     MeshDis& operator=(const MeshDis&);
513     
514     // do not allow operator ==
515     bool operator==(const MeshDis&); 
516     
517 }; // class MeshDis
518
519 /*
520 //----------------------------------------------------------------------------
521 //! This class provide thread-safety for MEDWrapper interaction
522 class TLockProxy
523 {
524   TLockProxy& operator=(const TLockProxy& );
525   MeshDis* myMeshDis;
526   boost::shared_ptr<boost::mutex> myMutex;
527
528 public:
529   TLockProxy(MeshDis* theMeshDis, boost::shared_ptr<boost::mutex> theMutex);
530
531   ~TLockProxy();
532
533   MeshDis * operator-> () const;
534 };
535
536 //----------------------------------------------------------------------------
537 //! To specialize the SharedPtr for MeshDis
538 template<class T>
539 class SharedPtr: public boost::shared_ptr<T>
540 {
541 public:
542   SharedPtr()
543     : myMutex(new boost::mutex())
544   {}
545
546   template<class Y>
547   explicit SharedPtr(Y * p)
548     : boost::shared_ptr<T>(p),
549       myMutex(new boost::mutex())
550   {}
551
552   template<class Y>
553   SharedPtr(SharedPtr<Y> const & r)
554     : boost::shared_ptr<T>(r,boost::detail::dynamic_cast_tag()),
555       myMutex(r->myMutex)
556   {}
557
558   template<class Y>
559   SharedPtr&
560   operator=(SharedPtr<Y> const & r)
561   {
562     boost::shared_ptr<T>(r,boost::detail::dynamic_cast_tag()).swap(*this);
563     myMutex = r->myMutex;
564     return *this;
565   }
566
567   template<class Y>
568   SharedPtr&
569   operator()(Y * p) // Y must be complete
570   {
571     return operator=<Y>(SharedPtr<Y>(p));
572   }
573
574   template<class Y>
575   SharedPtr&
576   operator()(SharedPtr<Y> const & r) // Y must be complete
577   {
578     return operator=<Y>(SharedPtr<Y>(r));
579   }
580
581   TLockProxy operator-> () const // never throws
582   {
583     return TLockProxy(this->get(), myMutex);
584   }
585
586   template<class Y>
587   void reset (Y * p) // Y must be complete
588   {
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);
595   }
596
597 protected:
598   operator const T& () const;
599
600   operator T& ();
601
602   T& operator* () const;
603
604   T * get() const // never throws
605   {
606     return boost::shared_ptr<T>::get();
607   }
608
609 private:
610   boost::shared_ptr<boost::mutex> myMutex;
611 };
612 */
613
614 } // namespace MULTIPR
615
616
617 #endif // MULTIPR_MESHDIS_HXX
618
619 // EOF