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