Salome HOME
d38a8ab3b2fead49a0c7e4d093fc70784710d653
[modules/med.git] / src / MEDMEM / MEDMEM_Meshing.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 /*
24   File MEDMEM_Meshing.cxx
25 */
26
27 #include <string>
28
29 #include "MEDMEM_Utilities.hxx"
30 #include "MEDMEM_STRING.hxx"
31 #include "MEDMEM_Exception.hxx"
32 #include "MEDMEM_define.hxx"
33
34 #include "MEDMEM_Meshing.hxx"
35 #include "MEDMEM_Group.hxx"
36
37 using namespace std;
38 using namespace MEDMEM;
39 using namespace MED_EN;
40
41 namespace MEDMEM {
42 /*!
43
44 \defgroup MESHING_constructors Constructors
45
46 \defgroup MESHING_general General information settings
47
48 \defgroup MESHING_nodes Node coordinates settings
49
50 \defgroup MESHING_connectivity Connectivity settings
51
52 When defining the connectivity, MED_CELL elements connectivity
53 should be defined first. If necessary, constituent connectivities (MED_FACE and/or MED_EDGE) can be defined afterwards. 
54
55 \warning It should be kept in mind that when defining connectivities,
56 elements should be sorted in ascending type order (the type order 
57 being defined by the number of nodes).
58
59
60 \defgroup MESHING_group Group creation
61
62 \defgroup MESHING_poly Polygons and Polyhedra creation
63
64 These methods belong to the meshing class and are necessary for
65 creating the connectivities of MED_POLYHEDRON and MED_POLYGON
66 elements.
67
68 */
69
70 /*!  
71 \addtogroup MESHING_constructors
72  @{  
73 */
74
75 /*! Creates an empty MESH. */
76 MESHING::MESHING(): MESH()
77 {
78   MESSAGE_MED("MESHING::MESHING()");
79   SCRUTE_MED(_coordinate);
80   SCRUTE_MED(_connectivity);
81 }
82 /*!  @}  */
83
84 MESHING::~MESHING()
85 {
86   MESSAGE_MED("Deleting MESHING !!");
87 }
88
89 /*!  
90 \addtogroup MESHING_nodes
91  @{  */
92
93 /*! 
94   Sets the whole coordinates array in a given system and interlacing mode.
95   The system coordinates are :
96     - "MED_CART"
97     - "MED_CYL"
98     - "MED_SPHER"
99   The interlacing mode are :
100     - MED_NO_INTERLACE   :  X1 X2 Y1 Y2 Z1 Z2
101     - MED_FULL_INTERLACE :  X1 Y1 Z1 X2 Y2 Z2
102
103 Example :
104 \verbatim
105 MESHING myMeshing ;
106 const int SpaceDimension=2;
107 const int NumberOfNodes=6;
108 int * Coordinates = new int[SpaceDimension*NumberOfNodes] ;
109 string System="CARTESIAN";
110 medModeSwitch Mode = MED_FULL_INTERLACE ;
111 myMeshing.setCoordinates(SpaceDimension,NumberOfNodes,Coordinates,System,Mode);
112 \endverbatim
113
114 */
115 void MESHING::setCoordinates(const int SpaceDimension,
116                              const int NumberOfNodes,
117                              const double * Coordinates,
118                              const string System,
119                              const MED_EN::medModeSwitch Mode)
120 {
121   _spaceDimension = SpaceDimension;
122   _numberOfNodes  = NumberOfNodes;
123   if (_connectivity)
124     _connectivity->setNumberOfNodes(NumberOfNodes);
125
126   if ( !NumberOfNodes && !Coordinates )
127     return; // enable using this method for setting SpaceDimension only
128
129   SCRUTE_MED(_coordinate);
130   SCRUTE_MED(_connectivity);
131
132   if ( _coordinate )
133     delete _coordinate, _coordinate = 0;
134   _coordinate = new COORDINATE(SpaceDimension,NumberOfNodes,Mode);
135   _coordinate->setCoordinates(Mode,Coordinates);
136   _coordinate->setCoordinatesSystem(System);
137 }
138 /*!  @}  */
139
140 /*! 
141  \addtogroup MESHING_general
142  @{  */
143 /*! Sets the coordinate names array.
144 Coordinates names must not exceed the storage length 
145 defined in MED-file : MED_TAILLE_PNOM (8).
146
147 Example:
148 \verbatim
149 string coord[3]={"x","y","z"};
150 meshing.setCoordinatesNames(coord);
151 \endverbatim
152 */
153 void MESHING::setCoordinatesNames(const string * name)
154 {
155 //    int SpaceDimension = getSpaceDimension() ;
156 //    _coordinate->setCoordinatesNames(SpaceDimension,name);
157   _coordinate->setCoordinatesNames(name);
158 }
159
160
161
162 /*! \ifnot  MEDMEM_ug
163   Sets the (i+1)-th component of coordinate names array.
164  Coordinates names must not exceed the storage length 
165 defined in MED-file : MED_TAILLE_PNOM (8).
166 \endif
167
168 */
169 void MESHING::setCoordinateName(const string name, const int i)
170 {
171   _coordinate->setCoordinateName(name,i);
172 }
173
174 /*! Sets the coordinate unit names array
175   of size n*MED_TAILLE_PNOM. Coordinates units must not exceed the storage length 
176 defined in MED-file : MED_TAILLE_PNOM (8).
177
178 Example:
179 \verbatim
180 string coord[3]={"cm","cm","cm"};
181 meshing.setCoordinatesUnits(coord);
182 \endverbatim
183 */
184 void MESHING::setCoordinatesUnits(const string * units)
185 {
186 //    int SpaceDimension = getSpaceDimension() ;
187 //    _coordinate->setCoordinatesUnits(SpaceDimension,units);
188   _coordinate->setCoordinatesUnits(units);
189 }
190
191 /*!\ifnot MEDMEM_ug
192   Sets the \f$ (i+1)^th \f$  component of the coordinate unit names array
193   ("cm       ","cm       ","cm       ") of size n*MED_TAILLE_PNOM
194  \endif
195 */
196 void MESHING::setCoordinateUnit(const string unit, const int i)
197 {
198   _coordinate->setCoordinateUnit(unit,i);
199 }
200 /*!  @}  */
201
202 /*! 
203  \addtogroup MESHING_connectivity
204  @{
205 */
206
207 /*!
208   Creates a new connectivity object with the given number of type and
209   entity. If a connectivity already exist, it is deleted by the call.
210
211   For exemple setNumberOfTypes(3,MED_CELL) creates a connectivity with 3 
212   medGeometryElement in MESH for MED_CELL entity (like MED_TETRA4, 
213   MED_PYRA5 and MED_HEXA6 for example).
214
215   Returns an exception if it could not create the connectivity (as if we set 
216   MED_FACE connectivity before MED_CELL).
217 */
218 void MESHING::setNumberOfTypes(const int NumberOfTypes,
219                                const MED_EN::medEntityMesh Entity) 
220   throw (MEDEXCEPTION)
221 {
222   const char * LOC = "MESHING::setNumberOfTypes( medEntityMesh ) : ";
223
224   // No defined for MED_NODE !
225   if (Entity == MED_NODE)
226     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Not required with MED_NODE !"));
227
228   if (MED_CELL == Entity) {
229     SCRUTE_MED(_connectivity);
230     if (_connectivity )
231       delete _connectivity ;
232     _connectivity = new CONNECTIVITY(NumberOfTypes,Entity) ;
233     _connectivity->setNumberOfNodes( _numberOfNodes );
234
235   } else {
236
237     if (_connectivity == NULL) // we must have defined MED_CELL connectivity
238       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"No connectivity on MED_CELL defined !"));
239
240     if (MED_FACE == Entity)
241       if (3 != getSpaceDimension())
242         throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"No connectivity on MED_FACE could be defined in non 3D space !"));
243
244     if (MED_EDGE == Entity)
245       {
246         if (3 == getSpaceDimension()) {
247           if (3 == getMeshDimension() && !_connectivity->existConnectivity(MED_NODAL,MED_FACE))
248             throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"No connectivity on MED_FACE defined !"));
249           if (2 > getMeshDimension())
250             throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Could not set connectivity on MED_EDGE !"));
251         } else {
252           if (2 != getSpaceDimension())
253             throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Could not set connectivity on MED_EDGE !"));
254         }
255       }
256     // all right, we could create connectivity !
257     CONNECTIVITY * myConnectivity = new CONNECTIVITY(NumberOfTypes,Entity) ;
258     myConnectivity->setNumberOfNodes(_connectivity->getNumberOfNodes());
259     _connectivity->setConstituent(myConnectivity);
260   }
261 }
262
263 /*!
264   Sets the list of geometric types used by a given entity.
265   medEntityMesh entity could be : MED_CELL, MED_FACE, MED_EDGE.
266   This method is used to set the differents geometrics types 
267 ({MED_TETRA4,MED_PYRA5,MED_HEXA8} for example). Geometric types should be given in increasing order of number of nodes for entity type \a entity.
268
269   Remark : Don't use MED_NODE and MED_ALL_ENTITIES.
270
271 If \a entity is not defined, the method will throw an exception.
272
273 */
274
275 void MESHING::setTypes(const MED_EN::medGeometryElement * Types,
276                        const MED_EN::medEntityMesh        entity)
277   throw (MEDEXCEPTION)
278 {
279   if (entity == MED_NODE)
280     throw MEDEXCEPTION(LOCALIZED("MESHING::setTypes : Not defined with MED_NODE entity !"));
281
282   if (_connectivity == NULL)
283     throw MEDEXCEPTION(LOCALIZED("MESHING::setTypes : No connectivity defined !"));
284
285   _connectivity->setGeometricTypes(Types,entity);
286 }
287
288 /*!
289   Sets the number of elements for each geometric type of given entity.
290
291   Example : setNumberOfElements(\{12,23\},MED_FACE);
292   If there are two types of face (MED_TRIA3 and MED_QUAD4), 
293   this sets 12 triangles and 23 quadrangles.
294 */
295 void MESHING::setNumberOfElements(const int * NumberOfElements,
296                                   const MED_EN::medEntityMesh Entity)
297   throw (MEDEXCEPTION)
298 {
299   const char * LOC = "MESHING::setNumberOfElements(const int *, medEntityMesh) : " ;
300
301   if (Entity==MED_NODE)
302     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Not defined with MED_NODE entity !"));
303
304   if (_connectivity == (CONNECTIVITY*)NULL)
305     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"No connectivity defined !"));
306
307   int NumberOfTypes = getNumberOfTypes(Entity) ;
308   int * Count = new int[NumberOfTypes+1] ;
309   Count[0]=1 ;
310   for (int i=0; i<NumberOfTypes; i++)
311     Count[i+1]=Count[i]+NumberOfElements[i] ;
312   _connectivity->setCount(Count,Entity) ;
313   delete[] Count ;
314 }
315
316 /*!
317   Sets the nodal connectivity for geometric type \a Type of  entity \a Entity.
318   The nodal connectivity must be defined one element type at a time :
319   \a MED_ALL_ELEMENTS is not a valid \a Type argument.
320   To define connectivity of \a MED_POLYGON and \a MED_POLYHEDRA, \a PolyConnectivityIndex
321   is also necessary, which defines index of the first node of each element.
322   Connectiviy of polyhedron must contain -1 as a separator of faces. For example,
323   a tetrahedron with connectivity {1,2,3,4} can be represented as a polyhedron by the following arrays:<br>
324 Connectivity : {1,2,3,-1,2,3,4,-1,3,4,1,-1,4,1,2}<br>
325 Connectivity_index : {1,16}
326
327   Example :
328
329 \verbatim
330 MESHING myMeshing ;
331 myMeshing.setCoordinates(SpaceDimension,NumberOfNodes,Coordinates,System,Mode);
332 myMeshing.setNumberOfTypes(2,MED_CELL);
333 myMeshing.setTypes({MED_TRIA3,MED_QUAD4},MED_CELL);
334 myMeshing.setNumberOfElements({3,2},MED_CELL); // 3 MED_TRIA3 and 2 MED_QUAD4
335 myMeshing.setConnectivity(MED_CELL,MED_TRIA3,{1,2,3,6,8,9,4,5,6});
336 myMeshing.setConnectivity(MED_CELL,MED_QUAD4,{1,3,4,5,4,5,7,8});
337 \endverbatim
338
339   Example : setConnectivity(MED_FACE,MED_TRIA3,{1,2,3,1,4,2})
340   Define 2 triangles face defined with nodes 1,2,3 and 1,4,2.
341 */
342 void MESHING::setConnectivity(const MED_EN::medEntityMesh Entity,
343                               const MED_EN::medGeometryElement Type,
344                               const int * Connectivity,
345                               const int * PolyConnectivityIndex)
346   throw (MEDEXCEPTION)
347 {
348   const char * LOC = "MESHING::setConnectivity : " ;
349
350   if (Entity==MED_NODE)
351     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Not defined with MED_NODE entity !"));
352
353   if (_connectivity == (CONNECTIVITY*)NULL)
354     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"No connectivity defined !"));
355
356   _connectivity->setNumberOfNodes(_numberOfNodes);
357   _connectivity->setNodal(Connectivity,Entity,Type,PolyConnectivityIndex) ;
358 }
359
360 /*!  @}  */
361
362 /*!  
363 \addtogroup MESHING_group
364  @{  */
365
366 /*!Adds group \a Group to the mesh.
367 This function registers the group in the list
368 of groups contained in the mesh, so that
369 when the mesh is used for file writing, the group
370 is written in the corresponding MED-file.
371 */
372
373 void MESHING::addGroup(const GROUP & Group)
374   throw (MEDEXCEPTION)
375 {
376   const char * LOC = "MESHING::addGroup : " ;
377
378   GROUP * myGroup = new GROUP(Group) ;
379   if(myGroup->getMesh()==this)
380     {
381       removeReference();
382     }
383   switch(Group.getEntity()){
384   case MED_CELL : {
385     _groupCell.push_back(myGroup);
386     break;
387   }
388   case MED_FACE : {
389      _groupFace.push_back(myGroup);
390     break;
391   }
392   case MED_EDGE : {
393      _groupEdge.push_back(myGroup);
394     break;
395   }
396   case MED_NODE : {
397      _groupNode.push_back(myGroup);
398     break;
399   }
400   default :
401     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Bad Entity !"));
402   }
403 }
404
405 }
406 /*!  @}  */