Salome HOME
MEDMEM suppression
[modules/med.git] / src / MEDSPLITTER / MEDSPLITTER_JointExchangeData.cxx
1 // Copyright (C) 2007-2013  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 // File      : MEDSPLITTER_JointExchangeData.cxx
20 // Created   : Thu Jul 23 13:01:35 2009
21 // Author    : Edward AGAPOV (eap)
22 //
23
24 #include "MEDSPLITTER_JointExchangeData.hxx"
25
26 #include "MEDSPLITTER_FaceModel.hxx"
27
28 #include <MEDMEM_Meshing.hxx>
29 #include <MEDMEM_ConnectZone.hxx>
30
31 using namespace MEDSPLITTER;
32 using namespace MED_EN;
33
34 //================================================================================
35 /*!
36  * \brief Initialization
37  */
38 //================================================================================
39
40 JointExchangeData::JointExchangeData():
41   _dist_domain(-1), _loc_domain(-1), _conn_here_size(0), _dist_mesh(0), _loc_mesh(0)
42 {
43 }
44
45 //================================================================================
46 /*!
47  * \brief Set meshes
48  */
49 //================================================================================
50
51 void JointExchangeData::setMeshes( int domain_dist, const MEDMEM::MESH* mesh_dist,
52                                    int domain_here, const MEDMEM::MESH* mesh_here)
53 {
54   _dist_domain = domain_dist;
55   _loc_domain  = domain_here;
56   _dist_mesh   = mesh_dist;
57   _loc_mesh    = mesh_here;
58 }
59
60 //================================================================================
61 /*!
62  * \brief Stores cell/cell pair of joint between domains (residing different procs by default)
63  *  \param mesh - mesh on this proc
64  *  \param domain_dist - distant domain
65  *  \param domain_here - local domain
66  *  \param glob_dist - global id of a distant domain
67  *  \param glob_here - global id of a local domain
68  *  \param loc_here - local id of a local domain (counted from 1)
69  *  \param loc_dist - local id of a another domain (counted from 1)
70  */
71 //================================================================================
72
73 void JointExchangeData::addCellCorrespondence(const MEDMEM::MESH* mesh,
74                                               int domain_dist, int domain_here,
75                                               int glob_dist,   int glob_here,
76                                               int loc_here,    int loc_dist)
77 {
78   int glob_key = ( domain_dist < domain_here ) ? glob_dist : glob_here;
79   _glob_to_locs_here_and_dist.insert ( make_pair( glob_key, make_pair( loc_here, loc_dist )));
80
81   _conn_here_size += mesh->getElementType( MED_CELL, loc_here ) % 100;
82 }
83
84 //================================================================================
85 /*!
86  * \brief Return data to send and size of data to receive
87  */
88 //================================================================================
89
90 int JointExchangeData::serialize(vector<int> & out_data) const
91 {
92   int data_size =
93     _glob_to_locs_here_and_dist.size() + _local_conn_here.size() + _global_conn_here.size();
94   out_data.resize( data_size );
95
96   int i = 0;
97   TGlob2LocsHD::const_iterator glob_hloc_dloc = _glob_to_locs_here_and_dist.begin();
98   for ( ; glob_hloc_dloc != _glob_to_locs_here_and_dist.end(); ++ glob_hloc_dloc )
99     out_data[i++] = glob_hloc_dloc->second.first;
100
101   for ( int n = 0; n < _local_conn_here.size(); ++n )
102     out_data[i++] = _local_conn_here[n];
103   
104   for ( int n = 0; n < _global_conn_here.size(); ++n )
105     out_data[i++] = _global_conn_here[n];
106
107   // evaluate size of data to receive
108
109   medGeometryElement last_type =
110     _dist_mesh->getTypes(MED_CELL)[ _dist_mesh->getNumberOfTypes(MED_CELL)-1 ];
111
112   int max_nb_node_by_cell = last_type % 100;
113   
114   data_size =
115     _glob_to_locs_here_and_dist.size() +
116     2 * max_nb_node_by_cell * _dist_mesh->getNumberOfElements( MED_CELL, MED_ALL_ELEMENTS );
117
118   return data_size;
119 }
120
121 //================================================================================
122 /*!
123  * \brief Stores received data
124  */
125 //================================================================================
126
127 void JointExchangeData::deserialize(const std::vector<int> & in_data)
128 {
129   const int* dist_loc = &in_data[0];
130
131   int conn_real_size = 0;
132   TGlob2LocsHD::iterator glob_hloc_dloc = _glob_to_locs_here_and_dist.begin();
133   for ( ; glob_hloc_dloc != _glob_to_locs_here_and_dist.end(); ++ glob_hloc_dloc )
134   {
135     conn_real_size += _dist_mesh->getElementType( MED_CELL, *dist_loc ) % 100;
136     glob_hloc_dloc->second.second = *dist_loc++;
137   }
138   
139   const int* dist_loc_conn = dist_loc;
140   const int* dist_glob_conn = dist_loc + conn_real_size;
141
142   _global_conn_dist.resize( conn_real_size );
143   _local_conn_dist.resize ( conn_real_size );
144
145   for ( int n = 0; n < conn_real_size; ++n )
146   {
147     _global_conn_dist[n] = *dist_glob_conn++;
148     _local_conn_dist [n] = *dist_loc_conn++;
149   }
150 }
151
152 //================================================================================
153 /*!
154  * \brief Create cell/cell correspondency array of the joint
155  */
156 //================================================================================
157
158 MEDMEM::MEDSKYLINEARRAY* JointExchangeData::makeCellCorrespArray() const
159 {
160   int nb_cells_here    = _loc_mesh->getNumberOfElements(MED_CELL,MED_ALL_ELEMENTS);
161   int cells_value_size = _glob_to_locs_here_and_dist.size();
162   int* cell_index = new int [nb_cells_here+1];
163   int* cell_value = new int [cells_value_size];
164
165   TGlob2LocsHD::const_iterator glob_hloc_dloc = _glob_to_locs_here_and_dist.begin();
166
167   // sort local/local pairs by locals of _loc_domain
168   multiset< pair< int, int > > here_and_dist_cells;
169   for ( ; glob_hloc_dloc != _glob_to_locs_here_and_dist.end(); ++ glob_hloc_dloc )
170     here_and_dist_cells.insert( glob_hloc_dloc->second );
171
172   multiset< pair< int, int > >::const_iterator here_dist_ids = here_and_dist_cells.begin();
173   if ( here_dist_ids->second < 1 )
174     throw MED_EXCEPTION("MEDSPLITTER::JointExchangeData::makeConnectZone(): "
175                         "ParaDomainSelector::exchangeJoint() must be called before!");
176   cell_index[0]=1;
177   for ( int loc_id_here = 1, i_dist = 0; loc_id_here <= nb_cells_here; ++loc_id_here)
178   {
179     cell_index[ loc_id_here ] = cell_index[ loc_id_here-1 ];
180     while ( here_dist_ids != here_and_dist_cells.end() &&
181             here_dist_ids->first == loc_id_here )
182     {
183       cell_value[ i_dist ] = here_dist_ids->second;
184       cell_index[ loc_id_here ]++;
185       here_dist_ids++;
186       i_dist++;
187     }
188   }
189
190   MEDMEM::MEDSKYLINEARRAY* cell_cell=
191     new MEDMEM::MEDSKYLINEARRAY( nb_cells_here, cells_value_size,
192                                  cell_index, cell_value,/*shallowcopy=*/true);
193   return cell_cell;
194 }
195
196 namespace
197 {
198   //================================================================================
199   /*!
200    * \brief Return CELLMODEL for the geom type
201    */
202   //================================================================================
203
204   const MEDMEM::CELLMODEL& getCellModel( medGeometryElement geom_type )
205   {
206     static map< medGeometryElement, MEDMEM::CELLMODEL > cell_models;
207     MEDMEM::CELLMODEL& model = cell_models[ geom_type ];
208     if ( model.getNumberOfNodes() < 1 )
209       model = MEDMEM::CELLMODEL( geom_type );
210     return model;
211   }
212 }
213
214 //================================================================================
215 /*!
216  * \brief Creates CONNECTZONE with MED_CELL and MED_NODE data filled.
217  *
218  * It must be exchanged with the corresponding joint on other proc using
219  * ParaDomainSelector::exchangeJoint()
220  */
221 //================================================================================
222
223 MEDMEM::CONNECTZONE* JointExchangeData::makeConnectZone(TGeom2FacesByDomian& face_map)
224 {
225   MEDMEM::CONNECTZONE* cz= new MEDMEM::CONNECTZONE();
226   cz->setLocalMesh          (const_cast<MEDMEM::MESH*>(_loc_mesh));
227   cz->setDistantMesh        (const_cast<MEDMEM::MESH*>(_dist_mesh));
228   cz->setLocalDomainNumber  (_loc_domain);
229   cz->setDistantDomainNumber(_dist_domain);
230   cz->setName               ("Connect zone defined by SPLITTER");
231   cz->setEntityCorresp( MED_CELL, MED_CELL, makeCellCorrespArray() );
232
233   // node/node correspondency
234
235   // map local node id on this proc to local node id on distant proc
236   map< int, int > here_2_dist_loc_nodes;
237   int iconn_here = 0, iconn_dist = 0;
238
239   TGlob2LocsHD::const_iterator glob_hloc_dloc = _glob_to_locs_here_and_dist.begin();
240   for ( ; glob_hloc_dloc != _glob_to_locs_here_and_dist.end(); ++ glob_hloc_dloc )
241   {
242     int cell_here = glob_hloc_dloc->second.first;
243     int cell_dist = glob_hloc_dloc->second.second;
244     int nb_cell_nodes_here =  _loc_mesh->getElementType( MED_CELL, cell_here ) % 100;
245     int nb_cell_nodes_dist = _dist_mesh->getElementType( MED_CELL, cell_dist ) % 100;
246     for ( int n_here = 0; n_here < nb_cell_nodes_here; ++n_here )
247     {
248       for ( int n_dist = 0; n_dist < nb_cell_nodes_dist; ++n_dist )
249         if ( _global_conn_here[ n_here + iconn_here ] == _global_conn_dist[ n_dist + iconn_dist])
250         {
251           here_2_dist_loc_nodes.insert( make_pair( _local_conn_here[ n_here + iconn_here ],
252                                                    _local_conn_dist[ n_dist + iconn_dist ]));
253           break;
254         }
255     }
256     iconn_here += nb_cell_nodes_here;
257     iconn_dist += nb_cell_nodes_dist;
258   }
259   // create MEDSKYLINEARRAY
260   int nb_nodes_here   = here_2_dist_loc_nodes.size();
261   int node_value_size = nb_nodes_here * 2;
262   int* node_index = new int [nb_nodes_here+1];
263   int* node_value = new int [node_value_size];
264   MEDMEM::MEDSKYLINEARRAY* node_node =
265     new MEDMEM::MEDSKYLINEARRAY( nb_nodes_here, node_value_size,
266                                  node_index, node_value,/*shallowcopy=*/true);
267
268   map< int, int >::const_iterator here_dist_ids = here_2_dist_loc_nodes.begin();
269   for ( int i = 1; here_dist_ids != here_2_dist_loc_nodes.end(); ++here_dist_ids)
270   {
271     *node_index++ = i++;
272     *node_value++ = here_dist_ids->first;
273     *node_value++ = here_dist_ids->second;
274   }
275   *node_index = nb_nodes_here+1;
276
277   here_2_dist_loc_nodes.clear();
278
279   cz->setNodeCorresp (node_node);
280
281   // Create faces
282
283   if ( face_map.size() > _loc_domain )
284   {
285     TGeom2Faces& faces_of_geom = face_map[ _loc_domain ];
286     
287     int iconn_here = 0, iconn_dist = 0;
288     glob_hloc_dloc = _glob_to_locs_here_and_dist.begin();
289     for ( int iface = 0; glob_hloc_dloc != _glob_to_locs_here_and_dist.end(); ++glob_hloc_dloc )
290     {
291       int cell_here = glob_hloc_dloc->second.first;
292       int cell_dist = glob_hloc_dloc->second.second;
293       medGeometryElement type_here = _loc_mesh ->getElementType( MED_CELL, cell_here );
294       medGeometryElement type_dist = _dist_mesh->getElementType( MED_CELL, cell_dist );
295       const MEDMEM::CELLMODEL& model_here = getCellModel( type_here );
296
297       MEDSPLITTER_FaceModel* face =
298         MEDSPLITTER_FaceModel::getCommonFace( &_global_conn_here[iconn_here],
299                                               &_local_conn_here [iconn_here],
300                                               model_here,
301                                               &_global_conn_dist[iconn_dist],
302                                               type_dist % 100,
303                                               _first_glob_sub_id + iface);
304       faces_of_geom[ face->getType() ].push_back( face );
305
306       iconn_here += type_here % 100;
307       iconn_dist += type_dist % 100;
308       iface++;
309     }
310   }
311
312   // clear
313   _glob_to_locs_here_and_dist.clear();
314   _global_conn_here.clear();
315   _global_conn_dist.clear();
316   _local_conn_here.clear();
317   _local_conn_dist.clear();
318
319   return cz;
320 }
321
322 //================================================================================
323 /*!
324  * \brief Set local and global conncetivity of joint cells
325  */
326 //================================================================================
327
328 void JointExchangeData::setConnectivity(const int* glob_fused_nodes)
329 {
330   _global_conn_here.reserve( _conn_here_size );
331   _local_conn_here.reserve ( _conn_here_size );
332   const int* conn  = _loc_mesh->getConnectivity(MED_NODAL, MED_CELL, MED_ALL_ELEMENTS);
333   const int* index = _loc_mesh->getConnectivityIndex(MED_NODAL, MED_CELL);
334
335   TGlob2LocsHD::iterator glob_locs_here_dist     = _glob_to_locs_here_and_dist.begin();
336   TGlob2LocsHD::iterator glob_locs_here_dist_end = _glob_to_locs_here_and_dist.end();
337   for ( ; glob_locs_here_dist != glob_locs_here_dist_end; ++glob_locs_here_dist )
338   {
339     int loc_cell_h = glob_locs_here_dist->second.first;
340     _local_conn_here.insert( _local_conn_here.end(),
341                              conn + index[ loc_cell_h-1 ]- 1,
342                              conn + index[ loc_cell_h   ]- 1);
343   }
344   for ( int i = 0; i < _conn_here_size; ++i )
345     _global_conn_here.push_back( glob_fused_nodes[ _local_conn_here[i]-1 ]);
346 }