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