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