1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // File : MEDSPLITTER_JointExchangeData.cxx
20 // Created : Thu Jul 23 13:01:35 2009
21 // Author : Edward AGAPOV (eap)
24 #include "MEDSPLITTER_JointExchangeData.hxx"
26 #include "MEDSPLITTER_FaceModel.hxx"
28 #include <MEDMEM_Meshing.hxx>
29 #include <MEDMEM_ConnectZone.hxx>
31 using namespace MEDSPLITTER;
32 using namespace MED_EN;
34 //================================================================================
36 * \brief Initialization
38 //================================================================================
40 JointExchangeData::JointExchangeData():
41 _dist_domain(-1), _loc_domain(-1), _conn_here_size(0), _dist_mesh(0), _loc_mesh(0)
45 //================================================================================
49 //================================================================================
51 void JointExchangeData::setMeshes( int domain_dist, const MEDMEM::MESH* mesh_dist,
52 int domain_here, const MEDMEM::MESH* mesh_here)
54 _dist_domain = domain_dist;
55 _loc_domain = domain_here;
56 _dist_mesh = mesh_dist;
57 _loc_mesh = mesh_here;
60 //================================================================================
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)
71 //================================================================================
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)
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 )));
81 _conn_here_size += mesh->getElementType( MED_CELL, loc_here ) % 100;
84 //================================================================================
86 * \brief Return data to send and size of data to receive
88 //================================================================================
90 int JointExchangeData::serialize(vector<int> & out_data) const
93 _glob_to_locs_here_and_dist.size() + _local_conn_here.size() + _global_conn_here.size();
94 out_data.resize( data_size );
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;
101 for ( int n = 0; n < _local_conn_here.size(); ++n )
102 out_data[i++] = _local_conn_here[n];
104 for ( int n = 0; n < _global_conn_here.size(); ++n )
105 out_data[i++] = _global_conn_here[n];
107 // evaluate size of data to receive
109 medGeometryElement last_type =
110 _dist_mesh->getTypes(MED_CELL)[ _dist_mesh->getNumberOfTypes(MED_CELL)-1 ];
112 int max_nb_node_by_cell = last_type % 100;
115 _glob_to_locs_here_and_dist.size() +
116 2 * max_nb_node_by_cell * _dist_mesh->getNumberOfElements( MED_CELL, MED_ALL_ELEMENTS );
121 //================================================================================
123 * \brief Stores received data
125 //================================================================================
127 void JointExchangeData::deserialize(const std::vector<int> & in_data)
129 const int* dist_loc = &in_data[0];
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 )
135 conn_real_size += _dist_mesh->getElementType( MED_CELL, *dist_loc ) % 100;
136 glob_hloc_dloc->second.second = *dist_loc++;
139 const int* dist_loc_conn = dist_loc;
140 const int* dist_glob_conn = dist_loc + conn_real_size;
142 _global_conn_dist.resize( conn_real_size );
143 _local_conn_dist.resize ( conn_real_size );
145 for ( int n = 0; n < conn_real_size; ++n )
147 _global_conn_dist[n] = *dist_glob_conn++;
148 _local_conn_dist [n] = *dist_loc_conn++;
152 //================================================================================
154 * \brief Create cell/cell correspondency array of the joint
156 //================================================================================
158 MEDMEM::MEDSKYLINEARRAY* JointExchangeData::makeCellCorrespArray() const
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];
165 TGlob2LocsHD::const_iterator glob_hloc_dloc = _glob_to_locs_here_and_dist.begin();
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 );
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!");
177 for ( int loc_id_here = 1, i_dist = 0; loc_id_here <= nb_cells_here; ++loc_id_here)
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 )
183 cell_value[ i_dist ] = here_dist_ids->second;
184 cell_index[ loc_id_here ]++;
190 MEDMEM::MEDSKYLINEARRAY* cell_cell=
191 new MEDMEM::MEDSKYLINEARRAY( nb_cells_here, cells_value_size,
192 cell_index, cell_value,/*shallowcopy=*/true);
198 //================================================================================
200 * \brief Return CELLMODEL for the geom type
202 //================================================================================
204 const MEDMEM::CELLMODEL& getCellModel( medGeometryElement geom_type )
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 );
214 //================================================================================
216 * \brief Creates CONNECTZONE with MED_CELL and MED_NODE data filled.
218 * It must be exchanged with the corresponding joint on other proc using
219 * ParaDomainSelector::exchangeJoint()
221 //================================================================================
223 MEDMEM::CONNECTZONE* JointExchangeData::makeConnectZone(TGeom2FacesByDomian& face_map)
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() );
233 // node/node correspondency
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;
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 )
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 )
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])
251 here_2_dist_loc_nodes.insert( make_pair( _local_conn_here[ n_here + iconn_here ],
252 _local_conn_dist[ n_dist + iconn_dist ]));
256 iconn_here += nb_cell_nodes_here;
257 iconn_dist += nb_cell_nodes_dist;
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);
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)
272 *node_value++ = here_dist_ids->first;
273 *node_value++ = here_dist_ids->second;
275 *node_index = nb_nodes_here+1;
277 here_2_dist_loc_nodes.clear();
279 cz->setNodeCorresp (node_node);
283 if ( face_map.size() > _loc_domain )
285 TGeom2Faces& faces_of_geom = face_map[ _loc_domain ];
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 )
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 );
297 MEDSPLITTER_FaceModel* face =
298 MEDSPLITTER_FaceModel::getCommonFace( &_global_conn_here[iconn_here],
299 &_local_conn_here [iconn_here],
301 &_global_conn_dist[iconn_dist],
303 _first_glob_sub_id + iface);
304 faces_of_geom[ face->getType() ].push_back( face );
306 iconn_here += type_here % 100;
307 iconn_dist += type_dist % 100;
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();
322 //================================================================================
324 * \brief Set local and global conncetivity of joint cells
326 //================================================================================
328 void JointExchangeData::setConnectivity(const int* glob_fused_nodes)
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);
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 )
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);
344 for ( int i = 0; i < _conn_here_size; ++i )
345 _global_conn_here.push_back( glob_fused_nodes[ _local_conn_here[i]-1 ]);