Salome HOME
Merge from V6_main_20120808 08Aug12
[samples/calculator.git] / src / CALCULATOR / CALCULATOR.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "CALCULATOR.hxx"
24
25 #include "MEDCouplingFieldDoubleClient.hxx"
26 #include "MEDCouplingMeshClient.hxx"
27
28 #include "MEDCouplingMeshServant.hxx"
29 #include "MEDCouplingFieldDoubleServant.hxx"
30
31 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
32 #include "MEDCouplingMemArray.hxx"
33
34 #include <string>
35 #include <sstream>
36
37 #include <iomanip>
38 #include <cmath>
39 #include <float.h>
40
41 #include <memory>
42
43 using namespace std;
44
45 CALCULATOR::CALCULATOR (CORBA::ORB_ptr orb,
46                         PortableServer::POA_ptr poa,
47                         PortableServer::ObjectId * contId, 
48                         const char *instanceName, 
49                         const char *interfaceName)
50   : Engines_Component_i(orb, poa, contId, instanceName, interfaceName, true),
51     _errorCode(CALCULATOR_ORB::NO_ERROR)
52 {
53   _thisObj = this;
54   _id = _poa->activate_object(_thisObj);
55 }
56
57 CALCULATOR::~CALCULATOR()
58 {
59 }
60
61 CORBA::Double CALCULATOR::norm2(SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field1)
62 {
63   beginService( "CALCULATOR::norm2");
64   _errorCode = CALCULATOR_ORB::NO_ERROR;
65   //const char* LOC = "CALCULATOR::Norm2(SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field1)";
66         
67   if(CORBA::is_nil(field1))
68     {
69       _errorCode = CALCULATOR_ORB::INVALID_FIELD;
70       return 0.0;
71     }
72
73   CORBA::Double norme = 0.0;
74   // Create a local field from corba field, apply method normMax on it.
75   // When exiting the function, f1 is deleted, and with it the remote corba field.
76   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> f1=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field1);
77   /*ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::DataArrayDouble> d=ParaMEDMEM::DataArrayDouble::Multiply(f1->getArray(),f1->getArray());
78   d->rearrange(1);
79   try {
80     norme = d->accumulate(0);
81   }
82   catch(...) {
83     _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
84   }*/
85   try
86     {
87       norme = f1->norm2();
88     }    
89   catch(...)
90     {
91       _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
92     }
93
94   endService( "CALCULATOR::norm2");
95   return norme;
96 }
97
98 CORBA::Double CALCULATOR::normL2(SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field1)
99 {
100   beginService( "CALCULATOR::normL2");
101   _errorCode = CALCULATOR_ORB::NO_ERROR;
102   //const char* LOC = "CALCULATOR::NormL2(SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field1)";
103   //BEGIN_OF(LOC);
104
105   if(CORBA::is_nil(field1))
106     {
107       _errorCode = CALCULATOR_ORB::INVALID_FIELD;
108       return 0.0;
109     }
110
111   //Check that the Field is not on the Nodes (a limitation of normL2)
112   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> f1=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field1);
113   
114   if(f1->getTypeOfField()==ParaMEDMEM::ON_NODES)
115     {
116       _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
117       return 0.0;
118     }
119         
120   CORBA::Double norme = 0.0;
121   try
122     {
123       norme = f1->normL2(0);
124     }    
125   catch(...)
126     {
127       _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
128     }
129     
130   // Send a notification message to supervision
131   ostringstream message("CALCULATOR::normL2 : ");
132   message << norme;
133   sendMessage("warning",message.str().c_str());
134   //END_OF(LOC);
135   endService( "CALCULATOR::normL2");
136   return norme;
137 }
138
139 CORBA::Double CALCULATOR::normMax(SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field1)
140 {
141   beginService( "CALCULATOR::normMax");
142   _errorCode = CALCULATOR_ORB::NO_ERROR;
143          
144   if(CORBA::is_nil(field1))
145     {
146       _errorCode = CALCULATOR_ORB::INVALID_FIELD;
147       return 0.0;
148     }
149
150   CORBA::Double norme = 0.0;
151   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> f1=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field1);
152   try
153     {
154       norme = f1->normMax();
155     }
156   catch(...)
157     {
158       _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
159     }
160     
161  
162   endService( "CALCULATOR::normMax");
163   return norme;
164 }
165
166 CORBA::Double CALCULATOR::normL1(SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field1)
167 {
168   beginService( "CALCULATOR::normL1");
169   _errorCode = CALCULATOR_ORB::NO_ERROR;
170
171   if(CORBA::is_nil(field1)) {
172     _errorCode = CALCULATOR_ORB::INVALID_FIELD;
173     return 0.0;
174   }
175
176   //Check that the Field is not on the Nodes (a limitation of normL1)
177   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> f1=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field1);
178   if (f1->getTypeOfField()==ParaMEDMEM::ON_NODES) {
179     _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
180     return 0.0;
181   }       
182         
183   CORBA::Double norme = 0.0;
184   try {
185     norme = f1->normL1(0);
186   }
187   catch(...) {
188     _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
189   }
190
191   endService( "CALCULATOR::normL1");
192   return norme;
193 }
194
195 SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr CALCULATOR::applyLin(SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field1,CORBA::Double a,CORBA::Double b)
196 {
197   beginService( "CALCULATOR::applyLin");
198   _errorCode = CALCULATOR_ORB::NO_ERROR;
199     
200   if(CORBA::is_nil(field1))
201     {
202       _errorCode = CALCULATOR_ORB::INVALID_FIELD;
203       return NULL;
204     }
205
206   // create a local field on the heap, because it has to remain after exiting the function
207   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> f1=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field1);
208   int nbOfCompo=f1->getArray()->getNumberOfComponents();
209   f1->getArray()->rearrange(1);
210   ParaMEDMEM::MEDCouplingFieldDoubleServant *NewField=NULL;
211   SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr myFieldIOR = NULL;
212
213   try
214     {
215       f1->applyLin(a,b,0);
216       f1->getArray()->rearrange(nbOfCompo);
217       // create servant from f1, give it the property of c++ field (parameter true).
218       // This imply that when the client will release it's field, it will delete NewField,
219       // and f1.
220       NewField = new ParaMEDMEM::MEDCouplingFieldDoubleServant(f1);
221       // activate object
222       myFieldIOR = NewField->_this() ;
223     }
224   catch(...)
225     {
226       _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
227     }
228   
229   endService( "CALCULATOR::applyLin");
230   return myFieldIOR;
231 }
232
233 SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr CALCULATOR::add(SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field1, SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field2) 
234 {
235   beginService( "CALCULATOR::add");
236   _errorCode = CALCULATOR_ORB::NO_ERROR;
237   //const char* LOC = "CALCULATOR::add(SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field1, SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field2)";
238
239   if(CORBA::is_nil(field1) || CORBA::is_nil(field2))
240     {
241       _errorCode = CALCULATOR_ORB::INVALID_FIELD;
242       return NULL;
243     }
244
245   // Create local fields from corba field
246   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> f1=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field1);
247   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> f2=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field2);
248     
249   // catch exception for non compatible fields
250   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble>  fres;
251   try
252     {
253       f2->changeUnderlyingMesh(f1->getMesh(),0,1e-12);
254       fres = (*f1)+(*f2);
255     }
256   catch(INTERP_KERNEL::Exception)
257     {
258       _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
259       return NULL;
260     }
261
262   // create CORBA field from c++ toField. give property to servant (true)
263   ParaMEDMEM::MEDCouplingFieldDoubleServant *myFieldDoubleI=new ParaMEDMEM::MEDCouplingFieldDoubleServant(fres);
264   SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr myFieldIOR = myFieldDoubleI->_this();
265   endService( "CALCULATOR::add");
266   return myFieldIOR;
267 }
268
269 void CALCULATOR::cloneField(SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field,
270                             SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_out clone1, SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_out clone2,
271                             SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_out clone3, SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_out clone4)
272 {
273   beginService( "CALCULATOR::cloneField");
274   _errorCode = CALCULATOR_ORB::NO_ERROR;
275
276   if(CORBA::is_nil(field))
277     {
278       _errorCode = CALCULATOR_ORB::INVALID_FIELD;
279       return;
280     }
281   
282   // load local field, using MED ressource file pointe.med
283   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> f=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field);
284
285   // create three c++ field on the heap by copying myField_
286   // All this fields share with f the same SUPPORT and MESH client.
287   // Both SUPPORT and MESH client are connected to a reference count, and will 
288   // be deleted after release of all the fields.
289   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> fc1=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field);
290   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> fc2=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field);
291   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> fc3=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field);
292   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> fc4=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field);
293     
294   // Initialize out references : 
295   // Create three CORBA clones with cloned c++ fields - give property of c++ fields to servant (true)
296   ParaMEDMEM::MEDCouplingFieldDoubleServant * myClone1 = new ParaMEDMEM::MEDCouplingFieldDoubleServant(fc1);
297   ParaMEDMEM::MEDCouplingFieldDoubleServant * myClone2 = new ParaMEDMEM::MEDCouplingFieldDoubleServant(fc2);
298   ParaMEDMEM::MEDCouplingFieldDoubleServant * myClone3 = new ParaMEDMEM::MEDCouplingFieldDoubleServant(fc3);
299   ParaMEDMEM::MEDCouplingFieldDoubleServant * myClone4 = new ParaMEDMEM::MEDCouplingFieldDoubleServant(fc4);
300   clone1 = myClone1->_this();
301   clone2 = myClone2->_this();
302   clone3 = myClone3->_this();
303   clone4 = myClone4->_this();
304   endService( "CALCULATOR::cloneField");
305   return;
306 }
307
308 void CALCULATOR::printField(SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field)
309 {
310   beginService( "CALCULATOR::printField");
311   _errorCode = CALCULATOR_ORB::NO_ERROR;
312
313   if(CORBA::is_nil(field))
314     {
315       _errorCode = CALCULATOR_ORB::INVALID_FIELD;
316       return;
317     }
318
319   // Create a local field from corba field.
320   // Use auto_ptr to perform automatic deletion after usage.
321   // The deletion of the FIELDClient will delete the remote Corba object.
322   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> myField=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field);
323   cout << myField->advancedRepr() ; 
324
325   cout << endl;
326   cout << "Norme euclidienne : " << myField->norm2() << endl;
327   cout << "Norme max         : " << myField->normMax() << endl;
328   cout << "------------------------------------------------------------------------" << endl << endl;
329   endService( "CALCULATOR::printField");
330   return;
331
332 }
333
334 CORBA::Double CALCULATOR::convergenceCriteria(SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field)
335 {
336   beginService( "CALCULATOR::convergenceCriteria");
337   _errorCode = CALCULATOR_ORB::NO_ERROR;
338
339   if(CORBA::is_nil(field))
340     {
341       _errorCode = CALCULATOR_ORB::INVALID_FIELD;
342       return 0.0;
343     }
344
345   double criteria=1;
346   static ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> fold(0);
347   ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble> fnew=ParaMEDMEM::MEDCouplingFieldDoubleClient::New(field);
348
349   try
350     {
351       if ((ParaMEDMEM::MEDCouplingFieldDouble*)fold == NULL) // if old field is not set, set it and return 1
352           fold=fnew;
353       else
354            {
355           // if size of fields are not equal, return 1
356               // catch exception for non compatible fields
357               ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr<ParaMEDMEM::MEDCouplingFieldDouble>  fres;
358               try
359                 {
360                    fnew->changeUnderlyingMesh(fold->getMesh(),0,1e-12);
361                    fres = (*fnew)-(*fold);
362                    criteria = fres->normMax();
363                 }
364               catch(INTERP_KERNEL::Exception)
365                 {
366                    _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
367                 }
368            }
369     }
370   catch(...)
371     {
372       _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
373     }
374   
375   endService( "CALCULATOR::convergenceCriteria");
376   return criteria;
377 }
378
379 CORBA::Boolean CALCULATOR::isDone()
380 {
381   return (_errorCode == CALCULATOR_ORB::NO_ERROR);                
382 }
383
384 CALCULATOR_ORB::ErrorCode CALCULATOR::getErrorCode()
385 {
386   return _errorCode;
387 }
388
389
390 //=============================================================================
391 /*!
392  *  CALCULATOREngine_factory
393  *
394  *  C factory, accessible with dlsym, after dlopen
395  */
396 //=============================================================================
397
398 extern "C"
399 {
400   PortableServer::ObjectId * CALCULATOREngine_factory (CORBA::ORB_ptr orb,
401                                                        PortableServer::POA_ptr poa,
402                                                        PortableServer::ObjectId * contId,
403                                                        const char *instanceName,
404                                                        const char *interfaceName)
405   {
406     CALCULATOR * myCALCULATOR = new CALCULATOR (orb, poa, contId, instanceName, interfaceName);
407     return myCALCULATOR->getId();
408   }
409 }
410