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