Salome HOME
Added methods getErrorCode and isDone. Changed the error treatment. Now in the case...
[samples/calculator.git] / src / CALCULATOR / CALCULATOR.cxx
1 // Copyright (C) 2005  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.
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 #include "CALCULATOR.hxx"
20 #include "FIELDClient.hxx"
21 #include "MESHClient.hxx"
22 #include <string>
23 #include <strstream>
24 #include "MEDMEM_Mesh_i.hxx"
25 #include "MEDMEM_Support_i.hxx"
26 #include "MEDMEM_FieldTemplate_i.hxx"
27 #include <iomanip>
28 #include <cmath>
29 using namespace std;
30 using namespace MEDMEM;
31
32 typedef FIELD<double,MEDMEM::FullInterlace> TFieldDouble;
33 typedef FIELDClient<double,MEDMEM::FullInterlace> TFieldDouble_c;
34 typedef FIELDTEMPLATE_I<double,MEDMEM::FullInterlace> TFieldDouble_i;
35
36 CALCULATOR::CALCULATOR(CORBA::ORB_ptr orb,
37         PortableServer::POA_ptr poa,
38         PortableServer::ObjectId * contId, 
39         const char *instanceName, 
40         const char *interfaceName) :
41   Engines_Component_i(orb, poa, contId, instanceName, interfaceName,true)
42 {
43   MESSAGE("activate object");
44   _thisObj = this ;
45   _id = _poa->activate_object(_thisObj);
46
47   _errorCode = CALCULATOR_ORB::NO_ERROR;
48 }
49
50 CALCULATOR::~CALCULATOR()
51 {
52 }
53
54 CORBA::Double CALCULATOR::norm2(SALOME_MED::FIELDDOUBLE_ptr field1)
55 {
56     beginService( "CALCULATOR::norm2");
57         _errorCode = CALCULATOR_ORB::NO_ERROR;
58     BEGIN_OF("CALCULATOR::Norm2(SALOME_MED::FIELDDOUBLE_ptr field1)");
59         
60         if(CORBA::is_nil(field1)) {
61                 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
62                 return 0.0;
63         }
64
65         CORBA::Double norme = 0.0;
66         // Create a local field from corba field, apply method normMax on it.
67         // When exiting the function, f1 is deleted, and with it the remote corba field.
68         TFieldDouble_c f1(field1);
69         
70         try {
71                 norme = f1.norm2();
72         }
73         catch(...) {
74           _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
75         }
76
77         END_OF("CALCULATOR::Norm2(SALOME_MED::FIELDDOUBLE_ptr field1)");
78     endService( "CALCULATOR::norm2");
79     return norme;
80 }
81
82 CORBA::Double CALCULATOR::normL2(SALOME_MED::FIELDDOUBLE_ptr field1)
83 {
84     beginService( "CALCULATOR::normL2");
85         _errorCode = CALCULATOR_ORB::NO_ERROR;
86         BEGIN_OF("CALCULATOR::NormL2(SALOME_MED::FIELDDOUBLE_ptr field1)");
87
88         if(CORBA::is_nil(field1)) {
89                 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
90                 return 0.0;
91         }
92
93     //Check that the Field is not on the Nodes (a limitation of normL2)
94         SALOME_MED::SUPPORT_var aSupport = field1->getSupport();
95         if(CORBA::is_nil(aSupport) || aSupport->getEntity() == SALOME_MED::MED_NODE) {
96            _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
97            return 0.0;
98         }
99
100     // Create a local field (on the stack) from corba field, apply method normMax on it.
101     // When exiting the function, FIELDClient f1 is deleted, and with it the remote corba field.
102     TFieldDouble_c  f1(field1);
103         
104     CORBA::Double norme = 0.0;
105         try {
106                 norme = f1.normL2();
107         }       
108         catch(...) {
109           _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
110         }
111     
112         // Send a notification message to supervision
113     ostringstream message("CALCULATOR::normL2 : ");
114     message << norme;
115     sendMessage("warning",message.str().c_str());
116     END_OF("CALCULATOR::NormL2(SALOME_MED::FIELDDOUBLE_ptr field1)");
117     endService( "CALCULATOR::normL2");
118     return norme;
119 }
120
121 CORBA::Double CALCULATOR::normMax(SALOME_MED::FIELDDOUBLE_ptr field1)
122 {
123     beginService( "CALCULATOR::normMax");
124         _errorCode = CALCULATOR_ORB::NO_ERROR;
125     BEGIN_OF("CALCULATOR::NormMax(SALOME_MED::FIELDDOUBLE_ptr field1)");
126         
127         if(CORBA::is_nil(field1)) {
128                 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
129                 return 0.0;
130         }
131
132         CORBA::Double norme = 0.0;
133         // An other way to do it : create an local field on the heap, inside an auto_ptr.
134         // When exiting the function, auto_ptr is deleted, and with it the local field and 
135         // the remote field if ownership was transferred.
136         auto_ptr<TFieldDouble> f1 (new TFieldDouble_c(field1) );
137
138         try {
139                 norme = f1->normMax();
140         }
141         catch(...) {
142           _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
143         }
144     
145         END_OF("CALCULATOR::NormMax(SALOME_MED::FIELDDOUBLE_ptr field1)");
146     endService( "CALCULATOR::normMax");
147     return norme;
148 }
149
150 CORBA::Double CALCULATOR::normL1(SALOME_MED::FIELDDOUBLE_ptr field1)
151 {
152     beginService( "CALCULATOR::normL1");
153         _errorCode = CALCULATOR_ORB::NO_ERROR;
154     BEGIN_OF("CALCULATOR::NormL1(SALOME_MED::FIELDDOUBLE_ptr field1)");
155
156         if(CORBA::is_nil(field1)) {
157                 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
158                 return 0.0;
159         }
160
161         //Check that the Field is not on the Nodes (a limitation of normL1)
162         SALOME_MED::SUPPORT_var aSupport = field1->getSupport();
163
164         if(CORBA::is_nil(aSupport) || aSupport->getEntity() == SALOME_MED::MED_NODE) {
165            _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
166            return 0.0;
167         }       
168         
169         CORBA::Double norme = 0.0;
170         auto_ptr<TFieldDouble> f1 (new TFieldDouble_c(field1) );
171
172         try {
173                 norme = f1->normL1();
174         }
175         catch(...) {
176           _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
177         }
178
179     END_OF("CALCULATOR::Norm2(SALOME_MED::FIELDDOUBLE_ptr field1)");
180     endService( "CALCULATOR::normL1");
181     return norme;
182 }
183
184
185 SALOME_MED::FIELDDOUBLE_ptr CALCULATOR::applyLin(SALOME_MED::FIELDDOUBLE_ptr field1,CORBA::Double a,CORBA::Double b)
186 {
187     beginService( "CALCULATOR::applyLin");
188         _errorCode = CALCULATOR_ORB::NO_ERROR;
189     BEGIN_OF("applyLin(SALOME_MED::FIELDDOUBLE_ptr field1,CORBA::Double a,CORBA::Double b)");
190     
191         if(CORBA::is_nil(field1)) {
192                 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
193                 return NULL;
194         }
195
196         SALOME_MED::FIELDDOUBLE_ptr myFieldIOR = NULL;
197         // create a local field on the heap, because it has to remain after exiting the function
198         TFieldDouble * f1 = new TFieldDouble_c(field1);
199         TFieldDouble_i * NewField = NULL;
200
201         try {
202                 f1->applyLin(a,b);
203                 // create servant from f1, give it the property of c++ field (parameter true).
204                 // This imply that when the client will release it's field, it will delete NewField,
205                 // and f1.
206                 NewField = new TFieldDouble_i(f1,true) ;
207                 // activate object
208                 myFieldIOR = NewField->_this() ;
209         }
210         catch(...) {
211           _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
212         }
213
214     END_OF("applyLin(SALOME_MED::FIELDDOUBLE_ptr field1,CORBA::Double a,CORBA::Double b)");
215     endService( "CALCULATOR::applyLin");
216     return myFieldIOR;
217 }
218
219 SALOME_MED::FIELDDOUBLE_ptr CALCULATOR::add(SALOME_MED::FIELDDOUBLE_ptr field1, SALOME_MED::FIELDDOUBLE_ptr field2) 
220 {
221     beginService( "CALCULATOR::add");
222         _errorCode = CALCULATOR_ORB::NO_ERROR;
223     BEGIN_OF("CALCULATOR::add(SALOME_MED::FIELDDOUBLE_ptr field1, SALOME_MED::FIELDDOUBLE_ptr field2)");
224
225         if(CORBA::is_nil(field1) || CORBA::is_nil(field2)) {
226                 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
227                 return NULL;
228         }
229
230     // Create local fields from corba field
231     TFieldDouble_c f1(field1);
232     TFieldDouble_c f2(field2);
233
234     // Create new c++ field on the heap by copying f1, add f2 to it.
235     TFieldDouble* fres = new TFieldDouble(f1);
236     
237         // catch exception for non compatible fields
238     try
239     {
240         *fres+=f2;
241     }
242     catch(MEDEXCEPTION)
243     {
244                  _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
245                  return NULL;
246     }
247
248     // create CORBA field from c++ toField. give property to servant (true)
249     TFieldDouble_i * myFieldDoubleI = new TFieldDouble_i(fres,true);
250     SALOME_MED::FIELDDOUBLE_ptr myFieldIOR = myFieldDoubleI->_this() ;
251
252     END_OF("CALCULATOR::add(SALOME_MED::FIELDDOUBLE_ptr field1, SALOME_MED::FIELDDOUBLE_ptr field2)");
253     endService( "CALCULATOR::add");
254     return myFieldIOR;
255 }
256
257 void CALCULATOR::cloneField(SALOME_MED::FIELDDOUBLE_ptr field,
258                 SALOME_MED::FIELDDOUBLE_out clone1, SALOME_MED::FIELDDOUBLE_out clone2,
259                 SALOME_MED::FIELDDOUBLE_out clone3, SALOME_MED::FIELDDOUBLE_out clone4)
260 {
261     beginService( "CALCULATOR::cloneField");
262         _errorCode = CALCULATOR_ORB::NO_ERROR;
263     BEGIN_OF("CALCULATOR::cloneField");
264
265         if(CORBA::is_nil(field)) {
266                 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
267                 return;
268         }
269
270     // load local field, using MED ressource file pointe.med
271     TFieldDouble_c f(field);
272
273     // create three c++ field on the heap by copying myField_
274     // All this fields share with f the same SUPPORT and MESH client.
275     // Both SUPPORT and MESH client are connected to a reference count, and will 
276     // be deleted after release of all the fields.
277     TFieldDouble* fc1 = new TFieldDouble(f);
278     TFieldDouble* fc2 = new TFieldDouble(f);
279     TFieldDouble* fc3 = new TFieldDouble(f);
280     TFieldDouble* fc4 = new TFieldDouble(f);
281     
282     // Initialize out references : 
283     // Create three CORBA clones with cloned c++ fields - give property of c++ fields to servant (true)
284     TFieldDouble_i * myClone1 = new TFieldDouble_i(fc1, true);
285     TFieldDouble_i * myClone2 = new TFieldDouble_i(fc2, true);
286     TFieldDouble_i * myClone3 = new TFieldDouble_i(fc3, true);
287     TFieldDouble_i * myClone4 = new TFieldDouble_i(fc4, true);
288     clone1 = myClone1->_this();
289     clone2 = myClone2->_this();
290     clone3 = myClone3->_this();
291     clone4 = myClone4->_this();
292     END_OF("CALCULATOR::cloneField");
293     endService( "CALCULATOR::cloneField");
294     return;
295 }
296
297 void CALCULATOR::printField(SALOME_MED::FIELDDOUBLE_ptr field)
298 {
299     beginService( "CALCULATOR::printField");
300     _errorCode = CALCULATOR_ORB::NO_ERROR;
301
302         if(CORBA::is_nil(field)) {
303                 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
304                 return;
305         }
306
307     // Create a local field from corba field.
308     // Use auto_ptr to perform automatic deletion after usage.
309     // The deletion of the FIELDClient will delete the remote Corba object.
310     auto_ptr<TFieldDouble> myField (new TFieldDouble_c(field) );
311
312     const SUPPORT * mySupport = myField->getSupport();
313     cout << "\n------------------ Field "<< myField->getName() << " : " <<myField->getDescription() << "------------------" <<  endl ;
314     int NumberOfComponents = myField->getNumberOfComponents() ;
315     cout << "- Type : " << mySupport->getEntity() << endl;
316     cout << "- Nombre de composantes : "<< NumberOfComponents << endl ;
317     cout << "- Nombre de valeurs     : "<< myField->getNumberOfValues() << endl ;
318     for (int i=1; i<NumberOfComponents+1; i++) {
319         cout << "  - composante "<<i<<" :"<<endl ;
320         cout << "      - nom         : "<<myField->getComponentName(i)<< endl;
321         cout << "      - description : "<<myField->getComponentDescription(i) << endl;
322         cout << "      - units       : "<<myField->getMEDComponentUnit(i) << endl;
323     }
324     cout << "- iteration :" << endl ;
325     cout << "    - numero : " << myField->getIterationNumber()<< endl  ;
326     cout << "    - ordre  : " << myField->getOrderNumber()<< endl  ;
327     cout << "    - temps  : " << myField->getTime()<< endl  ;
328     cout << "- Type : " << myField->getValueType()<< endl;
329     
330     cout << "- Valeurs :"<<endl;
331     int NumberOf = mySupport->getNumberOfElements(MED_ALL_ELEMENTS);
332
333     bool displayNode = mySupport->isOnAllElements() && mySupport->getEntity()==MED_NODE;
334     bool displayBary = mySupport->isOnAllElements() && mySupport->getEntity()==MED_CELL;
335     int dim_space = mySupport->getMesh()->getSpaceDimension();
336     const double * coord = mySupport->getMesh()->getCoordinates(MED_FULL_INTERLACE);
337
338     auto_ptr<TFieldDouble> barycenter(0);
339     if(displayBary)
340         barycenter=auto_ptr<TFieldDouble>(mySupport->getMesh()->getBarycenter(mySupport)) ;
341
342     const int width=10;
343     for (int i=1; i<NumberOf+1; i++) {
344         const double * value = myField->getRow(i) ;
345         if(displayNode)
346         {
347             int N=(i-1)*dim_space;
348             cout << setw(width) << i << setw(width) << coord[N] << " " << setw(width) << coord[N+1]<<  " " << setw(width) << coord[N+2] << "  : " ;
349         }
350         if(displayBary)
351             cout << setw(width) << i << setw(width) << barycenter->getValueIJ(i,1) << " " << setw(width) << barycenter->getValueIJ(i,2) 
352                  <<  " " << setw(width) << barycenter->getValueIJ(i,3) << "  : " ;
353         for (int j=0; j<NumberOfComponents; j++)
354             cout << value[j]<< " ";
355         cout<<endl;
356     }
357     cout << endl;
358     cout << "Norme euclidienne : " << myField->norm2() << endl;
359     cout << "Norme max         : " << myField->normMax() << endl;
360     cout << "------------------------------------------------------------------------" << endl << endl;
361     endService( "CALCULATOR::printField");
362     return;
363
364 }
365
366 CORBA::Double CALCULATOR::convergenceCriteria(SALOME_MED::FIELDDOUBLE_ptr field)
367 {
368     beginService( "CALCULATOR::convergenceCriteria");
369         _errorCode = CALCULATOR_ORB::NO_ERROR;
370     BEGIN_OF("CALCULATOR::convergenceCriteria(SALOME_MED::FIELDDOUBLE_ptr field)");
371
372         if(CORBA::is_nil(field)) {
373                 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
374                 return 0.0;
375         }
376
377     double criteria=1;
378         static auto_ptr<TFieldDouble> fold(0);
379         auto_ptr<TFieldDouble> fnew (new TFieldDouble_c(field) );
380
381         try {
382                 if (fold.get() == NULL) // if old field is not set, set it and return 1
383                 fold=fnew;
384                 else
385                 {
386                 // if size of fields are not equal, return 1
387                 const int size=fold->getNumberOfValues()*fold->getNumberOfComponents();
388                 if ( size == fnew->getNumberOfValues()*fnew->getNumberOfComponents() )
389                 {
390                         //MED_EN::medModeSwitch mode=fold->getInterlacingType(); // storage mode
391                         const double* oldVal= fold->getValue(); // retrieve values
392                         const double* newVal= fnew->getValue();
393                         criteria=0.0;
394                         double ecart_rel=0.0;
395                         for (unsigned i=0; i!=size; ++i) // compute criteria
396                         {
397                         if ( oldVal[i] != 0.0)
398                         {
399                             ecart_rel = std::abs( (oldVal[i]-newVal[i])/oldVal[i] );
400                                 if ( ecart_rel>criteria )
401                                 criteria=ecart_rel;
402                         }
403                         }
404                 }
405                 }
406         }
407         catch(...) {
408           _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
409         }
410
411     endService( "CALCULATOR::convergenceCriteria");
412     END_OF("CALCULATOR::convergenceCriteria(SALOME_MED::FIELDDOUBLE_ptr field1)");
413     return criteria;
414 }
415
416 CORBA::Boolean CALCULATOR::isDone()
417 {
418         return (_errorCode == CALCULATOR_ORB::NO_ERROR);                
419 }
420
421 CALCULATOR_ORB::ErrorCode CALCULATOR::getErrorCode()
422 {
423         return _errorCode;
424 }
425
426
427 extern "C"
428 {
429   PortableServer::ObjectId * CALCULATOREngine_factory(
430                                CORBA::ORB_ptr orb,
431                                PortableServer::POA_ptr poa, 
432                                PortableServer::ObjectId * contId,
433                                const char *instanceName, 
434                                const char *interfaceName)
435   {
436     MESSAGE("PortableServer::ObjectId * CALCULATOREngine_factory()");
437     SCRUTE(interfaceName);
438     CALCULATOR * myCALCULATOR 
439       = new CALCULATOR(orb, poa, contId, instanceName, interfaceName);
440     return myCALCULATOR->getId() ;
441   }
442 }