Salome HOME
adding a new test for makeMesh method.
[modules/med.git] / src / MULTIPR / MULTIPR_MeshDis.hxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Partitioning/decimation module for the SALOME v3.2 platform
20 //
21 /**
22  * \file    MULTIPR_MeshDis.hxx
23  *
24  * \brief   Class MeshDis: distributed mesh.
25  *          = MASTER file (ASCII) -> list of sequential MED file.
26  *
27  * \author  Olivier LE ROUX - CS, Virtual Reality Dpt
28  * 
29  * \date    01/2007
30  */
31
32 #ifndef MULTIPR_MESHDIS_HXX
33 #define MULTIPR_MESHDIS_HXX
34
35 //*****************************************************************************
36 // Includes section
37 //*****************************************************************************
38
39 extern "C"
40 {
41     #include "med.h"
42 }
43
44 #include <iostream>
45 #include <vector>
46
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"
55
56 #include <boost/thread/recursive_mutex.hpp>
57 #include <boost/thread/mutex.hpp>
58 #include <boost/shared_ptr.hpp>
59
60 namespace multipr
61 {
62
63 //*****************************************************************************
64 // Pre-declaration
65 //*****************************************************************************
66
67 class Mesh;
68 class Group;
69 class Profil;
70
71 //*****************************************************************************
72 // Class MeshDisPart = a sub-part of a distributed mesh.
73 //
74 // It can be :
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 //*****************************************************************************
79
80 class MeshDisPart
81 {
82
83 public:
84
85     /**
86      * Action to be done for this part on next writing on disk.
87      */
88     enum OnNextWrite
89     {
90         MULTIPR_UNDEFINED,
91         MULTIPR_KEEP_AS_IT,
92         MULTIPR_WRITE_MESH,
93         MULTIPR_WRITE_PARTS
94     };
95     
96 public:
97
98     /**
99      * Builds an empty part of a distributed mesh (default constructor).
100      */
101     MeshDisPart();
102     
103     /**
104      * Destructor. Removes everything.
105      */
106     ~MeshDisPart();
107     
108     /**
109      * Resets this object in its state by default (empty). Cleans memory.
110      */
111     void reset();
112     
113     /**
114      * Creates a MeshDisPart.
115      * \param  pToDoOnNextWrite
116      * \param  pMeshName
117      * \param  pId
118      * \param  pPartName
119      * \param  pPath
120      * \param  pMEDFileName file name excluding the path.
121      * \param  pMesh can be NULL.
122      */
123     void create(
124         OnNextWrite pToDoOnNextWrite,
125         const char* pMeshName, 
126         int         pId,
127         const char* pPartName,
128         const char* pPath,
129         const char* pMEDFileName,
130         Mesh*       pMesh);
131     
132     //---------------------------------------------------------------------
133     // Basic accessors/mutators
134     //---------------------------------------------------------------------
135     
136     /**
137      * Returns the name of this part.
138      * \return the name of this part.
139      */
140     const char* getPartName() const { return mPartName; }
141     
142     /**
143      * Returns the name of the mesh of this part.
144      * \return the name of the mesh of this part.
145      */
146     const char* getMeshName() const { return mMeshName; }
147     
148     /**
149      * Returns the mesh of this part.
150      * \return the mesh of this part.
151      */
152     const Mesh* getMesh() const { return mMesh; }
153         
154     /**
155      * Returns the MED filename which contain this part.
156      * \return the MED filename which contain this part.
157      */
158     const char* getMEDFileName() const { return mMEDFileName; }
159     
160     /**
161      * Returns the suffix of the related MED filename (without .med extension).
162      * For examples:
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"
166      */
167     const char* getMEDFileNameSuffix() const;
168     
169     /**
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.
172      */
173     OnNextWrite getOnNextWrite() const { return mToDoOnNextWrite; }
174      
175     //---------------------------------------------------------------------
176     // I/O
177     //---------------------------------------------------------------------
178     
179     /**
180      * Reads the sequentiel MED file corresponding to this part.
181      * \throw  IOException if an i/o error occurs.
182      */
183     void readMED();
184      
185     /**
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.
190      */
191     friend std::ostream& operator<<(std::ostream& pOs, MeshDisPart& pM);
192     
193 private:
194
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.
199     
200     OnNextWrite  mToDoOnNextWrite;               /**< See enum OnNextWrite. */
201     
202     //---------------------------------------------------------------------
203     // Case 1, 2, and 3
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. */
210     
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. */
215     
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. */
222     
223 private:
224
225     // do not allow copy constructor
226     MeshDisPart(const MeshDisPart&);
227     
228     // do not allow copy
229     MeshDisPart& operator=(const MeshDisPart&);
230     
231     // do not allow operator ==
232     bool operator==(const MeshDisPart&); 
233     
234     //---------------------------------------------------------------------
235     // Friends
236     //---------------------------------------------------------------------    
237     friend class MeshDis;
238     
239 }; // class MeshDisPart
240
241
242 //*****************************************************************************
243 // Class MeshDis
244 //*****************************************************************************
245
246 class MeshDis
247 {
248 public:
249
250     /**
251      * Builds an empty mesh (default constructor).
252      */
253     MeshDis();
254      
255     /**
256      * Destructor. Removes everything.
257      */
258     ~MeshDis();
259      
260     /**
261      * Resets this object in its state by default (empty). Clean memory.
262      */
263     void reset();
264     
265     //---------------------------------------------------------------------
266     // Basic accessors/mutators
267     //---------------------------------------------------------------------
268
269     /**
270      * Sets the name of the associated sequential MED file (=original MED file).
271      * \param  pFilename name of the associated sequential MED file.
272      */
273     void setSequentialMEDFilename(const char* pFilename);
274     
275     /**
276      * Returns the name of this sequential MED file (=original MED file).
277      * \return the name of this sequential MED file (=original MED file).
278      */
279     const char* getSequentialMEDFilename() const { return mSequentialMEDFilename; }
280        
281     /**
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).
284      */
285     const char* getDistributedMEDFilename() const { return mDistributedMEDFilename; }
286      
287     /**
288      * Adds a new part to this distributed mesh.
289      * Used by the split process (extract groups).
290      * \param  pToDoOnNextWrite
291      * \param  pMeshName
292      * \param  pId
293      * \param  pPartName
294      * \param  pPath
295      * \param  pMEDFileName
296      * \param  pMesh can be NULL.
297      */
298     void addMesh(
299         MeshDisPart::OnNextWrite pToDoOnNextWrite,
300         const char* pMeshName, 
301         int         pId,
302         const char* pPartName,
303         const char* pPath,
304         const char* pMEDFileName,
305         Mesh*       pMesh);
306     
307     /**
308      * Inserts a new part to this distributed mesh.
309      * Used by the decimation process.
310      * \param  pToDoOnNextWrite
311      * \param  pMeshName
312      * \param  pId
313      * \param  pPartName
314      * \param  pPath
315      * \param  pMEDFileName
316      * \param  pMesh can be NULL.
317      * \param  pPosition insert after this position. Start at 1.
318      */
319     void insertMesh(
320         MeshDisPart::OnNextWrite pToDoOnNextWrite,
321         const char* pMeshName, 
322         int         pId,
323         const char* pPartName,
324         const char* pPath,
325         const char* pMEDFileName,
326         Mesh*       pMesh,
327         int         pPosition);
328     
329     /**
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.
333      */
334     void removeParts(const char* pPrefixPartName);
335     
336     /**
337      * Returns the current number of parts in this distributed mesh.
338      * \return the current number of parts in this distributed mesh.
339      */
340     int getNumParts() const { return mParts.size(); }
341     
342     /**
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.
346      */
347     MeshDisPart* getPart(int pIndex) const { return mParts[pIndex]; }
348     
349     /**
350      * Returns the list of meshes contained in this distributed MED file.
351      * \return the list of meshes contained in this distributed MED file.
352      */
353     std::vector<std::string> getMeshes() const; 
354     
355     /**
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.
360      */
361     std::vector<std::string> getFields(const char* pPartList, bool pAddNbGaussPoint = false) const; 
362     
363     /**
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.
368      */
369     int getTimeStamps(const char* pPartList, const char* pFieldName) const; 
370     
371     /**
372      * Returns all information about a part.
373      * \param  pPartName name of the part.
374      * \return all information about a part.
375      */
376     std::string getPartInfo(const char* pPartName);
377      
378     //---------------------------------------------------------------------
379     // Algorithms
380     //---------------------------------------------------------------------
381     
382     /**
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.
388      */
389     MeshDisPart* findPart(const char* pPartName);
390     
391     /**
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.
398      */
399     void splitPart(const char* pPartName, int pNbParts, int pPartitionner);
400     
401     /**
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.
404      * \param  pPartName
405      * \param  pFielName
406      * \param  pFieldIt
407      * \param  pFilterName
408      * \param  pTMed        threshold used to generate MEDIUM resolution.
409      * \param  pTLow        threshold used to generate LOW resolution (must be >= pTMed).
410      * \param  pRadius
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.
414      */
415     std::list<std::string> decimatePart(
416         const char* pPartName, 
417         const char* pFieldName,
418         med_int     pFieldIt,
419         const char* pFilterName,
420         const char* pFilterParams);
421         
422     /**
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).
430      * \return 
431      */
432     std::string evalDecimationParams(
433         const char* pPartName, 
434         const char* pFieldName, 
435         int         pFieldIt, 
436         const char* pFilterName,
437         const char* pFilterParams);
438     
439         /**
440          * Get the statistics of the last decimation.
441          * The format is : "lowres-compression-rate medres-compression-rate".
442          */
443         std::string& getDecimationStatistics() { return mStats; }
444                 
445     //---------------------------------------------------------------------
446     // I/O
447     //---------------------------------------------------------------------
448     
449     /**
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.
454      */
455     void readDistributedMED(const char* pMEDfilename);
456
457     /**
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.
460      *
461      * \note This method is mentioned to be used only in persistence.
462      */
463     void readPersistentDistributedMED(const char* pMEDfilename);
464
465     /**
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.
470      */
471     void writeDistributedMED (const char* pMEDfilenamePrefix,
472                               bool        pIsPersistence = false);
473
474     /**
475      * Update save progress.
476      * \param pPercents current save progress in percents.
477      */
478     void setProgress (int pPercents);
479
480     /**
481      * Obtain save progress.
482      * \return current save progress in percents.
483      */
484     int getProgress();
485     
486     /**
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.
492      */
493     void readAndWriteFields (const char* pMeshName, std::vector<Group*>* pGroups,
494                              GaussIndexList* pGaussList, std::vector<Profil*>& pProfils);
495
496     /**
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.
501      */
502     friend std::ostream& operator<<(std::ostream& pOs, MeshDis& pM);
503     
504 private:
505
506     /**
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.
510      */
511     int computeNumParts();
512     
513 private:
514
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 */
519
520     int                       mWriteProgress;               /**< Mesh saving progress in percents */
521     boost::recursive_mutex    mWriteMutex;                  /**< For thread-safe access to mWriteProgress */
522
523 private:
524
525     // do not allow copy constructor
526     MeshDis(const MeshDis&);
527     
528     // do not allow copy
529     MeshDis& operator=(const MeshDis&);
530     
531     // do not allow operator ==
532     bool operator==(const MeshDis&); 
533     
534 }; // class MeshDis
535
536 /*
537 //----------------------------------------------------------------------------
538 //! This class provide thread-safety for MEDWrapper interaction
539 class TLockProxy
540 {
541   TLockProxy& operator=(const TLockProxy& );
542   MeshDis* myMeshDis;
543   boost::shared_ptr<boost::mutex> myMutex;
544
545 public:
546   TLockProxy(MeshDis* theMeshDis, boost::shared_ptr<boost::mutex> theMutex);
547
548   ~TLockProxy();
549
550   MeshDis * operator-> () const;
551 };
552
553 //----------------------------------------------------------------------------
554 //! To specialize the SharedPtr for MeshDis
555 template<class T>
556 class SharedPtr: public boost::shared_ptr<T>
557 {
558 public:
559   SharedPtr()
560     : myMutex(new boost::mutex())
561   {}
562
563   template<class Y>
564   explicit SharedPtr(Y * p)
565     : boost::shared_ptr<T>(p),
566       myMutex(new boost::mutex())
567   {}
568
569   template<class Y>
570   SharedPtr(SharedPtr<Y> const & r)
571     : boost::shared_ptr<T>(r,boost::detail::dynamic_cast_tag()),
572       myMutex(r->myMutex)
573   {}
574
575   template<class Y>
576   SharedPtr&
577   operator=(SharedPtr<Y> const & r)
578   {
579     boost::shared_ptr<T>(r,boost::detail::dynamic_cast_tag()).swap(*this);
580     myMutex = r->myMutex;
581     return *this;
582   }
583
584   template<class Y>
585   SharedPtr&
586   operator()(Y * p) // Y must be complete
587   {
588     return operator=<Y>(SharedPtr<Y>(p));
589   }
590
591   template<class Y>
592   SharedPtr&
593   operator()(SharedPtr<Y> const & r) // Y must be complete
594   {
595     return operator=<Y>(SharedPtr<Y>(r));
596   }
597
598   TLockProxy operator-> () const // never throws
599   {
600     return TLockProxy(this->get(), myMutex);
601   }
602
603   template<class Y>
604   void reset (Y * p) // Y must be complete
605   {
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);
612   }
613
614 protected:
615   operator const T& () const;
616
617   operator T& ();
618
619   T& operator* () const;
620
621   T * get() const // never throws
622   {
623     return boost::shared_ptr<T>::get();
624   }
625
626 private:
627   boost::shared_ptr<boost::mutex> myMutex;
628 };
629 */
630
631 } // namespace MULTIPR
632
633
634 #endif // MULTIPR_MESHDIS_HXX
635
636 // EOF