Salome HOME
ParaView-5.8.0 build options and patches
[tools/configuration.git] / config / patches / paraview.0001-LATA-reader.patch
1 From 8b92e13269c76f0c4b3422cd2774412bb24368b7 Mon Sep 17 00:00:00 2001
2 From: Antoine Gerschenfeld <antoine.gerschenfeld@cea.fr>
3 Date: Sun, 19 May 2019 20:24:42 +0200
4 Subject: [PATCH 1/3] LATA reader
5
6 ---
7  databases/CMakeLists.txt                      |    1 +
8  databases/readers/Lata/ArrOfBit.C             |  179 ++
9  databases/readers/Lata/ArrOfBit.h             |  110 +
10  databases/readers/Lata/ArrOfDouble.C          | 1185 +++++++++
11  databases/readers/Lata/ArrOfDouble.h          |  353 +++
12  databases/readers/Lata/ArrOfFloat.C           | 1185 +++++++++
13  databases/readers/Lata/ArrOfFloat.h           |  353 +++
14  databases/readers/Lata/ArrOfInt.C             | 1110 ++++++++
15  databases/readers/Lata/ArrOfInt.h             |  343 +++
16  .../readers/Lata/ArrOf_Scalar_Prototype.cpp.h | 1168 +++++++++
17  .../readers/Lata/ArrOf_Scalar_Prototype.h     |  357 +++
18  databases/readers/Lata/CMakeLists.txt         |   35 +
19  .../readers/Lata/Connectivite_som_elem.C      |  189 ++
20  .../readers/Lata/Connectivite_som_elem.h      |   44 +
21  databases/readers/Lata/DoubleTab.h            |   30 +
22  databases/readers/Lata/EFichier.h             |   60 +
23  databases/readers/Lata/Entree.h               |   77 +
24  databases/readers/Lata/FloatTab.h             |   30 +
25  databases/readers/Lata/IntTab.h               |   31 +
26  databases/readers/Lata/LataDB.C               | 2313 +++++++++++++++++
27  databases/readers/Lata/LataDB.h               |  303 +++
28  databases/readers/Lata/LataDBmed.h            |  586 +++++
29  databases/readers/Lata/LataFilter.C           | 1106 ++++++++
30  databases/readers/Lata/LataFilter.h           |  261 ++
31  databases/readers/Lata/LataJournal.h          |   36 +
32  databases/readers/Lata/LataStructures.C       |  743 ++++++
33  databases/readers/Lata/LataStructures.h       |  332 +++
34  .../readers/Lata/LataV1_field_definitions.C   |   84 +
35  .../readers/Lata/LataV1_field_definitions.h   |   35 +
36  databases/readers/Lata/LataVector.h           |   64 +
37  databases/readers/Lata/LataWriter.C           |  331 +++
38  databases/readers/Lata/LataWriter.h           |   61 +
39  databases/readers/Lata/Lata_tools.C           |  128 +
40  databases/readers/Lata/Lata_tools.h           |  194 ++
41  databases/readers/Lata/LmlReader.C            |  435 ++++
42  databases/readers/Lata/LmlReader.h            |   38 +
43  databases/readers/Lata/Motcle.C               |  142 +
44  databases/readers/Lata/Motcle.h               |  150 ++
45  databases/readers/Lata/Noms.h                 |   29 +
46  databases/readers/Lata/Objet_U.h              |   41 +
47  databases/readers/Lata/Octree_Double.C        |  395 +++
48  databases/readers/Lata/Octree_Double.h        |   89 +
49  databases/readers/Lata/Octree_Int.C           |  485 ++++
50  databases/readers/Lata/Octree_Int.h           |  103 +
51  databases/readers/Lata/OpenDXWriter.C         |  335 +++
52  databases/readers/Lata/OpenDXWriter.h         |   83 +
53  databases/readers/Lata/Operator.h             |  224 ++
54  databases/readers/Lata/OperatorBoundary.C     |  227 ++
55  databases/readers/Lata/OperatorDualMesh.C     |  222 ++
56  databases/readers/Lata/OperatorFacesMesh.C    |  130 +
57  databases/readers/Lata/OperatorReconnect.C    |  125 +
58  databases/readers/Lata/OperatorRegularize.C   |  296 +++
59  .../readers/Lata/Rebuild_virtual_layer.C      |  141 +
60  .../readers/Lata/Rebuild_virtual_layer.h      |   35 +
61  databases/readers/Lata/Sortie.h               |   44 +
62  databases/readers/Lata/Static_Int_Lists.C     |  128 +
63  databases/readers/Lata/Static_Int_Lists.h     |  110 +
64  databases/readers/Lata/UserFields.C           | 1038 ++++++++
65  databases/readers/Lata/UserFields.h           |  108 +
66  databases/readers/Lata/Vect.h                 |   34 +
67  databases/readers/Lata/VectArrOfInt.h         |   34 +
68  databases/readers/Lata/arch.h                 |   34 +
69  databases/readers/Lata/avtlataFileFormat.C    |  865 ++++++
70  databases/readers/Lata/avtlataFileFormat.h    |  114 +
71  databases/readers/Lata/simd_interface.h       |   31 +
72  databases/visit_readers.xml                   |   13 +
73  66 files changed, 19695 insertions(+)
74  create mode 100644 databases/readers/Lata/ArrOfBit.C
75  create mode 100644 databases/readers/Lata/ArrOfBit.h
76  create mode 100644 databases/readers/Lata/ArrOfDouble.C
77  create mode 100644 databases/readers/Lata/ArrOfDouble.h
78  create mode 100644 databases/readers/Lata/ArrOfFloat.C
79  create mode 100644 databases/readers/Lata/ArrOfFloat.h
80  create mode 100644 databases/readers/Lata/ArrOfInt.C
81  create mode 100644 databases/readers/Lata/ArrOfInt.h
82  create mode 100644 databases/readers/Lata/ArrOf_Scalar_Prototype.cpp.h
83  create mode 100644 databases/readers/Lata/ArrOf_Scalar_Prototype.h
84  create mode 100644 databases/readers/Lata/CMakeLists.txt
85  create mode 100644 databases/readers/Lata/Connectivite_som_elem.C
86  create mode 100644 databases/readers/Lata/Connectivite_som_elem.h
87  create mode 100644 databases/readers/Lata/DoubleTab.h
88  create mode 100644 databases/readers/Lata/EFichier.h
89  create mode 100644 databases/readers/Lata/Entree.h
90  create mode 100644 databases/readers/Lata/FloatTab.h
91  create mode 100644 databases/readers/Lata/IntTab.h
92  create mode 100644 databases/readers/Lata/LataDB.C
93  create mode 100644 databases/readers/Lata/LataDB.h
94  create mode 100644 databases/readers/Lata/LataDBmed.h
95  create mode 100644 databases/readers/Lata/LataFilter.C
96  create mode 100644 databases/readers/Lata/LataFilter.h
97  create mode 100644 databases/readers/Lata/LataJournal.h
98  create mode 100644 databases/readers/Lata/LataStructures.C
99  create mode 100644 databases/readers/Lata/LataStructures.h
100  create mode 100644 databases/readers/Lata/LataV1_field_definitions.C
101  create mode 100644 databases/readers/Lata/LataV1_field_definitions.h
102  create mode 100644 databases/readers/Lata/LataVector.h
103  create mode 100644 databases/readers/Lata/LataWriter.C
104  create mode 100644 databases/readers/Lata/LataWriter.h
105  create mode 100644 databases/readers/Lata/Lata_tools.C
106  create mode 100644 databases/readers/Lata/Lata_tools.h
107  create mode 100644 databases/readers/Lata/LmlReader.C
108  create mode 100644 databases/readers/Lata/LmlReader.h
109  create mode 100644 databases/readers/Lata/Motcle.C
110  create mode 100644 databases/readers/Lata/Motcle.h
111  create mode 100644 databases/readers/Lata/Noms.h
112  create mode 100644 databases/readers/Lata/Objet_U.h
113  create mode 100644 databases/readers/Lata/Octree_Double.C
114  create mode 100644 databases/readers/Lata/Octree_Double.h
115  create mode 100644 databases/readers/Lata/Octree_Int.C
116  create mode 100644 databases/readers/Lata/Octree_Int.h
117  create mode 100644 databases/readers/Lata/OpenDXWriter.C
118  create mode 100644 databases/readers/Lata/OpenDXWriter.h
119  create mode 100644 databases/readers/Lata/Operator.h
120  create mode 100644 databases/readers/Lata/OperatorBoundary.C
121  create mode 100644 databases/readers/Lata/OperatorDualMesh.C
122  create mode 100644 databases/readers/Lata/OperatorFacesMesh.C
123  create mode 100644 databases/readers/Lata/OperatorReconnect.C
124  create mode 100644 databases/readers/Lata/OperatorRegularize.C
125  create mode 100644 databases/readers/Lata/Rebuild_virtual_layer.C
126  create mode 100644 databases/readers/Lata/Rebuild_virtual_layer.h
127  create mode 100644 databases/readers/Lata/Sortie.h
128  create mode 100644 databases/readers/Lata/Static_Int_Lists.C
129  create mode 100644 databases/readers/Lata/Static_Int_Lists.h
130  create mode 100644 databases/readers/Lata/UserFields.C
131  create mode 100644 databases/readers/Lata/UserFields.h
132  create mode 100644 databases/readers/Lata/Vect.h
133  create mode 100644 databases/readers/Lata/VectArrOfInt.h
134  create mode 100644 databases/readers/Lata/arch.h
135  create mode 100644 databases/readers/Lata/avtlataFileFormat.C
136  create mode 100644 databases/readers/Lata/avtlataFileFormat.h
137  create mode 100644 databases/readers/Lata/simd_interface.h
138
139 diff --git a/databases/CMakeLists.txt b/databases/CMakeLists.txt
140 index a3d1b03..7b4bd48 100644
141 --- a/databases/CMakeLists.txt
142 +++ b/databases/CMakeLists.txt
143 @@ -35,6 +35,7 @@ set(DEFAULT_BRIDGE_READERS
144    H5Nimrod
145    Image
146    LAMMPS
147 +  Lata
148    Lines
149    M3D
150    M3DC1
151 diff --git a/databases/readers/Lata/ArrOfBit.C b/databases/readers/Lata/ArrOfBit.C
152 new file mode 100644
153 index 0000000..c1b4b45
154 --- /dev/null
155 +++ b/databases/readers/Lata/ArrOfBit.C
156 @@ -0,0 +1,179 @@
157 +/*****************************************************************************
158 +*
159 +* Copyright (c) 2011 - 2013, CEA
160 +* All rights reserved.
161 +* Redistribution and use in source and binary forms, with or without
162 +* modification, are permitted provided that the following conditions are met:
163 +*
164 +*     * Redistributions of source code must retain the above copyright
165 +*       notice, this list of conditions and the following disclaimer.
166 +*     * Redistributions in binary form must reproduce the above copyright
167 +*       notice, this list of conditions and the following disclaimer in the
168 +*       documentation and/or other materials provided with the distribution.
169 +*     * Neither the name of CEA, nor the
170 +*       names of its contributors may be used to endorse or promote products
171 +*       derived from this software without specific prior written permission.
172 +*
173 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
174 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
175 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
176 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
177 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
178 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
179 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
180 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
181 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
182 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
183 +*
184 +*****************************************************************************/
185 +
186 +#include <ArrOfBit.h>
187 +#include <string.h>
188 +//Implemente_instanciable_sans_constructeur_ni_destructeur(ArrOfBit,"ArrOfBit",Objet_U);
189 +
190 +const unsigned int ArrOfBit::SIZE_OF_INT_BITS = 5;
191 +const unsigned int ArrOfBit::DRAPEAUX_INT = 31;
192 +
193 +// Description: Constructeur d'un tableau de taille n, non initialise
194 +ArrOfBit::ArrOfBit(entier n)
195 +{
196 +  taille = 0;
197 +  data = 0;
198 +  resize_array(n);
199 +}
200 +
201 +// Description: Destructeur.
202 +ArrOfBit::~ArrOfBit()
203 +{
204 +  if (data)
205 +    delete[] data;
206 +  data = 0;
207 +}
208 +
209 +// Description: Constructeur par copie (deep copy)
210 +ArrOfBit::ArrOfBit(const ArrOfBit& array)
211 +{
212 +  taille = 0;
213 +  data = 0;
214 +  operator=(array);
215 +}
216 +
217 +// Description:
218 +// Taille en "int" du tableau requis pour stocker un tableau de bits
219 +// de taille donnees.
220 +entier ArrOfBit::calculer_int_size(entier taille) const
221 +{
222 +  assert(taille >= 0);
223 +  entier siz = taille >> SIZE_OF_INT_BITS;
224 +  if (taille & DRAPEAUX_INT)
225 +    siz++;
226 +  return siz;
227 +}
228 +
229 +// Description: Change la taille du tableau et copie les donnees
230 +// existantes. Si la taille est plus petite, les donnees sont
231 +// tronquees, et si la taille est plus grande, les nouveaux elements
232 +// ne sont pas initialises.
233 +ArrOfBit& ArrOfBit::resize_array(entier n)
234 +{
235 +  if (taille == n)
236 +    return *this;
237 +  assert(n >= 0);
238 +  if (n > 0)
239 +    {
240 +      entier oldsize = calculer_int_size(taille);
241 +      entier newsize = calculer_int_size(n);
242 +      unsigned int * newdata = new unsigned int[newsize];
243 +      entier size_copy = (newsize > oldsize) ? oldsize : newsize;
244 +      if (size_copy)
245 +        {
246 +          memcpy(newdata, data, size_copy);
247 +          delete[] data;
248 +        }
249 +      data = newdata;
250 +      taille = n;
251 +    }
252 +  else
253 +    {
254 +      delete[] data; // data!=0 sinon taille==n et on ne serait pas ici
255 +      data = 0;
256 +      taille = 0;
257 +    }
258 +  return *this;
259 +}
260 +
261 +// Description: Operateur copie (deep copy).
262 +ArrOfBit& ArrOfBit::operator=(const ArrOfBit& array)
263 +{
264 +  entier newsize = calculer_int_size(array.taille);
265 +  if (taille != array.taille)
266 +    {
267 +      if (data)
268 +        {
269 +          delete[] data;
270 +          data = 0;
271 +        }
272 +      if (newsize > 0)
273 +        data = new unsigned int[newsize];
274 +    }
275 +  taille = array.taille;
276 +  if (taille)
277 +    memcpy(data, array.data, newsize * sizeof(unsigned int));
278 +  return *this;
279 +}
280 +
281 +// Description: Si la valeur est non nulle, met la valeur 1 dans
282 +// tous les elements du tableau, sinon met la valeur 0.
283 +
284 +ArrOfBit& ArrOfBit::operator=(entier val)
285 +{
286 +  unsigned int valeur = val ? (~((unsigned int) 0)) : 0;
287 +  entier size = calculer_int_size(taille);
288 +  entier i;
289 +  for (i = 0; i < size; i++)
290 +    data[i] = valeur;
291 +  return *this;
292 +}
293 +
294 +// Description: Ecriture du tableau. Format:
295 +// n
296 +// 0 1 0 0 1 0 ... (n valeurs)
297 +Sortie& ArrOfBit::printOn(Sortie& os) const
298 +{
299 +  os << taille << finl;
300 +  entier i;
301 +  // Un retour a la ligne tous les 32 bits,
302 +  // Une espace tous les 8 bits
303 +  for (i = 0; i < taille; i++)
304 +    {
305 +      os << operator[](i);
306 +      if ((i & 7) == 7)
307 +        os << " ";
308 +      if ((i & 31) == 31)
309 +        os << finl;
310 +    }
311 +  // Un retour a la ligne si la derniere ligne n'etait pas terminee
312 +  if (i & 31)
313 +    os << finl;
314 +  return os;
315 +}
316 +
317 +// Description: Lecture du tableau. Format:
318 +// n
319 +// 0 1 0 0 1 0 ... (n valeurs)
320 +Entree& ArrOfBit::readOn(Entree& is)
321 +{
322 +  entier newsize;
323 +  is >> newsize;
324 +  resize_array(newsize);
325 +  operator=(0);
326 +
327 +  entier i;
328 +  for (i = 0; i < taille; i++)
329 +    {
330 +      entier bit;
331 +      is >> bit;
332 +      if (bit) setbit(i);
333 +    }
334 +  return is;
335 +}
336 diff --git a/databases/readers/Lata/ArrOfBit.h b/databases/readers/Lata/ArrOfBit.h
337 new file mode 100644
338 index 0000000..ed21f48
339 --- /dev/null
340 +++ b/databases/readers/Lata/ArrOfBit.h
341 @@ -0,0 +1,110 @@
342 +/*****************************************************************************
343 +*
344 +* Copyright (c) 2011 - 2013, CEA
345 +* All rights reserved.
346 +* Redistribution and use in source and binary forms, with or without
347 +* modification, are permitted provided that the following conditions are met:
348 +*
349 +*     * Redistributions of source code must retain the above copyright
350 +*       notice, this list of conditions and the following disclaimer.
351 +*     * Redistributions in binary form must reproduce the above copyright
352 +*       notice, this list of conditions and the following disclaimer in the
353 +*       documentation and/or other materials provided with the distribution.
354 +*     * Neither the name of CEA, nor the
355 +*       names of its contributors may be used to endorse or promote products
356 +*       derived from this software without specific prior written permission.
357 +*
358 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
359 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
360 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
361 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
362 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
363 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
364 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
365 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
366 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
367 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
368 +*
369 +*****************************************************************************/
370 +
371 +
372 +#ifndef ARROFBIT_H
373 +#define ARROFBIT_H
374 +
375 +#include <assert.h>
376 +#include <Objet_U.h>
377 +
378 +class ArrOfBit // : public Objet_U
379 +{
380 +// Declare_instanciable_sans_constructeur_ni_destructeur(ArrOfBit);
381 +protected:
382 +  Entree& readOn(Entree& is);
383 +  Sortie& printOn(Sortie& os) const;
384 +public:
385 +  ArrOfBit(entier n=0);
386 +  ArrOfBit(const ArrOfBit& array);              // Constructeur par copie
387 +  ~ArrOfBit();                                  // Destructeur
388 +  ArrOfBit& operator=(const ArrOfBit& array);   // Operateur copie
389 +  ArrOfBit& operator=(entier i);
390 +  inline entier operator[](entier i) const;
391 +  inline void setbit(entier i) const;
392 +  inline entier testsetbit(entier i) const;
393 +  inline void clearbit(entier i) const;
394 +  inline entier size_array() const;
395 +  ArrOfBit& resize_array(entier n);
396 +  entier calculer_int_size(entier taille) const;
397 +protected:
398 +  entier taille;
399 +  unsigned int *data;
400 +  static const unsigned int SIZE_OF_INT_BITS;
401 +  static const unsigned int DRAPEAUX_INT;
402 +};
403 +
404 +// Description: Renvoie 1 si le bit e est mis, 0 sinon.
405 +inline entier ArrOfBit::operator[](entier e) const
406 +{
407 +  assert(e >= 0 && e < taille);
408 +  unsigned int i = (unsigned int) e;
409 +  unsigned int x = data[i >> SIZE_OF_INT_BITS];
410 +  unsigned int flag = 1 << (i & DRAPEAUX_INT);
411 +  entier resultat = ((x & flag) != 0) ? 1 : 0;
412 +  return resultat;
413 +}
414 +
415 +// Description: Met le bit e a 1.
416 +inline void ArrOfBit::setbit(entier e) const
417 +{
418 +  assert(e >= 0 && e < taille);
419 +  unsigned int i = (unsigned int) e;
420 +  unsigned int flag = 1 << (i & DRAPEAUX_INT);
421 +  data[i >> SIZE_OF_INT_BITS] |= flag;
422 +}
423 +
424 +// Description: Renvoie la valeur du bit e, puis met le bit e a 1.
425 +inline entier ArrOfBit::testsetbit(entier e) const
426 +{
427 +  assert(e >= 0 && e < taille);
428 +  unsigned int i = (unsigned int) e;
429 +  unsigned int flag = 1 << (i & DRAPEAUX_INT);
430 +  entier index = i >> SIZE_OF_INT_BITS;
431 +  unsigned int old = data[index];
432 +  data[index] = old | flag;
433 +  return ((old & flag) != 0) ? 1 : 0;
434 +}
435 +
436 +// Description: Met le bit e a 0.
437 +inline void ArrOfBit::clearbit(entier e) const
438 +{
439 +  assert(e >= 0 && e < taille);
440 +  unsigned int i = (unsigned int) e;
441 +  unsigned int flag = 1 << (i & DRAPEAUX_INT);
442 +  data[i >> SIZE_OF_INT_BITS] &= ~flag;
443 +}
444 +
445 +// Description: Renvoie la taille du tableau en bits
446 +inline entier ArrOfBit::size_array() const
447 +{
448 +  return taille;
449 +}
450 +
451 +#endif
452 diff --git a/databases/readers/Lata/ArrOfDouble.C b/databases/readers/Lata/ArrOfDouble.C
453 new file mode 100644
454 index 0000000..5605a0d
455 --- /dev/null
456 +++ b/databases/readers/Lata/ArrOfDouble.C
457 @@ -0,0 +1,1185 @@
458 +/*****************************************************************************
459 +*
460 +* Copyright (c) 2011 - 2013, CEA
461 +* All rights reserved.
462 +* Redistribution and use in source and binary forms, with or without
463 +* modification, are permitted provided that the following conditions are met:
464 +*
465 +*     * Redistributions of source code must retain the above copyright
466 +*       notice, this list of conditions and the following disclaimer.
467 +*     * Redistributions in binary form must reproduce the above copyright
468 +*       notice, this list of conditions and the following disclaimer in the
469 +*       documentation and/or other materials provided with the distribution.
470 +*     * Neither the name of CEA, nor the
471 +*       names of its contributors may be used to endorse or promote products
472 +*       derived from this software without specific prior written permission.
473 +*
474 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
475 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
476 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
477 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
478 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
479 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
480 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
481 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
482 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
483 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
484 +*
485 +*****************************************************************************/
486 +
487 +////////////////////////////////////////////////////////////
488 +//
489 +// Warning : DO NOT EDIT !
490 +//          Please update ArrOf_Scalar_Prototype.cpp.h
491 +//          and this file will be generated automatically
492 +//           by the script file check.sh
493 +////////////////////////////////////////////////////////////
494 +
495 +#include <ArrOfDouble.h>
496 +#include <math.h>
497 +#include <stdlib.h>
498 +#include <Objet_U.h>
499 +#include <iostream>
500 +#include <stdlib.h>
501 +#include <string.h>
502 +#include "simd_interface.h"
503 +
504 +using namespace std;
505 +
506 +// ******************************************************************
507 +//
508 +//             Implementation des methodes de VDoubledata
509 +//
510 +// ******************************************************************
511 +////////////////////////////////////////////////////////////////////
512 +// .NOM        ArrOfDouble
513 +// .ENTETE     TRUST Math
514 +// .LIBRAIRIE  libtmath
515 +// .FILE       ArrOfDouble.h
516 +// .FILE       ArrOfDouble.cpp
517 +//
518 +// .DESCRIPTION
519 +// VDoubledata alloue une zone de memoire de la taille specifiee au
520 +// constructeur, et libere la zone de memoire a la destruction.
521 +//
522 +// "ref_count" compte le nombre de pointeurs qui font reference a "this".
523 +// (permet au dernier utilisateur de l'objet de le detruire), voir
524 +// ArrOfDouble.
525 +//
526 +// .SECTION voir aussi
527 +// .CONTRAINTES
528 +// .INVARIANTS
529 +// .HTML
530 +// .EPS
531 +///////////////////////////////////////////////////////////////////
532 +
533 +class VDoubledata
534 +{
535 +public:
536 +  VDoubledata(entier size, ArrOfDouble::Storage storage);
537 +  ~VDoubledata();
538 +  entier          add_one_ref();
539 +  entier          suppr_one_ref();
540 +  double *        get_data();
541 +  const double *  get_data() const;
542 +  inline entier   ref_count() const;
543 +  inline entier   get_size() const;
544 +private:
545 +  // Le constructeur par copie et l'operateur= sont interdits.
546 +  VDoubledata(const VDoubledata& v);
547 +  VDoubledata& operator=(const VDoubledata& v);
548 +
549 +  // "data" est un pointeur sur une zone de memoire de taille
550 +  // sz * sizeof(double), allouee par le
551 +  // constructeur et liberee par le destructeur.
552 +  // Ce pointeur n'est jamais nul meme si size_==0
553 +  double * data_;
554 +  // Compteur incremente par add_one_ref et decremente par suppr_one_ref.
555 +  // Contient le nombre d'objets ArrOfDouble dont le membre "p" pointe
556 +  // vers "this". On a ref_count_ >= 0.
557 +  entier ref_count_;
558 +  // "sz" est la taille du tableau "data_" alloue
559 +  // On a sz >= 0.
560 +  entier size_;
561 +  ArrOfDouble::Storage storage_;
562 +};
563 +
564 +
565 +// Description:
566 +//    Construit un VDoubledata de taille size >= 0
567 +// Parametre: entier s
568 +//    Signification: taille du VDoubledata, il faut size >= 0
569 +// Parametre: Storage storage
570 +//    Signification: indique si la memoire doit etre allouee
571 +//                   avec "new" ou avec "simd_malloc"
572 +//    Valeurs par defaut: STANDARD (allocation avec "new")
573 +// Postcondition:
574 +//    data_ n'est jamais nul, meme si size==0
575 +VDoubledata::VDoubledata(entier size, ArrOfDouble::Storage storage)
576 +{
577 +  if (size == 0)
578 +    storage = ArrOfDouble::STANDARD;
579 +
580 +  switch (storage)
581 +    {
582 +    case ArrOfDouble::STANDARD:
583 +      {
584 +#ifdef _EXCEPTION_
585 +        // Allocation de la memoire sur le tas
586 +        try
587 +          {
588 +            data_ = new double[size];
589 +          }
590 +        catch(...)
591 +          {
592 +            Cerr << "impossible d'allouer " << size << " double " << finl;
593 +            throw;
594 +          }
595 +#else
596 +        data_ = new double[size];
597 +        if(!data_)
598 +          {
599 +            Cerr << "impossible d'allouer " << size << "double " << finl;
600 +            throw ;
601 +          }
602 +#endif
603 +        break;
604 +      }
605 +    case ArrOfDouble::SIMD_ALIGNED:
606 +      {
607 +#ifdef SIMD_TOOLS_H
608 +        data_ = (double*) simd_malloc (sizeof(double) * size);
609 +#else
610 +        Cerr<<"unable to allocate simd_aligned, version compiled without simd "<<finl;
611 +        throw;
612 +#endif
613 +        break;
614 +      }
615 +    default:
616 +      throw;
617 +    }
618 +  ref_count_ = 1;
619 +  size_ = size;
620 +  storage_ = storage;
621 +  assert(data_ != 0);
622 +}
623 +
624 +// Description:
625 +//  Detruit la zone de memoire allouee.
626 +// Precondition:
627 +//  ref_count == 0 (la zone de memoire ne doit etre referencee nulle part)
628 +VDoubledata::~VDoubledata()
629 +{
630 +  assert(ref_count_ == 0);
631 +
632 +  // Stockage STANDARD
633 +  switch(storage_)
634 +    {
635 +    case ArrOfDouble::STANDARD:
636 +      delete[] data_;
637 +      break;
638 +    case ArrOfDouble::SIMD_ALIGNED:
639 +#ifdef SIMD_TOOLS_H
640 +      simd_free(data_);
641 +#else
642 +      Cerr<<"unable to allocate simd_aligned, version compiled without simd "<<finl;
643 +      throw;
644 +#endif
645 +      break;
646 +    default:
647 +      throw;
648 +    }
649 +
650 +  data_ = 0;  // paranoia: si size_==-1 c'est qu'on pointe sur un zombie
651 +  size_ = -1; //  (pointeur vers un objet qui a ete detruit)
652 +  storage_ = ArrOfDouble::STANDARD;
653 +}
654 +
655 +// Description: renvoie ref_count_
656 +inline entier VDoubledata::ref_count() const
657 +{
658 +  return ref_count_;
659 +}
660 +
661 +// Description: renvoie size_
662 +inline entier VDoubledata::get_size() const
663 +{
664 +  return size_;
665 +}
666 +
667 +// Description:
668 +//     Un nouveau tableau utilise cette zone memoire :
669 +//     incremente ref_count
670 +// Retour: int
671 +//    Signification: ref_count
672 +inline entier VDoubledata::add_one_ref()
673 +{
674 +  return ++ref_count_;
675 +}
676 +
677 +// Description:
678 +//     Un tableau de moins utilise cette zone memoire
679 +//     decremente ref_count
680 +// Precondition:
681 +//     ref_count_ > 0
682 +// Retour: int
683 +//    Signification: ref_count
684 +inline entier VDoubledata::suppr_one_ref()
685 +{
686 +  assert(ref_count_ > 0);
687 +  return (--ref_count_);
688 +}
689 +
690 +// Description: renvoie data_
691 +inline double * VDoubledata::get_data()
692 +{
693 +  return data_;
694 +}
695 +
696 +// Description: renvoie data_
697 +inline const double * VDoubledata::get_data() const
698 +{
699 +  return data_;
700 +}
701 +
702 +// Description: Constructeur par copie. Interdit : genere une erreur !
703 +VDoubledata::VDoubledata(const VDoubledata& v)
704 +{
705 +  Cerr << "Erreur dans VDoubledata::VDoubledata(const VDoubledata & v)" << finl;
706 +  throw;
707 +}
708 +
709 +// Description: Operateur= interdit. Genere une erreur !
710 +VDoubledata& VDoubledata::operator=(const VDoubledata& v)
711 +{
712 +  Cerr << "Erreur dans VDoubledata::operator=(const VDoubledata & v)" << finl;
713 +  throw;
714 +  return *this;
715 +}
716 +
717 +// ******************************************************************
718 +//
719 +//             Implementation des methodes de ArrOfDouble
720 +//
721 +// ******************************************************************
722 +
723 +
724 +// Definition des constantes pour les options de memory_resize
725 +const entier ArrOfDouble::COPY_OLD = 1;
726 +const entier ArrOfDouble::INITIALIZE_NEW = 2;
727 +
728 +// Description:
729 +//  Destructeur : appelle detach_array()
730 +ArrOfDouble::~ArrOfDouble()
731 +{
732 +  detach_array();
733 +  size_array_ = -1; // Paranoia: si size_array_==-1, c'est un zombie
734 +}
735 +
736 +// Description:
737 +//  Constructeur par defaut: cree un tableau "detache",
738 +//  soit p_==0, data_==0, size_array_==0, smart_resize_==0
739 +ArrOfDouble::ArrOfDouble() :
740 +  p_(0),
741 +  data_(0),
742 +  size_array_(0),
743 +  memory_size_(0),
744 +  smart_resize_(0),
745 +  storage_type_(STANDARD)
746 +{
747 +}
748 +
749 +// Description:
750 +//     Cree un tableau de taille n avec allocation standard
751 +//     (voir set_mem_storage).
752 +//     Valeur de remplissage par defaut: voir fill_default_value
753 +// Precondition:
754 +// Parametre: entier n
755 +//    Signification: taille du tableau
756 +ArrOfDouble::ArrOfDouble(entier n) :
757 +  p_(new VDoubledata(n, STANDARD)),
758 +  data_(p_->get_data()),
759 +  size_array_(n),
760 +  memory_size_(n),
761 +  smart_resize_(0),
762 +  storage_type_(STANDARD)
763 +{
764 +  if (n > 0)
765 +    fill_default_value(0, n);
766 +}
767 +
768 +// Description:
769 +//     Cree un tableau de taille n
770 +//     toutes les cases sont initialisees a x
771 +// Precondition:
772 +// Parametre: entier n
773 +//    Signification: taille du tableau
774 +// Parametre: double x
775 +//    Signification: valeur pour initialiser le tableau
776 +ArrOfDouble::ArrOfDouble(entier n, double x) :
777 +  p_(new VDoubledata(n, STANDARD)),
778 +  data_(p_->get_data()),
779 +  size_array_(n),
780 +  memory_size_(n),
781 +  smart_resize_(0),
782 +  storage_type_(STANDARD)
783 +{
784 +  *this = x;
785 +}
786 +
787 +// Description:
788 +//     Constructeur par copie. On alloue une nouvelle zone de memoire
789 +//     et on copie le contenu du tableau. L'attribut smart_resize_ est
790 +//     copie aussi.
791 +//     Si le tableau A est de taille nulle, on cree un tableau "detache",
792 +//     sinon on cree un tableau "normal".
793 +// Parametre: const ArrOfDouble& A
794 +//    Signification: le tableau a copier
795 +ArrOfDouble::ArrOfDouble(const ArrOfDouble& A)
796 +{
797 +  const entier size = A.size_array();
798 +  if (size > 0)
799 +    {
800 +      // Creation d'un tableau "normal"
801 +      storage_type_ = STANDARD;
802 +      p_ = new VDoubledata(size, STANDARD);
803 +      data_ = p_->get_data();
804 +      size_array_ = size;
805 +      memory_size_ = size;
806 +      smart_resize_ = A.smart_resize_;
807 +      inject_array(A);
808 +    }
809 +  else
810 +    {
811 +      // Creation d'un tableau "detache"
812 +      p_ = 0;
813 +      data_ = 0;
814 +      size_array_ = 0;
815 +      memory_size_ = 0;
816 +      smart_resize_ = 0;
817 +      storage_type_ = STANDARD;
818 +    }
819 +}
820 +
821 +// Description:
822 +//   Change le mode d'allocation memoire lors des resize
823 +//   (voir VDoubledata et Double_ptr_trav)
824 +//   Exemple pour creer un tableau avec allocation temporaire:
825 +//    DoubleTab tab; // Creation d'un tableau vide
826 +//    tab.set_mem_storage(TEMP_STORAGE); // Changement de mode d'allocation
827 +//    tab.resize(n); // Allocation memoire
828 +void ArrOfDouble::set_mem_storage(const Storage storage)
829 +{
830 +  storage_type_ = storage;
831 +}
832 +
833 +// Description:
834 +//   Renvoie le mode d'allocation du tableau (qui sera utilise
835 +//   lors du prochain resize si changement de taille).
836 +//   (voir VDoubledata et Double_ptr_trav)
837 +enum ArrOfDouble::Storage ArrOfDouble::get_mem_storage() const
838 +{
839 +  return storage_type_;
840 +}
841 +
842 +// Description:
843 +//   Change le mode l'allocation memoire: reallocation d'un tableau
844 +//   a chaque changement de taille (flag = 0) ou reallocation
845 +//   uniquement si la taille augmente et par doublement de la taille
846 +//   du tableau (flag = 1).
847 +void ArrOfDouble::set_smart_resize(entier flag)
848 +{
849 +  assert(flag == 0 || flag == 1);
850 +  smart_resize_ = flag;
851 +}
852 +
853 +// Description:
854 +//    Remet le tableau dans l'etat obtenu avec le constructeur par defaut
855 +//    (libere la memoire mais conserve le mode d'allocation memoire actuel)
856 +void ArrOfDouble::reset()
857 +{
858 +  detach_array();
859 +}
860 +
861 +// Description:
862 +//    Copie les donnees du tableau m.
863 +//    Si "m" n'a pas la meme taille que "*this", on fait un resize_array.
864 +//    Ensuite, on copie les valeurs de "m" dans "*this".
865 +//    Le type de tableau (methode d'allocation) n'est pas copie.
866 +// Precondition:
867 +//    Si le tableau n'a pas la meme taille que "m", alors *this doit
868 +//    etre "resizable" (ne pas etre de type "ref_data" et "ref_count == 1")
869 +// Parametre: const ArrOfDouble& m
870 +//    Signification: la tableau a copier
871 +// Retour:  ArrOfDouble&
872 +//    Signification: *this
873 +ArrOfDouble& ArrOfDouble::operator=(const ArrOfDouble& m)
874 +{
875 +  if (&m != this)
876 +    {
877 +      const entier new_size = m.size_array();
878 +      // Le code suivant est quasiment une copie de ArrOfDouble::resize()
879 +      // SAUF: memory_resize est appele avec NO_INITIALIZE (la zone de memoire
880 +      //  n'est pas initialisee)
881 +      if (new_size != size_array())
882 +        {
883 +          if ((smart_resize_ == 0) || (new_size > memory_size_))
884 +            memory_resize(new_size, 0); // Pas d'initialisation
885 +          size_array_ = new_size;
886 +        }
887 +      inject_array(m);
888 +    }
889 +  return *this;
890 +}
891 +
892 +
893 +// Description:
894 +//     x est affecte a toutes les cases
895 +// Precondition:
896 +// Parametre: double x
897 +//    Signification: la valeur a affecter a toutes les cases du tableau
898 +//    Valeurs par defaut:
899 +//    Contraintes:
900 +//    Acces:
901 +// Retour: ArrOfDouble&
902 +//    Signification: *this
903 +//    Contraintes:
904 +// Exception:
905 +// Effets de bord:
906 +// Postcondition:
907 +ArrOfDouble& ArrOfDouble::operator=(double x)
908 +{
909 +  const entier n = size_array();
910 +  double *data = addr();
911 +  for (entier i = 0; i < n; i++)
912 +    {
913 +      data[i] = x;
914 +    }
915 +  return *this;
916 +}
917 +
918 +// Description: appelle operator=(a)
919 +ArrOfDouble& ArrOfDouble::copy_array(const ArrOfDouble& a)
920 +{
921 +  operator=(a);
922 +  return *this;
923 +}
924 +
925 +// Description:
926 +//  Si besoin, alloue une nouvelle zone de memoire,
927 +//  copie les donnees et efface l'ancienne zone de memoire.
928 +//  Attention, on suppose que cette methode est appelee par
929 +//  resize_array().
930 +//  Attention: si ref_count_>1, l'appel a resize_array() est
931 +//  autorise uniquement si la nouvelle taille est identique
932 +//  a la precedente.
933 +// Precondition:
934 +//  Le tableau doit etre de type "detache" ou "normal" avec
935 +//  ref_count==1, et il faut new_size >= 0
936 +//  On suppose que size_array contient encore le nombre d'elements
937 +//  valides avant changement de taille.
938 +// Parametre: new_size
939 +//  Signification: nouvelle taille demandee pour le tableau.
940 +// Parametre: options
941 +//  Signification: COPY_OLD => on recopie les anciennes donnees dans le nouveau
942 +//                  tableau (jusqu'au max de l'ancienne et de la nouvelle taille).
943 +//                 INITIALIZE_NEW => initialisation des cases non copiees
944 +// Postcondition:
945 +//  p_ et data_ sont mis a jour, mais pas size_array_ !!!
946 +//  (on suppose que c'est fait dans resize_array()).
947 +//  Si la nouvelle taille est nulle, on detache le tableau.
948 +void  ArrOfDouble::memory_resize(entier new_size, entier options)
949 +{
950 +  assert(new_size >= 0);
951 +
952 +  // Occupation memoire de l'ancien tableau:
953 +  entier old_mem_size = 0;
954 +  if (p_)
955 +    old_mem_size = p_->get_size();
956 +
957 +  // Occupation memoire du nouveau tableau :
958 +  // Si smart_resize, on prend au moins deux fois la taille
959 +  // precedente, ou new_size
960 +  entier new_mem_size = new_size;
961 +  if (smart_resize_ && (old_mem_size * 2 > new_size))
962 +    new_mem_size = old_mem_size * 2;
963 +
964 +  if (new_mem_size != old_mem_size)
965 +    {
966 +      // detach_array() efface le contenu de size_array_. On le met de cote:
967 +      const entier old_size_array = size_array_;
968 +      // On va reellement changer l'adresse du tableau.
969 +      // Il ne faut pas qu'il existe d'autre reference a ce tableau.
970 +      assert(data_ == 0 || (p_ != 0 && ref_count() == 1));
971 +      if (new_mem_size == 0)
972 +        {
973 +          // La nouvelle taille est nulle, on cree un tableau "detache"
974 +          detach_array();
975 +        }
976 +      else
977 +        {
978 +          // Allocation d'une nouvelle zone
979 +          VDoubledata * new_p = new VDoubledata(new_mem_size, storage_type_);
980 +          double * new_data = new_p->get_data();
981 +          // Raccourci si le tableau etait "detache", inutile de copier
982 +          // les anciennes donnees. On copie si COPY_OLD est demande
983 +          entier copy_size = 0;
984 +          if (data_ != 0)
985 +            {
986 +              // Calcul du nombre d'elements a copier vers la nouvelle
987 +              // zone de memoire : c'est le min de l'ancienne et de
988 +              // la nouvelle taille.
989 +              if (options & COPY_OLD)
990 +                {
991 +                  copy_size = size_array_;
992 +                  if (new_size < copy_size)
993 +                    copy_size = new_size;
994 +                  // Copie des valeurs dans le nouveau tableau
995 +                  for (entier i = 0; i < copy_size; i++)
996 +                    new_data[i] = data_[i];
997 +                }
998 +              // Destruction de l'ancienne zone (si plus aucune reference)
999 +              detach_array();
1000 +            }
1001 +          // On attache la nouvelle zone de memoire
1002 +          p_ = new_p;
1003 +          data_ = new_data;
1004 +          memory_size_ = new_mem_size;
1005 +          // Initialisation des cases supplementaires avec une valeur par defaut
1006 +          if (options & INITIALIZE_NEW)
1007 +            fill_default_value(copy_size, new_mem_size - copy_size);
1008 +          // Restaure l'ancienne valeur de size_array_
1009 +          size_array_ = old_size_array;
1010 +        }
1011 +    }
1012 +}
1013 +
1014 +// Description:
1015 +//  Remplit "nb" cases consecutives du tableau a partir de la case "first"
1016 +//  avec une valeur par defaut.
1017 +//  Cette fonction est appelee lors d'un resize pour initialiser les
1018 +//  cases nouvellement creees.
1019 +//  Le comportement depend actuellement du type de tableau :
1020 +//  * Tableau de type "smart_resize":
1021 +//    * en mode debug (macro NDEBUG non definie) le tableau est initialise
1022 +//      avec une valeur invalide.
1023 +//    * en optimise, le tableau n'est pas initialise
1024 +//  * Tableau normal :
1025 +//    Le tableau est initialise avec la valeur 0. Ce comportement est choisi
1026 +//    pour des raisons de compatibilite avec l'implementation precedente.
1027 +//    Cette specification pourrait etre modifiee prochainement pour des raisons
1028 +//    de performances (pour ne pas avoir a initialiser inutilement les tableaux).
1029 +//    DONC: il faut supposer desormais que les nouvelles cases ne sont pas
1030 +//    initialisees lors d'un resize.
1031 +// Parametre: first
1032 +//  Signification: premiere case a initialiser.
1033 +//  Contrainte:    (nb==0) ou (0 <= first < memory_size_)
1034 +// Parametre: nb
1035 +//  Signification: nombre de cases a initialiser.
1036 +//  Contrainte:    (nb==0) ou (0 < nb <= memory_size_ - first)
1037 +void  ArrOfDouble::fill_default_value(entier first, entier nb)
1038 +{
1039 +  assert((nb == 0) || (first >= 0 && first < memory_size_));
1040 +  assert((nb == 0) || (nb > 0 && nb <= memory_size_ - first));
1041 +  double * data = addr();
1042 +  assert(data!=0 || nb==0);
1043 +  data += first;
1044 +  if (smart_resize_)
1045 +    {
1046 +      /*
1047 +          // On initialise uniquement en mode debug
1048 +      #ifndef NDEBUG
1049 +          // Ceci represente un NAN. N'importe quelle operation avec ca fait encore un NAN.
1050 +          // Si c'est pas portable, on peut remplacer par DMAX_FLOAT sur les autres machines.
1051 +          static const unsigned long long  VALEUR_INVALIDE =
1052 +            0x7ff7ffffffffffffULL;
1053 +
1054 +          // On utilise "memcpy" et non "=" car "=" peut provoquer une exception
1055 +          // si la copie passe par le fpu.
1056 +          for (entier i = 0; i < nb; i++)
1057 +            memcpy(data + i, & VALEUR_INVALIDE, sizeof(double));
1058 +      #endif
1059 +      */
1060 +    }
1061 +  else
1062 +    {
1063 +      // Comportement pour les tableaux normaux : compatibilite avec la
1064 +      // version precedente : on initialise avec 0.
1065 +      for (entier i = 0; i < nb; i++)
1066 +        data[i] = (double) 0;
1067 +    }
1068 +}
1069 +
1070 +// ****************************************************************
1071 +//
1072 +//         Fonctions non membres de la classe ArrOfDouble
1073 +//
1074 +// ****************************************************************
1075 +
1076 +// Description:
1077 +//  Renvoie 1 si les tableaux "v" et "a" sont de la meme taille
1078 +//  et contiennent les memes valeurs au sens strict, sinon renvoie 0.
1079 +//  Le test est !(v[i]!=a[i])
1080 +entier operator==(const ArrOfDouble& v, const ArrOfDouble& a)
1081 +{
1082 +  const entier n = v.size_array();
1083 +  const entier na = a.size_array();
1084 +  entier resu = 1;
1085 +  if (n != na)
1086 +    {
1087 +      resu = 0;
1088 +    }
1089 +  else
1090 +    {
1091 +      const double* vv = v.addr();
1092 +      const double* av = a.addr();
1093 +      entier i;
1094 +      for (i = 0; i < n; i++)
1095 +        {
1096 +          if (av[i] != vv[i])
1097 +            {
1098 +              resu = 0;
1099 +              break;
1100 +            }
1101 +        }
1102 +    }
1103 +  return resu;
1104 +}
1105 +
1106 +// Description:
1107 +//    Retourne l'indice du min ou -1 si le tableau est vide
1108 +// Precondition:
1109 +// Parametre: const ArrOfDouble& dx
1110 +//    Signification: tableau a utiliser
1111 +// Retour: int
1112 +//    Signification: indice du min
1113 +entier imin_array(const ArrOfDouble& dx)
1114 +{
1115 +  entier indice_min = -1;
1116 +  const entier size = dx.size_array();
1117 +  if (size > 0)
1118 +    {
1119 +      indice_min = 0;
1120 +      double valeur_min = dx[0];
1121 +      for(entier i = 1; i < size; i++)
1122 +        {
1123 +          const double val = dx[i];
1124 +          if(val < valeur_min)
1125 +            {
1126 +              indice_min = i;
1127 +              valeur_min = val;
1128 +            }
1129 +        }
1130 +    }
1131 +  return indice_min;
1132 +}
1133 +
1134 +// Description:
1135 +//    Retourne l'indice du max ou -1 si le tableau est vide
1136 +// Precondition:
1137 +// Parametre: const ArrOfDouble& dx
1138 +//    Signification: tableau a utiliser
1139 +// Retour: int
1140 +//    Signification: indice du max
1141 +entier imax_array(const ArrOfDouble& dx)
1142 +{
1143 +  entier indice_max = -1;
1144 +  const entier size = dx.size_array();
1145 +  if (size > 0)
1146 +    {
1147 +      indice_max = 0;
1148 +      double valeur_max = dx[0];
1149 +      for(entier i = 1; i < size; i++)
1150 +        {
1151 +          const double val = dx[i];
1152 +          if(val > valeur_max)
1153 +            {
1154 +              indice_max = i;
1155 +              valeur_max = val;
1156 +            }
1157 +        }
1158 +    }
1159 +  return indice_max;
1160 +}
1161 +
1162 +// Description:
1163 +//    Retourne la valeur minimale
1164 +// Precondition:
1165 +//    Le tableau doit contenir au moins une valeur
1166 +// Parametre: const ArrOfDouble& dx
1167 +//    Signification: tableau a utiliser
1168 +// Retour: double
1169 +//    Signification: valeur du min
1170 +double min_array(const ArrOfDouble& dx)
1171 +{
1172 +  const entier size = dx.size_array();
1173 +  assert(size > 0);
1174 +  double valeur_min = dx[0];
1175 +  for(entier i = 1; i < size; i++)
1176 +    {
1177 +      const double val = dx[i];
1178 +      if (val < valeur_min)
1179 +        valeur_min = val;
1180 +    }
1181 +  return valeur_min;
1182 +}
1183 +
1184 +// Description:
1185 +//    Retourne la valeur maximale
1186 +// Precondition:
1187 +//    Le tableau doit contenir au moins une valeur
1188 +// Parametre: const ArrOfDouble& dx
1189 +//    Signification: tableau a utiliser
1190 +// Retour: double
1191 +//    Signification: valeur du max
1192 +double max_array(const ArrOfDouble& dx)
1193 +{
1194 +  const entier size = dx.size_array();
1195 +  assert(size > 0);
1196 +  double valeur_max = dx[0];
1197 +  for(entier i = 1; i < size; i++)
1198 +    {
1199 +      const double val = dx[i];
1200 +      if (val > valeur_max)
1201 +        valeur_max = val;
1202 +    }
1203 +  return valeur_max;
1204 +}
1205 +
1206 +// Description:
1207 +//   Fonction de comparaison utilisee pour trier le tableau
1208 +//   dans ArrOfDouble::trier(). Voir man qsort
1209 +static int fonction_compare_arrofdouble_ordonner(const void * data1, const void * data2)
1210 +{
1211 +  const double x = *(const double*)data1;
1212 +  const double y = *(const double*)data2;
1213 +  if (x < y)
1214 +    return -1;
1215 +  else if (x > y)
1216 +    return 1;
1217 +  else
1218 +    return 0;
1219 +}
1220 +
1221 +// Description:
1222 +//   Tri des valeurs du tableau dans l'ordre croissant.
1223 +//   La fonction utilisee est qsort de stdlib (elle est en n*log(n)).
1224 +void ArrOfDouble::ordonne_array()
1225 +{
1226 +  const entier size = size_array();
1227 +  if (size > 1)
1228 +    {
1229 +      double * data = addr();
1230 +      qsort(data, size, sizeof(double),
1231 +            fonction_compare_arrofdouble_ordonner);
1232 +    }
1233 +}
1234 +
1235 +// Description:
1236 +//    Fait pointer le tableau vers les memes donnees qu'un tableau
1237 +//    existant. Le tableau sera du meme type que le tableau m ("detache",
1238 +//    "normal"). Le tableau m ne doit pas etre de type "ref_data"
1239 +//    Les donnes existantes sont perdues si elles
1240 +//    ne sont pas referencees ailleurs.
1241 +// Precondition:
1242 +// Parametre: const ArrOfDouble& m
1243 +//    Signification: le tableau a referencer (pas de type "ref_data"
1244 +//                   et different de *this !!!)
1245 +// Retour: ArrOfDouble&
1246 +//    Signification: *this
1247 +//    Contraintes:
1248 +// Exception:
1249 +// Effets de bord:
1250 +// Postcondition:
1251 +ArrOfDouble& ArrOfDouble::ref_array(const ArrOfDouble& m)
1252 +{
1253 +  assert(&m != this);
1254 +  // La condition 'm n'est pas de type "ref_data"' est necessaire pour
1255 +  // attach_array().
1256 +  detach_array();
1257 +  attach_array(m);
1258 +  return *this;
1259 +}
1260 +
1261 +// Description:
1262 +//    Fait pointer le tableau vers la zone de memoire "data_".
1263 +//    On detache la zone de memoire existante. Le tableau devient
1264 +//    de type "ref_data". Attention : ptr doit etre non nul.
1265 +//    La taille est initialisee avec size.
1266 +//    Cette methode est appelee notamment par DoubleVect::adopter.
1267 +// Parametre: double*
1268 +//    Signification: le tableau a recuperer. Si pointeur nul alors size
1269 +//                   doit etre nulle aussi et le tableau reste detache
1270 +// Parametre: entier size
1271 +//    Signification: le nombre d'elements du tableau.
1272 +// Retour: ArrOfDouble&
1273 +//    Signification: *this
1274 +ArrOfDouble& ArrOfDouble::ref_data(double* ptr, entier size)
1275 +{
1276 +  assert(ptr != 0 || size == 0);
1277 +  assert(size >= 0);
1278 +  detach_array();
1279 +  data_ = ptr;
1280 +  size_array_ = size;
1281 +  return *this;
1282 +}
1283 +
1284 +// Description:
1285 +//  Amene le tableau dans l'etat "detache". C'est a dire:
1286 +//  Si le tableau est "detache" :
1287 +//   * ne rien faire
1288 +//  Si le tableau est "normal" :
1289 +//   * decremente le nombre de references a *p
1290 +//   * detruit *p si p->ref_count==0
1291 +//   * annule p_, data_ et size_array_
1292 +//  Si le tableau est "ref_data" :
1293 +//   * annule data_ et size_array_
1294 +// Retour: int
1295 +//    Signification: 1 si les donnees du tableau ont ete supprimees
1296 +// Precondition:
1297 +// Postcondition:
1298 +//  On a p_==0, data_==0 et size_array_==0, memory_size_ = 0
1299 +//  L'attribut smart_resize_ est conserve.
1300 +entier ArrOfDouble::detach_array()
1301 +{
1302 +  entier retour = 0;
1303 +  if (p_)
1304 +    {
1305 +      // Le tableau est de type "normal"
1306 +      // Si la zone de memoire n'est plus utilisee par personne,
1307 +      // on la detruit.
1308 +      if ((p_->suppr_one_ref()) == 0)
1309 +        {
1310 +          delete p_;
1311 +          retour = 1;
1312 +        }
1313 +      p_ = 0;
1314 +    }
1315 +  data_ = 0;
1316 +  size_array_ = 0;
1317 +  memory_size_ = 0;
1318 +  return retour;
1319 +}
1320 +
1321 +// Description:
1322 +//    Amene le tableau dans l'etat "normal", "detache" ou "ref_array"
1323 +//    en associant la meme zone de memoire que le tableau m.
1324 +// Precondition:
1325 +//    Le tableau doit etre "detache"
1326 +// Parametre: const ArrOfDouble& m
1327 +//    Signification: tableau a utiliser
1328 +//                   le tableau doit etre different de *this !!!
1329 +// Retour:
1330 +//    Signification:
1331 +//    Contraintes:
1332 +// Exception:
1333 +// Effets de bord:
1334 +// Postcondition:
1335 +//    Si m est detache, le tableau reste detache,
1336 +//    si m est "ref_array", le tableau devient "ref_array",
1337 +//    sinon le tableau est "normal", avec ref_count > 1
1338 +//    Si m est de taille nulle, le tableau reste detache + Warning dans fichier .log
1339 +void ArrOfDouble::attach_array(const ArrOfDouble& m)
1340 +{
1341 +  // Le tableau doit etre detache
1342 +  assert(data_ == 0 && p_ == 0);
1343 +  // Le tableau doit etre different de *this
1344 +  assert(&m != this);
1345 +
1346 +  if (m.size_array() > 0)
1347 +    {
1348 +      p_ = m.p_;
1349 +      if (p_)
1350 +        p_->add_one_ref();
1351 +      data_ = m.data_;
1352 +      size_array_ = m.size_array_;
1353 +      memory_size_ = m.memory_size_;
1354 +      smart_resize_ = m.smart_resize_;
1355 +    }
1356 +  else
1357 +    {
1358 +      // Cas particulier ou on attache un tableau de taille nulle:
1359 +      //  en theorie, c'est pareil qu'un tableau de taille non nulle, MAIS
1360 +      //  dans les operateurs (ex:Op_Dift_VDF_Face_Axi), une ref est construite
1361 +      //  avant que le tableau ne prenne sa taille definitive. Donc, pour ne pas
1362 +      //  empecher le resize, il ne faut pas attacher le tableau s'il n'a pas
1363 +      //  encore la bonne taille. Solution propre: reecrire les operateurs pour
1364 +      //  qu'ils ne prennent pas une ref avant que le tableau ne soit valide
1365 +      //  et faire p_ = m.p_ dans tous les cas.
1366 +    }
1367 +}
1368 +
1369 +// Description:
1370 +//    Copie les elements source[first_element_source + i]
1371 +//    dans les elements  (*this)[first_element_dest + i] pour 0 <= i < nb_elements
1372 +//    Les autres elements de (*this) sont inchanges.
1373 +// Precondition:
1374 +// Parametre:       const ArrOfDouble& m
1375 +//  Signification:   le tableau a utiliser, doit etre different de *this !
1376 +// Parametre:       entier nb_elements
1377 +//  Signification:   nombre d'elements a copier, nb_elements >= -1.
1378 +//                   Si nb_elements==-1, on copie tout le tableau m.
1379 +//  Valeurs par defaut: -1
1380 +// Parametre:       entier first_element_dest
1381 +//  Valeurs par defaut: 0
1382 +// Parametre:       entier first_element_source
1383 +//  Valeurs par defaut: 0
1384 +// Retour: ArrOfDouble&
1385 +//    Signification: *this
1386 +//    Contraintes:
1387 +// Exception:
1388 +//    Sort en erreur si la taille du tableau m est plus grande que la
1389 +//    taille de tableau this.
1390 +// Effets de bord:
1391 +// Postcondition:
1392 +ArrOfDouble& ArrOfDouble::inject_array(const ArrOfDouble& source,
1393 +                                       entier nb_elements,
1394 +                                       entier first_element_dest,
1395 +                                       entier first_element_source)
1396 +{
1397 +  assert(&source != this);
1398 +  assert(nb_elements >= -1);
1399 +  assert(first_element_dest >= 0);
1400 +  assert(first_element_source >= 0);
1401 +
1402 +  if (nb_elements < 0)
1403 +    nb_elements = source.size_array();
1404 +
1405 +  assert(first_element_source + nb_elements <= source.size_array());
1406 +  assert(first_element_dest + nb_elements <= size_array());
1407 +
1408 +  if (nb_elements > 0)
1409 +    {
1410 +      double * addr_dest = addr() + first_element_dest;
1411 +      const double * addr_source = source.addr() + first_element_source;
1412 +      // memcpy(addr_dest , addr_source, nb_elements * sizeof(double));
1413 +      entier i;
1414 +      for (i = 0; i < nb_elements; i++)
1415 +        {
1416 +          addr_dest[i] = addr_source[i];
1417 +        }
1418 +    }
1419 +  return *this;
1420 +}
1421 +
1422 +// Description:
1423 +//    Retourne le nombre de references des donnees du tableau
1424 +//    si le tableau est "normal", -1 s'il est "detache" ou "ref_data"
1425 +// Retour: int
1426 +//    Signification: ref_count_
1427 +entier ArrOfDouble::ref_count() const
1428 +{
1429 +  if (p_)
1430 +    return p_->ref_count();
1431 +  else
1432 +    return -1;
1433 +}
1434 +
1435 +// Description:
1436 +//    Addition case a case sur toutes les cases du tableau
1437 +// Precondition:
1438 +//    la taille de y doit etre au moins egale a la taille de this
1439 +// Parametre: const ArrOfDouble& y
1440 +//    Signification: tableau a ajouter
1441 +//    Valeurs par defaut:
1442 +//    Contraintes:
1443 +//    Acces:
1444 +// Retour: ArrOfDouble&
1445 +//    Signification: *this
1446 +//    Contraintes:
1447 +// Exception:
1448 +// Effets de bord:
1449 +// Postcondition:
1450 +ArrOfDouble& ArrOfDouble::operator+=(const ArrOfDouble& y)
1451 +{
1452 +  assert(size_array()==y.size_array());
1453 +  double* dx = addr();
1454 +  const double* dy = y.addr();
1455 +  const entier n = size_array();
1456 +  for (entier i=0; i<n; i++)
1457 +    dx[i] += dy[i];
1458 +  return *this;
1459 +}
1460 +
1461 +// Description:
1462 +//     ajoute la meme valeur a toutes les cases du tableau
1463 +// Precondition:
1464 +// Parametre: const double dy
1465 +//    Signification: valeur a ajouter
1466 +//    Valeurs par defaut:
1467 +//    Contraintes:
1468 +//    Acces:
1469 +// Retour: ArrOfDouble
1470 +//    Signification: *this
1471 +//    Contraintes:
1472 +// Exception:
1473 +// Effets de bord:
1474 +// Postcondition:
1475 +ArrOfDouble& ArrOfDouble::operator+=(const double dy)
1476 +{
1477 +  double * data = addr();
1478 +  const entier n = size_array();
1479 +  for(entier i=0; i < n; i++)
1480 +    data[i] += dy;
1481 +  return *this;
1482 +}
1483 +// Description:
1484 +//    Soustraction case a case sur toutes les cases du tableau
1485 +// Parametre: const ArrOfDouble& y
1486 +//    Signification: tableau de meme taille que *this
1487 +// Retour: ArrOfDouble&
1488 +//    Signification: *this
1489 +ArrOfDouble& ArrOfDouble::operator-=(const ArrOfDouble& y)
1490 +{
1491 +  const entier size = size_array();
1492 +  assert(size == y.size_array());
1493 +  double * data = addr();
1494 +  const double * data_y = y.addr();
1495 +  for (entier i=0; i < size; i++)
1496 +    data[i] -= data_y[i];
1497 +  return *this;
1498 +}
1499 +
1500 +
1501 +// Description:
1502 +//     soustrait la meme valeur a toutes les cases
1503 +// Retour: ArrOfDouble &
1504 +//    Signification: *this
1505 +ArrOfDouble& ArrOfDouble::operator-=(const double dy)
1506 +{
1507 +  double * data = addr();
1508 +  const entier n = size_array();
1509 +  for(entier i=0; i < n; i++)
1510 +    data[i] -= dy;
1511 +  return *this;
1512 +}
1513 +
1514 +// Description:
1515 +//   Renvoie un pointeur sur le premier element du tableau.
1516 +//   Le pointeur est nul si le tableau est "detache".
1517 +//   Attention, l'adresse peut changer apres un appel
1518 +//   a resize_array(), ref_data, ref_array, ...
1519 +// Precondition:
1520 +// Retour: const double*
1521 +//   Signification: pointeur sur le premier element du tableau
1522 +const double* ArrOfDouble::addr() const
1523 +{
1524 +  return data_;
1525 +}
1526 +
1527 +// Description:
1528 +//   Renvoie un pointeur sur le premier element du tableau.
1529 +//   Le pointeur est nul si le tableau est "detache".
1530 +// Precondition:
1531 +// Retour: const double*
1532 +//    Signification: la zone memoire du tableau
1533 +double* ArrOfDouble::addr()
1534 +{
1535 +  return data_;
1536 +}
1537 +
1538 +
1539 +// Description:
1540 +//    Retourne le max des abs(i)
1541 +// Precondition:
1542 +//    Le tableau doit contenir au moins une valeur
1543 +// Parametre: const ArrOfDouble& dx
1544 +//    Signification: tableau a utiliser
1545 +//    Valeurs par defaut:
1546 +//    Contraintes:
1547 +//    Acces:
1548 +// Retour: double
1549 +//    Signification: valeur du max des valeurs absolues
1550 +//    Contraintes:
1551 +// Exception:
1552 +// Effets de bord:
1553 +// Postcondition:
1554 +double max_abs_array(const ArrOfDouble& dx)
1555 +{
1556 +  const entier size = dx.size_array();
1557 +  assert(size > 0);
1558 +  double valeur_max = fabs(dx[0]);
1559 +  for(entier i = 1; i < size; i++)
1560 +    {
1561 +      const double val = fabs(dx[i]);
1562 +      if (val > valeur_max)
1563 +        valeur_max = val;
1564 +    }
1565 +  return valeur_max;
1566 +}
1567 +
1568 +// Description:
1569 +//     muliplie toutes les cases par dy
1570 +// Retour: ArrOfDouble &
1571 +//    Signification: *this
1572 +ArrOfDouble& ArrOfDouble::operator*= (const double dy)
1573 +{
1574 +  double * data = addr();
1575 +  const entier n = size_array();
1576 +  for(entier i=0; i < n; i++)
1577 +    data[i] *= dy;
1578 +  return *this;
1579 +}
1580 +
1581 +
1582 +// Description:
1583 +//     divise toutes les cases par dy
1584 +// Retour: ArrOfDouble &
1585 +//    Signification: *this
1586 +ArrOfDouble& ArrOfDouble::operator/= (const double dy)
1587 +{
1588 +  // En theorie: les deux lignes suivantes sont plus efficaces, mais
1589 +  //  cela produit des differences sur certains cas tests
1590 +  //  (Hyd_C_VEF_Smago et Lambda_var_VEF_turb). Ca veut dire qu'il y
1591 +  //  a un probleme autre part mais pour l'instant on laisse l'ancien
1592 +  //  codage.
1593 +  // const double i_dy = 1. / dy;
1594 +  // operator*=(i_dy);
1595 +
1596 +  double * data = addr();
1597 +  const entier n = size_array();
1598 +  for(entier i=0; i < n; i++)
1599 +    data[i] /= dy;
1600 +
1601 +  return *this;
1602 +}
1603 +
1604 +DoubleTab::DoubleTab()
1605 +{
1606 +  // nb_dim_ = 2;
1607 +  dimensions_[0] = 0;
1608 +  dimensions_[1] = 0;
1609 +}
1610 +
1611 +DoubleTab::DoubleTab(const DoubleTab& tab) :
1612 +  ArrOfDouble(tab)
1613 +{
1614 +  // nb_dim_ = tab.nb_dim_;
1615 +  dimensions_[0] = tab.dimensions_[0];
1616 +  dimensions_[1] = tab.dimensions_[1];
1617 +}
1618 +DoubleTab::DoubleTab(const entier i, const entier j) :
1619 +  ArrOfDouble(i*j)
1620 +{
1621 +  // nb_dim_ = 2;
1622 +  dimensions_[0] = i;
1623 +  dimensions_[1] = j;
1624 +}
1625 +
1626 +DoubleTab& DoubleTab::operator=(const DoubleTab& tab)
1627 +{
1628 +  ArrOfDouble::operator=(tab);
1629 +  // nb_dim_ = tab.nb_dim_;
1630 +  dimensions_[0] = tab.dimensions_[0];
1631 +  dimensions_[1] = tab.dimensions_[1];
1632 +  return *this;
1633 +}
1634 +
1635 +void DoubleTab::reset()
1636 +{
1637 +  ArrOfDouble::reset();
1638 +  // nb_dim_ = 2;
1639 +  dimensions_[0] = 0;
1640 +  dimensions_[1] = 0;
1641 +}
1642 +
1643 diff --git a/databases/readers/Lata/ArrOfDouble.h b/databases/readers/Lata/ArrOfDouble.h
1644 new file mode 100644
1645 index 0000000..fcc08f1
1646 --- /dev/null
1647 +++ b/databases/readers/Lata/ArrOfDouble.h
1648 @@ -0,0 +1,353 @@
1649 +/*****************************************************************************
1650 +*
1651 +* Copyright (c) 2011 - 2013, CEA
1652 +* All rights reserved.
1653 +* Redistribution and use in source and binary forms, with or without
1654 +* modification, are permitted provided that the following conditions are met:
1655 +*
1656 +*     * Redistributions of source code must retain the above copyright
1657 +*       notice, this list of conditions and the following disclaimer.
1658 +*     * Redistributions in binary form must reproduce the above copyright
1659 +*       notice, this list of conditions and the following disclaimer in the
1660 +*       documentation and/or other materials provided with the distribution.
1661 +*     * Neither the name of CEA, nor the
1662 +*       names of its contributors may be used to endorse or promote products
1663 +*       derived from this software without specific prior written permission.
1664 +*
1665 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
1666 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1667 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1668 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
1669 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1670 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1671 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1672 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1673 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1674 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1675 +*
1676 +*****************************************************************************/
1677 +
1678 +////////////////////////////////////////////////////////////
1679 +//
1680 +// Warning : DO NOT EDIT !
1681 +//          Please update ArrOf_Scalar_Prototype.h.P
1682 +//          and this file will be generated automatically
1683 +//           by the script file check.sh
1684 +////////////////////////////////////////////////////////////
1685 +
1686 +#ifndef ArrOfDouble_H
1687 +#define ArrOfDouble_H
1688 +
1689 +#include <assert.h>
1690 +#include <arch.h>
1691 +#include <Objet_U.h>
1692 +
1693 +#if ! defined(DMAXFLOAT)
1694 +#define DMAXFLOAT 1e40
1695 +#endif
1696 +
1697 +class VDoubledata;
1698 +
1699 +class ArrOfDouble
1700 +{
1701 +public:
1702 +  //
1703 +  // Destructeur
1704 +  //
1705 +  virtual ~ArrOfDouble();
1706 +  //
1707 +  // Constructeurs
1708 +  //
1709 +  ArrOfDouble();
1710 +  ArrOfDouble(entier size);
1711 +  ArrOfDouble(entier size, double initial_value);
1712 +  // Constructeur par copie : deep copy (on duplique les donnees)
1713 +  ArrOfDouble(const ArrOfDouble& );
1714 +  //
1715 +  // Methodes de construction tardive (on cree un tableau vide avec ArrOfDouble()
1716 +  // puis on appelle ces methodes pour modifier les caracteristiques du tableau :
1717 +  //
1718 +  // Change le nombre d'elements du tableau
1719 +  inline ArrOfDouble& resize_array(entier new_size);
1720 +
1721 +  // Methodes de gestion de l'allocation memoire:
1722 +  // Assigne une valeur au drapeau "smart_resize"
1723 +  // (reallocation uniquement si la taille augmente)
1724 +  void    set_smart_resize(entier flag);
1725 +  // Gestion du type de memoire alouee (standard ou pool de memoire Trio-U)
1726 +  enum    Storage { STANDARD, TEMP_STORAGE, SIMD_ALIGNED };
1727 +  void    set_mem_storage(const Storage storage);
1728 +  Storage get_mem_storage() const;
1729 +
1730 +  // Construction de tableaux qui pointent vers des donnees existantes
1731 +  // !!! Utiliser ref_data avec precaution (attention a size_array_)
1732 +  ArrOfDouble& ref_data(double* ptr, entier size);
1733 +  ArrOfDouble& ref_array(const ArrOfDouble&);
1734 +  // Operateur copie
1735 +  ArrOfDouble& operator=(const ArrOfDouble&);
1736 +  // Remise du tableau dans l'etat initial (obtenu par le constructeur par defaut)
1737 +  virtual void reset();
1738 +
1739 +  //
1740 +  // Methodes d'acces aux donnees et aux caracteristiques du tableau
1741 +  //
1742 +  // Remplit le tableau avec la valeur en parametre
1743 +  ArrOfDouble& operator=(double valeur);
1744 +
1745 +  inline       double& operator[](entier i);
1746 +  inline const double& operator[](entier i) const;
1747 +
1748 +  // Ces methodes renvoient un pointeur vers le premier element du tableau.
1749 +  const double * addr() const;
1750 +  double * addr();
1751 +  // Renvoie le nombre d'elements du tableau (et non la taille allouee)
1752 +  inline entier size_array() const;
1753 +  // Renvoie le nombre de tableaux qui pointent vers la stucture "*p_"
1754 +  entier ref_count() const;
1755 +  // Ajoute une case en fin de tableau et y stocke la "valeur"
1756 +  inline void   append_array(double valeur);
1757 +
1758 +  //
1759 +  // Operateurs divers
1760 +  //
1761 +  ArrOfDouble& operator+=(const ArrOfDouble&);
1762 +  ArrOfDouble& operator+=(const double);
1763 +  ArrOfDouble& operator-=(const ArrOfDouble&);
1764 +  ArrOfDouble& operator-=(const double);
1765 +  ArrOfDouble& inject_array(const ArrOfDouble& source,
1766 +                            entier nb_elements = -1,
1767 +                            entier first_element_dest = 0,
1768 +                            entier first_element_source = 0);
1769 +  ArrOfDouble& copy_array(const ArrOfDouble&);
1770 +
1771 +  ArrOfDouble& operator*= (const double) ;
1772 +  ArrOfDouble& operator/= (const double) ;
1773 +
1774 +  void             ordonne_array();
1775 +
1776 +protected:
1777 +  //
1778 +  // Methodes accessibles depuis les descendants de ArrOfDouble
1779 +  //
1780 +  void   attach_array(const ArrOfDouble&);
1781 +  entier detach_array();
1782 +  void   fill_default_value(entier first, entier nb);
1783 +private:
1784 +  // B. Mathieu 22/06/2004 : je mets ces membres "private" pour forcer
1785 +  // le passage par les accesseurs dans les classes derivees, au cas ou
1786 +  // on voudrait modifier l'implementation.
1787 +
1788 +  // Zone de memoire contenant les valeurs du tableau.
1789 +  // Pointeur nul => le tableau est "detache" ou "ref_data"
1790 +  // Pointeur non nul => le tableau est "normal"
1791 +  VDoubledata* p_;
1792 +
1793 +  // Pointeur vers le premier element du tableau (egal a p_->data si p_!=0)
1794 +  // Pointeur nul => le tableau est "detache".
1795 +  // Pointeur non nul => le tableau est "normal" ou "ref_data"
1796 +  double*   data_;
1797 +
1798 +  // Nombre d'elements du tableau (inferieur ou egal a memory_size_).
1799 +  // Si le tableau est "detache", alors size_array_=0
1800 +  entier    size_array_;
1801 +  // Taille memoire reellement allouee pour le tableau
1802 +  // (pour le mecanisme smart_resize_). memory_size_ est nul
1803 +  // si le tableau est de type "ref_data". Sinon memory_size_
1804 +  // est egal a p_->size_.
1805 +  entier    memory_size_;
1806 +
1807 +  // Drapeau indiquant si on applique une strategie d'allocation
1808 +  // preventive (la memoire alouee augmente d'un facteur constant
1809 +  // si la taille devient insuffisante).
1810 +  // Si smart_resize_ == 0, alors on a toujours p_->size_ == size
1811 +  entier    smart_resize_;
1812 +
1813 +  // Drapeau indiquant si l'allocation memoire a lieu avec un new classique
1814 +  // ou dans le pool de memoire temporaire de Trio
1815 +  Storage   storage_type_;
1816 +
1817 +  // Partie non inline de resize_array():
1818 +  // Declaration des constantes pour les options de memory_resize
1819 +  static const entier COPY_OLD;
1820 +  static const entier INITIALIZE_NEW;
1821 +  void memory_resize(entier new_size, entier options);
1822 +};
1823 +
1824 +#define MAXDIMDoubleTab 2
1825 +
1826 +class DoubleTab : public ArrOfDouble
1827 +{
1828 +public:
1829 +  DoubleTab();
1830 +  DoubleTab(const DoubleTab&);
1831 +  DoubleTab(const entier i, const entier j);
1832 +  DoubleTab&    operator=(const DoubleTab&);
1833 +  void              reset();
1834 +
1835 +  inline double& operator()(entier i, entier j);
1836 +  inline double   operator()(entier i, entier j) const;
1837 +
1838 +  inline entier resize(entier i, entier j);
1839 +  inline entier dimension(entier i) const;
1840 +  inline entier dimension_tot(entier i) const;
1841 +
1842 +protected:
1843 +  // In order to mimic TRUST behavior, operator[] is forbidden
1844 +  // for 2 dimensionnal matrices, you must cast to ArrOf to use it..
1845 +  double&        operator[](entier i);
1846 +  const double& operator[](entier i) const;
1847 +
1848 +private:
1849 +  //  entier nb_dim_;
1850 +  entier dimensions_[MAXDIMDoubleTab];
1851 +};
1852 +
1853 +inline double& DoubleTab::operator()(entier i, entier j)
1854 +{
1855 +  // assert(nb_dim_ == 2);
1856 +  assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]);
1857 +  const entier n = i * dimensions_[1] + j;
1858 +  double& x = ArrOfDouble::operator[] (n);
1859 +  return x;
1860 +}
1861 +
1862 +inline double   DoubleTab::operator()(entier i, entier j) const
1863 +{
1864 +  // assert(nb_dim_ == 2);
1865 +  assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]);
1866 +  const entier n = i * dimensions_[1] + j;
1867 +  double x = ArrOfDouble::operator[] (n);
1868 +  return x;
1869 +}
1870 +
1871 +inline entier DoubleTab::resize(entier i, entier j)
1872 +{
1873 +  assert(i >= 0 && j >= 0);
1874 +  // nb_dim_ = 2;
1875 +  dimensions_[0] = i;
1876 +  dimensions_[1] = j;
1877 +  ArrOfDouble::resize_array(i * j);
1878 +  return i*j;
1879 +}
1880 +
1881 +inline entier DoubleTab::dimension(entier i) const
1882 +{
1883 +  assert(i >= 0 && i < 2);
1884 +  return dimensions_[i];
1885 +}
1886 +
1887 +// Description: renvoie la meme valeur que dimension.
1888 +inline entier DoubleTab::dimension_tot(entier i) const
1889 +{
1890 +  return dimension(i);
1891 +}
1892 +
1893 +//
1894 +// Declarations des fonctions non membres de la classe ArrOfDouble
1895 +//
1896 +entier operator==(const ArrOfDouble& x, const ArrOfDouble& y) ;
1897 +entier imin_array(const ArrOfDouble&) ;
1898 +entier imax_array(const ArrOfDouble&) ;
1899 +double min_array(const ArrOfDouble&) ;
1900 +double max_array(const ArrOfDouble&) ;
1901 +
1902 +double max_abs_array(const ArrOfDouble&) ;
1903 +
1904 +// ******************************************************************
1905 +//                   FONCTIONS MEMBRES DE ArrOfDouble
1906 +// ******************************************************************
1907 +
1908 +// Description :
1909 +//  Change le nombre d'elements du tableau. Cette fonction est inline
1910 +//  car elle doit etre tres rapide dans le cas ou smart_resize_==1
1911 +//  (utilisation frequente de resize_array())
1912 +//  Si smart_resize est non nul :
1913 +//   Si la nouvelle taille est inferieure ou egale a la taille
1914 +//   alouee (p->get_size()) on ne realloue pas de memoire
1915 +//   sinon, on realloue et on copie les donnees existantes.
1916 +//  Astuce pour ne pas copier les anciennes donnees:
1917 +//   resize(0); resize(n);
1918 +//  Si smart_resize est nul, on realloue une nouvelle zone memoire
1919 +//   uniquement si la nouvelle taille est differente de l'ancienne.
1920 +// Precondition :
1921 +//  Si "new_size" est egal a la taille du tableau, aucune condition.
1922 +//  Sinon, le tableau doit etre soit detache, soit normal (pas de type "ref_data")
1923 +//  et ref_count doit etre egal a 1 (pas d'autre reference au tableau).
1924 +//
1925 +inline ArrOfDouble& ArrOfDouble::resize_array(entier new_size)
1926 +{
1927 +  assert(new_size >= 0);
1928 +  // Soit le tableau est detache (data_==0), soit il est normal (p_!=0)
1929 +  // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau,
1930 +  // ou alors la taille ne doit pas changer.
1931 +  assert(new_size == size_array_ || data_ == 0 || (p_ != 0 && ref_count() == 1));
1932 +
1933 +  if ((smart_resize_ == 0) || (new_size > memory_size_))
1934 +    memory_resize(new_size, COPY_OLD + INITIALIZE_NEW);
1935 +  size_array_ = new_size;
1936 +  return *this;
1937 +}
1938 +
1939 +// Description:
1940 +//     operateur [] retourne le ieme element du tableau
1941 +// Precondition:
1942 +// Parametre: entier i
1943 +//    Signification: indice dans l'intervalle 0 <= i < size_array()
1944 +// Exception:
1945 +//    assert si la valeur sort de l'intervalle : [ -DMAXFLOAT,DMAXFLOAT ]
1946 +//    assert si i n'est pas dans l'intervalle
1947 +inline double& ArrOfDouble::operator[](entier i)
1948 +{
1949 +  assert(i >= 0 && i < size_array_);
1950 +  assert((smart_resize_==1)|| (data_[i] > -DMAXFLOAT && data_[i] < DMAXFLOAT));
1951 +  return data_[i];
1952 +}
1953 +
1954 +// Description:
1955 +//     operateur [] retourne le ieme element du tableau
1956 +// Precondition:
1957 +// Parametre: entier i
1958 +//    Signification: indice dans l'intervalle 0 <= i < size_array()
1959 +// Exception:
1960 +//    assert si la valeur sort de l'intervalle : [ -DMAXFLOAT,DMAXFLOAT ]
1961 +//    assert si i n'est pas dans l'intervalle
1962 +inline const double& ArrOfDouble::operator[](entier i) const
1963 +{
1964 +  assert(i >= 0 && i < size_array_);
1965 +  assert(data_[i] > -DMAXFLOAT && data_[i] < DMAXFLOAT);
1966 +  return data_[i];
1967 +}
1968 +
1969 +// Description:
1970 +//    Renvoie la taille du tableau (nombre d'elements declares
1971 +//    a la construction ou a resize_array()).
1972 +//    C'est le nombre d'elements accessibles a operator[]
1973 +// Retour: entier
1974 +inline entier  ArrOfDouble::size_array() const
1975 +{
1976 +  return size_array_;
1977 +}
1978 +
1979 +// Description:
1980 +//  Ajoute une case en fin de tableau et y stocke la "valeur"
1981 +// Precondition:
1982 +//  Tableau doit etre de type "smart_resize" (sinon, ecroulement
1983 +//  des performances). De plus, le tableau ne doit pas etre "ref_data",
1984 +//  et il ne doit pas y avoir plus d'une reference a la zone de
1985 +//  memoire pointee (meme precondition que resize_array())
1986 +inline void   ArrOfDouble::append_array(double valeur)
1987 +{
1988 +  assert(smart_resize_);
1989 +  // Soit le tableau est detache (data_==0), soit il est normal (p_!=0)
1990 +  // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau.
1991 +  assert(data_ == 0 || (p_ != 0 && ref_count() == 1));
1992 +
1993 +  if (size_array_+1 > memory_size_)
1994 +    memory_resize(size_array_+1, COPY_OLD);
1995 +  data_[size_array_] = valeur;
1996 +  size_array_++;
1997 +}
1998 +
1999 +// ArrOfDouble_H
2000 +#endif
2001 +
2002 diff --git a/databases/readers/Lata/ArrOfFloat.C b/databases/readers/Lata/ArrOfFloat.C
2003 new file mode 100644
2004 index 0000000..dd59a24
2005 --- /dev/null
2006 +++ b/databases/readers/Lata/ArrOfFloat.C
2007 @@ -0,0 +1,1185 @@
2008 +/*****************************************************************************
2009 +*
2010 +* Copyright (c) 2011 - 2013, CEA
2011 +* All rights reserved.
2012 +* Redistribution and use in source and binary forms, with or without
2013 +* modification, are permitted provided that the following conditions are met:
2014 +*
2015 +*     * Redistributions of source code must retain the above copyright
2016 +*       notice, this list of conditions and the following disclaimer.
2017 +*     * Redistributions in binary form must reproduce the above copyright
2018 +*       notice, this list of conditions and the following disclaimer in the
2019 +*       documentation and/or other materials provided with the distribution.
2020 +*     * Neither the name of CEA, nor the
2021 +*       names of its contributors may be used to endorse or promote products
2022 +*       derived from this software without specific prior written permission.
2023 +*
2024 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
2025 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2026 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2027 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
2028 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2029 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2030 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2031 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2032 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2033 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2034 +*
2035 +*****************************************************************************/
2036 +
2037 +////////////////////////////////////////////////////////////
2038 +//
2039 +// Warning : DO NOT EDIT !
2040 +//          Please update ArrOf_Scalar_Prototype.cpp.h
2041 +//          and this file will be generated automatically
2042 +//           by the script file check.sh
2043 +////////////////////////////////////////////////////////////
2044 +
2045 +#include <ArrOfFloat.h>
2046 +#include <math.h>
2047 +#include <stdlib.h>
2048 +#include <Objet_U.h>
2049 +#include <iostream>
2050 +#include <stdlib.h>
2051 +#include <string.h>
2052 +#include "simd_interface.h"
2053 +
2054 +using namespace std;
2055 +
2056 +// ******************************************************************
2057 +//
2058 +//             Implementation des methodes de VFloatdata
2059 +//
2060 +// ******************************************************************
2061 +////////////////////////////////////////////////////////////////////
2062 +// .NOM        ArrOfFloat
2063 +// .ENTETE     TRUST Math
2064 +// .LIBRAIRIE  libtmath
2065 +// .FILE       ArrOfFloat.h
2066 +// .FILE       ArrOfFloat.cpp
2067 +//
2068 +// .DESCRIPTION
2069 +// VFloatdata alloue une zone de memoire de la taille specifiee au
2070 +// constructeur, et libere la zone de memoire a la destruction.
2071 +//
2072 +// "ref_count" compte le nombre de pointeurs qui font reference a "this".
2073 +// (permet au dernier utilisateur de l'objet de le detruire), voir
2074 +// ArrOfFloat.
2075 +//
2076 +// .SECTION voir aussi
2077 +// .CONTRAINTES
2078 +// .INVARIANTS
2079 +// .HTML
2080 +// .EPS
2081 +///////////////////////////////////////////////////////////////////
2082 +
2083 +class VFloatdata
2084 +{
2085 +public:
2086 +  VFloatdata(entier size, ArrOfFloat::Storage storage);
2087 +  ~VFloatdata();
2088 +  entier          add_one_ref();
2089 +  entier          suppr_one_ref();
2090 +  float *        get_data();
2091 +  const float *  get_data() const;
2092 +  inline entier   ref_count() const;
2093 +  inline entier   get_size() const;
2094 +private:
2095 +  // Le constructeur par copie et l'operateur= sont interdits.
2096 +  VFloatdata(const VFloatdata& v);
2097 +  VFloatdata& operator=(const VFloatdata& v);
2098 +
2099 +  // "data" est un pointeur sur une zone de memoire de taille
2100 +  // sz * sizeof(float), allouee par le
2101 +  // constructeur et liberee par le destructeur.
2102 +  // Ce pointeur n'est jamais nul meme si size_==0
2103 +  float * data_;
2104 +  // Compteur incremente par add_one_ref et decremente par suppr_one_ref.
2105 +  // Contient le nombre d'objets ArrOfFloat dont le membre "p" pointe
2106 +  // vers "this". On a ref_count_ >= 0.
2107 +  entier ref_count_;
2108 +  // "sz" est la taille du tableau "data_" alloue
2109 +  // On a sz >= 0.
2110 +  entier size_;
2111 +  ArrOfFloat::Storage storage_;
2112 +};
2113 +
2114 +
2115 +// Description:
2116 +//    Construit un VFloatdata de taille size >= 0
2117 +// Parametre: entier s
2118 +//    Signification: taille du VFloatdata, il faut size >= 0
2119 +// Parametre: Storage storage
2120 +//    Signification: indique si la memoire doit etre allouee
2121 +//                   avec "new" ou avec "simd_malloc"
2122 +//    Valeurs par defaut: STANDARD (allocation avec "new")
2123 +// Postcondition:
2124 +//    data_ n'est jamais nul, meme si size==0
2125 +VFloatdata::VFloatdata(entier size, ArrOfFloat::Storage storage)
2126 +{
2127 +  if (size == 0)
2128 +    storage = ArrOfFloat::STANDARD;
2129 +
2130 +  switch (storage)
2131 +    {
2132 +    case ArrOfFloat::STANDARD:
2133 +      {
2134 +#ifdef _EXCEPTION_
2135 +        // Allocation de la memoire sur le tas
2136 +        try
2137 +          {
2138 +            data_ = new float[size];
2139 +          }
2140 +        catch(...)
2141 +          {
2142 +            Cerr << "impossible d'allouer " << size << " float " << finl;
2143 +            throw;
2144 +          }
2145 +#else
2146 +        data_ = new float[size];
2147 +        if(!data_)
2148 +          {
2149 +            Cerr << "impossible d'allouer " << size << "float " << finl;
2150 +            throw ;
2151 +          }
2152 +#endif
2153 +        break;
2154 +      }
2155 +    case ArrOfFloat::SIMD_ALIGNED:
2156 +      {
2157 +#ifdef SIMD_TOOLS_H
2158 +        data_ = (float*) simd_malloc (sizeof(float) * size);
2159 +#else
2160 +        Cerr<<"unable to allocate simd_aligned, version compiled without simd "<<finl;
2161 +        throw;
2162 +#endif
2163 +        break;
2164 +      }
2165 +    default:
2166 +      throw;
2167 +    }
2168 +  ref_count_ = 1;
2169 +  size_ = size;
2170 +  storage_ = storage;
2171 +  assert(data_ != 0);
2172 +}
2173 +
2174 +// Description:
2175 +//  Detruit la zone de memoire allouee.
2176 +// Precondition:
2177 +//  ref_count == 0 (la zone de memoire ne doit etre referencee nulle part)
2178 +VFloatdata::~VFloatdata()
2179 +{
2180 +  assert(ref_count_ == 0);
2181 +
2182 +  // Stockage STANDARD
2183 +  switch(storage_)
2184 +    {
2185 +    case ArrOfFloat::STANDARD:
2186 +      delete[] data_;
2187 +      break;
2188 +    case ArrOfFloat::SIMD_ALIGNED:
2189 +#ifdef SIMD_TOOLS_H
2190 +      simd_free(data_);
2191 +#else
2192 +      Cerr<<"unable to allocate simd_aligned, version compiled without simd "<<finl;
2193 +      throw;
2194 +#endif
2195 +      break;
2196 +    default:
2197 +      throw;
2198 +    }
2199 +
2200 +  data_ = 0;  // paranoia: si size_==-1 c'est qu'on pointe sur un zombie
2201 +  size_ = -1; //  (pointeur vers un objet qui a ete detruit)
2202 +  storage_ = ArrOfFloat::STANDARD;
2203 +}
2204 +
2205 +// Description: renvoie ref_count_
2206 +inline entier VFloatdata::ref_count() const
2207 +{
2208 +  return ref_count_;
2209 +}
2210 +
2211 +// Description: renvoie size_
2212 +inline entier VFloatdata::get_size() const
2213 +{
2214 +  return size_;
2215 +}
2216 +
2217 +// Description:
2218 +//     Un nouveau tableau utilise cette zone memoire :
2219 +//     incremente ref_count
2220 +// Retour: int
2221 +//    Signification: ref_count
2222 +inline entier VFloatdata::add_one_ref()
2223 +{
2224 +  return ++ref_count_;
2225 +}
2226 +
2227 +// Description:
2228 +//     Un tableau de moins utilise cette zone memoire
2229 +//     decremente ref_count
2230 +// Precondition:
2231 +//     ref_count_ > 0
2232 +// Retour: int
2233 +//    Signification: ref_count
2234 +inline entier VFloatdata::suppr_one_ref()
2235 +{
2236 +  assert(ref_count_ > 0);
2237 +  return (--ref_count_);
2238 +}
2239 +
2240 +// Description: renvoie data_
2241 +inline float * VFloatdata::get_data()
2242 +{
2243 +  return data_;
2244 +}
2245 +
2246 +// Description: renvoie data_
2247 +inline const float * VFloatdata::get_data() const
2248 +{
2249 +  return data_;
2250 +}
2251 +
2252 +// Description: Constructeur par copie. Interdit : genere une erreur !
2253 +VFloatdata::VFloatdata(const VFloatdata& v)
2254 +{
2255 +  Cerr << "Erreur dans VFloatdata::VFloatdata(const VFloatdata & v)" << finl;
2256 +  throw;
2257 +}
2258 +
2259 +// Description: Operateur= interdit. Genere une erreur !
2260 +VFloatdata& VFloatdata::operator=(const VFloatdata& v)
2261 +{
2262 +  Cerr << "Erreur dans VFloatdata::operator=(const VFloatdata & v)" << finl;
2263 +  throw;
2264 +  return *this;
2265 +}
2266 +
2267 +// ******************************************************************
2268 +//
2269 +//             Implementation des methodes de ArrOfFloat
2270 +//
2271 +// ******************************************************************
2272 +
2273 +
2274 +// Definition des constantes pour les options de memory_resize
2275 +const entier ArrOfFloat::COPY_OLD = 1;
2276 +const entier ArrOfFloat::INITIALIZE_NEW = 2;
2277 +
2278 +// Description:
2279 +//  Destructeur : appelle detach_array()
2280 +ArrOfFloat::~ArrOfFloat()
2281 +{
2282 +  detach_array();
2283 +  size_array_ = -1; // Paranoia: si size_array_==-1, c'est un zombie
2284 +}
2285 +
2286 +// Description:
2287 +//  Constructeur par defaut: cree un tableau "detache",
2288 +//  soit p_==0, data_==0, size_array_==0, smart_resize_==0
2289 +ArrOfFloat::ArrOfFloat() :
2290 +  p_(0),
2291 +  data_(0),
2292 +  size_array_(0),
2293 +  memory_size_(0),
2294 +  smart_resize_(0),
2295 +  storage_type_(STANDARD)
2296 +{
2297 +}
2298 +
2299 +// Description:
2300 +//     Cree un tableau de taille n avec allocation standard
2301 +//     (voir set_mem_storage).
2302 +//     Valeur de remplissage par defaut: voir fill_default_value
2303 +// Precondition:
2304 +// Parametre: entier n
2305 +//    Signification: taille du tableau
2306 +ArrOfFloat::ArrOfFloat(entier n) :
2307 +  p_(new VFloatdata(n, STANDARD)),
2308 +  data_(p_->get_data()),
2309 +  size_array_(n),
2310 +  memory_size_(n),
2311 +  smart_resize_(0),
2312 +  storage_type_(STANDARD)
2313 +{
2314 +  if (n > 0)
2315 +    fill_default_value(0, n);
2316 +}
2317 +
2318 +// Description:
2319 +//     Cree un tableau de taille n
2320 +//     toutes les cases sont initialisees a x
2321 +// Precondition:
2322 +// Parametre: entier n
2323 +//    Signification: taille du tableau
2324 +// Parametre: float x
2325 +//    Signification: valeur pour initialiser le tableau
2326 +ArrOfFloat::ArrOfFloat(entier n, float x) :
2327 +  p_(new VFloatdata(n, STANDARD)),
2328 +  data_(p_->get_data()),
2329 +  size_array_(n),
2330 +  memory_size_(n),
2331 +  smart_resize_(0),
2332 +  storage_type_(STANDARD)
2333 +{
2334 +  *this = x;
2335 +}
2336 +
2337 +// Description:
2338 +//     Constructeur par copie. On alloue une nouvelle zone de memoire
2339 +//     et on copie le contenu du tableau. L'attribut smart_resize_ est
2340 +//     copie aussi.
2341 +//     Si le tableau A est de taille nulle, on cree un tableau "detache",
2342 +//     sinon on cree un tableau "normal".
2343 +// Parametre: const ArrOfFloat& A
2344 +//    Signification: le tableau a copier
2345 +ArrOfFloat::ArrOfFloat(const ArrOfFloat& A)
2346 +{
2347 +  const entier size = A.size_array();
2348 +  if (size > 0)
2349 +    {
2350 +      // Creation d'un tableau "normal"
2351 +      storage_type_ = STANDARD;
2352 +      p_ = new VFloatdata(size, STANDARD);
2353 +      data_ = p_->get_data();
2354 +      size_array_ = size;
2355 +      memory_size_ = size;
2356 +      smart_resize_ = A.smart_resize_;
2357 +      inject_array(A);
2358 +    }
2359 +  else
2360 +    {
2361 +      // Creation d'un tableau "detache"
2362 +      p_ = 0;
2363 +      data_ = 0;
2364 +      size_array_ = 0;
2365 +      memory_size_ = 0;
2366 +      smart_resize_ = 0;
2367 +      storage_type_ = STANDARD;
2368 +    }
2369 +}
2370 +
2371 +// Description:
2372 +//   Change le mode d'allocation memoire lors des resize
2373 +//   (voir VFloatdata et Float_ptr_trav)
2374 +//   Exemple pour creer un tableau avec allocation temporaire:
2375 +//    DoubleTab tab; // Creation d'un tableau vide
2376 +//    tab.set_mem_storage(TEMP_STORAGE); // Changement de mode d'allocation
2377 +//    tab.resize(n); // Allocation memoire
2378 +void ArrOfFloat::set_mem_storage(const Storage storage)
2379 +{
2380 +  storage_type_ = storage;
2381 +}
2382 +
2383 +// Description:
2384 +//   Renvoie le mode d'allocation du tableau (qui sera utilise
2385 +//   lors du prochain resize si changement de taille).
2386 +//   (voir VFloatdata et Float_ptr_trav)
2387 +enum ArrOfFloat::Storage ArrOfFloat::get_mem_storage() const
2388 +{
2389 +  return storage_type_;
2390 +}
2391 +
2392 +// Description:
2393 +//   Change le mode l'allocation memoire: reallocation d'un tableau
2394 +//   a chaque changement de taille (flag = 0) ou reallocation
2395 +//   uniquement si la taille augmente et par doublement de la taille
2396 +//   du tableau (flag = 1).
2397 +void ArrOfFloat::set_smart_resize(entier flag)
2398 +{
2399 +  assert(flag == 0 || flag == 1);
2400 +  smart_resize_ = flag;
2401 +}
2402 +
2403 +// Description:
2404 +//    Remet le tableau dans l'etat obtenu avec le constructeur par defaut
2405 +//    (libere la memoire mais conserve le mode d'allocation memoire actuel)
2406 +void ArrOfFloat::reset()
2407 +{
2408 +  detach_array();
2409 +}
2410 +
2411 +// Description:
2412 +//    Copie les donnees du tableau m.
2413 +//    Si "m" n'a pas la meme taille que "*this", on fait un resize_array.
2414 +//    Ensuite, on copie les valeurs de "m" dans "*this".
2415 +//    Le type de tableau (methode d'allocation) n'est pas copie.
2416 +// Precondition:
2417 +//    Si le tableau n'a pas la meme taille que "m", alors *this doit
2418 +//    etre "resizable" (ne pas etre de type "ref_data" et "ref_count == 1")
2419 +// Parametre: const ArrOfFloat& m
2420 +//    Signification: la tableau a copier
2421 +// Retour:  ArrOfFloat&
2422 +//    Signification: *this
2423 +ArrOfFloat& ArrOfFloat::operator=(const ArrOfFloat& m)
2424 +{
2425 +  if (&m != this)
2426 +    {
2427 +      const entier new_size = m.size_array();
2428 +      // Le code suivant est quasiment une copie de ArrOfFloat::resize()
2429 +      // SAUF: memory_resize est appele avec NO_INITIALIZE (la zone de memoire
2430 +      //  n'est pas initialisee)
2431 +      if (new_size != size_array())
2432 +        {
2433 +          if ((smart_resize_ == 0) || (new_size > memory_size_))
2434 +            memory_resize(new_size, 0); // Pas d'initialisation
2435 +          size_array_ = new_size;
2436 +        }
2437 +      inject_array(m);
2438 +    }
2439 +  return *this;
2440 +}
2441 +
2442 +
2443 +// Description:
2444 +//     x est affecte a toutes les cases
2445 +// Precondition:
2446 +// Parametre: float x
2447 +//    Signification: la valeur a affecter a toutes les cases du tableau
2448 +//    Valeurs par defaut:
2449 +//    Contraintes:
2450 +//    Acces:
2451 +// Retour: ArrOfFloat&
2452 +//    Signification: *this
2453 +//    Contraintes:
2454 +// Exception:
2455 +// Effets de bord:
2456 +// Postcondition:
2457 +ArrOfFloat& ArrOfFloat::operator=(float x)
2458 +{
2459 +  const entier n = size_array();
2460 +  float *data = addr();
2461 +  for (entier i = 0; i < n; i++)
2462 +    {
2463 +      data[i] = x;
2464 +    }
2465 +  return *this;
2466 +}
2467 +
2468 +// Description: appelle operator=(a)
2469 +ArrOfFloat& ArrOfFloat::copy_array(const ArrOfFloat& a)
2470 +{
2471 +  operator=(a);
2472 +  return *this;
2473 +}
2474 +
2475 +// Description:
2476 +//  Si besoin, alloue une nouvelle zone de memoire,
2477 +//  copie les donnees et efface l'ancienne zone de memoire.
2478 +//  Attention, on suppose que cette methode est appelee par
2479 +//  resize_array().
2480 +//  Attention: si ref_count_>1, l'appel a resize_array() est
2481 +//  autorise uniquement si la nouvelle taille est identique
2482 +//  a la precedente.
2483 +// Precondition:
2484 +//  Le tableau doit etre de type "detache" ou "normal" avec
2485 +//  ref_count==1, et il faut new_size >= 0
2486 +//  On suppose que size_array contient encore le nombre d'elements
2487 +//  valides avant changement de taille.
2488 +// Parametre: new_size
2489 +//  Signification: nouvelle taille demandee pour le tableau.
2490 +// Parametre: options
2491 +//  Signification: COPY_OLD => on recopie les anciennes donnees dans le nouveau
2492 +//                  tableau (jusqu'au max de l'ancienne et de la nouvelle taille).
2493 +//                 INITIALIZE_NEW => initialisation des cases non copiees
2494 +// Postcondition:
2495 +//  p_ et data_ sont mis a jour, mais pas size_array_ !!!
2496 +//  (on suppose que c'est fait dans resize_array()).
2497 +//  Si la nouvelle taille est nulle, on detache le tableau.
2498 +void  ArrOfFloat::memory_resize(entier new_size, entier options)
2499 +{
2500 +  assert(new_size >= 0);
2501 +
2502 +  // Occupation memoire de l'ancien tableau:
2503 +  entier old_mem_size = 0;
2504 +  if (p_)
2505 +    old_mem_size = p_->get_size();
2506 +
2507 +  // Occupation memoire du nouveau tableau :
2508 +  // Si smart_resize, on prend au moins deux fois la taille
2509 +  // precedente, ou new_size
2510 +  entier new_mem_size = new_size;
2511 +  if (smart_resize_ && (old_mem_size * 2 > new_size))
2512 +    new_mem_size = old_mem_size * 2;
2513 +
2514 +  if (new_mem_size != old_mem_size)
2515 +    {
2516 +      // detach_array() efface le contenu de size_array_. On le met de cote:
2517 +      const entier old_size_array = size_array_;
2518 +      // On va reellement changer l'adresse du tableau.
2519 +      // Il ne faut pas qu'il existe d'autre reference a ce tableau.
2520 +      assert(data_ == 0 || (p_ != 0 && ref_count() == 1));
2521 +      if (new_mem_size == 0)
2522 +        {
2523 +          // La nouvelle taille est nulle, on cree un tableau "detache"
2524 +          detach_array();
2525 +        }
2526 +      else
2527 +        {
2528 +          // Allocation d'une nouvelle zone
2529 +          VFloatdata * new_p = new VFloatdata(new_mem_size, storage_type_);
2530 +          float * new_data = new_p->get_data();
2531 +          // Raccourci si le tableau etait "detache", inutile de copier
2532 +          // les anciennes donnees. On copie si COPY_OLD est demande
2533 +          entier copy_size = 0;
2534 +          if (data_ != 0)
2535 +            {
2536 +              // Calcul du nombre d'elements a copier vers la nouvelle
2537 +              // zone de memoire : c'est le min de l'ancienne et de
2538 +              // la nouvelle taille.
2539 +              if (options & COPY_OLD)
2540 +                {
2541 +                  copy_size = size_array_;
2542 +                  if (new_size < copy_size)
2543 +                    copy_size = new_size;
2544 +                  // Copie des valeurs dans le nouveau tableau
2545 +                  for (entier i = 0; i < copy_size; i++)
2546 +                    new_data[i] = data_[i];
2547 +                }
2548 +              // Destruction de l'ancienne zone (si plus aucune reference)
2549 +              detach_array();
2550 +            }
2551 +          // On attache la nouvelle zone de memoire
2552 +          p_ = new_p;
2553 +          data_ = new_data;
2554 +          memory_size_ = new_mem_size;
2555 +          // Initialisation des cases supplementaires avec une valeur par defaut
2556 +          if (options & INITIALIZE_NEW)
2557 +            fill_default_value(copy_size, new_mem_size - copy_size);
2558 +          // Restaure l'ancienne valeur de size_array_
2559 +          size_array_ = old_size_array;
2560 +        }
2561 +    }
2562 +}
2563 +
2564 +// Description:
2565 +//  Remplit "nb" cases consecutives du tableau a partir de la case "first"
2566 +//  avec une valeur par defaut.
2567 +//  Cette fonction est appelee lors d'un resize pour initialiser les
2568 +//  cases nouvellement creees.
2569 +//  Le comportement depend actuellement du type de tableau :
2570 +//  * Tableau de type "smart_resize":
2571 +//    * en mode debug (macro NDEBUG non definie) le tableau est initialise
2572 +//      avec une valeur invalide.
2573 +//    * en optimise, le tableau n'est pas initialise
2574 +//  * Tableau normal :
2575 +//    Le tableau est initialise avec la valeur 0. Ce comportement est choisi
2576 +//    pour des raisons de compatibilite avec l'implementation precedente.
2577 +//    Cette specification pourrait etre modifiee prochainement pour des raisons
2578 +//    de performances (pour ne pas avoir a initialiser inutilement les tableaux).
2579 +//    DONC: il faut supposer desormais que les nouvelles cases ne sont pas
2580 +//    initialisees lors d'un resize.
2581 +// Parametre: first
2582 +//  Signification: premiere case a initialiser.
2583 +//  Contrainte:    (nb==0) ou (0 <= first < memory_size_)
2584 +// Parametre: nb
2585 +//  Signification: nombre de cases a initialiser.
2586 +//  Contrainte:    (nb==0) ou (0 < nb <= memory_size_ - first)
2587 +void  ArrOfFloat::fill_default_value(entier first, entier nb)
2588 +{
2589 +  assert((nb == 0) || (first >= 0 && first < memory_size_));
2590 +  assert((nb == 0) || (nb > 0 && nb <= memory_size_ - first));
2591 +  float * data = addr();
2592 +  assert(data!=0 || nb==0);
2593 +  data += first;
2594 +  if (smart_resize_)
2595 +    {
2596 +      /*
2597 +          // On initialise uniquement en mode debug
2598 +      #ifndef NDEBUG
2599 +          // Ceci represente un NAN. N'importe quelle operation avec ca fait encore un NAN.
2600 +          // Si c'est pas portable, on peut remplacer par DMAX_FLOAT sur les autres machines.
2601 +          static const unsigned long long  VALEUR_INVALIDE =
2602 +            0x7ff7ffffffffffffULL;
2603 +
2604 +          // On utilise "memcpy" et non "=" car "=" peut provoquer une exception
2605 +          // si la copie passe par le fpu.
2606 +          for (entier i = 0; i < nb; i++)
2607 +            memcpy(data + i, & VALEUR_INVALIDE, sizeof(float));
2608 +      #endif
2609 +      */
2610 +    }
2611 +  else
2612 +    {
2613 +      // Comportement pour les tableaux normaux : compatibilite avec la
2614 +      // version precedente : on initialise avec 0.
2615 +      for (entier i = 0; i < nb; i++)
2616 +        data[i] = (float) 0;
2617 +    }
2618 +}
2619 +
2620 +// ****************************************************************
2621 +//
2622 +//         Fonctions non membres de la classe ArrOfFloat
2623 +//
2624 +// ****************************************************************
2625 +
2626 +// Description:
2627 +//  Renvoie 1 si les tableaux "v" et "a" sont de la meme taille
2628 +//  et contiennent les memes valeurs au sens strict, sinon renvoie 0.
2629 +//  Le test est !(v[i]!=a[i])
2630 +entier operator==(const ArrOfFloat& v, const ArrOfFloat& a)
2631 +{
2632 +  const entier n = v.size_array();
2633 +  const entier na = a.size_array();
2634 +  entier resu = 1;
2635 +  if (n != na)
2636 +    {
2637 +      resu = 0;
2638 +    }
2639 +  else
2640 +    {
2641 +      const float* vv = v.addr();
2642 +      const float* av = a.addr();
2643 +      entier i;
2644 +      for (i = 0; i < n; i++)
2645 +        {
2646 +          if (av[i] != vv[i])
2647 +            {
2648 +              resu = 0;
2649 +              break;
2650 +            }
2651 +        }
2652 +    }
2653 +  return resu;
2654 +}
2655 +
2656 +// Description:
2657 +//    Retourne l'indice du min ou -1 si le tableau est vide
2658 +// Precondition:
2659 +// Parametre: const ArrOfFloat& dx
2660 +//    Signification: tableau a utiliser
2661 +// Retour: int
2662 +//    Signification: indice du min
2663 +entier imin_array(const ArrOfFloat& dx)
2664 +{
2665 +  entier indice_min = -1;
2666 +  const entier size = dx.size_array();
2667 +  if (size > 0)
2668 +    {
2669 +      indice_min = 0;
2670 +      float valeur_min = dx[0];
2671 +      for(entier i = 1; i < size; i++)
2672 +        {
2673 +          const float val = dx[i];
2674 +          if(val < valeur_min)
2675 +            {
2676 +              indice_min = i;
2677 +              valeur_min = val;
2678 +            }
2679 +        }
2680 +    }
2681 +  return indice_min;
2682 +}
2683 +
2684 +// Description:
2685 +//    Retourne l'indice du max ou -1 si le tableau est vide
2686 +// Precondition:
2687 +// Parametre: const ArrOfFloat& dx
2688 +//    Signification: tableau a utiliser
2689 +// Retour: int
2690 +//    Signification: indice du max
2691 +entier imax_array(const ArrOfFloat& dx)
2692 +{
2693 +  entier indice_max = -1;
2694 +  const entier size = dx.size_array();
2695 +  if (size > 0)
2696 +    {
2697 +      indice_max = 0;
2698 +      float valeur_max = dx[0];
2699 +      for(entier i = 1; i < size; i++)
2700 +        {
2701 +          const float val = dx[i];
2702 +          if(val > valeur_max)
2703 +            {
2704 +              indice_max = i;
2705 +              valeur_max = val;
2706 +            }
2707 +        }
2708 +    }
2709 +  return indice_max;
2710 +}
2711 +
2712 +// Description:
2713 +//    Retourne la valeur minimale
2714 +// Precondition:
2715 +//    Le tableau doit contenir au moins une valeur
2716 +// Parametre: const ArrOfFloat& dx
2717 +//    Signification: tableau a utiliser
2718 +// Retour: float
2719 +//    Signification: valeur du min
2720 +float min_array(const ArrOfFloat& dx)
2721 +{
2722 +  const entier size = dx.size_array();
2723 +  assert(size > 0);
2724 +  float valeur_min = dx[0];
2725 +  for(entier i = 1; i < size; i++)
2726 +    {
2727 +      const float val = dx[i];
2728 +      if (val < valeur_min)
2729 +        valeur_min = val;
2730 +    }
2731 +  return valeur_min;
2732 +}
2733 +
2734 +// Description:
2735 +//    Retourne la valeur maximale
2736 +// Precondition:
2737 +//    Le tableau doit contenir au moins une valeur
2738 +// Parametre: const ArrOfFloat& dx
2739 +//    Signification: tableau a utiliser
2740 +// Retour: float
2741 +//    Signification: valeur du max
2742 +float max_array(const ArrOfFloat& dx)
2743 +{
2744 +  const entier size = dx.size_array();
2745 +  assert(size > 0);
2746 +  float valeur_max = dx[0];
2747 +  for(entier i = 1; i < size; i++)
2748 +    {
2749 +      const float val = dx[i];
2750 +      if (val > valeur_max)
2751 +        valeur_max = val;
2752 +    }
2753 +  return valeur_max;
2754 +}
2755 +
2756 +// Description:
2757 +//   Fonction de comparaison utilisee pour trier le tableau
2758 +//   dans ArrOfFloat::trier(). Voir man qsort
2759 +static int fonction_compare_arroffloat_ordonner(const void * data1, const void * data2)
2760 +{
2761 +  const float x = *(const float*)data1;
2762 +  const float y = *(const float*)data2;
2763 +  if (x < y)
2764 +    return -1;
2765 +  else if (x > y)
2766 +    return 1;
2767 +  else
2768 +    return 0;
2769 +}
2770 +
2771 +// Description:
2772 +//   Tri des valeurs du tableau dans l'ordre croissant.
2773 +//   La fonction utilisee est qsort de stdlib (elle est en n*log(n)).
2774 +void ArrOfFloat::ordonne_array()
2775 +{
2776 +  const entier size = size_array();
2777 +  if (size > 1)
2778 +    {
2779 +      float * data = addr();
2780 +      qsort(data, size, sizeof(float),
2781 +            fonction_compare_arroffloat_ordonner);
2782 +    }
2783 +}
2784 +
2785 +// Description:
2786 +//    Fait pointer le tableau vers les memes donnees qu'un tableau
2787 +//    existant. Le tableau sera du meme type que le tableau m ("detache",
2788 +//    "normal"). Le tableau m ne doit pas etre de type "ref_data"
2789 +//    Les donnes existantes sont perdues si elles
2790 +//    ne sont pas referencees ailleurs.
2791 +// Precondition:
2792 +// Parametre: const ArrOfFloat& m
2793 +//    Signification: le tableau a referencer (pas de type "ref_data"
2794 +//                   et different de *this !!!)
2795 +// Retour: ArrOfFloat&
2796 +//    Signification: *this
2797 +//    Contraintes:
2798 +// Exception:
2799 +// Effets de bord:
2800 +// Postcondition:
2801 +ArrOfFloat& ArrOfFloat::ref_array(const ArrOfFloat& m)
2802 +{
2803 +  assert(&m != this);
2804 +  // La condition 'm n'est pas de type "ref_data"' est necessaire pour
2805 +  // attach_array().
2806 +  detach_array();
2807 +  attach_array(m);
2808 +  return *this;
2809 +}
2810 +
2811 +// Description:
2812 +//    Fait pointer le tableau vers la zone de memoire "data_".
2813 +//    On detache la zone de memoire existante. Le tableau devient
2814 +//    de type "ref_data". Attention : ptr doit etre non nul.
2815 +//    La taille est initialisee avec size.
2816 +//    Cette methode est appelee notamment par FloatVect::adopter.
2817 +// Parametre: float*
2818 +//    Signification: le tableau a recuperer. Si pointeur nul alors size
2819 +//                   doit etre nulle aussi et le tableau reste detache
2820 +// Parametre: entier size
2821 +//    Signification: le nombre d'elements du tableau.
2822 +// Retour: ArrOfFloat&
2823 +//    Signification: *this
2824 +ArrOfFloat& ArrOfFloat::ref_data(float* ptr, entier size)
2825 +{
2826 +  assert(ptr != 0 || size == 0);
2827 +  assert(size >= 0);
2828 +  detach_array();
2829 +  data_ = ptr;
2830 +  size_array_ = size;
2831 +  return *this;
2832 +}
2833 +
2834 +// Description:
2835 +//  Amene le tableau dans l'etat "detache". C'est a dire:
2836 +//  Si le tableau est "detache" :
2837 +//   * ne rien faire
2838 +//  Si le tableau est "normal" :
2839 +//   * decremente le nombre de references a *p
2840 +//   * detruit *p si p->ref_count==0
2841 +//   * annule p_, data_ et size_array_
2842 +//  Si le tableau est "ref_data" :
2843 +//   * annule data_ et size_array_
2844 +// Retour: int
2845 +//    Signification: 1 si les donnees du tableau ont ete supprimees
2846 +// Precondition:
2847 +// Postcondition:
2848 +//  On a p_==0, data_==0 et size_array_==0, memory_size_ = 0
2849 +//  L'attribut smart_resize_ est conserve.
2850 +entier ArrOfFloat::detach_array()
2851 +{
2852 +  entier retour = 0;
2853 +  if (p_)
2854 +    {
2855 +      // Le tableau est de type "normal"
2856 +      // Si la zone de memoire n'est plus utilisee par personne,
2857 +      // on la detruit.
2858 +      if ((p_->suppr_one_ref()) == 0)
2859 +        {
2860 +          delete p_;
2861 +          retour = 1;
2862 +        }
2863 +      p_ = 0;
2864 +    }
2865 +  data_ = 0;
2866 +  size_array_ = 0;
2867 +  memory_size_ = 0;
2868 +  return retour;
2869 +}
2870 +
2871 +// Description:
2872 +//    Amene le tableau dans l'etat "normal", "detache" ou "ref_array"
2873 +//    en associant la meme zone de memoire que le tableau m.
2874 +// Precondition:
2875 +//    Le tableau doit etre "detache"
2876 +// Parametre: const ArrOfFloat& m
2877 +//    Signification: tableau a utiliser
2878 +//                   le tableau doit etre different de *this !!!
2879 +// Retour:
2880 +//    Signification:
2881 +//    Contraintes:
2882 +// Exception:
2883 +// Effets de bord:
2884 +// Postcondition:
2885 +//    Si m est detache, le tableau reste detache,
2886 +//    si m est "ref_array", le tableau devient "ref_array",
2887 +//    sinon le tableau est "normal", avec ref_count > 1
2888 +//    Si m est de taille nulle, le tableau reste detache + Warning dans fichier .log
2889 +void ArrOfFloat::attach_array(const ArrOfFloat& m)
2890 +{
2891 +  // Le tableau doit etre detache
2892 +  assert(data_ == 0 && p_ == 0);
2893 +  // Le tableau doit etre different de *this
2894 +  assert(&m != this);
2895 +
2896 +  if (m.size_array() > 0)
2897 +    {
2898 +      p_ = m.p_;
2899 +      if (p_)
2900 +        p_->add_one_ref();
2901 +      data_ = m.data_;
2902 +      size_array_ = m.size_array_;
2903 +      memory_size_ = m.memory_size_;
2904 +      smart_resize_ = m.smart_resize_;
2905 +    }
2906 +  else
2907 +    {
2908 +      // Cas particulier ou on attache un tableau de taille nulle:
2909 +      //  en theorie, c'est pareil qu'un tableau de taille non nulle, MAIS
2910 +      //  dans les operateurs (ex:Op_Dift_VDF_Face_Axi), une ref est construite
2911 +      //  avant que le tableau ne prenne sa taille definitive. Donc, pour ne pas
2912 +      //  empecher le resize, il ne faut pas attacher le tableau s'il n'a pas
2913 +      //  encore la bonne taille. Solution propre: reecrire les operateurs pour
2914 +      //  qu'ils ne prennent pas une ref avant que le tableau ne soit valide
2915 +      //  et faire p_ = m.p_ dans tous les cas.
2916 +    }
2917 +}
2918 +
2919 +// Description:
2920 +//    Copie les elements source[first_element_source + i]
2921 +//    dans les elements  (*this)[first_element_dest + i] pour 0 <= i < nb_elements
2922 +//    Les autres elements de (*this) sont inchanges.
2923 +// Precondition:
2924 +// Parametre:       const ArrOfFloat& m
2925 +//  Signification:   le tableau a utiliser, doit etre different de *this !
2926 +// Parametre:       entier nb_elements
2927 +//  Signification:   nombre d'elements a copier, nb_elements >= -1.
2928 +//                   Si nb_elements==-1, on copie tout le tableau m.
2929 +//  Valeurs par defaut: -1
2930 +// Parametre:       entier first_element_dest
2931 +//  Valeurs par defaut: 0
2932 +// Parametre:       entier first_element_source
2933 +//  Valeurs par defaut: 0
2934 +// Retour: ArrOfFloat&
2935 +//    Signification: *this
2936 +//    Contraintes:
2937 +// Exception:
2938 +//    Sort en erreur si la taille du tableau m est plus grande que la
2939 +//    taille de tableau this.
2940 +// Effets de bord:
2941 +// Postcondition:
2942 +ArrOfFloat& ArrOfFloat::inject_array(const ArrOfFloat& source,
2943 +                                     entier nb_elements,
2944 +                                     entier first_element_dest,
2945 +                                     entier first_element_source)
2946 +{
2947 +  assert(&source != this);
2948 +  assert(nb_elements >= -1);
2949 +  assert(first_element_dest >= 0);
2950 +  assert(first_element_source >= 0);
2951 +
2952 +  if (nb_elements < 0)
2953 +    nb_elements = source.size_array();
2954 +
2955 +  assert(first_element_source + nb_elements <= source.size_array());
2956 +  assert(first_element_dest + nb_elements <= size_array());
2957 +
2958 +  if (nb_elements > 0)
2959 +    {
2960 +      float * addr_dest = addr() + first_element_dest;
2961 +      const float * addr_source = source.addr() + first_element_source;
2962 +      // memcpy(addr_dest , addr_source, nb_elements * sizeof(float));
2963 +      entier i;
2964 +      for (i = 0; i < nb_elements; i++)
2965 +        {
2966 +          addr_dest[i] = addr_source[i];
2967 +        }
2968 +    }
2969 +  return *this;
2970 +}
2971 +
2972 +// Description:
2973 +//    Retourne le nombre de references des donnees du tableau
2974 +//    si le tableau est "normal", -1 s'il est "detache" ou "ref_data"
2975 +// Retour: int
2976 +//    Signification: ref_count_
2977 +entier ArrOfFloat::ref_count() const
2978 +{
2979 +  if (p_)
2980 +    return p_->ref_count();
2981 +  else
2982 +    return -1;
2983 +}
2984 +
2985 +// Description:
2986 +//    Addition case a case sur toutes les cases du tableau
2987 +// Precondition:
2988 +//    la taille de y doit etre au moins egale a la taille de this
2989 +// Parametre: const ArrOfFloat& y
2990 +//    Signification: tableau a ajouter
2991 +//    Valeurs par defaut:
2992 +//    Contraintes:
2993 +//    Acces:
2994 +// Retour: ArrOfFloat&
2995 +//    Signification: *this
2996 +//    Contraintes:
2997 +// Exception:
2998 +// Effets de bord:
2999 +// Postcondition:
3000 +ArrOfFloat& ArrOfFloat::operator+=(const ArrOfFloat& y)
3001 +{
3002 +  assert(size_array()==y.size_array());
3003 +  float* dx = addr();
3004 +  const float* dy = y.addr();
3005 +  const entier n = size_array();
3006 +  for (entier i=0; i<n; i++)
3007 +    dx[i] += dy[i];
3008 +  return *this;
3009 +}
3010 +
3011 +// Description:
3012 +//     ajoute la meme valeur a toutes les cases du tableau
3013 +// Precondition:
3014 +// Parametre: const float dy
3015 +//    Signification: valeur a ajouter
3016 +//    Valeurs par defaut:
3017 +//    Contraintes:
3018 +//    Acces:
3019 +// Retour: ArrOfFloat
3020 +//    Signification: *this
3021 +//    Contraintes:
3022 +// Exception:
3023 +// Effets de bord:
3024 +// Postcondition:
3025 +ArrOfFloat& ArrOfFloat::operator+=(const float dy)
3026 +{
3027 +  float * data = addr();
3028 +  const entier n = size_array();
3029 +  for(entier i=0; i < n; i++)
3030 +    data[i] += dy;
3031 +  return *this;
3032 +}
3033 +// Description:
3034 +//    Soustraction case a case sur toutes les cases du tableau
3035 +// Parametre: const ArrOfFloat& y
3036 +//    Signification: tableau de meme taille que *this
3037 +// Retour: ArrOfFloat&
3038 +//    Signification: *this
3039 +ArrOfFloat& ArrOfFloat::operator-=(const ArrOfFloat& y)
3040 +{
3041 +  const entier size = size_array();
3042 +  assert(size == y.size_array());
3043 +  float * data = addr();
3044 +  const float * data_y = y.addr();
3045 +  for (entier i=0; i < size; i++)
3046 +    data[i] -= data_y[i];
3047 +  return *this;
3048 +}
3049 +
3050 +
3051 +// Description:
3052 +//     soustrait la meme valeur a toutes les cases
3053 +// Retour: ArrOfFloat &
3054 +//    Signification: *this
3055 +ArrOfFloat& ArrOfFloat::operator-=(const float dy)
3056 +{
3057 +  float * data = addr();
3058 +  const entier n = size_array();
3059 +  for(entier i=0; i < n; i++)
3060 +    data[i] -= dy;
3061 +  return *this;
3062 +}
3063 +
3064 +// Description:
3065 +//   Renvoie un pointeur sur le premier element du tableau.
3066 +//   Le pointeur est nul si le tableau est "detache".
3067 +//   Attention, l'adresse peut changer apres un appel
3068 +//   a resize_array(), ref_data, ref_array, ...
3069 +// Precondition:
3070 +// Retour: const float*
3071 +//   Signification: pointeur sur le premier element du tableau
3072 +const float* ArrOfFloat::addr() const
3073 +{
3074 +  return data_;
3075 +}
3076 +
3077 +// Description:
3078 +//   Renvoie un pointeur sur le premier element du tableau.
3079 +//   Le pointeur est nul si le tableau est "detache".
3080 +// Precondition:
3081 +// Retour: const float*
3082 +//    Signification: la zone memoire du tableau
3083 +float* ArrOfFloat::addr()
3084 +{
3085 +  return data_;
3086 +}
3087 +
3088 +
3089 +// Description:
3090 +//    Retourne le max des abs(i)
3091 +// Precondition:
3092 +//    Le tableau doit contenir au moins une valeur
3093 +// Parametre: const ArrOfFloat& dx
3094 +//    Signification: tableau a utiliser
3095 +//    Valeurs par defaut:
3096 +//    Contraintes:
3097 +//    Acces:
3098 +// Retour: float
3099 +//    Signification: valeur du max des valeurs absolues
3100 +//    Contraintes:
3101 +// Exception:
3102 +// Effets de bord:
3103 +// Postcondition:
3104 +float max_abs_array(const ArrOfFloat& dx)
3105 +{
3106 +  const entier size = dx.size_array();
3107 +  assert(size > 0);
3108 +  float valeur_max = fabs(dx[0]);
3109 +  for(entier i = 1; i < size; i++)
3110 +    {
3111 +      const float val = fabs(dx[i]);
3112 +      if (val > valeur_max)
3113 +        valeur_max = val;
3114 +    }
3115 +  return valeur_max;
3116 +}
3117 +
3118 +// Description:
3119 +//     muliplie toutes les cases par dy
3120 +// Retour: ArrOfFloat &
3121 +//    Signification: *this
3122 +ArrOfFloat& ArrOfFloat::operator*= (const float dy)
3123 +{
3124 +  float * data = addr();
3125 +  const entier n = size_array();
3126 +  for(entier i=0; i < n; i++)
3127 +    data[i] *= dy;
3128 +  return *this;
3129 +}
3130 +
3131 +
3132 +// Description:
3133 +//     divise toutes les cases par dy
3134 +// Retour: ArrOfFloat &
3135 +//    Signification: *this
3136 +ArrOfFloat& ArrOfFloat::operator/= (const float dy)
3137 +{
3138 +  // En theorie: les deux lignes suivantes sont plus efficaces, mais
3139 +  //  cela produit des differences sur certains cas tests
3140 +  //  (Hyd_C_VEF_Smago et Lambda_var_VEF_turb). Ca veut dire qu'il y
3141 +  //  a un probleme autre part mais pour l'instant on laisse l'ancien
3142 +  //  codage.
3143 +  // const float i_dy = 1. / dy;
3144 +  // operator*=(i_dy);
3145 +
3146 +  float * data = addr();
3147 +  const entier n = size_array();
3148 +  for(entier i=0; i < n; i++)
3149 +    data[i] /= dy;
3150 +
3151 +  return *this;
3152 +}
3153 +
3154 +FloatTab::FloatTab()
3155 +{
3156 +  // nb_dim_ = 2;
3157 +  dimensions_[0] = 0;
3158 +  dimensions_[1] = 0;
3159 +}
3160 +
3161 +FloatTab::FloatTab(const FloatTab& tab) :
3162 +  ArrOfFloat(tab)
3163 +{
3164 +  // nb_dim_ = tab.nb_dim_;
3165 +  dimensions_[0] = tab.dimensions_[0];
3166 +  dimensions_[1] = tab.dimensions_[1];
3167 +}
3168 +FloatTab::FloatTab(const entier i, const entier j) :
3169 +  ArrOfFloat(i*j)
3170 +{
3171 +  // nb_dim_ = 2;
3172 +  dimensions_[0] = i;
3173 +  dimensions_[1] = j;
3174 +}
3175 +
3176 +FloatTab& FloatTab::operator=(const FloatTab& tab)
3177 +{
3178 +  ArrOfFloat::operator=(tab);
3179 +  // nb_dim_ = tab.nb_dim_;
3180 +  dimensions_[0] = tab.dimensions_[0];
3181 +  dimensions_[1] = tab.dimensions_[1];
3182 +  return *this;
3183 +}
3184 +
3185 +void FloatTab::reset()
3186 +{
3187 +  ArrOfFloat::reset();
3188 +  // nb_dim_ = 2;
3189 +  dimensions_[0] = 0;
3190 +  dimensions_[1] = 0;
3191 +}
3192 +
3193 diff --git a/databases/readers/Lata/ArrOfFloat.h b/databases/readers/Lata/ArrOfFloat.h
3194 new file mode 100644
3195 index 0000000..f80d4ee
3196 --- /dev/null
3197 +++ b/databases/readers/Lata/ArrOfFloat.h
3198 @@ -0,0 +1,353 @@
3199 +/*****************************************************************************
3200 +*
3201 +* Copyright (c) 2011 - 2013, CEA
3202 +* All rights reserved.
3203 +* Redistribution and use in source and binary forms, with or without
3204 +* modification, are permitted provided that the following conditions are met:
3205 +*
3206 +*     * Redistributions of source code must retain the above copyright
3207 +*       notice, this list of conditions and the following disclaimer.
3208 +*     * Redistributions in binary form must reproduce the above copyright
3209 +*       notice, this list of conditions and the following disclaimer in the
3210 +*       documentation and/or other materials provided with the distribution.
3211 +*     * Neither the name of CEA, nor the
3212 +*       names of its contributors may be used to endorse or promote products
3213 +*       derived from this software without specific prior written permission.
3214 +*
3215 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
3216 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3217 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3218 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
3219 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3220 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
3221 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
3222 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3223 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3224 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3225 +*
3226 +*****************************************************************************/
3227 +
3228 +////////////////////////////////////////////////////////////
3229 +//
3230 +// Warning : DO NOT EDIT !
3231 +//          Please update ArrOf_Scalar_Prototype.h.P
3232 +//          and this file will be generated automatically
3233 +//           by the script file check.sh
3234 +////////////////////////////////////////////////////////////
3235 +
3236 +#ifndef ArrOfFloat_H
3237 +#define ArrOfFloat_H
3238 +
3239 +#include <assert.h>
3240 +#include <arch.h>
3241 +#include <Objet_U.h>
3242 +
3243 +#if ! defined(DMAXFLOAT)
3244 +#define DMAXFLOAT 1e40
3245 +#endif
3246 +
3247 +class VFloatdata;
3248 +
3249 +class ArrOfFloat
3250 +{
3251 +public:
3252 +  //
3253 +  // Destructeur
3254 +  //
3255 +  virtual ~ArrOfFloat();
3256 +  //
3257 +  // Constructeurs
3258 +  //
3259 +  ArrOfFloat();
3260 +  ArrOfFloat(entier size);
3261 +  ArrOfFloat(entier size, float initial_value);
3262 +  // Constructeur par copie : deep copy (on duplique les donnees)
3263 +  ArrOfFloat(const ArrOfFloat& );
3264 +  //
3265 +  // Methodes de construction tardive (on cree un tableau vide avec ArrOfFloat()
3266 +  // puis on appelle ces methodes pour modifier les caracteristiques du tableau :
3267 +  //
3268 +  // Change le nombre d'elements du tableau
3269 +  inline ArrOfFloat& resize_array(entier new_size);
3270 +
3271 +  // Methodes de gestion de l'allocation memoire:
3272 +  // Assigne une valeur au drapeau "smart_resize"
3273 +  // (reallocation uniquement si la taille augmente)
3274 +  void    set_smart_resize(entier flag);
3275 +  // Gestion du type de memoire alouee (standard ou pool de memoire Trio-U)
3276 +  enum    Storage { STANDARD, TEMP_STORAGE, SIMD_ALIGNED };
3277 +  void    set_mem_storage(const Storage storage);
3278 +  Storage get_mem_storage() const;
3279 +
3280 +  // Construction de tableaux qui pointent vers des donnees existantes
3281 +  // !!! Utiliser ref_data avec precaution (attention a size_array_)
3282 +  ArrOfFloat& ref_data(float* ptr, entier size);
3283 +  ArrOfFloat& ref_array(const ArrOfFloat&);
3284 +  // Operateur copie
3285 +  ArrOfFloat& operator=(const ArrOfFloat&);
3286 +  // Remise du tableau dans l'etat initial (obtenu par le constructeur par defaut)
3287 +  virtual void reset();
3288 +
3289 +  //
3290 +  // Methodes d'acces aux donnees et aux caracteristiques du tableau
3291 +  //
3292 +  // Remplit le tableau avec la valeur en parametre
3293 +  ArrOfFloat& operator=(float valeur);
3294 +
3295 +  inline       float& operator[](entier i);
3296 +  inline const float& operator[](entier i) const;
3297 +
3298 +  // Ces methodes renvoient un pointeur vers le premier element du tableau.
3299 +  const float * addr() const;
3300 +  float * addr();
3301 +  // Renvoie le nombre d'elements du tableau (et non la taille allouee)
3302 +  inline entier size_array() const;
3303 +  // Renvoie le nombre de tableaux qui pointent vers la stucture "*p_"
3304 +  entier ref_count() const;
3305 +  // Ajoute une case en fin de tableau et y stocke la "valeur"
3306 +  inline void   append_array(float valeur);
3307 +
3308 +  //
3309 +  // Operateurs divers
3310 +  //
3311 +  ArrOfFloat& operator+=(const ArrOfFloat&);
3312 +  ArrOfFloat& operator+=(const float);
3313 +  ArrOfFloat& operator-=(const ArrOfFloat&);
3314 +  ArrOfFloat& operator-=(const float);
3315 +  ArrOfFloat& inject_array(const ArrOfFloat& source,
3316 +                           entier nb_elements = -1,
3317 +                           entier first_element_dest = 0,
3318 +                           entier first_element_source = 0);
3319 +  ArrOfFloat& copy_array(const ArrOfFloat&);
3320 +
3321 +  ArrOfFloat& operator*= (const float) ;
3322 +  ArrOfFloat& operator/= (const float) ;
3323 +
3324 +  void             ordonne_array();
3325 +
3326 +protected:
3327 +  //
3328 +  // Methodes accessibles depuis les descendants de ArrOfFloat
3329 +  //
3330 +  void   attach_array(const ArrOfFloat&);
3331 +  entier detach_array();
3332 +  void   fill_default_value(entier first, entier nb);
3333 +private:
3334 +  // B. Mathieu 22/06/2004 : je mets ces membres "private" pour forcer
3335 +  // le passage par les accesseurs dans les classes derivees, au cas ou
3336 +  // on voudrait modifier l'implementation.
3337 +
3338 +  // Zone de memoire contenant les valeurs du tableau.
3339 +  // Pointeur nul => le tableau est "detache" ou "ref_data"
3340 +  // Pointeur non nul => le tableau est "normal"
3341 +  VFloatdata* p_;
3342 +
3343 +  // Pointeur vers le premier element du tableau (egal a p_->data si p_!=0)
3344 +  // Pointeur nul => le tableau est "detache".
3345 +  // Pointeur non nul => le tableau est "normal" ou "ref_data"
3346 +  float*   data_;
3347 +
3348 +  // Nombre d'elements du tableau (inferieur ou egal a memory_size_).
3349 +  // Si le tableau est "detache", alors size_array_=0
3350 +  entier    size_array_;
3351 +  // Taille memoire reellement allouee pour le tableau
3352 +  // (pour le mecanisme smart_resize_). memory_size_ est nul
3353 +  // si le tableau est de type "ref_data". Sinon memory_size_
3354 +  // est egal a p_->size_.
3355 +  entier    memory_size_;
3356 +
3357 +  // Drapeau indiquant si on applique une strategie d'allocation
3358 +  // preventive (la memoire alouee augmente d'un facteur constant
3359 +  // si la taille devient insuffisante).
3360 +  // Si smart_resize_ == 0, alors on a toujours p_->size_ == size
3361 +  entier    smart_resize_;
3362 +
3363 +  // Drapeau indiquant si l'allocation memoire a lieu avec un new classique
3364 +  // ou dans le pool de memoire temporaire de Trio
3365 +  Storage   storage_type_;
3366 +
3367 +  // Partie non inline de resize_array():
3368 +  // Declaration des constantes pour les options de memory_resize
3369 +  static const entier COPY_OLD;
3370 +  static const entier INITIALIZE_NEW;
3371 +  void memory_resize(entier new_size, entier options);
3372 +};
3373 +
3374 +#define MAXDIMFloatTab 2
3375 +
3376 +class FloatTab : public ArrOfFloat
3377 +{
3378 +public:
3379 +  FloatTab();
3380 +  FloatTab(const FloatTab&);
3381 +  FloatTab(const entier i, const entier j);
3382 +  FloatTab&    operator=(const FloatTab&);
3383 +  void              reset();
3384 +
3385 +  inline float& operator()(entier i, entier j);
3386 +  inline float   operator()(entier i, entier j) const;
3387 +
3388 +  inline entier resize(entier i, entier j);
3389 +  inline entier dimension(entier i) const;
3390 +  inline entier dimension_tot(entier i) const;
3391 +
3392 +protected:
3393 +  // In order to mimic TRUST behavior, operator[] is forbidden
3394 +  // for 2 dimensionnal matrices, you must cast to ArrOf to use it..
3395 +  double&        operator[](entier i);
3396 +  const double& operator[](entier i) const;
3397 +
3398 +private:
3399 +  //  entier nb_dim_;
3400 +  entier dimensions_[MAXDIMFloatTab];
3401 +};
3402 +
3403 +inline float& FloatTab::operator()(entier i, entier j)
3404 +{
3405 +  // assert(nb_dim_ == 2);
3406 +  assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]);
3407 +  const entier n = i * dimensions_[1] + j;
3408 +  float& x = ArrOfFloat::operator[] (n);
3409 +  return x;
3410 +}
3411 +
3412 +inline float   FloatTab::operator()(entier i, entier j) const
3413 +{
3414 +  // assert(nb_dim_ == 2);
3415 +  assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]);
3416 +  const entier n = i * dimensions_[1] + j;
3417 +  float x = ArrOfFloat::operator[] (n);
3418 +  return x;
3419 +}
3420 +
3421 +inline entier FloatTab::resize(entier i, entier j)
3422 +{
3423 +  assert(i >= 0 && j >= 0);
3424 +  // nb_dim_ = 2;
3425 +  dimensions_[0] = i;
3426 +  dimensions_[1] = j;
3427 +  ArrOfFloat::resize_array(i * j);
3428 +  return i*j;
3429 +}
3430 +
3431 +inline entier FloatTab::dimension(entier i) const
3432 +{
3433 +  assert(i >= 0 && i < 2);
3434 +  return dimensions_[i];
3435 +}
3436 +
3437 +// Description: renvoie la meme valeur que dimension.
3438 +inline entier FloatTab::dimension_tot(entier i) const
3439 +{
3440 +  return dimension(i);
3441 +}
3442 +
3443 +//
3444 +// Declarations des fonctions non membres de la classe ArrOfFloat
3445 +//
3446 +entier operator==(const ArrOfFloat& x, const ArrOfFloat& y) ;
3447 +entier imin_array(const ArrOfFloat&) ;
3448 +entier imax_array(const ArrOfFloat&) ;
3449 +float min_array(const ArrOfFloat&) ;
3450 +float max_array(const ArrOfFloat&) ;
3451 +
3452 +float max_abs_array(const ArrOfFloat&) ;
3453 +
3454 +// ******************************************************************
3455 +//                   FONCTIONS MEMBRES DE ArrOfFloat
3456 +// ******************************************************************
3457 +
3458 +// Description :
3459 +//  Change le nombre d'elements du tableau. Cette fonction est inline
3460 +//  car elle doit etre tres rapide dans le cas ou smart_resize_==1
3461 +//  (utilisation frequente de resize_array())
3462 +//  Si smart_resize est non nul :
3463 +//   Si la nouvelle taille est inferieure ou egale a la taille
3464 +//   alouee (p->get_size()) on ne realloue pas de memoire
3465 +//   sinon, on realloue et on copie les donnees existantes.
3466 +//  Astuce pour ne pas copier les anciennes donnees:
3467 +//   resize(0); resize(n);
3468 +//  Si smart_resize est nul, on realloue une nouvelle zone memoire
3469 +//   uniquement si la nouvelle taille est differente de l'ancienne.
3470 +// Precondition :
3471 +//  Si "new_size" est egal a la taille du tableau, aucune condition.
3472 +//  Sinon, le tableau doit etre soit detache, soit normal (pas de type "ref_data")
3473 +//  et ref_count doit etre egal a 1 (pas d'autre reference au tableau).
3474 +//
3475 +inline ArrOfFloat& ArrOfFloat::resize_array(entier new_size)
3476 +{
3477 +  assert(new_size >= 0);
3478 +  // Soit le tableau est detache (data_==0), soit il est normal (p_!=0)
3479 +  // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau,
3480 +  // ou alors la taille ne doit pas changer.
3481 +  assert(new_size == size_array_ || data_ == 0 || (p_ != 0 && ref_count() == 1));
3482 +
3483 +  if ((smart_resize_ == 0) || (new_size > memory_size_))
3484 +    memory_resize(new_size, COPY_OLD + INITIALIZE_NEW);
3485 +  size_array_ = new_size;
3486 +  return *this;
3487 +}
3488 +
3489 +// Description:
3490 +//     operateur [] retourne le ieme element du tableau
3491 +// Precondition:
3492 +// Parametre: entier i
3493 +//    Signification: indice dans l'intervalle 0 <= i < size_array()
3494 +// Exception:
3495 +//    assert si la valeur sort de l'intervalle : [ -DMAXFLOAT,DMAXFLOAT ]
3496 +//    assert si i n'est pas dans l'intervalle
3497 +inline float& ArrOfFloat::operator[](entier i)
3498 +{
3499 +  assert(i >= 0 && i < size_array_);
3500 +  assert((smart_resize_==1)|| (data_[i] > -DMAXFLOAT && data_[i] < DMAXFLOAT));
3501 +  return data_[i];
3502 +}
3503 +
3504 +// Description:
3505 +//     operateur [] retourne le ieme element du tableau
3506 +// Precondition:
3507 +// Parametre: entier i
3508 +//    Signification: indice dans l'intervalle 0 <= i < size_array()
3509 +// Exception:
3510 +//    assert si la valeur sort de l'intervalle : [ -DMAXFLOAT,DMAXFLOAT ]
3511 +//    assert si i n'est pas dans l'intervalle
3512 +inline const float& ArrOfFloat::operator[](entier i) const
3513 +{
3514 +  assert(i >= 0 && i < size_array_);
3515 +  assert(data_[i] > -DMAXFLOAT && data_[i] < DMAXFLOAT);
3516 +  return data_[i];
3517 +}
3518 +
3519 +// Description:
3520 +//    Renvoie la taille du tableau (nombre d'elements declares
3521 +//    a la construction ou a resize_array()).
3522 +//    C'est le nombre d'elements accessibles a operator[]
3523 +// Retour: entier
3524 +inline entier  ArrOfFloat::size_array() const
3525 +{
3526 +  return size_array_;
3527 +}
3528 +
3529 +// Description:
3530 +//  Ajoute une case en fin de tableau et y stocke la "valeur"
3531 +// Precondition:
3532 +//  Tableau doit etre de type "smart_resize" (sinon, ecroulement
3533 +//  des performances). De plus, le tableau ne doit pas etre "ref_data",
3534 +//  et il ne doit pas y avoir plus d'une reference a la zone de
3535 +//  memoire pointee (meme precondition que resize_array())
3536 +inline void   ArrOfFloat::append_array(float valeur)
3537 +{
3538 +  assert(smart_resize_);
3539 +  // Soit le tableau est detache (data_==0), soit il est normal (p_!=0)
3540 +  // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau.
3541 +  assert(data_ == 0 || (p_ != 0 && ref_count() == 1));
3542 +
3543 +  if (size_array_+1 > memory_size_)
3544 +    memory_resize(size_array_+1, COPY_OLD);
3545 +  data_[size_array_] = valeur;
3546 +  size_array_++;
3547 +}
3548 +
3549 +// ArrOfFloat_H
3550 +#endif
3551 +
3552 diff --git a/databases/readers/Lata/ArrOfInt.C b/databases/readers/Lata/ArrOfInt.C
3553 new file mode 100644
3554 index 0000000..a4a150b
3555 --- /dev/null
3556 +++ b/databases/readers/Lata/ArrOfInt.C
3557 @@ -0,0 +1,1110 @@
3558 +/*****************************************************************************
3559 +*
3560 +* Copyright (c) 2011 - 2013, CEA
3561 +* All rights reserved.
3562 +* Redistribution and use in source and binary forms, with or without
3563 +* modification, are permitted provided that the following conditions are met:
3564 +*
3565 +*     * Redistributions of source code must retain the above copyright
3566 +*       notice, this list of conditions and the following disclaimer.
3567 +*     * Redistributions in binary form must reproduce the above copyright
3568 +*       notice, this list of conditions and the following disclaimer in the
3569 +*       documentation and/or other materials provided with the distribution.
3570 +*     * Neither the name of CEA, nor the
3571 +*       names of its contributors may be used to endorse or promote products
3572 +*       derived from this software without specific prior written permission.
3573 +*
3574 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
3575 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3576 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3577 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
3578 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3579 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
3580 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
3581 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3582 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3583 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3584 +*
3585 +*****************************************************************************/
3586 +
3587 +////////////////////////////////////////////////////////////
3588 +//
3589 +// Warning : DO NOT EDIT !
3590 +//          Please update ArrOf_Scalar_Prototype.cpp.h
3591 +//          and this file will be generated automatically
3592 +//           by the script file check.sh
3593 +////////////////////////////////////////////////////////////
3594 +
3595 +#include <ArrOfInt.h>
3596 +// limits.h definit INT_MIN, SHRT_MIN, ...
3597 +#include <limits.h>
3598 +#include <stdlib.h>
3599 +#include <Objet_U.h>
3600 +#include <iostream>
3601 +#include <stdlib.h>
3602 +#include <string.h>
3603 +#include "simd_interface.h"
3604 +
3605 +using namespace std;
3606 +
3607 +// ******************************************************************
3608 +//
3609 +//             Implementation des methodes de VIntdata
3610 +//
3611 +// ******************************************************************
3612 +////////////////////////////////////////////////////////////////////
3613 +// .NOM        ArrOfInt
3614 +// .ENTETE     TRUST Math
3615 +// .LIBRAIRIE  libtmath
3616 +// .FILE       ArrOfInt.h
3617 +// .FILE       ArrOfInt.cpp
3618 +//
3619 +// .DESCRIPTION
3620 +// VIntdata alloue une zone de memoire de la taille specifiee au
3621 +// constructeur, et libere la zone de memoire a la destruction.
3622 +//
3623 +// "ref_count" compte le nombre de pointeurs qui font reference a "this".
3624 +// (permet au dernier utilisateur de l'objet de le detruire), voir
3625 +// ArrOfInt.
3626 +//
3627 +// .SECTION voir aussi
3628 +// .CONTRAINTES
3629 +// .INVARIANTS
3630 +// .HTML
3631 +// .EPS
3632 +///////////////////////////////////////////////////////////////////
3633 +
3634 +class VIntdata
3635 +{
3636 +public:
3637 +  VIntdata(entier size, ArrOfInt::Storage storage);
3638 +  ~VIntdata();
3639 +  entier          add_one_ref();
3640 +  entier          suppr_one_ref();
3641 +  entier *        get_data();
3642 +  const entier *  get_data() const;
3643 +  inline entier   ref_count() const;
3644 +  inline entier   get_size() const;
3645 +private:
3646 +  // Le constructeur par copie et l'operateur= sont interdits.
3647 +  VIntdata(const VIntdata& v);
3648 +  VIntdata& operator=(const VIntdata& v);
3649 +
3650 +  // "data" est un pointeur sur une zone de memoire de taille
3651 +  // sz * sizeof(entier), allouee par le
3652 +  // constructeur et liberee par le destructeur.
3653 +  // Ce pointeur n'est jamais nul meme si size_==0
3654 +  entier * data_;
3655 +  // Compteur incremente par add_one_ref et decremente par suppr_one_ref.
3656 +  // Contient le nombre d'objets ArrOfInt dont le membre "p" pointe
3657 +  // vers "this". On a ref_count_ >= 0.
3658 +  entier ref_count_;
3659 +  // "sz" est la taille du tableau "data_" alloue
3660 +  // On a sz >= 0.
3661 +  entier size_;
3662 +  ArrOfInt::Storage storage_;
3663 +};
3664 +
3665 +
3666 +// Description:
3667 +//    Construit un VIntdata de taille size >= 0
3668 +// Parametre: entier s
3669 +//    Signification: taille du VIntdata, il faut size >= 0
3670 +// Parametre: Storage storage
3671 +//    Signification: indique si la memoire doit etre allouee
3672 +//                   avec "new" ou avec "simd_malloc"
3673 +//    Valeurs par defaut: STANDARD (allocation avec "new")
3674 +// Postcondition:
3675 +//    data_ n'est jamais nul, meme si size==0
3676 +VIntdata::VIntdata(entier size, ArrOfInt::Storage storage)
3677 +{
3678 +  if (size == 0)
3679 +    storage = ArrOfInt::STANDARD;
3680 +
3681 +  switch (storage)
3682 +    {
3683 +    case ArrOfInt::STANDARD:
3684 +      {
3685 +#ifdef _EXCEPTION_
3686 +        // Allocation de la memoire sur le tas
3687 +        try
3688 +          {
3689 +            data_ = new entier[size];
3690 +          }
3691 +        catch(...)
3692 +          {
3693 +            Cerr << "impossible d'allouer " << size << " entier " << finl;
3694 +            throw;
3695 +          }
3696 +#else
3697 +        data_ = new entier[size];
3698 +        if(!data_)
3699 +          {
3700 +            Cerr << "impossible d'allouer " << size << "entier " << finl;
3701 +            throw ;
3702 +          }
3703 +#endif
3704 +        break;
3705 +      }
3706 +    case ArrOfInt::SIMD_ALIGNED:
3707 +      {
3708 +#ifdef SIMD_TOOLS_H
3709 +        data_ = (entier*) simd_malloc (sizeof(entier) * size);
3710 +#else
3711 +        Cerr<<"unable to allocate simd_aligned, version compiled without simd "<<finl;
3712 +        throw;
3713 +#endif
3714 +        break;
3715 +      }
3716 +    default:
3717 +      throw;
3718 +    }
3719 +  ref_count_ = 1;
3720 +  size_ = size;
3721 +  storage_ = storage;
3722 +  assert(data_ != 0);
3723 +}
3724 +
3725 +// Description:
3726 +//  Detruit la zone de memoire allouee.
3727 +// Precondition:
3728 +//  ref_count == 0 (la zone de memoire ne doit etre referencee nulle part)
3729 +VIntdata::~VIntdata()
3730 +{
3731 +  assert(ref_count_ == 0);
3732 +
3733 +  // Stockage STANDARD
3734 +  switch(storage_)
3735 +    {
3736 +    case ArrOfInt::STANDARD:
3737 +      delete[] data_;
3738 +      break;
3739 +    case ArrOfInt::SIMD_ALIGNED:
3740 +#ifdef SIMD_TOOLS_H
3741 +      simd_free(data_);
3742 +#else
3743 +      Cerr<<"unable to allocate simd_aligned, version compiled without simd "<<finl;
3744 +      throw;
3745 +#endif
3746 +      break;
3747 +    default:
3748 +      throw;
3749 +    }
3750 +
3751 +  data_ = 0;  // paranoia: si size_==-1 c'est qu'on pointe sur un zombie
3752 +  size_ = -1; //  (pointeur vers un objet qui a ete detruit)
3753 +  storage_ = ArrOfInt::STANDARD;
3754 +}
3755 +
3756 +// Description: renvoie ref_count_
3757 +inline entier VIntdata::ref_count() const
3758 +{
3759 +  return ref_count_;
3760 +}
3761 +
3762 +// Description: renvoie size_
3763 +inline entier VIntdata::get_size() const
3764 +{
3765 +  return size_;
3766 +}
3767 +
3768 +// Description:
3769 +//     Un nouveau tableau utilise cette zone memoire :
3770 +//     incremente ref_count
3771 +// Retour: int
3772 +//    Signification: ref_count
3773 +inline entier VIntdata::add_one_ref()
3774 +{
3775 +  return ++ref_count_;
3776 +}
3777 +
3778 +// Description:
3779 +//     Un tableau de moins utilise cette zone memoire
3780 +//     decremente ref_count
3781 +// Precondition:
3782 +//     ref_count_ > 0
3783 +// Retour: int
3784 +//    Signification: ref_count
3785 +inline entier VIntdata::suppr_one_ref()
3786 +{
3787 +  assert(ref_count_ > 0);
3788 +  return (--ref_count_);
3789 +}
3790 +
3791 +// Description: renvoie data_
3792 +inline entier * VIntdata::get_data()
3793 +{
3794 +  return data_;
3795 +}
3796 +
3797 +// Description: renvoie data_
3798 +inline const entier * VIntdata::get_data() const
3799 +{
3800 +  return data_;
3801 +}
3802 +
3803 +// Description: Constructeur par copie. Interdit : genere une erreur !
3804 +VIntdata::VIntdata(const VIntdata& v)
3805 +{
3806 +  Cerr << "Erreur dans VIntdata::VIntdata(const VIntdata & v)" << finl;
3807 +  throw;
3808 +}
3809 +
3810 +// Description: Operateur= interdit. Genere une erreur !
3811 +VIntdata& VIntdata::operator=(const VIntdata& v)
3812 +{
3813 +  Cerr << "Erreur dans VIntdata::operator=(const VIntdata & v)" << finl;
3814 +  throw;
3815 +  return *this;
3816 +}
3817 +
3818 +// ******************************************************************
3819 +//
3820 +//             Implementation des methodes de ArrOfInt
3821 +//
3822 +// ******************************************************************
3823 +
3824 +
3825 +// Definition des constantes pour les options de memory_resize
3826 +const entier ArrOfInt::COPY_OLD = 1;
3827 +const entier ArrOfInt::INITIALIZE_NEW = 2;
3828 +
3829 +// Description:
3830 +//  Destructeur : appelle detach_array()
3831 +ArrOfInt::~ArrOfInt()
3832 +{
3833 +  detach_array();
3834 +  size_array_ = -1; // Paranoia: si size_array_==-1, c'est un zombie
3835 +}
3836 +
3837 +// Description:
3838 +//  Constructeur par defaut: cree un tableau "detache",
3839 +//  soit p_==0, data_==0, size_array_==0, smart_resize_==0
3840 +ArrOfInt::ArrOfInt() :
3841 +  p_(0),
3842 +  data_(0),
3843 +  size_array_(0),
3844 +  memory_size_(0),
3845 +  smart_resize_(0),
3846 +  storage_type_(STANDARD)
3847 +{
3848 +}
3849 +
3850 +// Description:
3851 +//     Cree un tableau de taille n avec allocation standard
3852 +//     (voir set_mem_storage).
3853 +//     Valeur de remplissage par defaut: voir fill_default_value
3854 +// Precondition:
3855 +// Parametre: entier n
3856 +//    Signification: taille du tableau
3857 +ArrOfInt::ArrOfInt(entier n) :
3858 +  p_(new VIntdata(n, STANDARD)),
3859 +  data_(p_->get_data()),
3860 +  size_array_(n),
3861 +  memory_size_(n),
3862 +  smart_resize_(0),
3863 +  storage_type_(STANDARD)
3864 +{
3865 +  if (n > 0)
3866 +    fill_default_value(0, n);
3867 +}
3868 +
3869 +// Description:
3870 +//     Cree un tableau de taille n
3871 +//     toutes les cases sont initialisees a x
3872 +// Precondition:
3873 +// Parametre: entier n
3874 +//    Signification: taille du tableau
3875 +// Parametre: entier x
3876 +//    Signification: valeur pour initialiser le tableau
3877 +ArrOfInt::ArrOfInt(entier n, entier x) :
3878 +  p_(new VIntdata(n, STANDARD)),
3879 +  data_(p_->get_data()),
3880 +  size_array_(n),
3881 +  memory_size_(n),
3882 +  smart_resize_(0),
3883 +  storage_type_(STANDARD)
3884 +{
3885 +  *this = x;
3886 +}
3887 +
3888 +// Description:
3889 +//     Constructeur par copie. On alloue une nouvelle zone de memoire
3890 +//     et on copie le contenu du tableau. L'attribut smart_resize_ est
3891 +//     copie aussi.
3892 +//     Si le tableau A est de taille nulle, on cree un tableau "detache",
3893 +//     sinon on cree un tableau "normal".
3894 +// Parametre: const ArrOfInt& A
3895 +//    Signification: le tableau a copier
3896 +ArrOfInt::ArrOfInt(const ArrOfInt& A)
3897 +{
3898 +  const entier size = A.size_array();
3899 +  if (size > 0)
3900 +    {
3901 +      // Creation d'un tableau "normal"
3902 +      storage_type_ = STANDARD;
3903 +      p_ = new VIntdata(size, STANDARD);
3904 +      data_ = p_->get_data();
3905 +      size_array_ = size;
3906 +      memory_size_ = size;
3907 +      smart_resize_ = A.smart_resize_;
3908 +      inject_array(A);
3909 +    }
3910 +  else
3911 +    {
3912 +      // Creation d'un tableau "detache"
3913 +      p_ = 0;
3914 +      data_ = 0;
3915 +      size_array_ = 0;
3916 +      memory_size_ = 0;
3917 +      smart_resize_ = 0;
3918 +      storage_type_ = STANDARD;
3919 +    }
3920 +}
3921 +
3922 +// Description:
3923 +//   Change le mode d'allocation memoire lors des resize
3924 +//   (voir VIntdata et Int_ptr_trav)
3925 +//   Exemple pour creer un tableau avec allocation temporaire:
3926 +//    DoubleTab tab; // Creation d'un tableau vide
3927 +//    tab.set_mem_storage(TEMP_STORAGE); // Changement de mode d'allocation
3928 +//    tab.resize(n); // Allocation memoire
3929 +void ArrOfInt::set_mem_storage(const Storage storage)
3930 +{
3931 +  storage_type_ = storage;
3932 +}
3933 +
3934 +// Description:
3935 +//   Renvoie le mode d'allocation du tableau (qui sera utilise
3936 +//   lors du prochain resize si changement de taille).
3937 +//   (voir VIntdata et Int_ptr_trav)
3938 +enum ArrOfInt::Storage ArrOfInt::get_mem_storage() const
3939 +{
3940 +  return storage_type_;
3941 +}
3942 +
3943 +// Description:
3944 +//   Change le mode l'allocation memoire: reallocation d'un tableau
3945 +//   a chaque changement de taille (flag = 0) ou reallocation
3946 +//   uniquement si la taille augmente et par doublement de la taille
3947 +//   du tableau (flag = 1).
3948 +void ArrOfInt::set_smart_resize(entier flag)
3949 +{
3950 +  assert(flag == 0 || flag == 1);
3951 +  smart_resize_ = flag;
3952 +}
3953 +
3954 +// Description:
3955 +//    Remet le tableau dans l'etat obtenu avec le constructeur par defaut
3956 +//    (libere la memoire mais conserve le mode d'allocation memoire actuel)
3957 +void ArrOfInt::reset()
3958 +{
3959 +  detach_array();
3960 +}
3961 +
3962 +// Description:
3963 +//    Copie les donnees du tableau m.
3964 +//    Si "m" n'a pas la meme taille que "*this", on fait un resize_array.
3965 +//    Ensuite, on copie les valeurs de "m" dans "*this".
3966 +//    Le type de tableau (methode d'allocation) n'est pas copie.
3967 +// Precondition:
3968 +//    Si le tableau n'a pas la meme taille que "m", alors *this doit
3969 +//    etre "resizable" (ne pas etre de type "ref_data" et "ref_count == 1")
3970 +// Parametre: const ArrOfInt& m
3971 +//    Signification: la tableau a copier
3972 +// Retour:  ArrOfInt&
3973 +//    Signification: *this
3974 +ArrOfInt& ArrOfInt::operator=(const ArrOfInt& m)
3975 +{
3976 +  if (&m != this)
3977 +    {
3978 +      const entier new_size = m.size_array();
3979 +      // Le code suivant est quasiment une copie de ArrOfInt::resize()
3980 +      // SAUF: memory_resize est appele avec NO_INITIALIZE (la zone de memoire
3981 +      //  n'est pas initialisee)
3982 +      if (new_size != size_array())
3983 +        {
3984 +          if ((smart_resize_ == 0) || (new_size > memory_size_))
3985 +            memory_resize(new_size, 0); // Pas d'initialisation
3986 +          size_array_ = new_size;
3987 +        }
3988 +      inject_array(m);
3989 +    }
3990 +  return *this;
3991 +}
3992 +
3993 +
3994 +// Description:
3995 +//     x est affecte a toutes les cases
3996 +// Precondition:
3997 +// Parametre: entier x
3998 +//    Signification: la valeur a affecter a toutes les cases du tableau
3999 +//    Valeurs par defaut:
4000 +//    Contraintes:
4001 +//    Acces:
4002 +// Retour: ArrOfInt&
4003 +//    Signification: *this
4004 +//    Contraintes:
4005 +// Exception:
4006 +// Effets de bord:
4007 +// Postcondition:
4008 +ArrOfInt& ArrOfInt::operator=(entier x)
4009 +{
4010 +  const entier n = size_array();
4011 +  entier *data = addr();
4012 +  for (entier i = 0; i < n; i++)
4013 +    {
4014 +      data[i] = x;
4015 +    }
4016 +  return *this;
4017 +}
4018 +
4019 +// Description: appelle operator=(a)
4020 +ArrOfInt& ArrOfInt::copy_array(const ArrOfInt& a)
4021 +{
4022 +  operator=(a);
4023 +  return *this;
4024 +}
4025 +
4026 +// Description:
4027 +//  Si besoin, alloue une nouvelle zone de memoire,
4028 +//  copie les donnees et efface l'ancienne zone de memoire.
4029 +//  Attention, on suppose que cette methode est appelee par
4030 +//  resize_array().
4031 +//  Attention: si ref_count_>1, l'appel a resize_array() est
4032 +//  autorise uniquement si la nouvelle taille est identique
4033 +//  a la precedente.
4034 +// Precondition:
4035 +//  Le tableau doit etre de type "detache" ou "normal" avec
4036 +//  ref_count==1, et il faut new_size >= 0
4037 +//  On suppose que size_array contient encore le nombre d'elements
4038 +//  valides avant changement de taille.
4039 +// Parametre: new_size
4040 +//  Signification: nouvelle taille demandee pour le tableau.
4041 +// Parametre: options
4042 +//  Signification: COPY_OLD => on recopie les anciennes donnees dans le nouveau
4043 +//                  tableau (jusqu'au max de l'ancienne et de la nouvelle taille).
4044 +//                 INITIALIZE_NEW => initialisation des cases non copiees
4045 +// Postcondition:
4046 +//  p_ et data_ sont mis a jour, mais pas size_array_ !!!
4047 +//  (on suppose que c'est fait dans resize_array()).
4048 +//  Si la nouvelle taille est nulle, on detache le tableau.
4049 +void  ArrOfInt::memory_resize(entier new_size, entier options)
4050 +{
4051 +  assert(new_size >= 0);
4052 +
4053 +  // Occupation memoire de l'ancien tableau:
4054 +  entier old_mem_size = 0;
4055 +  if (p_)
4056 +    old_mem_size = p_->get_size();
4057 +
4058 +  // Occupation memoire du nouveau tableau :
4059 +  // Si smart_resize, on prend au moins deux fois la taille
4060 +  // precedente, ou new_size
4061 +  entier new_mem_size = new_size;
4062 +  if (smart_resize_ && (old_mem_size * 2 > new_size))
4063 +    new_mem_size = old_mem_size * 2;
4064 +
4065 +  if (new_mem_size != old_mem_size)
4066 +    {
4067 +      // detach_array() efface le contenu de size_array_. On le met de cote:
4068 +      const entier old_size_array = size_array_;
4069 +      // On va reellement changer l'adresse du tableau.
4070 +      // Il ne faut pas qu'il existe d'autre reference a ce tableau.
4071 +      assert(data_ == 0 || (p_ != 0 && ref_count() == 1));
4072 +      if (new_mem_size == 0)
4073 +        {
4074 +          // La nouvelle taille est nulle, on cree un tableau "detache"
4075 +          detach_array();
4076 +        }
4077 +      else
4078 +        {
4079 +          // Allocation d'une nouvelle zone
4080 +          VIntdata * new_p = new VIntdata(new_mem_size, storage_type_);
4081 +          entier * new_data = new_p->get_data();
4082 +          // Raccourci si le tableau etait "detache", inutile de copier
4083 +          // les anciennes donnees. On copie si COPY_OLD est demande
4084 +          entier copy_size = 0;
4085 +          if (data_ != 0)
4086 +            {
4087 +              // Calcul du nombre d'elements a copier vers la nouvelle
4088 +              // zone de memoire : c'est le min de l'ancienne et de
4089 +              // la nouvelle taille.
4090 +              if (options & COPY_OLD)
4091 +                {
4092 +                  copy_size = size_array_;
4093 +                  if (new_size < copy_size)
4094 +                    copy_size = new_size;
4095 +                  // Copie des valeurs dans le nouveau tableau
4096 +                  for (entier i = 0; i < copy_size; i++)
4097 +                    new_data[i] = data_[i];
4098 +                }
4099 +              // Destruction de l'ancienne zone (si plus aucune reference)
4100 +              detach_array();
4101 +            }
4102 +          // On attache la nouvelle zone de memoire
4103 +          p_ = new_p;
4104 +          data_ = new_data;
4105 +          memory_size_ = new_mem_size;
4106 +          // Initialisation des cases supplementaires avec une valeur par defaut
4107 +          if (options & INITIALIZE_NEW)
4108 +            fill_default_value(copy_size, new_mem_size - copy_size);
4109 +          // Restaure l'ancienne valeur de size_array_
4110 +          size_array_ = old_size_array;
4111 +        }
4112 +    }
4113 +}
4114 +
4115 +// Description:
4116 +//  Remplit "nb" cases consecutives du tableau a partir de la case "first"
4117 +//  avec une valeur par defaut.
4118 +//  Cette fonction est appelee lors d'un resize pour initialiser les
4119 +//  cases nouvellement creees.
4120 +//  Le comportement depend actuellement du type de tableau :
4121 +//  * Tableau de type "smart_resize":
4122 +//    * en mode debug (macro NDEBUG non definie) le tableau est initialise
4123 +//      avec une valeur invalide.
4124 +//    * en optimise, le tableau n'est pas initialise
4125 +//  * Tableau normal :
4126 +//    Le tableau est initialise avec la valeur 0. Ce comportement est choisi
4127 +//    pour des raisons de compatibilite avec l'implementation precedente.
4128 +//    Cette specification pourrait etre modifiee prochainement pour des raisons
4129 +//    de performances (pour ne pas avoir a initialiser inutilement les tableaux).
4130 +//    DONC: il faut supposer desormais que les nouvelles cases ne sont pas
4131 +//    initialisees lors d'un resize.
4132 +// Parametre: first
4133 +//  Signification: premiere case a initialiser.
4134 +//  Contrainte:    (nb==0) ou (0 <= first < memory_size_)
4135 +// Parametre: nb
4136 +//  Signification: nombre de cases a initialiser.
4137 +//  Contrainte:    (nb==0) ou (0 < nb <= memory_size_ - first)
4138 +void  ArrOfInt::fill_default_value(entier first, entier nb)
4139 +{
4140 +  assert((nb == 0) || (first >= 0 && first < memory_size_));
4141 +  assert((nb == 0) || (nb > 0 && nb <= memory_size_ - first));
4142 +  entier * data = addr();
4143 +  assert(data!=0 || nb==0);
4144 +  data += first;
4145 +  if (smart_resize_)
4146 +    {
4147 +      /*
4148 +          // On initialise uniquement en mode debug
4149 +      #ifndef NDEBUG
4150 +          static const entier ENTIER_INVALIDE = INT_MIN;
4151 +          for (entier i = 0; i < nb; i++)
4152 +            data[i] = ENTIER_INVALIDE;
4153 +      #endif
4154 +      */
4155 +    }
4156 +  else
4157 +    {
4158 +      // Comportement pour les tableaux normaux : compatibilite avec la
4159 +      // version precedente : on initialise avec 0.
4160 +      for (entier i = 0; i < nb; i++)
4161 +        data[i] = (entier) 0;
4162 +    }
4163 +}
4164 +
4165 +// ****************************************************************
4166 +//
4167 +//         Fonctions non membres de la classe ArrOfInt
4168 +//
4169 +// ****************************************************************
4170 +
4171 +// Description:
4172 +//  Renvoie 1 si les tableaux "v" et "a" sont de la meme taille
4173 +//  et contiennent les memes valeurs au sens strict, sinon renvoie 0.
4174 +//  Le test est !(v[i]!=a[i])
4175 +entier operator==(const ArrOfInt& v, const ArrOfInt& a)
4176 +{
4177 +  const entier n = v.size_array();
4178 +  const entier na = a.size_array();
4179 +  entier resu = 1;
4180 +  if (n != na)
4181 +    {
4182 +      resu = 0;
4183 +    }
4184 +  else
4185 +    {
4186 +      const entier* vv = v.addr();
4187 +      const entier* av = a.addr();
4188 +      entier i;
4189 +      for (i = 0; i < n; i++)
4190 +        {
4191 +          if (av[i] != vv[i])
4192 +            {
4193 +              resu = 0;
4194 +              break;
4195 +            }
4196 +        }
4197 +    }
4198 +  return resu;
4199 +}
4200 +
4201 +// Description:
4202 +//    Retourne l'indice du min ou -1 si le tableau est vide
4203 +// Precondition:
4204 +// Parametre: const ArrOfInt& dx
4205 +//    Signification: tableau a utiliser
4206 +// Retour: int
4207 +//    Signification: indice du min
4208 +entier imin_array(const ArrOfInt& dx)
4209 +{
4210 +  entier indice_min = -1;
4211 +  const entier size = dx.size_array();
4212 +  if (size > 0)
4213 +    {
4214 +      indice_min = 0;
4215 +      entier valeur_min = dx[0];
4216 +      for(entier i = 1; i < size; i++)
4217 +        {
4218 +          const entier val = dx[i];
4219 +          if(val < valeur_min)
4220 +            {
4221 +              indice_min = i;
4222 +              valeur_min = val;
4223 +            }
4224 +        }
4225 +    }
4226 +  return indice_min;
4227 +}
4228 +
4229 +// Description:
4230 +//    Retourne l'indice du max ou -1 si le tableau est vide
4231 +// Precondition:
4232 +// Parametre: const ArrOfInt& dx
4233 +//    Signification: tableau a utiliser
4234 +// Retour: int
4235 +//    Signification: indice du max
4236 +entier imax_array(const ArrOfInt& dx)
4237 +{
4238 +  entier indice_max = -1;
4239 +  const entier size = dx.size_array();
4240 +  if (size > 0)
4241 +    {
4242 +      indice_max = 0;
4243 +      entier valeur_max = dx[0];
4244 +      for(entier i = 1; i < size; i++)
4245 +        {
4246 +          const entier val = dx[i];
4247 +          if(val > valeur_max)
4248 +            {
4249 +              indice_max = i;
4250 +              valeur_max = val;
4251 +            }
4252 +        }
4253 +    }
4254 +  return indice_max;
4255 +}
4256 +
4257 +// Description:
4258 +//    Retourne la valeur minimale
4259 +// Precondition:
4260 +//    Le tableau doit contenir au moins une valeur
4261 +// Parametre: const ArrOfInt& dx
4262 +//    Signification: tableau a utiliser
4263 +// Retour: entier
4264 +//    Signification: valeur du min
4265 +entier min_array(const ArrOfInt& dx)
4266 +{
4267 +  const entier size = dx.size_array();
4268 +  assert(size > 0);
4269 +  entier valeur_min = dx[0];
4270 +  for(entier i = 1; i < size; i++)
4271 +    {
4272 +      const entier val = dx[i];
4273 +      if (val < valeur_min)
4274 +        valeur_min = val;
4275 +    }
4276 +  return valeur_min;
4277 +}
4278 +
4279 +// Description:
4280 +//    Retourne la valeur maximale
4281 +// Precondition:
4282 +//    Le tableau doit contenir au moins une valeur
4283 +// Parametre: const ArrOfInt& dx
4284 +//    Signification: tableau a utiliser
4285 +// Retour: entier
4286 +//    Signification: valeur du max
4287 +entier max_array(const ArrOfInt& dx)
4288 +{
4289 +  const entier size = dx.size_array();
4290 +  assert(size > 0);
4291 +  entier valeur_max = dx[0];
4292 +  for(entier i = 1; i < size; i++)
4293 +    {
4294 +      const entier val = dx[i];
4295 +      if (val > valeur_max)
4296 +        valeur_max = val;
4297 +    }
4298 +  return valeur_max;
4299 +}
4300 +
4301 +// Description:
4302 +//   Fonction de comparaison utilisee pour trier le tableau
4303 +//   dans ArrOfInt::trier(). Voir man qsort
4304 +static int fonction_compare_arrofentier_ordonner(const void * data1, const void * data2)
4305 +{
4306 +  const entier x = *(const entier*)data1;
4307 +  const entier y = *(const entier*)data2;
4308 +  return x - y;
4309 +}
4310 +
4311 +// Description:
4312 +//   Tri des valeurs du tableau dans l'ordre croissant.
4313 +//   La fonction utilisee est qsort de stdlib (elle est en n*log(n)).
4314 +void ArrOfInt::ordonne_array()
4315 +{
4316 +  const entier size = size_array();
4317 +  if (size > 1)
4318 +    {
4319 +      entier * data = addr();
4320 +      qsort(data, size, sizeof(entier),
4321 +            fonction_compare_arrofentier_ordonner);
4322 +    }
4323 +}
4324 +
4325 +// Description:
4326 +//    Fait pointer le tableau vers les memes donnees qu'un tableau
4327 +//    existant. Le tableau sera du meme type que le tableau m ("detache",
4328 +//    "normal"). Le tableau m ne doit pas etre de type "ref_data"
4329 +//    Les donnes existantes sont perdues si elles
4330 +//    ne sont pas referencees ailleurs.
4331 +// Precondition:
4332 +// Parametre: const ArrOfInt& m
4333 +//    Signification: le tableau a referencer (pas de type "ref_data"
4334 +//                   et different de *this !!!)
4335 +// Retour: ArrOfInt&
4336 +//    Signification: *this
4337 +//    Contraintes:
4338 +// Exception:
4339 +// Effets de bord:
4340 +// Postcondition:
4341 +ArrOfInt& ArrOfInt::ref_array(const ArrOfInt& m)
4342 +{
4343 +  assert(&m != this);
4344 +  // La condition 'm n'est pas de type "ref_data"' est necessaire pour
4345 +  // attach_array().
4346 +  detach_array();
4347 +  attach_array(m);
4348 +  return *this;
4349 +}
4350 +
4351 +// Description:
4352 +//    Fait pointer le tableau vers la zone de memoire "data_".
4353 +//    On detache la zone de memoire existante. Le tableau devient
4354 +//    de type "ref_data". Attention : ptr doit etre non nul.
4355 +//    La taille est initialisee avec size.
4356 +//    Cette methode est appelee notamment par IntVect::adopter.
4357 +// Parametre: entier*
4358 +//    Signification: le tableau a recuperer. Si pointeur nul alors size
4359 +//                   doit etre nulle aussi et le tableau reste detache
4360 +// Parametre: entier size
4361 +//    Signification: le nombre d'elements du tableau.
4362 +// Retour: ArrOfInt&
4363 +//    Signification: *this
4364 +ArrOfInt& ArrOfInt::ref_data(entier* ptr, entier size)
4365 +{
4366 +  assert(ptr != 0 || size == 0);
4367 +  assert(size >= 0);
4368 +  detach_array();
4369 +  data_ = ptr;
4370 +  size_array_ = size;
4371 +  return *this;
4372 +}
4373 +
4374 +// Description:
4375 +//  Amene le tableau dans l'etat "detache". C'est a dire:
4376 +//  Si le tableau est "detache" :
4377 +//   * ne rien faire
4378 +//  Si le tableau est "normal" :
4379 +//   * decremente le nombre de references a *p
4380 +//   * detruit *p si p->ref_count==0
4381 +//   * annule p_, data_ et size_array_
4382 +//  Si le tableau est "ref_data" :
4383 +//   * annule data_ et size_array_
4384 +// Retour: int
4385 +//    Signification: 1 si les donnees du tableau ont ete supprimees
4386 +// Precondition:
4387 +// Postcondition:
4388 +//  On a p_==0, data_==0 et size_array_==0, memory_size_ = 0
4389 +//  L'attribut smart_resize_ est conserve.
4390 +entier ArrOfInt::detach_array()
4391 +{
4392 +  entier retour = 0;
4393 +  if (p_)
4394 +    {
4395 +      // Le tableau est de type "normal"
4396 +      // Si la zone de memoire n'est plus utilisee par personne,
4397 +      // on la detruit.
4398 +      if ((p_->suppr_one_ref()) == 0)
4399 +        {
4400 +          delete p_;
4401 +          retour = 1;
4402 +        }
4403 +      p_ = 0;
4404 +    }
4405 +  data_ = 0;
4406 +  size_array_ = 0;
4407 +  memory_size_ = 0;
4408 +  return retour;
4409 +}
4410 +
4411 +// Description:
4412 +//    Amene le tableau dans l'etat "normal", "detache" ou "ref_array"
4413 +//    en associant la meme zone de memoire que le tableau m.
4414 +// Precondition:
4415 +//    Le tableau doit etre "detache"
4416 +// Parametre: const ArrOfInt& m
4417 +//    Signification: tableau a utiliser
4418 +//                   le tableau doit etre different de *this !!!
4419 +// Retour:
4420 +//    Signification:
4421 +//    Contraintes:
4422 +// Exception:
4423 +// Effets de bord:
4424 +// Postcondition:
4425 +//    Si m est detache, le tableau reste detache,
4426 +//    si m est "ref_array", le tableau devient "ref_array",
4427 +//    sinon le tableau est "normal", avec ref_count > 1
4428 +//    Si m est de taille nulle, le tableau reste detache + Warning dans fichier .log
4429 +void ArrOfInt::attach_array(const ArrOfInt& m)
4430 +{
4431 +  // Le tableau doit etre detache
4432 +  assert(data_ == 0 && p_ == 0);
4433 +  // Le tableau doit etre different de *this
4434 +  assert(&m != this);
4435 +
4436 +  if (m.size_array() > 0)
4437 +    {
4438 +      p_ = m.p_;
4439 +      if (p_)
4440 +        p_->add_one_ref();
4441 +      data_ = m.data_;
4442 +      size_array_ = m.size_array_;
4443 +      memory_size_ = m.memory_size_;
4444 +      smart_resize_ = m.smart_resize_;
4445 +    }
4446 +  else
4447 +    {
4448 +      // Cas particulier ou on attache un tableau de taille nulle:
4449 +      //  en theorie, c'est pareil qu'un tableau de taille non nulle, MAIS
4450 +      //  dans les operateurs (ex:Op_Dift_VDF_Face_Axi), une ref est construite
4451 +      //  avant que le tableau ne prenne sa taille definitive. Donc, pour ne pas
4452 +      //  empecher le resize, il ne faut pas attacher le tableau s'il n'a pas
4453 +      //  encore la bonne taille. Solution propre: reecrire les operateurs pour
4454 +      //  qu'ils ne prennent pas une ref avant que le tableau ne soit valide
4455 +      //  et faire p_ = m.p_ dans tous les cas.
4456 +    }
4457 +}
4458 +
4459 +// Description:
4460 +//    Copie les elements source[first_element_source + i]
4461 +//    dans les elements  (*this)[first_element_dest + i] pour 0 <= i < nb_elements
4462 +//    Les autres elements de (*this) sont inchanges.
4463 +// Precondition:
4464 +// Parametre:       const ArrOfInt& m
4465 +//  Signification:   le tableau a utiliser, doit etre different de *this !
4466 +// Parametre:       entier nb_elements
4467 +//  Signification:   nombre d'elements a copier, nb_elements >= -1.
4468 +//                   Si nb_elements==-1, on copie tout le tableau m.
4469 +//  Valeurs par defaut: -1
4470 +// Parametre:       entier first_element_dest
4471 +//  Valeurs par defaut: 0
4472 +// Parametre:       entier first_element_source
4473 +//  Valeurs par defaut: 0
4474 +// Retour: ArrOfInt&
4475 +//    Signification: *this
4476 +//    Contraintes:
4477 +// Exception:
4478 +//    Sort en erreur si la taille du tableau m est plus grande que la
4479 +//    taille de tableau this.
4480 +// Effets de bord:
4481 +// Postcondition:
4482 +ArrOfInt& ArrOfInt::inject_array(const ArrOfInt& source,
4483 +                                 entier nb_elements,
4484 +                                 entier first_element_dest,
4485 +                                 entier first_element_source)
4486 +{
4487 +  assert(&source != this);
4488 +  assert(nb_elements >= -1);
4489 +  assert(first_element_dest >= 0);
4490 +  assert(first_element_source >= 0);
4491 +
4492 +  if (nb_elements < 0)
4493 +    nb_elements = source.size_array();
4494 +
4495 +  assert(first_element_source + nb_elements <= source.size_array());
4496 +  assert(first_element_dest + nb_elements <= size_array());
4497 +
4498 +  if (nb_elements > 0)
4499 +    {
4500 +      entier * addr_dest = addr() + first_element_dest;
4501 +      const entier * addr_source = source.addr() + first_element_source;
4502 +      // memcpy(addr_dest , addr_source, nb_elements * sizeof(entier));
4503 +      entier i;
4504 +      for (i = 0; i < nb_elements; i++)
4505 +        {
4506 +          addr_dest[i] = addr_source[i];
4507 +        }
4508 +    }
4509 +  return *this;
4510 +}
4511 +
4512 +// Description:
4513 +//    Retourne le nombre de references des donnees du tableau
4514 +//    si le tableau est "normal", -1 s'il est "detache" ou "ref_data"
4515 +// Retour: int
4516 +//    Signification: ref_count_
4517 +entier ArrOfInt::ref_count() const
4518 +{
4519 +  if (p_)
4520 +    return p_->ref_count();
4521 +  else
4522 +    return -1;
4523 +}
4524 +
4525 +// Description:
4526 +//    Addition case a case sur toutes les cases du tableau
4527 +// Precondition:
4528 +//    la taille de y doit etre au moins egale a la taille de this
4529 +// Parametre: const ArrOfInt& y
4530 +//    Signification: tableau a ajouter
4531 +//    Valeurs par defaut:
4532 +//    Contraintes:
4533 +//    Acces:
4534 +// Retour: ArrOfInt&
4535 +//    Signification: *this
4536 +//    Contraintes:
4537 +// Exception:
4538 +// Effets de bord:
4539 +// Postcondition:
4540 +ArrOfInt& ArrOfInt::operator+=(const ArrOfInt& y)
4541 +{
4542 +  assert(size_array()==y.size_array());
4543 +  entier* dx = addr();
4544 +  const entier* dy = y.addr();
4545 +  const entier n = size_array();
4546 +  for (entier i=0; i<n; i++)
4547 +    dx[i] += dy[i];
4548 +  return *this;
4549 +}
4550 +
4551 +// Description:
4552 +//     ajoute la meme valeur a toutes les cases du tableau
4553 +// Precondition:
4554 +// Parametre: const entier dy
4555 +//    Signification: valeur a ajouter
4556 +//    Valeurs par defaut:
4557 +//    Contraintes:
4558 +//    Acces:
4559 +// Retour: ArrOfInt
4560 +//    Signification: *this
4561 +//    Contraintes:
4562 +// Exception:
4563 +// Effets de bord:
4564 +// Postcondition:
4565 +ArrOfInt& ArrOfInt::operator+=(const entier dy)
4566 +{
4567 +  entier * data = addr();
4568 +  const entier n = size_array();
4569 +  for(entier i=0; i < n; i++)
4570 +    data[i] += dy;
4571 +  return *this;
4572 +}
4573 +// Description:
4574 +//    Soustraction case a case sur toutes les cases du tableau
4575 +// Parametre: const ArrOfInt& y
4576 +//    Signification: tableau de meme taille que *this
4577 +// Retour: ArrOfInt&
4578 +//    Signification: *this
4579 +ArrOfInt& ArrOfInt::operator-=(const ArrOfInt& y)
4580 +{
4581 +  const entier size = size_array();
4582 +  assert(size == y.size_array());
4583 +  entier * data = addr();
4584 +  const entier * data_y = y.addr();
4585 +  for (entier i=0; i < size; i++)
4586 +    data[i] -= data_y[i];
4587 +  return *this;
4588 +}
4589 +
4590 +
4591 +// Description:
4592 +//     soustrait la meme valeur a toutes les cases
4593 +// Retour: ArrOfInt &
4594 +//    Signification: *this
4595 +ArrOfInt& ArrOfInt::operator-=(const entier dy)
4596 +{
4597 +  entier * data = addr();
4598 +  const entier n = size_array();
4599 +  for(entier i=0; i < n; i++)
4600 +    data[i] -= dy;
4601 +  return *this;
4602 +}
4603 +
4604 +// Description:
4605 +//   Renvoie un pointeur sur le premier element du tableau.
4606 +//   Le pointeur est nul si le tableau est "detache".
4607 +//   Attention, l'adresse peut changer apres un appel
4608 +//   a resize_array(), ref_data, ref_array, ...
4609 +// Precondition:
4610 +// Retour: const entier*
4611 +//   Signification: pointeur sur le premier element du tableau
4612 +const entier* ArrOfInt::addr() const
4613 +{
4614 +  return data_;
4615 +}
4616 +
4617 +// Description:
4618 +//   Renvoie un pointeur sur le premier element du tableau.
4619 +//   Le pointeur est nul si le tableau est "detache".
4620 +// Precondition:
4621 +// Retour: const entier*
4622 +//    Signification: la zone memoire du tableau
4623 +entier* ArrOfInt::addr()
4624 +{
4625 +  return data_;
4626 +}
4627 +
4628 +
4629 +IntTab::IntTab()
4630 +{
4631 +  // nb_dim_ = 2;
4632 +  dimensions_[0] = 0;
4633 +  dimensions_[1] = 0;
4634 +}
4635 +
4636 +IntTab::IntTab(const IntTab& tab) :
4637 +  ArrOfInt(tab)
4638 +{
4639 +  // nb_dim_ = tab.nb_dim_;
4640 +  dimensions_[0] = tab.dimensions_[0];
4641 +  dimensions_[1] = tab.dimensions_[1];
4642 +}
4643 +IntTab::IntTab(const entier i, const entier j) :
4644 +  ArrOfInt(i*j)
4645 +{
4646 +  // nb_dim_ = 2;
4647 +  dimensions_[0] = i;
4648 +  dimensions_[1] = j;
4649 +}
4650 +
4651 +IntTab& IntTab::operator=(const IntTab& tab)
4652 +{
4653 +  ArrOfInt::operator=(tab);
4654 +  // nb_dim_ = tab.nb_dim_;
4655 +  dimensions_[0] = tab.dimensions_[0];
4656 +  dimensions_[1] = tab.dimensions_[1];
4657 +  return *this;
4658 +}
4659 +
4660 +void IntTab::reset()
4661 +{
4662 +  ArrOfInt::reset();
4663 +  // nb_dim_ = 2;
4664 +  dimensions_[0] = 0;
4665 +  dimensions_[1] = 0;
4666 +}
4667 +
4668 diff --git a/databases/readers/Lata/ArrOfInt.h b/databases/readers/Lata/ArrOfInt.h
4669 new file mode 100644
4670 index 0000000..9d9a542
4671 --- /dev/null
4672 +++ b/databases/readers/Lata/ArrOfInt.h
4673 @@ -0,0 +1,343 @@
4674 +/*****************************************************************************
4675 +*
4676 +* Copyright (c) 2011 - 2013, CEA
4677 +* All rights reserved.
4678 +* Redistribution and use in source and binary forms, with or without
4679 +* modification, are permitted provided that the following conditions are met:
4680 +*
4681 +*     * Redistributions of source code must retain the above copyright
4682 +*       notice, this list of conditions and the following disclaimer.
4683 +*     * Redistributions in binary form must reproduce the above copyright
4684 +*       notice, this list of conditions and the following disclaimer in the
4685 +*       documentation and/or other materials provided with the distribution.
4686 +*     * Neither the name of CEA, nor the
4687 +*       names of its contributors may be used to endorse or promote products
4688 +*       derived from this software without specific prior written permission.
4689 +*
4690 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
4691 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
4692 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
4693 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
4694 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
4695 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4696 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
4697 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4698 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
4699 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4700 +*
4701 +*****************************************************************************/
4702 +
4703 +////////////////////////////////////////////////////////////
4704 +//
4705 +// Warning : DO NOT EDIT !
4706 +//          Please update ArrOf_Scalar_Prototype.h.P
4707 +//          and this file will be generated automatically
4708 +//           by the script file check.sh
4709 +////////////////////////////////////////////////////////////
4710 +
4711 +#ifndef ArrOfInt_H
4712 +#define ArrOfInt_H
4713 +
4714 +#include <assert.h>
4715 +#include <arch.h>
4716 +#include <Objet_U.h>
4717 +
4718 +
4719 +class VIntdata;
4720 +
4721 +class ArrOfInt
4722 +{
4723 +public:
4724 +  //
4725 +  // Destructeur
4726 +  //
4727 +  virtual ~ArrOfInt();
4728 +  //
4729 +  // Constructeurs
4730 +  //
4731 +  ArrOfInt();
4732 +  ArrOfInt(entier size);
4733 +  ArrOfInt(entier size, entier initial_value);
4734 +  // Constructeur par copie : deep copy (on duplique les donnees)
4735 +  ArrOfInt(const ArrOfInt& );
4736 +  //
4737 +  // Methodes de construction tardive (on cree un tableau vide avec ArrOfInt()
4738 +  // puis on appelle ces methodes pour modifier les caracteristiques du tableau :
4739 +  //
4740 +  // Change le nombre d'elements du tableau
4741 +  inline ArrOfInt& resize_array(entier new_size);
4742 +
4743 +  // Methodes de gestion de l'allocation memoire:
4744 +  // Assigne une valeur au drapeau "smart_resize"
4745 +  // (reallocation uniquement si la taille augmente)
4746 +  void    set_smart_resize(entier flag);
4747 +  // Gestion du type de memoire alouee (standard ou pool de memoire Trio-U)
4748 +  enum    Storage { STANDARD, TEMP_STORAGE, SIMD_ALIGNED };
4749 +  void    set_mem_storage(const Storage storage);
4750 +  Storage get_mem_storage() const;
4751 +
4752 +  // Construction de tableaux qui pointent vers des donnees existantes
4753 +  // !!! Utiliser ref_data avec precaution (attention a size_array_)
4754 +  ArrOfInt& ref_data(entier* ptr, entier size);
4755 +  ArrOfInt& ref_array(const ArrOfInt&);
4756 +  // Operateur copie
4757 +  ArrOfInt& operator=(const ArrOfInt&);
4758 +  // Remise du tableau dans l'etat initial (obtenu par le constructeur par defaut)
4759 +  virtual void reset();
4760 +
4761 +  //
4762 +  // Methodes d'acces aux donnees et aux caracteristiques du tableau
4763 +  //
4764 +  // Remplit le tableau avec la valeur en parametre
4765 +  ArrOfInt& operator=(entier valeur);
4766 +
4767 +  inline       entier& operator[](entier i);
4768 +  inline const entier& operator[](entier i) const;
4769 +
4770 +  // Ces methodes renvoient un pointeur vers le premier element du tableau.
4771 +  const entier * addr() const;
4772 +  entier * addr();
4773 +  // Renvoie le nombre d'elements du tableau (et non la taille allouee)
4774 +  inline entier size_array() const;
4775 +  // Renvoie le nombre de tableaux qui pointent vers la stucture "*p_"
4776 +  entier ref_count() const;
4777 +  // Ajoute une case en fin de tableau et y stocke la "valeur"
4778 +  inline void   append_array(entier valeur);
4779 +
4780 +  //
4781 +  // Operateurs divers
4782 +  //
4783 +  ArrOfInt& operator+=(const ArrOfInt&);
4784 +  ArrOfInt& operator+=(const entier);
4785 +  ArrOfInt& operator-=(const ArrOfInt&);
4786 +  ArrOfInt& operator-=(const entier);
4787 +  ArrOfInt& inject_array(const ArrOfInt& source,
4788 +                         entier nb_elements = -1,
4789 +                         entier first_element_dest = 0,
4790 +                         entier first_element_source = 0);
4791 +  ArrOfInt& copy_array(const ArrOfInt&);
4792 +
4793 +
4794 +  void             ordonne_array();
4795 +
4796 +protected:
4797 +  //
4798 +  // Methodes accessibles depuis les descendants de ArrOfInt
4799 +  //
4800 +  void   attach_array(const ArrOfInt&);
4801 +  entier detach_array();
4802 +  void   fill_default_value(entier first, entier nb);
4803 +private:
4804 +  // B. Mathieu 22/06/2004 : je mets ces membres "private" pour forcer
4805 +  // le passage par les accesseurs dans les classes derivees, au cas ou
4806 +  // on voudrait modifier l'implementation.
4807 +
4808 +  // Zone de memoire contenant les valeurs du tableau.
4809 +  // Pointeur nul => le tableau est "detache" ou "ref_data"
4810 +  // Pointeur non nul => le tableau est "normal"
4811 +  VIntdata* p_;
4812 +
4813 +  // Pointeur vers le premier element du tableau (egal a p_->data si p_!=0)
4814 +  // Pointeur nul => le tableau est "detache".
4815 +  // Pointeur non nul => le tableau est "normal" ou "ref_data"
4816 +  entier*   data_;
4817 +
4818 +  // Nombre d'elements du tableau (inferieur ou egal a memory_size_).
4819 +  // Si le tableau est "detache", alors size_array_=0
4820 +  entier    size_array_;
4821 +  // Taille memoire reellement allouee pour le tableau
4822 +  // (pour le mecanisme smart_resize_). memory_size_ est nul
4823 +  // si le tableau est de type "ref_data". Sinon memory_size_
4824 +  // est egal a p_->size_.
4825 +  entier    memory_size_;
4826 +
4827 +  // Drapeau indiquant si on applique une strategie d'allocation
4828 +  // preventive (la memoire alouee augmente d'un facteur constant
4829 +  // si la taille devient insuffisante).
4830 +  // Si smart_resize_ == 0, alors on a toujours p_->size_ == size
4831 +  entier    smart_resize_;
4832 +
4833 +  // Drapeau indiquant si l'allocation memoire a lieu avec un new classique
4834 +  // ou dans le pool de memoire temporaire de Trio
4835 +  Storage   storage_type_;
4836 +
4837 +  // Partie non inline de resize_array():
4838 +  // Declaration des constantes pour les options de memory_resize
4839 +  static const entier COPY_OLD;
4840 +  static const entier INITIALIZE_NEW;
4841 +  void memory_resize(entier new_size, entier options);
4842 +};
4843 +
4844 +#define MAXDIMIntTab 2
4845 +
4846 +class IntTab : public ArrOfInt
4847 +{
4848 +public:
4849 +  IntTab();
4850 +  IntTab(const IntTab&);
4851 +  IntTab(const entier i, const entier j);
4852 +  IntTab&    operator=(const IntTab&);
4853 +  void              reset();
4854 +
4855 +  inline entier& operator()(entier i, entier j);
4856 +  inline entier   operator()(entier i, entier j) const;
4857 +
4858 +  inline entier resize(entier i, entier j);
4859 +  inline entier dimension(entier i) const;
4860 +  inline entier dimension_tot(entier i) const;
4861 +
4862 +protected:
4863 +  // In order to mimic TRUST behavior, operator[] is forbidden
4864 +  // for 2 dimensionnal matrices, you must cast to ArrOf to use it..
4865 +  double&        operator[](entier i);
4866 +  const double& operator[](entier i) const;
4867 +
4868 +private:
4869 +  //  entier nb_dim_;
4870 +  entier dimensions_[MAXDIMIntTab];
4871 +};
4872 +
4873 +inline entier& IntTab::operator()(entier i, entier j)
4874 +{
4875 +  // assert(nb_dim_ == 2);
4876 +  assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]);
4877 +  const entier n = i * dimensions_[1] + j;
4878 +  entier& x = ArrOfInt::operator[] (n);
4879 +  return x;
4880 +}
4881 +
4882 +inline entier   IntTab::operator()(entier i, entier j) const
4883 +{
4884 +  // assert(nb_dim_ == 2);
4885 +  assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]);
4886 +  const entier n = i * dimensions_[1] + j;
4887 +  entier x = ArrOfInt::operator[] (n);
4888 +  return x;
4889 +}
4890 +
4891 +inline entier IntTab::resize(entier i, entier j)
4892 +{
4893 +  assert(i >= 0 && j >= 0);
4894 +  // nb_dim_ = 2;
4895 +  dimensions_[0] = i;
4896 +  dimensions_[1] = j;
4897 +  ArrOfInt::resize_array(i * j);
4898 +  return i*j;
4899 +}
4900 +
4901 +inline entier IntTab::dimension(entier i) const
4902 +{
4903 +  assert(i >= 0 && i < 2);
4904 +  return dimensions_[i];
4905 +}
4906 +
4907 +// Description: renvoie la meme valeur que dimension.
4908 +inline entier IntTab::dimension_tot(entier i) const
4909 +{
4910 +  return dimension(i);
4911 +}
4912 +
4913 +//
4914 +// Declarations des fonctions non membres de la classe ArrOfInt
4915 +//
4916 +entier operator==(const ArrOfInt& x, const ArrOfInt& y) ;
4917 +entier imin_array(const ArrOfInt&) ;
4918 +entier imax_array(const ArrOfInt&) ;
4919 +entier min_array(const ArrOfInt&) ;
4920 +entier max_array(const ArrOfInt&) ;
4921 +
4922 +
4923 +// ******************************************************************
4924 +//                   FONCTIONS MEMBRES DE ArrOfInt
4925 +// ******************************************************************
4926 +
4927 +// Description :
4928 +//  Change le nombre d'elements du tableau. Cette fonction est inline
4929 +//  car elle doit etre tres rapide dans le cas ou smart_resize_==1
4930 +//  (utilisation frequente de resize_array())
4931 +//  Si smart_resize est non nul :
4932 +//   Si la nouvelle taille est inferieure ou egale a la taille
4933 +//   alouee (p->get_size()) on ne realloue pas de memoire
4934 +//   sinon, on realloue et on copie les donnees existantes.
4935 +//  Astuce pour ne pas copier les anciennes donnees:
4936 +//   resize(0); resize(n);
4937 +//  Si smart_resize est nul, on realloue une nouvelle zone memoire
4938 +//   uniquement si la nouvelle taille est differente de l'ancienne.
4939 +// Precondition :
4940 +//  Si "new_size" est egal a la taille du tableau, aucune condition.
4941 +//  Sinon, le tableau doit etre soit detache, soit normal (pas de type "ref_data")
4942 +//  et ref_count doit etre egal a 1 (pas d'autre reference au tableau).
4943 +//
4944 +inline ArrOfInt& ArrOfInt::resize_array(entier new_size)
4945 +{
4946 +  assert(new_size >= 0);
4947 +  // Soit le tableau est detache (data_==0), soit il est normal (p_!=0)
4948 +  // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau,
4949 +  // ou alors la taille ne doit pas changer.
4950 +  assert(new_size == size_array_ || data_ == 0 || (p_ != 0 && ref_count() == 1));
4951 +
4952 +  if ((smart_resize_ == 0) || (new_size > memory_size_))
4953 +    memory_resize(new_size, COPY_OLD + INITIALIZE_NEW);
4954 +  size_array_ = new_size;
4955 +  return *this;
4956 +}
4957 +
4958 +// Description:
4959 +//     operateur [] retourne le ieme element du tableau
4960 +// Precondition:
4961 +// Parametre: entier i
4962 +//    Signification: indice dans l'intervalle 0 <= i < size_array()
4963 +// Exception:
4964 +//    assert si i n'est pas dans l'intervalle
4965 +inline entier& ArrOfInt::operator[](entier i)
4966 +{
4967 +  assert(i >= 0 && i < size_array_);
4968 +  return data_[i];
4969 +}
4970 +
4971 +// Description:
4972 +//     operateur [] retourne le ieme element du tableau
4973 +// Precondition:
4974 +// Parametre: entier i
4975 +//    Signification: indice dans l'intervalle 0 <= i < size_array()
4976 +// Exception:
4977 +//    assert si i n'est pas dans l'intervalle
4978 +inline const entier& ArrOfInt::operator[](entier i) const
4979 +{
4980 +  assert(i >= 0 && i < size_array_);
4981 +  return data_[i];
4982 +}
4983 +
4984 +// Description:
4985 +//    Renvoie la taille du tableau (nombre d'elements declares
4986 +//    a la construction ou a resize_array()).
4987 +//    C'est le nombre d'elements accessibles a operator[]
4988 +// Retour: entier
4989 +inline entier  ArrOfInt::size_array() const
4990 +{
4991 +  return size_array_;
4992 +}
4993 +
4994 +// Description:
4995 +//  Ajoute une case en fin de tableau et y stocke la "valeur"
4996 +// Precondition:
4997 +//  Tableau doit etre de type "smart_resize" (sinon, ecroulement
4998 +//  des performances). De plus, le tableau ne doit pas etre "ref_data",
4999 +//  et il ne doit pas y avoir plus d'une reference a la zone de
5000 +//  memoire pointee (meme precondition que resize_array())
5001 +inline void   ArrOfInt::append_array(entier valeur)
5002 +{
5003 +  assert(smart_resize_);
5004 +  // Soit le tableau est detache (data_==0), soit il est normal (p_!=0)
5005 +  // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau.
5006 +  assert(data_ == 0 || (p_ != 0 && ref_count() == 1));
5007 +
5008 +  if (size_array_+1 > memory_size_)
5009 +    memory_resize(size_array_+1, COPY_OLD);
5010 +  data_[size_array_] = valeur;
5011 +  size_array_++;
5012 +}
5013 +
5014 +// ArrOfInt_H
5015 +#endif
5016 +
5017 diff --git a/databases/readers/Lata/ArrOf_Scalar_Prototype.cpp.h b/databases/readers/Lata/ArrOf_Scalar_Prototype.cpp.h
5018 new file mode 100644
5019 index 0000000..b881750
5020 --- /dev/null
5021 +++ b/databases/readers/Lata/ArrOf_Scalar_Prototype.cpp.h
5022 @@ -0,0 +1,1168 @@
5023 +/*****************************************************************************
5024 +*
5025 +* Copyright (c) 2011 - 2013, CEA
5026 +* All rights reserved.
5027 +* Redistribution and use in source and binary forms, with or without
5028 +* modification, are permitted provided that the following conditions are met:
5029 +*
5030 +*     * Redistributions of source code must retain the above copyright
5031 +*       notice, this list of conditions and the following disclaimer.
5032 +*     * Redistributions in binary form must reproduce the above copyright
5033 +*       notice, this list of conditions and the following disclaimer in the
5034 +*       documentation and/or other materials provided with the distribution.
5035 +*     * Neither the name of CEA, nor the
5036 +*       names of its contributors may be used to endorse or promote products
5037 +*       derived from this software without specific prior written permission.
5038 +*
5039 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
5040 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
5041 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
5042 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
5043 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
5044 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
5045 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
5046 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5047 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
5048 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5049 +*
5050 +*****************************************************************************/
5051 +
5052 +#include <ArrOf__Scalar__.h>
5053 +__DoubleOnlyBegin__
5054 +#include <math.h>
5055 +__DoubleOnlyEnd__
5056 +__IntOnlyBegin__
5057 +// limits.h definit INT_MIN, SHRT_MIN, ...
5058 +#include <limits.h>
5059 +__IntOnlyEnd__
5060 +#include <stdlib.h>
5061 +#include <Objet_U.h>
5062 +#include <iostream>
5063 +#include <stdlib.h>
5064 +
5065 +// ******************************************************************
5066 +//
5067 +//             Implementation des methodes de V__Scalar__data
5068 +//
5069 +// ******************************************************************
5070 +////////////////////////////////////////////////////////////////////
5071 +// .NOM        ArrOf__Scalar__
5072 +// .ENTETE     TRUST Math
5073 +// .LIBRAIRIE  libtmath
5074 +// .FILE       ArrOf__Scalar__.h
5075 +// .FILE       ArrOf__Scalar__.cpp
5076 +//
5077 +// .DESCRIPTION
5078 +// V__Scalar__data alloue une zone de memoire de la taille specifiee au
5079 +// constructeur, et libere la zone de memoire a la destruction.
5080 +// La memoire peut etre allouee sur le tas (avec new) ou par le
5081 +// mecanisme Memoire::add_trav___scalar__.
5082 +//
5083 +// "ref_count" compte le nombre de pointeurs qui font reference a "this".
5084 +// (permet au dernier utilisateur de l'objet de le detruire), voir
5085 +// ArrOf__Scalar__.
5086 +//
5087 +// .SECTION voir aussi
5088 +// .CONTRAINTES
5089 +// .INVARIANTS
5090 +// .HTML
5091 +// .EPS
5092 +///////////////////////////////////////////////////////////////////
5093 +
5094 +class V__Scalar__data
5095 +{
5096 +public:
5097 +  V__Scalar__data(entier size, ArrOf__Scalar__::Storage storage);
5098 +  ~V__Scalar__data();
5099 +  entier          add_one_ref();
5100 +  entier          suppr_one_ref();
5101 +  __scalar__ *        get_data();
5102 +  const __scalar__ *  get_data() const;
5103 +  inline entier   ref_count() const;
5104 +  inline entier   get_size() const;
5105 +private:
5106 +  // Le constructeur par copie et l'operateur= sont interdits.
5107 +  V__Scalar__data(const V__Scalar__data& v);
5108 +  V__Scalar__data& operator=(const V__Scalar__data& v);
5109 +
5110 +  // "data" est un pointeur sur une zone de memoire de taille
5111 +  // sz * sizeof(__scalar__), allouee par le
5112 +  // constructeur et liberee par le destructeur.
5113 +  // Ce pointeur n'est jamais nul meme si size_==0
5114 +  __scalar__ * data_;
5115 +  // Compteur incremente par add_one_ref et decremente par suppr_one_ref.
5116 +  // Contient le nombre d'objets ArrOf__Scalar__ dont le membre "p" pointe
5117 +  // vers "this". On a ref_count_ >= 0.
5118 +  entier ref_count_;
5119 +  // "sz" est la taille du tableau "data_" alloue
5120 +  // On a sz >= 0.
5121 +  entier size_;
5122 +  // Si storage est de type TEMP_STORAGE, d_ptr_trav porte la reference
5123 +  // a la zone allouee, sinon le pointeur est nul.
5124 +  //__Scalar___ptr_trav * d_ptr_trav_;
5125 +};
5126 +
5127 +
5128 +// Description:
5129 +//    Construit un V__Scalar__data de taille size >= 0
5130 +// Parametre: entier s
5131 +//    Signification: taille du V__Scalar__data, il faut size >= 0
5132 +// Parametre: Storage storage
5133 +//    Signification: indique si la memoire doit etre allouee
5134 +//                   avec "new" ou avec "memoire.add_trav___scalar__()"
5135 +//    Valeurs par defaut: STANDARD (allocation avec "new")
5136 +// Postcondition:
5137 +//    data_ n'est jamais nul, meme si size==0
5138 +V__Scalar__data::V__Scalar__data(entier size, ArrOf__Scalar__::Storage storage)
5139 +{
5140 +  if (size == 0)
5141 +    storage = ArrOf__Scalar__::STANDARD;
5142 +
5143 +  switch (storage)
5144 +    {
5145 +    case ArrOf__Scalar__::STANDARD:
5146 +      {
5147 +#ifdef _EXCEPTION_
5148 +        // Allocation de la memoire sur le tas
5149 +        try
5150 +          {
5151 +            data_ = new __scalar__[size];
5152 +          }
5153 +        catch(...)
5154 +          {
5155 +            Cerr << "impossible d'allouer " << size << " __scalar__ " << finl;
5156 +            throw;
5157 +          }
5158 +#else
5159 +        data_ = new __scalar__[size];
5160 +        if(!data_)
5161 +          {
5162 +            Cerr << "impossible d'allouer " << size << "__scalar__ " << finl;
5163 +            throw ;
5164 +          }
5165 +#endif
5166 +        break;
5167 +      }
5168 +    default:
5169 +      throw;
5170 +    }
5171 +  ref_count_ = 1;
5172 +  size_ = size;
5173 +
5174 +  assert(data_ != 0);
5175 +}
5176 +
5177 +// Description:
5178 +//  Detruit la zone de memoire allouee.
5179 +// Precondition:
5180 +//  ref_count == 0 (la zone de memoire ne doit etre referencee nulle part)
5181 +V__Scalar__data::~V__Scalar__data()
5182 +{
5183 +  assert(ref_count_ == 0);
5184 +
5185 +  // Stockage STANDARD
5186 +  delete[] data_;
5187 +
5188 +  data_ = 0;  // paranoia: si size_==-1 c'est qu'on pointe sur un zombie
5189 +  size_ = -1; //  (pointeur vers un objet qui a ete detruit)
5190 +}
5191 +
5192 +// Description: renvoie ref_count_
5193 +inline entier V__Scalar__data::ref_count() const
5194 +{
5195 +  return ref_count_;
5196 +}
5197 +
5198 +// Description: renvoie size_
5199 +inline entier V__Scalar__data::get_size() const
5200 +{
5201 +  return size_;
5202 +}
5203 +
5204 +// Description:
5205 +//     Un nouveau tableau utilise cette zone memoire :
5206 +//     incremente ref_count
5207 +// Retour: int
5208 +//    Signification: ref_count
5209 +inline entier V__Scalar__data::add_one_ref()
5210 +{
5211 +  return ++ref_count_;
5212 +}
5213 +
5214 +// Description:
5215 +//     Un tableau de moins utilise cette zone memoire
5216 +//     decremente ref_count
5217 +// Precondition:
5218 +//     ref_count_ > 0
5219 +// Retour: int
5220 +//    Signification: ref_count
5221 +inline entier V__Scalar__data::suppr_one_ref()
5222 +{
5223 +  assert(ref_count_ > 0);
5224 +  return (--ref_count_);
5225 +}
5226 +
5227 +// Description: renvoie data_
5228 +inline __scalar__ * V__Scalar__data::get_data()
5229 +{
5230 +  return data_;
5231 +}
5232 +
5233 +// Description: renvoie data_
5234 +inline const __scalar__ * V__Scalar__data::get_data() const
5235 +{
5236 +  return data_;
5237 +}
5238 +
5239 +// Description: Constructeur par copie. Interdit : genere une erreur !
5240 +V__Scalar__data::V__Scalar__data(const V__Scalar__data& v)
5241 +{
5242 +  Cerr << "Erreur dans V__Scalar__data::V__Scalar__data(const V__Scalar__data & v)" << finl;
5243 +  throw;
5244 +}
5245 +
5246 +// Description: Operateur= interdit. Genere une erreur !
5247 +V__Scalar__data& V__Scalar__data::operator=(const V__Scalar__data& v)
5248 +{
5249 +  Cerr << "Erreur dans V__Scalar__data::operator=(const V__Scalar__data & v)" << finl;
5250 +  throw;
5251 +  return *this;
5252 +}
5253 +
5254 +// ******************************************************************
5255 +//
5256 +//             Implementation des methodes de ArrOf__Scalar__
5257 +//
5258 +// ******************************************************************
5259 +
5260 +
5261 +// Definition des constantes pour les options de memory_resize
5262 +const entier ArrOf__Scalar__::COPY_OLD = 1;
5263 +const entier ArrOf__Scalar__::INITIALIZE_NEW = 2;
5264 +
5265 +// Description:
5266 +//  Destructeur : appelle detach_array()
5267 +ArrOf__Scalar__::~ArrOf__Scalar__()
5268 +{
5269 +  detach_array();
5270 +  size_array_ = -1; // Paranoia: si size_array_==-1, c'est un zombie
5271 +}
5272 +
5273 +// Description:
5274 +//  Constructeur par defaut: cree un tableau "detache",
5275 +//  soit p_==0, data_==0, size_array_==0, smart_resize_==0
5276 +ArrOf__Scalar__::ArrOf__Scalar__() :
5277 +  p_(0),
5278 +  data_(0),
5279 +  size_array_(0),
5280 +  memory_size_(0),
5281 +  smart_resize_(0),
5282 +  storage_type_(STANDARD)
5283 +{
5284 +}
5285 +
5286 +// Description:
5287 +//     Cree un tableau de taille n avec allocation standard
5288 +//     (voir set_mem_storage).
5289 +//     Valeur de remplissage par defaut: voir fill_default_value
5290 +// Precondition:
5291 +// Parametre: entier n
5292 +//    Signification: taille du tableau
5293 +ArrOf__Scalar__::ArrOf__Scalar__(entier n) :
5294 +  p_(new V__Scalar__data(n, STANDARD)),
5295 +  data_(p_->get_data()),
5296 +  size_array_(n),
5297 +  memory_size_(n),
5298 +  smart_resize_(0),
5299 +  storage_type_(STANDARD)
5300 +{
5301 +  if (n > 0)
5302 +    fill_default_value(0, n);
5303 +}
5304 +
5305 +// Description:
5306 +//     Cree un tableau de taille n
5307 +//     toutes les cases sont initialisees a x
5308 +// Precondition:
5309 +// Parametre: entier n
5310 +//    Signification: taille du tableau
5311 +// Parametre: __scalar__ x
5312 +//    Signification: valeur pour initialiser le tableau
5313 +ArrOf__Scalar__::ArrOf__Scalar__(entier n, __scalar__ x) :
5314 +  p_(new V__Scalar__data(n, STANDARD)),
5315 +  data_(p_->get_data()),
5316 +  size_array_(n),
5317 +  memory_size_(n),
5318 +  smart_resize_(0),
5319 +  storage_type_(STANDARD)
5320 +{
5321 +  *this = x;
5322 +}
5323 +
5324 +// Description:
5325 +//     Constructeur par copie. On alloue une nouvelle zone de memoire
5326 +//     et on copie le contenu du tableau. L'attribut smart_resize_ est
5327 +//     copie aussi.
5328 +//     Si le tableau A est de taille nulle, on cree un tableau "detache",
5329 +//     sinon on cree un tableau "normal".
5330 +// Parametre: const ArrOf__Scalar__& A
5331 +//    Signification: le tableau a copier
5332 +ArrOf__Scalar__::ArrOf__Scalar__(const ArrOf__Scalar__& A)
5333 +{
5334 +  const entier size = A.size_array();
5335 +  if (size > 0)
5336 +    {
5337 +      // Creation d'un tableau "normal"
5338 +      storage_type_ = STANDARD;
5339 +      p_ = new V__Scalar__data(size, STANDARD);
5340 +      data_ = p_->get_data();
5341 +      size_array_ = size;
5342 +      memory_size_ = size;
5343 +      smart_resize_ = A.smart_resize_;
5344 +      inject_array(A);
5345 +    }
5346 +  else
5347 +    {
5348 +      // Creation d'un tableau "detache"
5349 +      p_ = 0;
5350 +      data_ = 0;
5351 +      size_array_ = 0;
5352 +      memory_size_ = 0;
5353 +      smart_resize_ = 0;
5354 +      storage_type_ = STANDARD;
5355 +    }
5356 +}
5357 +
5358 +// Description:
5359 +//   Change le mode d'allocation memoire lors des resize
5360 +//   (voir V__Scalar__data et __Scalar___ptr_trav)
5361 +//   Exemple pour creer un tableau avec allocation temporaire:
5362 +//    DoubleTab tab; // Creation d'un tableau vide
5363 +//    tab.set_mem_storage(TEMP_STORAGE); // Changement de mode d'allocation
5364 +//    tab.resize(n); // Allocation memoire
5365 +void ArrOf__Scalar__::set_mem_storage(const Storage storage)
5366 +{
5367 +  storage_type_ = storage;
5368 +}
5369 +
5370 +// Description:
5371 +//   Renvoie le mode d'allocation du tableau (qui sera utilise
5372 +//   lors du prochain resize si changement de taille).
5373 +//   (voir V__Scalar__data et __Scalar___ptr_trav)
5374 +enum ArrOf__Scalar__::Storage ArrOf__Scalar__::get_mem_storage() const
5375 +{
5376 +  return storage_type_;
5377 +}
5378 +
5379 +// Description:
5380 +//   Change le mode l'allocation memoire: reallocation d'un tableau
5381 +//   a chaque changement de taille (flag = 0) ou reallocation
5382 +//   uniquement si la taille augmente et par doublement de la taille
5383 +//   du tableau (flag = 1).
5384 +void ArrOf__Scalar__::set_smart_resize(entier flag)
5385 +{
5386 +  assert(flag == 0 || flag == 1);
5387 +  smart_resize_ = flag;
5388 +}
5389 +
5390 +// Description:
5391 +//    Remet le tableau dans l'etat obtenu avec le constructeur par defaut
5392 +//    (libere la memoire mais conserve le mode d'allocation memoire actuel)
5393 +void ArrOf__Scalar__::reset()
5394 +{
5395 +  detach_array();
5396 +}
5397 +
5398 +// Description:
5399 +//    Copie les donnees du tableau m.
5400 +//    Si "m" n'a pas la meme taille que "*this", on fait un resize_array.
5401 +//    Ensuite, on copie les valeurs de "m" dans "*this".
5402 +//    Le type de tableau (methode d'allocation) n'est pas copie.
5403 +// Precondition:
5404 +//    Si le tableau n'a pas la meme taille que "m", alors *this doit
5405 +//    etre "resizable" (ne pas etre de type "ref_data" et "ref_count == 1")
5406 +// Parametre: const ArrOf__Scalar__& m
5407 +//    Signification: la tableau a copier
5408 +// Retour:  ArrOf__Scalar__&
5409 +//    Signification: *this
5410 +ArrOf__Scalar__& ArrOf__Scalar__::operator=(const ArrOf__Scalar__& m)
5411 +{
5412 +  if (&m != this)
5413 +    {
5414 +      const entier new_size = m.size_array();
5415 +      // Le code suivant est quasiment une copie de ArrOf__Scalar__::resize()
5416 +      // SAUF: memory_resize est appele avec NO_INITIALIZE (la zone de memoire
5417 +      //  n'est pas initialisee)
5418 +      if (new_size != size_array())
5419 +        {
5420 +          if ((smart_resize_ == 0) || (new_size > memory_size_))
5421 +            memory_resize(new_size, 0); // Pas d'initialisation
5422 +          size_array_ = new_size;
5423 +        }
5424 +      inject_array(m);
5425 +    }
5426 +  return *this;
5427 +}
5428 +
5429 +
5430 +// Description:
5431 +//     x est affecte a toutes les cases
5432 +// Precondition:
5433 +// Parametre: __scalar__ x
5434 +//    Signification: la valeur a affecter a toutes les cases du tableau
5435 +//    Valeurs par defaut:
5436 +//    Contraintes:
5437 +//    Acces:
5438 +// Retour: ArrOf__Scalar__&
5439 +//    Signification: *this
5440 +//    Contraintes:
5441 +// Exception:
5442 +// Effets de bord:
5443 +// Postcondition:
5444 +ArrOf__Scalar__& ArrOf__Scalar__::operator=(__scalar__ x)
5445 +{
5446 +  const entier n = size_array();
5447 +  __scalar__ *data = addr();
5448 +  for (entier i = 0; i < n; i++)
5449 +    {
5450 +      data[i] = x;
5451 +    }
5452 +  return *this;
5453 +}
5454 +
5455 +// Description: appelle operator=(a)
5456 +ArrOf__Scalar__& ArrOf__Scalar__::copy_array(const ArrOf__Scalar__ & a)
5457 +{
5458 +  operator=(a);
5459 +  return *this;
5460 +}
5461 +
5462 +// Description:
5463 +//  Si besoin, alloue une nouvelle zone de memoire,
5464 +//  copie les donnees et efface l'ancienne zone de memoire.
5465 +//  Attention, on suppose que cette methode est appelee par
5466 +//  resize_array().
5467 +//  Attention: si ref_count_>1, l'appel a resize_array() est
5468 +//  autorise uniquement si la nouvelle taille est identique
5469 +//  a la precedente.
5470 +// Precondition:
5471 +//  Le tableau doit etre de type "detache" ou "normal" avec
5472 +//  ref_count==1, et il faut new_size >= 0
5473 +//  On suppose que size_array contient encore le nombre d'elements
5474 +//  valides avant changement de taille.
5475 +// Parametre: new_size
5476 +//  Signification: nouvelle taille demandee pour le tableau.
5477 +// Parametre: options
5478 +//  Signification: COPY_OLD => on recopie les anciennes donnees dans le nouveau
5479 +//                  tableau (jusqu'au max de l'ancienne et de la nouvelle taille).
5480 +//                 INITIALIZE_NEW => initialisation des cases non copiees
5481 +// Postcondition:
5482 +//  p_ et data_ sont mis a jour, mais pas size_array_ !!!
5483 +//  (on suppose que c'est fait dans resize_array()).
5484 +//  Si la nouvelle taille est nulle, on detache le tableau.
5485 +void  ArrOf__Scalar__::memory_resize(entier new_size, entier options)
5486 +{
5487 +  assert(new_size >= 0);
5488 +
5489 +  // Occupation memoire de l'ancien tableau:
5490 +  entier old_mem_size = 0;
5491 +  if (p_)
5492 +    old_mem_size = p_->get_size();
5493 +
5494 +  // Occupation memoire du nouveau tableau :
5495 +  // Si smart_resize, on prend au moins deux fois la taille
5496 +  // precedente, ou new_size
5497 +  entier new_mem_size = new_size;
5498 +  if (smart_resize_ && (old_mem_size * 2 > new_size))
5499 +    new_mem_size = old_mem_size * 2;
5500 +
5501 +  if (new_mem_size != old_mem_size)
5502 +    {
5503 +      // detach_array() efface le contenu de size_array_. On le met de cote:
5504 +      const entier old_size_array = size_array_;
5505 +      // On va reellement changer l'adresse du tableau.
5506 +      // Il ne faut pas qu'il existe d'autre reference a ce tableau.
5507 +      assert(data_ == 0 || (p_ != 0 && ref_count() == 1));
5508 +      if (new_mem_size == 0)
5509 +        {
5510 +          // La nouvelle taille est nulle, on cree un tableau "detache"
5511 +          detach_array();
5512 +        }
5513 +      else
5514 +        {
5515 +          // Allocation d'une nouvelle zone
5516 +          V__Scalar__data * new_p = new V__Scalar__data(new_mem_size, storage_type_);
5517 +          __scalar__ * new_data = new_p->get_data();
5518 +          // Raccourci si le tableau etait "detache", inutile de copier
5519 +          // les anciennes donnees. On copie si COPY_OLD est demande
5520 +          entier copy_size = 0;
5521 +          if (data_ != 0)
5522 +            {
5523 +              // Calcul du nombre d'elements a copier vers la nouvelle
5524 +              // zone de memoire : c'est le min de l'ancienne et de
5525 +              // la nouvelle taille.
5526 +              if (options & COPY_OLD)
5527 +                {
5528 +                  copy_size = size_array_;
5529 +                  if (new_size < copy_size)
5530 +                    copy_size = new_size;
5531 +                  // Copie des valeurs dans le nouveau tableau
5532 +                  for (entier i = 0; i < copy_size; i++)
5533 +                    new_data[i] = data_[i];
5534 +                }
5535 +              // Destruction de l'ancienne zone (si plus aucune reference)
5536 +              detach_array();
5537 +            }
5538 +          // On attache la nouvelle zone de memoire
5539 +          p_ = new_p;
5540 +          data_ = new_data;
5541 +          memory_size_ = new_mem_size;
5542 +          // Initialisation des cases supplementaires avec une valeur par defaut
5543 +          if (options & INITIALIZE_NEW)
5544 +            fill_default_value(copy_size, new_mem_size - copy_size);
5545 +          // Restaure l'ancienne valeur de size_array_
5546 +          size_array_ = old_size_array;
5547 +        }
5548 +    }
5549 +}
5550 +
5551 +// Description:
5552 +//  Remplit "nb" cases consecutives du tableau a partir de la case "first"
5553 +//  avec une valeur par defaut.
5554 +//  Cette fonction est appelee lors d'un resize pour initialiser les
5555 +//  cases nouvellement creees.
5556 +//  Le comportement depend actuellement du type de tableau :
5557 +//  * Tableau de type "smart_resize":
5558 +//    * en mode debug (macro NDEBUG non definie) le tableau est initialise
5559 +//      avec une valeur invalide.
5560 +//    * en optimise, le tableau n'est pas initialise
5561 +//  * Tableau normal :
5562 +//    Le tableau est initialise avec la valeur 0. Ce comportement est choisi
5563 +//    pour des raisons de compatibilite avec l'implementation precedente.
5564 +//    Cette specification pourrait etre modifiee prochainement pour des raisons
5565 +//    de performances (pour ne pas avoir a initialiser inutilement les tableaux).
5566 +//    DONC: il faut supposer desormais que les nouvelles cases ne sont pas
5567 +//    initialisees lors d'un resize.
5568 +// Parametre: first
5569 +//  Signification: premiere case a initialiser.
5570 +//  Contrainte:    (nb==0) ou (0 <= first < memory_size_)
5571 +// Parametre: nb
5572 +//  Signification: nombre de cases a initialiser.
5573 +//  Contrainte:    (nb==0) ou (0 < nb <= memory_size_ - first)
5574 +void  ArrOf__Scalar__::fill_default_value(entier first, entier nb)
5575 +{
5576 +  assert((nb == 0) || (first >= 0 && first < memory_size_));
5577 +  assert((nb == 0) || (nb > 0 && nb <= memory_size_ - first));
5578 +  __scalar__ * data = addr();
5579 +  assert(data!=0 || nb==0);
5580 +  data += first;
5581 +  if (smart_resize_)
5582 +    {
5583 +      // On initialise uniquement en mode debug
5584 +#ifndef NDEBUG
5585 +      __IntOnlyBegin__
5586 +      static const entier ENTIER_INVALIDE = INT_MIN;
5587 +      for (entier i = 0; i < nb; i++)
5588 +        data[i] = ENTIER_INVALIDE;
5589 +      __IntOnlyEnd__
5590 +      __DoubleOnlyBegin__
5591 +      // Ceci represente un NAN. N'importe quelle operation avec ca fait encore un NAN.
5592 +      // Si c'est pas portable, on peut remplacer par DMAX_FLOAT sur les autres machines.
5593 +      static const unsigned long long  VALEUR_INVALIDE =
5594 +        0x7ff7ffffffffffffULL;
5595 +
5596 +      // On utilise "memcpy" et non "=" car "=" peut provoquer une exception
5597 +      // si la copie passe par le fpu.
5598 +      for (entier i = 0; i < nb; i++)
5599 +        memcpy(data + i, & VALEUR_INVALIDE, sizeof(__scalar__));
5600 +      __DoubleOnlyEnd__
5601 +#endif
5602 +    }
5603 +  else
5604 +    {
5605 +      // Comportement pour les tableaux normaux : compatibilite avec la
5606 +      // version precedente : on initialise avec 0.
5607 +      for (entier i = 0; i < nb; i++)
5608 +        data[i] = (__scalar__) 0;
5609 +    }
5610 +}
5611 +
5612 +// ****************************************************************
5613 +//
5614 +//         Fonctions non membres de la classe ArrOf__Scalar__
5615 +//
5616 +// ****************************************************************
5617 +
5618 +// Description:
5619 +//  Renvoie 1 si les tableaux "v" et "a" sont de la meme taille
5620 +//  et contiennent les memes valeurs au sens strict, sinon renvoie 0.
5621 +//  Le test est !(v[i]!=a[i])
5622 +entier operator==(const ArrOf__Scalar__& v, const ArrOf__Scalar__& a)
5623 +{
5624 +  const entier n = v.size_array();
5625 +  const entier na = a.size_array();
5626 +  entier resu = 1;
5627 +  if (n != na)
5628 +    {
5629 +      resu = 0;
5630 +    }
5631 +  else
5632 +    {
5633 +      const __scalar__* vv = v.addr();
5634 +      const __scalar__* av = a.addr();
5635 +      entier i;
5636 +      for (i = 0; i < n; i++)
5637 +        {
5638 +          if (av[i] != vv[i])
5639 +            {
5640 +              resu = 0;
5641 +              break;
5642 +            }
5643 +        }
5644 +    }
5645 +  return resu;
5646 +}
5647 +
5648 +// Description:
5649 +//    Retourne l'indice du min ou -1 si le tableau est vide
5650 +// Precondition:
5651 +// Parametre: const ArrOf__Scalar__& dx
5652 +//    Signification: tableau a utiliser
5653 +// Retour: int
5654 +//    Signification: indice du min
5655 +entier imin_array(const ArrOf__Scalar__& dx)
5656 +{
5657 +  entier indice_min = -1;
5658 +  const entier size = dx.size_array();
5659 +  if (size > 0)
5660 +    {
5661 +      indice_min = 0;
5662 +      __scalar__ valeur_min = dx[0];
5663 +      for(entier i = 1; i < size; i++)
5664 +        {
5665 +          const __scalar__ val = dx[i];
5666 +          if(val < valeur_min)
5667 +            {
5668 +              indice_min = i;
5669 +              valeur_min = val;
5670 +            }
5671 +        }
5672 +    }
5673 +  return indice_min;
5674 +}
5675 +
5676 +// Description:
5677 +//    Retourne l'indice du max ou -1 si le tableau est vide
5678 +// Precondition:
5679 +// Parametre: const ArrOf__Scalar__& dx
5680 +//    Signification: tableau a utiliser
5681 +// Retour: int
5682 +//    Signification: indice du max
5683 +entier imax_array(const ArrOf__Scalar__& dx)
5684 +{
5685 +  entier indice_max = -1;
5686 +  const entier size = dx.size_array();
5687 +  if (size > 0)
5688 +    {
5689 +      indice_max = 0;
5690 +      __scalar__ valeur_max = dx[0];
5691 +      for(entier i = 1; i < size; i++)
5692 +        {
5693 +          const __scalar__ val = dx[i];
5694 +          if(val > valeur_max)
5695 +            {
5696 +              indice_max = i;
5697 +              valeur_max = val;
5698 +            }
5699 +        }
5700 +    }
5701 +  return indice_max;
5702 +}
5703 +
5704 +// Description:
5705 +//    Retourne la valeur minimale
5706 +// Precondition:
5707 +//    Le tableau doit contenir au moins une valeur
5708 +// Parametre: const ArrOf__Scalar__& dx
5709 +//    Signification: tableau a utiliser
5710 +// Retour: __scalar__
5711 +//    Signification: valeur du min
5712 +__scalar__ min_array(const ArrOf__Scalar__& dx)
5713 +{
5714 +  const entier size = dx.size_array();
5715 +  assert(size > 0);
5716 +  __scalar__ valeur_min = dx[0];
5717 +  for(entier i = 1; i < size; i++)
5718 +    {
5719 +      const __scalar__ val = dx[i];
5720 +      if (val < valeur_min)
5721 +        valeur_min = val;
5722 +    }
5723 +  return valeur_min;
5724 +}
5725 +
5726 +// Description:
5727 +//    Retourne la valeur maximale
5728 +// Precondition:
5729 +//    Le tableau doit contenir au moins une valeur
5730 +// Parametre: const ArrOf__Scalar__& dx
5731 +//    Signification: tableau a utiliser
5732 +// Retour: __scalar__
5733 +//    Signification: valeur du max
5734 +__scalar__ max_array(const ArrOf__Scalar__& dx)
5735 +{
5736 +  const entier size = dx.size_array();
5737 +  assert(size > 0);
5738 +  __scalar__ valeur_max = dx[0];
5739 +  for(entier i = 1; i < size; i++)
5740 +    {
5741 +      const __scalar__ val = dx[i];
5742 +      if (val > valeur_max)
5743 +        valeur_max = val;
5744 +    }
5745 +  return valeur_max;
5746 +}
5747 +
5748 +// Description:
5749 +//   Fonction de comparaison utilisee pour trier le tableau
5750 +//   dans ArrOf__Scalar__::trier(). Voir man qsort
5751 +static int fonction_compare_arrof__scalar___ordonner(const void * data1, const void * data2)
5752 +{
5753 +  const __scalar__ x = *(const __scalar__*)data1;
5754 +  const __scalar__ y = *(const __scalar__*)data2;
5755 +  __DoubleOnlyBegin__
5756 +  if (x < y)
5757 +    return -1;
5758 +  else if (x > y)
5759 +    return 1;
5760 +  else
5761 +    return 0;
5762 +  __DoubleOnlyEnd__
5763 +  __IntOnlyBegin__
5764 +  return x - y;
5765 +  __IntOnlyEnd__
5766 +}
5767 +
5768 +// Description:
5769 +//   Tri des valeurs du tableau dans l'ordre croissant.
5770 +//   La fonction utilisee est qsort de stdlib (elle est en n*log(n)).
5771 +void ArrOf__Scalar__::ordonne_array()
5772 +{
5773 +  const entier size = size_array();
5774 +  if (size > 1)
5775 +    {
5776 +      __scalar__ * data = addr();
5777 +      qsort(data, size, sizeof(__scalar__),
5778 +            fonction_compare_arrof__scalar___ordonner);
5779 +    }
5780 +}
5781 +
5782 +// Description:
5783 +//    Fait pointer le tableau vers les memes donnees qu'un tableau
5784 +//    existant. Le tableau sera du meme type que le tableau m ("detache",
5785 +//    "normal"). Le tableau m ne doit pas etre de type "ref_data"
5786 +//    Les donnes existantes sont perdues si elles
5787 +//    ne sont pas referencees ailleurs.
5788 +// Precondition:
5789 +// Parametre: const ArrOf__Scalar__& m
5790 +//    Signification: le tableau a referencer (pas de type "ref_data"
5791 +//                   et different de *this !!!)
5792 +// Retour: ArrOf__Scalar__&
5793 +//    Signification: *this
5794 +//    Contraintes:
5795 +// Exception:
5796 +// Effets de bord:
5797 +// Postcondition:
5798 +ArrOf__Scalar__& ArrOf__Scalar__::ref_array(const ArrOf__Scalar__& m)
5799 +{
5800 +  assert(&m != this);
5801 +  // La condition 'm n'est pas de type "ref_data"' est necessaire pour
5802 +  // attach_array().
5803 +  detach_array();
5804 +  attach_array(m);
5805 +  return *this;
5806 +}
5807 +
5808 +// Description:
5809 +//    Fait pointer le tableau vers la zone de memoire "data_".
5810 +//    On detache la zone de memoire existante. Le tableau devient
5811 +//    de type "ref_data". Attention : ptr doit etre non nul.
5812 +//    La taille est initialisee avec size.
5813 +//    Cette methode est appelee notamment par __Scalar__Vect::adopter.
5814 +// Parametre: __scalar__*
5815 +//    Signification: le tableau a recuperer. Si pointeur nul alors size
5816 +//                   doit etre nulle aussi et le tableau reste detache
5817 +// Parametre: entier size
5818 +//    Signification: le nombre d'elements du tableau.
5819 +// Retour: ArrOf__Scalar__&
5820 +//    Signification: *this
5821 +ArrOf__Scalar__& ArrOf__Scalar__::ref_data(__scalar__* ptr, entier size)
5822 +{
5823 +  assert(ptr != 0 || size == 0);
5824 +  assert(size >= 0);
5825 +  detach_array();
5826 +  data_ = ptr;
5827 +  size_array_ = size;
5828 +  return *this;
5829 +}
5830 +
5831 +// Description:
5832 +//  Amene le tableau dans l'etat "detache". C'est a dire:
5833 +//  Si le tableau est "detache" :
5834 +//   * ne rien faire
5835 +//  Si le tableau est "normal" :
5836 +//   * decremente le nombre de references a *p
5837 +//   * detruit *p si p->ref_count==0
5838 +//   * annule p_, data_ et size_array_
5839 +//  Si le tableau est "ref_data" :
5840 +//   * annule data_ et size_array_
5841 +// Retour: int
5842 +//    Signification: 1 si les donnees du tableau ont ete supprimees
5843 +// Precondition:
5844 +// Postcondition:
5845 +//  On a p_==0, data_==0 et size_array_==0, memory_size_ = 0
5846 +//  L'attribut smart_resize_ est conserve.
5847 +entier ArrOf__Scalar__::detach_array()
5848 +{
5849 +  entier retour = 0;
5850 +  if (p_)
5851 +    {
5852 +      // Le tableau est de type "normal"
5853 +      // Si la zone de memoire n'est plus utilisee par personne,
5854 +      // on la detruit.
5855 +      if ((p_->suppr_one_ref()) == 0)
5856 +        {
5857 +          delete p_;
5858 +          retour = 1;
5859 +        }
5860 +      p_ = 0;
5861 +    }
5862 +  data_ = 0;
5863 +  size_array_ = 0;
5864 +  memory_size_ = 0;
5865 +  return retour;
5866 +}
5867 +
5868 +// Description:
5869 +//    Amene le tableau dans l'etat "normal", "detache" ou "ref_array"
5870 +//    en associant la meme zone de memoire que le tableau m.
5871 +// Precondition:
5872 +//    Le tableau doit etre "detache"
5873 +// Parametre: const ArrOf__Scalar__& m
5874 +//    Signification: tableau a utiliser
5875 +//                   le tableau doit etre different de *this !!!
5876 +// Retour:
5877 +//    Signification:
5878 +//    Contraintes:
5879 +// Exception:
5880 +// Effets de bord:
5881 +// Postcondition:
5882 +//    Si m est detache, le tableau reste detache,
5883 +//    si m est "ref_array", le tableau devient "ref_array",
5884 +//    sinon le tableau est "normal", avec ref_count > 1
5885 +//    Si m est de taille nulle, le tableau reste detache + Warning dans fichier .log
5886 +void ArrOf__Scalar__::attach_array(const ArrOf__Scalar__& m)
5887 +{
5888 +  // Le tableau doit etre detache
5889 +  assert(data_ == 0 && p_ == 0);
5890 +  // Le tableau doit etre different de *this
5891 +  assert(&m != this);
5892 +
5893 +  if (m.size_array() > 0)
5894 +    {
5895 +      p_ = m.p_;
5896 +      if (p_)
5897 +        p_->add_one_ref();
5898 +      data_ = m.data_;
5899 +      size_array_ = m.size_array_;
5900 +      memory_size_ = m.memory_size_;
5901 +      smart_resize_ = m.smart_resize_;
5902 +    }
5903 +  else
5904 +    {
5905 +      // Cas particulier ou on attache un tableau de taille nulle:
5906 +      //  en theorie, c'est pareil qu'un tableau de taille non nulle, MAIS
5907 +      //  dans les operateurs (ex:Op_Dift_VDF_Face_Axi), une ref est construite
5908 +      //  avant que le tableau ne prenne sa taille definitive. Donc, pour ne pas
5909 +      //  empecher le resize, il ne faut pas attacher le tableau s'il n'a pas
5910 +      //  encore la bonne taille. Solution propre: reecrire les operateurs pour
5911 +      //  qu'ils ne prennent pas une ref avant que le tableau ne soit valide
5912 +      //  et faire p_ = m.p_ dans tous les cas.
5913 +    }
5914 +}
5915 +
5916 +// Description:
5917 +//    Copie les elements source[first_element_source + i]
5918 +//    dans les elements  (*this)[first_element_dest + i] pour 0 <= i < nb_elements
5919 +//    Les autres elements de (*this) sont inchanges.
5920 +// Precondition:
5921 +// Parametre:       const ArrOf__Scalar__& m
5922 +//  Signification:   le tableau a utiliser, doit etre different de *this !
5923 +// Parametre:       entier nb_elements
5924 +//  Signification:   nombre d'elements a copier, nb_elements >= -1.
5925 +//                   Si nb_elements==-1, on copie tout le tableau m.
5926 +//  Valeurs par defaut: -1
5927 +// Parametre:       entier first_element_dest
5928 +//  Valeurs par defaut: 0
5929 +// Parametre:       entier first_element_source
5930 +//  Valeurs par defaut: 0
5931 +// Retour: ArrOf__Scalar__&
5932 +//    Signification: *this
5933 +//    Contraintes:
5934 +// Exception:
5935 +//    Sort en erreur si la taille du tableau m est plus grande que la
5936 +//    taille de tableau this.
5937 +// Effets de bord:
5938 +// Postcondition:
5939 +ArrOf__Scalar__& ArrOf__Scalar__::inject_array(const ArrOf__Scalar__& source,
5940 +    entier nb_elements,
5941 +    entier first_element_dest,
5942 +    entier first_element_source)
5943 +{
5944 +  assert(&source != this);
5945 +  assert(nb_elements >= -1);
5946 +  assert(first_element_dest >= 0);
5947 +  assert(first_element_source >= 0);
5948 +
5949 +  if (nb_elements < 0)
5950 +    nb_elements = source.size_array();
5951 +
5952 +  assert(first_element_source + nb_elements <= source.size_array());
5953 +  assert(first_element_dest + nb_elements <= size_array());
5954 +
5955 +  if (nb_elements > 0)
5956 +    {
5957 +      __scalar__ * addr_dest = addr() + first_element_dest;
5958 +      const __scalar__ * addr_source = source.addr() + first_element_source;
5959 +      // memcpy(addr_dest , addr_source, nb_elements * sizeof(__scalar__));
5960 +      entier i;
5961 +      for (i = 0; i < nb_elements; i++)
5962 +        {
5963 +          addr_dest[i] = addr_source[i];
5964 +        }
5965 +    }
5966 +  return *this;
5967 +}
5968 +
5969 +// Description:
5970 +//    Retourne le nombre de references des donnees du tableau
5971 +//    si le tableau est "normal", -1 s'il est "detache" ou "ref_data"
5972 +// Retour: int
5973 +//    Signification: ref_count_
5974 +entier ArrOf__Scalar__::ref_count() const
5975 +{
5976 +  if (p_)
5977 +    return p_->ref_count();
5978 +  else
5979 +    return -1;
5980 +}
5981 +
5982 +// Description:
5983 +//    Addition case a case sur toutes les cases du tableau
5984 +// Precondition:
5985 +//    la taille de y doit etre au moins egale a la taille de this
5986 +// Parametre: const ArrOf__Scalar__& y
5987 +//    Signification: tableau a ajouter
5988 +//    Valeurs par defaut:
5989 +//    Contraintes:
5990 +//    Acces:
5991 +// Retour: ArrOf__Scalar__&
5992 +//    Signification: *this
5993 +//    Contraintes:
5994 +// Exception:
5995 +// Effets de bord:
5996 +// Postcondition:
5997 +ArrOf__Scalar__& ArrOf__Scalar__::operator+=(const ArrOf__Scalar__& y)
5998 +{
5999 +  assert(size_array()==y.size_array());
6000 +  __scalar__* dx = addr();
6001 +  const __scalar__* dy = y.addr();
6002 +  const entier n = size_array();
6003 +  for (entier i=0; i<n; i++)
6004 +    dx[i] += dy[i];
6005 +  return *this;
6006 +}
6007 +
6008 +// Description:
6009 +//     ajoute la meme valeur a toutes les cases du tableau
6010 +// Precondition:
6011 +// Parametre: const __scalar__ dy
6012 +//    Signification: valeur a ajouter
6013 +//    Valeurs par defaut:
6014 +//    Contraintes:
6015 +//    Acces:
6016 +// Retour: ArrOf__Scalar__
6017 +//    Signification: *this
6018 +//    Contraintes:
6019 +// Exception:
6020 +// Effets de bord:
6021 +// Postcondition:
6022 +ArrOf__Scalar__& ArrOf__Scalar__::operator+=(const __scalar__ dy)
6023 +{
6024 +  __scalar__ * data = addr();
6025 +  const entier n = size_array();
6026 +  for(entier i=0; i < n; i++)
6027 +    data[i] += dy;
6028 +  return *this;
6029 +}
6030 +// Description:
6031 +//    Soustraction case a case sur toutes les cases du tableau
6032 +// Parametre: const ArrOf__Scalar__& y
6033 +//    Signification: tableau de meme taille que *this
6034 +// Retour: ArrOf__Scalar__&
6035 +//    Signification: *this
6036 +ArrOf__Scalar__& ArrOf__Scalar__::operator-=(const ArrOf__Scalar__& y)
6037 +{
6038 +  const entier size = size_array();
6039 +  assert(size == y.size_array());
6040 +  __scalar__ * data = addr();
6041 +  const __scalar__ * data_y = y.addr();
6042 +  for (entier i=0; i < size; i++)
6043 +    data[i] -= data_y[i];
6044 +  return *this;
6045 +}
6046 +
6047 +
6048 +// Description:
6049 +//     soustrait la meme valeur a toutes les cases
6050 +// Retour: ArrOf__Scalar__ &
6051 +//    Signification: *this
6052 +ArrOf__Scalar__& ArrOf__Scalar__::operator-=(const __scalar__ dy)
6053 +{
6054 +  __scalar__ * data = addr();
6055 +  const entier n = size_array();
6056 +  for(entier i=0; i < n; i++)
6057 +    data[i] -= dy;
6058 +  return *this;
6059 +}
6060 +
6061 +// Description:
6062 +//   Renvoie un pointeur sur le premier element du tableau.
6063 +//   Le pointeur est nul si le tableau est "detache".
6064 +//   Attention, l'adresse peut changer apres un appel
6065 +//   a resize_array(), ref_data, ref_array, ...
6066 +// Precondition:
6067 +// Retour: const __scalar__*
6068 +//   Signification: pointeur sur le premier element du tableau
6069 +const __scalar__* ArrOf__Scalar__::addr() const
6070 +{
6071 +  return data_;
6072 +}
6073 +
6074 +// Description:
6075 +//   Renvoie un pointeur sur le premier element du tableau.
6076 +//   Le pointeur est nul si le tableau est "detache".
6077 +// Precondition:
6078 +// Retour: const __scalar__*
6079 +//    Signification: la zone memoire du tableau
6080 +__scalar__* ArrOf__Scalar__::addr()
6081 +{
6082 +  return data_;
6083 +}
6084 +
6085 +__DoubleOnlyBegin__
6086 +
6087 +// Description:
6088 +//    Retourne le max des abs(i)
6089 +// Precondition:
6090 +//    Le tableau doit contenir au moins une valeur
6091 +// Parametre: const ArrOf__Scalar__& dx
6092 +//    Signification: tableau a utiliser
6093 +//    Valeurs par defaut:
6094 +//    Contraintes:
6095 +//    Acces:
6096 +// Retour: __scalar__
6097 +//    Signification: valeur du max des valeurs absolues
6098 +//    Contraintes:
6099 +// Exception:
6100 +// Effets de bord:
6101 +// Postcondition:
6102 +__scalar__ max_abs_array(const ArrOf__Scalar__& dx)
6103 +{
6104 +  const entier size = dx.size_array();
6105 +  assert(size > 0);
6106 +  __scalar__ valeur_max = fabs(dx[0]);
6107 +  for(entier i = 1; i < size; i++)
6108 +    {
6109 +      const __scalar__ val = fabs(dx[i]);
6110 +      if (val > valeur_max)
6111 +        valeur_max = val;
6112 +    }
6113 +  return valeur_max;
6114 +}
6115 +
6116 +// Description:
6117 +//     muliplie toutes les cases par dy
6118 +// Retour: ArrOf__Scalar__ &
6119 +//    Signification: *this
6120 +ArrOf__Scalar__& ArrOf__Scalar__::operator*= (const __scalar__ dy)
6121 +{
6122 +  __scalar__ * data = addr();
6123 +  const entier n = size_array();
6124 +  for(entier i=0; i < n; i++)
6125 +    data[i] *= dy;
6126 +  return *this;
6127 +}
6128 +
6129 +
6130 +// Description:
6131 +//     divise toutes les cases par dy
6132 +// Retour: ArrOf__Scalar__ &
6133 +//    Signification: *this
6134 +ArrOf__Scalar__& ArrOf__Scalar__::operator/= (const __scalar__ dy)
6135 +{
6136 +  // En theorie: les deux lignes suivantes sont plus efficaces, mais
6137 +  //  cela produit des differences sur certains cas tests
6138 +  //  (Hyd_C_VEF_Smago et Lambda_var_VEF_turb). Ca veut dire qu'il y
6139 +  //  a un probleme autre part mais pour l'instant on laisse l'ancien
6140 +  //  codage.
6141 +  // const __scalar__ i_dy = 1. / dy;
6142 +  // operator*=(i_dy);
6143 +
6144 +  __scalar__ * data = addr();
6145 +  const entier n = size_array();
6146 +  for(entier i=0; i < n; i++)
6147 +    data[i] /= dy;
6148 +
6149 +  return *this;
6150 +}
6151 +__DoubleOnlyEnd__
6152 +
6153 +__Scalar__Tab::__Scalar__Tab()
6154 +{
6155 +  nb_dim_ = 2;
6156 +  dimensions_[0] = 0;
6157 +  dimensions_[1] = 0;
6158 +}
6159 +
6160 +__Scalar__Tab::__Scalar__Tab(const __Scalar__Tab& tab) :
6161 +  ArrOf__Scalar__(tab)
6162 +{
6163 +  nb_dim_ = tab.nb_dim_;
6164 +  dimensions_[0] = tab.dimensions_[0];
6165 +  dimensions_[1] = tab.dimensions_[1];
6166 +}
6167 +__Scalar__Tab::__Scalar__Tab(const entier i, const entier j) :
6168 +  ArrOf__Scalar__(i*j)
6169 +{
6170 +  nb_dim_ = 2;
6171 +  dimensions_[0] = i;
6172 +  dimensions_[1] = j;
6173 +}
6174 +
6175 +__Scalar__Tab& __Scalar__Tab::operator=(const __Scalar__Tab& tab)
6176 +{
6177 +  ArrOf__Scalar__::operator=(tab);
6178 +  nb_dim_ = tab.nb_dim_;
6179 +  dimensions_[0] = tab.dimensions_[0];
6180 +  dimensions_[1] = tab.dimensions_[1];
6181 +  return *this;
6182 +}
6183 +
6184 +void __Scalar__Tab::reset()
6185 +{
6186 +  ArrOf__Scalar__::reset();
6187 +  nb_dim_ = 2;
6188 +  dimensions_[0] = 0;
6189 +  dimensions_[1] = 0;
6190 +}
6191 diff --git a/databases/readers/Lata/ArrOf_Scalar_Prototype.h b/databases/readers/Lata/ArrOf_Scalar_Prototype.h
6192 new file mode 100644
6193 index 0000000..689932f
6194 --- /dev/null
6195 +++ b/databases/readers/Lata/ArrOf_Scalar_Prototype.h
6196 @@ -0,0 +1,357 @@
6197 +/*****************************************************************************
6198 +*
6199 +* Copyright (c) 2011 - 2013, CEA
6200 +* All rights reserved.
6201 +* Redistribution and use in source and binary forms, with or without
6202 +* modification, are permitted provided that the following conditions are met:
6203 +*
6204 +*     * Redistributions of source code must retain the above copyright
6205 +*       notice, this list of conditions and the following disclaimer.
6206 +*     * Redistributions in binary form must reproduce the above copyright
6207 +*       notice, this list of conditions and the following disclaimer in the
6208 +*       documentation and/or other materials provided with the distribution.
6209 +*     * Neither the name of CEA, nor the
6210 +*       names of its contributors may be used to endorse or promote products
6211 +*       derived from this software without specific prior written permission.
6212 +*
6213 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
6214 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
6215 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
6216 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
6217 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
6218 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
6219 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6220 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6221 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
6222 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6223 +*
6224 +*****************************************************************************/
6225 +
6226 +
6227 +#ifndef ArrOf__Scalar___H
6228 +#define ArrOf__Scalar___H
6229 +
6230 +#include <assert.h>
6231 +#include <arch.h>
6232 +#include <Objet_U.h>
6233 +
6234 +__DoubleOnlyBegin__
6235 +#define DMAXFLOAT 1e40
6236 +__DoubleOnlyEnd__
6237 +
6238 +class V__Scalar__data;
6239 +
6240 +class ArrOf__Scalar__
6241 +{
6242 +public:
6243 +  //
6244 +  // Destructeur
6245 +  //
6246 +  virtual ~ArrOf__Scalar__();
6247 +  //
6248 +  // Constructeurs
6249 +  //
6250 +  ArrOf__Scalar__();
6251 +  ArrOf__Scalar__(entier size);
6252 +  ArrOf__Scalar__(entier size, __scalar__ initial_value);
6253 +  // Constructeur par copie : deep copy (on duplique les donnees)
6254 +  ArrOf__Scalar__(const ArrOf__Scalar__& );
6255 +  //
6256 +  // Methodes de construction tardive (on cree un tableau vide avec ArrOf__Scalar__()
6257 +  // puis on appelle ces methodes pour modifier les caracteristiques du tableau :
6258 +  //
6259 +  // Change le nombre d'elements du tableau
6260 +  inline ArrOf__Scalar__& resize_array(entier new_size);
6261 +
6262 +  // Methodes de gestion de l'allocation memoire:
6263 +  // Assigne une valeur au drapeau "smart_resize"
6264 +  // (reallocation uniquement si la taille augmente)
6265 +  void    set_smart_resize(entier flag);
6266 +  // Gestion du type de memoire alouee (standard ou pool de memoire Trio-U)
6267 +  enum    Storage { STANDARD, TEMP_STORAGE };
6268 +  void    set_mem_storage(const Storage storage);
6269 +  Storage get_mem_storage() const;
6270 +
6271 +  // Construction de tableaux qui pointent vers des donnees existantes
6272 +  // !!! Utiliser ref_data avec precaution (attention a size_array_)
6273 +  ArrOf__Scalar__& ref_data(__scalar__* ptr, entier size);
6274 +  ArrOf__Scalar__& ref_array(const ArrOf__Scalar__&);
6275 +  // Operateur copie
6276 +  ArrOf__Scalar__& operator=(const ArrOf__Scalar__&);
6277 +  // Remise du tableau dans l'etat initial (obtenu par le constructeur par defaut)
6278 +  virtual void reset();
6279 +
6280 +  //
6281 +  // Methodes d'acces aux donnees et aux caracteristiques du tableau
6282 +  //
6283 +  // Remplit le tableau avec la valeur en parametre
6284 +  ArrOf__Scalar__& operator=(__scalar__ valeur);
6285 +
6286 +  inline       __scalar__& operator[](entier i);
6287 +  inline const __scalar__& operator[](entier i) const;
6288 +
6289 +  // Ces methodes renvoient un pointeur vers le premier element du tableau.
6290 +  const __scalar__ * addr() const;
6291 +  __scalar__ * addr();
6292 +  // Renvoie le nombre d'elements du tableau (et non la taille allouee)
6293 +  inline entier size_array() const;
6294 +  // Renvoie le nombre de tableaux qui pointent vers la stucture "*p_"
6295 +  entier ref_count() const;
6296 +  // Ajoute une case en fin de tableau et y stocke la "valeur"
6297 +  inline void   append_array(__scalar__ valeur);
6298 +
6299 +  //
6300 +  // Operateurs divers
6301 +  //
6302 +  ArrOf__Scalar__& operator+=(const ArrOf__Scalar__&);
6303 +  ArrOf__Scalar__& operator+=(const __scalar__);
6304 +  ArrOf__Scalar__& operator-=(const ArrOf__Scalar__&);
6305 +  ArrOf__Scalar__& operator-=(const __scalar__);
6306 +  ArrOf__Scalar__& inject_array(const ArrOf__Scalar__ & source,
6307 +                                entier nb_elements = -1,
6308 +                                entier first_element_dest = 0,
6309 +                                entier first_element_source = 0);
6310 +  ArrOf__Scalar__& copy_array(const ArrOf__Scalar__&);
6311 +
6312 +  __DoubleOnlyBegin__
6313 +  ArrOf__Scalar__& operator*= (const __scalar__) ;
6314 +  ArrOf__Scalar__& operator/= (const __scalar__) ;
6315 +  __DoubleOnlyEnd__
6316 +
6317 +  void             ordonne_array();
6318 +
6319 +protected:
6320 +  //
6321 +  // Methodes accessibles depuis les descendants de ArrOf__Scalar__
6322 +  //
6323 +  void   attach_array(const ArrOf__Scalar__&);
6324 +  entier detach_array();
6325 +  void   fill_default_value(entier first, entier nb);
6326 +private:
6327 +  // B. Mathieu 22/06/2004 : je mets ces membres "private" pour forcer
6328 +  // le passage par les accesseurs dans les classes derivees, au cas ou
6329 +  // on voudrait modifier l'implementation.
6330 +
6331 +  // Zone de memoire contenant les valeurs du tableau.
6332 +  // Pointeur nul => le tableau est "detache" ou "ref_data"
6333 +  // Pointeur non nul => le tableau est "normal"
6334 +  V__Scalar__data* p_;
6335 +
6336 +  // Pointeur vers le premier element du tableau (egal a p_->data si p_!=0)
6337 +  // Pointeur nul => le tableau est "detache".
6338 +  // Pointeur non nul => le tableau est "normal" ou "ref_data"
6339 +  __scalar__*   data_;
6340 +
6341 +  // Nombre d'elements du tableau (inferieur ou egal a memory_size_).
6342 +  // Si le tableau est "detache", alors size_array_=0
6343 +  entier    size_array_;
6344 +  // Taille memoire reellement allouee pour le tableau
6345 +  // (pour le mecanisme smart_resize_). memory_size_ est nul
6346 +  // si le tableau est de type "ref_data". Sinon memory_size_
6347 +  // est egal a p_->size_.
6348 +  entier    memory_size_;
6349 +
6350 +  // Drapeau indiquant si on applique une strategie d'allocation
6351 +  // preventive (la memoire alouee augmente d'un facteur constant
6352 +  // si la taille devient insuffisante).
6353 +  // Si smart_resize_ == 0, alors on a toujours p_->size_ == size
6354 +  entier    smart_resize_;
6355 +
6356 +  // Drapeau indiquant si l'allocation memoire a lieu avec un new classique
6357 +  // ou dans le pool de memoire temporaire de Trio
6358 +  Storage   storage_type_;
6359 +
6360 +  // Partie non inline de resize_array():
6361 +  // Declaration des constantes pour les options de memory_resize
6362 +  static const entier COPY_OLD;
6363 +  static const entier INITIALIZE_NEW;
6364 +  void memory_resize(entier new_size, entier options);
6365 +};
6366 +
6367 +#define MAXDIM__Scalar__Tab 2
6368 +
6369 +class __Scalar__Tab : public ArrOf__Scalar__
6370 +{
6371 +public:
6372 +  __Scalar__Tab();
6373 +  __Scalar__Tab(const __Scalar__Tab&);
6374 +  __Scalar__Tab(const entier i, const entier j);
6375 +  __Scalar__Tab&    operator=(const __Scalar__Tab&);
6376 +  void              reset();
6377 +
6378 +  inline __scalar__& operator()(entier i, entier j);
6379 +  inline __scalar__   operator()(entier i, entier j) const;
6380 +
6381 +  inline entier resize(entier i, entier j);
6382 +  inline entier dimension(entier i) const;
6383 +  inline entier dimension_tot(entier i) const;
6384 +
6385 +protected:
6386 +  // In order to mimic TRUST behavior, operator[] is forbidden
6387 +  // for 2 dimensionnal matrices, you must cast to ArrOf to use it..
6388 +  double&        operator[](entier i);
6389 +  const double& operator[](entier i) const;
6390 +
6391 +private:
6392 +  entier nb_dim_;
6393 +  entier dimensions_[MAXDIM__Scalar__Tab];
6394 +};
6395 +
6396 +inline __scalar__& __Scalar__Tab::operator()(entier i, entier j)
6397 +{
6398 +  assert(nb_dim_ == 2);
6399 +  assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]);
6400 +  const entier n = i * dimensions_[1] + j;
6401 +  __scalar__ & x = ArrOf__Scalar__::operator[] (n);
6402 +  return x;
6403 +}
6404 +
6405 +inline __scalar__   __Scalar__Tab::operator()(entier i, entier j) const
6406 +{
6407 +  assert(nb_dim_ == 2);
6408 +  assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]);
6409 +  const entier n = i * dimensions_[1] + j;
6410 +  __scalar__ x = ArrOf__Scalar__::operator[] (n);
6411 +  return x;
6412 +}
6413 +
6414 +inline entier __Scalar__Tab::resize(entier i, entier j)
6415 +{
6416 +  assert(i >= 0 && j >= 0);
6417 +  nb_dim_ = 2;
6418 +  dimensions_[0] = i;
6419 +  dimensions_[1] = j;
6420 +  ArrOf__Scalar__::resize_array(i * j);
6421 +  return i*j;
6422 +}
6423 +
6424 +inline entier __Scalar__Tab::dimension(entier i) const
6425 +{
6426 +  assert(i >= 0 && i < nb_dim_);
6427 +  return dimensions_[i];
6428 +}
6429 +
6430 +// Description: renvoie la meme valeur que dimension.
6431 +inline entier __Scalar__Tab::dimension_tot(entier i) const
6432 +{
6433 +  return dimension(i);
6434 +}
6435 +
6436 +//
6437 +// Declarations des fonctions non membres de la classe ArrOf__Scalar__
6438 +//
6439 +entier operator==(const ArrOf__Scalar__& x, const ArrOf__Scalar__& y) ;
6440 +entier imin_array(const ArrOf__Scalar__&) ;
6441 +entier imax_array(const ArrOf__Scalar__&) ;
6442 +__scalar__ min_array(const ArrOf__Scalar__&) ;
6443 +__scalar__ max_array(const ArrOf__Scalar__&) ;
6444 +
6445 +__DoubleOnlyBegin__
6446 +__scalar__ max_abs_array(const ArrOf__Scalar__&) ;
6447 +__DoubleOnlyEnd__
6448 +
6449 +// ******************************************************************
6450 +//                   FONCTIONS MEMBRES DE ArrOf__Scalar__
6451 +// ******************************************************************
6452 +
6453 +// Description :
6454 +//  Change le nombre d'elements du tableau. Cette fonction est inline
6455 +//  car elle doit etre tres rapide dans le cas ou smart_resize_==1
6456 +//  (utilisation frequente de resize_array())
6457 +//  Si smart_resize est non nul :
6458 +//   Si la nouvelle taille est inferieure ou egale a la taille
6459 +//   alouee (p->get_size()) on ne realloue pas de memoire
6460 +//   sinon, on realloue et on copie les donnees existantes.
6461 +//  Astuce pour ne pas copier les anciennes donnees:
6462 +//   resize(0); resize(n);
6463 +//  Si smart_resize est nul, on realloue une nouvelle zone memoire
6464 +//   uniquement si la nouvelle taille est differente de l'ancienne.
6465 +// Precondition :
6466 +//  Si "new_size" est egal a la taille du tableau, aucune condition.
6467 +//  Sinon, le tableau doit etre soit detache, soit normal (pas de type "ref_data")
6468 +//  et ref_count doit etre egal a 1 (pas d'autre reference au tableau).
6469 +//
6470 +inline ArrOf__Scalar__& ArrOf__Scalar__::resize_array(entier new_size)
6471 +{
6472 +  assert(new_size >= 0);
6473 +  // Soit le tableau est detache (data_==0), soit il est normal (p_!=0)
6474 +  // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau,
6475 +  // ou alors la taille ne doit pas changer.
6476 +  assert(new_size == size_array_ || data_ == 0 || (p_ != 0 && ref_count() == 1));
6477 +
6478 +  if ((smart_resize_ == 0) || (new_size > memory_size_))
6479 +    memory_resize(new_size, COPY_OLD + INITIALIZE_NEW);
6480 +  size_array_ = new_size;
6481 +  return *this;
6482 +}
6483 +
6484 +// Description:
6485 +//     operateur [] retourne le ieme element du tableau
6486 +// Precondition:
6487 +// Parametre: entier i
6488 +//    Signification: indice dans l'intervalle 0 <= i < size_array()
6489 +// Exception:
6490 +__DoubleOnlyBegin__
6491 +//    assert si la valeur sort de l'intervalle : [ -DMAXFLOAT,DMAXFLOAT ]
6492 +__DoubleOnlyEnd__
6493 +//    assert si i n'est pas dans l'intervalle
6494 +inline __scalar__& ArrOf__Scalar__::operator[](entier i)
6495 +{
6496 +  assert(i >= 0 && i < size_array_);
6497 +  __DoubleOnlyBegin__
6498 +  assert(data_[i] > -DMAXFLOAT && data_[i] < DMAXFLOAT);
6499 +  __DoubleOnlyEnd__
6500 +  return data_[i];
6501 +}
6502 +
6503 +// Description:
6504 +//     operateur [] retourne le ieme element du tableau
6505 +// Precondition:
6506 +// Parametre: entier i
6507 +//    Signification: indice dans l'intervalle 0 <= i < size_array()
6508 +// Exception:
6509 +__DoubleOnlyBegin__
6510 +//    assert si la valeur sort de l'intervalle : [ -DMAXFLOAT,DMAXFLOAT ]
6511 +__DoubleOnlyEnd__
6512 +//    assert si i n'est pas dans l'intervalle
6513 +inline const __scalar__& ArrOf__Scalar__::operator[](entier i) const
6514 +{
6515 +  assert(i >= 0 && i < size_array_);
6516 +  __DoubleOnlyBegin__
6517 +  assert(data_[i] > -DMAXFLOAT && data_[i] < DMAXFLOAT);
6518 +  __DoubleOnlyEnd__
6519 +  return data_[i];
6520 +}
6521 +
6522 +// Description:
6523 +//    Renvoie la taille du tableau (nombre d'elements declares
6524 +//    a la construction ou a resize_array()).
6525 +//    C'est le nombre d'elements accessibles a operator[]
6526 +// Retour: entier
6527 +inline entier  ArrOf__Scalar__::size_array() const
6528 +{
6529 +  return size_array_;
6530 +}
6531 +
6532 +// Description:
6533 +//  Ajoute une case en fin de tableau et y stocke la "valeur"
6534 +// Precondition:
6535 +//  Tableau doit etre de type "smart_resize" (sinon, ecroulement
6536 +//  des performances). De plus, le tableau ne doit pas etre "ref_data",
6537 +//  et il ne doit pas y avoir plus d'une reference a la zone de
6538 +//  memoire pointee (meme precondition que resize_array())
6539 +inline void   ArrOf__Scalar__::append_array(__scalar__ valeur)
6540 +{
6541 +  assert(smart_resize_);
6542 +  // Soit le tableau est detache (data_==0), soit il est normal (p_!=0)
6543 +  // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau.
6544 +  assert(data_ == 0 || (p_ != 0 && ref_count() == 1));
6545 +
6546 +  if (size_array_+1 > memory_size_)
6547 +    memory_resize(size_array_+1, COPY_OLD);
6548 +  data_[size_array_] = valeur;
6549 +  size_array_++;
6550 +}
6551 +
6552 +// ArrOf__Scalar___H
6553 +#endif
6554 diff --git a/databases/readers/Lata/CMakeLists.txt b/databases/readers/Lata/CMakeLists.txt
6555 new file mode 100644
6556 index 0000000..be611f3
6557 --- /dev/null
6558 +++ b/databases/readers/Lata/CMakeLists.txt
6559 @@ -0,0 +1,35 @@
6560 +set(SOURCES
6561 +  avtlataFileFormat.C
6562 +  LataDB.C
6563 +  LataFilter.C
6564 +  LataStructures.C
6565 +  Lata_tools.C
6566 +  LataV1_field_definitions.C
6567 +  LataWriter.C
6568 +  LmlReader.C
6569 +  OpenDXWriter.C
6570 +  OperatorBoundary.C
6571 +  OperatorDualMesh.C
6572 +  OperatorFacesMesh.C
6573 +  OperatorReconnect.C
6574 +  OperatorRegularize.C
6575 +  Rebuild_virtual_layer.C
6576 +  UserFields.C
6577 +  ArrOfBit.C
6578 +  ArrOfDouble.C
6579 +  ArrOfFloat.C
6580 +  ArrOfInt.C
6581 +  Connectivite_som_elem.C
6582 +  Motcle.C
6583 +  Octree_Double.C
6584 +  Octree_Int.C
6585 +  Static_Int_Lists.C
6586 +  )
6587 +
6588 +MESSAGE("Here I am")
6589 +
6590 +ADD_VISIT_READER(VisItLataReader "1.0"
6591 +  VISIT_READER_TYPE "MTMD"
6592 +  VISIT_READER_NAME "avtlataFileFormat"
6593 +  SERVER_SOURCES ${SOURCES}
6594 +  )
6595 diff --git a/databases/readers/Lata/Connectivite_som_elem.C b/databases/readers/Lata/Connectivite_som_elem.C
6596 new file mode 100644
6597 index 0000000..2a268cc
6598 --- /dev/null
6599 +++ b/databases/readers/Lata/Connectivite_som_elem.C
6600 @@ -0,0 +1,189 @@
6601 +/*****************************************************************************
6602 +*
6603 +* Copyright (c) 2011 - 2013, CEA
6604 +* All rights reserved.
6605 +* Redistribution and use in source and binary forms, with or without
6606 +* modification, are permitted provided that the following conditions are met:
6607 +*
6608 +*     * Redistributions of source code must retain the above copyright
6609 +*       notice, this list of conditions and the following disclaimer.
6610 +*     * Redistributions in binary form must reproduce the above copyright
6611 +*       notice, this list of conditions and the following disclaimer in the
6612 +*       documentation and/or other materials provided with the distribution.
6613 +*     * Neither the name of CEA, nor the
6614 +*       names of its contributors may be used to endorse or promote products
6615 +*       derived from this software without specific prior written permission.
6616 +*
6617 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
6618 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
6619 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
6620 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
6621 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
6622 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
6623 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6624 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6625 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
6626 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6627 +*
6628 +*****************************************************************************/
6629 +
6630 +#include <Connectivite_som_elem.h>
6631 +#include <Static_Int_Lists.h>
6632 +#include <IntTab.h>
6633 +
6634 +// Description: construction de la structure som_elem pour la zone donnee
6635 +//  On cree pour chaque sommet i la liste des elements adjacents a ce sommet
6636 +//  (c'est la liste des elements k tels que il existe j tel que les_elems(k,j) == i)
6637 +// Parametre:   nb_sommets
6638 +// Description: nombre de sommets utilises dans les elements (som_elem contiendra
6639 +//              autant de listes). Si include_virtual==1, c'est le nombre de sommets
6640 +//              total, sinon c'est le nombre de sommets reels
6641 +// Parametre:   les_elems
6642 +// Description: tableau des elements (contient les numeros des sommets de chaque element)
6643 +//              Les valeurs du tableau doivent etre inferieurs a nb_sommets.
6644 +// Parametre:   som_elem
6645 +// Description: la structure dans laquelle on stocke le resultat. L'ancien
6646 +//   contenu est perdu. Chaque liste d'elements est triee dans l'ordre croissant
6647 +// Parametre:   include_virtual
6648 +// Description: 0 => seuls les elements reels sont inclus dans la structure
6649 +//              1 => on inclut les elements virtuels (donc les sommets virtuels)
6650 +void construire_connectivite_som_elem(const entier       nb_sommets,
6651 +                                      const IntTab&      les_elems,
6652 +                                      Static_Int_Lists& som_elem,
6653 +                                      const entier       include_virtual)
6654 +{
6655 +  // Nombre d'elements du domaine
6656 +  const entier nb_elem = (include_virtual) ? les_elems.dimension_tot(0) : les_elems.dimension(0);
6657 +  // Nombre de sommets par element
6658 +  const entier nb_sommets_par_element = les_elems.dimension(1);
6659 +
6660 +  // Construction d'un tableau initialise a zero : pour chaque sommet,
6661 +  // nombre d'elements voisins de ce sommet
6662 +  ArrOfInt nb_elements_voisins(nb_sommets, 0);
6663 +
6664 +  // Premier passage : on calcule le nombre d'elements voisins de chaque
6665 +  // sommet pour creer la structure de donnees
6666 +  entier elem, i;
6667 +
6668 +  for (elem = 0; elem < nb_elem; elem++)
6669 +    {
6670 +      for (i = 0; i < nb_sommets_par_element; i++)
6671 +        {
6672 +          entier sommet = les_elems(elem, i);
6673 +          // GF cas des polyedres
6674 +          if (sommet==-1) break;
6675 +          nb_elements_voisins[sommet]++;
6676 +        }
6677 +    }
6678 +
6679 +  som_elem.set_list_sizes(nb_elements_voisins);
6680 +
6681 +  // On reutilise le tableau pour stocker le nombre d'elements dans
6682 +  // chaque liste pendant qu'on la remplit
6683 +  nb_elements_voisins = 0;
6684 +
6685 +  // Remplissage du tableau des elements voisins.
6686 +  for (elem = 0; elem < nb_elem; elem++)
6687 +    {
6688 +      for (i = 0; i < nb_sommets_par_element; i++)
6689 +        {
6690 +          entier sommet = les_elems(elem, i);
6691 +          // GF cas des polyedres
6692 +          if (sommet==-1) break;
6693 +          entier n = (nb_elements_voisins[sommet])++;
6694 +          som_elem.set_value(sommet, n, elem);
6695 +        }
6696 +    }
6697 +
6698 +  // Tri de toutes les listes dans l'ordre croissant
6699 +  som_elem.trier_liste(-1);
6700 +}
6701 +
6702 +// Description: Cherche les elements qui contiennent tous les sommets
6703 +//  du tableau sommets_to_find (permet de trouver les elements
6704 +//  adjacents a une face ou une arete)
6705 +// Parametre:     som_elem
6706 +// Signification: pour chaque sommet, liste triee des elements adjacents
6707 +//                (voir construire_connectivite_som_elem)
6708 +// Parametre:     sommets_to_find
6709 +// Signification: une liste de sommets
6710 +// Parametre:     elements
6711 +// Signification: resultat de la recherche: la liste des elements qui
6712 +//                contiennent tous les sommets de sommets_to_find.
6713 +//                Si sommets_to_find est vide, on renvoie un tableau vide.
6714 +//                (en cas d'appels repetes a cette fonction, il est
6715 +//                 conseille de mettre le drapeau "smart_resize")
6716 +void find_adjacent_elements(const Static_Int_Lists& som_elem,
6717 +                            const ArrOfInt& sommets_to_find,
6718 +                            ArrOfInt& elements)
6719 +{
6720 +  entier nb_som_to_find = sommets_to_find.size_array();
6721 +  // on retire les sommets valant -1 (cas ou plusieurs types de faces)
6722 +  while (sommets_to_find[nb_som_to_find-1]==-1) nb_som_to_find--;
6723 +  if (nb_som_to_find == 0)
6724 +    {
6725 +      elements.resize_array(0);
6726 +      return;
6727 +    }
6728 +  // Algorithme: on initialise elements avec tous les elements adjacents
6729 +  //  au premier sommet de la liste.
6730 +  //  Puis pour chacun des autres sommets de la liste, on retire du tableau
6731 +  //  "elements" les elements qui ne sont pas voisins du sommet.
6732 +  //  A la fin, il ne reste que les elements qui sont dans toutes les listes.
6733 +  {
6734 +    // Initialisation avec les elements adjacents au premier sommet
6735 +    const entier sommet = sommets_to_find[0];
6736 +    som_elem.copy_list_to_array(sommet, elements);
6737 +  }
6738 +  entier nb_elem_found = elements.size_array();
6739 +  entier i_sommet;
6740 +  for (i_sommet = 1; i_sommet < nb_som_to_find; i_sommet++)
6741 +    {
6742 +      const entier sommet = sommets_to_find[i_sommet];
6743 +      // Calcul des elements communs entre elements[.] et som_elem(sommet,.)
6744 +      // Nombre d'elements communs entre elements et la nouvelle liste de sommets
6745 +      entier nb_elems_restants = 0;
6746 +      // Nombre d'elements adjacents au "sommet"
6747 +      const entier nb_elem_liste = som_elem.get_list_size(sommet);
6748 +      // On suppose que les listes d'elements sont triees dans l'ordre croissant
6749 +      // On parcourt simultanement les deux listes et on conserve les elements
6750 +      // communs.
6751 +      entier i = 0;
6752 +      entier j = 0;
6753 +      if (nb_elem_found == 0)
6754 +        break;
6755 +      if (nb_elem_liste > 0)
6756 +        {
6757 +          while (1)
6758 +            {
6759 +              const entier elem_i = elements[i];
6760 +              const entier elem_j = som_elem(sommet, j);
6761 +              if (elem_i == elem_j)
6762 +                {
6763 +                  // Element commun aux deux listes, on le garde
6764 +                  elements[nb_elems_restants] = elem_i;
6765 +                  nb_elems_restants++;
6766 +                }
6767 +              if (elem_i >= elem_j)
6768 +                {
6769 +                  j++;
6770 +                  if (j >= nb_elem_liste)
6771 +                    break;
6772 +                }
6773 +              if (elem_j >= elem_i)
6774 +                {
6775 +                  i++;
6776 +                  if (i >= nb_elem_found)
6777 +                    break;
6778 +                }
6779 +            }
6780 +        }
6781 +      else
6782 +        {
6783 +          nb_elems_restants = 0;
6784 +        }
6785 +      nb_elem_found = nb_elems_restants;
6786 +    }
6787 +  elements.resize_array(nb_elem_found);
6788 +}
6789 +
6790 diff --git a/databases/readers/Lata/Connectivite_som_elem.h b/databases/readers/Lata/Connectivite_som_elem.h
6791 new file mode 100644
6792 index 0000000..758b030
6793 --- /dev/null
6794 +++ b/databases/readers/Lata/Connectivite_som_elem.h
6795 @@ -0,0 +1,44 @@
6796 +/*****************************************************************************
6797 +*
6798 +* Copyright (c) 2011 - 2013, CEA
6799 +* All rights reserved.
6800 +* Redistribution and use in source and binary forms, with or without
6801 +* modification, are permitted provided that the following conditions are met:
6802 +*
6803 +*     * Redistributions of source code must retain the above copyright
6804 +*       notice, this list of conditions and the following disclaimer.
6805 +*     * Redistributions in binary form must reproduce the above copyright
6806 +*       notice, this list of conditions and the following disclaimer in the
6807 +*       documentation and/or other materials provided with the distribution.
6808 +*     * Neither the name of CEA, nor the
6809 +*       names of its contributors may be used to endorse or promote products
6810 +*       derived from this software without specific prior written permission.
6811 +*
6812 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
6813 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
6814 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
6815 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
6816 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
6817 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
6818 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6819 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6820 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
6821 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6822 +*
6823 +*****************************************************************************/
6824 +
6825 +
6826 +#include <arch.h>
6827 +
6828 +class IntTab;
6829 +class ArrOfInt;
6830 +class Static_Int_Lists;
6831 +
6832 +void construire_connectivite_som_elem(const entier       nb_sommets,
6833 +                                      const IntTab&      les_elems,
6834 +                                      Static_Int_Lists& som_elem,
6835 +                                      const entier       include_virtual);
6836 +
6837 +void find_adjacent_elements(const Static_Int_Lists& som_elem,
6838 +                            const ArrOfInt& sommets_to_find,
6839 +                            ArrOfInt& elements);
6840 diff --git a/databases/readers/Lata/DoubleTab.h b/databases/readers/Lata/DoubleTab.h
6841 new file mode 100644
6842 index 0000000..1731563
6843 --- /dev/null
6844 +++ b/databases/readers/Lata/DoubleTab.h
6845 @@ -0,0 +1,30 @@
6846 +/*****************************************************************************
6847 +*
6848 +* Copyright (c) 2011 - 2013, CEA
6849 +* All rights reserved.
6850 +* Redistribution and use in source and binary forms, with or without
6851 +* modification, are permitted provided that the following conditions are met:
6852 +*
6853 +*     * Redistributions of source code must retain the above copyright
6854 +*       notice, this list of conditions and the following disclaimer.
6855 +*     * Redistributions in binary form must reproduce the above copyright
6856 +*       notice, this list of conditions and the following disclaimer in the
6857 +*       documentation and/or other materials provided with the distribution.
6858 +*     * Neither the name of CEA, nor the
6859 +*       names of its contributors may be used to endorse or promote products
6860 +*       derived from this software without specific prior written permission.
6861 +*
6862 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
6863 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
6864 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
6865 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
6866 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
6867 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
6868 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6869 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6870 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
6871 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6872 +*
6873 +*****************************************************************************/
6874 +
6875 +#include <ArrOfDouble.h>
6876 diff --git a/databases/readers/Lata/EFichier.h b/databases/readers/Lata/EFichier.h
6877 new file mode 100644
6878 index 0000000..3cf0ee8
6879 --- /dev/null
6880 +++ b/databases/readers/Lata/EFichier.h
6881 @@ -0,0 +1,60 @@
6882 +/*****************************************************************************
6883 +*
6884 +* Copyright (c) 2011 - 2013, CEA
6885 +* All rights reserved.
6886 +* Redistribution and use in source and binary forms, with or without
6887 +* modification, are permitted provided that the following conditions are met:
6888 +*
6889 +*     * Redistributions of source code must retain the above copyright
6890 +*       notice, this list of conditions and the following disclaimer.
6891 +*     * Redistributions in binary form must reproduce the above copyright
6892 +*       notice, this list of conditions and the following disclaimer in the
6893 +*       documentation and/or other materials provided with the distribution.
6894 +*     * Neither the name of CEA, nor the
6895 +*       names of its contributors may be used to endorse or promote products
6896 +*       derived from this software without specific prior written permission.
6897 +*
6898 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
6899 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
6900 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
6901 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
6902 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
6903 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
6904 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6905 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6906 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
6907 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6908 +*
6909 +*****************************************************************************/
6910 +
6911 +#ifndef EFichier_H
6912 +#define EFichier_H
6913 +#include <Entree.h>
6914 +class EFichier : public Entree
6915 +{
6916 +public:
6917 +  int ouvrir(const char *name)
6918 +  {
6919 +    is_.open(name);
6920 +    return is_.good();
6921 +  }
6922 +  operator std::istream& ()
6923 +  {
6924 +    return is_;
6925 +  }
6926 +  int eof()
6927 +  {
6928 +    return is_.eof();
6929 +  }
6930 +  int good()
6931 +  {
6932 +    return is_.good();
6933 +  }
6934 +  std::istream& get_istream()
6935 +  {
6936 +    return is_;
6937 +  }
6938 +private:
6939 +  std::ifstream is_;
6940 +};
6941 +#endif
6942 diff --git a/databases/readers/Lata/Entree.h b/databases/readers/Lata/Entree.h
6943 new file mode 100644
6944 index 0000000..2f36fea
6945 --- /dev/null
6946 +++ b/databases/readers/Lata/Entree.h
6947 @@ -0,0 +1,77 @@
6948 +/*****************************************************************************
6949 +*
6950 +* Copyright (c) 2011 - 2013, CEA
6951 +* All rights reserved.
6952 +* Redistribution and use in source and binary forms, with or without
6953 +* modification, are permitted provided that the following conditions are met:
6954 +*
6955 +*     * Redistributions of source code must retain the above copyright
6956 +*       notice, this list of conditions and the following disclaimer.
6957 +*     * Redistributions in binary form must reproduce the above copyright
6958 +*       notice, this list of conditions and the following disclaimer in the
6959 +*       documentation and/or other materials provided with the distribution.
6960 +*     * Neither the name of CEA, nor the
6961 +*       names of its contributors may be used to endorse or promote products
6962 +*       derived from this software without specific prior written permission.
6963 +*
6964 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
6965 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
6966 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
6967 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
6968 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
6969 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
6970 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6971 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6972 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
6973 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6974 +*
6975 +*****************************************************************************/
6976 +
6977 +#ifndef Entree_H
6978 +#define Entree_H
6979 +#include <iostream>
6980 +#include <fstream>
6981 +#include <Motcle.h>
6982 +// This class emulates the main functionalities of the Entree and EFichier classes in TRUST
6983 +class Entree
6984 +{
6985 +public:
6986 +  virtual operator std::istream& () = 0;
6987 +  virtual int eof() = 0;
6988 +  virtual int good() = 0;
6989 +  virtual ~Entree() {};
6990 +  virtual std::istream& get_istream() = 0;
6991 +};
6992 +
6993 +inline Entree& operator>>(Entree& is, double& t)
6994 +{
6995 +  is.get_istream() >> t;
6996 +  return is;
6997 +}
6998 +inline Entree& operator>>(Entree& is, float& t)
6999 +{
7000 +  is.get_istream() >> t;
7001 +  return is;
7002 +}
7003 +inline Entree& operator>>(Entree& is, Nom& n)
7004 +{
7005 +  is.get_istream() >> n;
7006 +  return is;
7007 +}
7008 +inline Entree& operator>>(Entree& is, Motcle& n)
7009 +{
7010 +  is.get_istream() >> n;
7011 +  return is;
7012 +}
7013 +inline Entree& operator>>(Entree& is, entier& n)
7014 +{
7015 +  is.get_istream() >> n;
7016 +  return is;
7017 +}
7018 +class ArrOfInt;
7019 +// For Static_Int_Lists:
7020 +inline Entree& operator>>(Entree& is, ArrOfInt& t)
7021 +{
7022 +  throw;
7023 +}
7024 +#endif
7025 diff --git a/databases/readers/Lata/FloatTab.h b/databases/readers/Lata/FloatTab.h
7026 new file mode 100644
7027 index 0000000..351313d
7028 --- /dev/null
7029 +++ b/databases/readers/Lata/FloatTab.h
7030 @@ -0,0 +1,30 @@
7031 +/*****************************************************************************
7032 +*
7033 +* Copyright (c) 2011 - 2013, CEA
7034 +* All rights reserved.
7035 +* Redistribution and use in source and binary forms, with or without
7036 +* modification, are permitted provided that the following conditions are met:
7037 +*
7038 +*     * Redistributions of source code must retain the above copyright
7039 +*       notice, this list of conditions and the following disclaimer.
7040 +*     * Redistributions in binary form must reproduce the above copyright
7041 +*       notice, this list of conditions and the following disclaimer in the
7042 +*       documentation and/or other materials provided with the distribution.
7043 +*     * Neither the name of CEA, nor the
7044 +*       names of its contributors may be used to endorse or promote products
7045 +*       derived from this software without specific prior written permission.
7046 +*
7047 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
7048 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
7049 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
7050 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
7051 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
7052 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
7053 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
7054 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7055 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
7056 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7057 +*
7058 +*****************************************************************************/
7059 +
7060 +#include <ArrOfFloat.h>
7061 diff --git a/databases/readers/Lata/IntTab.h b/databases/readers/Lata/IntTab.h
7062 new file mode 100644
7063 index 0000000..c8cb65c
7064 --- /dev/null
7065 +++ b/databases/readers/Lata/IntTab.h
7066 @@ -0,0 +1,31 @@
7067 +/*****************************************************************************
7068 +*
7069 +* Copyright (c) 2011 - 2013, CEA
7070 +* All rights reserved.
7071 +* Redistribution and use in source and binary forms, with or without
7072 +* modification, are permitted provided that the following conditions are met:
7073 +*
7074 +*     * Redistributions of source code must retain the above copyright
7075 +*       notice, this list of conditions and the following disclaimer.
7076 +*     * Redistributions in binary form must reproduce the above copyright
7077 +*       notice, this list of conditions and the following disclaimer in the
7078 +*       documentation and/or other materials provided with the distribution.
7079 +*     * Neither the name of CEA, nor the
7080 +*       names of its contributors may be used to endorse or promote products
7081 +*       derived from this software without specific prior written permission.
7082 +*
7083 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
7084 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
7085 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
7086 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
7087 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
7088 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
7089 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
7090 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7091 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
7092 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7093 +*
7094 +*****************************************************************************/
7095 +
7096 +#include <ArrOfInt.h>
7097 +
7098 diff --git a/databases/readers/Lata/LataDB.C b/databases/readers/Lata/LataDB.C
7099 new file mode 100644
7100 index 0000000..84e4cc4
7101 --- /dev/null
7102 +++ b/databases/readers/Lata/LataDB.C
7103 @@ -0,0 +1,2313 @@
7104 +/*****************************************************************************
7105 +*
7106 +* Copyright (c) 2011 - 2013, CEA
7107 +* All rights reserved.
7108 +* Redistribution and use in source and binary forms, with or without
7109 +* modification, are permitted provided that the following conditions are met:
7110 +*
7111 +*     * Redistributions of source code must retain the above copyright
7112 +*       notice, this list of conditions and the following disclaimer.
7113 +*     * Redistributions in binary form must reproduce the above copyright
7114 +*       notice, this list of conditions and the following disclaimer in the
7115 +*       documentation and/or other materials provided with the distribution.
7116 +*     * Neither the name of CEA, nor the
7117 +*       names of its contributors may be used to endorse or promote products
7118 +*       derived from this software without specific prior written permission.
7119 +*
7120 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
7121 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
7122 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
7123 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
7124 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
7125 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
7126 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
7127 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7128 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
7129 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7130 +*
7131 +*****************************************************************************/
7132 +
7133 +#include <errno.h>
7134 +#include <LataDB.h>
7135 +#include <stdio.h>
7136 +#include <EFichier.h>
7137 +#include <LataV1_field_definitions.h>
7138 +#include <iostream>
7139 +#include <fstream>
7140 +#include <string.h>
7141 +#include <stdlib.h>
7142 +
7143 +#include <LataDBmed.h>
7144 +
7145 +// Verbose level for which main lata file interpretation should be printed:
7146 +//  Dump one line for the whole file at verb_level-1
7147 +//  Dump one line for each Geometry, Temps, or Champ at verb_level
7148 +//  Detailed Geometry and Champ metadata is printed out at verb_level+1
7149 +#define verb_level 4
7150 +// Verbose level for data bloc reading:
7151 +//  Dump one line for each read data bloc at this level
7152 +//  Dump detailed subbloc interpretation at level+1
7153 +#define verb_level_data_bloc 5
7154 +
7155 +typedef int LataDBInt32;
7156 +typedef long long int LataDBInt64;
7157 +
7158 +void arch_check()
7159 +{
7160 +  if (sizeof(LataDBInt32)!=4)
7161 +    Journal() << "Error in LataDB arch_check : wrong LataDBInt32" << endl;
7162 +  if (sizeof(LataDBInt64)!=8)
7163 +    Journal() << "Error in LataDB arch_check : wrong LataDBInt64" << endl;
7164 +}
7165 +
7166 +const char * LataDBField::memory_buffer_file()
7167 +{
7168 +  return "MEMORY_BUFFERED_DATA";
7169 +}
7170 +
7171 +Field_UName::Field_UName()
7172 +{
7173 +}
7174 +
7175 +Field_UName::Field_UName(const Field_UName & f) :
7176 +  geometry_(f.geometry_), field_name_(f.field_name_), loc_(f.loc_)
7177 +{
7178 +}
7179 +
7180 +Field_UName::Field_UName(const char *domain_name, const char *field_name, const char *loc) :
7181 +  geometry_(domain_name), field_name_(field_name), loc_(loc)
7182 +{
7183 +  if (loc_ == "??")
7184 +    loc_ = "";
7185 +}
7186 +
7187 +Field_UName & Field_UName::operator=(const Field_UName & f)
7188 +{
7189 +  geometry_ = f.geometry_;
7190 +  field_name_ = f.field_name_;
7191 +  loc_ = f.loc_;
7192 +  return *this;
7193 +}
7194 +
7195 +Nom Field_UName::build_string() const
7196 +{
7197 +  Nom n(geometry_);
7198 +  n += "_";
7199 +  n += field_name_;
7200 +  if (loc_ != "" && loc_ != "??") {
7201 +    n += "_";
7202 +    n += loc_;
7203 +  }
7204 +  return n;
7205 +}
7206 +
7207 +void Field_UName::set_field_name(const Nom & n)
7208 +{
7209 +  field_name_ = n;
7210 +}
7211 +
7212 +int Field_UName::operator==(const Field_UName & f) const
7213 +{
7214 +  return (geometry_ == f.geometry_) && (field_name_ == f.field_name_) && (loc_ == f.loc_);
7215 +}
7216 +
7217 +std::ostream & operator<<(std::ostream & os, const Field_UName & uname)
7218 +{
7219 +  os << uname.build_string();
7220 +  return os;
7221 +}
7222 +
7223 +// This is a duplicate of Domain... only used for old latav1 compatibility
7224 +// (otherwise, LataDB should not have to know about element types !)
7225 +LataDB::Element LataDB::element_type_from_string(const Motcle & type_elem)
7226 +{
7227 +  Element type;
7228 +  if (type_elem == "HEXAEDRE")
7229 +    type=hexa;
7230 +  else if (type_elem == "HEXAEDRE_AXI")
7231 +    type=hexa;
7232 +  else if (type_elem == "HEXAEDRE_VEF")
7233 +    type=hexa;
7234 +  else if (type_elem == "QUADRANGLE")
7235 +    type=quadri;
7236 +  else if (type_elem == "QUADRANGLE_3D")
7237 +    type=quadri;
7238 +  else if (type_elem == "RECTANGLE")
7239 +    type=quadri;
7240 +  else if (type_elem == "RECTANGLE_2D_AXI")
7241 +    type=quadri;
7242 +  else if (type_elem == "RECTANGLE_AXI")
7243 +    type=quadri;
7244 +  else if (type_elem == "SEGMENT")
7245 +    type=line;
7246 +  else if (type_elem == "SEGMENT_2D")
7247 +    type=line;
7248 +  else if (type_elem == "TETRAEDRE")
7249 +    type=tetra;
7250 +  else if (type_elem == "TRIANGLE")
7251 +    type=triangle;
7252 +  else if (type_elem == "TRIANGLE_3D")
7253 +    type=triangle;
7254 +  else if (type_elem.debute_par("POLYEDRE"))
7255 +    type=polyedre;
7256 +  else if (type_elem.debute_par("POLYGONE"))
7257 +    type=polygone;
7258 +  else {
7259 +    Journal() << "Error in elem_type_from_string: unknown element type " << type_elem << endl;
7260 +    throw(LataDBError(LataDBError::BAD_ELEM_TYPE));
7261 +  }
7262 +  return type;
7263 +}
7264 +
7265 +void LataDB::get_element_data(const Motcle & elemtype, entier & dimension, entier & elem_shape, entier & face_shape, entier & nb_elem_faces)
7266 +{
7267 +  Element elem = element_type_from_string(elemtype);
7268 +  switch(elem) {
7269 +  case line:        dimension = 2; elem_shape=2; face_shape=1; nb_elem_faces=2; break;
7270 +  case triangle:    dimension = (elemtype=="TRIANGLE") ? 2 : 3; 
7271 +    elem_shape=3; face_shape=2; nb_elem_faces=3; break;
7272 +  case quadri:      dimension = (elemtype=="QUADRANGLE_3D") ? 3 : 2;
7273 +    elem_shape=4; face_shape=2; nb_elem_faces=4; break;
7274 +  case tetra:       dimension = 3; elem_shape=4; face_shape=3; nb_elem_faces=4; break;
7275 +  case hexa:        dimension = 3; elem_shape=8; face_shape=4; nb_elem_faces=6; break;
7276 +  case polyedre:    dimension = 3; elem_shape=-1; face_shape=-1; nb_elem_faces=-1; break;
7277 +  case polygone:    dimension = 2; elem_shape=-1; face_shape=-1; nb_elem_faces=-1; break;
7278 +  default:
7279 +    Journal() << "LataDB::get_element_data element is unspecified" << endl;
7280 +    throw(LataDBError(LataDBError::BAD_ELEM_TYPE));
7281 +  }    
7282 +}
7283 +
7284 +// Description: in lata v1 format, the number of components in a Champ entry
7285 +//  is implicitely defined by the field name and the discretisation
7286 +entier LataDB::lata_v1_get_nb_comp(const Nom & fieldname, const Motcle & localisation, 
7287 +                                   const LataDBGeometry & dom, entier dim, LataDBField::Nature & nature,
7288 +                                   LataDBDataType::DataOrdering & ordering)
7289 +{
7290 +  // Search component name in std_components
7291 +  entier nb_comp = latav1_component_shape(fieldname);
7292 +  Motcle maj_field(fieldname);
7293 +  ordering = LataDBDataType::C_ORDERING;
7294 +  nature = LataDBField::SCALAR;
7295 +  Journal(verb_level+1) << " LataV2 known component name found : " << fieldname << endl;
7296 +  if (nb_comp == -1) {
7297 +    // This is a vector component. If it's not a VDF faces, nb_comp = dimension of the problem
7298 +    Element elt = element_type_from_string(dom.elem_type_);
7299 +    if (localisation == "FACES" && (elt == quadri || elt == hexa)) {
7300 +      nb_comp = 1;
7301 +      Journal(verb_level+1) << " Vector field. Detected a VDF faces discretisation => nb_comp=1" << endl;
7302 +    } else {
7303 +      nb_comp = dim;
7304 +      nature = LataDBField::VECTOR;
7305 +      ordering = LataDBDataType::F_ORDERING;
7306 +      Journal(verb_level+1) << " Vector field. nb_comp = dimension = " << nb_comp << endl;
7307 +      Journal(verb_level+1) << " Assume fortran ordering" << endl;
7308 +    }
7309 +  } else if (nb_comp == -2) {
7310 +    // This is the vorticity: scalar in 2D, vector in 3D
7311 +    if (dim == 2)
7312 +    {
7313 +      nb_comp = 1;
7314 +      Journal(verb_level+1) << " Scalar field, nb_comp=" << nb_comp << endl; 
7315 +    }
7316 +    else 
7317 +    {
7318 +      nb_comp = dim;
7319 +      nature = LataDBField::VECTOR;
7320 +      ordering = LataDBDataType::F_ORDERING;
7321 +      Journal(verb_level+1) << " Vector field. nb_comp = dimension = " << nb_comp << endl;
7322 +      Journal(verb_level+1) << " Assume fortran ordering" << endl;      
7323 +    }
7324 +  } else {
7325 +    //if (maj_field == "K_EPS") {
7326 +    if (nb_comp>1) {
7327 +      ordering = LataDBDataType::F_ORDERING;
7328 +      Journal(verb_level+1) << " Special K_EPS => Assume fortran ordering" << endl;
7329 +    }
7330 +    Journal(verb_level+1) << " Scalar field, nb_comp=" << nb_comp << endl; 
7331 +  }
7332 +  return nb_comp;
7333 +}
7334 +
7335 +// Description: in lata v1 format, the localisation is implicitely defined by the
7336 +//  file name of the data file:
7337 +void lata_v1_get_localisation(const char * filename, Nom & localisation_)
7338 +{
7339 +  if (strstr(filename, ".SOM."))
7340 +    localisation_ = "SOM";
7341 +  else if (strstr(filename, ".ELEM."))
7342 +    localisation_ = "ELEM";
7343 +  else if (strstr(filename, ".FACES."))
7344 +    localisation_ = "FACES";
7345 +  else {
7346 +    Journal() << "Error in lata_v1_get_localisation. Unable to find localisation in filename\n"
7347 +              << filename << endl;
7348 +    throw(LataDBError(LataDBError::READ_ERROR));
7349 +  }
7350 +}
7351 +
7352 +class LataDataFile
7353 +{
7354 +public:
7355 +  enum Mode { READ, WRITE, APPEND };
7356 +  LataDataFile(std::iostream & mem_buffer, const char *prefix, const char *name, const LataDBDataType::MSB& msb, Mode mode = READ)
7357 +  {
7358 +    exception_ = 1;
7359 +    msb_=msb;
7360 +    if (strcmp(name, LataDBField::memory_buffer_file()) == 0) {
7361 +      stream_ = &mem_buffer;
7362 +      fname_ = name;
7363 +      Journal(verb_level_data_bloc) << "LataDB: opening internal memory_buffer for read/write" << endl;
7364 +      if (mode == READ)
7365 +        (*stream_).seekg(0, std::ios::beg);
7366 +      else if (mode == WRITE) 
7367 +       { // on ne repositionne pas sur un fichier vide, Visual ne supporte pas
7368 +         // et c'est inutil
7369 +         if ((*stream_).tellp()>=0)
7370 +           (*stream_).seekp(0, std::ios::beg);
7371 +       }
7372 +      else
7373 +       {
7374 +         if ((*stream_).tellp()>=0)
7375 +           (*stream_).seekp(0, std::ios::end);
7376 +       }
7377 +      Journal(verb_level_data_bloc+1) << " current position: " << position() << endl;
7378 +      if (!fstream_.good()) {
7379 +        Journal() << "LataDataFile: Memory stream error" << endl;
7380 +        throw LataDBError(LataDBError::DATA_ERROR);
7381 +      }
7382 +    } else {
7383 +      stream_ = &fstream_;
7384 +      fname_ = prefix;;
7385 +      fname_ += name;
7386 +      Journal(verb_level_data_bloc) << "LataDB: opening data file " << fname_ << endl;
7387 +      if (msb_ == LataDBDataType::ASCII) {
7388 +      switch(mode) {
7389 +      case READ: fstream_.open(fname_, std::fstream::in); break;
7390 +      case WRITE: fstream_.open(fname_, std::fstream::out); break;
7391 +      case APPEND: fstream_.open(fname_, std::fstream::out | std::fstream::app); break;
7392 +      }
7393 +      }
7394 +      else 
7395 +        {
7396 +          if (msb_ != LataDBDataType::machine_msb_) {
7397 +            Journal() << "LataDB LataDataFile::write(int) not coded for reverse binary msb" << endl;
7398 +            throw;
7399 +          }
7400 +          switch(mode) {
7401 +          case READ: fstream_.open(fname_, std::fstream::in|std::fstream::binary); break;
7402 +          case WRITE: fstream_.open(fname_, std::fstream::out|std::fstream::binary); break;
7403 +          case APPEND: fstream_.open(fname_, std::fstream::out | std::fstream::app|std::fstream::binary); break;
7404 +          }
7405 +        }
7406 +      if (!fstream_.good()) {
7407 +        Journal() << "File not found " << fname_ << endl;
7408 +        throw LataDBError(LataDBError::FILE_NOT_FOUND);
7409 +      }
7410 +    }
7411 +  }
7412 +  void set_exception(int i) { exception_ = i; }
7413 +  FileOffset position() { return (*stream_).tellp(); };
7414 +  enum SeekType { ABSOLUTE, RELATIVE };
7415 +  void seek(FileOffset pos, SeekType seekt) {
7416 +    Journal(verb_level_data_bloc+1) << "Seeking file " << fname_ 
7417 +                                    << ((seekt == ABSOLUTE) ? " absolute position " : " relative position ")
7418 +                                    << pos << endl;
7419 +    if (seekt == ABSOLUTE)
7420 +      (*stream_).seekg(pos, std::ios::beg);
7421 +    else
7422 +      (*stream_).seekg(pos, std::ios::cur);
7423 +  
7424 +    if (exception_ && !(*stream_).good()) {
7425 +      Journal() << "Error seeking to position " << pos << " in file " << fname_ << endl;
7426 +      throw LataDBError(LataDBError::DATA_ERROR);
7427 +    }
7428 +  }
7429 +  void set_encoding(LataDBDataType::MSB msb, LataDBDataType::Type type) { msb_ = msb; type_ = type; };
7430 +  void set_err_message(const char *message) { message_ = message; };
7431 +  LataDataFile & operator>>(LataDBInt32 & x) { read(&x, 1); return *this; };
7432 +  LataDataFile & operator>>(float & x) { read(&x, 1); return *this; };
7433 +  LataDataFile & operator>>(Nom & n) {
7434 +    n = "";
7435 +    if (msb_ != LataDBDataType::ASCII) {
7436 +      for (;;) {
7437 +        char c[2];
7438 +        c[1] = 0;
7439 +        (*stream_).get(c[0]);
7440 +
7441 +        if (!(*stream_).good())
7442 +          break;
7443 +
7444 +        if (c[0] == '\0')
7445 +          break;
7446 +
7447 +        n += c;
7448 +      }
7449 +    } else {
7450 +      std::string tmp;
7451 +      (*stream_) >> tmp;
7452 +      if ((*stream_).good())
7453 +        n = tmp.c_str();
7454 +    }
7455 +    if (exception_ && !(*stream_).good()) {
7456 +      Journal() << "Error reading string in file " << fname_ << endl;
7457 +      throw LataDBError(LataDBError::DATA_ERROR);
7458 +    }
7459 +    return *this;
7460 +  }
7461 +  void read(LataDBInt32 *ptr, BigEntier n);
7462 +  void read(float *ptr, BigEntier n);
7463 +  LataDataFile & operator<<(LataDBInt32 & x) { write(&x, 1, 1); return *this; };
7464 +  LataDataFile & operator<<(float & x) { write(&x, 1, 1); return *this; };
7465 +  void write(const LataDBInt32 *ptr, BigEntier n, BigEntier col);
7466 +  void write(const float *ptr, BigEntier n, BigEntier col);
7467 +
7468 +protected:
7469 +  Nom fname_;
7470 +  const char * message_; // Message printed if error.
7471 +  std::fstream fstream_;
7472 +  std::iostream *stream_; // Points to fstream_ or mem_buffer passed to constructor
7473 +  LataDBDataType::MSB msb_;
7474 +  LataDBDataType::Type type_;
7475 +  int exception_;
7476 +};
7477 +
7478 +void LataDataFile::read(LataDBInt32 *ptr, BigEntier n)
7479 +{
7480 +  if (type_ != LataDBDataType::INT32 && type_ != LataDBDataType::INT64) {
7481 +    Journal() << "Error in lataDB bloc read: trying to read non integer data into integer array" << endl;
7482 +    throw LataDBError(LataDBError::DATA_ERROR); 
7483 +  }
7484 +  if (msb_ == LataDBDataType::ASCII) {
7485 +    BigEntier i;
7486 +    if (ptr)
7487 +      Journal(verb_level_data_bloc+1) << "Reading ascii int data bloc size=" << n << endl;
7488 +    else
7489 +      Journal(verb_level_data_bloc+1) << "Skipping ascii int data bloc size=" << n << endl;
7490 +    LataDBInt32 toto;
7491 +    for (i = 0; i < n; i++) {
7492 +      if (ptr)
7493 +        (*stream_) >> ptr[i];
7494 +      else
7495 +        (*stream_) >> toto;
7496 +      if (exception_ && !(*stream_).good()) {
7497 +        Journal() << "Error reading ascii file " << fname_ << " LataDBInt32[" << n << "] at index " 
7498 +                  << i << endl << (message_?message_:"") << endl;
7499 +        throw LataDBError(LataDBError::DATA_ERROR);
7500 +      }
7501 +    }
7502 +  } else {
7503 +    if (type_ != LataDBDataType::INT32) {
7504 +      Journal() << "Internal error in LataDB.cpp LataDataFile::read(LataDBInt32) : size conversion not coded" << endl;
7505 +      throw;
7506 +    }
7507 +    if (ptr) {
7508 +      Journal(verb_level_data_bloc+1) << "Reading binary int data bloc size=" << n << endl;
7509 +      (*stream_).read((char*)ptr, n * sizeof(LataDBInt32));
7510 +    } else {
7511 +      Journal(verb_level_data_bloc+1) << "Skipping binary int data bloc size=" << n << endl;
7512 +      seek(n * sizeof(LataDBInt32), RELATIVE);
7513 +    }
7514 +    if (exception_ && !(*stream_).good()) {
7515 +      Journal() << "Error reading binary file " << fname_ << " LataDBInt32[" << n << "]" 
7516 +                << endl << (message_?message_:"") << endl;
7517 +      throw LataDBError(LataDBError::DATA_ERROR);
7518 +    }
7519 +    if (msb_ != LataDBDataType::machine_msb_) {
7520 +      Journal() << "LataDB LataDataFile::read(LataDBInt32) not coded for reverse binary msb" << endl;
7521 +      throw;
7522 +      // Put code here (and test !) to reverse bytes in the binary bloc:
7523 +    }
7524 +  } 
7525 +}
7526 +
7527 +void LataDataFile::read(float *ptr, BigEntier n)
7528 +{
7529 +  if (type_ != LataDBDataType::REAL32) {
7530 +    Journal() << "Error in lataDB bloc read: trying to read non float data into float array" << endl;
7531 +    throw LataDBError(LataDBError::DATA_ERROR); 
7532 +  }
7533 +  if (msb_ == LataDBDataType::ASCII) {
7534 +    BigEntier i;
7535 +    if (ptr)
7536 +      Journal(verb_level_data_bloc+1) << "Reading ascii float data bloc size=" << n << endl;
7537 +    else
7538 +      Journal(verb_level_data_bloc+1) << "Skipping ascii float data bloc size=" << n << endl;
7539 +    float toto;
7540 +    for (i = 0; i < n; i++) {
7541 +      if (ptr)
7542 +        (*stream_) >> ptr[i];
7543 +      else
7544 +        (*stream_) >> toto;
7545 +      if (exception_ && !(*stream_).good()) {
7546 +        Journal() << "Error reading ascii file " << fname_ << " float[" << n << "] at index " 
7547 +                  << i << endl << message_ << endl;
7548 +        throw LataDBError(LataDBError::DATA_ERROR);
7549 +      }
7550 +    }
7551 +  } else {
7552 +    if (ptr) {
7553 +      Journal(verb_level_data_bloc+1) << "Reading binary float data bloc size=" << n << endl;
7554 +      (*stream_).read((char*)ptr, n * sizeof(float));
7555 +    } else {
7556 +      Journal(verb_level_data_bloc+1) << "Skipping binary float data bloc size=" << n << endl;
7557 +      seek(n * sizeof(float), RELATIVE);
7558 +    }
7559 +    if (exception_ && !(*stream_).good()) {
7560 +      Journal() << "Error reading binary file " << fname_ << " float[" << n << "]" 
7561 +                << endl << message_ << endl;
7562 +      throw LataDBError(LataDBError::DATA_ERROR);
7563 +    }
7564 +    if (msb_ != LataDBDataType::machine_msb_) {
7565 +      Journal() << "LataDB LataDataFile::read(float) not coded for reverse binary msb" << endl;
7566 +      throw;
7567 +      // Put code here (and test !) to reverse bytes in the binary bloc:
7568 +    }
7569 +  } 
7570 +}
7571 +
7572 +void LataDataFile::write(const LataDBInt32 *ptr, BigEntier n, BigEntier columns)
7573 +{
7574 +  Journal(verb_level_data_bloc+1) << "Writing int data bloc size=" << n << endl;
7575 +  if (type_ != LataDBDataType::INT32) {
7576 +    Journal() << "Error in lataDB bloc write: trying to write integer data to non integer file block" << endl;
7577 +    throw LataDBError(LataDBError::DATA_ERROR); 
7578 +  }
7579 +  if (msb_ == LataDBDataType::ASCII) {
7580 +    for (BigEntier i = 0; i < n; i+=columns) {
7581 +      BigEntier j;
7582 +      for (j = 0; j < columns-1; j++)
7583 +        (*stream_) << ptr[i+j] << " ";
7584 +      (*stream_) << ptr[i+j] << endl;
7585 +    }
7586 +  } else {
7587 +    if (msb_ != LataDBDataType::machine_msb_) {
7588 +      Journal() << "LataDB LataDataFile::write(int) not coded for reverse binary msb" << endl;
7589 +      throw;
7590 +      // Put code here (and test !) to reverse bytes in the binary bloc:
7591 +    }
7592 +    (*stream_).write((char*)ptr, n * sizeof(LataDBInt32));    
7593 +  }
7594 +  (*stream_).seekg(0, std::ios::end);
7595 +  if (exception_ && !(*stream_).good()) {
7596 +    Journal() << "Error writing file " << fname_ << " int[" << n << "]" 
7597 +              << endl << message_ << endl;
7598 +    throw LataDBError(LataDBError::DATA_ERROR);
7599 +  }
7600 +}
7601 +
7602 +void LataDataFile::write(const float *ptr, BigEntier n, BigEntier columns)
7603 +{
7604 +  Journal(verb_level_data_bloc+1) << "Writing float data bloc size=" << n << endl;
7605 +  if (type_ != LataDBDataType::REAL32) {
7606 +    Journal() << "Error in lataDB bloc write: trying to write float data to non float file block" << endl;
7607 +    throw LataDBError(LataDBError::DATA_ERROR); 
7608 +  }
7609 +  if (msb_ == LataDBDataType::ASCII) {
7610 +    for (BigEntier i = 0; i < n; i+=columns) {
7611 +      BigEntier j;
7612 +      for (j = 0; j < columns-1; j++)
7613 +        (*stream_) << ptr[i+j] << " ";
7614 +      (*stream_) << ptr[i+j] << endl;
7615 +    }
7616 +  } else {
7617 +    if (msb_ != LataDBDataType::machine_msb_) {
7618 +      Journal() << "LataDB LataDataFile::write(float) not coded for reverse binary msb" << endl;
7619 +      throw;
7620 +      // Put code here (and test !) to reverse bytes in the binary bloc:
7621 +    }
7622 +    (*stream_).write((char*)ptr, n * sizeof(float));    
7623 +  }
7624 +  (*stream_).seekg(0, std::ios::end);
7625 +  if (exception_ && !(*stream_).good()) {
7626 +    Journal() << "Error writing file " << fname_ << " float[" << n << "]" 
7627 +              << endl << message_ << endl;
7628 +    throw LataDBError(LataDBError::DATA_ERROR);
7629 +  }
7630 +}
7631 +
7632 +// Description: skips a fortran bloc size descriptor.
7633 +void skip_blocksize(LataDataFile & f, const LataDBDataType & type)
7634 +{
7635 +  if (type.fortran_bloc_markers_ == LataDBDataType::NO_BLOC_MARKER)
7636 +    return;
7637 +  f.set_err_message("Error reading fortran blocsize");
7638 +  f.set_encoding(type.msb_, type.bloc_marker_type_);
7639 +  int i;
7640 +  f >> i;
7641 +  Journal(verb_level_data_bloc+1) << "Skipping blocsize marker value=" << i << endl;
7642 +}
7643 +
7644 +template<class DEST_TYPE>
7645 +DEST_TYPE int_conversion(LataDBInt64 x, const char * err_msg = 0)
7646 +{
7647 +  DEST_TYPE result = (DEST_TYPE) x;
7648 +  if ((LataDBInt64) result != x) {
7649 +    if (err_msg)
7650 +      Journal() << "LataDB integer conversion failed: " << err_msg << endl;
7651 +    else 
7652 +      Journal() << "LataDB integer conversion failed: " << endl;
7653 +    throw(LataDBError(LataDBError::INTEGER_OVERFLOW));
7654 +  }
7655 +  return result;
7656 +}
7657 +
7658 +void write_blocksize(LataDataFile & f, const LataDBDataType & type, entier sz)
7659 +{
7660 +  if (type.fortran_bloc_markers_ == LataDBDataType::NO_BLOC_MARKER)
7661 +    return;
7662 +
7663 +  Journal(verb_level_data_bloc+1) << "Writing blocsize marker value=" << sz << endl;
7664 +  f.set_err_message("Error writing fortran blocsize");
7665 +  f.set_encoding(type.msb_, type.bloc_marker_type_);
7666 +  f << sz;
7667 +}
7668 +
7669 +void bloc_read_skip(LataDataFile & f, LataDBDataType::MSB msb, LataDBDataType::Type type, BigEntier size)
7670 +{
7671 +  f.set_encoding(msb, type);
7672 +  switch(type) {
7673 +  case LataDBDataType::INT32: f.read((LataDBInt32*) 0, size); break;
7674 +  case LataDBDataType::REAL32: f.read((float*) 0, size); break;
7675 +  default:
7676 +    Journal() << "Internal error: bloc read skip not code for this type" << endl;
7677 +    throw;
7678 +  }
7679 +}
7680 +
7681 +// Description: Read "tab.size_array()" values from file "f" at current file location
7682 +//  into the "tab" array. "msb" and "type" must match the data type written in the file.
7683 +void bloc_read(LataDataFile & f, LataDBDataType::MSB msb, LataDBDataType::Type type,
7684 +               ArrOfInt & tab)
7685 +{
7686 +  f.set_encoding(msb, type);
7687 +  f.read(tab.addr(), tab.size_array());
7688 +}
7689 +
7690 +void bloc_read(LataDataFile & f, LataDBDataType::MSB msb, LataDBDataType::Type type,
7691 +               ArrOfFloat & tab)
7692 +{
7693 +  f.set_encoding(msb, type);
7694 +  f.read(tab.addr(), tab.size_array());
7695 +}
7696 +
7697 +void bloc_write(LataDataFile & f, LataDBDataType::MSB msb, LataDBDataType::Type type,
7698 +                const ArrOfInt & tab, int columns)
7699 +{
7700 +  f.set_encoding(msb, type);
7701 +  f.write(tab.addr(), tab.size_array(), columns);
7702 +}
7703 +
7704 +void bloc_write(LataDataFile & f, LataDBDataType::MSB msb, LataDBDataType::Type type,
7705 +                const ArrOfFloat & tab, int columns)
7706 +{
7707 +  f.set_encoding(msb, type);
7708 +  f.write(tab.addr(), tab.size_array(), columns);
7709 +}
7710 +
7711 +LataDBDataType::MSB LataDBDataType::machine_msb_ = (mymachine_msb) ? LataDBDataType::MSB_BIG_ENDIAN : LataDBDataType::MSB_LITTLE_ENDIAN;
7712 +
7713 +void LataDB::add(entier tstep, const LataDBGeometry & item)
7714 +{
7715 +  Noms names = geometry_names(tstep);
7716 +  if (names.rang(item.name_) >= 0) {
7717 +    Journal() << "Error in LataDBTimestep::add(const LataDBGeometry &): duplicate geometry name " << item.name_ << endl;
7718 +    throw(LataDBError(LataDBError::READ_ERROR));
7719 +  }
7720 +  timesteps_[tstep].geoms_.add(item);
7721 +}
7722 +
7723 +void LataDB::add(entier tstep, const LataDBField & item)
7724 +{
7725 +  LataDBField & field = timesteps_[tstep].fields_.add(item);
7726 +  field.timestep_ = tstep;
7727 +  field.uname_ = Field_UName(item.geometry_, item.name_, item.localisation_);
7728 +  Journal(verb_level+1) << "LataDB::add " << tstep << " " << field.uname_ << endl;
7729 +}
7730 +
7731 +// Description: returns the number of timesteps in the database
7732 +//  (timestep 0 contains geometries and fields defined before the first TEMPS entry,
7733 +//   hence nb_timesteps() == number of TEMPS entries plus 1)
7734 +// Exceptions: BAD_TIMESTEP
7735 +entier LataDB::nb_timesteps() const
7736 +{ 
7737 +  return timesteps_.size(); 
7738 +}
7739 +
7740 +// Description: returns the physical time for this timestep
7741 +// Exceptions: BAD_TIMESTEP
7742 +double LataDB::get_time(entier tstep) const
7743 +{
7744 +  return get_tstep(tstep).time_;
7745 +}
7746 +
7747 +// Description: returns the requested geometry in the requested timestep
7748 +//  "where" tells where to seach this geometry (in the current timestep or
7749 +//  also in the first timestep.
7750 +// Exceptions: BAD_TIMESTEP NAME_NOT_FOUND
7751 +const LataDBGeometry & LataDB::get_geometry(entier tstep, const char* name,
7752 +                                            TStepSelector where) const
7753 +{
7754 +  if (!name)
7755 +    throw(LataDBError(LataDBError::NAME_NOT_FOUND));
7756 +  while (1) {
7757 +    const LataDBTimestep & t = get_tstep(tstep);
7758 +    const entier n = t.geoms_.size();
7759 +    for (entier i = 0; i < n; i++) {
7760 +      const LataDBGeometry & geom = t.geoms_[i];
7761 +      if (geom.name_ == name)
7762 +        return geom;
7763 +    }
7764 +    if (where == FIRST_AND_CURRENT && tstep > 0)
7765 +      tstep = 0;
7766 +    else
7767 +      break;
7768 +  }
7769 +  throw(LataDBError(LataDBError::NAME_NOT_FOUND));
7770 +}
7771 +
7772 +// Description: returns the requested field in the requested timestep.
7773 +// Exceptions: BAD_TIMESTEP NAME_NOT_FOUND
7774 +const LataDBField & LataDB::get_field(entier tstep, const Field_UName & uname,
7775 +                                      TStepSelector where) const
7776 +{
7777 +  while (1) {
7778 +    const LataDBTimestep & t = get_tstep(tstep);
7779 +    const entier n = t.fields_.size();
7780 +    for (entier i = 0; i < n; i++) {
7781 +      const LataDBField & field = t.fields_[i];
7782 +      if (field.uname_ == uname)
7783 +        return field;
7784 +    }
7785 +    if (where == FIRST_AND_CURRENT && tstep > 0)
7786 +      tstep = 0;
7787 +    else
7788 +      break;
7789 +  }
7790 +  throw(LataDBError(LataDBError::NAME_NOT_FOUND));
7791 +}
7792 +
7793 +// Description: shortcut, works only if the specified field exists and is unique.
7794 +const LataDBField & LataDB::get_field(entier tstep, const char *geom, const char *name, const char *loc,
7795 +                                      TStepSelector which_tstep) const
7796 +{
7797 +  Field_UNames fields = field_unames(tstep, geom, name, which_tstep);
7798 +  if (fields.size() > 1)
7799 +    cerr << "get_field(char *geom, char *name, ...) returned more than one field !" << endl;
7800 +  if (fields.size() != 1)
7801 +    throw(LataDBError(LataDBError::NAME_NOT_FOUND));
7802 +  return get_field(tstep, fields[0], which_tstep);
7803 +}
7804 +
7805 +// Description: return 1 if the field exists AND is unique. (means you can call get_field with the
7806 +//  same parameters)
7807 +entier LataDB::field_exists(entier tstep, const char *geom, const char *name, 
7808 +                            TStepSelector which_tstep) const
7809 +{
7810 +  Field_UNames fields = field_unames(tstep, geom, name, which_tstep);
7811 +  return fields.size() == 1;
7812 +}
7813 +
7814 +
7815 +LataDBField & LataDB::getset_field(entier tstep, const Field_UName & uname, TStepSelector which_tstep)
7816 +{
7817 +  return (LataDBField&) get_field(tstep, uname, which_tstep);
7818 +}
7819 +
7820 +// Description: returns the names of all geometries defined in the timestep
7821 +//  which_tstep tell where to search for geometries.
7822 +// Exceptions: BAD_TIMESTEP 
7823 +Noms LataDB::geometry_names(entier tstep, TStepSelector which_tstep) const
7824 +{
7825 +  Noms names;
7826 +  const LataDBTimestep & t = get_tstep(tstep);
7827 +  entier n = t.geoms_.size();
7828 +  for (entier i = 0; i < n; i++)
7829 +    names.add(t.geoms_[i].name_);
7830 +  if (which_tstep == FIRST_AND_CURRENT && tstep > 0) {
7831 +    const LataDBTimestep & t0 = get_tstep(0);
7832 +    entier n2 = t0.geoms_.size();
7833 +    for (entier i = 0; i < n2; i++)
7834 +      // add if not:
7835 +      if (names.rang(t0.geoms_[i].name_) < 0)
7836 +        names.add(t0.geoms_[i].name_);
7837 +  }
7838 +  return names;
7839 +}
7840 +
7841 +// Description: returns the unique_identifiers of all fields defined in the timestep and for which
7842 +//  the associated geometry is "geometry" and the name is "name". Some fields may have no associated geometry,
7843 +//  give a null pointer or empty string to get these fields.
7844 +//  If geometry="*", returns list for all geometries
7845 +//  If name="*", returns list for all field names
7846 +// Exceptions: BAD_TIMESTEP 
7847 +LataVector<Field_UName> LataDB::field_unames(entier tstep, const char * geometry, const char * name, TStepSelector which_tstep) const
7848 +{
7849 +  LataVector<Field_UName> unames;
7850 +  if (!geometry)
7851 +    geometry = "";
7852 +  for (;;) {
7853 +    const LataDBTimestep & t = get_tstep(tstep);
7854 +    entier n = t.fields_.size();
7855 +    for (entier i = 0; i < n; i++) {
7856 +      const LataDBField & field = t.fields_[i];
7857 +      if ((field.geometry_ == geometry || strcmp(geometry, "*")==0 )
7858 +          && (field.name_ == name || strcmp(name,"*")==0 ))
7859 +        unames.add(field.uname_);
7860 +    }
7861 +    if (tstep == 0 || which_tstep != FIRST_AND_CURRENT)
7862 +      break;
7863 +    tstep = 0;
7864 +  }
7865 +  return unames;
7866 +}
7867 +
7868 +void check(Entree & is, const char * msg)
7869 +{
7870 +  if (!is.good()) {
7871 +    Journal() << "LataDB::read_master_file " << msg << endl;
7872 +    throw(LataDBError(LataDBError::READ_ERROR));
7873 +  }
7874 +}
7875 +void read_keyword_nom(Entree & is, Nom& motlu)
7876 +{
7877 +  is >> motlu;
7878 +  if (is.eof()) {
7879 +    Journal(verb_level) << "LataDB::read_master_file end of file" << endl;
7880 +    motlu = "Fin";
7881 +  } else {
7882 +    check(is, "read string error but not eof !");
7883 +  }
7884 +  
7885 +}
7886 +
7887 +void read_keyword(Entree & is, Nom& nomlu, Motcle& motlu)
7888 +{
7889 +  read_keyword_nom(is,nomlu);
7890 +  motlu=nomlu;
7891 +}
7892 +
7893 +// On suppose que motlu contient "blabla=VALEUR". On extrait valeur et on la met dans "param".
7894 +// Bidouille: pour traiter le cas "blabla= VALEUR", s'il n'y a rien apres "=" dans motlu, on 
7895 +//  relit un mot dans is.
7896 +void read_long_param(Entree & is, const Motcle & motlu, LataDBInt64 & param, const char * err_msg)
7897 +{
7898 +  // Cherche le "="
7899 +  const char *s = motlu;
7900 +  while (((*s) != ('=')) && ((*s) != 0))
7901 +    s++;
7902 +  if (s==0) {
7903 +    Journal() << "LataDB::read_master_file error: " << err_msg << endl;
7904 +    throw(LataDBError(LataDBError::READ_ERROR));
7905 +  }
7906 +  s++;
7907 +  Nom tmp;
7908 +  if (*s==0) {
7909 +    // il y a une espace entre le = et le parametre ?
7910 +    read_keyword_nom(is, tmp);
7911 +    s = tmp;
7912 +  }
7913 +  errno = 0;
7914 +  char *errorptr = 0;
7915 +  param = strtoll(s, &errorptr, 0 /* base 10 par defaut */);
7916 +  if (errno || *errorptr != 0) {
7917 +    Journal() << "LataDB::read_master_file error: " << err_msg << endl
7918 +              << "Error converting a string to type long int : string = " << s << endl;
7919 +    throw(LataDBError(LataDBError::READ_ERROR));
7920 +  }
7921 +}
7922 +
7923 +void read_int_param(Entree & is, const Motcle & motlu, LataDBInt32 & param, const char * err_msg)
7924 +{
7925 +  LataDBInt64 i;
7926 +  read_long_param(is, motlu, i, err_msg);
7927 +  param = int_conversion<LataDBInt32>(i, err_msg);
7928 +}
7929 +
7930 +
7931 +// Idem que read_int_param pour des chaines de caracteres.
7932 +void read_string_param(Entree & is, const Nom & motlu, Nom & param, const char * err_msg)
7933 +{
7934 +  // Cherche le "="
7935 +  const char *s = motlu;
7936 +  while (((*s) != ('=')) && ((*s) != 0))
7937 +    s++;
7938 +  if (s==0) {
7939 +    Journal() << "LataDB::read_master_file error: " << err_msg << endl;
7940 +    throw(LataDBError(LataDBError::READ_ERROR));
7941 +  }
7942 +  s++;
7943 +  param = s;
7944 +  // S'il n'y a rien apres =, on lit un mot de plus.
7945 +  if (param == "")
7946 +    read_keyword_nom(is, param);
7947 +}
7948 +
7949 +
7950 +void read_noms_param(Entree & is, const Nom & motlu, Noms & param, const char * err_msg)
7951 +{
7952 +  Nom tmp;
7953 +  read_string_param(is,motlu,tmp,err_msg);
7954 +  /*
7955 +
7956 +  a faire extraire pour de vrai les differents mots de motlu
7957 +  Nom motlu2(tmp);
7958 +  int nb_comp=1;
7959 +  {
7960 +    const char *s = tmp;
7961 +    int p=0;
7962 +    while ( ((*s) != 0))
7963 +      {
7964 +        if ((*s) == (','))
7965 +          {
7966 +            nb_comp++;
7967 +            //    motlu2[p]='\0';
7968 +          }
7969 +        p++;
7970 +        s++;
7971 +      }
7972 +  }
7973 +  //  cerr<<nb_comp<<" "<<motlu2<<endl;
7974 +  // provisoire non fini
7975 +  param=Noms(nb_comp);
7976 +  {
7977 +    const char *s=motlu2;
7978 +    for (int i=0;i<nb_comp;i++)
7979 +      {
7980 +        
7981 +        int j=motlu2.find(",");
7982 +        if (j==-1) j=0;
7983 +        param[i]=(s+j);
7984 +        cerr<<param[i]<<endl;
7985 +      }
7986 +  }
7987 +  */
7988 +}
7989 +
7990 +// Description: internal tool: checks for valid i and returns the timestep
7991 +// Exceptions: BAD_TIMESTEP
7992 +const LataDBTimestep & LataDB::get_tstep(entier i) const
7993 +{
7994 +  if (i < 0 || i >= timesteps_.size()) {
7995 +    Journal() << "LataDB::timestep(" << i << ") : wrong timestep" << endl;
7996 +    throw(LataDBError(LataDBError::BAD_TIMESTEP));
7997 +  }
7998 +  return timesteps_[i];
7999 +}
8000 +
8001 +// Description: clears the database
8002 +void LataDB::reset()
8003 +{
8004 +  path_prefix_ = "";
8005 +  header_ = "";
8006 +  case_ = "";
8007 +  software_id_ = "";
8008 +  timesteps_.reset();
8009 +  std::string empty;
8010 +  internal_data_buffer_.str(empty);
8011 +}
8012 +
8013 +// We update only fields found in the string
8014 +// A string can contain both an int type and a float type: we get both in int_type and float_type
8015 +static void read_format_string(const Motcle & n, LataDBDataType & data_type, 
8016 +                               LataDBDataType::Type & int_type,
8017 +                               LataDBDataType::Type & float_type)
8018 +{
8019 +  int_type = LataDBDataType::UNKNOWN_TYPE;
8020 +  float_type = LataDBDataType::UNKNOWN_TYPE;
8021 +
8022 +  if (n.find("ASCII")>=0)
8023 +    data_type.msb_ = LataDBDataType::ASCII;
8024 +  if (n.find("BIG_ENDIAN")>=0)
8025 +    data_type.msb_ = LataDBDataType::MSB_BIG_ENDIAN;
8026 +  if (n.find("LITTLE_ENDIAN")>=0)
8027 +    data_type.msb_ = LataDBDataType::MSB_LITTLE_ENDIAN;
8028 +
8029 +  if (n.find("INT32")>=0) {
8030 +    int_type = data_type.type_ = LataDBDataType::INT32;
8031 +    data_type.bloc_marker_type_ = LataDBDataType::INT32;
8032 +  }
8033 +  if (n.find("INT64")>=0) {
8034 +    int_type = data_type.type_ = LataDBDataType::INT64;
8035 +    data_type.bloc_marker_type_ = LataDBDataType::INT64;
8036 +  }
8037 +  if (n.find("REAL32")>=0)
8038 +    float_type = data_type.type_ = LataDBDataType::REAL32;
8039 +  if (n.find("REAL64")>=0)
8040 +    float_type = data_type.type_ = LataDBDataType::REAL64;
8041 +
8042 +  if (n.find("C_INDEXING")>=0)
8043 +    data_type.array_index_ = LataDBDataType::C_INDEXING;
8044 +  if (n.find("F_INDEXING")>=0)
8045 +    data_type.array_index_ = LataDBDataType::F_INDEXING;
8046 +  if (n.find("NO_INDEXING")>=0)
8047 +    data_type.array_index_ = LataDBDataType::NOT_AN_INDEX;
8048 +  
8049 +  if (n.find("C_ORDERING")>=0)
8050 +    data_type.data_ordering_ = LataDBDataType::C_ORDERING;
8051 +  if (n.find("F_ORDERING")>=0)
8052 +    data_type.data_ordering_ = LataDBDataType::F_ORDERING;
8053 +
8054 +  if (n.find("F_MARKERS_NO")>=0)
8055 +    data_type.fortran_bloc_markers_ = LataDBDataType::NO_BLOC_MARKER;
8056 +  if (n.find("F_MARKERS_SINGLE")>=0)
8057 +    data_type.fortran_bloc_markers_ = LataDBDataType::BLOC_MARKERS_SINGLE_WRITE;
8058 +  if (n.find("F_MARKERS_MULTIPLE")>=0)
8059 +    data_type.fortran_bloc_markers_ = LataDBDataType::BLOC_MARKERS_MULTIPLE_WRITES;
8060 +
8061 +  // Fortran bloc markers are tested after INT32 and INT64 because they
8062 +  //  override the default value:
8063 +  if (n.find("MARKERS32")>=0)
8064 +    data_type.bloc_marker_type_ = LataDBDataType::INT32;
8065 +  if (n.find("MARKERS64")>=0)
8066 +    data_type.bloc_marker_type_ = LataDBDataType::INT64;
8067 +}
8068 +
8069 +// This must work together with read_format_string:
8070 +void build_format_string(const LataDBDataType & default_type, 
8071 +                         const LataDBDataType & type,
8072 +                         Motcle & n)
8073 +{
8074 +  n = "";
8075 +  if (type.msb_ != default_type.msb_) {
8076 +    switch(type.msb_) {
8077 +    case LataDBDataType::ASCII: n += "ASCII,"; break;
8078 +    case LataDBDataType::MSB_BIG_ENDIAN: n += "BIG_ENDIAN,"; break;
8079 +    case LataDBDataType::MSB_LITTLE_ENDIAN: n += "LITTLE_ENDIAN,"; break;
8080 +    default: 
8081 +      Journal() << "write master lata: invalid MSB" << endl;
8082 +      throw(LataDBError(LataDBError::INVALID_OPERATION));
8083 +    }
8084 +  }
8085 +
8086 +  // Is an integer type specified in the format string: then the default
8087 +  //  fortran bloc marker_type will be changed (look for MARKER32 in read_format_string)
8088 +  LataDBDataType::Type default_fortran_bloc_type = default_type.bloc_marker_type_;
8089 +
8090 +  if (type.type_ != default_type.type_) {
8091 +    switch(type.type_) {
8092 +    case LataDBDataType::INT32: n += "INT32,"; default_fortran_bloc_type = LataDBDataType::INT32; break;
8093 +    case LataDBDataType::INT64: n += "INT64,"; default_fortran_bloc_type = LataDBDataType::INT64; break;
8094 +    case LataDBDataType::REAL32: n += "REAL32,"; break;
8095 +    case LataDBDataType::REAL64: n += "REAL64,"; break;
8096 +    default:
8097 +      Journal() << "write master lata: invalid type" << endl;
8098 +      throw(LataDBError(LataDBError::INVALID_OPERATION));
8099 +    }
8100 +  }
8101 +
8102 +  // Specify indexing only if integer type:
8103 +  if ((type.type_ == LataDBDataType::INT32 || type.type_ == LataDBDataType::INT64)
8104 +      && type.array_index_ != default_type.array_index_)
8105 +    switch(type.array_index_) {
8106 +    case LataDBDataType::C_INDEXING: n += "C_INDEXING,"; break;
8107 +    case LataDBDataType::F_INDEXING: n += "F_INDEXING,"; break;
8108 +    case LataDBDataType::NOT_AN_INDEX: n += "NO_INDEXING,"; break;
8109 +    default:
8110 +      Journal() << "write master lata: invalid array_index_" << endl;
8111 +      throw(LataDBError(LataDBError::INVALID_OPERATION));
8112 +    }
8113 +
8114 +  if (type.data_ordering_ != default_type.data_ordering_) {
8115 +    switch(type.data_ordering_) {
8116 +    case LataDBDataType::C_ORDERING: n += "C_ORDERING,"; break;
8117 +    case LataDBDataType::F_ORDERING: n += "F_ORDERING,"; break;
8118 +    default:
8119 +      Journal() << "write master lata: invalid data_ordering_" << endl;
8120 +      throw(LataDBError(LataDBError::INVALID_OPERATION));
8121 +    }
8122 +  }
8123 +
8124 +  if (type.fortran_bloc_markers_ != default_type.fortran_bloc_markers_) {
8125 +    switch(type.fortran_bloc_markers_) {
8126 +    case LataDBDataType::NO_BLOC_MARKER: n += "F_MARKERS_NO,"; break;
8127 +    case LataDBDataType::BLOC_MARKERS_SINGLE_WRITE: n += "F_MARKERS_SINGLE,"; break;
8128 +    case LataDBDataType::BLOC_MARKERS_MULTIPLE_WRITES: n += "F_MARKERS_MULTIPLE,"; break;
8129 +    default:
8130 +      Journal() << "write master lata: invalid fortran_bloc_markers_" << endl;
8131 +      throw(LataDBError(LataDBError::INVALID_OPERATION));
8132 +    }
8133 +  }
8134 +  
8135 +  // Warning : tricky code to determine if we have to specify fortran bloc marker size:
8136 +  // If we specify a type_ and this type_ is an integer type, then the fortran bloc
8137 +  //  marker has implicitely the same type. We want to override this type if
8138 +  //  this assumption is wrong:
8139 +  if (type.fortran_bloc_markers_ != LataDBDataType::NO_BLOC_MARKER
8140 +      && default_fortran_bloc_type != type.bloc_marker_type_) {
8141 +    switch(type.bloc_marker_type_) {
8142 +    case LataDBDataType::INT32: n += "MARKER32,"; break;
8143 +    case LataDBDataType::INT64: n += "MARKER64,"; break;
8144 +    default:
8145 +      Journal() << "write master lata: invalid fortran bloc marker type" << endl;
8146 +      throw(LataDBError(LataDBError::INVALID_OPERATION));
8147 +    }
8148 +  }
8149 +
8150 +  // Remove trailing "," if any.
8151 +  n.prefix(",");
8152 +}
8153 +
8154 +// Description: returns the content of the third line of the file
8155 +// Exceptions: FILE_NOT_FOUND, BAD_HEADER (means that this is not a lata file)
8156 +Nom LataDB::read_master_file_options(const char *filename)
8157 +{
8158 +  LataDB db;
8159 +  EFichier is;
8160 +  db.read_master_file_header(filename, is);
8161 +  return db.software_id_; // Returns the content of the third line
8162 +}
8163 +
8164 +// Description:
8165 +//  Opens the file and reads the three firt lines.
8166 +//  Fills the following attributes of the class:
8167 +//   header_
8168 +//   case_
8169 +//   software_id_
8170 +//   old_style_lata_
8171 +void LataDB::read_master_file_header(const char *filename, EFichier & is)
8172 +{
8173 +  if (!filename)
8174 +    filename = ""; // Will trigger an error for sure !
8175 +  is.ouvrir(filename);
8176 +  if (!is.good()) { // isnogood ?
8177 +    Journal() << "LataDB::read_master_file_options failed opening file " << filename << endl;
8178 +    throw(LataDBError(LataDBError::FILE_NOT_FOUND));
8179 +  }
8180 +  Journal(verb_level-1) << "Trying to read master lata file format LATA " 
8181 +                        << filename << endl;
8182 +
8183 +  const entier bufsize=1024;
8184 +  char s[bufsize+1];
8185 +  // Lecture de l'entete:
8186 +  is.get_istream().getline(s, bufsize);
8187 +  check(is, "failed reading line 1");
8188 +  const char * lata_header = "LATA_V2.";
8189 +  old_style_lata_ = 0;
8190 +  if (strncmp(s, lata_header, strlen(lata_header)) == 0) {
8191 +    Journal(2) << "LataDB::read_master_file found lata format " << lata_header << endl;
8192 +    old_style_lata_ = 0;
8193 +  } else if ((Motcle(s).debute_par("Trio_U"))||(Motcle(s).debute_par("TRUST"))) {
8194 +    Journal(2) << "LataDB::read_master_file found old style lata format" << endl;
8195 +    old_style_lata_ = 1;
8196 +  } else {
8197 +    Journal(2) << "LataDB::read_master_file error reading header: expected LATA_V2.0 or TRUST" 
8198 +               << " instead of " << s << endl;
8199 +    throw(LataDBError(LataDBError::BAD_HEADER));
8200 +  }
8201 +  header_ = s;
8202 +  is.get_istream().getline(s, bufsize);
8203 +  check(is, "failed reading line 2");
8204 +  case_ = s;
8205 +  is.get_istream().getline(s, bufsize);
8206 +  check(is, "failed reading line 3");
8207 +  software_id_ = s; 
8208 +}
8209 +
8210 +int is_med(const char* filename)
8211 +{
8212 +  Motcle motcle_nom_fic(filename);
8213 +  
8214 +  if (motcle_nom_fic.finit_par(".med"))
8215 +    return 1;
8216 +  return 0;
8217 +}
8218 +
8219 +// Description: Reads the .lata database in the given file indicating than the 
8220 +//  associated data files will be found in directory "prefix".
8221 +//  If not empty, "prefix" must finish with a '/'.
8222 +//  For "prefix" and "filename", if they do not begin with '/', are relative to pwd.
8223 +// Exceptions: 
8224 +//  BAD_HEADER  means that the header found in this stream is not LATA_V2
8225 +//  READ_ERROR  means that an error has been found in the file (premature eof,
8226 +//              io error, bad keyword, ...)
8227 +//  FILE_NOT_FOUND means that, well, the lata file could not be opened
8228 +void LataDB::read_master_file(const char *prefix, const char *filename)
8229 +{
8230 +  reset();
8231 +
8232 +  if (!prefix)
8233 +    prefix = "";
8234 +  path_prefix_ = prefix;
8235 +
8236 +  if (is_med(filename)) 
8237 +    {
8238 +      path_prefix_ = ""; 
8239 +      read_master_file_med(prefix,filename);
8240 +      return;
8241 +    }
8242 +
8243 +  //Journal() << "RECOMPILED PLUGIN !" << endl;
8244 +
8245 +  EFichier is;
8246 +  read_master_file_header(filename, is);
8247 +
8248 +  // Defaults for lataV1
8249 +  default_type_int_.msb_ = LataDBDataType::ASCII;
8250 +  default_type_int_.type_ = LataDBDataType::INT32;
8251 +  default_type_int_.array_index_ = LataDBDataType::F_INDEXING;
8252 +  default_type_int_.data_ordering_ = LataDBDataType::C_ORDERING;
8253 +  default_type_int_.fortran_bloc_markers_ = LataDBDataType::BLOC_MARKERS_SINGLE_WRITE;
8254 +  default_type_int_.bloc_marker_type_ = LataDBDataType::INT32;
8255 +  default_float_type_ = LataDBDataType::REAL32;
8256 +  
8257 +  // Create timestep 0 (global domain and fields)
8258 +  timesteps_.add(LataDBTimestep());
8259 +  entier interface_file_not_found = 0;
8260 +  Nom nomlu;
8261 +  Motcle motlu;
8262 +  read_keyword(is, nomlu,motlu);
8263 +
8264 +  while (1) {
8265 +    if (motlu == "Fin") 
8266 +      {
8267 +        Journal(verb_level) << "End of file by FIN" << endl;
8268 +        break;
8269 +      } 
8270 +    else if (motlu == "Format") 
8271 +      {
8272 +        Journal(verb_level) << "Reading Format " << endl;
8273 +        read_keyword(is, nomlu, motlu);
8274 +        LataDBDataType::Type tmp_int_type;
8275 +        read_format_string(motlu, default_type_int_, tmp_int_type, default_float_type_);
8276 +        default_type_int_.type_ = tmp_int_type;
8277 +        read_keyword(is, nomlu, motlu);
8278 +      } 
8279 +    else if (motlu == "Temps") 
8280 +      {
8281 +        LataDBTimestep & t = timesteps_.add(LataDBTimestep());
8282 +        const entier i = timesteps_.size() - 1;
8283 +        is >> t.time_;
8284 +        check(is, "failed reading time parameter");
8285 +        Journal(verb_level) << "Reading timestep " << i << " t=" << t.time_ << endl;
8286 +        read_keyword(is, nomlu, motlu);
8287 +      }
8288 +    else if (motlu == "Geom")
8289 +      {
8290 +        // This is the new syntax to declare a geometry.
8291 +        // nodes, elements faces, files are declared in separate "champ" entries
8292 +        LataDBGeometry dom;
8293 +        dom.timestep_ = timesteps_.size()-1;
8294 +        is >> dom.name_;
8295 +        check(is, "failed reading domain name");
8296 +        Journal(verb_level) << "New domain " << dom.name_ << endl;
8297 +        while (1) {
8298 +          read_keyword(is, nomlu, motlu);
8299 +          if (motlu.debute_par("type_elem=")) {
8300 +            read_string_param(is, motlu, dom.elem_type_, "error reading type_elem parameter");
8301 +            Journal(verb_level+1) << " type_elem=" << dom.elem_type_ << endl;
8302 +          } else
8303 +            break;
8304 +        }
8305 +        if (dom.elem_type_ == "") {
8306 +          Journal() << "Error reading Geometry: missing type_elem parameter" << endl;
8307 +          throw(LataDBError(LataDBError::READ_ERROR));
8308 +        }
8309 +        add(timesteps_.size() - 1, dom);
8310 +      }
8311 +    else if (motlu == "Geometrie") 
8312 +      {
8313 +        // Declare a geometry: nodes and elements are embedded in a single file described here
8314 +        // (legacy syntax)
8315 +        LataDBGeometry dom;
8316 +        LataDBField som;
8317 +        // Name
8318 +        is >> dom.name_;
8319 +        dom.timestep_ = timesteps_.size()-1;
8320 +        check(is, "failed reading domain name");
8321 +        Journal(verb_level) << "Reading domain " << dom.name_ << endl;
8322 +        som.name_ = "SOMMETS";
8323 +        som.geometry_ = dom.name_;
8324 +        // Filenames
8325 +        Nom n;
8326 +        is >> n;
8327 +        check(is, "failed reading domain filename");
8328 +        som.filename_ = n;
8329 +        long long nb_elem = -1;
8330 +        long long nb_faces = -1;
8331 +        entier nproc = -1;
8332 +        Nom file_decal_som;
8333 +        Nom file_decal_elem;
8334 +        Nom file_decal_faces;
8335 +        while (1) {
8336 +          read_keyword(is, nomlu, motlu);
8337 +          if (motlu.debute_par("nb_som_tot=")) {
8338 +            read_long_param(is, motlu, som.size_, "bad nb_som_tot parameter");
8339 +          } else if (motlu.debute_par("nb_elem_tot=")) {
8340 +            read_long_param(is, motlu, nb_elem, "bad nb_elem_tot parameter");
8341 +          } else if (motlu.debute_par("type_elem=")) {
8342 +            read_string_param(is, motlu, dom.elem_type_, "error reading type_elem parameter");
8343 +          } else if (motlu.debute_par("nb_faces_tot=")) {
8344 +            read_long_param(is, motlu, nb_faces, "bad nb_elem_tot parameter");
8345 +          } else if (motlu.debute_par("format=")) {
8346 +            Motcle fmt;
8347 +            read_string_param(is, motlu, fmt, "bad format parameter");
8348 +            if (fmt=="BINARY") {
8349 +              default_type_int_.msb_ = LataDBDataType::machine_msb_;
8350 +            }
8351 +          } else if (motlu.debute_par("joints_sommets")) {
8352 +            read_keyword(is, nomlu, motlu);
8353 +            read_int_param(is, motlu, nproc, "bad nproc parameter");
8354 +            read_keyword(is, nomlu, motlu);
8355 +            read_string_param(is, nomlu, file_decal_som, "bad decalage file parameter");
8356 +            Journal(verb_level+1) << " decal_som " << nproc;
8357 +          } else if (motlu.debute_par("joints_elements")) {
8358 +            read_keyword(is, nomlu, motlu);
8359 +            read_int_param(is, motlu, nproc, "bad nproc parameter");
8360 +            read_keyword(is, nomlu, motlu);
8361 +            read_string_param(is, nomlu, file_decal_elem, "bad decalage file parameter");            
8362 +            Journal(verb_level+1) << " decal_elem " << nproc;
8363 +          } else if (motlu.debute_par("joints_faces")) {
8364 +            read_keyword(is, nomlu, motlu);
8365 +            read_int_param(is, motlu, nproc, "bad nproc parameter");
8366 +            read_keyword(is, nomlu, motlu);
8367 +            read_string_param(is, nomlu, file_decal_faces, "bad decalage file parameter");            
8368 +            Journal(verb_level+1) << " decal_faces " << nproc;
8369 +          } else
8370 +            break;
8371 +          Journal(verb_level+1) << " " << motlu << endl;
8372 +        }
8373 +        som.datatype_ = default_type_float();
8374 +        LataDBField elem(som);
8375 +        elem.size_ = nb_elem;
8376 +        elem.datatype_ = default_type_int_;
8377 +        LataDBField faces(elem); // copy filename_
8378 +        faces.size_ = nb_faces;
8379 +        LataDBField elem_faces(elem);
8380 +        elem_faces.size_ = nb_elem;
8381 +        elem.name_ = "ELEMENTS";
8382 +        faces.name_ = "FACES";
8383 +        elem_faces.name_ = "ELEM_FACES";
8384 +        elem.geometry_ = dom.name_;
8385 +        faces.geometry_ = dom.name_;
8386 +        elem_faces.geometry_ = dom.name_;
8387 +
8388 +        if (som.size_ < 0 || elem.size_ < 0) {
8389 +          Journal() << "Error reading Geometry: missing or bad nb_som_tot or nb_elem_tot parameter" << endl;
8390 +          throw(LataDBError(LataDBError::READ_ERROR));
8391 +        }
8392 +        if (dom.elem_type_ == "") {
8393 +          Journal() << "Error reading Geometry: missing type_elem parameter" << endl;
8394 +          throw(LataDBError(LataDBError::READ_ERROR));
8395 +        }
8396 +        get_element_data(dom.elem_type_, som.nb_comp_, elem.nb_comp_, faces.nb_comp_, elem_faces.nb_comp_);
8397 +
8398 +        // Add domain and som which are complete. We need the "som" to be in the database
8399 +        //  for the "old lata 2D hack" in read_data2_()
8400 +        add(timesteps_.size() - 1, dom);
8401 +        add(timesteps_.size() - 1, som);
8402 +        // Parse the geometry file to find file_offsets 
8403 +        {
8404 +          Journal(verb_level) << " Parsing geometry file to find file offset of data blocs" << endl;
8405 +          LataDataFile f(internal_data_buffer_, path_prefix_, som.filename_,som.datatype_.msb_);
8406 +          IntTab * null = 0; // Null pointer => don't actually read the data
8407 +          read_data2_(f, som, null);
8408 +          elem.datatype_.file_offset_ = f.position();
8409 +          Journal(verb_level+1) << "  elements at file offset " << elem.datatype_.file_offset_ << endl;
8410 +          if (faces.size_ >= 0) {
8411 +            read_data2_(f, elem, null);
8412 +            faces.datatype_.file_offset_ = f.position();
8413 +            Journal(verb_level+1) << "  faces at file offset " << faces.datatype_.file_offset_ << endl;
8414 +            read_data2_(f, faces, null);
8415 +            elem_faces.datatype_.file_offset_ = f.position();
8416 +            Journal(verb_level+1) << "  elem_faces at file offset " << elem_faces.datatype_.file_offset_ << endl;
8417 +          }
8418 +        }
8419 +
8420 +        add(timesteps_.size() - 1, elem);
8421 +        if (faces.size_ >= 0) {
8422 +          Journal(verb_level+1) << " Adding FACES and ELEM_FACES " << faces.size_ << endl;
8423 +          add(timesteps_.size() - 1, faces);
8424 +          add(timesteps_.size() - 1, elem_faces);
8425 +        }
8426 +        if (nproc > -1) {
8427 +          LataDBField joint(elem);
8428 +          joint.datatype_.file_offset_ = 0;
8429 +          joint.size_ = nproc;
8430 +          joint.nb_comp_ = 2;
8431 +          joint.reference_ = "";
8432 +          joint.name_ = "JOINTS_SOMMETS";
8433 +          joint.filename_ = file_decal_som;
8434 +          add(timesteps_.size() - 1, joint);
8435 +          joint.reference_ = "";
8436 +          joint.name_ = "JOINTS_ELEMENTS";
8437 +          joint.filename_ = file_decal_elem;
8438 +          add(timesteps_.size() - 1, joint);
8439 +          if (file_decal_faces != "??") {
8440 +            joint.reference_ = "";
8441 +            joint.name_ = "JOINTS_FACES";
8442 +            joint.filename_ = file_decal_faces;
8443 +            add(timesteps_.size() - 1, joint);
8444 +          }
8445 +        }
8446 +      }
8447 +    else if (motlu == "Champ")
8448 +      {
8449 +        LataDBField field;
8450 +        field.datatype_ = default_type_float();
8451 +        is >> field.name_;
8452 +        check(is, "failed reading field name");
8453 +        Journal(verb_level) << "Reading field " << field.name_ << endl; 
8454 +        Nom n;
8455 +        is >> n;
8456 +        check(is, "failed reading field filename");
8457 +        field.filename_ = n;
8458 +        Journal(verb_level+1) << " filename=" << n << endl;
8459 +
8460 +        if ((field.name_ == "INTERFACES" || field.name_ == "PARTICULES") && old_style_lata_) {
8461 +          // This is the old dirty syntax for moving meshes
8462 +
8463 +          Journal(verb_level+1) << " Parsing an oldstyle interface file" << endl;
8464 +          // Open the file and read the content
8465 +          try {
8466 +            LataDBDataType::MSB msb = default_type_int_.msb_;
8467 +            LataDataFile f(internal_data_buffer_, path_prefix_, field.filename_,msb);
8468 +           
8469 +            LataDBDataType::Type int_type = default_type_int_.type_;
8470 +            LataDBDataType::Type float_type = default_float_type_;
8471 +            LataDBGeometry dom;
8472 +            dom.timestep_ = timesteps_.size()-1;
8473 +            dom.name_ = field.name_;
8474 +            LataDBField som;
8475 +            som.name_ = "SOMMETS";
8476 +            som.filename_ = field.filename_;
8477 +            som.geometry_ = field.name_;
8478 +            som.datatype_ = default_type_float();
8479 +            som.datatype_.fortran_bloc_markers_ = LataDBDataType::NO_BLOC_MARKER;
8480 +            ArrOfInt tmptab(2);
8481 +            bloc_read(f, msb, int_type, tmptab);
8482 +            som.nb_comp_ = tmptab[0]; // dimension
8483 +            som.size_ = tmptab[1]; // nb nodes
8484 +            Journal(verb_level+1) << " Nb nodes=" << som.size_ << " dimension=" << som.nb_comp_ << endl;
8485 +            som.datatype_.file_offset_ = f.position();
8486 +            bloc_read_skip(f, msb, float_type, som.size_ * som.nb_comp_);
8487 +            LataDBField elem;
8488 +            elem.name_ = "ELEMENTS";
8489 +            elem.filename_ = field.filename_;
8490 +            elem.geometry_ = field.name_;
8491 +            elem.datatype_ = default_type_int_;
8492 +            elem.datatype_.fortran_bloc_markers_ = LataDBDataType::NO_BLOC_MARKER;
8493 +            elem.datatype_.array_index_ = LataDBDataType::C_INDEXING;
8494 +            bloc_read(f, msb, int_type, tmptab);
8495 +            elem.nb_comp_ = tmptab[0];
8496 +            elem.size_ = tmptab[1];
8497 +            Journal(verb_level+1) << " Nb elements=" << elem.size_ << " shape=" << elem.nb_comp_ << endl;
8498 +            if (field.name_ == "PARTICULES") {
8499 +              // Special case for front-tracking markers
8500 +              Journal(verb_level+1) << " PARTICULES: element type = point" << endl;
8501 +              dom.elem_type_ = "POINT";
8502 +            } else {
8503 +              if (elem.nb_comp_ == 2)
8504 +                dom.elem_type_ = "SEGMENT";
8505 +              else if (elem.nb_comp_ == 3)
8506 +                dom.elem_type_ = "TRIANGLE_3D";
8507 +              else {
8508 +                Journal() << "Error reading an interface: invalid element shape " << elem.nb_comp_ << endl;
8509 +                throw(LataDBError(LataDBError::READ_ERROR));
8510 +              }
8511 +            }
8512 +            elem.datatype_.file_offset_ = f.position();
8513 +            bloc_read_skip(f, msb, int_type, elem.size_ * elem.nb_comp_);
8514 +            add(timesteps_.size() - 1, dom);
8515 +            add(timesteps_.size() - 1, som);
8516 +            add(timesteps_.size() - 1, elem);
8517 +            // Read components:
8518 +            while(1) {
8519 +              LataDBField fieldbis;
8520 +              f.set_encoding(msb, int_type);
8521 +              f.set_exception(0);
8522 +              f >> fieldbis.localisation_;
8523 +              f.set_exception(1);
8524 +              if (fieldbis.localisation_ == "")
8525 +                break;
8526 +              fieldbis.filename_ = som.filename_;
8527 +              fieldbis.geometry_ = som.geometry_;
8528 +              fieldbis.datatype_ = som.datatype_;
8529 +              tmptab.resize_array(1);
8530 +              bloc_read(f, msb, int_type, tmptab);
8531 +              fieldbis.nb_comp_ = tmptab[0];
8532 +              if (fieldbis.nb_comp_ == som.nb_comp_)
8533 +                fieldbis.nature_ = LataDBField::VECTOR;
8534 +              else
8535 +                fieldbis.nature_ = LataDBField::SCALAR;
8536 +              f >> fieldbis.name_;
8537 +              if (fieldbis.localisation_ == "SOM") {
8538 +                fieldbis.size_ = som.size_;
8539 +              } else {
8540 +                fieldbis.size_ = elem.size_;
8541 +              }
8542 +              Journal(verb_level+1) << " Interface field " << fieldbis.localisation_ << " "
8543 +                                    << fieldbis.name_ << endl;
8544 +              fieldbis.datatype_.file_offset_ = f.position();
8545 +              bloc_read_skip(f, msb, float_type, fieldbis.size_ * fieldbis.nb_comp_);
8546 +              add(timesteps_.size() - 1, fieldbis);
8547 +            }
8548 +          }
8549 +          catch (LataDBError err) {
8550 +            // If file is missing, issue the "missing file" message and continue
8551 +            if (err.err_ != LataDBError::FILE_NOT_FOUND)
8552 +              throw;
8553 +            else
8554 +              interface_file_not_found++;
8555 +          }
8556 +          // Read next keyword:
8557 +          read_keyword(is, nomlu, motlu);
8558 +        } else {
8559 +          if (old_style_lata_) {
8560 +            // Old (legacy) syntax for champs: we must guess the properties from the filename!
8561 +
8562 +            field.datatype_ = default_type_float();
8563 +            // Extract other data from filename (nb_comp_, localisation_, etc)
8564 +            // find geometry name
8565 +            Noms dom_names = geometry_names(0 /* timestep */);
8566 +            const entier nb_geom = dom_names.size();
8567 +            entier i;
8568 +            for (i = 0; i < nb_geom; i++) {
8569 +              Nom testname(".");
8570 +              testname += dom_names[i];
8571 +              testname += ".";
8572 +              if (Motcle(n).find(testname)>=0)
8573 +                break;
8574 +            }
8575 +            if (i == nb_geom) {
8576 +              Journal() << "Error in LataDB_V1::read_master_file: could not find domain for Champ " << n << endl;
8577 +              throw(LataDBError(LataDBError::READ_ERROR));
8578 +            }
8579 +            Journal(verb_level+1) << " geometry=" << dom_names[i] << endl;
8580 +            const LataDBGeometry & dom = get_geometry(0, dom_names[i]);
8581 +            field.geometry_ = dom_names[i];
8582 +            lata_v1_get_localisation(n, field.localisation_);
8583 +            Journal(verb_level+1) << " localisation=" << field.localisation_ << endl;
8584 +            const LataDBField & sommets = get_field(0 /* timestep */, dom_names[i], "SOMMETS", "*");
8585 +            const entier dim = sommets.nb_comp_;
8586 +            field.nb_comp_ = lata_v1_get_nb_comp(field.name_, field.localisation_, dom, dim, field.nature_, field.datatype_.data_ordering_);
8587 +            Journal(verb_level+1) << " composantes=" << field.nb_comp_ << endl;
8588 +            if (field.localisation_.debute_par("SOM"))
8589 +              field.size_ = sommets.size_;
8590 +            else if (field.localisation_.debute_par("ELEM"))
8591 +              field.size_ = get_field(0 /* timestep */, dom_names[i], "ELEMENTS", "*").size_;
8592 +            else if (field.localisation_.debute_par("FACE"))
8593 +              field.size_ = get_field(0 /* timestep */, dom_names[i], "FACES", "*").size_;
8594 +            else {
8595 +              Journal() << "Error in LataDB_V1::read_master_file: invalid localisation "
8596 +                        << field.localisation_ << endl;
8597 +              throw(LataDBError(LataDBError::READ_ERROR));
8598 +            }
8599 +            // Read next keyword:
8600 +            read_keyword(is, nomlu, motlu);
8601 +          } else {
8602 +            // NEW LATAV2 SYNTAX for fields
8603 +            // The default data type is "float_"
8604 +            field.datatype_ = default_type_float();
8605 +            field.size_ = -1;
8606 +            while(1) {
8607 +              read_keyword(is, nomlu, motlu);
8608 +              if (motlu.debute_par("geometrie=")) {
8609 +                read_string_param(is, nomlu, field.geometry_, "error reading geometrie parameter");
8610 +                // Check that the geometry exists
8611 +                get_geometry(timesteps_.size() - 1, field.geometry_, FIRST_AND_CURRENT);
8612 +              } else if (motlu.debute_par("composantes=")) {
8613 +                read_int_param(is, motlu, field.nb_comp_, "bad composantes parameter");
8614 +              } else if (motlu.debute_par("localisation=")) {
8615 +                read_string_param(is, motlu, field.localisation_, "error reading localisation parameter");
8616 +              } else if (motlu.debute_par("format=")) {
8617 +                LataDBDataType::Type tmp_int_type; // Unused
8618 +                LataDBDataType::Type tmp_float_type; // unused
8619 +                read_format_string(motlu, field.datatype_, tmp_int_type, tmp_float_type);
8620 +              } else if (motlu.debute_par("size=")) {
8621 +                read_long_param(is, motlu, field.size_, "error reading size parameter");
8622 +              } else if (motlu.debute_par("file_offset=")) {
8623 +                read_long_param(is, motlu, field.datatype_.file_offset_, "error reading file offset parameter");
8624 +              } else if (motlu.debute_par("nature=")) {
8625 +                Motcle nat;
8626 +                read_string_param(is, motlu, nat, "error reading nature parameter");
8627 +                if (nat.find("SCALAR")>=0)
8628 +                  field.nature_ = LataDBField::SCALAR;
8629 +                else if (nat.find("VECTOR")>=0)
8630 +                  field.nature_ = LataDBField::VECTOR;
8631 +                else {
8632 +                  Journal() << "Error in LataDB_V1::read_master_file: invalid nature "
8633 +                            << nat << endl;
8634 +                  throw(LataDBError(LataDBError::READ_ERROR));
8635 +                }
8636 +              } else if (motlu.debute_par("reference=")) {
8637 +                Nom ref;
8638 +                read_string_param(is, motlu, ref, "error reading reference parameter");
8639 +                field.reference_ = ref;
8640 +              } else if (motlu.debute_par("noms_compo=")) {
8641 +                Noms ref;
8642 +                read_noms_param(is, motlu, ref, "error reading noms_compo");
8643 +                Journal(verb_level+1)<<"noms_compos pas interprete "<<motlu<<endl;
8644 +              }
8645 +              else
8646 +                break;
8647 +              Journal(verb_level+1) << " " << motlu << endl;
8648 +            }
8649 +            if (field.size_ < 0) {
8650 +              // This is untested. Deactivate for the moment.
8651 +              //              Journal(verb_level) << " No size parameter given. Take size of the localisation field: ";
8652 +              // if (field_exists(timesteps_.size() - 1, field.geometry_, field.localisation_, FIRST_AND_CURRENT)) {
8653 +              // field.size_ = get_field(timesteps_.size() - 1, field.geometry_, field.localisation_, FIRST_AND_CURRENT).size_;
8654 +              // } else {
8655 +              Journal() << " Error, no size parameter for field " << field.name_ << " and localisation " << field.localisation_ 
8656 +                        << " does not match any existing field" << endl;
8657 +              throw(LataDBError(LataDBError::READ_ERROR));
8658 +              // }
8659 +            }
8660 +          }
8661 +          add(timesteps_.size() - 1, field);
8662 +        }
8663 +      }
8664 +    else if (motlu == "import_file")
8665 +      {
8666 +        // Load another lata master file recursively and merge timesteps
8667 +        Nom filenamebis;
8668 +        is >> filenamebis; // Read filename (without prefix)
8669 +        LataDB newdb;
8670 +        Nom filename2(prefix);
8671 +        filename2 += filenamebis;
8672 +        Journal(verb_level) << "Importing another lata database from file: " << filename << endl;
8673 +        newdb.read_master_file(prefix, filename2);
8674 +      }
8675 +    else
8676 +      {
8677 +        Journal() << "Error: unknown keyword: " << motlu << endl;
8678 +        throw(LataDBError(LataDBError::READ_ERROR));
8679 +      }
8680 +  }
8681 +  if (interface_file_not_found)
8682 +    throw LataDBError(LataDBError::FILE_NOT_FOUND);
8683 +}
8684 +
8685 +// Read field data from file f into data array "data".
8686 +//  If data is a null pointer, just skip the data bloc and leave the file pointer
8687 +//  at the beginning of the next data bloc (used to parse the geometry file if file_offset
8688 +//  are not specified in the lata master file)
8689 +template <class C_Tab>
8690 +void LataDB::read_data2_(LataDataFile & f,
8691 +                         const LataDBField & fld,
8692 +                         C_Tab * const data, // const pointer to non const data !
8693 +                         long long debut, entier n, const ArrOfInt *lines_to_read) const
8694 +{
8695 +
8696 +  if (is_med(fld.filename_))
8697 +    {
8698 +      read_data2_med_(fld,data,debut,n,lines_to_read);
8699 +      return;
8700 +    }
8701 +  // Si file_offset_ vaut 0 on y va car on peut avoir lu a un autre endroit avant.
8702 +  if (fld.datatype_.file_offset_ >= 0) {
8703 +    Journal(verb_level_data_bloc+1) << " Seeking at position " << fld.datatype_.file_offset_ << endl; 
8704 +    f.seek(fld.datatype_.file_offset_, LataDataFile::ABSOLUTE);
8705 +  }
8706 +  if (n < 0) {
8707 +    if (lines_to_read)
8708 +      n = lines_to_read->size_array();
8709 +    else
8710 +      n = fld.size_;
8711 +  }
8712 +
8713 +  // in old lata format, 2d data is written as 3d:
8714 +  // Yeah: dirty specs make dirty code...
8715 +  long long size_in_file = fld.size_;
8716 +  entier nb_comp_in_file = fld.nb_comp_;
8717 +  // entier old_lata_hack = 0;
8718 +  if (old_style_lata_ && (Motcle(fld.geometry_) != "INTERFACES") && (Motcle(fld.geometry_) != "PARTICULES")) {
8719 +    const LataDBField & som = get_field(0, fld.geometry_, "SOMMETS", "*");
8720 +    if (som.nb_comp_ == 2) {
8721 +      //old_lata_hack = 1;
8722 +      if (fld.name_ == "ELEMENTS") {
8723 +        nb_comp_in_file *= 2;
8724 +      } else if (fld.name_ == "SOMMETS") {
8725 +        nb_comp_in_file = 3; // all coordinates in 3D
8726 +        size_in_file *= 2;
8727 +      } // else if (fld.localisation_.debute_par("SOM")) {
8728 +        // size_in_file *= 2;
8729 +      // }
8730 +      Journal(verb_level_data_bloc+1) << "Old lata hack for 2D" << endl;
8731 +    }
8732 +  }
8733 +  
8734 +  if (fld.nb_comp_ < 0 || fld.size_ < 0) {
8735 +    Journal() << "Error in LataDB::read_data_: nb_comp_ or size_ not initialized for component " << fld.name_ << endl;
8736 +    throw;
8737 +  }
8738 +
8739 +  if ((!lines_to_read) && (debut < 0 || debut + n > fld.size_)) {
8740 +    Journal() << "Error in LataDB::read_data_: [debut,debut+n] invalid range (size=" << fld.size_ << ")" << endl;
8741 +    throw;
8742 +  }
8743 +
8744 +  if (data)
8745 +    data->resize(n, nb_comp_in_file);
8746 +
8747 +  switch (fld.datatype_.data_ordering_) {
8748 +  case LataDBDataType::C_ORDERING:
8749 +    // data written like this: tab(0,0) tab(0,1) tab(0,2) ... tab(1,0) tab(1,1) tab(1,2) ...
8750 +    if (fld.datatype_.fortran_bloc_markers_ == LataDBDataType::BLOC_MARKERS_MULTIPLE_WRITES) {
8751 +      Journal() << "Error in LataDB::read_data_: fortran_bloc_markers_=MULTIPLE_WRITES is incompatible with data_ordering=C" << endl;
8752 +      throw LataDBError(LataDBError::DATA_ERROR);
8753 +    }
8754 +    skip_blocksize(f, fld.datatype_);
8755 +    if (data) {
8756 +      if (!lines_to_read) {
8757 +        bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, (FileOffset)debut * nb_comp_in_file);
8758 +        bloc_read(f, fld.datatype_.msb_, fld.datatype_.type_, *data);
8759 +        bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, (FileOffset)(size_in_file - debut - n) * nb_comp_in_file);
8760 +      } else {
8761 +        C_Tab tmp;
8762 +        // Read 1024 lines chunks at a time even if only some values are needed inside
8763 +        long long chunk_size = 0;
8764 +        long long current_chunk_pos = 0;
8765 +        long long current_file_pos = 0;
8766 +        const entier nl = lines_to_read->size_array();
8767 +        for (entier i = 0; i < nl; i++) {
8768 +          const long long next_line = (*lines_to_read)[i];
8769 +          // Is this line in the current chunk ?
8770 +          if (next_line >= current_chunk_pos + chunk_size) {
8771 +            // No => read the chunk containing this line
8772 +            chunk_size = size_in_file - next_line;
8773 +            if (chunk_size > 1024)
8774 +              chunk_size = 1024;
8775 +            tmp.resize(chunk_size, nb_comp_in_file);
8776 +            bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, (next_line - current_file_pos) * nb_comp_in_file);
8777 +            bloc_read(f, fld.datatype_.msb_, fld.datatype_.type_, tmp);
8778 +            current_chunk_pos = next_line;
8779 +            current_file_pos = next_line + chunk_size;
8780 +          }
8781 +          // Extract data from tmp array
8782 +          const long long tmp_index = next_line - current_chunk_pos;
8783 +          for (entier j = 0; j < nb_comp_in_file; j++)
8784 +            (*data)(i, j) = tmp(tmp_index, j);
8785 +        }
8786 +        if (current_file_pos != size_in_file)
8787 +          bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, (size_in_file - current_file_pos) * nb_comp_in_file);
8788 +      }
8789 +    } else {
8790 +      // just skip the data
8791 +      bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, size_in_file *  nb_comp_in_file);
8792 +    }
8793 +    skip_blocksize(f, fld.datatype_);
8794 +    break;
8795 +  case LataDBDataType::F_ORDERING:
8796 +    {
8797 +      // data written like this: tab(0,0) tab(1,0) tab(2,0) ... tab(0,1) tab(1,1) tab(2,1) ... tab(0,2) tab(1,2) tab(2,2) ...
8798 +      entier multiple_bloc_markers = (fld.datatype_.fortran_bloc_markers_ == LataDBDataType::BLOC_MARKERS_MULTIPLE_WRITES);
8799 +      // reverse rows and columns of the array
8800 +      C_Tab tmp;
8801 +      if (!multiple_bloc_markers)
8802 +        skip_blocksize(f, fld.datatype_);
8803 +      for (entier i = 0; i < nb_comp_in_file; i++) {
8804 +        if (multiple_bloc_markers)
8805 +          skip_blocksize(f, fld.datatype_);
8806 +        if (data) {
8807 +          if (!lines_to_read) {
8808 +            tmp.resize(n, 1);
8809 +            bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, debut);
8810 +            bloc_read(f, fld.datatype_.msb_, fld.datatype_.type_, tmp);
8811 +            bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, size_in_file - debut - n);
8812 +            for (entier j = 0; j < n; j++)
8813 +              (*data)(j, i) = tmp(j, 0);
8814 +          } else {
8815 +
8816 +            // Read 1024 lines chunks at a time even if only some values are needed inside
8817 +            long long chunk_size = 0;
8818 +            long long current_chunk_pos = 0;
8819 +            long long current_file_pos = 0;
8820 +            const entier nl = lines_to_read->size_array();
8821 +            for (entier j = 0; j < nl; j++) {
8822 +              const long long next_line = (*lines_to_read)[j];
8823 +              // Is this line in the current chunk ?
8824 +              if (next_line >= current_chunk_pos + chunk_size) {
8825 +                // No => read the chunk containing this line
8826 +                chunk_size = size_in_file - next_line;
8827 +                if (chunk_size > 1024)
8828 +                  chunk_size = 1024;
8829 +                tmp.resize(chunk_size, 1);
8830 +                bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, (next_line - current_file_pos));
8831 +                bloc_read(f, fld.datatype_.msb_, fld.datatype_.type_, tmp);
8832 +                current_chunk_pos = next_line;
8833 +                current_file_pos = next_line + chunk_size;
8834 +              }
8835 +              // Extract data from tmp array
8836 +              const entier tmp_index = (entier)(next_line - current_chunk_pos);
8837 +              (*data)(j, i) = tmp(tmp_index, 0);
8838 +            }
8839 +            if (current_file_pos != size_in_file)
8840 +              bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, (size_in_file - current_file_pos));
8841 +          }
8842 +        } else {
8843 +          bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, size_in_file);
8844 +        }
8845 +        if (multiple_bloc_markers)
8846 +          skip_blocksize(f, fld.datatype_);
8847 +      }
8848 +      if (!multiple_bloc_markers)
8849 +        skip_blocksize(f, fld.datatype_);
8850 +      break;
8851 +    }
8852 +  default:
8853 +    Journal() << "Error in LataDB::read_data_: data_ordering not implemented" << endl;
8854 +    throw;
8855 +  }
8856 +  
8857 +  // old lata 2d hack :
8858 +  if (data && nb_comp_in_file != fld.nb_comp_) {
8859 +    // drop column in data array
8860 +    C_Tab tmp(*data);
8861 +    data->resize(n, fld.nb_comp_);
8862 +    for (entier i = 0; i < n; i++) 
8863 +      for (entier j = 0; j < fld.nb_comp_; j++)
8864 +        (*data)(i,j) = tmp(i,j);
8865 +  }
8866 +}
8867 +
8868 +// Description: 
8869 +//  Read n * fld.nb_comp_ values in the file filename_, starting from debut * fld.nb_comp_
8870 +template <class C_Tab>
8871 +void LataDB::read_data_(const LataDBField & fld, 
8872 +                        C_Tab & data, long long debut, entier n) const
8873 +{
8874 +  Journal(verb_level_data_bloc) << "LataDB::read_data(" << fld.timestep_ << "," << fld.uname_
8875 +                                << ") Reading " << path_prefix_ << fld.filename_ << " start at " << debut << " size "
8876 +                                << n << endl;
8877 +
8878 +  LataDataFile f(internal_data_buffer_, path_prefix_, fld.filename_,fld.datatype_.msb_);
8879 +  read_data2_(f, fld, &data, debut, n);
8880 +
8881 +}
8882 +
8883 +// Description: 
8884 +//  Read n * fld.nb_comp_ values in the file filename_, starting from debut * fld.nb_comp_
8885 +template <class C_Tab>
8886 +void LataDB::read_data_(const LataDBField & fld,
8887 +                        C_Tab & data, const ArrOfInt & lines_to_read) const
8888 +{
8889 +  Journal(verb_level_data_bloc) << "LataDB::read_data(" << fld.timestep_ << "," << fld.uname_
8890 +                                << ") Reading " << path_prefix_ << fld.filename_ << ",  " << lines_to_read.size_array() << " non contiguous lines" 
8891 +                                << endl;
8892 +
8893 +  LataDataFile f(internal_data_buffer_, path_prefix_, fld.filename_,fld.datatype_.msb_);
8894 +  read_data2_(f, fld, &data, -1, -1, &lines_to_read);
8895 +}
8896 +
8897 +// Description: reads n * nb_comp values in the file filename_ starting from debut*nb_comp_
8898 +//  If array_index is F_STYLE, substract 1 to all values.
8899 +void LataDB::read_data(const LataDBField & fld, IntTab & data, long long debut, entier n) const
8900 +{
8901 +  read_data_(fld, data, debut, n);
8902 +  if (fld.datatype_.array_index_ == LataDBDataType::F_INDEXING) {
8903 +    ArrOfInt & data2 = data;
8904 +    const entier n2 = data2.size_array();
8905 +    for (entier i = 0; i < n2; i++)
8906 +      data2[i]--;
8907 +  }
8908 +}
8909 +
8910 +// Description: reads n * nb_comp values in the file filename_ starting from debut*nb_comp_
8911 +void LataDB::read_data(const LataDBField & fld, DoubleTab & data, long long debut, entier n) const
8912 +{
8913 +  Journal() << "LataDB::read_data not coded for double" << endl;
8914 +  throw;
8915 +}
8916 +
8917 +void LataDB::read_data(const LataDBField & fld, FloatTab & data, long long debut, entier n) const
8918 +{
8919 +  read_data_(fld, data, debut, n);
8920 +}
8921 +
8922 +// Description: reads lines_to_read.size_array() * nb_comp values.
8923 +//  If array_index is F_STYLE, substract 1 to all values.
8924 +void LataDB::read_data(const LataDBField & fld, IntTab & data, const ArrOfInt & lines_to_read) const
8925 +{
8926 +  read_data_(fld, data, lines_to_read);
8927 +  if (fld.datatype_.array_index_ == LataDBDataType::F_INDEXING) {
8928 +    ArrOfInt & data2 = data;
8929 +    const entier n = data2.size_array();
8930 +    for (entier i = 0; i < n; i++)
8931 +      data2[i]--;
8932 +  }
8933 +}
8934 +
8935 +// Description: reads lines_to_read.size_array() * nb_comp values.
8936 +void LataDB::read_data(const LataDBField & fld, DoubleTab & data, const ArrOfInt & lines_to_read) const
8937 +{
8938 +  Journal() << "LataDB::read_data not coded for double" << endl;
8939 +  throw;
8940 +}
8941 +
8942 +// Description: reads lines_to_read.size_array() * nb_comp values.
8943 +void LataDB::read_data(const LataDBField & fld, FloatTab & data, const ArrOfInt & lines_to_read) const
8944 +{
8945 +  read_data_(fld, data, lines_to_read);
8946 +}
8947 +
8948 +
8949 +// Description: copy the source LataDB object, keeping only timesteps, geometries and fields
8950 +//  that are specified (timestep 0 is always included, do not put it in the list).
8951 +//  field_nms can contain field.name_ (like VITESSE), or extended name with localisation
8952 +//  (like VITESSE_ELEM)
8953 +void LataDB::filter_db(const LataDB & source,
8954 +                       const Motcles & geometry_nms,
8955 +                       const Motcles & field_nms,
8956 +                       const ArrOfInt & timesteps)
8957 +{
8958 +  path_prefix_ = source.path_prefix_;
8959 +  header_ = source.header_;
8960 +  case_ = source.case_;
8961 +  software_id_ = source.software_id_;
8962 +  old_style_lata_ = source.old_style_lata_;
8963 +  default_type_int_ = source.default_type_int_;
8964 +  default_float_type_ = source.default_float_type_;
8965 +  
8966 +  const entier nb_tsteps = timesteps.size_array();
8967 +  for (entier it = 0; it < nb_tsteps + 1; it++) {
8968 +    entier src_tstep = 0;
8969 +    if (it > 0)
8970 +      src_tstep = timesteps[it-1];
8971 +    LataDBTimestep & tstep = timesteps_.add(LataDBTimestep());
8972 +    tstep.time_ = source.get_time(src_tstep);
8973 +    // Copy geometries
8974 +    Motcles geoms = noms_to_motcles(source.geometry_names(src_tstep));
8975 +    entier ig;
8976 +    for (ig = 0; ig < geoms.size(); ig++)
8977 +      if (geometry_nms.rang(geoms[ig]) >= 0)
8978 +        tstep.geoms_.add(source.get_geometry(src_tstep, geoms[ig]));
8979 +    // Copy fields
8980 +    geoms = noms_to_motcles(geometry_names(nb_timesteps()-1, FIRST_AND_CURRENT));
8981 +    for (ig = 0; ig < geoms.size(); ig++) {
8982 +      LataVector<Field_UName> unames = source.field_unames(src_tstep, geoms[ig], "*");
8983 +      for (entier i_f = 0; i_f < unames.size(); i_f++) {
8984 +        const LataDBField & src = source.get_field(src_tstep, unames[i_f]);
8985 +        Nom name_loc = src.name_;
8986 +        name_loc += "_";
8987 +        name_loc += src.localisation_;
8988 +        if (field_nms.rang(src.name_) >= 0 || field_nms.rang(name_loc) >= 0) 
8989 +          tstep.fields_.add(src);
8990 +      }
8991 +    }
8992 +  }
8993 +}
8994 +
8995 +// Description: set the default value of the path prefix where write_data() will write the data
8996 +// Warning: there is no check that the master lata file is actually written at the same place 
8997 +//  and that all the files and data blocks mentionned in the database actually exist.
8998 +// For the file_offset_ field, -2 is considered "unknown".
8999 +void LataDB::set_path_prefix(const char * s)
9000 +{
9001 +  path_prefix_ = s;
9002 +}
9003 +
9004 +#define UPDATE_MACRO(x,unknown) if (((old_type.x==unknown)||(type.x==old_type.x))&&(new_type.x!=unknown)) type.x=new_type.x
9005 +
9006 +// Description: changes the data type of all fields in the database.
9007 +//  The property "x" is changed to "new_type.x" if "new_type.x" is not "unknown"
9008 +//  and if "old_type.x" is "unknown" or "equal to the previous property" 
9009 +// Example: convert all data to ASCII:
9010 +//   LataDBDataType old_type; // All defaults to "unknown" => we update all fields
9011 +//   LataDBDataType new_type;
9012 +//   new_type.msb_ = LataDBDataType::ASCII; // Change msb_ property to ASCII:
9013 +// Example 2: change all REAL32 data to REAL64
9014 +//   LataDBDataType old_type;
9015 +//   old_type.type_ = LataDBDataType::REAL32;
9016 +//   LataDBDataType new_type;
9017 +//   new_type.msb_ = LataDBDataType::REAL64;
9018 +void LataDB::change_all_data_types(const LataDBDataType & old_type, const LataDBDataType & new_type)
9019 +{
9020 +  const entier nb_tsteps = timesteps_.size();
9021 +  for (entier src_tstep = 0; src_tstep < nb_tsteps; src_tstep++) {
9022 +    LataVector<LataDBField> & fields = timesteps_[src_tstep].fields_;
9023 +    const entier nb_fields = fields.size();
9024 +    for (entier i_field = 0; i_field < nb_fields; i_field++) {
9025 +      LataDBDataType & type = fields[i_field].datatype_;
9026 +      // For each field, if "old_type" is "unknown" or equal to the previous value,
9027 +      //  and if "new_type" is not "unknown, then update the field
9028 +      UPDATE_MACRO(msb_, LataDBDataType::UNKNOWN_MSB);
9029 +      UPDATE_MACRO(type_, LataDBDataType::UNKNOWN_TYPE);
9030 +      UPDATE_MACRO(array_index_, LataDBDataType::UNKNOWN_ARRAYINDEX);
9031 +      UPDATE_MACRO(data_ordering_, LataDBDataType::UNKNOWN_ORDERING);
9032 +      UPDATE_MACRO(fortran_bloc_markers_, LataDBDataType::UNKNOWN_MARKERS);
9033 +      UPDATE_MACRO(bloc_marker_type_, LataDBDataType::UNKNOWN_TYPE);
9034 +    }
9035 +  }
9036 +}
9037 +#undef UPDATE_MACRO
9038 +
9039 +void LataDB::change_all_data_filenames(const Nom & old_prefix, const Nom & new_prefix)
9040 +{
9041 +  const entier nb_tsteps = timesteps_.size();
9042 +  for (entier i = 0; i < nb_tsteps; i++) {
9043 +    LataVector<LataDBField> & fields = timesteps_[i].fields_;
9044 +    // Browse all fields:
9045 +    const entier nb_fields = fields.size();
9046 +    for (entier j = 0; j < nb_fields; j++) {
9047 +      Nom & filename = fields[j].filename_;
9048 +      Nom old_filename = filename;
9049 +      filename = new_prefix;
9050 +      if (old_filename.debute_par(old_prefix)) {
9051 +        const entier n = old_filename.longueur()-1;
9052 +        const char * s = old_filename;
9053 +        for (entier ii = old_prefix.longueur()-1; ii < n; ii++)
9054 +          filename += Nom(s[ii]);
9055 +      } else if (old_filename == LataDBField::memory_buffer_file()) {
9056 +        filename += Nom(".data");
9057 +      } else {
9058 +        filename += Nom('_');
9059 +        filename += old_filename;
9060 +      }
9061 +      Journal(verb_level+1) << " Changing filename " << old_filename << " -> " << filename << endl;
9062 +    }
9063 +  } 
9064 +}
9065 +
9066 +// This method takes all filenames mentionned in the database and sets the file_offset_ entry:
9067 +//  - set to 0 for the first field where a given filename appears,
9068 +//  - then for all subsequent files referring to the same name:
9069 +//      If split_files != 0, rename the files by appending a "_number" and set file_offset to 0
9070 +//      otherwise set file_offset_ to 1
9071 +void LataDB::check_all_data_fileoffsets(entier split_files)
9072 +{
9073 +  Noms existing_filenames;
9074 +  ArrOfInt counts; // For each filenames, number of fields referring to it
9075 +  counts.set_smart_resize(1);
9076 +
9077 +  const entier nb_tsteps = timesteps_.size();
9078 +  for (entier i = 0; i < nb_tsteps; i++) {
9079 +    LataVector<LataDBField> & fields = timesteps_[i].fields_;
9080 +    // Browse all fields:
9081 +    const entier nb_fields = fields.size();
9082 +    for (entier j = 0; j < nb_fields; j++) {
9083 +      LataDBField & field = fields[j];
9084 +      const entier rank = existing_filenames.rang(field.filename_);
9085 +      if (rank < 0) {
9086 +        // New filename
9087 +        existing_filenames.add(field.filename_);
9088 +        counts.append_array(1);
9089 +        field.datatype_.file_offset_ = 0;
9090 +        Journal(verb_level+1) << " Changing fileoffset to 0 for file " << field.filename_ 
9091 +                              << " " << field.name_ << endl;
9092 +      } else {
9093 +        // Existing filename
9094 +        if (split_files) {
9095 +          entier n = counts[rank]++;
9096 +          field.filename_ += "_";
9097 +          field.filename_ += Nom(n);
9098 +          field.datatype_.file_offset_ = 0;
9099 +          Journal(verb_level+1) << " Changing fileoffset to 0 and renaming file " << field.filename_  
9100 +                                << " " << field.name_ << endl;
9101 +        } else {
9102 +          field.datatype_.file_offset_ = 1;
9103 +          Journal(verb_level+1) << " Changing fileoffset to 1 for file " << field.filename_  
9104 +                                << " " << field.name_ << endl; 
9105 +        }
9106 +      }
9107 +    }
9108 +  }  
9109 +}
9110 +
9111 +// Returns the rank of the created timestep (always at the end)
9112 +entier LataDB::add_timestep(double time)
9113 +{
9114 +  const entier n = nb_timesteps();
9115 +  // Timestep 0 can have any time: test only versus other timesteps:
9116 +  if (n > 1 && time <= get_time(n-1)) {
9117 +    Journal() << "Error in LataDB::add_timestep(" << time 
9118 +              << "): time is below or equal to last timestep " << get_time(n-1) << endl;
9119 +    throw(LataDBError(LataDBError::INVALID_OPERATION));
9120 +  }
9121 +  LataDBTimestep & t = timesteps_.add(LataDBTimestep());
9122 +  t.time_ = time;
9123 +  Journal(verb_level+1) << "LataDB::add_timestep " << n << " " << time << endl;
9124 +  return n;
9125 +}
9126 +
9127 +static void add_geom_check(const LataDBGeometry & geom, entier test_flag, const char *message)
9128 +{
9129 +  if (!test_flag) {
9130 +    Journal() << "Error in LataDB::add_geometry, name_=" << geom.name_ << endl
9131 +              << " geometry data is invalid because of: " << message << endl;
9132 +    throw(LataDBError(LataDBError::INVALID_OPERATION));
9133 +  }
9134 +}
9135 +
9136 +void LataDB::add_geometry(const LataDBGeometry & geom)
9137 +{  
9138 +  add_geom_check(geom, geom.timestep_ >= 0 && geom.timestep_ < nb_timesteps(), "timestep");
9139 +  Noms geoms= geometry_names(geom.timestep_, CURRENT);
9140 +  add_geom_check(geom, geom.name_ != "" && geom.name_ != "??" && geoms.rang(geom.name_) < 0, "empty or already existing name"); 
9141 +
9142 +  add(geom.timestep_, geom);
9143 +  Journal(verb_level+1) << "LataDB::add_geometry " << geom.name_ << endl;
9144 +}
9145 +
9146 +void LataDB::set_elemtype(entier tstep, const char *geom_name, const char *elem_type)
9147 +{
9148 +  LataDBGeometry & geom = (LataDBGeometry&) get_geometry(tstep, geom_name);
9149 +  geom.elem_type_ = elem_type;
9150 +}
9151 +
9152 +
9153 +static void add_field_check(const LataDBField & field, entier test_flag, const char *message)
9154 +{
9155 +  if (!test_flag) {
9156 +    Journal() << "Error in LataDB::add_field, name_=" << field.name_ << " geometry=" << field.geometry_ << endl
9157 +              << " field data is invalid because of: " << message << endl;
9158 +    throw(LataDBError(LataDBError::INVALID_OPERATION));
9159 +  }
9160 +}
9161 +
9162 +// Adds a new field to the database.
9163 +// The field.datatype_.file_offset_ will be interpreted in a particular way if the data is
9164 +//  written with write_data(), see write_data() documentation.
9165 +// Take special care if the same file is referenced more than once in the database:
9166 +//  only one file should have file_offset_ <= 0 and this one will have to be written first 
9167 +//  with write_data()  (or you know what you are doing...)
9168 +void LataDB::add_field(const LataDBField & field)
9169 +{
9170 +  add_field_check(field, field.timestep_ >= 0 && field.timestep_ < nb_timesteps(), "timestep");
9171 +  add_field_check(field, field.filename_ != "" && field.filename_ != "??", "filename");
9172 +  add_field_check(field, field.nb_comp_ > 0, "nb_comp");
9173 +  Noms geoms = geometry_names(field.timestep_, FIRST_AND_CURRENT);
9174 +  add_field_check(field, field.geometry_ == "" || geoms.rang(field.geometry_) >= 0, "unknown geometry name");
9175 +  add_field_check(field, field.name_ != "" && field.name_ != "??", "empty name"); 
9176 +  add_field_check(field, field.component_names_.size() == 0 || field.component_names_.size() == field.nb_comp_, "number of component_names");
9177 +  add_field_check(field, field.size_ >= 0, "size");
9178 +  add_field_check(field, field.datatype_.msb_ != LataDBDataType::UNKNOWN_MSB, "datatype msb unspecified");
9179 +  add_field_check(field, field.datatype_.type_ == LataDBDataType::INT32
9180 +                  || field.datatype_.type_ == LataDBDataType::INT64
9181 +                  || field.datatype_.type_ == LataDBDataType::REAL32
9182 +                  || field.datatype_.type_ == LataDBDataType::REAL64, "datatype type unspecified");
9183 +  // If integer type, we must say the indexing type:
9184 +  add_field_check(field, 
9185 +                  field.datatype_.type_ == LataDBDataType::REAL32
9186 +                  || field.datatype_.type_ == LataDBDataType::REAL64
9187 +                  || field.datatype_.array_index_ != LataDBDataType::UNKNOWN_ARRAYINDEX, 
9188 +                  "datatype array indexing unspecified");
9189 +  add_field_check(field, field.datatype_.data_ordering_ != LataDBDataType::UNKNOWN_ORDERING, "datatype data ordering unspecified");
9190 +  add_field_check(field, field.datatype_.fortran_bloc_markers_ != LataDBDataType::UNKNOWN_MARKERS, "datatype fortran bloc markers unspecified");
9191 +  add_field_check(field, field.datatype_.file_offset_ >= 0, "datatype file_offset_");
9192 +  // ouf...
9193 +  add(field.timestep_, field);
9194 +  Journal(verb_level+1) << "LataDB::add_field : " << field.name_ << " " << field.geometry_ << " " << field.filename_ << " " << field.uname_ << endl;
9195 +}
9196 +
9197 +LataDBDataType LataDB::default_type_float() const
9198 +{
9199 +  LataDBDataType type = default_type_int_;
9200 +  type.type_ = default_float_type_;
9201 +  return type;
9202 +}
9203 +
9204 +// Description: Writes the lata master file to filename (filename must contain the path
9205 +//  if you don't want to write in the current working directory). All data contained
9206 +//  in the database is dumped to the file. 
9207 +void LataDB::write_master_file(const char *filename) const
9208 +{
9209 +  if (!filename) {
9210 +    Journal() << "LataDB::write_master_file got a null filename !!!" << endl;
9211 +    throw(LataDBError(LataDBError::INVALID_OPERATION));    
9212 +  }
9213 +  std::ofstream os(filename);
9214 +  if (!os.good()) { // isnogood ?
9215 +    Journal() << "LataDB::write_master_file failed opening file " << filename << endl;
9216 +    throw(LataDBError(LataDBError::FILE_NOT_FOUND));
9217 +  }
9218 +  // Try to write, if error, catch and close the file:
9219 +  Journal(verb_level-1) << "Writing lata master file:" << filename << endl;
9220 +  os << "LATA_V2.1" << endl;
9221 +  os << case_ << endl;
9222 +  os << software_id_ << endl;
9223 +  
9224 +  // ****************************************************************
9225 +  // Writing data format information:
9226 +  {
9227 +    Motcle fmt, fmt2;
9228 +    build_format_string(LataDBDataType(), default_type_int_, fmt);
9229 +    build_format_string(default_type_int_, default_type_float(), fmt2);
9230 +    os << "Format " << fmt << "," << fmt2 << endl;
9231 +  }
9232 +
9233 +  // ***************************************************************
9234 +  // Writing timesteps:
9235 +  const entier nb_tsteps = nb_timesteps();
9236 +  for (entier tstep = 0; tstep < nb_tsteps; tstep++) {
9237 +    if (tstep > 0)
9238 +      os << "TEMPS " << get_time(tstep) << endl;
9239 +
9240 +    Noms geoms = geometry_names(tstep);
9241 +    const entier nb_geoms = geoms.size();
9242 +    for (entier i_geom = 0; i_geom < nb_geoms; i_geom++) {
9243 +      const LataDBGeometry & geom = get_geometry(tstep, geoms[i_geom], FIRST_AND_CURRENT);
9244 +      // Do not write geometries of the first timestep
9245 +      if (geom.timestep_ == tstep)
9246 +        os << "GEOM  " << geom.name_ << " type_elem=" << geom.elem_type_ << endl;
9247 +    }
9248 +    Field_UNames unames = field_unames(tstep, "*", "*");
9249 +    for (entier i_field = 0; i_field < unames.size(); i_field++) {
9250 +      const LataDBField & field = get_field(tstep, unames[i_field]);
9251 +      os << "CHAMP " << field.name_ 
9252 +         << " " << field.filename_;
9253 +      if (field.geometry_ != "")
9254 +        os << " geometrie=" << field.geometry_;
9255 +      os << " size=" << field.size_;
9256 +      os << " composantes=" << field.nb_comp_;
9257 +      if (field.localisation_ != "??" && field.localisation_ != "")
9258 +        os << " localisation=" << field.localisation_;
9259 +      if (field.component_names_.size() > 0) {
9260 +        os << " noms_compo=";
9261 +        const entier n = field.component_names_.size();
9262 +        for (entier i = 0; i < n; i++) {
9263 +          os << field.component_names_[i];
9264 +          if (i < n-1)
9265 +            os << ",";
9266 +        }
9267 +      }
9268 +      switch(field.nature_) {
9269 +      case LataDBField::UNKNOWN: break;
9270 +      case LataDBField::SCALAR: os << " nature=scalar"; break;
9271 +      case LataDBField::VECTOR: os << " nature=vector"; break;
9272 +      default:
9273 +        Journal() << "LataDB::write_master_file error: unknown NATURE" << endl;
9274 +        throw(LataDBError(LataDBError::INVALID_OPERATION));
9275 +      }
9276 +      if (field.reference_ != "" && field.reference_ != "??")
9277 +        os << " reference=" << field.reference_;
9278 +      Motcle format_string;
9279 +      build_format_string(default_type_float(), field.datatype_, format_string);
9280 +      if (format_string != "") 
9281 +        os << " format=" << format_string;
9282 +      if (field.datatype_.file_offset_ > 0)
9283 +        os << " file_offset=" << field.datatype_.file_offset_;
9284 +      os << endl;
9285 +    }
9286 +  }
9287 +  os << "FIN" << endl;
9288 +  write_master_file_to_call_ = 0;
9289 +}
9290 +
9291 +// Description: internal template to write a data block. We provide explicit methods write_data()
9292 +//  to the user instead of a template.
9293 +template <class C_Tab>
9294 +FileOffset LataDB::write_data_(entier tstep, const Field_UName & uname, const C_Tab & data)
9295 +{
9296 +  LataDBField & fld = getset_field(tstep, uname);
9297 +
9298 +  LataDataFile f(internal_data_buffer_, path_prefix_, fld.filename_,
9299 +                 fld.datatype_.msb_,
9300 +                 (fld.datatype_.file_offset_ <= 0) ? LataDataFile::WRITE : LataDataFile::APPEND);
9301 +  fld.datatype_.file_offset_ = f.position();
9302 +  Journal(verb_level_data_bloc) << "Writing block data at offset " << fld.datatype_.file_offset_ << endl;
9303 +  if (fld.nb_comp_ != data.dimension(1) || fld.size_ != data.dimension(0)) {
9304 +    Journal() << "Error in LataDB::write_data_: nb_comp_ or size_ declared in the field doesnt match array dimensions." << fld.name_ << endl;
9305 +    throw;
9306 +  }
9307 +
9308 +  const entier n = fld.size_;
9309 +  
9310 +  switch (fld.datatype_.data_ordering_) {
9311 +  case LataDBDataType::C_ORDERING: 
9312 +    {
9313 +      if (fld.datatype_.fortran_bloc_markers_ == LataDBDataType::BLOC_MARKERS_MULTIPLE_WRITES) {
9314 +        Journal() << "Error in LataDB::write_data_: fortran_bloc_markers_=MULTIPLE_WRITES is incompatible with data_ordering=C" << endl;
9315 +        throw LataDBError(LataDBError::DATA_ERROR);
9316 +      }
9317 +      const entier sz = data.size_array();
9318 +      write_blocksize(f, fld.datatype_, sz);
9319 +      bloc_write(f, fld.datatype_.msb_, fld.datatype_.type_, data, fld.nb_comp_);
9320 +      write_blocksize(f, fld.datatype_, sz);
9321 +      break;
9322 +    }
9323 +  case LataDBDataType::F_ORDERING:
9324 +    {
9325 +      entier multiple_bloc_markers = (fld.datatype_.fortran_bloc_markers_ == LataDBDataType::BLOC_MARKERS_MULTIPLE_WRITES);
9326 +      // reverse rows and columns of the array
9327 +      C_Tab tmp;
9328 +      tmp.resize(n, 1);
9329 +      if (!multiple_bloc_markers)
9330 +        write_blocksize(f, fld.datatype_, data.size_array());
9331 +      for (entier i = 0; i < fld.nb_comp_; i++) {
9332 +        if (multiple_bloc_markers)
9333 +          write_blocksize(f, fld.datatype_, n);
9334 +        for (entier j = 0; j < n; j++)
9335 +          tmp(j, 0) = data(j, i);
9336 +        bloc_write(f, fld.datatype_.msb_, fld.datatype_.type_, tmp, 1);
9337 +        if (multiple_bloc_markers)
9338 +          write_blocksize(f, fld.datatype_, n);
9339 +      }
9340 +      if (!multiple_bloc_markers)
9341 +        write_blocksize(f, fld.datatype_, data.size_array());
9342 +      break;
9343 +    }
9344 +  default:
9345 +    Journal() << "Error in LataDB::write_data_: data_ordering not implemented" << endl;
9346 +    throw;
9347 +  }
9348 +  write_master_file_to_call_ = 1;
9349 +  return f.position();
9350 +}
9351 +
9352 +// Writes the data to disk according to datatype_ of the field.
9353 +// The filename will be "path_prefix_ + field.filename_".
9354 +// The path_prefix_ can be changed with set_path_prefix()
9355 +// If field.datatype_.file_offset_<=0, any existing file is deleted and the data is written at offset 0
9356 +// otherwise the data is written at the end of the file and file_offset_ for this field is updated.
9357 +// Returns the FileOffset of the file pointer after writing the data (points to the end of the file)
9358 +// The call to write_master_file() must be done after all write_data (otherwise the file_offset_ might be wrong)
9359 +FileOffset LataDB::write_data(entier tstep, const Field_UName & uname, const DoubleTab &tab)
9360 +{
9361 +  Journal() << " LataDB::write_data not coded for double" << endl;
9362 +  throw;
9363 +  return 0;
9364 +}
9365 +
9366 +// See write_data(..., const DoubleTab &)
9367 +FileOffset LataDB::write_data(entier tstep, const Field_UName & uname, const FloatTab &tab)
9368 +{
9369 +  return write_data_(tstep, uname, tab);
9370 +}
9371 +
9372 +// See write_data(..., const DoubleTab &)
9373 +FileOffset LataDB::write_data(entier tstep, const Field_UName & uname, const IntTab &tab)
9374 +{
9375 +  if (get_field(tstep, uname).datatype_.array_index_ == LataDBDataType::F_INDEXING) {
9376 +    IntTab tmp;
9377 +    tmp.set_smart_resize(1);
9378 +    tmp.resize(tab.dimension(0), tab.dimension(1));
9379 +    ArrOfInt & array = tmp;
9380 +    const ArrOfInt & src = tab;
9381 +    for (entier i = 0; i < array.size_array(); i++)
9382 +      array[i] = src[i] + 1;
9383 +    return write_data_(tstep, uname, tmp);
9384 +  }
9385 +
9386 +  return write_data_(tstep, uname, tab);
9387 +}
9388 +
9389 +LataDB::~LataDB()
9390 +{
9391 +#if 0
9392 +  if (write_master_file_to_call_) {
9393 +    Journal() << "Internal Error !!! write_data() has been called without calling write_master_file() after." << endl;
9394 +//    exit(); // In c++ it is forbidden to throw exceptions in a destructor.
9395 +  }
9396 +#endif
9397 +}
9398 +
9399 +const char *LataDBError::describe() const
9400 +{
9401 +  switch(err_) {
9402 +  case READ_ERROR: return "READ_ERROR"; break;
9403 +  case BAD_HEADER: return "BAD_HEADER"; break;
9404 +  case BAD_TIMESTEP: return "BAD_TIMESTEP"; break;
9405 +  case NAME_NOT_FOUND: return "NAME_NOT_FOUND"; break;
9406 +  case DATA_ERROR: return "DATA_ERROR"; break;
9407 +  case FILE_NOT_FOUND: return "FILE_NOT_FOUND"; break;
9408 +  case BAD_ELEM_TYPE: return "BAD_ELEM_TYPE"; break;
9409 +  case INVALID_OPERATION: return "INVALID_OPERATION"; break;
9410 +  case INTEGER_OVERFLOW: return "INTEGER_OVERFLOW"; break;
9411 +  default: ;
9412 +  }
9413 +  return "LataDB_unknown_error";
9414 +}
9415 +#undef verb_level
9416 +#undef verb_level_data_bloc
9417 diff --git a/databases/readers/Lata/LataDB.h b/databases/readers/Lata/LataDB.h
9418 new file mode 100644
9419 index 0000000..8862d3c
9420 --- /dev/null
9421 +++ b/databases/readers/Lata/LataDB.h
9422 @@ -0,0 +1,303 @@
9423 +/*****************************************************************************
9424 +*
9425 +* Copyright (c) 2011 - 2013, CEA
9426 +* All rights reserved.
9427 +* Redistribution and use in source and binary forms, with or without
9428 +* modification, are permitted provided that the following conditions are met:
9429 +*
9430 +*     * Redistributions of source code must retain the above copyright
9431 +*       notice, this list of conditions and the following disclaimer.
9432 +*     * Redistributions in binary form must reproduce the above copyright
9433 +*       notice, this list of conditions and the following disclaimer in the
9434 +*       documentation and/or other materials provided with the distribution.
9435 +*     * Neither the name of CEA, nor the
9436 +*       names of its contributors may be used to endorse or promote products
9437 +*       derived from this software without specific prior written permission.
9438 +*
9439 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
9440 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9441 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
9442 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
9443 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
9444 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
9445 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
9446 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9447 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
9448 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9449 +*
9450 +*****************************************************************************/
9451 +
9452 +#ifndef LataDB_include_
9453 +#define LataDB_include_
9454 +#include <Lata_tools.h>
9455 +#include <sstream>
9456 +
9457 +// This file describes the LataDB class and all associated data structures.
9458 +//  LataDB stores all the meta contained in the .lata master file, and not more.
9459 +//  It provides services to add meta-data, read data to a user specified array,
9460 +//  and write data to a lata file.
9461 +
9462 +typedef BigEntier FileOffset;
9463 +
9464 +// .Description: LataDBError is the type used for thrown exceptions in LataDBxxx classes
9465 +class LataDBError
9466 +{
9467 +public:
9468 +  // READ_ERROR: low level io error while reading .lata file
9469 +  // BAD_HEADER: the header in the .lata file is not correct
9470 +  // BAD_TIMESTEP: request for a non existant timestep
9471 +  // NAME_NOT_FOUND: request for a non existant domain or field name
9472 +  // DATA_ERROR: low level io error while reading a data bloc file
9473 +  // FILE_NOT_FOUND: a file (.lata or data) couldn't be opened on disc.
9474 +  // INVALID_OPERATION: trying to read from a modified database, etc...
9475 +  // INTEGER_OVERFLOW: trying to convert an integer to a too small data type
9476 +  //  (if error when reading a data file, you must recompile with typedef long long entier,
9477 +  //   if error when writing a data file, you must use INT64 type_ for data blocks)
9478 +  enum ErrType { READ_ERROR, BAD_HEADER, BAD_TIMESTEP, NAME_NOT_FOUND, DATA_ERROR,
9479 +                 FILE_NOT_FOUND, BAD_ELEM_TYPE, INVALID_OPERATION, INTEGER_OVERFLOW };
9480 +  LataDBError(ErrType err) : err_(err) {};
9481 +  ErrType err_;
9482 +  const char *describe() const;
9483 +};
9484 +
9485 +// .Description: This is the data type for a specific part of a data bloc.
9486 +//  In order to read a data bloc, we need a LataDBDataType for the "bloc size" id (this is an integer),
9487 +//  and a LataDBDataType for the bloc content. LataDBGeometry blocs need two types, one for
9488 +//  the node coordinates and one for the elements
9489 +class LataDBDataType
9490 +{
9491 +public:
9492 +  enum MSB { UNKNOWN_MSB, MSB_BIG_ENDIAN, MSB_LITTLE_ENDIAN, ASCII };
9493 +  MSB msb_;
9494 +  enum Type { UNKNOWN_TYPE, INT32, INT64, REAL32, REAL64 };
9495 +  Type type_;
9496 +  // Array index is ignored if type_ is REAL.
9497 +  // NOT_AN_INDEX: array does not contain indexes.
9498 +  // C_INDEXING: If array contains indexes to other items, 0 <= array[i] < nb_items
9499 +  // F_INDEXING: 1 <= array[i] <= nb_items (Fortran index)
9500 +  // See LataDB::read_data
9501 +  enum ArrayIndex { UNKNOWN_ARRAYINDEX, NOT_AN_INDEX, C_INDEXING, F_INDEXING };
9502 +  ArrayIndex array_index_;
9503 +  // C_ORDERING: If multidimensionnal array is read, data ordering is like in C
9504 +  //               (all components for first node, then all components for second node, etc)
9505 +  // F_ORDERING: like in fortran (first all values for component 0 then all values for compo 1 etc)
9506 +  enum DataOrdering { UNKNOWN_ORDERING, C_ORDERING, F_ORDERING };
9507 +  DataOrdering data_ordering_;
9508 +
9509 +  //   _NO_BLOC:         no fortran bloc marker
9510 +  //   _SINGLE_WRITE:    all data written in one fortran write instruction
9511 +  //   _MULTIPLE_WRITES: one fortran write instruction for each component
9512 +  enum FortranBlocMarkers { UNKNOWN_MARKERS, NO_BLOC_MARKER, BLOC_MARKERS_SINGLE_WRITE, BLOC_MARKERS_MULTIPLE_WRITES };
9513 +  FortranBlocMarkers fortran_bloc_markers_;
9514 +
9515 +  // The data type for fortran bloc markers
9516 +  Type bloc_marker_type_;
9517 +
9518 +  // Data is located at this offset in the file
9519 +  FileOffset file_offset_;
9520 +
9521 +  LataDBDataType() : msb_(UNKNOWN_MSB), type_(UNKNOWN_TYPE), array_index_(UNKNOWN_ARRAYINDEX), 
9522 +                     data_ordering_(UNKNOWN_ORDERING), fortran_bloc_markers_(UNKNOWN_MARKERS), bloc_marker_type_(UNKNOWN_TYPE),
9523 +                     file_offset_(0)
9524 +  {};
9525 +  static MSB machine_msb_;
9526 +};
9527 +
9528 +// .Description: Description of a geometry (= a mesh)
9529 +class LataDBGeometry
9530 +{
9531 +public:
9532 +  LataDBGeometry() { timestep_ = -1; }
9533 +  // Item name
9534 +  Nom name_;
9535 +  // Type of elements
9536 +  Motcle elem_type_;
9537 +  entier timestep_;
9538 +};
9539 +
9540 +// This is a unique identifier for fields
9541 +//  at this time, contains domain name, field name and localisation,
9542 +//  might be further extended if needed
9543 +class Field_UName
9544 +{
9545 +public:
9546 +  Field_UName();
9547 +  Field_UName(const char *domain_name, const char *field_name, const char *loc);
9548 +  Field_UName(const Field_UName &);
9549 +  int operator==(const Field_UName &) const;
9550 +  Field_UName & operator=(const Field_UName &);
9551 +  Nom build_string() const;
9552 +  const Motcle & get_localisation() const { return loc_; }
9553 +  const Motcle & get_field_name() const { return field_name_; }
9554 +  const Motcle & get_geometry() const { return geometry_; }
9555 +  void        set_field_name(const Nom &);
9556 +protected:
9557 +  Motcle geometry_;
9558 +  Motcle field_name_;
9559 +  Motcle loc_;
9560 +};
9561 +
9562 +std::ostream & operator<<(std::ostream &, const Field_UName &);
9563 +
9564 +typedef LataVector<Field_UName> Field_UNames;
9565 +class EFichier;
9566 +
9567 +// .Description: Description of a field
9568 +class LataDBField
9569 +{
9570 +public:
9571 +  LataDBField() { timestep_ = -1; nb_comp_ = -1; nature_ = UNKNOWN; size_ = -1; }
9572 +
9573 +  // Unique identifier
9574 +  Field_UName uname_;
9575 +  // Field name (without localisation spec)
9576 +  Nom name_;
9577 +  // Where is it ?
9578 +  int timestep_;
9579 +  // Filename containing the data
9580 +  // Special names: memory_buffer_file() => data stored in the LataDB memory buffer.
9581 +  Nom filename_;
9582 +  // Number of components
9583 +  entier nb_comp_;
9584 +  // LataDBGeometry
9585 +  Nom geometry_;
9586 +  // Name of the components
9587 +  Noms component_names_;
9588 +  Noms unites_;
9589 +  // Scalar or vector ?
9590 +  enum Nature { UNKNOWN, SCALAR, VECTOR };
9591 +  Nature nature_;
9592 +  // Type and formatting info of the data
9593 +  LataDBDataType datatype_;
9594 +  // Localisation (elem, som, faces, ...)
9595 +  Motcle localisation_;
9596 +  // Ref
9597 +  Nom reference_;
9598 +  // Size (number of lines) 
9599 +  long long size_;
9600 +  
9601 +  static const char * memory_buffer_file();
9602 +};
9603 +
9604 +// .Description: Description of one timestep (contains a vector of items)
9605 +class LataDBTimestep
9606 +{
9607 +public:
9608 +  LataDBTimestep() { time_ = -1.; }
9609 +  double time_;
9610 +protected:
9611 +  friend class LataDB;
9612 +  LataVector<LataDBGeometry> geoms_;
9613 +  LataVector<LataDBField> fields_;
9614 +};
9615 +
9616 +class LataDataFile;
9617 +class ArrOfInt;
9618 +class LataDB
9619 +{
9620 +public:
9621 +  LataDB() : internal_data_buffer_(std::ios::in | std::ios::out | std::ios::app | std::ios::binary) { old_style_lata_ = 0; path_prefix_ = ""; write_master_file_to_call_ = 0; }
9622 +  LataDB(const LataDB & src) :
9623 +    header_(src.header_),
9624 +    case_(src.case_),
9625 +    software_id_(src.software_id_),
9626 +    default_type_int_(src.default_type_int_),
9627 +    default_float_type_(src.default_float_type_),
9628 +    timesteps_(src.timesteps_),    
9629 +    path_prefix_(src.path_prefix_),
9630 +    old_style_lata_(src.old_style_lata_),
9631 +    write_master_file_to_call_(src.write_master_file_to_call_) {
9632 +    // Note B.M. il faudrait copier internal_data_buffer_ pour faire marcher lml->lata mais je ne sais pas faire...
9633 +  }
9634 +  virtual ~LataDB();
9635 +  void reset();
9636 +  virtual void read_master_file(const char * path_prefix_, const char * filename);
9637 +  void read_master_file_med(const char *prefix, const char *filename);
9638 +  static Nom   read_master_file_options(const char * filename);
9639 +  
9640 +  virtual void filter_db(const LataDB & source,
9641 +                         const Motcles & geometry_names,
9642 +                         const Motcles & field_names,
9643 +                         const ArrOfInt & timesteps);
9644 +
9645 +  entier                 nb_timesteps() const;
9646 +  double                 get_time(entier tstep) const;
9647 +  enum TStepSelector { CURRENT, FIRST_AND_CURRENT };
9648 +  Noms                   geometry_names(entier tstep, TStepSelector which_tstep = CURRENT) const;
9649 +  Field_UNames           field_unames(entier tstep, const char * geometry, const char * name, TStepSelector which_tstep = CURRENT) const;
9650 +  const LataDBGeometry & get_geometry(entier tstep, const char * name, TStepSelector which_tstep = CURRENT) const;
9651 +  entier                 field_exists(entier tstep, const char *geom, const char *name, TStepSelector which_tstep = CURRENT) const;
9652 +  const LataDBField &    get_field(entier tstep, const Field_UName & uname, TStepSelector which_tstep = CURRENT) const;
9653 +  const LataDBField &    get_field(entier tstep, const char *geom, const char *name, const char *loc, TStepSelector which_tstep = CURRENT) const;
9654 +  const Nom &            path_prefix() const { return path_prefix_; };
9655 +  void                   set_path_prefix(const char * s);
9656 +
9657 +  // First line in the .lata file
9658 +  Nom header_;
9659 +  // Second line in the .lata file
9660 +  Nom case_;
9661 +  // Third line in the .lata file
9662 +  Nom software_id_;
9663 +
9664 +  LataDBDataType default_type_float() const; // Everything same as int, but type_=default_float_type_
9665 +  LataDBDataType default_type_int_;
9666 +  LataDBDataType::Type default_float_type_;
9667 +
9668 +  virtual void read_data(const LataDBField &, DoubleTab & data, long long debut = 0, entier n = -1) const;
9669 +  virtual void read_data(const LataDBField &, FloatTab & data, long long debut = 0, entier n = -1) const;
9670 +  virtual void read_data(const LataDBField &, IntTab & data, long long debut = 0, entier n = -1) const;
9671 +  virtual void read_data(const LataDBField &, DoubleTab & data, const ArrOfInt & lines_to_read) const;
9672 +  virtual void read_data(const LataDBField &, FloatTab & data, const ArrOfInt & lines_to_read) const;
9673 +  virtual void read_data(const LataDBField &, IntTab & data, const ArrOfInt & lines_to_read) const;
9674 +
9675 +  enum Element { line, triangle, quadri, tetra, hexa, triangle_3D, quadri_3D, polyedre,polygone, unspecified };
9676 +  static Element element_type_from_string(const Motcle & type_elem);
9677 +
9678 +  // Tools to create/update the database and write lata data to disk
9679 +  void   change_all_data_types(const LataDBDataType & old_type, const LataDBDataType & new_type);
9680 +  void   change_all_data_filenames(const Nom & old_prefix, const Nom & new_prefix);
9681 +  void   check_all_data_fileoffsets(entier split_files);
9682 +  entier add_timestep(double time);
9683 +  void   add_geometry(const LataDBGeometry & geom);
9684 +  void   set_elemtype(entier tstep, const char *geom_name, const char *elem_type);  
9685 +  entier check_duplicate_filename(const char *filename) const;
9686 +  void   add_field(const LataDBField & field);
9687 +  void   write_master_file(const char *filename) const;
9688 +  FileOffset write_data(entier tstep, const Field_UName &, const DoubleTab &);
9689 +  FileOffset write_data(entier tstep, const Field_UName &, const FloatTab &);
9690 +  FileOffset write_data(entier tstep, const Field_UName &, const IntTab &);
9691 +
9692 +protected:
9693 +  LataDBField & getset_field(entier tstep, const Field_UName & uname, TStepSelector which_tstep = CURRENT);
9694 +  void          read_master_file_header(const char *filename, EFichier & is);
9695 +  static entier lata_v1_dim_from_elem_type(const Motcle & elem_type);
9696 +  static entier lata_v1_get_nb_comp(const Nom & fieldname, const Motcle & localisation, const LataDBGeometry & dom, entier dim, LataDBField::Nature & nature, LataDBDataType::DataOrdering &);
9697 +  static void get_element_data(const Motcle & elemtype, entier & dimension, entier & elem_shape, entier & face_shape, entier & nb_elem_faces);
9698 +
9699 +  const LataDBTimestep & get_tstep(entier i) const;
9700 +  void add(entier tstep, const LataDBGeometry & item);
9701 +  void add(entier tstep, const LataDBField & item);
9702 +  template <class C_Tab> void read_data_(const LataDBField &, C_Tab & data, long long debut, entier n) const;
9703 +  template <class C_Tab> void read_data_(const LataDBField &, C_Tab & data, const ArrOfInt & lines_to_read) const;
9704 +  template <class C_Tab> void read_data2_(LataDataFile & f, const LataDBField & fld, C_Tab * const data, long long debut = 0, entier n = -1, const ArrOfInt *lines_to_read = 0) const;
9705 +  template <class C_Tab> void read_data2_med_( const LataDBField & fld, C_Tab * const data, entier debut = 0, entier n = -1, const ArrOfInt *lines_to_read = 0) const;
9706 +  template <class C_Tab> FileOffset write_data_(entier tstep, const Field_UName & uname, const C_Tab &);
9707 +
9708 +  // Timestep 0 contains global domains and field definition
9709 +  // Timestep 1..size()-1 contain the data for each "TEMPS" entry
9710 +  LataVector<LataDBTimestep> timesteps_;
9711 +
9712 +  // Path prefix for all data blocks (used by read_data() and write_data())
9713 +  Nom path_prefix_;
9714 +
9715 +  // Is this an old-style lata file ? (with INTERFACES special files and 2D elements expanded to 3D elements)
9716 +  entier old_style_lata_;
9717 +
9718 +  // This flag tells if some write_data calls have been made since the last write_master_file
9719 +  // If yes, issue a message to say that's wrong !
9720 +  mutable entier write_master_file_to_call_;
9721 +
9722 +  // This is a memory buffer where data can be written to create a temporary data base
9723 +  mutable std::stringstream internal_data_buffer_;
9724 +};
9725 +#endif
9726 diff --git a/databases/readers/Lata/LataDBmed.h b/databases/readers/Lata/LataDBmed.h
9727 new file mode 100644
9728 index 0000000..13cfdbe
9729 --- /dev/null
9730 +++ b/databases/readers/Lata/LataDBmed.h
9731 @@ -0,0 +1,586 @@
9732 +/*****************************************************************************
9733 +*
9734 +* Copyright (c) 2011 - 2013, CEA
9735 +* All rights reserved.
9736 +* Redistribution and use in source and binary forms, with or without
9737 +* modification, are permitted provided that the following conditions are met:
9738 +*
9739 +*     * Redistributions of source code must retain the above copyright
9740 +*       notice, this list of conditions and the following disclaimer.
9741 +*     * Redistributions in binary form must reproduce the above copyright
9742 +*       notice, this list of conditions and the following disclaimer in the
9743 +*       documentation and/or other materials provided with the distribution.
9744 +*     * Neither the name of CEA, nor the
9745 +*       names of its contributors may be used to endorse or promote products
9746 +*       derived from this software without specific prior written permission.
9747 +*
9748 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
9749 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9750 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
9751 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
9752 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
9753 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
9754 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
9755 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9756 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
9757 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9758 +*
9759 +*****************************************************************************/
9760 +
9761 +//#define WITH_MEDLOADER
9762 +#ifndef WITH_MEDLOADER
9763 +void LataDB::read_master_file_med(const char *prefix, const char *filename)
9764 +{
9765 +  Journal() << "MED PLUGIN not compiled!" << endl;
9766 +  throw;
9767 +}
9768 +template <class C_Tab> void LataDB::read_data2_med_(
9769 +                         const LataDBField & fld,
9770 +                         C_Tab * const data, // const pointer to non const data !
9771 +                         entier debut, entier n, const ArrOfInt *lines_to_read) const
9772 +{
9773 +   Journal() << "MED PLUGIN not compiled!" << endl;
9774 +  
9775 +   throw;    
9776 +}
9777 +#else
9778 +
9779 +#include <MEDLoader.hxx>
9780 +#include <MEDCouplingMemArray.hxx>
9781 +#include <MEDCouplingUMesh.hxx>
9782 +#include <MEDCouplingFieldDouble.hxx>
9783 +#include <CellModel.hxx>
9784 +#include <MEDFileField.hxx>
9785 +
9786 +using std::vector;
9787 +using std::pair;
9788 +using std::string;
9789 +
9790 +
9791 +Nom latadb_name_from_type_geo(const med_geometry_type& type_geo)
9792 +{
9793 +  Nom type_elem;
9794 +  switch(type_geo)
9795 +    {
9796 +      case MED_QUAD4:
9797 +        type_elem="Rectangle";
9798 +        break;
9799 +      case MED_HEXA8:
9800 +        type_elem="Hexaedre";      
9801 +        break;
9802 +      case MED_TRIA3:
9803 +        type_elem="Triangle";break;
9804 +      case MED_TETRA4:
9805 +        type_elem="Tetraedre";break;
9806 +      case MED_PENTA6:
9807 +        type_elem="Prisme";break;
9808 +      case MED_POLYHEDRON:
9809 +        type_elem="Polyedre"; break;
9810 +      case MED_POLYGON:
9811 +        type_elem="Polygone"; break;
9812 +      case MED_SEG2:
9813 +        type_elem="Segment"; break;
9814 +      default:
9815 +        Cerr<<"type_geo " << (int)type_geo <<" is not a supported element."<<finl;
9816 +       throw;
9817 +        break;
9818 +      }
9819 +  return type_elem;
9820 +}
9821 +
9822 +
9823 +// passage de la connectivite trio a MED si sens=1
9824 +// de MED a trio si sens=-1
9825 +ArrOfInt renum_conn(const LataDB::Element& type)
9826 +{
9827 +  //  cerr<<"type elem "<<type_elem<<endl;
9828 +  ArrOfInt filter;
9829 +  if (type==LataDB::quadri ) {
9830 +      filter.resize_array(4) ;
9831 +   
9832 +      filter[0] = 0 ;
9833 +      filter[1] = 2 ;
9834 +      filter[2] = 3 ;
9835 +      filter[3] = 1 ;
9836 +
9837 +      
9838 +    }
9839
9840 +  if (type== LataDB::hexa  )  {
9841 +      filter.resize_array(8) ;
9842
9843 +        
9844 +      filter[0] = 0 ;
9845 +      filter[1] = 2 ;
9846 +      filter[2] = 3 ;
9847 +      filter[3] = 1 ;
9848 +      filter[4] = 4 ;
9849 +      filter[5] = 6 ;
9850 +      filter[6] = 7 ;
9851 +      filter[7] = 5 ;        
9852 +      
9853 +    }
9854 +   
9855 +    
9856 +  return filter;
9857 +
9858 +}
9859 +
9860 +extern med_geometry_type typmai3[MED_N_CELL_FIXED_GEO];
9861 +
9862 +void latadb_get_info_mesh_med(const char* filename,const char* meshname,med_geometry_type& type_geo,int& ncells,int& nnodes,int& spacedim, int &nbcomp,int& is_structured, std::vector<int>& NIJK)
9863 +{
9864 +    is_structured=0;
9865 +  int meshDim, i;
9866 +  try {
9867 +  std::vector< std::vector< std::pair<INTERP_KERNEL::NormalizedCellType,int> > > res = MEDCoupling::GetUMeshGlobalInfo(filename, meshname, meshDim, spacedim, nnodes);
9868 +  
9869 +
9870 +  // on prend que la dimension la plus grande et on verifie que l'on a qu'un type elt 
9871 +  if (res.size()>1)
9872 +    {
9873 +      cerr<<"error multi dimension in "<<meshname<<endl;
9874 +      //throw;
9875 +    }
9876 +  if (res[0].size()>1)
9877 +    {  
9878 +      cerr<<"error multi elements in "<<meshname<<endl;
9879 +      throw;
9880 +    }  
9881 +  type_geo=typmai3[res[0][0].first];
9882 +
9883 +  if ((type_geo==MED_POLYGON)||(type_geo==MED_POLYHEDRON))
9884 +    {
9885 +      //on est force de lire le maillage pour avoir le bon nombre de cellules  
9886 +      MEDCoupling::MEDCouplingUMesh * mesh=  MEDCoupling::ReadUMeshFromFile(filename,meshname);
9887 +      ncells = mesh->getNumberOfCells();
9888 +      const int *idx = mesh->getNodalConnectivityIndex()->getConstPointer();
9889 +      for (i = 0, nbcomp = 0; i < ncells; i++) if (nbcomp < idx[i + 1] - idx[i] - 1) nbcomp = idx[i + 1] - idx[i] - 1;
9890 +      mesh->decrRef();
9891 +    }
9892 +  else
9893 +    ncells=res[0][0].second;
9894 +    }
9895 +  catch (...)
9896 +  {
9897 +    // No UMesh try CMesh
9898 +      MEDCoupling::MEDCouplingMesh* mesh=  MEDCoupling::ReadMeshFromFile(filename, meshname);
9899 +      /* 
9900 +        type_geo,int& ncells,int& nnodes,int& spacedim, int &nbcomp
9901 +       */
9902 +      MEDCoupling::MEDCouplingCMesh* cmesh = dynamic_cast<MEDCoupling::MEDCouplingCMesh*>(mesh);
9903 +      spacedim=cmesh-> getSpaceDimension() ;
9904 +      
9905 +      NIJK= cmesh->getNodeGridStructure();
9906 +      ncells=mesh->getNumberOfCells();
9907 +      nnodes=mesh->getNumberOfNodes();
9908 +      
9909 +    
9910 +   // std::cout << ncells<< " "<<sizes[2]<<std::endl;
9911 +      mesh->decrRef();
9912 +      
9913 +      if (spacedim==3)
9914 +            type_geo =MED_HEXA8;
9915 +      else if (spacedim==2)
9916 +           type_geo =MED_QUAD4;
9917 +        else 
9918 +         abort();
9919 +        is_structured=1;
9920 +      //abort();
9921 +      return;
9922 +  }
9923 +}
9924 +
9925 +
9926 +
9927 +// Description: Reads the .lata database in the given file indicating than the 
9928 +//  associated data files will be found in directory "prefix".
9929 +//  If not empty, "prefix" must finish with a '/'.
9930 +//  For "prefix" and "filename", if they do not begin with '/', are relative to pwd.
9931 +// Exceptions: 
9932 +//  BAD_HEADER  means that the header found in this stream is not LATA_V2
9933 +//  READ_ERROR  means that an error has been found in the file (premature eof,
9934 +//              io error, bad keyword, ...)
9935 +//  FILE_NOT_FOUND means that, well, the lata file could not be opened
9936 +void LataDB::read_master_file_med(const char *prefix, const char *filename)
9937 +{
9938 +  
9939 +  
9940 +  Journal() << "MED PLUGIN !" << endl;
9941 +
9942 +  // Defaults for lataV1
9943 +  default_type_int_.msb_ = LataDBDataType::ASCII;
9944 +  default_type_int_.type_ = LataDBDataType::INT32;
9945 +  default_type_int_.array_index_ = LataDBDataType::F_INDEXING;
9946 +  default_type_int_.data_ordering_ = LataDBDataType::C_ORDERING;
9947 +  default_type_int_.fortran_bloc_markers_ = LataDBDataType::BLOC_MARKERS_SINGLE_WRITE;
9948 +  default_type_int_.bloc_marker_type_ = LataDBDataType::INT32;
9949 +  default_float_type_ = LataDBDataType::REAL32;
9950 +  
9951 +  
9952 +
9953 +  // Create timestep 0 (global domain and fields)
9954 +  timesteps_.add(LataDBTimestep());
9955 +
9956 +
9957 +  // on ajoute les geom 
9958 +  // on verra apres pour les champs elem et som
9959 +  vector<string> geoms= MEDCoupling::GetMeshNames(filename);
9960 +  
9961 +  vector<double> times;
9962 +  LataDBTimestep  table; 
9963 +  int first=1;
9964 +  
9965 +  for (int i=0;i<geoms.size();i++)
9966 +    {
9967 +      LataDBGeometry dom;
9968 +      dom.timestep_ = timesteps_.size()-1;
9969 +      dom.name_=geoms[i];
9970 +      med_geometry_type type_geo;
9971 +      int ncells,nnodes,spacedim, nbcomp;
9972 +      int is_structured;
9973 +      std::vector<int> NIJK;
9974 +      latadb_get_info_mesh_med(filename,geoms[i].c_str(),type_geo,ncells,nnodes,spacedim,nbcomp,is_structured,NIJK);
9975 +            
9976 +      dom.elem_type_=latadb_name_from_type_geo(type_geo);
9977 +
9978 +      if (is_structured==0)
9979 +      {
9980 +      LataDBField som;
9981 +      som.name_ = "SOMMETS";
9982 +      som.geometry_ = dom.name_;
9983 +      som.filename_ = filename;
9984 +      som.size_=nnodes;
9985 +      som.datatype_ = default_type_float(); // ??
9986 +      som.nb_comp_=spacedim;
9987 +      
9988 +      LataDBField elem;
9989 +      elem.name_ = "ELEMENTS";
9990 +      elem.geometry_ = dom.name_;
9991 +      elem.filename_ = filename;
9992 +      elem.size_=ncells;
9993 +      elem.datatype_ = default_type_float(); // ??
9994 +
9995 +      int dim,ff,ef;
9996 +      get_element_data(dom.elem_type_, dim, elem.nb_comp_, ff, ef);
9997 +      if (elem.nb_comp_ == -1) elem.nb_comp_ = nbcomp;
9998 +      
9999 +      add(timesteps_.size() - 1, dom);
10000 +      add(timesteps_.size() - 1, som);
10001 +      add(timesteps_.size() - 1, elem);
10002 +      }
10003 +      else
10004 +      {
10005 +      add(timesteps_.size() - 1, dom);
10006 +       {
10007 +        LataDBField som;
10008 +        som.name_ = "SOMMETS_IJK_I";
10009 +        som.geometry_ = dom.name_;
10010 +        som.filename_ = filename;
10011 +        som.size_=NIJK[0];
10012 +        som.datatype_ = default_type_float(); // ??
10013 +        som.nb_comp_=1;
10014 +        add(timesteps_.size() - 1, som);
10015 +      }
10016 +       {
10017 +        LataDBField som;
10018 +        som.name_ = "SOMMETS_IJK_J";
10019 +        som.geometry_ = dom.name_;
10020 +        som.filename_ = filename;
10021 +        som.size_=NIJK[1];
10022 +        som.datatype_ = default_type_float(); // ??
10023 +        som.nb_comp_=1;
10024 +        add(timesteps_.size() - 1, som);
10025 +      }
10026 +       {
10027 +        LataDBField som;
10028 +        som.name_ = "SOMMETS_IJK_K";
10029 +        som.geometry_ = dom.name_;
10030 +        som.filename_ = filename;
10031 +        som.size_=NIJK[2];
10032 +        som.datatype_ = default_type_float(); // ??
10033 +        som.nb_comp_=1;
10034 +        add(timesteps_.size() - 1, som);
10035 +      }
10036 +          
10037 +      }
10038 +      
10039 +    
10040 +  vector<string> fields; 
10041 +  fields= MEDCoupling::GetAllFieldNamesOnMesh(filename,dom.name_.getString());
10042 +  
10043 +
10044 +  for (int i=0;i<fields.size();i++)
10045 +    {
10046 +      LataDBField som;
10047 +      som.name_ = fields[i];
10048 +      
10049 +      som.filename_ = filename;
10050 +      
10051 +      som.datatype_ = default_type_float(); // ??
10052 +      
10053 +      som.nature_ = LataDBField::SCALAR;
10054 +  
10055 +  
10056 +      const Nom& meshname = dom.name_; 
10057 +      som.geometry_ = meshname;
10058 +      Motcle newname(fields[i].c_str());
10059 +      Motcle ajout("_");
10060 +
10061 +      // cerr<<"field " <<fields[i]<< " "<< meshname<<" ";
10062 +      vector< MEDCoupling::TypeOfField > ltypes=MEDCoupling::GetTypesOfField(filename,meshname.getString(),fields[i].c_str());
10063 +      //if (ltypes.size()!=1) throw;
10064 +      for (int t=0;t<ltypes.size();t++)
10065 +      {
10066 +      switch (ltypes[t])
10067 +       {
10068 +         //    case :
10069 +       case MEDCoupling::ON_CELLS :
10070 +         //cerr<<"elem"<<endl;
10071 +         som.size_=ncells;
10072 +         som.localisation_="ELEM";
10073 +         break;
10074 +       case  MEDCoupling::ON_NODES :
10075 +         //cerr<<"som"<<endl;
10076 +         som.size_=nnodes;
10077 +         som.localisation_="SOM";
10078 +         break;
10079 +       default:
10080 +         cerr<<"type inconnu "<<endl;throw;
10081 +       }
10082 +
10083 +      som.nb_comp_=1;
10084 +      // pour recupere nb_comp !!!
10085 +      
10086 +      som.nb_comp_=MEDCoupling::GetComponentsNamesOfField(filename,fields[i].c_str()).size();
10087 +
10088 +      
10089 +      if (spacedim==som.nb_comp_)
10090 +       som.nature_ = LataDBField::VECTOR;
10091 +      ajout+=som.localisation_;
10092 +      ajout+="_";
10093 +      ajout+=meshname;
10094 +      newname=newname.prefix(ajout);
10095 +     
10096 +      som.name_=newname;
10097 +     
10098 +      //som.uname_= Field_UName(meshname, newname, som.localisation_);
10099 +      
10100 +      table.fields_.add(som);
10101 +    
10102 +      if (1) 
10103 +      {
10104 +       if (ltypes.size()>1)
10105 +         {
10106 +           vector<pair< int, int > > iters= MEDCoupling::GetFieldIterations(ltypes[t],filename,meshname.getString(),fields[i].c_str());
10107 +           for (int iter=0;iter<iters.size();iter++)
10108 +             {
10109 +               double t= MEDCoupling::GetTimeAttachedOnFieldIteration(filename,fields[i].c_str(),iters[iter].first,iters[iter].second);
10110 +               if (first==1)
10111 +                 {
10112 +                   times.push_back(t);
10113 +                   //cerr<<"M ici  "<<t <<" "<<iters[iter].first<<" "<<iters[iter].second<<endl;
10114 +                 }
10115 +               else
10116 +                 {
10117 +                   if (times[iter]!=t)
10118 +                     {
10119 +                       cerr<<"field " <<fields[i]<<" M time "<< t << " diff "<<times[iter] << endl;
10120 +                       //throw;
10121 +                     }
10122 +                 }
10123 +             }
10124 +           
10125 +         }
10126 +       else
10127 +         {
10128 +           vector<pair<pair<int,int>,double> > vtimes=MEDCoupling::GetAllFieldIterations(filename,/*meshname,*/fields[i].c_str());
10129 +           for (int it=0;it<vtimes.size();it++)
10130 +             {
10131 +               
10132 +               double t=vtimes[it].second;
10133 +               if (first==1)
10134 +                 {
10135 +                   times.push_back(t);
10136 +                   //  cerr<<" ici  "<<t <<endl;
10137 +                 }
10138 +               else
10139 +                 {
10140 +                   if (times[it]!=t)
10141 +                     {
10142 +                       cerr<<"field " <<fields[i]<<" time "<< t << " diff "<<times[it] << endl;
10143 +                       //throw;
10144 +                     }
10145 +                 }
10146 +             }
10147 +
10148 +         }
10149 +      }
10150 +      first=0;
10151 +    }
10152 +    }
10153 +    }
10154 +  if (times.size()>0)
10155 +    for (int i=0;i<times.size();i++)
10156 +    {
10157 +      
10158 +      //LataDBTimestep & t = timesteps_.add(table);
10159 +      LataDBTimestep& t = timesteps_.add(LataDBTimestep());
10160 +      t.time_=times[i];
10161 +      for (int f=0;f<table.fields_.size();f++)
10162 +       add(i+1,table.fields_[f]);
10163 +    
10164 +    }
10165 +  for (int i=0;i<times.size()*0;i++)
10166 +    cerr<<" time "<<times[i]<<endl;
10167 +}
10168 +
10169 +
10170 +template <class C_Tab>
10171 +void LataDB::read_data2_med_(
10172 +                         const LataDBField & fld,
10173 +                         C_Tab * const data, // const pointer to non const data !
10174 +                         entier debut, entier n, const ArrOfInt *lines_to_read) const
10175 +{
10176 +  assert(debut==0);
10177 +  //assert(n==-1);
10178 +  assert(lines_to_read==NULL);
10179
10180 +  if (fld.name_=="SOMMETS")
10181 +    {
10182 +      //    cerr<<"load sommets "<<endl;
10183 +      MEDCoupling::MEDCouplingUMesh * mesh=  MEDCoupling::ReadUMeshFromFile(fld.filename_.getString(),fld.geometry_.getString());
10184 +      const  MEDCoupling::DataArrayDouble* coords=mesh->getCoords();
10185 +      data->resize(fld.size_,fld.nb_comp_);
10186 +      for (int i=0;i<fld.size_;i++)
10187 +       for (int j=0;j<fld.nb_comp_;j++)
10188 +         {
10189 +           (*data)(i,j)=coords->getIJ(i,j);
10190 +         }
10191 +      mesh->decrRef();
10192 +      
10193 +    }
10194 +  else if (fld.name_=="ELEMENTS")
10195 +    {
10196 +      // cerr<<"load elements "<<endl;
10197 +      Nom type_elem=get_geometry(fld.timestep_,fld.geometry_).elem_type_;
10198 +      LataDB::Element type =LataDB::element_type_from_string(type_elem);
10199 +      ArrOfInt filter=renum_conn(type);
10200 +      MEDCoupling::MEDCouplingUMesh * mesh=  MEDCoupling::ReadUMeshFromFile(fld.filename_.getString(),fld.geometry_.getString());
10201 +      const  MEDCoupling::DataArrayInt *elems = mesh->getNodalConnectivity(), *idx = mesh->getNodalConnectivityIndex();
10202 +      const int *ptr_elems=elems->getConstPointer(), *ptr_idx = idx->getConstPointer();
10203 +      data->resize(fld.size_,fld.nb_comp_);
10204 +      int compt=0;
10205 +      for (int i=0;i<fld.size_;i++)
10206 +      {
10207 +          compt++;
10208 +          for (int j=0;j<fld.nb_comp_;j++)
10209 +          {
10210 +              int reel = j + ptr_idx[i] + 1 < ptr_idx[i + 1];
10211 +              (*data)(i,filter.size_array()>0 ? filter[j] : j) = reel ? ptr_elems[compt] + 1 : 0;
10212 +              compt += reel;
10213 +          }
10214 +      }
10215 +      mesh->decrRef();
10216 +    }
10217 +  else if (fld.name_.debute_par("SOMMETS_IJK_"))
10218 +    {
10219 +      MEDCoupling::MEDCouplingMesh * mesh=  MEDCoupling::ReadMeshFromFile(fld.filename_.getString(),fld.geometry_.getString());
10220 +      data->resize(fld.size_,fld.nb_comp_);
10221 +      MEDCoupling::MEDCouplingCMesh* cmesh = dynamic_cast<MEDCoupling::MEDCouplingCMesh*>(mesh);
10222 +      int dir;
10223 +      if (fld.name_=="SOMMETS_IJK_I")
10224 +          dir=0;
10225 +      else  if (fld.name_=="SOMMETS_IJK_J")
10226 +          dir=1;
10227 +      else if (fld.name_=="SOMMETS_IJK_K")
10228 +          dir=2;
10229 +      else
10230 +          abort();
10231 +      const MEDCoupling::DataArrayDouble* coords=cmesh->getCoordsAt(dir);
10232 +      for (int i=0;i<fld.size_;i++)
10233 +       for (int j=0;j<fld.nb_comp_;j++)
10234 +         {
10235 +           (*data)(i,j)=coords->getIJ(i,j);
10236 +         }
10237 +      mesh->decrRef();
10238 +    }
10239 +  
10240 +  else 
10241 +    {
10242 +      
10243 +      data->resize(fld.size_,fld.nb_comp_);
10244 +     
10245 +      //  if (fld.timestep_==1) iter.first=1;
10246 +      // double t;
10247 +      Nom fieldname=fld.name_;
10248 +      fieldname+="_";
10249 +      fieldname+=fld.localisation_;
10250 +      fieldname+="_";
10251 +      fieldname+=fld.geometry_;
10252 +      
10253 +      int ok=0;
10254 +   
10255 +      vector<string> fields= MEDCoupling::GetAllFieldNamesOnMesh(fld.filename_.getString(),fld.geometry_.getString());
10256 +      
10257 +      for (int f=0;f<fields.size();f++)
10258 +       {
10259 +         if (fieldname==fields[f].c_str())
10260 +           {
10261 +             ok=1;
10262 +             break;
10263 +           }
10264 +       }
10265 +      if (ok==0)
10266 +       {
10267 +         fieldname=fld.name_;
10268 +       }
10269 +      vector<pair<pair<int,int>,double> > vtimes=MEDCoupling::GetAllFieldIterations(fld.filename_.getString(),fieldname.getString());
10270 +
10271 +      int it=fld.timestep_-1;
10272 +      pair <int,int> iter(fld.timestep_-1,-1);
10273 +      if (fld.timestep_==1) it=0;
10274 +      //Cerr<<iter.first <<" 00 "<<vtimes.size()<<finl;
10275 +    
10276 +      iter.first=vtimes[it].first.first;
10277 +      iter.second=vtimes[it].first.second;
10278 +      // Cerr<<"iiii"<<iter.first<<" "<< it<<finl;
10279 +      double t=MEDCoupling::GetTimeAttachedOnFieldIteration(fld.filename_.getString(),fieldname.getString(),iter.first,iter.second);
10280 +        
10281 +      
10282 +      MEDCoupling::TypeOfField type;
10283 +      if (fld.localisation_=="ELEM")
10284 +       type=MEDCoupling::ON_CELLS;
10285 +      else
10286 +       {
10287 +         type=MEDCoupling::ON_NODES;
10288 +         assert(fld.localisation_=="SOM");
10289 +       }
10290 +      MEDCoupling::MEDFileField1TS *  field ;
10291 +      
10292 +       
10293 +      field =  MEDCoupling::MEDFileField1TS::New(fld.filename_.getString(),fieldname.getString(),iter.first,iter.second);
10294 +
10295 +      const MEDCoupling::DataArrayDouble * values=field->getUndergroundDataArray();
10296 +     
10297 +      if (field->getNumberOfComponents()!=fld.nb_comp_)
10298 +       {
10299 +         cerr<<field->getNumberOfComponents()<<" test "<< endl;
10300 +         Journal()<<fieldname<<" not loaded "<<endl;
10301 +       }
10302 +      else
10303 +       {
10304 +         assert(field->getNumberOfComponents()==fld.nb_comp_);
10305 +         const double* ptr=values->getConstPointer();
10306 +         for (int i=0;i<fld.size_;i++)
10307 +           {
10308 +             for (int j=0;j<fld.nb_comp_;j++)
10309 +               {                
10310 +                 (*data)(i,j)=ptr[i*fld.nb_comp_+j];
10311 +               }
10312 +           }
10313 +       }
10314 +      field->decrRef();
10315 +    }
10316 +}
10317 +#endif
10318 diff --git a/databases/readers/Lata/LataFilter.C b/databases/readers/Lata/LataFilter.C
10319 new file mode 100644
10320 index 0000000..5c4a764
10321 --- /dev/null
10322 +++ b/databases/readers/Lata/LataFilter.C
10323 @@ -0,0 +1,1106 @@
10324 +/*****************************************************************************
10325 +*
10326 +* Copyright (c) 2011 - 2013, CEA
10327 +* All rights reserved.
10328 +* Redistribution and use in source and binary forms, with or without
10329 +* modification, are permitted provided that the following conditions are met:
10330 +*
10331 +*     * Redistributions of source code must retain the above copyright
10332 +*       notice, this list of conditions and the following disclaimer.
10333 +*     * Redistributions in binary form must reproduce the above copyright
10334 +*       notice, this list of conditions and the following disclaimer in the
10335 +*       documentation and/or other materials provided with the distribution.
10336 +*     * Neither the name of CEA, nor the
10337 +*       names of its contributors may be used to endorse or promote products
10338 +*       derived from this software without specific prior written permission.
10339 +*
10340 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
10341 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10342 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
10343 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
10344 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
10345 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
10346 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
10347 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
10348 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
10349 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10350 +*
10351 +*****************************************************************************/
10352 +
10353 +#include <iostream>
10354 +#include <fstream>
10355 +#include <stdlib.h>
10356 +#include <stdio.h>
10357 +#include <stdarg.h>
10358 +#include <math.h>
10359 +#include <assert.h>
10360 +#include <LataFilter.h>
10361 +#include <list>
10362 +#include <Static_Int_Lists.h>
10363 +#include <Connectivite_som_elem.h>
10364 +#include <LataDB.h>
10365 +#include <Lata_tools.h>
10366 +#include <Operator.h>
10367 +#include <errno.h>
10368 +#include <UserFields.h>
10369 +#include <string.h>
10370 +static const entier cache_info_level = 5;
10371 +static const entier filter_info_level = 4;
10372 +
10373 +entier LataOptions::read_int_opt(const Nom & s)
10374 +{
10375 +  const char *ptr = strstr(s, "=");
10376 +  if (!ptr) 
10377 +    ptr = s;
10378 +  errno = 0;
10379 +  char *errorptr = 0;
10380 +  entier x = strtol(ptr+1, &errorptr, 0 /* base 10 par defaut */);
10381 +  if (errno || *errorptr != 0) {
10382 +    Journal() << "LataOptions error reading int parameter: " << s << endl;
10383 +    throw;
10384 +  }
10385 +  return x;
10386 +}
10387 +
10388 +double LataOptions::read_float_opt(const Nom & s)
10389 +{
10390 +  const char *ptr = strstr(s, "=");
10391 +  if (!ptr) 
10392 +    ptr = s;
10393 +  errno = 0;
10394 +  char *errorptr = 0;
10395 +  double x = strtod(ptr+1, &errorptr);
10396 +  if (errno || *errorptr != 0) {
10397 +    Journal() << "LataOptions error reading float parameter: " << s << endl;
10398 +    throw;
10399 +  }
10400 +  return x;
10401 +}
10402 +
10403 +Nom LataOptions::read_string_opt(const Nom & s)
10404 +{
10405 +  const char *ptr = strstr(s, "=");
10406 +  if (!ptr) 
10407 +    return s;
10408 +  else
10409 +    return Nom(ptr+1);
10410 +}
10411 +
10412 +Noms extract_list(const Nom & n) 
10413 +{
10414 +  Noms liste;
10415 +  if (n == "")
10416 +    return liste;
10417 +  const char *ptr = n;
10418 +  Nom tmp("");
10419 +  while (*ptr) {
10420 +    if (*ptr == ',') {
10421 +      liste.add(tmp);
10422 +      tmp = "";
10423 +    } else {
10424 +      tmp += Nom(*ptr);
10425 +    }
10426 +  }
10427 +  liste.add(tmp);
10428 +  return liste;
10429 +}
10430 +
10431 +void LataOptions::describe()
10432 +{
10433 +  cerr << "Data processing options (provided by the LataFilter module)" << endl;
10434 +  cerr << " reconnect=tolerance : Find duplicate positions, and redefine connections to use" << endl;
10435 +  cerr << "           always the same positions. tolerance is the maximum distance between" << endl;
10436 +  cerr << "           positions that are considered equal." << endl;
10437 +  cerr << "           Useful for results of parallel runs, where the domain could" << endl;
10438 +  cerr << "           appear fragmented in as many subdomains as procs used." << endl;
10439 +  cerr << "           This operator modifies the loaded domain, does not create a new domain." << endl;
10440 +  cerr << " regularize=tolerance : Try to transform the irregular domain in a ijk domain." << endl;
10441 +  cerr << "            tolerance is the maximum dx, dy or dz between positions that are" << endl;
10442 +  cerr << "            considered to have the same x, y or z." << endl;
10443 +  cerr << "            !Attention! regularize recalculates positions, connections, and fields" << endl;
10444 +  cerr << "            Except in particularly simple cases, you cannot use a regularized domain" << endl;
10445 +  cerr << "            for a field that has not been regularized the same way." << endl;
10446 +  cerr << "            Create a new domain DOM -> DOM_IJK" << endl;
10447 +  cerr << " regularize_polyedre=N : tells how to convert polyedre elements to VTK:" << endl;
10448 +  cerr << "                         N=0 (default): any shape, handled as general VTK_CONVEX_POINT_SET" << endl;
10449 +  cerr << "                         N=1: all elements are extruded in the Z direction (faster and nicer)" << endl;
10450 +  cerr << " ijk_mesh_nb_parts=N : When loading an IJK mesh, automatically split the mesh into" << endl;
10451 +  cerr << "            N blocks (N must be <= number of elements in the K direction, usefull in visit)" << endl;
10452 +  cerr << " invalidate : together with regularize, create \"invalid positions\" and \"invalid connections\"" << endl;
10453 +  cerr << "            components. Otherwise only set the values of the field to zeroes." << endl;
10454 +  cerr << " extend_domain=n : When regularizing, add n nodes in each directions to have a layer" << endl;
10455 +  cerr << "           of invalid positions and connections." << endl;
10456 +  cerr << " dualmesh: Build and export the dual mesh" << endl;
10457 +  cerr << "           (control volume for the velocities in VEF)" << endl;
10458 +  cerr << "           data at faces become data at elements on the dual mesh." << endl;
10459 +  cerr << "           Create a new domain DOM -> DOM_dual" << endl;
10460 +  cerr << " facesmesh: Build and export the faces mesh" << endl;
10461 +  cerr << "           (control volume for the velocities in VEF)" << endl;
10462 +  cerr << "           data at faces become data at elements on the faces mesh." << endl;
10463 +  cerr << "           Create a new domain DOM -> DOM_faces" << endl;
10464 +
10465 +  //cerr << " ncmesh:   Build and export a non-conforming mesh" << endl;
10466 +  //cerr << "           (each mesh element has its proprietary nodes, elements are not topologically connected)" << endl;
10467 +  //cerr << "           face dependent data become position dependent data on the new mesh." << endl;
10468 +  //cerr << "           Create a new domain DOM -> DOM_nc" << endl;
10469 +  cerr << " boundarymesh: Build new domains containing the boundaries only" << endl;
10470 +  cerr << "            Create a new domain DOM -> DOM_Boundary" << endl;
10471 +  //cerr << " clipbox=xmin,ymin,zmin,xmax,ymax,zmax : remove from all meshes all nodes," << endl;
10472 +  //cerr << "           connections and faces outside of this box" << endl;
10473 +  cerr << " load_virtual_elements: Read the VIRTUAL_ELEMENTS data in the input database, if available" << endl
10474 +       << "           and merge nodes, elements and faces to each requested subdomain (using reconnect)" << endl;
10475 +  cerr << "           Does not create a new domain, but modifies the loaded domain" << endl;
10476 +  cerr << " ijk_virt_layer=N: load N layers of virtual elements if domain is ijk in lata file" << endl;
10477 +  cerr << " reconnect_tolerance=: specify tolerance for all reconnect operations" << endl;
10478 +  cerr << "           (reconnection is applied with load_virtual_elements)" << endl;
10479 +  cerr << " user_fields: activate the User_Fields module (WARN: this module is often application specific," << endl;
10480 +  cerr << "           it will fail if some requiered domains/fields are missing in the input database)" << endl;
10481 +  cerr << " export_fields_at_faces: tells to export fields located at faces" << endl;
10482 +  cerr << endl;
10483 +  user_fields_options_.print_help_option();
10484 +}
10485 +
10486 +entier LataOptions::parse_option(const Nom & s)
10487 +{
10488 +  if (s.debute_par("verbosity=")) {
10489 +    entier level = read_int_opt(s);
10490 +    set_Journal_level(level);
10491 +  } else if (s.debute_par("regularize=")) {
10492 +    regularize = true;
10493 +    regularize_tolerance = read_float_opt(s);
10494 +  } else if (s.debute_par("regularize_polyedre=")) {
10495 +    regularize_polyedre = read_int_opt(s);
10496 +  } else if (s.debute_par("extend_domain=")) {
10497 +    extend_domain = read_int_opt(s);
10498 +  } else if (s == "invalidate") {
10499 +    invalidate = true;
10500 +  } else if (s.debute_par("reconnect=")) {
10501 +    reconnect = true;
10502 +    reconnect_tolerance = read_float_opt(s);   
10503 +  } else if (s.debute_par("reconnect_tolerance=")) {
10504 +    reconnect_tolerance = read_float_opt(s);   
10505 +  } else if (s == "dualmesh") {
10506 +    dual_mesh = true;
10507 +  } else if (s == "nodualmesh") {
10508 +    dual_mesh = false;
10509 +  } else if (s == "ncmesh") {
10510 +    nc_mesh = true;
10511 +  } else if (s == "facesmesh") {
10512 +    faces_mesh = true;
10513 +  } else if (s == "nofacesmesh") {
10514 +    faces_mesh = false;
10515 +  } else if (s == "boundarymesh") {
10516 +    boundary_mesh = true;
10517 +  } else if (s.debute_par("clipbox=")) {
10518 +    Noms list = extract_list(((const char*)s)+8);
10519 +    if (list.size() != 6) {
10520 +      Journal() << "Error : clipbox parameters expects 6 values" << endl;
10521 +      throw;
10522 +    }
10523 +    for (entier i = 0; i < 3; i++) {
10524 +      clipbox_min[i] = read_float_opt(list[i]);
10525 +      clipbox_max[i] = read_float_opt(list[i+3]);
10526 +    }
10527 +  } else if (s == "load_virtual_elements") {
10528 +    load_virtual_elements = true;
10529 +  } else if (s == "user_fields") {
10530 +    user_fields_ = true;
10531 +    Journal() << "Option: User_fields ON" << endl;
10532 +  } else if (s.debute_par("ijk_mesh_nb_parts")) {
10533 +    ijk_mesh_nb_parts_ = read_int_opt(s);
10534 +  } else if (s == "export_fields_at_faces") {
10535 +    export_fields_at_faces_ = 1;
10536 +  } else if (s.debute_par("ijk_virt_layer=")) {
10537 +    ijk_virt_layer = read_int_opt(s);
10538 +  } else
10539 +    return user_fields_options_.parse_option(s);;
10540 +  return 1;
10541 +}
10542 +
10543 +void LataFilterCache::set_cache_properties(entier clear_on_tstep_change, BigEntier mem_limit)
10544 +{ 
10545 +  clear_cache_on_tstep_change_ = clear_on_tstep_change;
10546 +  cache_memory_limit_ = mem_limit;
10547 +}
10548 +
10549 +// Description: if an entry with "id" tag and timestep exists in the cache,
10550 +//  returns the entry, otherwise returns a reference to an empty DERIV that
10551 +//  is stored in the cache and stores the associated "id" and timestep.
10552 +//  The entry is locked and given a new last_access_time_ to show that it has
10553 +//  been used recently.
10554 +//  The entry must be released by release_item() when we are finished working
10555 +//  with it.
10556 +LataDeriv<LataObject> & LataFilterCache::get_item_(const Nom & id, entier tstep)
10557 +{
10558 +  entier i;
10559 +  const entier n = data_.size();
10560 +  for (i = 0; i < n; i++) {
10561 +    const DataCacheItem & item = data_[i];
10562 +    if (item.id_ == id && item.tstep_ == tstep)
10563 +      break;
10564 +  }
10565 +  if (i == n) {
10566 +    // Look for an empty slot:
10567 +    for (i = 0; i < n; i++)
10568 +      if (data_[i].id_ == "??")
10569 +        break;
10570 +    // No empty slot: create a new slot:
10571 +    if (i == n)
10572 +      data_.add();
10573 +    DataCacheItem & item = data_[i];
10574 +    item.id_ = id;
10575 +    item.tstep_ = tstep;
10576 +    item.lock_ = 0;
10577 +    Journal(cache_info_level) << "LataFilterCache<C>::get " << id << " (new cache entry " << i << ")." << endl;
10578 +  } else {
10579 +    Journal(cache_info_level) << "LataFilterCache<C>::get " << id << " (existing cache entry " << i << ")." << endl;
10580 +  }
10581 +  // Mark item and lock it:
10582 +  DataCacheItem & item = data_[i];
10583 +  item.last_access_time_ = cache_data_access_count_++;
10584 +  item.lock_++;
10585 +  return item.item_;
10586 +}
10587 +
10588 +
10589 +// Description: tells that if needed the item can be deleted from cache
10590 +//  (there is no reference to it anymore outside of the cache).
10591 +//  We update the memory size of this item here.
10592 +void LataFilterCache::release_item(const Nom & id)
10593 +{
10594 +  Journal(cache_info_level) << "LataFilterCache::release_item " << id << endl;
10595 +  const entier n = data_.size();
10596 +  entier i;
10597 +  for (i = 0; i < n; i++) {
10598 +    const DataCacheItem & item = data_[i];
10599 +    if (item.id_ == id)
10600 +      break;
10601 +  }
10602 +  if (i == n) {
10603 +    Journal() << "LataFilterCache::release_item internal error: unknown item " << id << endl;
10604 +    throw;
10605 +  }
10606 +  if (data_[i].lock_ <= 0) {
10607 +    Journal() << "LataFilterCache::release_item internal error: item is already unlocked" << id << endl;
10608 +    throw;
10609 +  }
10610 +  data_[i].last_access_time_ = cache_data_access_count_++;
10611 +  data_[i].lock_--;
10612 +  if (data_[i].item_.non_nul())
10613 +    data_[i].memory_size_ = data_[i].item_.valeur().compute_memory_size();
10614 +  else
10615 +    data_[i].memory_size_ = 0;
10616 +}
10617 +
10618 +// Description: removes from the cache the oldest items until the total
10619 +//  memory used by the cache is below max_mem_size (in bytes), and
10620 +//  if tstep_to_keep > 0, also removes all timesteps except 0 and tstep_to_keep
10621 +void LataFilterCache::cleanup_cache(entier tstep_to_keep)
10622 +{
10623 +  if (clear_cache_on_tstep_change_ && tstep_to_keep > 0) {
10624 +    Journal(cache_info_level) << "LataFilterCache::clear_cache_tsteps except 0 and " << tstep_to_keep << endl;
10625 +    const entier n = data_.size();
10626 +    for (entier i = 0; i < n; i++) {
10627 +      DataCacheItem & item = data_[i];
10628 +      if (item.id_ != "??") {
10629 +        if (item.tstep_ == 0 || item.tstep_ == tstep_to_keep) {
10630 +          Journal(cache_info_level+1) << " item " << item.id_ << " timestep " << item.tstep_ << " kept" << endl;
10631 +        } else if (item.lock_) {
10632 +          Journal(cache_info_level+1) << " item " << item.id_ << " locked" << endl;
10633 +        } else {
10634 +          Journal(cache_info_level) << " deleting item " << item.id_ << " " << item.tstep_ << endl;
10635 +          item.item_.reset();
10636 +          item.id_ = "??";
10637 +          item.tstep_ = -1;
10638 +        }
10639 +      }
10640 +    }
10641 +  }
10642 +  if (cache_memory_limit_ >= 0) {
10643 +    Journal(cache_info_level) << "LataFilterCache::clear_cache_memory " << cache_memory_limit_ << endl;
10644 +    do {
10645 +      const entier n = data_.size();
10646 +      // Scan cached data, looking for the oldest item and summing up memory
10647 +      BigEntier total_memsize = 0;
10648 +      entier oldest = -1;
10649 +      BigEntier oldest_time = cache_data_access_count_;
10650 +      for (entier i = 0; i < n; i++) {
10651 +        const DataCacheItem & item = data_[i];
10652 +        if (item.id_ != "??") {
10653 +          total_memsize += item.memory_size_;
10654 +          if (!item.lock_ && item.last_access_time_ < oldest_time) {
10655 +            oldest_time = item.last_access_time_;
10656 +            oldest = i;
10657 +          }
10658 +        }
10659 +      }
10660 +      if (oldest < 0 || total_memsize < cache_memory_limit_) 
10661 +        break;
10662 +      
10663 +      DataCacheItem & item = data_[oldest];
10664 +      Journal(cache_info_level) << " deleting item " << item.id_ << " " << item.tstep_ << endl;
10665 +      item.item_.reset();
10666 +      item.id_ = "??";
10667 +      item.tstep_ = -1;
10668 +    } while(1);
10669 +  }
10670 +}
10671 +
10672 +// Description: Cleanup everything, associate the lata_db and fills metadata information.
10673 +void LataFilter::initialize(const LataOptions & opt, const LataDB & lata_db)
10674 +{
10675 +  opt_ = opt;
10676 +  data_cache_.reset();
10677 +  lataDB__ = &lata_db;
10678 +  if (opt_.user_fields_) {
10679 +    user_fields_.instancie(UserFields);
10680 +    user_fields_.valeur().set_options(opt_.user_fields_options_);
10681 +  }
10682 +
10683 +  get_all_metadata(geoms_metadata_, fields_metadata_);
10684 +}
10685 +
10686 +void LataFilter::set_cache_properties(BigEntier max_memory, const entier keep_all_timesteps)
10687 +{
10688 +  data_cache_.set_cache_properties(!keep_all_timesteps, max_memory);
10689 +}
10690 +
10691 +// Description: Return the number of timesteps in the database
10692 +//   (=number of physical timesteps + one containing global definitions at timestep 0)
10693 +entier LataFilter::get_nb_timesteps() const
10694 +{
10695 +  return lataDB().nb_timesteps();
10696 +}
10697 +
10698 +// Description: Return the physical time for this timestep.
10699 +//  returns -1.0 for timestep 0 (global definitions)
10700 +double LataFilter::get_timestep(entier i) const
10701 +{
10702 +  if (i == 0)
10703 +    return -1.0;
10704 +  else
10705 +    return lataDB().get_time(i);
10706 +}
10707 +
10708 +static void add_fields_to_metadata_list(const LataDB & lataDB, 
10709 +                                        const Nom & lata_geom, 
10710 +                                        const Nom & dest_geom, 
10711 +                                        const Nom & options,
10712 +                                        entier dim,
10713 +                                        LataVector<LataFieldMetaData> & fields_data,
10714 +                                        const Motcle & source,
10715 +                                        const Nom & source_domain)
10716 +{
10717 +  if (lataDB.nb_timesteps()<2) return;
10718 +  // Query for existing fields in the latadb :
10719 +  Field_UNames lata_fields = lataDB.field_unames(1, lata_geom, "*", LataDB::FIRST_AND_CURRENT);
10720 +  const entier nb_fields = lata_fields.size();
10721 +  for (entier i_field = 0; i_field < nb_fields; i_field++) {
10722 +    const LataDBField & lata_field = lataDB.get_field(1, lata_fields[i_field], LataDB::FIRST_AND_CURRENT);
10723 +    LataField_base::Elem_som loc = LataField_base::localisation_from_string(lata_field.localisation_);
10724 +
10725 +    // Hidden special fields
10726 +    if (Motcle(lata_field.name_) == "INVALID_CONNECTIONS")
10727 +      continue;
10728 +   if (Motcle(lata_field.name_) == "ELEMENTS")
10729 +      continue;
10730 +   if (Motcle(lata_field.name_) == "FACES")
10731 +      continue;
10732 +   if (Motcle(lata_field.name_) == "ELEM_FACES")
10733 +     continue;
10734 +    LataFieldMetaData data;
10735 +    data.name_ = lata_field.name_;
10736 +    data.geometry_name_ = dest_geom;
10737 +    data.component_names_ = lata_field.component_names_;
10738 +    data.nb_components_ = lata_field.nb_comp_;
10739 +    data.source_localisation_ = lata_field.localisation_;
10740 +
10741 +    if (options.find("to_vector")>=0) {
10742 +      data.is_vector_ = 1;
10743 +      data.nb_components_ = dim;
10744 +    } else 
10745 +      data.is_vector_ = (lata_field.nature_ == LataDBField::VECTOR);
10746 +
10747 +    if (options.find("to_elem")>=0)
10748 +      data.localisation_ = LataField_base::ELEM;
10749 +    else if (options.find("to_som")>=0)
10750 +      data.localisation_ = LataField_base::SOM;
10751 +    else if (options.find("to_faces")>=0)
10752 +      data.localisation_ = LataField_base::FACES;
10753 +    else
10754 +      data.localisation_ = loc;
10755 +
10756 +    data.source_ = source;
10757 +    data.uname_ = Field_UName(data.geometry_name_, 
10758 +                              data.name_, 
10759 +                              LataField_base::localisation_to_string(data.localisation_));
10760 +    data.source_field_ = Field_UName(source_domain,
10761 +                                     data.name_,
10762 +                                     lata_fields[i_field].get_localisation());
10763 +
10764 +    if ((loc == LataField_base::ELEM && options.find("from_elem")>=0)
10765 +        || (loc == LataField_base::SOM && options.find("from_som")>=0)
10766 +        || (loc == LataField_base::FACES && options.find("from_faces")>=0)) {
10767 +      Journal(filter_info_level) << " register field metadata: " << data.uname_ << endl;
10768 +      fields_data.add(data);
10769 +    }
10770 +  }
10771 +}
10772 +
10773 +// Process the content of the source LataDB structure and builds the metadata for
10774 +//  all geometries and fields that the filter can export (depending on options,
10775 +//  for example, provide dual mesh geometry and fields only if dualmesh option is on).
10776 +void LataFilter::get_all_metadata(LataVector<LataGeometryMetaData> & geoms_data, LataVector<LataFieldMetaData> & fields_data)
10777 +{
10778 +  geoms_data.reset();
10779 +  fields_data.reset();
10780 +  entier current_tstep = 1;
10781 +  // If no real timestep, just check timestep 0
10782 +  if (lataDB().nb_timesteps() < 2)
10783 +    current_tstep = 0;
10784 +  Noms lata_geoms_names = lataDB().geometry_names(current_tstep, LataDB::FIRST_AND_CURRENT);
10785 +  const entier nb_geoms = lata_geoms_names.size();
10786 +  for (entier i_geom = 0; i_geom < nb_geoms; i_geom++) {
10787 +    // Name of the current geometry (from lataDB)
10788 +    const Nom & lata_geom_name = lata_geoms_names[i_geom];
10789 +    const LataDBGeometry & lata_geom = lataDB().get_geometry(current_tstep, lata_geom_name, LataDB::FIRST_AND_CURRENT);
10790 +    // Query properties from LataDB:
10791 +    // Is it a dynamic mesh ?
10792 +    const entier dynamic = lata_geom.timestep_ > 0;
10793 +    // Element type ?
10794 +    Domain::Element element_type = Domain::element_type_from_string(lata_geom.elem_type_);
10795 +    // Query for dimension
10796 +    const entier domain_already_ijk = lataDB().field_exists(current_tstep, lata_geom_name, "SOMMETS_IJK_I", LataDB::FIRST_AND_CURRENT);
10797 +
10798 +    // Do we have faces ?
10799 +    const entier have_faces = 
10800 +      domain_already_ijk ||
10801 +      (lataDB().field_exists(current_tstep, lata_geom_name, "FACES", LataDB::FIRST_AND_CURRENT)
10802 +       && lataDB().field_exists(current_tstep, lata_geom_name, "ELEM_FACES", LataDB::FIRST_AND_CURRENT));
10803 +
10804 +    entier dim = 1;
10805 +    // Query for number of blocks in the lata file:
10806 +    entier nblocks = 1;
10807 +    if (domain_already_ijk) {
10808 +      if (lataDB().field_exists(current_tstep, lata_geom_name, "SOMMETS_IJK_K", LataDB::FIRST_AND_CURRENT))
10809 +        dim = 3;
10810 +      else
10811 +        dim = 2;
10812 +      nblocks = opt_.ijk_mesh_nb_parts_;
10813 +      Nom nom_sommets;
10814 +      if (dim == 2)
10815 +        nom_sommets = "SOMMETS_IJK_J";
10816 +      else
10817 +        nom_sommets = "SOMMETS_IJK_K";
10818 +      const LataDBField & coord = lataDB().get_field(current_tstep, lata_geom_name, nom_sommets, "", LataDB::FIRST_AND_CURRENT);
10819 +      // Nombre d'elements dans la direction du decoupage parallele:
10820 +      const entier nelem = coord.size_ - 1;
10821 +      // Si les tranches sont trop petites diminuer le nombre de blocs
10822 +      if (nblocks > (nelem + 3) / 4)
10823 +        nblocks = (nelem + 3) / 4;
10824 +    } else {
10825 +      dim = lataDB().get_field(current_tstep, lata_geom_name, "SOMMETS", "*", LataDB::FIRST_AND_CURRENT).nb_comp_;
10826 +      if (lataDB().field_exists(current_tstep, lata_geom_name, "JOINTS_SOMMETS", LataDB::FIRST_AND_CURRENT))
10827 +        nblocks = lataDB().get_field(current_tstep, lata_geom_name, "JOINTS_SOMMETS", "*", LataDB::FIRST_AND_CURRENT).size_;
10828 +    }
10829 +
10830 +    // Initialize data common to all domains:
10831 +    LataGeometryMetaData data;
10832 +    data.dynamic_ = dynamic;
10833 +    data.dimension_ = dim;
10834 +    data.element_type_ = element_type;
10835 +    data.is_ijk_=domain_already_ijk;
10836 +     
10837 +    // If we reconnect all subdomains, always load all of them:
10838 +    if (!opt_.reconnect)
10839 +      data.nblocks_ = nblocks;
10840 +    else
10841 +      data.nblocks_ = 1;
10842 +
10843 +    data.internal_name_ = lata_geom_name;
10844 +    data.displayed_name_ = lata_geom_name;
10845 +    
10846 +    Nom separ("boundaries_");
10847 +    int m=data.displayed_name_.find(separ);
10848 +    if (m>0)
10849 +      {
10850 +       const Nom& name= data.displayed_name_;
10851 +       // on remplace boundaries_ par boundaries/
10852 +       const char* jj =name;
10853 +       Nom disp(name);
10854 +       disp.prefix(jj+m-1);
10855 +       // GF le nom du domaine existe t il siuoi on a peut etre postraite sur un bord
10856 +       if  (lata_geoms_names.rang(disp)>-1)
10857 +         {
10858 +           Nom bord(jj+m+separ.longueur()-1);
10859 +           disp+=Nom("_boundaries/");
10860 +           disp+=bord;
10861 +           data.displayed_name_=disp;
10862 +         }
10863 +      }
10864 +    //   cerr<< data.displayed_name_<<endl;
10865 +    data.source_ = "latadb";
10866 +    Journal(filter_info_level) << " metadata: adding geometry " << lata_geom_name << " displayed name=" << data.displayed_name_ << endl;
10867 +    geoms_data.add(data);
10868 +    // Add fields at som and elem:
10869 +    add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
10870 +                                "from_elem,from_som,from_faces", dim, fields_data,
10871 +                                "latadb",
10872 +                                "??");
10873 +    // It is regularizable ?
10874 +    entier regularizable = (((element_type == Domain::quadri)&&(data.dimension_==2)) || ((element_type == Domain::hexa)&&(data.dimension_==3)))
10875 +      && (lata_geom.elem_type_ != "HEXAEDRE_AXI") && (lata_geom.elem_type_ != "RECTANGLE_AXI");
10876 +    Journal(filter_info_level) << " metadata: geometry " << lata_geom_name << " element type says regularizable=" << regularizable << endl;
10877 +    if (regularizable && ((opt_.regularize_tolerance < 0) || (!opt_.regularize))) {
10878 +      regularizable = 0;
10879 +      Journal(filter_info_level) << " regularize option not set: don't build ijk domain" << endl;
10880 +    }
10881 +    if (regularizable && domain_already_ijk) {
10882 +      regularizable = 0;
10883 +      Journal(filter_info_level) << " domain is already IJK: do not regularize" << endl;
10884 +    }
10885 +
10886 +    // opt_.regularize == 2 means: provide ijk only if faces are present
10887 +    if (regularizable && opt_.regularize == 2) {
10888 +      if (!have_faces) {
10889 +        Journal(filter_info_level) << " regularize option==2 and no faces => do not regularize" << endl;
10890 +        regularizable = 0;
10891 +      }
10892 +    }
10893 +    if (regularizable) {
10894 +      data.internal_name_ = lata_geom_name;
10895 +      data.internal_name_ += "_IJK";
10896 +      data.is_ijk_=1;
10897 +      data.displayed_name_ = lata_geom_name;
10898 +      data.source_ = "operator_ijk";
10899 +      data.source_domain_ = lata_geom_name;
10900 +      geoms_data.add(data);
10901 +      Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl;
10902 +      // Add fields at som and elem:
10903 +      add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
10904 +                                  "from_elem,from_som,from_faces", dim, fields_data,
10905 +                                  "operator_ijk",
10906 +                                  data.source_domain_);
10907 +    }
10908 +
10909 +    // Provide dual mesh
10910 +    if (opt_.dual_mesh && have_faces) {
10911 +      data.internal_name_ = lata_geom_name;
10912 +      
10913 +      // If it's quadri or hexa, we need the regular mesh
10914 +      data.source_domain_ = data.internal_name_;
10915 +      if (regularizable) {
10916 +        data.internal_name_ += "_IJK";
10917 +        data.source_domain_ += "_IJK";
10918 +       data.is_ijk_=1;
10919 +      }
10920 +      data.internal_name_ += "_dual";
10921 +      data.displayed_name_ += "_dual";
10922 +
10923 +      data.source_ = "operator_dual";
10924 +      geoms_data.add(data);
10925 +      Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl;
10926 +      // Add fields at faces, localisation will be at elements,
10927 +      //  forced to vector type if vdf:
10928 +      Nom options("from_faces,to_elem");
10929 +      if (regularizable)
10930 +        options += ",to_vector";
10931 +      add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
10932 +                                  options, dim, fields_data,
10933 +                                  "operator_dual",
10934 +                                  data.source_domain_);      
10935 +    }
10936 +
10937 +    // Provide nc mesh if possible
10938 +    if (opt_.nc_mesh && have_faces && !regularizable /* doesn't work for vdf */) {
10939 +      data.internal_name_ = lata_geom_name;
10940 +      data.internal_name_ += "_nc";
10941 +      data.displayed_name_ = data.internal_name_;
10942 +      data.source_ = "operator_nc";
10943 +      data.source_domain_ = lata_geom_name;
10944 +      geoms_data.add(data);
10945 +      Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl;
10946 +      // Add fields at faces, localisation will be at nodes
10947 +      Nom options("from_faces,to_som");
10948 +      add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
10949 +                                  options, dim, fields_data,
10950 +                                  "operator_nc",
10951 +                                  data.source_domain_);
10952 +    }
10953 +    // Provide faces mesh if possible
10954 +    if (opt_.faces_mesh && have_faces && !regularizable /* doesn't work for vdf */ &&  !(domain_already_ijk) ) {
10955 +   
10956 +      data.internal_name_ = lata_geom_name;
10957 +      data.internal_name_ += "_centerfaces";
10958 +      data.displayed_name_ = data.internal_name_;
10959 +      data.source_ = "operator_faces";
10960 +      data.source_domain_ = lata_geom_name;
10961 +      if (data.element_type_ == Domain::triangle)
10962 +        data.element_type_=Domain::line;
10963 +      else if ( data.element_type_ == Domain::tetra)
10964 +        data.element_type_=Domain::triangle;
10965 +
10966 +      geoms_data.add(data);
10967 +      Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl;
10968 +      // Add fields at faces, localisation will be at nodes
10969 +      Nom options("from_faces,to_elem");
10970 +      add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
10971 +                                  options, dim, fields_data,
10972 +                                  "operator_faces",
10973 +                                  data.source_domain_);
10974 +    }
10975 +    // Provide boundary mesh
10976 +    if (opt_.boundary_mesh && (element_type == Domain::hexa || element_type == Domain::tetra)) {
10977 +      data.internal_name_ = lata_geom_name;
10978 +      data.internal_name_ += "_Boundary";
10979 +      data.displayed_name_ = data.internal_name_;
10980 +      data.source_ = "operator_boundary";
10981 +      data.source_domain_ = lata_geom_name;
10982 +      geoms_data.add(data);
10983 +      Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl;
10984 +      Nom options("from_elem,from_som");
10985 +      add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
10986 +                                  options, dim, fields_data,
10987 +                                  "operator_boundary",
10988 +                                  data.source_domain_);
10989 +      options = "from_faces,to_elem";
10990 +      add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_,
10991 +                                  options, dim, fields_data,
10992 +                                  "operator_boundary",
10993 +                                  data.source_domain_);
10994 +    }
10995 +  }
10996 +
10997 +  if (user_fields_.non_nul())
10998 +    user_fields_.valeur().new_fields_metadata(*this, fields_data);
10999 +}
11000 +
11001 +// Description: Return a list of domain names available from get_geometry_metadata()
11002 +//  and that we want to show to the user.
11003 +//  This includes the domains loaded from the lata file plus new constructed domains
11004 +//  (nc_mesh, dual_mesh, boundary_mesh, etc) if requested in options and if available
11005 +//  (depending if requiered data (eg faces, ...)
11006 +Noms LataFilter::get_exportable_geometry_names() const
11007 +{
11008 +  Noms names;
11009 +  entier i;
11010 +  for (i = 0; i < geoms_metadata_.size(); i++)
11011 +    names.add(geoms_metadata_[i].internal_name_);
11012 +
11013 +  // If an IJK domain is here, don't show the original domain:
11014 +  Noms names2;
11015 +  for (i = 0; i < names.size(); i++) {
11016 +    Nom n(names[i]);
11017 +    n += "_IJK";
11018 +    if (names.rang(n) < 0)
11019 +      names2.add(names[i]);
11020 +  }
11021 +  return names2;
11022 +}
11023 +
11024 +// Description: the same, with field names...
11025 +//  If geometry=="*", returns all fields
11026 +//  Currently, doesn't show fields located at faces...
11027 +Field_UNames LataFilter::get_exportable_field_unames(const char * geometry) const
11028 +{
11029 +  Field_UNames unames;
11030 +  Motcle geom(geometry);
11031 +  for (entier i = 0; i < fields_metadata_.size(); i++)
11032 +    if (geom == fields_metadata_[i].geometry_name_ || geom == "*") 
11033 +      // Do not show faces located fields to the user...
11034 +      if (fields_metadata_[i].localisation_ != LataField_base::FACES || opt_.export_fields_at_faces_)
11035 +        unames.add(fields_metadata_[i].uname_);
11036 +
11037 +  return unames;
11038 +}
11039 +
11040 +// Description: fill "data" for the requested "geometry". "geometry" must be a name
11041 +//  returned by get_exportable_geometry_names()
11042 +const LataGeometryMetaData & LataFilter::get_geometry_metadata(const char * geometry) const
11043 +{
11044 +  Motcle geom(geometry);
11045 +  for (entier i = 0; i < geoms_metadata_.size(); i++)
11046 +    if (geom == geoms_metadata_[i].internal_name_)
11047 +      return geoms_metadata_[i];
11048 +
11049 +  Journal() << "Error in LataFilter::get_geometry_metadata: unknown geometry " << geometry << endl;
11050 +  throw LataError(LataError::INVALID_DOMAIN,"unknown geometry");
11051 +  return geoms_metadata_[0];
11052 +}
11053 +
11054 +// Description: fill "data" for the requested "geometry/field". "geometry"  and "field" must be names
11055 +//  returned by get_exportable_geometry_names() and get_exportable_field_names()
11056 +const LataFieldMetaData & LataFilter::get_field_metadata(const Field_UName & uname) const
11057 +{
11058 +  for (entier i = 0; i < fields_metadata_.size(); i++)
11059 +    if (fields_metadata_[i].uname_ == uname)
11060 +      return fields_metadata_[i];
11061 +  
11062 +  Journal() << "Error in LataFilter::get_field_metadata: unknown field " << uname << endl;
11063 +  throw LataError(LataError::INVALID_COMPONENT,"unknown field");
11064 +  return fields_metadata_[0];
11065 +}
11066 +
11067 +// Description: 
11068 +//  Returns a reference to the requested geometry.
11069 +//  If the geometry is not found at the requested timestep, it
11070 +//  is seached in the first timestep.
11071 +//  If the geometry does not exist in the cache, all needed data is loaded
11072 +//   and the geometry is allocated and built in the internal cache.
11073 +//  The reference is valid until the user calls release_geometry()
11074 +//  The user MUST call release_geometry() to allow the data to be
11075 +//   removed from the data cache.
11076 +const Domain & LataFilter::get_geometry(const Domain_Id & id)
11077 +{
11078 +  Journal(filter_info_level) << "LataFilter::get_geometry " 
11079 +                             << id.name_ << " time=" << id.timestep_ 
11080 +                             << " bloc=" << id.block_ << endl;
11081 +  data_cache_.cleanup_cache(id.timestep_);
11082 +
11083 +  Domain_Id requested_id(id);
11084 +  // Get the real timestep where this domain is stored:
11085 +  const LataGeometryMetaData & geom_metadata = get_geometry_metadata(id.name_);
11086 +  if (geom_metadata.dynamic_) 
11087 +    requested_id.timestep_ = id.timestep_;
11088 +  else
11089 +    requested_id.timestep_ = 0;
11090 +
11091 +  LataDeriv<Domain> & dom_ptr = get_cached_domain(requested_id);
11092 +  if (!dom_ptr.non_nul()) {
11093 +    if (geom_metadata.source_ == "latadb") {
11094 +      // Request for a native domain : load it from lataDB
11095 +      // If reconnect and loading all subdomains, go ! Don't store the operator in cache since it's
11096 +      //  not required to process fields.
11097 +      
11098 +      // Is it a structured or unstructured mesh ?
11099 +      if (lataDB().field_exists(requested_id.timestep_, requested_id.name_, "SOMMETS")) 
11100 +        {
11101 +          DomainUnstructured & dom = dom_ptr.instancie(DomainUnstructured);
11102 +      
11103 +          if (opt_.reconnect) {
11104 +            // Bloc demande, peut etre le bloc 0 ou le bloc -1:
11105 +            const entier req_block = requested_id.block_;
11106 +            if (requested_id.block_ > 0) {
11107 +              Cerr << "Error: requesting block " << requested_id.block_ << " with reconnect option" << endl;
11108 +             throw;
11109 +            }
11110 +            requested_id.block_ = -1; // load all blocks
11111 +            dom.fill_domain_from_lataDB(lataDB(), requested_id, 1 /* faces */, 0);
11112 +            Reconnect::reconnect_geometry(dom, opt_.reconnect_tolerance);
11113 +            dom.id_.block_ = req_block;
11114 +          } else {
11115 +            dom.fill_domain_from_lataDB(lataDB(), requested_id, 1 /* faces */, opt_.load_virtual_elements ? 1 : 0);
11116 +            if (opt_.load_virtual_elements && dom.nb_virt_items(LataField_base::ELEM) > 0) {
11117 +              Reconnect::reconnect_geometry(dom, opt_.reconnect_tolerance,
11118 +                                            dom.nb_nodes() - dom.nb_virt_items(LataField_base::SOM));
11119 +            }
11120 +          }
11121 +        }
11122 +      else
11123 +        {
11124 +          // Structured ijk:
11125 +          DomainIJK & dom = dom_ptr.instancie(DomainIJK);
11126 +          if (opt_.reconnect || requested_id.block_ < 0) {
11127 +            dom.fill_domain_from_lataDB(lataDB(), requested_id, 1 /* parallel splitting */, 
11128 +                                        0 /* no virtual elements */);
11129 +          } else {
11130 +            const entier nparts = opt_.ijk_mesh_nb_parts_;
11131 +            const entier virtual_size = opt_.load_virtual_elements ? opt_.ijk_virt_layer : 0;
11132 +            dom.fill_domain_from_lataDB(lataDB(), requested_id, nparts /* parallel splitting */, 
11133 +                                        virtual_size /* with virtual elements */);
11134 +          }
11135 +        }
11136 +    } else if (geom_metadata.source_.debute_par("OPERATOR")) {
11137 +      const Domain & src_domain = get_geometry(Domain_Id(geom_metadata.source_domain_, 
11138 +                                                         requested_id.timestep_,
11139 +                                                         requested_id.block_));
11140 +      Operator & op = get_set_operator(requested_id);
11141 +      op.build_geometry(src_domain, dom_ptr);
11142 +      dom_ptr.valeur().id_ = requested_id;
11143 +      release_cached_operator(requested_id);
11144 +      release_geometry(src_domain);
11145 +    } else {
11146 +      Journal() << "Unknown source in geometry metadata " << geom_metadata.source_ << endl;
11147 +      throw;
11148 +    }
11149 +  }
11150 +
11151 +  return dom_ptr.valeur();
11152 +}
11153 +
11154 +Operator & LataFilter::get_set_operator(const Domain_Id & id)
11155 +{
11156 +  LataDeriv<Operator> & op_ptr  = get_cached_operator(id);
11157 +  if (!op_ptr.non_nul()) {
11158 +    // Operator not in the cache ? Build it:
11159 +    if (id.name_.finit_par("_IJK")) {
11160 +      OperatorRegularize & op = op_ptr.instancie(OperatorRegularize);
11161 +      op.set_tolerance(opt_.regularize_tolerance);
11162 +      op.set_extend_layer(opt_.extend_domain);
11163 +    } else if (id.name_.finit_par("_dual")) {
11164 +      op_ptr.instancie(OperatorDualMesh);
11165 +    } else if (id.name_.finit_par("_Boundary")) {
11166 +      op_ptr.instancie(OperatorBoundary);
11167 +    } else if (id.name_.finit_par("_centerfaces")) {
11168 +      op_ptr.instancie(OperatorFacesMesh);
11169 +    } else {
11170 +      Journal() << "Internal error in LataFilter::get_operator: forgot to implement operator choice for " << id.name_ << endl;
11171 +      throw;
11172 +    }
11173 +  }
11174 +  return op_ptr.valeur();
11175 +}
11176 +
11177 +
11178 +// Description: returns the requested field, computing it if it is not
11179 +//  already in the cache. You MUST call release_field() on the returned field
11180 +//  when you don't need it any more...
11181 +//  See also class Field_Id
11182 +const LataField_base & LataFilter::get_field(const Field_Id & id)
11183 +{
11184 +  Journal(filter_info_level) << "LataFilter::get_field " 
11185 +                             << id.uname_ << " time=" << id.timestep_ 
11186 +                             << " bloc=" << id.block_ << endl;
11187 +
11188 +  data_cache_.cleanup_cache(id.timestep_);
11189 +
11190 +  const LataFieldMetaData & field_metadata = get_field_metadata(id.uname_);
11191 +
11192 +  LataDeriv<LataField_base> & field_ptr = get_cached_field(id);
11193 +  if (!field_ptr.non_nul()) {
11194 +    if (field_metadata.source_ == "latadb") {
11195 +      // Request for a native field : load it from lataDB
11196 +      const Domain & dom = get_geometry(id);
11197 +      dom.fill_field_from_lataDB(lataDB(), id, field_ptr);
11198 +      release_geometry(dom);
11199 +    } else if (field_metadata.source_.debute_par("OPERATOR")) {
11200 +      const Field_Id src_id(field_metadata.source_field_,
11201 +                            id.timestep_,
11202 +                            id.block_);
11203 +      const Domain & src_domain = get_geometry(src_id);
11204 +      const LataField_base & src_field = get_field(src_id);
11205 +      const Domain & dest_domain = get_geometry(id);
11206 +      Operator & op = get_set_operator(dest_domain.id_);
11207 +      op.build_field(src_domain, src_field, dest_domain, field_ptr);
11208 +      field_ptr.valeur().id_ = Field_Id(field_metadata.uname_, src_field.id_.timestep_, src_field.id_.block_);
11209 +      release_field(src_field);
11210 +      release_geometry(src_domain);
11211 +      release_geometry(dest_domain);
11212 +      release_cached_operator(dest_domain.id_);
11213 +    } else if (field_metadata.source_ == "user_fields") {
11214 +      Field<FloatTab> & f = field_ptr.instancie(Field<FloatTab> );
11215 +      f = user_fields_.valeur().get_field(id);
11216 +      // Force field id to correct value:
11217 +      f.id_ = id;
11218 +      f.component_names_ = field_metadata.component_names_;
11219 +      f.nature_ = field_metadata.is_vector_ ? LataDBField::VECTOR : LataDBField::SCALAR;
11220 +      f.localisation_ = field_metadata.localisation_;
11221 +    }
11222 +  }
11223 +
11224 +  return field_ptr.valeur();
11225 +}
11226 +
11227 +// Description: returns the requested float field, computing it if it is not
11228 +//  already in the cache. You MUST call release_field() on the returned field
11229 +//  when you don't need it any more...
11230 +//  See also class Field_Id
11231 +const FieldFloat & LataFilter::get_float_field(const Field_Id & id) 
11232 +{
11233 +  const LataField_base & field = get_field(id);
11234 +  const FieldFloat * float_field_ptr = dynamic_cast<const FieldFloat*>(&field);
11235 +  if (! float_field_ptr) { /*assert(! float_field_ptr);*/ throw LataError(LataError::INVALID_COMPONENT,"unknown field");}
11236 +  const FieldFloat & fld = *float_field_ptr;
11237 +  return fld;
11238 +}
11239 +void LataFilter::release_geometry(const Domain & dom)
11240 +{
11241 +  Journal(filter_info_level) << "LataFilter::release_geometry " 
11242 +                             << dom.id_.name_ << " time=" << dom.id_.timestep_ 
11243 +                             << " bloc=" << dom.id_.block_ << endl;
11244 +  release_cached_domain(dom.id_);
11245 +}
11246 +
11247 +void LataFilter::release_field(const LataField_base & field)
11248 +{
11249 +  Journal(filter_info_level) << "LataFilter::release_field " 
11250 +                             << field.id_.uname_ << " time=" << field.id_.timestep_ 
11251 +                             << " bloc=" << field.id_.block_ << endl;
11252 +  release_cached_field(field.id_);
11253 +}
11254 +  
11255 +void build_mangeld_domain_name(const Domain_Id & id, Nom & name)
11256 +{
11257 +  name = id.name_;
11258 +  name += "_";
11259 +  name += Nom(id.timestep_);
11260 +  name += "_";
11261 +  name += Nom(id.block_);
11262 +  name.majuscule();
11263 +}
11264 +
11265 +void build_mangeld_field_name(const Field_Id & id, Nom & name)
11266 +{
11267 +  name = id.uname_.build_string();
11268 +  name += "_";
11269 +  name += Nom(id.timestep_);
11270 +  name += "_";
11271 +  name += Nom(id.block_);
11272 +  name.majuscule();
11273 +}
11274 +
11275 +LataDeriv<LataField_base> & LataFilter::get_cached_field(const Field_Id& id)
11276 +{
11277 +  Nom n;
11278 +  build_mangeld_field_name(id, n);
11279 +  return data_cache_.get_item<LataDeriv<LataField_base> >(n, id.timestep_);
11280 +}
11281 +LataDeriv<Domain> &     LataFilter::get_cached_domain(const Domain_Id& id)
11282 +{
11283 +  Nom n;
11284 +  build_mangeld_domain_name(id, n);
11285 +  return data_cache_.get_item<LataDeriv<Domain> >(n, id.timestep_);
11286 +}
11287 +LataDeriv<Operator> &   LataFilter::get_cached_operator(const Domain_Id& id)
11288 +{
11289 +  Nom n;
11290 +  build_mangeld_domain_name(id, n);
11291 +  n += "_OP";
11292 +  return data_cache_.get_item<LataDeriv<Operator> >(n, id.timestep_);  
11293 +}
11294 +void LataFilter::release_cached_domain(const Domain_Id& id)
11295 +{
11296 +  Nom n;
11297 +  build_mangeld_domain_name(id, n);
11298 +  data_cache_.release_item(n);
11299 +}
11300 +void LataFilter::release_cached_field(const Field_Id& id)
11301 +{
11302 +  Nom n;
11303 +  build_mangeld_field_name(id, n);
11304 +  data_cache_.release_item(n);
11305 +}
11306 +void LataFilter::release_cached_operator(const Domain_Id& id)
11307 +{
11308 +  Nom n;
11309 +  build_mangeld_domain_name(id, n);
11310 +  n += "_OP";
11311 +  data_cache_.release_item(n);  
11312 +}
11313 +
11314 +void LataOptions::extract_path_basename(const char * s, Nom & path_prefix, Nom & basename)
11315 +{
11316 +  int i;
11317 +  for (i=(int)strlen(s)-1;i>=0;i--)
11318 +    if ((s[i]==PATH_SEPARATOR) ||(s[i]=='\\'))
11319 +      break;
11320 +  path_prefix = "";
11321 +  int j;
11322 +  for (j = 0; j <= i; j++)
11323 +    path_prefix += Nom(s[j]);
11324 +  
11325 +  // Parse basename : if extension given, remove it
11326 +  int n = (int)strlen(s);
11327 +  if (n > 5 && strcmp(s+n-5,".lata") == 0)
11328 +    n -= 5;
11329 +  basename = "";
11330 +  for (j = i+1; j < n; j++)
11331 +    basename += Nom(s[j]);
11332 +  //  Journal(9)<<" prefix "<<path_prefix<< " "<<i<<endl;
11333 +}
11334 +
11335 +LataOptions::LataOptions()
11336 +{
11337 +  dual_mesh = false;
11338 +  faces_mesh=false;
11339 +  nc_mesh = false;
11340 +  boundary_mesh = false;
11341 +  reconnect = false;
11342 +  reconnect_tolerance = 1e-6;
11343 +  regularize = false;
11344 +  extend_domain = 0;
11345 +  regularize_tolerance = 1e-6;
11346 +  invalidate = false;
11347 +  load_virtual_elements = false;
11348 +  user_fields_ = false;
11349 +  ijk_mesh_nb_parts_ = 1;
11350 +  ijk_virt_layer = 1;
11351 +  export_fields_at_faces_ = 0;
11352 +  regularize_polyedre=0;
11353 +}
11354 +
11355 +void build_geometry_(Operator & op, const Domain & src, LataDeriv<Domain> & dest)
11356 +{
11357 +  Journal() << "Error in an operator: build_geometry not coded for this Operator/Domain" << endl;
11358 +  throw;
11359 +}
11360 +
11361 +void build_field_(Operator & op, const Domain & src, const Domain & dest, 
11362 +                  const LataField_base & srcf, LataField_base & destf)
11363 +{
11364 +  Journal() << "Error in an operator: build_field not coded for this Operator/Domain/Field" << endl;
11365 +  throw;  
11366 +}
11367 +
11368 +void LataDB_apply_input_filter(const LataDB & lata_db, LataDB & filtered_db, 
11369 +                        const ArrOfInt & input_timesteps_filter,
11370 +                        const Noms & input_domains_filter,
11371 +                        const Noms & input_components_filter)
11372 +{
11373 +  ArrOfInt timesteps_filter(input_timesteps_filter);
11374 +  Noms domains_filter(input_domains_filter);
11375 +  Noms components_filter(input_components_filter);
11376 +
11377 +  // Build a list of all available geometries and components
11378 +  Noms list_all_domains = lata_db.geometry_names(lata_db.nb_timesteps()-1, LataDB::FIRST_AND_CURRENT);
11379 +  Noms list_all_fields;
11380 +  {
11381 +    Field_UNames fields = lata_db.field_unames(lata_db.nb_timesteps()-1, "*", "*", LataDB::FIRST_AND_CURRENT);
11382 +    for (entier i = 0; i < fields.size(); i++) {
11383 +      const Nom & n = fields[i].get_field_name();
11384 +      if (list_all_fields.rang(n) < 0)
11385 +        list_all_fields.add(n);
11386 +    }
11387 +  }
11388 +
11389 +  if (timesteps_filter.size_array() == 0) {
11390 +    // Add all timesteps, timestep 0 is implicitely added.
11391 +    entier n = lata_db.nb_timesteps();
11392 +    timesteps_filter.resize_array(n-1);
11393 +    for (entier i = 1; i < n; i++)
11394 +      timesteps_filter[i-1] = i;
11395 +    Journal(3) << " Exporting all " << n-1 << " timesteps" << endl;
11396 +  } else if (timesteps_filter[0] < 0) {
11397 +    timesteps_filter.resize_array(0);
11398 +    Journal(3) << " Request timestep -1: Exporting only global time independent data" << endl;
11399 +  }
11400 +  if (domains_filter.size() == 0) {
11401 +    // Add all geometries
11402 +    domains_filter = list_all_domains;
11403 +    Journal(3) << " Exporting all geometries" << endl;
11404 +  } 
11405 +  if (components_filter.size() == 0) {
11406 +    // Add all fields of the selected geometries
11407 +    components_filter = list_all_fields;
11408 +    Journal(3) << " Exporting all fields:" << endl;
11409 +  } else {
11410 +    // Add all known geometry data fields
11411 +    components_filter.add("SOMMETS");
11412 +    components_filter.add("ELEMENTS");
11413 +    components_filter.add("FACES");
11414 +    components_filter.add("ELEM_FACES");
11415 +    components_filter.add("JOINTS_SOMMETS");
11416 +    components_filter.add("JOINTS_ELEMENTS");
11417 +    components_filter.add("JOINTS_FACES");
11418 +    components_filter.add("VIRTUAL_ELEMENTS");
11419 +    // these are for ijk meshs:
11420 +    components_filter.add("SOMMETS_IJK_I");
11421 +    components_filter.add("SOMMETS_IJK_J");
11422 +    components_filter.add("SOMMETS_IJK_K");
11423 +    components_filter.add("INVALID_CONNECTIONS");
11424 +  }
11425 +  filtered_db.filter_db(lata_db,
11426 +                        noms_to_motcles(domains_filter),
11427 +                        noms_to_motcles(components_filter),
11428 +                        timesteps_filter);
11429 +}
11430 diff --git a/databases/readers/Lata/LataFilter.h b/databases/readers/Lata/LataFilter.h
11431 new file mode 100644
11432 index 0000000..77f24d9
11433 --- /dev/null
11434 +++ b/databases/readers/Lata/LataFilter.h
11435 @@ -0,0 +1,261 @@
11436 +/*****************************************************************************
11437 +*
11438 +* Copyright (c) 2011 - 2013, CEA
11439 +* All rights reserved.
11440 +* Redistribution and use in source and binary forms, with or without
11441 +* modification, are permitted provided that the following conditions are met:
11442 +*
11443 +*     * Redistributions of source code must retain the above copyright
11444 +*       notice, this list of conditions and the following disclaimer.
11445 +*     * Redistributions in binary form must reproduce the above copyright
11446 +*       notice, this list of conditions and the following disclaimer in the
11447 +*       documentation and/or other materials provided with the distribution.
11448 +*     * Neither the name of CEA, nor the
11449 +*       names of its contributors may be used to endorse or promote products
11450 +*       derived from this software without specific prior written permission.
11451 +*
11452 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
11453 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
11454 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11455 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
11456 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11457 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
11458 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
11459 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
11460 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
11461 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11462 +*
11463 +*****************************************************************************/
11464 +
11465 +#ifndef LATA_H_INCLUDE
11466 +#define LATA_H_INCLUDE
11467 +
11468 +#include <LataDB.h>
11469 +#include <LataStructures.h>
11470 +#include <UserFields.h>
11471 +
11472 +typedef Field<FloatTab> FieldFloat;
11473 +
11474 +// This file provides the LataFilter class: it is a dynamic mesh
11475 +//  and field generator which is able to load data from a lata file,
11476 +//  apply operators. Once computed, the data is kept in a data cache
11477 +//  to speed up further access to the same data.
11478 +
11479 +// This class holds the LataFilter configuration (determines which 
11480 +//   combination of operators should be applied to the data)
11481 +class LataOptions 
11482 +{
11483 +public :
11484 +  static void extract_path_basename(const char * s, Nom & path_prefix, Nom & basename);
11485 +  static entier read_int_opt(const Nom & s);
11486 +  static double read_float_opt(const Nom & s);
11487 +  static Nom read_string_opt(const Nom & s);
11488 +
11489 +  Nom basename; // Name of the case. 
11490 +  Nom path_prefix; // Path for the case.
11491 +
11492 +  // Generate de the following meshes and associated data, if the flag is set.
11493 +  bool dual_mesh;
11494 +  bool nc_mesh;
11495 +  bool faces_mesh;
11496 +  bool boundary_mesh;
11497 +
11498 +  bool   reconnect;  // Do we want to reconnect multiblock meshes
11499 +  float  reconnect_tolerance;
11500 +  int regularize_polyedre ; // if 1 Treate polyedre as poyledre extruder
11501 +  int    regularize;    // Do we want to force regularize the domain ie convert the mesh to a structured ijk (not necessary except for dual-mesh vdf)
11502 +                        // special value 2 means "regularize if faces present and vdf"
11503 +  int    extend_domain; // Extend the regularized domaine by n layers of cells
11504 +  float  regularize_tolerance;
11505 +  bool   invalidate; // invalidate unused positions and connections;
11506 +  bool   load_virtual_elements; // Do we want to extend the loaded mesh subblocks with a layer of virtual elements
11507 +  bool   export_fields_at_faces_; // Should we show these fields in exportable fields
11508 +  
11509 +  // When loading ijk regular meshes, virtually create this number of blocks in the K direction:
11510 +  int    ijk_mesh_nb_parts_;
11511 +  // When loading ijk regular meshes, merge N layers of virtual elements (default=1)
11512 +  int    ijk_virt_layer;
11513 +
11514 +  bool   user_fields_; //activate user fields ?
11515 +
11516 +  ArrOfDouble clipbox_min;
11517 +  ArrOfDouble clipbox_max;
11518 +
11519 +  UserFields_options user_fields_options_;
11520 +
11521 +  LataOptions();
11522 +  virtual entier parse_option(const Nom &);
11523 +  virtual void describe();
11524 +  virtual ~LataOptions() {};
11525 +};
11526 +
11527 +class Operator : public LataObject
11528 +{
11529 +public:
11530 +  virtual void build_field(const Domain & src_domain, const LataField_base & src_field, 
11531 +                           const Domain & dest_domain, LataDeriv<LataField_base> & dest) = 0;
11532 +  virtual void build_geometry(const Domain & src_domain, LataDeriv<Domain> & dest) = 0;
11533 +protected:
11534 +};
11535 +
11536 +struct LataGeometryMetaData
11537 +{
11538 +  Nom internal_name_; // Internal full name (eg DOM_IJK)
11539 +  Nom displayed_name_; // Short name showed to the user (DOM for DOM_IJK, ?? if the geometry should not be exported)
11540 +  entier dynamic_; // Is the geometry changing at each timestep ?
11541 +  entier dimension_; // spatial dimension of coordinates
11542 +  Domain::Element element_type_;
11543 +  entier nblocks_; // Number of sub_blocks in the geometry (parallel computation)
11544 +  Motcle source_; // How to build this domain ("latadb", "operator_ijk", "operator_dual", "operator_boundary", "user_fields")
11545 +  Nom source_domain_;
11546 +  entier is_ijk_;
11547 +};
11548 +
11549 +struct LataFieldMetaData
11550 +{
11551 +  Field_UName uname_;
11552 +  Nom name_;
11553 +  Nom geometry_name_;
11554 +  Noms component_names_;
11555 +  entier nb_components_;
11556 +  entier is_vector_; // Yes => nb_components is equal to spatial dimension
11557 +  LataField_base::Elem_som localisation_;
11558 +  Nom source_localisation_; // Localisation of source field (for displayed name in visit)
11559 +  Motcle source_; // How to build this field ("latadb", "operator_ijk", "operator_dual", "operator_boundary", "user_fields")
11560 +  Field_UName source_field_;
11561 +};
11562 +
11563 +class DataCacheItem
11564 +{
11565 +public:
11566 +  DataCacheItem() : tstep_(-1), last_access_time_(0), lock_(0), memory_size_(0) {}
11567 +  LataDeriv<LataObject> item_; // The cached item
11568 +  Nom id_; // The id for this item
11569 +  entier tstep_; // The timestep of the cached data (for cache cleanup)
11570 +  BigEntier last_access_time_; // Last time this item has been accessed (for cache cleanup)
11571 +  // Is the item locked ? => cannot be deleted by clear_cache()
11572 +  // This is a counter: get_item increases, release_item dereases.
11573 +  // (this is when we simultaneously need several items, we must lock them to be sure)
11574 +  entier lock_; 
11575 +  // The memory size is computed when the item is released
11576 +  BigEntier memory_size_;
11577 +};
11578 +
11579 +class LataFilterCache 
11580 +{
11581 +public:
11582 +  LataFilterCache() : cache_data_access_count_(0),
11583 +                      clear_cache_on_tstep_change_(1), cache_memory_limit_(-1) {};
11584 +  void reset() { data_.reset(); cache_data_access_count_ = 0; }
11585 +  void set_cache_properties(entier clear_on_tstep_change, BigEntier mem_limit);
11586 +  template<class C> C & get_item(const Nom & id, entier tstep)
11587 +  {
11588 +    LataDeriv<LataObject> & obj = get_item_(id, tstep);
11589 +    if (obj.non_nul())
11590 +      return obj.refcast(C);
11591 +    else
11592 +      return obj.instancie(C);
11593 +  }
11594 +  void release_item(const Nom & id);
11595 +  void remove_item(const Nom & id);
11596 +  void cleanup_cache(entier tstep_to_keep);
11597 +protected:
11598 +  LataDeriv<LataObject> & get_item_(const Nom & id, entier tstep);
11599 +  // Stored data (depends on caching strategy)
11600 +  // data_ grows when needed. 
11601 +  LataVector<DataCacheItem> data_;
11602 +  BigEntier cache_data_access_count_;
11603 +  // If nonzero, whenever we ask a timestep,
11604 +  //  remove all cached data from other timesteps
11605 +  entier clear_cache_on_tstep_change_;
11606 +  // If before getting a new geometry or field, the data cache
11607 +  //  uses more than the limit, remove old data until we are below.
11608 +  // -1 means "no limit"
11609 +  BigEntier cache_memory_limit_; // Limit in bytes
11610 +};
11611 +
11612 +// Description: This is the MAIN class for the lata filter tool:
11613 +//  It reads data from a lata database on disk (initialize), 
11614 +//   and proposes several geometries and fields (get_exportable...) to the user.
11615 +//  The user can get them with get_geometry and get_field.
11616 +//  He must then call release_geometry and release_field to free the memory.
11617 +//  The user can also get metadata information (available without loading all
11618 +//   the data from disk) for geometries and fields and also timestep informations.
11619 +//  Timestep 0 contains global geometry and field definitions, timestep 1..n
11620 +//  are associated with each "TEMPS" entry in the lata file.
11621 +//
11622 +// LataFilter uses a data cache internally: it keeps fields and geometries after
11623 +// the user calls release_xxx(). The cache is controlled by set_cache_properties()
11624 +class LataFilter {
11625 +public:
11626 +  LataFilter() : lataDB__(0) {};
11627 +  void initialize(const LataOptions & opt, const LataDB & db);
11628 +  void set_cache_properties(BigEntier max_memory, const entier keep_all_timesteps);
11629 +  Noms get_exportable_geometry_names() const;
11630 +  const LataGeometryMetaData & get_geometry_metadata(const char * geometry) const;
11631 +  LataVector<Field_UName> get_exportable_field_unames(const char * geometry) const;
11632 +  const LataFieldMetaData & get_field_metadata(const Field_UName & uname) const;
11633 +  entier get_nb_timesteps() const;
11634 +  double get_timestep(entier i) const;
11635 +
11636 +  const Domain &     get_geometry(const Domain_Id &);  
11637 +
11638 +  void               release_geometry(const Domain &);
11639 +  const LataField_base & get_field(const Field_Id &);
11640 +  const FieldFloat & get_float_field(const Field_Id &) ;
11641 +
11642 +  void               release_field(const LataField_base &);
11643 +
11644 +  const LataDB & get_lataDB() const { return lataDB(); }
11645 +
11646 +  const LataOptions & get_options() const { return opt_; }
11647 +protected:
11648 +  Operator &              get_set_operator(const Domain_Id & id);
11649 +  LataDeriv<LataField_base> & get_cached_field(const Field_Id&);
11650 +  LataDeriv<Domain> &     get_cached_domain(const Domain_Id&);
11651 +  LataDeriv<Operator> &   get_cached_operator(const Domain_Id&);
11652 +  void release_cached_domain(const Domain_Id&);
11653 +  void release_cached_field(const Field_Id&);
11654 +  void release_cached_operator(const Domain_Id&);
11655 +  const Domain & get_geom_field_(const Field_Id & id, LataRef<const LataField_base> & field_result);
11656 +  void get_all_metadata(LataVector<LataGeometryMetaData> & geoms_data, LataVector<LataFieldMetaData> & fields_data);
11657 +  // LataDB       & lataDB() { return lataDB__; }
11658 +  const LataDB & lataDB() const { assert(lataDB__); return *lataDB__; }
11659 +
11660 +  // We store in the cache objects of type:
11661 +  //  LataDeriv<Domain>
11662 +  //  derived types of Operator
11663 +  //  LataDeriv<LataField_base>
11664 +  LataFilterCache data_cache_;
11665 +
11666 +  // LataV2 masterfile database 
11667 +  const LataDB *lataDB__;
11668 +  LataOptions opt_;
11669 +  // Metadata information for all fields and geometries (built in initialize)
11670 +  LataVector<LataGeometryMetaData> geoms_metadata_;
11671 +  LataVector<LataFieldMetaData>    fields_metadata_;
11672 +
11673 +  LataDeriv<UserFields> user_fields_;
11674 +};
11675 +
11676 +struct LataError
11677 +{
11678 +  enum ErrorCode { NEED_REGULAR, NO_FACES, WRONG_ELT_TYPE, INVALID_TSTEP, INVALID_COMPONENT, 
11679 +                   INVALID_DOMAIN, OTHER};
11680 +  LataError(ErrorCode code, const char * msg) : code_(code), msg_(msg) {};
11681 +  ErrorCode code_;
11682 +  const char *msg_;
11683 +};
11684 +
11685 +struct InternalError
11686 +{
11687 +  InternalError(const char *msg) : msg_(msg) {};
11688 +  const char *msg_;
11689 +};
11690 +
11691 +void LataDB_apply_input_filter(const LataDB & lata_db, LataDB & filtered_db, 
11692 +                               const ArrOfInt & input_timesteps_filter,
11693 +                               const Noms & input_domains_filter,
11694 +                               const Noms & input_components_filter);
11695 +#endif
11696 +
11697 diff --git a/databases/readers/Lata/LataJournal.h b/databases/readers/Lata/LataJournal.h
11698 new file mode 100644
11699 index 0000000..acc68e3
11700 --- /dev/null
11701 +++ b/databases/readers/Lata/LataJournal.h
11702 @@ -0,0 +1,36 @@
11703 +/*****************************************************************************
11704 +*
11705 +* Copyright (c) 2011 - 2013, CEA
11706 +* All rights reserved.
11707 +* Redistribution and use in source and binary forms, with or without
11708 +* modification, are permitted provided that the following conditions are met:
11709 +*
11710 +*     * Redistributions of source code must retain the above copyright
11711 +*       notice, this list of conditions and the following disclaimer.
11712 +*     * Redistributions in binary form must reproduce the above copyright
11713 +*       notice, this list of conditions and the following disclaimer in the
11714 +*       documentation and/or other materials provided with the distribution.
11715 +*     * Neither the name of CEA, nor the
11716 +*       names of its contributors may be used to endorse or promote products
11717 +*       derived from this software without specific prior written permission.
11718 +*
11719 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
11720 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
11721 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11722 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
11723 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11724 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
11725 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
11726 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
11727 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
11728 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11729 +*
11730 +*****************************************************************************/
11731 +
11732 +#ifndef LataJournal_H
11733 +#define LataJournal_H
11734 +#include <iostream>
11735 +#include <arch.h>
11736 +std::ostream & Journal(entier level=0);
11737 +void set_Journal_level(entier level);
11738 +#endif
11739 diff --git a/databases/readers/Lata/LataStructures.C b/databases/readers/Lata/LataStructures.C
11740 new file mode 100644
11741 index 0000000..390d289
11742 --- /dev/null
11743 +++ b/databases/readers/Lata/LataStructures.C
11744 @@ -0,0 +1,743 @@
11745 +/*****************************************************************************
11746 +*
11747 +* Copyright (c) 2011 - 2013, CEA
11748 +* All rights reserved.
11749 +* Redistribution and use in source and binary forms, with or without
11750 +* modification, are permitted provided that the following conditions are met:
11751 +*
11752 +*     * Redistributions of source code must retain the above copyright
11753 +*       notice, this list of conditions and the following disclaimer.
11754 +*     * Redistributions in binary form must reproduce the above copyright
11755 +*       notice, this list of conditions and the following disclaimer in the
11756 +*       documentation and/or other materials provided with the distribution.
11757 +*     * Neither the name of CEA, nor the
11758 +*       names of its contributors may be used to endorse or promote products
11759 +*       derived from this software without specific prior written permission.
11760 +*
11761 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
11762 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
11763 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11764 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
11765 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11766 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
11767 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
11768 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
11769 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
11770 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11771 +*
11772 +*****************************************************************************/
11773 +
11774 +#include <LataStructures.h>
11775 +#include <LataDB.h>
11776 +#include <stdlib.h>
11777 +static const entier info_level = 4;
11778 +
11779 +// Description: returns the number of items of the given type
11780 +entier Domain::nb_items(const LataField_base::Elem_som loc) const
11781 +{
11782 +  entier n = -1;
11783 +  switch (loc) {
11784 +  case LataField_base::SOM: n = nb_nodes(); break;
11785 +  case LataField_base::ELEM: n = nb_elements(); break;
11786 +  case LataField_base::FACES: n = nb_faces(); break;
11787 +  default:
11788 +    Journal() << "Invalid localisation " << (int) loc << " in Domain::nb_items" << endl;
11789 +    throw;
11790 +  }
11791 +  return n;
11792 +}
11793 +
11794 +// Description: returns the offset in the lata block on disk of the first
11795 +//  item for this Domain.id_.block_ (parallel computation).
11796 +//  (this value must be set with set_lata_block_offset)
11797 +entier Domain::lata_block_offset(const LataField_base::Elem_som loc) const
11798 +{
11799 +  entier n = -1;
11800 +  switch (loc) {
11801 +  case LataField_base::SOM: n = decal_nodes_lata_; break;
11802 +  case LataField_base::ELEM: n = decal_elements_lata_; break;
11803 +  case LataField_base::FACES: n = decal_faces_lata_; break;
11804 +  default:
11805 +    Journal() << "Invalid localisation " << (int) loc << " in Domain::lata_block_offset" << endl;
11806 +    throw;
11807 +  }
11808 +  if (n < 0) {
11809 +    Journal() << "Error: lata_block_offset not set for localisation " << (int) loc << endl;
11810 +    throw;
11811 +  }
11812 +  return n;
11813 +}
11814 +
11815 +// Description: set the lata_block_offset (see lata_block_offset)
11816 +void Domain::set_lata_block_offset(const LataField_base::Elem_som loc, entier n)
11817 +{
11818 +  switch (loc) {
11819 +  case LataField_base::SOM: decal_nodes_lata_ = n; break;
11820 +  case LataField_base::ELEM: decal_elements_lata_ = n; break;
11821 +  case LataField_base::FACES: decal_faces_lata_ = n; break;
11822 +  default:
11823 +    Journal() << "Invalid localisation " << (int) loc << " in Domain::set_lata_block_offset" << endl;
11824 +    throw;
11825 +  }
11826 +}
11827 +
11828 +template<class TabType>
11829 +void DomainUnstructured::compute_cell_center_coordinates(TabType & coord, entier index_begin) const
11830 +{
11831 +  const entier dim = nodes_.dimension(1);
11832 +  const entier nb_elem = elements_.dimension(0);
11833 +  const entier nb_som_elem = elements_.dimension(1);
11834 +  const double facteur = 1. / (double) nb_som_elem;
11835 +  double tmp[3];
11836 +  for (int i = 0; i < nb_elem; i++) {
11837 +    int j, k;
11838 +    tmp[0] = tmp[1] = tmp[2] = 0.;
11839 +    for (j = 0; j < nb_som_elem; j++) {
11840 +      int som = elements_(i, j);
11841 +      for (k = 0; k < loop_max(dim, 3); k++) {
11842 +        tmp[k] += nodes_(som, k);
11843 +        break_loop(k, dim);
11844 +      }
11845 +    }
11846 +    for (k = 0; k < loop_max(dim, 3); k++) {
11847 +      coord(index_begin + i, k) = tmp[k] * facteur;
11848 +      break_loop(k, dim);
11849 +    }
11850 +  }
11851 +}
11852 +
11853 +template
11854 +void DomainUnstructured::compute_cell_center_coordinates(FloatTab & coord, entier index_begin) const;
11855 +template
11856 +void DomainUnstructured::compute_cell_center_coordinates(DoubleTab & coord, entier index_begin) const;
11857 +
11858 +
11859 +LataField_base::Elem_som LataField_base::localisation_from_string(const Motcle & loc)
11860 +{
11861 +  if (loc.debute_par("SOM"))
11862 +    return SOM;
11863 +  else if (loc.debute_par("ELEM"))
11864 +    return ELEM;
11865 +  else if (loc.debute_par("FACE"))
11866 +    return FACES;
11867 +  else
11868 +    return UNKNOWN;
11869 +}
11870 +
11871 +Nom LataField_base::localisation_to_string(const Elem_som loc)
11872 +{
11873 +  Nom n;
11874 +  switch(loc) {
11875 +  case SOM: n = "SOM"; break;
11876 +  case ELEM: n = "ELEM"; break;
11877 +  case FACES: n = "FACES"; break;
11878 +  case UNKNOWN: n = "";
11879 +  }
11880 +  return n;
11881 +}
11882 +
11883 +Motcle Domain::lata_element_name(Domain::Element type)
11884 +{
11885 +  switch(type) {
11886 +  case point: return "POINT"; break;
11887 +  case line: return "SEGMENT"; break;
11888 +  case triangle: return "TRIANGLE"; break;
11889 +  case quadri: return "QUADRANGLE"; break;
11890 +  case tetra: return "TETRAEDRE"; break;
11891 +  case hexa: return "HEXAEDRE"; break;
11892 +  case prism6: return "PRISM6"; break;
11893 +  case polyedre: return "POLYEDRE"; break;
11894 +  case polygone: return "POLYGONE"; break;
11895 +  default: return "UNSPECIFIED";
11896 +  }
11897 +  return "UNSPECIFIED";
11898 +}
11899 +
11900 +Domain::Element Domain::element_type_from_string(const Motcle & type_elem)
11901 +{
11902 +  Element type;
11903 +  if (type_elem == "HEXAEDRE")
11904 +    type=hexa;
11905 +  else if (type_elem == "HEXAEDRE_AXI")
11906 +    type=hexa;
11907 +  else if (type_elem == "HEXAEDRE_VEF")
11908 +    type=hexa;
11909 +  else if (type_elem == "QUADRANGLE")
11910 +    type=quadri;
11911 +  else if (type_elem == "QUADRANGLE_3D")
11912 +    type=quadri;
11913 +  else if (type_elem == "RECTANGLE")
11914 +    type=quadri;
11915 +  else if (type_elem == "RECTANGLE_2D_AXI")
11916 +    type=quadri;
11917 +  else if (type_elem == "RECTANGLE_AXI")
11918 +    type=quadri;
11919 +  else if (type_elem == "SEGMENT")
11920 +    type=line;
11921 +  else if (type_elem == "SEGMENT_2D")
11922 +    type=line;
11923 +  else if (type_elem == "TETRAEDRE")
11924 +    type=tetra;
11925 +  else if (type_elem == "TRIANGLE")
11926 +    type=triangle;
11927 +  else if (type_elem == "TRIANGLE_3D")
11928 +    type=triangle;
11929 +  else if (type_elem == "POINT")
11930 +    type=point;
11931 +  else if ((type_elem == "PRISM6")||(type_elem == "PRISME"))
11932 +    type=prism6;
11933 +  else if (type_elem.debute_par("POLYEDRE"))
11934 +    type=polyedre;
11935 +  else if (type_elem.debute_par("POLYGONE"))
11936 +    type=polygone;
11937 +  else {
11938 +    Journal() << "Error in elem_type_from_string: unknown element type " << type_elem << endl;
11939 +    throw;
11940 +  }
11941 +  return type;
11942 +}
11943 +
11944 +Nom Domain::element_type_to_string(Element type)
11945 +{
11946 +  Nom n;
11947 +  switch(type) {
11948 +  case point:       n = "POINT"; break;
11949 +  case line:        n = "SEGMENT"; break;
11950 +  case triangle:    n = "TRIANGLE"; break;
11951 +  case quadri:      n = "QUADRANGLE"; break;
11952 +  case tetra:       n = "TETRAEDRE"; break;
11953 +  case hexa:        n = "HEXAEDRE"; break;
11954 +  case prism6:      n = "PRISM6"; break;
11955 +  case polyedre:    n = "POLYEDRE_0"; break;
11956 +  case polygone:    n = "POLYGONE"; break;
11957 +  case unspecified: n = "UNKNOWN"; break;
11958 +  }
11959 +  return n;
11960 +}
11961 +
11962 +// Description: read the specified geometry from the lataDB_ structure and put it in "dom".
11963 +//  load_faces: flag, tells if we should read faces definitions in the lata file
11964 +//  merge_virtual_elements: flag, if a "VIRTUAL_ELEMENTS" array is present in the lata file,
11965 +//   merges these elements to the requested block.
11966 +void DomainUnstructured::fill_domain_from_lataDB(const LataDB & lataDB,
11967 +                                                 const Domain_Id & id,
11968 +                                                 entier load_faces, 
11969 +                                                 entier merge_virtual_elements) 
11970 +{
11971 +  operator=(DomainUnstructured()); // Reset all data.
11972 +
11973 +  id_ = id;
11974 +  const LataDBGeometry & geom = lataDB.get_geometry(id.timestep_, id.name_);
11975 +
11976 +  // ********************************
11977 +  // 1) Look for the sub-block items to read (parallel computation)
11978 +  entier decal_nodes = 0;
11979 +  entier decal_elements = 0;
11980 +  entier decal_faces = 0;
11981 +  entier nb_sommets = -1;
11982 +  entier nbelements = -1;
11983 +  entier nbfaces = -1;
11984 +
11985 +  entier domain_has_faces = load_faces && lataDB.field_exists(id.timestep_, id.name_, "FACES");
11986 +  
11987 +  // Tableau de 3 joints (SOM, ELEM et FACES)
11988 +  LataVector<IntTab> joints;
11989 +  entier nproc = 1;
11990 +  for (entier i_item = 0; i_item < 3; i_item++) {
11991 +    //    LataField_base::Elem_som loc = LataField_base::SOM;
11992 +    Nom nom("JOINTS_SOMMETS");
11993 +    Nom nom2("SOMMETS");
11994 +    if (i_item == 1) {
11995 +      //loc = LataField_base::ELEM;
11996 +      nom = "JOINTS_ELEMENTS";
11997 +      nom2 = "ELEMENTS";
11998 +    } else if (i_item == 2) {
11999 +      // loc = LataField_base::FACES;
12000 +      nom = "JOINTS_FACES";
12001 +      nom2 = "FACES";
12002 +    }
12003 +
12004 +    IntTab & joint = joints.add();
12005 +    if (lataDB.field_exists(id.timestep_, id.name_, nom)) {
12006 +      entier nbitems = lataDB.get_field(id.timestep_, id.name_, nom2, "*").size_;
12007 +      IntTab tmp;
12008 +      lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, nom, "*"), tmp);
12009 +      nproc = tmp.dimension(0);
12010 +      // Recalcule la deuxieme colonne en fonction de la premiere
12011 +      joint.resize(nproc, 2);
12012 +      for (entier i = 0; i < nproc; i++) {
12013 +        joint(i, 0) = tmp(i, 0);
12014 +        if (i < nproc-1)
12015 +          joint(i, 1) = tmp(i+1, 0) - tmp(i, 0);
12016 +        else 
12017 +          joint(i, 1) = nbitems - tmp(i, 0);
12018 +      }
12019 +    } 
12020 +  }
12021 +
12022 +  if (id_.block_ < 0 || nproc == 1) {
12023 +    // read all blocks at once default values are ok
12024 +    set_joints(LataField_base::SOM) = joints[0];
12025 +    set_joints(LataField_base::ELEM) = joints[1];
12026 +    set_joints(LataField_base::FACES) = joints[2];
12027 +  } else {
12028 +    if (id_.block_ >= nproc) {
12029 +      Journal() << "LataFilter::get_geometry : request non existant block " << id.block_ 
12030 +                << " in geometry " << id.name_ << endl;
12031 +      throw;
12032 +    }
12033 +    const entier n = id_.block_;
12034 +    decal_nodes = joints[0](n, 0);
12035 +    nb_sommets = joints[0](n, 1);
12036 +    decal_elements = joints[1](n, 0);
12037 +    nbelements = joints[1](n, 1);
12038 +    if (domain_has_faces) {
12039 +      decal_faces = joints[2](n, 0);
12040 +      nbfaces = joints[2](n, 1);
12041 +    }
12042 +  }
12043 +
12044 +  // ******************************
12045 +  // 2) Read nodes, elements and faces data
12046 +  elt_type_ = Domain::element_type_from_string(geom.elem_type_);
12047 +
12048 +  lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "SOMMETS", "*"), nodes_, decal_nodes, nb_sommets);
12049 +  lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "ELEMENTS", "*"), elements_, decal_elements, nbelements);
12050 +  set_lata_block_offset(LataField_base::SOM, decal_nodes);
12051 +  set_lata_block_offset(LataField_base::ELEM, decal_elements);
12052 +  if (decal_nodes > 0) {
12053 +    // Nodes are stored with global numbering in the lata file: transform to sub_block numbering :
12054 +    elements_ -= decal_nodes;
12055 +  }
12056 +  if (domain_has_faces) {
12057 +    set_lata_block_offset(LataField_base::FACES, decal_faces);
12058 +    lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "FACES", "*"), faces_, decal_faces, nbfaces);
12059 +    if (decal_nodes > 0)
12060 +      faces_ -= decal_nodes;
12061 +    lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "ELEM_FACES", "*"), elem_faces_, decal_elements, nbelements);
12062 +    if (decal_faces > 0)
12063 +      elem_faces_ -= decal_faces;
12064 +  }
12065 +
12066 +  // *************************
12067 +  // 3) Merge virtual elements if requested
12068 +  if (merge_virtual_elements && lataDB.field_exists(id.timestep_, id.name_, "VIRTUAL_ELEMENTS") && id.block_ >= 0) 
12069 +    {
12070 +      Journal(info_level) << " Merging virtual elements" << endl;
12071 +      // joints_virt_elems(sub_block, 0) = index of first virtual element in the VIRTUAL_ELEMENTS array
12072 +      IntTab joints_virt_elems;
12073 +      // Load the virtual elements (nodes are in global numbering)
12074 +      //  First: find the index and number of virtual elements for block number id.block_:
12075 +      lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "JOINTS_VIRTUAL_ELEMENTS", "*"), joints_virt_elems);
12076 +      entier nb_virt_elems;
12077 +      if (id.block_ < nproc-1)
12078 +        nb_virt_elems = joints_virt_elems(id.block_+1, 0) - joints_virt_elems(id.block_, 0);
12079 +      else
12080 +        nb_virt_elems = lataDB.get_field(id.timestep_, id.name_, "VIRTUAL_ELEMENTS", "*").size_ - joints_virt_elems(id.block_, 0);
12081 +      Journal(info_level+1) << " Number of virtual elements for block " << id.block_ << "=" << nb_virt_elems << endl;
12082 +      //  Second: load the indexes of the virtual elements to load:
12083 +      IntTab virt_elems;
12084 +      lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "VIRTUAL_ELEMENTS", "*"), virt_elems, joints_virt_elems(id.block_,0), nb_virt_elems);
12085 +      set_virt_items(LataField_base::ELEM, virt_elems);
12086 +
12087 +      {
12088 +        //  Third: load the virtual elements (virt_elems contains the global indexes of the elements to
12089 +        //  load and virt_elem_som will contain global nodes indexes of the virtual elements)
12090 +        IntTab virt_elem_som;
12091 +        lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "ELEMENTS", "*"), virt_elem_som, virt_elems);
12092 +        // Find which virtual nodes are required and load them: virtual nodes to load are
12093 +        // all nodes of the virtual elements (they have duplicates).
12094 +        ArrOfInt index;
12095 +        ArrOfInt & virt_elem_som_array = virt_elem_som; // Array seen as monodimensionnal
12096 +        array_sort_indirect(virt_elem_som_array, index);
12097 +        // Global nodes indexes of needed virtual nodes 
12098 +        ArrOfInt nodes_to_read;
12099 +        nodes_to_read.set_smart_resize(1);
12100 +        {
12101 +          const entier n = index.size_array();
12102 +          // Global index of the last loaded node:
12103 +          entier last_node = -1;
12104 +          // Local index of the new loaded node:
12105 +          entier new_node_index = nodes_.dimension(0)-1;
12106 +          for (entier i = 0; i < n; i++) {
12107 +            // Take nodes to load in ascending order of their global numbers:
12108 +            const entier idx = index[i];
12109 +            const entier node = virt_elem_som_array[idx];
12110 +            if (node != last_node) {
12111 +              // Node not yet encountered
12112 +              nodes_to_read.append_array(node);
12113 +              new_node_index++;
12114 +              last_node = node;
12115 +            }
12116 +            virt_elem_som_array[idx] = new_node_index;
12117 +          }
12118 +        }
12119 +        set_virt_items(LataField_base::SOM, nodes_to_read);
12120 +        // Copy virtual elements to elements_
12121 +        entier debut = elements_.size_array();
12122 +        elements_.resize(elements_.dimension(0) + virt_elem_som.dimension(0),
12123 +                         elements_.dimension(1));
12124 +        elements_.inject_array(virt_elem_som, virt_elem_som.size_array(), debut);
12125 +        // Load virtual nodes
12126 +        FloatTab tmp_nodes;
12127 +        lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "SOMMETS", "*"), tmp_nodes, nodes_to_read);
12128 +        // Copy to nodes_
12129 +        debut = nodes_.size_array();
12130 +        nodes_.resize(nodes_.dimension(0) + tmp_nodes.dimension(0),
12131 +                      nodes_.dimension(1));
12132 +        nodes_.inject_array(tmp_nodes, tmp_nodes.size_array(), debut);
12133 +      }
12134 +
12135 +      if (domain_has_faces) {
12136 +        // Find which virtual faces are required and load them
12137 +        // For each virtual element, index of its faces (like virt_elem_som)
12138 +        IntTab virt_elem_faces; 
12139 +        lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "ELEM_FACES", "*"), virt_elem_faces, virt_elems);
12140 +        // Build the list of missing faces:
12141 +        ArrOfInt index;
12142 +        ArrOfInt & virt_elem_faces_array = virt_elem_faces; // Array seen as monodimensionnal
12143 +        array_sort_indirect(virt_elem_faces_array, index);
12144 +        ArrOfInt faces_to_read;
12145 +        faces_to_read.set_smart_resize(1);
12146 +        {
12147 +          const entier n = index.size_array();
12148 +          // Global index of the last loaded face:
12149 +          entier last_face = -1;
12150 +          // Local index of the new loaded node:
12151 +          entier new_face_index = faces_.dimension(0)-1;
12152 +          for (entier i = 0; i < n; i++) {
12153 +            // Take nodes to load in ascending order of their global numbers:
12154 +            const entier idx = index[i];
12155 +            const entier face = virt_elem_faces_array[idx];
12156 +            if (face != last_face) {
12157 +              // Node not yet encountered
12158 +              faces_to_read.append_array(face);
12159 +              new_face_index++;
12160 +              last_face = face;
12161 +            }
12162 +            virt_elem_faces_array[idx] = new_face_index;
12163 +          }
12164 +        }
12165 +        set_virt_items(LataField_base::FACES, faces_to_read);
12166 +        // Copy virtual elem_faces to elem_faces
12167 +        entier debut = elem_faces_.size_array();
12168 +        elem_faces_.resize(elem_faces_.dimension(0) + virt_elem_faces.dimension(0),
12169 +                           elem_faces_.dimension(1));
12170 +        elem_faces_.inject_array(virt_elem_faces, virt_elem_faces.size_array(), debut);
12171 +
12172 +        // Load virtual faces
12173 +        IntTab tmp_faces_nodes;
12174 +        lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "FACES", "*"), tmp_faces_nodes, faces_to_read);
12175 +        // Convert global nodes indexes to local loaded nodes indexes in tmp_faces_nodes
12176 +        {
12177 +          // sort tmp_faces in ascending order so that the search requires linear time
12178 +          ArrOfInt & array_tmp_faces_nodes = tmp_faces_nodes;
12179 +          index.reset();
12180 +          array_sort_indirect(array_tmp_faces_nodes, index);
12181 +          const entier n = array_tmp_faces_nodes.size_array();
12182 +          // Take nodes in tmp_faces_nodes in ascending order and find the corresponding node in nodes_to_read
12183 +          // (which is also in sorted)
12184 +          entier i1; // index in array_tmp_faces_nodes (the current node to convert)
12185 +          entier i2 = 0; // index in nodes_to_read
12186 +          const entier index_of_first_virtual_node = nodes_.dimension(0) - nb_virt_items(LataField_base::SOM);
12187 +          const ArrOfInt & nodes_to_read = get_virt_items(LataField_base::SOM);
12188 +          const entier max_i2 = nodes_to_read.size_array();
12189 +          for (i1 = 0; i1 < n; i1++) {
12190 +            const entier j = index[i1];
12191 +            const entier global_node_index_to_find = array_tmp_faces_nodes[j];
12192 +            // find the matching node in nodes_to_read (nodes_to_read is in ascending order)
12193 +            while (nodes_to_read[i2] != global_node_index_to_find) {
12194 +              i2++;
12195 +              if (i2 >= max_i2) {
12196 +                cerr << "Internal error in DomainUnstructured::fill_domain_from_lataDB:\n"
12197 +                     << " node " << global_node_index_to_find << " of a virtual face does not belong to a virtual element" << endl;
12198 +               throw;
12199 +              }
12200 +            }
12201 +            array_tmp_faces_nodes[j] = index_of_first_virtual_node + i2; // index of this node in the local nodes_ array
12202 +          }
12203 +        }
12204 +        // Copy to faces_ array
12205 +        debut = faces_.size_array();
12206 +        faces_.resize(faces_.dimension(0) + tmp_faces_nodes.dimension(0),
12207 +                      faces_.dimension(1));
12208 +        faces_.inject_array(tmp_faces_nodes, tmp_faces_nodes.size_array(), debut);
12209 +      }
12210 +    }
12211 +}
12212 +
12213 +void Domain::fill_field_from_lataDB(const LataDB & lataDB,
12214 +                                    const Field_Id & id, 
12215 +                                    LataDeriv<LataField_base> & field) const
12216 +{
12217 +  Journal() << "Error : fill_field_from_lataDB not coded for this domain type" << endl;
12218 +  throw;
12219 +}
12220 +
12221 +// Reads the requested field to "field" structure.
12222 +// id.block_ is not used, the data block read is the same as the domain.
12223 +void DomainUnstructured::fill_field_from_lataDB(const LataDB & lataDB,
12224 +                                                const Field_Id & id, 
12225 +                                                LataDeriv<LataField_base> & field) const
12226 +{
12227 +  const LataDBField & lata_field = lataDB.get_field(id.timestep_, id.uname_);
12228 +  LataField_base::Elem_som loc = LataField_base::localisation_from_string(lata_field.localisation_);
12229 +  const entier decal = lata_block_offset(loc);
12230 +
12231 +  const ArrOfInt & virt_items = get_virt_items(loc);
12232 +  const entier virt_size = virt_items.size_array();
12233 +  const entier size = nb_items(loc) - virt_size;
12234 +
12235 +  const LataDBDataType & type = lata_field.datatype_;
12236 +  switch(type.type_) {
12237 +  case LataDBDataType::REAL32: {
12238 +    FloatTab & data = field.instancie(Field<FloatTab> ).data_;
12239 +    lataDB.read_data(lata_field, data, decal, size);
12240 +    if (virt_size > 0) {
12241 +      FloatTab tmp;
12242 +      lataDB.read_data(lata_field, tmp, virt_items);
12243 +      const entier debut = data.size_array();
12244 +      data.resize(data.dimension(0)+virt_size, data.dimension(1));
12245 +      data.inject_array(tmp, virt_size, debut);
12246 +    }
12247 +    break;
12248 +  }
12249 +  case LataDBDataType::REAL64: {
12250 +    DoubleTab & data = field.instancie(Field<DoubleTab> ).data_; 
12251 +    lataDB.read_data(lata_field, data, decal, size);
12252 +    if (virt_size > 0) {
12253 +      DoubleTab tmp;
12254 +      lataDB.read_data(lata_field, tmp, virt_items);
12255 +      const entier debut = data.size_array();
12256 +      data.resize(data.dimension(0)+virt_size, data.dimension(1));
12257 +      data.inject_array(tmp, virt_size, debut);
12258 +    }
12259 +    break;
12260 +  }
12261 +  case LataDBDataType::INT32:
12262 +  case LataDBDataType::INT64: {
12263 +    IntTab & data = field.instancie(Field<IntTab> ).data_; 
12264 +    lataDB.read_data(lata_field, data, decal, size);
12265 +    if (virt_size > 0) {
12266 +      IntTab tmp;
12267 +      lataDB.read_data(lata_field, tmp, virt_items);
12268 +      const entier debut = data.size_array();
12269 +      data.resize(data.dimension(0)+virt_size, data.dimension(1));
12270 +      data.inject_array(tmp, virt_size, debut);
12271 +    }
12272 +    break;
12273 +  }
12274 +  default:
12275 +    Journal() << "LataFilter::get_field_from_lataDB " << id.uname_ << ": data type not implemented" << endl;
12276 +    throw;
12277 +  }
12278 +  field.valeur().id_ = id;
12279 +  field.valeur().component_names_ = lata_field.component_names_;
12280 +  field.valeur().localisation_ = loc;
12281 +  field.valeur().nature_ = lata_field.nature_;
12282 +}
12283 +
12284 +DomainIJK::DomainIJK()
12285 +{
12286 +  part_begin_ = 0;
12287 +  part_end_ = 0;
12288 +  virtual_layer_begin_ = 0;
12289 +  virtual_layer_end_ = 0;
12290 +}
12291 +
12292 +void DomainIJK::fill_domain_from_lataDB(const LataDB & lataDB,
12293 +                                        const Domain_Id & id,                                        
12294 +                                        entier split_in_N_parts,
12295 +                                        const entier virt_layer_size)
12296 +{
12297 +  if (virt_layer_size < 0) {
12298 +    Journal() << "Error in DomainIJK::fill_domain_from_lataDB: virt_layer_size < 0" << endl;
12299 +    throw;
12300 +  }
12301 +  id_ = id;
12302 +
12303 +  Journal(info_level) << "Filling ijk domain " << id.name_ << " tstep " << id.timestep_ << " block " << id.block_ << endl;
12304 +  coord_.reset();
12305 +  entier dim3 = lataDB.field_exists(id.timestep_, id.name_, "SOMMETS_IJK_K", LataDB::FIRST_AND_CURRENT /* timestep */);
12306 +  {
12307 +    const LataDBField & coord = lataDB.get_field(id.timestep_, 
12308 +                                                 Field_UName(id.name_, "SOMMETS_IJK_I", ""),
12309 +                                                 LataDB::FIRST_AND_CURRENT /* timestep */);
12310 +    FloatTab tmp;
12311 +    lataDB.read_data(coord, tmp);
12312 +    coord_.add();
12313 +    coord_[0] = tmp;
12314 +  }
12315 +  {
12316 +    const LataDBField & coord = lataDB.get_field(id.timestep_, 
12317 +                                                 Field_UName(id.name_, "SOMMETS_IJK_J", ""),
12318 +                                                 LataDB::FIRST_AND_CURRENT /* timestep */);
12319 +    FloatTab tmp;
12320 +    lataDB.read_data(coord, tmp);
12321 +    coord_.add();
12322 +    coord_[1] = tmp;
12323 +  }
12324 +  if (dim3) {
12325 +    const LataDBField & coord = lataDB.get_field(id.timestep_, 
12326 +                                                 Field_UName(id.name_, "SOMMETS_IJK_K", ""),
12327 +                                                 LataDB::FIRST_AND_CURRENT /* timestep */);
12328 +    FloatTab tmp;
12329 +    lataDB.read_data(coord, tmp);
12330 +    coord_.add();
12331 +    coord_[2] = tmp;
12332 +  }
12333 +
12334 +  elt_type_ = dim3 ? hexa : quadri;
12335 +
12336 +  entier block = (id.block_) < 0 ? 0 : id.block_;
12337 +
12338 +  if (id.block_ >= split_in_N_parts) {
12339 +    Journal() << "Error in DomainIJK::fill_domain_from_lataDB: invalid block " << id.block_ << endl;
12340 +    throw;
12341 +  }
12342 +
12343 +  // Load the N-th part
12344 +  //  The ijk domain is virtually split in the Z direction (or Y en 2D)
12345 +  entier maxdim = coord_.size() - 1;
12346 +  // Number of elements in the Z direction:
12347 +  const entier nelem = coord_[maxdim].size_array() - 1;
12348 +  entier part_size = nelem / split_in_N_parts;
12349 +  if (part_size * split_in_N_parts < nelem)
12350 +    part_size++;
12351 +  
12352 +  // Begin and end of the requested part:
12353 +  part_begin_ = part_size * block - virt_layer_size;
12354 +  if (part_begin_ < 0)
12355 +    part_begin_ = 0;
12356 +  part_end_ = part_size * block + part_size + virt_layer_size;
12357 +  if (part_end_ > nelem)
12358 +    part_end_ = nelem;
12359 +  if (part_begin_ > part_end_)
12360 +    // empty block
12361 +    part_begin_ = part_end_ = 0; 
12362 +
12363 +  if (block > 0 && part_end_ > part_begin_)
12364 +    // There is a virtual layer at the begin
12365 +    virtual_layer_begin_ = virt_layer_size;
12366 +  if (block < split_in_N_parts-1 && part_end_ > part_begin_)
12367 +    virtual_layer_end_ = virt_layer_size;
12368 +
12369 +  // Extract coordinates:
12370 +  ArrOfFloat tmp(coord_[maxdim]);
12371 +  const entier n = part_end_ - part_begin_ + 1;
12372 +  coord_[maxdim].resize_array(n);
12373 +  for (entier i = 0; i < n; i++)
12374 +    coord_[maxdim][i] = tmp[i + part_begin_];
12375 +
12376 +  Journal(info_level) << "Domain " << id.name_ << " has number of nodes: [ ";
12377 +  for (entier dim = 0; dim < coord_.size(); dim++) 
12378 +    Journal(info_level) << coord_[dim].size_array() << " ";
12379 +  Journal(info_level) << "]" << endl;
12380 +
12381 +  if (part_end_ > part_begin_ // part might be empty if too many processors
12382 +      && lataDB.field_exists(id.timestep_, id.name_, "INVALID_CONNECTIONS", LataDB::FIRST_AND_CURRENT /* timestep */))
12383 +    {
12384 +      Journal(info_level) << " loading invalid_connections" << endl;
12385 +      IntTab Itmp;
12386 +      entier ij = 0, offset = 0, sz = 0;
12387 +      // Product of number of elements in directions I and J
12388 +      ij = coord_[0].size_array() - 1;
12389 +      if (coord_.size() > 2)
12390 +        ij *= coord_[1].size_array() - 1;
12391 +      // Select a range of elements in direction K
12392 +      offset = ij * part_begin_;
12393 +      sz = nb_elements();
12394 +      const LataDBField & lata_field = lataDB.get_field(id.timestep_,  id.name_, "INVALID_CONNECTIONS", "ELEM",
12395 +                                                        LataDB::FIRST_AND_CURRENT);
12396 +      
12397 +      lataDB.read_data(lata_field, Itmp, offset, sz);
12398 +
12399 +      invalid_connections_.resize_array(nb_elements());
12400 +      invalid_connections_ = 0; // everything valid by default
12401 +      
12402 +      for (entier i = 0; i < sz; i++) {
12403 +        if (Itmp(i, 0) != 0)
12404 +          invalid_connections_.setbit(i);
12405 +      }
12406 +    }
12407 +}
12408 +
12409 +void DomainIJK::fill_field_from_lataDB(const LataDB & lataDB,
12410 +                                       const Field_Id & id, 
12411 +                                       LataDeriv<LataField_base> & field) const
12412 +{
12413 +  const LataDBField & lata_field = lataDB.get_field(id.timestep_, id.uname_);
12414 +  LataField_base::Elem_som loc = LataField_base::localisation_from_string(lata_field.localisation_);
12415 +
12416 +  entier ij = 0, offset = 0, sz = 0;
12417 +  switch(loc) {
12418 +  case LataField_base::ELEM: 
12419 +    // Product of number of elements in directions I and J
12420 +    ij = coord_[0].size_array() - 1;
12421 +    if (coord_.size() > 2)
12422 +      ij *= coord_[1].size_array() - 1;
12423 +    // Select a range of elements in direction K
12424 +    offset = ij * part_begin_;
12425 +    sz = ij * (part_end_ - part_begin_);
12426 +    break;
12427 +  case LataField_base::SOM:
12428 +  case LataField_base::FACES:
12429 +    // Product of number of nodes in directions I and J
12430 +    ij = coord_[0].size_array();
12431 +    if (coord_.size() > 2)
12432 +      ij *= coord_[1].size_array();
12433 +    offset = ij * part_begin_;
12434 +    sz = ij * (part_end_ + 1 - part_begin_);
12435 +    break;
12436 +  default:
12437 +    Journal() << "Error in DomainIJK::fill_field_from_lataDB: unknown localisation" << endl;
12438 +    throw;
12439 +  }
12440 +  
12441 +  const LataDBDataType & type = lata_field.datatype_;
12442 +  switch(type.type_) {
12443 +  case LataDBDataType::REAL32: {
12444 +    FloatTab & data = field.instancie(Field<FloatTab> ).data_;
12445 +    lataDB.read_data(lata_field, data, offset, sz);
12446 +    break;
12447 +  }
12448 +  case LataDBDataType::REAL64: {
12449 +    DoubleTab & data = field.instancie(Field<DoubleTab> ).data_; 
12450 +    lataDB.read_data(lata_field, data, offset, sz);
12451 +    break;
12452 +  }
12453 +  case LataDBDataType::INT32:
12454 +  case LataDBDataType::INT64: {
12455 +    IntTab & data = field.instancie(Field<IntTab> ).data_; 
12456 +    lataDB.read_data(lata_field, data, offset, sz);
12457 +    break;
12458 +  }
12459 +  default:
12460 +    Journal() << "LataFilter::get_field_from_lataDB " << id.uname_ << ": data type not implemented" << endl;
12461 +    throw;
12462 +  }
12463 +  field.valeur().id_ = id;
12464 +  field.valeur().component_names_ = lata_field.component_names_;
12465 +  field.valeur().localisation_ = loc;
12466 +  field.valeur().nature_ = lata_field.nature_;
12467 +}
12468 +
12469 +
12470 +Domain::DomainType Domain::get_domain_type() const
12471 +{
12472 +  const DomainUnstructured* geom_ptr = dynamic_cast<const DomainUnstructured*>(this);
12473 +  if (geom_ptr!=0)
12474 +    return UNSTRUCTURED;
12475 +  const DomainIJK* ijk_ptr = dynamic_cast<const DomainIJK*>(this);
12476 +  if (ijk_ptr!=0)
12477 +    return IJK;
12478 +  throw ("Not implemeneted");
12479 +}
12480 +const DomainUnstructured & Domain::cast_DomainUnstructured() const
12481 +{
12482 +  return dynamic_cast<const DomainUnstructured&>(*this);
12483 +}
12484 +const DomainIJK &  Domain::cast_DomainIJK() const
12485 +{
12486 +  return dynamic_cast<const DomainIJK&>(*this);
12487 +}
12488 diff --git a/databases/readers/Lata/LataStructures.h b/databases/readers/Lata/LataStructures.h
12489 new file mode 100644
12490 index 0000000..74fa765
12491 --- /dev/null
12492 +++ b/databases/readers/Lata/LataStructures.h
12493 @@ -0,0 +1,332 @@
12494 +/*****************************************************************************
12495 +*
12496 +* Copyright (c) 2011 - 2013, CEA
12497 +* All rights reserved.
12498 +* Redistribution and use in source and binary forms, with or without
12499 +* modification, are permitted provided that the following conditions are met:
12500 +*
12501 +*     * Redistributions of source code must retain the above copyright
12502 +*       notice, this list of conditions and the following disclaimer.
12503 +*     * Redistributions in binary form must reproduce the above copyright
12504 +*       notice, this list of conditions and the following disclaimer in the
12505 +*       documentation and/or other materials provided with the distribution.
12506 +*     * Neither the name of CEA, nor the
12507 +*       names of its contributors may be used to endorse or promote products
12508 +*       derived from this software without specific prior written permission.
12509 +*
12510 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
12511 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
12512 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
12513 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
12514 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
12515 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
12516 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
12517 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12518 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
12519 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12520 +*
12521 +*****************************************************************************/
12522 +
12523 +#ifndef LataStructures_H
12524 +#define LataStructures_H
12525 +
12526 +#include <ArrOfBit.h>
12527 +#include <Lata_tools.h>
12528 +#include <LataDB.h>
12529 +
12530 +// This file contains definitions of data structures containind meshes and fields
12531 +//  used by LataFilter.
12532 +
12533 +// Description: Domain_Id is what you need to identify the content
12534 +//  of a Domain object (at this time, the domain name, the timestep and the 
12535 +//  parallel sub_block number)
12536 +class Domain_Id
12537 +{
12538 +public:
12539 +  Domain_Id(const char * name = "??", int t = 0, int block = -1) :
12540 +    name_(name), timestep_(t), block_(block) {};
12541 +  // Domain name
12542 +  Nom name_;
12543 +  // At which timestep (needed for dynamic domains)
12544 +  int timestep_;
12545 +  // Which block of the parallel computation ? -1 => all blocks
12546 +  int block_;
12547 +};
12548 +
12549 +// Description: Field_Id is what you need to identify the content of a
12550 +//  LataField_base structure (at this time, the field uname, 
12551 +//  the timestep and the parallel sub_block number)
12552 +class Field_Id
12553 +{
12554 +public:
12555 +  Field_Id() : timestep_(0) {};
12556 +  Field_Id(const Field_UName & uname, int timestep, int block) :
12557 +    timestep_(timestep), block_(block), uname_(uname)  {};
12558 +  
12559 +  int         timestep_;
12560 +  int         block_;
12561 +  Field_UName uname_;
12562 +
12563 +  operator Domain_Id() const { return Domain_Id(uname_.get_geometry(), timestep_, block_); }
12564 +};
12565 +
12566 +// Description: This structure contains a discrete data array for a specific
12567 +//  field, at one timestep, for one sub_block of the geometry, with
12568 +//  one localisation (but many components)
12569 +class LataField_base : public LataObject
12570 +{
12571 +public:
12572 +  LataField_base() { localisation_ = UNKNOWN; nature_ = LataDBField::UNKNOWN; }
12573 +  Field_Id  id_;
12574 +  Noms      component_names_;
12575 +  enum Elem_som { ELEM, SOM, FACES, UNKNOWN };
12576 +  Elem_som  localisation_;
12577 +  LataDBField::Nature nature_;
12578 +
12579 +  static Elem_som localisation_from_string(const Motcle &);
12580 +  static Nom      localisation_to_string(const Elem_som);
12581 +};
12582 +class DomainUnstructured;
12583 +class DomainIJK;
12584 +
12585 +// This class stores the geometry of a domain
12586 +class Domain : public LataObject
12587 +{
12588 +public:
12589 +  Domain_Id id_;
12590 +  enum Element { point, line, triangle, quadri, tetra, hexa, prism6, polyedre, polygone, unspecified };
12591 +  enum DomainType { IJK, UNSTRUCTURED };
12592 +  static Element element_type_from_string(const Motcle & type_elem);
12593 +  static Nom     element_type_to_string(Element type);
12594 +  Element elt_type_;
12595 +
12596 +  Domain() : 
12597 +    elt_type_(unspecified),
12598 +    decal_nodes_lata_(-1), // -1 indicates: value not set. see lata_block_offset
12599 +    decal_elements_lata_(-1), 
12600 +    decal_faces_lata_(-1) {};
12601 +    DomainType get_domain_type() const;
12602 +    const DomainUnstructured & cast_DomainUnstructured() const;
12603 +    const DomainIJK &  cast_DomainIJK() const;
12604 +  virtual entier dimension() const = 0;
12605 +  virtual entier nb_nodes() const = 0;
12606 +  virtual entier nb_elements() const = 0;
12607 +  virtual entier nb_faces() const = 0;
12608 +  virtual entier nb_items(const LataField_base::Elem_som) const;
12609 +  virtual entier lata_block_offset(const LataField_base::Elem_som) const;
12610 +  virtual void   set_lata_block_offset(const LataField_base::Elem_som, entier n);
12611 +
12612 +  virtual void fill_field_from_lataDB(const LataDB & lataDB,
12613 +                                      const Field_Id & id, 
12614 +                                      LataDeriv<LataField_base> & field) const = 0;
12615 +
12616 +  static Motcle lata_element_name(Domain::Element type);
12617 +
12618 +protected:
12619 +  // If the Domain has been loaded from a lata file and it's not the
12620 +  // first block this is the offset in the lata file:
12621 +  entier decal_nodes_lata_;
12622 +  entier decal_elements_lata_;
12623 +  entier decal_faces_lata_;
12624 +};
12625 +
12626 +class DomainUnstructured : public Domain
12627 +{
12628 +public:
12629 +  DomainUnstructured() { nb_virt_nodes_ = 0; nb_virt_elements_ = 0; nb_virt_faces_ = 0; }
12630 +
12631 +  FloatTab  nodes_;
12632 +  // For each element, indexes of the nodes (first node is at index 0)
12633 +  // Nodes ordering in an element is the same as in TRUST
12634 +  IntTab    elements_;
12635 +  // For each face, indexes of the nodes (if present in lata file)
12636 +  IntTab    faces_;
12637 +  // For each elements, indexes of the faces (first face at index 0, if present in lata file)
12638 +  // Faces ordering in an element is the same as in TRUST
12639 +  IntTab    elem_faces_;
12640 +
12641 +  entier dimension() const { return nodes_.dimension(1); }
12642 +  entier nb_nodes() const { return nodes_.dimension(0); }
12643 +  entier nb_elements() const { return elements_.dimension(0); }
12644 +  entier nb_faces() const { return faces_.dimension(0); }
12645 +  // Tests if the geometry contains faces description
12646 +  entier faces_ok() const { return elem_faces_.dimension(0) == elements_.dimension(0); }
12647 +  template<class TabType>
12648 +  void compute_cell_center_coordinates(TabType & coord, entier index_begin) const;
12649 +  BigEntier compute_memory_size() const
12650 +  { return
12651 +      memory_size(nodes_)
12652 +      + memory_size(elements_)
12653 +      + memory_size(faces_)
12654 +      + memory_size(elem_faces_); 
12655 +  }
12656 +  const IntTab & get_joints(LataField_base::Elem_som loc) const { 
12657 +    const IntTab * ptr = 0;
12658 +    switch(loc) {
12659 +    case LataField_base::SOM: ptr = &joints_sommets_; break;
12660 +    case LataField_base::ELEM: ptr = &joints_elements_; break;
12661 +    case LataField_base::FACES: ptr = &joints_faces_; break;
12662 +    default: throw;
12663 +    }
12664 +    if (ptr->dimension(1) == 0) throw;
12665 +    return *ptr;
12666 +  }
12667 +  IntTab & set_joints(LataField_base::Elem_som loc) {
12668 +    IntTab * ptr = 0;
12669 +    switch(loc) {
12670 +    case LataField_base::SOM: ptr = &joints_sommets_; break;
12671 +    case LataField_base::ELEM: ptr = &joints_elements_; break;
12672 +    case LataField_base::FACES: ptr = &joints_faces_; break;
12673 +    default: throw;
12674 +    }
12675 +    return *ptr;
12676 +  }
12677 +  const ArrOfInt & get_virt_items(LataField_base::Elem_som loc) const {
12678 +    switch(loc) {
12679 +    case LataField_base::SOM: return virt_nodes_; break;
12680 +    case LataField_base::ELEM: return virt_elements_; break;
12681 +    case LataField_base::FACES: return virt_faces_; break;
12682 +    default: throw;
12683 +    }
12684 +    return virt_nodes_;
12685 +  }
12686 +  void set_virt_items(LataField_base::Elem_som loc, const ArrOfInt & list) {
12687 +    switch(loc) {
12688 +    case LataField_base::SOM: virt_nodes_ = list; nb_virt_nodes_ = list.size_array(); break;
12689 +    case LataField_base::ELEM: virt_elements_ = list; nb_virt_elements_ = list.size_array(); break;
12690 +    case LataField_base::FACES: virt_faces_ = list; nb_virt_faces_ = list.size_array(); break;
12691 +    default: throw;
12692 +    }
12693 +  };
12694 +  void set_nb_virt_items(LataField_base::Elem_som loc, entier n) {
12695 +    switch(loc) {
12696 +    case LataField_base::SOM:   nb_virt_nodes_ = n; break;
12697 +    case LataField_base::ELEM:  nb_virt_elements_ = n; break;
12698 +    case LataField_base::FACES: nb_virt_faces_ = n; break;
12699 +    default: throw;
12700 +    }
12701 +  };
12702 +  entier nb_virt_items(LataField_base::Elem_som loc) const {
12703 +    switch(loc) {
12704 +    case LataField_base::SOM: return nb_virt_nodes_; break;
12705 +    case LataField_base::ELEM: return nb_virt_elements_; break;
12706 +    case LataField_base::FACES: return nb_virt_faces_; break;
12707 +    default: throw;
12708 +    }
12709 +    return nb_virt_nodes_;
12710 +  }
12711 +
12712 +  virtual void fill_domain_from_lataDB(const LataDB & lataDB,
12713 +                                       const Domain_Id & id,
12714 +                                       entier load_faces = 1, 
12715 +                                       entier merge_virtual_elements = 0);
12716 +  virtual void fill_field_from_lataDB(const LataDB & lataDB,
12717 +                                      const Field_Id & id, 
12718 +                                      LataDeriv<LataField_base> & field) const;
12719 +
12720 +protected:
12721 +  // data not always filled:
12722 +  IntTab joints_sommets_;
12723 +  IntTab joints_elements_;
12724 +  IntTab joints_faces_;
12725 +  ArrOfInt virt_nodes_; // Global indexes of virtual nodes to load
12726 +  ArrOfInt virt_elements_; // Global indexes of virtual elements to load
12727 +  ArrOfInt virt_faces_; // Global indexes of virtual faces to load
12728 +  entier nb_virt_nodes_;
12729 +  entier nb_virt_elements_;
12730 +  entier nb_virt_faces_;
12731 +};
12732 +
12733 +// This is a structured grid, grid axes aligned on X, Y and Z.
12734 +// The grid can have "invalid_positions_" and "invalid_connections_".
12735 +// Nodes are numbered like this:
12736 +//  node_index(i,j,k) = (k * nb_nodes_y + j) * nb_nodes_x + i
12737 +// Elements are numbered like this:
12738 +//  element_index(i,j,k) = (k * nb_elements_y + j) * nb_elements_x + i
12739 +// Faces are numbered like this: faces of each direction have a numbering starting at zero.
12740 +//  The number of a particular face is the smallest number of its nodes.
12741 +//  Hence some numbers are not used (le last face of each "row" depending on the
12742 +//  direction)
12743 +class DomainIJK : public Domain
12744 +{
12745 +public:
12746 +  DomainIJK();
12747 +  // In each spatial direction, ordered list of coordinates of the IJK grid
12748 +  LataVector<ArrOfFloat> coord_;
12749 +
12750 +  // For each node and each element, flag indicates if it is valid or not
12751 +  // (eg, has usable field values)
12752 +  // If array is empty, all data is valid.
12753 +  ArrOfBit invalid_positions_;
12754 +  ArrOfBit invalid_connections_;
12755 +
12756 +  entier dimension() const { return coord_.size(); }
12757 +  entier nb_nodes() const {
12758 +    entier n = 1, d = coord_.size(); 
12759 +    for (entier i=0; i<d; i++) 
12760 +      n *= coord_[i].size_array();
12761 +    return n; 
12762 +  }
12763 +  entier nb_elements() const {
12764 +    entier n = 1, d = coord_.size(); 
12765 +    for (entier i=0; i<d; i++) 
12766 +      n *= coord_[i].size_array()-1;
12767 +    return n; 
12768 +  }
12769 +  // Dimension(0) des tableaux de valeurs aux faces
12770 +  //  (voir convention sur la numerotation des faces)
12771 +  //  les champs associes aux faces des differentes directions sont
12772 +  //  stockes dans les composantes du champ.
12773 +  entier nb_faces() const { return nb_nodes(); }
12774 +  BigEntier compute_memory_size() const
12775 +  { 
12776 +    BigEntier x = 0;
12777 +    const entier n = coord_.size();
12778 +    for (entier i = 0; i < n; i++) 
12779 +      x += memory_size(coord_[i]);
12780 +    return x + memory_size(invalid_positions_) + memory_size(invalid_connections_);
12781 +  }
12782 +
12783 +  // renvoie le nombre de sommets dans la direction dir
12784 +  //  (renvoie 1 si dir >= dimension())
12785 +  entier nb_som_dir(entier dir) const {
12786 +    if (dir >= dimension())
12787 +      return 1;
12788 +    else
12789 +      return coord_[dir].size_array();
12790 +  }
12791 +  // renvoie le nombre d'elements dans la direction dir
12792 +  //  (renvoie 1 si dir >= dimension())
12793 +  entier nb_elem_dir(entier dir) const {
12794 +    if (dir >= dimension())
12795 +      return 1;
12796 +    else
12797 +      return coord_[dir].size_array() - 1;
12798 +  }
12799 +
12800 +  virtual void fill_domain_from_lataDB(const LataDB & lataDB,
12801 +                                       const Domain_Id & id,
12802 +                                       const entier split_in_nparts = 1,
12803 +                                       const entier virt_layer_size = 1);
12804 +  virtual void fill_field_from_lataDB(const LataDB & lataDB,
12805 +                                      const Field_Id & id, 
12806 +                                      LataDeriv<LataField_base> & field) const;
12807 +
12808 +  // when loading fields, we will load elements (i,j,k) with 
12809 +  //   part_begin_ <= k < part_end_
12810 +  // (or j in 2D), part_begin_ and part_end_ include the virtual layer
12811 +  entier part_begin_;
12812 +  entier part_end_;
12813 +  // number of layers of virtual elements at each side:
12814 +  entier virtual_layer_begin_;
12815 +  entier virtual_layer_end_;
12816 +};
12817 +
12818 +template <class TabType>
12819 +class Field : public LataField_base
12820 +{
12821 +public:
12822 +  TabType data_;
12823 +  BigEntier compute_memory_size() const { return memory_size(data_); }
12824 +};
12825 +#endif
12826 diff --git a/databases/readers/Lata/LataV1_field_definitions.C b/databases/readers/Lata/LataV1_field_definitions.C
12827 new file mode 100644
12828 index 0000000..7bb0e2f
12829 --- /dev/null
12830 +++ b/databases/readers/Lata/LataV1_field_definitions.C
12831 @@ -0,0 +1,84 @@
12832 +/*****************************************************************************
12833 +*
12834 +* Copyright (c) 2011 - 2013, CEA
12835 +* All rights reserved.
12836 +* Redistribution and use in source and binary forms, with or without
12837 +* modification, are permitted provided that the following conditions are met:
12838 +*
12839 +*     * Redistributions of source code must retain the above copyright
12840 +*       notice, this list of conditions and the following disclaimer.
12841 +*     * Redistributions in binary form must reproduce the above copyright
12842 +*       notice, this list of conditions and the following disclaimer in the
12843 +*       documentation and/or other materials provided with the distribution.
12844 +*     * Neither the name of CEA, nor the
12845 +*       names of its contributors may be used to endorse or promote products
12846 +*       derived from this software without specific prior written permission.
12847 +*
12848 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
12849 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
12850 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
12851 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
12852 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
12853 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
12854 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
12855 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12856 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
12857 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12858 +*
12859 +*****************************************************************************/
12860 +
12861 +#include <LataV1_field_definitions.h>
12862 +#include <Motcle.h>
12863 +
12864 +typedef struct {
12865 +  const char * name;
12866 +  int shape; // Vector size (-1 => dimension of the problem)
12867 +} StdComponents;
12868 +
12869 +// COMPOSANTES EN MAJUSCULES !!!!!
12870 +// Components are checked in the same order than this array.
12871 +// We assume that the component has been found if component
12872 +// name begins with the string in this array. For example
12873 +// if the lata file contains INDICATRICE_INTERF, we will
12874 +// find that it is an "INDICATRICE" component.
12875 +// Therefore, long names must be placed before short names:
12876 +// If we have a component "K" and a component "K_EPS", then
12877 +// "K_EPS" must be placed before "K", otherwise "K_EPS" will
12878 +// never be found.
12879 +const StdComponents std_components[] =
12880 +  { 
12881 +    { "VITESSE",             -1 },
12882 +    { "primal",              -1 },
12883 +    { "VORTICITE",           -2 },
12884 +    { "MOYENNE_VITESSE",     -1 },
12885 +    { "ECART_TYPE_VITESSE",  -1 },
12886 +    { "MOYENNE_VORTICITE",   -2 },
12887 +    { "ECART_TYPE_VORTICITE", -2 },
12888 +    { "GRADIENT_PRESSION",            -1 },
12889 +    { "DERIVEE_U_ETOILE",             -1 },
12890 +    { "TERME_DIFFUSION_VITESSE",      -1 },
12891 +    { "TERME_CONVECTION_VITESSE",     -1 },
12892 +    { "TERME_SOURCE_VITESSE",         -1 },
12893 +    { "GRAD",         -1 },
12894 +    { "NORMALE_INTERFACE",            -1 },
12895 +    { "K_EPS",                             2 },
12896 +    { "ACCELERATION",        -1 },
12897 +    { "CHAMP_VECTORIEL",     -1},
12898 +    { "2_",     2},
12899 +    { "3_",     3},
12900 +    { "6_",     6},
12901 +    { "9_",     9},
12902 +    { "",                  1 }
12903 +    // Empty label means end of the table
12904 +  };
12905 +
12906 +int latav1_component_shape(const Motcle & compo)
12907 +{
12908 +  entier i = 0;
12909 +  while (std_components[i].name[0] != 0) {
12910 +    if (compo.debute_par(std_components[i].name))
12911 +      return std_components[i].shape;
12912 +    i++;
12913 +  }
12914 +  return 1;
12915 +}
12916 diff --git a/databases/readers/Lata/LataV1_field_definitions.h b/databases/readers/Lata/LataV1_field_definitions.h
12917 new file mode 100644
12918 index 0000000..8aaca6a
12919 --- /dev/null
12920 +++ b/databases/readers/Lata/LataV1_field_definitions.h
12921 @@ -0,0 +1,35 @@
12922 +/*****************************************************************************
12923 +*
12924 +* Copyright (c) 2011 - 2013, CEA
12925 +* All rights reserved.
12926 +* Redistribution and use in source and binary forms, with or without
12927 +* modification, are permitted provided that the following conditions are met:
12928 +*
12929 +*     * Redistributions of source code must retain the above copyright
12930 +*       notice, this list of conditions and the following disclaimer.
12931 +*     * Redistributions in binary form must reproduce the above copyright
12932 +*       notice, this list of conditions and the following disclaimer in the
12933 +*       documentation and/or other materials provided with the distribution.
12934 +*     * Neither the name of CEA, nor the
12935 +*       names of its contributors may be used to endorse or promote products
12936 +*       derived from this software without specific prior written permission.
12937 +*
12938 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
12939 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
12940 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
12941 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
12942 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
12943 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
12944 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
12945 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12946 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
12947 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12948 +*
12949 +*****************************************************************************/
12950 +
12951 +// This file is included in LataDB.cpp (and only there)
12952 +// It contains fields definitions for the old LataV1 format
12953 +// (separated from LataDB.cpp so that changes in this file are
12954 +//  easily identified)
12955 +class Motcle;
12956 +int latav1_component_shape(const Motcle & compo);
12957 diff --git a/databases/readers/Lata/LataVector.h b/databases/readers/Lata/LataVector.h
12958 new file mode 100644
12959 index 0000000..18e46f6
12960 --- /dev/null
12961 +++ b/databases/readers/Lata/LataVector.h
12962 @@ -0,0 +1,64 @@
12963 +/*****************************************************************************
12964 +*
12965 +* Copyright (c) 2011 - 2013, CEA
12966 +* All rights reserved.
12967 +* Redistribution and use in source and binary forms, with or without
12968 +* modification, are permitted provided that the following conditions are met:
12969 +*
12970 +*     * Redistributions of source code must retain the above copyright
12971 +*       notice, this list of conditions and the following disclaimer.
12972 +*     * Redistributions in binary form must reproduce the above copyright
12973 +*       notice, this list of conditions and the following disclaimer in the
12974 +*       documentation and/or other materials provided with the distribution.
12975 +*     * Neither the name of CEA, nor the
12976 +*       names of its contributors may be used to endorse or promote products
12977 +*       derived from this software without specific prior written permission.
12978 +*
12979 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
12980 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
12981 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
12982 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
12983 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
12984 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
12985 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
12986 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12987 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
12988 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12989 +*
12990 +*****************************************************************************/
12991 +
12992 +#ifndef LataVector_H
12993 +#define LataVector_H
12994 +#include <assert.h>
12995 +#include <arch.h>
12996 +// This vector class uses an array of pointers so that objects stored are never
12997 +// moved in memory when the array is resized.
12998 +template <class C>
12999 +class LataVector
13000 +{
13001 +public:
13002 +  LataVector() : n_(0), data_(0) { }
13003 +  LataVector(const LataVector<C> & x) : n_(0), data_(0) { operator=(x); }
13004 +  LataVector(entier n) : n_(0), data_(0) { for (entier i=0; i<n; i++) add(); }
13005 +  ~LataVector() { reset(); }
13006 +  void reset() { for (int i=0; i<n_; i++) { delete data_[i]; }; delete[] data_; n_ = 0; data_ = 0; }
13007 +  const C & operator[](entier i) const { assert(i>=0 && i<n_); return *(data_[i]); }
13008 +  C & operator[](entier i) { assert(i>=0 && i<n_); return *(data_[i]); }
13009 +  C & add(const C & item) { return add_item(new C(item)); }
13010 +  C & add() { return add_item(new C); }
13011 +  entier size() const { return n_; }
13012 +  entier rang(const C & c) const { for (entier i = 0; i < n_; i++) if (*(data_[i]) == c) return i; return -1; }
13013 +  LataVector<C> & operator=(const LataVector<C> & x) { reset(); for (int i=0; i<x.n_; i++) add(x[i]); return *this; }
13014 +private:
13015 +  C & add_item(C* added_item) {
13016 +    C** old = data_; 
13017 +    data_ = new C*[n_+1]; 
13018 +    for (int i=0; i<n_; i++) data_[i] = old[i]; 
13019 +    delete[] old;
13020 +    data_[n_++] = added_item;
13021 +    return *added_item;
13022 +  }
13023 +  entier n_;
13024 +  C** data_;
13025 +};
13026 +#endif
13027 diff --git a/databases/readers/Lata/LataWriter.C b/databases/readers/Lata/LataWriter.C
13028 new file mode 100644
13029 index 0000000..3387570
13030 --- /dev/null
13031 +++ b/databases/readers/Lata/LataWriter.C
13032 @@ -0,0 +1,331 @@
13033 +/*****************************************************************************
13034 +*
13035 +* Copyright (c) 2011 - 2013, CEA
13036 +* All rights reserved.
13037 +* Redistribution and use in source and binary forms, with or without
13038 +* modification, are permitted provided that the following conditions are met:
13039 +*
13040 +*     * Redistributions of source code must retain the above copyright
13041 +*       notice, this list of conditions and the following disclaimer.
13042 +*     * Redistributions in binary form must reproduce the above copyright
13043 +*       notice, this list of conditions and the following disclaimer in the
13044 +*       documentation and/or other materials provided with the distribution.
13045 +*     * Neither the name of CEA, nor the
13046 +*       names of its contributors may be used to endorse or promote products
13047 +*       derived from this software without specific prior written permission.
13048 +*
13049 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
13050 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
13051 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
13052 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
13053 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13054 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
13055 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
13056 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13057 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
13058 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13059 +*
13060 +*****************************************************************************/
13061 +
13062 +#include <LataWriter.h>
13063 +#include <LataStructures.h>
13064 +
13065 +// Path, if not empty, must include a trailing '/'
13066 +// basename must not include the .lata extension
13067 +void LataWriter::init_file(const Nom & path, const Nom & basename,
13068 +                           const LataDBDataType & default_int_format, 
13069 +                           LataDBDataType::Type default_float_type)
13070 +{
13071 +  db_.reset();
13072 +  db_.set_path_prefix(path);
13073 +  basename_ = basename;
13074 +  db_.default_type_int_ = default_int_format;
13075 +  db_.default_float_type_ = default_float_type;
13076 +  db_.header_ = "Lata V2";
13077 +  db_.case_ = "lata2dx";
13078 +  db_.software_id_ = "Trio_U";
13079 +  //split_ = split;
13080 +
13081 +  // Global geometries and fields:
13082 +  db_.add_timestep(0.);
13083 +}
13084 +
13085 +// Add a new timestep to the lata database (new TEMPS entry)
13086 +// Geometries and fields are always written in the last added timestep
13087 +//  (the timestep stored within the domain or field is ignored)
13088 +// Those written before the first call to write_time() go into global
13089 +//  fields and geometry definitions.
13090 +void LataWriter::write_time(double t)
13091 +{
13092 +  db_.add_timestep(t);
13093 +}
13094 +
13095 +void LataWriter::write_geometry(const Domain & dom)
13096 +{
13097 +  // Index of the last timestep:
13098 +  const entier tstep = db_.nb_timesteps() - 1;
13099 +
13100 +  // Build a geometry database entry and add it to database
13101 +  LataDBGeometry geom;
13102 +  geom.name_ = dom.id_.name_;
13103 +  geom.elem_type_ = dom.element_type_to_string(dom.elt_type_);
13104 +  geom.timestep_ = tstep;
13105 +  db_.add_geometry(geom);
13106 +
13107 +  // Write geometry data
13108 +  const DomainUnstructured * dom1_ptr = dynamic_cast<const DomainUnstructured*>(&dom);
13109 +  const DomainIJK * dom2_ptr = dynamic_cast<const DomainIJK*>(&dom);
13110 +  
13111 +  if (dom1_ptr)
13112 +    {
13113 +      // For unstructured meshes, we write the following fields:
13114 +      //  SOMMETS
13115 +      //  ELEMENTS
13116 +      //  [ FACES ]
13117 +      //  [ ELEM_FACES ]
13118 +      const DomainUnstructured & domain = *dom1_ptr;
13119 +      LataDBField field;
13120 +      // Write nodes
13121 +      Nom fieldname = "SOMMETS";
13122 +      field.uname_ = Field_UName(geom.name_, fieldname, "" /* localisation */);
13123 +      field.name_ = fieldname;
13124 +      field.timestep_ = tstep;
13125 +
13126 +      field.filename_ = basename_;
13127 +      field.filename_ += ".lata.";
13128 +      field.filename_ += fieldname;
13129 +      field.filename_ += ".";
13130 +      field.filename_ += geom.name_;
13131 +      if (tstep > 0) { 
13132 +        field.filename_ += ".";
13133 +        field.filename_ += Nom(tstep);
13134 +      }
13135 +      field.nb_comp_ = domain.dimension();
13136 +      field.geometry_ = geom.name_;
13137 +      field.datatype_ = db_.default_type_float();
13138 +      field.localisation_ = "";
13139 +      field.reference_ = "";
13140 +      field.size_ = domain.nb_nodes();
13141 +
13142 +      db_.add_field(field);
13143 +      db_.write_data(tstep, field.uname_, domain.nodes_);
13144 +
13145 +      // Write elements
13146 +      fieldname = "ELEMENTS";
13147 +      field.uname_ = Field_UName(geom.name_, fieldname, "" /* localisation */);
13148 +      field.name_ = fieldname;
13149 +      field.timestep_ = tstep;
13150 +
13151 +      field.filename_ = basename_;
13152 +      field.filename_ += ".lata.";
13153 +      field.filename_ += fieldname;
13154 +      field.filename_ += ".";
13155 +      field.filename_ += geom.name_;
13156 +      if (tstep > 0) { 
13157 +        field.filename_ += ".";
13158 +        field.filename_ += Nom(tstep);
13159 +      }
13160 +      field.nb_comp_ = domain.elements_.dimension(1);
13161 +      field.geometry_ = geom.name_;
13162 +      field.datatype_ = db_.default_type_int_;
13163 +      field.localisation_ = "";
13164 +      field.reference_ = "SOMMETS";
13165 +      field.size_ = domain.nb_elements();
13166 +      
13167 +      db_.add_field(field);
13168 +      db_.write_data(tstep, field.uname_, domain.elements_);
13169 +
13170 +      // Write faces
13171 +      if (domain.faces_ok()) {
13172 +       fieldname = "FACES";
13173 +       field.uname_ = Field_UName(geom.name_, fieldname, "" /* localisation */);
13174 +       field.name_ = fieldname;
13175 +       field.timestep_ = tstep; 
13176 +
13177 +       field.filename_ = basename_;
13178 +       field.filename_ += ".lata.";
13179 +       field.filename_ += fieldname;
13180 +       field.filename_ += ".";
13181 +       field.filename_ += geom.name_;
13182 +       if (tstep > 0) { 
13183 +        field.filename_ += ".";
13184 +        field.filename_ += Nom(tstep);
13185 +       }
13186 +       field.nb_comp_ = domain.faces_.dimension(1);
13187 +       field.geometry_ = geom.name_;
13188 +       field.datatype_ = db_.default_type_int_;
13189 +       field.localisation_ = "";
13190 +       field.reference_ = "SOMMETS";
13191 +       field.size_ = domain.nb_faces();
13192 +      
13193 +       db_.add_field(field);
13194 +       db_.write_data(tstep, field.uname_, domain.faces_);
13195 +
13196 +       fieldname = "ELEM_FACES";
13197 +       field.uname_ = Field_UName(geom.name_, fieldname, "" /* localisation */);
13198 +       field.name_ = fieldname;
13199 +       field.timestep_ = tstep; 
13200 +
13201 +       field.filename_ = basename_;
13202 +       field.filename_ += ".lata.";
13203 +       field.filename_ += fieldname;
13204 +       field.filename_ += ".";
13205 +       field.filename_ += geom.name_;
13206 +       if (tstep > 0) { 
13207 +        field.filename_ += ".";
13208 +        field.filename_ += Nom(tstep);
13209 +       }
13210 +       field.nb_comp_ = domain.elem_faces_.dimension(1);
13211 +       field.geometry_ = geom.name_;
13212 +       field.datatype_ = db_.default_type_int_;
13213 +       field.localisation_ = "";
13214 +       field.reference_ = "FACES";
13215 +       field.size_ = domain.nb_elements();
13216 +      
13217 +       db_.add_field(field);
13218 +       db_.write_data(tstep, field.uname_, domain.elem_faces_);
13219 +     }
13220 +    }
13221 +  else if (dom2_ptr)
13222 +    {
13223 +      // For IJK we write 2 or 3 fields containing 1-dimensionnal arrays with
13224 +      //  the nodes coordinates in each direction:
13225 +      //  SOMMETS_IJK_I, SOMMETS_IJK_J, SOMMETS_IJK_K.
13226 +
13227 +      const DomainIJK & domain = *dom2_ptr;
13228 +      // Write coordinates
13229 +      const entier dim = domain.coord_.size();
13230 +      if (dim > 3) {
13231 +        Journal() << "Error in LataWriter::write_geometry: dimension > 3" << endl;
13232 +        throw InternalError;
13233 +      }
13234 +      Noms dir_names(3);
13235 +      dir_names[0] = "I";
13236 +      dir_names[1] = "J";
13237 +      dir_names[2] = "K";
13238 +      for (entier i_dim = 0; i_dim < dim; i_dim++) {
13239 +        FloatTab coord;
13240 +        {
13241 +          const ArrOfFloat & x = domain.coord_[i_dim];
13242 +          const entier n = x.size_array();
13243 +          coord.resize(n, 1);
13244 +          for (entier i = 0; i < n; i++)
13245 +            coord(i, 0) = x[i];
13246 +        }
13247 +        
13248 +        Nom fieldname = "SOMMETS_IJK_";
13249 +        fieldname += dir_names[i_dim];
13250 +        LataDBField field;
13251 +        field.uname_ = Field_UName(geom.name_, fieldname, "" /* localisation */);
13252 +        field.name_ = fieldname;
13253 +        field.timestep_ = tstep;
13254 +
13255 +        field.filename_ = basename_;
13256 +        field.filename_ += ".lata.";
13257 +        field.filename_ += fieldname;
13258 +        field.filename_ += ".";
13259 +        field.filename_ += geom.name_;
13260 +        if (tstep > 0) { 
13261 +          field.filename_ += ".";
13262 +          field.filename_ += Nom(tstep);
13263 +        }
13264 +        field.nb_comp_ = 1;
13265 +        field.geometry_ = geom.name_;
13266 +        field.datatype_ = db_.default_type_float();
13267 +        field.localisation_ = "";
13268 +        field.reference_ = "";
13269 +        field.size_ = coord.dimension(0);
13270 +
13271 +        db_.add_field(field);
13272 +        db_.write_data(tstep, field.uname_, coord);
13273 +      }
13274 +      
13275 +      if (domain.invalid_connections_.size_array() > 0) {
13276 +        const entier n = domain.invalid_connections_.size_array();
13277 +        IntTab tmp(n, 1);
13278 +        for (entier i = 0; i < n; i++) 
13279 +          tmp(i, 0) = domain.invalid_connections_[i];
13280 +
13281 +        Nom fieldname = "INVALID_CONNECTIONS";
13282 +        LataDBField field;
13283 +        field.uname_ = Field_UName(geom.name_, fieldname, "ELEM" /* localisation */);
13284 +        field.name_ = fieldname;
13285 +        field.timestep_ = tstep;
13286 +
13287 +        field.filename_ = basename_;
13288 +        field.filename_ += ".lata.";
13289 +        field.filename_ += fieldname;
13290 +        field.filename_ += ".";
13291 +        field.filename_ += geom.name_;
13292 +        if (tstep > 0) { 
13293 +          field.filename_ += ".";
13294 +          field.filename_ += Nom(tstep);
13295 +        }
13296 +        field.nb_comp_ = 1;
13297 +        field.geometry_ = geom.name_;
13298 +        field.datatype_ = db_.default_type_int_;
13299 +        field.datatype_.array_index_ = LataDBDataType::NOT_AN_INDEX;
13300 +        field.localisation_ = "ELEM";
13301 +        field.reference_ = "";
13302 +        field.size_ = n;
13303 +
13304 +        db_.add_field(field);
13305 +        db_.write_data(tstep, field.uname_, tmp);
13306 +      }
13307 +    }
13308 +  else
13309 +    {
13310 +      Journal() << "Error LataWriter::write_geometry domain type not supported" << endl;
13311 +      throw InternalError;
13312 +    }
13313 +}
13314 +
13315 +void LataWriter::write_component(const LataField_base & field)
13316 +{
13317 +  // Index of the last timestep:
13318 +  const entier tstep = db_.nb_timesteps() - 1;
13319 +  
13320 +  LataDBField lata_field;
13321 +  
13322 +  lata_field.uname_ = field.id_.uname_;
13323 +  lata_field.name_ = field.id_.uname_.get_field_name();
13324 +  lata_field.timestep_ = tstep;
13325 +  lata_field.filename_ = basename_;
13326 +  lata_field.filename_ += ".lata.";
13327 +  lata_field.filename_ += lata_field.uname_.build_string();
13328 +  if (tstep > 0) { 
13329 +    lata_field.filename_ += ".";
13330 +    lata_field.filename_ += Nom(tstep);
13331 +  }
13332 +  lata_field.geometry_ = field.id_.uname_.get_geometry();
13333 +  lata_field.component_names_ = field.component_names_;
13334 +  // Unites a remplir
13335 +  // Size = -1 => valeur par defaut cherchee dans la geometrie
13336 +  lata_field.localisation_ = LataField_base::localisation_to_string(field.localisation_);
13337 +  lata_field.nature_ = field.nature_;
13338 +
13339 +  const Field<FloatTab> * float_f = dynamic_cast<const Field<FloatTab>*>(&field);
13340 +  const Field<IntTab>* int_f = dynamic_cast<const Field<IntTab>*>(&field);
13341 +  if (int_f) {
13342 +    lata_field.nb_comp_ = int_f->data_.dimension(1);
13343 +    lata_field.size_ = int_f->data_.dimension(0);
13344 +    lata_field.datatype_ = db_.default_type_int_;
13345 +    lata_field.datatype_.array_index_ = LataDBDataType::NOT_AN_INDEX;
13346 +    db_.add_field(lata_field);
13347 +    db_.write_data(tstep, lata_field.uname_, int_f->data_);
13348 +  } else if (float_f) {
13349 +    lata_field.nb_comp_ = float_f->data_.dimension(1);
13350 +    lata_field.size_ = float_f->data_.dimension(0);
13351 +    lata_field.datatype_ = db_.default_type_float();
13352 +    db_.add_field(lata_field);
13353 +    db_.write_data(tstep, lata_field.uname_, float_f->data_);
13354 +  }
13355 +}
13356 +
13357 +void LataWriter::finish()
13358 +{
13359 +  Nom n(db_.path_prefix());
13360 +  n += basename_;
13361 +  n += ".lata";
13362 +  db_.write_master_file(n);
13363 +}
13364 diff --git a/databases/readers/Lata/LataWriter.h b/databases/readers/Lata/LataWriter.h
13365 new file mode 100644
13366 index 0000000..d17c413
13367 --- /dev/null
13368 +++ b/databases/readers/Lata/LataWriter.h
13369 @@ -0,0 +1,61 @@
13370 +/*****************************************************************************
13371 +*
13372 +* Copyright (c) 2011 - 2013, CEA
13373 +* All rights reserved.
13374 +* Redistribution and use in source and binary forms, with or without
13375 +* modification, are permitted provided that the following conditions are met:
13376 +*
13377 +*     * Redistributions of source code must retain the above copyright
13378 +*       notice, this list of conditions and the following disclaimer.
13379 +*     * Redistributions in binary form must reproduce the above copyright
13380 +*       notice, this list of conditions and the following disclaimer in the
13381 +*       documentation and/or other materials provided with the distribution.
13382 +*     * Neither the name of CEA, nor the
13383 +*       names of its contributors may be used to endorse or promote products
13384 +*       derived from this software without specific prior written permission.
13385 +*
13386 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
13387 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
13388 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
13389 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
13390 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13391 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
13392 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
13393 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13394 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
13395 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13396 +*
13397 +*****************************************************************************/
13398 +
13399 +#ifndef LataWriter_H
13400 +#define LataWriter_H
13401 +#include <LataDB.h>
13402 +class Domain;
13403 +class LataField_base;
13404 +
13405 +// This class provides general services to write lata files
13406 +//  from the "high level" objects Domain and Field (the LataDB class provides
13407 +//  only low level services to write arrays)
13408 +class LataWriter
13409 +{
13410 +public:
13411 +  enum FileSplittingOption { MULTIPLE_FILES, SINGLE_FILE };
13412 +  void init_file(const Nom & path, const Nom & basename,
13413 +                 const LataDBDataType & default_int_format, 
13414 +                 LataDBDataType::Type default_float_type);
13415 +
13416 +  void write_time(double t);
13417 +  void write_geometry(const Domain & dom);
13418 +  void write_component(const LataField_base & field);
13419 +
13420 +  void finish();
13421 +  enum ERRORS { InternalError };
13422 +
13423 +protected:
13424 +  // This is the database where we put all data...
13425 +  LataDB db_;
13426 +  // Basename for files and lata master file:
13427 +  Nom basename_;
13428 +  // FileSplittingOption split_;
13429 +};
13430 +#endif
13431 diff --git a/databases/readers/Lata/Lata_tools.C b/databases/readers/Lata/Lata_tools.C
13432 new file mode 100644
13433 index 0000000..fb97479
13434 --- /dev/null
13435 +++ b/databases/readers/Lata/Lata_tools.C
13436 @@ -0,0 +1,128 @@
13437 +/*****************************************************************************
13438 +*
13439 +* Copyright (c) 2011 - 2013, CEA
13440 +* All rights reserved.
13441 +* Redistribution and use in source and binary forms, with or without
13442 +* modification, are permitted provided that the following conditions are met:
13443 +*
13444 +*     * Redistributions of source code must retain the above copyright
13445 +*       notice, this list of conditions and the following disclaimer.
13446 +*     * Redistributions in binary form must reproduce the above copyright
13447 +*       notice, this list of conditions and the following disclaimer in the
13448 +*       documentation and/or other materials provided with the distribution.
13449 +*     * Neither the name of CEA, nor the
13450 +*       names of its contributors may be used to endorse or promote products
13451 +*       derived from this software without specific prior written permission.
13452 +*
13453 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
13454 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
13455 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
13456 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
13457 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13458 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
13459 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
13460 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13461 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
13462 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13463 +*
13464 +*****************************************************************************/
13465 +
13466 +#include <Lata_tools.h>
13467 +#include <ArrOfInt.h>
13468 +#include <ArrOfDouble.h>
13469 +#include <ArrOfFloat.h>
13470 +#include <ArrOfBit.h>
13471 +#include <sstream>
13472 +#include <string.h>
13473 +#include <stdlib.h>
13474 +
13475 +static int journal_level = 0;
13476 +
13477 +void set_Journal_level(entier level)
13478 +{
13479 +  if (journal_level==level) return;
13480 +  journal_level = level;
13481 +  Journal() << "Changed lata journal level: " << journal_level << endl;
13482 +}
13483 +
13484 +static std::ostringstream junk_journal;
13485 +
13486 +std::ostream & Journal(entier level)
13487 +{
13488 +  if (level <= journal_level) {
13489 +    cerr << "[" << level << "] ";
13490 +    return cerr;
13491 +  } else {
13492 +    junk_journal.seekp(0);
13493 +    return junk_journal;
13494 +  }
13495 +}
13496 +
13497 +// Description: this method must return the total memory consumption
13498 +//  of the object (used to compute the size of the data cache)
13499 +BigEntier LataObject::compute_memory_size() const
13500 +{
13501 +  Journal() << "Error in LataObject::compute_memory_size(): function not implemented" << endl;
13502 +  throw;
13503 +}
13504 +
13505 +BigEntier memory_size(const ArrOfInt & tab)
13506 +{
13507 +  // On ne tient pas compte du caractere smart_resize ou ref du tableau
13508 +  // c'est pas tres grave pour l'instant pour ce qu'on en fait...
13509 +  return ((BigEntier)sizeof(tab)) + ((BigEntier)tab.size_array()) * sizeof(entier);
13510 +}
13511 +
13512 +BigEntier memory_size(const ArrOfDouble & tab)
13513 +{
13514 +  // on ne tient pas compte du caractere smart_resize ou ref du tableau
13515 +  // c'est pas tres grave pour l'instant pour ce qu'on en fait...
13516 +  return ((BigEntier)sizeof(tab)) + ((BigEntier)tab.size_array()) * sizeof(double);
13517 +}
13518 +
13519 +BigEntier memory_size(const ArrOfFloat & tab)
13520 +{
13521 +  // on ne tient pas compte du caractere smart_resize ou ref du tableau
13522 +  // c'est pas tres grave pour l'instant pour ce qu'on en fait...
13523 +  return ((BigEntier)sizeof(tab)) + ((BigEntier)tab.size_array()) * sizeof(float);
13524 +}
13525 +
13526 +BigEntier memory_size(const ArrOfBit & tab)
13527 +{
13528 +  return ((BigEntier)sizeof(tab)) + ((BigEntier)tab.size_array()) * sizeof(int) / 32; 
13529 +}
13530 +
13531 +void split_path_filename(const char *s, Nom & path, Nom & filename)
13532 +{
13533 +  int i;
13534 +  for (i=(int)strlen(s)-1;i>=0;i--)
13535 +    if ((s[i]==PATH_SEPARATOR) || (s[i]=='\\'))
13536 +      break;
13537 +  path = "";
13538 +  int j;
13539 +  for (j = 0; j <= i; j++)
13540 +    path += Nom(s[j]);
13541 +  
13542 +  // Parse basename : if extension given, remove it
13543 +  filename = s+i+1;
13544 +}
13545 +
13546 +static const ArrOfInt * array_to_sort_ptr = 0;
13547 +int compare_indirect(const void *ptr1, const void *ptr2)
13548 +{
13549 +  entier i1 = *(const entier*)ptr1;
13550 +  entier i2 = *(const entier*)ptr2;
13551 +  entier diff = (*array_to_sort_ptr)[i1] - (*array_to_sort_ptr)[i2];
13552 +  return (diff>0) ? 1 : ((diff==0) ? 0 : -1);
13553 +}
13554 +
13555 +void array_sort_indirect(const ArrOfInt & array_to_sort, ArrOfInt & index)
13556 +{
13557 +  const entier n = array_to_sort.size_array();
13558 +  index.set_smart_resize(1);
13559 +  index.resize_array(n);
13560 +  for (entier i = 0; i < n; i++)
13561 +    index[i] = i;
13562 +  array_to_sort_ptr = &array_to_sort;
13563 +  qsort(index.addr(), n, sizeof(entier), compare_indirect);
13564 +}
13565 diff --git a/databases/readers/Lata/Lata_tools.h b/databases/readers/Lata/Lata_tools.h
13566 new file mode 100644
13567 index 0000000..940fc54
13568 --- /dev/null
13569 +++ b/databases/readers/Lata/Lata_tools.h
13570 @@ -0,0 +1,194 @@
13571 +/*****************************************************************************
13572 +*
13573 +* Copyright (c) 2011 - 2013, CEA
13574 +* All rights reserved.
13575 +* Redistribution and use in source and binary forms, with or without
13576 +* modification, are permitted provided that the following conditions are met:
13577 +*
13578 +*     * Redistributions of source code must retain the above copyright
13579 +*       notice, this list of conditions and the following disclaimer.
13580 +*     * Redistributions in binary form must reproduce the above copyright
13581 +*       notice, this list of conditions and the following disclaimer in the
13582 +*       documentation and/or other materials provided with the distribution.
13583 +*     * Neither the name of CEA, nor the
13584 +*       names of its contributors may be used to endorse or promote products
13585 +*       derived from this software without specific prior written permission.
13586 +*
13587 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
13588 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
13589 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
13590 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
13591 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13592 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
13593 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
13594 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13595 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
13596 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13597 +*
13598 +*****************************************************************************/
13599 +
13600 +#ifndef Lata_tools_include_
13601 +#define Lata_tools_include_
13602 +#include <assert.h>
13603 +#include <arch.h>
13604 +
13605 +
13606 +
13607 +
13608 +
13609 +#ifdef WIN32
13610 +#define __BIG_ENDIAN    111
13611 +#define __LITTLE_ENDIAN 121
13612 +#define __BYTE_ORDER __LITTLE_ENDIAN
13613 +
13614 +#define strtoll _strtoi64
13615 +// This must be able to contain a total memory size
13616 +// or a very big operation counter.
13617 +typedef __int64 BigEntier;
13618 +
13619 +#else
13620 +#ifdef __APPLE__
13621 +// Assume we only have x86, x86_64 based Macs.
13622 +#define __BIG_ENDIAN    111
13623 +#define __LITTLE_ENDIAN 121
13624 +#define __BYTE_ORDER __LITTLE_ENDIAN
13625 +#endif
13626 +
13627 +// This must be able to contain a total memory size
13628 +// or a very big operation counter.
13629 +typedef long long BigEntier;
13630 +#endif
13631 +
13632 +#ifndef __BYTE_ORDER
13633 +#include <endian.h>
13634 +#endif
13635 +
13636 +#include <LataVector.h>
13637 +
13638 +
13639 +#define PATH_SEPARATOR '/'
13640 +
13641 +#ifndef __BYTE_ORDER
13642 +#error "Byte order not defined."
13643 +#endif
13644 +#if (__BYTE_ORDER == __BIG_ENDIAN)
13645 +const bool mymachine_msb =  true;
13646 +#elif (__BYTE_ORDER == __LITTLE_ENDIAN)
13647 +const bool mymachine_msb =  false;
13648 +#else
13649 +#error "Byte order is neither __BIG_ENDIAN nor __LITTLE_ENDIAN : "
13650 +#endif
13651 +
13652 +class ArrOfInt;
13653 +class ArrOfDouble;
13654 +class ArrOfFloat;
13655 +class ArrOfBit;
13656 +BigEntier memory_size(const ArrOfInt &);
13657 +BigEntier memory_size(const ArrOfDouble &);
13658 +BigEntier memory_size(const ArrOfFloat &);
13659 +BigEntier memory_size(const ArrOfBit &);
13660 +
13661 +class LataObject
13662 +{
13663 +public:
13664 +  virtual ~LataObject() {};
13665 +  virtual BigEntier compute_memory_size() const;
13666 +};
13667 +
13668 +// A 'LataDeriv<X> ptr' object can hold an object of class Y which is any derived type of X.
13669 +// The contained object can be accessed via "valeur()" (you get an object of type X)
13670 +//   or "refcast()" (get an object of any derived type Z between X and Y)
13671 +//   (refcast() throws an exception if you try to cast with a wrong type)
13672 +// It can also be null (hold no object). valeur() will then throw an exception.
13673 +// Example:
13674 +//  LataDeriv<X> deriv_x;
13675 +//  Y & y = deriv_x.instancie(Y); // Creates an instance of type Y within deriv_x
13676 +//  X & x = deriv_x.valeur(); // Get a reference to the contained object
13677 +//  Y & y2 = deriv_x.refcast(Y); // Same, but you get a reference of type Y
13678 +//  Z & z = deriv_x.refcast(Z); // Throw an exception if Z is not a derived class of X and a base class of Y
13679 +//  x.reset(); // Destroys the contained object (also destroyed when deriv_x is destroyed)
13680 +#define instancie(x) instancie_(new x)
13681 +#define refcast(x) refcast_((x*) 0)
13682 +
13683 +template <class C>
13684 +class LataDeriv : public LataObject
13685 +{
13686 +public:
13687 +  enum DERIV_ERROR { ERROR_TYPE, ERROR_NULL };
13688 +  LataDeriv() : ptr_(0) { };
13689 +  ~LataDeriv() { delete ptr_; ptr_ = 0; }
13690 +  void reset() { delete ptr_; ptr_ = 0; }
13691 +  entier non_nul() const { return ptr_ != 0; }
13692 +  // operator C &() { return valeur(); }
13693 +  // operator const C &() const { return valeur(); }
13694 +  C & valeur() { if (!ptr_) throw ERROR_NULL; return *ptr_; }
13695 +  const C & valeur() const { if (!ptr_) throw ERROR_NULL; return *ptr_; }
13696 +  template<class DER_C> DER_C & instancie_(DER_C *ptr) {
13697 +    reset();
13698 +    ptr_ = ptr;
13699 +    if (!dynamic_cast<C*>(ptr_)) {
13700 +      delete ptr_;
13701 +      throw ERROR_TYPE; // DER_C is not a derived type of C
13702 +    }
13703 +    return (DER_C &) (*ptr_); 
13704 +  }
13705 +  template<class DER_C> DER_C & refcast_(DER_C *cast_type) {
13706 +    if (!ptr_)
13707 +      throw ERROR_NULL;
13708 +    DER_C * x = dynamic_cast<DER_C *>(ptr_);
13709 +    if (!x)
13710 +      throw ERROR_TYPE;
13711 +    return *x;
13712 +  }
13713 +  BigEntier compute_memory_size() const { if (ptr_) return ptr_->compute_memory_size(); else return 0; }
13714 +protected:
13715 +  LataDeriv(const LataDeriv<C> & c) { ptr_ = 0; operator=(c); }
13716 +  LataDeriv(const C & c) { ptr_ = 0; operator=(c); }
13717 +  LataDeriv<C> & operator=(const LataDeriv<C> &);
13718 +  LataDeriv<C> & operator=(const C &);
13719 +  C *ptr_;
13720 +};
13721 +
13722 +// This is a reference to an object of type C, but thr reference can be null
13723 +template<class C>
13724 +class LataRef
13725 +{
13726 +public:
13727 +  enum REF_ERROR { ERROR_NULL };
13728 +  LataRef() : ptr_(0) { }
13729 +  ~LataRef() { ptr_ = 0; }
13730 +  LataRef(const LataRef<C> & x) : ptr_(x.ptr_) { }
13731 +  LataRef(C & x) : ptr_(&x) { }
13732 +  LataRef<C> & operator=(LataRef<C> & x) { ptr_ = x.ptr_; return *this; }
13733 +  LataRef<C> & operator=(C & x) { ptr_ = &x; return *this; }
13734 +  void reset() { ptr_ = 0; }
13735 +  operator C&() { if (!ptr_) throw ERROR_NULL; return *ptr_; }  
13736 +  C& valeur() { if (!ptr_) throw ERROR_NULL; return *ptr_; }  
13737 +  entier non_nul() const { return ptr_ != 0; }
13738 +protected:
13739 +  C *ptr_;
13740 +};
13741 +
13742 +void array_sort_indirect(const ArrOfInt & array_to_sort, ArrOfInt & index);
13743 +
13744 +class Nom;
13745 +void split_path_filename(const char *full_name, Nom & path, Nom & filename);
13746 +
13747 +// To optimize small loops: replace for(i=0;i<n;i++) with n<=3 by
13748 +//  for (i=0; i<loop_max(n,3); i++) {
13749 +//    loop_instructions();...
13750 +//    break_loop(i,n);
13751 +//  }
13752 +#define loop_max(nloops,max) max
13753 +#define break_loop(index,nloops) if (index >= nloops-1) break
13754 +
13755 +#include <LataJournal.h>
13756 +#include <Motcle.h>
13757 +#include <Noms.h>
13758 +#include <DoubleTab.h>
13759 +#include <IntTab.h>
13760 +#include <FloatTab.h>
13761 +
13762 +Motcles noms_to_motcles(const Noms & noms);
13763 +
13764 +#endif
13765 diff --git a/databases/readers/Lata/LmlReader.C b/databases/readers/Lata/LmlReader.C
13766 new file mode 100644
13767 index 0000000..1b1b7d2
13768 --- /dev/null
13769 +++ b/databases/readers/Lata/LmlReader.C
13770 @@ -0,0 +1,435 @@
13771 +/*****************************************************************************
13772 +*
13773 +* Copyright (c) 2011 - 2013, CEA
13774 +* All rights reserved.
13775 +* Redistribution and use in source and binary forms, with or without
13776 +* modification, are permitted provided that the following conditions are met:
13777 +*
13778 +*     * Redistributions of source code must retain the above copyright
13779 +*       notice, this list of conditions and the following disclaimer.
13780 +*     * Redistributions in binary form must reproduce the above copyright
13781 +*       notice, this list of conditions and the following disclaimer in the
13782 +*       documentation and/or other materials provided with the distribution.
13783 +*     * Neither the name of CEA, nor the
13784 +*       names of its contributors may be used to endorse or promote products
13785 +*       derived from this software without specific prior written permission.
13786 +*
13787 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
13788 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
13789 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
13790 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
13791 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13792 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
13793 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
13794 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13795 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
13796 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13797 +*
13798 +*****************************************************************************/
13799 +
13800 +#define BUFSZ 1000
13801 +#include <iostream>
13802 +#include <EFichier.h>
13803 +#include <LataDB.h>
13804 +#include <LataFilter.h>
13805 +#include <stdlib.h>
13806 +#include <string.h>
13807 +// lml files contain double precision values that can overflow or underflow
13808 +//  if converted to float. Check for overflow, ignore underflow
13809 +static inline float double_to_float(double x)
13810 +{
13811 +  // Written like this, the code will also stop on NAN values:
13812 +  if (!(x < 1.e38 && x > -1.e38)) {
13813 +    Journal() << "lml reader: Error converting double value " << x << " to float" << endl;
13814 +    throw LataDBError(LataDBError::READ_ERROR);
13815 +  }
13816 +  return (float) x;
13817 +}
13818 +
13819 +// Reads the lml file, fills the lata_db and writes the data (coordinates, elements and
13820 +//  fields data) to a unique file data_filename.
13821 +// The default format used to write data in the data_filename is lata_db.default_type_*
13822 +// data_filename must not contain the path but only a filename with extension.
13823 +// The path to the data file must be set by lata_db.set_path_prefix() before.
13824 +// If data_filename is a null pointer, data files are not written and file offsets in lata_db will
13825 +//  be wrong (useful for just getting metadata)
13826 +void lml_reader(const char * lmlfilename, const char * data_filename, LataDB & lata_db)
13827 +{
13828 +  Nom filename_in_master_file;
13829 +  if (!data_filename)
13830 +    filename_in_master_file = "DATA_NOT_WRITTEN";
13831 +  else
13832 +    filename_in_master_file = data_filename;
13833 +  
13834 +  const entier lmllevel=4;
13835 +  EFichier is;
13836 +  Journal(lmllevel) << "lml_reader: " << endl;
13837 +  is.ouvrir(lmlfilename);
13838 +  if (!is.good()) {
13839 +    Journal() << "Error: cannot open lml file " << lmlfilename << endl;
13840 +    throw;
13841 +  }
13842 +  char s[BUFSZ+1];
13843 +  is.get_istream().getline(s, BUFSZ);
13844 +  if (!is.good()) {
13845 +    Journal() << "Lml file " << lmlfilename << " is empty" << endl;
13846 +    // Just put an empty initial timestep:
13847 +    lata_db.add_timestep(-1.);
13848 +    return;
13849 +  }
13850 +  lata_db.header_ = s;
13851 +  Journal(lmllevel) << "Header: " << s << endl;
13852 +  is.get_istream().getline(s, BUFSZ);
13853 +  lata_db.case_ = s;
13854 +  Journal(lmllevel) << "Case: " << s << endl;
13855 +  is.get_istream().getline(s, BUFSZ);
13856 +  lata_db.software_id_ = s;
13857 +  Journal(lmllevel) << "Software_id: " << s << endl;
13858 +
13859 +  Noms liste_noms_geoms;
13860 +  Noms liste_noms_topo;
13861 +  // Create first timestep (global definitions)
13862 +  lata_db.add_timestep(-1.);
13863 +  // file_offset_blurb:
13864 +  // the file offset will be computed by LataDB::write_data(),
13865 +  // but we must tell write_data() if it must put the data at the beginning
13866 +  //  (file_offset==0) or append the data at the end of the file (file_offset!=0)
13867 +  // file_offset is 0 for the first data block and it is incremented for each block.
13868 +  entier file_offset = 0;
13869 +  LataDBField sommets;
13870 +  FloatTab nodes;
13871 +  while(1) {
13872 +    const entier tstep = lata_db.nb_timesteps() - 1;
13873 +    Motcle motlu;
13874 +    is >> motlu;
13875 +    if (!is.good()) break;
13876 +    if (motlu == "GRILLE") {
13877 +      LataDBGeometry geom;
13878 +      sommets.name_ = "SOMMETS";
13879 +      geom.timestep_ = sommets.timestep_ = tstep;
13880 +      sommets.filename_ = filename_in_master_file;
13881 +      Nom mottmp;
13882 +      is >> mottmp;
13883 +      geom.name_ = ((const char*)mottmp)+7; // retire GRILLE_ du nom
13884 +      Journal(lmllevel) << "lml_reader: GRILLE " << geom.name_ << endl;
13885 +      is >> sommets.nb_comp_;
13886 +      {
13887 +       int tmp;
13888 +       is >> tmp; 
13889 +       sommets.size_ = tmp; // size_ est long long...
13890 +      }
13891 +      if (!is.good())
13892 +        throw LataDBError(LataDBError::READ_ERROR);
13893 +      sommets.geometry_ = geom.name_;
13894 +      sommets.uname_ = Field_UName(sommets.geometry_, sommets.name_, "");
13895 +      sommets.datatype_ = lata_db.default_type_float();
13896 +      sommets.datatype_.file_offset_ = file_offset++; // see file_offset_blurb
13897 +      nodes.resize(sommets.size_, sommets.nb_comp_);
13898 +      for (entier i = 0; i < sommets.size_; i++)
13899 +        for (entier j = 0; j < sommets.nb_comp_; j++) {
13900 +          double x;
13901 +          is >> x;
13902 +          if (!is.good())
13903 +            throw LataDBError(LataDBError::READ_ERROR);
13904 +          nodes(i,j) = double_to_float(x);
13905 +        }
13906 +      Journal(lmllevel+1) << "Finished reading nodes" << endl;
13907 +      
13908 +      lata_db.add_geometry(geom);
13909 +      // Write nodes to disk later: in 2D they will be cropped
13910 +    } else if (motlu == "TOPOLOGIE") {
13911 +      LataDBField elements;
13912 +      elements.name_ = "ELEMENTS";
13913 +      elements.timestep_ = tstep;
13914 +      elements.filename_ = filename_in_master_file;
13915 +      elements.datatype_ = lata_db.default_type_int_;
13916 +      elements.datatype_.file_offset_ = file_offset++; // see file_offset_blurb
13917 +      Nom ident;
13918 +      is >> ident; // Topologie_MAILLAGE_VOLUMIQUE_XXX
13919 +      Nom mottmp;
13920 +      is >> mottmp;
13921 +      if (!is.good())
13922 +        throw LataDBError(LataDBError::READ_ERROR);
13923 +      elements.geometry_ = ((const char*)mottmp)+7; // retire GRILLE_ du nom
13924 +      elements.uname_ = Field_UName(elements.geometry_, elements.name_, "");
13925 +      liste_noms_geoms.add(elements.geometry_);
13926 +      liste_noms_topo.add(ident);
13927 +      is >> motlu;
13928 +      if (motlu != "MAILLE") {
13929 +        Journal() << "Error reading TOPOLOGIE: expected MAILLE" << endl;
13930 +        throw;
13931 +      }
13932 +      {
13933 +       int tmp;
13934 +       is >> tmp; // size_ est long long...
13935 +       elements.size_ = tmp;
13936 +      }
13937 +      is >> motlu;
13938 +      int borne_index_min=0;
13939 +      if (motlu == "TETRA4") {
13940 +        lata_db.set_elemtype(tstep, elements.geometry_, "TETRAEDRE");
13941 +        elements.nb_comp_ = 4;
13942 +      } else if (motlu == "TRIANGLE_3D") {
13943 +        elements.nb_comp_ = 3;
13944 +        lata_db.set_elemtype(tstep, elements.geometry_, "TRIANGLE_3D");
13945 +      } else if (motlu == "QUADRANGLE_3D") {
13946 +        elements.nb_comp_ = 4;
13947 +        lata_db.set_elemtype(tstep, elements.geometry_, "QUADRANGLE_3D");
13948 +      } else if (motlu == "VOXEL8") {
13949 +        elements.nb_comp_ = 8;
13950 +        lata_db.set_elemtype(tstep, elements.geometry_, "HEXAEDRE");
13951 +      } else if (motlu == "SEGMENT") {
13952 +        elements.nb_comp_ = 2;
13953 +        lata_db.set_elemtype(tstep, elements.geometry_, "SEGMENT");
13954 +      } else if (motlu == "POINT") {
13955 +        elements.nb_comp_ = 1;
13956 +        lata_db.set_elemtype(tstep, elements.geometry_, "POINT");
13957 +      } else if (motlu == "PRISM6") {
13958 +        lata_db.set_elemtype(tstep, elements.geometry_, "PRISM6");
13959 +        elements.nb_comp_ = 6;
13960 +      } else if (motlu.debute_par("POLYEDRE_")) {
13961 +        lata_db.set_elemtype(tstep, elements.geometry_, motlu);
13962 +        elements.nb_comp_ = atoi(((const char *)motlu) + strlen("polyedre_"));
13963 +        borne_index_min=-1;
13964 +      } else if (motlu.debute_par("POLYGONE_")) {
13965 +        lata_db.set_elemtype(tstep, elements.geometry_, motlu);
13966 +        elements.nb_comp_ = atoi(((const char *)motlu) + strlen("polygone_"));
13967 +        borne_index_min=-1;
13968 +      } else {
13969 +        Journal() << "Error reading TOPOLOGIE: unknown element type" << endl;
13970 +        throw;
13971 +      }
13972 +
13973 +      Journal(lmllevel+1) << " " << elements.size_ << " elements " << motlu << endl;
13974 +      IntTab elems;
13975 +      elems.resize(elements.size_, elements.nb_comp_);
13976 +      for (entier i = 0; i < elements.size_; i++) {
13977 +        if (i != 0) {
13978 +          is >> motlu; // element type
13979 +          if (!is.good())
13980 +            throw LataDBError(LataDBError::READ_ERROR);
13981 +        }
13982 +        entier j;
13983 +        for (j = 0; j < elements.nb_comp_; j++) {
13984 +          is >> elems(i,j);
13985 +          if (!is.good())
13986 +            throw LataDBError(LataDBError::READ_ERROR);
13987 +          elems(i,j)--;
13988 +          if (elems(i,j) < borne_index_min || elems(i,j) >= sommets.size_ ) {
13989 +            Journal() << "Error reading TOPOLOGIE: bad node number elem(" << i << "," << j << ")=" << elems(i,j) << endl;
13990 +            throw;
13991 +          }
13992 +        }
13993 +      }
13994 +      Journal(lmllevel+1) << " finished reading elements" << endl;
13995 +      lata_db.add_field(sommets);
13996 +      if (data_filename)
13997 +        lata_db.write_data(tstep, sommets.uname_, nodes);
13998 +      lata_db.add_field(elements);
13999 +      if (data_filename)
14000 +        lata_db.write_data(tstep, elements.uname_, elems);
14001 +    } else if (motlu == "FACE") {
14002 +      int n;
14003 +      is >> n;
14004 +      if (!is.good())
14005 +        throw LataDBError(LataDBError::READ_ERROR);
14006 +      Journal(lmllevel+1) << " faces " << n << endl;      
14007 +    } else if (motlu == "TEMPS") {
14008 +      double t;
14009 +      is >> t;
14010 +      if (!is.good())
14011 +        throw LataDBError(LataDBError::READ_ERROR);
14012 +      lata_db.add_timestep(t);
14013 +      Journal(lmllevel+1) << " new time: " << t << endl;      
14014 +    } else if (motlu == "CHAMPMAILLE" || motlu == "CHAMPPOINT") {
14015 +      LataDBField field;
14016 +      is >> field.name_;
14017 +      if (!is.good())
14018 +        throw LataDBError(LataDBError::READ_ERROR);
14019 +      Journal(lmllevel+1) << " new field: " << field.name_ << endl;      
14020 +      field.timestep_ = tstep;
14021 +      field.filename_ = filename_in_master_file;
14022 +      if (motlu == "CHAMPMAILLE")
14023 +        field.localisation_ = "ELEM";
14024 +      else
14025 +        field.localisation_ ="SOM";
14026 +      Nom nom_topo;
14027 +      is >> nom_topo;
14028 +      if (!is.good())
14029 +        throw LataDBError(LataDBError::READ_ERROR);
14030 +
14031 +      const entier rang_topo = liste_noms_topo.rang(nom_topo);
14032 +      if (rang_topo < 0) {
14033 +        Journal() << "Error reading lml file : unknown topology name " << nom_topo << endl;
14034 +        throw;
14035 +      }
14036 +      field.geometry_ = liste_noms_geoms[rang_topo];
14037 +      Motcle mottmp(field.name_);
14038 +      Motcle tmp2("_");
14039 +      tmp2 += field.localisation_;
14040 +      tmp2 += "_";
14041 +      tmp2 += field.geometry_;
14042 +      mottmp.prefix(tmp2); // Retire _SOM_dom du nom
14043 +      field.name_ = mottmp;
14044 +      field.uname_ = Field_UName(field.geometry_, field.name_, field.localisation_);
14045 +      double t;
14046 +      is >> t; // Unused time value
14047 +      if (!is.good())
14048 +        throw LataDBError(LataDBError::READ_ERROR);
14049 +      is >> motlu; // Repeat fieldname
14050 +      if (!is.good())
14051 +        throw LataDBError(LataDBError::READ_ERROR);
14052 +      is >> field.nb_comp_;
14053 +      if (!is.good())
14054 +        throw LataDBError(LataDBError::READ_ERROR);
14055 +      Nom unit;
14056 +      is >> unit;
14057 +      if (!is.good())
14058 +        throw LataDBError(LataDBError::READ_ERROR);
14059 +      field.unites_.add(unit);
14060 +      is >> motlu; // type0
14061 +      if (!is.good())
14062 +        throw LataDBError(LataDBError::READ_ERROR);
14063 +      {
14064 +       int tmp;
14065 +       is >> tmp;
14066 +       field.size_ = tmp; // long long convert
14067 +      }
14068 +      if (!is.good())
14069 +        throw LataDBError(LataDBError::READ_ERROR);
14070 +      // By default, 3 components fields are vectors:
14071 +      if (field.nb_comp_ == 3) {
14072 +        Journal(lmllevel+1) << " 3 components=> say it's a vector" << endl;
14073 +        field.nature_ = LataDBField::VECTOR;
14074 +      } else {
14075 +        field.nature_ = LataDBField::SCALAR;
14076 +      }
14077 +      field.datatype_ = lata_db.default_type_float();
14078 +      field.datatype_.file_offset_ = file_offset++; // see file_offset_blurb
14079 +      FloatTab tab;
14080 +      tab.resize(field.size_, field.nb_comp_);
14081 +      for (entier i = 0; i < field.size_; i++) {
14082 +        entier n;
14083 +        is >> n;
14084 +        if (!is.good())
14085 +          throw LataDBError(LataDBError::READ_ERROR);
14086 +        for (entier j = 0; j < field.nb_comp_; j++) {
14087 +          double x;
14088 +          is >> x;
14089 +          if (!is.good())
14090 +            throw LataDBError(LataDBError::READ_ERROR);
14091 +          tab(i,j) = double_to_float(x);
14092 +        }
14093 +      }
14094 +      Journal(lmllevel+1) << " finished reading field " << field.name_ << endl;
14095 +      lata_db.add_field(field);
14096 +      if (data_filename)
14097 +        lata_db.write_data(tstep, field.uname_, tab);
14098 +    } else if (motlu == "FIN") {
14099 +      break;
14100 +    } else {
14101 +      Journal() << "Error reading lml file, unknown keyword " << motlu << endl;
14102 +      throw;
14103 +    }
14104 +  }
14105 +}
14106 +
14107 +void lml_to_lata(const char *lmlname, const char *latafilename, 
14108 +                 entier ascii, entier fortran_blocs, entier fortran_ordering, entier fortran_indexing)
14109 +{
14110 +  const entier lmllevel=4;
14111 +  Journal(lmllevel) << "lml_to_lata " << lmlname << " -> " << latafilename << endl;
14112 +  LataDB lata_db;
14113 +  Nom dest_prefix, dest_name;
14114 +  LataOptions::extract_path_basename(latafilename, dest_prefix, dest_name);
14115 +  // Nom du fichier .data a ecrire (sans le chemin)
14116 +  Nom datafile(dest_name);
14117 +  datafile += ".lata.data";
14118 +  lata_db.set_path_prefix(dest_prefix);
14119 +  // Nom complet du fichier lml a lire
14120 +  LataDBDataType type;
14121 +  if (ascii)
14122 +    type.msb_ = LataDBDataType::ASCII;
14123 +  else
14124 +    type.msb_ = LataDBDataType::machine_msb_;
14125 +  type.type_ = LataDBDataType::INT32;
14126 +  type.array_index_ = fortran_indexing ? LataDBDataType::F_INDEXING : LataDBDataType::C_INDEXING;
14127 +  type.data_ordering_ = fortran_ordering ? LataDBDataType::F_ORDERING : LataDBDataType::C_ORDERING;
14128 +  type.fortran_bloc_markers_ = fortran_blocs ? LataDBDataType::BLOC_MARKERS_SINGLE_WRITE : LataDBDataType::NO_BLOC_MARKER;
14129 +  type.bloc_marker_type_ = LataDBDataType::INT32;
14130 +  type.file_offset_ = 0;
14131 +  lata_db.default_type_int_ = type;
14132 +  lata_db.default_float_type_ =  LataDBDataType::REAL32;
14133 +  
14134 +  lml_reader(lmlname, datafile, lata_db);
14135 +  Journal(lmllevel) << "lml_to_lata writing lata master file" << endl;
14136 +  lata_db.write_master_file(latafilename);
14137 +}
14138 +
14139 +// Reads lml or lata file into lata_db. lml data is loaded in an internal memory buffer
14140 +//  file: full name with path
14141 +//  path_prefix: the path (used to access lata data files)
14142 +// If dest_file_if_lml is not null, puts lml data into this file...
14143 +// In this case, you must set lata_db.default_type* to tell which format to use.
14144 +void read_any_format(const char * file, const Nom & path_prefix, LataDB & lata_db)
14145 +{
14146 +  // Is it an lml ?
14147 +  Motcle motcle_nom_fic(file);
14148 +  if (motcle_nom_fic.finit_par(".lml")) {
14149 +    Journal(1) << "Detected lml file : " << file << endl;
14150 +    // Nom complet du fichier lml a lire
14151 +    Journal(1) << "Reading lml file to memory buffer" << endl;
14152 +    // data will be put in an internal memory buffer.
14153 +    // choose appropriate data format:
14154 +    LataDBDataType type;
14155 +    type.msb_ = LataDBDataType::machine_msb_;
14156 +    type.type_ = LataDBDataType::INT32;
14157 +    type.array_index_ = LataDBDataType::C_INDEXING;
14158 +    type.data_ordering_ = LataDBDataType::C_ORDERING;
14159 +    type.fortran_bloc_markers_ = LataDBDataType::NO_BLOC_MARKER;
14160 +    type.bloc_marker_type_ = LataDBDataType::INT32;
14161 +    type.file_offset_ = 0;
14162 +    lata_db.default_type_int_ = type;
14163 +    lata_db.default_float_type_ =  LataDBDataType::REAL32;
14164 +    lml_reader(file, LataDBField::memory_buffer_file(), lata_db);
14165 +  } else {
14166 +    Journal(1) << "Detected lata file : " << file << endl;
14167 +    lata_db.read_master_file(path_prefix, file);
14168 +  }
14169 +}
14170 +
14171 +// Description: if the file is a lata file, read the third line and interprets it as options
14172 +//  if lml format, do nothing
14173 +//  otherwise, error.
14174 +void read_any_format_options(const char * file, LataOptions & opt)
14175 +{
14176 +  Motcle nom_fic(file);
14177 +  if (nom_fic.finit_par(".lml")) {
14178 +    // do nothing
14179 +  } else if (nom_fic.finit_par(".med")) {
14180 +         // do nothing
14181 +  } else if (nom_fic.finit_par(".lata")) {
14182 +    Journal(1) << "Lata file: Interpreting LataFilter options on third line" << endl;
14183 +    Nom ligne = LataDB::read_master_file_options(file);
14184 +    const char *s = ligne;
14185 +    while (*s) {
14186 +      Nom toto("");
14187 +      while ((*s) != ' ' && (*s) != 0) {
14188 +        toto += Nom(*s);
14189 +        s++;
14190 +      }
14191 +      if ((toto != "Trio_U")&&(toto != "TRUST" )) {
14192 +        if (!opt.parse_option(toto)) {
14193 +          Journal(0) << "Interpreting option: " << toto <<"  Failed." << endl;
14194 +          throw LataDBError::BAD_HEADER;
14195 +        } else
14196 +          Journal(1) << "Interpreting option: " << toto <<"  Success." << endl;
14197 +      }
14198 +      while ((*s) == ' ')
14199 +        s++;
14200 +    }
14201 +  } else {
14202 +    Journal(0) << "read_any_format_options: file " << nom_fic << " has unsupported extension" << endl;
14203 +    throw LataDBError::BAD_HEADER;
14204 +  }
14205 +}
14206 diff --git a/databases/readers/Lata/LmlReader.h b/databases/readers/Lata/LmlReader.h
14207 new file mode 100644
14208 index 0000000..9a37ab5
14209 --- /dev/null
14210 +++ b/databases/readers/Lata/LmlReader.h
14211 @@ -0,0 +1,38 @@
14212 +/*****************************************************************************
14213 +*
14214 +* Copyright (c) 2011 - 2013, CEA
14215 +* All rights reserved.
14216 +* Redistribution and use in source and binary forms, with or without
14217 +* modification, are permitted provided that the following conditions are met:
14218 +*
14219 +*     * Redistributions of source code must retain the above copyright
14220 +*       notice, this list of conditions and the following disclaimer.
14221 +*     * Redistributions in binary form must reproduce the above copyright
14222 +*       notice, this list of conditions and the following disclaimer in the
14223 +*       documentation and/or other materials provided with the distribution.
14224 +*     * Neither the name of CEA, nor the
14225 +*       names of its contributors may be used to endorse or promote products
14226 +*       derived from this software without specific prior written permission.
14227 +*
14228 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
14229 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14230 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14231 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
14232 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
14233 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
14234 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
14235 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14236 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14237 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14238 +*
14239 +*****************************************************************************/
14240 +
14241 +#ifndef LMLREADER_H
14242 +#define LMLREADER_H
14243 +void lml_reader(const char * lmlfilename, const char * data_filename, LataDB & lata_db);
14244 +void lml_to_lata(const char *lmlfilename, const char *latafilename, 
14245 +                 entier ascii = 0, entier fortran_blocs = 1, entier fortran_ordering = 0, entier fortran_indexing = 1);
14246 +void read_any_format(const char * file, const Nom & path_prefix, LataDB & lata_db);
14247 +void read_any_format_options(const char * file, LataOptions & opt);
14248 +#endif
14249 +
14250 diff --git a/databases/readers/Lata/Motcle.C b/databases/readers/Lata/Motcle.C
14251 new file mode 100644
14252 index 0000000..4227be6
14253 --- /dev/null
14254 +++ b/databases/readers/Lata/Motcle.C
14255 @@ -0,0 +1,142 @@
14256 +/*****************************************************************************
14257 +*
14258 +* Copyright (c) 2011 - 2013, CEA
14259 +* All rights reserved.
14260 +* Redistribution and use in source and binary forms, with or without
14261 +* modification, are permitted provided that the following conditions are met:
14262 +*
14263 +*     * Redistributions of source code must retain the above copyright
14264 +*       notice, this list of conditions and the following disclaimer.
14265 +*     * Redistributions in binary form must reproduce the above copyright
14266 +*       notice, this list of conditions and the following disclaimer in the
14267 +*       documentation and/or other materials provided with the distribution.
14268 +*     * Neither the name of CEA, nor the
14269 +*       names of its contributors may be used to endorse or promote products
14270 +*       derived from this software without specific prior written permission.
14271 +*
14272 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
14273 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14274 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14275 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
14276 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
14277 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
14278 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
14279 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14280 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14281 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14282 +*
14283 +*****************************************************************************/
14284 +
14285 +#include <Motcle.h>
14286 +#include <string.h>
14287 +#include <istream>
14288 +#include <ostream>
14289 +#include <string>
14290 +Nom& Nom::majuscule()
14291 +{
14292 +  const int n = longueur()-1;
14293 +  for (int i = 0; i < n; i++)
14294 +    {
14295 +      char c = s_[i];
14296 +      if (c >= 'a' && c <= 'z')
14297 +        s_[i] = c + 'A' - 'a';
14298 +    }
14299 +  return *this;
14300 +}
14301 +
14302 +static inline char char_uppercase(char c)
14303 +{
14304 +  if (c >= 'a' && c <= 'z')
14305 +    c += 'A' - 'a';
14306 +  return c;
14307 +}
14308 +
14309 +
14310 +// opt=0 => comparaison des chaines completes
14311 +// opt=1 => le debut de n1 doit etre egal a n2
14312 +int Motcle::strcmp_uppercase(const char *n1, const char *n2, int opt)
14313 +{
14314 +  entier i = 0;
14315 +  unsigned char c1, c2;
14316 +  entier delta;
14317 +  do
14318 +    {
14319 +      c1 = (unsigned char) char_uppercase(n1[i]);
14320 +      c2 = (unsigned char) char_uppercase(n2[i]);
14321 +      delta = c1 - c2;
14322 +      i++;
14323 +      if (c2 == 0 && opt == 1)
14324 +        {
14325 +          // Fin de la deuxieme chaine et opt=1 (fonction "debute_par"):
14326 +          // Test ok
14327 +          return 0;
14328 +        }
14329 +    }
14330 +  while ((delta == 0) && (c1 != 0) && (c2 != 0));
14331 +  return delta;
14332 +}
14333 +
14334 +int Nom::debute_par(const char * s) const
14335 +{
14336 +  const int l1 = longueur()-1;
14337 +  const int l2 = (int)strlen(s);
14338 +  return (l1>=l2) ? (strncmp(s_.c_str(), s, l2) == 0) : 0;
14339 +}
14340 +
14341 +int Nom::finit_par(const char * s) const
14342 +{
14343 +  const int l1 = longueur()-1;
14344 +  const int l2 = (int)strlen(s);
14345 +  return (l1>=l2) ? (strncmp(s_.c_str()+(l1-l2), s, l2) == 0) : 0;
14346 +}
14347 +
14348 +entier Nom::find(const char * n) const
14349 +{
14350 +  std::size_t x = s_.find(n);
14351 +  return (x != std::string::npos) ? x : -1;
14352 +}
14353 +
14354 +Nom& Nom::prefix(const char *s)
14355 +{
14356 +  if (finit_par(s))
14357 +    {
14358 +      entier n = strlen(s_.c_str());
14359 +      entier n2 = strlen(s);
14360 +      s_.erase(n-n2,n2);
14361 +    }
14362 +  return *this;
14363 +}
14364 +
14365 +int Motcle::debute_par(const char * s) const
14366 +{
14367 +  return (strcmp_uppercase(s_.c_str(), s, 1) == 0);
14368 +}
14369 +
14370 +int Motcle::finit_par(const char * s) const
14371 +{
14372 +  const int l1 = longueur()-1;
14373 +  const int l2 = (int)strlen(s);
14374 +  return (l1>=l2) ? (strcmp_uppercase(s_.c_str()+(l1-l2), s) == 0) : 0;
14375 +}
14376 +
14377 +Motcles noms_to_motcles(const Noms& a)
14378 +{
14379 +  Motcles b;
14380 +  entier n = a.size();
14381 +  for (entier i = 0; i < n; i++)
14382 +    b.add() = a[i]; // ouais, ecriture bizarre mais la plus efficace...
14383 +  return b;
14384 +}
14385 +
14386 +std::istream& operator>>(std::istream& is, Nom& nom)
14387 +{
14388 +  nom.read(is);
14389 +  return is;
14390 +}
14391 +
14392 +std::ostream& operator<<(std::ostream& os, const Nom& nom)
14393 +{
14394 +  nom.write(os);
14395 +  return os;
14396 +}
14397 +
14398 diff --git a/databases/readers/Lata/Motcle.h b/databases/readers/Lata/Motcle.h
14399 new file mode 100644
14400 index 0000000..e1a992d
14401 --- /dev/null
14402 +++ b/databases/readers/Lata/Motcle.h
14403 @@ -0,0 +1,150 @@
14404 +/*****************************************************************************
14405 +*
14406 +* Copyright (c) 2011 - 2013, CEA
14407 +* All rights reserved.
14408 +* Redistribution and use in source and binary forms, with or without
14409 +* modification, are permitted provided that the following conditions are met:
14410 +*
14411 +*     * Redistributions of source code must retain the above copyright
14412 +*       notice, this list of conditions and the following disclaimer.
14413 +*     * Redistributions in binary form must reproduce the above copyright
14414 +*       notice, this list of conditions and the following disclaimer in the
14415 +*       documentation and/or other materials provided with the distribution.
14416 +*     * Neither the name of CEA, nor the
14417 +*       names of its contributors may be used to endorse or promote products
14418 +*       derived from this software without specific prior written permission.
14419 +*
14420 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
14421 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14422 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14423 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
14424 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
14425 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
14426 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
14427 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14428 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14429 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14430 +*
14431 +*****************************************************************************/
14432 +
14433 +#ifndef LataMotcle_H
14434 +#define LataMotcle_H
14435 +#include <string>
14436 +#include <iostream>
14437 +#include <LataVector.h>
14438 +#include <arch.h>
14439 +// pour gcc 2.96:
14440 +#include <stdio.h>
14441 +
14442 +class Motcle;
14443 +
14444 +class Nom
14445 +{
14446 +public:
14447 +  Nom()
14448 +  {
14449 +    s_ = "??";
14450 +  };
14451 +
14452 +
14453 +
14454 +  Nom(std::string str)
14455 +  {
14456 +    s_ = str;
14457 +  }
14458 +
14459 +  inline const std::string& getString() const { return s_; }
14460 +
14461 +  virtual ~Nom() { };
14462 +  Nom(const char * nom)  : s_(nom) { };
14463 +  Nom(char c)
14464 +  {
14465 +    s_ = c;
14466 +  };
14467 +  Nom(int i)
14468 +  {
14469 +    char s[30];
14470 +    sprintf(s, "%d", i);
14471 +    s_ = s;
14472 +  }
14473 +  operator const char *() const
14474 +  {
14475 +    return s_.c_str();
14476 +  }
14477 +  virtual Nom& operator=(const char * nom)
14478 +  {
14479 +    s_ = nom;
14480 +    return *this;
14481 +  }
14482 +  virtual entier longueur() const
14483 +  {
14484 +    return static_cast<entier>(s_.length())+1; /*ATTENTION: +1 pour compatibilite avec TRUST*/
14485 +  }
14486 +  virtual void read(std::istream& is)
14487 +  {
14488 +    is >> s_;
14489 +  }
14490 +  virtual void write(std::ostream& os) const
14491 +  {
14492 +    os << s_;
14493 +  }
14494 +  virtual int operator==(const char * s) const
14495 +  {
14496 +    return (s_ == s);
14497 +  }
14498 +  virtual int operator!=(const char * s) const
14499 +  {
14500 +    return !operator==(s);
14501 +  }
14502 +  virtual Nom& operator+=(const char * n)
14503 +  {
14504 +    s_ += n;
14505 +    return *this;
14506 +  }
14507 +  virtual entier find(const char * n) const;
14508 +  virtual int debute_par(const char * s) const;
14509 +  virtual int finit_par(const char * s) const;
14510 +  virtual Nom& prefix(const char * s);
14511 +  Nom&          majuscule();
14512 +protected:
14513 +  friend class Motcle;
14514 +  std::string s_;
14515 +};
14516 +
14517 +class Motcle : public Nom
14518 +{
14519 +public:
14520 +  Motcle() {};
14521 +  Motcle(const char * s) : Nom(s) {};
14522 +  Motcle(const Nom& n) : Nom(n) {};
14523 +  ~Motcle() {};
14524 +  int operator==(const char * s) const
14525 +  {
14526 +    return (strcmp_uppercase(s_.c_str(), s) == 0);
14527 +  }
14528 +  int operator!=(const char * s) const
14529 +  {
14530 +    return !operator==(s);
14531 +  }
14532 +  Motcle& operator+=(const char * n)
14533 +  {
14534 +    s_ += n;
14535 +    return *this;
14536 +  }
14537 +  int debute_par(const char * s) const;
14538 +  int finit_par(const char * s) const;
14539 +
14540 +  static int strcmp_uppercase(const char * s1, const char * s2, int opt = 0);
14541 +  virtual entier find(const char * n) const
14542 +  {
14543 +    return Nom(*this).majuscule().find(Nom(n).majuscule());
14544 +  }
14545 +};
14546 +
14547 +typedef LataVector<Motcle> Motcles;
14548 +typedef LataVector<Nom> Noms;
14549 +
14550 +std::istream& operator>>(std::istream& is, Nom& nom);
14551 +std::ostream& operator<<(std::ostream& os, const Nom& nom);
14552 +
14553 +#endif
14554 diff --git a/databases/readers/Lata/Noms.h b/databases/readers/Lata/Noms.h
14555 new file mode 100644
14556 index 0000000..d9231d2
14557 --- /dev/null
14558 +++ b/databases/readers/Lata/Noms.h
14559 @@ -0,0 +1,29 @@
14560 +/*****************************************************************************
14561 +*
14562 +* Copyright (c) 2011 - 2013, CEA
14563 +* All rights reserved.
14564 +* Redistribution and use in source and binary forms, with or without
14565 +* modification, are permitted provided that the following conditions are met:
14566 +*
14567 +*     * Redistributions of source code must retain the above copyright
14568 +*       notice, this list of conditions and the following disclaimer.
14569 +*     * Redistributions in binary form must reproduce the above copyright
14570 +*       notice, this list of conditions and the following disclaimer in the
14571 +*       documentation and/or other materials provided with the distribution.
14572 +*     * Neither the name of CEA, nor the
14573 +*       names of its contributors may be used to endorse or promote products
14574 +*       derived from this software without specific prior written permission.
14575 +*
14576 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
14577 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14578 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14579 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
14580 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
14581 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
14582 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
14583 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14584 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14585 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14586 +*
14587 +*****************************************************************************/
14588 +
14589 diff --git a/databases/readers/Lata/Objet_U.h b/databases/readers/Lata/Objet_U.h
14590 new file mode 100644
14591 index 0000000..1f63425
14592 --- /dev/null
14593 +++ b/databases/readers/Lata/Objet_U.h
14594 @@ -0,0 +1,41 @@
14595 +/*****************************************************************************
14596 +*
14597 +* Copyright (c) 2011 - 2013, CEA
14598 +* All rights reserved.
14599 +* Redistribution and use in source and binary forms, with or without
14600 +* modification, are permitted provided that the following conditions are met:
14601 +*
14602 +*     * Redistributions of source code must retain the above copyright
14603 +*       notice, this list of conditions and the following disclaimer.
14604 +*     * Redistributions in binary form must reproduce the above copyright
14605 +*       notice, this list of conditions and the following disclaimer in the
14606 +*       documentation and/or other materials provided with the distribution.
14607 +*     * Neither the name of CEA, nor the
14608 +*       names of its contributors may be used to endorse or promote products
14609 +*       derived from this software without specific prior written permission.
14610 +*
14611 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
14612 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14613 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14614 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
14615 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
14616 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
14617 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
14618 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14619 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14620 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14621 +*
14622 +*****************************************************************************/
14623 +
14624 +// Class declared for compatibility with TRUST
14625 +#ifndef Objet_U_inclu
14626 +#define Objet_U_inclu
14627 +#include <LataJournal.h>
14628 +#include <Sortie.h>
14629 +#include <Entree.h>
14630 +#include <math.h>
14631 +
14632 +#define Cerr Journal()
14633 +#define finl std::endl
14634 +
14635 +#endif
14636 diff --git a/databases/readers/Lata/Octree_Double.C b/databases/readers/Lata/Octree_Double.C
14637 new file mode 100644
14638 index 0000000..f7cb229
14639 --- /dev/null
14640 +++ b/databases/readers/Lata/Octree_Double.C
14641 @@ -0,0 +1,395 @@
14642 +/*****************************************************************************
14643 +*
14644 +* Copyright (c) 2011 - 2013, CEA
14645 +* All rights reserved.
14646 +* Redistribution and use in source and binary forms, with or without
14647 +* modification, are permitted provided that the following conditions are met:
14648 +*
14649 +*     * Redistributions of source code must retain the above copyright
14650 +*       notice, this list of conditions and the following disclaimer.
14651 +*     * Redistributions in binary form must reproduce the above copyright
14652 +*       notice, this list of conditions and the following disclaimer in the
14653 +*       documentation and/or other materials provided with the distribution.
14654 +*     * Neither the name of CEA, nor the
14655 +*       names of its contributors may be used to endorse or promote products
14656 +*       derived from this software without specific prior written permission.
14657 +*
14658 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
14659 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14660 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14661 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
14662 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
14663 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
14664 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
14665 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14666 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14667 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14668 +*
14669 +*****************************************************************************/
14670 +
14671 +#include <Octree_Double.h>
14672 +#include <DoubleTab.h>
14673 +#include <FloatTab.h>
14674 +
14675 +Octree_Double::Octree_Double()
14676 +{
14677 +  dim_ = 0;
14678 +}
14679 +
14680 +void Octree_Double::reset()
14681 +{
14682 +  dim_ = 0;
14683 +  octree_int_.reset();
14684 +  origin_.reset();
14685 +  factor_.reset();
14686 +}
14687 +
14688 +// Description: Convertit une coordonnees reele en coordonnee entiere pour l'octree_int
14689 +// Valeur de retour: 1 si ok, 0 si coordonnee hors de l'octree
14690 +inline entier Octree_Double::integer_position(double x, entier direction, entier& ix) const
14691 +{
14692 +  const double coord_max = (double) Octree_Int::coord_max_;
14693 +  double rnd_x = (x - origin_[direction]) * factor_[direction];
14694 +  // 0.49 permet d'accepter une coordonnee x egale a xmin ou xmax de l'octree,
14695 +  //  sinon pour un octree cree a partir de sommets, il y a un risque
14696 +  //  de ne pas trouver les coordonnees des points qu'on avait mis au bord de l'octree.
14697 +  if (rnd_x >= -0.49 && rnd_x <= coord_max + 0.49)
14698 +    {
14699 +      ix = (entier) floor(rnd_x + 0.5);
14700 +      return 1;
14701 +    }
14702 +  return 0;
14703 +}
14704 +
14705 +// Valeur de retour: 1 s'il y a une intersection non vide avec l'octree, 0 sinon
14706 +inline entier Octree_Double::integer_position_clip(double xmin, double xmax,
14707 +    entier& x0, entier& x1,
14708 +    entier direction) const
14709 +{
14710 +  const double coord_max = (double) Octree_Int::coord_max_;
14711 +  xmin = (xmin - origin_[direction]) * factor_[direction];
14712 +  xmax = (xmax - origin_[direction]) * factor_[direction];
14713 +  // pas de marge ici comme on cherche avec une boite, l'epsilon est deja
14714 +  // dans la dimension de la boite.
14715 +  if (xmin > coord_max || xmax < 0.)
14716 +    return 0;
14717 +  if (xmin < .0)
14718 +    x0 = 0;
14719 +  else
14720 +    x0 = (entier) (floor(xmin+0.5));
14721 +  if (xmax > coord_max)
14722 +    x1 = Octree_Int::coord_max_;
14723 +  else
14724 +    x1 = (entier) (floor(xmax+0.5));
14725 +  return 1;
14726 +}
14727 +
14728 +// Description: cherche les elements ou les points contenus dans l'octree_floor qui
14729 +//  contient le point (x,y,z). Renvoie le nombre n de ces elements.
14730 +//  Les indices des elements sont dans floor_elements()[index+i] pour 0 <= i < n
14731 +entier Octree_Double::search_elements(double x, double y, double z, entier& index) const
14732 +{
14733 +  if (dim_ == 0)
14734 +    return 0; // octree vide
14735 +  entier ix = 0, iy = 0, iz = 0;
14736 +  entier ok = integer_position(x, 0, ix)
14737 +              && integer_position(y, 1, iy)
14738 +              && integer_position(z, 2, iz);
14739 +  if (ok)
14740 +    {
14741 +      return octree_int_.search_elements(ix, iy, iz, index);
14742 +    }
14743 +  else
14744 +    {
14745 +      return 0;
14746 +    }
14747 +}
14748 +
14749 +// Description: methode outil pour build_nodes et build_elements
14750 +//  (calcul des facteurs de conversion entre reels et entiers pour Octree_Int
14751 +void Octree_Double::compute_origin_factors(const DoubleTab& coords,
14752 +    const double epsilon,
14753 +    const entier include_virtual)
14754 +{
14755 +  // Recherche des coordonnees min et max du domaine
14756 +  const entier nb_som = include_virtual ? coords.dimension_tot(0) : coords.dimension(0);
14757 +  if (nb_som == 0)
14758 +    return; // octree vide
14759 +
14760 +  const entier dim = coords.dimension(1);
14761 +  dim_ = dim;
14762 +  origin_.resize_array(3);
14763 +  factor_.resize_array(3);
14764 +  ArrOfDouble xmin(dim, 1.e37);
14765 +  ArrOfDouble xmax(dim, -1.e-37);
14766 +  assert(dim >= 1 && dim <= 3);
14767 +  entier i, j;
14768 +  for (i = 0; i < nb_som; i++)
14769 +    {
14770 +      for (j = 0; j < dim; j++)
14771 +        {
14772 +          const double x = coords(i, j);
14773 +          if (x < xmin[j])
14774 +            xmin[j] = x;
14775 +          if (x > xmax[j])
14776 +            xmax[j] = x;
14777 +        }
14778 +    }
14779 +  const double coord_max = (double) Octree_Int::coord_max_;
14780 +  for (j = 0; j < dim; j++)
14781 +    {
14782 +      xmin[j] -= epsilon;
14783 +      xmax[j] += epsilon;
14784 +      origin_[j] = xmin[j];
14785 +      if (xmax[j] - xmin[j] > 0.)
14786 +        {
14787 +          factor_[j] = coord_max / (xmax[j] - xmin[j]);
14788 +        }
14789 +      else
14790 +        factor_[j] = 0.;
14791 +    }
14792 +}
14793 +void Octree_Double::compute_origin_factors(const FloatTab& coords,
14794 +    const double epsilon,
14795 +    const entier include_virtual)
14796 +{
14797 +  // Recherche des coordonnees min et max du domaine
14798 +  const entier nb_som = include_virtual ? coords.dimension_tot(0) : coords.dimension(0);
14799 +  if (nb_som == 0)
14800 +    return; // octree vide
14801 +
14802 +  const entier dim = coords.dimension(1);
14803 +  dim_ = dim;
14804 +  origin_.resize_array(3);
14805 +  factor_.resize_array(3);
14806 +  ArrOfDouble xmin(dim, 1.e37);
14807 +  ArrOfDouble xmax(dim, -1.e-37);
14808 +  assert(dim >= 1 && dim <= 3);
14809 +  entier i, j;
14810 +  for (i = 0; i < nb_som; i++)
14811 +    {
14812 +      for (j = 0; j < dim; j++)
14813 +        {
14814 +          const double x = coords(i, j);
14815 +          if (x < xmin[j])
14816 +            xmin[j] = x;
14817 +          if (x > xmax[j])
14818 +            xmax[j] = x;
14819 +        }
14820 +    }
14821 +  const double coord_max = (double) Octree_Int::coord_max_;
14822 +  for (j = 0; j < dim; j++)
14823 +    {
14824 +      xmin[j] -= epsilon;
14825 +      xmax[j] += epsilon;
14826 +      origin_[j] = xmin[j];
14827 +      if (xmax[j] - xmin[j] > 0.)
14828 +        {
14829 +          factor_[j] = coord_max / (xmax[j] - xmin[j]);
14830 +        }
14831 +      else
14832 +        factor_[j] = 0.;
14833 +    }
14834 +}
14835 +
14836 +// Description: construit un octree contenant les points de coordonnees coords.
14837 +//  Si include_virtual=1, on stocke coords.dimension_tot(0) elements, sinon on en
14838 +//  stocke coords.dimension(0)
14839 +void Octree_Double::build_nodes(const DoubleTab& coords, const entier include_virtual)
14840 +{
14841 +  octree_int_.reset();
14842 +  compute_origin_factors(coords, 0. /* epsilon */, include_virtual);
14843 +  const entier nb_som = include_virtual ? coords.dimension_tot(0) : coords.dimension(0);
14844 +  if (nb_som == 0)
14845 +    return; // octree vide
14846 +  const entier dim = coords.dimension(1);
14847 +  IntTab elements_boxes(nb_som, dim);
14848 +  for (entier i = 0; i < nb_som; i++)
14849 +    {
14850 +      for (entier j = 0; j < dim; j++)
14851 +        {
14852 +          entier pos1 = 0;
14853 +          const double x = coords(i, j);
14854 +          if (!integer_position(x, j, pos1))
14855 +            {
14856 +              Cerr << "Fatal error in octree : integer position outside octree" << finl;
14857 +              throw;
14858 +            }
14859 +          elements_boxes(i, j) = pos1;
14860 +        }
14861 +    }
14862 +  octree_int_.build(dim, elements_boxes);
14863 +}
14864 +
14865 +// Description: Construit un octree a partir d'elements volumiques decrits par des
14866 +//  ensembles de sommets. On stocke dans l'octree les parallelipipdes englobant chaque
14867 +//  element (contenant tous les sommets de l'element) plus une marge de epsilon.
14868 +//  Si include_virtual=1, on stocke elements.dimension_tot(0) elements, sinon on en
14869 +//  stocke elements.dimension(0)
14870 +void Octree_Double::build_elements(const DoubleTab& coords, const IntTab& elements,
14871 +                                   const double epsilon, const entier include_virtual)
14872 +{
14873 +  octree_int_.reset();
14874 +  compute_origin_factors(coords, epsilon, include_virtual);
14875 +
14876 +  const entier nb_elems = include_virtual ? elements.dimension_tot(0) : elements.dimension(0);
14877 +  const entier nb_som_elem = elements.dimension(1);
14878 +  const entier dim = coords.dimension(1);
14879 +  IntTab elements_boxes(nb_elems, dim * 2);
14880 +  for (entier i = 0; i < nb_elems; i++)
14881 +    {
14882 +      for (entier j = 0; j < dim; j++)
14883 +        {
14884 +          double xmin = 1.e37;
14885 +          double xmax = -1.e37;
14886 +          for (entier k = 0; k < nb_som_elem; k++)
14887 +            {
14888 +              const entier som = elements(i, k);
14889 +                         if (som>=0) { // polyedre som peut valoir -1
14890 +              const double x = coords(som, j);
14891 +              xmin = (x<xmin) ? x : xmin;
14892 +              xmax = (x>xmax) ? x : xmax;
14893 +                         }
14894 +            }
14895 +          entier pos1 = 0, pos2 = 0;
14896 +          if (!integer_position(xmin, j, pos1) || !integer_position(xmax, j, pos2))
14897 +            {
14898 +              Cerr << "Fatal error in octree : integer position outside octree" << finl;
14899 +              throw;
14900 +            }
14901 +          elements_boxes(i, j) = pos1;
14902 +          elements_boxes(i, j+dim) = pos2;
14903 +        }
14904 +    }
14905 +  octree_int_.build(dim, elements_boxes);
14906 +}
14907 +
14908 +void Octree_Double::build_elements(const FloatTab& coords, const IntTab& elements,
14909 +                                   const double epsilon, const entier include_virtual)
14910 +{
14911 +  octree_int_.reset();
14912 +  compute_origin_factors(coords, epsilon, include_virtual);
14913 +
14914 +  const entier nb_elems = include_virtual ? elements.dimension_tot(0) : elements.dimension(0);
14915 +  const entier nb_som_elem = elements.dimension(1);
14916 +  const entier dim = coords.dimension(1);
14917 +  IntTab elements_boxes(nb_elems, dim * 2);
14918 +  for (entier i = 0; i < nb_elems; i++)
14919 +    {
14920 +      for (entier j = 0; j < dim; j++)
14921 +        {
14922 +          double xmin = 1.e37;
14923 +          double xmax = -1.e37;
14924 +          for (entier k = 0; k < nb_som_elem; k++)
14925 +            {
14926 +              const entier som = elements(i, k);
14927 +                         if (som>=0) { // polyedre som peut valoir -1
14928 +              const double x = coords(som, j);
14929 +              xmin = (x<xmin) ? x : xmin;
14930 +              xmax = (x>xmax) ? x : xmax;
14931 +                         }
14932 +            }
14933 +          entier pos1 = 0, pos2 = 0;
14934 +          if (!integer_position(xmin, j, pos1) || !integer_position(xmax, j, pos2))
14935 +            {
14936 +              Cerr << "Fatal error in octree : integer position outside octree" << finl;
14937 +              throw;
14938 +            }
14939 +          elements_boxes(i, j) = pos1;
14940 +          elements_boxes(i, j+dim) = pos2;
14941 +        }
14942 +    }
14943 +  octree_int_.build(dim, elements_boxes);
14944 +}
14945 +
14946 +// Description: cherche tous les elements ou points ayant potentiellement une intersection
14947 +//  non vide avec la boite donnee.
14948 +entier Octree_Double::search_elements_box(double xmin, double ymin, double zmin,
14949 +    double xmax, double ymax, double zmax,
14950 +    ArrOfInt& elements) const
14951 +{
14952 +  const entier dim = dim_;
14953 +  if (dim == 0)
14954 +    {
14955 +      elements.resize_array(0);
14956 +      return 0;
14957 +    }
14958 +  entier x0 = 0, x1 = 0, y0 = 0, y1 = 0, z0 = 0, z1 = 0;
14959 +  entier ok = integer_position_clip(xmin, xmax, x0, x1, 0);
14960 +  if (ok && dim >= 1)
14961 +    {
14962 +      ok = integer_position_clip(ymin, ymax, y0, y1, 1);
14963 +      if (ok && dim >= 2)
14964 +        ok = integer_position_clip(zmin, zmax, z0, z1, 2);
14965 +    }
14966 +  if (ok)
14967 +    octree_int_.search_elements_box(x0, y0, z0, x1, y1, z1, elements);
14968 +  else
14969 +    elements.resize_array(0);
14970 +  return elements.size_array();
14971 +}
14972 +
14973 +// Description: cherche tous les elements ou points ayant potentiellement une intersection
14974 +//  non vide avec la boite donnee (centre + ou - radius dans chaque direction)
14975 +entier Octree_Double::search_elements_box(const ArrOfDouble& center, const double radius,
14976 +    ArrOfInt& elements) const
14977 +{
14978 +  entier dim = center.size_array();
14979 +  double x = center[0];
14980 +  double y = (dim>=2) ? center[1] : 0.;
14981 +  double z = (dim>2) ? center[2] : 0.;
14982 +  entier i = search_elements_box(x-radius, y-radius, z-radius,
14983 +                                 x+radius, y+radius, z+radius,
14984 +                                 elements);
14985 +  return i;
14986 +}
14987 +
14988 +// Description: Methode hors classe
14989 +//  Cherche parmi les sommets de la liste node_list ceux qui sont a une
14990 +//  distance inferieure a epsilon du point (x,y,z). node_list contient des indices de
14991 +//  sommets dans le tableau coords. La liste des noeuds verifiant le critere est mise
14992 +//  dans node_list. On renvoie l'indice dans le tableau coords du sommet le plus proche.
14993 +entier Octree_Double::search_nodes_close_to(double x, double y, double z,
14994 +    const DoubleTab& coords, ArrOfInt& node_list,
14995 +    double epsilon)
14996 +{
14997 +  const entier n = node_list.size_array();
14998 +  double eps2 = epsilon * epsilon;
14999 +  entier count = 0;
15000 +  const entier dim = coords.dimension(1);
15001 +  double dmin = eps2;
15002 +  entier nearest = -1;
15003 +  for (entier i = 0; i < n; i++)
15004 +    {
15005 +      const entier som = node_list[i];
15006 +      double dx = x - coords(som, 0);
15007 +      double dy = (dim >= 2) ? y - coords(som, 1) : 0.;
15008 +      double dz = (dim >= 3) ? z - coords(som, 2) : 0.;
15009 +      double d2 = dx * dx + dy * dy + dz * dz;
15010 +      if (d2 < eps2)
15011 +        {
15012 +          node_list[count] = som;
15013 +          if (d2 < dmin)
15014 +            {
15015 +              dmin = d2;
15016 +              nearest = som;
15017 +            }
15018 +          count++;
15019 +        }
15020 +    }
15021 +  node_list.resize_array(count);
15022 +  return nearest;
15023 +}
15024 +
15025 +// Description: Idem que search_nodes_close_to(double x, double y, double z, ...)
15026 +entier Octree_Double::search_nodes_close_to(const ArrOfDouble& point,
15027 +    const DoubleTab& coords, ArrOfInt& node_list,
15028 +    double epsilon)
15029 +{
15030 +  entier dim = point.size_array();
15031 +  double x = point[0];
15032 +  double y = (dim>=2) ? point[1] : 0.;
15033 +  double z = (dim>2) ? point[2] : 0.;
15034 +  entier i = search_nodes_close_to(x, y, z, coords, node_list, epsilon);
15035 +  return i;
15036 +}
15037 diff --git a/databases/readers/Lata/Octree_Double.h b/databases/readers/Lata/Octree_Double.h
15038 new file mode 100644
15039 index 0000000..abf3258
15040 --- /dev/null
15041 +++ b/databases/readers/Lata/Octree_Double.h
15042 @@ -0,0 +1,89 @@
15043 +/*****************************************************************************
15044 +*
15045 +* Copyright (c) 2011 - 2013, CEA
15046 +* All rights reserved.
15047 +* Redistribution and use in source and binary forms, with or without
15048 +* modification, are permitted provided that the following conditions are met:
15049 +*
15050 +*     * Redistributions of source code must retain the above copyright
15051 +*       notice, this list of conditions and the following disclaimer.
15052 +*     * Redistributions in binary form must reproduce the above copyright
15053 +*       notice, this list of conditions and the following disclaimer in the
15054 +*       documentation and/or other materials provided with the distribution.
15055 +*     * Neither the name of CEA, nor the
15056 +*       names of its contributors may be used to endorse or promote products
15057 +*       derived from this software without specific prior written permission.
15058 +*
15059 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
15060 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15061 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15062 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
15063 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
15064 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
15065 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
15066 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
15067 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
15068 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15069 +*
15070 +*****************************************************************************/
15071 +
15072 +
15073 +#ifndef Octree_Double_inclu
15074 +#define Octree_Double_inclu
15075 +#include <Octree_Int.h>
15076 +#include <ArrOfDouble.h>
15077 +class DoubleTab;
15078 +class FloatTab;
15079 +
15080 +// .DESCRIPTION : Un octree permettant de chercher dans l'espace des elements ou des points
15081 +//  decrits par des coordonnees reeles. Cet objet est base sur Octree_Int.
15082 +class Octree_Double
15083 +{
15084 +public:
15085 +  Octree_Double();
15086 +  void   reset();
15087 +  void   build_elements(const FloatTab& coords, const IntTab& elements,
15088 +                        const double epsilon, const entier include_virtual);
15089 +  void   build_elements(const DoubleTab& coords, const IntTab& elements,
15090 +                        const double epsilon, const entier include_virtual);
15091 +  void   build_nodes(const DoubleTab& coords, const entier include_virtual);
15092 +  entier search_elements(double x, double y, double z, entier& index) const;
15093 +  entier search_elements_box(double xmin, double ymin, double zmin,
15094 +                             double xmax, double ymax, double zmax,
15095 +                             ArrOfInt& elements) const;
15096 +  static entier search_nodes_close_to(double x, double y, double z,
15097 +                                      const DoubleTab& coords, ArrOfInt& node_list,
15098 +                                      double epsilon);
15099 +  entier search_elements_box(const ArrOfDouble& center, const double radius,
15100 +                             ArrOfInt& elements) const;
15101 +  static entier search_nodes_close_to(const ArrOfDouble& point,
15102 +                                      const DoubleTab& coords, ArrOfInt& node_list,
15103 +                                      double epsilon);
15104 +  entier dimension() const
15105 +  {
15106 +    assert(dim_ > 0);
15107 +    return dim_;
15108 +  }
15109 +  inline const ArrOfInt& floor_elements() const
15110 +  {
15111 +    return octree_int_.floor_elements();
15112 +  };
15113 +protected:
15114 +  inline entier integer_position(double x, entier direction, entier& ix) const;
15115 +  inline entier integer_position_clip(double xmin, double xmax,
15116 +                                      entier& x0, entier& x1,
15117 +                                      entier direction) const;
15118 +  void compute_origin_factors(const DoubleTab& coords,
15119 +                              const double epsilon,
15120 +                              const entier include_virtual);
15121 +  void compute_origin_factors(const FloatTab& coords,
15122 +                              const double epsilon,
15123 +                              const entier include_virtual);
15124 +
15125 +  Octree_Int octree_int_;
15126 +  // Ces deux tableaux sont toujours de taille 3 par commodite
15127 +  ArrOfDouble origin_;
15128 +  ArrOfDouble factor_;
15129 +  entier dim_;
15130 +};
15131 +#endif
15132 diff --git a/databases/readers/Lata/Octree_Int.C b/databases/readers/Lata/Octree_Int.C
15133 new file mode 100644
15134 index 0000000..4f96b7c
15135 --- /dev/null
15136 +++ b/databases/readers/Lata/Octree_Int.C
15137 @@ -0,0 +1,485 @@
15138 +/*****************************************************************************
15139 +*
15140 +* Copyright (c) 2011 - 2013, CEA
15141 +* All rights reserved.
15142 +* Redistribution and use in source and binary forms, with or without
15143 +* modification, are permitted provided that the following conditions are met:
15144 +*
15145 +*     * Redistributions of source code must retain the above copyright
15146 +*       notice, this list of conditions and the following disclaimer.
15147 +*     * Redistributions in binary form must reproduce the above copyright
15148 +*       notice, this list of conditions and the following disclaimer in the
15149 +*       documentation and/or other materials provided with the distribution.
15150 +*     * Neither the name of CEA, nor the
15151 +*       names of its contributors may be used to endorse or promote products
15152 +*       derived from this software without specific prior written permission.
15153 +*
15154 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
15155 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15156 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15157 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
15158 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
15159 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
15160 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
15161 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
15162 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
15163 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15164 +*
15165 +*****************************************************************************/
15166 +
15167 +#include <Octree_Int.h>
15168 +#include <ArrOfBit.h>
15169 +
15170 +static const entier max_levels_ = 32; // 1 de plus que le nombre de bits=1 dans coords_max
15171 +// La valeur suivante doit etre une puissance de deux
15172 +const entier Octree_Int::root_octree_half_width_ = 1073741824; /* 2^30   = 0100 0000  0000 0000  0000 0000  0000 0000b */
15173 +// La valeur suivante doit etre egale a (root_octree_half_width_ * 2 - 1)
15174 +const entier Octree_Int::coord_max_ = 2147483647;              /* 2^31-1 = 0111 1111  1111 1111  1111 1111  1111 1111b */
15175 +
15176 +// Description: construction d'un octree_id (voir octree_structure_)
15177 +//  Si type==EMPTY, on l'octree_id est 0
15178 +//  Si type==OCTREE, on suppose que index est un indice dans octree_structure_
15179 +//  Si type==FLOOR, on suppose que index est un indice dans floor_elements_
15180 +inline entier Octree_Int::octree_id(entier index, Octree_Type type)
15181 +{
15182 +  switch(type)
15183 +    {
15184 +    case EMPTY:
15185 +      return 0;
15186 +    case OCTREE:
15187 +      return index + 1;
15188 +    case FLOOR:
15189 +      return - index - 1;
15190 +    }
15191 +  return -1;
15192 +}
15193 +
15194 +// Description: calcul de l'index de l'octree dans octree_structure ou floor_elements
15195 +//  en fonction du type de l'octree et de son octree_id.
15196 +//  En general on a deja determine le type avant, on le passe en parametre pour optimiser.
15197 +inline entier Octree_Int::octree_index(entier octree_id, Octree_Type type)
15198 +{
15199 +  assert(type==octree_type(octree_id));
15200 +  switch(type)
15201 +    {
15202 +    case EMPTY:
15203 +      return -1;
15204 +    case OCTREE:
15205 +      return octree_id - 1;
15206 +    case FLOOR:
15207 +      return - octree_id - 1;
15208 +    }
15209 +  return -1;
15210 +}
15211 +
15212 +// Description: Renvoie le type d'un octree en fonction de son octree_id.
15213 +inline Octree_Int::Octree_Type Octree_Int::octree_type(entier octree_id)
15214 +{
15215 +  if (octree_id > 0)
15216 +    return OCTREE;
15217 +  else if (octree_id == 0)
15218 +    return EMPTY;
15219 +  else
15220 +    return FLOOR;
15221 +}
15222 +
15223 +// Description: construction de l'octree. On donne la dimension (1, 2 ou 3)
15224 +//  et un tableau d'elements a stocker dans l'octree. Deux possibilites:
15225 +//  1) les elements sont ponctuels si elements_boxes.dimension(1) == dimension.
15226 +//     Dans ce cas, chaque element se trouve dans un et un seul octree_floor
15227 +//  2) les elements sont des parallelipipedes, si elements_boxes.dimension(1) == dimension*2
15228 +//     Les "dimension" premieres colonnes sont les coordonnees inferieures,
15229 +//     les "dimension" suivantes sont les coordonnees superieures.
15230 +//     Un parallelipipede peut etre affecte a plusieurs octree_floor.
15231 +//  Les coordonnees stockees dans elements_boxes peuvent aller de 0 a coord_max_ inclus.
15232 +//  Il vaut mieux utiliser toute la plage des entiers en multipliant par un facteur adequat.
15233 +void Octree_Int::build(const entier dimension, const IntTab& elements_boxes)
15234 +{
15235 +  assert(dimension >= 1 && dimension <= 3);
15236 +  assert(elements_boxes.dimension(1) == dimension
15237 +         || elements_boxes.dimension(1) == dimension * 2 );
15238 +
15239 +  const entier nb_elems = elements_boxes.dimension(0);
15240 +  nb_elements_ = nb_elems;
15241 +  entier i;
15242 +  octree_structure_.set_smart_resize(1);
15243 +  floor_elements_.set_smart_resize(1);
15244 +  floor_elements_.resize_array(0);
15245 +  const entier nb_octrees = 1 << dimension;
15246 +  octree_structure_.resize(0, nb_octrees);
15247 +
15248 +  assert(elements_boxes.size_array() == 0
15249 +         || (min_array(elements_boxes) >= 0 && max_array(elements_boxes) <= coord_max_));
15250 +
15251 +  VECT(ArrOfInt) tmp_elem_flags(max_levels_);
15252 +  VECT(ArrOfInt) tmp_elem_list(max_levels_);
15253 +  for (i = 0; i < max_levels_; i++)
15254 +    {
15255 +      tmp_elem_flags[i].set_smart_resize(1);
15256 +      tmp_elem_list[i].set_smart_resize(1);
15257 +    }
15258 +  ArrOfInt& elements_list = tmp_elem_list[0];
15259 +  elements_list.resize_array(nb_elems);
15260 +  for (entier i = 0; i < nb_elems; i++)
15261 +    elements_list[i] = i;
15262 +
15263 +  root_octree_id_ = build_octree_recursively(root_octree_half_width_,root_octree_half_width_,root_octree_half_width_,
15264 +                    root_octree_half_width_,
15265 +                    elements_boxes,
15266 +                    tmp_elem_list,
15267 +                    0,
15268 +                    tmp_elem_flags);
15269 +}
15270 +
15271 +// Description: renvoie la liste des elements contenant potentiellement le point (x,y,z)
15272 +//  On renvoie n=nombre d'elements de la liste et les elements sont dans
15273 +//  floor_elements()[index+i] pour 0 <= i < n.
15274 +//  En realite on renvoie tous les elements qui ont une intersection non vide avec l'octree_floor
15275 +//  contenant le point (x,y,z)
15276 +entier Octree_Int::search_elements(entier x, entier y, entier z, entier& index) const
15277 +{
15278 +  const entier nb_octrees = octree_structure_.dimension(1);
15279 +  if (nb_octrees == 2)
15280 +    y = 0; // important pour ne pas tomber sur des cubes inexistants
15281 +  if (nb_octrees <= 4)
15282 +    z = 0; // idem
15283 +  assert(x >= 0 && x <= coord_max_);
15284 +  assert(y >= 0 && y <= coord_max_);
15285 +  assert(z >= 0 && z <= coord_max_);
15286 +
15287 +  const entier octree_id = search_octree_floor(x, y, z);
15288 +
15289 +  if (octree_type(octree_id) == EMPTY)
15290 +    {
15291 +      return 0;
15292 +    }
15293 +  const entier idx = octree_index(octree_id, FLOOR);
15294 +  const entier n = floor_elements_[idx];
15295 +  index = idx + 1;
15296 +  return n;
15297 +}
15298 +
15299 +struct IntBoxData
15300 +{
15301 +  IntBoxData(entier xmin, entier ymin, entier zmin,
15302 +             entier xmax, entier ymax, entier zmax,
15303 +             ArrOfInt& elements,
15304 +             ArrOfBit *markers) :
15305 +    xmin_(xmin), ymin_(ymin), zmin_(zmin),
15306 +    xmax_(xmax), ymax_(ymax), zmax_(zmax),
15307 +    elements_(elements),
15308 +    markers_(markers) { };
15309 +  entier xmin_, ymin_, zmin_;
15310 +  entier xmax_, ymax_, zmax_;
15311 +  ArrOfInt& elements_;
15312 +  ArrOfBit *markers_;
15313 +};
15314 +
15315 +// Description: cherche les elements ayant potentiellement une intersection non vide avec la
15316 +//  boite xmin..zmax. Le tableau elements doit etre de type smart_resize(1).
15317 +//  Les elements peuvent apparaitre plusieurs fois dans le tableau "elements"
15318 +entier Octree_Int::search_elements_box(entier xmin, entier ymin, entier zmin,
15319 +                                       entier xmax, entier ymax, entier zmax,
15320 +                                       ArrOfInt& elements) const
15321 +{
15322 +  const entier nb_octrees = octree_structure_.dimension(1);
15323 +  if (nb_octrees == 2)
15324 +    ymin = ymax = 0; // important pour ne pas tomber sur des cubes inexistants
15325 +  if (nb_octrees <= 4)
15326 +    zmin = zmax = 0; // idem
15327 +  assert(xmin >= 0 && xmin <= coord_max_);
15328 +  assert(ymin >= 0 && ymin <= coord_max_);
15329 +  assert(zmin >= 0 && zmin <= coord_max_);
15330 +  assert(xmax >= 0 && xmax <= coord_max_);
15331 +  assert(ymax >= 0 && ymax <= coord_max_);
15332 +  assert(zmax >= 0 && zmax <= coord_max_);
15333 +
15334 +  elements.resize_array(0);
15335 +  IntBoxData boxdata(xmin, ymin, zmin, xmax, ymax, zmax, elements, 0);
15336 +  switch(octree_type(root_octree_id_))
15337 +    {
15338 +    case FLOOR:
15339 +      search_elements_box_floor(boxdata, root_octree_id_);
15340 +      break;
15341 +    case OCTREE:
15342 +      search_elements_box_recursively(boxdata, root_octree_id_,
15343 +                                      root_octree_half_width_,root_octree_half_width_,root_octree_half_width_,
15344 +                                      root_octree_half_width_);
15345 +      break;
15346 +    case EMPTY:
15347 +      break;
15348 +    }
15349 +  const entier n = elements.size_array();
15350 +  return n;
15351 +}
15352 +
15353 +// Description: ajoute des elements de l'octree_floor a boxdata.elements_
15354 +void Octree_Int::search_elements_box_floor(IntBoxData& boxdata,
15355 +    entier octree_floor_id) const
15356 +{
15357 +  const entier idx = octree_index(octree_floor_id, FLOOR);
15358 +  const entier n = floor_elements_[idx];
15359 +  if (boxdata.markers_)
15360 +    for (entier i = 0; i < n; i++)
15361 +      {
15362 +        const entier elem = floor_elements_[idx+1+i];
15363 +        if (!boxdata.markers_->testsetbit(elem))
15364 +          boxdata.elements_.append_array(elem);
15365 +      }
15366 +  else
15367 +    for (entier i = 0; i < n; i++)
15368 +      {
15369 +        const entier elem = floor_elements_[idx+1+i];
15370 +        boxdata.elements_.append_array(elem);
15371 +      }
15372 +}
15373 +
15374 +// Pour chaque direction, drapeaux des cubes de la rangee inferieure
15375 +static entier sub_cube_flags_min[3] = { 1+4+16+64, /* drapeaux des cubes 0,2,4,6 */
15376 +                                        1+2+16+32, /* drapeaux des cubes 0,1,4,5 */
15377 +                                        1+2+4+8    /* drapeaux des cubes 0,1,2,3 */
15378 +                                      };
15379 +static entier sub_cube_flags_max[3] = { 2+8+32+128, /* drapeaux des cubes 1,3,5,7 */
15380 +                                        4+8+64+128, /* drapeaux des cubes 2,3,7,8 */
15381 +                                        16+32+64+128 /* drapeaux des cubes 4,5,6,7 */
15382 +                                      };
15383 +
15384 +// Description: cherche recursivement les elements inclus dans la boite
15385 +//  boxdata pour l'octree_id donne, de centre cx, cy, cz.
15386 +
15387 +void Octree_Int::search_elements_box_recursively(IntBoxData& boxdata,
15388 +    entier octree_id,
15389 +    entier cx, entier cy, entier cz,
15390 +    entier half_width) const
15391 +{
15392 +  entier flags = 255;
15393 +  if (cx > boxdata.xmax_) // les cubes superieurs en x ne sont pas dedans
15394 +    flags &= sub_cube_flags_min[0];
15395 +  if (cx <= boxdata.xmin_) // les cubes inferieurs ne sont pas dedans
15396 +    flags &= sub_cube_flags_max[0];
15397 +  if (cy > boxdata.ymax_)
15398 +    flags &= sub_cube_flags_min[1];
15399 +  if (cy <= boxdata.ymin_)
15400 +    flags &= sub_cube_flags_max[1];
15401 +  if (cz > boxdata.zmax_)
15402 +    flags &= sub_cube_flags_min[2];
15403 +  if (cz <= boxdata.zmin_)
15404 +    flags &= sub_cube_flags_max[2];
15405 +  entier test_flag = 1;
15406 +  const entier idx = octree_index(octree_id, OCTREE);
15407 +  const entier half_width_2 = half_width >> 1;
15408 +  const entier mhalf_width = - half_width_2;
15409 +  entier cx2, cy2, cz2;
15410 +  for (entier i = 0; i < 8; i++, test_flag <<= 1)
15411 +    {
15412 +      if ((flags & test_flag) != 0)
15413 +        {
15414 +          const entier id = octree_structure_(idx, i);
15415 +          switch(octree_type(id))
15416 +            {
15417 +            case FLOOR:
15418 +              search_elements_box_floor(boxdata, id);
15419 +              break;
15420 +            case OCTREE:
15421 +              cx2 = cx + ((i & 1) ? half_width_2 : mhalf_width);
15422 +              cy2 = cy + ((i & 2) ? half_width_2 : mhalf_width);
15423 +              cz2 = cz + ((i & 4) ? half_width_2 : mhalf_width);
15424 +              search_elements_box_recursively(boxdata, id,
15425 +                                              cx2, cy2, cz2,
15426 +                                              half_width_2);
15427 +              break;
15428 +            case EMPTY:
15429 +              break;
15430 +            }
15431 +        }
15432 +    }
15433 +}
15434 +
15435 +void Octree_Int::reset()
15436 +{
15437 +  root_octree_id_ = octree_id(0, EMPTY);
15438 +  nb_elements_ = 0;
15439 +  octree_structure_.reset();
15440 +  floor_elements_.reset();
15441 +}
15442 +
15443 +// Description: construit un octree_floor avec la liste d'elements donnee et
15444 +//  renvoie l'octree_id de cet octree_floor
15445 +entier Octree_Int::build_octree_floor(const ArrOfInt& elements_list)
15446 +{
15447 +  const entier nb_elems = elements_list.size_array();
15448 +  const entier index = floor_elements_.size_array();
15449 +  floor_elements_.resize_array(index + nb_elems + 1);
15450 +  floor_elements_[index] = nb_elems;
15451 +  for (entier i = 0; i < nb_elems; i++)
15452 +    floor_elements_[index + 1 + i] = elements_list[i];
15453 +  return octree_id(index, FLOOR);
15454 +}
15455 +
15456 +// Description:
15457 +//  octree_center_i est le premier entier de la moitie superieure de l'octree dans la direction i.
15458 +//  octree_half_width est une puissance de 2 egale a octree_center_i-octree_min_i (octree_min_i
15459 +//   est le premier entier inclu dans cet octree dans la direction i)
15460 +// Valeur de retour: octree_id de l'octree construit (void octree_structure_)
15461 +entier Octree_Int::build_octree_recursively(const entier octree_center_x,
15462 +    const entier octree_center_y,
15463 +    const entier octree_center_z,
15464 +    const entier octree_half_width,
15465 +    const IntTab& elements_boxes,
15466 +    VECT(ArrOfInt) & vect_elements_list,
15467 +    const entier level,
15468 +    VECT(ArrOfInt) & tmp_elem_flags)
15469 +{
15470 +  // Criteres d'arret de la subdivision:
15471 +  // Nombre maximal d'elements dans un sous-cube floor
15472 +  static const entier octree_floor_max_elems = 8;
15473 +  // S'il y a beaucoup d'elements dupliques, mais pas trop, et que le nombre d'elements
15474 +  //  dans l'octree est superieur a cette valeur, on subdivise quand-meme
15475 +  static const entier octree_duplicate_elements_limit = 32;
15476 +  const ArrOfInt& elements_list = vect_elements_list[level];
15477 +  // Si le nombre d'elements est inferieur a la limite, on cree un floor_element,
15478 +  // sinon on subdivise
15479 +  const entier nb_elems = elements_list.size_array();
15480 +  if (nb_elems == 0)
15481 +    return octree_id(0, EMPTY);
15482 +
15483 +  if (nb_elems < octree_floor_max_elems || octree_half_width == 1 /* dernier niveau */)
15484 +    {
15485 +      const entier octree_id = build_octree_floor(elements_list);
15486 +      return octree_id;
15487 +    }
15488 +
15489 +  ArrOfInt& elem_flags = tmp_elem_flags[level];
15490 +  elem_flags.resize_array(0); // Ne pas conserver les anciennes valeurs
15491 +  elem_flags.resize_array(nb_elems);
15492 +
15493 +  const entier nb_octrees = octree_structure_.dimension(1);
15494 +  assert(nb_octrees == 2 || nb_octrees == 4 || nb_octrees == 8);
15495 +  const entier elem_box_dim = elements_boxes.dimension(1);
15496 +  // Soit elements_boxes contient dimension colonnes, soit dimension*2
15497 +  const entier box_delta = (elem_box_dim > 3) ? (elem_box_dim >> 1) : 0;
15498 +  // Nombre d'elements stockes en double dans l'octree (a cause des elements a cheval
15499 +  //  sur plusieurs sous-octrees)
15500 +  entier nb_duplicate_elements = 0;
15501 +  // On range les elements de la liste dans 8 sous-cubes (remplissage de elem_flags)
15502 +  for (entier i_elem = 0; i_elem < nb_elems; i_elem++)
15503 +    {
15504 +      const entier elem = elements_list[i_elem];
15505 +      // dir_flag vaut 1 pour la direction x, 2 pour y et 4 pour z
15506 +      entier dir_flag = 1;
15507 +      // sub_cube_flags contient 2^dim drapeaux binaires (1 par sous-cube),
15508 +      // et indique les sous-cubes coupes par l'element
15509 +      entier octree_flags = 255;
15510 +      // dans combien de sous-octree cet element est-il stocke ?
15511 +      entier nb_duplicates = 1;
15512 +
15513 +      for (entier direction = 0; direction < 3; direction++)
15514 +        {
15515 +          const entier elem_min = elements_boxes(elem, direction);
15516 +          const entier elem_max = elements_boxes(elem, box_delta+direction);
15517 +          assert(elem_max >= elem_min);
15518 +          // coordonnee du centre du cube dans la direction j:
15519 +          const entier center = (direction==0) ? octree_center_x : ((direction==1) ? octree_center_y : octree_center_z);
15520 +          // L'element coupe-t-il la partie inferieure et la partie superieure du cube dans la "direction" ?
15521 +          if (elem_min >= center) // non -> on retire les flags des cubes de la partie inferieure
15522 +            octree_flags &= sub_cube_flags_max[direction];
15523 +          else if (elem_max < center) // non -> on retire les flags des cubes de la partie superieure
15524 +            octree_flags &= sub_cube_flags_min[direction];
15525 +          else
15526 +            nb_duplicates <<= 1; // l'element coupe les deux parties !
15527 +          dir_flag = dir_flag << 1;
15528 +          if (dir_flag == nb_octrees)
15529 +            break;
15530 +        }
15531 +      elem_flags[i_elem] = octree_flags;
15532 +      nb_duplicate_elements += nb_duplicates - 1;
15533 +    }
15534 +
15535 +  // Critere un peu complique : s'il y a vraiment beaucoup d'elements
15536 +  //  dans cet octree, on autorise jusqu'a dupliquer tous les elements,
15537 +  //  ce qui permet de ranger des elements tres alonges qui sont forcement
15538 +  //  dupliques dans une direction (>octree_duplicate_elements_limit).
15539 +  if ((nb_duplicate_elements * 2 >= nb_elems && nb_elems < octree_duplicate_elements_limit)
15540 +      || nb_duplicate_elements > nb_elems)
15541 +    {
15542 +      const entier octree_id = build_octree_floor(elements_list);
15543 +      // On renvoie un index d'octreefloor
15544 +      return octree_id;
15545 +    }
15546 +
15547 +  // On reserve une case a la fin de octree_structure pour stocker cet octree:
15548 +  const entier index_octree = octree_structure_.dimension(0);
15549 +  octree_structure_.resize(index_octree + 1, nb_octrees);
15550 +  ArrOfInt& new_liste_elems = vect_elements_list[level+1];
15551 +  new_liste_elems.resize_array(0);
15552 +  const entier width = octree_half_width >> 1;
15553 +  const entier m_width = - width;
15554 +  // Traitement recursif des sous-cubes de l'octree:
15555 +  entier i_cube;
15556 +  for (i_cube = 0; i_cube < nb_octrees; i_cube++)
15557 +    {
15558 +      const entier octree_flag = 1 << i_cube;
15559 +      new_liste_elems.resize_array(0); // ne pas conserver les anciennes valeurs
15560 +      new_liste_elems.resize_array(nb_elems);
15561 +      entier count = 0;
15562 +      // Liste des elements inclus dans le sous-cube:
15563 +      for (entier i_elem = 0; i_elem < nb_elems; i_elem++)
15564 +        if ((elem_flags[i_elem] & octree_flag) != 0)
15565 +          new_liste_elems[count++] = elements_list[i_elem];
15566 +      new_liste_elems.resize_array(count);
15567 +
15568 +      entier sub_octree_id;
15569 +      if (new_liste_elems.size_array() == 0)
15570 +        {
15571 +          sub_octree_id = octree_id(-1, EMPTY);
15572 +        }
15573 +      else
15574 +        {
15575 +          // Coordonnees du nouveau sous-cube
15576 +          const entier cx = octree_center_x + ((i_cube&1) ? width : m_width);
15577 +          const entier cy = octree_center_y + ((i_cube&2) ? width : m_width);
15578 +          const entier cz = octree_center_z + ((i_cube&4) ? width : m_width);
15579 +          sub_octree_id = build_octree_recursively(cx, cy, cz, width,
15580 +                          elements_boxes,
15581 +                          vect_elements_list,
15582 +                          level+1,
15583 +                          tmp_elem_flags);
15584 +        }
15585 +      octree_structure_(index_octree, i_cube) = sub_octree_id;
15586 +    }
15587 +
15588 +  return octree_id(index_octree, OCTREE);
15589 +}
15590 +
15591 +// Description: renvoie l'octree_id de l'octree_floor contenant le sommet (x,y,z)
15592 +//  (peut renvoyer l'octree EMPTY)
15593 +entier Octree_Int::search_octree_floor(entier x, entier y, entier z) const
15594 +{
15595 +  if (octree_type(root_octree_id_) != OCTREE)
15596 +    return root_octree_id_;
15597 +  // Le test pour savoir si on est dans la partie superieure ou
15598 +  // inferieure d'un octree au niveau i consiste simplement a tester
15599 +  // le i-ieme bit de la position.
15600 +  entier flag = root_octree_half_width_;
15601 +
15602 +  entier index = octree_index(root_octree_id_, OCTREE);
15603 +
15604 +  // Descendre dans la hierarchie d'octree subdivises jusqu'au cube
15605 +  //  le plus petit
15606 +  while (1)
15607 +    {
15608 +      // Numero du sous-cube dans lequel se trouve le sommet x,y,z
15609 +      const entier ix = (x & flag) ? 1 : 0;
15610 +      const entier iy = (y & flag) ? 2 : 0;
15611 +      const entier iz = (z & flag) ? 4 : 0;
15612 +      entier i_sous_cube = ix + iy + iz;
15613 +      // On entre dans le sous-cube :
15614 +      const entier octree_id = octree_structure_(index, i_sous_cube);
15615 +      if (octree_type(octree_id) != OCTREE)
15616 +        return octree_id;
15617 +
15618 +      index = octree_index(octree_id, OCTREE);
15619 +      flag >>= 1;
15620 +    }
15621 +  return -1; // On n'arrive jamais ici !
15622 +}
15623 diff --git a/databases/readers/Lata/Octree_Int.h b/databases/readers/Lata/Octree_Int.h
15624 new file mode 100644
15625 index 0000000..ace9c2d
15626 --- /dev/null
15627 +++ b/databases/readers/Lata/Octree_Int.h
15628 @@ -0,0 +1,103 @@
15629 +/*****************************************************************************
15630 +*
15631 +* Copyright (c) 2011 - 2013, CEA
15632 +* All rights reserved.
15633 +* Redistribution and use in source and binary forms, with or without
15634 +* modification, are permitted provided that the following conditions are met:
15635 +*
15636 +*     * Redistributions of source code must retain the above copyright
15637 +*       notice, this list of conditions and the following disclaimer.
15638 +*     * Redistributions in binary form must reproduce the above copyright
15639 +*       notice, this list of conditions and the following disclaimer in the
15640 +*       documentation and/or other materials provided with the distribution.
15641 +*     * Neither the name of CEA, nor the
15642 +*       names of its contributors may be used to endorse or promote products
15643 +*       derived from this software without specific prior written permission.
15644 +*
15645 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
15646 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15647 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15648 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
15649 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
15650 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
15651 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
15652 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
15653 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
15654 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15655 +*
15656 +*****************************************************************************/
15657 +
15658 +#ifndef Octree_Int_inclus
15659 +#define Octree_Int_inclus
15660 +#include <IntTab.h>
15661 +#include <VectArrOfInt.h>
15662 +
15663 +struct IntBoxData;
15664 +class ArrOfBit;
15665 +
15666 +// .DESCRIPTION : Un octree permettant de retrouver des objets ponctuels ou
15667 +//   parallelipipediques dans un espace 1D, 2D ou 3D et des coordonnees entieres
15668 +class Octree_Int
15669 +{
15670 +public:
15671 +  void   build(const entier dimension, const IntTab& elements_boxes);
15672 +  entier search_elements(entier x, entier y, entier z, entier& floor_elements_index) const;
15673 +  entier search_elements_box(entier xmin, entier ymin, entier zmin,
15674 +                             entier xmax, entier ymax, entier zmax,
15675 +                             ArrOfInt& elements) const;
15676 +  void   reset();
15677 +
15678 +  inline const ArrOfInt& floor_elements() const
15679 +  {
15680 +    return floor_elements_;
15681 +  };
15682 +
15683 +  // Le plus grand entier autorise pour les coordonnees (du type 2^n - 1)
15684 +  static const entier coord_max_;
15685 +  // Premier entier de la moitie superieure de l'octree root (si coord_max_=2^n-1, half_width_=2^(n-1))
15686 +  static const entier root_octree_half_width_;
15687 +protected:
15688 +  entier build_octree_recursively(const entier octree_center_x, const entier octree_center_y, const entier octree_center_z,
15689 +                                  const entier octree_half_width,
15690 +                                  const IntTab& elements_boxes,
15691 +                                  VECT(ArrOfInt) & vect_elements_list,
15692 +                                  const entier level,
15693 +                                  VECT(ArrOfInt) & tmp_elem_flags);
15694 +  entier build_octree_floor(const ArrOfInt& elements_list);
15695 +
15696 +  entier search_octree_floor(entier x_pos, entier y_pos, entier z_pos) const;
15697 +  void   search_elements_box_floor(IntBoxData& boxdata,
15698 +                                   entier octree_floor_id) const;
15699 +  void   search_elements_box_recursively(IntBoxData& boxdata,
15700 +                                         entier octree_id,
15701 +                                         entier cx, entier cy, entier cz,
15702 +                                         entier half_width) const;
15703 +
15704 +  // Un octree peut etre soit vide, soit subdivise en nb_octrees autres octrees,
15705 +  // soit un octree_floor contenant une liste d'elements.
15706 +  enum Octree_Type { EMPTY, OCTREE, FLOOR };
15707 +
15708 +  static inline entier octree_id(entier index, Octree_Type type);
15709 +  static inline entier octree_index(entier octree_id, Octree_Type type);
15710 +  static inline Octree_Type octree_type(entier octree_id);
15711 +
15712 +  // Octree_id du cube principal : peut etre EMPTY, OCTREE ou FLOOR
15713 +  entier root_octree_id_;
15714 +  // Nombre d'elements stockes (dimension(0) du tableau elements_boxes)
15715 +  entier nb_elements_;
15716 +  // Tableau contenant tous les cubes qui sont divises en sous-cubes
15717 +  //  octree_structure_(i, j) decrit le contenu du sous-cube j du cube d'index i.
15718 +  //  pour 0 <= j < nombre de sous-cubes par cube.
15719 +  //  On appelle "octree_id" une valeur X=octree_structure_(i,j) (identifiant octree)
15720 +  //  L'octree id encode a la fois le type de l'octree et l'index ou
15721 +  //  il se trouve dans les tableaux (voir octree_id(entier, Octree_Type))
15722 +  IntTab octree_structure_;
15723 +
15724 +  // Tableau contenant la liste des elements de chaque sous-cube final non subdivise.
15725 +  // Si X < 0, on note i_debut = -X-1.
15726 +  // floor_elements_(i_debut) = n = nombre d'elements dans ce sous-cube
15727 +  // floor_elements_[i_debut+j] = numero d'un element qui coupe ce sous-cube pour 1 <= j <= n
15728 +  ArrOfInt floor_elements_;
15729 +};
15730 +
15731 +#endif
15732 diff --git a/databases/readers/Lata/OpenDXWriter.C b/databases/readers/Lata/OpenDXWriter.C
15733 new file mode 100644
15734 index 0000000..7add5ed
15735 --- /dev/null
15736 +++ b/databases/readers/Lata/OpenDXWriter.C
15737 @@ -0,0 +1,335 @@
15738 +/*****************************************************************************
15739 +*
15740 +* Copyright (c) 2011 - 2013, CEA
15741 +* All rights reserved.
15742 +* Redistribution and use in source and binary forms, with or without
15743 +* modification, are permitted provided that the following conditions are met:
15744 +*
15745 +*     * Redistributions of source code must retain the above copyright
15746 +*       notice, this list of conditions and the following disclaimer.
15747 +*     * Redistributions in binary form must reproduce the above copyright
15748 +*       notice, this list of conditions and the following disclaimer in the
15749 +*       documentation and/or other materials provided with the distribution.
15750 +*     * Neither the name of CEA, nor the
15751 +*       names of its contributors may be used to endorse or promote products
15752 +*       derived from this software without specific prior written permission.
15753 +*
15754 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
15755 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15756 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15757 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
15758 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
15759 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
15760 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
15761 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
15762 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
15763 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15764 +*
15765 +*****************************************************************************/
15766 +
15767 +#include <OpenDXWriter.h>
15768 +#include <LataFilter.h>
15769 +#include <iostream>
15770 +#include <fstream>
15771 +#include <iosfwd>
15772 +
15773 +class DX_stream;
15774 +
15775 +class DX_stream
15776 +{
15777 +public:
15778 +  DX_stream() : os_to_cout_(0), os_(0) {};
15779 +  void init_cout(int is_ascii) 
15780 +  { 
15781 +    reset();
15782 +    os_to_cout_ = 1;
15783 +    ascii_ = is_ascii;
15784 +    os_ = &std::cout;
15785 +  }
15786 +  void init_file(const char *fname, int is_ascii)
15787 +  {
15788 +    reset();
15789 +    os_to_cout_ = 0;
15790 +    ascii_ = is_ascii;
15791 +    os_ = new std::ofstream(fname);
15792 +  }
15793 +  ~DX_stream() { reset(); }
15794 +  void reset()
15795 +  {
15796 +    if (!os_to_cout_)
15797 +      delete os_;
15798 +    os_ = 0;
15799 +    os_to_cout_ = 0;
15800 +  }
15801 +  DX_stream & operator<<(const float f) { (*os_) << f; return *this; }
15802 +  DX_stream & operator<<(const int i) { (*os_) << i; return *this; }
15803 +  DX_stream & operator<<(const char * s) { (*os_) << s; return *this; }
15804 +  DX_stream & operator<<(DX_stream & f(DX_stream &)) { return f(*this); }
15805 +
15806 +  void write(char * ptr, int sz) { os_->write(ptr, sz); }
15807 +  entier ok() { return os_ != 0; }
15808 +  entier ascii() { return ascii_; }
15809 +  std::ostream & stream() { return *os_; }
15810 +protected:
15811 +  int os_to_cout_;
15812 +  int ascii_;
15813 +  std::ostream *os_;
15814 +};
15815 +
15816 +DX_stream & endl(DX_stream & os) 
15817 +{ 
15818 +  os.stream() << std::endl; 
15819 +  return os; 
15820 +}
15821 +
15822 +void DX_write_vect(DX_stream & os, int dxobject, const ArrOfFloat & v)
15823 +{
15824 +  const int places = v.size_array();
15825 +  os << "object " << dxobject << " class array" << endl;
15826 +  os << "type float rank 1 shape 1 items " << places << " ";
15827 +
15828 +  if (!os.ascii()) {
15829 +    os << (mymachine_msb ? "msb ieee" : "lsb ieee") << " data follows" << endl;
15830 +    os.write((char*)v.addr(), sizeof(float) * places);
15831 +  } else {
15832 +    os << "ascii data follows" << endl;
15833 +    for (int i=0;i<places;i++) {
15834 +      os << v[i] << " ";
15835 +      os << endl;
15836 +    }
15837 +  }
15838 +}
15839 +void DX_write_vect(DX_stream & os, int dxobject, const FloatTab & v)
15840 +{
15841 +  const int places = v.dimension(0);
15842 +  const int shape  = v.dimension(1);
15843 +  os << "object " << dxobject << " class array" << endl;
15844 +  os << "type float rank 1 shape " << shape << " items " << places << " ";
15845 +
15846 +  if (!os.ascii()) {
15847 +    os << (mymachine_msb ? "msb ieee" : "lsb ieee") << " data follows" << endl;
15848 +    os.write((char*)v.addr(), sizeof(float) * places * shape);
15849 +  } else {
15850 +    os << "ascii data follows" << endl;
15851 +    for (int i=0;i<places;i++) {
15852 +      for (int j=0;j<shape;j++)
15853 +        os << v(i, j) << " ";
15854 +      os << endl;
15855 +    }
15856 +  }
15857 +}
15858 +
15859 +void DX_write_vect(DX_stream & os, int dxobject, const IntTab & v)
15860 +{
15861 +  if (sizeof(int) != 4) {
15862 +    Journal() << "Error DX_write_vect : int size != 32 bits" << endl;
15863 +    throw OpenDXWriter::DXInternalError;
15864 +  }
15865 +  const int places = v.dimension(0);
15866 +  const int shape  = v.dimension(1);
15867 +  os << "object " << dxobject << " class array" << endl;
15868 +  os << "type int rank 1 shape " << shape << " items " << places << " ";
15869 +
15870 +  if (!os.ascii()) {
15871 +    os << (mymachine_msb ? "msb ieee" : "lsb ieee") << " data follows" << endl;
15872 +    os.write((char*)v.addr(), sizeof(int) * places * shape);
15873 +  } else {
15874 +    os << "ascii data follows" << endl;
15875 +    for (int i=0;i<places;i++) {
15876 +      for (int j=0;j<shape;j++)
15877 +        os << v(i, j) << " ";
15878 +      os << endl;
15879 +    }
15880 +  }
15881 +}
15882 +
15883 +OpenDXWriter::OpenDXWriter()
15884 +{
15885 +  os_ = new DX_stream;
15886 +}
15887 +
15888 +OpenDXWriter::~OpenDXWriter()
15889 +{
15890 +  delete os_;
15891 +}
15892 +
15893 +void OpenDXWriter::reset()
15894 +{
15895 +  index_counter_ = 0;
15896 +  fields_indexes_.resize_array(0);
15897 +  fields_indexes_.set_smart_resize(1);
15898 +  fields_names_ = Noms();
15899 +  nodes_index_ = -1;
15900 +  finish_geometry(); // reset geometry data
15901 +}
15902 +
15903 +void OpenDXWriter::init_cout(double time, int ascii)
15904 +{
15905 +  reset();
15906 +  os_->init_cout(ascii);
15907 +  dx_time_index_ = ++index_counter_;
15908 +  FloatTab t;
15909 +  t.resize(1,1);
15910 +  t(0,0) = time;
15911 +  DX_write_vect(*os_, dx_time_index_, t);
15912 +}
15913 +
15914 +void OpenDXWriter::init_file(double time, Nom & filename_, int ascii)
15915 +{
15916 +  reset();
15917 +  os_->init_file(filename_, ascii);
15918 +  dx_time_index_ = ++index_counter_;
15919 +  FloatTab t;
15920 +  t.resize(1,1);
15921 +  t(0,0) = time;
15922 +  DX_write_vect(*os_, dx_time_index_, t);
15923 +}
15924 +
15925 +const char * DX_element_name(Domain::Element elem)
15926 +{
15927 +  switch(elem) {
15928 +  case Domain::line: return "lines";
15929 +  case Domain::triangle: return "triangles";
15930 +  case Domain::quadri: return "quads";
15931 +  case Domain::tetra: return "tetrahedra";
15932 +  case Domain::hexa: return "cubes";
15933 +  default:
15934 +    Journal() << "DX_element_name unknown element" << endl;
15935 +    throw OpenDXWriter::DXInternalError;
15936 +  }
15937 +}
15938 +
15939 +void OpenDXWriter::write_geometry(const Domain & dom)
15940 +{
15941 +  // Write last geometry and begin a new one
15942 +  finish_geometry();
15943 +  const DomainUnstructured * dom1 = dynamic_cast<const DomainUnstructured*>(&dom);
15944 +  const DomainIJK * dom2 = dynamic_cast<const DomainIJK*>(&dom);
15945 +  DX_stream & os = *os_;
15946 +  if (dom1) {
15947 +    nodes_index_ = ++index_counter_;
15948 +    DX_write_vect(os, nodes_index_, dom1->nodes_);
15949 +    elements_index_ = ++index_counter_;
15950 +    DX_write_vect(os, elements_index_, dom1->elements_);
15951 +    os << "attribute \"element type\" string \"" << DX_element_name(dom.elt_type_) << "\"" << endl;
15952 +    os << "attribute \"ref\" string \"positions\"" << endl;
15953 +  } else if (dom2) {
15954 +    const entier dim = dom.dimension();
15955 +    ArrOfInt dx_coord_index(dim);
15956 +    for (entier i = 0; i < dim; i++) {
15957 +      dx_coord_index[i] = ++index_counter_;
15958 +      const entier n = dom2->coord_[i].size_array();
15959 +      FloatTab tmp;
15960 +      tmp.resize(n, 3);
15961 +      for (entier j = 0; j < n; j++)
15962 +        tmp(j, i) = dom2->coord_[i][j];
15963 +      DX_write_vect(os, dx_coord_index[i], tmp);
15964 +    }
15965 +    nodes_index_ = ++index_counter_;
15966 +    os << "object " << nodes_index_ << " class productarray" << endl;
15967 +    entier i;
15968 +    for (i = dim-1; i >= 0; i--)
15969 +      os << " term " << dx_coord_index[i] << endl;
15970 +    elements_index_ = ++index_counter_;
15971 +    os << "object " << elements_index_ << " class gridconnections counts";
15972 +    for (i = dim-1; i >= 0; i--)
15973 +      os << " " << dom2->coord_[i].size_array();
15974 +    os << endl;
15975 +    os << "attribute \"element type\" string \"" << ((dim==2)?"quads":"cubes") << "\"" << endl;
15976 +    os << "attribute \"ref\" string \"positions\"" << endl;
15977 +    const entier n1 = dom2->invalid_positions_.size_array();
15978 +    if (n1 > 0) {
15979 +      invalid_positions_ = ++index_counter_;
15980 +      IntTab tmp;
15981 +      tmp.resize(n1, 1);
15982 +      ArrOfInt & array = tmp;
15983 +      for (entier ii = 0; ii < n1; ii++) array[ii] = dom2->invalid_positions_[ii];
15984 +      DX_write_vect(os, invalid_positions_, tmp);
15985 +      os << "attribute \"ref\" string \"positions\"" << endl;
15986 +    }
15987 +#if 0
15988 +    if (n2 > 0) {
15989 +      IntTab tmp;
15990 +      tmp.resize(n2, 1);
15991 +      ArrOfInt & array = tmp;
15992 +      for (entier i = 0; i < n2; i++) array[i] = dom2->invalid_connections_[i];
15993 +      DX_write_vect(os, invalid_connections_, tmp);
15994 +      os << "attribute \"ref\" string \"connections\"" << endl;
15995 +    }
15996 +#endif
15997 +  } else {
15998 +    Journal() << "Error OpenDXWriter::write_geometry domain type not supported" << endl;
15999 +    throw DXInternalError;
16000 +  }
16001 +  fields_names_.add(dom.id_.name_);
16002 +}
16003 +
16004 +void OpenDXWriter::finish_geometry()
16005 +{
16006 +  if (nodes_index_ >= 0) {
16007 +    index_counter_++;
16008 +    fields_indexes_.append_array(index_counter_);
16009 +    DX_stream & os = *os_;
16010 +    os << "object " << index_counter_ << " class field" << endl;
16011 +    os << " component \"positions\" " << nodes_index_ << endl;
16012 +    os << " component \"connections\" " << elements_index_ << endl;
16013 +    if (invalid_positions_ >= 0)
16014 +      os << " component \"invalid positions\" " << invalid_positions_ << endl;
16015 +    if (invalid_connections_ >= 0)
16016 +      os << " component \"invalid connections\" " << invalid_connections_ << endl;
16017 +    os << " component \"TIME\" " << dx_time_index_ << endl;
16018 +
16019 +    for (entier i=0; i < components_indexes_.size_array(); i++)
16020 +      os << " component \"" << components_names_[i] << "\" " << components_indexes_[i] << endl;
16021 +  }
16022 +  nodes_index_ = -1;
16023 +  elements_index_ = -1;
16024 +  components_indexes_.resize_array(0);
16025 +  components_indexes_.set_smart_resize(1);
16026 +  components_names_ = Noms();
16027 +  invalid_positions_ = -1;
16028 +  invalid_connections_ = -1;
16029 +}
16030 +
16031 +void OpenDXWriter::write_component(const LataField_base & field)
16032 +{
16033 +  index_counter_++;
16034 +  const Field<IntTab> * int_field = dynamic_cast<const Field<IntTab>*>(&field);
16035 +  const Field<FloatTab> * float_field = dynamic_cast<const Field<FloatTab>*>(&field);
16036 +  if (int_field)
16037 +    DX_write_vect(*os_, index_counter_, int_field->data_);
16038 +  else if (float_field)
16039 +    DX_write_vect(*os_, index_counter_, float_field->data_);
16040 +  else {
16041 +    Journal() << "Error OpenDXWriter::write_component: unknown field type" << endl;
16042 +    throw;
16043 +  }
16044 +  if (field.localisation_ == LataField_base::ELEM)
16045 +    (*os_) << "attribute \"dep\" string \"connections\"" << endl;
16046 +  else if (field.localisation_ == LataField_base::SOM)
16047 +    (*os_) << "attribute \"dep\" string \"positions\"" << endl;
16048 +  else
16049 +   {
16050 +    ; // no attribute
16051 +   }
16052 +  components_indexes_.append_array(index_counter_);
16053 +  Nom n = field.id_.uname_.get_field_name();
16054 +  n += "_";
16055 +  n += field.id_.uname_.get_localisation();
16056 +  components_names_.add(n);
16057 +}
16058 +
16059 +entier OpenDXWriter::finish(int force_group)
16060 +{
16061 +  DX_stream & os = *os_;
16062 +  finish_geometry();
16063 +  if (force_group || fields_indexes_.size_array() > 1) {
16064 +    //DX_stream & os = *os_;
16065 +    os << "object " << ++index_counter_ << " class group" << endl;
16066 +    for (entier i = 0; i < fields_indexes_.size_array(); i++) {
16067 +      os << " member \"" << fields_names_[i] << "\" value " << fields_indexes_[i] << endl;
16068 +    }
16069 +  }
16070 +  os << "END" << endl;
16071 +  return index_counter_;
16072 +}
16073 diff --git a/databases/readers/Lata/OpenDXWriter.h b/databases/readers/Lata/OpenDXWriter.h
16074 new file mode 100644
16075 index 0000000..e8f6358
16076 --- /dev/null
16077 +++ b/databases/readers/Lata/OpenDXWriter.h
16078 @@ -0,0 +1,83 @@
16079 +/*****************************************************************************
16080 +*
16081 +* Copyright (c) 2011 - 2013, CEA
16082 +* All rights reserved.
16083 +* Redistribution and use in source and binary forms, with or without
16084 +* modification, are permitted provided that the following conditions are met:
16085 +*
16086 +*     * Redistributions of source code must retain the above copyright
16087 +*       notice, this list of conditions and the following disclaimer.
16088 +*     * Redistributions in binary form must reproduce the above copyright
16089 +*       notice, this list of conditions and the following disclaimer in the
16090 +*       documentation and/or other materials provided with the distribution.
16091 +*     * Neither the name of CEA, nor the
16092 +*       names of its contributors may be used to endorse or promote products
16093 +*       derived from this software without specific prior written permission.
16094 +*
16095 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
16096 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16097 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16098 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
16099 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16100 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
16101 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
16102 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
16103 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
16104 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16105 +*
16106 +*****************************************************************************/
16107 +
16108 +#ifndef OpenDXWriter_H_
16109 +#define OpenDXWriter_H_
16110 +#include <ArrOfInt.h>
16111 +#include <Lata_tools.h>
16112 +
16113 +class Domain;
16114 +class LataField_base;
16115 +// Usage:
16116 +//   init_cout(...) or init_file(...)
16117 +//   for (i=0; i < nb_geometries; i++) {
16118 +//     write_geometry(...);
16119 +//     for (j=0; j < nb_fields; j++)
16120 +//       write_component(...);
16121 +//   }
16122 +//   finish();
16123 +class DX_stream;
16124 +class OpenDXWriter
16125 +{
16126 +public:
16127 +  OpenDXWriter();
16128 +  ~OpenDXWriter();
16129 +  void init_cout(double time, int ascii = 0);
16130 +  void init_file(double time, Nom & filename_, int ascii = 0);
16131 +
16132 +  void write_geometry(const Domain & dom);
16133 +  void write_component(const LataField_base & field);
16134 +
16135 +  entier finish(int force_group = 0);
16136 +  enum DXErrors { DXInternalError };
16137 +protected:
16138 +  void reset();
16139 +  void finish_geometry();
16140 +
16141 +  int dx_time_index_;
16142 +  int index_counter_;
16143 +  // Indexes of all DXfield objects in the file (to build the final group)
16144 +  ArrOfInt fields_indexes_;
16145 +  // Names of the DXfields:
16146 +  Noms fields_names_;
16147 +
16148 +  // Index of the nodes array of the last geometry
16149 +  int nodes_index_;
16150 +  // Index of the elements array of the last geometry
16151 +  int elements_index_;
16152 +  // Index of these arrays:
16153 +  int invalid_positions_;
16154 +  int invalid_connections_;
16155 +  // Indexes of the components associated with the last geometry
16156 +  ArrOfInt components_indexes_;
16157 +  Noms components_names_;
16158 +
16159 +  DX_stream * os_;
16160 +};
16161 +#endif
16162 diff --git a/databases/readers/Lata/Operator.h b/databases/readers/Lata/Operator.h
16163 new file mode 100644
16164 index 0000000..2ae94bf
16165 --- /dev/null
16166 +++ b/databases/readers/Lata/Operator.h
16167 @@ -0,0 +1,224 @@
16168 +/*****************************************************************************
16169 +*
16170 +* Copyright (c) 2011 - 2013, CEA
16171 +* All rights reserved.
16172 +* Redistribution and use in source and binary forms, with or without
16173 +* modification, are permitted provided that the following conditions are met:
16174 +*
16175 +*     * Redistributions of source code must retain the above copyright
16176 +*       notice, this list of conditions and the following disclaimer.
16177 +*     * Redistributions in binary form must reproduce the above copyright
16178 +*       notice, this list of conditions and the following disclaimer in the
16179 +*       documentation and/or other materials provided with the distribution.
16180 +*     * Neither the name of CEA, nor the
16181 +*       names of its contributors may be used to endorse or promote products
16182 +*       derived from this software without specific prior written permission.
16183 +*
16184 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
16185 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16186 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16187 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
16188 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16189 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
16190 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
16191 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
16192 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
16193 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16194 +*
16195 +*****************************************************************************/
16196 +
16197 +#ifndef OPERATORS_H
16198 +#define OPERATORS_H
16199 +#include <LataFilter.h>
16200 +
16201 +// A tool to "reconnect" several subdomains of a parallel computation:
16202 +//  reconnect_geometry() searches for duplicate node coordinates and 
16203 +//  changes the elements_ and faces_ arrays to use the smallest node
16204 +//  index that has the same coordinate. Hence, we recover the connectivity
16205 +//  between blocks.
16206 +class Reconnect
16207 +{
16208 +public:
16209 +  static void reconnect_geometry(DomainUnstructured & geom, double tolerance, entier nb_nodes_untouched = 0);
16210 +  static void apply_renumbering(const ArrOfInt & nodes_renumber, ArrOfInt & data);
16211 +  static void search_duplicate_nodes(const FloatTab & src_coord,
16212 +                                     ArrOfInt & nodes_renumber,
16213 +                                     double eps,
16214 +                                     entier nb_nodes_untouched = 0);
16215 +};
16216 +
16217 +class OperatorClipbox : public Operator
16218 +{
16219 +public:
16220 +  void build_geometry(const Domain & src_domain, LataDeriv<Domain> & dest);
16221 +  void build_field(const Domain & src_domain, const LataField_base & src_field, 
16222 +                   const Domain & dest_domain, LataDeriv<LataField_base> & dest);
16223 +  // Renumerotation des sommets, elements et faces par rapport aux donnees brutes lues
16224 +  // renum_truc_[new_index] = index in lata file;
16225 +  // La renumerotation vient de clip_box et de regularize
16226 +  ArrOfInt renum_nodes_;
16227 +  ArrOfInt renum_elements_;
16228 +  ArrOfInt renum_faces_;
16229 +};
16230 +
16231 +class OperatorBoundary : public Operator
16232 +{
16233 +public:
16234 +  OperatorBoundary() { geom_init_ = 0; }
16235 +  void build_geometry(const Domain & src_domain, LataDeriv<Domain> & dest);
16236 +  void build_field(const Domain & src_domain, const LataField_base & src_field, 
16237 +                   const Domain & dest_domain, LataDeriv<LataField_base> & dest);
16238 +  BigEntier compute_memory_size() const {
16239 +    return
16240 +      memory_size(src_nodes_)
16241 +      + memory_size(src_element_)
16242 +      + memory_size(src_face_);
16243 +  }
16244 +  // Renumerotation des sommets, elements et faces par rapport aux donnees brutes lues
16245 +  // renum_truc_[new_index] = index in lata file;
16246 +  // La renumerotation vient de clip_box et de regularize
16247 +  ArrOfInt src_nodes_; // for each boundary node, which node is it in source domain ?
16248 +  ArrOfInt src_element_; // same for boundary face vs source domain element
16249 +  ArrOfInt src_face_; // local face number on src_element_
16250 +  entier geom_init_;
16251 +};
16252 +
16253 +class OperatorRegularize : public Operator
16254 +{
16255 +public:
16256 +  OperatorRegularize() { tolerance_ = -1.; geom_init_ = 0; extend_layer_ = 0; }
16257 +  void set_tolerance(double epsilon) { tolerance_ = epsilon; }
16258 +  void set_extend_layer(entier n) { if (n >= 0) extend_layer_ = n; else extend_layer_ = 0; }
16259 +  void build_geometry(const Domain & src_domain, LataDeriv<Domain> & dest);
16260 +  void build_field(const Domain & src_domain, const LataField_base & src_field, 
16261 +                   const Domain & dest_domain, LataDeriv<LataField_base> & dest);
16262 +  
16263 +  BigEntier compute_memory_size() const {
16264 +    return
16265 +      memory_size(renum_nodes_)
16266 +      + memory_size(renum_elements_)
16267 +      + memory_size(renum_faces_);
16268 +  }
16269 +  // Renumerotation des sommets, elements et faces par rapport aux donnees brutes lues
16270 +  // renum_truc_[old_index] = new_index;
16271 +  ArrOfInt renum_nodes_;
16272 +  ArrOfInt renum_elements_;
16273 +  // Pour les faces: les faces de chaque direction du domaine ijk sont numerotees 
16274 +  //  separement: faces de normales X entre 0 et N, faces de normales Y entre 0 et N, etc...
16275 +  // Le numero d'une face est egal au plus petit des numeros de ses sommets du le maillage ijk.
16276 +  // Renum faces contient le codage suivant:
16277 +  //  numero de la face = renum_faces_[i] >> 2;
16278 +  //  direction de la face  = (renum_faces_ & 3)
16279 +  ArrOfInt renum_faces_;
16280 +  double tolerance_;
16281 +  entier extend_layer_;
16282 +  entier geom_init_;
16283 +};
16284 +
16285 +class OperatorDualMesh : public Operator
16286 +{
16287 +public:
16288 +  void build_geometry(const Domain & src_domain, LataDeriv<Domain> & dest);
16289 +  void build_field(const Domain & src_domain, const LataField_base & src_field, 
16290 +                   const Domain & dest_domain, LataDeriv<LataField_base> & dest);
16291 +  BigEntier compute_memory_size() const { return 0; }
16292 +};
16293 +class OperatorFacesMesh : public Operator
16294 +{
16295 +public:
16296 +  void build_geometry(const Domain & src_domain, LataDeriv<Domain> & dest);
16297 +  void build_field(const Domain & src_domain, const LataField_base & src_field, 
16298 +                   const Domain & dest_domain, LataDeriv<LataField_base> & dest);
16299 +  BigEntier compute_memory_size() const { return 0; }
16300 +};
16301 +
16302 +class OperatorNCMesh : public Operator
16303 +{
16304 +public:
16305 +  void build_geometry(const Domain & src_domain, LataDeriv<Domain> & dest);
16306 +  void build_field(const Domain & src_domain, const LataField_base & src_field, 
16307 +                   const Domain & dest_domain, LataDeriv<LataField_base> & dest);  
16308 +  BigEntier compute_memory_size() const { return 0; }
16309 +};
16310 +
16311 +// These generic methods just say that the particular function does not exist:
16312 +void build_geometry_(Operator & op, const Domain & src, LataDeriv<Domain> & dest);
16313 +void build_field_(Operator & op, const Domain & src, const Domain & dest, 
16314 +                  const LataField_base & srcf, LataField_base & destf);
16315 +
16316 +template<class Op>
16317 +void apply_geometry(Op & op, const Domain & src_domain, LataDeriv<Domain> & dest)
16318 +{
16319 +  const DomainUnstructured *src1 = dynamic_cast<const DomainUnstructured*>(&src_domain);
16320 +  const DomainIJK *src2 = dynamic_cast<const DomainIJK*>(&src_domain);
16321 +
16322 +  if (src1) {
16323 +    build_geometry_(op, *src1, dest);
16324 +  } else if (src2) {
16325 +    build_geometry_(op, *src2, dest);
16326 +  } else {
16327 +    Journal() << "Error in OperatorDualMesh::build_geometry: unsupported domain type" << endl;
16328 +    throw;
16329 +  } 
16330 +}
16331 +
16332 +// See apply_field
16333 +template <class Op, class DomSrc, class DomDest>
16334 +void apply_field3(Op & op, const DomSrc & src_domain, const LataField_base & src_field,
16335 +                  const DomDest & dest_domain, LataDeriv<LataField_base> & dest)
16336 +{
16337 +  const Field<DoubleTab> *src1 = dynamic_cast<const Field<DoubleTab>*> (&src_field);
16338 +  const Field<FloatTab>  *src2 = dynamic_cast<const Field<FloatTab>*> (&src_field);
16339 +  const Field<IntTab>    *src3 = dynamic_cast<const Field<IntTab>*> (&src_field);
16340 +  
16341 +  if (src1)
16342 +    build_field_(op, src_domain, dest_domain, *src1, dest.instancie(Field<DoubleTab> ));
16343 +  else if (src2)
16344 +    build_field_(op, src_domain, dest_domain, *src2, dest.instancie(Field<FloatTab> ));
16345 +  else if (src3)
16346 +    build_field_(op, src_domain, dest_domain, *src3, dest.instancie(Field<IntTab> ));
16347 +  else {
16348 +    Journal() << "Error in apply_field3: unsupported field type" << endl;
16349 +    throw;
16350 +  }
16351 +}
16352 +
16353 +// See apply_field
16354 +template <class Op, class DomSrc>
16355 +void apply_field2(Op & op, const DomSrc & src_domain, const LataField_base & src_field,
16356 +                  const Domain & dest_domain, LataDeriv<LataField_base> & dest)
16357 +{
16358 +  const DomainUnstructured *d1 = dynamic_cast<const DomainUnstructured*>(&dest_domain);
16359 +  const DomainIJK          *d2 = dynamic_cast<const DomainIJK*>(&dest_domain);
16360 +  if (d1)
16361 +    apply_field3(op, src_domain, src_field, *d1, dest);
16362 +  else if (d2)
16363 +    apply_field3(op, src_domain, src_field, *d2, dest);
16364 +  else {
16365 +    Journal() << "Error in apply_field2: unsupported destination domain type" << endl;
16366 +    throw;
16367 +  }
16368 +}
16369 +
16370 +// This template calls the appropriate "build_field_()" method in the given operator.
16371 +//  The operator should implement non virtual methods for any usefull combination
16372 +//  of source domain type, destination domain type and source field type. This template
16373 +//  will call the correct method depending on the effective type of the parameters
16374 +//  (determined with dynamic_cast).
16375 +template <class Op>
16376 +void apply_field(Op & op, const Domain & src_domain, const LataField_base & src_field,
16377 +                 const Domain & dest_domain, LataDeriv<LataField_base> & dest)
16378 +{
16379 +  const DomainUnstructured *d1 = dynamic_cast<const DomainUnstructured*>(&src_domain);
16380 +  const DomainIJK          *d2 = dynamic_cast<const DomainIJK*>(&src_domain);
16381 +  if (d1)
16382 +    apply_field2(op, *d1, src_field, dest_domain, dest);
16383 +  else if (d2)
16384 +    apply_field2(op, *d2, src_field, dest_domain, dest);
16385 +  else {
16386 +    Journal() << "Error in apply_field: unsupported source domain type" << endl;
16387 +    throw;
16388 +  }
16389 +}
16390 +
16391 +#endif
16392 diff --git a/databases/readers/Lata/OperatorBoundary.C b/databases/readers/Lata/OperatorBoundary.C
16393 new file mode 100644
16394 index 0000000..1e10d1a
16395 --- /dev/null
16396 +++ b/databases/readers/Lata/OperatorBoundary.C
16397 @@ -0,0 +1,227 @@
16398 +/*****************************************************************************
16399 +*
16400 +* Copyright (c) 2011 - 2013, CEA
16401 +* All rights reserved.
16402 +* Redistribution and use in source and binary forms, with or without
16403 +* modification, are permitted provided that the following conditions are met:
16404 +*
16405 +*     * Redistributions of source code must retain the above copyright
16406 +*       notice, this list of conditions and the following disclaimer.
16407 +*     * Redistributions in binary form must reproduce the above copyright
16408 +*       notice, this list of conditions and the following disclaimer in the
16409 +*       documentation and/or other materials provided with the distribution.
16410 +*     * Neither the name of CEA, nor the
16411 +*       names of its contributors may be used to endorse or promote products
16412 +*       derived from this software without specific prior written permission.
16413 +*
16414 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
16415 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16416 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16417 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
16418 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16419 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
16420 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
16421 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
16422 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
16423 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16424 +*
16425 +*****************************************************************************/
16426 +
16427 +#include <LataFilter.h>
16428 +#include <Operator.h>
16429 +#include <Static_Int_Lists.h>
16430 +#include <Connectivite_som_elem.h>
16431 +
16432 +// Journal level for messages
16433 +#define verb_level 4
16434 +
16435 +void build_ref_elem_face(const Domain::Element elt_type, IntTab & ref_elem_face)
16436 +{
16437 +  static entier faces_sommets_tetra[4][3] = 
16438 +    { { 1, 2, 3 },
16439 +      { 0, 3, 2 },
16440 +      { 3, 0, 1 },
16441 +      { 0, 2, 1 } };
16442 +  static entier faces_sommets_hexa[6][4] = 
16443 +    { { 0, 2, 4, 6 },
16444 +      { 0, 1, 4, 5 },
16445 +      { 0, 1, 2, 3 },
16446 +      { 1, 3, 5, 7 },
16447 +      { 2, 3, 6, 7 },
16448 +      { 4, 5, 6, 7 } };
16449 +
16450 +  int i, j;
16451 +  switch(elt_type) {
16452 +  case Domain::tetra:
16453 +    ref_elem_face.resize(4,3);
16454 +    for(i=0;i<4;i++)
16455 +      for(j=0;j<3;j++)
16456 +        ref_elem_face(i,j) = faces_sommets_tetra[i][j];
16457 +    break;
16458 +  case Domain::hexa:
16459 +    ref_elem_face.resize(6,4);
16460 +    for(i=0;i<6;i++)
16461 +      for(j=0;j<4;j++)
16462 +        ref_elem_face(i,j) = faces_sommets_hexa[i][j];
16463 +    break;
16464 +  default:
16465 +    Journal() << "build_ref_elem_face : non code pour element "
16466 +              << endl;
16467 +  }
16468 +}
16469 +
16470 +void build_geometry_(OperatorBoundary & op,
16471 +                     const DomainUnstructured & src, LataDeriv<Domain> & dest_domain)
16472 +{
16473 +  Journal(verb_level) << "OperatorBoundary domain " << src.id_.name_ << endl;
16474 +  DomainUnstructured & dest = dest_domain.instancie(DomainUnstructured);
16475 +  switch(src.elt_type_) {
16476 +  case Domain::tetra: dest.elt_type_ = Domain::triangle; break;
16477 +  case Domain::hexa:  dest.elt_type_ = Domain::quadri; break;
16478 +  default:
16479 +    Journal() << "Error in OperatorBoundary: element type not supported" << endl;
16480 +    throw;
16481 +  }
16482 +
16483 +  Static_Int_Lists som_elem;
16484 +  construire_connectivite_som_elem(src.nb_nodes(), src.elements_, som_elem, 0);
16485 +  // For each element:
16486 +  //  for each face of this element
16487 +  //    how many neighbouring elements ?
16488 +  //      if only one neighbour, it's a boundary face !
16489 +
16490 +  IntTab element_faces;
16491 +  build_ref_elem_face(src.elt_type_, element_faces);
16492 +  op.src_element_.set_smart_resize(1);
16493 +  op.src_face_.set_smart_resize(1);
16494 +  op.src_nodes_.set_smart_resize(1);
16495 +  const int nb_nodes_per_face = element_faces.dimension(1);
16496 +  const int nb_faces_per_element = element_faces.dimension(0);
16497 +
16498 +  ArrOfInt one_face(nb_nodes_per_face);
16499 +  ArrOfInt adjacent_elements;
16500 +
16501 +  // For each node in the source domain, node number on the boundary:
16502 +  ArrOfInt nodes_renumber;
16503 +  nodes_renumber.resize_array(src.nb_nodes());
16504 +  nodes_renumber = -1;
16505 +
16506 +  entier element_index, local_face_index;
16507 +  // Browse only real elements (so we don't see boundaries between processors)
16508 +  const entier nelem = src.nb_elements() - src.nb_virt_items(LataField_base::ELEM);
16509 +  entier i;
16510 +  entier count = 0;
16511 +  for (element_index = 0; element_index < nelem; element_index++) {
16512 +    for (local_face_index = 0; local_face_index < nb_faces_per_element; local_face_index++) {
16513 +      for (i = 0; i < nb_nodes_per_face; i++) {
16514 +        int local_node = element_faces(local_face_index, i);
16515 +        int node = src.elements_(element_index, local_node);
16516 +        one_face[i] = node;
16517 +      }
16518 +      find_adjacent_elements(som_elem, one_face, adjacent_elements);
16519 +      if (adjacent_elements.size_array() == 1) {
16520 +        op.src_element_.append_array(element_index);
16521 +        op.src_face_.append_array(local_face_index);
16522 +        for (i = 0; i < nb_nodes_per_face; i++) {
16523 +          const entier node = one_face[i];
16524 +          entier dest_node = nodes_renumber[node];
16525 +          if (dest_node < 0) {
16526 +            dest_node = count++;
16527 +            op.src_nodes_.append_array(node);
16528 +            nodes_renumber[node] = dest_node;
16529 +          }
16530 +        }
16531 +      }
16532 +    }
16533 +  }
16534 +
16535 +  // Build nodes
16536 +  const entier nb_nodes = op.src_nodes_.size_array();
16537 +  const entier dim = src.nodes_.dimension(1);
16538 +  dest.nodes_.resize(nb_nodes, dim);
16539 +  for (i = 0; i < nb_nodes; i++) {
16540 +    const entier n = op.src_nodes_[i];
16541 +    for (entier j = 0; j < dim; j++) 
16542 +      dest.nodes_(i, j) = src.nodes_(n, j);
16543 +  }
16544 +
16545 +  // Build elements
16546 +  const entier nb_elems = op.src_element_.size_array();
16547 +  dest.elements_.resize(nb_elems, nb_nodes_per_face);
16548 +  for (i = 0; i < nb_elems; i++) {
16549 +    const entier elem = op.src_element_[i];
16550 +    const entier face = op.src_face_[i];
16551 +    for (entier j = 0; j < nb_nodes_per_face; j++) {
16552 +      const entier src_node = src.elements_(elem, element_faces(face, j));
16553 +      dest.elements_(i, j) = nodes_renumber[src_node];
16554 +    }
16555 +  }
16556 +  op.geom_init_ = 1;
16557 +}
16558 +
16559 +template <class TabType>
16560 +void build_field_(OperatorBoundary & op,
16561 +                  const DomainUnstructured & src_domain,
16562 +                  const DomainUnstructured & dest_domain,
16563 +                  const Field<TabType> & src,
16564 +                  Field<TabType> & dest)
16565 +{
16566 +  if (!op.geom_init_) {
16567 +    // Must fill the renum_.... arrays first !
16568 +    LataDeriv<Domain> destb;
16569 +    op.build_geometry(src_domain, destb);
16570 +  }
16571 +  dest.component_names_ = src.component_names_;
16572 +  dest.localisation_ = src.localisation_;
16573 +  dest.nature_ = src.nature_;
16574 +  if (dest.localisation_ == LataField_base::FACES)
16575 +    dest.localisation_ = LataField_base::ELEM;
16576 +
16577 +  const entier nb_compo = src.data_.dimension(1);
16578 +  entier i, sz = 0;
16579 +  switch(src.localisation_) {
16580 +  case LataField_base::ELEM:
16581 +    sz = dest_domain.nb_elements();
16582 +    dest.data_.resize(sz, nb_compo);
16583 +    for (i = 0; i < sz; i++) {
16584 +      const entier old_i = op.src_element_[i];
16585 +      for (entier j = 0; j < nb_compo; j++)
16586 +        dest.data_(i, j) = src.data_(old_i, j);
16587 +    }
16588 +    break;
16589 +  case LataField_base::SOM:
16590 +    sz = dest_domain.nb_nodes();
16591 +    dest.data_.resize(sz, nb_compo);
16592 +    for (i = 0; i < sz; i++) {
16593 +      const entier old_i = op.src_nodes_[i];
16594 +      for (entier j = 0; j < nb_compo; j++)
16595 +        dest.data_(i, j) = src.data_(old_i, j);
16596 +    }
16597 +    break;
16598 +  case LataField_base::FACES:
16599 +    sz = dest_domain.nb_elements();
16600 +    dest.data_.resize(sz, nb_compo);
16601 +    for (i = 0; i < sz; i++) {
16602 +      const entier old_i = src_domain.elem_faces_(op.src_element_[i], op.src_face_[i]);
16603 +      for (entier j = 0; j < nb_compo; j++)
16604 +        dest.data_(i, j) = src.data_(old_i, j);
16605 +    }
16606 +    break;
16607 +  default:
16608 +    Journal() << "Error in OperatorRegularize::build_field_: unknown localisation" << endl;
16609 +    throw;   
16610 +  }
16611 +}
16612 +
16613 +void OperatorBoundary::build_geometry(const Domain & src_domain, LataDeriv<Domain> & dest)
16614 +{
16615 +  apply_geometry(*this, src_domain, dest);
16616 +}
16617 +
16618 +void OperatorBoundary::build_field(const Domain & src_domain, const LataField_base & src_field,
16619 +                                   const Domain & dest_domain, LataDeriv<LataField_base> & dest)
16620 +{
16621 +  apply_field(*this, src_domain, src_field, dest_domain, dest);
16622 +}
16623 +
16624 +#undef verb_level
16625 diff --git a/databases/readers/Lata/OperatorDualMesh.C b/databases/readers/Lata/OperatorDualMesh.C
16626 new file mode 100644
16627 index 0000000..9ecd859
16628 --- /dev/null
16629 +++ b/databases/readers/Lata/OperatorDualMesh.C
16630 @@ -0,0 +1,222 @@
16631 +/*****************************************************************************
16632 +*
16633 +* Copyright (c) 2011 - 2013, CEA
16634 +* All rights reserved.
16635 +* Redistribution and use in source and binary forms, with or without
16636 +* modification, are permitted provided that the following conditions are met:
16637 +*
16638 +*     * Redistributions of source code must retain the above copyright
16639 +*       notice, this list of conditions and the following disclaimer.
16640 +*     * Redistributions in binary form must reproduce the above copyright
16641 +*       notice, this list of conditions and the following disclaimer in the
16642 +*       documentation and/or other materials provided with the distribution.
16643 +*     * Neither the name of CEA, nor the
16644 +*       names of its contributors may be used to endorse or promote products
16645 +*       derived from this software without specific prior written permission.
16646 +*
16647 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
16648 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16649 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16650 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
16651 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16652 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
16653 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
16654 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
16655 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
16656 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16657 +*
16658 +*****************************************************************************/
16659 +
16660 +#include <LataFilter.h>
16661 +#include <Operator.h>
16662 +
16663 +// Journal level
16664 +#define verb_level 4
16665 +
16666 +void build_geometry_(OperatorDualMesh & op,
16667 +                     const DomainUnstructured & src, LataDeriv<Domain> & dest_domain)
16668 +{
16669 +  Journal(verb_level) << "OperatorDualMesh geometry(unstructured) " << src.id_.name_ << endl;
16670 +  if (!src.faces_ok()) {
16671 +    Journal() << "Error in OperatorDualMesh::build_geometry: source domain has no faces data" << endl;
16672 +    throw;
16673 +  }
16674 +  const int max_nb_som_face = 3; // for tetrahedra
16675 +  if (src.elt_type_ != Domain::triangle && src.elt_type_ != Domain::tetra) {
16676 +    Journal() << "Error in OperatorDualMesh::build_geometry: cannot operate on unstructured mesh with this element type" << endl;
16677 +    throw;
16678 +  }
16679 +  const entier nb_som = src.nodes_.dimension(0);
16680 +  const entier nb_elem = src.elem_faces_.dimension(0); // Not elements_, in case elem_faces_ has no virtual data.
16681 +  const entier dim = src.dimension();
16682 +
16683 +  DomainUnstructured & dest = dest_domain.instancie(DomainUnstructured);
16684 +  dest.id_ = src.id_;
16685 +  dest.id_.name_ += "_dual";
16686 +  dest.elt_type_ = src.elt_type_;
16687 +
16688 +  dest.nodes_ = src.nodes_;
16689 +  dest.nodes_.resize(nb_som + nb_elem, dim);
16690 +  src.compute_cell_center_coordinates(dest.nodes_, nb_som);
16691 +
16692 +  const entier nb_faces_elem = src.elem_faces_.dimension(1);
16693 +  const entier nb_som_face = src.faces_.dimension(1);
16694 +  const entier nb_som_elem = src.elements_.dimension(1);
16695 +  dest.elements_.resize(nb_elem * nb_faces_elem, nb_som_elem);
16696 +  int index = 0;
16697 +  for (int i = 0; i < nb_elem; i++) {
16698 +    const int central_node = nb_som + i;
16699 +    for (int j = 0; j < nb_faces_elem; j++) {
16700 +      const int face = src.elem_faces_(i, j);
16701 +      dest.elements_(index, 0) = central_node;
16702 +      for (int k = 0; k < loop_max(nb_som_face, max_nb_som_face); k++) {
16703 +        dest.elements_(index, k+1) = src.faces_(face, k);
16704 +        break_loop(k, nb_som_face);
16705 +      }
16706 +      index++;
16707 +    }
16708 +  }
16709 +  const entier nb_elem_virt = src.nb_virt_items(LataField_base::ELEM);
16710 +  dest.set_nb_virt_items(LataField_base::ELEM, nb_elem_virt * nb_faces_elem);
16711 +}
16712 +
16713 +// Builds a field on the dual domain from the field on the source domain.
16714 +// Source field must be located at faces.
16715 +// (destination field is located at the elements. the value for an element
16716 +//  is the value associated to the adjacent face of the source domain).
16717 +template <class TabType>
16718 +void build_field_(OperatorDualMesh & op,
16719 +                  const DomainUnstructured & src_domain,
16720 +                  const DomainUnstructured & dest_domain,
16721 +                  const Field<TabType> & src,
16722 +                  Field<TabType> & dest)
16723 +{
16724 +  Journal(verb_level) << "OperatorDualMesh field(unstructured) " << src.id_.uname_ << endl;
16725 +  dest.component_names_ = src.component_names_;
16726 +  dest.localisation_ = LataField_base::ELEM;
16727 +  dest.nature_ = src.nature_;
16728 +  const entier nb_elem = src_domain.elements_.dimension(0);
16729 +  const entier nb_face_elem = src_domain.elem_faces_.dimension(1);
16730 +  const entier nb_comp = src.data_.dimension(1);
16731 +  dest.data_.resize(nb_elem * nb_face_elem, nb_comp);
16732 +  int index = 0;
16733 +  for (int i = 0; i < nb_elem; i++) {
16734 +    for (int j = 0; j < nb_face_elem; j++) {
16735 +      const int face = src_domain.elem_faces_(i, j);
16736 +      for (int k = 0; k < nb_comp; k++)
16737 +        dest.data_(index, k) = src.data_(face, k);
16738 +      index++;
16739 +    }
16740 +  }
16741 +}
16742 +
16743 +void build_geometry_(OperatorDualMesh & op,
16744 +                     const DomainIJK & src, LataDeriv<Domain> & dest_domain)
16745 +{
16746 +  Journal(verb_level) << "OperatorDualMesh geometry(ijk) " << src.id_.name_ << endl;
16747 +  if (src.elt_type_ != Domain::quadri && src.elt_type_ != Domain::hexa) {
16748 +    Journal() << "Error in OperatorDualMesh::build_geometry: cannot operate on unstructured mesh with this element type" << endl;
16749 +    throw;
16750 +  }
16751 +
16752 +  DomainIJK & dest = dest_domain.instancie(DomainIJK);
16753 +  dest.elt_type_ = src.elt_type_;
16754 +  const entier dim = src.dimension();
16755 +  for (entier i_dim = 0; i_dim < dim; i_dim++) {
16756 +    const ArrOfFloat & c1 = src.coord_[i_dim];
16757 +    ArrOfFloat & c2 = dest.coord_.add(ArrOfFloat());
16758 +    const int n = c1.size_array() - 1;
16759 +    c2.resize_array(n*2+1);
16760 +    for (int i = 0; i < n; i++) {
16761 +      c2[i*2] = c1[i];
16762 +      c2[i*2+1] = (c1[i] + c1[i+1]) * 0.5;
16763 +    }
16764 +    c2[n*2] = c1[n];
16765 +  }
16766 +
16767 +  if (src.invalid_connections_.size_array() > 0) {
16768 +    dest.invalid_connections_.resize_array(dest.nb_elements());
16769 +    dest.invalid_connections_ = 0;
16770 +    int index = 0;
16771 +    
16772 +    const entier ni = dest.coord_[0].size_array()-1;
16773 +    const entier nj = dest.coord_[1].size_array()-1;
16774 +    const entier nk = (dim==3) ? (dest.coord_[2].size_array()-1) : 1;
16775 +    const entier ni_src = src.coord_[0].size_array() - 1;
16776 +    const entier nj_src = src.coord_[1].size_array() - 1;
16777 +    for (int k = 0; k < nk; k++) {
16778 +      const int k_src = k / 2;
16779 +      for (int j = 0; j < nj; j++) {
16780 +        const int j_src = j / 2;
16781 +        const int idx_source = (k_src * nj_src + j_src) * ni_src;
16782 +        for (int i = 0; i < ni; i++) {
16783 +          const int idx = idx_source + i / 2;
16784 +          if (src.invalid_connections_[idx])
16785 +            dest.invalid_connections_.setbit(index);
16786 +          index++;
16787 +        }
16788 +      }
16789 +    }
16790 +  }
16791 +  dest.virtual_layer_begin_ = 2 * src.virtual_layer_begin_;
16792 +  dest.virtual_layer_end_ = 2 * src.virtual_layer_end_;
16793 +}
16794 +#define IJK(i,j,k) (k*nj_ni_src + j*ni_src + i)
16795 +
16796 +template <class TabType>
16797 +void build_field_(OperatorDualMesh & op,
16798 +                  const DomainIJK & src_domain,
16799 +                  const DomainIJK & dest_domain,
16800 +                  const Field<TabType> & src,
16801 +                  Field<TabType> & dest)
16802 +{
16803 +  Journal(verb_level) << "OperatorDualMesh field(ijk) " << src.id_.uname_ << endl;
16804 +  dest.component_names_ = src.component_names_;
16805 +  dest.localisation_ = LataField_base::ELEM;
16806 +  dest.nature_ = LataDBField::VECTOR;
16807 +  const entier dim = src_domain.dimension();
16808 +  int index = 0;
16809 +
16810 +  // Loop on destination elements
16811 +  const entier ni = dest_domain.coord_[0].size_array()-1;
16812 +  const entier nj = dest_domain.coord_[1].size_array()-1;
16813 +  const entier nk = (dim==3) ? (dest_domain.coord_[2].size_array()-1) : 1;
16814 +  dest.data_.resize(ni*nj*nk, dim);
16815 +  const entier ni_src = src_domain.coord_[0].size_array();
16816 +  const entier nj_ni_src = src_domain.coord_[1].size_array() * ni_src;
16817 +  for (int k = 0; k < nk; k++) {
16818 +    const int k2 = k/2;
16819 +    const int k3 = (k+1)/2;
16820 +    for (int j = 0; j < nj; j++) {
16821 +      const int j2 = j/2;
16822 +      const int j3 = (j+1)/2;
16823 +      for (int i = 0; i < ni; i++) {
16824 +        const int i2 = i/2;
16825 +        const int i3 = (i+1)/2;
16826 +        dest.data_(index, 0) = src.data_(IJK(i3,j2,k2), 0);
16827 +        dest.data_(index, 1) = src.data_(IJK(i2,j3,k2), 1);
16828 +        if (dim==3)
16829 +          dest.data_(index, 2) = src.data_(IJK(i2,j2,k3), 2);
16830 +        index++;
16831 +      }
16832 +    }
16833 +  }
16834 +}
16835 +
16836 +#undef IJK
16837 +
16838 +void OperatorDualMesh::build_geometry(const Domain & src_domain, LataDeriv<Domain> & dest)
16839 +{
16840 +  apply_geometry(*this, src_domain, dest);
16841 +}
16842 +
16843 +void OperatorDualMesh::build_field(const Domain & src_domain, const LataField_base & src_field,
16844 +                                   const Domain & dest_domain, LataDeriv<LataField_base> & dest)
16845 +{
16846 +  if (src_field.localisation_ != LataField_base::FACES) {
16847 +    Journal() << "Error in OperatorDualMesh::build_field: source field is not located at faces" << endl;
16848 +    throw;
16849 +  }
16850 +  apply_field(*this, src_domain, src_field, dest_domain, dest);
16851 +}
16852 +#undef level
16853 diff --git a/databases/readers/Lata/OperatorFacesMesh.C b/databases/readers/Lata/OperatorFacesMesh.C
16854 new file mode 100644
16855 index 0000000..6aa85a5
16856 --- /dev/null
16857 +++ b/databases/readers/Lata/OperatorFacesMesh.C
16858 @@ -0,0 +1,130 @@
16859 +/*****************************************************************************
16860 +*
16861 +* Copyright (c) 2011 - 2013, CEA
16862 +* All rights reserved.
16863 +* Redistribution and use in source and binary forms, with or without
16864 +* modification, are permitted provided that the following conditions are met:
16865 +*
16866 +*     * Redistributions of source code must retain the above copyright
16867 +*       notice, this list of conditions and the following disclaimer.
16868 +*     * Redistributions in binary form must reproduce the above copyright
16869 +*       notice, this list of conditions and the following disclaimer in the
16870 +*       documentation and/or other materials provided with the distribution.
16871 +*     * Neither the name of CEA, nor the
16872 +*       names of its contributors may be used to endorse or promote products
16873 +*       derived from this software without specific prior written permission.
16874 +*
16875 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
16876 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16877 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16878 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
16879 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16880 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
16881 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
16882 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
16883 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
16884 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16885 +*
16886 +*****************************************************************************/
16887 +
16888 +#include <LataFilter.h>
16889 +#include <Operator.h>
16890 +
16891 +// Journal level
16892 +#define verb_level 4
16893 +
16894 +void build_geometry_(OperatorFacesMesh & op,
16895 +                     const DomainUnstructured & src, LataDeriv<Domain> & dest_domain)
16896 +{
16897 +  Journal(verb_level) << "OperatorFacesMesh geometry(unstructured) " << src.id_.name_ << endl;
16898 +  if (!src.faces_ok()) {
16899 +    Journal() << "Error in OperatorFacesMesh::build_geometry: source domain has no faces data" << endl;
16900 +    throw;
16901 +  }
16902 +  // const int max_nb_som_face = 3; // for tetrahedra
16903 +  if (src.elt_type_ != Domain::triangle && src.elt_type_ != Domain::polygone && src.elt_type_ != Domain::tetra && src.elt_type_ != Domain::polyedre) {
16904 +    Journal() << "Error in OperatorFacesMesh::build_geometry: cannot operate on unstructured mesh with this element type" << endl;
16905 +    throw;
16906 +  }
16907 +  //  const entier nb_som = src.nodes_.dimension(0);
16908 +  // const entier nb_elem = src.elem_faces_.dimension(0); // Not elements_, in case elem_faces_ has no virtual data.
16909 +  //const entier dim = src.dimension();
16910 +
16911 +  DomainUnstructured & dest = dest_domain.instancie(DomainUnstructured);
16912 +  dest.id_ = src.id_;
16913 +  dest.id_.name_ += "_centerfaces";
16914 +  if (src.elt_type_ == Domain::triangle || src.elt_type_ == Domain::polygone)
16915 +    dest.elt_type_=Domain::line;
16916 +  else if ( src.elt_type_ == Domain::tetra)
16917 +    dest.elt_type_=Domain::triangle;
16918 +  else if ( src.elt_type_ == Domain::polyedre)
16919 +    dest.elt_type_=Domain::polygone;
16920 +
16921 +  dest.nodes_ = src.nodes_;
16922 +  dest.elements_ = src.faces_;
16923 +      
16924 +    
16925 +
16926 +  
16927 +  const entier nb_elem_virt = src.nb_virt_items(LataField_base::FACES);
16928 +  dest.set_nb_virt_items(LataField_base::ELEM, nb_elem_virt );
16929 +}
16930 +
16931 +// Builds a field on the dual domain from the field on the source domain.
16932 +// Source field must be located at faces.
16933 +// (destination field is located at the elements. the value for an element
16934 +//  is the value associated to the adjacent face of the source domain).
16935 +template <class TabType>
16936 +void build_field_(OperatorFacesMesh & op,
16937 +                  const DomainUnstructured & src_domain,
16938 +                  const DomainUnstructured & dest_domain,
16939 +                  const Field<TabType> & src,
16940 +                  Field<TabType> & dest)
16941 +{
16942 +  Journal(verb_level) << "OperatorFacesMesh field(unstructured) " << src.id_.uname_ << endl;
16943 +  dest.component_names_ = src.component_names_;
16944 +  dest.localisation_ = LataField_base::ELEM;
16945 +  dest.nature_ = src.nature_;
16946 +
16947 +  dest.data_=src.data_;
16948 +   
16949 +  
16950 +} 
16951 +
16952 +void build_geometry_(OperatorFacesMesh & op,
16953 +                     const DomainIJK & src, LataDeriv<Domain> & dest_domain)
16954 +{
16955 +  Journal(verb_level) << "OperatorFacesMesh geometry(ijk) " << src.id_.name_ << endl;
16956 +  Journal() << "Error in OperatorFacesMesh::build_geometry: cannot operate on domainIJK" << endl;
16957 +  throw;
16958 +
16959 +}
16960 +template <class TabType>
16961 +void build_field_(OperatorFacesMesh & op,
16962 +                  const DomainIJK & src_domain,
16963 +                  const DomainIJK & dest_domain,
16964 +                  const Field<TabType> & src,
16965 +                  Field<TabType> & dest)
16966 +{
16967 +  Journal(verb_level) << "OperatorFacesMesh field(ijk) " << src.id_.uname_ << endl;
16968 +  Journal() << "Error in OperatorFacesMesh::build_geometry: cannot operate on domainIJK" << endl;
16969 +  throw;
16970 +} 
16971 +
16972 +
16973 +
16974 +void OperatorFacesMesh::build_geometry(const Domain & src_domain, LataDeriv<Domain> & dest)
16975 +{
16976 +  apply_geometry(*this, src_domain, dest);
16977 +}
16978 +
16979 +void OperatorFacesMesh::build_field(const Domain & src_domain, const LataField_base & src_field,
16980 +                                   const Domain & dest_domain, LataDeriv<LataField_base> & dest)
16981 +{
16982 +  if (src_field.localisation_ != LataField_base::FACES) {
16983 +    Journal() << "Error in OperatorFacesMesh::build_field: source field is not located at faces" << endl;
16984 +    throw;
16985 +  }
16986 +  apply_field(*this, src_domain, src_field, dest_domain, dest);
16987 +}
16988 +#undef level
16989 diff --git a/databases/readers/Lata/OperatorReconnect.C b/databases/readers/Lata/OperatorReconnect.C
16990 new file mode 100644
16991 index 0000000..4cabccc
16992 --- /dev/null
16993 +++ b/databases/readers/Lata/OperatorReconnect.C
16994 @@ -0,0 +1,125 @@
16995 +/*****************************************************************************
16996 +*
16997 +* Copyright (c) 2011 - 2013, CEA
16998 +* All rights reserved.
16999 +* Redistribution and use in source and binary forms, with or without
17000 +* modification, are permitted provided that the following conditions are met:
17001 +*
17002 +*     * Redistributions of source code must retain the above copyright
17003 +*       notice, this list of conditions and the following disclaimer.
17004 +*     * Redistributions in binary form must reproduce the above copyright
17005 +*       notice, this list of conditions and the following disclaimer in the
17006 +*       documentation and/or other materials provided with the distribution.
17007 +*     * Neither the name of CEA, nor the
17008 +*       names of its contributors may be used to endorse or promote products
17009 +*       derived from this software without specific prior written permission.
17010 +*
17011 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17012 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17013 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17014 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
17015 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17016 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
17017 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
17018 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17019 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
17020 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17021 +*
17022 +*****************************************************************************/
17023 +
17024 +#include <Operator.h>
17025 +#include <Octree_Double.h>
17026 +
17027 +#define verb_level 4
17028 +
17029 +// Description: Find duplicate coordinates in the "coord" array.
17030 +//  nodes_renumber will have dimension src_coord.dimension(0)
17031 +//  nodes_renumber[i] = i if the node imust be conserved,
17032 +//  nodes_renumber[i] = j if the node i is identical to node j. We always have j<i
17033 +//  eps = tolerance in each direction to consider that two nodes are identical
17034 +//  nb_nodes_untouched : do not search duplicate nodes in the "nb_nodes_untouched"
17035 +//   first nodes. The remaining nodes are still compared to all nodes.
17036 +void Reconnect::search_duplicate_nodes(const FloatTab & src_coord,
17037 +                                       ArrOfInt & nodes_renumber,
17038 +                                       double eps,
17039 +                                       entier nb_nodes_untouched)
17040 +{
17041 +  // Create a temporary DoubleTab (coords are normally float)
17042 +  const entier nb_nodes = src_coord.dimension(0);
17043 +  const entier dim = src_coord.dimension(1);
17044 +  entier i;
17045 +  // Build an octree with all coordinates
17046 +  Journal(verb_level+1) << " Building octree" << endl;
17047 +  DoubleTab coords;
17048 +  coords.resize(nb_nodes, dim);
17049 +  for (i = 0; i < nb_nodes; i++) 
17050 +    for (entier j = 0; j < dim; j++)
17051 +      coords(i,j) = src_coord(i,j);
17052 +  Octree_Double octree;
17053 +  octree.build_nodes(coords, 0 /* no virtual nodes */);
17054 +  
17055 +  Journal(verb_level+1) << " Searching duplicate nodes" << endl;
17056 +  nodes_renumber.resize_array(nb_nodes);
17057 +  for (i = 0; i < nb_nodes; i++)
17058 +    nodes_renumber[i] = i;
17059 +  // For each node, are there several nodes within epsilon ?
17060 +  ArrOfInt node_list;
17061 +  node_list.set_smart_resize(1);
17062 +  entier count = 0; // Number of nodes renumbered
17063 +  for (i = 0; i < nb_nodes; i++) {
17064 +    if (nodes_renumber[i] != i)
17065 +      continue; // node already suppressed
17066 +
17067 +    const double x = coords(i, 0);
17068 +    const double y = (dim>1) ? coords(i, 1) : 0.;
17069 +    const double z = (dim>2) ? coords(i, 2) : 0.;
17070 +    octree.search_elements_box(x-eps, y-eps, z-eps,
17071 +                               x+eps, y+eps, z+eps,
17072 +                               node_list);
17073 +    Octree_Double::search_nodes_close_to(x, y, z,
17074 +                                         coords, node_list,
17075 +                                         eps);
17076 +    const entier n = node_list.size_array();
17077 +    if (n > 1) {
17078 +      for (entier j = 0; j < n; j++) {
17079 +        // Change only nodes with rank > i
17080 +        const entier node = node_list[j];
17081 +        if (node > j) {
17082 +          nodes_renumber[node] = i;
17083 +          count++;
17084 +        }
17085 +      }
17086 +    }
17087 +  }
17088 +  Journal(verb_level+1) << " " << count << " duplicate nodes will be removed" << endl;
17089 +}
17090 +
17091 +void Reconnect::apply_renumbering(const ArrOfInt & nodes_renumber, ArrOfInt & data)
17092 +{
17093 +  entier ntot = data.size_array();
17094 +  entier i;
17095 +  for (i = 0; i < ntot; i++) {
17096 +    const entier node = data[i];
17097 +    const entier n = nodes_renumber[node];
17098 +    if (n != node)
17099 +      data[i] = n;
17100 +  }  
17101 +}
17102 +
17103 +// Description: updates the elements_ and faces_ arrays of the domain so that
17104 +//  all nodes having the same coordinates are replaced by one unique node
17105 +//  in these arrays. See search_duplicate_nodes for nb_nodes_untouched description.
17106 +void Reconnect::reconnect_geometry(DomainUnstructured & geom, double tolerance, entier nb_nodes_untouched)
17107 +{
17108 +  Journal(verb_level) << "Reconnect domain " << geom.id_.name_ << endl;
17109 +
17110 +  ArrOfInt nodes_renumber;
17111 +  search_duplicate_nodes(geom.nodes_, nodes_renumber, tolerance, nb_nodes_untouched);
17112 +
17113 +  apply_renumbering(nodes_renumber, geom.elements_);
17114 +  
17115 +  if (geom.faces_ok()) 
17116 +    apply_renumbering(nodes_renumber, geom.faces_);
17117 +}
17118 +
17119 +#undef verb_level
17120 diff --git a/databases/readers/Lata/OperatorRegularize.C b/databases/readers/Lata/OperatorRegularize.C
17121 new file mode 100644
17122 index 0000000..5bbde88
17123 --- /dev/null
17124 +++ b/databases/readers/Lata/OperatorRegularize.C
17125 @@ -0,0 +1,296 @@
17126 +/*****************************************************************************
17127 +*
17128 +* Copyright (c) 2011 - 2013, CEA
17129 +* All rights reserved.
17130 +* Redistribution and use in source and binary forms, with or without
17131 +* modification, are permitted provided that the following conditions are met:
17132 +*
17133 +*     * Redistributions of source code must retain the above copyright
17134 +*       notice, this list of conditions and the following disclaimer.
17135 +*     * Redistributions in binary form must reproduce the above copyright
17136 +*       notice, this list of conditions and the following disclaimer in the
17137 +*       documentation and/or other materials provided with the distribution.
17138 +*     * Neither the name of CEA, nor the
17139 +*       names of its contributors may be used to endorse or promote products
17140 +*       derived from this software without specific prior written permission.
17141 +*
17142 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17143 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17144 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17145 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
17146 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17147 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
17148 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
17149 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17150 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
17151 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17152 +*
17153 +*****************************************************************************/
17154 +
17155 +#include <LataFilter.h>
17156 +#include <Operator.h>
17157 +
17158 +#define verb_level 4
17159 +
17160 +template<class T, class Tab> int search_in_ordered_vect(T x, const Tab & v, const T epsilon) {
17161 +  if (!v.size_array())
17162 +    return -1;
17163 +  int i1=0;
17164 +  int i;
17165 +  int i2 = (int)v.size_array()-1;
17166 +  while (i1 != i2) {
17167 +    i = (i1+i2)/2;
17168 +    if (epsilon+ v[i] < x)
17169 +      i1=i+1;
17170 +    else
17171 +      i2=i;
17172 +  }
17173 +  if (v[i1] == x)
17174 +    return i1;
17175 +  if (((v[i1] - x) * (v[i1] - x))<= (epsilon*epsilon) )
17176 +    return i1;
17177 +
17178 +  return -1;
17179 +}
17180 +
17181 +template<class T, class Tab>
17182 +static void retirer_doublons(Tab & tab, const T epsilon)
17183 +{
17184 +  int i = 0;
17185 +  int j;
17186 +  const int n = tab.size_array();
17187 +  T last_tab_i = -1e40;
17188 +  for (j = 0; j < n; j++) {
17189 +    const T x = tab[j];
17190 +    assert(x >= last_tab_i); // Array must be sorted
17191 +    if (x - last_tab_i > epsilon) {
17192 +      tab[i] = x;
17193 +      last_tab_i = x;
17194 +      i++;
17195 +    }
17196 +  }
17197 +  tab.resize_array(i);
17198 +}
17199 +
17200 +void build_geometry_(OperatorRegularize & op,
17201 +                     const DomainUnstructured & src, LataDeriv<Domain> & dest_domain)
17202 +{
17203 +  Journal(verb_level) << "OperatorRegularize domain " << src.id_.name_ << endl;
17204 +  if (src.elt_type_ != Domain::quadri && src.elt_type_ != Domain::hexa) {
17205 +    Journal() << "Error in OperatorRegularize::build_geometry: cannot operate on unstructured mesh with this element type" << endl;
17206 +    throw;
17207 +  }
17208 +
17209 +  DomainIJK & dest = dest_domain.instancie(DomainIJK);
17210 +  dest.elt_type_ = src.elt_type_;
17211 +  const entier nsom = src.nodes_.dimension(0);
17212 +  const entier dim = src.nodes_.dimension(1);
17213 +  ArrOfInt nb_som_dir(dim);
17214 +  {
17215 +    double product_n = 1.;
17216 +    for (entier i_dim = 0; i_dim < dim; i_dim++) {
17217 +      ArrOfFloat & coord = dest.coord_.add(ArrOfFloat());
17218 +      coord.resize_array(nsom);
17219 +      entier i;
17220 +      for (i = 0; i < nsom; i++)
17221 +        coord[i] = src.nodes_(i, i_dim);
17222 +      coord.ordonne_array();
17223 +      retirer_doublons(coord, op.tolerance_);
17224 +      product_n *= coord.size_array();
17225 +      // Add extended domain layer:
17226 +      if (coord.size_array() > 1) {
17227 +        const entier n = coord.size_array();
17228 +        const entier l = op.extend_layer_;
17229 +        coord.resize_array(n + l * 2);
17230 +        double x0 = coord[n-1];
17231 +        double delta = coord[n-2] - x0;
17232 +        for (i = 1; i <= l; i++)
17233 +          coord[n + l + i] = x0 + delta * i;
17234 +        for (i = l-1; i >= 0; i--)
17235 +          coord[i + l] = coord[i];
17236 +        x0 = coord[l];
17237 +        delta = coord[l+1] - x0;
17238 +        for (i = 1; i <= l; i++)
17239 +          coord[l - i] = x0 - delta * i;
17240 +      }
17241 +      nb_som_dir[i_dim] = coord.size_array();
17242 +    }
17243 +    // Verifying that unique has deleted many points...
17244 +    // If well organised, nsom=nx*ny*nz
17245 +    // If chaos, nsom=(nx+ny+nz)/3
17246 +    // We want to verify that we are nearer to organisation than to chaos !
17247 +    if (product_n > (double) nsom * (double) nsom - 1.) {
17248 +      Journal() << "Positions do not seam regular !" << endl;
17249 +      throw;
17250 +    }
17251 +  }
17252 +  int i;
17253 +  op.renum_nodes_.resize_array(nsom);
17254 +  int nb_som_ijk = 1;
17255 +  for (i = 0; i < dim; i++) 
17256 +    nb_som_ijk *= nb_som_dir[i];
17257 +  IntTab ijk_indexes;
17258 +  ijk_indexes.resize(nsom, dim);
17259 +  for (i = 0; i < nsom; i++) {
17260 +    entier ijk_index = 0;
17261 +    for (int j = dim-1; j >= 0; j--) {
17262 +      const double x = src.nodes_(i,j);
17263 +      int index = search_in_ordered_vect(x, dest.coord_[j],op.tolerance_);
17264 +      if (index < 0) {
17265 +        Journal() << "Error: coordinate (" << i << "," << j << ") = " << x << " not found in regularize" << endl
17266 +                  << "Try reducing regularize tolerance value (option regularize=epsilon)" << endl;
17267 +        throw;
17268 +      }
17269 +      ijk_indexes(i, j) = index;
17270 +      ijk_index += index;
17271 +      if (j)
17272 +        ijk_index *= nb_som_dir[j-1];
17273 +    }
17274 +    op.renum_nodes_[i] = ijk_index;
17275 +  }
17276 +  const int max_index = max_array(nb_som_dir);
17277 +  int nb_elems_ijk = 1;
17278 +  for (i = 0; i < dim; i++)
17279 +    nb_elems_ijk *= nb_som_dir[i] - 1;
17280 +  dest.invalid_connections_.resize_array(nb_elems_ijk);
17281 +  dest.invalid_connections_ = 1; // Everything invalid by default
17282 +  const int nelem = src.elements_.dimension(0);
17283 +  const int nb_som_elem = src.elements_.dimension(1);
17284 +  op.renum_elements_.resize_array(nelem);
17285 +  // Pour chaque element, indice dans le maillage ijk du plus sommet le plus proche de l'origine
17286 +  // (pour les faces...)
17287 +  ArrOfInt idx_elem_som;
17288 +  idx_elem_som.resize_array(nelem);
17289 +  int min_index[3];
17290 +  for (i = 0; i < nelem; i++) {
17291 +    min_index[0] = min_index[1] = min_index[2] = max_index;
17292 +    for (int j = 0; j < nb_som_elem; j++) {
17293 +      int node = src.elements_(i,j);
17294 +      for (int k = 0; k < loop_max(dim, 3); k++) {
17295 +        int idx = ijk_indexes(node, k);
17296 +        min_index[k] = (idx < min_index[k]) ? idx : min_index[k];
17297 +        break_loop(k,dim);
17298 +      }
17299 +    }
17300 +    entier idx = 0;
17301 +    entier idx_som = 0;
17302 +    if (dim == 1) {
17303 +      idx = min_index[0];
17304 +      idx_som = idx;
17305 +    } else if (dim == 2) {
17306 +      idx = min_index[1] * (nb_som_dir[0]-1) + min_index[0];
17307 +      idx_som = min_index[1] * nb_som_dir[0] + min_index[0];
17308 +    } else if (dim == 3) {
17309 +      idx = (min_index[2] * (nb_som_dir[1]-1) + min_index[1]) * (nb_som_dir[0]-1) + min_index[0];
17310 +      idx_som = (min_index[2] * nb_som_dir[1] + min_index[1]) * nb_som_dir[0] + min_index[0];
17311 +    } else
17312 +      throw;
17313 +    op.renum_elements_[i] = idx;
17314 +    dest.invalid_connections_.clearbit(idx);
17315 +    idx_elem_som[i] = idx_som;
17316 +  }
17317 +  
17318 +  if (src.faces_ok()) {
17319 +    const int nfaces = src.faces_.dimension(0);
17320 +    op.renum_faces_.resize_array(nfaces);
17321 +    op.renum_faces_ = -1;
17322 +    const int nb_elem_face = src.elem_faces_.dimension(1);
17323 +    ArrOfInt delta_dir(dim);
17324 +    delta_dir[0] = 1;
17325 +    for (i = 1; i < dim; i++)
17326 +      delta_dir[i] = delta_dir[i-1] * nb_som_dir[i-1];
17327 +    for (i = 0; i < nelem; i++) {
17328 +      // Les faces haut, gauche et arriere du cube a l'origine portent le numero 0
17329 +      // Voir DomaineIJK pour la convention sur la numerotation des faces
17330 +      for (entier j = 0; j < nb_elem_face; j++) {
17331 +        const entier i_face = src.elem_faces_(i, j);
17332 +        entier dir = j % dim;
17333 +        entier index = idx_elem_som[i];
17334 +        if (j>=dim) 
17335 +          index += delta_dir[dir];
17336 +        // Encodage du numero de la face et de la direction
17337 +        index = (index << 2) + dir;
17338 +        if (op.renum_faces_[i_face] < 0) {
17339 +          op.renum_faces_[i_face] = index;
17340 +        } else if (op.renum_faces_[i_face] != index) {
17341 +          Journal() << "Error in OperatorRegularize: faces renumbering failed" << endl;
17342 +          throw;
17343 +        }
17344 +      }
17345 +    }
17346 +  }
17347 +  op.geom_init_ = 1;
17348 +}
17349 +
17350 +template <class TabType>
17351 +void build_field_(OperatorRegularize & op,
17352 +                  const DomainUnstructured & src_domain,
17353 +                  const DomainIJK          & dest_domain,
17354 +                  const Field<TabType> & src,
17355 +                  Field<TabType> & dest)
17356 +{
17357 +  Journal(verb_level) << "OperatorRegularize field " << src.id_.uname_ << endl;
17358 +  if (!op.geom_init_) {
17359 +    // Must fill the renum_.... arrays first !
17360 +    LataDeriv<Domain> destr;
17361 +    op.build_geometry(src_domain, destr);
17362 +  }
17363 +  dest.component_names_ = src.component_names_;
17364 +  dest.localisation_ = src.localisation_;
17365 +  dest.nature_ = src.nature_;
17366 +  const entier sz = src.data_.dimension(0);
17367 +  const entier nb_compo = src.data_.dimension(1);
17368 +  entier i;
17369 +  switch(src.localisation_) {
17370 +  case LataField_base::ELEM:
17371 +    dest.data_.resize(dest_domain.nb_elements(), nb_compo);
17372 +    for (i = 0; i < sz; i++) {
17373 +      const entier new_i = op.renum_elements_[i];
17374 +      for (entier j = 0; j < nb_compo; j++)
17375 +        dest.data_(new_i, j) = src.data_(i, j);
17376 +    }
17377 +    break;
17378 +  case LataField_base::SOM:
17379 +    dest.data_.resize(dest_domain.nb_nodes(), nb_compo);
17380 +    for (i = 0; i < sz; i++) {
17381 +      const entier new_i = op.renum_nodes_[i];
17382 +      for (entier j = 0; j < nb_compo; j++)
17383 +        dest.data_(new_i, j) = src.data_(i, j);
17384 +    }
17385 +    break;
17386 +  case LataField_base::FACES:
17387 +    {
17388 +      if (nb_compo != 1) {
17389 +        Journal() << "Error in OperatorRegularize: field at faces has nb_compo != 1" << endl;
17390 +        throw;
17391 +      }
17392 +      dest.nature_ = LataDBField::VECTOR;
17393 +      const entier nb_dim = dest_domain.dimension();
17394 +      dest.data_.resize(dest_domain.nb_faces(), nb_dim);
17395 +      // Field is interpreted as normal component to the face
17396 +      for (i = 0; i < sz; i++) {
17397 +        const entier code = op.renum_faces_[i];
17398 +        // decodage numero et direction de la face:
17399 +        const entier new_i = code >> 2;
17400 +        const entier direction = (code & 3);
17401 +        dest.data_(new_i, direction) = src.data_(i, 0);
17402 +      }
17403 +    }
17404 +    break;
17405 +  default:
17406 +    Journal() << "Error in OperatorRegularize::build_field_: unknown localisation" << endl;
17407 +    throw;
17408 +  }
17409 +}
17410 +
17411 +void OperatorRegularize::build_geometry(const Domain & src_domain, LataDeriv<Domain> & dest)
17412 +{
17413 +  apply_geometry(*this, src_domain, dest);
17414 +}
17415 +
17416 +void OperatorRegularize::build_field(const Domain & src_domain, const LataField_base & src_field,
17417 +                                     const Domain & dest_domain, LataDeriv<LataField_base> & dest)
17418 +{
17419 +  apply_field(*this, src_domain, src_field, dest_domain, dest);
17420 +}
17421 +#undef verb_level
17422 diff --git a/databases/readers/Lata/Rebuild_virtual_layer.C b/databases/readers/Lata/Rebuild_virtual_layer.C
17423 new file mode 100644
17424 index 0000000..ac29742
17425 --- /dev/null
17426 +++ b/databases/readers/Lata/Rebuild_virtual_layer.C
17427 @@ -0,0 +1,141 @@
17428 +/*****************************************************************************
17429 +*
17430 +* Copyright (c) 2011 - 2013, CEA
17431 +* All rights reserved.
17432 +* Redistribution and use in source and binary forms, with or without
17433 +* modification, are permitted provided that the following conditions are met:
17434 +*
17435 +*     * Redistributions of source code must retain the above copyright
17436 +*       notice, this list of conditions and the following disclaimer.
17437 +*     * Redistributions in binary form must reproduce the above copyright
17438 +*       notice, this list of conditions and the following disclaimer in the
17439 +*       documentation and/or other materials provided with the distribution.
17440 +*     * Neither the name of CEA, nor the
17441 +*       names of its contributors may be used to endorse or promote products
17442 +*       derived from this software without specific prior written permission.
17443 +*
17444 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17445 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17446 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17447 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
17448 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17449 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
17450 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
17451 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17452 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
17453 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17454 +*
17455 +*****************************************************************************/
17456 +
17457 +#include <LataFilter.h>
17458 +#include <Connectivite_som_elem.h>
17459 +#include <Operator.h>
17460 +#include <Static_Int_Lists.h>
17461 +#include <Rebuild_virtual_layer.h>
17462 +void find_virtual_layer(DomainUnstructured & domain,
17463 +                        IntTab & virtual_elements,
17464 +                        IntTab & joints_virtual_elements,
17465 +                        double tolerance)
17466 +{
17467 +  Journal(4) << "Searching virtual elements for domain " << domain.id_.name_ << endl;
17468 +  // Step 1 : find duplicate nodes
17469 +  ArrOfInt nodes_renumber;
17470 +  Reconnect::search_duplicate_nodes(domain.nodes_,
17471 +                                    nodes_renumber,
17472 +                                    tolerance,
17473 +                                    0);
17474
17475 +  // Build reconnected elements
17476 +  Reconnect::apply_renumbering(nodes_renumber, domain.elements_);
17477 +  
17478 +  Static_Int_Lists som_elem;
17479 +  construire_connectivite_som_elem(domain.nb_nodes(),
17480 +                                   domain.elements_,
17481 +                                   som_elem,
17482 +                                   0 /* include virtual */);
17483 +
17484 +  virtual_elements.resize(0, 1);
17485 +  virtual_elements.set_smart_resize(1);
17486 +
17487 +  // Step 2 : for each sub_zone, add to virtual_elements list all elements 
17488 +  // touching the zone and not included in the zone
17489 +  const IntTab & joints_sommets = domain.get_joints(LataField_base::SOM);
17490 +  const IntTab & joints_elements = domain.get_joints(LataField_base::ELEM);
17491 +  const entier nprocs = joints_sommets.dimension(0);
17492 +  joints_virtual_elements.resize(nprocs, 2);
17493 +  ArrOfInt tmp;
17494 +  tmp.set_smart_resize(1);
17495 +  for (entier i_proc = 0; i_proc < nprocs; i_proc++) {
17496 +    entier first_elem_zone = joints_elements(i_proc, 0);
17497 +    entier end_elems_zone = first_elem_zone + joints_elements(i_proc, 1);
17498 +    entier first_node_zone = joints_sommets(i_proc, 0);
17499 +    entier end_nodes_zone = first_node_zone + joints_sommets(i_proc, 1);
17500 +    const entier first_virtual_element = virtual_elements.dimension(0);
17501 +    tmp.resize_array(0);
17502 +    for (entier i_node = first_node_zone; i_node < end_nodes_zone; i_node++) {
17503 +      const entier renum_node = nodes_renumber[i_node];
17504 +      const entier nb_elems_voisins = som_elem.get_list_size(renum_node);
17505 +      for (entier i = 0; i < nb_elems_voisins; i++) {
17506 +        const entier elem = som_elem(renum_node, i);
17507 +        if (elem < first_elem_zone || elem >= end_elems_zone)
17508 +          tmp.append_array(elem);
17509 +      }
17510 +    }
17511 +    // Retirer les doublons
17512 +    tmp.ordonne_array();
17513 +    const entier n = tmp.size_array();
17514 +    entier last = -1;
17515 +    for (entier i = 0; i < n; i++) {
17516 +      const entier elem = tmp[i];
17517 +      if (elem != last) {
17518 +        const entier idx = virtual_elements.dimension(0);
17519 +        virtual_elements.resize(idx+1, 1);
17520 +        virtual_elements(idx, 0) = elem;
17521 +        last = elem;
17522 +      }
17523 +    }
17524 +    joints_virtual_elements(i_proc, 0) = first_virtual_element;
17525 +    joints_virtual_elements(i_proc, 1) = virtual_elements.dimension(0) - first_virtual_element;
17526 +    Journal(5) << "Zone " << i_proc << " has " << joints_virtual_elements(i_proc, 1) << " virtual elements" << endl;
17527 +  }
17528 +}
17529 +
17530 +entier rebuild_virtual_layer(LataDB & lataDB, Domain_Id id, double reconnect_tolerance)
17531 +{
17532 +  Journal(4) << "rebuilt_virtual_layer domain " << id.name_ << " " << id.timestep_ << endl;
17533 +  if (lataDB.field_exists(id.timestep_, id.name_, "VIRTUAL_ELEMENTS")) {
17534 +    Journal(4) << " Virtual elements data already exist. Skip" << endl;
17535 +    return 1;
17536 +  }
17537 +  if (!lataDB.field_exists(id.timestep_, id.name_, "JOINTS_ELEMENTS")) {
17538 +    Journal(4) << " Domain has no processor splitting information. Skip" << endl;
17539 +    return 0;
17540 +  }
17541 +  // Load all domain, without faces:
17542 +  id.block_ = -1;
17543 +  DomainUnstructured dom;
17544 +  dom.fill_domain_from_lataDB(lataDB, id, 0 /* no faces */);
17545 +  // Compute virtual zones:
17546 +  IntTab joints_virtual_elements;
17547 +  IntTab virtual_elements;
17548 +  find_virtual_layer(dom, virtual_elements, joints_virtual_elements, reconnect_tolerance);
17549 +  // Write data to disk
17550 +  const LataDBField & joints = lataDB.get_field(id.timestep_, id.name_, "JOINTS_ELEMENTS", "*");
17551 +  LataDBField fld(joints);
17552 +  // Append virtual_elements data to JOINTS_ELEMENTS, same format, etc
17553 +  fld.name_ = "JOINTS_VIRTUAL_ELEMENTS";
17554 +  fld.uname_ = Field_UName(fld.geometry_, fld.name_, "");
17555 +  fld.nb_comp_ = 2;
17556 +  fld.datatype_.file_offset_ = 0;
17557 +  fld.filename_ += ".ghostdata";
17558 +  lataDB.add_field(fld);
17559 +  lataDB.write_data(id.timestep_, fld.uname_, joints_virtual_elements);
17560 +  fld.name_ = "VIRTUAL_ELEMENTS";
17561 +  fld.uname_ = Field_UName(fld.geometry_, fld.name_, "");
17562 +  fld.nb_comp_ = 1;
17563 +  fld.datatype_.file_offset_ = 1; // append
17564 +  fld.size_ = virtual_elements.dimension(0);
17565 +  lataDB.add_field(fld);
17566 +  lataDB.write_data(id.timestep_, fld.uname_, virtual_elements);
17567 +  return 1;
17568 +}
17569 diff --git a/databases/readers/Lata/Rebuild_virtual_layer.h b/databases/readers/Lata/Rebuild_virtual_layer.h
17570 new file mode 100644
17571 index 0000000..f2666dd
17572 --- /dev/null
17573 +++ b/databases/readers/Lata/Rebuild_virtual_layer.h
17574 @@ -0,0 +1,35 @@
17575 +/*****************************************************************************
17576 +*
17577 +* Copyright (c) 2011 - 2013, CEA
17578 +* All rights reserved.
17579 +* Redistribution and use in source and binary forms, with or without
17580 +* modification, are permitted provided that the following conditions are met:
17581 +*
17582 +*     * Redistributions of source code must retain the above copyright
17583 +*       notice, this list of conditions and the following disclaimer.
17584 +*     * Redistributions in binary form must reproduce the above copyright
17585 +*       notice, this list of conditions and the following disclaimer in the
17586 +*       documentation and/or other materials provided with the distribution.
17587 +*     * Neither the name of CEA, nor the
17588 +*       names of its contributors may be used to endorse or promote products
17589 +*       derived from this software without specific prior written permission.
17590 +*
17591 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17592 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17593 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17594 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
17595 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17596 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
17597 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
17598 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17599 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
17600 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17601 +*
17602 +*****************************************************************************/
17603 +
17604 +void find_virtual_layer(DomainUnstructured & domain,
17605 +                        IntTab & virtual_elements,
17606 +                        IntTab & joints_virtual_elements,
17607 +                        double tolerance);
17608 +
17609 +entier rebuild_virtual_layer(LataDB & lataDB, Domain_Id id, double reconnect_tolerance);
17610 diff --git a/databases/readers/Lata/Sortie.h b/databases/readers/Lata/Sortie.h
17611 new file mode 100644
17612 index 0000000..69c967e
17613 --- /dev/null
17614 +++ b/databases/readers/Lata/Sortie.h
17615 @@ -0,0 +1,44 @@
17616 +/*****************************************************************************
17617 +*
17618 +* Copyright (c) 2011 - 2013, CEA
17619 +* All rights reserved.
17620 +* Redistribution and use in source and binary forms, with or without
17621 +* modification, are permitted provided that the following conditions are met:
17622 +*
17623 +*     * Redistributions of source code must retain the above copyright
17624 +*       notice, this list of conditions and the following disclaimer.
17625 +*     * Redistributions in binary form must reproduce the above copyright
17626 +*       notice, this list of conditions and the following disclaimer in the
17627 +*       documentation and/or other materials provided with the distribution.
17628 +*     * Neither the name of CEA, nor the
17629 +*       names of its contributors may be used to endorse or promote products
17630 +*       derived from this software without specific prior written permission.
17631 +*
17632 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17633 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17634 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17635 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
17636 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17637 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
17638 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
17639 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17640 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
17641 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17642 +*
17643 +*****************************************************************************/
17644 +
17645 +#ifndef Sortie_h_inclu
17646 +#define Sortie_h_inclu
17647 +#include <ostream>
17648 +//using namespace std;
17649 +using std::cerr;
17650 +using std::endl;
17651 +#define Sortie std::ostream
17652 +class ArrOfInt;
17653 +// for Static_Int_Lists
17654 +inline Sortie& operator<<(Sortie& is, const ArrOfInt& t)
17655 +{
17656 +  throw;
17657 +  return is;
17658 +}
17659 +#endif
17660 diff --git a/databases/readers/Lata/Static_Int_Lists.C b/databases/readers/Lata/Static_Int_Lists.C
17661 new file mode 100644
17662 index 0000000..4c3f065
17663 --- /dev/null
17664 +++ b/databases/readers/Lata/Static_Int_Lists.C
17665 @@ -0,0 +1,128 @@
17666 +/*****************************************************************************
17667 +*
17668 +* Copyright (c) 2011 - 2013, CEA
17669 +* All rights reserved.
17670 +* Redistribution and use in source and binary forms, with or without
17671 +* modification, are permitted provided that the following conditions are met:
17672 +*
17673 +*     * Redistributions of source code must retain the above copyright
17674 +*       notice, this list of conditions and the following disclaimer.
17675 +*     * Redistributions in binary form must reproduce the above copyright
17676 +*       notice, this list of conditions and the following disclaimer in the
17677 +*       documentation and/or other materials provided with the distribution.
17678 +*     * Neither the name of CEA, nor the
17679 +*       names of its contributors may be used to endorse or promote products
17680 +*       derived from this software without specific prior written permission.
17681 +*
17682 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17683 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17684 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17685 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
17686 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17687 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
17688 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
17689 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17690 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
17691 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17692 +*
17693 +*****************************************************************************/
17694 +
17695 +#include <Static_Int_Lists.h>
17696 +// Description: detruit toutes les listes
17697 +void Static_Int_Lists::reset()
17698 +{
17699 +  index_.resize_array(0);
17700 +  valeurs_.resize_array(0);
17701 +}
17702 +
17703 +// Description: detruit les listes existantes et en cree de nouvelles.
17704 +//  On cree autant de listes que d'elements dans le tableau sizes.
17705 +//  La i-ieme liste a une taille sizes[i]
17706 +//  Les valeurs sizes doivent etre positives ou nulles.
17707 +void Static_Int_Lists::set_list_sizes(const ArrOfInt& sizes)
17708 +{
17709 +  reset();
17710 +
17711 +  const entier nb_listes = sizes.size_array();
17712 +  index_.resize_array(nb_listes + 1);
17713 +  // Construction du tableau d'index
17714 +  index_[0];
17715 +  entier i;
17716 +  for (i = 0; i < nb_listes; i++)
17717 +    {
17718 +      assert(sizes[i] >= 0);
17719 +      index_[i+1] = index_[i] + sizes[i];
17720 +    }
17721 +  const entier somme_sizes = index_[nb_listes];
17722 +  valeurs_.resize_array(somme_sizes);
17723 +}
17724 +
17725 +// Description: tri par ordre croissant des valeurs de la i-ieme liste.
17726 +//  Si num_liste < 0, on trie toutes les listes.
17727 +void Static_Int_Lists::trier_liste(entier num_liste)
17728 +{
17729 +  const entier i_debut = (num_liste < 0) ? 0 : num_liste;
17730 +  const entier i_fin   = (num_liste < 0) ? index_.size_array() - 1 : num_liste + 1;
17731 +
17732 +  entier i;
17733 +  ArrOfInt valeurs_liste;
17734 +  for (i = i_debut; i < i_fin; i++)
17735 +    {
17736 +      const entier index = index_[i];
17737 +      const entier size  = index_[i+1] - index;
17738 +      entier * data      = valeurs_.addr() + index;
17739 +      valeurs_liste.ref_data(data, size);
17740 +      valeurs_liste.ordonne_array();
17741 +    }
17742 +}
17743 +
17744 +// Description: copie la i-ieme liste dans le tableau fourni
17745 +//  Le tableau array doit etre resizable.
17746 +void Static_Int_Lists::copy_list_to_array(entier i, ArrOfInt& array) const
17747 +{
17748 +  const entier n = get_list_size(i);
17749 +  array.resize_array(0); // Ne pas copier les donnees d'origine
17750 +  array.resize_array(n);
17751 +  entier index = index_[i];
17752 +  entier j = 0;
17753 +  for (j = 0; j < n; index++, j++)
17754 +    array[j] = valeurs_[index];
17755 +}
17756 +
17757 +Sortie& Static_Int_Lists::printOn(Sortie& os) const
17758 +{
17759 +  os << index_   << " ";
17760 +  os << valeurs_ << " ";
17761 +  return os;
17762 +}
17763 +
17764 +Entree& Static_Int_Lists::readOn(Entree& is)
17765 +{
17766 +  reset();
17767 +  is >> index_;
17768 +  is >> valeurs_;
17769 +  return is;
17770 +}
17771 +
17772 +Sortie& Static_Int_Lists::ecrire(Sortie& os) const
17773 +{
17774 +  os << "nb lists       : " << get_nb_lists() << finl;
17775 +  os << "sizes of lists : ";
17776 +  for (entier i=0; i<get_nb_lists(); ++i)
17777 +    {
17778 +      os << get_list_size(i) << " ";
17779 +    }
17780 +  os << finl;
17781 +
17782 +  for (entier i=0; i<get_nb_lists(); ++i)
17783 +    {
17784 +      os << "{ " ;
17785 +      const entier sz = get_list_size(i);
17786 +      for (entier j=0; j<sz; ++j)
17787 +        {
17788 +          os <<  valeurs_[(index_[i]+j)] << " ";
17789 +        }
17790 +      os << "}" << finl;
17791 +    }
17792 +  return os;
17793 +}
17794 diff --git a/databases/readers/Lata/Static_Int_Lists.h b/databases/readers/Lata/Static_Int_Lists.h
17795 new file mode 100644
17796 index 0000000..3f28783
17797 --- /dev/null
17798 +++ b/databases/readers/Lata/Static_Int_Lists.h
17799 @@ -0,0 +1,110 @@
17800 +/*****************************************************************************
17801 +*
17802 +* Copyright (c) 2011 - 2013, CEA
17803 +* All rights reserved.
17804 +* Redistribution and use in source and binary forms, with or without
17805 +* modification, are permitted provided that the following conditions are met:
17806 +*
17807 +*     * Redistributions of source code must retain the above copyright
17808 +*       notice, this list of conditions and the following disclaimer.
17809 +*     * Redistributions in binary form must reproduce the above copyright
17810 +*       notice, this list of conditions and the following disclaimer in the
17811 +*       documentation and/or other materials provided with the distribution.
17812 +*     * Neither the name of CEA, nor the
17813 +*       names of its contributors may be used to endorse or promote products
17814 +*       derived from this software without specific prior written permission.
17815 +*
17816 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17817 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17818 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17819 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
17820 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17821 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
17822 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
17823 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17824 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
17825 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17826 +*
17827 +*****************************************************************************/
17828 +
17829 +#ifndef Static_Int_Lists_def
17830 +#define Static_Int_Lists_def
17831 +
17832 +#include <ArrOfInt.h>
17833 +
17834 +// .DESCRIPTION
17835 +//  Cette classe permet de stocker des listes d'entiers accessibles
17836 +//  en temps constant. La taille des listes ne peut pas changer sans
17837 +//  perdre le contenu (ce sont des listes statiques).
17838 +//  Exemple:
17839 +//   Static_Int_List l;
17840 +//   ArrOfInt tailles(3);
17841 +//   tailles[0] = 2; tailles[1] = 3; tailles[2] = 0;
17842 +//   // On reserve la memoire pour trois listes de taille 2, 3 et 0:
17843 +//   l.set_list_sizes(tailles);
17844 +//   // On affecte une valeur au deuxieme element de la premiere liste:
17845 +//   l.set_value(0,1,765);
17846 +//   // Affiche la valeur
17847 +//   cout << l(0,1);
17848 +class Static_Int_Lists
17849 +{
17850 +public:
17851 +  void set_list_sizes(const ArrOfInt& sizes);
17852 +  void reset();
17853 +  void copy_list_to_array(entier i_liste, ArrOfInt& array) const;
17854 +
17855 +  inline void   set_value(entier i_liste, entier i_element, entier valeur);
17856 +  inline entier operator() (entier i_liste, entier i_element) const;
17857 +  inline entier get_list_size(entier i_liste) const;
17858 +  inline entier get_nb_lists() const;
17859 +
17860 +  void trier_liste(entier i);
17861 +
17862 +  Sortie& printOn(Sortie& os) const;
17863 +  Entree& readOn(Entree& is);
17864 +
17865 +  Sortie& ecrire(Sortie& os) const;
17866 +
17867 +private:
17868 +  // Les listes d'entiers sont stockees de facon contigue
17869 +  // dans le tableau valeurs_.
17870 +  // Le premier element de la liste i est valeurs_[index_[i]]
17871 +  // et le dernier element est valeurs_[index_[i+1]-1]
17872 +  // (c'est comme le stockage morse des matrices).
17873 +  ArrOfInt index_;
17874 +  ArrOfInt valeurs_;
17875 +};
17876 +
17877 +// Description: affecte la "valeur" au j-ieme element de la i-ieme liste avec
17878 +//  0 <= i < get_nb_lists()  et  0 <= j < get_list_size(i)
17879 +inline void Static_Int_Lists::set_value(entier i, entier j, entier valeur)
17880 +{
17881 +  const entier index = index_[i] + j;
17882 +  assert(index < index_[i+1]);
17883 +  valeurs_[index] = valeur;
17884 +}
17885 +
17886 +// Description: renvoie le j-ieme element de la i-ieme liste avec
17887 +//  0 <= i < get_nb_lists()  et  0 <= j < get_list_size(i)
17888 +inline entier Static_Int_Lists::operator() (entier i, entier j) const
17889 +{
17890 +  const entier index = index_[i] + j;
17891 +  assert(index < index_[i+1]);
17892 +  const entier val = valeurs_[index];
17893 +  return val;
17894 +}
17895 +
17896 +// Description: renvoie le nombre d'elements de la liste i
17897 +inline entier Static_Int_Lists::get_list_size(entier i) const
17898 +{
17899 +  const entier size = index_[i+1] - index_[i];
17900 +  return size;
17901 +}
17902 +
17903 +// Description: renvoie le nombre de listes stockees
17904 +inline entier Static_Int_Lists::get_nb_lists() const
17905 +{
17906 +  return index_.size_array() - 1;
17907 +}
17908 +
17909 +#endif
17910 diff --git a/databases/readers/Lata/UserFields.C b/databases/readers/Lata/UserFields.C
17911 new file mode 100644
17912 index 0000000..575c231
17913 --- /dev/null
17914 +++ b/databases/readers/Lata/UserFields.C
17915 @@ -0,0 +1,1038 @@
17916 +/*****************************************************************************
17917 +*
17918 +* Copyright (c) 2011 - 2013, CEA
17919 +* All rights reserved.
17920 +* Redistribution and use in source and binary forms, with or without
17921 +* modification, are permitted provided that the following conditions are met:
17922 +*
17923 +*     * Redistributions of source code must retain the above copyright
17924 +*       notice, this list of conditions and the following disclaimer.
17925 +*     * Redistributions in binary form must reproduce the above copyright
17926 +*       notice, this list of conditions and the following disclaimer in the
17927 +*       documentation and/or other materials provided with the distribution.
17928 +*     * Neither the name of CEA, nor the
17929 +*       names of its contributors may be used to endorse or promote products
17930 +*       derived from this software without specific prior written permission.
17931 +*
17932 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17933 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17934 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17935 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
17936 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17937 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
17938 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
17939 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17940 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
17941 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17942 +*
17943 +*****************************************************************************/
17944 +
17945 +#include <UserFields.h>
17946 +#include <LataFilter.h>
17947 +#include <stdlib.h>
17948 +// ********************************************************************************
17949 +// METHODES OUTILS DE GESTION
17950 +//  (normalement, on n'a pas besoin de les modifier mais on peut en ajouter...)
17951 +// ********************************************************************************
17952 +
17953 +// Implementation de la classe Geometry_handle
17954 +// (utiliser cette classe pour eviter d'avoir a faire des dynamic_cast
17955 +//  compliques et pour ne pas avoir a gerer get_geometry et release_geometry a la main)
17956 +// Exemple d'utilisation: voir interpoler_elem_vers_som()
17957 +Geometry_handle::Geometry_handle()
17958 +{
17959 +}
17960 +void Geometry_handle::set(LataFilter & lata_filter, const Domain_Id & id)
17961 +{
17962 +  lata_filter_ = lata_filter;
17963 +  geom_ = lata_filter.get_geometry(id);
17964 +}
17965 +Geometry_handle::Geometry_handle(Geometry_handle & handle)
17966 +{
17967 +  operator=(handle);
17968 +}
17969 +Geometry_handle & Geometry_handle::operator=(Geometry_handle & handle)
17970 +{
17971 +  reset();
17972 +  lata_filter_ = handle.lata_filter_;
17973 +  // Get another reference from the lata filter (to increment ref counter in the cache)
17974 +  geom_ = lata_filter_.valeur().get_geometry(handle.geom_.valeur().id_);
17975 +  return *this;
17976 +}
17977 +Geometry_handle::~Geometry_handle()
17978 +{
17979 +  reset();
17980 +}
17981 +void Geometry_handle::reset()
17982 +{
17983 +  if (geom_.non_nul())
17984 +    lata_filter_.valeur().release_geometry(geom_.valeur());
17985 +  geom_.reset();
17986 +  lata_filter_.reset();
17987 +}
17988 +const DomainUnstructured & Geometry_handle::geom()
17989 +{
17990 +  if (!geom_.non_nul()) {
17991 +    Journal() << "Internal error in Geometry_handle::geom() : nul pointer" << endl;
17992 +    throw;
17993 +  }
17994 +  const DomainUnstructured* ptr = dynamic_cast<const DomainUnstructured *>(&geom_.valeur());
17995 +  if (!ptr) {
17996 +    Journal() << "Error in Geometry_handle::geom() : domain " 
17997 +              << geom_.valeur().id_.name_ << " is not unstructured" << endl;
17998 +    throw;
17999 +  }
18000 +  return *ptr;
18001 +}
18002 +const DomainIJK & Geometry_handle::geom_ijk()
18003 +{
18004 +  if (!geom_.non_nul()) {
18005 +    Journal() << "Internal error in Geometry_handle::geom() : nul pointer" << endl;
18006 +    throw;
18007 +  }
18008 +  const DomainIJK* ptr = dynamic_cast<const DomainIJK *>(&geom_.valeur());
18009 +  if (!ptr) {
18010 +    Journal() << "Error in Geometry_handle::geom() : domain " 
18011 +              << geom_.valeur().id_.name_ << " is not IJK" << endl;
18012 +    throw;
18013 +  }
18014 +  return *ptr;
18015 +}
18016 +entier Geometry_handle::test_ijk()
18017 +{
18018 +  if (!geom_.non_nul()) {
18019 +    Journal() << "Internal error in Geometry_handle::geom() : nul pointer" << endl;
18020 +    throw;
18021 +  }
18022 +  const DomainIJK* ptr = dynamic_cast<const DomainIJK *>(&geom_.valeur());
18023 +  if (ptr)
18024 +    return 1;
18025 +  else
18026 +    return 0;
18027 +}
18028 +
18029 +// Petite fonction outil qui construit l'objet LataFieldMetaData en changeant uniquement 
18030 +//  le nom du champ (dimension, localisation, geometrie, nombre de composantes sont identiques)
18031 +//  Le champ "source" est rempli avec une reference a source, on pourra donc appeler
18032 +//  get_champ_source() (voir interpoler_elem_vers_som pour un exemple)
18033 +// Voir new_fields_metadata() pour un exemple d'utilisation.
18034 +static LataFieldMetaData declare_new_name(const LataFieldMetaData & source, 
18035 +                                          const char * name)
18036 +{
18037 +  LataFieldMetaData dest = source;
18038 +  // Lorsqu'on demandera ce champ, on saura que c'est UserFields qui devra le calculer
18039 +  dest.source_ = "user_fields";
18040 +  // On change le nom du champ:
18041 +  dest.name_ = name;
18042 +  dest.uname_.set_field_name(name);
18043 +  // On remplit le champ source
18044 +  dest.source_field_ = source.uname_;
18045 +  
18046 +  return dest;
18047 +}
18048 +
18049 +// Fonction identique a declare_new_name, mais pour declarer un champ avec une localisation
18050 +//  differente.
18051 +// Voir new_fields_metadata() pour un exemple d'utilisation.
18052 +static LataFieldMetaData declare_new_name_localisation(const LataFieldMetaData & source, 
18053 +                                                       const char * name,
18054 +                                                       LataField_base::Elem_som loc)
18055 +{
18056 +  LataFieldMetaData dest = source;
18057 +  // Lorsqu'on demandera ce champ, on saura que c'est UserFields qui devra le calculer
18058 +  dest.source_ = "user_fields";
18059 +  // On change le nom du champ et la localisation:
18060 +  dest.name_ = name;
18061 +  dest.uname_ = Field_UName(source.uname_.get_geometry(),
18062 +                            name,
18063 +                            LataField_base::localisation_to_string(loc));
18064 +  // On remplit le champ source
18065 +  dest.source_field_ = source.uname_;
18066 +
18067 +  // En plus: je change la localisation:
18068 +  dest.localisation_ = loc;
18069 +
18070 +  return dest;
18071 +}
18072 +
18073 +// Fonction identique a declare_new_name, mais pour declarer un champ avec une localisation
18074 +//  differente de type vectoriel.
18075 +// Voir new_fields_metadata() pour un exemple d'utilisation.
18076 +static LataFieldMetaData declare_new_vector_field(const LataFieldMetaData & source, 
18077 +                                                  const char * name,
18078 +                                                  LataField_base::Elem_som loc,
18079 +                                                  const entier dim)
18080 +{
18081 +  LataFieldMetaData dest = source;
18082 +  // Lorsqu'on demandera ce champ, on saura que c'est UserFields qui devra le calculer
18083 +  dest.source_ = "user_fields";
18084 +  // On change le nom du champ et la localisation:
18085 +  dest.name_ = name;
18086 +  dest.uname_ = Field_UName(source.uname_.get_geometry(),
18087 +                            name,
18088 +                            LataField_base::localisation_to_string(loc));
18089 +  // On remplit le champ source
18090 +  dest.source_field_ = source.uname_;
18091 +
18092 +  // En plus: je change la localisation:
18093 +  dest.localisation_ = loc;
18094 +
18095 +  // et le type (vecteur)
18096 +  dest.component_names_.reset();
18097 +  dest.nb_components_ = dim;
18098 +  dest.is_vector_ = 1;
18099 +
18100 +  return dest;
18101 +}
18102 +
18103 +// Description: demande a la classe LataFilter le champ source du champ "id"
18104 +//  qui a ete declare quand on a appele declare_new_name() au debut
18105 +// Voir filtre_boite() pour un exemple d'utilisation.
18106 +FieldType UserFields::get_champ_source(const Field_Id & id)
18107 +{
18108 +  // Cherche la structure LataFieldMetaData du champ "id":
18109 +  const LataFieldMetaData & data = lata_filter_.valeur().get_field_metadata(id.uname_);
18110 +  Field_Id id2(data.source_field_, id.timestep_, id.block_);
18111 +  FieldType tmp;
18112 +  const LataField_base & field = lata_filter_.valeur().get_field(id2);
18113 +  const FieldType* ptr = dynamic_cast<const FieldType *>(&field);
18114 +  if (!ptr) {
18115 +    Journal() << "Error in UserFields::get_champ_source : field " << id.uname_ 
18116 +              << " is not a floattab" << endl;
18117 +    throw;
18118 +  }
18119 +  // Copie le contenu du champ dans un tableau temporaire:
18120 +  tmp = *ptr;
18121 +  // Libere le champ d'origine
18122 +  lata_filter_.valeur().release_field(field);
18123 +  return tmp;
18124 +}
18125 +
18126 +// Description: demande a la classe LataFilter le champ de nom "nom" et dont
18127 +//  la geometrie, le pas de temps et la localisation sont celles de "id".
18128 +FieldType UserFields::get_champ(const Nom & nom, const Field_Id & id)
18129 +{
18130 +  FieldType tmp;
18131 +  // Construit un Field_Id identique, seul le nom du champ chamge:
18132 +  Field_Id id2(id);
18133 +  id2.uname_.set_field_name(nom);
18134 +  const LataField_base & field = lata_filter_.valeur().get_field(id2);
18135 +  const FieldType* ptr = dynamic_cast<const FieldType *>(&field);
18136 +  if (!ptr) {
18137 +    Journal() << "Error in UserFields::get_champ : field " << id.uname_ 
18138 +              << " is not a floattab" << endl;
18139 +    throw;
18140 +  }
18141 +  // Copie le contenu du champ dans un tableau temporaire:
18142 +  tmp = *ptr;
18143 +  // Libere le champ d'origine
18144 +  lata_filter_.valeur().release_field(field);
18145 +
18146 +  return tmp;
18147 +}
18148 +
18149 +// Description: idem, mais cherche un champ avec une localisation differente de id
18150 +FieldType UserFields::get_champ_loc(const Nom & nom, LataField_base::Elem_som loc, const Field_Id & id)
18151 +{
18152 +  FieldType tmp;
18153 +  // Construit un Field_Id identique, seul le nom du champ chamge:
18154 +  Field_Id id2(id);
18155 +  id2.uname_ = Field_UName(id.uname_.get_geometry(), nom, LataField_base::localisation_to_string(loc));
18156 +  
18157 +  const LataField_base & field = lata_filter_.valeur().get_field(id2);
18158 +  const FieldType* ptr = dynamic_cast<const FieldType *>(&field);
18159 +  if (!ptr) {
18160 +    Journal() << "Error in UserFields::get_champ : field " << id.uname_ 
18161 +              << " is not a floattab" << endl;
18162 +    throw;
18163 +  }
18164 +  // Copie le contenu du champ dans un tableau temporaire:
18165 +  tmp = *ptr;
18166 +  // Libere le champ d'origine
18167 +  lata_filter_.valeur().release_field(field);
18168 +
18169 +  return tmp;
18170 +}
18171 +
18172 +// Description: renvoie un objet Geometry_handle qui pointe sur le domaine
18173 +//  support du champ "id".
18174 +// Voir interpoler_elem_vers_som() pour un exemple d'utilisation
18175 +void UserFields::get_geometry(const Domain_Id & id, Geometry_handle & h)
18176 +{
18177 +  h.set(lata_filter_.valeur(), id);
18178 +}
18179 +
18180 +// ********************************************************************************
18181 +//  METHODES OUTILS DE CALCUL
18182 +//  Ces methodes sont des fonctions qui calculent un champ en fonction d'un autre champ.
18183 +//  On peut les modifier comme on veut, en ajouter, etc... 
18184 +//  Lachez-vous...
18185 +// ********************************************************************************
18186 +
18187 +// Description:
18188 +//  Fonction d'interpolation qui transforme un champ aux "elements"
18189 +//  en un champ aux "sommets".
18190 +//  Dans cet exemple, on a deux algorithmes selon que le champ est sur
18191 +//  un maillage ijk ou non.
18192 +//  La valeur aux sommets est la moyenne des valeurs sur les elements adjacents.
18193 +FieldType UserFields::interpoler_elem_vers_som(const Field_Id & id)
18194 +{
18195 +  // Recupere le champ a filtrer (champ aux elements)
18196 +  FieldType source = get_champ_source(id);
18197 +
18198 +  FieldType resu;
18199 +  // Remplissage des meta-data du champ:
18200 +  resu.id_ = id;
18201 +  resu.component_names_ = source.component_names_;
18202 +  resu.localisation_ = LataField_base::SOM;
18203 +  resu.nature_ = source.nature_;
18204 +  
18205 +  // Recupere la geometrie (domaine ijk ou non structure) sur laquelle est definie
18206 +  //  le champ source:
18207 +  Geometry_handle geom;
18208 +  get_geometry(id, geom);
18209 +  ArrOfFloat poids;
18210 +
18211 +  if (geom.test_ijk()) {
18212 +    const DomainIJK & dom = geom.geom_ijk();
18213 +    // Le code suivant marche en 1D, 2D et 3D:
18214 +    const entier nbsom = dom.nb_nodes();
18215 +    const entier nbcompo = source.data_.dimension(1);
18216 +    resu.data_.resize(nbsom, nbcompo);
18217 +    const entier nsom_x = dom.nb_som_dir(0);
18218 +    const entier nsom_y = dom.nb_som_dir(1);
18219 +    const entier nelem_x = dom.nb_elem_dir(0);
18220 +    const entier nelem_y = dom.nb_elem_dir(1);
18221 +    const entier nelem_z = dom.nb_elem_dir(2);
18222 +    poids.resize_array(nbsom);
18223 +    const entier ni = 2;
18224 +    const entier nj = (dom.dimension() > 1) ? 2 : 1;
18225 +    const entier nk = (dom.dimension() > 2) ? 2 : 1;
18226 +
18227 +    // Avec les boucles imbriquees comme ceci, on parcourt tous les
18228 +    //  elements dans l'ordre croissant:
18229 +    // (l'indice de l'element (i,j,k) est :
18230 +    //    elem = (k * nelem_y + j) * nelem_x + i
18231 +    entier elem = 0;
18232 +    for (entier k = 0; k < nelem_z; k++) {
18233 +      for (entier j = 0; j < nelem_y; j++) {
18234 +        for (entier i = 0; i < nelem_x; i++) {
18235 +          if (dom.invalid_connections_.size_array() == 0 || dom.invalid_connections_[elem] == 0) {
18236 +            // Element valide:
18237 +            // Boucle sur les sommets de l'element
18238 +            const entier som0 = (k * nsom_y + j) * nsom_x + i;
18239 +            for (entier kk = 0; kk < nk; kk++) {
18240 +              for (entier jj = 0; jj < nj; jj++) {
18241 +                for (entier ii = 0; ii < ni; ii++) {
18242 +                  entier som = som0 + (kk * nsom_y + jj) * nsom_x + ii;
18243 +                  for (entier compo = 0; compo < nbcompo; compo++)
18244 +                    resu.data_(som, compo) += source.data_(elem, compo);
18245 +                  poids[som] += 1.;
18246 +                }
18247 +              }
18248 +            }
18249 +          }
18250 +          elem++;
18251 +        }
18252 +      }
18253 +    }
18254 +  } else {
18255 +    const DomainUnstructured & dom = geom.geom();
18256 +
18257 +    const entier nbsom = dom.nb_nodes();
18258 +    const entier nbcompo = source.data_.dimension(1);
18259 +    resu.data_.resize(nbsom, nbcompo);
18260 +    poids.resize_array(nbsom);
18261 +    const IntTab & les_elem = dom.elements_;
18262 +    const entier n = les_elem.dimension(0);
18263 +    const entier m = les_elem.dimension(1);
18264 +    int i, j, k;
18265 +    for ( i = 0; i < n; i++) {
18266 +      for (j = 0; j < m; j++) {
18267 +        entier som = les_elem(i,j);
18268 +        for (k = 0; k < nbcompo; k++) {
18269 +          float x = source.data_(i, k);
18270 +          resu.data_(som, k) += x;
18271 +        }
18272 +        poids[som] += 1.;
18273 +      }
18274 +    }
18275 +  }
18276 +  const entier nbsom = poids.size_array();
18277 +  const entier nbcompo = resu.data_.dimension(1);
18278 +  for (entier i = 0; i < nbsom; i++)
18279 +    for (entier k = 0; k < nbcompo; k++)
18280 +      resu.data_(i, k) /= poids[i];
18281 +
18282 +  return resu;
18283 +}
18284 +
18285 +
18286 +
18287 +
18288 +
18289 +//  Attention: le constructeur par defaut n'initialise pas le vecteur !
18290 +class Vecteur3
18291 +{
18292 +public:
18293 +  Vecteur3() {};
18294 +  Vecteur3(const Vecteur3 & w) {
18295 +    v[0] = w.v[0]; v[1] = w.v[1]; v[2] = w.v[2];
18296 +  }
18297 +  Vecteur3(double x, double y, double z) {
18298 +    v[0] = x; v[1] = y; v[2] = z;
18299 +  }
18300 +  void  set(double x, double y, double z) {
18301 +    v[0] = x; v[1] = y; v[2] = z;
18302 +  }
18303 +  double length() const { return sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); };
18304 +  Vecteur3(const DoubleTab & tab, entier i) {
18305 +    //assert(tab.line_size() == 3);
18306 +    assert(i >= 0 && i < tab.dimension_tot(0));
18307 +    const double *ptr = tab.addr() + i * 3;
18308 +    v[0] = ptr[0];
18309 +    v[1] = ptr[1];
18310 +    v[2] = ptr[2];
18311 +  }
18312 +  Vecteur3 & operator=(double x) {
18313 +    v[0] = x; v[1] = x; v[2] = x;
18314 +    return *this;
18315 +  }
18316 +  Vecteur3 & operator*=(double x) {
18317 +    v[0] *= x; v[1] *= x; v[2] *= x;
18318 +    return *this;
18319 +  }
18320 +
18321 +  Vecteur3 & operator=(const Vecteur3 & w) {
18322 +    v[0] = w.v[0]; v[1] = w.v[1]; v[2] = w.v[2];
18323 +    return *this;
18324 +  }
18325 +  double               operator[](entier i) const { assert(i>=0 && i<3); return v[i]; }
18326 +  double &             operator[](entier i)       { assert(i>=0 && i<3); return v[i]; }
18327 +  inline        double norme_Linfini();
18328 +  static inline void   produit_vectoriel(const Vecteur3 & x, const Vecteur3 & y, Vecteur3 & resu);
18329 +  static inline double produit_scalaire(const Vecteur3 & x, const Vecteur3 & y);
18330 +  friend Vecteur3 operator-(const Vecteur3 &, const Vecteur3 &);
18331 +protected:
18332 +  double v[3];
18333 +};
18334 +
18335 +
18336 +inline void Vecteur3::produit_vectoriel(const Vecteur3 & x, const Vecteur3 & y, Vecteur3 & z)
18337 +{
18338 +  z.v[0] = x.v[1] * y.v[2] - x.v[2] * y.v[1];
18339 +  z.v[1] = x.v[2] * y.v[0] - x.v[0] * y.v[2];
18340 +  z.v[2] = x.v[0] * y.v[1] - x.v[1] * y.v[0];
18341 +}
18342 +
18343 +inline double Vecteur3::produit_scalaire(const Vecteur3 & x, const Vecteur3 & y)
18344 +{
18345 +  double r = x.v[0] * y.v[0] + x.v[1] * y.v[1] + x.v[2] * y.v[2];
18346 +  return r;
18347 +}
18348 +
18349 +// Description: norme L_infini, c'est le max des abs(v[i])
18350 +inline double Vecteur3::norme_Linfini()
18351 +{
18352 +  double x = fabs(v[0]);
18353 +  double y = fabs(v[1]);
18354 +  double z = fabs(v[2]);
18355 +  double resu = ((x > y) ? x : y);
18356 +  resu = ((resu > z) ? resu : z);
18357 +  return resu;  
18358 +}
18359 +
18360 +inline Vecteur3 operator-(const Vecteur3 & x, const Vecteur3 & y)
18361 +{
18362 +  Vecteur3 z;
18363 +  z.v[0] = x.v[0] - y.v[0];
18364 +  z.v[1] = x.v[1] - y.v[1];
18365 +  z.v[2] = x.v[2] - y.v[2];
18366 +  return z;
18367 +}
18368 +
18369 +double largest_angle_2(const DoubleTab& coords)
18370 +        
18371 +{
18372 +  if (((coords.dimension(0)!=4)&&(coords.dimension(0)!=3))||(coords.dimension(1)!=3))
18373 +    {
18374 +      Cerr<<" cas nn prevu"<<endl; 
18375 +      throw;
18376 +    }
18377 +  int nb_face=coords.dimension(0);
18378 +  Vecteur3 normals[4];
18379 +  Vecteur3 edge[2],opp;
18380 +  edge[1].set(0,0,1);
18381 +  for (int n=0;n<nb_face;n++)
18382 +    {
18383 +     
18384 +      int prem=0;
18385 +      if (n==0) prem=1;
18386 +      int compteur=0;
18387 +      for (int s=0;s<nb_face;s++)
18388 +        {
18389 +
18390 +          if ((s!=n) && (s!=prem))
18391 +            {
18392 +              edge[compteur].set(coords(s,0)-coords(prem,0),
18393 +                                 coords(s,1)-coords(prem,1),
18394 +                                 coords(s,2)-coords(prem,2));
18395 +              compteur++;
18396 +            }
18397 +        }
18398 +      if (compteur!=nb_face-2) throw;
18399 +      opp.set(coords(n,0)-coords(prem,0),
18400 +              coords(n,1)-coords(prem,1),
18401 +              coords(n,2)-coords(prem,2));
18402 +      Vecteur3::produit_vectoriel(edge[0],edge[1],normals[n]);
18403 +      //normals[n]=edge[0]*edge[1];
18404 +      normals[n]*=1./normals[n].length();
18405 +      if (Vecteur3::produit_scalaire(normals[n],opp)<0)
18406 +        normals[n]*=-1;
18407 +    }
18408 +  // on a les 4 normals orientes vers l'interieur
18409 +  double max_pscal=-100;
18410 +  for (int n1=0;n1<nb_face;n1++)
18411 +    for (int n2=n1+1;n2<nb_face;n2++)
18412 +      {
18413 +        double pscal=Vecteur3::produit_scalaire(normals[n1],normals[n2]);
18414 +        //min_pscal=pscal;
18415 +        if (pscal>max_pscal)
18416 +          max_pscal=pscal;
18417 +      }
18418 +  double tet=acos(max_pscal)/acos(-1.)*180; // PL: acos(-1) ne compile pas sur de multiples plateformes
18419 +  
18420 +  tet=180-tet;
18421 +  return tet;
18422 +}
18423 +
18424 +
18425 +
18426 +FieldType UserFields::calculer_angle(const Field_Id & id)
18427 +{
18428 +  // Recupere le champ a filtrer (champ aux elements)
18429 +  //  FieldType source = get_champ_source(id);
18430 +  
18431 +  FieldType resu;
18432 +  // Remplissage des meta-data du champ:
18433 +  resu.id_ = id;
18434 +  const LataFieldMetaData & data = lata_filter_.valeur().get_field_metadata(id.uname_);
18435 +  resu.component_names_ = data.component_names_;
18436 +  resu.localisation_ = data.localisation_;
18437 +  resu.nature_ = LataDBField::SCALAR;
18438 +  
18439 +  // Recupere la geometrie (domaine ijk ou non structure) sur laquelle est definie
18440 +  //  le champ source:
18441 +  Geometry_handle geom;
18442 +  get_geometry(id, geom);
18443 +
18444 +  if (geom.test_ijk()) {
18445 +    Journal() <<    "non code" <<endl;
18446 +    throw;
18447 +  } else {
18448 +    const DomainUnstructured & dom = geom.geom();
18449 +    const entier nbcompo = dom.dimension();
18450 +    //poids.resize_array(nbsom);
18451 +    const IntTab & les_elem = dom.elements_;
18452 +    const entier n = les_elem.dimension(0);
18453
18454 +    resu.data_.resize(n, nbcompo);
18455 +    
18456 +    const FloatTab& nodes_=dom.nodes_;
18457 +    int nb_som_elem=les_elem.dimension(1);
18458 +    DoubleTab coords(nb_som_elem,3);
18459 +    for ( int i = 0; i < n; i++) {
18460 +      for (int s=0;s<nb_som_elem;s++)
18461 +        for (int d=0;d<nodes_.dimension(1);d++)
18462 +          coords(s,d)=nodes_(les_elem(i,s),d);
18463 +      resu.data_(i, 0) = largest_angle_2(coords);
18464 +        
18465 +    }
18466 +  
18467 +  }
18468 +  return resu;
18469 +}
18470 +
18471 +FieldType UserFields::calculer_normale(const Field_Id & id)
18472 +{
18473 +
18474 +  // Recupere le champ a filtrer (champ aux elements)
18475 +  //  FieldType source = get_champ_source(id);
18476 +
18477 +  FieldType resu;
18478 +  // Remplissage des meta-data du champ:
18479 +  resu.id_ = id;
18480 +  const LataFieldMetaData & data = lata_filter_.valeur().get_field_metadata(id.uname_);
18481 +  resu.component_names_ = data.component_names_;
18482 +  resu.localisation_ = data.localisation_;
18483 +  resu.nature_ = LataDBField::VECTOR;
18484 +  
18485 +  // Recupere la geometrie (domaine ijk ou non structure) sur laquelle est definie
18486 +  //  le champ source:
18487 +  Geometry_handle geom;
18488 +  get_geometry(id, geom);
18489 +
18490 +  if (geom.test_ijk()) {
18491 +    Journal() <<    "non code" <<endl;
18492 +    throw;
18493 +  } else {
18494 +    const DomainUnstructured & dom = geom.geom();
18495 +    const entier nbcompo = dom.dimension();
18496 +    const IntTab & les_elem = dom.elements_;
18497 +    const entier n = les_elem.dimension(0);
18498
18499 +    resu.data_.resize(n, nbcompo);
18500 +    
18501 +    const FloatTab& nodes_=dom.nodes_;
18502 +    
18503 +    ArrOfFloat v1( nbcompo),v2(nbcompo);
18504 +    ArrOfDouble nor(nbcompo);
18505 +    for ( int i = 0; i < n; i++) {
18506 +      // calcul de la normale
18507 +      entier som0 = les_elem(i,0);
18508 +      entier som1 = les_elem(i,1);
18509 +      for (int j=0;j<nbcompo;j++)
18510 +        v1[j]=nodes_(som1,j)-nodes_(som0,j);
18511 +      if (nbcompo==3)
18512 +        {
18513 +          entier som2 = les_elem(i,2);
18514 +          for (int j=0;j<nbcompo;j++)
18515 +            v2[j]=nodes_(som2,j)-nodes_(som0,j);
18516 +          
18517 +          nor[0]=v1[1]*v2[2]-v1[2]*v2[1];
18518 +          nor[1]=v1[2]*v2[0]-v1[0]*v2[2];
18519 +          nor[2]=v1[0]*v2[1]-v1[1]*v2[0];
18520 +          nor/=2.;
18521 +        }
18522 +      else
18523 +        {
18524 +          assert(nbcompo==2);
18525 +          nor[0]=v1[1];
18526 +          nor[1]=-v1[0];
18527 +          
18528 +        }
18529 +      for (int k = 0; k < nbcompo; k++) {
18530 +        resu.data_(i, k) = nor[k];
18531 +      }
18532 +       
18533 +    }
18534 +    
18535 +  }
18536 +  
18537 +
18538 +  return resu;
18539 +}
18540 +
18541 +// Description:
18542 +//  Fonction d'interpolation qui transforme un champ de vitesse VDF aux "faces"
18543 +//  en un champ aux "elements".
18544 +//  Ne fonctionne que sur les maillages ijk !
18545 +//  On attend un champ scalaire a une composante en entree (champ source)
18546 +//  et on fournit en sortie un champ vectoriel a "dimension" composantes.
18547 +FieldType UserFields::interpoler_faces_vdf_vers_elem(const Field_Id & id)
18548 +{
18549 +  // Recupere le champ a filtrer (champ aux elements)
18550 +  FieldType source = get_champ_source(id);
18551 +  
18552 +  if (source.localisation_ != LataField_base::FACES) {
18553 +    Journal() << "Error in UserFields::interpoler_faces_vdf_vers_elem: source field " << id.uname_.build_string()
18554 +              << " is not at faces !" << endl;
18555 +    throw;
18556 +  }
18557 +
18558 +  // Get geometry:
18559 +  Geometry_handle geom;
18560 +  get_geometry(id, geom);
18561 +  if (!geom.test_ijk()) {
18562 +    Journal() << "Error in UserFields::interpoler_faces_vdf_vers_elem: geometry of field " << id.uname_.build_string()
18563 +              << " is not IJK" << endl;
18564 +    throw;
18565 +  }
18566 +  const DomainIJK & dom = geom.geom_ijk();
18567 +
18568 +  const entier dim = dom.dimension();
18569 +  
18570 +  if (source.data_.dimension(1) != dim) {
18571 +    Journal() << "Error in UserFields::interpoler_faces_vdf_vers_elem: source field " << id.uname_.build_string()
18572 +              << " must have " << dim << " components !" << endl;
18573 +    throw;
18574 +  }
18575 +
18576 +  FieldType resu;
18577 +  // Remplissage des meta-data du champ:
18578 +  resu.id_ = id;
18579 +  resu.component_names_.reset();
18580 +  resu.localisation_ = LataField_base::ELEM;
18581 +  resu.nature_ = LataDBField::VECTOR;
18582 +
18583 +  // Le code suivant marche en 1D, 2D et 3D:
18584 +  const entier nbelem = dom.nb_elements();
18585 +  const entier nbcompo = dim;
18586 +  resu.data_.resize(nbelem, nbcompo);
18587 +  const entier nelem_x = dom.nb_elem_dir(0);
18588 +  const entier nelem_y = dom.nb_elem_dir(1);
18589 +  const entier nelem_z = dom.nb_elem_dir(2);
18590 +  const entier nfaces_x = dom.nb_som_dir(0);
18591 +  const entier nfaces_y = dom.nb_som_dir(1);
18592 +  // Avec les boucles imbriquees comme ceci, on parcourt tous les
18593 +  //  elements dans l'ordre croissant:
18594 +  // (l'indice de l'element (i,j,k) est :
18595 +  //    elem = (k * nelem_y + j) * nelem_x + i
18596 +  entier elem = 0;
18597 +  for (entier k = 0; k < nelem_z; k++) {
18598 +    for (entier j = 0; j < nelem_y; j++) {
18599 +      for (entier i = 0; i < nelem_x; i++) {
18600 +        if (dom.invalid_connections_.size_array() == 0 || dom.invalid_connections_[elem] == 0) {
18601 +          // Element valide:
18602 +          // Boucle sur les trois directions:
18603 +          for (entier dir = 0; dir < dim; dir++) {
18604 +            // indices des deux faces opposees de l'element dan la direction dir:
18605 +            const entier face1 = (k * nfaces_y + j) * nfaces_x + i;
18606 +            entier face2;
18607 +            if (dir == 0)
18608 +              face2 = face1 + 1;
18609 +            else if (dir == 1)
18610 +              face2 = face1 + nfaces_x;
18611 +            else
18612 +              face2 = face1 + nfaces_y * nfaces_x;
18613 +            // On fait la moyenne des vitesses sur les deux faces
18614 +            double v_moy = (source.data_(face1, dir) + source.data_(face2, dir)) * 0.5;
18615 +            resu.data_(elem, dir) = v_moy;
18616 +          }
18617 +        }
18618 +        elem++;
18619 +      }
18620 +    }
18621 +  }
18622 +  return resu;
18623 +}
18624 +
18625 +// **********************************************************************************
18626 +// METHODES UTILISATEUR: ces methodes sont a mettre a jour en fonction des besoins
18627 +//  specifiques...
18628 +// **********************************************************************************
18629 +
18630 +// Description: Constructeur de la classe.
18631 +//  Attention: penser a initialiser toutes les variables de la classe (options)
18632 +UserFields_options::UserFields_options()
18633 +{
18634 +  demie_largeur_filtre_boite_ = 1;
18635 +}
18636 +
18637 +// Cette methode est appelee avec les options en ligne de commande ou sur la troisieme
18638 +//  ligne. Il faut renvoyer 0 si on ne comprend pas l'option, sinon 1.
18639 +entier UserFields_options::parse_option(const Nom & option)
18640 +{
18641 +  if (option.debute_par("demie_largeur_filtre_boite=")) {
18642 +    demie_largeur_filtre_boite_ = LataOptions::read_int_opt(option);
18643 +  } else {
18644 +    return 0;
18645 +  }
18646 +  return 1;
18647 +}
18648 +
18649 +// Cette methode est appelee par lata2dx en ligne de commande pour afficher une aide.
18650 +// On peut decrire toutes les options...
18651 +void UserFields_options::print_help_option() const
18652 +{
18653 +  cerr << "Options provided by UserFields:" << endl;
18654 +  cerr << " demie_largeur_filtre_boite=N  (see filtre_boite implementation)" << endl;
18655 +}
18656 +
18657 +// Description:
18658 +//  Cette methode est appelee par lata2dx au debut pour connaitre la liste
18659 +//  des champs que UserFields est capable de calculer.
18660 +//  fields_data contient en entree tous les champs deja fournis par lata2dx
18661 +//   (champs presents dans le fichier .lata, plus les champs resultant des operateurs
18662 +//    standards (regularize, dualmesh etc...)
18663 +//  On doit ajouter dans fields_data la description des champs supplementaires 
18664 +//   que UserFields peut calculer.
18665 +void UserFields::new_fields_metadata(LataFilter & filter,
18666 +                                     LataVector<LataFieldMetaData> & fields_data)
18667 +{
18668 +  lata_filter_ = filter;
18669 +
18670 +  const Noms geoms = filter.get_exportable_geometry_names();
18671 +  
18672 +  const entier nb_geometries = geoms.size();
18673 +  
18674 +  for (int i = 0; i < nb_geometries; i++) {
18675 +    const LataGeometryMetaData data = filter.get_geometry_metadata(geoms[i]);
18676 +    
18677 +    // Si on a des faces, proposer la normale aux faces
18678 +    int topo_dim=data.dimension_;
18679 +    
18680 +    switch(data.element_type_) {
18681 +    case Domain::point:     topo_dim = 0; break;
18682 +    case Domain::line:      topo_dim = 1; break;
18683 +    case Domain::triangle:
18684 +    case Domain::polygone:
18685 +    case Domain::quadri:    topo_dim = 2; break;
18686 +    case Domain::tetra:
18687 +    case Domain::prism6:
18688 +    case Domain::polyedre:
18689 +    case Domain::hexa:      topo_dim = 3; break;
18690 +    default:
18691 +      cerr << "avtlataFileFormat::PopulateDatabaseMetaData error: unknown element type" << endl;
18692 +      throw;
18693 +    }
18694 +    if ((data.dimension_>1)&&(topo_dim!=data.dimension_)) {
18695 +      Journal(1)<<"Ajout de la normale"<<endl;
18696 +      LataFieldMetaData dest;
18697 +      dest.name_ = "normals/NORMALE";
18698 +      dest.geometry_name_ = data.internal_name_;
18699 +      dest.component_names_.reset() ;
18700 +      
18701 +      dest.nb_components_ = data.dimension_;
18702 +      dest.is_vector_ = 1;
18703 +      dest.localisation_ = LataField_base::ELEM;
18704 +      dest.source_localisation_ = "ELEM";
18705 +      dest.source_ = "user_fields";
18706 +      // source_field_ inutile.
18707 +      
18708 +      dest.uname_ = Field_UName(dest.geometry_name_,
18709 +                                dest.name_,
18710 +                                LataField_base::localisation_to_string(dest.localisation_));
18711 +      fields_data.add(dest);
18712 +    }
18713 +    else
18714 +    if (data.element_type_==Domain::triangle||data.element_type_==Domain::tetra)
18715 +      
18716 +      {
18717 +         Journal(1)<<"Ajout de mesh_quality/LargestAngle"<<endl;
18718 +         LataFieldMetaData dest;
18719 +         dest.name_ = "mesh_quality/LargestAngle";
18720 +         dest.geometry_name_ = data.internal_name_;
18721 +         dest.component_names_.reset() ;
18722 +      
18723 +         dest.nb_components_ = 1;
18724 +         dest.is_vector_ = 0;
18725 +         dest.localisation_ = LataField_base::ELEM;
18726 +         dest.source_localisation_ = "ELEM";
18727 +         dest.source_ = "user_fields";
18728 +         // source_field_ inutile.
18729 +      
18730 +         dest.uname_ = Field_UName(dest.geometry_name_,
18731 +                                   dest.name_,
18732 +                                   LataField_base::localisation_to_string(dest.localisation_));
18733 +         fields_data.add(dest);
18734 +      }
18735 +  }
18736 +  // on laisse les lignes pour verifier la compilation
18737 +  if ( 0) {
18738 +  const entier nb_fields_debut = fields_data.size();
18739 +  
18740 +  // On fait une boucle sur tous les champs disponibles dans le filtre
18741 +  //  (nb_fields_debut est le nombre de champs existant avant qu'on 
18742 +  //   commence a en ajouter dans le tableau fields_data)
18743 +
18744 +  for (int i_in = 0; i_in < nb_fields_debut; i_in++) 
18745 +    {
18746 +      // On cherche si le champ de temperature aux elements existe
18747 +      //  sur une geometrie IJK (Motcle permet d'ignorer majuscule/minuscule)
18748 +      const LataFieldMetaData data = fields_data[i_in];
18749 +
18750 +      // Les deux if suivants sont des EXEMPLES
18751 +
18752 +      if (Motcle(data.name_) == "TEMPERATURE"
18753 +          && data.localisation_ == LataField_base::ELEM
18754 +          && Motcle(data.geometry_name_).finit_par("_IJK"))
18755 +        {
18756 +          // On declare un champ identique qui s'appelle MOYENNE_TEMPERATURE
18757 +          fields_data.add(declare_new_name(data, "MOYENNE_TEMPERATURE"));
18758 +        }
18759 +
18760 +      // Si le champ est aux elements, on propose une interpolation aux sommets
18761 +      // On reconnaitra le champ parce que son nom finira par elem_vers_som (voir get_field())
18762 +      if (data.localisation_ == LataField_base::ELEM)
18763 +        {
18764 +          Nom nom = data.name_;
18765 +          nom += "_elem_vers_som";
18766 +          fields_data.add(declare_new_name_localisation(data, nom, LataField_base::SOM));
18767 +        }
18768 +
18769 +      // Si le champ est aux faces et le maillage est ijk, on propose
18770 +      //  une interpolation aux elements
18771 +      if (data.localisation_ == LataField_base::FACES
18772 +          && Motcle(data.geometry_name_).finit_par("_IJK"))
18773 +        {
18774 +          Nom nom = data.name_;
18775 +          nom += "_faces_vers_elem";
18776 +          // Le champ aux faces a deja dimension composantes
18777 +          const entier dim = data.nb_components_;
18778 +          fields_data.add(declare_new_vector_field(data, nom, LataField_base::ELEM, dim));
18779 +        }
18780 +    }
18781 +  }
18782 +}
18783 +
18784 +// Description:
18785 +//  Cette methode publique est appelee par lata2dx pour obtenir les champs declares dans
18786 +//  new_fields_metadata. Il faut tester "id" et calculer le champ demande.
18787 +//  On a le droit d'appeler get_champ() pour obtenir d'autres champs.
18788 +FieldType UserFields::get_field(const Field_Id & id)
18789 +{
18790 +  // Convertit le nom du champ en majuscules:
18791 +  Motcle nom(id.uname_.get_field_name());
18792 +
18793 +  // Ces deux lignes sont des EXEMPLES (a remplacer par les champs qu'on veut
18794 +  //  effectivement calculer)
18795 +  if (nom == "moyenne_temperature")    return filtre_boite(id);
18796 +  else if (nom.finit_par("_elem_vers_som")) return interpoler_elem_vers_som(id);
18797 +  else if (nom.finit_par("_faces_vers_elem")) return interpoler_faces_vdf_vers_elem(id);
18798 +  else if (nom.debute_par("normals/NORMALE")) return calculer_normale(id);
18799 +  else if (nom.debute_par("mesh_quality/LargestAngle")) return calculer_angle(id);
18800 +  // Ceci doit rester:
18801 +  else {
18802 +    Journal() << "Error in UserFields::get_field: unknown field " << nom << endl;
18803 +    throw;
18804 +  }
18805 +}
18806 +
18807 +class FiltreSpatial
18808 +{   
18809 +public:
18810 +  FiltreSpatial(LataFilter & lata, const Domain_Id & id, entier demi_pas) :
18811 +    demi_pas_(-1), pbDim_(-1), nx_(-1), ny_(-1), nz_(-1), dx_(-1.), dy_(-1.), dz_(-1.)
18812 +  {
18813 +    init(lata, id, demi_pas); 
18814 +  }
18815 +  FieldType filtrer(const FieldType & f, const Field_Id & id) const;
18816 +  FieldType gradient(const FieldType & f, const Field_Id & id) const;
18817 +  float volume() const { return dx_ * dy_ * dz_; }
18818 +protected:
18819 +  void init(LataFilter & lata, const Domain_Id & id, entier demi_pas);
18820 +  FloatTab calculer_somme_dir(const FloatTab & src, const int dir) const;
18821 +  FloatTab annu_bord(const FloatTab & input, int epaisseur) const;
18822 +  int ijk_index(int i, int j, int k) const {
18823 +    if (i < 0)
18824 +      i = 0;
18825 +    else if (i >= nx_)
18826 +      i = nx_-1;
18827 +    if (j < 0)
18828 +      j = 0;
18829 +    else if (j >= ny_)
18830 +      j = ny_ - 1;
18831 +    if (k < 0)
18832 +      k = 0;
18833 +    else if (k >= nz_)
18834 +      k = nz_-1; 
18835 +    return k * ny_ * nx_ + j * nx_ + i;
18836 +  } 
18837 +
18838 +  // Tableau: pour chaque element, 1 s'il est INVALIDE, 0 s'il est OK
18839 +  ArrOfBit invalid_connections_;
18840 +
18841 +  entier demi_pas_;
18842 +  int pbDim_; // dimension
18843 +  int nx_;
18844 +  int ny_;
18845 +  int nz_;
18846 +  float dx_;
18847 +  float dy_;
18848 +  float dz_;
18849 +};
18850 +
18851 +void FiltreSpatial::init(LataFilter & lata, const Domain_Id & id, entier demi_pas)
18852 +{
18853 +  const Domain & dom = lata.get_geometry(id);
18854 +  const DomainIJK * ptr = dynamic_cast<const DomainIJK *>(&dom);
18855 +  if (!ptr) {
18856 +    Journal() << "Error in FiltreSpatial::init : domain " << id.name_ << " is not IJK" << endl;
18857 +    throw;
18858 +  }
18859 +  demi_pas_ = demi_pas;
18860 +  pbDim_ = ptr->coord_.size();
18861 +  nx_ = ptr->coord_[0].size_array() - 1;
18862 +  ny_ = ptr->coord_[1].size_array() - 1;
18863 +  if (pbDim_ == 3)
18864 +    nz_ = ptr->coord_[2].size_array() - 1;
18865 +  else
18866 +    nz_ = 1;
18867 +
18868 +  dx_ = ptr->coord_[0][1] - ptr->coord_[0][0];
18869 +  dy_ = ptr->coord_[1][1] - ptr->coord_[1][0];
18870 +  if (pbDim_ == 3)
18871 +    dz_ = ptr->coord_[2][1] - ptr->coord_[2][0];
18872 +  else
18873 +    dz_ = 1.;
18874 +
18875 +  invalid_connections_ = ptr->invalid_connections_;
18876 +
18877 +  if (invalid_connections_.size_array() == 0) {
18878 +    invalid_connections_.resize_array(ptr->nb_elements());
18879 +    invalid_connections_ = 0;
18880 +  }
18881 +
18882 +  lata.release_geometry(dom);
18883 +}
18884 +
18885 +FloatTab FiltreSpatial::calculer_somme_dir(const FloatTab & src, const int dir) const
18886 +{
18887 +  const int n = src.dimension(0);
18888 +  const int nb_compo = src.dimension(1);
18889 +  FloatTab tmp;
18890 +  tmp.resize(n, nb_compo);
18891 +
18892 +  int index_resu = 0;
18893 +  for (int k = 0; k < nz_; k++) {
18894 +    for (int j = 0; j < ny_; j++) {
18895 +      for (int i = 0; i < nx_; i++) {
18896 +        for (int count = -demi_pas_; count <= demi_pas_; count++) {
18897 +          int index;
18898 +          switch(dir) {
18899 +          case 0: index = ijk_index(i+count, j, k); break;
18900 +          case 1: index = ijk_index(i, j+count, k); break;
18901 +          case 2: index = ijk_index(i, j, k+count); break;
18902 +          default:
18903 +            throw;
18904 +          }
18905 +
18906 +          if (invalid_connections_[index] == 1 && dir == 0) {
18907 +            // element invalide !
18908 +          } else {
18909 +            // element ok !
18910 +            for (int compo = 0; compo < nb_compo; compo++)
18911 +              tmp(index_resu, compo) += src(index, compo);
18912 +          }
18913 +        }
18914 +        index_resu++;
18915 +      }
18916 +    }
18917 +  }
18918 +  return tmp;
18919 +}
18920 +
18921 +FieldType FiltreSpatial::filtrer(const FieldType & source, const Field_Id & id) const
18922 +{
18923 +  // On copie tout pour avoir les noms des composantes, localisation etc...
18924 +  FieldType resu = source;
18925 +  resu.id_ = id;
18926 +
18927 +  FloatTab somme_x = calculer_somme_dir(source.data_, 0);
18928 +  FloatTab somme_y = calculer_somme_dir(somme_x, 1);
18929 +  if (pbDim_ == 3)
18930 +    resu.data_ = calculer_somme_dir(somme_y, 2);
18931 +  else
18932 +    resu.data_ = somme_y;
18933 +
18934 +  entier pas = demi_pas_ * 2 + 1;
18935 +  double fact = pas * pas;
18936 +  if (pbDim_ == 3)
18937 +    fact *= pas;
18938 +  resu.data_ *= (1. / fact);
18939 +
18940 +  return resu;
18941 +}
18942 +
18943 +FieldType UserFields::filtre_boite(const Field_Id & id)
18944 +{
18945 +  FieldType source = get_champ_source(id);
18946 +
18947 +  FiltreSpatial filtre(lata_filter_.valeur(), id, opt_.demie_largeur_filtre_boite_);
18948 +
18949 +  FieldType resu = filtre.filtrer(source, id);
18950 +
18951 +  return resu;
18952 +}
18953 +
18954 diff --git a/databases/readers/Lata/UserFields.h b/databases/readers/Lata/UserFields.h
18955 new file mode 100644
18956 index 0000000..8e2052c
18957 --- /dev/null
18958 +++ b/databases/readers/Lata/UserFields.h
18959 @@ -0,0 +1,108 @@
18960 +/*****************************************************************************
18961 +*
18962 +* Copyright (c) 2011 - 2013, CEA
18963 +* All rights reserved.
18964 +* Redistribution and use in source and binary forms, with or without
18965 +* modification, are permitted provided that the following conditions are met:
18966 +*
18967 +*     * Redistributions of source code must retain the above copyright
18968 +*       notice, this list of conditions and the following disclaimer.
18969 +*     * Redistributions in binary form must reproduce the above copyright
18970 +*       notice, this list of conditions and the following disclaimer in the
18971 +*       documentation and/or other materials provided with the distribution.
18972 +*     * Neither the name of CEA, nor the
18973 +*       names of its contributors may be used to endorse or promote products
18974 +*       derived from this software without specific prior written permission.
18975 +*
18976 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
18977 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18978 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18979 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
18980 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18981 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18982 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
18983 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
18984 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
18985 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18986 +*
18987 +*****************************************************************************/
18988 +
18989 +#ifndef UserFields_H
18990 +#define UserFields_H
18991 +#include <Lata_tools.h>
18992 +#include <LataStructures.h>
18993 +
18994 +template<class F> class Field;
18995 +class FloatTab;
18996 +typedef Field<FloatTab> FieldType;
18997 +class Field_Id;
18998 +class LataFilter;
18999 +struct LataFieldMetaData;
19000 +class DomainUnstructured;
19001 +class DomainIJK;
19002 +
19003 +// Description: classe outil pour acceder a une geometrie dans LataFilter.
19004 +//  La geometrie est chargee en memoire quand cet objet est cree,
19005 +//  elle est dechargee quand il est detruit.
19006 +// Exemple d'utilisation dans UserFields::interpoler_elem_vers_som
19007 +class Geometry_handle
19008 +{
19009 +public:
19010 +  Geometry_handle();
19011 +  Geometry_handle(Geometry_handle &);
19012 +  Geometry_handle & operator=(Geometry_handle &);
19013 +  ~Geometry_handle();
19014 +  void set(LataFilter & filter, const Domain_Id &);
19015 +  const DomainUnstructured & geom();
19016 +  const DomainIJK &          geom_ijk();
19017 +  entier                     test_ijk();
19018 +protected:
19019 +  void                       reset();
19020 +  LataRef<LataFilter> lata_filter_;
19021 +  LataRef<const Domain> geom_;
19022 +};
19023 +
19024 +class UserFields_options
19025 +{
19026 +public:
19027 +  UserFields_options();
19028 +  entier parse_option(const Nom &);
19029 +  void   print_help_option() const;
19030 +
19031 +  // Exemple de parametre en option (commentaires bienvenus !)
19032 +
19033 +  // demie-largeur du filtre_boite en mailles
19034 +  entier demie_largeur_filtre_boite_;
19035 +};
19036 +
19037 +class UserFields
19038 +{
19039 +public:
19040 +  void set_options(const UserFields_options & opt) { opt_ = opt; }
19041 +
19042 +  void   new_fields_metadata(LataFilter & filter,
19043 +                             LataVector<LataFieldMetaData> & fields_data);
19044 +
19045 +  FieldType get_field(const Field_Id & id);
19046 +
19047 +  BigEntier compute_memory_size() { return 0; }
19048 +
19049 +protected:
19050 +  // Declaration de methodes outils
19051 +  FieldType get_champ_source(const Field_Id & id);
19052 +  FieldType get_champ(const Nom & nom, const Field_Id & id);
19053 +  FieldType get_champ_loc(const Nom & nom, LataField_base::Elem_som loc, const Field_Id & id);
19054 +  void      get_geometry(const Domain_Id & id, Geometry_handle &);
19055 +
19056 +  FieldType filtre_boite(const Field_Id & id);
19057 +  FieldType calculer_normale(const Field_Id & id);
19058 +  FieldType calculer_angle(const Field_Id & id);
19059 +  FieldType interpoler_elem_vers_som(const Field_Id & id);
19060 +  FieldType interpoler_faces_vdf_vers_elem(const Field_Id & id);
19061 +
19062 +  // Reference a la classe LataFilter (pour recuperer les champs sources)
19063 +  LataRef<LataFilter> lata_filter_;
19064 +
19065 +  UserFields_options opt_;
19066 +};
19067 +#endif
19068 diff --git a/databases/readers/Lata/Vect.h b/databases/readers/Lata/Vect.h
19069 new file mode 100644
19070 index 0000000..a650806
19071 --- /dev/null
19072 +++ b/databases/readers/Lata/Vect.h
19073 @@ -0,0 +1,34 @@
19074 +/*****************************************************************************
19075 +*
19076 +* Copyright (c) 2011 - 2013, CEA
19077 +* All rights reserved.
19078 +* Redistribution and use in source and binary forms, with or without
19079 +* modification, are permitted provided that the following conditions are met:
19080 +*
19081 +*     * Redistributions of source code must retain the above copyright
19082 +*       notice, this list of conditions and the following disclaimer.
19083 +*     * Redistributions in binary form must reproduce the above copyright
19084 +*       notice, this list of conditions and the following disclaimer in the
19085 +*       documentation and/or other materials provided with the distribution.
19086 +*     * Neither the name of CEA, nor the
19087 +*       names of its contributors may be used to endorse or promote products
19088 +*       derived from this software without specific prior written permission.
19089 +*
19090 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
19091 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19092 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19093 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
19094 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19095 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19096 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19097 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
19098 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19099 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19100 +*
19101 +*****************************************************************************/
19102 +
19103 +#ifndef Vect_h_inclu
19104 +#define Vect_h_inclu
19105 +#include <LataVector.h>
19106 +#define VECT(x) LataVector<x >
19107 +#endif
19108 diff --git a/databases/readers/Lata/VectArrOfInt.h b/databases/readers/Lata/VectArrOfInt.h
19109 new file mode 100644
19110 index 0000000..c666311
19111 --- /dev/null
19112 +++ b/databases/readers/Lata/VectArrOfInt.h
19113 @@ -0,0 +1,34 @@
19114 +/*****************************************************************************
19115 +*
19116 +* Copyright (c) 2011 - 2013, CEA
19117 +* All rights reserved.
19118 +* Redistribution and use in source and binary forms, with or without
19119 +* modification, are permitted provided that the following conditions are met:
19120 +*
19121 +*     * Redistributions of source code must retain the above copyright
19122 +*       notice, this list of conditions and the following disclaimer.
19123 +*     * Redistributions in binary form must reproduce the above copyright
19124 +*       notice, this list of conditions and the following disclaimer in the
19125 +*       documentation and/or other materials provided with the distribution.
19126 +*     * Neither the name of CEA, nor the
19127 +*       names of its contributors may be used to endorse or promote products
19128 +*       derived from this software without specific prior written permission.
19129 +*
19130 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
19131 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19132 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19133 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
19134 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19135 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19136 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19137 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
19138 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19139 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19140 +*
19141 +*****************************************************************************/
19142 +
19143 +#ifndef VectArrOfInt_h_inclu
19144 +#define VectArrOfInt_h_inclu
19145 +#include <ArrOfInt.h>
19146 +#include <Vect.h>
19147 +#endif
19148 diff --git a/databases/readers/Lata/arch.h b/databases/readers/Lata/arch.h
19149 new file mode 100644
19150 index 0000000..68c5800
19151 --- /dev/null
19152 +++ b/databases/readers/Lata/arch.h
19153 @@ -0,0 +1,34 @@
19154 +/*****************************************************************************
19155 +*
19156 +* Copyright (c) 2011 - 2013, CEA
19157 +* All rights reserved.
19158 +* Redistribution and use in source and binary forms, with or without
19159 +* modification, are permitted provided that the following conditions are met:
19160 +*
19161 +*     * Redistributions of source code must retain the above copyright
19162 +*       notice, this list of conditions and the following disclaimer.
19163 +*     * Redistributions in binary form must reproduce the above copyright
19164 +*       notice, this list of conditions and the following disclaimer in the
19165 +*       documentation and/or other materials provided with the distribution.
19166 +*     * Neither the name of CEA, nor the
19167 +*       names of its contributors may be used to endorse or promote products
19168 +*       derived from this software without specific prior written permission.
19169 +*
19170 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
19171 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19172 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19173 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
19174 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19175 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19176 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19177 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
19178 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19179 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19180 +*
19181 +*****************************************************************************/
19182 +
19183 +#ifndef arch_include_
19184 +#define arch_include_
19185 +typedef int entier;
19186 +#endif
19187 +
19188 diff --git a/databases/readers/Lata/avtlataFileFormat.C b/databases/readers/Lata/avtlataFileFormat.C
19189 new file mode 100644
19190 index 0000000..2c4d27c
19191 --- /dev/null
19192 +++ b/databases/readers/Lata/avtlataFileFormat.C
19193 @@ -0,0 +1,865 @@
19194 +/*****************************************************************************
19195 + *
19196 + * Copyright (c) 2000 - 2015, Lawrence Livermore National Security, LLC
19197 + * Produced at the Lawrence Livermore National Laboratory
19198 + * All rights reserved.
19199 + *
19200 + * This file is part of VisIt. For details, see http://www.llnl.gov/visit/. The
19201 + * full copyright notice is contained in the file COPYRIGHT located at the root
19202 + * of the VisIt distribution or at http://www.llnl.gov/visit/copyright.html.
19203 + *
19204 + * Redistribution  and  use  in  source  and  binary  forms,  with  or  without
19205 + * modification, are permitted provided that the following conditions are met:
19206 + *
19207 + *  - Redistributions of  source code must  retain the above  copyright notice,
19208 + *    this list of conditions and the disclaimer below.
19209 + *  - Redistributions in binary form must reproduce the above copyright notice,
19210 + *    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
19211 + *    documentation and/or materials provided with the distribution.
19212 + *  - Neither the name of the UC/LLNL nor  the names of its contributors may be
19213 + *    used to  endorse or  promote products derived from  this software without
19214 + *    specific prior written permission.
19215 + *
19216 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
19217 + * AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
19218 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
19219 + * ARE  DISCLAIMED.  IN  NO  EVENT  SHALL  THE  REGENTS  OF  THE  UNIVERSITY OF
19220 + * CALIFORNIA, THE U.S.  DEPARTMENT  OF  ENERGY OR CONTRIBUTORS BE  LIABLE  FOR
19221 + * ANY  DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR CONSEQUENTIAL
19222 + * DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
19223 + * SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
19224 + * CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
19225 + * LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
19226 + * OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
19227 + * DAMAGE.
19228 + *
19229 + *****************************************************************************/
19230 +
19231 +// ************************************************************************* //
19232 +//                            avtlataFileFormat.C                           //
19233 +// ************************************************************************* //
19234 +
19235 +#include <avtlataFileFormat.h>
19236 +
19237 +#include <LmlReader.h>
19238 +#include <LataJournal.h>
19239 +
19240 +#include <avtDatabaseMetaData.h>
19241 +#include <avtGhostData.h>
19242 +#include <DebugStream.h>
19243 +#include <Expression.h>
19244 +#include <InvalidVariableException.h>
19245 +
19246 +#include <vtkCellData.h>
19247 +#include <vtkCellType.h>
19248 +#include <vtkFloatArray.h>
19249 +#include <vtkInformation.h>
19250 +#include <vtkIntArray.h>
19251 +#include <vtkRectilinearGrid.h>
19252 +#include <vtkStreamingDemandDrivenPipeline.h>
19253 +#include <vtkStructuredGrid.h>
19254 +#include <vtkUnsignedCharArray.h>
19255 +#include <vtkUnstructuredGrid.h>
19256 +
19257 +#include <string>
19258 +#include <fstream>
19259 +#include <iostream>
19260 +#include <visitstream.h>
19261 +#include <vector>
19262 +
19263 +// ****************************************************************************
19264 +//  Method: avtlata constructor
19265 +//
19266 +//  Programmer: fauchet -- generated by xml2avt
19267 +//
19268 +// ****************************************************************************
19269 +
19270 +avtlataFileFormat::avtlataFileFormat(const char *filename)
19271 +  : avtMTMDFileFormat(filename)
19272 +{
19273 +  debug1 << "avtlataFileFormat constructor " << filename << endl;
19274 +  try {
19275 +    set_Journal_level(0);
19276 +
19277 +    LataOptions opt;
19278 +    LataOptions::extract_path_basename(filename, opt.path_prefix, opt.basename);
19279 +    opt.dual_mesh = true;
19280 +    opt.faces_mesh = true;
19281 +    opt.regularize = 2;
19282 +    opt.regularize_tolerance = 1e-7;
19283 +    opt.user_fields_=true;
19284 +    read_any_format_options(filename, opt);
19285 +    debug1 << "avtlataFileFormat: initializing filter" << endl;
19286 +    // Read the source file to the lata database
19287 +    read_any_format(filename, opt.path_prefix, lata_db_);
19288 +    filter_.initialize(opt, lata_db_);
19289 +  }
19290 +  catch (LataDBError err) {
19291 +    cerr << "Error in LataFilter::initialize " << filename << " " << err.describe() << endl;
19292 +    throw;
19293 +  }
19294 +}
19295 +
19296 +avtlataFileFormat::~avtlataFileFormat()
19297 +{
19298 +}
19299 +
19300 +// ****************************************************************************
19301 +//  Method: avtEMSTDFileFormat::GetNTimesteps
19302 +//
19303 +//  Purpose:
19304 +//      Tells the rest of the code how many timesteps there are in this file.
19305 +//
19306 +//  Programmer: fauchet -- generated by xml2avt
19307 +//
19308 +// ****************************************************************************
19309 +
19310 +int
19311 +avtlataFileFormat::GetNTimesteps(void)
19312 +{
19313 +  int n;
19314 +  try {
19315 +    n = filter_.get_nb_timesteps();
19316 +    // Timestep 0 contains global definitions.
19317 +    // If we have "real" timesteps, do not show timestep 0
19318 +    if (n > 1)
19319 +      n--;
19320 +  }
19321 +  catch (LataDBError err) {
19322 +    cerr << "Error in getntimesteps " << filename << " " << err.describe() << endl;
19323 +    throw;
19324 +  }
19325 +  return n;
19326 +}
19327 +
19328 +void avtlataFileFormat::GetTimes(std::vector<double>& times) 
19329 +{ 
19330 +  int n;
19331 +  try {
19332 +    n = filter_.get_nb_timesteps();
19333 +    if (n == 1)
19334 +      times.push_back(0.);
19335 +    else
19336 +      for (int i = 1; i < n; i++)
19337 +        times.push_back(filter_.get_timestep(i));
19338 +  }
19339 +  catch (LataDBError err) {
19340 +    cerr << "Error in gettimes " << filename << " " << err.describe() << endl;
19341 +    throw;
19342 +  }
19343 +  return;
19344 +}
19345 +
19346 +// ****************************************************************************
19347 +//  Method: avtlataFileFormat::FreeUpResources
19348 +//
19349 +//  Purpose:
19350 +//      When VisIt is done focusing on a particular timestep, it asks that
19351 +//      timestep to free up any resources (memory, file descriptors) that
19352 +//      it has associated with it.  This method is the mechanism for doing
19353 +//      that.
19354 +//
19355 +//  Programmer: fauchet -- generated by xml2avt
19356 +//
19357 +// ****************************************************************************
19358 +
19359 +void
19360 +avtlataFileFormat::FreeUpResources(void)
19361 +{
19362 +}
19363 +
19364 +
19365 +// ****************************************************************************
19366 +//  Method: avtlataFileFormat::PopulateDatabaseMetaData
19367 +//
19368 +//  Purpose:
19369 +//      This database meta-data object is like a table of contents for the
19370 +//      file.  By populating it, you are telling the rest of VisIt what
19371 +//      information it can request from you.
19372 +//
19373 +//  Programmer: fauchet -- generated by xml2avt
19374 +//
19375 +// ****************************************************************************
19376 +
19377 +void
19378 +avtlataFileFormat::PopulateDatabaseMetaData(avtDatabaseMetaData *md, int timeState)
19379 +{
19380 +  try {
19381 +  debug1 << "avtlataFileFormat::PopulateDatabaseMetaData : " 
19382 +         << filename << " " << timeState << endl;
19383 +
19384 +  const char *suffix_vector_names[] = { "_X", "_Y", "_Z" };
19385 +  const char *suffix_vector_expr[] = { "[0]", "[1]", "[2]" };
19386 +
19387 +  const Noms geoms = filter_.get_exportable_geometry_names();
19388 +
19389 +  for (int i_geom = 0; i_geom < geoms.size(); i_geom++) {
19390 +    debug1 << " Domain : " << geoms[i_geom] << endl;
19391 +    const LataGeometryMetaData data = filter_.get_geometry_metadata(geoms[i_geom]);
19392 +
19393 +    avtMeshType mt = AVT_UNSTRUCTURED_MESH;
19394 +    
19395 +    if (data.is_ijk_==1)
19396 +      {
19397 +        mt = AVT_RECTILINEAR_MESH;
19398 +      }
19399 +    int block_origin = 0;
19400 +    int topo_dim;
19401 +    switch(data.element_type_) {
19402 +    case Domain::point:     topo_dim = 0; mt = AVT_POINT_MESH; break;
19403 +    case Domain::line:      topo_dim = 1; break;
19404 +    case Domain::triangle: 
19405 +    case Domain::polygone:
19406 +    case Domain::quadri:    topo_dim = 2; break;
19407 +    case Domain::tetra:
19408 +    case Domain::prism6:
19409 +    case Domain::polyedre:
19410 +    case Domain::hexa:      topo_dim = 3; break;
19411 +    default:
19412 +      cerr << "avtlataFileFormat::PopulateDatabaseMetaData error: unknown element type" << endl;
19413 +      topo_dim = 3; ///TODO: this should be an error in default case!
19414 +      EXCEPTION1(InvalidVariableException, 
19415 +                 "avtlataFileFormat::PopulateDatabaseMetaData error: unknown element type");
19416 +      throw;
19417 +    }
19418 +
19419 +    int mesh_faces=0;
19420 +    if  (data.internal_name_.finit_par("_centerfaces"))
19421 +      {
19422 +        //cerr<<"la "<<data.internal_name_<<endl;
19423 +        mesh_faces=1;
19424 +      }
19425 +    double *extents = NULL;
19426 +    const std::string geom_name(data.displayed_name_);
19427 +    AddMeshToMetaData(md, geom_name, mt, extents, data.nblocks_, block_origin,
19428 +                      data.dimension_, topo_dim);
19429 +    mesh_username_.add(data.displayed_name_);
19430 +    mesh_latafilter_name_.add(data.internal_name_);
19431 +
19432 +    Field_UNames fields = filter_.get_exportable_field_unames(geoms[i_geom]);
19433 +
19434 +    for (int i_field = 0; i_field < fields.size(); i_field++) {
19435 +      const LataFieldMetaData data2 = filter_.get_field_metadata(fields[i_field]);
19436 +      avtCentering cent;
19437 +      switch (data2.localisation_) {
19438 +      case LataField_base::ELEM: cent = AVT_ZONECENT; break;
19439 +      case LataField_base::SOM:  cent = AVT_NODECENT; break;
19440 +      default:
19441 +        // Do not export fields that cannot be shown
19442 +        continue;
19443 +      }
19444 +
19445 +      // Take localisation of source field
19446 +      Nom loc = data2.source_localisation_;
19447 +      std::string varname(data2.name_);
19448 +      varname += "_";
19449 +      varname += loc;
19450 +      varname += "_";
19451 +      varname += geom_name;
19452 +      if (data2.nb_components_ == 1) {
19453 +        // Scalar field
19454 +        // We append the geometry name to the component name:
19455 +        register_fieldname(varname.c_str(), fields[i_field], 0);
19456 +        if (mesh_faces==0)
19457 +         AddScalarVarToMetaData(md, varname, geom_name, cent);
19458 +      } else if (data2.is_vector_ && data2.nb_components_ == data.dimension_) {
19459 +        // Vector field
19460 +        register_fieldname(varname.c_str(), fields[i_field], -1);
19461 +        AddVectorVarToMetaData(md, varname, geom_name, cent, data2.nb_components_);
19462 +        if (mesh_faces==0)
19463 +          {
19464 +        std::string n;
19465 +        for (entier i = 0; i < data2.nb_components_; i++) {
19466 +          Expression v;
19467 +          n = data2.name_;
19468 +          n += suffix_vector_names[i];
19469 +          n += "_";
19470 +          n += loc;
19471 +          n += "_";
19472 +          n += geom_name;
19473 +          v.SetName(n);
19474 +          n = varname;
19475 +          n += suffix_vector_expr[i];
19476 +          v.SetDefinition(n);
19477 +          v.SetType(Expression::ScalarMeshVar);
19478 +          md->AddExpression(&v);
19479 +        }
19480 +       if (varname.find_first_of("/",0)==std::string::npos)
19481 +       {
19482 +          // On calcule la norme des vecteurs de premier niveau (pas de / dans le chemin)
19483 +           Expression norme_v;
19484 +           n = "norme_";
19485 +           n += varname;
19486 +           norme_v.SetName(n);
19487 +           n = "magnitude(";
19488 +           n += varname;
19489 +           n += ")";
19490 +           norme_v.SetDefinition(n);
19491 +           norme_v.SetType(Expression::ScalarMeshVar);
19492 +           md->AddExpression(&norme_v);
19493 +       }
19494 +          }
19495 +      } else {
19496 +        // Multiscalar field 
19497 +        // I chose to postfix the varname with the component name, perhaps not the best choice.
19498 +        if (mesh_faces==0)
19499 +          {
19500 +        for (entier i_compo = 0; i_compo < data2.nb_components_; i_compo++) { 
19501 +          std::string varname2(data2.name_);
19502 +          varname2 += "_";
19503 +          if (data2.component_names_.size() == data2.nb_components_) {
19504 +            varname2 += data2.component_names_[i_compo];
19505 +          } else {
19506 +            Nom n(i_compo);
19507 +            varname2 += n;
19508 +          }
19509 +          varname2 += "_";
19510 +          varname2 += loc; 
19511 +          varname2 += "_";
19512 +          varname2 += geom_name;
19513 +          register_fieldname(varname2.c_str(), fields[i_field], i_compo);
19514 +          AddScalarVarToMetaData(md, varname2, geom_name, cent);
19515 +        }
19516 +          }
19517 +      }
19518 +    }
19519 +  }
19520 +  debug1 << "End avtlataFileFormat::PopulateDatabaseMetaData" << endl;
19521 +  }
19522 +  catch (LataDBError err) {
19523 +    cerr << "Error in PopulateDatabaseMetaData " << err.describe() << endl;
19524 +    throw;
19525 +  }
19526 +}
19527 +
19528 +void
19529 +avtlataFileFormat::register_fieldname(const char *visit_name, const Field_UName & uname, int component)
19530 +{
19531 +  if (field_username_.rang(visit_name) >= 0) {
19532 +    cerr << "Error in avtlataFileFormat::register_fieldname: duplicate field name " << visit_name << endl;
19533 +    cerr << "Ignoring field" << endl;
19534 +    return;
19535 +  }
19536 +  field_username_.add(visit_name);
19537 +  field_uname_.add(uname);
19538 +  field_component_.add(component);
19539 +}
19540 +
19541 +void
19542 +avtlataFileFormat::register_meshname(const char *visit_name, const char *latafilter_name)
19543 +{
19544 +  if (mesh_username_.rang(visit_name) >= 0) {
19545 +    cerr << "Error in avtlataFileFormat::register_meshname: duplicate name " << visit_name << endl;
19546 +    cerr << "Ignoring mesh" << endl;
19547 +    return;    
19548 +  }
19549 +  mesh_username_.add(visit_name);
19550 +  mesh_latafilter_name_.add(latafilter_name);
19551 +}
19552 +
19553 +// ****************************************************************************
19554 +//  Method: avtlataFileFormat::GetMesh
19555 +//
19556 +//  Purpose:
19557 +//      Gets the mesh associated with this file.  The mesh is returned as a
19558 +//      derived type of vtkDataSet (ie vtkRectilinearGrid, vtkStructuredGrid,
19559 +//      vtkUnstructuredGrid, etc).
19560 +//
19561 +//  Arguments:
19562 +//      timestate   The index of the timestate.  If GetNTimesteps returned
19563 +//                  'N' time steps, this is guaranteed to be between 0 and N-1.
19564 +//      domain      The index of the domain.  If there are NDomains, this
19565 +//                  value is guaranteed to be between 0 and NDomains-1,
19566 +//                  regardless of block origin.
19567 +//      meshname    The name of the mesh of interest.  This can be ignored if
19568 +//                  there is only one mesh.
19569 +//
19570 +//  Programmer: fauchet -- generated by xml2avt
19571 +//
19572 +// ****************************************************************************
19573 +
19574 +vtkDataSet *
19575 +avtlataFileFormat::GetMesh(int timestate, int block, const char *meshname)
19576 +{
19577 +  vtkDataSet *return_value = 0;
19578 +  try {
19579 +  debug1 << " avtlataFileFormat::GetMesh ts=" << timestate 
19580 +         << " block=" << block 
19581 +         << " meshname=" << meshname << endl;
19582 +
19583 +  // We have real timesteps in the database, add one to timestep index:
19584 +  if (filter_.get_nb_timesteps() > 1)
19585 +    timestate++;
19586 +
19587 +  const entier index = mesh_username_.rang(meshname);
19588 +  if (index < 0) {
19589 +    cerr << "internal error in avtlataFileFormat::GetMesh: name " << meshname << " not found" << endl;
19590 +    throw;
19591 +  }
19592 +  Domain_Id id(mesh_latafilter_name_[index], timestate, block);
19593 +  const Domain & geometry = filter_.get_geometry(id);
19594 +
19595 +  const DomainUnstructured * geom_ptr = dynamic_cast<const DomainUnstructured*>(&geometry);
19596 +  const DomainIJK          * ijk_ptr = dynamic_cast<const DomainIJK*>(&geometry);
19597 +
19598 +  if (geom_ptr) {
19599 +    const DomainUnstructured & geom = *geom_ptr;
19600 +
19601 +    vtkUnstructuredGrid *ugrid = vtkUnstructuredGrid::New();
19602 +    vtkPoints *points = vtkPoints::New();
19603 +    const FloatTab & pos = geom.nodes_;
19604 +    const int nnodes = pos.dimension(0);
19605 +    const int dim3 = pos.dimension(1) == 3;
19606 +    points->SetNumberOfPoints(nnodes);
19607 +    float* pts = (float *) points->GetVoidPointer(0);
19608 +    int jl=0;
19609 +    int i;
19610 +    for (i = 0; i < nnodes; i++) {
19611 +      pts[jl]   = pos(i,0);
19612 +      pts[jl+1] = pos(i,1);
19613 +      pts[jl+2] = dim3 ? pos(i,2) : 0.;
19614 +      jl+=3;
19615 +    }
19616 +    ugrid->SetPoints(points);
19617 +    points->Delete();
19618 +    
19619 +    const IntTab & conn = geom.elements_;
19620 +    const IntTab & elem_faces = geom.elem_faces_;
19621 +    const IntTab & faces = geom.faces_;
19622 +    const int ncells = conn.dimension(0);
19623 +    int nverts = conn.dimension(1);
19624 +    
19625 +    int type_cell;
19626 +    switch (geom.elt_type_) {
19627 +    case Domain::point:
19628 +      type_cell=VTK_VERTEX; 
19629 +      if (ncells == 0) 
19630 +        nverts = 1;
19631 +      break;
19632 +    case Domain::line:
19633 +      type_cell=VTK_LINE;
19634 +      break;
19635 +    case Domain::triangle:
19636 +      type_cell=VTK_TRIANGLE;
19637 +      break;
19638 +    case Domain::quadri:
19639 +      type_cell=VTK_QUAD;
19640 +      break;
19641 +    case Domain::tetra:
19642 +      type_cell=VTK_TETRA;
19643 +      break;
19644 +    case Domain::prism6:
19645 +      type_cell=VTK_WEDGE;
19646 +      break;
19647 +    case Domain::hexa:
19648 +      type_cell=VTK_HEXAHEDRON;
19649 +      break;
19650 +    case Domain::polygone:
19651 +      type_cell=VTK_POLYGON;
19652 +      break;
19653 +    case Domain::polyedre:
19654 +      type_cell= elem_faces.dimension(0) > 0 ? VTK_POLYHEDRON : VTK_CONVEX_POINT_SET;
19655 +      break;
19656 +    default:
19657 +      type_cell=-1;
19658 +      cerr<<"avtlataFileFormat::GetMesh unknown elt type "<<endl;
19659 +      throw;
19660 +      break;
19661 +    }
19662 +    vtkIdType *verts = new vtkIdType[nverts];
19663 +    std::vector<vtkIdType> poly_p, poly_f;
19664 +    if (type_cell == VTK_VERTEX && ncells == 0) {
19665 +      // Cells are implicit. Create them:
19666 +      ugrid->Allocate(nnodes);
19667 +      for (i = 0; i < nnodes; i++) {
19668 +        verts[0] = i;
19669 +        ugrid->InsertNextCell(type_cell, nverts, verts);
19670 +      }
19671 +    } else {
19672 +      ugrid->Allocate(ncells);
19673 +      for (i = 0; i < ncells; i++) {
19674 +        if (type_cell==VTK_QUAD) {
19675 +          // Nodes order is different in visit than in trio_u
19676 +          verts[0]=conn(i,0);
19677 +          verts[1]=conn(i,1);
19678 +          verts[2]=conn(i,3);
19679 +          verts[3]=conn(i,2);
19680 +        } else if (type_cell==VTK_HEXAHEDRON) {
19681 +          // Nodes order is different in visit than in trio_u
19682 +          verts[0]=conn(i,0);
19683 +          verts[1]=conn(i,1);
19684 +          verts[2]=conn(i,3);
19685 +          verts[3]=conn(i,2);
19686 +          verts[4]=conn(i,4);
19687 +          verts[5]=conn(i,5);
19688 +          verts[6]=conn(i,7);
19689 +          verts[7]=conn(i,6);
19690 +        } else if (type_cell==VTK_POLYHEDRON) { 
19691 +          //polyhedra, face by face
19692 +          int j, nfaces = 0, npts = 0, k, i_f, s, f;
19693 +          poly_p.resize(0), poly_f.resize(0);
19694 +          for (j = 0; j < conn.dimension(1); j++) if ((s = conn(i, j)) >= 0) poly_p.push_back(s), npts++;
19695 +          for (j = 0; j < elem_faces.dimension(1); j++) if ((f = elem_faces(i, j)) >= 0)
19696 +            for (k = 0, nfaces++, i_f = poly_f.size(), poly_f.push_back(0); k < faces.dimension(1) ; k++) if ((s = faces(f, k)) >= 0)
19697 +              poly_f.push_back(s), poly_f[i_f]++;
19698 +          ugrid->InsertNextCell(type_cell, npts, &poly_p[0], nfaces, &poly_f[0]);
19699 +        } else if ((type_cell==VTK_CONVEX_POINT_SET)||(type_cell==VTK_POLYGON)) {
19700 +          int nverts_loc=nverts;
19701 +          for (int j = 0; j < nverts; j++) 
19702 +            {
19703 +              verts[j] = conn(i,j);
19704 +             
19705 +              if (verts[j]<=-1)
19706 +                {  
19707 +                  nverts_loc=j; 
19708 +                  break;
19709 +                }    
19710 +  /*            else
19711 +               {
19712 +               if (verts[j]<-1)
19713 +               {
19714 +               std::cerr<<i<<" iiiii "<< j<<" "<<verts[j]<<finl;
19715 +}
19716 +
19717 +}      */
19718 +            }
19719 +          int  nb_som_max_to_regularize=0;
19720 +          if (filter_.get_options().regularize_polyedre!=0)
19721 +            {
19722 +              nb_som_max_to_regularize=8;
19723 +              if (filter_.get_options().regularize_polyedre==-1)
19724 +                  nb_som_max_to_regularize=32000;
19725 +            }
19726 +          if ( geom.elt_type_==Domain::polygone)
19727 +               nb_som_max_to_regularize=-1;
19728 +          if ((nb_som_max_to_regularize>=6) && (nverts_loc==6))
19729 +            ugrid->InsertNextCell(VTK_WEDGE, nverts_loc, verts);
19730 +          else if ((nb_som_max_to_regularize>=12)&&(nverts_loc==12))
19731 +            ugrid->InsertNextCell(VTK_HEXAGONAL_PRISM, nverts_loc, verts);
19732 +          else if ((nb_som_max_to_regularize>=8)&&(nverts_loc==8))
19733 +            {
19734 +                        // Nodes order is different in visit than in trio_u
19735 +              verts[0]=conn(i,0);
19736 +              verts[1]=conn(i,1);
19737 +              verts[2]=conn(i,3);
19738 +              verts[3]=conn(i,2);
19739 +              verts[4]=conn(i,4);
19740 +              verts[5]=conn(i,5);
19741 +              verts[6]=conn(i,7);
19742 +              verts[7]=conn(i,6);
19743 +              ugrid->InsertNextCell(VTK_HEXAHEDRON, nverts_loc, verts);
19744 +               
19745 +            }
19746 +          else
19747 +            ugrid->InsertNextCell(type_cell, nverts_loc, verts);
19748 +        }
19749 +        else {
19750 +          for (int j = 0; j < nverts; j++) 
19751 +            verts[j] = conn(i,j);
19752 +        }
19753 +        if ((type_cell!=VTK_POLYHEDRON) &&(type_cell!=VTK_CONVEX_POINT_SET) && (type_cell!=VTK_POLYGON))
19754 +         
19755 +          ugrid->InsertNextCell(type_cell, nverts, verts);
19756 +      }
19757 +    }
19758 +    delete [] verts;
19759 +    verts = 0;
19760 +    // Declare ghost elements:
19761 +    const int n = geom.nb_virt_items(LataField_base::ELEM);
19762 +    if (n > 0) {
19763 +      unsigned char realVal = 0;
19764 +      unsigned char ghost   = 0; // Sera modifie par AddGhostZoneType
19765 +      avtGhostData::AddGhostZoneType(ghost, DUPLICATED_ZONE_INTERNAL_TO_PROBLEM);
19766 +      vtkUnsignedCharArray *ghostcells = vtkUnsignedCharArray::New();
19767 +      ghostcells->SetName("avtGhostZones");
19768 +      ghostcells->SetNumberOfTuples(ncells);
19769 +      unsigned char *dat = (unsigned char *) ghostcells->GetVoidPointer(0);
19770 +      for (i = 0; i < ncells - n; i++)
19771 +        dat[i] = realVal;
19772 +      for (i = ncells - n; i < ncells; i++)
19773 +        dat[i] = ghost;
19774 +      ugrid->GetCellData()->AddArray(ghostcells);
19775 +      ugrid->GetInformation()->Set(
19776 +        vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), 0);
19777 +      ghostcells->Delete();
19778 +    }
19779 +    return_value = ugrid;
19780 +    
19781 +  } else if (ijk_ptr) {
19782 +    const DomainIJK & geom = *ijk_ptr;
19783 +
19784 +    // Maillage regulier : on transmet la grille ijk
19785 +    vtkRectilinearGrid *sgrid = vtkRectilinearGrid::New();
19786 +
19787 +    const int dim = geom.coord_.size();
19788 +    ArrOfInt ncoord(3, 1);
19789 +    int i;
19790 +    for (i = 0; i < dim; i++) 
19791 +      ncoord[i] = geom.coord_[i].size_array();
19792 +    sgrid->SetDimensions(ncoord[0], ncoord[1], ncoord[2]);
19793 +
19794 +    for (i = 0; i < 3; i++) {
19795 +      float *data;
19796 +      vtkFloatArray *c;
19797 +      c = vtkFloatArray::New();
19798 +      const int n = ncoord[i];
19799 +      c->SetNumberOfTuples(n);
19800 +      data = (float *) c->GetVoidPointer(0);
19801 +      if (i < dim) {
19802 +        const ArrOfFloat & coord = geom.coord_[i];
19803 +        for (int j = 0; j < n; j++)
19804 +          data[j] = coord[j];
19805 +      } else {
19806 +        data[0] = 0.;
19807 +      }
19808 +      switch(i) {
19809 +      case 0: sgrid->SetXCoordinates(c); break;
19810 +      case 1: sgrid->SetYCoordinates(c); break;
19811 +      case 2: sgrid->SetZCoordinates(c); break;
19812 +      default: ;
19813 +      }
19814 +      c->Delete();
19815 +    }
19816 +    // Create "invalid cells" data (GettingDataIntoVisit.pdf, page 136)
19817 +    // and "ghost cells"
19818 +    const int n = geom.invalid_connections_.size_array();
19819 +    if (n > 0 || geom.virtual_layer_begin_ || geom.virtual_layer_end_) {
19820 +      const int ncells = geom.nb_elements();
19821 +      unsigned char realVal = 0;
19822 +      unsigned char invalid = 0; // Sera modifie par AddGhostZoneType
19823 +      unsigned char ghost   = 0;
19824 +      avtGhostData::AddGhostZoneType(invalid, ZONE_NOT_APPLICABLE_TO_PROBLEM);
19825 +      avtGhostData::AddGhostZoneType(ghost, DUPLICATED_ZONE_INTERNAL_TO_PROBLEM);
19826 +      vtkUnsignedCharArray *ghostcells = vtkUnsignedCharArray::New();
19827 +      ghostcells->SetName("avtGhostZones");
19828 +      ghostcells->SetNumberOfTuples(ncells);
19829 +      unsigned char *dat = (unsigned char *) ghostcells->GetVoidPointer(0);
19830 +
19831 +      for (i = 0; i < ncells; i++)
19832 +          dat[i] = realVal;
19833 +
19834 +      if (n > 0) {
19835 +        // invalid cells
19836 +        for (i = 0; i < ncells; i++) {
19837 +          if (geom.invalid_connections_[i])
19838 +            dat[i] = invalid;
19839 +        }
19840 +      }
19841 +      
19842 +      // ghost cells
19843 +      entier ij = 1;
19844 +      for (i = 0; i < dim-1; i++)
19845 +        ij *= ncoord[i]-1;
19846 +      if (geom.virtual_layer_begin_) {
19847 +        // first layer of cells is ghost
19848 +        for (i = 0; i < ij * geom.virtual_layer_begin_; i++)
19849 +          dat[i] += ghost;
19850 +      }
19851 +      if (geom.virtual_layer_end_) {
19852 +        // last layer of cells is ghost
19853 +        for (i = ncells - ij * geom.virtual_layer_end_; i < ncells; i++)
19854 +          dat[i] += ghost;
19855 +      }
19856 +      
19857 +      sgrid->GetCellData()->AddArray(ghostcells);
19858 +      sgrid->GetInformation()->Set(
19859 +        vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), 0);
19860 +      ghostcells->Delete();
19861 +    }
19862 +
19863 +    return_value = sgrid;
19864 +  } else {
19865 +    cerr << "Error in avtlataFileFormat::GetMesh: unknown geometry type" << endl;
19866 +    throw;
19867 +  }
19868 +
19869 +  filter_.release_geometry(geometry);
19870 +  }
19871 +  catch (LataDBError err) {
19872 +    cerr << "Error in getmesh " << timestate << " " << block << " " << meshname << " " << err.describe() << endl;
19873 +    throw;
19874 +  }
19875 +
19876 +  return return_value;
19877 +}
19878 +
19879 +
19880 +// ****************************************************************************
19881 +//  Method: avtlataFileFormat::GetVar
19882 +//
19883 +//  Purpose:
19884 +//      Gets a scalar variable associated with this file.  Although VTK has
19885 +//      support for many different types, the best bet is vtkFloatArray, since
19886 +//      that is supported everywhere through VisIt.
19887 +//
19888 +//  Arguments:
19889 +//      timestate  The index of the timestate.  If GetNTimesteps returned
19890 +//                 'N' time steps, this is guaranteed to be between 0 and N-1.
19891 +//      domain     The index of the domain.  If there are NDomains, this
19892 +//                 value is guaranteed to be between 0 and NDomains-1,
19893 +//                 regardless of block origin.
19894 +//      varname    The name of the variable requested.
19895 +//
19896 +//  Programmer: fauchet -- generated by xml2avt
19897 +//
19898 +// ****************************************************************************
19899 +
19900 +vtkDataArray *
19901 +avtlataFileFormat::GetVar(int timestate, int block, const char *varname)
19902 +{
19903 +  vtkDataArray * return_value = 0;
19904 +  try {
19905 +  debug1 << "Getvar time:" << timestate
19906 +         << " block:" << block
19907 +         << " varname:" << varname << endl;
19908 +
19909 +  if (filter_.get_nb_timesteps() > 1)
19910 +    timestate++;
19911 +
19912 +  Field_UName field_uname;
19913 +  int component;
19914 +  get_field_info_from_visitname(varname, field_uname, component);
19915 +
19916 +  if (component < 0) {
19917 +    cerr << "Error: avtlataFileFormat::GetVar called for vector field" << endl;
19918 +    throw;
19919 +  }
19920 +
19921 +  Field_Id id(field_uname, timestate, block);
19922 +
19923 +  const LataField_base & field = filter_.get_field(id);
19924 +
19925 +  const Field<FloatTab> * float_field_ptr = dynamic_cast<const Field<FloatTab>*>(&field);
19926 +  const Field<IntTab> * int_field_ptr = dynamic_cast<const Field<IntTab>*>(&field);
19927 +
19928 +  if (float_field_ptr) {
19929 +    vtkFloatArray *rv = vtkFloatArray::New();
19930 +    const Field<FloatTab> & fld = *float_field_ptr;
19931 +    const FloatTab & values = fld.data_;
19932 +    int ntuples = values.dimension(0);
19933 +    rv->SetNumberOfTuples(ntuples);
19934 +    float * data = rv->GetPointer(0);
19935 +    for (int i = 0; i < ntuples; i++) 
19936 +      data[i] = values(i, component);
19937 +    return_value = rv;
19938 +  } else if (int_field_ptr) {
19939 +    vtkIntArray *rv = vtkIntArray::New();
19940 +    const Field<IntTab> & fld = *int_field_ptr;
19941 +    const IntTab & values = fld.data_;
19942 +    int ntuples = values.dimension(0);
19943 +    rv->SetNumberOfTuples(ntuples);
19944 +    int * data = rv->GetPointer(0);
19945 +    for (int i = 0; i < ntuples; i++) 
19946 +      data[i] = values(i, component);    
19947 +    return_value = rv;
19948 +  } else {
19949 +    cerr << "Error in avtlataFileFormat::GetVar: unknown data type" << endl;
19950 +    throw;
19951 +  }
19952 +  filter_.release_field(field);
19953 +  }
19954 +  catch (LataDBError err) {
19955 +    cerr << "Error in getvar " << timestate << " " << block << " " << varname << " " << err.describe() << endl;
19956 +    throw;
19957 +  }
19958 +  return return_value; 
19959 +}
19960 +
19961 +
19962 +// ****************************************************************************
19963 +//  Method: avtlataFileFormat::GetVectorVar
19964 +//
19965 +//  Purpose:
19966 +//      Gets a vector variable associated with this file.  Although VTK has
19967 +//      support for many different types, the best bet is vtkFloatArray, since
19968 +//      that is supported everywhere through VisIt.
19969 +//
19970 +//  Arguments:
19971 +//      timestate  The index of the timestate.  If GetNTimesteps returned
19972 +//                 'N' time steps, this is guaranteed to be between 0 and N-1.
19973 +//      domain     The index of the domain.  If there are NDomains, this
19974 +//                 value is guaranteed to be between 0 and NDomains-1,
19975 +//                 regardless of block origin.
19976 +//      varname    The name of the variable requested.
19977 +//
19978 +//  Programmer: fauchet -- generated by xml2avt
19979 +//
19980 +// ****************************************************************************
19981 +
19982 +vtkDataArray *
19983 +avtlataFileFormat::GetVectorVar(int timestate, int block, const char *varname)
19984 +{
19985 +  vtkDataArray * return_value = 0;
19986 +  try {
19987 +  debug1 << "Getvectorvar time:" << timestate
19988 +         << " block:" << block
19989 +         << " varname:" << varname << endl;
19990 +
19991 +  if (filter_.get_nb_timesteps() > 1)
19992 +    timestate++;
19993 +
19994 +  Field_UName field_uname;
19995 +  int component;
19996 +  get_field_info_from_visitname(varname, field_uname, component);
19997 +
19998 +  if (component >= 0) {
19999 +    cerr << "Error: avtlataFileFormat::GetVectorVar called for scalar field" << endl;
20000 +    throw;
20001 +  }
20002 +
20003 +  Field_Id id(field_uname, timestate, block);
20004 +
20005 +  const LataField_base & field = filter_.get_field(id);
20006 +
20007 +  const Field<FloatTab> * float_field_ptr = dynamic_cast<const Field<FloatTab>*>(&field);
20008 +  const Field<IntTab> * int_field_ptr = dynamic_cast<const Field<IntTab>*>(&field);
20009 +
20010 +  if (float_field_ptr) {
20011 +    vtkFloatArray *rv = vtkFloatArray::New();
20012 +    const Field<FloatTab> & fld = *float_field_ptr;
20013 +    const FloatTab & values = fld.data_;
20014 +    int ntuples = values.dimension(0);
20015 +    int dim = values.dimension(1);
20016 +    rv->SetNumberOfComponents(3);
20017 +    rv->SetNumberOfTuples(ntuples);
20018 +    float* data= rv->WritePointer(0,3*ntuples);
20019 +    for (int i = 0; i < ntuples; i++)
20020 +      for (int j = 0; j < 3; j++)
20021 +        data[i*3+j] = (j<dim) ? values(i, j) : 0.;
20022 +    return_value = rv;
20023 +  } else if (int_field_ptr) {
20024 +    vtkIntArray *rv = vtkIntArray::New();
20025 +    const Field<IntTab> & fld = *int_field_ptr;
20026 +    const IntTab & values = fld.data_;
20027 +    int ntuples = values.dimension(0);
20028 +    int dim = values.dimension(1);
20029 +    rv->SetNumberOfComponents(3);
20030 +    rv->SetNumberOfTuples(ntuples);
20031 +    int* data= rv->WritePointer(0,3*ntuples);
20032 +    for (int i = 0; i < ntuples; i++) 
20033 +      for (int j = 0; j < 3; j++)
20034 +        data[i*3+j] = (j<dim) ? values(i, j) : 0;
20035 +    return_value = rv;
20036 +  } else {
20037 +    cerr << "Error in avtlataFileFormat::GetVectorVar: unknown data type" << endl;
20038 +    throw;
20039 +  }
20040 +  filter_.release_field(field);
20041 +  }
20042 +  catch (LataDBError err) {
20043 +    cerr << "Error in getvectorvar " << timestate << " " << block << " " << varname << " " << err.describe() << endl;
20044 +    throw;
20045 +  }
20046 +  return return_value; 
20047 +}
20048 +
20049 +void avtlataFileFormat::get_field_info_from_visitname(const char *varname, Field_UName & uname, int & component) const
20050 +{
20051 +  const int k = field_username_.rang(varname);
20052 +  if (k < 0) {
20053 +    cerr << "Error in avtlataFileFormat::get_field_info_from_visitname: field " << varname << " not found" << endl;
20054 +    throw  ;
20055 +  }
20056 +  uname = field_uname_[k];
20057 +  component = field_component_[k];
20058 +}
20059 diff --git a/databases/readers/Lata/avtlataFileFormat.h b/databases/readers/Lata/avtlataFileFormat.h
20060 new file mode 100644
20061 index 0000000..3dd8e43
20062 --- /dev/null
20063 +++ b/databases/readers/Lata/avtlataFileFormat.h
20064 @@ -0,0 +1,114 @@
20065 +/*****************************************************************************
20066 +*
20067 +* Copyright (c) 2000 - 2012, Lawrence Livermore National Security, LLC
20068 +* Produced at the Lawrence Livermore National Laboratory
20069 +* All rights reserved.
20070 +*
20071 +* This file is part of VisIt. For details, see http://www.llnl.gov/visit/. The
20072 +* full copyright notice is contained in the file COPYRIGHT located at the root
20073 +* of the VisIt distribution or at http://www.llnl.gov/visit/copyright.html.
20074 +*
20075 +* Redistribution  and  use  in  source  and  binary  forms,  with  or  without
20076 +* modification, are permitted provided that the following conditions are met:
20077 +*
20078 +*  - Redistributions of  source code must  retain the above  copyright notice,
20079 +*    this list of conditions and the disclaimer below.
20080 +*  - Redistributions in binary form must reproduce the above copyright notice,
20081 +*    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
20082 +*    documentation and/or materials provided with the distribution.
20083 +*  - Neither the name of the UC/LLNL nor  the names of its contributors may be
20084 +*    used to  endorse or  promote products derived from  this software without
20085 +*    specific prior written permission.
20086 +*
20087 +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
20088 +* AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
20089 +* IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
20090 +* ARE  DISCLAIMED.  IN  NO  EVENT  SHALL  THE  REGENTS  OF  THE  UNIVERSITY OF
20091 +* CALIFORNIA, THE U.S.  DEPARTMENT  OF  ENERGY OR CONTRIBUTORS BE  LIABLE  FOR
20092 +* ANY  DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR CONSEQUENTIAL
20093 +* DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
20094 +* SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
20095 +* CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
20096 +* LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
20097 +* OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
20098 +* DAMAGE.
20099 +*
20100 +*****************************************************************************/
20101 +
20102 +// ************************************************************************* //
20103 +//                            avtlataFileFormat.h                           //
20104 +// ************************************************************************* //
20105 +
20106 +#ifndef AVT_lata_FILE_FORMAT_H
20107 +#define AVT_lata_FILE_FORMAT_H
20108 +
20109 +#include <avtMTMDFileFormat.h>
20110 +
20111 +#include <vector>
20112 +#include "LataFilter.h"
20113 +
20114 +// ****************************************************************************
20115 +//  Class: avtlataFileFormat
20116 +//
20117 +//  Purpose:
20118 +//      Reads in lata files as a plugin to VisIt.
20119 +//
20120 +//  Programmer: fauchet -- generated by xml2avt
20121 +//
20122 +// ****************************************************************************
20123 +
20124 +class avtlataFileFormat : public avtMTMDFileFormat
20125 +{
20126 +  public:
20127 +    avtlataFileFormat(const char *);
20128 +    virtual ~avtlataFileFormat();
20129 +
20130 +    //
20131 +    // This is used to return unconvention data -- ranging from material
20132 +    // information to information about block connectivity.
20133 +    //
20134 +    // virtual void      *GetAuxiliaryData(const char *var, const char *type,
20135 +    //                                     int timestep, int domain,void *args, 
20136 +    //                                     DestructorFunction &);
20137 +    //
20138 +
20139 +    //
20140 +    // If you know the times and cycle numbers, overload this function.
20141 +    // Otherwise, VisIt will make up some reasonable ones for you.
20142 +    //
20143 +    // virtual void        GetCycles(std::vector<int> &);
20144 +    // virtual void        GetTimes(std::vector<double> &);
20145 +    //
20146 +
20147 +    virtual int            GetNTimesteps(void);
20148 +
20149 +    virtual const char    *GetType(void)   { return "lata"; };
20150 +    virtual void           FreeUpResources(void); 
20151 +
20152 +    virtual vtkDataSet    *GetMesh(int, int, const char *);
20153 +    virtual vtkDataArray  *GetVar(int, int, const char *);
20154 +    virtual vtkDataArray  *GetVectorVar(int, int, const char *);
20155 +    virtual void GetTimes(std::vector<double>& times);
20156 +  protected:
20157 +    // DATA MEMBERS
20158 +
20159 +    virtual void           PopulateDatabaseMetaData(avtDatabaseMetaData *, int);
20160 +
20161 +    void register_fieldname(const char *visit_name, const Field_UName &, int component);
20162 +    void register_meshname(const char *visit_name, const char *latafilter_name);
20163 +    void get_field_info_from_visitname(const char *varname, Field_UName &, int & component) const;
20164 +
20165 +    LataDB      lata_db_; // Source database
20166 +    LataFilter  filter_; // Data processor and cache
20167 +    Noms field_username_;
20168 +    Field_UNames field_uname_;
20169 +
20170 +    Noms mesh_username_;
20171 +    Noms mesh_latafilter_name_;
20172 +
20173 +    // For each name, which component is it in the source field:
20174 +    LataVector<int> field_component_;
20175 +};
20176 +
20177 +
20178 +#endif
20179 diff --git a/databases/readers/Lata/simd_interface.h b/databases/readers/Lata/simd_interface.h
20180 new file mode 100644
20181 index 0000000..e14c409
20182 --- /dev/null
20183 +++ b/databases/readers/Lata/simd_interface.h
20184 @@ -0,0 +1,31 @@
20185 +/*****************************************************************************
20186 +*
20187 +* Copyright (c) 2011 - 2013, CEA
20188 +* All rights reserved.
20189 +* Redistribution and use in source and binary forms, with or without
20190 +* modification, are permitted provided that the following conditions are met:
20191 +*
20192 +*     * Redistributions of source code must retain the above copyright
20193 +*       notice, this list of conditions and the following disclaimer.
20194 +*     * Redistributions in binary form must reproduce the above copyright
20195 +*       notice, this list of conditions and the following disclaimer in the
20196 +*       documentation and/or other materials provided with the distribution.
20197 +*     * Neither the name of CEA, nor the
20198 +*       names of its contributors may be used to endorse or promote products
20199 +*       derived from this software without specific prior written permission.
20200 +*
20201 +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
20202 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20203 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20204 +* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20205 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20206 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20207 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20208 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20209 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
20210 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20211 +*
20212 +*****************************************************************************/
20213 +#ifdef WITH_SIMD
20214 +#include "simd_tools.h"
20215 +#endif
20216 diff --git a/databases/visit_readers.xml b/databases/visit_readers.xml
20217 index 0b1405c..05aa776 100644
20218 --- a/databases/visit_readers.xml
20219 +++ b/databases/visit_readers.xml
20220 @@ -781,6 +781,19 @@
20221       </Hints>
20222      </SourceProxy>
20223  
20224 +    <SourceProxy name="VisItLataReader" class="vtkVisItLataReader"
20225 +    base_proxygroup="internal_readers" base_proxyname="VisItReaderBase">
20226 +    <Documentation
20227 +       long_help="Lata file reader">
20228 +       Note this reader is automatically generated from wrapping a third party reader. For more information on the reader see https://wci.llnl.gov/codes/visit
20229 +       The default file extensions is .lata
20230 +    </Documentation>
20231 +     <Hints>
20232 +       <ReaderFactory extensions="lata"
20233 +                      file_description="Lata Files" />
20234 +     </Hints>
20235 +    </SourceProxy>
20236 +
20237      <SourceProxy name="VisItM3DReader" class="vtkVisItM3DReader"
20238        base_proxygroup="internal_readers" base_proxyname="VisItReaderBase">
20239      <Documentation
20240 -- 
20241 2.17.0
20242