Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[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
48 CALCULATOR::~CALCULATOR()
49 {
50 }
51
52 CORBA::Double CALCULATOR::norm2(SALOME_MED::FIELDDOUBLE_ptr field1)
53 {
54     beginService( "CALCULATOR::norm2");
55     BEGIN_OF("CALCULATOR::Norm2(SALOME_MED::FIELDDOUBLE_ptr field1)");
56     // Create a local field from corba field, apply method normMax on it.
57     // When exiting the function, f1 is deleted, and with it the remote corba field.
58     TFieldDouble_c f1(field1);
59     CORBA::Double norme = f1.norm2();
60     END_OF("CALCULATOR::Norm2(SALOME_MED::FIELDDOUBLE_ptr field1)");
61     endService( "CALCULATOR::norm2");
62     return norme;
63 }
64
65 CORBA::Double CALCULATOR::normL2(SALOME_MED::FIELDDOUBLE_ptr field1)
66 {
67     beginService( "CALCULATOR::normL2");
68     BEGIN_OF("CALCULATOR::NormL2(SALOME_MED::FIELDDOUBLE_ptr field1)");
69
70     // Create a local field (on the stack) from corba field, apply method normMax on it.
71     // When exiting the function, FIELDClient f1 is deleted, and with it the remote corba field.
72     TFieldDouble_c  f1(field1);
73     CORBA::Double norme = f1.normL2();
74     // Send a notification message to supervision
75     ostringstream message("CALCULATOR::normL2 : ");
76     message << norme;
77     sendMessage("warning",message.str().c_str());
78     END_OF("CALCULATOR::NormL2(SALOME_MED::FIELDDOUBLE_ptr field1)");
79     endService( "CALCULATOR::normL2");
80     return norme;
81 }
82
83 CORBA::Double CALCULATOR::normMax(SALOME_MED::FIELDDOUBLE_ptr field1)
84 {
85     beginService( "CALCULATOR::normMax");
86     BEGIN_OF("CALCULATOR::NormMax(SALOME_MED::FIELDDOUBLE_ptr field1)");
87     // An other way to do it : create an local field on the heap, inside an auto_ptr.
88     // When exiting the function, auto_ptr is deleted, and with it the local field and 
89     // the remote field if ownership was transferred.
90     auto_ptr<TFieldDouble> f1 (new TFieldDouble_c(field1) );
91     CORBA::Double norme = f1->normMax();
92     END_OF("CALCULATOR::NormMax(SALOME_MED::FIELDDOUBLE_ptr field1)");
93     endService( "CALCULATOR::normMax");
94     return norme;
95 }
96
97 CORBA::Double CALCULATOR::normL1(SALOME_MED::FIELDDOUBLE_ptr field1)
98 {
99     beginService( "CALCULATOR::normL1");
100     BEGIN_OF("CALCULATOR::NormL1(SALOME_MED::FIELDDOUBLE_ptr field1)");
101     auto_ptr<TFieldDouble> f1 (new TFieldDouble_c(field1) );
102     CORBA::Double norme = f1->normL1();
103     END_OF("CALCULATOR::Norm2(SALOME_MED::FIELDDOUBLE_ptr field1)");
104     endService( "CALCULATOR::normL1");
105     return norme;
106 }
107
108
109 SALOME_MED::FIELDDOUBLE_ptr CALCULATOR::applyLin(SALOME_MED::FIELDDOUBLE_ptr field1,CORBA::Double a,CORBA::Double b)
110 {
111     beginService( "CALCULATOR::applyLin");
112     BEGIN_OF("applyLin(SALOME_MED::FIELDDOUBLE_ptr field1,CORBA::Double a,CORBA::Double b)");
113     // create a local field on the heap, because it has to remain after exiting the function
114     TFieldDouble * f1 = new TFieldDouble_c(field1);
115     f1->applyLin(a,b);
116     
117     // create servant from f1, give it the property of c++ field (parameter true).
118     // This imply that when the client will release it's field, it will delete NewField,
119     // and f1.
120     TFieldDouble_i * NewField = new TFieldDouble_i(f1,true) ;
121     // activate object
122     SALOME_MED::FIELDDOUBLE_ptr myFieldIOR = NewField->_this() ;
123
124     END_OF("applyLin(SALOME_MED::FIELDDOUBLE_ptr field1,CORBA::Double a,CORBA::Double b)");
125     endService( "CALCULATOR::applyLin");
126     return myFieldIOR;
127 }
128
129 SALOME_MED::FIELDDOUBLE_ptr CALCULATOR::add(SALOME_MED::FIELDDOUBLE_ptr field1, SALOME_MED::FIELDDOUBLE_ptr field2) 
130     throw ( SALOME::SALOME_Exception )
131 {
132     beginService( "CALCULATOR::add");
133     BEGIN_OF("CALCULATOR::add(SALOME_MED::FIELDDOUBLE_ptr field1, SALOME_MED::FIELDDOUBLE_ptr field2)");
134     // Create local fields from corba field
135     TFieldDouble_c f1(field1);
136     TFieldDouble_c f2(field2);
137
138     // Create new c++ field on the heap by copying f1, add f2 to it.
139     TFieldDouble* fres = new TFieldDouble(f1);
140     // catch exception for non compatible fields
141     try
142     {
143         *fres+=f2;
144     }
145     catch(MEDEXCEPTION)
146     {
147         throw(SALOME_Exception(LOCALIZED("Fields are not compatible")));
148     }
149     // create CORBA field from c++ toField. give property to servant (true)
150     TFieldDouble_i * myFieldDoubleI = new TFieldDouble_i(fres,true);
151     SALOME_MED::FIELDDOUBLE_ptr myFieldIOR = myFieldDoubleI->_this() ;
152
153     END_OF("CALCULATOR::add(SALOME_MED::FIELDDOUBLE_ptr field1, SALOME_MED::FIELDDOUBLE_ptr field2)");
154     endService( "CALCULATOR::add");
155     return myFieldIOR;
156 }
157
158 void CALCULATOR::cloneField(SALOME_MED::FIELDDOUBLE_ptr field,
159                 SALOME_MED::FIELDDOUBLE_out clone1, SALOME_MED::FIELDDOUBLE_out clone2,
160                 SALOME_MED::FIELDDOUBLE_out clone3, SALOME_MED::FIELDDOUBLE_out clone4)
161 {
162     beginService( "CALCULATOR::cloneField");
163     BEGIN_OF("CALCULATOR::cloneField");
164
165     // load local field, using MED ressource file pointe.med
166     TFieldDouble_c f(field);
167
168     // create three c++ field on the heap by copying myField_
169     // All this fields share with f the same SUPPORT and MESH client.
170     // Both SUPPORT and MESH client are connected to a reference count, and will 
171     // be deleted after release of all the fields.
172     TFieldDouble* fc1 = new TFieldDouble(f);
173     TFieldDouble* fc2 = new TFieldDouble(f);
174     TFieldDouble* fc3 = new TFieldDouble(f);
175     TFieldDouble* fc4 = new TFieldDouble(f);
176     
177     // Initialize out references : 
178     // Create three CORBA clones with cloned c++ fields - give property of c++ fields to servant (true)
179     TFieldDouble_i * myClone1 = new TFieldDouble_i(fc1, true);
180     TFieldDouble_i * myClone2 = new TFieldDouble_i(fc2, true);
181     TFieldDouble_i * myClone3 = new TFieldDouble_i(fc3, true);
182     TFieldDouble_i * myClone4 = new TFieldDouble_i(fc4, true);
183     clone1 = myClone1->_this();
184     clone2 = myClone2->_this();
185     clone3 = myClone3->_this();
186     clone4 = myClone4->_this();
187     END_OF("CALCULATOR::cloneField");
188     endService( "CALCULATOR::cloneField");
189     return;
190 }
191
192 void CALCULATOR::printField(SALOME_MED::FIELDDOUBLE_ptr field)
193 {
194     beginService( "CALCULATOR::printField");
195     
196     // Create a local field from corba field.
197     // Use auto_ptr to perform automatic deletion after usage.
198     // The deletion of the FIELDClient will delete the remote Corba object.
199     auto_ptr<TFieldDouble> myField (new TFieldDouble_c(field) );
200
201     const SUPPORT * mySupport = myField->getSupport();
202     cout << "\n------------------ Field "<< myField->getName() << " : " <<myField->getDescription() << "------------------" <<  endl ;
203     int NumberOfComponents = myField->getNumberOfComponents() ;
204     cout << "- Type : " << mySupport->getEntity() << endl;
205     cout << "- Nombre de composantes : "<< NumberOfComponents << endl ;
206     cout << "- Nombre de valeurs     : "<< myField->getNumberOfValues() << endl ;
207     for (int i=1; i<NumberOfComponents+1; i++) {
208         cout << "  - composante "<<i<<" :"<<endl ;
209         cout << "      - nom         : "<<myField->getComponentName(i)<< endl;
210         cout << "      - description : "<<myField->getComponentDescription(i) << endl;
211         cout << "      - units       : "<<myField->getMEDComponentUnit(i) << endl;
212     }
213     cout << "- iteration :" << endl ;
214     cout << "    - numero : " << myField->getIterationNumber()<< endl  ;
215     cout << "    - ordre  : " << myField->getOrderNumber()<< endl  ;
216     cout << "    - temps  : " << myField->getTime()<< endl  ;
217     cout << "- Type : " << myField->getValueType()<< endl;
218     
219     cout << "- Valeurs :"<<endl;
220     int NumberOf = mySupport->getNumberOfElements(MED_ALL_ELEMENTS);
221
222     bool displayNode = mySupport->isOnAllElements() && mySupport->getEntity()==MED_NODE;
223     bool displayBary = mySupport->isOnAllElements() && mySupport->getEntity()==MED_CELL;
224     int dim_space = mySupport->getMesh()->getSpaceDimension();
225     const double * coord = mySupport->getMesh()->getCoordinates(MED_FULL_INTERLACE);
226
227     auto_ptr<TFieldDouble> barycenter(0);
228     if(displayBary)
229         barycenter=auto_ptr<TFieldDouble>(mySupport->getMesh()->getBarycenter(mySupport)) ;
230
231     const int width=10;
232     for (int i=1; i<NumberOf+1; i++) {
233         const double * value = myField->getRow(i) ;
234         if(displayNode)
235         {
236             int N=(i-1)*dim_space;
237             cout << setw(width) << i << setw(width) << coord[N] << " " << setw(width) << coord[N+1]<<  " " << setw(width) << coord[N+2] << "  : " ;
238         }
239         if(displayBary)
240             cout << setw(width) << i << setw(width) << barycenter->getValueIJ(i,1) << " " << setw(width) << barycenter->getValueIJ(i,2) 
241                  <<  " " << setw(width) << barycenter->getValueIJ(i,3) << "  : " ;
242         for (int j=0; j<NumberOfComponents; j++)
243             cout << value[j]<< " ";
244         cout<<endl;
245     }
246     cout << endl;
247     cout << "Norme euclidienne : " << myField->norm2() << endl;
248     cout << "Norme max         : " << myField->normMax() << endl;
249     cout << "------------------------------------------------------------------------" << endl << endl;
250     endService( "CALCULATOR::printField");
251     return;
252
253 }
254
255 CORBA::Double CALCULATOR::convergenceCriteria(SALOME_MED::FIELDDOUBLE_ptr field)
256 {
257     beginService( "CALCULATOR::convergenceCriteria");
258     BEGIN_OF("CALCULATOR::convergenceCriteria(SALOME_MED::FIELDDOUBLE_ptr field)");
259
260     double criteria=1;
261     static auto_ptr<TFieldDouble> fold(0);
262     auto_ptr<TFieldDouble> fnew (new TFieldDouble_c(field) );
263     if (fold.get() == NULL) // if old field is not set, set it and return 1
264         fold=fnew;
265     else
266     {
267         // if size of fields are not equal, return 1
268         const int size=fold->getNumberOfValues()*fold->getNumberOfComponents();
269         if ( size == fnew->getNumberOfValues()*fnew->getNumberOfComponents() )
270         {
271             MED_EN::medModeSwitch mode=fold->getInterlacingType(); // storage mode
272             const double* oldVal= fold->getValue(); // retrieve values
273             const double* newVal= fnew->getValue();
274             criteria=0.0;
275             double ecart_rel=0.0;
276             for (unsigned i=0; i!=size; ++i) // compute criteria
277             {
278                 if ( oldVal[i] != 0.0)
279                 {
280                     ecart_rel = std::abs( (oldVal[i]-newVal[i])/oldVal[i] );
281                     if ( ecart_rel>criteria )
282                         criteria=ecart_rel;
283                 }
284             }
285
286         }
287     }
288
289     endService( "CALCULATOR::convergenceCriteria");
290     END_OF("CALCULATOR::convergenceCriteria(SALOME_MED::FIELDDOUBLE_ptr field1)");
291     return criteria;
292 }
293
294
295
296 extern "C"
297 {
298   PortableServer::ObjectId * CALCULATOREngine_factory(
299                                CORBA::ORB_ptr orb,
300                                PortableServer::POA_ptr poa, 
301                                PortableServer::ObjectId * contId,
302                                const char *instanceName, 
303                                const char *interfaceName)
304   {
305     MESSAGE("PortableServer::ObjectId * CALCULATOREngine_factory()");
306     SCRUTE(interfaceName);
307     CALCULATOR * myCALCULATOR 
308       = new CALCULATOR(orb, poa, contId, instanceName, interfaceName);
309     return myCALCULATOR->getId() ;
310   }
311 }