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