]> SALOME platform Git repositories - modules/med.git/blob - src/MEDMEM/MEDMEM_DriverTools.hxx
Salome HOME
update after merging trhe branches CEA_V3_0_x, OCC_V3_1_0_a1_x, and the main
[modules/med.git] / src / MEDMEM / MEDMEM_DriverTools.hxx
1 #ifndef DRIVERTOOLS_HXX
2 #define DRIVERTOOLS_HXX
3
4
5 #include "MEDMEM_define.hxx"
6 #include "MEDMEM_Exception.hxx"
7 #include "MEDMEM_Field.hxx"
8 #include <string>
9 #include <vector>
10 #include <set>
11 #include <list>
12 #include <map>
13 #include <iostream>
14 #include <iomanip>
15
16 namespace MEDMEM {
17 class MESH;
18 class CONNECTIVITY;
19 class COORDINATE;
20 class GROUP;
21 class FAMILY;
22 struct _noeud
23 {
24     mutable int number;
25     std::vector<double> coord;
26 };
27
28 typedef pair<int,int> _link; // a pair of node numbers
29
30 struct _maille
31 {
32     typedef std::map<int,_noeud>::iterator iter;
33     MED_EN::medGeometryElement geometricType;
34     std::vector< iter > sommets;
35     mutable unsigned ordre; // l'ordre est fixé après insertion dans le set, et ne change ni l'état, ni l'ordre -> mutable
36     mutable bool reverse; // to reverse sommets of a face
37     mutable list<unsigned> groupes; // the GROUPs maille belongs to, used to create families
38
39     _maille() : geometricType(MED_EN::MED_NONE),ordre(0),reverse(false)
40     {
41     };
42     _maille(MED_EN::medGeometryElement _geometricType, size_t nelem) : geometricType(_geometricType),ordre(0),reverse(false)
43     {
44         sommets.reserve(nelem);
45     };
46     int dimension() const // retourne la dimension de la maille
47     {
48         return geometricType/100;
49     };
50     bool operator < (const _maille& ma) const;
51     MED_EN::medEntityMesh getEntity(const int meshDimension) const throw (MEDEXCEPTION);
52    _link link(int i) const;
53 };
54
55 struct _mailleIteratorCompare // pour ordonner le set d'iterateurs sur mailles
56 {
57     bool operator () (std::set<_maille>::iterator i1, std::set<_maille>::iterator i2)
58     {
59         return *i1<*i2;
60     }
61 };
62
63 struct _groupe
64 {
65     typedef std::vector< std::set<_maille>::iterator>::const_iterator mailleIter;
66     std::string nom;
67     std::vector< std::set<_maille>::iterator > mailles; // iterateurs sur les mailles composant le groupe
68     std::vector<int> groupes; // indices des sous-groupes composant le groupe
69     std::map<const _maille*,int> relocMap; // map _maille* -> index in MEDMEM::GROUP.getNumber(MED_ALL_ELEMENTS). It is built by _intermediateMED::getGroups()
70     bool empty() const { return mailles.empty() && groupes.empty(); }
71 };
72
73 struct _fieldBase {
74   // a field contains several subcomponents each referring to its own support and
75   // having several named components
76   struct _sub_data {
77     int                      _supp_id;    // group index within _intermediateMED::groupes
78     std::vector<std::string> _comp_names; // componenet names
79     void setData( int nb_comp, int supp_id )
80     { _supp_id = supp_id - 1; _comp_names.resize(nb_comp); }
81     int nbComponents() const { return _comp_names.size(); }
82     std::string & compName( int i_comp ) { return _comp_names[ i_comp ]; }
83   };
84   std::vector< _sub_data > _sub;
85   int                      _group_id; // group index within _intermediateMED::groupes
86   // if _group_id == -1 then each subcomponent makes a separate MEDMEM::FIELD, else all subcomponents
87   // are converted into one MEDMEM::FIELD. The latter is possible only if nb of components in all subs
88   // is the same and supports of subcomponents do not overlap
89   MED_EN::med_type_champ   _type;
90   string                   _name;
91
92   _fieldBase( MED_EN::med_type_champ theType, int nb_sub )
93     : _group_id(-1),_type(theType) { _sub.resize( nb_sub ); }
94   virtual std::list<std::pair< FIELD_*, int> > getField(std::vector<_groupe>& groupes) const = 0;
95   void getGroupIds( std::set<int> & ids, bool all ) const; // return ids of main and/or sub-groups
96   bool hasCommonSupport() const { return _group_id >= 0; } // true if there is one support for all subs
97   bool hasSameComponentsBySupport() const;
98   virtual void dump(std::ostream&) const;
99   virtual ~_fieldBase() {}
100 };
101
102 template< class T > class _field: public _fieldBase
103 {
104   std::vector< std::vector< T > > comp_values;
105  public:
106   _field< T > ( MED_EN::med_type_champ theType, int nb_sub, int total_nb_comp )
107     : _fieldBase( theType, nb_sub ) { comp_values.reserve( total_nb_comp ); }
108   std::vector< T >& addComponent( int nb_values ); // return a vector ready to fill in
109   std::list<std::pair< FIELD_*, int> > getField(std::vector<_groupe>& groupes) const;
110   virtual void dump(std::ostream&) const;
111 };
112
113 /*!
114  * \if developper
115  * Intermediate structure used by drivers to store data read from the other format file.
116  * The structure provides functions that transform the stored data to the MED format : 
117  * getCoordinate(), getConnectivity(), getGroups().
118  * The elements inserted in maillage and points are automaticaly ordered.
119  * Renumbering are performed by getConnectivity & getGroups before writing the MED structures.
120  * Read the conception ducumentation for more details.
121  * \endif
122  */
123 struct _intermediateMED
124 {
125     std::set<_maille>        maillage;
126     std::vector<_groupe>     groupes;
127     std::vector<GROUP *>     medGroupes;
128     std::map< int, _noeud >  points;
129     std::list< _fieldBase* > fields;
130     bool hasMixedCells; // true if there are groups with mixed entity types
131
132     CONNECTIVITY * getConnectivity(); // set MED connectivity from the intermediate structure
133     COORDINATE * getCoordinate(const string & coordinateSystem="CARTESIAN"); // set MED coordinate from the 
134                                                                              // intermediate structure
135     void getFamilies(std::vector<FAMILY *> & _famCell, std::vector<FAMILY *> & _famFace, 
136                      std::vector<FAMILY *> & _famEdge, std::vector<FAMILY *> & _famNode, MESH * _ptrMesh);
137     void getGroups(std::vector<GROUP *> & _groupCell, std::vector<GROUP *> & _groupFace, 
138             std::vector<GROUP *> & _groupEdge, std::vector<GROUP *> & _groupNode, MESH * _ptrMesh);
139     GROUP * getGroup( int i );
140
141     void getFields(std::list< FIELD_* >& fields);
142
143     // used by previous functions to renumber points & mesh.
144     void treatGroupes(); // detect groupes of mixed dimention
145     void numerotationMaillage(); 
146     void numerotationPoints();
147
148     ~_intermediateMED();
149 };
150
151 std::ostream& operator << (std::ostream& , const _maille& );
152 std::ostream& operator << (std::ostream& , const _groupe& );
153 std::ostream& operator << (std::ostream& , const _noeud& );
154 std::ostream& operator << (std::ostream& , const _intermediateMED& );
155 std::ostream& operator << (std::ostream& , const _fieldBase* );
156
157 // ===========================================================
158 //                 field template implementation           //
159 // ===========================================================
160
161 template <class T>
162   std::vector< T >& _field< T >::addComponent( int nb_values )
163 {
164   comp_values.push_back( std::vector< T >() );
165   std::vector< T >& res = comp_values.back();
166   res.resize( nb_values );
167   return res;
168 }
169
170 //=======================================================================
171 //function : getField
172 //purpose  : return list of pairs< field, supporting_group_id >
173 //=======================================================================
174
175 template <class T>
176 std::list<std::pair< FIELD_*, int> > _field< T >::getField(std::vector<_groupe> & groupes) const
177 {
178   std::list<std::pair< FIELD_*, int> > res;
179
180   _groupe* grp = 0;
181   if ( hasCommonSupport() ) { // several subs are combined into one field
182     grp = & groupes[ _group_id ];
183     if ( !grp || grp->empty() )
184       return res;
185   }
186   FIELD< T > * f = 0;
187   int i_comp_tot = 0, nb_fields = 0;
188   std::set<int> supp_id_set;
189   // loop on subs of this field
190   std::vector< _sub_data >::const_iterator sub_data = _sub.begin();
191   for ( int i_sub = 1; sub_data != _sub.end(); ++sub_data, ++i_sub )
192   {
193     // nb values in a field
194     if ( !hasCommonSupport() )
195       grp = & groupes[ sub_data->_supp_id ];
196     int nb_val = grp->relocMap.size();
197     if ( !nb_val ) {
198       INFOS("Skip field <" << _name << ">: invalid supporting group "
199             << (hasCommonSupport() ? _group_id : sub_data->_supp_id )
200             << " of " << i_sub << "-th subcomponent" );
201       return res;
202     }
203
204     //create a field
205     if ( !f || !hasCommonSupport() || !supp_id_set.insert( sub_data->_supp_id ).second )
206     {
207       supp_id_set.clear();
208       ++nb_fields;
209       f = new FIELD< T >;
210       f->setNumberOfComponents( sub_data->nbComponents() );
211       f->setComponentsNames( & sub_data->_comp_names[ 0 ] );
212       f->setNumberOfValues ( nb_val );
213       f->setName( _name );
214       f->setValueType( _type );
215       vector<string> str( sub_data->nbComponents() );
216       f->setComponentsDescriptions( &str[0] );
217       f->setMEDComponentsUnits( &str[0] );
218       res.push_back( make_pair( f , hasCommonSupport() ? _group_id : sub_data->_supp_id ));
219       MESSAGE(" MAKE " << nb_fields << "-th field <" << _name << "> on group_id " << _group_id );
220     }
221     // set values
222     MEDARRAY< T > * medarray =
223       new MEDARRAY< T >( sub_data->nbComponents(), nb_val, MED_EN::MED_NO_INTERLACE );
224     f->setValue( medarray );
225     // loop on components of a sub
226     for ( int i_comp = 0; i_comp < sub_data->nbComponents(); ++i_comp )
227     {
228       // get nb elements in a group
229       _groupe & sub_grp = groupes[ sub_data->_supp_id ];
230       int nb_supp_elems = sub_grp.mailles.size();
231       MESSAGE("insert sub data, group_id: " << sub_data->_supp_id <<
232               ", nb values: " << comp_values[ i_comp_tot ].size() <<
233               ", relocMap.size: " << sub_grp.relocMap.size() <<
234               ", nb mailles: " << nb_supp_elems);
235
236       // store values
237       const std::vector< T > & values = comp_values[ i_comp_tot++ ];
238       bool oneValue = ( values.size() == 1 );
239       ASSERT( oneValue || values.size() == nb_supp_elems );
240       for ( int k = 0; k < nb_supp_elems; ++k )
241       {
242         const T& val = oneValue ? values[ 0 ] : values[ k ];
243         const _maille* ma = &(*sub_grp.mailles[ k ]);
244         std::map<const _maille*,int>::const_iterator ma_i = grp->relocMap.find( ma );
245         if ( ma_i == grp->relocMap.end() )
246           throw MEDEXCEPTION
247             (LOCALIZED(STRING("_field< T >::getField(), cant find elem index. ")
248                        << k << "-th elem: " << ma));
249         if ( ma_i->second > nb_val )
250           throw MEDEXCEPTION
251             (LOCALIZED(STRING("_field< T >::getField(), wrong elem position. ")
252                        << k << "-th elem: " << ma
253                        << ", pos (" << ma_i->second << ") must be <= " << nb_val));
254         medarray->setIJ( ma_i->second, i_comp + 1, val );
255       }
256     }
257   }
258   return res;
259 }
260
261
262 template <class T> void _field< T >::dump(std::ostream& os) const
263 {
264   _fieldBase::dump(os);
265   os << endl;
266   for ( int i = 0 ; i < comp_values.size(); ++i )
267   {
268     os << "    " << i+1 << "-th component, nb values: " << comp_values[ i ].size() << endl;
269   }
270 }
271
272 }; // namespace MEDMEM
273
274 #endif /* DRIVERTOOLS_HXX */