Salome HOME
Copyright update 2022
[modules/paravis.git] / src / Insitu / VisualizationComponent / VisualizationComponent.cxx
1 // Copyright (C) 2016-2022  CEA/DEN, EDF R&D
2 //
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, or (at your option) any later version.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "VisualizationComponent.hxx"
21 #include <string>
22 #include <unistd.h>
23 #include <signal.h>
24 #include <SALOME_NamingService.hxx>
25 #include <Utils_SALOME_Exception.hxx>
26 #include "Utils_CorbaException.hxx"
27 #include <pthread.h>
28 #include <execinfo.h>
29
30 typedef struct
31 {
32   bool exception;
33   std::string msg;
34 } exception_st;
35
36 //DEFS
37
38 #include "visu.hxx"
39 #include "MEDCouplingFieldDoubleClient.hxx"
40 #include "ParaMEDCouplingFieldDoubleServant.hxx"
41 #include "omniORB4/poa.h"
42
43 //ENDDEF
44
45
46 using namespace std;
47
48 //! Constructor for component "VisualizationComponent" instance
49 /*!
50  *
51  */
52 VisualizationComponent_i::VisualizationComponent_i(CORBA::ORB_ptr orb,
53                      PortableServer::POA_ptr poa,
54                      PortableServer::ObjectId * contId,
55                      const char *instanceName,
56                      const char *interfaceName,
57                      bool regist)
58           : Engines_Component_i(orb, poa, contId, instanceName, interfaceName,
59                                 false, regist)
60 {
61   _thisObj = this ;
62   _id = _poa->activate_object(_thisObj);
63 }
64
65 VisualizationComponent_i::VisualizationComponent_i(CORBA::ORB_ptr orb,
66                      PortableServer::POA_ptr poa,
67                      Engines::Container_ptr container,
68                      const char *instanceName,
69                      const char *interfaceName,
70                      bool regist)
71           : Engines_Component_i(orb, poa, container, instanceName, interfaceName,
72                                 false, regist)
73 {
74   _thisObj = this ;
75   _id = _poa->activate_object(_thisObj);
76 }
77
78 //! Destructor for component "VisualizationComponent" instance
79 VisualizationComponent_i::~VisualizationComponent_i()
80 {
81 }
82
83
84 void * th_Visualize(void * s)
85 {
86   std::ostringstream msg;
87   exception_st *est = new exception_st;
88   est->exception = false;
89   
90   thread_Visualize_struct *st = (thread_Visualize_struct *)s;
91   
92   try
93   {
94     
95     PARAVIS_ORB::VisualizationComponent_var compo = PARAVIS_ORB::VisualizationComponent::_narrow((*(st->tior))[st->ip]);
96     compo->Visualize(st->field,st->path_python_file);
97   }
98   catch(const SALOME::SALOME_Exception &ex)
99   {
100     est->exception = true;
101     est->msg = ex.details.text;
102   }
103   catch(const CORBA::Exception &ex)
104   {
105     est->exception = true;
106     msg << "CORBA::Exception: " << ex;
107     est->msg = msg.str();
108   }
109   
110   delete st;
111   return ((void*)est);
112 }
113
114 void VisualizationComponent_i::Visualize(SALOME_MED::ParaMEDCouplingFieldDoubleCorbaInterface_ptr field,const char* path_python_file)
115 {
116   beginService("VisualizationComponent_i::Visualize");
117   void *ret_th;
118   pthread_t *th = 0;
119   exception_st *est;
120
121   try
122     {
123       // Run the service in every MPI process
124       if(_numproc == 0)
125       {
126         th = new pthread_t[_nbproc];
127         for(int ip=1;ip<_nbproc;ip++)
128         {
129             thread_Visualize_struct *st = new thread_Visualize_struct;
130             st->ip = ip;
131             st->tior = _tior;
132             st->field = field;
133 st->path_python_file = path_python_file;
134             pthread_create(&(th[ip]),NULL,th_Visualize,(void*)st);
135         }
136       }
137       
138 //BODY
139
140 const MEDCoupling::MEDCouplingFieldDouble * local_field(NULL);
141 int nb_fields = field->tior()->length();
142 if(nb_fields == _nbproc)
143 {
144   SALOME_MED::ParaMEDCouplingFieldDoubleCorbaInterface_ptr local_corba_field = 
145                SALOME_MED::ParaMEDCouplingFieldDoubleCorbaInterface::_narrow((*(field->tior()))[_numproc]);
146
147
148   PortableServer::ServantBase *ret;
149   try {
150     ret=PortableServer::POA::_the_root_poa()->reference_to_servant(local_corba_field);
151     std::cerr << "Servant succeeded!" << std::endl;
152     MEDCoupling::ParaMEDCouplingFieldDoubleServant* servant_field = 
153                dynamic_cast<MEDCoupling::ParaMEDCouplingFieldDoubleServant*>(ret);
154     if(servant_field != NULL)
155     {
156       std::cerr << "In-situ configuration!" << std::endl;
157       // same container, same mpi proc, use the pointer directly.
158       local_field = servant_field->getPointer();
159       ret->_remove_ref();
160     }
161   }
162   catch(...){
163     // different container - need to make a copy of the field.
164     ret = NULL;
165     std::cerr << "Co-processing configuration!" << std::endl;
166     local_field = MEDCoupling::MEDCouplingFieldDoubleClient::New(local_corba_field);
167   }
168 }
169 else if(nb_fields < _nbproc)
170 {
171   if(_numproc < nb_fields)
172   {
173     SALOME_MED::ParaMEDCouplingFieldDoubleCorbaInterface_ptr local_corba_field = 
174                SALOME_MED::ParaMEDCouplingFieldDoubleCorbaInterface::_narrow((*(field->tior()))[_numproc]);
175     local_field = MEDCoupling::MEDCouplingFieldDoubleClient::New(local_corba_field);
176   }
177 }
178 else //nb_fields > _nbproc
179 {
180   int q = nb_fields / _nbproc; // int division
181   int r = nb_fields - q * _nbproc;
182   int start, end;
183   
184   if(_numproc < r)
185   {
186     // get one more field to process
187     start = _numproc * (q + 1);
188     end = start + q + 1;
189   }
190   else
191   {
192     start = r * (q + 1) + (_numproc - r) * q;
193     end = start + q;
194   }
195   
196   std::cerr << "Proc n° " << _numproc << ". Merge fields from " << start << " to " << end << std::endl;
197   
198   std::vector<const MEDCoupling::MEDCouplingFieldDouble *> fieldsToProcess;
199   for(int i = start; i < end; i++)
200   {
201     SALOME_MED::ParaMEDCouplingFieldDoubleCorbaInterface_ptr local_corba_field = 
202                SALOME_MED::ParaMEDCouplingFieldDoubleCorbaInterface::_narrow((*(field->tior()))[i]);
203     fieldsToProcess.push_back(MEDCoupling::MEDCouplingFieldDoubleClient::New(local_corba_field));
204   }
205   
206   local_field = MEDCoupling::MEDCouplingFieldDouble::MergeFields(fieldsToProcess);
207 }
208
209 Visualization v;
210 v.run(const_cast<MEDCoupling::MEDCouplingFieldDouble*>(local_field), path_python_file);
211
212 //ENDBODY
213       if(_numproc == 0)
214       {
215         for(int ip=1;ip<_nbproc;ip++)
216         {
217           pthread_join(th[ip],&ret_th);
218           est = (exception_st*)ret_th;
219           if(est->exception)
220           {
221               std::ostringstream msg;
222               msg << "[" << ip << "] " << est->msg;
223               delete est;
224               delete[] th;
225               THROW_SALOME_CORBA_EXCEPTION(msg.str().c_str(),SALOME::INTERNAL_ERROR);
226           }
227           delete est;
228         }
229         delete[] th;
230       }
231     }
232   catch ( const SALOME_Exception & ex)
233     {
234       THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(ex.what()), SALOME::INTERNAL_ERROR);
235     }
236   catch ( const SALOME::SALOME_Exception & ex)
237     {
238       throw;
239     }
240   catch ( const std::exception& ex)
241     {
242       THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(ex.what()), SALOME::INTERNAL_ERROR);
243     }
244   catch (...)
245     {
246       THROW_SALOME_CORBA_EXCEPTION("unknown exception", SALOME::INTERNAL_ERROR);
247     }
248   endService("VisualizationComponent_i::Visualize");
249 }
250
251
252
253 extern "C"
254 {
255   PortableServer::ObjectId * VisualizationComponentEngine_factory( CORBA::ORB_ptr orb,
256                                                     PortableServer::POA_ptr poa,
257                                                     PortableServer::ObjectId * contId,
258                                                     const char *instanceName,
259                                                     const char *interfaceName)
260   {
261     MESSAGE("PortableServer::ObjectId * VisualizationComponentEngine_factory()");
262     int is_mpi_container;
263     bool regist;
264     int numproc;
265     
266     MPI_Initialized(&is_mpi_container);
267     if (!is_mpi_container)
268     {
269       int argc = 0;
270       char ** argv = NULL;
271       MPI_Init(&argc, &argv);
272     }
273     
274     MPI_Comm_rank( MPI_COMM_WORLD, &numproc );
275     regist = ( numproc == 0 );
276     VisualizationComponent_i * myEngine = new VisualizationComponent_i(orb, poa, contId, instanceName, interfaceName, regist);
277     return myEngine->getId() ;
278   }
279 }