Back to index

salome-med  6.5.0
MEDSPLITTER_MeshSendReceive.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_MeshSendReceive.cxx
00020 // Created   : Tue Jun 30 20:39:33 2009
00021 // Author    : Edward AGAPOV (eap)
00022 
00023 
00024 #include "MEDSPLITTER_MeshSendReceive.hxx"
00025 
00026 #include "MEDMEM_Meshing.hxx"
00027 #include "MEDMEM_Group.hxx"
00028 
00029 using namespace MEDSPLITTER;
00030 
00031 
00032 
00033 #ifdef HAVE_MPI2
00034 
00035 //=======================================================================
00036 //function : MeshSendReceive
00037 //purpose  : 
00038 //=======================================================================
00039 
00040 MeshSendReceive::MeshSendReceive():_mesh(0)
00041 {
00042   _int_request = _coord_request = _char_request = MPI_REQUEST_NULL;
00043   _node_nums_request = _cell_nums_request = _face_nums_request = MPI_REQUEST_NULL;
00044 }
00045 
00046 //================================================================================
00050 //================================================================================
00051 
00052 MeshSendReceive::~MeshSendReceive()
00053 {
00054   clear();
00055 }
00056 
00057 //================================================================================
00061 //================================================================================
00062 
00063 void MeshSendReceive::clear()
00064 {
00065   MPI_Request* request[6] = { &_int_request, &_coord_request, &_char_request,
00066                               &_node_nums_request, &_cell_nums_request, &_face_nums_request };
00067 
00068   for ( int i = 0; i < 6; ++i )
00069   {
00070     if ( *request[i] != MPI_REQUEST_NULL ) {
00071       MPI_Status status;
00072       MPI_Wait( request[i], &status);
00073     }
00074     switch ( i ) {
00075     case 0: _int_buf.clear(); break;
00076     case 1: /*_coord_buf.clear()*/; break;
00077     case 2: _char_buf.clear(); break;
00078     case 3: _node_glob_numbers.clear(); break;
00079     case 4: _cell_glob_numbers.clear(); break;
00080     case 5: _face_glob_numbers.clear(); break;
00081     }
00082   }
00083 }
00084 
00085 //================================================================================
00089 //================================================================================
00090 
00091 bool MeshSendReceive::isSent()
00092 {
00093   MPI_Request* request[6] = { &_int_request, &_coord_request, &_char_request,
00094                               &_node_nums_request, &_cell_nums_request, &_face_nums_request };
00095 
00096   for ( int i = 0; i < 6; ++i )
00097     if ( *request[i] != MPI_REQUEST_NULL )
00098     {
00099       int complete;
00100       MPI_Status status;
00101       MPI_Request_get_status(*request[i], &complete, &status);
00102       if ( !complete )
00103         return false;
00104     }
00105   return true;
00106 }
00107 
00108 //================================================================================
00109 namespace { // local utils
00110 //================================================================================
00111 
00112   using namespace MED_EN;
00116   template< typename T > struct TSlice
00117   {
00118     typedef MEDMEM::PointerOf<T> TPtr;
00119     TPtr _pointer;
00120     int  _size;
00121 
00122     TSlice(): _size(0) {}
00123     TSlice& operator=(const TSlice& s){_size = s._size; _pointer.set(_size,s._pointer); return *this;}
00124     TSlice(const TSlice& other): _size(other._size),_pointer(other._size, other._pointer){} // copy
00125     void resize(int nb) { _size=nb; _pointer.set(nb); }
00126     void setPtr(int nb, const T* ptr) { _size=nb; _pointer.set(ptr); } // shallowcopy
00127     void copy  (int nb, const T* ptr) { _size=nb; _pointer.set(nb,ptr); } // deep copy
00128     void clear() { _size=0; _pointer.set(0); }
00129     T& operator[](const int i) { return _pointer[i]; }
00130     string dumpPtr() const; // debug
00131   };
00132   template<> string TSlice<char>::dumpPtr() const
00133   {
00134     return _size > 0 ? string(_pointer) : string("");
00135   }
00136   template<typename T> string TSlice<T>::dumpPtr() const
00137   {
00138     MEDMEM::STRING res("");
00139     for ( int i = 0; i < _size && res.size() < 200; ++i )
00140       res << _pointer[i] << " ";
00141     return res;
00142   }
00143   typedef TSlice<int>    TIntSlice;
00144   typedef TSlice<char>   TCharSlice;
00145   typedef TSlice<double> TDoubleSlice;
00146 
00147   //================================================================================
00151   //================================================================================
00152 
00153   TCharSlice toCharSlice( const string& str )
00154   {
00155     TCharSlice slice;
00156     if ( !str.empty() )
00157       slice.setPtr( str.size() + 1, str.c_str());
00158     return slice;
00159   }
00160 
00161   //================================================================================
00165   //================================================================================
00166 
00167   string fromCharSlice( TCharSlice& slice  )
00168   {
00169     return slice._size < 1 ? string() : string( slice._pointer );
00170   }
00171 
00172 #define DEB_OUT(txt) \
00173 //cout << txt << endl;
00174   //================================================================================
00180   //================================================================================
00181   template< typename T >
00182   void serialize( vector< TSlice< T > >& data, vector< T >& buffer)
00183   {
00184     // mesure data
00185     int shift = max( 1, int(sizeof(int)/sizeof(T))); // nb of T to store int
00186     int size = shift; // to store nb of slices in data
00187     typename vector< TSlice< T > >::iterator slice = data.begin();
00188     for ( ; slice != data.end(); ++slice )
00189       size += slice->_size + shift; // +shift - to store each slice size in the buffer
00190 
00191     // fill in the buffer
00192 
00193     buffer.resize( size );
00194     T* ptr = & buffer[0];
00195     // store nb of slices as the first number
00196     *((int*) ptr) = (int) data.size();
00197     ptr += shift;
00198 
00199     DEB_OUT( "\n *** Nb slices: " << data.size());
00200     for ( slice = data.begin(); slice != data.end(); ++slice )
00201     {
00202       *((int*) ptr) = (int) slice->_size;
00203       ptr += shift;
00204       if ( slice->_size )
00205         memcpy( ptr, slice->_pointer, slice->_size * sizeof(T));
00206       ptr += slice->_size;
00207       DEB_OUT("#"<< slice - data.begin() << ": \tsize " << slice->_size << " \t" << slice->dumpPtr());
00208       slice->clear();
00209     }
00210     data.clear();
00211   }
00212   //================================================================================
00219   //================================================================================
00220 
00221   template< typename T >
00222   int deserialize( vector< T >& buffer, vector< TSlice< T > >& data )
00223   {
00224     T* ptr = & buffer[0];
00225     T* end = ptr + buffer.size();
00226 
00227     int nb_slices = *((int*) ptr);
00228     data.resize( nb_slices );
00229     int shift = max( 1, int(sizeof(int)/sizeof(T))); // nb of T to store int
00230     ptr += shift;
00231 
00232     DEB_OUT( "Nb slices: " << data.size());
00233     for ( int i = 0; i < nb_slices; ++i )
00234     {
00235       data[i]._size = *((int*) ptr);
00236       ptr += shift;
00237       data[i]._pointer.set( ptr );
00238       DEB_OUT("#"<< i << ": \tsize " << data[i]._size << " \t" << data[i].dumpPtr());
00239       if ( data[i]._size < 0 || data[i]._size > end - ptr )
00240         return i + 1; // error
00241       ptr += data[i]._size;
00242     }
00243     DEB_OUT(" *** END" << endl )
00244     return 0;
00245   }
00246 
00247   //================================================================================
00251   //================================================================================
00252 
00253   void getGroupsAndFamilies( MEDMEM::MESH*              mesh,
00254                              vector< MEDMEM::GROUP*>&   groups,
00255                              vector< MEDMEM::FAMILY*> & families)
00256   {
00257     medEntityMesh face_entity = mesh->getMeshDimension()==3 ? MED_FACE : MED_EDGE;
00258 
00259     // get all groups
00260     groups = mesh->getGroups( MED_CELL );
00261     vector< MEDMEM::GROUP* > face_groups = mesh->getGroups( face_entity );
00262     vector< MEDMEM::GROUP* > node_groups = mesh->getGroups( MED_NODE );
00263     groups.insert( groups.end(), face_groups.begin(), face_groups.end());
00264     groups.insert( groups.end(), node_groups.begin(), node_groups.end());
00265 
00266     // get all families
00267     families = mesh->getFamilies( MED_CELL );
00268     vector< MEDMEM::FAMILY* > face_families = mesh->getFamilies( face_entity );
00269     vector< MEDMEM::FAMILY* > node_families = mesh->getFamilies( MED_NODE );
00270     families.insert( families.end(), face_families.begin(), face_families.end() );
00271     families.insert( families.end(), node_families.begin(), node_families.end() );
00272   }
00273 
00274   enum SliceEnum // indices of fixed slices and sub-indices within slices
00275     {
00276       // INT slices
00277       SLC_GENERAL_INFO = 0,
00278       SLC_GEOM_TYPES,
00279       SLC_FAMILY_GEN_DATA,
00280       SLC_FAMILY_GROUP_IDS,
00281       SLC_POLYGON_INDEX,
00282       SLC_POLYHED_INDEX,
00283       SLC_FIRST_STD_CONN, // index of the first of non-fixed int slices:
00284       // - connectivities of std types and
00285       // - elements of families
00286 
00287       // sub-indices of SLC_GENERAL_INFO:
00288       I_SPACEDIM = 0, I_MESHDIM,
00289       I_NB_CELL_TYPES,  I_NB_FACE_TYPES,  I_NB_NODES, I_NB_GROUPS,
00290       I_NB_CELL_FAMILY, I_NB_FACE_FAMILY, I_NB_NODES_FAMILY,
00291       I_HAD_FAMILIES,
00292       I_MIN_SIZE, // size of SLC_GENERAL_INFO
00293 
00294       // sub-indices repeated within SLC_FAMILY_DATA for each group:
00295       I_FAM_ID = 0, I_NB_FAM_TYPES, I_NB_FAM_GROUPS,
00296       I_FAM_DATA_SIZE,
00297 
00298       // CHAR slices
00299       SLC_MESH_NAME = 0,
00300       SLC_MESH_DESC,
00301       SLC_COORD_SYS,
00302       SLC_FIRST_COORD_NAME // index of the first of non-fixed char slices:
00303       // - coord names
00304       // - coord unites
00305       // - family names
00306       // - group names
00307     };
00308   enum TagEnum
00309     {
00310       // MPI message tags
00311       TAG_INT = 1032, TAG_COORD = 2064, TAG_CHAR = 3008,
00312       TAG_NODE_NUMS = 4032, TAG_CELL_NUMS = 5032, TAG_FACE_NUMS = 6032,
00313 
00314       // miscellaneous
00315       IS_ON_ALL_FLAG = -1
00316     };
00317 
00318   //================================================================================
00322   //================================================================================
00323 
00324   struct TMESHING : public MEDMEM::MESHING
00325   {
00326     MEDMEM::FAMILY* addFamily(MEDMEM::FAMILY* family, const medEntityMesh& entity)
00327     {
00328       switch ( entity ) {
00329       case MED_CELL: _familyCell.push_back(family); break;
00330       case MED_FACE: _familyFace.push_back(family); break;
00331       case MED_EDGE: _familyEdge.push_back(family); break;
00332       case MED_NODE: _familyNode.push_back(family); break;
00333       default :
00334         throw MED_EXCEPTION(LOCALIZED("Bad Entity !"));
00335       }
00336       family->setMesh( this );
00337       family->setEntity( entity );
00338       return family;
00339     }
00340     //================================================================================
00345     //================================================================================
00346 
00347     void clearFamilies()
00348     {
00349       vector< MEDMEM::GROUP*> groups;
00350       vector< MEDMEM::FAMILY*> families;
00351       getGroupsAndFamilies(this, groups, families);
00352 
00353       for ( int i = 0; i < families.size(); ++i )
00354       {
00355         addReference();
00356         families[i]->removeReference();
00357       }
00358       _familyCell.clear();
00359       _familyFace.clear();
00360       _familyEdge.clear();
00361       _familyNode.clear();
00362 
00363       families.clear();
00364       for ( int i = 0; i < groups.size(); ++i )
00365         groups[i]->setNumberOfFamilies(0), groups[i]->setFamilies(families);
00366     }
00367 
00368     //================================================================================
00372     //================================================================================
00373 
00374     void setCoordinatesSystem(const std::string& system)
00375     {
00376       _coordinate->setCoordinatesSystem(system);
00377     }
00378 
00379     //================================================================================
00383     //================================================================================
00384 
00385     void setSpaceDimension( int dim )
00386     {
00387       _spaceDimension = dim;
00388     }
00389 
00390     //================================================================================
00394     //================================================================================
00395 
00396     void setNumberOfNodes(const int NumberOfNodes)
00397     {
00398       _numberOfNodes = NumberOfNodes ;
00399     }
00400   };
00401 
00402   //================================================================================
00406   //================================================================================
00407 
00408   void setNames( vector< TCharSlice> & char_data, MEDMEM::MESH* mesh )
00409   {
00410     if ( char_data.size() < SLC_FIRST_COORD_NAME + 2 * mesh->getSpaceDimension() )
00411       throw MED_EXCEPTION(LOCALIZED("Internal error in MeshSendReceive::recv()"));
00412 
00413     TMESHING* meshing = (TMESHING*) mesh;
00414 
00415     meshing->setName             ( fromCharSlice( char_data[ SLC_MESH_NAME ]));
00416     meshing->setDescription      ( fromCharSlice( char_data[ SLC_MESH_DESC ]));
00417     meshing->setCoordinatesSystem( fromCharSlice( char_data[ SLC_COORD_SYS ]));
00418 
00419     int char_slice = SLC_FIRST_COORD_NAME;
00420     for ( int ax = 0; ax < meshing->getSpaceDimension(); ++ax )
00421     {
00422       meshing->setCoordinateName( fromCharSlice( char_data[ char_slice++ ]), ax );
00423       meshing->setCoordinateUnit( fromCharSlice( char_data[ char_slice++ ]), ax );
00424     }
00425 
00426     // names of groups and families
00427 
00428     vector< MEDMEM::GROUP* > groups;
00429     vector< MEDMEM::FAMILY*> families;
00430     getGroupsAndFamilies( mesh, groups, families );
00431 
00432     int group_slice_0 = char_slice + families.size();
00433     for ( int f = 0; char_slice < char_data.size() && f < families.size(); ++char_slice, ++f )
00434     {
00435       families[f]->setName ( fromCharSlice( char_data[ char_slice ]));
00436       // group names in families
00437       const string* group_ids = families[f]->getGroupsNames();
00438       vector< string > group_names( families[f]->getNumberOfGroups() );
00439       for ( int i = 0; i < families[f]->getNumberOfGroups(); ++i )
00440       {
00441         int group_id = atoi( group_ids[i].c_str() );
00442         group_names[i] = fromCharSlice( char_data[ group_slice_0 + group_id ]);
00443       }
00444       families[f]->setGroupsNames( & group_names[0] );
00445     }
00446     // group names
00447     for ( int g = 0; char_slice < char_data.size() && g < groups.size(); ++char_slice, ++g )
00448       groups[g]->setName( fromCharSlice( char_data[ char_slice ]));
00449   }
00450 
00451 
00452   //================================================================================
00456   //================================================================================
00457 
00458   void makeGroupsAndFamilies ( TMESHING* mesh, vector< TIntSlice >& int_data, int first_elem_slice )
00459   {
00460     int nb_cell_fams = int_data [ SLC_GENERAL_INFO ][ I_NB_CELL_FAMILY  ];
00461     int nb_face_fams = int_data [ SLC_GENERAL_INFO ][ I_NB_FACE_FAMILY  ];
00462     int nb_node_fams = int_data [ SLC_GENERAL_INFO ][ I_NB_NODES_FAMILY ];
00463 
00464     medEntityMesh face_entity = mesh->getMeshDimension()==3 ? MED_FACE : MED_EDGE;
00465 
00466     // make families
00467     vector< MEDMEM::FAMILY*> families;
00468     for ( int g = 0; g < nb_cell_fams; ++g )
00469       families.push_back( mesh->addFamily( new MEDMEM::FAMILY, MED_CELL ));
00470     for ( int g = 0; g < nb_face_fams; ++g ) 
00471       families.push_back( mesh->addFamily( new MEDMEM::FAMILY, face_entity ));
00472     for ( int g = 0; g < nb_node_fams; ++g )
00473       families.push_back( mesh->addFamily( new MEDMEM::FAMILY, MED_NODE ));
00474 
00475     vector< list< MEDMEM::FAMILY* > > fams_of_group( int_data[ SLC_GENERAL_INFO ][ I_NB_GROUPS ]);
00476 
00477     const int* fam_data   = int_data [ SLC_FAMILY_GEN_DATA  ]._pointer;
00478     const int* fam_groups = int_data [ SLC_FAMILY_GROUP_IDS ]._pointer;
00479     int i_group = 0, fam_elem_slice = first_elem_slice;
00480 
00481     // set family data
00482     for ( int f = 0; f < families.size(); ++f, fam_data += I_FAM_DATA_SIZE )
00483     {
00484       families[f]->setIdentifier( fam_data[ I_FAM_ID ] );
00485       // set types and elements
00486       int nb_geom_types = fam_data[ I_NB_FAM_TYPES ];
00487       families[f]->setNumberOfGeometricType( nb_geom_types );
00488       if ( nb_geom_types < 1 || int_data[ fam_elem_slice ]._size < 1 )
00489       {
00490       }
00491       else if ( int_data[ fam_elem_slice ][0] == IS_ON_ALL_FLAG )
00492       {
00493         families[f]->setAll(true);
00494         families[f]->update();
00495       }
00496       else
00497       {
00498         vector< medGeometryElement > geom_types( nb_geom_types );
00499         vector< int >               nb_elements( nb_geom_types );
00500         vector< int >                     index( nb_geom_types + 1);
00501         index[0] = 1;
00502         for ( int t = 0; t < nb_geom_types; ++t )
00503         {
00504           if ( families[f]->getEntity() != MED_NODE )
00505             geom_types[t] = mesh->getElementType( families[f]->getEntity(),
00506                                                   int_data[ fam_elem_slice + t ][0] );
00507           else
00508             geom_types[t] = MED_NONE;
00509           nb_elements[t] = int_data[ fam_elem_slice ]._size;
00510           index[t+1] = index[t] + nb_elements[t];
00511         }
00512         families[f]->setGeometricType( &geom_types[0] );
00513         families[f]->setNumberOfElements( &nb_elements[0] );
00514         families[f]->setNumber(new MEDMEM::MEDSKYLINEARRAY(nb_geom_types, index[nb_geom_types]-1));
00515         families[f]->getnumber()->setIndex( & index[0] );
00516         for ( int t = 0; t < nb_geom_types; ++t )
00517           families[f]->getnumber()->setI( t+1, int_data[ fam_elem_slice + t ]._pointer );
00518       }
00519       fam_elem_slice += nb_geom_types;
00520 
00521       // set groups of a family
00522       vector< string > group_names( fam_data[ I_NB_FAM_GROUPS] );
00523       for ( int g = 0; g < group_names.size(); ++g )
00524       {
00525         int group_id = fam_groups[ i_group++ ];
00526         fams_of_group[ group_id ].push_back( families[f] );
00527         // store group id as string until real names are read
00528         group_names[g] = MEDMEM::STRING( group_id );
00529       }
00530       families[f]->setNumberOfGroups( group_names.size() );
00531       families[f]->setGroupsNames( &group_names[0] );
00532     }
00533     // create groups
00534 
00535     for ( int g = 0; g < fams_of_group.size(); ++g )
00536     {
00537       MEDMEM::GROUP* group = new MEDMEM::GROUP( "", fams_of_group[ g ]);
00538       mesh->addGroup( *group );
00539       group->removeReference();
00540     }
00541   }
00542 
00543   //================================================================================
00547   //================================================================================
00548 
00549   MEDMEM::MESH* makeMesh( vector< TIntSlice >& int_data, bool& toClearFamilies )
00550   {
00551     if ( int_data.empty() || int_data[ SLC_GENERAL_INFO ]._size < I_MIN_SIZE ||
00552          int_data[ SLC_GENERAL_INFO ][ I_NB_NODES ] < 1 )
00553       return 0;
00554 
00555     TMESHING* mesh = new TMESHING();
00556     // general info
00557     mesh->setSpaceDimension( int_data[ SLC_GENERAL_INFO ][ I_SPACEDIM ]);
00558     mesh->setNumberOfNodes ( int_data[ SLC_GENERAL_INFO ][ I_NB_NODES ]);
00559     int meshDimension = int_data[ SLC_GENERAL_INFO ][ I_MESHDIM ];
00560 
00561     // nb of types
00562     medEntityMesh face_entity = meshDimension==3 ? MED_FACE : MED_EDGE;
00563     int nb_cell_types = int_data[ SLC_GENERAL_INFO ][ I_NB_CELL_TYPES ];
00564     int nb_face_types = int_data[ SLC_GENERAL_INFO ][ I_NB_FACE_TYPES ];
00565     mesh->setNumberOfTypes ( nb_cell_types, MED_CELL );
00566     mesh->setNumberOfTypes ( nb_face_types, face_entity );
00567 
00568     // types and nb of elems
00569     vector< medGeometryElement > types( nb_cell_types + nb_face_types );
00570     vector< int >                nbElementsByType( types.size() ) ;
00571     int t = 0, conn_slice = SLC_FIRST_STD_CONN;
00572     for ( ; t < types.size(); ++t )
00573     {
00574       types[t] = medGeometryElement( int_data[ SLC_GEOM_TYPES ][t] );
00575       if ( types[t] == MED_POLYGON )
00576       {
00577         nbElementsByType[t] = int_data[ SLC_POLYGON_INDEX ]._size - 1;
00578       }
00579       else if ( types[t] == MED_POLYHEDRA )
00580       {
00581         nbElementsByType[t] = int_data[ SLC_POLYHED_INDEX ]._size - 1;
00582       }
00583       else
00584       {
00585         int nn = types[t] % 100;
00586         nbElementsByType[t] = int_data[ conn_slice++ ]._size / nn;
00587       }
00588     }
00589     mesh->setTypes( &types[0], MED_CELL );
00590     mesh->setTypes( &types[0] + nb_cell_types, face_entity );
00591     mesh->setNumberOfElements( &nbElementsByType[0], MED_CELL );
00592     mesh->setNumberOfElements( &nbElementsByType[0] + nb_cell_types, face_entity );
00593 
00594     // connectivity
00595     const int * index = 0;
00596     for ( t = 0, conn_slice = SLC_FIRST_STD_CONN; t < types.size(); ++t )
00597     {
00598       if ( types[t] == MED_POLYGON )
00599       {
00600         index = int_data[ SLC_POLYGON_INDEX ]._pointer;
00601       }
00602       else if ( types[t] == MED_POLYHEDRA )
00603       {
00604         index = int_data[ SLC_POLYHED_INDEX ]._pointer;
00605       }
00606 
00607       mesh->setConnectivity( t < nb_cell_types ? MED_CELL : face_entity,
00608                              types[ t ],
00609                              int_data[ conn_slice++ ]._pointer,
00610                              index);
00611     }
00612 
00613     // make families and groups
00614 
00615     makeGroupsAndFamilies( mesh, int_data, SLC_FIRST_STD_CONN + types.size() );
00616 
00617     toClearFamilies = ! int_data[ SLC_GENERAL_INFO ][ I_HAD_FAMILIES ];
00618 
00619     return mesh;
00620   }
00621 
00622   //================================================================================
00627   //================================================================================
00628 
00629   int getFamilyData( MEDMEM::MESH*             mesh,
00630                      vector<MEDMEM::FAMILY*> & families,
00631                      vector<MEDMEM::GROUP *> & groups,
00632                      vector<int> &             family_gen_data,
00633                      vector<int> &             family_group_ids )
00634   {
00635     // get all groups and families of mesh
00636     getGroupsAndFamilies( mesh, groups, families );
00637     if ( families.empty() ) return 0;
00638 
00639     // assign ids to groups
00640     map < string, int > group_ids;
00641     map < string, int >::iterator name_id;
00642     for ( int id = 0; id < groups.size(); ++id )
00643       if ( !group_ids.insert( make_pair( groups[id]->getName(), id)).second )
00644         throw MED_EXCEPTION(LOCALIZED("Equal group names"));
00645 
00646 
00647     family_gen_data.resize( families.size() * I_FAM_DATA_SIZE );
00648     family_group_ids.clear();
00649     int nb_fam_types = 0, *fam_data = &family_gen_data[0];
00650 
00651     for ( int f = 0; f < families.size(); ++f, fam_data += I_FAM_DATA_SIZE )
00652     {
00653       // sum up number of geom types of families
00654       int nb_types =
00655         families[f]->getEntity() == MED_NODE || families[f]->isOnAllElements() ?
00656         1 :
00657         families[f]->getNumberOfTypes();
00658       nb_fam_types += nb_types;
00659 
00660       // fill in family_group_ids
00661       for ( int g = 0; g < families[f]->getNumberOfGroups(); ++g )
00662       {
00663         name_id = group_ids.find( families[f]->getGroupName( g+1 ));
00664         if ( name_id == group_ids.end() )
00665           throw  MED_EXCEPTION (LOCALIZED(MEDMEM::STRING("Non-exiting group name:>")<<
00666                                           families[f]->getGroupName( g )<<"<"));
00667         family_group_ids.push_back( name_id->second );
00668       }
00669       // fill in family_gen_data
00670       fam_data[ I_FAM_ID ]        = families[f]->getIdentifier();
00671       fam_data[ I_NB_FAM_TYPES ]  = nb_types;
00672       fam_data[ I_NB_FAM_GROUPS ] = families[f]->getNumberOfGroups();
00673     }
00674     return nb_fam_types;
00675   }
00676 
00677   //================================================================================
00681   //================================================================================
00682 
00683   bool getMeshData(MEDMEM::MESH*         mesh,
00684                    vector< TIntSlice >&  int_data,
00685                    vector< TCharSlice >& char_data,
00686                    TDoubleSlice&         coords)
00687   {
00688     if ( !mesh || mesh->getNumberOfNodes() < 1 )
00689       return false;
00690     medEntityMesh face_entity = mesh->getMeshDimension()==3 ? MED_FACE : MED_EDGE;
00691     medConnectivity conn = MED_NODAL;
00692     bool have_faces = mesh->existConnectivity( conn, face_entity );
00693     bool have_families = ( mesh->getNumberOfFamilies( MED_CELL ) +
00694                            mesh->getNumberOfFamilies( face_entity ) +
00695                            mesh->getNumberOfFamilies( MED_NODE ));
00696 
00697     // create missing families
00698     if ( !have_families && ( mesh->getNumberOfGroups( MED_CELL ) > 0 ||
00699                              mesh->getNumberOfGroups(face_entity) > 0 ||
00700                              mesh->getNumberOfGroups( MED_NODE) > 0 ))
00701       mesh->createFamilies();
00702 
00703     // general info
00704 
00705     int general_info[ I_MIN_SIZE ] = { // SLC_GENERAL_INFO
00706       mesh->getSpaceDimension(),
00707       mesh->getMeshDimension(),
00708       mesh->getNumberOfTypes( MED_CELL ),
00709       have_faces ? mesh->getNumberOfTypes( face_entity ) : 0,
00710       mesh->getNumberOfNodes(),
00711       mesh->getNumberOfGroups( MED_CELL )
00712       + mesh->getNumberOfGroups( face_entity )
00713       + mesh->getNumberOfGroups( MED_NODE ),
00714       mesh->getNumberOfFamilies( MED_CELL ),
00715       mesh->getNumberOfFamilies( face_entity ),
00716       mesh->getNumberOfFamilies( MED_NODE ),
00717       int( have_families )
00718     };
00719     vector<MEDMEM::FAMILY*> families;
00720     vector<MEDMEM::GROUP *> groups;
00721     vector<int> family_gen_data, family_group_ids;
00722     int nb_fam_types = getFamilyData( mesh, families, groups, family_gen_data, family_group_ids );
00723 
00724     // count nb of int data slices taking into account non-fixed slices:
00725     // 1) connectivities of std types and 2) elements per type of family
00726     int nb_int_slices =
00727       SLC_FIRST_STD_CONN +
00728       general_info[ I_NB_CELL_TYPES ] +
00729       general_info[ I_NB_FACE_TYPES ] +
00730       nb_fam_types;
00731 
00732     // nb of char slices (names)
00733     int nb_char_slices =
00734       SLC_FIRST_COORD_NAME +
00735       2 * general_info[ I_SPACEDIM ] + // coord names + coord unites
00736       families.size() +                // family names
00737       groups.size();                   // group names
00738 
00739     int_data. resize( nb_int_slices );
00740     char_data.resize( nb_char_slices );
00741 
00742     // general info and strings of mesh
00743 
00744     int_data[ SLC_GENERAL_INFO ].copy( I_MIN_SIZE, general_info );
00745     char_data[ SLC_MESH_NAME ] = toCharSlice( mesh->getName() );
00746     char_data[ SLC_MESH_DESC ] = toCharSlice( mesh->getDescription() );
00747     char_data[ SLC_COORD_SYS ] = toCharSlice( mesh->getCoordinatesSystem() );
00748     int char_slice = SLC_FIRST_COORD_NAME; // next non-filled char slice
00749     for ( int ax = 0; ax < general_info[ I_SPACEDIM ]; ++ax )
00750     {
00751       char_data[ char_slice++ ] = toCharSlice( mesh->getCoordinatesNames()[ax] );
00752       char_data[ char_slice++ ] = toCharSlice( mesh->getCoordinatesUnits()[ax] );
00753     }
00754     int_data[ SLC_FAMILY_GEN_DATA  ].copy( family_gen_data.size(),  &family_gen_data[0] );
00755     int_data[ SLC_FAMILY_GROUP_IDS ].copy( family_group_ids.size(), &family_group_ids[0] );
00756     family_gen_data.clear(); family_group_ids.clear();
00757 
00758     // geom types and their connectvity
00759 
00760     int_data[ SLC_GEOM_TYPES ].resize( general_info[I_NB_CELL_TYPES] +
00761                                        general_info[I_NB_FACE_TYPES] );
00762     int* type_ptr = int_data[ SLC_GEOM_TYPES]._pointer;
00763     int i_slice = SLC_FIRST_STD_CONN;
00764 
00765     const medGeometryElement * cell_types = mesh->getTypes(MED_CELL);
00766     for ( int t = 0; t < general_info[I_NB_CELL_TYPES]; ++t )
00767     {
00768       *type_ptr++ = cell_types[t];
00769       int_data[ i_slice++ ].setPtr( mesh->getConnectivityLength( conn, MED_CELL, cell_types[t]),
00770                                     mesh->getConnectivity      ( conn, MED_CELL, cell_types[t]));
00771     }
00772     if ( have_faces )
00773     {
00774       const medGeometryElement * face_types = mesh->getTypes( face_entity );
00775       for ( int t = 0; t < general_info[I_NB_FACE_TYPES]; ++t )
00776       {
00777         *type_ptr++ = face_types[t];
00778         int_data[ i_slice++ ].setPtr(mesh->getConnectivityLength( conn, face_entity, face_types[t]),
00779                                      mesh->getConnectivity( conn, face_entity, face_types[t]));
00780       }
00781     }
00782     // polygon connectivity index
00783 
00784     medEntityMesh polygon_entity = mesh->getMeshDimension()==2 ? MED_CELL : MED_FACE;
00785     if ( int nb_polygon = mesh->getNumberOfElements( polygon_entity, MED_POLYGON ))
00786     {
00787       const int nbTypes = mesh->getNumberOfTypes( polygon_entity );
00788       const int * index = mesh->getConnectivityIndex( conn, polygon_entity );
00789       index += mesh->getGlobalNumberingIndex( polygon_entity )[ nbTypes-1 ] - 1;
00790       int_data[SLC_POLYGON_INDEX].setPtr( nb_polygon + 1, index );
00791     }
00792     // polyherdra connectivity index
00793 
00794     if ( int nb_polyhedra = mesh->getNumberOfElements( MED_CELL, MED_POLYHEDRA ))
00795     {
00796       const int nbTypes = mesh->getNumberOfTypes( MED_CELL );
00797       const int * index = mesh->getConnectivityIndex( conn, MED_CELL );
00798       index += mesh->getGlobalNumberingIndex( MED_CELL )[ nbTypes-1 ] - 1;
00799       int_data[SLC_POLYHED_INDEX].setPtr( nb_polyhedra + 1, index );
00800     }
00801     // coordinates
00802 
00803     coords.setPtr( general_info[I_NB_NODES] * general_info[I_SPACEDIM],
00804                    mesh->getCoordinates( MED_FULL_INTERLACE ));
00805 
00806     // elements and names of families
00807 
00808     int is_on_all_elements[] = { IS_ON_ALL_FLAG };
00809     for ( int f = 0; f < families.size(); ++f )
00810     {
00811       char_data[ char_slice++ ] = toCharSlice( families[f]->getName() );
00812 
00813       if ( families[f]->isOnAllElements() )
00814       {
00815         int_data[ i_slice++ ].copy( 1, is_on_all_elements);
00816       }
00817       else
00818       {
00819         bool is_nodal = ( families[f]->getEntity() == MED_NODE );
00820         int nb_types = is_nodal ? 1 : families[f]->getNumberOfTypes();
00821         for ( int t = 0; t < nb_types; ++t )
00822         {
00823           medGeometryElement type = is_nodal ? MED_ALL_ELEMENTS : families[f]->getTypes()[t];
00824           int_data[ i_slice++ ].setPtr( families[f]->getNumberOfElements( type ),
00825                                         families[f]->getNumber( type ));
00826         }
00827       }
00828     }
00829     // names of groups
00830 
00831     for ( int g = 0; g < groups.size(); ++g )
00832       char_data[ char_slice++ ] = toCharSlice( groups[g]->getName() );
00833 
00834     return true;
00835   }
00836 
00837 }
00838 
00839 //================================================================================
00845 //================================================================================
00846 
00847 void MeshSendReceive::send(int                irank,
00848                            int                idomain,
00849                            MEDMEM::MESH*      mesh,
00850                            const vector<int>& cell_glob_numbers,
00851                            const vector<int>& face_glob_numbers,
00852                            const vector<int>& node_glob_numbers)
00853 {
00854   _mesh = mesh;
00855   vector< TIntSlice  > int_data;
00856   vector< TCharSlice > char_data;
00857   TDoubleSlice         coords;
00858   if ( _mesh && getMeshData( _mesh, int_data, char_data, coords ))
00859   {
00860     serialize( int_data, _int_buf );
00861     serialize( char_data, _char_buf );
00862     _node_glob_numbers = node_glob_numbers;
00863     _cell_glob_numbers = cell_glob_numbers;
00864     _face_glob_numbers = face_glob_numbers;
00865 
00866     // sending
00867     MPI_Isend((void*)&_int_buf[0], _int_buf.size(), MPI_INT, irank,
00868               idomain + TAG_INT, MPI_COMM_WORLD, &_int_request);
00869 
00870     MPI_Isend((void*)coords._pointer, coords._size, MPI_DOUBLE, irank,
00871               idomain + TAG_COORD, MPI_COMM_WORLD, &_coord_request);
00872 
00873     MPI_Isend((void*)&_char_buf[0], _char_buf.size(), MPI_CHAR, irank,
00874               idomain + TAG_CHAR, MPI_COMM_WORLD, &_char_request);
00875 
00876     MPI_Isend((void*)&_cell_glob_numbers[0], _cell_glob_numbers.size(), MPI_INT, irank,
00877               idomain + TAG_CELL_NUMS, MPI_COMM_WORLD, &_cell_nums_request);
00878 
00879     MPI_Isend((void*)&_face_glob_numbers[0], _face_glob_numbers.size(), MPI_INT, irank,
00880               idomain + TAG_FACE_NUMS, MPI_COMM_WORLD, &_face_nums_request);
00881 
00882     MPI_Isend((void*)&_node_glob_numbers[0], _node_glob_numbers.size(), MPI_INT, irank,
00883               idomain + TAG_NODE_NUMS, MPI_COMM_WORLD, &_node_nums_request);
00884   }
00885   else
00886   {
00887     // send anything not to block recv()
00888     MPI_Isend((void*)&irank, 1, MPI_INT, irank,
00889               idomain + TAG_INT, MPI_COMM_WORLD, &_int_request);
00890   }
00891 }
00892 
00893 //================================================================================
00897 //================================================================================
00898 
00899 MEDMEM::MESH* MeshSendReceive::recv(int irank, int idomain,
00900                                     vector<int>& cell_glob_numbers,
00901                                     vector<int>& face_glob_numbers,
00902                                     vector<int>& node_glob_numbers)
00903 {
00904   _mesh = 0;
00905 
00906   // receive INT data
00907 
00908   MPI_Status status;
00909   MPI_Probe(irank, idomain + TAG_INT, MPI_COMM_WORLD, &status); // wait for the message
00910   int msg_size = 0;
00911   MPI_Get_count( &status, MPI_INT, &msg_size ); // size of arrived message
00912   _int_buf.resize( msg_size );
00913   MPI_Recv((void*)&_int_buf[0], _int_buf.size(), MPI_INT, irank,
00914            idomain + TAG_INT, MPI_COMM_WORLD, &status);
00915   if ( msg_size <= I_MIN_SIZE )
00916     return 0; // mesh not sent
00917 
00918   // receive coordinates
00919 
00920   MPI_Probe(irank, idomain + TAG_COORD, MPI_COMM_WORLD, &status); // wait for the message
00921   MPI_Get_count( &status, MPI_DOUBLE, &msg_size ); // size of arrived message
00922   vector< double > coord_buf( msg_size );
00923   MPI_Recv((void*)&coord_buf[0], msg_size, MPI_DOUBLE, irank,
00924            idomain + TAG_COORD, MPI_COMM_WORLD, &status);
00925 
00926   // receive chars
00927 
00928   MPI_Probe(irank, idomain + TAG_CHAR, MPI_COMM_WORLD, &status); // wait for the message
00929   MPI_Get_count( &status, MPI_CHAR, &msg_size ); // size of arrived message
00930   _char_buf.resize( msg_size );
00931   MPI_Recv((void*)&_char_buf[0], _char_buf.size(), MPI_CHAR, irank,
00932            idomain + TAG_CHAR, MPI_COMM_WORLD, &status);
00933 
00934   // receive global cell numbers
00935 
00936   MPI_Probe(irank, idomain + TAG_CELL_NUMS, MPI_COMM_WORLD, &status); // wait for the message
00937   MPI_Get_count( &status, MPI_INT, &msg_size ); // size of arrived message
00938   cell_glob_numbers.resize( msg_size );
00939   MPI_Recv((void*)&cell_glob_numbers[0], cell_glob_numbers.size(), MPI_INT, irank,
00940            idomain + TAG_CELL_NUMS, MPI_COMM_WORLD, &status);
00941 
00942   // receive global face numbers
00943 
00944   MPI_Probe(irank, idomain + TAG_FACE_NUMS, MPI_COMM_WORLD, &status); // wait for the message
00945   MPI_Get_count( &status, MPI_INT, &msg_size ); // size of arrived message
00946   face_glob_numbers.resize( msg_size );
00947   MPI_Recv((void*)&face_glob_numbers[0], face_glob_numbers.size(), MPI_INT, irank,
00948            idomain + TAG_FACE_NUMS, MPI_COMM_WORLD, &status);
00949 
00950   // receive global node numbers
00951 
00952   MPI_Probe(irank, idomain + TAG_NODE_NUMS, MPI_COMM_WORLD, &status); // wait for the message
00953   MPI_Get_count( &status, MPI_INT, &msg_size ); // size of arrived message
00954   node_glob_numbers.resize( msg_size );
00955   MPI_Recv((void*)&node_glob_numbers[0], node_glob_numbers.size(), MPI_INT, irank,
00956            idomain + TAG_NODE_NUMS, MPI_COMM_WORLD, &status);
00957 
00958   // make mesh
00959 
00960   vector< TIntSlice > int_data;
00961   if ( int badSlice = deserialize( _int_buf, int_data ))
00962     throw MED_EXCEPTION(MEDMEM::STRING("MeshSendReceive::recv(")<<irank<<"): "
00963                                   << "int deserialization error on slice "<< badSlice);
00964 
00965   bool toClearFamilies;
00966   _mesh = makeMesh( int_data, toClearFamilies );
00967   _int_buf.clear();
00968   if ( !_mesh )
00969     return 0;
00970 
00971   // set coordinates
00972 
00973   ((MEDMEM::MESHING*)_mesh)->setCoordinates( _mesh->getSpaceDimension(),
00974                                              _mesh->getNumberOfNodes(),
00975                                              &coord_buf[0], "",
00976                                              MED_EN::MED_FULL_INTERLACE);
00977   coord_buf.clear();
00978 
00979   // set names
00980 
00981   vector< TCharSlice > char_data;
00982   if ( int badSlice = deserialize( _char_buf, char_data ))
00983     throw MED_EXCEPTION(MEDMEM::STRING("MeshSendReceive::recv(")<<irank<<"): "
00984                         << "char deserialization error on slice "<< badSlice);
00985   setNames( char_data, _mesh );
00986   _char_buf.clear();
00987 
00988   if ( toClearFamilies )
00989     ((TMESHING*) _mesh)->clearFamilies();
00990 
00991   return _mesh;
00992 }
00993 
00994 //=======================================================================
00995 #else // #ifdef HAVE_MPI2
00996 
00997 MeshSendReceive::MeshSendReceive() {}
00998 MeshSendReceive::~MeshSendReceive() {}
00999 void MeshSendReceive::send(int irank, int idomain, MEDMEM::MESH* mesh, const vector<int>& cell_glob_nums, const vector<int>& face_glob_nums, const vector<int>& node_glob_numbers) {}
01000 MEDMEM::MESH* MeshSendReceive::recv(int irank,int idomain, vector<int>& cell_glob_nums, vector<int>& face_glob_nums, vector<int>& node_glob_numbers) { return 0; }
01001 bool MeshSendReceive::isSent() { return 0; }
01002 void MeshSendReceive::clear() {}
01003 
01004 #endif
01005 //=======================================================================