Salome HOME
Merge from BR_V5_DEV 16Feb09
[modules/med.git] / src / MEDMEMCppTest / MEDMEMTest_Coordinate.cxx
1 //  Copyright (C) 2007-2008  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.
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 #include "MEDMEMTest.hxx"
23 #include <cppunit/Message.h>
24 #include <cppunit/TestAssert.h>
25
26 #include "MEDMEM_Array.hxx"
27 #include "MEDMEM_Coordinate.hxx"
28
29 #include <sstream>
30 #include <cmath>
31
32 // use this define to enable lines, execution of which leads to Segmentation Fault
33 //#define ENABLE_FAULTS
34
35 // use this define to enable CPPUNIT asserts and fails, showing bugs
36 //#define ENABLE_FORCED_FAILURES
37
38 using namespace std;
39 using namespace MEDMEM;
40
41 // #8: MEDMEM_Coordinate.hxx  }  MEDMEMTest_Coordinate.cxx
42
43 /*!
44  *  Check methods (23), defined in MEDMEM_Coordinate.hxx:
45  *  class COORDINATE {
46  *   (+)     COORDINATE();
47  *   (+)     COORDINATE(int SpaceDimension, int NumberOfNodes, MED_EN::medModeSwitch Mode);
48  *   (+)     COORDINATE(int SpaceDimension,const string * CoordinateName, const string * CoordinateUnit);
49  *   (+)     COORDINATE(const COORDINATE & m);
50  *   (+)     virtual ~COORDINATE();
51  *   (+)     void setCoordinates(MEDARRAY<double> *Coordinate,bool shallowCopy=false);
52  *   (+)     void setCoordinates(const MED_EN::medModeSwitch Mode, const double *Coordinate);
53  *   (+)     void setCoordinatesNames(const string * CoordinateName);
54  *   (+)     void setCoordinateName(const string CoordinateName, const int i);
55  *   (+)     void setCoordinatesUnits(const string * CoordinateUnit);
56  *   (+)     void setCoordinateUnit(const string CoordinateUnit, const int i);
57  *   (+)     void setCoordinatesSystem(const string CoordinateSystem);
58  *   (+)     void setNodesNumbers(const int * NodeNumber);
59  *   (+)     int  getSpaceDimension() const;
60  *   (+)     int  getNumberOfNodes() const;
61  *   (+)     virtual const int* getNodesNumbers() const;
62  *   (+)     string getCoordinatesSystem() const;
63  *   (+)     virtual const double * getCoordinates(MED_EN::medModeSwitch Mode);
64  *   (+)     virtual double         getCoordinate(int Number,int Axis);
65  *   (+)     virtual const double * getCoordinateAxis(int Axis);
66  *   (+)     const string * getCoordinatesNames() const;
67  *   (+)     string getCoordinateName(int Axis) const;
68  *   (+)     const string * getCoordinatesUnits() const;
69  *   (+)     string getCoordinateUnit(int Axis) const;
70  *  }
71  *
72  *  Use code of MEDMEM/tests/testUCoordinate.cxx
73  *              MEDMEM/test_copie_coordinate.cxx
74  */
75 void MEDMEMTest::testCoordinate()
76 {
77   //////////////////////////////////////////////
78   // TEST 1: MEDMEM/tests/testUCoordinate.cxx //
79   //////////////////////////////////////////////
80   {
81     const double pouieme = 0.009;
82
83     int SpaceDim = 3;
84     int NbOfNodes = 5;
85
86     string * noms = new string[3];
87     noms[0] = " X ";
88     noms[1] = " Y ";
89     noms[2] = " Z ";
90
91     string  units[3];
92     units[0] = " m ";
93     units[1] = " m ";
94     units[2] = " m ";
95
96     int * numbers = new int[5];
97     for (int i = 0; i < 5; i++) numbers[i] = 10 + i;
98
99     double coor[15] = {0,0,0,0,0,1,0,1,0,1,0,0,0.5,0.5,0.5};
100     CPPUNIT_ASSERT(SpaceDim * NbOfNodes == 15);
101
102     double * coor1 = new double [SpaceDim*NbOfNodes];
103     for (int k = 0; k < SpaceDim*NbOfNodes; k++)
104       coor1[k] = coor[k];
105
106     MEDARRAY<double>* CoordinateArray =
107       new MEDARRAY<double>(coor1, SpaceDim, NbOfNodes, MED_EN::MED_FULL_INTERLACE);
108     COORDINATE mycoo;
109     CPPUNIT_ASSERT_NO_THROW(mycoo.setCoordinates(CoordinateArray));
110
111     //--------------------------------------------------------------------//
112     //                        Tests des methodes                          //
113     //                                                                    //
114     // - setCoordinatesNames                                              //
115     // - setCoordinatesUnits                                              //
116     // - setCoordinatesSystem                                             //
117     // - setNodesNumbers                                                  //
118     //                                                                    //
119     //--------------------------------------------------------------------//
120
121     CPPUNIT_ASSERT_NO_THROW(mycoo.setCoordinatesNames(noms));
122     CPPUNIT_ASSERT_NO_THROW(mycoo.setCoordinatesUnits(units));
123     CPPUNIT_ASSERT_NO_THROW(mycoo.setCoordinatesSystem("cartesien"));
124     CPPUNIT_ASSERT_NO_THROW(mycoo.setNodesNumbers(numbers));
125
126     //--------------------------------------------------------------------//
127     //                        Tests des methodes                          //
128     //                                                                    //
129     // - getCoordinatesNames                                              //
130     // - getCoordinatesUnits                                              //
131     // - getCoordinatesUnit                                               //
132     // - getCoordinatesSystem                                             //
133     // - getNodesNumbers                                                  //
134     //                                                                    //
135     //--------------------------------------------------------------------//
136     CPPUNIT_ASSERT_NO_THROW(CPPUNIT_ASSERT(mycoo.getCoordinatesSystem() == "cartesien"));
137
138     const string * units2;
139     try
140     {
141       units2 = mycoo.getCoordinatesUnits();
142       for (int axe = 0; axe < SpaceDim; axe++) {
143         string verif = mycoo.getCoordinateUnit(axe+1);
144         CPPUNIT_ASSERT(verif == units2[axe]);
145       }
146     }
147     catch (const std::exception &e)
148     {
149       CPPUNIT_FAIL(e.what());
150     }
151     catch (...)
152     {
153       CPPUNIT_FAIL("Unknown exception");
154     }
155
156     const string * noms2;
157     try
158     {
159       noms2 = mycoo.getCoordinatesNames();
160       for (int axe = 0; axe < SpaceDim; axe++) {
161         string verif = mycoo.getCoordinateName(axe+1);
162         CPPUNIT_ASSERT(verif == noms2[axe]);
163       }
164     }
165     catch (const std::exception &e)
166     {
167       CPPUNIT_FAIL(e.what());
168     }
169     catch (...)
170     {
171       CPPUNIT_FAIL("Unknown exception");
172     }
173
174     try
175     {
176       const double * coor2 = mycoo.getCoordinates(MED_EN::MED_FULL_INTERLACE);
177
178       for (int axe = 0; axe < SpaceDim; axe++) {
179         const double * coor3 = mycoo.getCoordinateAxis(axe+1);
180         for (int num = 0; num < NbOfNodes; num++) {
181           const double d = mycoo.getCoordinate(num + 1, axe + 1);
182           CPPUNIT_ASSERT(fabs(d - coor3[num                 ]) < pouieme);
183           CPPUNIT_ASSERT(fabs(d - coor2[(num * SpaceDim)+axe]) < pouieme);
184           CPPUNIT_ASSERT(fabs(d - coor [(num * SpaceDim)+axe]) < pouieme);
185         }
186       }
187     }
188     catch (const std::exception &e)
189     {
190       CPPUNIT_FAIL(e.what());
191     }
192     catch (...)
193     {
194       CPPUNIT_FAIL("Unknown exception");
195     }
196
197     delete [] noms;
198     delete [] numbers;
199     delete [] coor1;
200
201     delete CoordinateArray;
202   }
203
204   //////////////////////////////////////////////
205   // TEST 2: MEDMEM/test_copie_coordinate.cxx //
206   //////////////////////////////////////////////
207   {
208     const int numberofNodes = 5;
209     const int spaceDimension = 3;
210     const MED_EN::medModeSwitch mode = MED_EN::MED_FULL_INTERLACE;
211
212     //construction tableau MEDARRAY des coordonnées
213     MEDARRAY<double> * myMedArray = new MEDARRAY<double>(spaceDimension, numberofNodes, mode);
214     for (int i = 1; i <= myMedArray->getLengthValue(); i++) {
215       for (int j = 1; j <= myMedArray->getLeadingValue(); j++)
216         myMedArray->setIJ(i, j, (double) i*j);
217     }
218
219     //construction noms des coordonnées
220     string * myCoordinatesNames = new string[spaceDimension];
221     if (spaceDimension >= 1) myCoordinatesNames[0] = "x";
222     if (spaceDimension >= 2) myCoordinatesNames[1] = "y";
223     if (spaceDimension >= 3) myCoordinatesNames[2] = "z";
224
225     //construction unités des coordonnées
226     string * myCoordinatesUnits = new string[spaceDimension];
227     if (spaceDimension >= 1) myCoordinatesUnits[0] = "m";
228     if (spaceDimension >= 2) myCoordinatesUnits[1] = "m";
229     if (spaceDimension >= 3) myCoordinatesUnits[2] = "m";
230
231     //construction des indices des noeuds
232     int * myNodeNumber = new int[numberofNodes];
233     for (int i = 0; i < numberofNodes; i++)
234       myNodeNumber[i] = numberofNodes - i - 1;
235
236     //construction de l'objet COORDINATE
237     COORDINATE * myCoordinate = new COORDINATE();
238     myCoordinate->setCoordinates(myMedArray);
239     myCoordinate->setCoordinatesNames(myCoordinatesNames);
240     myCoordinate->setCoordinatesUnits(myCoordinatesUnits);
241     myCoordinate->setNodesNumbers(myNodeNumber);
242
243     delete myMedArray;
244     delete[] myCoordinatesNames;
245     delete[] myCoordinatesUnits;
246     delete[] myNodeNumber;
247
248     COORDINATE * myCoordinate2 = new COORDINATE(* myCoordinate);
249     delete myCoordinate;
250     myCoordinate = NULL;
251
252     // check copied coordinate
253     int _spaceDimension = myCoordinate2->getSpaceDimension();
254     int _numberofNodes  = myCoordinate2->getNumberOfNodes();
255     CPPUNIT_ASSERT(_spaceDimension == spaceDimension);
256     CPPUNIT_ASSERT(_numberofNodes  == numberofNodes);
257
258     for (int i = 1; i <= _numberofNodes; i++) {
259       for (int j = 1; j <= _spaceDimension; j++) {
260         CPPUNIT_ASSERT_DOUBLES_EQUAL(i*j, myCoordinate2->getCoordinate(i, j), 0.000001);
261       }
262     }
263
264     CPPUNIT_ASSERT(myCoordinate2->getCoordinateName(1) == "x");
265     CPPUNIT_ASSERT(myCoordinate2->getCoordinateName(2) == "y");
266     CPPUNIT_ASSERT(myCoordinate2->getCoordinateName(3) == "z");
267
268     CPPUNIT_ASSERT(myCoordinate2->getCoordinateUnit(1) == "m");
269     CPPUNIT_ASSERT(myCoordinate2->getCoordinateUnit(2) == "m");
270     CPPUNIT_ASSERT(myCoordinate2->getCoordinateUnit(3) == "m");
271
272     for (int i = 0; i < _numberofNodes; i++)
273       CPPUNIT_ASSERT(myCoordinate2->getNodesNumbers()[i] == _numberofNodes - i - 1);
274
275     delete myCoordinate2;
276   }
277
278   ////////////
279   // TEST 3 //
280   ////////////
281   {
282     // COORDINATE(int SpaceDimension, int NumberOfNodes, MED_EN::medModeSwitch Mode);
283     COORDINATE anEmptyC (2, 10, MED_EN::MED_FULL_INTERLACE);
284     CPPUNIT_ASSERT(anEmptyC.getSpaceDimension() == 2);
285     CPPUNIT_ASSERT(anEmptyC.getNumberOfNodes()  == 10);
286     CPPUNIT_ASSERT(anEmptyC.getNodesNumbers() == NULL);
287     // ?: how to fill it with coordinates?
288     // 1. void setCoordinates(MEDARRAY<double> *Coordinate,bool shallowCopy=false);
289     // but this way we can override all three constructor parameters
290     // 2. void setCoordinates(const MED_EN::medModeSwitch Mode, const double *Coordinate);
291     // in this case we can override Mode
292
293 //#ifdef ENABLE_FAULTS
294     // (BUG) Incoherence between setCoordinateName() and getCoordinateName()
295     //anEmptyC.setCoordinateName("alpha", 1);
296     //anEmptyC.setCoordinateName("betta", 2);
297     // (BUG) Incoherence between setCoordinateUnit() and getCoordinateUnit()
298     //anEmptyC.setCoordinateUnit("ttt", 1);
299     //anEmptyC.setCoordinateUnit("sss", 2);
300 //#else
301     anEmptyC.setCoordinateName("alpha", 0);
302     anEmptyC.setCoordinateName("betta", 1);
303
304     anEmptyC.setCoordinateUnit("ttt", 0);
305     anEmptyC.setCoordinateUnit("sss", 1);
306 //#endif
307 //#ifdef ENABLE_FORCED_FAILURES
308     //CPPUNIT_FAIL("Incoherence between COORDINATE::setCoordinateName() and COORDINATE::getCoordinateName()");
309     //CPPUNIT_FAIL("Incoherence between COORDINATE::setCoordinateUnit() and COORDINATE::getCoordinateUnit()");
310 //#endif
311
312     int len = 10 * 2;
313     double * cc = new double[len];
314     for (int i = 0; i < len; i++) {
315       cc[i] = (double)(i + 1);
316     }
317     anEmptyC.setCoordinates(MED_EN::MED_NO_INTERLACE, cc);
318
319     CPPUNIT_ASSERT(anEmptyC.getCoordinateName(1) == "alpha");
320     CPPUNIT_ASSERT(anEmptyC.getCoordinateName(2) == "betta");
321     CPPUNIT_ASSERT(anEmptyC.getCoordinateUnit(1) == "ttt");
322     CPPUNIT_ASSERT(anEmptyC.getCoordinateUnit(2) == "sss");
323     for (int nn = 1; nn <= 10; nn++) {
324       for (int aa = 1; aa <= 2; aa++) {
325         CPPUNIT_ASSERT_DOUBLES_EQUAL(nn + (aa - 1) * 10, anEmptyC.getCoordinate(nn, aa), 0.000001);
326       }
327     }
328
329     CPPUNIT_ASSERT_THROW(anEmptyC.getCoordinate(0, 0), MEDEXCEPTION);
330     CPPUNIT_ASSERT_THROW(anEmptyC.getCoordinate(10, 10), MEDEXCEPTION);
331
332     MEDARRAY<double> mcc (cc, 2, 10, MED_EN::MED_FULL_INTERLACE, false, false);
333     anEmptyC.setCoordinates(&mcc, false);
334
335     // coordinates names and units are not changed
336     CPPUNIT_ASSERT(anEmptyC.getCoordinateName(1) == "alpha");
337     CPPUNIT_ASSERT(anEmptyC.getCoordinateName(2) == "betta");
338     CPPUNIT_ASSERT(anEmptyC.getCoordinateUnit(1) == "ttt");
339     CPPUNIT_ASSERT(anEmptyC.getCoordinateUnit(2) == "sss");
340     for (int nn = 1; nn <= 10; nn++) {
341       for (int aa = 1; aa <= 2; aa++) {
342         // coordinates changed
343         CPPUNIT_ASSERT_DOUBLES_EQUAL((nn - 1) * 2 + aa, anEmptyC.getCoordinate(nn, aa), 0.000001);
344       }
345     }
346
347     delete [] cc;
348
349 //#ifdef ENABLE_FAULTS
350     // (BUG) Segmentation Fault or Hang up after anEmptyC and mcc destruction,
351     // because array will be owned by two pointers (in mcc and in anEmptyC) after this call
352     //???skl anEmptyC.setCoordinates(&mcc, true);
353     // In other case (if we dynamically allocate mcc and do not free it) we will have memory leak.
354 //#endif
355 //#ifdef ENABLE_FORCED_FAILURES
356     //CPPUNIT_FAIL("Bug in COORDINATE::setCoordinates() in shallow copy mode");
357 //#endif
358   }
359
360   ////////////
361   // TEST 4 //
362   ////////////
363   {
364     // COORDINATE(int SpaceDimension,const string * CoordinateName, const string * CoordinateUnit);
365     string cnames [3] = {"al", "be", "ga"};
366     string cunits [3] = {"kg", "mm", "s2"};
367     COORDINATE anEmptyA (3, cnames, cunits);
368
369     CPPUNIT_ASSERT(anEmptyA.getCoordinateName(1) == "al");
370     CPPUNIT_ASSERT(anEmptyA.getCoordinateName(2) == "be");
371     CPPUNIT_ASSERT(anEmptyA.getCoordinateName(3) == "ga");
372
373     CPPUNIT_ASSERT(anEmptyA.getCoordinateUnit(1) == "kg");
374     CPPUNIT_ASSERT(anEmptyA.getCoordinateUnit(2) == "mm");
375     CPPUNIT_ASSERT(anEmptyA.getCoordinateUnit(3) == "s2");
376
377     CPPUNIT_ASSERT_EQUAL(anEmptyA.getSpaceDimension(), 0);
378     CPPUNIT_ASSERT_EQUAL(anEmptyA.getNumberOfNodes(),  0);
379
380     MEDARRAY<double> mcc (3, 7, MED_EN::MED_NO_INTERLACE);
381     anEmptyA.setCoordinates(&mcc, false);
382
383     CPPUNIT_ASSERT_EQUAL(anEmptyA.getSpaceDimension(), 3);
384     CPPUNIT_ASSERT_EQUAL(anEmptyA.getNumberOfNodes(),  7);
385
386     CPPUNIT_ASSERT(anEmptyA.getCoordinateName(1) == "al");
387     CPPUNIT_ASSERT(anEmptyA.getCoordinateName(2) == "be");
388     CPPUNIT_ASSERT(anEmptyA.getCoordinateName(3) == "ga");
389
390     CPPUNIT_ASSERT(anEmptyA.getCoordinateUnit(1) == "kg");
391     CPPUNIT_ASSERT(anEmptyA.getCoordinateUnit(2) == "mm");
392     CPPUNIT_ASSERT(anEmptyA.getCoordinateUnit(3) == "s2");
393
394     CPPUNIT_ASSERT_THROW(anEmptyA.getCoordinate(-1, 0), MEDEXCEPTION);
395     CPPUNIT_ASSERT_THROW(anEmptyA.getCoordinate(10, 10), MEDEXCEPTION);
396
397     // No COORDINATE::operator=, but this is compilable
398     // good
399     //COORDINATE anEmptyB;
400     //COORDINATE anEmptyD (3, cnames, cunits);
401     //anEmptyB = anEmptyD;
402     //CPPUNIT_ASSERT(anEmptyB.getCoordinateName(1) == "al");
403
404     // bad (assert fails)
405     //COORDINATE anEmptyB;
406     // Object, created in this line, is destructed right after it.
407     //anEmptyB = COORDINATE(3, cnames, cunits);
408     // Now a pointer _coordinateName inside anEmptyB points to a desallocated memory zone
409     //CPPUNIT_ASSERT(anEmptyB.getCoordinateName(1) == "al");
410   }
411 }