1 // Copyright (C) 2007-2012 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_MeshSendReceive.cxx
20 // Created : Tue Jun 30 20:39:33 2009
21 // Author : Edward AGAPOV (eap)
24 #include "MEDSPLITTER_MeshSendReceive.hxx"
26 #include "MEDMEM_Meshing.hxx"
27 #include "MEDMEM_Group.hxx"
29 using namespace MEDSPLITTER;
35 //=======================================================================
36 //function : MeshSendReceive
38 //=======================================================================
40 MeshSendReceive::MeshSendReceive():_mesh(0)
42 _int_request = _coord_request = _char_request = MPI_REQUEST_NULL;
43 _node_nums_request = _cell_nums_request = _face_nums_request = MPI_REQUEST_NULL;
46 //================================================================================
48 * \brief Do not die until everything is sent
50 //================================================================================
52 MeshSendReceive::~MeshSendReceive()
57 //================================================================================
59 * \brief Wait for ending send() before freeing buffers
61 //================================================================================
63 void MeshSendReceive::clear()
65 MPI_Request* request[6] = { &_int_request, &_coord_request, &_char_request,
66 &_node_nums_request, &_cell_nums_request, &_face_nums_request };
68 for ( int i = 0; i < 6; ++i )
70 if ( *request[i] != MPI_REQUEST_NULL ) {
72 MPI_Wait( request[i], &status);
75 case 0: _int_buf.clear(); break;
76 case 1: /*_coord_buf.clear()*/; break;
77 case 2: _char_buf.clear(); break;
78 case 3: _node_glob_numbers.clear(); break;
79 case 4: _cell_glob_numbers.clear(); break;
80 case 5: _face_glob_numbers.clear(); break;
85 //================================================================================
87 * \brief Return true if mesh is already sent
89 //================================================================================
91 bool MeshSendReceive::isSent()
93 MPI_Request* request[6] = { &_int_request, &_coord_request, &_char_request,
94 &_node_nums_request, &_cell_nums_request, &_face_nums_request };
96 for ( int i = 0; i < 6; ++i )
97 if ( *request[i] != MPI_REQUEST_NULL )
101 MPI_Request_get_status(*request[i], &complete, &status);
108 //================================================================================
109 namespace { // local utils
110 //================================================================================
112 using namespace MED_EN;
114 * \brief Pointer to data and size of data
116 template< typename T > struct TSlice
118 typedef MEDMEM::PointerOf<T> TPtr;
122 TSlice(): _size(0) {}
123 TSlice& operator=(const TSlice& s){_size = s._size; _pointer.set(_size,s._pointer); return *this;}
124 TSlice(const TSlice& other): _size(other._size),_pointer(other._size, other._pointer){} // copy
125 void resize(int nb) { _size=nb; _pointer.set(nb); }
126 void setPtr(int nb, const T* ptr) { _size=nb; _pointer.set(ptr); } // shallowcopy
127 void copy (int nb, const T* ptr) { _size=nb; _pointer.set(nb,ptr); } // deep copy
128 void clear() { _size=0; _pointer.set(0); }
129 T& operator[](const int i) { return _pointer[i]; }
130 string dumpPtr() const; // debug
132 template<> string TSlice<char>::dumpPtr() const
134 return _size > 0 ? string(_pointer) : string("");
136 template<typename T> string TSlice<T>::dumpPtr() const
138 MEDMEM::STRING res("");
139 for ( int i = 0; i < _size && res.size() < 200; ++i )
140 res << _pointer[i] << " ";
143 typedef TSlice<int> TIntSlice;
144 typedef TSlice<char> TCharSlice;
145 typedef TSlice<double> TDoubleSlice;
147 //================================================================================
149 * \brief Make TCharSlice from string
151 //================================================================================
153 TCharSlice toCharSlice( const string& str )
157 slice.setPtr( str.size() + 1, str.c_str());
161 //================================================================================
163 * \brief Make string from TCharSlice
165 //================================================================================
167 string fromCharSlice( TCharSlice& slice )
169 return slice._size < 1 ? string() : string( slice._pointer );
172 #define DEB_OUT(txt) \
173 //cout << txt << endl;
174 //================================================================================
176 * \brief Put list of slices into one array
177 * \param data - slices of data
178 * \param buffer - output array
180 //================================================================================
181 template< typename T >
182 void serialize( vector< TSlice< T > >& data, vector< T >& buffer)
185 int shift = max( 1, int(sizeof(int)/sizeof(T))); // nb of T to store int
186 int size = shift; // to store nb of slices in data
187 typename vector< TSlice< T > >::iterator slice = data.begin();
188 for ( ; slice != data.end(); ++slice )
189 size += slice->_size + shift; // +shift - to store each slice size in the buffer
191 // fill in the buffer
193 buffer.resize( size );
194 T* ptr = & buffer[0];
195 // store nb of slices as the first number
196 *((int*) ptr) = (int) data.size();
199 DEB_OUT( "\n *** Nb slices: " << data.size());
200 for ( slice = data.begin(); slice != data.end(); ++slice )
202 *((int*) ptr) = (int) slice->_size;
205 memcpy( ptr, slice->_pointer, slice->_size * sizeof(T));
207 DEB_OUT("#"<< slice - data.begin() << ": \tsize " << slice->_size << " \t" << slice->dumpPtr());
212 //================================================================================
214 * \brief Retrieve data slices from array
215 * \param data - output slices of data
216 * \param buffer - data array
217 * \retval int - zero or slice index (counting from 1) where deserialization failed
219 //================================================================================
221 template< typename T >
222 int deserialize( vector< T >& buffer, vector< TSlice< T > >& data )
224 T* ptr = & buffer[0];
225 T* end = ptr + buffer.size();
227 int nb_slices = *((int*) ptr);
228 data.resize( nb_slices );
229 int shift = max( 1, int(sizeof(int)/sizeof(T))); // nb of T to store int
232 DEB_OUT( "Nb slices: " << data.size());
233 for ( int i = 0; i < nb_slices; ++i )
235 data[i]._size = *((int*) ptr);
237 data[i]._pointer.set( ptr );
238 DEB_OUT("#"<< i << ": \tsize " << data[i]._size << " \t" << data[i].dumpPtr());
239 if ( data[i]._size < 0 || data[i]._size > end - ptr )
240 return i + 1; // error
241 ptr += data[i]._size;
243 DEB_OUT(" *** END" << endl )
247 //================================================================================
249 * \brief Return all groups and families of mesh
251 //================================================================================
253 void getGroupsAndFamilies( MEDMEM::MESH* mesh,
254 vector< MEDMEM::GROUP*>& groups,
255 vector< MEDMEM::FAMILY*> & families)
257 medEntityMesh face_entity = mesh->getMeshDimension()==3 ? MED_FACE : MED_EDGE;
260 groups = mesh->getGroups( MED_CELL );
261 vector< MEDMEM::GROUP* > face_groups = mesh->getGroups( face_entity );
262 vector< MEDMEM::GROUP* > node_groups = mesh->getGroups( MED_NODE );
263 groups.insert( groups.end(), face_groups.begin(), face_groups.end());
264 groups.insert( groups.end(), node_groups.begin(), node_groups.end());
267 families = mesh->getFamilies( MED_CELL );
268 vector< MEDMEM::FAMILY* > face_families = mesh->getFamilies( face_entity );
269 vector< MEDMEM::FAMILY* > node_families = mesh->getFamilies( MED_NODE );
270 families.insert( families.end(), face_families.begin(), face_families.end() );
271 families.insert( families.end(), node_families.begin(), node_families.end() );
274 enum SliceEnum // indices of fixed slices and sub-indices within slices
277 SLC_GENERAL_INFO = 0,
280 SLC_FAMILY_GROUP_IDS,
283 SLC_FIRST_STD_CONN, // index of the first of non-fixed int slices:
284 // - connectivities of std types and
285 // - elements of families
287 // sub-indices of SLC_GENERAL_INFO:
288 I_SPACEDIM = 0, I_MESHDIM,
289 I_NB_CELL_TYPES, I_NB_FACE_TYPES, I_NB_NODES, I_NB_GROUPS,
290 I_NB_CELL_FAMILY, I_NB_FACE_FAMILY, I_NB_NODES_FAMILY,
292 I_MIN_SIZE, // size of SLC_GENERAL_INFO
294 // sub-indices repeated within SLC_FAMILY_DATA for each group:
295 I_FAM_ID = 0, I_NB_FAM_TYPES, I_NB_FAM_GROUPS,
302 SLC_FIRST_COORD_NAME // index of the first of non-fixed char slices:
311 TAG_INT = 1032, TAG_COORD = 2064, TAG_CHAR = 3008,
312 TAG_NODE_NUMS = 4032, TAG_CELL_NUMS = 5032, TAG_FACE_NUMS = 6032,
318 //================================================================================
320 * \brief Enrich MEDMEM::MESHING with addFamily() etc
322 //================================================================================
324 struct TMESHING : public MEDMEM::MESHING
326 MEDMEM::FAMILY* addFamily(MEDMEM::FAMILY* family, const medEntityMesh& entity)
329 case MED_CELL: _familyCell.push_back(family); break;
330 case MED_FACE: _familyFace.push_back(family); break;
331 case MED_EDGE: _familyEdge.push_back(family); break;
332 case MED_NODE: _familyNode.push_back(family); break;
334 throw MED_EXCEPTION(LOCALIZED("Bad Entity !"));
336 family->setMesh( this );
337 family->setEntity( entity );
340 //================================================================================
342 * \brief Remove all families that prevent correct writting groups that not pass through
343 * send/recieve as no families exist for them
345 //================================================================================
349 vector< MEDMEM::GROUP*> groups;
350 vector< MEDMEM::FAMILY*> families;
351 getGroupsAndFamilies(this, groups, families);
353 for ( int i = 0; i < families.size(); ++i )
356 families[i]->removeReference();
364 for ( int i = 0; i < groups.size(); ++i )
365 groups[i]->setNumberOfFamilies(0), groups[i]->setFamilies(families);
368 //================================================================================
370 * \brief Sets type of coordinate system
372 //================================================================================
374 void setCoordinatesSystem(const std::string& system)
376 _coordinate->setCoordinatesSystem(system);
379 //================================================================================
381 * \brief Sets space dimension
383 //================================================================================
385 void setSpaceDimension( int dim )
387 _spaceDimension = dim;
390 //================================================================================
392 * \brief Sets the number of nodes in the mesh
394 //================================================================================
396 void setNumberOfNodes(const int NumberOfNodes)
398 _numberOfNodes = NumberOfNodes ;
402 //================================================================================
404 * \brief Set string data to mesh
406 //================================================================================
408 void setNames( vector< TCharSlice> & char_data, MEDMEM::MESH* mesh )
410 if ( char_data.size() < SLC_FIRST_COORD_NAME + 2 * mesh->getSpaceDimension() )
411 throw MED_EXCEPTION(LOCALIZED("Internal error in MeshSendReceive::recv()"));
413 TMESHING* meshing = (TMESHING*) mesh;
415 meshing->setName ( fromCharSlice( char_data[ SLC_MESH_NAME ]));
416 meshing->setDescription ( fromCharSlice( char_data[ SLC_MESH_DESC ]));
417 meshing->setCoordinatesSystem( fromCharSlice( char_data[ SLC_COORD_SYS ]));
419 int char_slice = SLC_FIRST_COORD_NAME;
420 for ( int ax = 0; ax < meshing->getSpaceDimension(); ++ax )
422 meshing->setCoordinateName( fromCharSlice( char_data[ char_slice++ ]), ax );
423 meshing->setCoordinateUnit( fromCharSlice( char_data[ char_slice++ ]), ax );
426 // names of groups and families
428 vector< MEDMEM::GROUP* > groups;
429 vector< MEDMEM::FAMILY*> families;
430 getGroupsAndFamilies( mesh, groups, families );
432 int group_slice_0 = char_slice + families.size();
433 for ( int f = 0; char_slice < char_data.size() && f < families.size(); ++char_slice, ++f )
435 families[f]->setName ( fromCharSlice( char_data[ char_slice ]));
436 // group names in families
437 const string* group_ids = families[f]->getGroupsNames();
438 vector< string > group_names( families[f]->getNumberOfGroups() );
439 for ( int i = 0; i < families[f]->getNumberOfGroups(); ++i )
441 int group_id = atoi( group_ids[i].c_str() );
442 group_names[i] = fromCharSlice( char_data[ group_slice_0 + group_id ]);
444 families[f]->setGroupsNames( & group_names[0] );
447 for ( int g = 0; char_slice < char_data.size() && g < groups.size(); ++char_slice, ++g )
448 groups[g]->setName( fromCharSlice( char_data[ char_slice ]));
452 //================================================================================
454 * \brief Creates families and groups in the mesh
456 //================================================================================
458 void makeGroupsAndFamilies ( TMESHING* mesh, vector< TIntSlice >& int_data, int first_elem_slice )
460 int nb_cell_fams = int_data [ SLC_GENERAL_INFO ][ I_NB_CELL_FAMILY ];
461 int nb_face_fams = int_data [ SLC_GENERAL_INFO ][ I_NB_FACE_FAMILY ];
462 int nb_node_fams = int_data [ SLC_GENERAL_INFO ][ I_NB_NODES_FAMILY ];
464 medEntityMesh face_entity = mesh->getMeshDimension()==3 ? MED_FACE : MED_EDGE;
467 vector< MEDMEM::FAMILY*> families;
468 for ( int g = 0; g < nb_cell_fams; ++g )
469 families.push_back( mesh->addFamily( new MEDMEM::FAMILY, MED_CELL ));
470 for ( int g = 0; g < nb_face_fams; ++g )
471 families.push_back( mesh->addFamily( new MEDMEM::FAMILY, face_entity ));
472 for ( int g = 0; g < nb_node_fams; ++g )
473 families.push_back( mesh->addFamily( new MEDMEM::FAMILY, MED_NODE ));
475 vector< list< MEDMEM::FAMILY* > > fams_of_group( int_data[ SLC_GENERAL_INFO ][ I_NB_GROUPS ]);
477 const int* fam_data = int_data [ SLC_FAMILY_GEN_DATA ]._pointer;
478 const int* fam_groups = int_data [ SLC_FAMILY_GROUP_IDS ]._pointer;
479 int i_group = 0, fam_elem_slice = first_elem_slice;
482 for ( int f = 0; f < families.size(); ++f, fam_data += I_FAM_DATA_SIZE )
484 families[f]->setIdentifier( fam_data[ I_FAM_ID ] );
485 // set types and elements
486 int nb_geom_types = fam_data[ I_NB_FAM_TYPES ];
487 families[f]->setNumberOfGeometricType( nb_geom_types );
488 if ( nb_geom_types < 1 || int_data[ fam_elem_slice ]._size < 1 )
491 else if ( int_data[ fam_elem_slice ][0] == IS_ON_ALL_FLAG )
493 families[f]->setAll(true);
494 families[f]->update();
498 vector< medGeometryElement > geom_types( nb_geom_types );
499 vector< int > nb_elements( nb_geom_types );
500 vector< int > index( nb_geom_types + 1);
502 for ( int t = 0; t < nb_geom_types; ++t )
504 if ( families[f]->getEntity() != MED_NODE )
505 geom_types[t] = mesh->getElementType( families[f]->getEntity(),
506 int_data[ fam_elem_slice + t ][0] );
508 geom_types[t] = MED_NONE;
509 nb_elements[t] = int_data[ fam_elem_slice ]._size;
510 index[t+1] = index[t] + nb_elements[t];
512 families[f]->setGeometricType( &geom_types[0] );
513 families[f]->setNumberOfElements( &nb_elements[0] );
514 families[f]->setNumber(new MEDMEM::MEDSKYLINEARRAY(nb_geom_types, index[nb_geom_types]-1));
515 families[f]->getnumber()->setIndex( & index[0] );
516 for ( int t = 0; t < nb_geom_types; ++t )
517 families[f]->getnumber()->setI( t+1, int_data[ fam_elem_slice + t ]._pointer );
519 fam_elem_slice += nb_geom_types;
521 // set groups of a family
522 vector< string > group_names( fam_data[ I_NB_FAM_GROUPS] );
523 for ( int g = 0; g < group_names.size(); ++g )
525 int group_id = fam_groups[ i_group++ ];
526 fams_of_group[ group_id ].push_back( families[f] );
527 // store group id as string until real names are read
528 group_names[g] = MEDMEM::STRING( group_id );
530 families[f]->setNumberOfGroups( group_names.size() );
531 families[f]->setGroupsNames( &group_names[0] );
535 for ( int g = 0; g < fams_of_group.size(); ++g )
537 MEDMEM::GROUP* group = new MEDMEM::GROUP( "", fams_of_group[ g ]);
538 mesh->addGroup( *group );
539 group->removeReference();
543 //================================================================================
545 * \brief Restore mesh from received data
547 //================================================================================
549 MEDMEM::MESH* makeMesh( vector< TIntSlice >& int_data, bool& toClearFamilies )
551 if ( int_data.empty() || int_data[ SLC_GENERAL_INFO ]._size < I_MIN_SIZE ||
552 int_data[ SLC_GENERAL_INFO ][ I_NB_NODES ] < 1 )
555 TMESHING* mesh = new TMESHING();
557 mesh->setSpaceDimension( int_data[ SLC_GENERAL_INFO ][ I_SPACEDIM ]);
558 mesh->setNumberOfNodes ( int_data[ SLC_GENERAL_INFO ][ I_NB_NODES ]);
559 int meshDimension = int_data[ SLC_GENERAL_INFO ][ I_MESHDIM ];
562 medEntityMesh face_entity = meshDimension==3 ? MED_FACE : MED_EDGE;
563 int nb_cell_types = int_data[ SLC_GENERAL_INFO ][ I_NB_CELL_TYPES ];
564 int nb_face_types = int_data[ SLC_GENERAL_INFO ][ I_NB_FACE_TYPES ];
565 mesh->setNumberOfTypes ( nb_cell_types, MED_CELL );
566 mesh->setNumberOfTypes ( nb_face_types, face_entity );
568 // types and nb of elems
569 vector< medGeometryElement > types( nb_cell_types + nb_face_types );
570 vector< int > nbElementsByType( types.size() ) ;
571 int t = 0, conn_slice = SLC_FIRST_STD_CONN;
572 for ( ; t < types.size(); ++t )
574 types[t] = medGeometryElement( int_data[ SLC_GEOM_TYPES ][t] );
575 if ( types[t] == MED_POLYGON )
577 nbElementsByType[t] = int_data[ SLC_POLYGON_INDEX ]._size - 1;
579 else if ( types[t] == MED_POLYHEDRA )
581 nbElementsByType[t] = int_data[ SLC_POLYHED_INDEX ]._size - 1;
585 int nn = types[t] % 100;
586 nbElementsByType[t] = int_data[ conn_slice++ ]._size / nn;
589 mesh->setTypes( &types[0], MED_CELL );
590 mesh->setTypes( &types[0] + nb_cell_types, face_entity );
591 mesh->setNumberOfElements( &nbElementsByType[0], MED_CELL );
592 mesh->setNumberOfElements( &nbElementsByType[0] + nb_cell_types, face_entity );
595 const int * index = 0;
596 for ( t = 0, conn_slice = SLC_FIRST_STD_CONN; t < types.size(); ++t )
598 if ( types[t] == MED_POLYGON )
600 index = int_data[ SLC_POLYGON_INDEX ]._pointer;
602 else if ( types[t] == MED_POLYHEDRA )
604 index = int_data[ SLC_POLYHED_INDEX ]._pointer;
607 mesh->setConnectivity( t < nb_cell_types ? MED_CELL : face_entity,
609 int_data[ conn_slice++ ]._pointer,
613 // make families and groups
615 makeGroupsAndFamilies( mesh, int_data, SLC_FIRST_STD_CONN + types.size() );
617 toClearFamilies = ! int_data[ SLC_GENERAL_INFO ][ I_HAD_FAMILIES ];
622 //================================================================================
624 * \brief Retrieve data of groups and families
625 * \retval int - number of geom types in all families
627 //================================================================================
629 int getFamilyData( MEDMEM::MESH* mesh,
630 vector<MEDMEM::FAMILY*> & families,
631 vector<MEDMEM::GROUP *> & groups,
632 vector<int> & family_gen_data,
633 vector<int> & family_group_ids )
635 // get all groups and families of mesh
636 getGroupsAndFamilies( mesh, groups, families );
637 if ( families.empty() ) return 0;
639 // assign ids to groups
640 map < string, int > group_ids;
641 map < string, int >::iterator name_id;
642 for ( int id = 0; id < groups.size(); ++id )
643 if ( !group_ids.insert( make_pair( groups[id]->getName(), id)).second )
644 throw MED_EXCEPTION(LOCALIZED("Equal group names"));
647 family_gen_data.resize( families.size() * I_FAM_DATA_SIZE );
648 family_group_ids.clear();
649 int nb_fam_types = 0, *fam_data = &family_gen_data[0];
651 for ( int f = 0; f < families.size(); ++f, fam_data += I_FAM_DATA_SIZE )
653 // sum up number of geom types of families
655 families[f]->getEntity() == MED_NODE || families[f]->isOnAllElements() ?
657 families[f]->getNumberOfTypes();
658 nb_fam_types += nb_types;
660 // fill in family_group_ids
661 for ( int g = 0; g < families[f]->getNumberOfGroups(); ++g )
663 name_id = group_ids.find( families[f]->getGroupName( g+1 ));
664 if ( name_id == group_ids.end() )
665 throw MED_EXCEPTION (LOCALIZED(MEDMEM::STRING("Non-exiting group name:>")<<
666 families[f]->getGroupName( g )<<"<"));
667 family_group_ids.push_back( name_id->second );
669 // fill in family_gen_data
670 fam_data[ I_FAM_ID ] = families[f]->getIdentifier();
671 fam_data[ I_NB_FAM_TYPES ] = nb_types;
672 fam_data[ I_NB_FAM_GROUPS ] = families[f]->getNumberOfGroups();
677 //================================================================================
679 * \brief Store mesh as arrayrs of ints, doubles and chars
681 //================================================================================
683 bool getMeshData(MEDMEM::MESH* mesh,
684 vector< TIntSlice >& int_data,
685 vector< TCharSlice >& char_data,
686 TDoubleSlice& coords)
688 if ( !mesh || mesh->getNumberOfNodes() < 1 )
690 medEntityMesh face_entity = mesh->getMeshDimension()==3 ? MED_FACE : MED_EDGE;
691 medConnectivity conn = MED_NODAL;
692 bool have_faces = mesh->existConnectivity( conn, face_entity );
693 bool have_families = ( mesh->getNumberOfFamilies( MED_CELL ) +
694 mesh->getNumberOfFamilies( face_entity ) +
695 mesh->getNumberOfFamilies( MED_NODE ));
697 // create missing families
698 if ( !have_families && ( mesh->getNumberOfGroups( MED_CELL ) > 0 ||
699 mesh->getNumberOfGroups(face_entity) > 0 ||
700 mesh->getNumberOfGroups( MED_NODE) > 0 ))
701 mesh->createFamilies();
705 int general_info[ I_MIN_SIZE ] = { // SLC_GENERAL_INFO
706 mesh->getSpaceDimension(),
707 mesh->getMeshDimension(),
708 mesh->getNumberOfTypes( MED_CELL ),
709 have_faces ? mesh->getNumberOfTypes( face_entity ) : 0,
710 mesh->getNumberOfNodes(),
711 mesh->getNumberOfGroups( MED_CELL )
712 + mesh->getNumberOfGroups( face_entity )
713 + mesh->getNumberOfGroups( MED_NODE ),
714 mesh->getNumberOfFamilies( MED_CELL ),
715 mesh->getNumberOfFamilies( face_entity ),
716 mesh->getNumberOfFamilies( MED_NODE ),
719 vector<MEDMEM::FAMILY*> families;
720 vector<MEDMEM::GROUP *> groups;
721 vector<int> family_gen_data, family_group_ids;
722 int nb_fam_types = getFamilyData( mesh, families, groups, family_gen_data, family_group_ids );
724 // count nb of int data slices taking into account non-fixed slices:
725 // 1) connectivities of std types and 2) elements per type of family
728 general_info[ I_NB_CELL_TYPES ] +
729 general_info[ I_NB_FACE_TYPES ] +
732 // nb of char slices (names)
734 SLC_FIRST_COORD_NAME +
735 2 * general_info[ I_SPACEDIM ] + // coord names + coord unites
736 families.size() + // family names
737 groups.size(); // group names
739 int_data. resize( nb_int_slices );
740 char_data.resize( nb_char_slices );
742 // general info and strings of mesh
744 int_data[ SLC_GENERAL_INFO ].copy( I_MIN_SIZE, general_info );
745 char_data[ SLC_MESH_NAME ] = toCharSlice( mesh->getName() );
746 char_data[ SLC_MESH_DESC ] = toCharSlice( mesh->getDescription() );
747 char_data[ SLC_COORD_SYS ] = toCharSlice( mesh->getCoordinatesSystem() );
748 int char_slice = SLC_FIRST_COORD_NAME; // next non-filled char slice
749 for ( int ax = 0; ax < general_info[ I_SPACEDIM ]; ++ax )
751 char_data[ char_slice++ ] = toCharSlice( mesh->getCoordinatesNames()[ax] );
752 char_data[ char_slice++ ] = toCharSlice( mesh->getCoordinatesUnits()[ax] );
754 int_data[ SLC_FAMILY_GEN_DATA ].copy( family_gen_data.size(), &family_gen_data[0] );
755 int_data[ SLC_FAMILY_GROUP_IDS ].copy( family_group_ids.size(), &family_group_ids[0] );
756 family_gen_data.clear(); family_group_ids.clear();
758 // geom types and their connectvity
760 int_data[ SLC_GEOM_TYPES ].resize( general_info[I_NB_CELL_TYPES] +
761 general_info[I_NB_FACE_TYPES] );
762 int* type_ptr = int_data[ SLC_GEOM_TYPES]._pointer;
763 int i_slice = SLC_FIRST_STD_CONN;
765 const medGeometryElement * cell_types = mesh->getTypes(MED_CELL);
766 for ( int t = 0; t < general_info[I_NB_CELL_TYPES]; ++t )
768 *type_ptr++ = cell_types[t];
769 int_data[ i_slice++ ].setPtr( mesh->getConnectivityLength( conn, MED_CELL, cell_types[t]),
770 mesh->getConnectivity ( conn, MED_CELL, cell_types[t]));
774 const medGeometryElement * face_types = mesh->getTypes( face_entity );
775 for ( int t = 0; t < general_info[I_NB_FACE_TYPES]; ++t )
777 *type_ptr++ = face_types[t];
778 int_data[ i_slice++ ].setPtr(mesh->getConnectivityLength( conn, face_entity, face_types[t]),
779 mesh->getConnectivity( conn, face_entity, face_types[t]));
782 // polygon connectivity index
784 medEntityMesh polygon_entity = mesh->getMeshDimension()==2 ? MED_CELL : MED_FACE;
785 if ( int nb_polygon = mesh->getNumberOfElements( polygon_entity, MED_POLYGON ))
787 const int nbTypes = mesh->getNumberOfTypes( polygon_entity );
788 const int * index = mesh->getConnectivityIndex( conn, polygon_entity );
789 index += mesh->getGlobalNumberingIndex( polygon_entity )[ nbTypes-1 ] - 1;
790 int_data[SLC_POLYGON_INDEX].setPtr( nb_polygon + 1, index );
792 // polyherdra connectivity index
794 if ( int nb_polyhedra = mesh->getNumberOfElements( MED_CELL, MED_POLYHEDRA ))
796 const int nbTypes = mesh->getNumberOfTypes( MED_CELL );
797 const int * index = mesh->getConnectivityIndex( conn, MED_CELL );
798 index += mesh->getGlobalNumberingIndex( MED_CELL )[ nbTypes-1 ] - 1;
799 int_data[SLC_POLYHED_INDEX].setPtr( nb_polyhedra + 1, index );
803 coords.setPtr( general_info[I_NB_NODES] * general_info[I_SPACEDIM],
804 mesh->getCoordinates( MED_FULL_INTERLACE ));
806 // elements and names of families
808 int is_on_all_elements[] = { IS_ON_ALL_FLAG };
809 for ( int f = 0; f < families.size(); ++f )
811 char_data[ char_slice++ ] = toCharSlice( families[f]->getName() );
813 if ( families[f]->isOnAllElements() )
815 int_data[ i_slice++ ].copy( 1, is_on_all_elements);
819 bool is_nodal = ( families[f]->getEntity() == MED_NODE );
820 int nb_types = is_nodal ? 1 : families[f]->getNumberOfTypes();
821 for ( int t = 0; t < nb_types; ++t )
823 medGeometryElement type = is_nodal ? MED_ALL_ELEMENTS : families[f]->getTypes()[t];
824 int_data[ i_slice++ ].setPtr( families[f]->getNumberOfElements( type ),
825 families[f]->getNumber( type ));
831 for ( int g = 0; g < groups.size(); ++g )
832 char_data[ char_slice++ ] = toCharSlice( groups[g]->getName() );
839 //================================================================================
841 * \brief Send mesh to processor irank
843 * WARNING: do NOT delete the mesh until this->isSent()!
845 //================================================================================
847 void MeshSendReceive::send(int irank,
850 const vector<int>& cell_glob_numbers,
851 const vector<int>& face_glob_numbers,
852 const vector<int>& node_glob_numbers)
855 vector< TIntSlice > int_data;
856 vector< TCharSlice > char_data;
858 if ( _mesh && getMeshData( _mesh, int_data, char_data, coords ))
860 serialize( int_data, _int_buf );
861 serialize( char_data, _char_buf );
862 _node_glob_numbers = node_glob_numbers;
863 _cell_glob_numbers = cell_glob_numbers;
864 _face_glob_numbers = face_glob_numbers;
867 MPI_Isend((void*)&_int_buf[0], _int_buf.size(), MPI_INT, irank,
868 idomain + TAG_INT, MPI_COMM_WORLD, &_int_request);
870 MPI_Isend((void*)coords._pointer, coords._size, MPI_DOUBLE, irank,
871 idomain + TAG_COORD, MPI_COMM_WORLD, &_coord_request);
873 MPI_Isend((void*)&_char_buf[0], _char_buf.size(), MPI_CHAR, irank,
874 idomain + TAG_CHAR, MPI_COMM_WORLD, &_char_request);
876 MPI_Isend((void*)&_cell_glob_numbers[0], _cell_glob_numbers.size(), MPI_INT, irank,
877 idomain + TAG_CELL_NUMS, MPI_COMM_WORLD, &_cell_nums_request);
879 MPI_Isend((void*)&_face_glob_numbers[0], _face_glob_numbers.size(), MPI_INT, irank,
880 idomain + TAG_FACE_NUMS, MPI_COMM_WORLD, &_face_nums_request);
882 MPI_Isend((void*)&_node_glob_numbers[0], _node_glob_numbers.size(), MPI_INT, irank,
883 idomain + TAG_NODE_NUMS, MPI_COMM_WORLD, &_node_nums_request);
887 // send anything not to block recv()
888 MPI_Isend((void*)&irank, 1, MPI_INT, irank,
889 idomain + TAG_INT, MPI_COMM_WORLD, &_int_request);
893 //================================================================================
895 * \brief Receive mesh from irank processor synchronously
897 //================================================================================
899 MEDMEM::MESH* MeshSendReceive::recv(int irank, int idomain,
900 vector<int>& cell_glob_numbers,
901 vector<int>& face_glob_numbers,
902 vector<int>& node_glob_numbers)
909 MPI_Probe(irank, idomain + TAG_INT, MPI_COMM_WORLD, &status); // wait for the message
911 MPI_Get_count( &status, MPI_INT, &msg_size ); // size of arrived message
912 _int_buf.resize( msg_size );
913 MPI_Recv((void*)&_int_buf[0], _int_buf.size(), MPI_INT, irank,
914 idomain + TAG_INT, MPI_COMM_WORLD, &status);
915 if ( msg_size <= I_MIN_SIZE )
916 return 0; // mesh not sent
918 // receive coordinates
920 MPI_Probe(irank, idomain + TAG_COORD, MPI_COMM_WORLD, &status); // wait for the message
921 MPI_Get_count( &status, MPI_DOUBLE, &msg_size ); // size of arrived message
922 vector< double > coord_buf( msg_size );
923 MPI_Recv((void*)&coord_buf[0], msg_size, MPI_DOUBLE, irank,
924 idomain + TAG_COORD, MPI_COMM_WORLD, &status);
928 MPI_Probe(irank, idomain + TAG_CHAR, MPI_COMM_WORLD, &status); // wait for the message
929 MPI_Get_count( &status, MPI_CHAR, &msg_size ); // size of arrived message
930 _char_buf.resize( msg_size );
931 MPI_Recv((void*)&_char_buf[0], _char_buf.size(), MPI_CHAR, irank,
932 idomain + TAG_CHAR, MPI_COMM_WORLD, &status);
934 // receive global cell numbers
936 MPI_Probe(irank, idomain + TAG_CELL_NUMS, MPI_COMM_WORLD, &status); // wait for the message
937 MPI_Get_count( &status, MPI_INT, &msg_size ); // size of arrived message
938 cell_glob_numbers.resize( msg_size );
939 MPI_Recv((void*)&cell_glob_numbers[0], cell_glob_numbers.size(), MPI_INT, irank,
940 idomain + TAG_CELL_NUMS, MPI_COMM_WORLD, &status);
942 // receive global face numbers
944 MPI_Probe(irank, idomain + TAG_FACE_NUMS, MPI_COMM_WORLD, &status); // wait for the message
945 MPI_Get_count( &status, MPI_INT, &msg_size ); // size of arrived message
946 face_glob_numbers.resize( msg_size );
947 MPI_Recv((void*)&face_glob_numbers[0], face_glob_numbers.size(), MPI_INT, irank,
948 idomain + TAG_FACE_NUMS, MPI_COMM_WORLD, &status);
950 // receive global node numbers
952 MPI_Probe(irank, idomain + TAG_NODE_NUMS, MPI_COMM_WORLD, &status); // wait for the message
953 MPI_Get_count( &status, MPI_INT, &msg_size ); // size of arrived message
954 node_glob_numbers.resize( msg_size );
955 MPI_Recv((void*)&node_glob_numbers[0], node_glob_numbers.size(), MPI_INT, irank,
956 idomain + TAG_NODE_NUMS, MPI_COMM_WORLD, &status);
960 vector< TIntSlice > int_data;
961 if ( int badSlice = deserialize( _int_buf, int_data ))
962 throw MED_EXCEPTION(MEDMEM::STRING("MeshSendReceive::recv(")<<irank<<"): "
963 << "int deserialization error on slice "<< badSlice);
965 bool toClearFamilies;
966 _mesh = makeMesh( int_data, toClearFamilies );
973 ((MEDMEM::MESHING*)_mesh)->setCoordinates( _mesh->getSpaceDimension(),
974 _mesh->getNumberOfNodes(),
976 MED_EN::MED_FULL_INTERLACE);
981 vector< TCharSlice > char_data;
982 if ( int badSlice = deserialize( _char_buf, char_data ))
983 throw MED_EXCEPTION(MEDMEM::STRING("MeshSendReceive::recv(")<<irank<<"): "
984 << "char deserialization error on slice "<< badSlice);
985 setNames( char_data, _mesh );
988 if ( toClearFamilies )
989 ((TMESHING*) _mesh)->clearFamilies();
994 //=======================================================================
995 #else // #ifdef HAVE_MPI2
997 MeshSendReceive::MeshSendReceive() {}
998 MeshSendReceive::~MeshSendReceive() {}
999 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) {}
1000 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; }
1001 bool MeshSendReceive::isSent() { return 0; }
1002 void MeshSendReceive::clear() {}
1005 //=======================================================================