Back to index

salome-med  6.5.0
MEDSPLITTER_JointExchangeData.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 // File      : MEDSPLITTER_JointExchangeData.cxx
00020 // Created   : Thu Jul 23 13:01:35 2009
00021 // Author    : Edward AGAPOV (eap)
00022 //
00023 
00024 #include "MEDSPLITTER_JointExchangeData.hxx"
00025 
00026 #include "MEDSPLITTER_FaceModel.hxx"
00027 
00028 #include <MEDMEM_Meshing.hxx>
00029 #include <MEDMEM_ConnectZone.hxx>
00030 
00031 using namespace MEDSPLITTER;
00032 using namespace MED_EN;
00033 
00034 //================================================================================
00038 //================================================================================
00039 
00040 JointExchangeData::JointExchangeData():
00041   _dist_domain(-1), _loc_domain(-1), _conn_here_size(0), _dist_mesh(0), _loc_mesh(0)
00042 {
00043 }
00044 
00045 //================================================================================
00049 //================================================================================
00050 
00051 void JointExchangeData::setMeshes( int domain_dist, const MEDMEM::MESH* mesh_dist,
00052                                    int domain_here, const MEDMEM::MESH* mesh_here)
00053 {
00054   _dist_domain = domain_dist;
00055   _loc_domain  = domain_here;
00056   _dist_mesh   = mesh_dist;
00057   _loc_mesh    = mesh_here;
00058 }
00059 
00060 //================================================================================
00071 //================================================================================
00072 
00073 void JointExchangeData::addCellCorrespondence(const MEDMEM::MESH* mesh,
00074                                               int domain_dist, int domain_here,
00075                                               int glob_dist,   int glob_here,
00076                                               int loc_here,    int loc_dist)
00077 {
00078   int glob_key = ( domain_dist < domain_here ) ? glob_dist : glob_here;
00079   _glob_to_locs_here_and_dist.insert ( make_pair( glob_key, make_pair( loc_here, loc_dist )));
00080 
00081   _conn_here_size += mesh->getElementType( MED_CELL, loc_here ) % 100;
00082 }
00083 
00084 //================================================================================
00088 //================================================================================
00089 
00090 int JointExchangeData::serialize(vector<int> & out_data) const
00091 {
00092   int data_size =
00093     _glob_to_locs_here_and_dist.size() + _local_conn_here.size() + _global_conn_here.size();
00094   out_data.resize( data_size );
00095 
00096   int i = 0;
00097   TGlob2LocsHD::const_iterator glob_hloc_dloc = _glob_to_locs_here_and_dist.begin();
00098   for ( ; glob_hloc_dloc != _glob_to_locs_here_and_dist.end(); ++ glob_hloc_dloc )
00099     out_data[i++] = glob_hloc_dloc->second.first;
00100 
00101   for ( int n = 0; n < _local_conn_here.size(); ++n )
00102     out_data[i++] = _local_conn_here[n];
00103   
00104   for ( int n = 0; n < _global_conn_here.size(); ++n )
00105     out_data[i++] = _global_conn_here[n];
00106 
00107   // evaluate size of data to receive
00108 
00109   medGeometryElement last_type =
00110     _dist_mesh->getTypes(MED_CELL)[ _dist_mesh->getNumberOfTypes(MED_CELL)-1 ];
00111 
00112   int max_nb_node_by_cell = last_type % 100;
00113   
00114   data_size =
00115     _glob_to_locs_here_and_dist.size() +
00116     2 * max_nb_node_by_cell * _dist_mesh->getNumberOfElements( MED_CELL, MED_ALL_ELEMENTS );
00117 
00118   return data_size;
00119 }
00120 
00121 //================================================================================
00125 //================================================================================
00126 
00127 void JointExchangeData::deserialize(const std::vector<int> & in_data)
00128 {
00129   const int* dist_loc = &in_data[0];
00130 
00131   int conn_real_size = 0;
00132   TGlob2LocsHD::iterator glob_hloc_dloc = _glob_to_locs_here_and_dist.begin();
00133   for ( ; glob_hloc_dloc != _glob_to_locs_here_and_dist.end(); ++ glob_hloc_dloc )
00134   {
00135     conn_real_size += _dist_mesh->getElementType( MED_CELL, *dist_loc ) % 100;
00136     glob_hloc_dloc->second.second = *dist_loc++;
00137   }
00138   
00139   const int* dist_loc_conn = dist_loc;
00140   const int* dist_glob_conn = dist_loc + conn_real_size;
00141 
00142   _global_conn_dist.resize( conn_real_size );
00143   _local_conn_dist.resize ( conn_real_size );
00144 
00145   for ( int n = 0; n < conn_real_size; ++n )
00146   {
00147     _global_conn_dist[n] = *dist_glob_conn++;
00148     _local_conn_dist [n] = *dist_loc_conn++;
00149   }
00150 }
00151 
00152 //================================================================================
00156 //================================================================================
00157 
00158 MEDMEM::MEDSKYLINEARRAY* JointExchangeData::makeCellCorrespArray() const
00159 {
00160   int nb_cells_here    = _loc_mesh->getNumberOfElements(MED_CELL,MED_ALL_ELEMENTS);
00161   int cells_value_size = _glob_to_locs_here_and_dist.size();
00162   int* cell_index = new int [nb_cells_here+1];
00163   int* cell_value = new int [cells_value_size];
00164 
00165   TGlob2LocsHD::const_iterator glob_hloc_dloc = _glob_to_locs_here_and_dist.begin();
00166 
00167   // sort local/local pairs by locals of _loc_domain
00168   multiset< pair< int, int > > here_and_dist_cells;
00169   for ( ; glob_hloc_dloc != _glob_to_locs_here_and_dist.end(); ++ glob_hloc_dloc )
00170     here_and_dist_cells.insert( glob_hloc_dloc->second );
00171 
00172   multiset< pair< int, int > >::const_iterator here_dist_ids = here_and_dist_cells.begin();
00173   if ( here_dist_ids->second < 1 )
00174     throw MED_EXCEPTION("MEDSPLITTER::JointExchangeData::makeConnectZone(): "
00175                         "ParaDomainSelector::exchangeJoint() must be called before!");
00176   cell_index[0]=1;
00177   for ( int loc_id_here = 1, i_dist = 0; loc_id_here <= nb_cells_here; ++loc_id_here)
00178   {
00179     cell_index[ loc_id_here ] = cell_index[ loc_id_here-1 ];
00180     while ( here_dist_ids != here_and_dist_cells.end() &&
00181             here_dist_ids->first == loc_id_here )
00182     {
00183       cell_value[ i_dist ] = here_dist_ids->second;
00184       cell_index[ loc_id_here ]++;
00185       here_dist_ids++;
00186       i_dist++;
00187     }
00188   }
00189 
00190   MEDMEM::MEDSKYLINEARRAY* cell_cell=
00191     new MEDMEM::MEDSKYLINEARRAY( nb_cells_here, cells_value_size,
00192                                  cell_index, cell_value,/*shallowcopy=*/true);
00193   return cell_cell;
00194 }
00195 
00196 namespace
00197 {
00198   //================================================================================
00202   //================================================================================
00203 
00204   const MEDMEM::CELLMODEL& getCellModel( medGeometryElement geom_type )
00205   {
00206     static map< medGeometryElement, MEDMEM::CELLMODEL > cell_models;
00207     MEDMEM::CELLMODEL& model = cell_models[ geom_type ];
00208     if ( model.getNumberOfNodes() < 1 )
00209       model = MEDMEM::CELLMODEL( geom_type );
00210     return model;
00211   }
00212 }
00213 
00214 //================================================================================
00221 //================================================================================
00222 
00223 MEDMEM::CONNECTZONE* JointExchangeData::makeConnectZone(TGeom2FacesByDomian& face_map)
00224 {
00225   MEDMEM::CONNECTZONE* cz= new MEDMEM::CONNECTZONE();
00226   cz->setLocalMesh          (const_cast<MEDMEM::MESH*>(_loc_mesh));
00227   cz->setDistantMesh        (const_cast<MEDMEM::MESH*>(_dist_mesh));
00228   cz->setLocalDomainNumber  (_loc_domain);
00229   cz->setDistantDomainNumber(_dist_domain);
00230   cz->setName               ("Connect zone defined by SPLITTER");
00231   cz->setEntityCorresp( MED_CELL, MED_CELL, makeCellCorrespArray() );
00232 
00233   // node/node correspondency
00234 
00235   // map local node id on this proc to local node id on distant proc
00236   map< int, int > here_2_dist_loc_nodes;
00237   int iconn_here = 0, iconn_dist = 0;
00238 
00239   TGlob2LocsHD::const_iterator glob_hloc_dloc = _glob_to_locs_here_and_dist.begin();
00240   for ( ; glob_hloc_dloc != _glob_to_locs_here_and_dist.end(); ++ glob_hloc_dloc )
00241   {
00242     int cell_here = glob_hloc_dloc->second.first;
00243     int cell_dist = glob_hloc_dloc->second.second;
00244     int nb_cell_nodes_here =  _loc_mesh->getElementType( MED_CELL, cell_here ) % 100;
00245     int nb_cell_nodes_dist = _dist_mesh->getElementType( MED_CELL, cell_dist ) % 100;
00246     for ( int n_here = 0; n_here < nb_cell_nodes_here; ++n_here )
00247     {
00248       for ( int n_dist = 0; n_dist < nb_cell_nodes_dist; ++n_dist )
00249         if ( _global_conn_here[ n_here + iconn_here ] == _global_conn_dist[ n_dist + iconn_dist])
00250         {
00251           here_2_dist_loc_nodes.insert( make_pair( _local_conn_here[ n_here + iconn_here ],
00252                                                    _local_conn_dist[ n_dist + iconn_dist ]));
00253           break;
00254         }
00255     }
00256     iconn_here += nb_cell_nodes_here;
00257     iconn_dist += nb_cell_nodes_dist;
00258   }
00259   // create MEDSKYLINEARRAY
00260   int nb_nodes_here   = here_2_dist_loc_nodes.size();
00261   int node_value_size = nb_nodes_here * 2;
00262   int* node_index = new int [nb_nodes_here+1];
00263   int* node_value = new int [node_value_size];
00264   MEDMEM::MEDSKYLINEARRAY* node_node =
00265     new MEDMEM::MEDSKYLINEARRAY( nb_nodes_here, node_value_size,
00266                                  node_index, node_value,/*shallowcopy=*/true);
00267 
00268   map< int, int >::const_iterator here_dist_ids = here_2_dist_loc_nodes.begin();
00269   for ( int i = 1; here_dist_ids != here_2_dist_loc_nodes.end(); ++here_dist_ids)
00270   {
00271     *node_index++ = i++;
00272     *node_value++ = here_dist_ids->first;
00273     *node_value++ = here_dist_ids->second;
00274   }
00275   *node_index = nb_nodes_here+1;
00276 
00277   here_2_dist_loc_nodes.clear();
00278 
00279   cz->setNodeCorresp (node_node);
00280 
00281   // Create faces
00282 
00283   if ( face_map.size() > _loc_domain )
00284   {
00285     TGeom2Faces& faces_of_geom = face_map[ _loc_domain ];
00286     
00287     int iconn_here = 0, iconn_dist = 0;
00288     glob_hloc_dloc = _glob_to_locs_here_and_dist.begin();
00289     for ( int iface = 0; glob_hloc_dloc != _glob_to_locs_here_and_dist.end(); ++glob_hloc_dloc )
00290     {
00291       int cell_here = glob_hloc_dloc->second.first;
00292       int cell_dist = glob_hloc_dloc->second.second;
00293       medGeometryElement type_here = _loc_mesh ->getElementType( MED_CELL, cell_here );
00294       medGeometryElement type_dist = _dist_mesh->getElementType( MED_CELL, cell_dist );
00295       const MEDMEM::CELLMODEL& model_here = getCellModel( type_here );
00296 
00297       MEDSPLITTER_FaceModel* face =
00298         MEDSPLITTER_FaceModel::getCommonFace( &_global_conn_here[iconn_here],
00299                                               &_local_conn_here [iconn_here],
00300                                               model_here,
00301                                               &_global_conn_dist[iconn_dist],
00302                                               type_dist % 100,
00303                                               _first_glob_sub_id + iface);
00304       faces_of_geom[ face->getType() ].push_back( face );
00305 
00306       iconn_here += type_here % 100;
00307       iconn_dist += type_dist % 100;
00308       iface++;
00309     }
00310   }
00311 
00312   // clear
00313   _glob_to_locs_here_and_dist.clear();
00314   _global_conn_here.clear();
00315   _global_conn_dist.clear();
00316   _local_conn_here.clear();
00317   _local_conn_dist.clear();
00318 
00319   return cz;
00320 }
00321 
00322 //================================================================================
00326 //================================================================================
00327 
00328 void JointExchangeData::setConnectivity(const int* glob_fused_nodes)
00329 {
00330   _global_conn_here.reserve( _conn_here_size );
00331   _local_conn_here.reserve ( _conn_here_size );
00332   const int* conn  = _loc_mesh->getConnectivity(MED_NODAL, MED_CELL, MED_ALL_ELEMENTS);
00333   const int* index = _loc_mesh->getConnectivityIndex(MED_NODAL, MED_CELL);
00334 
00335   TGlob2LocsHD::iterator glob_locs_here_dist     = _glob_to_locs_here_and_dist.begin();
00336   TGlob2LocsHD::iterator glob_locs_here_dist_end = _glob_to_locs_here_and_dist.end();
00337   for ( ; glob_locs_here_dist != glob_locs_here_dist_end; ++glob_locs_here_dist )
00338   {
00339     int loc_cell_h = glob_locs_here_dist->second.first;
00340     _local_conn_here.insert( _local_conn_here.end(),
00341                              conn + index[ loc_cell_h-1 ]- 1,
00342                              conn + index[ loc_cell_h   ]- 1);
00343   }
00344   for ( int i = 0; i < _conn_here_size; ++i )
00345     _global_conn_here.push_back( glob_fused_nodes[ _local_conn_here[i]-1 ]);
00346 }