Salome HOME
aa768a765bcd7218aed7756d590ace5f22c00906
[samples/calculator.git] / src / CALCULATOR / CALCULATOR.cxx
1 // Copyright (C) 2007-2023  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 <MCAuto.hxx>
27 #include <MEDCouplingFieldDoubleClient.hxx>
28 #include <MEDCouplingFieldDoubleServant.hxx>
29 #include <MEDCouplingMemArray.hxx>
30 #include <MEDCouplingMeshClient.hxx>
31 #include <MEDCouplingMeshServant.hxx>
32
33 #include <iostream>
34
35 /*!
36   \brief Constructor
37   \param orb Reference to CORBA ORB 
38   \param poa Reference to Root POA
39   \param contId Parent SALOME container ID
40   \param instanceName Instance name of this engine
41   \param interfaceName Interface name of this engine
42 */
43 CALCULATOR_Abstract::CALCULATOR_Abstract( CORBA::ORB_ptr orb,
44                                           PortableServer::POA_ptr poa,
45                                           PortableServer::ObjectId* contId, 
46                                           const char* instanceName, 
47                                           const char* interfaceName,
48                                           bool withRegistry )
49   : Engines_Component_i( orb, poa, contId, instanceName, interfaceName, true, withRegistry ),
50     _errorCode( CALCULATOR_ORB::RES_OK )
51 {
52   _thisObj = this;
53   _id = _poa->activate_object( _thisObj );
54 }
55
56 /*!
57   \brief Destructor
58 */
59 CALCULATOR_Abstract::~CALCULATOR_Abstract()
60 {
61 }
62
63 /*!
64   \brief Get Euclidian norm of field
65   \param field Input field
66   \return Euclidian norm value
67 */
68 CORBA::Double CALCULATOR_Abstract::norm2( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field )
69 {
70   beginService( "CALCULATOR_Abstract::norm2" );
71   _errorCode = CALCULATOR_ORB::RES_OK;
72         
73   if ( CORBA::is_nil( field ) )
74   {
75     _errorCode = CALCULATOR_ORB::INVALID_FIELD;
76     return 0.0;
77   }
78
79   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f1 =
80     MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
81
82   CORBA::Double norme = 0.0;
83
84   try
85   {
86     norme = f1->norm2();
87   }    
88   catch (...)
89   {
90     _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
91   }
92   
93   endService( "CALCULATOR_Abstract::norm2" );
94   return norme;
95 }
96
97 /*!
98   \brief Get L2 norm of field
99   \param field Input field
100   \return L2 norm value
101 */
102 CORBA::Double CALCULATOR_Abstract::normL2( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field )
103 {
104   beginService( "CALCULATOR_Abstract::normL2" );
105   _errorCode = CALCULATOR_ORB::RES_OK;
106
107   if ( CORBA::is_nil( field ) )
108   {
109     _errorCode = CALCULATOR_ORB::INVALID_FIELD;
110     return 0.0;
111   }
112
113   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f1 =
114     MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
115   
116   // Check that the source field is not on the nodes (a limitation of normL2)
117   if ( f1->getTypeOfField() == MEDCoupling::ON_NODES)
118   {
119     _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
120     return 0.0;
121   }
122         
123   CORBA::Double norme = 0.0;
124
125   try
126   {
127     norme = f1->normL2( 0 );
128   }    
129   catch (...)
130   {
131     _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
132   }
133   
134   endService( "CALCULATOR_Abstract::normL2" );
135   return norme;
136 }
137
138 /*!
139   \brief Get max norm of field
140   \param field Input field
141   \return Max norm value
142 */
143 CORBA::Double CALCULATOR_Abstract::normMax( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field )
144 {
145   beginService( "CALCULATOR_Abstract::normMax" );
146   _errorCode = CALCULATOR_ORB::RES_OK;
147          
148   if ( CORBA::is_nil( field ) )
149   {
150     _errorCode = CALCULATOR_ORB::INVALID_FIELD;
151     return 0.0;
152   }
153   
154   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f1 =
155     MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
156
157   CORBA::Double norme = 0.0;
158
159   try
160   {
161     norme = f1->normMax( 0 );
162   }
163   catch (...)
164   {
165     _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
166   }
167  
168   endService( "CALCULATOR_Abstract::normMax" );
169   return norme;
170 }
171
172 /*!
173   \brief Get L1 norm of field
174   \param field Input field
175   \return L1 norm value
176 */
177 CORBA::Double CALCULATOR_Abstract::normL1( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field )
178 {
179   beginService( "CALCULATOR_Abstract::normL1" );
180   _errorCode = CALCULATOR_ORB::RES_OK;
181
182   if ( CORBA::is_nil( field ) )
183   {
184     _errorCode = CALCULATOR_ORB::INVALID_FIELD;
185     return 0.0;
186   }
187
188   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f1 =
189     MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
190
191   // Check that the source field is not on the nodes (a limitation of normL1)
192   if ( f1->getTypeOfField() == MEDCoupling::ON_NODES ) {
193     _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
194     return 0.0;
195   }       
196   
197   CORBA::Double norme = 0.0;
198   try
199   {
200     norme = f1->normL1( 0 );
201   }
202   catch (...)
203   {
204     _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
205   }
206
207   endService( "CALCULATOR_Abstract::normL1" );
208   return norme;
209 }
210
211 /*!
212   \brief Apply to each (scalar) field component the linear function x -> ax+b
213   \param field Input field
214   \param a First coefficient of linear function
215   \param b Second coefficient of linear function
216   \return Resulting field
217 */
218 SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr
219 CALCULATOR_Abstract::applyLin( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field,
220                                CORBA::Double a, CORBA::Double b )
221 {
222   beginService( "CALCULATOR_Abstract::applyLin" );
223   _errorCode = CALCULATOR_ORB::RES_OK;
224     
225   if ( CORBA::is_nil( field ) )
226   {
227     _errorCode = CALCULATOR_ORB::INVALID_FIELD;
228     return NULL;
229   }
230
231   // Create a local field on the heap, because it has to remain after exiting the function
232   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f1 =
233     MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
234
235   int nbOfCompo = f1->getArray()->getNumberOfComponents();
236   f1->getArray()->rearrange(1);
237   MEDCoupling::MEDCouplingFieldDoubleServant* NewField = NULL;
238   SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr myFieldIOR;
239
240   try
241   {
242     f1->applyLin( a, b, 0 );
243     f1->getArray()->rearrange( nbOfCompo );
244     // Create servant from f1, give it the property of c++ field (parameter true).
245     // This implies that when the client will release it's field, it will delete NewField,
246     // and f1 too.
247     NewField = new MEDCoupling::MEDCouplingFieldDoubleServant( f1 );
248     // Activate servant
249     myFieldIOR = NewField->_this();
250   }
251   catch (...)
252   {
253     _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
254   }
255   
256   endService( "CALCULATOR_Abstract::applyLin" );
257   return myFieldIOR;
258 }
259
260 /*!
261   \brief Sum two fields
262   \param field1 First input field
263   \param field2 Second input field
264   \return Resulting field
265 */
266 SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr
267 CALCULATOR_Abstract::add( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field1,
268                           SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field2 )
269 {
270   beginService( "CALCULATOR_Abstract::add" );
271   _errorCode = CALCULATOR_ORB::RES_OK;
272
273   if ( CORBA::is_nil( field1 ) || CORBA::is_nil( field2 ) )
274   {
275     _errorCode = CALCULATOR_ORB::INVALID_FIELD;
276     return NULL;
277   }
278   
279   // Create local fields from source corba fields
280   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f1 =
281     MEDCoupling::MEDCouplingFieldDoubleClient::New( field1 );
282   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f2 =
283     MEDCoupling::MEDCouplingFieldDoubleClient::New( field2 );
284     
285   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fres;
286   
287   try
288   {
289     f2->changeUnderlyingMesh( f1->getMesh(), 0, 1e-12 );
290     fres = (*f1) + (*f2);
291   }
292   catch ( INTERP_KERNEL::Exception )
293   {
294     _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
295     return NULL;
296   }
297
298   // Create CORBA field from c++ field fres; give property to servant (true).
299   MEDCoupling::MEDCouplingFieldDoubleServant* myFieldDoubleI = new MEDCoupling::MEDCouplingFieldDoubleServant( fres );
300   // Activate servant
301   SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr myFieldIOR = myFieldDoubleI->_this();
302
303   endService( "CALCULATOR_Abstract::add" );
304   return myFieldIOR;
305 }
306
307 /*!
308   \brief Clone source field into four copies
309   \param field Input field
310   \param clone1 First resulting clone field
311   \param clone2 Second resulting clone field
312   \param clone3 Third resulting clone field
313   \param clone4 Fourth resulting clone field
314 */
315 void CALCULATOR_Abstract::cloneField( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field,
316                                       SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_out clone1,
317                                       SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_out clone2,
318                                       SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_out clone3,
319                                       SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_out clone4 )
320 {
321   beginService( "CALCULATOR_Abstract::cloneField" );
322   _errorCode = CALCULATOR_ORB::RES_OK;
323
324   if ( CORBA::is_nil( field ) )
325   {
326     _errorCode = CALCULATOR_ORB::INVALID_FIELD;
327     return;
328   }
329   
330   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f =
331     MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
332
333   // Create four c++ fields on the heap by copying source field.
334   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fc1 =
335     MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
336   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fc2 =
337     MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
338   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fc3 =
339     MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
340   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fc4 =
341     MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
342     
343   // Initialize out references: 
344   // Create CORBA clones from c++ fields - give property of c++ fields to servant (true)
345   MEDCoupling::MEDCouplingFieldDoubleServant* myClone1 = new MEDCoupling::MEDCouplingFieldDoubleServant( fc1 );
346   MEDCoupling::MEDCouplingFieldDoubleServant* myClone2 = new MEDCoupling::MEDCouplingFieldDoubleServant( fc2 );
347   MEDCoupling::MEDCouplingFieldDoubleServant* myClone3 = new MEDCoupling::MEDCouplingFieldDoubleServant( fc3 );
348   MEDCoupling::MEDCouplingFieldDoubleServant* myClone4 = new MEDCoupling::MEDCouplingFieldDoubleServant( fc4 );
349   // Activate servants
350   clone1 = myClone1->_this();
351   clone2 = myClone2->_this();
352   clone3 = myClone3->_this();
353   clone4 = myClone4->_this();
354
355   endService( "CALCULATOR_Abstract::cloneField" );
356 }
357
358 /*!
359   \brief Print out the coordinates and field values to standard output
360   \param field Input field
361 */
362 void CALCULATOR_Abstract::printField( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field )
363 {
364   beginService( "CALCULATOR_Abstract::printField" );
365   _errorCode = CALCULATOR_ORB::RES_OK;
366
367   if ( CORBA::is_nil( field ) )
368   {
369     _errorCode = CALCULATOR_ORB::INVALID_FIELD;
370     return;
371   }
372
373   // Create a local field from source corba field.
374   // Use auto_ptr to perform automatic deletion after usage.
375   // The deletion of the client object will delete the remote corba object.
376   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> myField =
377     MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
378
379   std::cout << myField->advancedRepr(); 
380   std::cout << std::endl;
381   std::cout << "Euclidian norm: " << myField->norm2() << std::endl;
382   std::cout << "Max norm:       " << myField->normMax( 0 ) << std::endl;
383   std::cout << "------------------------------------------------------------------------" << std::endl << std::endl;
384
385   endService( "CALCULATOR_Abstract::printField" );
386 }
387
388 /*!
389   \brief Calculate maximum relative difference of field with the previous one
390   \param field Input field
391   \return Convergence criterion value
392 */
393 CORBA::Double CALCULATOR_Abstract::convergenceCriteria( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field )
394 {
395   beginService( "CALCULATOR_Abstract::convergenceCriteria" );
396   _errorCode = CALCULATOR_ORB::RES_OK;
397
398   if ( CORBA::is_nil( field ) )
399   {
400     _errorCode = CALCULATOR_ORB::INVALID_FIELD;
401     return 0.0;
402   }
403   
404   double criteria = 1;
405   static MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fold;
406   MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fnew =
407     MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
408
409   try
410   {
411     if ( (MEDCoupling::MEDCouplingFieldDouble*)fold == NULL )
412     {
413       // if old field is not set, set it and return 1
414       fold = fnew;
415     }
416     else
417     {
418       // if size of fields are not equal, return 1
419       // catch exception for non compatible fields
420       MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fres;
421       try
422       {
423         fnew->changeUnderlyingMesh( fold->getMesh(), 0, 1e-12 );
424         fres = (*fnew) - (*fold);
425         criteria = fres->normMax( 0 );
426       }
427       catch ( INTERP_KERNEL::Exception )
428       {
429         _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
430       }
431     }
432   }
433   catch (...)
434   {
435     _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
436   }
437   
438   endService( "CALCULATOR_Abstract::convergenceCriteria" );
439   return criteria;
440 }
441
442 /*!
443   \brief Get last operation status
444   \return Last operation status: \c true if last operation succeded or \c false otherwise
445 */
446 CORBA::Boolean CALCULATOR_Abstract::isDone()
447 {
448   return (_errorCode == CALCULATOR_ORB::RES_OK );
449 }
450
451 /*!
452   \brief Get last operation status
453   \return Last error code
454 */
455 CALCULATOR_ORB::ErrorCode CALCULATOR_Abstract::getErrorCode()
456 {
457   return _errorCode;
458 }
459
460 /*!
461   \brief Get version information
462   \return Version of CALCULATOR engine
463 */
464 char* CALCULATOR_Abstract::getVersion()
465 {
466 #if defined(CALCULATOR_DEVELOPMENT)
467   return CORBA::string_dup( CALCULATOR_VERSION_STR"dev" );
468 #else
469   return CORBA::string_dup( CALCULATOR_VERSION_STR );
470 #endif
471 }
472
473 extern "C"
474 {
475   CALCULATORENGINE_EXPORT
476   PortableServer::ObjectId* CALCULATOREngine_factory( CORBA::ORB_ptr orb,
477                                                       PortableServer::POA_ptr poa,
478                                                       PortableServer::ObjectId* contId,
479                                                       const char* instanceName,
480                                                       const char* interfaceName )
481   {
482     CORBA::Object_var o = poa->id_to_reference(*contId);
483     Engines::Container_var cont = Engines::Container::_narrow(o);
484     if (cont->is_SSL_mode())
485     {
486       CALCULATOR_No_Session* calc = new CALCULATOR_No_Session(orb, poa, contId, instanceName, interfaceName);
487       return calc->getId();
488     }
489     else
490     {
491       CALCULATOR_Session* calc = new CALCULATOR_Session( orb, poa, contId, instanceName, interfaceName );
492       return calc->getId();
493     }
494   }
495 }