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