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
20 #include "ParaMEDMEMComponent_i.hxx"
21 #include "utilities.h"
22 #include "Utils_SALOME_Exception.hxx"
24 using namespace ParaMEDMEM;
32 pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
33 pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
35 ParaMEDMEMComponent_i::ParaMEDMEMComponent_i()
37 _interface = new CommInterface;
40 ParaMEDMEMComponent_i::ParaMEDMEMComponent_i(CORBA::ORB_ptr orb,
41 PortableServer::POA_ptr poa,
42 PortableServer::ObjectId * contId,
43 const char *instanceName,
44 const char *interfaceName,
46 : Engines_Component_i(orb,poa,contId,instanceName,interfaceName,false,regist)
48 _interface = new CommInterface;
51 ParaMEDMEMComponent_i::~ParaMEDMEMComponent_i()
53 MESSAGE("* [" << _numproc << "] ParaMEDMEMComponent destructor");
55 pthread_mutex_destroy (&m1);
56 pthread_mutex_destroy (&m2);
59 void ParaMEDMEMComponent_i::initializeCoupling(const char * coupling, const char * ior) throw(SALOME::SALOME_Exception)
67 pthread_mutex_lock(&m1);
70 th = new pthread_t[_nbproc];
71 for(int ip=1;ip<_nbproc;ip++)
73 thread_st *st = new thread_st;
76 st->coupling = coupling;
78 pthread_create(&(th[ip]),NULL,th_initializecoupling,(void*)st);
83 string service = coupling;
84 if( service.size() == 0 )
85 throw SALOME_Exception("You have to give a service name !");
87 if( _gcom.find(service) != _gcom.end() )
89 msg << "service " << service << " already exists !";
90 throw SALOME_Exception(msg.str().c_str());
93 // Connection to distributed parallel component
95 remoteMPI2Connect(coupling);
97 throw SALOME_Exception("You have to use a MPI2 compliant mpi implementation !");
100 MPI_Comm_size( _gcom[coupling], &gsize );
101 MPI_Comm_rank( _gcom[coupling], &grank );
102 MESSAGE("[" << grank << "] new communicator of " << gsize << " processes");
104 // Creation of processors group for ParaMEDMEM
105 // source is always the lower processor numbers
106 // target is always the upper processor numbers
109 _source[coupling] = new MPIProcessorGroup(*_interface,0,_nbproc-1,_gcom[coupling]);
110 _target[coupling] = new MPIProcessorGroup(*_interface,_nbproc,gsize-1,_gcom[coupling]);
111 _commgroup[coupling] = _source[coupling];
115 _source[coupling] = new MPIProcessorGroup(*_interface,0,gsize-_nbproc-1,_gcom[coupling]);
116 _target[coupling] = new MPIProcessorGroup(*_interface,gsize-_nbproc,gsize-1,_gcom[coupling]);
117 _commgroup[coupling] = _target[coupling];
119 _connectto [coupling] = ior;
120 _dec[coupling] = NULL;
121 _dec_options[coupling] = NULL;
124 catch(const std::exception &ex)
127 THROW_SALOME_CORBA_EXCEPTION(ex.what(),SALOME::INTERNAL_ERROR);
130 pthread_mutex_unlock(&m1);
133 for(int ip=1;ip<_nbproc;ip++)
135 pthread_join(th[ip],&ret_th);
136 est = (except_st*)ret_th;
139 msg << "[" << ip << "] " << est->msg;
140 THROW_SALOME_CORBA_EXCEPTION(msg.str().c_str(),SALOME::INTERNAL_ERROR);
148 void ParaMEDMEMComponent_i::terminateCoupling(const char * coupling) throw(SALOME::SALOME_Exception)
155 pthread_mutex_lock(&m2);
158 th = new pthread_t[_nbproc];
159 for(int ip=1;ip<_nbproc;ip++)
161 thread_st *st = new thread_st;
164 st->coupling = coupling;
165 pthread_create(&(th[ip]),NULL,th_terminatecoupling,(void*)st);
170 string service = coupling;
171 if( service.size() == 0 )
172 throw SALOME_Exception("You have to give a service name !");
174 if( _gcom.find(service) == _gcom.end() )
176 msg << "service " << service << " doesn't exist !";
177 throw SALOME_Exception(msg.str().c_str());
180 // Disconnection to distributed parallel component
182 remoteMPI2Disconnect(coupling);
184 throw SALOME_Exception("You have to use a MPI2 compliant mpi implementation !");
187 /* Processors groups and DEC destruction */
188 delete _source[coupling];
189 _source.erase(coupling);
190 delete _target[coupling];
191 _target.erase(coupling);
192 delete _dec[coupling];
193 _dec.erase(coupling);
194 _commgroup.erase(coupling);
195 if(_dec_options[coupling])
197 delete _dec_options[coupling];
198 _dec_options.erase(coupling);
200 _connectto.erase(coupling);
202 catch(const std::exception &ex)
205 THROW_SALOME_CORBA_EXCEPTION(ex.what(),SALOME::INTERNAL_ERROR);
207 pthread_mutex_unlock(&m2);
210 for(int ip=1;ip<_nbproc;ip++)
212 pthread_join(th[ip],&ret_th);
213 est = (except_st*)ret_th;
217 msg << "[" << ip << "] " << est->msg;
218 THROW_SALOME_CORBA_EXCEPTION(msg.str().c_str(),SALOME::INTERNAL_ERROR);
226 void ParaMEDMEMComponent_i::setInterpolationOptions(const char * coupling,
227 CORBA::Long print_level,
228 const char * intersection_type,
229 CORBA::Double precision,
230 CORBA::Double median_plane,
231 CORBA::Boolean do_rotate,
232 CORBA::Double bounding_box_adjustment,
233 CORBA::Double bounding_box_adjustment_abs,
234 CORBA::Double max_distance_for_3Dsurf_intersect,
235 CORBA::Long orientation,
236 CORBA::Boolean measure_abs,
237 const char * splitting_policy,
238 CORBA::Boolean P1P0_bary_method ) throw(SALOME::SALOME_Exception)
247 th = new pthread_t[_nbproc];
248 for(int ip=1;ip<_nbproc;ip++)
250 thread_st *st = new thread_st;
253 st->coupling = coupling;
254 st->print_level = print_level;
255 st->intersection_type = intersection_type;
256 st->precision = precision;
257 st->median_plane = median_plane;
258 st->do_rotate = do_rotate;
259 st->bounding_box_adjustment = bounding_box_adjustment;
260 st->bounding_box_adjustment_abs = bounding_box_adjustment_abs;
261 st->max_distance_for_3Dsurf_intersect = max_distance_for_3Dsurf_intersect;
262 st->orientation = orientation;
263 st->measure_abs = measure_abs;
264 st->splitting_policy = splitting_policy;
265 st->P1P0_bary_method = P1P0_bary_method;
266 pthread_create(&(th[ip]),NULL,th_setinterpolationoptions,(void*)st);
270 if(!_dec_options[coupling])
271 _dec_options[coupling] = new INTERP_KERNEL::InterpolationOptions;
273 bool ret = _dec_options[coupling]->setInterpolationOptions(print_level,
278 bounding_box_adjustment,
279 bounding_box_adjustment_abs,
280 max_distance_for_3Dsurf_intersect,
288 MESSAGE("Error on setting interpolation options");
289 THROW_SALOME_CORBA_EXCEPTION("Error on setting interpolation options",SALOME::INTERNAL_ERROR);
294 for(int ip=1;ip<_nbproc;ip++)
296 pthread_join(th[ip],&ret_th);
297 est = (except_st*)ret_th;
300 msg << "[" << ip << "] " << est->msg;
301 THROW_SALOME_CORBA_EXCEPTION(msg.str().c_str(),SALOME::INTERNAL_ERROR);
309 void ParaMEDMEMComponent_i::_setInputField(SALOME_MED::MPIMEDCouplingFieldDoubleCorbaInterface_ptr fieldptr, MEDCouplingFieldDouble *field)
318 std::map<std::string,std::string>::const_iterator it = mapSearchByValue(_connectto, fieldptr->getRef());
319 if(it != _connectto.end())
320 coupling = (*it).first.c_str();
322 throw SALOME_Exception("Reference of remote component doesn't find in connectto map !");
326 thread_st *st = new thread_st;
327 st->fieldptr = fieldptr;
328 st->coupling = coupling;
329 pthread_create(&th,NULL,th_getdata,(void*)st);
332 if( coupling.size() == 0 )
333 throw SALOME_Exception("You have to give a service name !");
335 if( _gcom.find(coupling) == _gcom.end() )
337 msg << "service " << coupling << " doesn't exist !";
338 throw SALOME_Exception(msg.str().c_str());
344 MPI_Comm_rank( _gcom[coupling], &grank );
346 // Creating the intersection Data Exchange Channel
347 // Processors which received the field are always the second argument of InterpKernelDEC object
349 _dec[coupling] = new InterpKernelDEC(*_target[coupling], *_source[coupling]);
351 _dec[coupling] = new InterpKernelDEC(*_source[coupling], *_target[coupling]);
353 if(_dec_options[coupling])
354 _dec[coupling]->copyOptions(*(_dec_options[coupling]));
356 //Attaching the field to the DEC
357 _dec[coupling]->attachLocalField(field);
359 // computing the interpolation matrix
360 _dec[coupling]->synchronize();
364 //Attaching the field to the DEC
365 _dec[coupling]->attachLocalField(field);
368 _dec[coupling]->recvData();
372 pthread_join(th,&ret_th);
373 est = (except_st*)ret_th;
375 throw SALOME_Exception(est->msg.c_str());
381 void ParaMEDMEMComponent_i::_getOutputField(const char * coupling, MEDCouplingFieldDouble *field)
384 string service = coupling;
387 if( service.size() == 0 )
388 throw SALOME_Exception("You have to give a service name !");
390 if( _gcom.find(service) == _gcom.end() )
392 msg << "service " << service << " doesn't exist !";
393 throw SALOME_Exception(msg.str().c_str());
399 MPI_Comm_rank( _gcom[coupling], &grank );
401 // Creating the intersection Data Exchange Channel
402 // Processors which sent the field are always the first argument of InterpKernelDEC object
404 _dec[coupling] = new InterpKernelDEC(*_source[coupling], *_target[coupling]);
406 _dec[coupling] = new InterpKernelDEC(*_target[coupling], *_source[coupling]);
408 if(_dec_options[coupling])
409 _dec[coupling]->copyOptions(*(_dec_options[coupling]));
411 //Attaching the field to the DEC
412 _dec[coupling]->attachLocalField(field);
414 // computing the interpolation matrix
415 _dec[coupling]->synchronize();
418 //Attaching the field to the DEC
419 _dec[coupling]->attachLocalField(field);
422 _dec[coupling]->sendData();
425 void ParaMEDMEMComponent_i::_initializeCoupling(SALOME_MED::MPIMEDCouplingFieldDoubleCorbaInterface_ptr fieldptr)
430 //this string specifies the coupling
432 //getting IOR string of the remote object
433 string rcompo = fieldptr->getRef();
435 //getting IOR string of the local object
436 CORBA::Object_var my_ref = _poa->servant_to_reference (_thisObj);
437 string lcompo = _orb->object_to_string(my_ref);
438 //the component does not communicate with itself, a connection is required
439 if( rcompo.find(lcompo) == std::string::npos ){
440 th = new pthread_t[1];
441 //finding the IOR of the remote object in the map
442 std::map<std::string,std::string>::const_iterator it = mapSearchByValue(_connectto, rcompo);
443 //if it is not found : connecting two objects : this is the first (and the only) connection between these objects
444 if (it == _connectto.end()){
445 //generating the coupling string : concatenation of two IOR strings
446 coupling = lcompo + rcompo;
448 //initializing the coupling on the remote object in a thread
449 thread_st *st = new thread_st;
450 CORBA::Object_var obj = _orb->string_to_object (rcompo.c_str());
451 SALOME_MED::ParaMEDMEMComponent_var compo = SALOME_MED::ParaMEDMEMComponent::_narrow(obj);
452 st->compo = compo._retn();
453 st->coupling = coupling;
456 pthread_create(&(th[0]),NULL,th_initializecouplingdist,(void*)st);
458 //initializing the coupling on the local object
459 initializeCoupling (coupling.c_str(), rcompo.c_str());
460 pthread_join (th[0], &ret_th);
461 est = (except_st*)ret_th;
463 THROW_SALOME_CORBA_EXCEPTION(est->msg.c_str(),SALOME::INTERNAL_ERROR);
471 std::map<std::string,std::string>::const_iterator ParaMEDMEMComponent_i::mapSearchByValue(std::map<std::string,std::string> & search_map, std::string search_val)
473 std::map<std::string,std::string>::const_iterator iRet = search_map.end();
474 for (std::map<std::string,std::string>::const_iterator iTer = search_map.begin(); iTer != search_map.end(); iTer ++)
476 if( iTer->second.find(search_val) != std::string::npos )
485 bool ParaMEDMEMComponent_i::amICoupledWithThisComponent(const char* cref)
487 std::map<std::string,std::string>::const_iterator it = mapSearchByValue(_connectto, cref);
488 if(it != _connectto.end())
494 void *th_setinterpolationoptions(void *s)
497 thread_st *st = (thread_st*)s;
498 except_st *est = new except_st;
499 est->exception = false;
502 SALOME_MED::ParaMEDMEMComponent_var compo=SALOME_MED::ParaMEDMEMComponent::_narrow((*(st->tior))[st->ip]);
503 compo->setInterpolationOptions(st->coupling.c_str(),
505 st->intersection_type,
509 st->bounding_box_adjustment,
510 st->bounding_box_adjustment_abs,
511 st->max_distance_for_3Dsurf_intersect,
514 st->splitting_policy,
515 st->P1P0_bary_method);
517 catch(const SALOME::SALOME_Exception &ex)
519 est->exception = true;
520 est->msg = ex.details.text;
522 catch(const CORBA::Exception &ex)
524 est->exception = true;
525 msg << "CORBA::Exception: " << ex;
526 est->msg = msg.str();
532 void *th_initializecoupling(void *s)
535 thread_st *st = (thread_st*)s;
536 except_st *est = new except_st;
537 est->exception = false;
541 SALOME_MED::ParaMEDMEMComponent_var compo=SALOME_MED::ParaMEDMEMComponent::_narrow((*(st->tior))[st->ip]);
542 compo->initializeCoupling(st->coupling.c_str(),st->ior.c_str());
544 catch(const SALOME::SALOME_Exception &ex)
546 est->exception = true;
547 est->msg = ex.details.text;
549 catch(const CORBA::Exception &ex)
551 est->exception = true;
552 msg << "CORBA::Exception: " << ex;
553 est->msg = msg.str();
559 void *th_terminatecoupling(void *s)
562 thread_st *st = (thread_st*)s;
563 except_st *est = new except_st;
564 est->exception = false;
568 SALOME_MED::ParaMEDMEMComponent_var compo=SALOME_MED::ParaMEDMEMComponent::_narrow((*(st->tior))[st->ip]);
569 compo->terminateCoupling(st->coupling.c_str());
571 catch(const SALOME::SALOME_Exception &ex)
573 est->exception = true;
574 est->msg = ex.details.text;
576 catch(const CORBA::Exception &ex)
578 est->exception = true;
579 msg << "CORBA::Exception: " << ex;
580 est->msg = msg.str();
586 void *th_getdata(void *s)
589 thread_st *st = (thread_st*)s;
590 except_st *est = new except_st;
591 est->exception = false;
595 st->fieldptr->getDataByMPI(st->coupling.c_str());
597 catch(const SALOME::SALOME_Exception &ex)
599 est->exception = true;
600 est->msg = ex.details.text;
602 catch(const CORBA::Exception &ex)
604 est->exception = true;
605 msg << "CORBA::Exception: " << ex;
606 est->msg = msg.str();
612 void *th_initializecouplingdist(void *s)
615 thread_st *st = (thread_st*)s;
616 except_st *est = new except_st;
617 est->exception = false;
621 st->compo->initializeCoupling(st->coupling.c_str(), st->ior.c_str());
623 catch(const SALOME::SALOME_Exception &ex)
625 est->exception = true;
626 est->msg = ex.details.text;
628 catch(const CORBA::Exception &ex)
630 est->exception = true;
631 msg << "CORBA::Exception: " << ex;
632 est->msg = msg.str();
638 void *th_terminatecouplingdist(void *s)
641 thread_st *st = (thread_st*)s;
642 except_st *est = new except_st;
643 est->exception = false;
647 st->compo->terminateCoupling(st->coupling.c_str());
649 catch(const SALOME::SALOME_Exception &ex)
651 est->exception = true;
652 est->msg = ex.details.text;
654 catch(const CORBA::Exception &ex)
656 est->exception = true;
657 msg << "CORBA::Exception: " << ex;
658 est->msg = msg.str();