From aa6790b2f1f69864cca1db0181e0aee7ded81e2a Mon Sep 17 00:00:00 2001 From: rnv Date: Wed, 1 Apr 2020 13:39:31 +0300 Subject: [PATCH 1/1] ParaView-5.8.0 build options and patches --- .../occ/options_compilation_salome_master.txt | 2 +- .../patches/paraview.0001-LATA-reader.patch | 20242 ++++++++++++++++ ...ridRelevantPointsFilter-fix-for-poly.patch | 118 + .../paraview.0003-ParaViewClient.patch | 10 + .../patches/paraview.0004-ParaView_hdf5.patch | 14 + .../paraview.0005-ParaView_find_cgns.patch | 15 + .../paraview.0006-ParaView_find_libxml2.patch | 14 + ...paraview.0007-ParaView_find_freetype.patch | 15 + ...aview.001_against_multiple_py_sv_thr.patch | 17 - .../paraview.002_statestorage_bug.patch | 34 - config/patches/paraview.004_forwarding.patch | 12 - 11 files changed, 20429 insertions(+), 64 deletions(-) create mode 100644 config/patches/paraview.0001-LATA-reader.patch create mode 100644 config/patches/paraview.0002-vtkUnstructuredGridRelevantPointsFilter-fix-for-poly.patch create mode 100644 config/patches/paraview.0003-ParaViewClient.patch create mode 100644 config/patches/paraview.0004-ParaView_hdf5.patch create mode 100644 config/patches/paraview.0005-ParaView_find_cgns.patch create mode 100644 config/patches/paraview.0006-ParaView_find_libxml2.patch create mode 100644 config/patches/paraview.0007-ParaView_find_freetype.patch delete mode 100644 config/patches/paraview.001_against_multiple_py_sv_thr.patch delete mode 100644 config/patches/paraview.002_statestorage_bug.patch delete mode 100644 config/patches/paraview.004_forwarding.patch diff --git a/config/build_options/occ/options_compilation_salome_master.txt b/config/build_options/occ/options_compilation_salome_master.txt index 2e53e1a..f0378cd 100644 --- a/config/build_options/occ/options_compilation_salome_master.txt +++ b/config/build_options/occ/options_compilation_salome_master.txt @@ -152,7 +152,7 @@ CAS > cmake -DINSTALL_DIR:STRING=${CAS_ROOT_DIR} -D3RDPARTY_TCL_DIR:PATH=${TCLTK_ROOT_DIR} -DUSE_TBB:BOOL=ON -D3RDPARTY_TBB_DIR:PATH=${TBB_ROOT_DIR} -D3RDPARTY_FREETYPE_DIR:PATH=${FREETYPE_ROOT_DIR} -DUSE_FREEIMAGE:BOOL=ON -D3RDPARTY_FREEIMAGE_DIR:PATH=${FREEIMAGE_ROOT_DIR} -DUSE_GL2PS:BOOL=ON -D3RDPARTY_GL2PS_DIR:PATH=${GL2PS_ROOT_DIR} -DCMAKE_BUILD_TYPE:STRING=Release ${CAS_SRC_DIR} Paraview -cmake -DCMAKE_INSTALL_PREFIX:STRING=${PARAVIEW_ROOT_DIR} -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_SHARED_LIBS:BOOL=ON -DBUILD_TESTING:BOOL=OFF -DCMAKE_CXX_FLAGS:STRING=-m64 -DCMAKE_C_FLAGS:STRING=-m64 -DPARAVIEW_INSTALL_DEVELOPMENT_FILES:BOOL=ON -DVTK_PYTHON_FULL_THREADSAFE:BOOL=ON -DVTK_NO_PYTHON_THREADS:BOOL=OFF -DVTK_PYTHON_VERSION:STRING=3 -DOpenGL_GL_PREFERENCE:STRING=LEGACY -DPARAVIEW_USE_OSPRAY:BOOL=ON -DOSPRAY_INSTALL_DIR:PATH=${OSPRAY_ROOT_DIR} -Dembree_DIR:PATH=${EMBREE_ROOT_DIR}/lib64/cmake/embree-3.5.2 -DVTK_USE_64BIT_IDS:BOOL=OFF -DVTK_REPORT_OPENGL_ERRORS:BOOL=OFF -DVTK_RENDERING_BACKEND:STRING=OpenGL2 -DPARAVIEW_BUILD_QT_GUI:BOOL=ON -DQT_HELP_GENERATOR:STRING=${QT5_ROOT_DIR}/bin/qhelpgenerator -DPARAVIEW_QT_VERSION:STRING=5 -DVTK_BUILD_QT_DESIGNER_PLUGIN:BOOL=OFF -DPARAVIEW_ENABLE_PYTHON:BOOL=ON -DVTK_WRAP_PYTHON:BOOL=ON -DPYTHON_EXECUTABLE:STRING=${PYTHON_ROOT_DIR}/bin/python3.6 -DPYTHON_INCLUDE_DIR:STRING=${PYTHON_ROOT_DIR}/include/python3.6 -DPYTHON_LIBRARY:STRING=${PYTHON_ROOT_DIR}/lib/libpython3.6.so -DVTK_NO_PYTHON_THREADS:BOOL=OFF -DVTK_USE_SYSTEM_PYGMENTS:BOOL=ON -DVTK_WRAP_JAVA:BOOL=OFF -DPARAVIEW_USE_MPI:BOOL=OFF -DVTK_USE_SYSTEM_HDF5:BOOL=ON -DHDF5_USE_STATIC_LIBRARIES:BOOL=OFF -DHDF5_ROOT:PATH=${HDF5_ROOT_DIR} -DHDF5_INCLUDE_DIRS:STRING=${HDF5_ROOT_DIR}/include -DHDF5_LIBRARIES:FILEPATH=${HDF5_ROOT_DIR}/lib/libhdf5.so;${HDF5_ROOT_DIR}/lib/libhdf5_hl.so -DHDF5_INCLUDE_DIR:PATH=${HDF5_ROOT_DIR}/include -DPARAVIEW_USE_VISITBRIDGE:BOOL=ON -DBOOST_ROOT:PATH=${BOOST_ROOT_DIR} -DVTK_USE_SYSTEM_GL2PS:BOOL=ON -DGL2PS_INCLUDE_DIR:STRING=${GL2PS_ROOT_DIR}/include -DGL2PS_LIBRARY:STRING=${GL2PS_ROOT_DIR}/lib/libgl2ps.so -DVTK_USE_SYSTEM_LIBXML2:BOOL=ON -DLIBXML2_INCLUDE_DIR:STRING=${LIBXML2_ROOT_DIR}/include/libxml2 -DLIBXML2_LIBRARIES:STRING=${LIBXML2_ROOT_DIR}/lib/libxml2.so -DVTK_USE_SYSTEM_FREETYPE:BOOL=ON -DPARAVIEW_BUILD_PLUGIN_Moments:BOOL=OFF -DPARAVIEW_BUILD_PLUGIN_SLACTools:BOOL=OFF -DPARAVIEW_BUILD_PLUGIN_SierraPlotTools:BOOL=OFF -DPARAVIEW_BUILD_PLUGIN_PacMan:BOOL=OFF -DPARAVIEW_ENABLE_COPROCESSING:BOOL=OFF -DPARAVIEW_BUILD_PLUGIN_EyeDomeLighting:BOOL=ON -DPARAVIEW_BUILD_PLUGIN_PointSprite:BOOL=ON -DPARAVIEW_BUILD_PLUGIN_SurfaceLIC:BOOL=ON -DPARAVIEW_ENABLE_MATPLOTLIB:BOOL=ON ${PARAVIEW_SRC_DIR} +cmake -DCMAKE_INSTALL_PREFIX:STRING=${PARAVIEW_ROOT_DIR} -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_CXX_FLAGS:STRING=-m64 -DCMAKE_C_FLAGS:STRING=-m64 -DPARAVIEW_BUILD_SHARED_LIBS:BOOL=ON -DPARAVIEW_BUILD_TESTING:BOOL=OFF -DPARAVIEW_INSTALL_DEVELOPMENT_FILES:BOOL=ON -DOpenGL_GL_PREFERENCE:STRING=LEGACY -DPARAVIEW_ENABLE_RAYTRACING:BOOL=ON -DVTK_ENABLE_OSPRAY:BOOL=ON -Dembree_DIR:PATH=${EMBREE_ROOT_DIR}/lib64/cmake/embree-3.3.0 -DTBB_ROOT:PATH=${TBB_ROOT_DIR} -DVTK_USE_64BIT_IDS:BOOL=OFF -DVTK_REPORT_OPENGL_ERRORS:BOOL=OFF -DVTK_MODULE_ENABLE_VTK_RenderingLOD:INTERNAL=YES -DVTK_MODULE_ENABLE_VTK_FiltersCore:INTERNAL=YES -DVTK_MODULE_ENABLE_VTK_CommonCore:INTERNAL=YES -DVTK_MODULE_ENABLE_VTK_IOCore:INTERNAL=YES -DVTK_MODULE_ENABLE_VTK_IOEnSight:INTERNAL=YES -DVTK_MODULE_ENABLE_VTK_IOInfovis:INTERNAL=YES -DPARAVIEW_USE_QT:BOOL=ON -DVTK_BUILD_QT_DESIGNER_PLUGIN:BOOL=OFF -DPARAVIEW_USE_PYTHON:BOOL=ON -DVTK_WRAP_PYTHON:BOOL=ON -DPython3_INCLUDE_DIR:STRING=${PYTHON_ROOT_DIR}/include/python3.6 -DPython3_LIBRARY:STRING=${PYTHON_ROOT_DIR}/lib/libpython3.6.so -DVTK_PYTHON_FULL_THREADSAFE:BOOL=ON -DVTK_NO_PYTHON_THREADS:BOOL=OFF -DVTK_PYTHON_VERSION:STRING=3 -DVTK_WRAP_JAVA:BOOL=OFF -DPARAVIEW_USE_MPI:BOOL=OFF -DVTK_MODULE_USE_EXTERNAL_VTK_hdf5:BOOL=ON -DHDF5_DIR:PATH=${HDF5_ROOT_DIR}/share/cmake/hdf5 -DHDF5_USE_STATIC_LIBRARIES:BOOL=OFF -DPARAVIEW_ENABLE_VISITBRIDGE:BOOL=ON -DBOOST_ROOT:PATH=${BOOST_ROOT_DIR} -DBoost_NO_BOOST_CMAKE:BOOL=ON -DBoost_NO_SYSTEM_PATHS:BOOL=ON -DVTK_MODULE_USE_EXTERNAL_VTK_gl2ps:BOOL=OFF -DVTK_MODULE_USE_EXTERNAL_VTK_libxml2:BOOL=ON -DLIBXML2_INCLUDE_DIR:STRING=${LIBXML2_ROOT_DIR}/include/libxml2 -DLIBXML2_LIBRARIES:STRING=${LIBXML2_ROOT_DIR}/lib/libxml2.so -DVTK_MODULE_USE_EXTERNAL_VTK_freetype:BOOL=ON -DVTK_MODULE_USE_EXTERNAL_ParaView_cgns:BOOL=ON -DCGNS_INCLUDE_DIR:PATH=${CGNS_ROOT_DIR}/include -DCGNS_LIBRARY:PATH=${CGNS_ROOT_DIR}/lib/libcgns.so -DVTK_MODULE_ENABLE_ParaView_cgns:INTERNAL=YES -DVTK_MODULE_ENABLE_ParaView_VTKExtensionsCGNSReader:INTERNAL=YES -DVTK_MODULE_ENABLE_ParaView_VTKExtensionsCGNSWriter:INTERNAL=YES -DPARAVIEW_PLUGINS_DEFAULT:BOOL=ON -DPARAVIEW_PLUGIN_ENABLE_Moments:BOOL=OFF -DPARAVIEW_PLUGIN_ENABLE_SLACTools:BOOL=OFF -DPARAVIEW_PLUGIN_ENABLE_SierraPlotTools:BOOL=OFF -DPARAVIEW_PLUGIN_ENABLE_PacMan:BOOL=OFF -DPARAVIEW_PLUGIN_ENABLE_pvblot:BOOL=OFF ${PARAVIEW_SRC_DIR} PyQt > python3 ./configure.py -b ${PYQT5_ROOT_DIR}/bin -d ${PYQT5_ROOT_DIR} -v ${PYQT5_ROOT_DIR}/sip --confirm-license --designer-plugindir=${PYQT5_ROOT_DIR}/plugins/designer --qml-plugindir=${PYQT5_ROOT_DIR}/plugins/qml --no-qsci-api --sip-incdir=${SIP_ROOT_DIR}/include/python3.6 diff --git a/config/patches/paraview.0001-LATA-reader.patch b/config/patches/paraview.0001-LATA-reader.patch new file mode 100644 index 0000000..873c94d --- /dev/null +++ b/config/patches/paraview.0001-LATA-reader.patch @@ -0,0 +1,20242 @@ +From 8b92e13269c76f0c4b3422cd2774412bb24368b7 Mon Sep 17 00:00:00 2001 +From: Antoine Gerschenfeld +Date: Sun, 19 May 2019 20:24:42 +0200 +Subject: [PATCH 1/3] LATA reader + +--- + databases/CMakeLists.txt | 1 + + databases/readers/Lata/ArrOfBit.C | 179 ++ + databases/readers/Lata/ArrOfBit.h | 110 + + databases/readers/Lata/ArrOfDouble.C | 1185 +++++++++ + databases/readers/Lata/ArrOfDouble.h | 353 +++ + databases/readers/Lata/ArrOfFloat.C | 1185 +++++++++ + databases/readers/Lata/ArrOfFloat.h | 353 +++ + databases/readers/Lata/ArrOfInt.C | 1110 ++++++++ + databases/readers/Lata/ArrOfInt.h | 343 +++ + .../readers/Lata/ArrOf_Scalar_Prototype.cpp.h | 1168 +++++++++ + .../readers/Lata/ArrOf_Scalar_Prototype.h | 357 +++ + databases/readers/Lata/CMakeLists.txt | 35 + + .../readers/Lata/Connectivite_som_elem.C | 189 ++ + .../readers/Lata/Connectivite_som_elem.h | 44 + + databases/readers/Lata/DoubleTab.h | 30 + + databases/readers/Lata/EFichier.h | 60 + + databases/readers/Lata/Entree.h | 77 + + databases/readers/Lata/FloatTab.h | 30 + + databases/readers/Lata/IntTab.h | 31 + + databases/readers/Lata/LataDB.C | 2313 +++++++++++++++++ + databases/readers/Lata/LataDB.h | 303 +++ + databases/readers/Lata/LataDBmed.h | 586 +++++ + databases/readers/Lata/LataFilter.C | 1106 ++++++++ + databases/readers/Lata/LataFilter.h | 261 ++ + databases/readers/Lata/LataJournal.h | 36 + + databases/readers/Lata/LataStructures.C | 743 ++++++ + databases/readers/Lata/LataStructures.h | 332 +++ + .../readers/Lata/LataV1_field_definitions.C | 84 + + .../readers/Lata/LataV1_field_definitions.h | 35 + + databases/readers/Lata/LataVector.h | 64 + + databases/readers/Lata/LataWriter.C | 331 +++ + databases/readers/Lata/LataWriter.h | 61 + + databases/readers/Lata/Lata_tools.C | 128 + + databases/readers/Lata/Lata_tools.h | 194 ++ + databases/readers/Lata/LmlReader.C | 435 ++++ + databases/readers/Lata/LmlReader.h | 38 + + databases/readers/Lata/Motcle.C | 142 + + databases/readers/Lata/Motcle.h | 150 ++ + databases/readers/Lata/Noms.h | 29 + + databases/readers/Lata/Objet_U.h | 41 + + databases/readers/Lata/Octree_Double.C | 395 +++ + databases/readers/Lata/Octree_Double.h | 89 + + databases/readers/Lata/Octree_Int.C | 485 ++++ + databases/readers/Lata/Octree_Int.h | 103 + + databases/readers/Lata/OpenDXWriter.C | 335 +++ + databases/readers/Lata/OpenDXWriter.h | 83 + + databases/readers/Lata/Operator.h | 224 ++ + databases/readers/Lata/OperatorBoundary.C | 227 ++ + databases/readers/Lata/OperatorDualMesh.C | 222 ++ + databases/readers/Lata/OperatorFacesMesh.C | 130 + + databases/readers/Lata/OperatorReconnect.C | 125 + + databases/readers/Lata/OperatorRegularize.C | 296 +++ + .../readers/Lata/Rebuild_virtual_layer.C | 141 + + .../readers/Lata/Rebuild_virtual_layer.h | 35 + + databases/readers/Lata/Sortie.h | 44 + + databases/readers/Lata/Static_Int_Lists.C | 128 + + databases/readers/Lata/Static_Int_Lists.h | 110 + + databases/readers/Lata/UserFields.C | 1038 ++++++++ + databases/readers/Lata/UserFields.h | 108 + + databases/readers/Lata/Vect.h | 34 + + databases/readers/Lata/VectArrOfInt.h | 34 + + databases/readers/Lata/arch.h | 34 + + databases/readers/Lata/avtlataFileFormat.C | 865 ++++++ + databases/readers/Lata/avtlataFileFormat.h | 114 + + databases/readers/Lata/simd_interface.h | 31 + + databases/visit_readers.xml | 13 + + 66 files changed, 19695 insertions(+) + create mode 100644 databases/readers/Lata/ArrOfBit.C + create mode 100644 databases/readers/Lata/ArrOfBit.h + create mode 100644 databases/readers/Lata/ArrOfDouble.C + create mode 100644 databases/readers/Lata/ArrOfDouble.h + create mode 100644 databases/readers/Lata/ArrOfFloat.C + create mode 100644 databases/readers/Lata/ArrOfFloat.h + create mode 100644 databases/readers/Lata/ArrOfInt.C + create mode 100644 databases/readers/Lata/ArrOfInt.h + create mode 100644 databases/readers/Lata/ArrOf_Scalar_Prototype.cpp.h + create mode 100644 databases/readers/Lata/ArrOf_Scalar_Prototype.h + create mode 100644 databases/readers/Lata/CMakeLists.txt + create mode 100644 databases/readers/Lata/Connectivite_som_elem.C + create mode 100644 databases/readers/Lata/Connectivite_som_elem.h + create mode 100644 databases/readers/Lata/DoubleTab.h + create mode 100644 databases/readers/Lata/EFichier.h + create mode 100644 databases/readers/Lata/Entree.h + create mode 100644 databases/readers/Lata/FloatTab.h + create mode 100644 databases/readers/Lata/IntTab.h + create mode 100644 databases/readers/Lata/LataDB.C + create mode 100644 databases/readers/Lata/LataDB.h + create mode 100644 databases/readers/Lata/LataDBmed.h + create mode 100644 databases/readers/Lata/LataFilter.C + create mode 100644 databases/readers/Lata/LataFilter.h + create mode 100644 databases/readers/Lata/LataJournal.h + create mode 100644 databases/readers/Lata/LataStructures.C + create mode 100644 databases/readers/Lata/LataStructures.h + create mode 100644 databases/readers/Lata/LataV1_field_definitions.C + create mode 100644 databases/readers/Lata/LataV1_field_definitions.h + create mode 100644 databases/readers/Lata/LataVector.h + create mode 100644 databases/readers/Lata/LataWriter.C + create mode 100644 databases/readers/Lata/LataWriter.h + create mode 100644 databases/readers/Lata/Lata_tools.C + create mode 100644 databases/readers/Lata/Lata_tools.h + create mode 100644 databases/readers/Lata/LmlReader.C + create mode 100644 databases/readers/Lata/LmlReader.h + create mode 100644 databases/readers/Lata/Motcle.C + create mode 100644 databases/readers/Lata/Motcle.h + create mode 100644 databases/readers/Lata/Noms.h + create mode 100644 databases/readers/Lata/Objet_U.h + create mode 100644 databases/readers/Lata/Octree_Double.C + create mode 100644 databases/readers/Lata/Octree_Double.h + create mode 100644 databases/readers/Lata/Octree_Int.C + create mode 100644 databases/readers/Lata/Octree_Int.h + create mode 100644 databases/readers/Lata/OpenDXWriter.C + create mode 100644 databases/readers/Lata/OpenDXWriter.h + create mode 100644 databases/readers/Lata/Operator.h + create mode 100644 databases/readers/Lata/OperatorBoundary.C + create mode 100644 databases/readers/Lata/OperatorDualMesh.C + create mode 100644 databases/readers/Lata/OperatorFacesMesh.C + create mode 100644 databases/readers/Lata/OperatorReconnect.C + create mode 100644 databases/readers/Lata/OperatorRegularize.C + create mode 100644 databases/readers/Lata/Rebuild_virtual_layer.C + create mode 100644 databases/readers/Lata/Rebuild_virtual_layer.h + create mode 100644 databases/readers/Lata/Sortie.h + create mode 100644 databases/readers/Lata/Static_Int_Lists.C + create mode 100644 databases/readers/Lata/Static_Int_Lists.h + create mode 100644 databases/readers/Lata/UserFields.C + create mode 100644 databases/readers/Lata/UserFields.h + create mode 100644 databases/readers/Lata/Vect.h + create mode 100644 databases/readers/Lata/VectArrOfInt.h + create mode 100644 databases/readers/Lata/arch.h + create mode 100644 databases/readers/Lata/avtlataFileFormat.C + create mode 100644 databases/readers/Lata/avtlataFileFormat.h + create mode 100644 databases/readers/Lata/simd_interface.h + +diff --git a/databases/CMakeLists.txt b/databases/CMakeLists.txt +index a3d1b03..7b4bd48 100644 +--- a/databases/CMakeLists.txt ++++ b/databases/CMakeLists.txt +@@ -35,6 +35,7 @@ set(DEFAULT_BRIDGE_READERS + H5Nimrod + Image + LAMMPS ++ Lata + Lines + M3D + M3DC1 +diff --git a/databases/readers/Lata/ArrOfBit.C b/databases/readers/Lata/ArrOfBit.C +new file mode 100644 +index 0000000..c1b4b45 +--- /dev/null ++++ b/databases/readers/Lata/ArrOfBit.C +@@ -0,0 +1,179 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++//Implemente_instanciable_sans_constructeur_ni_destructeur(ArrOfBit,"ArrOfBit",Objet_U); ++ ++const unsigned int ArrOfBit::SIZE_OF_INT_BITS = 5; ++const unsigned int ArrOfBit::DRAPEAUX_INT = 31; ++ ++// Description: Constructeur d'un tableau de taille n, non initialise ++ArrOfBit::ArrOfBit(entier n) ++{ ++ taille = 0; ++ data = 0; ++ resize_array(n); ++} ++ ++// Description: Destructeur. ++ArrOfBit::~ArrOfBit() ++{ ++ if (data) ++ delete[] data; ++ data = 0; ++} ++ ++// Description: Constructeur par copie (deep copy) ++ArrOfBit::ArrOfBit(const ArrOfBit& array) ++{ ++ taille = 0; ++ data = 0; ++ operator=(array); ++} ++ ++// Description: ++// Taille en "int" du tableau requis pour stocker un tableau de bits ++// de taille donnees. ++entier ArrOfBit::calculer_int_size(entier taille) const ++{ ++ assert(taille >= 0); ++ entier siz = taille >> SIZE_OF_INT_BITS; ++ if (taille & DRAPEAUX_INT) ++ siz++; ++ return siz; ++} ++ ++// Description: Change la taille du tableau et copie les donnees ++// existantes. Si la taille est plus petite, les donnees sont ++// tronquees, et si la taille est plus grande, les nouveaux elements ++// ne sont pas initialises. ++ArrOfBit& ArrOfBit::resize_array(entier n) ++{ ++ if (taille == n) ++ return *this; ++ assert(n >= 0); ++ if (n > 0) ++ { ++ entier oldsize = calculer_int_size(taille); ++ entier newsize = calculer_int_size(n); ++ unsigned int * newdata = new unsigned int[newsize]; ++ entier size_copy = (newsize > oldsize) ? oldsize : newsize; ++ if (size_copy) ++ { ++ memcpy(newdata, data, size_copy); ++ delete[] data; ++ } ++ data = newdata; ++ taille = n; ++ } ++ else ++ { ++ delete[] data; // data!=0 sinon taille==n et on ne serait pas ici ++ data = 0; ++ taille = 0; ++ } ++ return *this; ++} ++ ++// Description: Operateur copie (deep copy). ++ArrOfBit& ArrOfBit::operator=(const ArrOfBit& array) ++{ ++ entier newsize = calculer_int_size(array.taille); ++ if (taille != array.taille) ++ { ++ if (data) ++ { ++ delete[] data; ++ data = 0; ++ } ++ if (newsize > 0) ++ data = new unsigned int[newsize]; ++ } ++ taille = array.taille; ++ if (taille) ++ memcpy(data, array.data, newsize * sizeof(unsigned int)); ++ return *this; ++} ++ ++// Description: Si la valeur est non nulle, met la valeur 1 dans ++// tous les elements du tableau, sinon met la valeur 0. ++ ++ArrOfBit& ArrOfBit::operator=(entier val) ++{ ++ unsigned int valeur = val ? (~((unsigned int) 0)) : 0; ++ entier size = calculer_int_size(taille); ++ entier i; ++ for (i = 0; i < size; i++) ++ data[i] = valeur; ++ return *this; ++} ++ ++// Description: Ecriture du tableau. Format: ++// n ++// 0 1 0 0 1 0 ... (n valeurs) ++Sortie& ArrOfBit::printOn(Sortie& os) const ++{ ++ os << taille << finl; ++ entier i; ++ // Un retour a la ligne tous les 32 bits, ++ // Une espace tous les 8 bits ++ for (i = 0; i < taille; i++) ++ { ++ os << operator[](i); ++ if ((i & 7) == 7) ++ os << " "; ++ if ((i & 31) == 31) ++ os << finl; ++ } ++ // Un retour a la ligne si la derniere ligne n'etait pas terminee ++ if (i & 31) ++ os << finl; ++ return os; ++} ++ ++// Description: Lecture du tableau. Format: ++// n ++// 0 1 0 0 1 0 ... (n valeurs) ++Entree& ArrOfBit::readOn(Entree& is) ++{ ++ entier newsize; ++ is >> newsize; ++ resize_array(newsize); ++ operator=(0); ++ ++ entier i; ++ for (i = 0; i < taille; i++) ++ { ++ entier bit; ++ is >> bit; ++ if (bit) setbit(i); ++ } ++ return is; ++} +diff --git a/databases/readers/Lata/ArrOfBit.h b/databases/readers/Lata/ArrOfBit.h +new file mode 100644 +index 0000000..ed21f48 +--- /dev/null ++++ b/databases/readers/Lata/ArrOfBit.h +@@ -0,0 +1,110 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++ ++#ifndef ARROFBIT_H ++#define ARROFBIT_H ++ ++#include ++#include ++ ++class ArrOfBit // : public Objet_U ++{ ++// Declare_instanciable_sans_constructeur_ni_destructeur(ArrOfBit); ++protected: ++ Entree& readOn(Entree& is); ++ Sortie& printOn(Sortie& os) const; ++public: ++ ArrOfBit(entier n=0); ++ ArrOfBit(const ArrOfBit& array); // Constructeur par copie ++ ~ArrOfBit(); // Destructeur ++ ArrOfBit& operator=(const ArrOfBit& array); // Operateur copie ++ ArrOfBit& operator=(entier i); ++ inline entier operator[](entier i) const; ++ inline void setbit(entier i) const; ++ inline entier testsetbit(entier i) const; ++ inline void clearbit(entier i) const; ++ inline entier size_array() const; ++ ArrOfBit& resize_array(entier n); ++ entier calculer_int_size(entier taille) const; ++protected: ++ entier taille; ++ unsigned int *data; ++ static const unsigned int SIZE_OF_INT_BITS; ++ static const unsigned int DRAPEAUX_INT; ++}; ++ ++// Description: Renvoie 1 si le bit e est mis, 0 sinon. ++inline entier ArrOfBit::operator[](entier e) const ++{ ++ assert(e >= 0 && e < taille); ++ unsigned int i = (unsigned int) e; ++ unsigned int x = data[i >> SIZE_OF_INT_BITS]; ++ unsigned int flag = 1 << (i & DRAPEAUX_INT); ++ entier resultat = ((x & flag) != 0) ? 1 : 0; ++ return resultat; ++} ++ ++// Description: Met le bit e a 1. ++inline void ArrOfBit::setbit(entier e) const ++{ ++ assert(e >= 0 && e < taille); ++ unsigned int i = (unsigned int) e; ++ unsigned int flag = 1 << (i & DRAPEAUX_INT); ++ data[i >> SIZE_OF_INT_BITS] |= flag; ++} ++ ++// Description: Renvoie la valeur du bit e, puis met le bit e a 1. ++inline entier ArrOfBit::testsetbit(entier e) const ++{ ++ assert(e >= 0 && e < taille); ++ unsigned int i = (unsigned int) e; ++ unsigned int flag = 1 << (i & DRAPEAUX_INT); ++ entier index = i >> SIZE_OF_INT_BITS; ++ unsigned int old = data[index]; ++ data[index] = old | flag; ++ return ((old & flag) != 0) ? 1 : 0; ++} ++ ++// Description: Met le bit e a 0. ++inline void ArrOfBit::clearbit(entier e) const ++{ ++ assert(e >= 0 && e < taille); ++ unsigned int i = (unsigned int) e; ++ unsigned int flag = 1 << (i & DRAPEAUX_INT); ++ data[i >> SIZE_OF_INT_BITS] &= ~flag; ++} ++ ++// Description: Renvoie la taille du tableau en bits ++inline entier ArrOfBit::size_array() const ++{ ++ return taille; ++} ++ ++#endif +diff --git a/databases/readers/Lata/ArrOfDouble.C b/databases/readers/Lata/ArrOfDouble.C +new file mode 100644 +index 0000000..5605a0d +--- /dev/null ++++ b/databases/readers/Lata/ArrOfDouble.C +@@ -0,0 +1,1185 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++//////////////////////////////////////////////////////////// ++// ++// Warning : DO NOT EDIT ! ++// Please update ArrOf_Scalar_Prototype.cpp.h ++// and this file will be generated automatically ++// by the script file check.sh ++//////////////////////////////////////////////////////////// ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "simd_interface.h" ++ ++using namespace std; ++ ++// ****************************************************************** ++// ++// Implementation des methodes de VDoubledata ++// ++// ****************************************************************** ++//////////////////////////////////////////////////////////////////// ++// .NOM ArrOfDouble ++// .ENTETE TRUST Math ++// .LIBRAIRIE libtmath ++// .FILE ArrOfDouble.h ++// .FILE ArrOfDouble.cpp ++// ++// .DESCRIPTION ++// VDoubledata alloue une zone de memoire de la taille specifiee au ++// constructeur, et libere la zone de memoire a la destruction. ++// ++// "ref_count" compte le nombre de pointeurs qui font reference a "this". ++// (permet au dernier utilisateur de l'objet de le detruire), voir ++// ArrOfDouble. ++// ++// .SECTION voir aussi ++// .CONTRAINTES ++// .INVARIANTS ++// .HTML ++// .EPS ++/////////////////////////////////////////////////////////////////// ++ ++class VDoubledata ++{ ++public: ++ VDoubledata(entier size, ArrOfDouble::Storage storage); ++ ~VDoubledata(); ++ entier add_one_ref(); ++ entier suppr_one_ref(); ++ double * get_data(); ++ const double * get_data() const; ++ inline entier ref_count() const; ++ inline entier get_size() const; ++private: ++ // Le constructeur par copie et l'operateur= sont interdits. ++ VDoubledata(const VDoubledata& v); ++ VDoubledata& operator=(const VDoubledata& v); ++ ++ // "data" est un pointeur sur une zone de memoire de taille ++ // sz * sizeof(double), allouee par le ++ // constructeur et liberee par le destructeur. ++ // Ce pointeur n'est jamais nul meme si size_==0 ++ double * data_; ++ // Compteur incremente par add_one_ref et decremente par suppr_one_ref. ++ // Contient le nombre d'objets ArrOfDouble dont le membre "p" pointe ++ // vers "this". On a ref_count_ >= 0. ++ entier ref_count_; ++ // "sz" est la taille du tableau "data_" alloue ++ // On a sz >= 0. ++ entier size_; ++ ArrOfDouble::Storage storage_; ++}; ++ ++ ++// Description: ++// Construit un VDoubledata de taille size >= 0 ++// Parametre: entier s ++// Signification: taille du VDoubledata, il faut size >= 0 ++// Parametre: Storage storage ++// Signification: indique si la memoire doit etre allouee ++// avec "new" ou avec "simd_malloc" ++// Valeurs par defaut: STANDARD (allocation avec "new") ++// Postcondition: ++// data_ n'est jamais nul, meme si size==0 ++VDoubledata::VDoubledata(entier size, ArrOfDouble::Storage storage) ++{ ++ if (size == 0) ++ storage = ArrOfDouble::STANDARD; ++ ++ switch (storage) ++ { ++ case ArrOfDouble::STANDARD: ++ { ++#ifdef _EXCEPTION_ ++ // Allocation de la memoire sur le tas ++ try ++ { ++ data_ = new double[size]; ++ } ++ catch(...) ++ { ++ Cerr << "impossible d'allouer " << size << " double " << finl; ++ throw; ++ } ++#else ++ data_ = new double[size]; ++ if(!data_) ++ { ++ Cerr << "impossible d'allouer " << size << "double " << finl; ++ throw ; ++ } ++#endif ++ break; ++ } ++ case ArrOfDouble::SIMD_ALIGNED: ++ { ++#ifdef SIMD_TOOLS_H ++ data_ = (double*) simd_malloc (sizeof(double) * size); ++#else ++ Cerr<<"unable to allocate simd_aligned, version compiled without simd "< 0 ++// Retour: int ++// Signification: ref_count ++inline entier VDoubledata::suppr_one_ref() ++{ ++ assert(ref_count_ > 0); ++ return (--ref_count_); ++} ++ ++// Description: renvoie data_ ++inline double * VDoubledata::get_data() ++{ ++ return data_; ++} ++ ++// Description: renvoie data_ ++inline const double * VDoubledata::get_data() const ++{ ++ return data_; ++} ++ ++// Description: Constructeur par copie. Interdit : genere une erreur ! ++VDoubledata::VDoubledata(const VDoubledata& v) ++{ ++ Cerr << "Erreur dans VDoubledata::VDoubledata(const VDoubledata & v)" << finl; ++ throw; ++} ++ ++// Description: Operateur= interdit. Genere une erreur ! ++VDoubledata& VDoubledata::operator=(const VDoubledata& v) ++{ ++ Cerr << "Erreur dans VDoubledata::operator=(const VDoubledata & v)" << finl; ++ throw; ++ return *this; ++} ++ ++// ****************************************************************** ++// ++// Implementation des methodes de ArrOfDouble ++// ++// ****************************************************************** ++ ++ ++// Definition des constantes pour les options de memory_resize ++const entier ArrOfDouble::COPY_OLD = 1; ++const entier ArrOfDouble::INITIALIZE_NEW = 2; ++ ++// Description: ++// Destructeur : appelle detach_array() ++ArrOfDouble::~ArrOfDouble() ++{ ++ detach_array(); ++ size_array_ = -1; // Paranoia: si size_array_==-1, c'est un zombie ++} ++ ++// Description: ++// Constructeur par defaut: cree un tableau "detache", ++// soit p_==0, data_==0, size_array_==0, smart_resize_==0 ++ArrOfDouble::ArrOfDouble() : ++ p_(0), ++ data_(0), ++ size_array_(0), ++ memory_size_(0), ++ smart_resize_(0), ++ storage_type_(STANDARD) ++{ ++} ++ ++// Description: ++// Cree un tableau de taille n avec allocation standard ++// (voir set_mem_storage). ++// Valeur de remplissage par defaut: voir fill_default_value ++// Precondition: ++// Parametre: entier n ++// Signification: taille du tableau ++ArrOfDouble::ArrOfDouble(entier n) : ++ p_(new VDoubledata(n, STANDARD)), ++ data_(p_->get_data()), ++ size_array_(n), ++ memory_size_(n), ++ smart_resize_(0), ++ storage_type_(STANDARD) ++{ ++ if (n > 0) ++ fill_default_value(0, n); ++} ++ ++// Description: ++// Cree un tableau de taille n ++// toutes les cases sont initialisees a x ++// Precondition: ++// Parametre: entier n ++// Signification: taille du tableau ++// Parametre: double x ++// Signification: valeur pour initialiser le tableau ++ArrOfDouble::ArrOfDouble(entier n, double x) : ++ p_(new VDoubledata(n, STANDARD)), ++ data_(p_->get_data()), ++ size_array_(n), ++ memory_size_(n), ++ smart_resize_(0), ++ storage_type_(STANDARD) ++{ ++ *this = x; ++} ++ ++// Description: ++// Constructeur par copie. On alloue une nouvelle zone de memoire ++// et on copie le contenu du tableau. L'attribut smart_resize_ est ++// copie aussi. ++// Si le tableau A est de taille nulle, on cree un tableau "detache", ++// sinon on cree un tableau "normal". ++// Parametre: const ArrOfDouble& A ++// Signification: le tableau a copier ++ArrOfDouble::ArrOfDouble(const ArrOfDouble& A) ++{ ++ const entier size = A.size_array(); ++ if (size > 0) ++ { ++ // Creation d'un tableau "normal" ++ storage_type_ = STANDARD; ++ p_ = new VDoubledata(size, STANDARD); ++ data_ = p_->get_data(); ++ size_array_ = size; ++ memory_size_ = size; ++ smart_resize_ = A.smart_resize_; ++ inject_array(A); ++ } ++ else ++ { ++ // Creation d'un tableau "detache" ++ p_ = 0; ++ data_ = 0; ++ size_array_ = 0; ++ memory_size_ = 0; ++ smart_resize_ = 0; ++ storage_type_ = STANDARD; ++ } ++} ++ ++// Description: ++// Change le mode d'allocation memoire lors des resize ++// (voir VDoubledata et Double_ptr_trav) ++// Exemple pour creer un tableau avec allocation temporaire: ++// DoubleTab tab; // Creation d'un tableau vide ++// tab.set_mem_storage(TEMP_STORAGE); // Changement de mode d'allocation ++// tab.resize(n); // Allocation memoire ++void ArrOfDouble::set_mem_storage(const Storage storage) ++{ ++ storage_type_ = storage; ++} ++ ++// Description: ++// Renvoie le mode d'allocation du tableau (qui sera utilise ++// lors du prochain resize si changement de taille). ++// (voir VDoubledata et Double_ptr_trav) ++enum ArrOfDouble::Storage ArrOfDouble::get_mem_storage() const ++{ ++ return storage_type_; ++} ++ ++// Description: ++// Change le mode l'allocation memoire: reallocation d'un tableau ++// a chaque changement de taille (flag = 0) ou reallocation ++// uniquement si la taille augmente et par doublement de la taille ++// du tableau (flag = 1). ++void ArrOfDouble::set_smart_resize(entier flag) ++{ ++ assert(flag == 0 || flag == 1); ++ smart_resize_ = flag; ++} ++ ++// Description: ++// Remet le tableau dans l'etat obtenu avec le constructeur par defaut ++// (libere la memoire mais conserve le mode d'allocation memoire actuel) ++void ArrOfDouble::reset() ++{ ++ detach_array(); ++} ++ ++// Description: ++// Copie les donnees du tableau m. ++// Si "m" n'a pas la meme taille que "*this", on fait un resize_array. ++// Ensuite, on copie les valeurs de "m" dans "*this". ++// Le type de tableau (methode d'allocation) n'est pas copie. ++// Precondition: ++// Si le tableau n'a pas la meme taille que "m", alors *this doit ++// etre "resizable" (ne pas etre de type "ref_data" et "ref_count == 1") ++// Parametre: const ArrOfDouble& m ++// Signification: la tableau a copier ++// Retour: ArrOfDouble& ++// Signification: *this ++ArrOfDouble& ArrOfDouble::operator=(const ArrOfDouble& m) ++{ ++ if (&m != this) ++ { ++ const entier new_size = m.size_array(); ++ // Le code suivant est quasiment une copie de ArrOfDouble::resize() ++ // SAUF: memory_resize est appele avec NO_INITIALIZE (la zone de memoire ++ // n'est pas initialisee) ++ if (new_size != size_array()) ++ { ++ if ((smart_resize_ == 0) || (new_size > memory_size_)) ++ memory_resize(new_size, 0); // Pas d'initialisation ++ size_array_ = new_size; ++ } ++ inject_array(m); ++ } ++ return *this; ++} ++ ++ ++// Description: ++// x est affecte a toutes les cases ++// Precondition: ++// Parametre: double x ++// Signification: la valeur a affecter a toutes les cases du tableau ++// Valeurs par defaut: ++// Contraintes: ++// Acces: ++// Retour: ArrOfDouble& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++ArrOfDouble& ArrOfDouble::operator=(double x) ++{ ++ const entier n = size_array(); ++ double *data = addr(); ++ for (entier i = 0; i < n; i++) ++ { ++ data[i] = x; ++ } ++ return *this; ++} ++ ++// Description: appelle operator=(a) ++ArrOfDouble& ArrOfDouble::copy_array(const ArrOfDouble& a) ++{ ++ operator=(a); ++ return *this; ++} ++ ++// Description: ++// Si besoin, alloue une nouvelle zone de memoire, ++// copie les donnees et efface l'ancienne zone de memoire. ++// Attention, on suppose que cette methode est appelee par ++// resize_array(). ++// Attention: si ref_count_>1, l'appel a resize_array() est ++// autorise uniquement si la nouvelle taille est identique ++// a la precedente. ++// Precondition: ++// Le tableau doit etre de type "detache" ou "normal" avec ++// ref_count==1, et il faut new_size >= 0 ++// On suppose que size_array contient encore le nombre d'elements ++// valides avant changement de taille. ++// Parametre: new_size ++// Signification: nouvelle taille demandee pour le tableau. ++// Parametre: options ++// Signification: COPY_OLD => on recopie les anciennes donnees dans le nouveau ++// tableau (jusqu'au max de l'ancienne et de la nouvelle taille). ++// INITIALIZE_NEW => initialisation des cases non copiees ++// Postcondition: ++// p_ et data_ sont mis a jour, mais pas size_array_ !!! ++// (on suppose que c'est fait dans resize_array()). ++// Si la nouvelle taille est nulle, on detache le tableau. ++void ArrOfDouble::memory_resize(entier new_size, entier options) ++{ ++ assert(new_size >= 0); ++ ++ // Occupation memoire de l'ancien tableau: ++ entier old_mem_size = 0; ++ if (p_) ++ old_mem_size = p_->get_size(); ++ ++ // Occupation memoire du nouveau tableau : ++ // Si smart_resize, on prend au moins deux fois la taille ++ // precedente, ou new_size ++ entier new_mem_size = new_size; ++ if (smart_resize_ && (old_mem_size * 2 > new_size)) ++ new_mem_size = old_mem_size * 2; ++ ++ if (new_mem_size != old_mem_size) ++ { ++ // detach_array() efface le contenu de size_array_. On le met de cote: ++ const entier old_size_array = size_array_; ++ // On va reellement changer l'adresse du tableau. ++ // Il ne faut pas qu'il existe d'autre reference a ce tableau. ++ assert(data_ == 0 || (p_ != 0 && ref_count() == 1)); ++ if (new_mem_size == 0) ++ { ++ // La nouvelle taille est nulle, on cree un tableau "detache" ++ detach_array(); ++ } ++ else ++ { ++ // Allocation d'une nouvelle zone ++ VDoubledata * new_p = new VDoubledata(new_mem_size, storage_type_); ++ double * new_data = new_p->get_data(); ++ // Raccourci si le tableau etait "detache", inutile de copier ++ // les anciennes donnees. On copie si COPY_OLD est demande ++ entier copy_size = 0; ++ if (data_ != 0) ++ { ++ // Calcul du nombre d'elements a copier vers la nouvelle ++ // zone de memoire : c'est le min de l'ancienne et de ++ // la nouvelle taille. ++ if (options & COPY_OLD) ++ { ++ copy_size = size_array_; ++ if (new_size < copy_size) ++ copy_size = new_size; ++ // Copie des valeurs dans le nouveau tableau ++ for (entier i = 0; i < copy_size; i++) ++ new_data[i] = data_[i]; ++ } ++ // Destruction de l'ancienne zone (si plus aucune reference) ++ detach_array(); ++ } ++ // On attache la nouvelle zone de memoire ++ p_ = new_p; ++ data_ = new_data; ++ memory_size_ = new_mem_size; ++ // Initialisation des cases supplementaires avec une valeur par defaut ++ if (options & INITIALIZE_NEW) ++ fill_default_value(copy_size, new_mem_size - copy_size); ++ // Restaure l'ancienne valeur de size_array_ ++ size_array_ = old_size_array; ++ } ++ } ++} ++ ++// Description: ++// Remplit "nb" cases consecutives du tableau a partir de la case "first" ++// avec une valeur par defaut. ++// Cette fonction est appelee lors d'un resize pour initialiser les ++// cases nouvellement creees. ++// Le comportement depend actuellement du type de tableau : ++// * Tableau de type "smart_resize": ++// * en mode debug (macro NDEBUG non definie) le tableau est initialise ++// avec une valeur invalide. ++// * en optimise, le tableau n'est pas initialise ++// * Tableau normal : ++// Le tableau est initialise avec la valeur 0. Ce comportement est choisi ++// pour des raisons de compatibilite avec l'implementation precedente. ++// Cette specification pourrait etre modifiee prochainement pour des raisons ++// de performances (pour ne pas avoir a initialiser inutilement les tableaux). ++// DONC: il faut supposer desormais que les nouvelles cases ne sont pas ++// initialisees lors d'un resize. ++// Parametre: first ++// Signification: premiere case a initialiser. ++// Contrainte: (nb==0) ou (0 <= first < memory_size_) ++// Parametre: nb ++// Signification: nombre de cases a initialiser. ++// Contrainte: (nb==0) ou (0 < nb <= memory_size_ - first) ++void ArrOfDouble::fill_default_value(entier first, entier nb) ++{ ++ assert((nb == 0) || (first >= 0 && first < memory_size_)); ++ assert((nb == 0) || (nb > 0 && nb <= memory_size_ - first)); ++ double * data = addr(); ++ assert(data!=0 || nb==0); ++ data += first; ++ if (smart_resize_) ++ { ++ /* ++ // On initialise uniquement en mode debug ++ #ifndef NDEBUG ++ // Ceci represente un NAN. N'importe quelle operation avec ca fait encore un NAN. ++ // Si c'est pas portable, on peut remplacer par DMAX_FLOAT sur les autres machines. ++ static const unsigned long long VALEUR_INVALIDE = ++ 0x7ff7ffffffffffffULL; ++ ++ // On utilise "memcpy" et non "=" car "=" peut provoquer une exception ++ // si la copie passe par le fpu. ++ for (entier i = 0; i < nb; i++) ++ memcpy(data + i, & VALEUR_INVALIDE, sizeof(double)); ++ #endif ++ */ ++ } ++ else ++ { ++ // Comportement pour les tableaux normaux : compatibilite avec la ++ // version precedente : on initialise avec 0. ++ for (entier i = 0; i < nb; i++) ++ data[i] = (double) 0; ++ } ++} ++ ++// **************************************************************** ++// ++// Fonctions non membres de la classe ArrOfDouble ++// ++// **************************************************************** ++ ++// Description: ++// Renvoie 1 si les tableaux "v" et "a" sont de la meme taille ++// et contiennent les memes valeurs au sens strict, sinon renvoie 0. ++// Le test est !(v[i]!=a[i]) ++entier operator==(const ArrOfDouble& v, const ArrOfDouble& a) ++{ ++ const entier n = v.size_array(); ++ const entier na = a.size_array(); ++ entier resu = 1; ++ if (n != na) ++ { ++ resu = 0; ++ } ++ else ++ { ++ const double* vv = v.addr(); ++ const double* av = a.addr(); ++ entier i; ++ for (i = 0; i < n; i++) ++ { ++ if (av[i] != vv[i]) ++ { ++ resu = 0; ++ break; ++ } ++ } ++ } ++ return resu; ++} ++ ++// Description: ++// Retourne l'indice du min ou -1 si le tableau est vide ++// Precondition: ++// Parametre: const ArrOfDouble& dx ++// Signification: tableau a utiliser ++// Retour: int ++// Signification: indice du min ++entier imin_array(const ArrOfDouble& dx) ++{ ++ entier indice_min = -1; ++ const entier size = dx.size_array(); ++ if (size > 0) ++ { ++ indice_min = 0; ++ double valeur_min = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const double val = dx[i]; ++ if(val < valeur_min) ++ { ++ indice_min = i; ++ valeur_min = val; ++ } ++ } ++ } ++ return indice_min; ++} ++ ++// Description: ++// Retourne l'indice du max ou -1 si le tableau est vide ++// Precondition: ++// Parametre: const ArrOfDouble& dx ++// Signification: tableau a utiliser ++// Retour: int ++// Signification: indice du max ++entier imax_array(const ArrOfDouble& dx) ++{ ++ entier indice_max = -1; ++ const entier size = dx.size_array(); ++ if (size > 0) ++ { ++ indice_max = 0; ++ double valeur_max = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const double val = dx[i]; ++ if(val > valeur_max) ++ { ++ indice_max = i; ++ valeur_max = val; ++ } ++ } ++ } ++ return indice_max; ++} ++ ++// Description: ++// Retourne la valeur minimale ++// Precondition: ++// Le tableau doit contenir au moins une valeur ++// Parametre: const ArrOfDouble& dx ++// Signification: tableau a utiliser ++// Retour: double ++// Signification: valeur du min ++double min_array(const ArrOfDouble& dx) ++{ ++ const entier size = dx.size_array(); ++ assert(size > 0); ++ double valeur_min = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const double val = dx[i]; ++ if (val < valeur_min) ++ valeur_min = val; ++ } ++ return valeur_min; ++} ++ ++// Description: ++// Retourne la valeur maximale ++// Precondition: ++// Le tableau doit contenir au moins une valeur ++// Parametre: const ArrOfDouble& dx ++// Signification: tableau a utiliser ++// Retour: double ++// Signification: valeur du max ++double max_array(const ArrOfDouble& dx) ++{ ++ const entier size = dx.size_array(); ++ assert(size > 0); ++ double valeur_max = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const double val = dx[i]; ++ if (val > valeur_max) ++ valeur_max = val; ++ } ++ return valeur_max; ++} ++ ++// Description: ++// Fonction de comparaison utilisee pour trier le tableau ++// dans ArrOfDouble::trier(). Voir man qsort ++static int fonction_compare_arrofdouble_ordonner(const void * data1, const void * data2) ++{ ++ const double x = *(const double*)data1; ++ const double y = *(const double*)data2; ++ if (x < y) ++ return -1; ++ else if (x > y) ++ return 1; ++ else ++ return 0; ++} ++ ++// Description: ++// Tri des valeurs du tableau dans l'ordre croissant. ++// La fonction utilisee est qsort de stdlib (elle est en n*log(n)). ++void ArrOfDouble::ordonne_array() ++{ ++ const entier size = size_array(); ++ if (size > 1) ++ { ++ double * data = addr(); ++ qsort(data, size, sizeof(double), ++ fonction_compare_arrofdouble_ordonner); ++ } ++} ++ ++// Description: ++// Fait pointer le tableau vers les memes donnees qu'un tableau ++// existant. Le tableau sera du meme type que le tableau m ("detache", ++// "normal"). Le tableau m ne doit pas etre de type "ref_data" ++// Les donnes existantes sont perdues si elles ++// ne sont pas referencees ailleurs. ++// Precondition: ++// Parametre: const ArrOfDouble& m ++// Signification: le tableau a referencer (pas de type "ref_data" ++// et different de *this !!!) ++// Retour: ArrOfDouble& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++ArrOfDouble& ArrOfDouble::ref_array(const ArrOfDouble& m) ++{ ++ assert(&m != this); ++ // La condition 'm n'est pas de type "ref_data"' est necessaire pour ++ // attach_array(). ++ detach_array(); ++ attach_array(m); ++ return *this; ++} ++ ++// Description: ++// Fait pointer le tableau vers la zone de memoire "data_". ++// On detache la zone de memoire existante. Le tableau devient ++// de type "ref_data". Attention : ptr doit etre non nul. ++// La taille est initialisee avec size. ++// Cette methode est appelee notamment par DoubleVect::adopter. ++// Parametre: double* ++// Signification: le tableau a recuperer. Si pointeur nul alors size ++// doit etre nulle aussi et le tableau reste detache ++// Parametre: entier size ++// Signification: le nombre d'elements du tableau. ++// Retour: ArrOfDouble& ++// Signification: *this ++ArrOfDouble& ArrOfDouble::ref_data(double* ptr, entier size) ++{ ++ assert(ptr != 0 || size == 0); ++ assert(size >= 0); ++ detach_array(); ++ data_ = ptr; ++ size_array_ = size; ++ return *this; ++} ++ ++// Description: ++// Amene le tableau dans l'etat "detache". C'est a dire: ++// Si le tableau est "detache" : ++// * ne rien faire ++// Si le tableau est "normal" : ++// * decremente le nombre de references a *p ++// * detruit *p si p->ref_count==0 ++// * annule p_, data_ et size_array_ ++// Si le tableau est "ref_data" : ++// * annule data_ et size_array_ ++// Retour: int ++// Signification: 1 si les donnees du tableau ont ete supprimees ++// Precondition: ++// Postcondition: ++// On a p_==0, data_==0 et size_array_==0, memory_size_ = 0 ++// L'attribut smart_resize_ est conserve. ++entier ArrOfDouble::detach_array() ++{ ++ entier retour = 0; ++ if (p_) ++ { ++ // Le tableau est de type "normal" ++ // Si la zone de memoire n'est plus utilisee par personne, ++ // on la detruit. ++ if ((p_->suppr_one_ref()) == 0) ++ { ++ delete p_; ++ retour = 1; ++ } ++ p_ = 0; ++ } ++ data_ = 0; ++ size_array_ = 0; ++ memory_size_ = 0; ++ return retour; ++} ++ ++// Description: ++// Amene le tableau dans l'etat "normal", "detache" ou "ref_array" ++// en associant la meme zone de memoire que le tableau m. ++// Precondition: ++// Le tableau doit etre "detache" ++// Parametre: const ArrOfDouble& m ++// Signification: tableau a utiliser ++// le tableau doit etre different de *this !!! ++// Retour: ++// Signification: ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++// Si m est detache, le tableau reste detache, ++// si m est "ref_array", le tableau devient "ref_array", ++// sinon le tableau est "normal", avec ref_count > 1 ++// Si m est de taille nulle, le tableau reste detache + Warning dans fichier .log ++void ArrOfDouble::attach_array(const ArrOfDouble& m) ++{ ++ // Le tableau doit etre detache ++ assert(data_ == 0 && p_ == 0); ++ // Le tableau doit etre different de *this ++ assert(&m != this); ++ ++ if (m.size_array() > 0) ++ { ++ p_ = m.p_; ++ if (p_) ++ p_->add_one_ref(); ++ data_ = m.data_; ++ size_array_ = m.size_array_; ++ memory_size_ = m.memory_size_; ++ smart_resize_ = m.smart_resize_; ++ } ++ else ++ { ++ // Cas particulier ou on attache un tableau de taille nulle: ++ // en theorie, c'est pareil qu'un tableau de taille non nulle, MAIS ++ // dans les operateurs (ex:Op_Dift_VDF_Face_Axi), une ref est construite ++ // avant que le tableau ne prenne sa taille definitive. Donc, pour ne pas ++ // empecher le resize, il ne faut pas attacher le tableau s'il n'a pas ++ // encore la bonne taille. Solution propre: reecrire les operateurs pour ++ // qu'ils ne prennent pas une ref avant que le tableau ne soit valide ++ // et faire p_ = m.p_ dans tous les cas. ++ } ++} ++ ++// Description: ++// Copie les elements source[first_element_source + i] ++// dans les elements (*this)[first_element_dest + i] pour 0 <= i < nb_elements ++// Les autres elements de (*this) sont inchanges. ++// Precondition: ++// Parametre: const ArrOfDouble& m ++// Signification: le tableau a utiliser, doit etre different de *this ! ++// Parametre: entier nb_elements ++// Signification: nombre d'elements a copier, nb_elements >= -1. ++// Si nb_elements==-1, on copie tout le tableau m. ++// Valeurs par defaut: -1 ++// Parametre: entier first_element_dest ++// Valeurs par defaut: 0 ++// Parametre: entier first_element_source ++// Valeurs par defaut: 0 ++// Retour: ArrOfDouble& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Sort en erreur si la taille du tableau m est plus grande que la ++// taille de tableau this. ++// Effets de bord: ++// Postcondition: ++ArrOfDouble& ArrOfDouble::inject_array(const ArrOfDouble& source, ++ entier nb_elements, ++ entier first_element_dest, ++ entier first_element_source) ++{ ++ assert(&source != this); ++ assert(nb_elements >= -1); ++ assert(first_element_dest >= 0); ++ assert(first_element_source >= 0); ++ ++ if (nb_elements < 0) ++ nb_elements = source.size_array(); ++ ++ assert(first_element_source + nb_elements <= source.size_array()); ++ assert(first_element_dest + nb_elements <= size_array()); ++ ++ if (nb_elements > 0) ++ { ++ double * addr_dest = addr() + first_element_dest; ++ const double * addr_source = source.addr() + first_element_source; ++ // memcpy(addr_dest , addr_source, nb_elements * sizeof(double)); ++ entier i; ++ for (i = 0; i < nb_elements; i++) ++ { ++ addr_dest[i] = addr_source[i]; ++ } ++ } ++ return *this; ++} ++ ++// Description: ++// Retourne le nombre de references des donnees du tableau ++// si le tableau est "normal", -1 s'il est "detache" ou "ref_data" ++// Retour: int ++// Signification: ref_count_ ++entier ArrOfDouble::ref_count() const ++{ ++ if (p_) ++ return p_->ref_count(); ++ else ++ return -1; ++} ++ ++// Description: ++// Addition case a case sur toutes les cases du tableau ++// Precondition: ++// la taille de y doit etre au moins egale a la taille de this ++// Parametre: const ArrOfDouble& y ++// Signification: tableau a ajouter ++// Valeurs par defaut: ++// Contraintes: ++// Acces: ++// Retour: ArrOfDouble& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++ArrOfDouble& ArrOfDouble::operator+=(const ArrOfDouble& y) ++{ ++ assert(size_array()==y.size_array()); ++ double* dx = addr(); ++ const double* dy = y.addr(); ++ const entier n = size_array(); ++ for (entier i=0; i 0); ++ double valeur_max = fabs(dx[0]); ++ for(entier i = 1; i < size; i++) ++ { ++ const double val = fabs(dx[i]); ++ if (val > valeur_max) ++ valeur_max = val; ++ } ++ return valeur_max; ++} ++ ++// Description: ++// muliplie toutes les cases par dy ++// Retour: ArrOfDouble & ++// Signification: *this ++ArrOfDouble& ArrOfDouble::operator*= (const double dy) ++{ ++ double * data = addr(); ++ const entier n = size_array(); ++ for(entier i=0; i < n; i++) ++ data[i] *= dy; ++ return *this; ++} ++ ++ ++// Description: ++// divise toutes les cases par dy ++// Retour: ArrOfDouble & ++// Signification: *this ++ArrOfDouble& ArrOfDouble::operator/= (const double dy) ++{ ++ // En theorie: les deux lignes suivantes sont plus efficaces, mais ++ // cela produit des differences sur certains cas tests ++ // (Hyd_C_VEF_Smago et Lambda_var_VEF_turb). Ca veut dire qu'il y ++ // a un probleme autre part mais pour l'instant on laisse l'ancien ++ // codage. ++ // const double i_dy = 1. / dy; ++ // operator*=(i_dy); ++ ++ double * data = addr(); ++ const entier n = size_array(); ++ for(entier i=0; i < n; i++) ++ data[i] /= dy; ++ ++ return *this; ++} ++ ++DoubleTab::DoubleTab() ++{ ++ // nb_dim_ = 2; ++ dimensions_[0] = 0; ++ dimensions_[1] = 0; ++} ++ ++DoubleTab::DoubleTab(const DoubleTab& tab) : ++ ArrOfDouble(tab) ++{ ++ // nb_dim_ = tab.nb_dim_; ++ dimensions_[0] = tab.dimensions_[0]; ++ dimensions_[1] = tab.dimensions_[1]; ++} ++DoubleTab::DoubleTab(const entier i, const entier j) : ++ ArrOfDouble(i*j) ++{ ++ // nb_dim_ = 2; ++ dimensions_[0] = i; ++ dimensions_[1] = j; ++} ++ ++DoubleTab& DoubleTab::operator=(const DoubleTab& tab) ++{ ++ ArrOfDouble::operator=(tab); ++ // nb_dim_ = tab.nb_dim_; ++ dimensions_[0] = tab.dimensions_[0]; ++ dimensions_[1] = tab.dimensions_[1]; ++ return *this; ++} ++ ++void DoubleTab::reset() ++{ ++ ArrOfDouble::reset(); ++ // nb_dim_ = 2; ++ dimensions_[0] = 0; ++ dimensions_[1] = 0; ++} ++ +diff --git a/databases/readers/Lata/ArrOfDouble.h b/databases/readers/Lata/ArrOfDouble.h +new file mode 100644 +index 0000000..fcc08f1 +--- /dev/null ++++ b/databases/readers/Lata/ArrOfDouble.h +@@ -0,0 +1,353 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++//////////////////////////////////////////////////////////// ++// ++// Warning : DO NOT EDIT ! ++// Please update ArrOf_Scalar_Prototype.h.P ++// and this file will be generated automatically ++// by the script file check.sh ++//////////////////////////////////////////////////////////// ++ ++#ifndef ArrOfDouble_H ++#define ArrOfDouble_H ++ ++#include ++#include ++#include ++ ++#if ! defined(DMAXFLOAT) ++#define DMAXFLOAT 1e40 ++#endif ++ ++class VDoubledata; ++ ++class ArrOfDouble ++{ ++public: ++ // ++ // Destructeur ++ // ++ virtual ~ArrOfDouble(); ++ // ++ // Constructeurs ++ // ++ ArrOfDouble(); ++ ArrOfDouble(entier size); ++ ArrOfDouble(entier size, double initial_value); ++ // Constructeur par copie : deep copy (on duplique les donnees) ++ ArrOfDouble(const ArrOfDouble& ); ++ // ++ // Methodes de construction tardive (on cree un tableau vide avec ArrOfDouble() ++ // puis on appelle ces methodes pour modifier les caracteristiques du tableau : ++ // ++ // Change le nombre d'elements du tableau ++ inline ArrOfDouble& resize_array(entier new_size); ++ ++ // Methodes de gestion de l'allocation memoire: ++ // Assigne une valeur au drapeau "smart_resize" ++ // (reallocation uniquement si la taille augmente) ++ void set_smart_resize(entier flag); ++ // Gestion du type de memoire alouee (standard ou pool de memoire Trio-U) ++ enum Storage { STANDARD, TEMP_STORAGE, SIMD_ALIGNED }; ++ void set_mem_storage(const Storage storage); ++ Storage get_mem_storage() const; ++ ++ // Construction de tableaux qui pointent vers des donnees existantes ++ // !!! Utiliser ref_data avec precaution (attention a size_array_) ++ ArrOfDouble& ref_data(double* ptr, entier size); ++ ArrOfDouble& ref_array(const ArrOfDouble&); ++ // Operateur copie ++ ArrOfDouble& operator=(const ArrOfDouble&); ++ // Remise du tableau dans l'etat initial (obtenu par le constructeur par defaut) ++ virtual void reset(); ++ ++ // ++ // Methodes d'acces aux donnees et aux caracteristiques du tableau ++ // ++ // Remplit le tableau avec la valeur en parametre ++ ArrOfDouble& operator=(double valeur); ++ ++ inline double& operator[](entier i); ++ inline const double& operator[](entier i) const; ++ ++ // Ces methodes renvoient un pointeur vers le premier element du tableau. ++ const double * addr() const; ++ double * addr(); ++ // Renvoie le nombre d'elements du tableau (et non la taille allouee) ++ inline entier size_array() const; ++ // Renvoie le nombre de tableaux qui pointent vers la stucture "*p_" ++ entier ref_count() const; ++ // Ajoute une case en fin de tableau et y stocke la "valeur" ++ inline void append_array(double valeur); ++ ++ // ++ // Operateurs divers ++ // ++ ArrOfDouble& operator+=(const ArrOfDouble&); ++ ArrOfDouble& operator+=(const double); ++ ArrOfDouble& operator-=(const ArrOfDouble&); ++ ArrOfDouble& operator-=(const double); ++ ArrOfDouble& inject_array(const ArrOfDouble& source, ++ entier nb_elements = -1, ++ entier first_element_dest = 0, ++ entier first_element_source = 0); ++ ArrOfDouble& copy_array(const ArrOfDouble&); ++ ++ ArrOfDouble& operator*= (const double) ; ++ ArrOfDouble& operator/= (const double) ; ++ ++ void ordonne_array(); ++ ++protected: ++ // ++ // Methodes accessibles depuis les descendants de ArrOfDouble ++ // ++ void attach_array(const ArrOfDouble&); ++ entier detach_array(); ++ void fill_default_value(entier first, entier nb); ++private: ++ // B. Mathieu 22/06/2004 : je mets ces membres "private" pour forcer ++ // le passage par les accesseurs dans les classes derivees, au cas ou ++ // on voudrait modifier l'implementation. ++ ++ // Zone de memoire contenant les valeurs du tableau. ++ // Pointeur nul => le tableau est "detache" ou "ref_data" ++ // Pointeur non nul => le tableau est "normal" ++ VDoubledata* p_; ++ ++ // Pointeur vers le premier element du tableau (egal a p_->data si p_!=0) ++ // Pointeur nul => le tableau est "detache". ++ // Pointeur non nul => le tableau est "normal" ou "ref_data" ++ double* data_; ++ ++ // Nombre d'elements du tableau (inferieur ou egal a memory_size_). ++ // Si le tableau est "detache", alors size_array_=0 ++ entier size_array_; ++ // Taille memoire reellement allouee pour le tableau ++ // (pour le mecanisme smart_resize_). memory_size_ est nul ++ // si le tableau est de type "ref_data". Sinon memory_size_ ++ // est egal a p_->size_. ++ entier memory_size_; ++ ++ // Drapeau indiquant si on applique une strategie d'allocation ++ // preventive (la memoire alouee augmente d'un facteur constant ++ // si la taille devient insuffisante). ++ // Si smart_resize_ == 0, alors on a toujours p_->size_ == size ++ entier smart_resize_; ++ ++ // Drapeau indiquant si l'allocation memoire a lieu avec un new classique ++ // ou dans le pool de memoire temporaire de Trio ++ Storage storage_type_; ++ ++ // Partie non inline de resize_array(): ++ // Declaration des constantes pour les options de memory_resize ++ static const entier COPY_OLD; ++ static const entier INITIALIZE_NEW; ++ void memory_resize(entier new_size, entier options); ++}; ++ ++#define MAXDIMDoubleTab 2 ++ ++class DoubleTab : public ArrOfDouble ++{ ++public: ++ DoubleTab(); ++ DoubleTab(const DoubleTab&); ++ DoubleTab(const entier i, const entier j); ++ DoubleTab& operator=(const DoubleTab&); ++ void reset(); ++ ++ inline double& operator()(entier i, entier j); ++ inline double operator()(entier i, entier j) const; ++ ++ inline entier resize(entier i, entier j); ++ inline entier dimension(entier i) const; ++ inline entier dimension_tot(entier i) const; ++ ++protected: ++ // In order to mimic TRUST behavior, operator[] is forbidden ++ // for 2 dimensionnal matrices, you must cast to ArrOf to use it.. ++ double& operator[](entier i); ++ const double& operator[](entier i) const; ++ ++private: ++ // entier nb_dim_; ++ entier dimensions_[MAXDIMDoubleTab]; ++}; ++ ++inline double& DoubleTab::operator()(entier i, entier j) ++{ ++ // assert(nb_dim_ == 2); ++ assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]); ++ const entier n = i * dimensions_[1] + j; ++ double& x = ArrOfDouble::operator[] (n); ++ return x; ++} ++ ++inline double DoubleTab::operator()(entier i, entier j) const ++{ ++ // assert(nb_dim_ == 2); ++ assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]); ++ const entier n = i * dimensions_[1] + j; ++ double x = ArrOfDouble::operator[] (n); ++ return x; ++} ++ ++inline entier DoubleTab::resize(entier i, entier j) ++{ ++ assert(i >= 0 && j >= 0); ++ // nb_dim_ = 2; ++ dimensions_[0] = i; ++ dimensions_[1] = j; ++ ArrOfDouble::resize_array(i * j); ++ return i*j; ++} ++ ++inline entier DoubleTab::dimension(entier i) const ++{ ++ assert(i >= 0 && i < 2); ++ return dimensions_[i]; ++} ++ ++// Description: renvoie la meme valeur que dimension. ++inline entier DoubleTab::dimension_tot(entier i) const ++{ ++ return dimension(i); ++} ++ ++// ++// Declarations des fonctions non membres de la classe ArrOfDouble ++// ++entier operator==(const ArrOfDouble& x, const ArrOfDouble& y) ; ++entier imin_array(const ArrOfDouble&) ; ++entier imax_array(const ArrOfDouble&) ; ++double min_array(const ArrOfDouble&) ; ++double max_array(const ArrOfDouble&) ; ++ ++double max_abs_array(const ArrOfDouble&) ; ++ ++// ****************************************************************** ++// FONCTIONS MEMBRES DE ArrOfDouble ++// ****************************************************************** ++ ++// Description : ++// Change le nombre d'elements du tableau. Cette fonction est inline ++// car elle doit etre tres rapide dans le cas ou smart_resize_==1 ++// (utilisation frequente de resize_array()) ++// Si smart_resize est non nul : ++// Si la nouvelle taille est inferieure ou egale a la taille ++// alouee (p->get_size()) on ne realloue pas de memoire ++// sinon, on realloue et on copie les donnees existantes. ++// Astuce pour ne pas copier les anciennes donnees: ++// resize(0); resize(n); ++// Si smart_resize est nul, on realloue une nouvelle zone memoire ++// uniquement si la nouvelle taille est differente de l'ancienne. ++// Precondition : ++// Si "new_size" est egal a la taille du tableau, aucune condition. ++// Sinon, le tableau doit etre soit detache, soit normal (pas de type "ref_data") ++// et ref_count doit etre egal a 1 (pas d'autre reference au tableau). ++// ++inline ArrOfDouble& ArrOfDouble::resize_array(entier new_size) ++{ ++ assert(new_size >= 0); ++ // Soit le tableau est detache (data_==0), soit il est normal (p_!=0) ++ // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau, ++ // ou alors la taille ne doit pas changer. ++ assert(new_size == size_array_ || data_ == 0 || (p_ != 0 && ref_count() == 1)); ++ ++ if ((smart_resize_ == 0) || (new_size > memory_size_)) ++ memory_resize(new_size, COPY_OLD + INITIALIZE_NEW); ++ size_array_ = new_size; ++ return *this; ++} ++ ++// Description: ++// operateur [] retourne le ieme element du tableau ++// Precondition: ++// Parametre: entier i ++// Signification: indice dans l'intervalle 0 <= i < size_array() ++// Exception: ++// assert si la valeur sort de l'intervalle : [ -DMAXFLOAT,DMAXFLOAT ] ++// assert si i n'est pas dans l'intervalle ++inline double& ArrOfDouble::operator[](entier i) ++{ ++ assert(i >= 0 && i < size_array_); ++ assert((smart_resize_==1)|| (data_[i] > -DMAXFLOAT && data_[i] < DMAXFLOAT)); ++ return data_[i]; ++} ++ ++// Description: ++// operateur [] retourne le ieme element du tableau ++// Precondition: ++// Parametre: entier i ++// Signification: indice dans l'intervalle 0 <= i < size_array() ++// Exception: ++// assert si la valeur sort de l'intervalle : [ -DMAXFLOAT,DMAXFLOAT ] ++// assert si i n'est pas dans l'intervalle ++inline const double& ArrOfDouble::operator[](entier i) const ++{ ++ assert(i >= 0 && i < size_array_); ++ assert(data_[i] > -DMAXFLOAT && data_[i] < DMAXFLOAT); ++ return data_[i]; ++} ++ ++// Description: ++// Renvoie la taille du tableau (nombre d'elements declares ++// a la construction ou a resize_array()). ++// C'est le nombre d'elements accessibles a operator[] ++// Retour: entier ++inline entier ArrOfDouble::size_array() const ++{ ++ return size_array_; ++} ++ ++// Description: ++// Ajoute une case en fin de tableau et y stocke la "valeur" ++// Precondition: ++// Tableau doit etre de type "smart_resize" (sinon, ecroulement ++// des performances). De plus, le tableau ne doit pas etre "ref_data", ++// et il ne doit pas y avoir plus d'une reference a la zone de ++// memoire pointee (meme precondition que resize_array()) ++inline void ArrOfDouble::append_array(double valeur) ++{ ++ assert(smart_resize_); ++ // Soit le tableau est detache (data_==0), soit il est normal (p_!=0) ++ // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau. ++ assert(data_ == 0 || (p_ != 0 && ref_count() == 1)); ++ ++ if (size_array_+1 > memory_size_) ++ memory_resize(size_array_+1, COPY_OLD); ++ data_[size_array_] = valeur; ++ size_array_++; ++} ++ ++// ArrOfDouble_H ++#endif ++ +diff --git a/databases/readers/Lata/ArrOfFloat.C b/databases/readers/Lata/ArrOfFloat.C +new file mode 100644 +index 0000000..dd59a24 +--- /dev/null ++++ b/databases/readers/Lata/ArrOfFloat.C +@@ -0,0 +1,1185 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++//////////////////////////////////////////////////////////// ++// ++// Warning : DO NOT EDIT ! ++// Please update ArrOf_Scalar_Prototype.cpp.h ++// and this file will be generated automatically ++// by the script file check.sh ++//////////////////////////////////////////////////////////// ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "simd_interface.h" ++ ++using namespace std; ++ ++// ****************************************************************** ++// ++// Implementation des methodes de VFloatdata ++// ++// ****************************************************************** ++//////////////////////////////////////////////////////////////////// ++// .NOM ArrOfFloat ++// .ENTETE TRUST Math ++// .LIBRAIRIE libtmath ++// .FILE ArrOfFloat.h ++// .FILE ArrOfFloat.cpp ++// ++// .DESCRIPTION ++// VFloatdata alloue une zone de memoire de la taille specifiee au ++// constructeur, et libere la zone de memoire a la destruction. ++// ++// "ref_count" compte le nombre de pointeurs qui font reference a "this". ++// (permet au dernier utilisateur de l'objet de le detruire), voir ++// ArrOfFloat. ++// ++// .SECTION voir aussi ++// .CONTRAINTES ++// .INVARIANTS ++// .HTML ++// .EPS ++/////////////////////////////////////////////////////////////////// ++ ++class VFloatdata ++{ ++public: ++ VFloatdata(entier size, ArrOfFloat::Storage storage); ++ ~VFloatdata(); ++ entier add_one_ref(); ++ entier suppr_one_ref(); ++ float * get_data(); ++ const float * get_data() const; ++ inline entier ref_count() const; ++ inline entier get_size() const; ++private: ++ // Le constructeur par copie et l'operateur= sont interdits. ++ VFloatdata(const VFloatdata& v); ++ VFloatdata& operator=(const VFloatdata& v); ++ ++ // "data" est un pointeur sur une zone de memoire de taille ++ // sz * sizeof(float), allouee par le ++ // constructeur et liberee par le destructeur. ++ // Ce pointeur n'est jamais nul meme si size_==0 ++ float * data_; ++ // Compteur incremente par add_one_ref et decremente par suppr_one_ref. ++ // Contient le nombre d'objets ArrOfFloat dont le membre "p" pointe ++ // vers "this". On a ref_count_ >= 0. ++ entier ref_count_; ++ // "sz" est la taille du tableau "data_" alloue ++ // On a sz >= 0. ++ entier size_; ++ ArrOfFloat::Storage storage_; ++}; ++ ++ ++// Description: ++// Construit un VFloatdata de taille size >= 0 ++// Parametre: entier s ++// Signification: taille du VFloatdata, il faut size >= 0 ++// Parametre: Storage storage ++// Signification: indique si la memoire doit etre allouee ++// avec "new" ou avec "simd_malloc" ++// Valeurs par defaut: STANDARD (allocation avec "new") ++// Postcondition: ++// data_ n'est jamais nul, meme si size==0 ++VFloatdata::VFloatdata(entier size, ArrOfFloat::Storage storage) ++{ ++ if (size == 0) ++ storage = ArrOfFloat::STANDARD; ++ ++ switch (storage) ++ { ++ case ArrOfFloat::STANDARD: ++ { ++#ifdef _EXCEPTION_ ++ // Allocation de la memoire sur le tas ++ try ++ { ++ data_ = new float[size]; ++ } ++ catch(...) ++ { ++ Cerr << "impossible d'allouer " << size << " float " << finl; ++ throw; ++ } ++#else ++ data_ = new float[size]; ++ if(!data_) ++ { ++ Cerr << "impossible d'allouer " << size << "float " << finl; ++ throw ; ++ } ++#endif ++ break; ++ } ++ case ArrOfFloat::SIMD_ALIGNED: ++ { ++#ifdef SIMD_TOOLS_H ++ data_ = (float*) simd_malloc (sizeof(float) * size); ++#else ++ Cerr<<"unable to allocate simd_aligned, version compiled without simd "< 0 ++// Retour: int ++// Signification: ref_count ++inline entier VFloatdata::suppr_one_ref() ++{ ++ assert(ref_count_ > 0); ++ return (--ref_count_); ++} ++ ++// Description: renvoie data_ ++inline float * VFloatdata::get_data() ++{ ++ return data_; ++} ++ ++// Description: renvoie data_ ++inline const float * VFloatdata::get_data() const ++{ ++ return data_; ++} ++ ++// Description: Constructeur par copie. Interdit : genere une erreur ! ++VFloatdata::VFloatdata(const VFloatdata& v) ++{ ++ Cerr << "Erreur dans VFloatdata::VFloatdata(const VFloatdata & v)" << finl; ++ throw; ++} ++ ++// Description: Operateur= interdit. Genere une erreur ! ++VFloatdata& VFloatdata::operator=(const VFloatdata& v) ++{ ++ Cerr << "Erreur dans VFloatdata::operator=(const VFloatdata & v)" << finl; ++ throw; ++ return *this; ++} ++ ++// ****************************************************************** ++// ++// Implementation des methodes de ArrOfFloat ++// ++// ****************************************************************** ++ ++ ++// Definition des constantes pour les options de memory_resize ++const entier ArrOfFloat::COPY_OLD = 1; ++const entier ArrOfFloat::INITIALIZE_NEW = 2; ++ ++// Description: ++// Destructeur : appelle detach_array() ++ArrOfFloat::~ArrOfFloat() ++{ ++ detach_array(); ++ size_array_ = -1; // Paranoia: si size_array_==-1, c'est un zombie ++} ++ ++// Description: ++// Constructeur par defaut: cree un tableau "detache", ++// soit p_==0, data_==0, size_array_==0, smart_resize_==0 ++ArrOfFloat::ArrOfFloat() : ++ p_(0), ++ data_(0), ++ size_array_(0), ++ memory_size_(0), ++ smart_resize_(0), ++ storage_type_(STANDARD) ++{ ++} ++ ++// Description: ++// Cree un tableau de taille n avec allocation standard ++// (voir set_mem_storage). ++// Valeur de remplissage par defaut: voir fill_default_value ++// Precondition: ++// Parametre: entier n ++// Signification: taille du tableau ++ArrOfFloat::ArrOfFloat(entier n) : ++ p_(new VFloatdata(n, STANDARD)), ++ data_(p_->get_data()), ++ size_array_(n), ++ memory_size_(n), ++ smart_resize_(0), ++ storage_type_(STANDARD) ++{ ++ if (n > 0) ++ fill_default_value(0, n); ++} ++ ++// Description: ++// Cree un tableau de taille n ++// toutes les cases sont initialisees a x ++// Precondition: ++// Parametre: entier n ++// Signification: taille du tableau ++// Parametre: float x ++// Signification: valeur pour initialiser le tableau ++ArrOfFloat::ArrOfFloat(entier n, float x) : ++ p_(new VFloatdata(n, STANDARD)), ++ data_(p_->get_data()), ++ size_array_(n), ++ memory_size_(n), ++ smart_resize_(0), ++ storage_type_(STANDARD) ++{ ++ *this = x; ++} ++ ++// Description: ++// Constructeur par copie. On alloue une nouvelle zone de memoire ++// et on copie le contenu du tableau. L'attribut smart_resize_ est ++// copie aussi. ++// Si le tableau A est de taille nulle, on cree un tableau "detache", ++// sinon on cree un tableau "normal". ++// Parametre: const ArrOfFloat& A ++// Signification: le tableau a copier ++ArrOfFloat::ArrOfFloat(const ArrOfFloat& A) ++{ ++ const entier size = A.size_array(); ++ if (size > 0) ++ { ++ // Creation d'un tableau "normal" ++ storage_type_ = STANDARD; ++ p_ = new VFloatdata(size, STANDARD); ++ data_ = p_->get_data(); ++ size_array_ = size; ++ memory_size_ = size; ++ smart_resize_ = A.smart_resize_; ++ inject_array(A); ++ } ++ else ++ { ++ // Creation d'un tableau "detache" ++ p_ = 0; ++ data_ = 0; ++ size_array_ = 0; ++ memory_size_ = 0; ++ smart_resize_ = 0; ++ storage_type_ = STANDARD; ++ } ++} ++ ++// Description: ++// Change le mode d'allocation memoire lors des resize ++// (voir VFloatdata et Float_ptr_trav) ++// Exemple pour creer un tableau avec allocation temporaire: ++// DoubleTab tab; // Creation d'un tableau vide ++// tab.set_mem_storage(TEMP_STORAGE); // Changement de mode d'allocation ++// tab.resize(n); // Allocation memoire ++void ArrOfFloat::set_mem_storage(const Storage storage) ++{ ++ storage_type_ = storage; ++} ++ ++// Description: ++// Renvoie le mode d'allocation du tableau (qui sera utilise ++// lors du prochain resize si changement de taille). ++// (voir VFloatdata et Float_ptr_trav) ++enum ArrOfFloat::Storage ArrOfFloat::get_mem_storage() const ++{ ++ return storage_type_; ++} ++ ++// Description: ++// Change le mode l'allocation memoire: reallocation d'un tableau ++// a chaque changement de taille (flag = 0) ou reallocation ++// uniquement si la taille augmente et par doublement de la taille ++// du tableau (flag = 1). ++void ArrOfFloat::set_smart_resize(entier flag) ++{ ++ assert(flag == 0 || flag == 1); ++ smart_resize_ = flag; ++} ++ ++// Description: ++// Remet le tableau dans l'etat obtenu avec le constructeur par defaut ++// (libere la memoire mais conserve le mode d'allocation memoire actuel) ++void ArrOfFloat::reset() ++{ ++ detach_array(); ++} ++ ++// Description: ++// Copie les donnees du tableau m. ++// Si "m" n'a pas la meme taille que "*this", on fait un resize_array. ++// Ensuite, on copie les valeurs de "m" dans "*this". ++// Le type de tableau (methode d'allocation) n'est pas copie. ++// Precondition: ++// Si le tableau n'a pas la meme taille que "m", alors *this doit ++// etre "resizable" (ne pas etre de type "ref_data" et "ref_count == 1") ++// Parametre: const ArrOfFloat& m ++// Signification: la tableau a copier ++// Retour: ArrOfFloat& ++// Signification: *this ++ArrOfFloat& ArrOfFloat::operator=(const ArrOfFloat& m) ++{ ++ if (&m != this) ++ { ++ const entier new_size = m.size_array(); ++ // Le code suivant est quasiment une copie de ArrOfFloat::resize() ++ // SAUF: memory_resize est appele avec NO_INITIALIZE (la zone de memoire ++ // n'est pas initialisee) ++ if (new_size != size_array()) ++ { ++ if ((smart_resize_ == 0) || (new_size > memory_size_)) ++ memory_resize(new_size, 0); // Pas d'initialisation ++ size_array_ = new_size; ++ } ++ inject_array(m); ++ } ++ return *this; ++} ++ ++ ++// Description: ++// x est affecte a toutes les cases ++// Precondition: ++// Parametre: float x ++// Signification: la valeur a affecter a toutes les cases du tableau ++// Valeurs par defaut: ++// Contraintes: ++// Acces: ++// Retour: ArrOfFloat& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++ArrOfFloat& ArrOfFloat::operator=(float x) ++{ ++ const entier n = size_array(); ++ float *data = addr(); ++ for (entier i = 0; i < n; i++) ++ { ++ data[i] = x; ++ } ++ return *this; ++} ++ ++// Description: appelle operator=(a) ++ArrOfFloat& ArrOfFloat::copy_array(const ArrOfFloat& a) ++{ ++ operator=(a); ++ return *this; ++} ++ ++// Description: ++// Si besoin, alloue une nouvelle zone de memoire, ++// copie les donnees et efface l'ancienne zone de memoire. ++// Attention, on suppose que cette methode est appelee par ++// resize_array(). ++// Attention: si ref_count_>1, l'appel a resize_array() est ++// autorise uniquement si la nouvelle taille est identique ++// a la precedente. ++// Precondition: ++// Le tableau doit etre de type "detache" ou "normal" avec ++// ref_count==1, et il faut new_size >= 0 ++// On suppose que size_array contient encore le nombre d'elements ++// valides avant changement de taille. ++// Parametre: new_size ++// Signification: nouvelle taille demandee pour le tableau. ++// Parametre: options ++// Signification: COPY_OLD => on recopie les anciennes donnees dans le nouveau ++// tableau (jusqu'au max de l'ancienne et de la nouvelle taille). ++// INITIALIZE_NEW => initialisation des cases non copiees ++// Postcondition: ++// p_ et data_ sont mis a jour, mais pas size_array_ !!! ++// (on suppose que c'est fait dans resize_array()). ++// Si la nouvelle taille est nulle, on detache le tableau. ++void ArrOfFloat::memory_resize(entier new_size, entier options) ++{ ++ assert(new_size >= 0); ++ ++ // Occupation memoire de l'ancien tableau: ++ entier old_mem_size = 0; ++ if (p_) ++ old_mem_size = p_->get_size(); ++ ++ // Occupation memoire du nouveau tableau : ++ // Si smart_resize, on prend au moins deux fois la taille ++ // precedente, ou new_size ++ entier new_mem_size = new_size; ++ if (smart_resize_ && (old_mem_size * 2 > new_size)) ++ new_mem_size = old_mem_size * 2; ++ ++ if (new_mem_size != old_mem_size) ++ { ++ // detach_array() efface le contenu de size_array_. On le met de cote: ++ const entier old_size_array = size_array_; ++ // On va reellement changer l'adresse du tableau. ++ // Il ne faut pas qu'il existe d'autre reference a ce tableau. ++ assert(data_ == 0 || (p_ != 0 && ref_count() == 1)); ++ if (new_mem_size == 0) ++ { ++ // La nouvelle taille est nulle, on cree un tableau "detache" ++ detach_array(); ++ } ++ else ++ { ++ // Allocation d'une nouvelle zone ++ VFloatdata * new_p = new VFloatdata(new_mem_size, storage_type_); ++ float * new_data = new_p->get_data(); ++ // Raccourci si le tableau etait "detache", inutile de copier ++ // les anciennes donnees. On copie si COPY_OLD est demande ++ entier copy_size = 0; ++ if (data_ != 0) ++ { ++ // Calcul du nombre d'elements a copier vers la nouvelle ++ // zone de memoire : c'est le min de l'ancienne et de ++ // la nouvelle taille. ++ if (options & COPY_OLD) ++ { ++ copy_size = size_array_; ++ if (new_size < copy_size) ++ copy_size = new_size; ++ // Copie des valeurs dans le nouveau tableau ++ for (entier i = 0; i < copy_size; i++) ++ new_data[i] = data_[i]; ++ } ++ // Destruction de l'ancienne zone (si plus aucune reference) ++ detach_array(); ++ } ++ // On attache la nouvelle zone de memoire ++ p_ = new_p; ++ data_ = new_data; ++ memory_size_ = new_mem_size; ++ // Initialisation des cases supplementaires avec une valeur par defaut ++ if (options & INITIALIZE_NEW) ++ fill_default_value(copy_size, new_mem_size - copy_size); ++ // Restaure l'ancienne valeur de size_array_ ++ size_array_ = old_size_array; ++ } ++ } ++} ++ ++// Description: ++// Remplit "nb" cases consecutives du tableau a partir de la case "first" ++// avec une valeur par defaut. ++// Cette fonction est appelee lors d'un resize pour initialiser les ++// cases nouvellement creees. ++// Le comportement depend actuellement du type de tableau : ++// * Tableau de type "smart_resize": ++// * en mode debug (macro NDEBUG non definie) le tableau est initialise ++// avec une valeur invalide. ++// * en optimise, le tableau n'est pas initialise ++// * Tableau normal : ++// Le tableau est initialise avec la valeur 0. Ce comportement est choisi ++// pour des raisons de compatibilite avec l'implementation precedente. ++// Cette specification pourrait etre modifiee prochainement pour des raisons ++// de performances (pour ne pas avoir a initialiser inutilement les tableaux). ++// DONC: il faut supposer desormais que les nouvelles cases ne sont pas ++// initialisees lors d'un resize. ++// Parametre: first ++// Signification: premiere case a initialiser. ++// Contrainte: (nb==0) ou (0 <= first < memory_size_) ++// Parametre: nb ++// Signification: nombre de cases a initialiser. ++// Contrainte: (nb==0) ou (0 < nb <= memory_size_ - first) ++void ArrOfFloat::fill_default_value(entier first, entier nb) ++{ ++ assert((nb == 0) || (first >= 0 && first < memory_size_)); ++ assert((nb == 0) || (nb > 0 && nb <= memory_size_ - first)); ++ float * data = addr(); ++ assert(data!=0 || nb==0); ++ data += first; ++ if (smart_resize_) ++ { ++ /* ++ // On initialise uniquement en mode debug ++ #ifndef NDEBUG ++ // Ceci represente un NAN. N'importe quelle operation avec ca fait encore un NAN. ++ // Si c'est pas portable, on peut remplacer par DMAX_FLOAT sur les autres machines. ++ static const unsigned long long VALEUR_INVALIDE = ++ 0x7ff7ffffffffffffULL; ++ ++ // On utilise "memcpy" et non "=" car "=" peut provoquer une exception ++ // si la copie passe par le fpu. ++ for (entier i = 0; i < nb; i++) ++ memcpy(data + i, & VALEUR_INVALIDE, sizeof(float)); ++ #endif ++ */ ++ } ++ else ++ { ++ // Comportement pour les tableaux normaux : compatibilite avec la ++ // version precedente : on initialise avec 0. ++ for (entier i = 0; i < nb; i++) ++ data[i] = (float) 0; ++ } ++} ++ ++// **************************************************************** ++// ++// Fonctions non membres de la classe ArrOfFloat ++// ++// **************************************************************** ++ ++// Description: ++// Renvoie 1 si les tableaux "v" et "a" sont de la meme taille ++// et contiennent les memes valeurs au sens strict, sinon renvoie 0. ++// Le test est !(v[i]!=a[i]) ++entier operator==(const ArrOfFloat& v, const ArrOfFloat& a) ++{ ++ const entier n = v.size_array(); ++ const entier na = a.size_array(); ++ entier resu = 1; ++ if (n != na) ++ { ++ resu = 0; ++ } ++ else ++ { ++ const float* vv = v.addr(); ++ const float* av = a.addr(); ++ entier i; ++ for (i = 0; i < n; i++) ++ { ++ if (av[i] != vv[i]) ++ { ++ resu = 0; ++ break; ++ } ++ } ++ } ++ return resu; ++} ++ ++// Description: ++// Retourne l'indice du min ou -1 si le tableau est vide ++// Precondition: ++// Parametre: const ArrOfFloat& dx ++// Signification: tableau a utiliser ++// Retour: int ++// Signification: indice du min ++entier imin_array(const ArrOfFloat& dx) ++{ ++ entier indice_min = -1; ++ const entier size = dx.size_array(); ++ if (size > 0) ++ { ++ indice_min = 0; ++ float valeur_min = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const float val = dx[i]; ++ if(val < valeur_min) ++ { ++ indice_min = i; ++ valeur_min = val; ++ } ++ } ++ } ++ return indice_min; ++} ++ ++// Description: ++// Retourne l'indice du max ou -1 si le tableau est vide ++// Precondition: ++// Parametre: const ArrOfFloat& dx ++// Signification: tableau a utiliser ++// Retour: int ++// Signification: indice du max ++entier imax_array(const ArrOfFloat& dx) ++{ ++ entier indice_max = -1; ++ const entier size = dx.size_array(); ++ if (size > 0) ++ { ++ indice_max = 0; ++ float valeur_max = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const float val = dx[i]; ++ if(val > valeur_max) ++ { ++ indice_max = i; ++ valeur_max = val; ++ } ++ } ++ } ++ return indice_max; ++} ++ ++// Description: ++// Retourne la valeur minimale ++// Precondition: ++// Le tableau doit contenir au moins une valeur ++// Parametre: const ArrOfFloat& dx ++// Signification: tableau a utiliser ++// Retour: float ++// Signification: valeur du min ++float min_array(const ArrOfFloat& dx) ++{ ++ const entier size = dx.size_array(); ++ assert(size > 0); ++ float valeur_min = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const float val = dx[i]; ++ if (val < valeur_min) ++ valeur_min = val; ++ } ++ return valeur_min; ++} ++ ++// Description: ++// Retourne la valeur maximale ++// Precondition: ++// Le tableau doit contenir au moins une valeur ++// Parametre: const ArrOfFloat& dx ++// Signification: tableau a utiliser ++// Retour: float ++// Signification: valeur du max ++float max_array(const ArrOfFloat& dx) ++{ ++ const entier size = dx.size_array(); ++ assert(size > 0); ++ float valeur_max = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const float val = dx[i]; ++ if (val > valeur_max) ++ valeur_max = val; ++ } ++ return valeur_max; ++} ++ ++// Description: ++// Fonction de comparaison utilisee pour trier le tableau ++// dans ArrOfFloat::trier(). Voir man qsort ++static int fonction_compare_arroffloat_ordonner(const void * data1, const void * data2) ++{ ++ const float x = *(const float*)data1; ++ const float y = *(const float*)data2; ++ if (x < y) ++ return -1; ++ else if (x > y) ++ return 1; ++ else ++ return 0; ++} ++ ++// Description: ++// Tri des valeurs du tableau dans l'ordre croissant. ++// La fonction utilisee est qsort de stdlib (elle est en n*log(n)). ++void ArrOfFloat::ordonne_array() ++{ ++ const entier size = size_array(); ++ if (size > 1) ++ { ++ float * data = addr(); ++ qsort(data, size, sizeof(float), ++ fonction_compare_arroffloat_ordonner); ++ } ++} ++ ++// Description: ++// Fait pointer le tableau vers les memes donnees qu'un tableau ++// existant. Le tableau sera du meme type que le tableau m ("detache", ++// "normal"). Le tableau m ne doit pas etre de type "ref_data" ++// Les donnes existantes sont perdues si elles ++// ne sont pas referencees ailleurs. ++// Precondition: ++// Parametre: const ArrOfFloat& m ++// Signification: le tableau a referencer (pas de type "ref_data" ++// et different de *this !!!) ++// Retour: ArrOfFloat& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++ArrOfFloat& ArrOfFloat::ref_array(const ArrOfFloat& m) ++{ ++ assert(&m != this); ++ // La condition 'm n'est pas de type "ref_data"' est necessaire pour ++ // attach_array(). ++ detach_array(); ++ attach_array(m); ++ return *this; ++} ++ ++// Description: ++// Fait pointer le tableau vers la zone de memoire "data_". ++// On detache la zone de memoire existante. Le tableau devient ++// de type "ref_data". Attention : ptr doit etre non nul. ++// La taille est initialisee avec size. ++// Cette methode est appelee notamment par FloatVect::adopter. ++// Parametre: float* ++// Signification: le tableau a recuperer. Si pointeur nul alors size ++// doit etre nulle aussi et le tableau reste detache ++// Parametre: entier size ++// Signification: le nombre d'elements du tableau. ++// Retour: ArrOfFloat& ++// Signification: *this ++ArrOfFloat& ArrOfFloat::ref_data(float* ptr, entier size) ++{ ++ assert(ptr != 0 || size == 0); ++ assert(size >= 0); ++ detach_array(); ++ data_ = ptr; ++ size_array_ = size; ++ return *this; ++} ++ ++// Description: ++// Amene le tableau dans l'etat "detache". C'est a dire: ++// Si le tableau est "detache" : ++// * ne rien faire ++// Si le tableau est "normal" : ++// * decremente le nombre de references a *p ++// * detruit *p si p->ref_count==0 ++// * annule p_, data_ et size_array_ ++// Si le tableau est "ref_data" : ++// * annule data_ et size_array_ ++// Retour: int ++// Signification: 1 si les donnees du tableau ont ete supprimees ++// Precondition: ++// Postcondition: ++// On a p_==0, data_==0 et size_array_==0, memory_size_ = 0 ++// L'attribut smart_resize_ est conserve. ++entier ArrOfFloat::detach_array() ++{ ++ entier retour = 0; ++ if (p_) ++ { ++ // Le tableau est de type "normal" ++ // Si la zone de memoire n'est plus utilisee par personne, ++ // on la detruit. ++ if ((p_->suppr_one_ref()) == 0) ++ { ++ delete p_; ++ retour = 1; ++ } ++ p_ = 0; ++ } ++ data_ = 0; ++ size_array_ = 0; ++ memory_size_ = 0; ++ return retour; ++} ++ ++// Description: ++// Amene le tableau dans l'etat "normal", "detache" ou "ref_array" ++// en associant la meme zone de memoire que le tableau m. ++// Precondition: ++// Le tableau doit etre "detache" ++// Parametre: const ArrOfFloat& m ++// Signification: tableau a utiliser ++// le tableau doit etre different de *this !!! ++// Retour: ++// Signification: ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++// Si m est detache, le tableau reste detache, ++// si m est "ref_array", le tableau devient "ref_array", ++// sinon le tableau est "normal", avec ref_count > 1 ++// Si m est de taille nulle, le tableau reste detache + Warning dans fichier .log ++void ArrOfFloat::attach_array(const ArrOfFloat& m) ++{ ++ // Le tableau doit etre detache ++ assert(data_ == 0 && p_ == 0); ++ // Le tableau doit etre different de *this ++ assert(&m != this); ++ ++ if (m.size_array() > 0) ++ { ++ p_ = m.p_; ++ if (p_) ++ p_->add_one_ref(); ++ data_ = m.data_; ++ size_array_ = m.size_array_; ++ memory_size_ = m.memory_size_; ++ smart_resize_ = m.smart_resize_; ++ } ++ else ++ { ++ // Cas particulier ou on attache un tableau de taille nulle: ++ // en theorie, c'est pareil qu'un tableau de taille non nulle, MAIS ++ // dans les operateurs (ex:Op_Dift_VDF_Face_Axi), une ref est construite ++ // avant que le tableau ne prenne sa taille definitive. Donc, pour ne pas ++ // empecher le resize, il ne faut pas attacher le tableau s'il n'a pas ++ // encore la bonne taille. Solution propre: reecrire les operateurs pour ++ // qu'ils ne prennent pas une ref avant que le tableau ne soit valide ++ // et faire p_ = m.p_ dans tous les cas. ++ } ++} ++ ++// Description: ++// Copie les elements source[first_element_source + i] ++// dans les elements (*this)[first_element_dest + i] pour 0 <= i < nb_elements ++// Les autres elements de (*this) sont inchanges. ++// Precondition: ++// Parametre: const ArrOfFloat& m ++// Signification: le tableau a utiliser, doit etre different de *this ! ++// Parametre: entier nb_elements ++// Signification: nombre d'elements a copier, nb_elements >= -1. ++// Si nb_elements==-1, on copie tout le tableau m. ++// Valeurs par defaut: -1 ++// Parametre: entier first_element_dest ++// Valeurs par defaut: 0 ++// Parametre: entier first_element_source ++// Valeurs par defaut: 0 ++// Retour: ArrOfFloat& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Sort en erreur si la taille du tableau m est plus grande que la ++// taille de tableau this. ++// Effets de bord: ++// Postcondition: ++ArrOfFloat& ArrOfFloat::inject_array(const ArrOfFloat& source, ++ entier nb_elements, ++ entier first_element_dest, ++ entier first_element_source) ++{ ++ assert(&source != this); ++ assert(nb_elements >= -1); ++ assert(first_element_dest >= 0); ++ assert(first_element_source >= 0); ++ ++ if (nb_elements < 0) ++ nb_elements = source.size_array(); ++ ++ assert(first_element_source + nb_elements <= source.size_array()); ++ assert(first_element_dest + nb_elements <= size_array()); ++ ++ if (nb_elements > 0) ++ { ++ float * addr_dest = addr() + first_element_dest; ++ const float * addr_source = source.addr() + first_element_source; ++ // memcpy(addr_dest , addr_source, nb_elements * sizeof(float)); ++ entier i; ++ for (i = 0; i < nb_elements; i++) ++ { ++ addr_dest[i] = addr_source[i]; ++ } ++ } ++ return *this; ++} ++ ++// Description: ++// Retourne le nombre de references des donnees du tableau ++// si le tableau est "normal", -1 s'il est "detache" ou "ref_data" ++// Retour: int ++// Signification: ref_count_ ++entier ArrOfFloat::ref_count() const ++{ ++ if (p_) ++ return p_->ref_count(); ++ else ++ return -1; ++} ++ ++// Description: ++// Addition case a case sur toutes les cases du tableau ++// Precondition: ++// la taille de y doit etre au moins egale a la taille de this ++// Parametre: const ArrOfFloat& y ++// Signification: tableau a ajouter ++// Valeurs par defaut: ++// Contraintes: ++// Acces: ++// Retour: ArrOfFloat& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++ArrOfFloat& ArrOfFloat::operator+=(const ArrOfFloat& y) ++{ ++ assert(size_array()==y.size_array()); ++ float* dx = addr(); ++ const float* dy = y.addr(); ++ const entier n = size_array(); ++ for (entier i=0; i 0); ++ float valeur_max = fabs(dx[0]); ++ for(entier i = 1; i < size; i++) ++ { ++ const float val = fabs(dx[i]); ++ if (val > valeur_max) ++ valeur_max = val; ++ } ++ return valeur_max; ++} ++ ++// Description: ++// muliplie toutes les cases par dy ++// Retour: ArrOfFloat & ++// Signification: *this ++ArrOfFloat& ArrOfFloat::operator*= (const float dy) ++{ ++ float * data = addr(); ++ const entier n = size_array(); ++ for(entier i=0; i < n; i++) ++ data[i] *= dy; ++ return *this; ++} ++ ++ ++// Description: ++// divise toutes les cases par dy ++// Retour: ArrOfFloat & ++// Signification: *this ++ArrOfFloat& ArrOfFloat::operator/= (const float dy) ++{ ++ // En theorie: les deux lignes suivantes sont plus efficaces, mais ++ // cela produit des differences sur certains cas tests ++ // (Hyd_C_VEF_Smago et Lambda_var_VEF_turb). Ca veut dire qu'il y ++ // a un probleme autre part mais pour l'instant on laisse l'ancien ++ // codage. ++ // const float i_dy = 1. / dy; ++ // operator*=(i_dy); ++ ++ float * data = addr(); ++ const entier n = size_array(); ++ for(entier i=0; i < n; i++) ++ data[i] /= dy; ++ ++ return *this; ++} ++ ++FloatTab::FloatTab() ++{ ++ // nb_dim_ = 2; ++ dimensions_[0] = 0; ++ dimensions_[1] = 0; ++} ++ ++FloatTab::FloatTab(const FloatTab& tab) : ++ ArrOfFloat(tab) ++{ ++ // nb_dim_ = tab.nb_dim_; ++ dimensions_[0] = tab.dimensions_[0]; ++ dimensions_[1] = tab.dimensions_[1]; ++} ++FloatTab::FloatTab(const entier i, const entier j) : ++ ArrOfFloat(i*j) ++{ ++ // nb_dim_ = 2; ++ dimensions_[0] = i; ++ dimensions_[1] = j; ++} ++ ++FloatTab& FloatTab::operator=(const FloatTab& tab) ++{ ++ ArrOfFloat::operator=(tab); ++ // nb_dim_ = tab.nb_dim_; ++ dimensions_[0] = tab.dimensions_[0]; ++ dimensions_[1] = tab.dimensions_[1]; ++ return *this; ++} ++ ++void FloatTab::reset() ++{ ++ ArrOfFloat::reset(); ++ // nb_dim_ = 2; ++ dimensions_[0] = 0; ++ dimensions_[1] = 0; ++} ++ +diff --git a/databases/readers/Lata/ArrOfFloat.h b/databases/readers/Lata/ArrOfFloat.h +new file mode 100644 +index 0000000..f80d4ee +--- /dev/null ++++ b/databases/readers/Lata/ArrOfFloat.h +@@ -0,0 +1,353 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++//////////////////////////////////////////////////////////// ++// ++// Warning : DO NOT EDIT ! ++// Please update ArrOf_Scalar_Prototype.h.P ++// and this file will be generated automatically ++// by the script file check.sh ++//////////////////////////////////////////////////////////// ++ ++#ifndef ArrOfFloat_H ++#define ArrOfFloat_H ++ ++#include ++#include ++#include ++ ++#if ! defined(DMAXFLOAT) ++#define DMAXFLOAT 1e40 ++#endif ++ ++class VFloatdata; ++ ++class ArrOfFloat ++{ ++public: ++ // ++ // Destructeur ++ // ++ virtual ~ArrOfFloat(); ++ // ++ // Constructeurs ++ // ++ ArrOfFloat(); ++ ArrOfFloat(entier size); ++ ArrOfFloat(entier size, float initial_value); ++ // Constructeur par copie : deep copy (on duplique les donnees) ++ ArrOfFloat(const ArrOfFloat& ); ++ // ++ // Methodes de construction tardive (on cree un tableau vide avec ArrOfFloat() ++ // puis on appelle ces methodes pour modifier les caracteristiques du tableau : ++ // ++ // Change le nombre d'elements du tableau ++ inline ArrOfFloat& resize_array(entier new_size); ++ ++ // Methodes de gestion de l'allocation memoire: ++ // Assigne une valeur au drapeau "smart_resize" ++ // (reallocation uniquement si la taille augmente) ++ void set_smart_resize(entier flag); ++ // Gestion du type de memoire alouee (standard ou pool de memoire Trio-U) ++ enum Storage { STANDARD, TEMP_STORAGE, SIMD_ALIGNED }; ++ void set_mem_storage(const Storage storage); ++ Storage get_mem_storage() const; ++ ++ // Construction de tableaux qui pointent vers des donnees existantes ++ // !!! Utiliser ref_data avec precaution (attention a size_array_) ++ ArrOfFloat& ref_data(float* ptr, entier size); ++ ArrOfFloat& ref_array(const ArrOfFloat&); ++ // Operateur copie ++ ArrOfFloat& operator=(const ArrOfFloat&); ++ // Remise du tableau dans l'etat initial (obtenu par le constructeur par defaut) ++ virtual void reset(); ++ ++ // ++ // Methodes d'acces aux donnees et aux caracteristiques du tableau ++ // ++ // Remplit le tableau avec la valeur en parametre ++ ArrOfFloat& operator=(float valeur); ++ ++ inline float& operator[](entier i); ++ inline const float& operator[](entier i) const; ++ ++ // Ces methodes renvoient un pointeur vers le premier element du tableau. ++ const float * addr() const; ++ float * addr(); ++ // Renvoie le nombre d'elements du tableau (et non la taille allouee) ++ inline entier size_array() const; ++ // Renvoie le nombre de tableaux qui pointent vers la stucture "*p_" ++ entier ref_count() const; ++ // Ajoute une case en fin de tableau et y stocke la "valeur" ++ inline void append_array(float valeur); ++ ++ // ++ // Operateurs divers ++ // ++ ArrOfFloat& operator+=(const ArrOfFloat&); ++ ArrOfFloat& operator+=(const float); ++ ArrOfFloat& operator-=(const ArrOfFloat&); ++ ArrOfFloat& operator-=(const float); ++ ArrOfFloat& inject_array(const ArrOfFloat& source, ++ entier nb_elements = -1, ++ entier first_element_dest = 0, ++ entier first_element_source = 0); ++ ArrOfFloat& copy_array(const ArrOfFloat&); ++ ++ ArrOfFloat& operator*= (const float) ; ++ ArrOfFloat& operator/= (const float) ; ++ ++ void ordonne_array(); ++ ++protected: ++ // ++ // Methodes accessibles depuis les descendants de ArrOfFloat ++ // ++ void attach_array(const ArrOfFloat&); ++ entier detach_array(); ++ void fill_default_value(entier first, entier nb); ++private: ++ // B. Mathieu 22/06/2004 : je mets ces membres "private" pour forcer ++ // le passage par les accesseurs dans les classes derivees, au cas ou ++ // on voudrait modifier l'implementation. ++ ++ // Zone de memoire contenant les valeurs du tableau. ++ // Pointeur nul => le tableau est "detache" ou "ref_data" ++ // Pointeur non nul => le tableau est "normal" ++ VFloatdata* p_; ++ ++ // Pointeur vers le premier element du tableau (egal a p_->data si p_!=0) ++ // Pointeur nul => le tableau est "detache". ++ // Pointeur non nul => le tableau est "normal" ou "ref_data" ++ float* data_; ++ ++ // Nombre d'elements du tableau (inferieur ou egal a memory_size_). ++ // Si le tableau est "detache", alors size_array_=0 ++ entier size_array_; ++ // Taille memoire reellement allouee pour le tableau ++ // (pour le mecanisme smart_resize_). memory_size_ est nul ++ // si le tableau est de type "ref_data". Sinon memory_size_ ++ // est egal a p_->size_. ++ entier memory_size_; ++ ++ // Drapeau indiquant si on applique une strategie d'allocation ++ // preventive (la memoire alouee augmente d'un facteur constant ++ // si la taille devient insuffisante). ++ // Si smart_resize_ == 0, alors on a toujours p_->size_ == size ++ entier smart_resize_; ++ ++ // Drapeau indiquant si l'allocation memoire a lieu avec un new classique ++ // ou dans le pool de memoire temporaire de Trio ++ Storage storage_type_; ++ ++ // Partie non inline de resize_array(): ++ // Declaration des constantes pour les options de memory_resize ++ static const entier COPY_OLD; ++ static const entier INITIALIZE_NEW; ++ void memory_resize(entier new_size, entier options); ++}; ++ ++#define MAXDIMFloatTab 2 ++ ++class FloatTab : public ArrOfFloat ++{ ++public: ++ FloatTab(); ++ FloatTab(const FloatTab&); ++ FloatTab(const entier i, const entier j); ++ FloatTab& operator=(const FloatTab&); ++ void reset(); ++ ++ inline float& operator()(entier i, entier j); ++ inline float operator()(entier i, entier j) const; ++ ++ inline entier resize(entier i, entier j); ++ inline entier dimension(entier i) const; ++ inline entier dimension_tot(entier i) const; ++ ++protected: ++ // In order to mimic TRUST behavior, operator[] is forbidden ++ // for 2 dimensionnal matrices, you must cast to ArrOf to use it.. ++ double& operator[](entier i); ++ const double& operator[](entier i) const; ++ ++private: ++ // entier nb_dim_; ++ entier dimensions_[MAXDIMFloatTab]; ++}; ++ ++inline float& FloatTab::operator()(entier i, entier j) ++{ ++ // assert(nb_dim_ == 2); ++ assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]); ++ const entier n = i * dimensions_[1] + j; ++ float& x = ArrOfFloat::operator[] (n); ++ return x; ++} ++ ++inline float FloatTab::operator()(entier i, entier j) const ++{ ++ // assert(nb_dim_ == 2); ++ assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]); ++ const entier n = i * dimensions_[1] + j; ++ float x = ArrOfFloat::operator[] (n); ++ return x; ++} ++ ++inline entier FloatTab::resize(entier i, entier j) ++{ ++ assert(i >= 0 && j >= 0); ++ // nb_dim_ = 2; ++ dimensions_[0] = i; ++ dimensions_[1] = j; ++ ArrOfFloat::resize_array(i * j); ++ return i*j; ++} ++ ++inline entier FloatTab::dimension(entier i) const ++{ ++ assert(i >= 0 && i < 2); ++ return dimensions_[i]; ++} ++ ++// Description: renvoie la meme valeur que dimension. ++inline entier FloatTab::dimension_tot(entier i) const ++{ ++ return dimension(i); ++} ++ ++// ++// Declarations des fonctions non membres de la classe ArrOfFloat ++// ++entier operator==(const ArrOfFloat& x, const ArrOfFloat& y) ; ++entier imin_array(const ArrOfFloat&) ; ++entier imax_array(const ArrOfFloat&) ; ++float min_array(const ArrOfFloat&) ; ++float max_array(const ArrOfFloat&) ; ++ ++float max_abs_array(const ArrOfFloat&) ; ++ ++// ****************************************************************** ++// FONCTIONS MEMBRES DE ArrOfFloat ++// ****************************************************************** ++ ++// Description : ++// Change le nombre d'elements du tableau. Cette fonction est inline ++// car elle doit etre tres rapide dans le cas ou smart_resize_==1 ++// (utilisation frequente de resize_array()) ++// Si smart_resize est non nul : ++// Si la nouvelle taille est inferieure ou egale a la taille ++// alouee (p->get_size()) on ne realloue pas de memoire ++// sinon, on realloue et on copie les donnees existantes. ++// Astuce pour ne pas copier les anciennes donnees: ++// resize(0); resize(n); ++// Si smart_resize est nul, on realloue une nouvelle zone memoire ++// uniquement si la nouvelle taille est differente de l'ancienne. ++// Precondition : ++// Si "new_size" est egal a la taille du tableau, aucune condition. ++// Sinon, le tableau doit etre soit detache, soit normal (pas de type "ref_data") ++// et ref_count doit etre egal a 1 (pas d'autre reference au tableau). ++// ++inline ArrOfFloat& ArrOfFloat::resize_array(entier new_size) ++{ ++ assert(new_size >= 0); ++ // Soit le tableau est detache (data_==0), soit il est normal (p_!=0) ++ // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau, ++ // ou alors la taille ne doit pas changer. ++ assert(new_size == size_array_ || data_ == 0 || (p_ != 0 && ref_count() == 1)); ++ ++ if ((smart_resize_ == 0) || (new_size > memory_size_)) ++ memory_resize(new_size, COPY_OLD + INITIALIZE_NEW); ++ size_array_ = new_size; ++ return *this; ++} ++ ++// Description: ++// operateur [] retourne le ieme element du tableau ++// Precondition: ++// Parametre: entier i ++// Signification: indice dans l'intervalle 0 <= i < size_array() ++// Exception: ++// assert si la valeur sort de l'intervalle : [ -DMAXFLOAT,DMAXFLOAT ] ++// assert si i n'est pas dans l'intervalle ++inline float& ArrOfFloat::operator[](entier i) ++{ ++ assert(i >= 0 && i < size_array_); ++ assert((smart_resize_==1)|| (data_[i] > -DMAXFLOAT && data_[i] < DMAXFLOAT)); ++ return data_[i]; ++} ++ ++// Description: ++// operateur [] retourne le ieme element du tableau ++// Precondition: ++// Parametre: entier i ++// Signification: indice dans l'intervalle 0 <= i < size_array() ++// Exception: ++// assert si la valeur sort de l'intervalle : [ -DMAXFLOAT,DMAXFLOAT ] ++// assert si i n'est pas dans l'intervalle ++inline const float& ArrOfFloat::operator[](entier i) const ++{ ++ assert(i >= 0 && i < size_array_); ++ assert(data_[i] > -DMAXFLOAT && data_[i] < DMAXFLOAT); ++ return data_[i]; ++} ++ ++// Description: ++// Renvoie la taille du tableau (nombre d'elements declares ++// a la construction ou a resize_array()). ++// C'est le nombre d'elements accessibles a operator[] ++// Retour: entier ++inline entier ArrOfFloat::size_array() const ++{ ++ return size_array_; ++} ++ ++// Description: ++// Ajoute une case en fin de tableau et y stocke la "valeur" ++// Precondition: ++// Tableau doit etre de type "smart_resize" (sinon, ecroulement ++// des performances). De plus, le tableau ne doit pas etre "ref_data", ++// et il ne doit pas y avoir plus d'une reference a la zone de ++// memoire pointee (meme precondition que resize_array()) ++inline void ArrOfFloat::append_array(float valeur) ++{ ++ assert(smart_resize_); ++ // Soit le tableau est detache (data_==0), soit il est normal (p_!=0) ++ // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau. ++ assert(data_ == 0 || (p_ != 0 && ref_count() == 1)); ++ ++ if (size_array_+1 > memory_size_) ++ memory_resize(size_array_+1, COPY_OLD); ++ data_[size_array_] = valeur; ++ size_array_++; ++} ++ ++// ArrOfFloat_H ++#endif ++ +diff --git a/databases/readers/Lata/ArrOfInt.C b/databases/readers/Lata/ArrOfInt.C +new file mode 100644 +index 0000000..a4a150b +--- /dev/null ++++ b/databases/readers/Lata/ArrOfInt.C +@@ -0,0 +1,1110 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++//////////////////////////////////////////////////////////// ++// ++// Warning : DO NOT EDIT ! ++// Please update ArrOf_Scalar_Prototype.cpp.h ++// and this file will be generated automatically ++// by the script file check.sh ++//////////////////////////////////////////////////////////// ++ ++#include ++// limits.h definit INT_MIN, SHRT_MIN, ... ++#include ++#include ++#include ++#include ++#include ++#include ++#include "simd_interface.h" ++ ++using namespace std; ++ ++// ****************************************************************** ++// ++// Implementation des methodes de VIntdata ++// ++// ****************************************************************** ++//////////////////////////////////////////////////////////////////// ++// .NOM ArrOfInt ++// .ENTETE TRUST Math ++// .LIBRAIRIE libtmath ++// .FILE ArrOfInt.h ++// .FILE ArrOfInt.cpp ++// ++// .DESCRIPTION ++// VIntdata alloue une zone de memoire de la taille specifiee au ++// constructeur, et libere la zone de memoire a la destruction. ++// ++// "ref_count" compte le nombre de pointeurs qui font reference a "this". ++// (permet au dernier utilisateur de l'objet de le detruire), voir ++// ArrOfInt. ++// ++// .SECTION voir aussi ++// .CONTRAINTES ++// .INVARIANTS ++// .HTML ++// .EPS ++/////////////////////////////////////////////////////////////////// ++ ++class VIntdata ++{ ++public: ++ VIntdata(entier size, ArrOfInt::Storage storage); ++ ~VIntdata(); ++ entier add_one_ref(); ++ entier suppr_one_ref(); ++ entier * get_data(); ++ const entier * get_data() const; ++ inline entier ref_count() const; ++ inline entier get_size() const; ++private: ++ // Le constructeur par copie et l'operateur= sont interdits. ++ VIntdata(const VIntdata& v); ++ VIntdata& operator=(const VIntdata& v); ++ ++ // "data" est un pointeur sur une zone de memoire de taille ++ // sz * sizeof(entier), allouee par le ++ // constructeur et liberee par le destructeur. ++ // Ce pointeur n'est jamais nul meme si size_==0 ++ entier * data_; ++ // Compteur incremente par add_one_ref et decremente par suppr_one_ref. ++ // Contient le nombre d'objets ArrOfInt dont le membre "p" pointe ++ // vers "this". On a ref_count_ >= 0. ++ entier ref_count_; ++ // "sz" est la taille du tableau "data_" alloue ++ // On a sz >= 0. ++ entier size_; ++ ArrOfInt::Storage storage_; ++}; ++ ++ ++// Description: ++// Construit un VIntdata de taille size >= 0 ++// Parametre: entier s ++// Signification: taille du VIntdata, il faut size >= 0 ++// Parametre: Storage storage ++// Signification: indique si la memoire doit etre allouee ++// avec "new" ou avec "simd_malloc" ++// Valeurs par defaut: STANDARD (allocation avec "new") ++// Postcondition: ++// data_ n'est jamais nul, meme si size==0 ++VIntdata::VIntdata(entier size, ArrOfInt::Storage storage) ++{ ++ if (size == 0) ++ storage = ArrOfInt::STANDARD; ++ ++ switch (storage) ++ { ++ case ArrOfInt::STANDARD: ++ { ++#ifdef _EXCEPTION_ ++ // Allocation de la memoire sur le tas ++ try ++ { ++ data_ = new entier[size]; ++ } ++ catch(...) ++ { ++ Cerr << "impossible d'allouer " << size << " entier " << finl; ++ throw; ++ } ++#else ++ data_ = new entier[size]; ++ if(!data_) ++ { ++ Cerr << "impossible d'allouer " << size << "entier " << finl; ++ throw ; ++ } ++#endif ++ break; ++ } ++ case ArrOfInt::SIMD_ALIGNED: ++ { ++#ifdef SIMD_TOOLS_H ++ data_ = (entier*) simd_malloc (sizeof(entier) * size); ++#else ++ Cerr<<"unable to allocate simd_aligned, version compiled without simd "< 0 ++// Retour: int ++// Signification: ref_count ++inline entier VIntdata::suppr_one_ref() ++{ ++ assert(ref_count_ > 0); ++ return (--ref_count_); ++} ++ ++// Description: renvoie data_ ++inline entier * VIntdata::get_data() ++{ ++ return data_; ++} ++ ++// Description: renvoie data_ ++inline const entier * VIntdata::get_data() const ++{ ++ return data_; ++} ++ ++// Description: Constructeur par copie. Interdit : genere une erreur ! ++VIntdata::VIntdata(const VIntdata& v) ++{ ++ Cerr << "Erreur dans VIntdata::VIntdata(const VIntdata & v)" << finl; ++ throw; ++} ++ ++// Description: Operateur= interdit. Genere une erreur ! ++VIntdata& VIntdata::operator=(const VIntdata& v) ++{ ++ Cerr << "Erreur dans VIntdata::operator=(const VIntdata & v)" << finl; ++ throw; ++ return *this; ++} ++ ++// ****************************************************************** ++// ++// Implementation des methodes de ArrOfInt ++// ++// ****************************************************************** ++ ++ ++// Definition des constantes pour les options de memory_resize ++const entier ArrOfInt::COPY_OLD = 1; ++const entier ArrOfInt::INITIALIZE_NEW = 2; ++ ++// Description: ++// Destructeur : appelle detach_array() ++ArrOfInt::~ArrOfInt() ++{ ++ detach_array(); ++ size_array_ = -1; // Paranoia: si size_array_==-1, c'est un zombie ++} ++ ++// Description: ++// Constructeur par defaut: cree un tableau "detache", ++// soit p_==0, data_==0, size_array_==0, smart_resize_==0 ++ArrOfInt::ArrOfInt() : ++ p_(0), ++ data_(0), ++ size_array_(0), ++ memory_size_(0), ++ smart_resize_(0), ++ storage_type_(STANDARD) ++{ ++} ++ ++// Description: ++// Cree un tableau de taille n avec allocation standard ++// (voir set_mem_storage). ++// Valeur de remplissage par defaut: voir fill_default_value ++// Precondition: ++// Parametre: entier n ++// Signification: taille du tableau ++ArrOfInt::ArrOfInt(entier n) : ++ p_(new VIntdata(n, STANDARD)), ++ data_(p_->get_data()), ++ size_array_(n), ++ memory_size_(n), ++ smart_resize_(0), ++ storage_type_(STANDARD) ++{ ++ if (n > 0) ++ fill_default_value(0, n); ++} ++ ++// Description: ++// Cree un tableau de taille n ++// toutes les cases sont initialisees a x ++// Precondition: ++// Parametre: entier n ++// Signification: taille du tableau ++// Parametre: entier x ++// Signification: valeur pour initialiser le tableau ++ArrOfInt::ArrOfInt(entier n, entier x) : ++ p_(new VIntdata(n, STANDARD)), ++ data_(p_->get_data()), ++ size_array_(n), ++ memory_size_(n), ++ smart_resize_(0), ++ storage_type_(STANDARD) ++{ ++ *this = x; ++} ++ ++// Description: ++// Constructeur par copie. On alloue une nouvelle zone de memoire ++// et on copie le contenu du tableau. L'attribut smart_resize_ est ++// copie aussi. ++// Si le tableau A est de taille nulle, on cree un tableau "detache", ++// sinon on cree un tableau "normal". ++// Parametre: const ArrOfInt& A ++// Signification: le tableau a copier ++ArrOfInt::ArrOfInt(const ArrOfInt& A) ++{ ++ const entier size = A.size_array(); ++ if (size > 0) ++ { ++ // Creation d'un tableau "normal" ++ storage_type_ = STANDARD; ++ p_ = new VIntdata(size, STANDARD); ++ data_ = p_->get_data(); ++ size_array_ = size; ++ memory_size_ = size; ++ smart_resize_ = A.smart_resize_; ++ inject_array(A); ++ } ++ else ++ { ++ // Creation d'un tableau "detache" ++ p_ = 0; ++ data_ = 0; ++ size_array_ = 0; ++ memory_size_ = 0; ++ smart_resize_ = 0; ++ storage_type_ = STANDARD; ++ } ++} ++ ++// Description: ++// Change le mode d'allocation memoire lors des resize ++// (voir VIntdata et Int_ptr_trav) ++// Exemple pour creer un tableau avec allocation temporaire: ++// DoubleTab tab; // Creation d'un tableau vide ++// tab.set_mem_storage(TEMP_STORAGE); // Changement de mode d'allocation ++// tab.resize(n); // Allocation memoire ++void ArrOfInt::set_mem_storage(const Storage storage) ++{ ++ storage_type_ = storage; ++} ++ ++// Description: ++// Renvoie le mode d'allocation du tableau (qui sera utilise ++// lors du prochain resize si changement de taille). ++// (voir VIntdata et Int_ptr_trav) ++enum ArrOfInt::Storage ArrOfInt::get_mem_storage() const ++{ ++ return storage_type_; ++} ++ ++// Description: ++// Change le mode l'allocation memoire: reallocation d'un tableau ++// a chaque changement de taille (flag = 0) ou reallocation ++// uniquement si la taille augmente et par doublement de la taille ++// du tableau (flag = 1). ++void ArrOfInt::set_smart_resize(entier flag) ++{ ++ assert(flag == 0 || flag == 1); ++ smart_resize_ = flag; ++} ++ ++// Description: ++// Remet le tableau dans l'etat obtenu avec le constructeur par defaut ++// (libere la memoire mais conserve le mode d'allocation memoire actuel) ++void ArrOfInt::reset() ++{ ++ detach_array(); ++} ++ ++// Description: ++// Copie les donnees du tableau m. ++// Si "m" n'a pas la meme taille que "*this", on fait un resize_array. ++// Ensuite, on copie les valeurs de "m" dans "*this". ++// Le type de tableau (methode d'allocation) n'est pas copie. ++// Precondition: ++// Si le tableau n'a pas la meme taille que "m", alors *this doit ++// etre "resizable" (ne pas etre de type "ref_data" et "ref_count == 1") ++// Parametre: const ArrOfInt& m ++// Signification: la tableau a copier ++// Retour: ArrOfInt& ++// Signification: *this ++ArrOfInt& ArrOfInt::operator=(const ArrOfInt& m) ++{ ++ if (&m != this) ++ { ++ const entier new_size = m.size_array(); ++ // Le code suivant est quasiment une copie de ArrOfInt::resize() ++ // SAUF: memory_resize est appele avec NO_INITIALIZE (la zone de memoire ++ // n'est pas initialisee) ++ if (new_size != size_array()) ++ { ++ if ((smart_resize_ == 0) || (new_size > memory_size_)) ++ memory_resize(new_size, 0); // Pas d'initialisation ++ size_array_ = new_size; ++ } ++ inject_array(m); ++ } ++ return *this; ++} ++ ++ ++// Description: ++// x est affecte a toutes les cases ++// Precondition: ++// Parametre: entier x ++// Signification: la valeur a affecter a toutes les cases du tableau ++// Valeurs par defaut: ++// Contraintes: ++// Acces: ++// Retour: ArrOfInt& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++ArrOfInt& ArrOfInt::operator=(entier x) ++{ ++ const entier n = size_array(); ++ entier *data = addr(); ++ for (entier i = 0; i < n; i++) ++ { ++ data[i] = x; ++ } ++ return *this; ++} ++ ++// Description: appelle operator=(a) ++ArrOfInt& ArrOfInt::copy_array(const ArrOfInt& a) ++{ ++ operator=(a); ++ return *this; ++} ++ ++// Description: ++// Si besoin, alloue une nouvelle zone de memoire, ++// copie les donnees et efface l'ancienne zone de memoire. ++// Attention, on suppose que cette methode est appelee par ++// resize_array(). ++// Attention: si ref_count_>1, l'appel a resize_array() est ++// autorise uniquement si la nouvelle taille est identique ++// a la precedente. ++// Precondition: ++// Le tableau doit etre de type "detache" ou "normal" avec ++// ref_count==1, et il faut new_size >= 0 ++// On suppose que size_array contient encore le nombre d'elements ++// valides avant changement de taille. ++// Parametre: new_size ++// Signification: nouvelle taille demandee pour le tableau. ++// Parametre: options ++// Signification: COPY_OLD => on recopie les anciennes donnees dans le nouveau ++// tableau (jusqu'au max de l'ancienne et de la nouvelle taille). ++// INITIALIZE_NEW => initialisation des cases non copiees ++// Postcondition: ++// p_ et data_ sont mis a jour, mais pas size_array_ !!! ++// (on suppose que c'est fait dans resize_array()). ++// Si la nouvelle taille est nulle, on detache le tableau. ++void ArrOfInt::memory_resize(entier new_size, entier options) ++{ ++ assert(new_size >= 0); ++ ++ // Occupation memoire de l'ancien tableau: ++ entier old_mem_size = 0; ++ if (p_) ++ old_mem_size = p_->get_size(); ++ ++ // Occupation memoire du nouveau tableau : ++ // Si smart_resize, on prend au moins deux fois la taille ++ // precedente, ou new_size ++ entier new_mem_size = new_size; ++ if (smart_resize_ && (old_mem_size * 2 > new_size)) ++ new_mem_size = old_mem_size * 2; ++ ++ if (new_mem_size != old_mem_size) ++ { ++ // detach_array() efface le contenu de size_array_. On le met de cote: ++ const entier old_size_array = size_array_; ++ // On va reellement changer l'adresse du tableau. ++ // Il ne faut pas qu'il existe d'autre reference a ce tableau. ++ assert(data_ == 0 || (p_ != 0 && ref_count() == 1)); ++ if (new_mem_size == 0) ++ { ++ // La nouvelle taille est nulle, on cree un tableau "detache" ++ detach_array(); ++ } ++ else ++ { ++ // Allocation d'une nouvelle zone ++ VIntdata * new_p = new VIntdata(new_mem_size, storage_type_); ++ entier * new_data = new_p->get_data(); ++ // Raccourci si le tableau etait "detache", inutile de copier ++ // les anciennes donnees. On copie si COPY_OLD est demande ++ entier copy_size = 0; ++ if (data_ != 0) ++ { ++ // Calcul du nombre d'elements a copier vers la nouvelle ++ // zone de memoire : c'est le min de l'ancienne et de ++ // la nouvelle taille. ++ if (options & COPY_OLD) ++ { ++ copy_size = size_array_; ++ if (new_size < copy_size) ++ copy_size = new_size; ++ // Copie des valeurs dans le nouveau tableau ++ for (entier i = 0; i < copy_size; i++) ++ new_data[i] = data_[i]; ++ } ++ // Destruction de l'ancienne zone (si plus aucune reference) ++ detach_array(); ++ } ++ // On attache la nouvelle zone de memoire ++ p_ = new_p; ++ data_ = new_data; ++ memory_size_ = new_mem_size; ++ // Initialisation des cases supplementaires avec une valeur par defaut ++ if (options & INITIALIZE_NEW) ++ fill_default_value(copy_size, new_mem_size - copy_size); ++ // Restaure l'ancienne valeur de size_array_ ++ size_array_ = old_size_array; ++ } ++ } ++} ++ ++// Description: ++// Remplit "nb" cases consecutives du tableau a partir de la case "first" ++// avec une valeur par defaut. ++// Cette fonction est appelee lors d'un resize pour initialiser les ++// cases nouvellement creees. ++// Le comportement depend actuellement du type de tableau : ++// * Tableau de type "smart_resize": ++// * en mode debug (macro NDEBUG non definie) le tableau est initialise ++// avec une valeur invalide. ++// * en optimise, le tableau n'est pas initialise ++// * Tableau normal : ++// Le tableau est initialise avec la valeur 0. Ce comportement est choisi ++// pour des raisons de compatibilite avec l'implementation precedente. ++// Cette specification pourrait etre modifiee prochainement pour des raisons ++// de performances (pour ne pas avoir a initialiser inutilement les tableaux). ++// DONC: il faut supposer desormais que les nouvelles cases ne sont pas ++// initialisees lors d'un resize. ++// Parametre: first ++// Signification: premiere case a initialiser. ++// Contrainte: (nb==0) ou (0 <= first < memory_size_) ++// Parametre: nb ++// Signification: nombre de cases a initialiser. ++// Contrainte: (nb==0) ou (0 < nb <= memory_size_ - first) ++void ArrOfInt::fill_default_value(entier first, entier nb) ++{ ++ assert((nb == 0) || (first >= 0 && first < memory_size_)); ++ assert((nb == 0) || (nb > 0 && nb <= memory_size_ - first)); ++ entier * data = addr(); ++ assert(data!=0 || nb==0); ++ data += first; ++ if (smart_resize_) ++ { ++ /* ++ // On initialise uniquement en mode debug ++ #ifndef NDEBUG ++ static const entier ENTIER_INVALIDE = INT_MIN; ++ for (entier i = 0; i < nb; i++) ++ data[i] = ENTIER_INVALIDE; ++ #endif ++ */ ++ } ++ else ++ { ++ // Comportement pour les tableaux normaux : compatibilite avec la ++ // version precedente : on initialise avec 0. ++ for (entier i = 0; i < nb; i++) ++ data[i] = (entier) 0; ++ } ++} ++ ++// **************************************************************** ++// ++// Fonctions non membres de la classe ArrOfInt ++// ++// **************************************************************** ++ ++// Description: ++// Renvoie 1 si les tableaux "v" et "a" sont de la meme taille ++// et contiennent les memes valeurs au sens strict, sinon renvoie 0. ++// Le test est !(v[i]!=a[i]) ++entier operator==(const ArrOfInt& v, const ArrOfInt& a) ++{ ++ const entier n = v.size_array(); ++ const entier na = a.size_array(); ++ entier resu = 1; ++ if (n != na) ++ { ++ resu = 0; ++ } ++ else ++ { ++ const entier* vv = v.addr(); ++ const entier* av = a.addr(); ++ entier i; ++ for (i = 0; i < n; i++) ++ { ++ if (av[i] != vv[i]) ++ { ++ resu = 0; ++ break; ++ } ++ } ++ } ++ return resu; ++} ++ ++// Description: ++// Retourne l'indice du min ou -1 si le tableau est vide ++// Precondition: ++// Parametre: const ArrOfInt& dx ++// Signification: tableau a utiliser ++// Retour: int ++// Signification: indice du min ++entier imin_array(const ArrOfInt& dx) ++{ ++ entier indice_min = -1; ++ const entier size = dx.size_array(); ++ if (size > 0) ++ { ++ indice_min = 0; ++ entier valeur_min = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const entier val = dx[i]; ++ if(val < valeur_min) ++ { ++ indice_min = i; ++ valeur_min = val; ++ } ++ } ++ } ++ return indice_min; ++} ++ ++// Description: ++// Retourne l'indice du max ou -1 si le tableau est vide ++// Precondition: ++// Parametre: const ArrOfInt& dx ++// Signification: tableau a utiliser ++// Retour: int ++// Signification: indice du max ++entier imax_array(const ArrOfInt& dx) ++{ ++ entier indice_max = -1; ++ const entier size = dx.size_array(); ++ if (size > 0) ++ { ++ indice_max = 0; ++ entier valeur_max = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const entier val = dx[i]; ++ if(val > valeur_max) ++ { ++ indice_max = i; ++ valeur_max = val; ++ } ++ } ++ } ++ return indice_max; ++} ++ ++// Description: ++// Retourne la valeur minimale ++// Precondition: ++// Le tableau doit contenir au moins une valeur ++// Parametre: const ArrOfInt& dx ++// Signification: tableau a utiliser ++// Retour: entier ++// Signification: valeur du min ++entier min_array(const ArrOfInt& dx) ++{ ++ const entier size = dx.size_array(); ++ assert(size > 0); ++ entier valeur_min = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const entier val = dx[i]; ++ if (val < valeur_min) ++ valeur_min = val; ++ } ++ return valeur_min; ++} ++ ++// Description: ++// Retourne la valeur maximale ++// Precondition: ++// Le tableau doit contenir au moins une valeur ++// Parametre: const ArrOfInt& dx ++// Signification: tableau a utiliser ++// Retour: entier ++// Signification: valeur du max ++entier max_array(const ArrOfInt& dx) ++{ ++ const entier size = dx.size_array(); ++ assert(size > 0); ++ entier valeur_max = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const entier val = dx[i]; ++ if (val > valeur_max) ++ valeur_max = val; ++ } ++ return valeur_max; ++} ++ ++// Description: ++// Fonction de comparaison utilisee pour trier le tableau ++// dans ArrOfInt::trier(). Voir man qsort ++static int fonction_compare_arrofentier_ordonner(const void * data1, const void * data2) ++{ ++ const entier x = *(const entier*)data1; ++ const entier y = *(const entier*)data2; ++ return x - y; ++} ++ ++// Description: ++// Tri des valeurs du tableau dans l'ordre croissant. ++// La fonction utilisee est qsort de stdlib (elle est en n*log(n)). ++void ArrOfInt::ordonne_array() ++{ ++ const entier size = size_array(); ++ if (size > 1) ++ { ++ entier * data = addr(); ++ qsort(data, size, sizeof(entier), ++ fonction_compare_arrofentier_ordonner); ++ } ++} ++ ++// Description: ++// Fait pointer le tableau vers les memes donnees qu'un tableau ++// existant. Le tableau sera du meme type que le tableau m ("detache", ++// "normal"). Le tableau m ne doit pas etre de type "ref_data" ++// Les donnes existantes sont perdues si elles ++// ne sont pas referencees ailleurs. ++// Precondition: ++// Parametre: const ArrOfInt& m ++// Signification: le tableau a referencer (pas de type "ref_data" ++// et different de *this !!!) ++// Retour: ArrOfInt& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++ArrOfInt& ArrOfInt::ref_array(const ArrOfInt& m) ++{ ++ assert(&m != this); ++ // La condition 'm n'est pas de type "ref_data"' est necessaire pour ++ // attach_array(). ++ detach_array(); ++ attach_array(m); ++ return *this; ++} ++ ++// Description: ++// Fait pointer le tableau vers la zone de memoire "data_". ++// On detache la zone de memoire existante. Le tableau devient ++// de type "ref_data". Attention : ptr doit etre non nul. ++// La taille est initialisee avec size. ++// Cette methode est appelee notamment par IntVect::adopter. ++// Parametre: entier* ++// Signification: le tableau a recuperer. Si pointeur nul alors size ++// doit etre nulle aussi et le tableau reste detache ++// Parametre: entier size ++// Signification: le nombre d'elements du tableau. ++// Retour: ArrOfInt& ++// Signification: *this ++ArrOfInt& ArrOfInt::ref_data(entier* ptr, entier size) ++{ ++ assert(ptr != 0 || size == 0); ++ assert(size >= 0); ++ detach_array(); ++ data_ = ptr; ++ size_array_ = size; ++ return *this; ++} ++ ++// Description: ++// Amene le tableau dans l'etat "detache". C'est a dire: ++// Si le tableau est "detache" : ++// * ne rien faire ++// Si le tableau est "normal" : ++// * decremente le nombre de references a *p ++// * detruit *p si p->ref_count==0 ++// * annule p_, data_ et size_array_ ++// Si le tableau est "ref_data" : ++// * annule data_ et size_array_ ++// Retour: int ++// Signification: 1 si les donnees du tableau ont ete supprimees ++// Precondition: ++// Postcondition: ++// On a p_==0, data_==0 et size_array_==0, memory_size_ = 0 ++// L'attribut smart_resize_ est conserve. ++entier ArrOfInt::detach_array() ++{ ++ entier retour = 0; ++ if (p_) ++ { ++ // Le tableau est de type "normal" ++ // Si la zone de memoire n'est plus utilisee par personne, ++ // on la detruit. ++ if ((p_->suppr_one_ref()) == 0) ++ { ++ delete p_; ++ retour = 1; ++ } ++ p_ = 0; ++ } ++ data_ = 0; ++ size_array_ = 0; ++ memory_size_ = 0; ++ return retour; ++} ++ ++// Description: ++// Amene le tableau dans l'etat "normal", "detache" ou "ref_array" ++// en associant la meme zone de memoire que le tableau m. ++// Precondition: ++// Le tableau doit etre "detache" ++// Parametre: const ArrOfInt& m ++// Signification: tableau a utiliser ++// le tableau doit etre different de *this !!! ++// Retour: ++// Signification: ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++// Si m est detache, le tableau reste detache, ++// si m est "ref_array", le tableau devient "ref_array", ++// sinon le tableau est "normal", avec ref_count > 1 ++// Si m est de taille nulle, le tableau reste detache + Warning dans fichier .log ++void ArrOfInt::attach_array(const ArrOfInt& m) ++{ ++ // Le tableau doit etre detache ++ assert(data_ == 0 && p_ == 0); ++ // Le tableau doit etre different de *this ++ assert(&m != this); ++ ++ if (m.size_array() > 0) ++ { ++ p_ = m.p_; ++ if (p_) ++ p_->add_one_ref(); ++ data_ = m.data_; ++ size_array_ = m.size_array_; ++ memory_size_ = m.memory_size_; ++ smart_resize_ = m.smart_resize_; ++ } ++ else ++ { ++ // Cas particulier ou on attache un tableau de taille nulle: ++ // en theorie, c'est pareil qu'un tableau de taille non nulle, MAIS ++ // dans les operateurs (ex:Op_Dift_VDF_Face_Axi), une ref est construite ++ // avant que le tableau ne prenne sa taille definitive. Donc, pour ne pas ++ // empecher le resize, il ne faut pas attacher le tableau s'il n'a pas ++ // encore la bonne taille. Solution propre: reecrire les operateurs pour ++ // qu'ils ne prennent pas une ref avant que le tableau ne soit valide ++ // et faire p_ = m.p_ dans tous les cas. ++ } ++} ++ ++// Description: ++// Copie les elements source[first_element_source + i] ++// dans les elements (*this)[first_element_dest + i] pour 0 <= i < nb_elements ++// Les autres elements de (*this) sont inchanges. ++// Precondition: ++// Parametre: const ArrOfInt& m ++// Signification: le tableau a utiliser, doit etre different de *this ! ++// Parametre: entier nb_elements ++// Signification: nombre d'elements a copier, nb_elements >= -1. ++// Si nb_elements==-1, on copie tout le tableau m. ++// Valeurs par defaut: -1 ++// Parametre: entier first_element_dest ++// Valeurs par defaut: 0 ++// Parametre: entier first_element_source ++// Valeurs par defaut: 0 ++// Retour: ArrOfInt& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Sort en erreur si la taille du tableau m est plus grande que la ++// taille de tableau this. ++// Effets de bord: ++// Postcondition: ++ArrOfInt& ArrOfInt::inject_array(const ArrOfInt& source, ++ entier nb_elements, ++ entier first_element_dest, ++ entier first_element_source) ++{ ++ assert(&source != this); ++ assert(nb_elements >= -1); ++ assert(first_element_dest >= 0); ++ assert(first_element_source >= 0); ++ ++ if (nb_elements < 0) ++ nb_elements = source.size_array(); ++ ++ assert(first_element_source + nb_elements <= source.size_array()); ++ assert(first_element_dest + nb_elements <= size_array()); ++ ++ if (nb_elements > 0) ++ { ++ entier * addr_dest = addr() + first_element_dest; ++ const entier * addr_source = source.addr() + first_element_source; ++ // memcpy(addr_dest , addr_source, nb_elements * sizeof(entier)); ++ entier i; ++ for (i = 0; i < nb_elements; i++) ++ { ++ addr_dest[i] = addr_source[i]; ++ } ++ } ++ return *this; ++} ++ ++// Description: ++// Retourne le nombre de references des donnees du tableau ++// si le tableau est "normal", -1 s'il est "detache" ou "ref_data" ++// Retour: int ++// Signification: ref_count_ ++entier ArrOfInt::ref_count() const ++{ ++ if (p_) ++ return p_->ref_count(); ++ else ++ return -1; ++} ++ ++// Description: ++// Addition case a case sur toutes les cases du tableau ++// Precondition: ++// la taille de y doit etre au moins egale a la taille de this ++// Parametre: const ArrOfInt& y ++// Signification: tableau a ajouter ++// Valeurs par defaut: ++// Contraintes: ++// Acces: ++// Retour: ArrOfInt& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++ArrOfInt& ArrOfInt::operator+=(const ArrOfInt& y) ++{ ++ assert(size_array()==y.size_array()); ++ entier* dx = addr(); ++ const entier* dy = y.addr(); ++ const entier n = size_array(); ++ for (entier i=0; i ++#include ++#include ++ ++ ++class VIntdata; ++ ++class ArrOfInt ++{ ++public: ++ // ++ // Destructeur ++ // ++ virtual ~ArrOfInt(); ++ // ++ // Constructeurs ++ // ++ ArrOfInt(); ++ ArrOfInt(entier size); ++ ArrOfInt(entier size, entier initial_value); ++ // Constructeur par copie : deep copy (on duplique les donnees) ++ ArrOfInt(const ArrOfInt& ); ++ // ++ // Methodes de construction tardive (on cree un tableau vide avec ArrOfInt() ++ // puis on appelle ces methodes pour modifier les caracteristiques du tableau : ++ // ++ // Change le nombre d'elements du tableau ++ inline ArrOfInt& resize_array(entier new_size); ++ ++ // Methodes de gestion de l'allocation memoire: ++ // Assigne une valeur au drapeau "smart_resize" ++ // (reallocation uniquement si la taille augmente) ++ void set_smart_resize(entier flag); ++ // Gestion du type de memoire alouee (standard ou pool de memoire Trio-U) ++ enum Storage { STANDARD, TEMP_STORAGE, SIMD_ALIGNED }; ++ void set_mem_storage(const Storage storage); ++ Storage get_mem_storage() const; ++ ++ // Construction de tableaux qui pointent vers des donnees existantes ++ // !!! Utiliser ref_data avec precaution (attention a size_array_) ++ ArrOfInt& ref_data(entier* ptr, entier size); ++ ArrOfInt& ref_array(const ArrOfInt&); ++ // Operateur copie ++ ArrOfInt& operator=(const ArrOfInt&); ++ // Remise du tableau dans l'etat initial (obtenu par le constructeur par defaut) ++ virtual void reset(); ++ ++ // ++ // Methodes d'acces aux donnees et aux caracteristiques du tableau ++ // ++ // Remplit le tableau avec la valeur en parametre ++ ArrOfInt& operator=(entier valeur); ++ ++ inline entier& operator[](entier i); ++ inline const entier& operator[](entier i) const; ++ ++ // Ces methodes renvoient un pointeur vers le premier element du tableau. ++ const entier * addr() const; ++ entier * addr(); ++ // Renvoie le nombre d'elements du tableau (et non la taille allouee) ++ inline entier size_array() const; ++ // Renvoie le nombre de tableaux qui pointent vers la stucture "*p_" ++ entier ref_count() const; ++ // Ajoute une case en fin de tableau et y stocke la "valeur" ++ inline void append_array(entier valeur); ++ ++ // ++ // Operateurs divers ++ // ++ ArrOfInt& operator+=(const ArrOfInt&); ++ ArrOfInt& operator+=(const entier); ++ ArrOfInt& operator-=(const ArrOfInt&); ++ ArrOfInt& operator-=(const entier); ++ ArrOfInt& inject_array(const ArrOfInt& source, ++ entier nb_elements = -1, ++ entier first_element_dest = 0, ++ entier first_element_source = 0); ++ ArrOfInt& copy_array(const ArrOfInt&); ++ ++ ++ void ordonne_array(); ++ ++protected: ++ // ++ // Methodes accessibles depuis les descendants de ArrOfInt ++ // ++ void attach_array(const ArrOfInt&); ++ entier detach_array(); ++ void fill_default_value(entier first, entier nb); ++private: ++ // B. Mathieu 22/06/2004 : je mets ces membres "private" pour forcer ++ // le passage par les accesseurs dans les classes derivees, au cas ou ++ // on voudrait modifier l'implementation. ++ ++ // Zone de memoire contenant les valeurs du tableau. ++ // Pointeur nul => le tableau est "detache" ou "ref_data" ++ // Pointeur non nul => le tableau est "normal" ++ VIntdata* p_; ++ ++ // Pointeur vers le premier element du tableau (egal a p_->data si p_!=0) ++ // Pointeur nul => le tableau est "detache". ++ // Pointeur non nul => le tableau est "normal" ou "ref_data" ++ entier* data_; ++ ++ // Nombre d'elements du tableau (inferieur ou egal a memory_size_). ++ // Si le tableau est "detache", alors size_array_=0 ++ entier size_array_; ++ // Taille memoire reellement allouee pour le tableau ++ // (pour le mecanisme smart_resize_). memory_size_ est nul ++ // si le tableau est de type "ref_data". Sinon memory_size_ ++ // est egal a p_->size_. ++ entier memory_size_; ++ ++ // Drapeau indiquant si on applique une strategie d'allocation ++ // preventive (la memoire alouee augmente d'un facteur constant ++ // si la taille devient insuffisante). ++ // Si smart_resize_ == 0, alors on a toujours p_->size_ == size ++ entier smart_resize_; ++ ++ // Drapeau indiquant si l'allocation memoire a lieu avec un new classique ++ // ou dans le pool de memoire temporaire de Trio ++ Storage storage_type_; ++ ++ // Partie non inline de resize_array(): ++ // Declaration des constantes pour les options de memory_resize ++ static const entier COPY_OLD; ++ static const entier INITIALIZE_NEW; ++ void memory_resize(entier new_size, entier options); ++}; ++ ++#define MAXDIMIntTab 2 ++ ++class IntTab : public ArrOfInt ++{ ++public: ++ IntTab(); ++ IntTab(const IntTab&); ++ IntTab(const entier i, const entier j); ++ IntTab& operator=(const IntTab&); ++ void reset(); ++ ++ inline entier& operator()(entier i, entier j); ++ inline entier operator()(entier i, entier j) const; ++ ++ inline entier resize(entier i, entier j); ++ inline entier dimension(entier i) const; ++ inline entier dimension_tot(entier i) const; ++ ++protected: ++ // In order to mimic TRUST behavior, operator[] is forbidden ++ // for 2 dimensionnal matrices, you must cast to ArrOf to use it.. ++ double& operator[](entier i); ++ const double& operator[](entier i) const; ++ ++private: ++ // entier nb_dim_; ++ entier dimensions_[MAXDIMIntTab]; ++}; ++ ++inline entier& IntTab::operator()(entier i, entier j) ++{ ++ // assert(nb_dim_ == 2); ++ assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]); ++ const entier n = i * dimensions_[1] + j; ++ entier& x = ArrOfInt::operator[] (n); ++ return x; ++} ++ ++inline entier IntTab::operator()(entier i, entier j) const ++{ ++ // assert(nb_dim_ == 2); ++ assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]); ++ const entier n = i * dimensions_[1] + j; ++ entier x = ArrOfInt::operator[] (n); ++ return x; ++} ++ ++inline entier IntTab::resize(entier i, entier j) ++{ ++ assert(i >= 0 && j >= 0); ++ // nb_dim_ = 2; ++ dimensions_[0] = i; ++ dimensions_[1] = j; ++ ArrOfInt::resize_array(i * j); ++ return i*j; ++} ++ ++inline entier IntTab::dimension(entier i) const ++{ ++ assert(i >= 0 && i < 2); ++ return dimensions_[i]; ++} ++ ++// Description: renvoie la meme valeur que dimension. ++inline entier IntTab::dimension_tot(entier i) const ++{ ++ return dimension(i); ++} ++ ++// ++// Declarations des fonctions non membres de la classe ArrOfInt ++// ++entier operator==(const ArrOfInt& x, const ArrOfInt& y) ; ++entier imin_array(const ArrOfInt&) ; ++entier imax_array(const ArrOfInt&) ; ++entier min_array(const ArrOfInt&) ; ++entier max_array(const ArrOfInt&) ; ++ ++ ++// ****************************************************************** ++// FONCTIONS MEMBRES DE ArrOfInt ++// ****************************************************************** ++ ++// Description : ++// Change le nombre d'elements du tableau. Cette fonction est inline ++// car elle doit etre tres rapide dans le cas ou smart_resize_==1 ++// (utilisation frequente de resize_array()) ++// Si smart_resize est non nul : ++// Si la nouvelle taille est inferieure ou egale a la taille ++// alouee (p->get_size()) on ne realloue pas de memoire ++// sinon, on realloue et on copie les donnees existantes. ++// Astuce pour ne pas copier les anciennes donnees: ++// resize(0); resize(n); ++// Si smart_resize est nul, on realloue une nouvelle zone memoire ++// uniquement si la nouvelle taille est differente de l'ancienne. ++// Precondition : ++// Si "new_size" est egal a la taille du tableau, aucune condition. ++// Sinon, le tableau doit etre soit detache, soit normal (pas de type "ref_data") ++// et ref_count doit etre egal a 1 (pas d'autre reference au tableau). ++// ++inline ArrOfInt& ArrOfInt::resize_array(entier new_size) ++{ ++ assert(new_size >= 0); ++ // Soit le tableau est detache (data_==0), soit il est normal (p_!=0) ++ // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau, ++ // ou alors la taille ne doit pas changer. ++ assert(new_size == size_array_ || data_ == 0 || (p_ != 0 && ref_count() == 1)); ++ ++ if ((smart_resize_ == 0) || (new_size > memory_size_)) ++ memory_resize(new_size, COPY_OLD + INITIALIZE_NEW); ++ size_array_ = new_size; ++ return *this; ++} ++ ++// Description: ++// operateur [] retourne le ieme element du tableau ++// Precondition: ++// Parametre: entier i ++// Signification: indice dans l'intervalle 0 <= i < size_array() ++// Exception: ++// assert si i n'est pas dans l'intervalle ++inline entier& ArrOfInt::operator[](entier i) ++{ ++ assert(i >= 0 && i < size_array_); ++ return data_[i]; ++} ++ ++// Description: ++// operateur [] retourne le ieme element du tableau ++// Precondition: ++// Parametre: entier i ++// Signification: indice dans l'intervalle 0 <= i < size_array() ++// Exception: ++// assert si i n'est pas dans l'intervalle ++inline const entier& ArrOfInt::operator[](entier i) const ++{ ++ assert(i >= 0 && i < size_array_); ++ return data_[i]; ++} ++ ++// Description: ++// Renvoie la taille du tableau (nombre d'elements declares ++// a la construction ou a resize_array()). ++// C'est le nombre d'elements accessibles a operator[] ++// Retour: entier ++inline entier ArrOfInt::size_array() const ++{ ++ return size_array_; ++} ++ ++// Description: ++// Ajoute une case en fin de tableau et y stocke la "valeur" ++// Precondition: ++// Tableau doit etre de type "smart_resize" (sinon, ecroulement ++// des performances). De plus, le tableau ne doit pas etre "ref_data", ++// et il ne doit pas y avoir plus d'une reference a la zone de ++// memoire pointee (meme precondition que resize_array()) ++inline void ArrOfInt::append_array(entier valeur) ++{ ++ assert(smart_resize_); ++ // Soit le tableau est detache (data_==0), soit il est normal (p_!=0) ++ // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau. ++ assert(data_ == 0 || (p_ != 0 && ref_count() == 1)); ++ ++ if (size_array_+1 > memory_size_) ++ memory_resize(size_array_+1, COPY_OLD); ++ data_[size_array_] = valeur; ++ size_array_++; ++} ++ ++// ArrOfInt_H ++#endif ++ +diff --git a/databases/readers/Lata/ArrOf_Scalar_Prototype.cpp.h b/databases/readers/Lata/ArrOf_Scalar_Prototype.cpp.h +new file mode 100644 +index 0000000..b881750 +--- /dev/null ++++ b/databases/readers/Lata/ArrOf_Scalar_Prototype.cpp.h +@@ -0,0 +1,1168 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++__DoubleOnlyBegin__ ++#include ++__DoubleOnlyEnd__ ++__IntOnlyBegin__ ++// limits.h definit INT_MIN, SHRT_MIN, ... ++#include ++__IntOnlyEnd__ ++#include ++#include ++#include ++#include ++ ++// ****************************************************************** ++// ++// Implementation des methodes de V__Scalar__data ++// ++// ****************************************************************** ++//////////////////////////////////////////////////////////////////// ++// .NOM ArrOf__Scalar__ ++// .ENTETE TRUST Math ++// .LIBRAIRIE libtmath ++// .FILE ArrOf__Scalar__.h ++// .FILE ArrOf__Scalar__.cpp ++// ++// .DESCRIPTION ++// V__Scalar__data alloue une zone de memoire de la taille specifiee au ++// constructeur, et libere la zone de memoire a la destruction. ++// La memoire peut etre allouee sur le tas (avec new) ou par le ++// mecanisme Memoire::add_trav___scalar__. ++// ++// "ref_count" compte le nombre de pointeurs qui font reference a "this". ++// (permet au dernier utilisateur de l'objet de le detruire), voir ++// ArrOf__Scalar__. ++// ++// .SECTION voir aussi ++// .CONTRAINTES ++// .INVARIANTS ++// .HTML ++// .EPS ++/////////////////////////////////////////////////////////////////// ++ ++class V__Scalar__data ++{ ++public: ++ V__Scalar__data(entier size, ArrOf__Scalar__::Storage storage); ++ ~V__Scalar__data(); ++ entier add_one_ref(); ++ entier suppr_one_ref(); ++ __scalar__ * get_data(); ++ const __scalar__ * get_data() const; ++ inline entier ref_count() const; ++ inline entier get_size() const; ++private: ++ // Le constructeur par copie et l'operateur= sont interdits. ++ V__Scalar__data(const V__Scalar__data& v); ++ V__Scalar__data& operator=(const V__Scalar__data& v); ++ ++ // "data" est un pointeur sur une zone de memoire de taille ++ // sz * sizeof(__scalar__), allouee par le ++ // constructeur et liberee par le destructeur. ++ // Ce pointeur n'est jamais nul meme si size_==0 ++ __scalar__ * data_; ++ // Compteur incremente par add_one_ref et decremente par suppr_one_ref. ++ // Contient le nombre d'objets ArrOf__Scalar__ dont le membre "p" pointe ++ // vers "this". On a ref_count_ >= 0. ++ entier ref_count_; ++ // "sz" est la taille du tableau "data_" alloue ++ // On a sz >= 0. ++ entier size_; ++ // Si storage est de type TEMP_STORAGE, d_ptr_trav porte la reference ++ // a la zone allouee, sinon le pointeur est nul. ++ //__Scalar___ptr_trav * d_ptr_trav_; ++}; ++ ++ ++// Description: ++// Construit un V__Scalar__data de taille size >= 0 ++// Parametre: entier s ++// Signification: taille du V__Scalar__data, il faut size >= 0 ++// Parametre: Storage storage ++// Signification: indique si la memoire doit etre allouee ++// avec "new" ou avec "memoire.add_trav___scalar__()" ++// Valeurs par defaut: STANDARD (allocation avec "new") ++// Postcondition: ++// data_ n'est jamais nul, meme si size==0 ++V__Scalar__data::V__Scalar__data(entier size, ArrOf__Scalar__::Storage storage) ++{ ++ if (size == 0) ++ storage = ArrOf__Scalar__::STANDARD; ++ ++ switch (storage) ++ { ++ case ArrOf__Scalar__::STANDARD: ++ { ++#ifdef _EXCEPTION_ ++ // Allocation de la memoire sur le tas ++ try ++ { ++ data_ = new __scalar__[size]; ++ } ++ catch(...) ++ { ++ Cerr << "impossible d'allouer " << size << " __scalar__ " << finl; ++ throw; ++ } ++#else ++ data_ = new __scalar__[size]; ++ if(!data_) ++ { ++ Cerr << "impossible d'allouer " << size << "__scalar__ " << finl; ++ throw ; ++ } ++#endif ++ break; ++ } ++ default: ++ throw; ++ } ++ ref_count_ = 1; ++ size_ = size; ++ ++ assert(data_ != 0); ++} ++ ++// Description: ++// Detruit la zone de memoire allouee. ++// Precondition: ++// ref_count == 0 (la zone de memoire ne doit etre referencee nulle part) ++V__Scalar__data::~V__Scalar__data() ++{ ++ assert(ref_count_ == 0); ++ ++ // Stockage STANDARD ++ delete[] data_; ++ ++ data_ = 0; // paranoia: si size_==-1 c'est qu'on pointe sur un zombie ++ size_ = -1; // (pointeur vers un objet qui a ete detruit) ++} ++ ++// Description: renvoie ref_count_ ++inline entier V__Scalar__data::ref_count() const ++{ ++ return ref_count_; ++} ++ ++// Description: renvoie size_ ++inline entier V__Scalar__data::get_size() const ++{ ++ return size_; ++} ++ ++// Description: ++// Un nouveau tableau utilise cette zone memoire : ++// incremente ref_count ++// Retour: int ++// Signification: ref_count ++inline entier V__Scalar__data::add_one_ref() ++{ ++ return ++ref_count_; ++} ++ ++// Description: ++// Un tableau de moins utilise cette zone memoire ++// decremente ref_count ++// Precondition: ++// ref_count_ > 0 ++// Retour: int ++// Signification: ref_count ++inline entier V__Scalar__data::suppr_one_ref() ++{ ++ assert(ref_count_ > 0); ++ return (--ref_count_); ++} ++ ++// Description: renvoie data_ ++inline __scalar__ * V__Scalar__data::get_data() ++{ ++ return data_; ++} ++ ++// Description: renvoie data_ ++inline const __scalar__ * V__Scalar__data::get_data() const ++{ ++ return data_; ++} ++ ++// Description: Constructeur par copie. Interdit : genere une erreur ! ++V__Scalar__data::V__Scalar__data(const V__Scalar__data& v) ++{ ++ Cerr << "Erreur dans V__Scalar__data::V__Scalar__data(const V__Scalar__data & v)" << finl; ++ throw; ++} ++ ++// Description: Operateur= interdit. Genere une erreur ! ++V__Scalar__data& V__Scalar__data::operator=(const V__Scalar__data& v) ++{ ++ Cerr << "Erreur dans V__Scalar__data::operator=(const V__Scalar__data & v)" << finl; ++ throw; ++ return *this; ++} ++ ++// ****************************************************************** ++// ++// Implementation des methodes de ArrOf__Scalar__ ++// ++// ****************************************************************** ++ ++ ++// Definition des constantes pour les options de memory_resize ++const entier ArrOf__Scalar__::COPY_OLD = 1; ++const entier ArrOf__Scalar__::INITIALIZE_NEW = 2; ++ ++// Description: ++// Destructeur : appelle detach_array() ++ArrOf__Scalar__::~ArrOf__Scalar__() ++{ ++ detach_array(); ++ size_array_ = -1; // Paranoia: si size_array_==-1, c'est un zombie ++} ++ ++// Description: ++// Constructeur par defaut: cree un tableau "detache", ++// soit p_==0, data_==0, size_array_==0, smart_resize_==0 ++ArrOf__Scalar__::ArrOf__Scalar__() : ++ p_(0), ++ data_(0), ++ size_array_(0), ++ memory_size_(0), ++ smart_resize_(0), ++ storage_type_(STANDARD) ++{ ++} ++ ++// Description: ++// Cree un tableau de taille n avec allocation standard ++// (voir set_mem_storage). ++// Valeur de remplissage par defaut: voir fill_default_value ++// Precondition: ++// Parametre: entier n ++// Signification: taille du tableau ++ArrOf__Scalar__::ArrOf__Scalar__(entier n) : ++ p_(new V__Scalar__data(n, STANDARD)), ++ data_(p_->get_data()), ++ size_array_(n), ++ memory_size_(n), ++ smart_resize_(0), ++ storage_type_(STANDARD) ++{ ++ if (n > 0) ++ fill_default_value(0, n); ++} ++ ++// Description: ++// Cree un tableau de taille n ++// toutes les cases sont initialisees a x ++// Precondition: ++// Parametre: entier n ++// Signification: taille du tableau ++// Parametre: __scalar__ x ++// Signification: valeur pour initialiser le tableau ++ArrOf__Scalar__::ArrOf__Scalar__(entier n, __scalar__ x) : ++ p_(new V__Scalar__data(n, STANDARD)), ++ data_(p_->get_data()), ++ size_array_(n), ++ memory_size_(n), ++ smart_resize_(0), ++ storage_type_(STANDARD) ++{ ++ *this = x; ++} ++ ++// Description: ++// Constructeur par copie. On alloue une nouvelle zone de memoire ++// et on copie le contenu du tableau. L'attribut smart_resize_ est ++// copie aussi. ++// Si le tableau A est de taille nulle, on cree un tableau "detache", ++// sinon on cree un tableau "normal". ++// Parametre: const ArrOf__Scalar__& A ++// Signification: le tableau a copier ++ArrOf__Scalar__::ArrOf__Scalar__(const ArrOf__Scalar__& A) ++{ ++ const entier size = A.size_array(); ++ if (size > 0) ++ { ++ // Creation d'un tableau "normal" ++ storage_type_ = STANDARD; ++ p_ = new V__Scalar__data(size, STANDARD); ++ data_ = p_->get_data(); ++ size_array_ = size; ++ memory_size_ = size; ++ smart_resize_ = A.smart_resize_; ++ inject_array(A); ++ } ++ else ++ { ++ // Creation d'un tableau "detache" ++ p_ = 0; ++ data_ = 0; ++ size_array_ = 0; ++ memory_size_ = 0; ++ smart_resize_ = 0; ++ storage_type_ = STANDARD; ++ } ++} ++ ++// Description: ++// Change le mode d'allocation memoire lors des resize ++// (voir V__Scalar__data et __Scalar___ptr_trav) ++// Exemple pour creer un tableau avec allocation temporaire: ++// DoubleTab tab; // Creation d'un tableau vide ++// tab.set_mem_storage(TEMP_STORAGE); // Changement de mode d'allocation ++// tab.resize(n); // Allocation memoire ++void ArrOf__Scalar__::set_mem_storage(const Storage storage) ++{ ++ storage_type_ = storage; ++} ++ ++// Description: ++// Renvoie le mode d'allocation du tableau (qui sera utilise ++// lors du prochain resize si changement de taille). ++// (voir V__Scalar__data et __Scalar___ptr_trav) ++enum ArrOf__Scalar__::Storage ArrOf__Scalar__::get_mem_storage() const ++{ ++ return storage_type_; ++} ++ ++// Description: ++// Change le mode l'allocation memoire: reallocation d'un tableau ++// a chaque changement de taille (flag = 0) ou reallocation ++// uniquement si la taille augmente et par doublement de la taille ++// du tableau (flag = 1). ++void ArrOf__Scalar__::set_smart_resize(entier flag) ++{ ++ assert(flag == 0 || flag == 1); ++ smart_resize_ = flag; ++} ++ ++// Description: ++// Remet le tableau dans l'etat obtenu avec le constructeur par defaut ++// (libere la memoire mais conserve le mode d'allocation memoire actuel) ++void ArrOf__Scalar__::reset() ++{ ++ detach_array(); ++} ++ ++// Description: ++// Copie les donnees du tableau m. ++// Si "m" n'a pas la meme taille que "*this", on fait un resize_array. ++// Ensuite, on copie les valeurs de "m" dans "*this". ++// Le type de tableau (methode d'allocation) n'est pas copie. ++// Precondition: ++// Si le tableau n'a pas la meme taille que "m", alors *this doit ++// etre "resizable" (ne pas etre de type "ref_data" et "ref_count == 1") ++// Parametre: const ArrOf__Scalar__& m ++// Signification: la tableau a copier ++// Retour: ArrOf__Scalar__& ++// Signification: *this ++ArrOf__Scalar__& ArrOf__Scalar__::operator=(const ArrOf__Scalar__& m) ++{ ++ if (&m != this) ++ { ++ const entier new_size = m.size_array(); ++ // Le code suivant est quasiment une copie de ArrOf__Scalar__::resize() ++ // SAUF: memory_resize est appele avec NO_INITIALIZE (la zone de memoire ++ // n'est pas initialisee) ++ if (new_size != size_array()) ++ { ++ if ((smart_resize_ == 0) || (new_size > memory_size_)) ++ memory_resize(new_size, 0); // Pas d'initialisation ++ size_array_ = new_size; ++ } ++ inject_array(m); ++ } ++ return *this; ++} ++ ++ ++// Description: ++// x est affecte a toutes les cases ++// Precondition: ++// Parametre: __scalar__ x ++// Signification: la valeur a affecter a toutes les cases du tableau ++// Valeurs par defaut: ++// Contraintes: ++// Acces: ++// Retour: ArrOf__Scalar__& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++ArrOf__Scalar__& ArrOf__Scalar__::operator=(__scalar__ x) ++{ ++ const entier n = size_array(); ++ __scalar__ *data = addr(); ++ for (entier i = 0; i < n; i++) ++ { ++ data[i] = x; ++ } ++ return *this; ++} ++ ++// Description: appelle operator=(a) ++ArrOf__Scalar__& ArrOf__Scalar__::copy_array(const ArrOf__Scalar__ & a) ++{ ++ operator=(a); ++ return *this; ++} ++ ++// Description: ++// Si besoin, alloue une nouvelle zone de memoire, ++// copie les donnees et efface l'ancienne zone de memoire. ++// Attention, on suppose que cette methode est appelee par ++// resize_array(). ++// Attention: si ref_count_>1, l'appel a resize_array() est ++// autorise uniquement si la nouvelle taille est identique ++// a la precedente. ++// Precondition: ++// Le tableau doit etre de type "detache" ou "normal" avec ++// ref_count==1, et il faut new_size >= 0 ++// On suppose que size_array contient encore le nombre d'elements ++// valides avant changement de taille. ++// Parametre: new_size ++// Signification: nouvelle taille demandee pour le tableau. ++// Parametre: options ++// Signification: COPY_OLD => on recopie les anciennes donnees dans le nouveau ++// tableau (jusqu'au max de l'ancienne et de la nouvelle taille). ++// INITIALIZE_NEW => initialisation des cases non copiees ++// Postcondition: ++// p_ et data_ sont mis a jour, mais pas size_array_ !!! ++// (on suppose que c'est fait dans resize_array()). ++// Si la nouvelle taille est nulle, on detache le tableau. ++void ArrOf__Scalar__::memory_resize(entier new_size, entier options) ++{ ++ assert(new_size >= 0); ++ ++ // Occupation memoire de l'ancien tableau: ++ entier old_mem_size = 0; ++ if (p_) ++ old_mem_size = p_->get_size(); ++ ++ // Occupation memoire du nouveau tableau : ++ // Si smart_resize, on prend au moins deux fois la taille ++ // precedente, ou new_size ++ entier new_mem_size = new_size; ++ if (smart_resize_ && (old_mem_size * 2 > new_size)) ++ new_mem_size = old_mem_size * 2; ++ ++ if (new_mem_size != old_mem_size) ++ { ++ // detach_array() efface le contenu de size_array_. On le met de cote: ++ const entier old_size_array = size_array_; ++ // On va reellement changer l'adresse du tableau. ++ // Il ne faut pas qu'il existe d'autre reference a ce tableau. ++ assert(data_ == 0 || (p_ != 0 && ref_count() == 1)); ++ if (new_mem_size == 0) ++ { ++ // La nouvelle taille est nulle, on cree un tableau "detache" ++ detach_array(); ++ } ++ else ++ { ++ // Allocation d'une nouvelle zone ++ V__Scalar__data * new_p = new V__Scalar__data(new_mem_size, storage_type_); ++ __scalar__ * new_data = new_p->get_data(); ++ // Raccourci si le tableau etait "detache", inutile de copier ++ // les anciennes donnees. On copie si COPY_OLD est demande ++ entier copy_size = 0; ++ if (data_ != 0) ++ { ++ // Calcul du nombre d'elements a copier vers la nouvelle ++ // zone de memoire : c'est le min de l'ancienne et de ++ // la nouvelle taille. ++ if (options & COPY_OLD) ++ { ++ copy_size = size_array_; ++ if (new_size < copy_size) ++ copy_size = new_size; ++ // Copie des valeurs dans le nouveau tableau ++ for (entier i = 0; i < copy_size; i++) ++ new_data[i] = data_[i]; ++ } ++ // Destruction de l'ancienne zone (si plus aucune reference) ++ detach_array(); ++ } ++ // On attache la nouvelle zone de memoire ++ p_ = new_p; ++ data_ = new_data; ++ memory_size_ = new_mem_size; ++ // Initialisation des cases supplementaires avec une valeur par defaut ++ if (options & INITIALIZE_NEW) ++ fill_default_value(copy_size, new_mem_size - copy_size); ++ // Restaure l'ancienne valeur de size_array_ ++ size_array_ = old_size_array; ++ } ++ } ++} ++ ++// Description: ++// Remplit "nb" cases consecutives du tableau a partir de la case "first" ++// avec une valeur par defaut. ++// Cette fonction est appelee lors d'un resize pour initialiser les ++// cases nouvellement creees. ++// Le comportement depend actuellement du type de tableau : ++// * Tableau de type "smart_resize": ++// * en mode debug (macro NDEBUG non definie) le tableau est initialise ++// avec une valeur invalide. ++// * en optimise, le tableau n'est pas initialise ++// * Tableau normal : ++// Le tableau est initialise avec la valeur 0. Ce comportement est choisi ++// pour des raisons de compatibilite avec l'implementation precedente. ++// Cette specification pourrait etre modifiee prochainement pour des raisons ++// de performances (pour ne pas avoir a initialiser inutilement les tableaux). ++// DONC: il faut supposer desormais que les nouvelles cases ne sont pas ++// initialisees lors d'un resize. ++// Parametre: first ++// Signification: premiere case a initialiser. ++// Contrainte: (nb==0) ou (0 <= first < memory_size_) ++// Parametre: nb ++// Signification: nombre de cases a initialiser. ++// Contrainte: (nb==0) ou (0 < nb <= memory_size_ - first) ++void ArrOf__Scalar__::fill_default_value(entier first, entier nb) ++{ ++ assert((nb == 0) || (first >= 0 && first < memory_size_)); ++ assert((nb == 0) || (nb > 0 && nb <= memory_size_ - first)); ++ __scalar__ * data = addr(); ++ assert(data!=0 || nb==0); ++ data += first; ++ if (smart_resize_) ++ { ++ // On initialise uniquement en mode debug ++#ifndef NDEBUG ++ __IntOnlyBegin__ ++ static const entier ENTIER_INVALIDE = INT_MIN; ++ for (entier i = 0; i < nb; i++) ++ data[i] = ENTIER_INVALIDE; ++ __IntOnlyEnd__ ++ __DoubleOnlyBegin__ ++ // Ceci represente un NAN. N'importe quelle operation avec ca fait encore un NAN. ++ // Si c'est pas portable, on peut remplacer par DMAX_FLOAT sur les autres machines. ++ static const unsigned long long VALEUR_INVALIDE = ++ 0x7ff7ffffffffffffULL; ++ ++ // On utilise "memcpy" et non "=" car "=" peut provoquer une exception ++ // si la copie passe par le fpu. ++ for (entier i = 0; i < nb; i++) ++ memcpy(data + i, & VALEUR_INVALIDE, sizeof(__scalar__)); ++ __DoubleOnlyEnd__ ++#endif ++ } ++ else ++ { ++ // Comportement pour les tableaux normaux : compatibilite avec la ++ // version precedente : on initialise avec 0. ++ for (entier i = 0; i < nb; i++) ++ data[i] = (__scalar__) 0; ++ } ++} ++ ++// **************************************************************** ++// ++// Fonctions non membres de la classe ArrOf__Scalar__ ++// ++// **************************************************************** ++ ++// Description: ++// Renvoie 1 si les tableaux "v" et "a" sont de la meme taille ++// et contiennent les memes valeurs au sens strict, sinon renvoie 0. ++// Le test est !(v[i]!=a[i]) ++entier operator==(const ArrOf__Scalar__& v, const ArrOf__Scalar__& a) ++{ ++ const entier n = v.size_array(); ++ const entier na = a.size_array(); ++ entier resu = 1; ++ if (n != na) ++ { ++ resu = 0; ++ } ++ else ++ { ++ const __scalar__* vv = v.addr(); ++ const __scalar__* av = a.addr(); ++ entier i; ++ for (i = 0; i < n; i++) ++ { ++ if (av[i] != vv[i]) ++ { ++ resu = 0; ++ break; ++ } ++ } ++ } ++ return resu; ++} ++ ++// Description: ++// Retourne l'indice du min ou -1 si le tableau est vide ++// Precondition: ++// Parametre: const ArrOf__Scalar__& dx ++// Signification: tableau a utiliser ++// Retour: int ++// Signification: indice du min ++entier imin_array(const ArrOf__Scalar__& dx) ++{ ++ entier indice_min = -1; ++ const entier size = dx.size_array(); ++ if (size > 0) ++ { ++ indice_min = 0; ++ __scalar__ valeur_min = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const __scalar__ val = dx[i]; ++ if(val < valeur_min) ++ { ++ indice_min = i; ++ valeur_min = val; ++ } ++ } ++ } ++ return indice_min; ++} ++ ++// Description: ++// Retourne l'indice du max ou -1 si le tableau est vide ++// Precondition: ++// Parametre: const ArrOf__Scalar__& dx ++// Signification: tableau a utiliser ++// Retour: int ++// Signification: indice du max ++entier imax_array(const ArrOf__Scalar__& dx) ++{ ++ entier indice_max = -1; ++ const entier size = dx.size_array(); ++ if (size > 0) ++ { ++ indice_max = 0; ++ __scalar__ valeur_max = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const __scalar__ val = dx[i]; ++ if(val > valeur_max) ++ { ++ indice_max = i; ++ valeur_max = val; ++ } ++ } ++ } ++ return indice_max; ++} ++ ++// Description: ++// Retourne la valeur minimale ++// Precondition: ++// Le tableau doit contenir au moins une valeur ++// Parametre: const ArrOf__Scalar__& dx ++// Signification: tableau a utiliser ++// Retour: __scalar__ ++// Signification: valeur du min ++__scalar__ min_array(const ArrOf__Scalar__& dx) ++{ ++ const entier size = dx.size_array(); ++ assert(size > 0); ++ __scalar__ valeur_min = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const __scalar__ val = dx[i]; ++ if (val < valeur_min) ++ valeur_min = val; ++ } ++ return valeur_min; ++} ++ ++// Description: ++// Retourne la valeur maximale ++// Precondition: ++// Le tableau doit contenir au moins une valeur ++// Parametre: const ArrOf__Scalar__& dx ++// Signification: tableau a utiliser ++// Retour: __scalar__ ++// Signification: valeur du max ++__scalar__ max_array(const ArrOf__Scalar__& dx) ++{ ++ const entier size = dx.size_array(); ++ assert(size > 0); ++ __scalar__ valeur_max = dx[0]; ++ for(entier i = 1; i < size; i++) ++ { ++ const __scalar__ val = dx[i]; ++ if (val > valeur_max) ++ valeur_max = val; ++ } ++ return valeur_max; ++} ++ ++// Description: ++// Fonction de comparaison utilisee pour trier le tableau ++// dans ArrOf__Scalar__::trier(). Voir man qsort ++static int fonction_compare_arrof__scalar___ordonner(const void * data1, const void * data2) ++{ ++ const __scalar__ x = *(const __scalar__*)data1; ++ const __scalar__ y = *(const __scalar__*)data2; ++ __DoubleOnlyBegin__ ++ if (x < y) ++ return -1; ++ else if (x > y) ++ return 1; ++ else ++ return 0; ++ __DoubleOnlyEnd__ ++ __IntOnlyBegin__ ++ return x - y; ++ __IntOnlyEnd__ ++} ++ ++// Description: ++// Tri des valeurs du tableau dans l'ordre croissant. ++// La fonction utilisee est qsort de stdlib (elle est en n*log(n)). ++void ArrOf__Scalar__::ordonne_array() ++{ ++ const entier size = size_array(); ++ if (size > 1) ++ { ++ __scalar__ * data = addr(); ++ qsort(data, size, sizeof(__scalar__), ++ fonction_compare_arrof__scalar___ordonner); ++ } ++} ++ ++// Description: ++// Fait pointer le tableau vers les memes donnees qu'un tableau ++// existant. Le tableau sera du meme type que le tableau m ("detache", ++// "normal"). Le tableau m ne doit pas etre de type "ref_data" ++// Les donnes existantes sont perdues si elles ++// ne sont pas referencees ailleurs. ++// Precondition: ++// Parametre: const ArrOf__Scalar__& m ++// Signification: le tableau a referencer (pas de type "ref_data" ++// et different de *this !!!) ++// Retour: ArrOf__Scalar__& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++ArrOf__Scalar__& ArrOf__Scalar__::ref_array(const ArrOf__Scalar__& m) ++{ ++ assert(&m != this); ++ // La condition 'm n'est pas de type "ref_data"' est necessaire pour ++ // attach_array(). ++ detach_array(); ++ attach_array(m); ++ return *this; ++} ++ ++// Description: ++// Fait pointer le tableau vers la zone de memoire "data_". ++// On detache la zone de memoire existante. Le tableau devient ++// de type "ref_data". Attention : ptr doit etre non nul. ++// La taille est initialisee avec size. ++// Cette methode est appelee notamment par __Scalar__Vect::adopter. ++// Parametre: __scalar__* ++// Signification: le tableau a recuperer. Si pointeur nul alors size ++// doit etre nulle aussi et le tableau reste detache ++// Parametre: entier size ++// Signification: le nombre d'elements du tableau. ++// Retour: ArrOf__Scalar__& ++// Signification: *this ++ArrOf__Scalar__& ArrOf__Scalar__::ref_data(__scalar__* ptr, entier size) ++{ ++ assert(ptr != 0 || size == 0); ++ assert(size >= 0); ++ detach_array(); ++ data_ = ptr; ++ size_array_ = size; ++ return *this; ++} ++ ++// Description: ++// Amene le tableau dans l'etat "detache". C'est a dire: ++// Si le tableau est "detache" : ++// * ne rien faire ++// Si le tableau est "normal" : ++// * decremente le nombre de references a *p ++// * detruit *p si p->ref_count==0 ++// * annule p_, data_ et size_array_ ++// Si le tableau est "ref_data" : ++// * annule data_ et size_array_ ++// Retour: int ++// Signification: 1 si les donnees du tableau ont ete supprimees ++// Precondition: ++// Postcondition: ++// On a p_==0, data_==0 et size_array_==0, memory_size_ = 0 ++// L'attribut smart_resize_ est conserve. ++entier ArrOf__Scalar__::detach_array() ++{ ++ entier retour = 0; ++ if (p_) ++ { ++ // Le tableau est de type "normal" ++ // Si la zone de memoire n'est plus utilisee par personne, ++ // on la detruit. ++ if ((p_->suppr_one_ref()) == 0) ++ { ++ delete p_; ++ retour = 1; ++ } ++ p_ = 0; ++ } ++ data_ = 0; ++ size_array_ = 0; ++ memory_size_ = 0; ++ return retour; ++} ++ ++// Description: ++// Amene le tableau dans l'etat "normal", "detache" ou "ref_array" ++// en associant la meme zone de memoire que le tableau m. ++// Precondition: ++// Le tableau doit etre "detache" ++// Parametre: const ArrOf__Scalar__& m ++// Signification: tableau a utiliser ++// le tableau doit etre different de *this !!! ++// Retour: ++// Signification: ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++// Si m est detache, le tableau reste detache, ++// si m est "ref_array", le tableau devient "ref_array", ++// sinon le tableau est "normal", avec ref_count > 1 ++// Si m est de taille nulle, le tableau reste detache + Warning dans fichier .log ++void ArrOf__Scalar__::attach_array(const ArrOf__Scalar__& m) ++{ ++ // Le tableau doit etre detache ++ assert(data_ == 0 && p_ == 0); ++ // Le tableau doit etre different de *this ++ assert(&m != this); ++ ++ if (m.size_array() > 0) ++ { ++ p_ = m.p_; ++ if (p_) ++ p_->add_one_ref(); ++ data_ = m.data_; ++ size_array_ = m.size_array_; ++ memory_size_ = m.memory_size_; ++ smart_resize_ = m.smart_resize_; ++ } ++ else ++ { ++ // Cas particulier ou on attache un tableau de taille nulle: ++ // en theorie, c'est pareil qu'un tableau de taille non nulle, MAIS ++ // dans les operateurs (ex:Op_Dift_VDF_Face_Axi), une ref est construite ++ // avant que le tableau ne prenne sa taille definitive. Donc, pour ne pas ++ // empecher le resize, il ne faut pas attacher le tableau s'il n'a pas ++ // encore la bonne taille. Solution propre: reecrire les operateurs pour ++ // qu'ils ne prennent pas une ref avant que le tableau ne soit valide ++ // et faire p_ = m.p_ dans tous les cas. ++ } ++} ++ ++// Description: ++// Copie les elements source[first_element_source + i] ++// dans les elements (*this)[first_element_dest + i] pour 0 <= i < nb_elements ++// Les autres elements de (*this) sont inchanges. ++// Precondition: ++// Parametre: const ArrOf__Scalar__& m ++// Signification: le tableau a utiliser, doit etre different de *this ! ++// Parametre: entier nb_elements ++// Signification: nombre d'elements a copier, nb_elements >= -1. ++// Si nb_elements==-1, on copie tout le tableau m. ++// Valeurs par defaut: -1 ++// Parametre: entier first_element_dest ++// Valeurs par defaut: 0 ++// Parametre: entier first_element_source ++// Valeurs par defaut: 0 ++// Retour: ArrOf__Scalar__& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Sort en erreur si la taille du tableau m est plus grande que la ++// taille de tableau this. ++// Effets de bord: ++// Postcondition: ++ArrOf__Scalar__& ArrOf__Scalar__::inject_array(const ArrOf__Scalar__& source, ++ entier nb_elements, ++ entier first_element_dest, ++ entier first_element_source) ++{ ++ assert(&source != this); ++ assert(nb_elements >= -1); ++ assert(first_element_dest >= 0); ++ assert(first_element_source >= 0); ++ ++ if (nb_elements < 0) ++ nb_elements = source.size_array(); ++ ++ assert(first_element_source + nb_elements <= source.size_array()); ++ assert(first_element_dest + nb_elements <= size_array()); ++ ++ if (nb_elements > 0) ++ { ++ __scalar__ * addr_dest = addr() + first_element_dest; ++ const __scalar__ * addr_source = source.addr() + first_element_source; ++ // memcpy(addr_dest , addr_source, nb_elements * sizeof(__scalar__)); ++ entier i; ++ for (i = 0; i < nb_elements; i++) ++ { ++ addr_dest[i] = addr_source[i]; ++ } ++ } ++ return *this; ++} ++ ++// Description: ++// Retourne le nombre de references des donnees du tableau ++// si le tableau est "normal", -1 s'il est "detache" ou "ref_data" ++// Retour: int ++// Signification: ref_count_ ++entier ArrOf__Scalar__::ref_count() const ++{ ++ if (p_) ++ return p_->ref_count(); ++ else ++ return -1; ++} ++ ++// Description: ++// Addition case a case sur toutes les cases du tableau ++// Precondition: ++// la taille de y doit etre au moins egale a la taille de this ++// Parametre: const ArrOf__Scalar__& y ++// Signification: tableau a ajouter ++// Valeurs par defaut: ++// Contraintes: ++// Acces: ++// Retour: ArrOf__Scalar__& ++// Signification: *this ++// Contraintes: ++// Exception: ++// Effets de bord: ++// Postcondition: ++ArrOf__Scalar__& ArrOf__Scalar__::operator+=(const ArrOf__Scalar__& y) ++{ ++ assert(size_array()==y.size_array()); ++ __scalar__* dx = addr(); ++ const __scalar__* dy = y.addr(); ++ const entier n = size_array(); ++ for (entier i=0; i 0); ++ __scalar__ valeur_max = fabs(dx[0]); ++ for(entier i = 1; i < size; i++) ++ { ++ const __scalar__ val = fabs(dx[i]); ++ if (val > valeur_max) ++ valeur_max = val; ++ } ++ return valeur_max; ++} ++ ++// Description: ++// muliplie toutes les cases par dy ++// Retour: ArrOf__Scalar__ & ++// Signification: *this ++ArrOf__Scalar__& ArrOf__Scalar__::operator*= (const __scalar__ dy) ++{ ++ __scalar__ * data = addr(); ++ const entier n = size_array(); ++ for(entier i=0; i < n; i++) ++ data[i] *= dy; ++ return *this; ++} ++ ++ ++// Description: ++// divise toutes les cases par dy ++// Retour: ArrOf__Scalar__ & ++// Signification: *this ++ArrOf__Scalar__& ArrOf__Scalar__::operator/= (const __scalar__ dy) ++{ ++ // En theorie: les deux lignes suivantes sont plus efficaces, mais ++ // cela produit des differences sur certains cas tests ++ // (Hyd_C_VEF_Smago et Lambda_var_VEF_turb). Ca veut dire qu'il y ++ // a un probleme autre part mais pour l'instant on laisse l'ancien ++ // codage. ++ // const __scalar__ i_dy = 1. / dy; ++ // operator*=(i_dy); ++ ++ __scalar__ * data = addr(); ++ const entier n = size_array(); ++ for(entier i=0; i < n; i++) ++ data[i] /= dy; ++ ++ return *this; ++} ++__DoubleOnlyEnd__ ++ ++__Scalar__Tab::__Scalar__Tab() ++{ ++ nb_dim_ = 2; ++ dimensions_[0] = 0; ++ dimensions_[1] = 0; ++} ++ ++__Scalar__Tab::__Scalar__Tab(const __Scalar__Tab& tab) : ++ ArrOf__Scalar__(tab) ++{ ++ nb_dim_ = tab.nb_dim_; ++ dimensions_[0] = tab.dimensions_[0]; ++ dimensions_[1] = tab.dimensions_[1]; ++} ++__Scalar__Tab::__Scalar__Tab(const entier i, const entier j) : ++ ArrOf__Scalar__(i*j) ++{ ++ nb_dim_ = 2; ++ dimensions_[0] = i; ++ dimensions_[1] = j; ++} ++ ++__Scalar__Tab& __Scalar__Tab::operator=(const __Scalar__Tab& tab) ++{ ++ ArrOf__Scalar__::operator=(tab); ++ nb_dim_ = tab.nb_dim_; ++ dimensions_[0] = tab.dimensions_[0]; ++ dimensions_[1] = tab.dimensions_[1]; ++ return *this; ++} ++ ++void __Scalar__Tab::reset() ++{ ++ ArrOf__Scalar__::reset(); ++ nb_dim_ = 2; ++ dimensions_[0] = 0; ++ dimensions_[1] = 0; ++} +diff --git a/databases/readers/Lata/ArrOf_Scalar_Prototype.h b/databases/readers/Lata/ArrOf_Scalar_Prototype.h +new file mode 100644 +index 0000000..689932f +--- /dev/null ++++ b/databases/readers/Lata/ArrOf_Scalar_Prototype.h +@@ -0,0 +1,357 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++ ++#ifndef ArrOf__Scalar___H ++#define ArrOf__Scalar___H ++ ++#include ++#include ++#include ++ ++__DoubleOnlyBegin__ ++#define DMAXFLOAT 1e40 ++__DoubleOnlyEnd__ ++ ++class V__Scalar__data; ++ ++class ArrOf__Scalar__ ++{ ++public: ++ // ++ // Destructeur ++ // ++ virtual ~ArrOf__Scalar__(); ++ // ++ // Constructeurs ++ // ++ ArrOf__Scalar__(); ++ ArrOf__Scalar__(entier size); ++ ArrOf__Scalar__(entier size, __scalar__ initial_value); ++ // Constructeur par copie : deep copy (on duplique les donnees) ++ ArrOf__Scalar__(const ArrOf__Scalar__& ); ++ // ++ // Methodes de construction tardive (on cree un tableau vide avec ArrOf__Scalar__() ++ // puis on appelle ces methodes pour modifier les caracteristiques du tableau : ++ // ++ // Change le nombre d'elements du tableau ++ inline ArrOf__Scalar__& resize_array(entier new_size); ++ ++ // Methodes de gestion de l'allocation memoire: ++ // Assigne une valeur au drapeau "smart_resize" ++ // (reallocation uniquement si la taille augmente) ++ void set_smart_resize(entier flag); ++ // Gestion du type de memoire alouee (standard ou pool de memoire Trio-U) ++ enum Storage { STANDARD, TEMP_STORAGE }; ++ void set_mem_storage(const Storage storage); ++ Storage get_mem_storage() const; ++ ++ // Construction de tableaux qui pointent vers des donnees existantes ++ // !!! Utiliser ref_data avec precaution (attention a size_array_) ++ ArrOf__Scalar__& ref_data(__scalar__* ptr, entier size); ++ ArrOf__Scalar__& ref_array(const ArrOf__Scalar__&); ++ // Operateur copie ++ ArrOf__Scalar__& operator=(const ArrOf__Scalar__&); ++ // Remise du tableau dans l'etat initial (obtenu par le constructeur par defaut) ++ virtual void reset(); ++ ++ // ++ // Methodes d'acces aux donnees et aux caracteristiques du tableau ++ // ++ // Remplit le tableau avec la valeur en parametre ++ ArrOf__Scalar__& operator=(__scalar__ valeur); ++ ++ inline __scalar__& operator[](entier i); ++ inline const __scalar__& operator[](entier i) const; ++ ++ // Ces methodes renvoient un pointeur vers le premier element du tableau. ++ const __scalar__ * addr() const; ++ __scalar__ * addr(); ++ // Renvoie le nombre d'elements du tableau (et non la taille allouee) ++ inline entier size_array() const; ++ // Renvoie le nombre de tableaux qui pointent vers la stucture "*p_" ++ entier ref_count() const; ++ // Ajoute une case en fin de tableau et y stocke la "valeur" ++ inline void append_array(__scalar__ valeur); ++ ++ // ++ // Operateurs divers ++ // ++ ArrOf__Scalar__& operator+=(const ArrOf__Scalar__&); ++ ArrOf__Scalar__& operator+=(const __scalar__); ++ ArrOf__Scalar__& operator-=(const ArrOf__Scalar__&); ++ ArrOf__Scalar__& operator-=(const __scalar__); ++ ArrOf__Scalar__& inject_array(const ArrOf__Scalar__ & source, ++ entier nb_elements = -1, ++ entier first_element_dest = 0, ++ entier first_element_source = 0); ++ ArrOf__Scalar__& copy_array(const ArrOf__Scalar__&); ++ ++ __DoubleOnlyBegin__ ++ ArrOf__Scalar__& operator*= (const __scalar__) ; ++ ArrOf__Scalar__& operator/= (const __scalar__) ; ++ __DoubleOnlyEnd__ ++ ++ void ordonne_array(); ++ ++protected: ++ // ++ // Methodes accessibles depuis les descendants de ArrOf__Scalar__ ++ // ++ void attach_array(const ArrOf__Scalar__&); ++ entier detach_array(); ++ void fill_default_value(entier first, entier nb); ++private: ++ // B. Mathieu 22/06/2004 : je mets ces membres "private" pour forcer ++ // le passage par les accesseurs dans les classes derivees, au cas ou ++ // on voudrait modifier l'implementation. ++ ++ // Zone de memoire contenant les valeurs du tableau. ++ // Pointeur nul => le tableau est "detache" ou "ref_data" ++ // Pointeur non nul => le tableau est "normal" ++ V__Scalar__data* p_; ++ ++ // Pointeur vers le premier element du tableau (egal a p_->data si p_!=0) ++ // Pointeur nul => le tableau est "detache". ++ // Pointeur non nul => le tableau est "normal" ou "ref_data" ++ __scalar__* data_; ++ ++ // Nombre d'elements du tableau (inferieur ou egal a memory_size_). ++ // Si le tableau est "detache", alors size_array_=0 ++ entier size_array_; ++ // Taille memoire reellement allouee pour le tableau ++ // (pour le mecanisme smart_resize_). memory_size_ est nul ++ // si le tableau est de type "ref_data". Sinon memory_size_ ++ // est egal a p_->size_. ++ entier memory_size_; ++ ++ // Drapeau indiquant si on applique une strategie d'allocation ++ // preventive (la memoire alouee augmente d'un facteur constant ++ // si la taille devient insuffisante). ++ // Si smart_resize_ == 0, alors on a toujours p_->size_ == size ++ entier smart_resize_; ++ ++ // Drapeau indiquant si l'allocation memoire a lieu avec un new classique ++ // ou dans le pool de memoire temporaire de Trio ++ Storage storage_type_; ++ ++ // Partie non inline de resize_array(): ++ // Declaration des constantes pour les options de memory_resize ++ static const entier COPY_OLD; ++ static const entier INITIALIZE_NEW; ++ void memory_resize(entier new_size, entier options); ++}; ++ ++#define MAXDIM__Scalar__Tab 2 ++ ++class __Scalar__Tab : public ArrOf__Scalar__ ++{ ++public: ++ __Scalar__Tab(); ++ __Scalar__Tab(const __Scalar__Tab&); ++ __Scalar__Tab(const entier i, const entier j); ++ __Scalar__Tab& operator=(const __Scalar__Tab&); ++ void reset(); ++ ++ inline __scalar__& operator()(entier i, entier j); ++ inline __scalar__ operator()(entier i, entier j) const; ++ ++ inline entier resize(entier i, entier j); ++ inline entier dimension(entier i) const; ++ inline entier dimension_tot(entier i) const; ++ ++protected: ++ // In order to mimic TRUST behavior, operator[] is forbidden ++ // for 2 dimensionnal matrices, you must cast to ArrOf to use it.. ++ double& operator[](entier i); ++ const double& operator[](entier i) const; ++ ++private: ++ entier nb_dim_; ++ entier dimensions_[MAXDIM__Scalar__Tab]; ++}; ++ ++inline __scalar__& __Scalar__Tab::operator()(entier i, entier j) ++{ ++ assert(nb_dim_ == 2); ++ assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]); ++ const entier n = i * dimensions_[1] + j; ++ __scalar__ & x = ArrOf__Scalar__::operator[] (n); ++ return x; ++} ++ ++inline __scalar__ __Scalar__Tab::operator()(entier i, entier j) const ++{ ++ assert(nb_dim_ == 2); ++ assert(i >= 0 && i < dimensions_[0] && j >= 0 && j < dimensions_[1]); ++ const entier n = i * dimensions_[1] + j; ++ __scalar__ x = ArrOf__Scalar__::operator[] (n); ++ return x; ++} ++ ++inline entier __Scalar__Tab::resize(entier i, entier j) ++{ ++ assert(i >= 0 && j >= 0); ++ nb_dim_ = 2; ++ dimensions_[0] = i; ++ dimensions_[1] = j; ++ ArrOf__Scalar__::resize_array(i * j); ++ return i*j; ++} ++ ++inline entier __Scalar__Tab::dimension(entier i) const ++{ ++ assert(i >= 0 && i < nb_dim_); ++ return dimensions_[i]; ++} ++ ++// Description: renvoie la meme valeur que dimension. ++inline entier __Scalar__Tab::dimension_tot(entier i) const ++{ ++ return dimension(i); ++} ++ ++// ++// Declarations des fonctions non membres de la classe ArrOf__Scalar__ ++// ++entier operator==(const ArrOf__Scalar__& x, const ArrOf__Scalar__& y) ; ++entier imin_array(const ArrOf__Scalar__&) ; ++entier imax_array(const ArrOf__Scalar__&) ; ++__scalar__ min_array(const ArrOf__Scalar__&) ; ++__scalar__ max_array(const ArrOf__Scalar__&) ; ++ ++__DoubleOnlyBegin__ ++__scalar__ max_abs_array(const ArrOf__Scalar__&) ; ++__DoubleOnlyEnd__ ++ ++// ****************************************************************** ++// FONCTIONS MEMBRES DE ArrOf__Scalar__ ++// ****************************************************************** ++ ++// Description : ++// Change le nombre d'elements du tableau. Cette fonction est inline ++// car elle doit etre tres rapide dans le cas ou smart_resize_==1 ++// (utilisation frequente de resize_array()) ++// Si smart_resize est non nul : ++// Si la nouvelle taille est inferieure ou egale a la taille ++// alouee (p->get_size()) on ne realloue pas de memoire ++// sinon, on realloue et on copie les donnees existantes. ++// Astuce pour ne pas copier les anciennes donnees: ++// resize(0); resize(n); ++// Si smart_resize est nul, on realloue une nouvelle zone memoire ++// uniquement si la nouvelle taille est differente de l'ancienne. ++// Precondition : ++// Si "new_size" est egal a la taille du tableau, aucune condition. ++// Sinon, le tableau doit etre soit detache, soit normal (pas de type "ref_data") ++// et ref_count doit etre egal a 1 (pas d'autre reference au tableau). ++// ++inline ArrOf__Scalar__& ArrOf__Scalar__::resize_array(entier new_size) ++{ ++ assert(new_size >= 0); ++ // Soit le tableau est detache (data_==0), soit il est normal (p_!=0) ++ // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau, ++ // ou alors la taille ne doit pas changer. ++ assert(new_size == size_array_ || data_ == 0 || (p_ != 0 && ref_count() == 1)); ++ ++ if ((smart_resize_ == 0) || (new_size > memory_size_)) ++ memory_resize(new_size, COPY_OLD + INITIALIZE_NEW); ++ size_array_ = new_size; ++ return *this; ++} ++ ++// Description: ++// operateur [] retourne le ieme element du tableau ++// Precondition: ++// Parametre: entier i ++// Signification: indice dans l'intervalle 0 <= i < size_array() ++// Exception: ++__DoubleOnlyBegin__ ++// assert si la valeur sort de l'intervalle : [ -DMAXFLOAT,DMAXFLOAT ] ++__DoubleOnlyEnd__ ++// assert si i n'est pas dans l'intervalle ++inline __scalar__& ArrOf__Scalar__::operator[](entier i) ++{ ++ assert(i >= 0 && i < size_array_); ++ __DoubleOnlyBegin__ ++ assert(data_[i] > -DMAXFLOAT && data_[i] < DMAXFLOAT); ++ __DoubleOnlyEnd__ ++ return data_[i]; ++} ++ ++// Description: ++// operateur [] retourne le ieme element du tableau ++// Precondition: ++// Parametre: entier i ++// Signification: indice dans l'intervalle 0 <= i < size_array() ++// Exception: ++__DoubleOnlyBegin__ ++// assert si la valeur sort de l'intervalle : [ -DMAXFLOAT,DMAXFLOAT ] ++__DoubleOnlyEnd__ ++// assert si i n'est pas dans l'intervalle ++inline const __scalar__& ArrOf__Scalar__::operator[](entier i) const ++{ ++ assert(i >= 0 && i < size_array_); ++ __DoubleOnlyBegin__ ++ assert(data_[i] > -DMAXFLOAT && data_[i] < DMAXFLOAT); ++ __DoubleOnlyEnd__ ++ return data_[i]; ++} ++ ++// Description: ++// Renvoie la taille du tableau (nombre d'elements declares ++// a la construction ou a resize_array()). ++// C'est le nombre d'elements accessibles a operator[] ++// Retour: entier ++inline entier ArrOf__Scalar__::size_array() const ++{ ++ return size_array_; ++} ++ ++// Description: ++// Ajoute une case en fin de tableau et y stocke la "valeur" ++// Precondition: ++// Tableau doit etre de type "smart_resize" (sinon, ecroulement ++// des performances). De plus, le tableau ne doit pas etre "ref_data", ++// et il ne doit pas y avoir plus d'une reference a la zone de ++// memoire pointee (meme precondition que resize_array()) ++inline void ArrOf__Scalar__::append_array(__scalar__ valeur) ++{ ++ assert(smart_resize_); ++ // Soit le tableau est detache (data_==0), soit il est normal (p_!=0) ++ // S'il est normal, il ne faut pas qu'il y ait d'autre reference au tableau. ++ assert(data_ == 0 || (p_ != 0 && ref_count() == 1)); ++ ++ if (size_array_+1 > memory_size_) ++ memory_resize(size_array_+1, COPY_OLD); ++ data_[size_array_] = valeur; ++ size_array_++; ++} ++ ++// ArrOf__Scalar___H ++#endif +diff --git a/databases/readers/Lata/CMakeLists.txt b/databases/readers/Lata/CMakeLists.txt +new file mode 100644 +index 0000000..be611f3 +--- /dev/null ++++ b/databases/readers/Lata/CMakeLists.txt +@@ -0,0 +1,35 @@ ++set(SOURCES ++ avtlataFileFormat.C ++ LataDB.C ++ LataFilter.C ++ LataStructures.C ++ Lata_tools.C ++ LataV1_field_definitions.C ++ LataWriter.C ++ LmlReader.C ++ OpenDXWriter.C ++ OperatorBoundary.C ++ OperatorDualMesh.C ++ OperatorFacesMesh.C ++ OperatorReconnect.C ++ OperatorRegularize.C ++ Rebuild_virtual_layer.C ++ UserFields.C ++ ArrOfBit.C ++ ArrOfDouble.C ++ ArrOfFloat.C ++ ArrOfInt.C ++ Connectivite_som_elem.C ++ Motcle.C ++ Octree_Double.C ++ Octree_Int.C ++ Static_Int_Lists.C ++ ) ++ ++MESSAGE("Here I am") ++ ++ADD_VISIT_READER(VisItLataReader "1.0" ++ VISIT_READER_TYPE "MTMD" ++ VISIT_READER_NAME "avtlataFileFormat" ++ SERVER_SOURCES ${SOURCES} ++ ) +diff --git a/databases/readers/Lata/Connectivite_som_elem.C b/databases/readers/Lata/Connectivite_som_elem.C +new file mode 100644 +index 0000000..2a268cc +--- /dev/null ++++ b/databases/readers/Lata/Connectivite_som_elem.C +@@ -0,0 +1,189 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++#include ++ ++// Description: construction de la structure som_elem pour la zone donnee ++// On cree pour chaque sommet i la liste des elements adjacents a ce sommet ++// (c'est la liste des elements k tels que il existe j tel que les_elems(k,j) == i) ++// Parametre: nb_sommets ++// Description: nombre de sommets utilises dans les elements (som_elem contiendra ++// autant de listes). Si include_virtual==1, c'est le nombre de sommets ++// total, sinon c'est le nombre de sommets reels ++// Parametre: les_elems ++// Description: tableau des elements (contient les numeros des sommets de chaque element) ++// Les valeurs du tableau doivent etre inferieurs a nb_sommets. ++// Parametre: som_elem ++// Description: la structure dans laquelle on stocke le resultat. L'ancien ++// contenu est perdu. Chaque liste d'elements est triee dans l'ordre croissant ++// Parametre: include_virtual ++// Description: 0 => seuls les elements reels sont inclus dans la structure ++// 1 => on inclut les elements virtuels (donc les sommets virtuels) ++void construire_connectivite_som_elem(const entier nb_sommets, ++ const IntTab& les_elems, ++ Static_Int_Lists& som_elem, ++ const entier include_virtual) ++{ ++ // Nombre d'elements du domaine ++ const entier nb_elem = (include_virtual) ? les_elems.dimension_tot(0) : les_elems.dimension(0); ++ // Nombre de sommets par element ++ const entier nb_sommets_par_element = les_elems.dimension(1); ++ ++ // Construction d'un tableau initialise a zero : pour chaque sommet, ++ // nombre d'elements voisins de ce sommet ++ ArrOfInt nb_elements_voisins(nb_sommets, 0); ++ ++ // Premier passage : on calcule le nombre d'elements voisins de chaque ++ // sommet pour creer la structure de donnees ++ entier elem, i; ++ ++ for (elem = 0; elem < nb_elem; elem++) ++ { ++ for (i = 0; i < nb_sommets_par_element; i++) ++ { ++ entier sommet = les_elems(elem, i); ++ // GF cas des polyedres ++ if (sommet==-1) break; ++ nb_elements_voisins[sommet]++; ++ } ++ } ++ ++ som_elem.set_list_sizes(nb_elements_voisins); ++ ++ // On reutilise le tableau pour stocker le nombre d'elements dans ++ // chaque liste pendant qu'on la remplit ++ nb_elements_voisins = 0; ++ ++ // Remplissage du tableau des elements voisins. ++ for (elem = 0; elem < nb_elem; elem++) ++ { ++ for (i = 0; i < nb_sommets_par_element; i++) ++ { ++ entier sommet = les_elems(elem, i); ++ // GF cas des polyedres ++ if (sommet==-1) break; ++ entier n = (nb_elements_voisins[sommet])++; ++ som_elem.set_value(sommet, n, elem); ++ } ++ } ++ ++ // Tri de toutes les listes dans l'ordre croissant ++ som_elem.trier_liste(-1); ++} ++ ++// Description: Cherche les elements qui contiennent tous les sommets ++// du tableau sommets_to_find (permet de trouver les elements ++// adjacents a une face ou une arete) ++// Parametre: som_elem ++// Signification: pour chaque sommet, liste triee des elements adjacents ++// (voir construire_connectivite_som_elem) ++// Parametre: sommets_to_find ++// Signification: une liste de sommets ++// Parametre: elements ++// Signification: resultat de la recherche: la liste des elements qui ++// contiennent tous les sommets de sommets_to_find. ++// Si sommets_to_find est vide, on renvoie un tableau vide. ++// (en cas d'appels repetes a cette fonction, il est ++// conseille de mettre le drapeau "smart_resize") ++void find_adjacent_elements(const Static_Int_Lists& som_elem, ++ const ArrOfInt& sommets_to_find, ++ ArrOfInt& elements) ++{ ++ entier nb_som_to_find = sommets_to_find.size_array(); ++ // on retire les sommets valant -1 (cas ou plusieurs types de faces) ++ while (sommets_to_find[nb_som_to_find-1]==-1) nb_som_to_find--; ++ if (nb_som_to_find == 0) ++ { ++ elements.resize_array(0); ++ return; ++ } ++ // Algorithme: on initialise elements avec tous les elements adjacents ++ // au premier sommet de la liste. ++ // Puis pour chacun des autres sommets de la liste, on retire du tableau ++ // "elements" les elements qui ne sont pas voisins du sommet. ++ // A la fin, il ne reste que les elements qui sont dans toutes les listes. ++ { ++ // Initialisation avec les elements adjacents au premier sommet ++ const entier sommet = sommets_to_find[0]; ++ som_elem.copy_list_to_array(sommet, elements); ++ } ++ entier nb_elem_found = elements.size_array(); ++ entier i_sommet; ++ for (i_sommet = 1; i_sommet < nb_som_to_find; i_sommet++) ++ { ++ const entier sommet = sommets_to_find[i_sommet]; ++ // Calcul des elements communs entre elements[.] et som_elem(sommet,.) ++ // Nombre d'elements communs entre elements et la nouvelle liste de sommets ++ entier nb_elems_restants = 0; ++ // Nombre d'elements adjacents au "sommet" ++ const entier nb_elem_liste = som_elem.get_list_size(sommet); ++ // On suppose que les listes d'elements sont triees dans l'ordre croissant ++ // On parcourt simultanement les deux listes et on conserve les elements ++ // communs. ++ entier i = 0; ++ entier j = 0; ++ if (nb_elem_found == 0) ++ break; ++ if (nb_elem_liste > 0) ++ { ++ while (1) ++ { ++ const entier elem_i = elements[i]; ++ const entier elem_j = som_elem(sommet, j); ++ if (elem_i == elem_j) ++ { ++ // Element commun aux deux listes, on le garde ++ elements[nb_elems_restants] = elem_i; ++ nb_elems_restants++; ++ } ++ if (elem_i >= elem_j) ++ { ++ j++; ++ if (j >= nb_elem_liste) ++ break; ++ } ++ if (elem_j >= elem_i) ++ { ++ i++; ++ if (i >= nb_elem_found) ++ break; ++ } ++ } ++ } ++ else ++ { ++ nb_elems_restants = 0; ++ } ++ nb_elem_found = nb_elems_restants; ++ } ++ elements.resize_array(nb_elem_found); ++} ++ +diff --git a/databases/readers/Lata/Connectivite_som_elem.h b/databases/readers/Lata/Connectivite_som_elem.h +new file mode 100644 +index 0000000..758b030 +--- /dev/null ++++ b/databases/readers/Lata/Connectivite_som_elem.h +@@ -0,0 +1,44 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++ ++#include ++ ++class IntTab; ++class ArrOfInt; ++class Static_Int_Lists; ++ ++void construire_connectivite_som_elem(const entier nb_sommets, ++ const IntTab& les_elems, ++ Static_Int_Lists& som_elem, ++ const entier include_virtual); ++ ++void find_adjacent_elements(const Static_Int_Lists& som_elem, ++ const ArrOfInt& sommets_to_find, ++ ArrOfInt& elements); +diff --git a/databases/readers/Lata/DoubleTab.h b/databases/readers/Lata/DoubleTab.h +new file mode 100644 +index 0000000..1731563 +--- /dev/null ++++ b/databases/readers/Lata/DoubleTab.h +@@ -0,0 +1,30 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include +diff --git a/databases/readers/Lata/EFichier.h b/databases/readers/Lata/EFichier.h +new file mode 100644 +index 0000000..3cf0ee8 +--- /dev/null ++++ b/databases/readers/Lata/EFichier.h +@@ -0,0 +1,60 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef EFichier_H ++#define EFichier_H ++#include ++class EFichier : public Entree ++{ ++public: ++ int ouvrir(const char *name) ++ { ++ is_.open(name); ++ return is_.good(); ++ } ++ operator std::istream& () ++ { ++ return is_; ++ } ++ int eof() ++ { ++ return is_.eof(); ++ } ++ int good() ++ { ++ return is_.good(); ++ } ++ std::istream& get_istream() ++ { ++ return is_; ++ } ++private: ++ std::ifstream is_; ++}; ++#endif +diff --git a/databases/readers/Lata/Entree.h b/databases/readers/Lata/Entree.h +new file mode 100644 +index 0000000..2f36fea +--- /dev/null ++++ b/databases/readers/Lata/Entree.h +@@ -0,0 +1,77 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef Entree_H ++#define Entree_H ++#include ++#include ++#include ++// This class emulates the main functionalities of the Entree and EFichier classes in TRUST ++class Entree ++{ ++public: ++ virtual operator std::istream& () = 0; ++ virtual int eof() = 0; ++ virtual int good() = 0; ++ virtual ~Entree() {}; ++ virtual std::istream& get_istream() = 0; ++}; ++ ++inline Entree& operator>>(Entree& is, double& t) ++{ ++ is.get_istream() >> t; ++ return is; ++} ++inline Entree& operator>>(Entree& is, float& t) ++{ ++ is.get_istream() >> t; ++ return is; ++} ++inline Entree& operator>>(Entree& is, Nom& n) ++{ ++ is.get_istream() >> n; ++ return is; ++} ++inline Entree& operator>>(Entree& is, Motcle& n) ++{ ++ is.get_istream() >> n; ++ return is; ++} ++inline Entree& operator>>(Entree& is, entier& n) ++{ ++ is.get_istream() >> n; ++ return is; ++} ++class ArrOfInt; ++// For Static_Int_Lists: ++inline Entree& operator>>(Entree& is, ArrOfInt& t) ++{ ++ throw; ++} ++#endif +diff --git a/databases/readers/Lata/FloatTab.h b/databases/readers/Lata/FloatTab.h +new file mode 100644 +index 0000000..351313d +--- /dev/null ++++ b/databases/readers/Lata/FloatTab.h +@@ -0,0 +1,30 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include +diff --git a/databases/readers/Lata/IntTab.h b/databases/readers/Lata/IntTab.h +new file mode 100644 +index 0000000..c8cb65c +--- /dev/null ++++ b/databases/readers/Lata/IntTab.h +@@ -0,0 +1,31 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++ +diff --git a/databases/readers/Lata/LataDB.C b/databases/readers/Lata/LataDB.C +new file mode 100644 +index 0000000..84e4cc4 +--- /dev/null ++++ b/databases/readers/Lata/LataDB.C +@@ -0,0 +1,2313 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++// Verbose level for which main lata file interpretation should be printed: ++// Dump one line for the whole file at verb_level-1 ++// Dump one line for each Geometry, Temps, or Champ at verb_level ++// Detailed Geometry and Champ metadata is printed out at verb_level+1 ++#define verb_level 4 ++// Verbose level for data bloc reading: ++// Dump one line for each read data bloc at this level ++// Dump detailed subbloc interpretation at level+1 ++#define verb_level_data_bloc 5 ++ ++typedef int LataDBInt32; ++typedef long long int LataDBInt64; ++ ++void arch_check() ++{ ++ if (sizeof(LataDBInt32)!=4) ++ Journal() << "Error in LataDB arch_check : wrong LataDBInt32" << endl; ++ if (sizeof(LataDBInt64)!=8) ++ Journal() << "Error in LataDB arch_check : wrong LataDBInt64" << endl; ++} ++ ++const char * LataDBField::memory_buffer_file() ++{ ++ return "MEMORY_BUFFERED_DATA"; ++} ++ ++Field_UName::Field_UName() ++{ ++} ++ ++Field_UName::Field_UName(const Field_UName & f) : ++ geometry_(f.geometry_), field_name_(f.field_name_), loc_(f.loc_) ++{ ++} ++ ++Field_UName::Field_UName(const char *domain_name, const char *field_name, const char *loc) : ++ geometry_(domain_name), field_name_(field_name), loc_(loc) ++{ ++ if (loc_ == "??") ++ loc_ = ""; ++} ++ ++Field_UName & Field_UName::operator=(const Field_UName & f) ++{ ++ geometry_ = f.geometry_; ++ field_name_ = f.field_name_; ++ loc_ = f.loc_; ++ return *this; ++} ++ ++Nom Field_UName::build_string() const ++{ ++ Nom n(geometry_); ++ n += "_"; ++ n += field_name_; ++ if (loc_ != "" && loc_ != "??") { ++ n += "_"; ++ n += loc_; ++ } ++ return n; ++} ++ ++void Field_UName::set_field_name(const Nom & n) ++{ ++ field_name_ = n; ++} ++ ++int Field_UName::operator==(const Field_UName & f) const ++{ ++ return (geometry_ == f.geometry_) && (field_name_ == f.field_name_) && (loc_ == f.loc_); ++} ++ ++std::ostream & operator<<(std::ostream & os, const Field_UName & uname) ++{ ++ os << uname.build_string(); ++ return os; ++} ++ ++// This is a duplicate of Domain... only used for old latav1 compatibility ++// (otherwise, LataDB should not have to know about element types !) ++LataDB::Element LataDB::element_type_from_string(const Motcle & type_elem) ++{ ++ Element type; ++ if (type_elem == "HEXAEDRE") ++ type=hexa; ++ else if (type_elem == "HEXAEDRE_AXI") ++ type=hexa; ++ else if (type_elem == "HEXAEDRE_VEF") ++ type=hexa; ++ else if (type_elem == "QUADRANGLE") ++ type=quadri; ++ else if (type_elem == "QUADRANGLE_3D") ++ type=quadri; ++ else if (type_elem == "RECTANGLE") ++ type=quadri; ++ else if (type_elem == "RECTANGLE_2D_AXI") ++ type=quadri; ++ else if (type_elem == "RECTANGLE_AXI") ++ type=quadri; ++ else if (type_elem == "SEGMENT") ++ type=line; ++ else if (type_elem == "SEGMENT_2D") ++ type=line; ++ else if (type_elem == "TETRAEDRE") ++ type=tetra; ++ else if (type_elem == "TRIANGLE") ++ type=triangle; ++ else if (type_elem == "TRIANGLE_3D") ++ type=triangle; ++ else if (type_elem.debute_par("POLYEDRE")) ++ type=polyedre; ++ else if (type_elem.debute_par("POLYGONE")) ++ type=polygone; ++ else { ++ Journal() << "Error in elem_type_from_string: unknown element type " << type_elem << endl; ++ throw(LataDBError(LataDBError::BAD_ELEM_TYPE)); ++ } ++ return type; ++} ++ ++void LataDB::get_element_data(const Motcle & elemtype, entier & dimension, entier & elem_shape, entier & face_shape, entier & nb_elem_faces) ++{ ++ Element elem = element_type_from_string(elemtype); ++ switch(elem) { ++ case line: dimension = 2; elem_shape=2; face_shape=1; nb_elem_faces=2; break; ++ case triangle: dimension = (elemtype=="TRIANGLE") ? 2 : 3; ++ elem_shape=3; face_shape=2; nb_elem_faces=3; break; ++ case quadri: dimension = (elemtype=="QUADRANGLE_3D") ? 3 : 2; ++ elem_shape=4; face_shape=2; nb_elem_faces=4; break; ++ case tetra: dimension = 3; elem_shape=4; face_shape=3; nb_elem_faces=4; break; ++ case hexa: dimension = 3; elem_shape=8; face_shape=4; nb_elem_faces=6; break; ++ case polyedre: dimension = 3; elem_shape=-1; face_shape=-1; nb_elem_faces=-1; break; ++ case polygone: dimension = 2; elem_shape=-1; face_shape=-1; nb_elem_faces=-1; break; ++ default: ++ Journal() << "LataDB::get_element_data element is unspecified" << endl; ++ throw(LataDBError(LataDBError::BAD_ELEM_TYPE)); ++ } ++} ++ ++// Description: in lata v1 format, the number of components in a Champ entry ++// is implicitely defined by the field name and the discretisation ++entier LataDB::lata_v1_get_nb_comp(const Nom & fieldname, const Motcle & localisation, ++ const LataDBGeometry & dom, entier dim, LataDBField::Nature & nature, ++ LataDBDataType::DataOrdering & ordering) ++{ ++ // Search component name in std_components ++ entier nb_comp = latav1_component_shape(fieldname); ++ Motcle maj_field(fieldname); ++ ordering = LataDBDataType::C_ORDERING; ++ nature = LataDBField::SCALAR; ++ Journal(verb_level+1) << " LataV2 known component name found : " << fieldname << endl; ++ if (nb_comp == -1) { ++ // This is a vector component. If it's not a VDF faces, nb_comp = dimension of the problem ++ Element elt = element_type_from_string(dom.elem_type_); ++ if (localisation == "FACES" && (elt == quadri || elt == hexa)) { ++ nb_comp = 1; ++ Journal(verb_level+1) << " Vector field. Detected a VDF faces discretisation => nb_comp=1" << endl; ++ } else { ++ nb_comp = dim; ++ nature = LataDBField::VECTOR; ++ ordering = LataDBDataType::F_ORDERING; ++ Journal(verb_level+1) << " Vector field. nb_comp = dimension = " << nb_comp << endl; ++ Journal(verb_level+1) << " Assume fortran ordering" << endl; ++ } ++ } else if (nb_comp == -2) { ++ // This is the vorticity: scalar in 2D, vector in 3D ++ if (dim == 2) ++ { ++ nb_comp = 1; ++ Journal(verb_level+1) << " Scalar field, nb_comp=" << nb_comp << endl; ++ } ++ else ++ { ++ nb_comp = dim; ++ nature = LataDBField::VECTOR; ++ ordering = LataDBDataType::F_ORDERING; ++ Journal(verb_level+1) << " Vector field. nb_comp = dimension = " << nb_comp << endl; ++ Journal(verb_level+1) << " Assume fortran ordering" << endl; ++ } ++ } else { ++ //if (maj_field == "K_EPS") { ++ if (nb_comp>1) { ++ ordering = LataDBDataType::F_ORDERING; ++ Journal(verb_level+1) << " Special K_EPS => Assume fortran ordering" << endl; ++ } ++ Journal(verb_level+1) << " Scalar field, nb_comp=" << nb_comp << endl; ++ } ++ return nb_comp; ++} ++ ++// Description: in lata v1 format, the localisation is implicitely defined by the ++// file name of the data file: ++void lata_v1_get_localisation(const char * filename, Nom & localisation_) ++{ ++ if (strstr(filename, ".SOM.")) ++ localisation_ = "SOM"; ++ else if (strstr(filename, ".ELEM.")) ++ localisation_ = "ELEM"; ++ else if (strstr(filename, ".FACES.")) ++ localisation_ = "FACES"; ++ else { ++ Journal() << "Error in lata_v1_get_localisation. Unable to find localisation in filename\n" ++ << filename << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++} ++ ++class LataDataFile ++{ ++public: ++ enum Mode { READ, WRITE, APPEND }; ++ LataDataFile(std::iostream & mem_buffer, const char *prefix, const char *name, const LataDBDataType::MSB& msb, Mode mode = READ) ++ { ++ exception_ = 1; ++ msb_=msb; ++ if (strcmp(name, LataDBField::memory_buffer_file()) == 0) { ++ stream_ = &mem_buffer; ++ fname_ = name; ++ Journal(verb_level_data_bloc) << "LataDB: opening internal memory_buffer for read/write" << endl; ++ if (mode == READ) ++ (*stream_).seekg(0, std::ios::beg); ++ else if (mode == WRITE) ++ { // on ne repositionne pas sur un fichier vide, Visual ne supporte pas ++ // et c'est inutil ++ if ((*stream_).tellp()>=0) ++ (*stream_).seekp(0, std::ios::beg); ++ } ++ else ++ { ++ if ((*stream_).tellp()>=0) ++ (*stream_).seekp(0, std::ios::end); ++ } ++ Journal(verb_level_data_bloc+1) << " current position: " << position() << endl; ++ if (!fstream_.good()) { ++ Journal() << "LataDataFile: Memory stream error" << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++ } else { ++ stream_ = &fstream_; ++ fname_ = prefix;; ++ fname_ += name; ++ Journal(verb_level_data_bloc) << "LataDB: opening data file " << fname_ << endl; ++ if (msb_ == LataDBDataType::ASCII) { ++ switch(mode) { ++ case READ: fstream_.open(fname_, std::fstream::in); break; ++ case WRITE: fstream_.open(fname_, std::fstream::out); break; ++ case APPEND: fstream_.open(fname_, std::fstream::out | std::fstream::app); break; ++ } ++ } ++ else ++ { ++ if (msb_ != LataDBDataType::machine_msb_) { ++ Journal() << "LataDB LataDataFile::write(int) not coded for reverse binary msb" << endl; ++ throw; ++ } ++ switch(mode) { ++ case READ: fstream_.open(fname_, std::fstream::in|std::fstream::binary); break; ++ case WRITE: fstream_.open(fname_, std::fstream::out|std::fstream::binary); break; ++ case APPEND: fstream_.open(fname_, std::fstream::out | std::fstream::app|std::fstream::binary); break; ++ } ++ } ++ if (!fstream_.good()) { ++ Journal() << "File not found " << fname_ << endl; ++ throw LataDBError(LataDBError::FILE_NOT_FOUND); ++ } ++ } ++ } ++ void set_exception(int i) { exception_ = i; } ++ FileOffset position() { return (*stream_).tellp(); }; ++ enum SeekType { ABSOLUTE, RELATIVE }; ++ void seek(FileOffset pos, SeekType seekt) { ++ Journal(verb_level_data_bloc+1) << "Seeking file " << fname_ ++ << ((seekt == ABSOLUTE) ? " absolute position " : " relative position ") ++ << pos << endl; ++ if (seekt == ABSOLUTE) ++ (*stream_).seekg(pos, std::ios::beg); ++ else ++ (*stream_).seekg(pos, std::ios::cur); ++ ++ if (exception_ && !(*stream_).good()) { ++ Journal() << "Error seeking to position " << pos << " in file " << fname_ << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++ } ++ void set_encoding(LataDBDataType::MSB msb, LataDBDataType::Type type) { msb_ = msb; type_ = type; }; ++ void set_err_message(const char *message) { message_ = message; }; ++ LataDataFile & operator>>(LataDBInt32 & x) { read(&x, 1); return *this; }; ++ LataDataFile & operator>>(float & x) { read(&x, 1); return *this; }; ++ LataDataFile & operator>>(Nom & n) { ++ n = ""; ++ if (msb_ != LataDBDataType::ASCII) { ++ for (;;) { ++ char c[2]; ++ c[1] = 0; ++ (*stream_).get(c[0]); ++ ++ if (!(*stream_).good()) ++ break; ++ ++ if (c[0] == '\0') ++ break; ++ ++ n += c; ++ } ++ } else { ++ std::string tmp; ++ (*stream_) >> tmp; ++ if ((*stream_).good()) ++ n = tmp.c_str(); ++ } ++ if (exception_ && !(*stream_).good()) { ++ Journal() << "Error reading string in file " << fname_ << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++ return *this; ++ } ++ void read(LataDBInt32 *ptr, BigEntier n); ++ void read(float *ptr, BigEntier n); ++ LataDataFile & operator<<(LataDBInt32 & x) { write(&x, 1, 1); return *this; }; ++ LataDataFile & operator<<(float & x) { write(&x, 1, 1); return *this; }; ++ void write(const LataDBInt32 *ptr, BigEntier n, BigEntier col); ++ void write(const float *ptr, BigEntier n, BigEntier col); ++ ++protected: ++ Nom fname_; ++ const char * message_; // Message printed if error. ++ std::fstream fstream_; ++ std::iostream *stream_; // Points to fstream_ or mem_buffer passed to constructor ++ LataDBDataType::MSB msb_; ++ LataDBDataType::Type type_; ++ int exception_; ++}; ++ ++void LataDataFile::read(LataDBInt32 *ptr, BigEntier n) ++{ ++ if (type_ != LataDBDataType::INT32 && type_ != LataDBDataType::INT64) { ++ Journal() << "Error in lataDB bloc read: trying to read non integer data into integer array" << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++ if (msb_ == LataDBDataType::ASCII) { ++ BigEntier i; ++ if (ptr) ++ Journal(verb_level_data_bloc+1) << "Reading ascii int data bloc size=" << n << endl; ++ else ++ Journal(verb_level_data_bloc+1) << "Skipping ascii int data bloc size=" << n << endl; ++ LataDBInt32 toto; ++ for (i = 0; i < n; i++) { ++ if (ptr) ++ (*stream_) >> ptr[i]; ++ else ++ (*stream_) >> toto; ++ if (exception_ && !(*stream_).good()) { ++ Journal() << "Error reading ascii file " << fname_ << " LataDBInt32[" << n << "] at index " ++ << i << endl << (message_?message_:"") << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++ } ++ } else { ++ if (type_ != LataDBDataType::INT32) { ++ Journal() << "Internal error in LataDB.cpp LataDataFile::read(LataDBInt32) : size conversion not coded" << endl; ++ throw; ++ } ++ if (ptr) { ++ Journal(verb_level_data_bloc+1) << "Reading binary int data bloc size=" << n << endl; ++ (*stream_).read((char*)ptr, n * sizeof(LataDBInt32)); ++ } else { ++ Journal(verb_level_data_bloc+1) << "Skipping binary int data bloc size=" << n << endl; ++ seek(n * sizeof(LataDBInt32), RELATIVE); ++ } ++ if (exception_ && !(*stream_).good()) { ++ Journal() << "Error reading binary file " << fname_ << " LataDBInt32[" << n << "]" ++ << endl << (message_?message_:"") << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++ if (msb_ != LataDBDataType::machine_msb_) { ++ Journal() << "LataDB LataDataFile::read(LataDBInt32) not coded for reverse binary msb" << endl; ++ throw; ++ // Put code here (and test !) to reverse bytes in the binary bloc: ++ } ++ } ++} ++ ++void LataDataFile::read(float *ptr, BigEntier n) ++{ ++ if (type_ != LataDBDataType::REAL32) { ++ Journal() << "Error in lataDB bloc read: trying to read non float data into float array" << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++ if (msb_ == LataDBDataType::ASCII) { ++ BigEntier i; ++ if (ptr) ++ Journal(verb_level_data_bloc+1) << "Reading ascii float data bloc size=" << n << endl; ++ else ++ Journal(verb_level_data_bloc+1) << "Skipping ascii float data bloc size=" << n << endl; ++ float toto; ++ for (i = 0; i < n; i++) { ++ if (ptr) ++ (*stream_) >> ptr[i]; ++ else ++ (*stream_) >> toto; ++ if (exception_ && !(*stream_).good()) { ++ Journal() << "Error reading ascii file " << fname_ << " float[" << n << "] at index " ++ << i << endl << message_ << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++ } ++ } else { ++ if (ptr) { ++ Journal(verb_level_data_bloc+1) << "Reading binary float data bloc size=" << n << endl; ++ (*stream_).read((char*)ptr, n * sizeof(float)); ++ } else { ++ Journal(verb_level_data_bloc+1) << "Skipping binary float data bloc size=" << n << endl; ++ seek(n * sizeof(float), RELATIVE); ++ } ++ if (exception_ && !(*stream_).good()) { ++ Journal() << "Error reading binary file " << fname_ << " float[" << n << "]" ++ << endl << message_ << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++ if (msb_ != LataDBDataType::machine_msb_) { ++ Journal() << "LataDB LataDataFile::read(float) not coded for reverse binary msb" << endl; ++ throw; ++ // Put code here (and test !) to reverse bytes in the binary bloc: ++ } ++ } ++} ++ ++void LataDataFile::write(const LataDBInt32 *ptr, BigEntier n, BigEntier columns) ++{ ++ Journal(verb_level_data_bloc+1) << "Writing int data bloc size=" << n << endl; ++ if (type_ != LataDBDataType::INT32) { ++ Journal() << "Error in lataDB bloc write: trying to write integer data to non integer file block" << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++ if (msb_ == LataDBDataType::ASCII) { ++ for (BigEntier i = 0; i < n; i+=columns) { ++ BigEntier j; ++ for (j = 0; j < columns-1; j++) ++ (*stream_) << ptr[i+j] << " "; ++ (*stream_) << ptr[i+j] << endl; ++ } ++ } else { ++ if (msb_ != LataDBDataType::machine_msb_) { ++ Journal() << "LataDB LataDataFile::write(int) not coded for reverse binary msb" << endl; ++ throw; ++ // Put code here (and test !) to reverse bytes in the binary bloc: ++ } ++ (*stream_).write((char*)ptr, n * sizeof(LataDBInt32)); ++ } ++ (*stream_).seekg(0, std::ios::end); ++ if (exception_ && !(*stream_).good()) { ++ Journal() << "Error writing file " << fname_ << " int[" << n << "]" ++ << endl << message_ << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++} ++ ++void LataDataFile::write(const float *ptr, BigEntier n, BigEntier columns) ++{ ++ Journal(verb_level_data_bloc+1) << "Writing float data bloc size=" << n << endl; ++ if (type_ != LataDBDataType::REAL32) { ++ Journal() << "Error in lataDB bloc write: trying to write float data to non float file block" << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++ if (msb_ == LataDBDataType::ASCII) { ++ for (BigEntier i = 0; i < n; i+=columns) { ++ BigEntier j; ++ for (j = 0; j < columns-1; j++) ++ (*stream_) << ptr[i+j] << " "; ++ (*stream_) << ptr[i+j] << endl; ++ } ++ } else { ++ if (msb_ != LataDBDataType::machine_msb_) { ++ Journal() << "LataDB LataDataFile::write(float) not coded for reverse binary msb" << endl; ++ throw; ++ // Put code here (and test !) to reverse bytes in the binary bloc: ++ } ++ (*stream_).write((char*)ptr, n * sizeof(float)); ++ } ++ (*stream_).seekg(0, std::ios::end); ++ if (exception_ && !(*stream_).good()) { ++ Journal() << "Error writing file " << fname_ << " float[" << n << "]" ++ << endl << message_ << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++} ++ ++// Description: skips a fortran bloc size descriptor. ++void skip_blocksize(LataDataFile & f, const LataDBDataType & type) ++{ ++ if (type.fortran_bloc_markers_ == LataDBDataType::NO_BLOC_MARKER) ++ return; ++ f.set_err_message("Error reading fortran blocsize"); ++ f.set_encoding(type.msb_, type.bloc_marker_type_); ++ int i; ++ f >> i; ++ Journal(verb_level_data_bloc+1) << "Skipping blocsize marker value=" << i << endl; ++} ++ ++template ++DEST_TYPE int_conversion(LataDBInt64 x, const char * err_msg = 0) ++{ ++ DEST_TYPE result = (DEST_TYPE) x; ++ if ((LataDBInt64) result != x) { ++ if (err_msg) ++ Journal() << "LataDB integer conversion failed: " << err_msg << endl; ++ else ++ Journal() << "LataDB integer conversion failed: " << endl; ++ throw(LataDBError(LataDBError::INTEGER_OVERFLOW)); ++ } ++ return result; ++} ++ ++void write_blocksize(LataDataFile & f, const LataDBDataType & type, entier sz) ++{ ++ if (type.fortran_bloc_markers_ == LataDBDataType::NO_BLOC_MARKER) ++ return; ++ ++ Journal(verb_level_data_bloc+1) << "Writing blocsize marker value=" << sz << endl; ++ f.set_err_message("Error writing fortran blocsize"); ++ f.set_encoding(type.msb_, type.bloc_marker_type_); ++ f << sz; ++} ++ ++void bloc_read_skip(LataDataFile & f, LataDBDataType::MSB msb, LataDBDataType::Type type, BigEntier size) ++{ ++ f.set_encoding(msb, type); ++ switch(type) { ++ case LataDBDataType::INT32: f.read((LataDBInt32*) 0, size); break; ++ case LataDBDataType::REAL32: f.read((float*) 0, size); break; ++ default: ++ Journal() << "Internal error: bloc read skip not code for this type" << endl; ++ throw; ++ } ++} ++ ++// Description: Read "tab.size_array()" values from file "f" at current file location ++// into the "tab" array. "msb" and "type" must match the data type written in the file. ++void bloc_read(LataDataFile & f, LataDBDataType::MSB msb, LataDBDataType::Type type, ++ ArrOfInt & tab) ++{ ++ f.set_encoding(msb, type); ++ f.read(tab.addr(), tab.size_array()); ++} ++ ++void bloc_read(LataDataFile & f, LataDBDataType::MSB msb, LataDBDataType::Type type, ++ ArrOfFloat & tab) ++{ ++ f.set_encoding(msb, type); ++ f.read(tab.addr(), tab.size_array()); ++} ++ ++void bloc_write(LataDataFile & f, LataDBDataType::MSB msb, LataDBDataType::Type type, ++ const ArrOfInt & tab, int columns) ++{ ++ f.set_encoding(msb, type); ++ f.write(tab.addr(), tab.size_array(), columns); ++} ++ ++void bloc_write(LataDataFile & f, LataDBDataType::MSB msb, LataDBDataType::Type type, ++ const ArrOfFloat & tab, int columns) ++{ ++ f.set_encoding(msb, type); ++ f.write(tab.addr(), tab.size_array(), columns); ++} ++ ++LataDBDataType::MSB LataDBDataType::machine_msb_ = (mymachine_msb) ? LataDBDataType::MSB_BIG_ENDIAN : LataDBDataType::MSB_LITTLE_ENDIAN; ++ ++void LataDB::add(entier tstep, const LataDBGeometry & item) ++{ ++ Noms names = geometry_names(tstep); ++ if (names.rang(item.name_) >= 0) { ++ Journal() << "Error in LataDBTimestep::add(const LataDBGeometry &): duplicate geometry name " << item.name_ << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++ timesteps_[tstep].geoms_.add(item); ++} ++ ++void LataDB::add(entier tstep, const LataDBField & item) ++{ ++ LataDBField & field = timesteps_[tstep].fields_.add(item); ++ field.timestep_ = tstep; ++ field.uname_ = Field_UName(item.geometry_, item.name_, item.localisation_); ++ Journal(verb_level+1) << "LataDB::add " << tstep << " " << field.uname_ << endl; ++} ++ ++// Description: returns the number of timesteps in the database ++// (timestep 0 contains geometries and fields defined before the first TEMPS entry, ++// hence nb_timesteps() == number of TEMPS entries plus 1) ++// Exceptions: BAD_TIMESTEP ++entier LataDB::nb_timesteps() const ++{ ++ return timesteps_.size(); ++} ++ ++// Description: returns the physical time for this timestep ++// Exceptions: BAD_TIMESTEP ++double LataDB::get_time(entier tstep) const ++{ ++ return get_tstep(tstep).time_; ++} ++ ++// Description: returns the requested geometry in the requested timestep ++// "where" tells where to seach this geometry (in the current timestep or ++// also in the first timestep. ++// Exceptions: BAD_TIMESTEP NAME_NOT_FOUND ++const LataDBGeometry & LataDB::get_geometry(entier tstep, const char* name, ++ TStepSelector where) const ++{ ++ if (!name) ++ throw(LataDBError(LataDBError::NAME_NOT_FOUND)); ++ while (1) { ++ const LataDBTimestep & t = get_tstep(tstep); ++ const entier n = t.geoms_.size(); ++ for (entier i = 0; i < n; i++) { ++ const LataDBGeometry & geom = t.geoms_[i]; ++ if (geom.name_ == name) ++ return geom; ++ } ++ if (where == FIRST_AND_CURRENT && tstep > 0) ++ tstep = 0; ++ else ++ break; ++ } ++ throw(LataDBError(LataDBError::NAME_NOT_FOUND)); ++} ++ ++// Description: returns the requested field in the requested timestep. ++// Exceptions: BAD_TIMESTEP NAME_NOT_FOUND ++const LataDBField & LataDB::get_field(entier tstep, const Field_UName & uname, ++ TStepSelector where) const ++{ ++ while (1) { ++ const LataDBTimestep & t = get_tstep(tstep); ++ const entier n = t.fields_.size(); ++ for (entier i = 0; i < n; i++) { ++ const LataDBField & field = t.fields_[i]; ++ if (field.uname_ == uname) ++ return field; ++ } ++ if (where == FIRST_AND_CURRENT && tstep > 0) ++ tstep = 0; ++ else ++ break; ++ } ++ throw(LataDBError(LataDBError::NAME_NOT_FOUND)); ++} ++ ++// Description: shortcut, works only if the specified field exists and is unique. ++const LataDBField & LataDB::get_field(entier tstep, const char *geom, const char *name, const char *loc, ++ TStepSelector which_tstep) const ++{ ++ Field_UNames fields = field_unames(tstep, geom, name, which_tstep); ++ if (fields.size() > 1) ++ cerr << "get_field(char *geom, char *name, ...) returned more than one field !" << endl; ++ if (fields.size() != 1) ++ throw(LataDBError(LataDBError::NAME_NOT_FOUND)); ++ return get_field(tstep, fields[0], which_tstep); ++} ++ ++// Description: return 1 if the field exists AND is unique. (means you can call get_field with the ++// same parameters) ++entier LataDB::field_exists(entier tstep, const char *geom, const char *name, ++ TStepSelector which_tstep) const ++{ ++ Field_UNames fields = field_unames(tstep, geom, name, which_tstep); ++ return fields.size() == 1; ++} ++ ++ ++LataDBField & LataDB::getset_field(entier tstep, const Field_UName & uname, TStepSelector which_tstep) ++{ ++ return (LataDBField&) get_field(tstep, uname, which_tstep); ++} ++ ++// Description: returns the names of all geometries defined in the timestep ++// which_tstep tell where to search for geometries. ++// Exceptions: BAD_TIMESTEP ++Noms LataDB::geometry_names(entier tstep, TStepSelector which_tstep) const ++{ ++ Noms names; ++ const LataDBTimestep & t = get_tstep(tstep); ++ entier n = t.geoms_.size(); ++ for (entier i = 0; i < n; i++) ++ names.add(t.geoms_[i].name_); ++ if (which_tstep == FIRST_AND_CURRENT && tstep > 0) { ++ const LataDBTimestep & t0 = get_tstep(0); ++ entier n2 = t0.geoms_.size(); ++ for (entier i = 0; i < n2; i++) ++ // add if not: ++ if (names.rang(t0.geoms_[i].name_) < 0) ++ names.add(t0.geoms_[i].name_); ++ } ++ return names; ++} ++ ++// Description: returns the unique_identifiers of all fields defined in the timestep and for which ++// the associated geometry is "geometry" and the name is "name". Some fields may have no associated geometry, ++// give a null pointer or empty string to get these fields. ++// If geometry="*", returns list for all geometries ++// If name="*", returns list for all field names ++// Exceptions: BAD_TIMESTEP ++LataVector LataDB::field_unames(entier tstep, const char * geometry, const char * name, TStepSelector which_tstep) const ++{ ++ LataVector unames; ++ if (!geometry) ++ geometry = ""; ++ for (;;) { ++ const LataDBTimestep & t = get_tstep(tstep); ++ entier n = t.fields_.size(); ++ for (entier i = 0; i < n; i++) { ++ const LataDBField & field = t.fields_[i]; ++ if ((field.geometry_ == geometry || strcmp(geometry, "*")==0 ) ++ && (field.name_ == name || strcmp(name,"*")==0 )) ++ unames.add(field.uname_); ++ } ++ if (tstep == 0 || which_tstep != FIRST_AND_CURRENT) ++ break; ++ tstep = 0; ++ } ++ return unames; ++} ++ ++void check(Entree & is, const char * msg) ++{ ++ if (!is.good()) { ++ Journal() << "LataDB::read_master_file " << msg << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++} ++void read_keyword_nom(Entree & is, Nom& motlu) ++{ ++ is >> motlu; ++ if (is.eof()) { ++ Journal(verb_level) << "LataDB::read_master_file end of file" << endl; ++ motlu = "Fin"; ++ } else { ++ check(is, "read string error but not eof !"); ++ } ++ ++} ++ ++void read_keyword(Entree & is, Nom& nomlu, Motcle& motlu) ++{ ++ read_keyword_nom(is,nomlu); ++ motlu=nomlu; ++} ++ ++// On suppose que motlu contient "blabla=VALEUR". On extrait valeur et on la met dans "param". ++// Bidouille: pour traiter le cas "blabla= VALEUR", s'il n'y a rien apres "=" dans motlu, on ++// relit un mot dans is. ++void read_long_param(Entree & is, const Motcle & motlu, LataDBInt64 & param, const char * err_msg) ++{ ++ // Cherche le "=" ++ const char *s = motlu; ++ while (((*s) != ('=')) && ((*s) != 0)) ++ s++; ++ if (s==0) { ++ Journal() << "LataDB::read_master_file error: " << err_msg << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++ s++; ++ Nom tmp; ++ if (*s==0) { ++ // il y a une espace entre le = et le parametre ? ++ read_keyword_nom(is, tmp); ++ s = tmp; ++ } ++ errno = 0; ++ char *errorptr = 0; ++ param = strtoll(s, &errorptr, 0 /* base 10 par defaut */); ++ if (errno || *errorptr != 0) { ++ Journal() << "LataDB::read_master_file error: " << err_msg << endl ++ << "Error converting a string to type long int : string = " << s << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++} ++ ++void read_int_param(Entree & is, const Motcle & motlu, LataDBInt32 & param, const char * err_msg) ++{ ++ LataDBInt64 i; ++ read_long_param(is, motlu, i, err_msg); ++ param = int_conversion(i, err_msg); ++} ++ ++ ++// Idem que read_int_param pour des chaines de caracteres. ++void read_string_param(Entree & is, const Nom & motlu, Nom & param, const char * err_msg) ++{ ++ // Cherche le "=" ++ const char *s = motlu; ++ while (((*s) != ('=')) && ((*s) != 0)) ++ s++; ++ if (s==0) { ++ Journal() << "LataDB::read_master_file error: " << err_msg << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++ s++; ++ param = s; ++ // S'il n'y a rien apres =, on lit un mot de plus. ++ if (param == "") ++ read_keyword_nom(is, param); ++} ++ ++ ++void read_noms_param(Entree & is, const Nom & motlu, Noms & param, const char * err_msg) ++{ ++ Nom tmp; ++ read_string_param(is,motlu,tmp,err_msg); ++ /* ++ ++ a faire extraire pour de vrai les differents mots de motlu ++ Nom motlu2(tmp); ++ int nb_comp=1; ++ { ++ const char *s = tmp; ++ int p=0; ++ while ( ((*s) != 0)) ++ { ++ if ((*s) == (',')) ++ { ++ nb_comp++; ++ // motlu2[p]='\0'; ++ } ++ p++; ++ s++; ++ } ++ } ++ // cerr<= timesteps_.size()) { ++ Journal() << "LataDB::timestep(" << i << ") : wrong timestep" << endl; ++ throw(LataDBError(LataDBError::BAD_TIMESTEP)); ++ } ++ return timesteps_[i]; ++} ++ ++// Description: clears the database ++void LataDB::reset() ++{ ++ path_prefix_ = ""; ++ header_ = ""; ++ case_ = ""; ++ software_id_ = ""; ++ timesteps_.reset(); ++ std::string empty; ++ internal_data_buffer_.str(empty); ++} ++ ++// We update only fields found in the string ++// A string can contain both an int type and a float type: we get both in int_type and float_type ++static void read_format_string(const Motcle & n, LataDBDataType & data_type, ++ LataDBDataType::Type & int_type, ++ LataDBDataType::Type & float_type) ++{ ++ int_type = LataDBDataType::UNKNOWN_TYPE; ++ float_type = LataDBDataType::UNKNOWN_TYPE; ++ ++ if (n.find("ASCII")>=0) ++ data_type.msb_ = LataDBDataType::ASCII; ++ if (n.find("BIG_ENDIAN")>=0) ++ data_type.msb_ = LataDBDataType::MSB_BIG_ENDIAN; ++ if (n.find("LITTLE_ENDIAN")>=0) ++ data_type.msb_ = LataDBDataType::MSB_LITTLE_ENDIAN; ++ ++ if (n.find("INT32")>=0) { ++ int_type = data_type.type_ = LataDBDataType::INT32; ++ data_type.bloc_marker_type_ = LataDBDataType::INT32; ++ } ++ if (n.find("INT64")>=0) { ++ int_type = data_type.type_ = LataDBDataType::INT64; ++ data_type.bloc_marker_type_ = LataDBDataType::INT64; ++ } ++ if (n.find("REAL32")>=0) ++ float_type = data_type.type_ = LataDBDataType::REAL32; ++ if (n.find("REAL64")>=0) ++ float_type = data_type.type_ = LataDBDataType::REAL64; ++ ++ if (n.find("C_INDEXING")>=0) ++ data_type.array_index_ = LataDBDataType::C_INDEXING; ++ if (n.find("F_INDEXING")>=0) ++ data_type.array_index_ = LataDBDataType::F_INDEXING; ++ if (n.find("NO_INDEXING")>=0) ++ data_type.array_index_ = LataDBDataType::NOT_AN_INDEX; ++ ++ if (n.find("C_ORDERING")>=0) ++ data_type.data_ordering_ = LataDBDataType::C_ORDERING; ++ if (n.find("F_ORDERING")>=0) ++ data_type.data_ordering_ = LataDBDataType::F_ORDERING; ++ ++ if (n.find("F_MARKERS_NO")>=0) ++ data_type.fortran_bloc_markers_ = LataDBDataType::NO_BLOC_MARKER; ++ if (n.find("F_MARKERS_SINGLE")>=0) ++ data_type.fortran_bloc_markers_ = LataDBDataType::BLOC_MARKERS_SINGLE_WRITE; ++ if (n.find("F_MARKERS_MULTIPLE")>=0) ++ data_type.fortran_bloc_markers_ = LataDBDataType::BLOC_MARKERS_MULTIPLE_WRITES; ++ ++ // Fortran bloc markers are tested after INT32 and INT64 because they ++ // override the default value: ++ if (n.find("MARKERS32")>=0) ++ data_type.bloc_marker_type_ = LataDBDataType::INT32; ++ if (n.find("MARKERS64")>=0) ++ data_type.bloc_marker_type_ = LataDBDataType::INT64; ++} ++ ++// This must work together with read_format_string: ++void build_format_string(const LataDBDataType & default_type, ++ const LataDBDataType & type, ++ Motcle & n) ++{ ++ n = ""; ++ if (type.msb_ != default_type.msb_) { ++ switch(type.msb_) { ++ case LataDBDataType::ASCII: n += "ASCII,"; break; ++ case LataDBDataType::MSB_BIG_ENDIAN: n += "BIG_ENDIAN,"; break; ++ case LataDBDataType::MSB_LITTLE_ENDIAN: n += "LITTLE_ENDIAN,"; break; ++ default: ++ Journal() << "write master lata: invalid MSB" << endl; ++ throw(LataDBError(LataDBError::INVALID_OPERATION)); ++ } ++ } ++ ++ // Is an integer type specified in the format string: then the default ++ // fortran bloc marker_type will be changed (look for MARKER32 in read_format_string) ++ LataDBDataType::Type default_fortran_bloc_type = default_type.bloc_marker_type_; ++ ++ if (type.type_ != default_type.type_) { ++ switch(type.type_) { ++ case LataDBDataType::INT32: n += "INT32,"; default_fortran_bloc_type = LataDBDataType::INT32; break; ++ case LataDBDataType::INT64: n += "INT64,"; default_fortran_bloc_type = LataDBDataType::INT64; break; ++ case LataDBDataType::REAL32: n += "REAL32,"; break; ++ case LataDBDataType::REAL64: n += "REAL64,"; break; ++ default: ++ Journal() << "write master lata: invalid type" << endl; ++ throw(LataDBError(LataDBError::INVALID_OPERATION)); ++ } ++ } ++ ++ // Specify indexing only if integer type: ++ if ((type.type_ == LataDBDataType::INT32 || type.type_ == LataDBDataType::INT64) ++ && type.array_index_ != default_type.array_index_) ++ switch(type.array_index_) { ++ case LataDBDataType::C_INDEXING: n += "C_INDEXING,"; break; ++ case LataDBDataType::F_INDEXING: n += "F_INDEXING,"; break; ++ case LataDBDataType::NOT_AN_INDEX: n += "NO_INDEXING,"; break; ++ default: ++ Journal() << "write master lata: invalid array_index_" << endl; ++ throw(LataDBError(LataDBError::INVALID_OPERATION)); ++ } ++ ++ if (type.data_ordering_ != default_type.data_ordering_) { ++ switch(type.data_ordering_) { ++ case LataDBDataType::C_ORDERING: n += "C_ORDERING,"; break; ++ case LataDBDataType::F_ORDERING: n += "F_ORDERING,"; break; ++ default: ++ Journal() << "write master lata: invalid data_ordering_" << endl; ++ throw(LataDBError(LataDBError::INVALID_OPERATION)); ++ } ++ } ++ ++ if (type.fortran_bloc_markers_ != default_type.fortran_bloc_markers_) { ++ switch(type.fortran_bloc_markers_) { ++ case LataDBDataType::NO_BLOC_MARKER: n += "F_MARKERS_NO,"; break; ++ case LataDBDataType::BLOC_MARKERS_SINGLE_WRITE: n += "F_MARKERS_SINGLE,"; break; ++ case LataDBDataType::BLOC_MARKERS_MULTIPLE_WRITES: n += "F_MARKERS_MULTIPLE,"; break; ++ default: ++ Journal() << "write master lata: invalid fortran_bloc_markers_" << endl; ++ throw(LataDBError(LataDBError::INVALID_OPERATION)); ++ } ++ } ++ ++ // Warning : tricky code to determine if we have to specify fortran bloc marker size: ++ // If we specify a type_ and this type_ is an integer type, then the fortran bloc ++ // marker has implicitely the same type. We want to override this type if ++ // this assumption is wrong: ++ if (type.fortran_bloc_markers_ != LataDBDataType::NO_BLOC_MARKER ++ && default_fortran_bloc_type != type.bloc_marker_type_) { ++ switch(type.bloc_marker_type_) { ++ case LataDBDataType::INT32: n += "MARKER32,"; break; ++ case LataDBDataType::INT64: n += "MARKER64,"; break; ++ default: ++ Journal() << "write master lata: invalid fortran bloc marker type" << endl; ++ throw(LataDBError(LataDBError::INVALID_OPERATION)); ++ } ++ } ++ ++ // Remove trailing "," if any. ++ n.prefix(","); ++} ++ ++// Description: returns the content of the third line of the file ++// Exceptions: FILE_NOT_FOUND, BAD_HEADER (means that this is not a lata file) ++Nom LataDB::read_master_file_options(const char *filename) ++{ ++ LataDB db; ++ EFichier is; ++ db.read_master_file_header(filename, is); ++ return db.software_id_; // Returns the content of the third line ++} ++ ++// Description: ++// Opens the file and reads the three firt lines. ++// Fills the following attributes of the class: ++// header_ ++// case_ ++// software_id_ ++// old_style_lata_ ++void LataDB::read_master_file_header(const char *filename, EFichier & is) ++{ ++ if (!filename) ++ filename = ""; // Will trigger an error for sure ! ++ is.ouvrir(filename); ++ if (!is.good()) { // isnogood ? ++ Journal() << "LataDB::read_master_file_options failed opening file " << filename << endl; ++ throw(LataDBError(LataDBError::FILE_NOT_FOUND)); ++ } ++ Journal(verb_level-1) << "Trying to read master lata file format LATA " ++ << filename << endl; ++ ++ const entier bufsize=1024; ++ char s[bufsize+1]; ++ // Lecture de l'entete: ++ is.get_istream().getline(s, bufsize); ++ check(is, "failed reading line 1"); ++ const char * lata_header = "LATA_V2."; ++ old_style_lata_ = 0; ++ if (strncmp(s, lata_header, strlen(lata_header)) == 0) { ++ Journal(2) << "LataDB::read_master_file found lata format " << lata_header << endl; ++ old_style_lata_ = 0; ++ } else if ((Motcle(s).debute_par("Trio_U"))||(Motcle(s).debute_par("TRUST"))) { ++ Journal(2) << "LataDB::read_master_file found old style lata format" << endl; ++ old_style_lata_ = 1; ++ } else { ++ Journal(2) << "LataDB::read_master_file error reading header: expected LATA_V2.0 or TRUST" ++ << " instead of " << s << endl; ++ throw(LataDBError(LataDBError::BAD_HEADER)); ++ } ++ header_ = s; ++ is.get_istream().getline(s, bufsize); ++ check(is, "failed reading line 2"); ++ case_ = s; ++ is.get_istream().getline(s, bufsize); ++ check(is, "failed reading line 3"); ++ software_id_ = s; ++} ++ ++int is_med(const char* filename) ++{ ++ Motcle motcle_nom_fic(filename); ++ ++ if (motcle_nom_fic.finit_par(".med")) ++ return 1; ++ return 0; ++} ++ ++// Description: Reads the .lata database in the given file indicating than the ++// associated data files will be found in directory "prefix". ++// If not empty, "prefix" must finish with a '/'. ++// For "prefix" and "filename", if they do not begin with '/', are relative to pwd. ++// Exceptions: ++// BAD_HEADER means that the header found in this stream is not LATA_V2 ++// READ_ERROR means that an error has been found in the file (premature eof, ++// io error, bad keyword, ...) ++// FILE_NOT_FOUND means that, well, the lata file could not be opened ++void LataDB::read_master_file(const char *prefix, const char *filename) ++{ ++ reset(); ++ ++ if (!prefix) ++ prefix = ""; ++ path_prefix_ = prefix; ++ ++ if (is_med(filename)) ++ { ++ path_prefix_ = ""; ++ read_master_file_med(prefix,filename); ++ return; ++ } ++ ++ //Journal() << "RECOMPILED PLUGIN !" << endl; ++ ++ EFichier is; ++ read_master_file_header(filename, is); ++ ++ // Defaults for lataV1 ++ default_type_int_.msb_ = LataDBDataType::ASCII; ++ default_type_int_.type_ = LataDBDataType::INT32; ++ default_type_int_.array_index_ = LataDBDataType::F_INDEXING; ++ default_type_int_.data_ordering_ = LataDBDataType::C_ORDERING; ++ default_type_int_.fortran_bloc_markers_ = LataDBDataType::BLOC_MARKERS_SINGLE_WRITE; ++ default_type_int_.bloc_marker_type_ = LataDBDataType::INT32; ++ default_float_type_ = LataDBDataType::REAL32; ++ ++ // Create timestep 0 (global domain and fields) ++ timesteps_.add(LataDBTimestep()); ++ entier interface_file_not_found = 0; ++ Nom nomlu; ++ Motcle motlu; ++ read_keyword(is, nomlu,motlu); ++ ++ while (1) { ++ if (motlu == "Fin") ++ { ++ Journal(verb_level) << "End of file by FIN" << endl; ++ break; ++ } ++ else if (motlu == "Format") ++ { ++ Journal(verb_level) << "Reading Format " << endl; ++ read_keyword(is, nomlu, motlu); ++ LataDBDataType::Type tmp_int_type; ++ read_format_string(motlu, default_type_int_, tmp_int_type, default_float_type_); ++ default_type_int_.type_ = tmp_int_type; ++ read_keyword(is, nomlu, motlu); ++ } ++ else if (motlu == "Temps") ++ { ++ LataDBTimestep & t = timesteps_.add(LataDBTimestep()); ++ const entier i = timesteps_.size() - 1; ++ is >> t.time_; ++ check(is, "failed reading time parameter"); ++ Journal(verb_level) << "Reading timestep " << i << " t=" << t.time_ << endl; ++ read_keyword(is, nomlu, motlu); ++ } ++ else if (motlu == "Geom") ++ { ++ // This is the new syntax to declare a geometry. ++ // nodes, elements faces, files are declared in separate "champ" entries ++ LataDBGeometry dom; ++ dom.timestep_ = timesteps_.size()-1; ++ is >> dom.name_; ++ check(is, "failed reading domain name"); ++ Journal(verb_level) << "New domain " << dom.name_ << endl; ++ while (1) { ++ read_keyword(is, nomlu, motlu); ++ if (motlu.debute_par("type_elem=")) { ++ read_string_param(is, motlu, dom.elem_type_, "error reading type_elem parameter"); ++ Journal(verb_level+1) << " type_elem=" << dom.elem_type_ << endl; ++ } else ++ break; ++ } ++ if (dom.elem_type_ == "") { ++ Journal() << "Error reading Geometry: missing type_elem parameter" << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++ add(timesteps_.size() - 1, dom); ++ } ++ else if (motlu == "Geometrie") ++ { ++ // Declare a geometry: nodes and elements are embedded in a single file described here ++ // (legacy syntax) ++ LataDBGeometry dom; ++ LataDBField som; ++ // Name ++ is >> dom.name_; ++ dom.timestep_ = timesteps_.size()-1; ++ check(is, "failed reading domain name"); ++ Journal(verb_level) << "Reading domain " << dom.name_ << endl; ++ som.name_ = "SOMMETS"; ++ som.geometry_ = dom.name_; ++ // Filenames ++ Nom n; ++ is >> n; ++ check(is, "failed reading domain filename"); ++ som.filename_ = n; ++ long long nb_elem = -1; ++ long long nb_faces = -1; ++ entier nproc = -1; ++ Nom file_decal_som; ++ Nom file_decal_elem; ++ Nom file_decal_faces; ++ while (1) { ++ read_keyword(is, nomlu, motlu); ++ if (motlu.debute_par("nb_som_tot=")) { ++ read_long_param(is, motlu, som.size_, "bad nb_som_tot parameter"); ++ } else if (motlu.debute_par("nb_elem_tot=")) { ++ read_long_param(is, motlu, nb_elem, "bad nb_elem_tot parameter"); ++ } else if (motlu.debute_par("type_elem=")) { ++ read_string_param(is, motlu, dom.elem_type_, "error reading type_elem parameter"); ++ } else if (motlu.debute_par("nb_faces_tot=")) { ++ read_long_param(is, motlu, nb_faces, "bad nb_elem_tot parameter"); ++ } else if (motlu.debute_par("format=")) { ++ Motcle fmt; ++ read_string_param(is, motlu, fmt, "bad format parameter"); ++ if (fmt=="BINARY") { ++ default_type_int_.msb_ = LataDBDataType::machine_msb_; ++ } ++ } else if (motlu.debute_par("joints_sommets")) { ++ read_keyword(is, nomlu, motlu); ++ read_int_param(is, motlu, nproc, "bad nproc parameter"); ++ read_keyword(is, nomlu, motlu); ++ read_string_param(is, nomlu, file_decal_som, "bad decalage file parameter"); ++ Journal(verb_level+1) << " decal_som " << nproc; ++ } else if (motlu.debute_par("joints_elements")) { ++ read_keyword(is, nomlu, motlu); ++ read_int_param(is, motlu, nproc, "bad nproc parameter"); ++ read_keyword(is, nomlu, motlu); ++ read_string_param(is, nomlu, file_decal_elem, "bad decalage file parameter"); ++ Journal(verb_level+1) << " decal_elem " << nproc; ++ } else if (motlu.debute_par("joints_faces")) { ++ read_keyword(is, nomlu, motlu); ++ read_int_param(is, motlu, nproc, "bad nproc parameter"); ++ read_keyword(is, nomlu, motlu); ++ read_string_param(is, nomlu, file_decal_faces, "bad decalage file parameter"); ++ Journal(verb_level+1) << " decal_faces " << nproc; ++ } else ++ break; ++ Journal(verb_level+1) << " " << motlu << endl; ++ } ++ som.datatype_ = default_type_float(); ++ LataDBField elem(som); ++ elem.size_ = nb_elem; ++ elem.datatype_ = default_type_int_; ++ LataDBField faces(elem); // copy filename_ ++ faces.size_ = nb_faces; ++ LataDBField elem_faces(elem); ++ elem_faces.size_ = nb_elem; ++ elem.name_ = "ELEMENTS"; ++ faces.name_ = "FACES"; ++ elem_faces.name_ = "ELEM_FACES"; ++ elem.geometry_ = dom.name_; ++ faces.geometry_ = dom.name_; ++ elem_faces.geometry_ = dom.name_; ++ ++ if (som.size_ < 0 || elem.size_ < 0) { ++ Journal() << "Error reading Geometry: missing or bad nb_som_tot or nb_elem_tot parameter" << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++ if (dom.elem_type_ == "") { ++ Journal() << "Error reading Geometry: missing type_elem parameter" << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++ get_element_data(dom.elem_type_, som.nb_comp_, elem.nb_comp_, faces.nb_comp_, elem_faces.nb_comp_); ++ ++ // Add domain and som which are complete. We need the "som" to be in the database ++ // for the "old lata 2D hack" in read_data2_() ++ add(timesteps_.size() - 1, dom); ++ add(timesteps_.size() - 1, som); ++ // Parse the geometry file to find file_offsets ++ { ++ Journal(verb_level) << " Parsing geometry file to find file offset of data blocs" << endl; ++ LataDataFile f(internal_data_buffer_, path_prefix_, som.filename_,som.datatype_.msb_); ++ IntTab * null = 0; // Null pointer => don't actually read the data ++ read_data2_(f, som, null); ++ elem.datatype_.file_offset_ = f.position(); ++ Journal(verb_level+1) << " elements at file offset " << elem.datatype_.file_offset_ << endl; ++ if (faces.size_ >= 0) { ++ read_data2_(f, elem, null); ++ faces.datatype_.file_offset_ = f.position(); ++ Journal(verb_level+1) << " faces at file offset " << faces.datatype_.file_offset_ << endl; ++ read_data2_(f, faces, null); ++ elem_faces.datatype_.file_offset_ = f.position(); ++ Journal(verb_level+1) << " elem_faces at file offset " << elem_faces.datatype_.file_offset_ << endl; ++ } ++ } ++ ++ add(timesteps_.size() - 1, elem); ++ if (faces.size_ >= 0) { ++ Journal(verb_level+1) << " Adding FACES and ELEM_FACES " << faces.size_ << endl; ++ add(timesteps_.size() - 1, faces); ++ add(timesteps_.size() - 1, elem_faces); ++ } ++ if (nproc > -1) { ++ LataDBField joint(elem); ++ joint.datatype_.file_offset_ = 0; ++ joint.size_ = nproc; ++ joint.nb_comp_ = 2; ++ joint.reference_ = ""; ++ joint.name_ = "JOINTS_SOMMETS"; ++ joint.filename_ = file_decal_som; ++ add(timesteps_.size() - 1, joint); ++ joint.reference_ = ""; ++ joint.name_ = "JOINTS_ELEMENTS"; ++ joint.filename_ = file_decal_elem; ++ add(timesteps_.size() - 1, joint); ++ if (file_decal_faces != "??") { ++ joint.reference_ = ""; ++ joint.name_ = "JOINTS_FACES"; ++ joint.filename_ = file_decal_faces; ++ add(timesteps_.size() - 1, joint); ++ } ++ } ++ } ++ else if (motlu == "Champ") ++ { ++ LataDBField field; ++ field.datatype_ = default_type_float(); ++ is >> field.name_; ++ check(is, "failed reading field name"); ++ Journal(verb_level) << "Reading field " << field.name_ << endl; ++ Nom n; ++ is >> n; ++ check(is, "failed reading field filename"); ++ field.filename_ = n; ++ Journal(verb_level+1) << " filename=" << n << endl; ++ ++ if ((field.name_ == "INTERFACES" || field.name_ == "PARTICULES") && old_style_lata_) { ++ // This is the old dirty syntax for moving meshes ++ ++ Journal(verb_level+1) << " Parsing an oldstyle interface file" << endl; ++ // Open the file and read the content ++ try { ++ LataDBDataType::MSB msb = default_type_int_.msb_; ++ LataDataFile f(internal_data_buffer_, path_prefix_, field.filename_,msb); ++ ++ LataDBDataType::Type int_type = default_type_int_.type_; ++ LataDBDataType::Type float_type = default_float_type_; ++ LataDBGeometry dom; ++ dom.timestep_ = timesteps_.size()-1; ++ dom.name_ = field.name_; ++ LataDBField som; ++ som.name_ = "SOMMETS"; ++ som.filename_ = field.filename_; ++ som.geometry_ = field.name_; ++ som.datatype_ = default_type_float(); ++ som.datatype_.fortran_bloc_markers_ = LataDBDataType::NO_BLOC_MARKER; ++ ArrOfInt tmptab(2); ++ bloc_read(f, msb, int_type, tmptab); ++ som.nb_comp_ = tmptab[0]; // dimension ++ som.size_ = tmptab[1]; // nb nodes ++ Journal(verb_level+1) << " Nb nodes=" << som.size_ << " dimension=" << som.nb_comp_ << endl; ++ som.datatype_.file_offset_ = f.position(); ++ bloc_read_skip(f, msb, float_type, som.size_ * som.nb_comp_); ++ LataDBField elem; ++ elem.name_ = "ELEMENTS"; ++ elem.filename_ = field.filename_; ++ elem.geometry_ = field.name_; ++ elem.datatype_ = default_type_int_; ++ elem.datatype_.fortran_bloc_markers_ = LataDBDataType::NO_BLOC_MARKER; ++ elem.datatype_.array_index_ = LataDBDataType::C_INDEXING; ++ bloc_read(f, msb, int_type, tmptab); ++ elem.nb_comp_ = tmptab[0]; ++ elem.size_ = tmptab[1]; ++ Journal(verb_level+1) << " Nb elements=" << elem.size_ << " shape=" << elem.nb_comp_ << endl; ++ if (field.name_ == "PARTICULES") { ++ // Special case for front-tracking markers ++ Journal(verb_level+1) << " PARTICULES: element type = point" << endl; ++ dom.elem_type_ = "POINT"; ++ } else { ++ if (elem.nb_comp_ == 2) ++ dom.elem_type_ = "SEGMENT"; ++ else if (elem.nb_comp_ == 3) ++ dom.elem_type_ = "TRIANGLE_3D"; ++ else { ++ Journal() << "Error reading an interface: invalid element shape " << elem.nb_comp_ << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++ } ++ elem.datatype_.file_offset_ = f.position(); ++ bloc_read_skip(f, msb, int_type, elem.size_ * elem.nb_comp_); ++ add(timesteps_.size() - 1, dom); ++ add(timesteps_.size() - 1, som); ++ add(timesteps_.size() - 1, elem); ++ // Read components: ++ while(1) { ++ LataDBField fieldbis; ++ f.set_encoding(msb, int_type); ++ f.set_exception(0); ++ f >> fieldbis.localisation_; ++ f.set_exception(1); ++ if (fieldbis.localisation_ == "") ++ break; ++ fieldbis.filename_ = som.filename_; ++ fieldbis.geometry_ = som.geometry_; ++ fieldbis.datatype_ = som.datatype_; ++ tmptab.resize_array(1); ++ bloc_read(f, msb, int_type, tmptab); ++ fieldbis.nb_comp_ = tmptab[0]; ++ if (fieldbis.nb_comp_ == som.nb_comp_) ++ fieldbis.nature_ = LataDBField::VECTOR; ++ else ++ fieldbis.nature_ = LataDBField::SCALAR; ++ f >> fieldbis.name_; ++ if (fieldbis.localisation_ == "SOM") { ++ fieldbis.size_ = som.size_; ++ } else { ++ fieldbis.size_ = elem.size_; ++ } ++ Journal(verb_level+1) << " Interface field " << fieldbis.localisation_ << " " ++ << fieldbis.name_ << endl; ++ fieldbis.datatype_.file_offset_ = f.position(); ++ bloc_read_skip(f, msb, float_type, fieldbis.size_ * fieldbis.nb_comp_); ++ add(timesteps_.size() - 1, fieldbis); ++ } ++ } ++ catch (LataDBError err) { ++ // If file is missing, issue the "missing file" message and continue ++ if (err.err_ != LataDBError::FILE_NOT_FOUND) ++ throw; ++ else ++ interface_file_not_found++; ++ } ++ // Read next keyword: ++ read_keyword(is, nomlu, motlu); ++ } else { ++ if (old_style_lata_) { ++ // Old (legacy) syntax for champs: we must guess the properties from the filename! ++ ++ field.datatype_ = default_type_float(); ++ // Extract other data from filename (nb_comp_, localisation_, etc) ++ // find geometry name ++ Noms dom_names = geometry_names(0 /* timestep */); ++ const entier nb_geom = dom_names.size(); ++ entier i; ++ for (i = 0; i < nb_geom; i++) { ++ Nom testname("."); ++ testname += dom_names[i]; ++ testname += "."; ++ if (Motcle(n).find(testname)>=0) ++ break; ++ } ++ if (i == nb_geom) { ++ Journal() << "Error in LataDB_V1::read_master_file: could not find domain for Champ " << n << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++ Journal(verb_level+1) << " geometry=" << dom_names[i] << endl; ++ const LataDBGeometry & dom = get_geometry(0, dom_names[i]); ++ field.geometry_ = dom_names[i]; ++ lata_v1_get_localisation(n, field.localisation_); ++ Journal(verb_level+1) << " localisation=" << field.localisation_ << endl; ++ const LataDBField & sommets = get_field(0 /* timestep */, dom_names[i], "SOMMETS", "*"); ++ const entier dim = sommets.nb_comp_; ++ field.nb_comp_ = lata_v1_get_nb_comp(field.name_, field.localisation_, dom, dim, field.nature_, field.datatype_.data_ordering_); ++ Journal(verb_level+1) << " composantes=" << field.nb_comp_ << endl; ++ if (field.localisation_.debute_par("SOM")) ++ field.size_ = sommets.size_; ++ else if (field.localisation_.debute_par("ELEM")) ++ field.size_ = get_field(0 /* timestep */, dom_names[i], "ELEMENTS", "*").size_; ++ else if (field.localisation_.debute_par("FACE")) ++ field.size_ = get_field(0 /* timestep */, dom_names[i], "FACES", "*").size_; ++ else { ++ Journal() << "Error in LataDB_V1::read_master_file: invalid localisation " ++ << field.localisation_ << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++ // Read next keyword: ++ read_keyword(is, nomlu, motlu); ++ } else { ++ // NEW LATAV2 SYNTAX for fields ++ // The default data type is "float_" ++ field.datatype_ = default_type_float(); ++ field.size_ = -1; ++ while(1) { ++ read_keyword(is, nomlu, motlu); ++ if (motlu.debute_par("geometrie=")) { ++ read_string_param(is, nomlu, field.geometry_, "error reading geometrie parameter"); ++ // Check that the geometry exists ++ get_geometry(timesteps_.size() - 1, field.geometry_, FIRST_AND_CURRENT); ++ } else if (motlu.debute_par("composantes=")) { ++ read_int_param(is, motlu, field.nb_comp_, "bad composantes parameter"); ++ } else if (motlu.debute_par("localisation=")) { ++ read_string_param(is, motlu, field.localisation_, "error reading localisation parameter"); ++ } else if (motlu.debute_par("format=")) { ++ LataDBDataType::Type tmp_int_type; // Unused ++ LataDBDataType::Type tmp_float_type; // unused ++ read_format_string(motlu, field.datatype_, tmp_int_type, tmp_float_type); ++ } else if (motlu.debute_par("size=")) { ++ read_long_param(is, motlu, field.size_, "error reading size parameter"); ++ } else if (motlu.debute_par("file_offset=")) { ++ read_long_param(is, motlu, field.datatype_.file_offset_, "error reading file offset parameter"); ++ } else if (motlu.debute_par("nature=")) { ++ Motcle nat; ++ read_string_param(is, motlu, nat, "error reading nature parameter"); ++ if (nat.find("SCALAR")>=0) ++ field.nature_ = LataDBField::SCALAR; ++ else if (nat.find("VECTOR")>=0) ++ field.nature_ = LataDBField::VECTOR; ++ else { ++ Journal() << "Error in LataDB_V1::read_master_file: invalid nature " ++ << nat << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++ } else if (motlu.debute_par("reference=")) { ++ Nom ref; ++ read_string_param(is, motlu, ref, "error reading reference parameter"); ++ field.reference_ = ref; ++ } else if (motlu.debute_par("noms_compo=")) { ++ Noms ref; ++ read_noms_param(is, motlu, ref, "error reading noms_compo"); ++ Journal(verb_level+1)<<"noms_compos pas interprete "<> filenamebis; // Read filename (without prefix) ++ LataDB newdb; ++ Nom filename2(prefix); ++ filename2 += filenamebis; ++ Journal(verb_level) << "Importing another lata database from file: " << filename << endl; ++ newdb.read_master_file(prefix, filename2); ++ } ++ else ++ { ++ Journal() << "Error: unknown keyword: " << motlu << endl; ++ throw(LataDBError(LataDBError::READ_ERROR)); ++ } ++ } ++ if (interface_file_not_found) ++ throw LataDBError(LataDBError::FILE_NOT_FOUND); ++} ++ ++// Read field data from file f into data array "data". ++// If data is a null pointer, just skip the data bloc and leave the file pointer ++// at the beginning of the next data bloc (used to parse the geometry file if file_offset ++// are not specified in the lata master file) ++template ++void LataDB::read_data2_(LataDataFile & f, ++ const LataDBField & fld, ++ C_Tab * const data, // const pointer to non const data ! ++ long long debut, entier n, const ArrOfInt *lines_to_read) const ++{ ++ ++ if (is_med(fld.filename_)) ++ { ++ read_data2_med_(fld,data,debut,n,lines_to_read); ++ return; ++ } ++ // Si file_offset_ vaut 0 on y va car on peut avoir lu a un autre endroit avant. ++ if (fld.datatype_.file_offset_ >= 0) { ++ Journal(verb_level_data_bloc+1) << " Seeking at position " << fld.datatype_.file_offset_ << endl; ++ f.seek(fld.datatype_.file_offset_, LataDataFile::ABSOLUTE); ++ } ++ if (n < 0) { ++ if (lines_to_read) ++ n = lines_to_read->size_array(); ++ else ++ n = fld.size_; ++ } ++ ++ // in old lata format, 2d data is written as 3d: ++ // Yeah: dirty specs make dirty code... ++ long long size_in_file = fld.size_; ++ entier nb_comp_in_file = fld.nb_comp_; ++ // entier old_lata_hack = 0; ++ if (old_style_lata_ && (Motcle(fld.geometry_) != "INTERFACES") && (Motcle(fld.geometry_) != "PARTICULES")) { ++ const LataDBField & som = get_field(0, fld.geometry_, "SOMMETS", "*"); ++ if (som.nb_comp_ == 2) { ++ //old_lata_hack = 1; ++ if (fld.name_ == "ELEMENTS") { ++ nb_comp_in_file *= 2; ++ } else if (fld.name_ == "SOMMETS") { ++ nb_comp_in_file = 3; // all coordinates in 3D ++ size_in_file *= 2; ++ } // else if (fld.localisation_.debute_par("SOM")) { ++ // size_in_file *= 2; ++ // } ++ Journal(verb_level_data_bloc+1) << "Old lata hack for 2D" << endl; ++ } ++ } ++ ++ if (fld.nb_comp_ < 0 || fld.size_ < 0) { ++ Journal() << "Error in LataDB::read_data_: nb_comp_ or size_ not initialized for component " << fld.name_ << endl; ++ throw; ++ } ++ ++ if ((!lines_to_read) && (debut < 0 || debut + n > fld.size_)) { ++ Journal() << "Error in LataDB::read_data_: [debut,debut+n] invalid range (size=" << fld.size_ << ")" << endl; ++ throw; ++ } ++ ++ if (data) ++ data->resize(n, nb_comp_in_file); ++ ++ switch (fld.datatype_.data_ordering_) { ++ case LataDBDataType::C_ORDERING: ++ // data written like this: tab(0,0) tab(0,1) tab(0,2) ... tab(1,0) tab(1,1) tab(1,2) ... ++ if (fld.datatype_.fortran_bloc_markers_ == LataDBDataType::BLOC_MARKERS_MULTIPLE_WRITES) { ++ Journal() << "Error in LataDB::read_data_: fortran_bloc_markers_=MULTIPLE_WRITES is incompatible with data_ordering=C" << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++ skip_blocksize(f, fld.datatype_); ++ if (data) { ++ if (!lines_to_read) { ++ bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, (FileOffset)debut * nb_comp_in_file); ++ bloc_read(f, fld.datatype_.msb_, fld.datatype_.type_, *data); ++ bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, (FileOffset)(size_in_file - debut - n) * nb_comp_in_file); ++ } else { ++ C_Tab tmp; ++ // Read 1024 lines chunks at a time even if only some values are needed inside ++ long long chunk_size = 0; ++ long long current_chunk_pos = 0; ++ long long current_file_pos = 0; ++ const entier nl = lines_to_read->size_array(); ++ for (entier i = 0; i < nl; i++) { ++ const long long next_line = (*lines_to_read)[i]; ++ // Is this line in the current chunk ? ++ if (next_line >= current_chunk_pos + chunk_size) { ++ // No => read the chunk containing this line ++ chunk_size = size_in_file - next_line; ++ if (chunk_size > 1024) ++ chunk_size = 1024; ++ tmp.resize(chunk_size, nb_comp_in_file); ++ bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, (next_line - current_file_pos) * nb_comp_in_file); ++ bloc_read(f, fld.datatype_.msb_, fld.datatype_.type_, tmp); ++ current_chunk_pos = next_line; ++ current_file_pos = next_line + chunk_size; ++ } ++ // Extract data from tmp array ++ const long long tmp_index = next_line - current_chunk_pos; ++ for (entier j = 0; j < nb_comp_in_file; j++) ++ (*data)(i, j) = tmp(tmp_index, j); ++ } ++ if (current_file_pos != size_in_file) ++ bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, (size_in_file - current_file_pos) * nb_comp_in_file); ++ } ++ } else { ++ // just skip the data ++ bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, size_in_file * nb_comp_in_file); ++ } ++ skip_blocksize(f, fld.datatype_); ++ break; ++ case LataDBDataType::F_ORDERING: ++ { ++ // 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) ... ++ entier multiple_bloc_markers = (fld.datatype_.fortran_bloc_markers_ == LataDBDataType::BLOC_MARKERS_MULTIPLE_WRITES); ++ // reverse rows and columns of the array ++ C_Tab tmp; ++ if (!multiple_bloc_markers) ++ skip_blocksize(f, fld.datatype_); ++ for (entier i = 0; i < nb_comp_in_file; i++) { ++ if (multiple_bloc_markers) ++ skip_blocksize(f, fld.datatype_); ++ if (data) { ++ if (!lines_to_read) { ++ tmp.resize(n, 1); ++ bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, debut); ++ bloc_read(f, fld.datatype_.msb_, fld.datatype_.type_, tmp); ++ bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, size_in_file - debut - n); ++ for (entier j = 0; j < n; j++) ++ (*data)(j, i) = tmp(j, 0); ++ } else { ++ ++ // Read 1024 lines chunks at a time even if only some values are needed inside ++ long long chunk_size = 0; ++ long long current_chunk_pos = 0; ++ long long current_file_pos = 0; ++ const entier nl = lines_to_read->size_array(); ++ for (entier j = 0; j < nl; j++) { ++ const long long next_line = (*lines_to_read)[j]; ++ // Is this line in the current chunk ? ++ if (next_line >= current_chunk_pos + chunk_size) { ++ // No => read the chunk containing this line ++ chunk_size = size_in_file - next_line; ++ if (chunk_size > 1024) ++ chunk_size = 1024; ++ tmp.resize(chunk_size, 1); ++ bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, (next_line - current_file_pos)); ++ bloc_read(f, fld.datatype_.msb_, fld.datatype_.type_, tmp); ++ current_chunk_pos = next_line; ++ current_file_pos = next_line + chunk_size; ++ } ++ // Extract data from tmp array ++ const entier tmp_index = (entier)(next_line - current_chunk_pos); ++ (*data)(j, i) = tmp(tmp_index, 0); ++ } ++ if (current_file_pos != size_in_file) ++ bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, (size_in_file - current_file_pos)); ++ } ++ } else { ++ bloc_read_skip(f, fld.datatype_.msb_, fld.datatype_.type_, size_in_file); ++ } ++ if (multiple_bloc_markers) ++ skip_blocksize(f, fld.datatype_); ++ } ++ if (!multiple_bloc_markers) ++ skip_blocksize(f, fld.datatype_); ++ break; ++ } ++ default: ++ Journal() << "Error in LataDB::read_data_: data_ordering not implemented" << endl; ++ throw; ++ } ++ ++ // old lata 2d hack : ++ if (data && nb_comp_in_file != fld.nb_comp_) { ++ // drop column in data array ++ C_Tab tmp(*data); ++ data->resize(n, fld.nb_comp_); ++ for (entier i = 0; i < n; i++) ++ for (entier j = 0; j < fld.nb_comp_; j++) ++ (*data)(i,j) = tmp(i,j); ++ } ++} ++ ++// Description: ++// Read n * fld.nb_comp_ values in the file filename_, starting from debut * fld.nb_comp_ ++template ++void LataDB::read_data_(const LataDBField & fld, ++ C_Tab & data, long long debut, entier n) const ++{ ++ Journal(verb_level_data_bloc) << "LataDB::read_data(" << fld.timestep_ << "," << fld.uname_ ++ << ") Reading " << path_prefix_ << fld.filename_ << " start at " << debut << " size " ++ << n << endl; ++ ++ LataDataFile f(internal_data_buffer_, path_prefix_, fld.filename_,fld.datatype_.msb_); ++ read_data2_(f, fld, &data, debut, n); ++ ++} ++ ++// Description: ++// Read n * fld.nb_comp_ values in the file filename_, starting from debut * fld.nb_comp_ ++template ++void LataDB::read_data_(const LataDBField & fld, ++ C_Tab & data, const ArrOfInt & lines_to_read) const ++{ ++ Journal(verb_level_data_bloc) << "LataDB::read_data(" << fld.timestep_ << "," << fld.uname_ ++ << ") Reading " << path_prefix_ << fld.filename_ << ", " << lines_to_read.size_array() << " non contiguous lines" ++ << endl; ++ ++ LataDataFile f(internal_data_buffer_, path_prefix_, fld.filename_,fld.datatype_.msb_); ++ read_data2_(f, fld, &data, -1, -1, &lines_to_read); ++} ++ ++// Description: reads n * nb_comp values in the file filename_ starting from debut*nb_comp_ ++// If array_index is F_STYLE, substract 1 to all values. ++void LataDB::read_data(const LataDBField & fld, IntTab & data, long long debut, entier n) const ++{ ++ read_data_(fld, data, debut, n); ++ if (fld.datatype_.array_index_ == LataDBDataType::F_INDEXING) { ++ ArrOfInt & data2 = data; ++ const entier n2 = data2.size_array(); ++ for (entier i = 0; i < n2; i++) ++ data2[i]--; ++ } ++} ++ ++// Description: reads n * nb_comp values in the file filename_ starting from debut*nb_comp_ ++void LataDB::read_data(const LataDBField & fld, DoubleTab & data, long long debut, entier n) const ++{ ++ Journal() << "LataDB::read_data not coded for double" << endl; ++ throw; ++} ++ ++void LataDB::read_data(const LataDBField & fld, FloatTab & data, long long debut, entier n) const ++{ ++ read_data_(fld, data, debut, n); ++} ++ ++// Description: reads lines_to_read.size_array() * nb_comp values. ++// If array_index is F_STYLE, substract 1 to all values. ++void LataDB::read_data(const LataDBField & fld, IntTab & data, const ArrOfInt & lines_to_read) const ++{ ++ read_data_(fld, data, lines_to_read); ++ if (fld.datatype_.array_index_ == LataDBDataType::F_INDEXING) { ++ ArrOfInt & data2 = data; ++ const entier n = data2.size_array(); ++ for (entier i = 0; i < n; i++) ++ data2[i]--; ++ } ++} ++ ++// Description: reads lines_to_read.size_array() * nb_comp values. ++void LataDB::read_data(const LataDBField & fld, DoubleTab & data, const ArrOfInt & lines_to_read) const ++{ ++ Journal() << "LataDB::read_data not coded for double" << endl; ++ throw; ++} ++ ++// Description: reads lines_to_read.size_array() * nb_comp values. ++void LataDB::read_data(const LataDBField & fld, FloatTab & data, const ArrOfInt & lines_to_read) const ++{ ++ read_data_(fld, data, lines_to_read); ++} ++ ++ ++// Description: copy the source LataDB object, keeping only timesteps, geometries and fields ++// that are specified (timestep 0 is always included, do not put it in the list). ++// field_nms can contain field.name_ (like VITESSE), or extended name with localisation ++// (like VITESSE_ELEM) ++void LataDB::filter_db(const LataDB & source, ++ const Motcles & geometry_nms, ++ const Motcles & field_nms, ++ const ArrOfInt & timesteps) ++{ ++ path_prefix_ = source.path_prefix_; ++ header_ = source.header_; ++ case_ = source.case_; ++ software_id_ = source.software_id_; ++ old_style_lata_ = source.old_style_lata_; ++ default_type_int_ = source.default_type_int_; ++ default_float_type_ = source.default_float_type_; ++ ++ const entier nb_tsteps = timesteps.size_array(); ++ for (entier it = 0; it < nb_tsteps + 1; it++) { ++ entier src_tstep = 0; ++ if (it > 0) ++ src_tstep = timesteps[it-1]; ++ LataDBTimestep & tstep = timesteps_.add(LataDBTimestep()); ++ tstep.time_ = source.get_time(src_tstep); ++ // Copy geometries ++ Motcles geoms = noms_to_motcles(source.geometry_names(src_tstep)); ++ entier ig; ++ for (ig = 0; ig < geoms.size(); ig++) ++ if (geometry_nms.rang(geoms[ig]) >= 0) ++ tstep.geoms_.add(source.get_geometry(src_tstep, geoms[ig])); ++ // Copy fields ++ geoms = noms_to_motcles(geometry_names(nb_timesteps()-1, FIRST_AND_CURRENT)); ++ for (ig = 0; ig < geoms.size(); ig++) { ++ LataVector unames = source.field_unames(src_tstep, geoms[ig], "*"); ++ for (entier i_f = 0; i_f < unames.size(); i_f++) { ++ const LataDBField & src = source.get_field(src_tstep, unames[i_f]); ++ Nom name_loc = src.name_; ++ name_loc += "_"; ++ name_loc += src.localisation_; ++ if (field_nms.rang(src.name_) >= 0 || field_nms.rang(name_loc) >= 0) ++ tstep.fields_.add(src); ++ } ++ } ++ } ++} ++ ++// Description: set the default value of the path prefix where write_data() will write the data ++// Warning: there is no check that the master lata file is actually written at the same place ++// and that all the files and data blocks mentionned in the database actually exist. ++// For the file_offset_ field, -2 is considered "unknown". ++void LataDB::set_path_prefix(const char * s) ++{ ++ path_prefix_ = s; ++} ++ ++#define UPDATE_MACRO(x,unknown) if (((old_type.x==unknown)||(type.x==old_type.x))&&(new_type.x!=unknown)) type.x=new_type.x ++ ++// Description: changes the data type of all fields in the database. ++// The property "x" is changed to "new_type.x" if "new_type.x" is not "unknown" ++// and if "old_type.x" is "unknown" or "equal to the previous property" ++// Example: convert all data to ASCII: ++// LataDBDataType old_type; // All defaults to "unknown" => we update all fields ++// LataDBDataType new_type; ++// new_type.msb_ = LataDBDataType::ASCII; // Change msb_ property to ASCII: ++// Example 2: change all REAL32 data to REAL64 ++// LataDBDataType old_type; ++// old_type.type_ = LataDBDataType::REAL32; ++// LataDBDataType new_type; ++// new_type.msb_ = LataDBDataType::REAL64; ++void LataDB::change_all_data_types(const LataDBDataType & old_type, const LataDBDataType & new_type) ++{ ++ const entier nb_tsteps = timesteps_.size(); ++ for (entier src_tstep = 0; src_tstep < nb_tsteps; src_tstep++) { ++ LataVector & fields = timesteps_[src_tstep].fields_; ++ const entier nb_fields = fields.size(); ++ for (entier i_field = 0; i_field < nb_fields; i_field++) { ++ LataDBDataType & type = fields[i_field].datatype_; ++ // For each field, if "old_type" is "unknown" or equal to the previous value, ++ // and if "new_type" is not "unknown, then update the field ++ UPDATE_MACRO(msb_, LataDBDataType::UNKNOWN_MSB); ++ UPDATE_MACRO(type_, LataDBDataType::UNKNOWN_TYPE); ++ UPDATE_MACRO(array_index_, LataDBDataType::UNKNOWN_ARRAYINDEX); ++ UPDATE_MACRO(data_ordering_, LataDBDataType::UNKNOWN_ORDERING); ++ UPDATE_MACRO(fortran_bloc_markers_, LataDBDataType::UNKNOWN_MARKERS); ++ UPDATE_MACRO(bloc_marker_type_, LataDBDataType::UNKNOWN_TYPE); ++ } ++ } ++} ++#undef UPDATE_MACRO ++ ++void LataDB::change_all_data_filenames(const Nom & old_prefix, const Nom & new_prefix) ++{ ++ const entier nb_tsteps = timesteps_.size(); ++ for (entier i = 0; i < nb_tsteps; i++) { ++ LataVector & fields = timesteps_[i].fields_; ++ // Browse all fields: ++ const entier nb_fields = fields.size(); ++ for (entier j = 0; j < nb_fields; j++) { ++ Nom & filename = fields[j].filename_; ++ Nom old_filename = filename; ++ filename = new_prefix; ++ if (old_filename.debute_par(old_prefix)) { ++ const entier n = old_filename.longueur()-1; ++ const char * s = old_filename; ++ for (entier ii = old_prefix.longueur()-1; ii < n; ii++) ++ filename += Nom(s[ii]); ++ } else if (old_filename == LataDBField::memory_buffer_file()) { ++ filename += Nom(".data"); ++ } else { ++ filename += Nom('_'); ++ filename += old_filename; ++ } ++ Journal(verb_level+1) << " Changing filename " << old_filename << " -> " << filename << endl; ++ } ++ } ++} ++ ++// This method takes all filenames mentionned in the database and sets the file_offset_ entry: ++// - set to 0 for the first field where a given filename appears, ++// - then for all subsequent files referring to the same name: ++// If split_files != 0, rename the files by appending a "_number" and set file_offset to 0 ++// otherwise set file_offset_ to 1 ++void LataDB::check_all_data_fileoffsets(entier split_files) ++{ ++ Noms existing_filenames; ++ ArrOfInt counts; // For each filenames, number of fields referring to it ++ counts.set_smart_resize(1); ++ ++ const entier nb_tsteps = timesteps_.size(); ++ for (entier i = 0; i < nb_tsteps; i++) { ++ LataVector & fields = timesteps_[i].fields_; ++ // Browse all fields: ++ const entier nb_fields = fields.size(); ++ for (entier j = 0; j < nb_fields; j++) { ++ LataDBField & field = fields[j]; ++ const entier rank = existing_filenames.rang(field.filename_); ++ if (rank < 0) { ++ // New filename ++ existing_filenames.add(field.filename_); ++ counts.append_array(1); ++ field.datatype_.file_offset_ = 0; ++ Journal(verb_level+1) << " Changing fileoffset to 0 for file " << field.filename_ ++ << " " << field.name_ << endl; ++ } else { ++ // Existing filename ++ if (split_files) { ++ entier n = counts[rank]++; ++ field.filename_ += "_"; ++ field.filename_ += Nom(n); ++ field.datatype_.file_offset_ = 0; ++ Journal(verb_level+1) << " Changing fileoffset to 0 and renaming file " << field.filename_ ++ << " " << field.name_ << endl; ++ } else { ++ field.datatype_.file_offset_ = 1; ++ Journal(verb_level+1) << " Changing fileoffset to 1 for file " << field.filename_ ++ << " " << field.name_ << endl; ++ } ++ } ++ } ++ } ++} ++ ++// Returns the rank of the created timestep (always at the end) ++entier LataDB::add_timestep(double time) ++{ ++ const entier n = nb_timesteps(); ++ // Timestep 0 can have any time: test only versus other timesteps: ++ if (n > 1 && time <= get_time(n-1)) { ++ Journal() << "Error in LataDB::add_timestep(" << time ++ << "): time is below or equal to last timestep " << get_time(n-1) << endl; ++ throw(LataDBError(LataDBError::INVALID_OPERATION)); ++ } ++ LataDBTimestep & t = timesteps_.add(LataDBTimestep()); ++ t.time_ = time; ++ Journal(verb_level+1) << "LataDB::add_timestep " << n << " " << time << endl; ++ return n; ++} ++ ++static void add_geom_check(const LataDBGeometry & geom, entier test_flag, const char *message) ++{ ++ if (!test_flag) { ++ Journal() << "Error in LataDB::add_geometry, name_=" << geom.name_ << endl ++ << " geometry data is invalid because of: " << message << endl; ++ throw(LataDBError(LataDBError::INVALID_OPERATION)); ++ } ++} ++ ++void LataDB::add_geometry(const LataDBGeometry & geom) ++{ ++ add_geom_check(geom, geom.timestep_ >= 0 && geom.timestep_ < nb_timesteps(), "timestep"); ++ Noms geoms= geometry_names(geom.timestep_, CURRENT); ++ add_geom_check(geom, geom.name_ != "" && geom.name_ != "??" && geoms.rang(geom.name_) < 0, "empty or already existing name"); ++ ++ add(geom.timestep_, geom); ++ Journal(verb_level+1) << "LataDB::add_geometry " << geom.name_ << endl; ++} ++ ++void LataDB::set_elemtype(entier tstep, const char *geom_name, const char *elem_type) ++{ ++ LataDBGeometry & geom = (LataDBGeometry&) get_geometry(tstep, geom_name); ++ geom.elem_type_ = elem_type; ++} ++ ++ ++static void add_field_check(const LataDBField & field, entier test_flag, const char *message) ++{ ++ if (!test_flag) { ++ Journal() << "Error in LataDB::add_field, name_=" << field.name_ << " geometry=" << field.geometry_ << endl ++ << " field data is invalid because of: " << message << endl; ++ throw(LataDBError(LataDBError::INVALID_OPERATION)); ++ } ++} ++ ++// Adds a new field to the database. ++// The field.datatype_.file_offset_ will be interpreted in a particular way if the data is ++// written with write_data(), see write_data() documentation. ++// Take special care if the same file is referenced more than once in the database: ++// only one file should have file_offset_ <= 0 and this one will have to be written first ++// with write_data() (or you know what you are doing...) ++void LataDB::add_field(const LataDBField & field) ++{ ++ add_field_check(field, field.timestep_ >= 0 && field.timestep_ < nb_timesteps(), "timestep"); ++ add_field_check(field, field.filename_ != "" && field.filename_ != "??", "filename"); ++ add_field_check(field, field.nb_comp_ > 0, "nb_comp"); ++ Noms geoms = geometry_names(field.timestep_, FIRST_AND_CURRENT); ++ add_field_check(field, field.geometry_ == "" || geoms.rang(field.geometry_) >= 0, "unknown geometry name"); ++ add_field_check(field, field.name_ != "" && field.name_ != "??", "empty name"); ++ add_field_check(field, field.component_names_.size() == 0 || field.component_names_.size() == field.nb_comp_, "number of component_names"); ++ add_field_check(field, field.size_ >= 0, "size"); ++ add_field_check(field, field.datatype_.msb_ != LataDBDataType::UNKNOWN_MSB, "datatype msb unspecified"); ++ add_field_check(field, field.datatype_.type_ == LataDBDataType::INT32 ++ || field.datatype_.type_ == LataDBDataType::INT64 ++ || field.datatype_.type_ == LataDBDataType::REAL32 ++ || field.datatype_.type_ == LataDBDataType::REAL64, "datatype type unspecified"); ++ // If integer type, we must say the indexing type: ++ add_field_check(field, ++ field.datatype_.type_ == LataDBDataType::REAL32 ++ || field.datatype_.type_ == LataDBDataType::REAL64 ++ || field.datatype_.array_index_ != LataDBDataType::UNKNOWN_ARRAYINDEX, ++ "datatype array indexing unspecified"); ++ add_field_check(field, field.datatype_.data_ordering_ != LataDBDataType::UNKNOWN_ORDERING, "datatype data ordering unspecified"); ++ add_field_check(field, field.datatype_.fortran_bloc_markers_ != LataDBDataType::UNKNOWN_MARKERS, "datatype fortran bloc markers unspecified"); ++ add_field_check(field, field.datatype_.file_offset_ >= 0, "datatype file_offset_"); ++ // ouf... ++ add(field.timestep_, field); ++ Journal(verb_level+1) << "LataDB::add_field : " << field.name_ << " " << field.geometry_ << " " << field.filename_ << " " << field.uname_ << endl; ++} ++ ++LataDBDataType LataDB::default_type_float() const ++{ ++ LataDBDataType type = default_type_int_; ++ type.type_ = default_float_type_; ++ return type; ++} ++ ++// Description: Writes the lata master file to filename (filename must contain the path ++// if you don't want to write in the current working directory). All data contained ++// in the database is dumped to the file. ++void LataDB::write_master_file(const char *filename) const ++{ ++ if (!filename) { ++ Journal() << "LataDB::write_master_file got a null filename !!!" << endl; ++ throw(LataDBError(LataDBError::INVALID_OPERATION)); ++ } ++ std::ofstream os(filename); ++ if (!os.good()) { // isnogood ? ++ Journal() << "LataDB::write_master_file failed opening file " << filename << endl; ++ throw(LataDBError(LataDBError::FILE_NOT_FOUND)); ++ } ++ // Try to write, if error, catch and close the file: ++ Journal(verb_level-1) << "Writing lata master file:" << filename << endl; ++ os << "LATA_V2.1" << endl; ++ os << case_ << endl; ++ os << software_id_ << endl; ++ ++ // **************************************************************** ++ // Writing data format information: ++ { ++ Motcle fmt, fmt2; ++ build_format_string(LataDBDataType(), default_type_int_, fmt); ++ build_format_string(default_type_int_, default_type_float(), fmt2); ++ os << "Format " << fmt << "," << fmt2 << endl; ++ } ++ ++ // *************************************************************** ++ // Writing timesteps: ++ const entier nb_tsteps = nb_timesteps(); ++ for (entier tstep = 0; tstep < nb_tsteps; tstep++) { ++ if (tstep > 0) ++ os << "TEMPS " << get_time(tstep) << endl; ++ ++ Noms geoms = geometry_names(tstep); ++ const entier nb_geoms = geoms.size(); ++ for (entier i_geom = 0; i_geom < nb_geoms; i_geom++) { ++ const LataDBGeometry & geom = get_geometry(tstep, geoms[i_geom], FIRST_AND_CURRENT); ++ // Do not write geometries of the first timestep ++ if (geom.timestep_ == tstep) ++ os << "GEOM " << geom.name_ << " type_elem=" << geom.elem_type_ << endl; ++ } ++ Field_UNames unames = field_unames(tstep, "*", "*"); ++ for (entier i_field = 0; i_field < unames.size(); i_field++) { ++ const LataDBField & field = get_field(tstep, unames[i_field]); ++ os << "CHAMP " << field.name_ ++ << " " << field.filename_; ++ if (field.geometry_ != "") ++ os << " geometrie=" << field.geometry_; ++ os << " size=" << field.size_; ++ os << " composantes=" << field.nb_comp_; ++ if (field.localisation_ != "??" && field.localisation_ != "") ++ os << " localisation=" << field.localisation_; ++ if (field.component_names_.size() > 0) { ++ os << " noms_compo="; ++ const entier n = field.component_names_.size(); ++ for (entier i = 0; i < n; i++) { ++ os << field.component_names_[i]; ++ if (i < n-1) ++ os << ","; ++ } ++ } ++ switch(field.nature_) { ++ case LataDBField::UNKNOWN: break; ++ case LataDBField::SCALAR: os << " nature=scalar"; break; ++ case LataDBField::VECTOR: os << " nature=vector"; break; ++ default: ++ Journal() << "LataDB::write_master_file error: unknown NATURE" << endl; ++ throw(LataDBError(LataDBError::INVALID_OPERATION)); ++ } ++ if (field.reference_ != "" && field.reference_ != "??") ++ os << " reference=" << field.reference_; ++ Motcle format_string; ++ build_format_string(default_type_float(), field.datatype_, format_string); ++ if (format_string != "") ++ os << " format=" << format_string; ++ if (field.datatype_.file_offset_ > 0) ++ os << " file_offset=" << field.datatype_.file_offset_; ++ os << endl; ++ } ++ } ++ os << "FIN" << endl; ++ write_master_file_to_call_ = 0; ++} ++ ++// Description: internal template to write a data block. We provide explicit methods write_data() ++// to the user instead of a template. ++template ++FileOffset LataDB::write_data_(entier tstep, const Field_UName & uname, const C_Tab & data) ++{ ++ LataDBField & fld = getset_field(tstep, uname); ++ ++ LataDataFile f(internal_data_buffer_, path_prefix_, fld.filename_, ++ fld.datatype_.msb_, ++ (fld.datatype_.file_offset_ <= 0) ? LataDataFile::WRITE : LataDataFile::APPEND); ++ fld.datatype_.file_offset_ = f.position(); ++ Journal(verb_level_data_bloc) << "Writing block data at offset " << fld.datatype_.file_offset_ << endl; ++ if (fld.nb_comp_ != data.dimension(1) || fld.size_ != data.dimension(0)) { ++ Journal() << "Error in LataDB::write_data_: nb_comp_ or size_ declared in the field doesnt match array dimensions." << fld.name_ << endl; ++ throw; ++ } ++ ++ const entier n = fld.size_; ++ ++ switch (fld.datatype_.data_ordering_) { ++ case LataDBDataType::C_ORDERING: ++ { ++ if (fld.datatype_.fortran_bloc_markers_ == LataDBDataType::BLOC_MARKERS_MULTIPLE_WRITES) { ++ Journal() << "Error in LataDB::write_data_: fortran_bloc_markers_=MULTIPLE_WRITES is incompatible with data_ordering=C" << endl; ++ throw LataDBError(LataDBError::DATA_ERROR); ++ } ++ const entier sz = data.size_array(); ++ write_blocksize(f, fld.datatype_, sz); ++ bloc_write(f, fld.datatype_.msb_, fld.datatype_.type_, data, fld.nb_comp_); ++ write_blocksize(f, fld.datatype_, sz); ++ break; ++ } ++ case LataDBDataType::F_ORDERING: ++ { ++ entier multiple_bloc_markers = (fld.datatype_.fortran_bloc_markers_ == LataDBDataType::BLOC_MARKERS_MULTIPLE_WRITES); ++ // reverse rows and columns of the array ++ C_Tab tmp; ++ tmp.resize(n, 1); ++ if (!multiple_bloc_markers) ++ write_blocksize(f, fld.datatype_, data.size_array()); ++ for (entier i = 0; i < fld.nb_comp_; i++) { ++ if (multiple_bloc_markers) ++ write_blocksize(f, fld.datatype_, n); ++ for (entier j = 0; j < n; j++) ++ tmp(j, 0) = data(j, i); ++ bloc_write(f, fld.datatype_.msb_, fld.datatype_.type_, tmp, 1); ++ if (multiple_bloc_markers) ++ write_blocksize(f, fld.datatype_, n); ++ } ++ if (!multiple_bloc_markers) ++ write_blocksize(f, fld.datatype_, data.size_array()); ++ break; ++ } ++ default: ++ Journal() << "Error in LataDB::write_data_: data_ordering not implemented" << endl; ++ throw; ++ } ++ write_master_file_to_call_ = 1; ++ return f.position(); ++} ++ ++// Writes the data to disk according to datatype_ of the field. ++// The filename will be "path_prefix_ + field.filename_". ++// The path_prefix_ can be changed with set_path_prefix() ++// If field.datatype_.file_offset_<=0, any existing file is deleted and the data is written at offset 0 ++// otherwise the data is written at the end of the file and file_offset_ for this field is updated. ++// Returns the FileOffset of the file pointer after writing the data (points to the end of the file) ++// The call to write_master_file() must be done after all write_data (otherwise the file_offset_ might be wrong) ++FileOffset LataDB::write_data(entier tstep, const Field_UName & uname, const DoubleTab &tab) ++{ ++ Journal() << " LataDB::write_data not coded for double" << endl; ++ throw; ++ return 0; ++} ++ ++// See write_data(..., const DoubleTab &) ++FileOffset LataDB::write_data(entier tstep, const Field_UName & uname, const FloatTab &tab) ++{ ++ return write_data_(tstep, uname, tab); ++} ++ ++// See write_data(..., const DoubleTab &) ++FileOffset LataDB::write_data(entier tstep, const Field_UName & uname, const IntTab &tab) ++{ ++ if (get_field(tstep, uname).datatype_.array_index_ == LataDBDataType::F_INDEXING) { ++ IntTab tmp; ++ tmp.set_smart_resize(1); ++ tmp.resize(tab.dimension(0), tab.dimension(1)); ++ ArrOfInt & array = tmp; ++ const ArrOfInt & src = tab; ++ for (entier i = 0; i < array.size_array(); i++) ++ array[i] = src[i] + 1; ++ return write_data_(tstep, uname, tmp); ++ } ++ ++ return write_data_(tstep, uname, tab); ++} ++ ++LataDB::~LataDB() ++{ ++#if 0 ++ if (write_master_file_to_call_) { ++ Journal() << "Internal Error !!! write_data() has been called without calling write_master_file() after." << endl; ++// exit(); // In c++ it is forbidden to throw exceptions in a destructor. ++ } ++#endif ++} ++ ++const char *LataDBError::describe() const ++{ ++ switch(err_) { ++ case READ_ERROR: return "READ_ERROR"; break; ++ case BAD_HEADER: return "BAD_HEADER"; break; ++ case BAD_TIMESTEP: return "BAD_TIMESTEP"; break; ++ case NAME_NOT_FOUND: return "NAME_NOT_FOUND"; break; ++ case DATA_ERROR: return "DATA_ERROR"; break; ++ case FILE_NOT_FOUND: return "FILE_NOT_FOUND"; break; ++ case BAD_ELEM_TYPE: return "BAD_ELEM_TYPE"; break; ++ case INVALID_OPERATION: return "INVALID_OPERATION"; break; ++ case INTEGER_OVERFLOW: return "INTEGER_OVERFLOW"; break; ++ default: ; ++ } ++ return "LataDB_unknown_error"; ++} ++#undef verb_level ++#undef verb_level_data_bloc +diff --git a/databases/readers/Lata/LataDB.h b/databases/readers/Lata/LataDB.h +new file mode 100644 +index 0000000..8862d3c +--- /dev/null ++++ b/databases/readers/Lata/LataDB.h +@@ -0,0 +1,303 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef LataDB_include_ ++#define LataDB_include_ ++#include ++#include ++ ++// This file describes the LataDB class and all associated data structures. ++// LataDB stores all the meta contained in the .lata master file, and not more. ++// It provides services to add meta-data, read data to a user specified array, ++// and write data to a lata file. ++ ++typedef BigEntier FileOffset; ++ ++// .Description: LataDBError is the type used for thrown exceptions in LataDBxxx classes ++class LataDBError ++{ ++public: ++ // READ_ERROR: low level io error while reading .lata file ++ // BAD_HEADER: the header in the .lata file is not correct ++ // BAD_TIMESTEP: request for a non existant timestep ++ // NAME_NOT_FOUND: request for a non existant domain or field name ++ // DATA_ERROR: low level io error while reading a data bloc file ++ // FILE_NOT_FOUND: a file (.lata or data) couldn't be opened on disc. ++ // INVALID_OPERATION: trying to read from a modified database, etc... ++ // INTEGER_OVERFLOW: trying to convert an integer to a too small data type ++ // (if error when reading a data file, you must recompile with typedef long long entier, ++ // if error when writing a data file, you must use INT64 type_ for data blocks) ++ enum ErrType { READ_ERROR, BAD_HEADER, BAD_TIMESTEP, NAME_NOT_FOUND, DATA_ERROR, ++ FILE_NOT_FOUND, BAD_ELEM_TYPE, INVALID_OPERATION, INTEGER_OVERFLOW }; ++ LataDBError(ErrType err) : err_(err) {}; ++ ErrType err_; ++ const char *describe() const; ++}; ++ ++// .Description: This is the data type for a specific part of a data bloc. ++// In order to read a data bloc, we need a LataDBDataType for the "bloc size" id (this is an integer), ++// and a LataDBDataType for the bloc content. LataDBGeometry blocs need two types, one for ++// the node coordinates and one for the elements ++class LataDBDataType ++{ ++public: ++ enum MSB { UNKNOWN_MSB, MSB_BIG_ENDIAN, MSB_LITTLE_ENDIAN, ASCII }; ++ MSB msb_; ++ enum Type { UNKNOWN_TYPE, INT32, INT64, REAL32, REAL64 }; ++ Type type_; ++ // Array index is ignored if type_ is REAL. ++ // NOT_AN_INDEX: array does not contain indexes. ++ // C_INDEXING: If array contains indexes to other items, 0 <= array[i] < nb_items ++ // F_INDEXING: 1 <= array[i] <= nb_items (Fortran index) ++ // See LataDB::read_data ++ enum ArrayIndex { UNKNOWN_ARRAYINDEX, NOT_AN_INDEX, C_INDEXING, F_INDEXING }; ++ ArrayIndex array_index_; ++ // C_ORDERING: If multidimensionnal array is read, data ordering is like in C ++ // (all components for first node, then all components for second node, etc) ++ // F_ORDERING: like in fortran (first all values for component 0 then all values for compo 1 etc) ++ enum DataOrdering { UNKNOWN_ORDERING, C_ORDERING, F_ORDERING }; ++ DataOrdering data_ordering_; ++ ++ // _NO_BLOC: no fortran bloc marker ++ // _SINGLE_WRITE: all data written in one fortran write instruction ++ // _MULTIPLE_WRITES: one fortran write instruction for each component ++ enum FortranBlocMarkers { UNKNOWN_MARKERS, NO_BLOC_MARKER, BLOC_MARKERS_SINGLE_WRITE, BLOC_MARKERS_MULTIPLE_WRITES }; ++ FortranBlocMarkers fortran_bloc_markers_; ++ ++ // The data type for fortran bloc markers ++ Type bloc_marker_type_; ++ ++ // Data is located at this offset in the file ++ FileOffset file_offset_; ++ ++ LataDBDataType() : msb_(UNKNOWN_MSB), type_(UNKNOWN_TYPE), array_index_(UNKNOWN_ARRAYINDEX), ++ data_ordering_(UNKNOWN_ORDERING), fortran_bloc_markers_(UNKNOWN_MARKERS), bloc_marker_type_(UNKNOWN_TYPE), ++ file_offset_(0) ++ {}; ++ static MSB machine_msb_; ++}; ++ ++// .Description: Description of a geometry (= a mesh) ++class LataDBGeometry ++{ ++public: ++ LataDBGeometry() { timestep_ = -1; } ++ // Item name ++ Nom name_; ++ // Type of elements ++ Motcle elem_type_; ++ entier timestep_; ++}; ++ ++// This is a unique identifier for fields ++// at this time, contains domain name, field name and localisation, ++// might be further extended if needed ++class Field_UName ++{ ++public: ++ Field_UName(); ++ Field_UName(const char *domain_name, const char *field_name, const char *loc); ++ Field_UName(const Field_UName &); ++ int operator==(const Field_UName &) const; ++ Field_UName & operator=(const Field_UName &); ++ Nom build_string() const; ++ const Motcle & get_localisation() const { return loc_; } ++ const Motcle & get_field_name() const { return field_name_; } ++ const Motcle & get_geometry() const { return geometry_; } ++ void set_field_name(const Nom &); ++protected: ++ Motcle geometry_; ++ Motcle field_name_; ++ Motcle loc_; ++}; ++ ++std::ostream & operator<<(std::ostream &, const Field_UName &); ++ ++typedef LataVector Field_UNames; ++class EFichier; ++ ++// .Description: Description of a field ++class LataDBField ++{ ++public: ++ LataDBField() { timestep_ = -1; nb_comp_ = -1; nature_ = UNKNOWN; size_ = -1; } ++ ++ // Unique identifier ++ Field_UName uname_; ++ // Field name (without localisation spec) ++ Nom name_; ++ // Where is it ? ++ int timestep_; ++ // Filename containing the data ++ // Special names: memory_buffer_file() => data stored in the LataDB memory buffer. ++ Nom filename_; ++ // Number of components ++ entier nb_comp_; ++ // LataDBGeometry ++ Nom geometry_; ++ // Name of the components ++ Noms component_names_; ++ Noms unites_; ++ // Scalar or vector ? ++ enum Nature { UNKNOWN, SCALAR, VECTOR }; ++ Nature nature_; ++ // Type and formatting info of the data ++ LataDBDataType datatype_; ++ // Localisation (elem, som, faces, ...) ++ Motcle localisation_; ++ // Ref ++ Nom reference_; ++ // Size (number of lines) ++ long long size_; ++ ++ static const char * memory_buffer_file(); ++}; ++ ++// .Description: Description of one timestep (contains a vector of items) ++class LataDBTimestep ++{ ++public: ++ LataDBTimestep() { time_ = -1.; } ++ double time_; ++protected: ++ friend class LataDB; ++ LataVector geoms_; ++ LataVector fields_; ++}; ++ ++class LataDataFile; ++class ArrOfInt; ++class LataDB ++{ ++public: ++ 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; } ++ LataDB(const LataDB & src) : ++ header_(src.header_), ++ case_(src.case_), ++ software_id_(src.software_id_), ++ default_type_int_(src.default_type_int_), ++ default_float_type_(src.default_float_type_), ++ timesteps_(src.timesteps_), ++ path_prefix_(src.path_prefix_), ++ old_style_lata_(src.old_style_lata_), ++ write_master_file_to_call_(src.write_master_file_to_call_) { ++ // Note B.M. il faudrait copier internal_data_buffer_ pour faire marcher lml->lata mais je ne sais pas faire... ++ } ++ virtual ~LataDB(); ++ void reset(); ++ virtual void read_master_file(const char * path_prefix_, const char * filename); ++ void read_master_file_med(const char *prefix, const char *filename); ++ static Nom read_master_file_options(const char * filename); ++ ++ virtual void filter_db(const LataDB & source, ++ const Motcles & geometry_names, ++ const Motcles & field_names, ++ const ArrOfInt & timesteps); ++ ++ entier nb_timesteps() const; ++ double get_time(entier tstep) const; ++ enum TStepSelector { CURRENT, FIRST_AND_CURRENT }; ++ Noms geometry_names(entier tstep, TStepSelector which_tstep = CURRENT) const; ++ Field_UNames field_unames(entier tstep, const char * geometry, const char * name, TStepSelector which_tstep = CURRENT) const; ++ const LataDBGeometry & get_geometry(entier tstep, const char * name, TStepSelector which_tstep = CURRENT) const; ++ entier field_exists(entier tstep, const char *geom, const char *name, TStepSelector which_tstep = CURRENT) const; ++ const LataDBField & get_field(entier tstep, const Field_UName & uname, TStepSelector which_tstep = CURRENT) const; ++ const LataDBField & get_field(entier tstep, const char *geom, const char *name, const char *loc, TStepSelector which_tstep = CURRENT) const; ++ const Nom & path_prefix() const { return path_prefix_; }; ++ void set_path_prefix(const char * s); ++ ++ // First line in the .lata file ++ Nom header_; ++ // Second line in the .lata file ++ Nom case_; ++ // Third line in the .lata file ++ Nom software_id_; ++ ++ LataDBDataType default_type_float() const; // Everything same as int, but type_=default_float_type_ ++ LataDBDataType default_type_int_; ++ LataDBDataType::Type default_float_type_; ++ ++ virtual void read_data(const LataDBField &, DoubleTab & data, long long debut = 0, entier n = -1) const; ++ virtual void read_data(const LataDBField &, FloatTab & data, long long debut = 0, entier n = -1) const; ++ virtual void read_data(const LataDBField &, IntTab & data, long long debut = 0, entier n = -1) const; ++ virtual void read_data(const LataDBField &, DoubleTab & data, const ArrOfInt & lines_to_read) const; ++ virtual void read_data(const LataDBField &, FloatTab & data, const ArrOfInt & lines_to_read) const; ++ virtual void read_data(const LataDBField &, IntTab & data, const ArrOfInt & lines_to_read) const; ++ ++ enum Element { line, triangle, quadri, tetra, hexa, triangle_3D, quadri_3D, polyedre,polygone, unspecified }; ++ static Element element_type_from_string(const Motcle & type_elem); ++ ++ // Tools to create/update the database and write lata data to disk ++ void change_all_data_types(const LataDBDataType & old_type, const LataDBDataType & new_type); ++ void change_all_data_filenames(const Nom & old_prefix, const Nom & new_prefix); ++ void check_all_data_fileoffsets(entier split_files); ++ entier add_timestep(double time); ++ void add_geometry(const LataDBGeometry & geom); ++ void set_elemtype(entier tstep, const char *geom_name, const char *elem_type); ++ entier check_duplicate_filename(const char *filename) const; ++ void add_field(const LataDBField & field); ++ void write_master_file(const char *filename) const; ++ FileOffset write_data(entier tstep, const Field_UName &, const DoubleTab &); ++ FileOffset write_data(entier tstep, const Field_UName &, const FloatTab &); ++ FileOffset write_data(entier tstep, const Field_UName &, const IntTab &); ++ ++protected: ++ LataDBField & getset_field(entier tstep, const Field_UName & uname, TStepSelector which_tstep = CURRENT); ++ void read_master_file_header(const char *filename, EFichier & is); ++ static entier lata_v1_dim_from_elem_type(const Motcle & elem_type); ++ static entier lata_v1_get_nb_comp(const Nom & fieldname, const Motcle & localisation, const LataDBGeometry & dom, entier dim, LataDBField::Nature & nature, LataDBDataType::DataOrdering &); ++ static void get_element_data(const Motcle & elemtype, entier & dimension, entier & elem_shape, entier & face_shape, entier & nb_elem_faces); ++ ++ const LataDBTimestep & get_tstep(entier i) const; ++ void add(entier tstep, const LataDBGeometry & item); ++ void add(entier tstep, const LataDBField & item); ++ template void read_data_(const LataDBField &, C_Tab & data, long long debut, entier n) const; ++ template void read_data_(const LataDBField &, C_Tab & data, const ArrOfInt & lines_to_read) const; ++ template 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; ++ template void read_data2_med_( const LataDBField & fld, C_Tab * const data, entier debut = 0, entier n = -1, const ArrOfInt *lines_to_read = 0) const; ++ template FileOffset write_data_(entier tstep, const Field_UName & uname, const C_Tab &); ++ ++ // Timestep 0 contains global domains and field definition ++ // Timestep 1..size()-1 contain the data for each "TEMPS" entry ++ LataVector timesteps_; ++ ++ // Path prefix for all data blocks (used by read_data() and write_data()) ++ Nom path_prefix_; ++ ++ // Is this an old-style lata file ? (with INTERFACES special files and 2D elements expanded to 3D elements) ++ entier old_style_lata_; ++ ++ // This flag tells if some write_data calls have been made since the last write_master_file ++ // If yes, issue a message to say that's wrong ! ++ mutable entier write_master_file_to_call_; ++ ++ // This is a memory buffer where data can be written to create a temporary data base ++ mutable std::stringstream internal_data_buffer_; ++}; ++#endif +diff --git a/databases/readers/Lata/LataDBmed.h b/databases/readers/Lata/LataDBmed.h +new file mode 100644 +index 0000000..13cfdbe +--- /dev/null ++++ b/databases/readers/Lata/LataDBmed.h +@@ -0,0 +1,586 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++//#define WITH_MEDLOADER ++#ifndef WITH_MEDLOADER ++void LataDB::read_master_file_med(const char *prefix, const char *filename) ++{ ++ Journal() << "MED PLUGIN not compiled!" << endl; ++ throw; ++} ++template void LataDB::read_data2_med_( ++ const LataDBField & fld, ++ C_Tab * const data, // const pointer to non const data ! ++ entier debut, entier n, const ArrOfInt *lines_to_read) const ++{ ++ Journal() << "MED PLUGIN not compiled!" << endl; ++ ++ throw; ++} ++#else ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++using std::vector; ++using std::pair; ++using std::string; ++ ++ ++Nom latadb_name_from_type_geo(const med_geometry_type& type_geo) ++{ ++ Nom type_elem; ++ switch(type_geo) ++ { ++ case MED_QUAD4: ++ type_elem="Rectangle"; ++ break; ++ case MED_HEXA8: ++ type_elem="Hexaedre"; ++ break; ++ case MED_TRIA3: ++ type_elem="Triangle";break; ++ case MED_TETRA4: ++ type_elem="Tetraedre";break; ++ case MED_PENTA6: ++ type_elem="Prisme";break; ++ case MED_POLYHEDRON: ++ type_elem="Polyedre"; break; ++ case MED_POLYGON: ++ type_elem="Polygone"; break; ++ case MED_SEG2: ++ type_elem="Segment"; break; ++ default: ++ Cerr<<"type_geo " << (int)type_geo <<" is not a supported element."<& NIJK) ++{ ++ is_structured=0; ++ int meshDim, i; ++ try { ++ std::vector< std::vector< std::pair > > res = MEDCoupling::GetUMeshGlobalInfo(filename, meshname, meshDim, spacedim, nnodes); ++ ++ ++ // on prend que la dimension la plus grande et on verifie que l'on a qu'un type elt ++ if (res.size()>1) ++ { ++ cerr<<"error multi dimension in "<1) ++ { ++ cerr<<"error multi elements in "<getNumberOfCells(); ++ const int *idx = mesh->getNodalConnectivityIndex()->getConstPointer(); ++ for (i = 0, nbcomp = 0; i < ncells; i++) if (nbcomp < idx[i + 1] - idx[i] - 1) nbcomp = idx[i + 1] - idx[i] - 1; ++ mesh->decrRef(); ++ } ++ else ++ ncells=res[0][0].second; ++ } ++ catch (...) ++ { ++ // No UMesh try CMesh ++ MEDCoupling::MEDCouplingMesh* mesh= MEDCoupling::ReadMeshFromFile(filename, meshname); ++ /* ++ type_geo,int& ncells,int& nnodes,int& spacedim, int &nbcomp ++ */ ++ MEDCoupling::MEDCouplingCMesh* cmesh = dynamic_cast(mesh); ++ spacedim=cmesh-> getSpaceDimension() ; ++ ++ NIJK= cmesh->getNodeGridStructure(); ++ ncells=mesh->getNumberOfCells(); ++ nnodes=mesh->getNumberOfNodes(); ++ ++ ++ // std::cout << ncells<< " "<decrRef(); ++ ++ if (spacedim==3) ++ type_geo =MED_HEXA8; ++ else if (spacedim==2) ++ type_geo =MED_QUAD4; ++ else ++ abort(); ++ is_structured=1; ++ //abort(); ++ return; ++ } ++} ++ ++ ++ ++// Description: Reads the .lata database in the given file indicating than the ++// associated data files will be found in directory "prefix". ++// If not empty, "prefix" must finish with a '/'. ++// For "prefix" and "filename", if they do not begin with '/', are relative to pwd. ++// Exceptions: ++// BAD_HEADER means that the header found in this stream is not LATA_V2 ++// READ_ERROR means that an error has been found in the file (premature eof, ++// io error, bad keyword, ...) ++// FILE_NOT_FOUND means that, well, the lata file could not be opened ++void LataDB::read_master_file_med(const char *prefix, const char *filename) ++{ ++ ++ ++ Journal() << "MED PLUGIN !" << endl; ++ ++ // Defaults for lataV1 ++ default_type_int_.msb_ = LataDBDataType::ASCII; ++ default_type_int_.type_ = LataDBDataType::INT32; ++ default_type_int_.array_index_ = LataDBDataType::F_INDEXING; ++ default_type_int_.data_ordering_ = LataDBDataType::C_ORDERING; ++ default_type_int_.fortran_bloc_markers_ = LataDBDataType::BLOC_MARKERS_SINGLE_WRITE; ++ default_type_int_.bloc_marker_type_ = LataDBDataType::INT32; ++ default_float_type_ = LataDBDataType::REAL32; ++ ++ ++ ++ // Create timestep 0 (global domain and fields) ++ timesteps_.add(LataDBTimestep()); ++ ++ ++ // on ajoute les geom ++ // on verra apres pour les champs elem et som ++ vector geoms= MEDCoupling::GetMeshNames(filename); ++ ++ vector times; ++ LataDBTimestep table; ++ int first=1; ++ ++ for (int i=0;i NIJK; ++ latadb_get_info_mesh_med(filename,geoms[i].c_str(),type_geo,ncells,nnodes,spacedim,nbcomp,is_structured,NIJK); ++ ++ dom.elem_type_=latadb_name_from_type_geo(type_geo); ++ ++ if (is_structured==0) ++ { ++ LataDBField som; ++ som.name_ = "SOMMETS"; ++ som.geometry_ = dom.name_; ++ som.filename_ = filename; ++ som.size_=nnodes; ++ som.datatype_ = default_type_float(); // ?? ++ som.nb_comp_=spacedim; ++ ++ LataDBField elem; ++ elem.name_ = "ELEMENTS"; ++ elem.geometry_ = dom.name_; ++ elem.filename_ = filename; ++ elem.size_=ncells; ++ elem.datatype_ = default_type_float(); // ?? ++ ++ int dim,ff,ef; ++ get_element_data(dom.elem_type_, dim, elem.nb_comp_, ff, ef); ++ if (elem.nb_comp_ == -1) elem.nb_comp_ = nbcomp; ++ ++ add(timesteps_.size() - 1, dom); ++ add(timesteps_.size() - 1, som); ++ add(timesteps_.size() - 1, elem); ++ } ++ else ++ { ++ add(timesteps_.size() - 1, dom); ++ { ++ LataDBField som; ++ som.name_ = "SOMMETS_IJK_I"; ++ som.geometry_ = dom.name_; ++ som.filename_ = filename; ++ som.size_=NIJK[0]; ++ som.datatype_ = default_type_float(); // ?? ++ som.nb_comp_=1; ++ add(timesteps_.size() - 1, som); ++ } ++ { ++ LataDBField som; ++ som.name_ = "SOMMETS_IJK_J"; ++ som.geometry_ = dom.name_; ++ som.filename_ = filename; ++ som.size_=NIJK[1]; ++ som.datatype_ = default_type_float(); // ?? ++ som.nb_comp_=1; ++ add(timesteps_.size() - 1, som); ++ } ++ { ++ LataDBField som; ++ som.name_ = "SOMMETS_IJK_K"; ++ som.geometry_ = dom.name_; ++ som.filename_ = filename; ++ som.size_=NIJK[2]; ++ som.datatype_ = default_type_float(); // ?? ++ som.nb_comp_=1; ++ add(timesteps_.size() - 1, som); ++ } ++ ++ } ++ ++ ++ vector fields; ++ fields= MEDCoupling::GetAllFieldNamesOnMesh(filename,dom.name_.getString()); ++ ++ ++ for (int i=0;i ltypes=MEDCoupling::GetTypesOfField(filename,meshname.getString(),fields[i].c_str()); ++ //if (ltypes.size()!=1) throw; ++ for (int t=0;t1) ++ { ++ vector > iters= MEDCoupling::GetFieldIterations(ltypes[t],filename,meshname.getString(),fields[i].c_str()); ++ for (int iter=0;iter,double> > vtimes=MEDCoupling::GetAllFieldIterations(filename,/*meshname,*/fields[i].c_str()); ++ for (int it=0;it0) ++ for (int i=0;i ++void LataDB::read_data2_med_( ++ const LataDBField & fld, ++ C_Tab * const data, // const pointer to non const data ! ++ entier debut, entier n, const ArrOfInt *lines_to_read) const ++{ ++ assert(debut==0); ++ //assert(n==-1); ++ assert(lines_to_read==NULL); ++ ++ if (fld.name_=="SOMMETS") ++ { ++ // cerr<<"load sommets "<getCoords(); ++ data->resize(fld.size_,fld.nb_comp_); ++ for (int i=0;igetIJ(i,j); ++ } ++ mesh->decrRef(); ++ ++ } ++ else if (fld.name_=="ELEMENTS") ++ { ++ // cerr<<"load elements "<getNodalConnectivity(), *idx = mesh->getNodalConnectivityIndex(); ++ const int *ptr_elems=elems->getConstPointer(), *ptr_idx = idx->getConstPointer(); ++ data->resize(fld.size_,fld.nb_comp_); ++ int compt=0; ++ for (int i=0;i0 ? filter[j] : j) = reel ? ptr_elems[compt] + 1 : 0; ++ compt += reel; ++ } ++ } ++ mesh->decrRef(); ++ } ++ else if (fld.name_.debute_par("SOMMETS_IJK_")) ++ { ++ MEDCoupling::MEDCouplingMesh * mesh= MEDCoupling::ReadMeshFromFile(fld.filename_.getString(),fld.geometry_.getString()); ++ data->resize(fld.size_,fld.nb_comp_); ++ MEDCoupling::MEDCouplingCMesh* cmesh = dynamic_cast(mesh); ++ int dir; ++ if (fld.name_=="SOMMETS_IJK_I") ++ dir=0; ++ else if (fld.name_=="SOMMETS_IJK_J") ++ dir=1; ++ else if (fld.name_=="SOMMETS_IJK_K") ++ dir=2; ++ else ++ abort(); ++ const MEDCoupling::DataArrayDouble* coords=cmesh->getCoordsAt(dir); ++ for (int i=0;igetIJ(i,j); ++ } ++ mesh->decrRef(); ++ } ++ ++ else ++ { ++ ++ data->resize(fld.size_,fld.nb_comp_); ++ ++ // if (fld.timestep_==1) iter.first=1; ++ // double t; ++ Nom fieldname=fld.name_; ++ fieldname+="_"; ++ fieldname+=fld.localisation_; ++ fieldname+="_"; ++ fieldname+=fld.geometry_; ++ ++ int ok=0; ++ ++ vector fields= MEDCoupling::GetAllFieldNamesOnMesh(fld.filename_.getString(),fld.geometry_.getString()); ++ ++ for (int f=0;f,double> > vtimes=MEDCoupling::GetAllFieldIterations(fld.filename_.getString(),fieldname.getString()); ++ ++ int it=fld.timestep_-1; ++ pair iter(fld.timestep_-1,-1); ++ if (fld.timestep_==1) it=0; ++ //Cerr<getUndergroundDataArray(); ++ ++ if (field->getNumberOfComponents()!=fld.nb_comp_) ++ { ++ cerr<getNumberOfComponents()<<" test "<< endl; ++ Journal()<getNumberOfComponents()==fld.nb_comp_); ++ const double* ptr=values->getConstPointer(); ++ for (int i=0;idecrRef(); ++ } ++} ++#endif +diff --git a/databases/readers/Lata/LataFilter.C b/databases/readers/Lata/LataFilter.C +new file mode 100644 +index 0000000..5c4a764 +--- /dev/null ++++ b/databases/readers/Lata/LataFilter.C +@@ -0,0 +1,1106 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++static const entier cache_info_level = 5; ++static const entier filter_info_level = 4; ++ ++entier LataOptions::read_int_opt(const Nom & s) ++{ ++ const char *ptr = strstr(s, "="); ++ if (!ptr) ++ ptr = s; ++ errno = 0; ++ char *errorptr = 0; ++ entier x = strtol(ptr+1, &errorptr, 0 /* base 10 par defaut */); ++ if (errno || *errorptr != 0) { ++ Journal() << "LataOptions error reading int parameter: " << s << endl; ++ throw; ++ } ++ return x; ++} ++ ++double LataOptions::read_float_opt(const Nom & s) ++{ ++ const char *ptr = strstr(s, "="); ++ if (!ptr) ++ ptr = s; ++ errno = 0; ++ char *errorptr = 0; ++ double x = strtod(ptr+1, &errorptr); ++ if (errno || *errorptr != 0) { ++ Journal() << "LataOptions error reading float parameter: " << s << endl; ++ throw; ++ } ++ return x; ++} ++ ++Nom LataOptions::read_string_opt(const Nom & s) ++{ ++ const char *ptr = strstr(s, "="); ++ if (!ptr) ++ return s; ++ else ++ return Nom(ptr+1); ++} ++ ++Noms extract_list(const Nom & n) ++{ ++ Noms liste; ++ if (n == "") ++ return liste; ++ const char *ptr = n; ++ Nom tmp(""); ++ while (*ptr) { ++ if (*ptr == ',') { ++ liste.add(tmp); ++ tmp = ""; ++ } else { ++ tmp += Nom(*ptr); ++ } ++ } ++ liste.add(tmp); ++ return liste; ++} ++ ++void LataOptions::describe() ++{ ++ cerr << "Data processing options (provided by the LataFilter module)" << endl; ++ cerr << " reconnect=tolerance : Find duplicate positions, and redefine connections to use" << endl; ++ cerr << " always the same positions. tolerance is the maximum distance between" << endl; ++ cerr << " positions that are considered equal." << endl; ++ cerr << " Useful for results of parallel runs, where the domain could" << endl; ++ cerr << " appear fragmented in as many subdomains as procs used." << endl; ++ cerr << " This operator modifies the loaded domain, does not create a new domain." << endl; ++ cerr << " regularize=tolerance : Try to transform the irregular domain in a ijk domain." << endl; ++ cerr << " tolerance is the maximum dx, dy or dz between positions that are" << endl; ++ cerr << " considered to have the same x, y or z." << endl; ++ cerr << " !Attention! regularize recalculates positions, connections, and fields" << endl; ++ cerr << " Except in particularly simple cases, you cannot use a regularized domain" << endl; ++ cerr << " for a field that has not been regularized the same way." << endl; ++ cerr << " Create a new domain DOM -> DOM_IJK" << endl; ++ cerr << " regularize_polyedre=N : tells how to convert polyedre elements to VTK:" << endl; ++ cerr << " N=0 (default): any shape, handled as general VTK_CONVEX_POINT_SET" << endl; ++ cerr << " N=1: all elements are extruded in the Z direction (faster and nicer)" << endl; ++ cerr << " ijk_mesh_nb_parts=N : When loading an IJK mesh, automatically split the mesh into" << endl; ++ cerr << " N blocks (N must be <= number of elements in the K direction, usefull in visit)" << endl; ++ cerr << " invalidate : together with regularize, create \"invalid positions\" and \"invalid connections\"" << endl; ++ cerr << " components. Otherwise only set the values of the field to zeroes." << endl; ++ cerr << " extend_domain=n : When regularizing, add n nodes in each directions to have a layer" << endl; ++ cerr << " of invalid positions and connections." << endl; ++ cerr << " dualmesh: Build and export the dual mesh" << endl; ++ cerr << " (control volume for the velocities in VEF)" << endl; ++ cerr << " data at faces become data at elements on the dual mesh." << endl; ++ cerr << " Create a new domain DOM -> DOM_dual" << endl; ++ cerr << " facesmesh: Build and export the faces mesh" << endl; ++ cerr << " (control volume for the velocities in VEF)" << endl; ++ cerr << " data at faces become data at elements on the faces mesh." << endl; ++ cerr << " Create a new domain DOM -> DOM_faces" << endl; ++ ++ //cerr << " ncmesh: Build and export a non-conforming mesh" << endl; ++ //cerr << " (each mesh element has its proprietary nodes, elements are not topologically connected)" << endl; ++ //cerr << " face dependent data become position dependent data on the new mesh." << endl; ++ //cerr << " Create a new domain DOM -> DOM_nc" << endl; ++ cerr << " boundarymesh: Build new domains containing the boundaries only" << endl; ++ cerr << " Create a new domain DOM -> DOM_Boundary" << endl; ++ //cerr << " clipbox=xmin,ymin,zmin,xmax,ymax,zmax : remove from all meshes all nodes," << endl; ++ //cerr << " connections and faces outside of this box" << endl; ++ cerr << " load_virtual_elements: Read the VIRTUAL_ELEMENTS data in the input database, if available" << endl ++ << " and merge nodes, elements and faces to each requested subdomain (using reconnect)" << endl; ++ cerr << " Does not create a new domain, but modifies the loaded domain" << endl; ++ cerr << " ijk_virt_layer=N: load N layers of virtual elements if domain is ijk in lata file" << endl; ++ cerr << " reconnect_tolerance=: specify tolerance for all reconnect operations" << endl; ++ cerr << " (reconnection is applied with load_virtual_elements)" << endl; ++ cerr << " user_fields: activate the User_Fields module (WARN: this module is often application specific," << endl; ++ cerr << " it will fail if some requiered domains/fields are missing in the input database)" << endl; ++ cerr << " export_fields_at_faces: tells to export fields located at faces" << endl; ++ cerr << endl; ++ user_fields_options_.print_help_option(); ++} ++ ++entier LataOptions::parse_option(const Nom & s) ++{ ++ if (s.debute_par("verbosity=")) { ++ entier level = read_int_opt(s); ++ set_Journal_level(level); ++ } else if (s.debute_par("regularize=")) { ++ regularize = true; ++ regularize_tolerance = read_float_opt(s); ++ } else if (s.debute_par("regularize_polyedre=")) { ++ regularize_polyedre = read_int_opt(s); ++ } else if (s.debute_par("extend_domain=")) { ++ extend_domain = read_int_opt(s); ++ } else if (s == "invalidate") { ++ invalidate = true; ++ } else if (s.debute_par("reconnect=")) { ++ reconnect = true; ++ reconnect_tolerance = read_float_opt(s); ++ } else if (s.debute_par("reconnect_tolerance=")) { ++ reconnect_tolerance = read_float_opt(s); ++ } else if (s == "dualmesh") { ++ dual_mesh = true; ++ } else if (s == "nodualmesh") { ++ dual_mesh = false; ++ } else if (s == "ncmesh") { ++ nc_mesh = true; ++ } else if (s == "facesmesh") { ++ faces_mesh = true; ++ } else if (s == "nofacesmesh") { ++ faces_mesh = false; ++ } else if (s == "boundarymesh") { ++ boundary_mesh = true; ++ } else if (s.debute_par("clipbox=")) { ++ Noms list = extract_list(((const char*)s)+8); ++ if (list.size() != 6) { ++ Journal() << "Error : clipbox parameters expects 6 values" << endl; ++ throw; ++ } ++ for (entier i = 0; i < 3; i++) { ++ clipbox_min[i] = read_float_opt(list[i]); ++ clipbox_max[i] = read_float_opt(list[i+3]); ++ } ++ } else if (s == "load_virtual_elements") { ++ load_virtual_elements = true; ++ } else if (s == "user_fields") { ++ user_fields_ = true; ++ Journal() << "Option: User_fields ON" << endl; ++ } else if (s.debute_par("ijk_mesh_nb_parts")) { ++ ijk_mesh_nb_parts_ = read_int_opt(s); ++ } else if (s == "export_fields_at_faces") { ++ export_fields_at_faces_ = 1; ++ } else if (s.debute_par("ijk_virt_layer=")) { ++ ijk_virt_layer = read_int_opt(s); ++ } else ++ return user_fields_options_.parse_option(s);; ++ return 1; ++} ++ ++void LataFilterCache::set_cache_properties(entier clear_on_tstep_change, BigEntier mem_limit) ++{ ++ clear_cache_on_tstep_change_ = clear_on_tstep_change; ++ cache_memory_limit_ = mem_limit; ++} ++ ++// Description: if an entry with "id" tag and timestep exists in the cache, ++// returns the entry, otherwise returns a reference to an empty DERIV that ++// is stored in the cache and stores the associated "id" and timestep. ++// The entry is locked and given a new last_access_time_ to show that it has ++// been used recently. ++// The entry must be released by release_item() when we are finished working ++// with it. ++LataDeriv & LataFilterCache::get_item_(const Nom & id, entier tstep) ++{ ++ entier i; ++ const entier n = data_.size(); ++ for (i = 0; i < n; i++) { ++ const DataCacheItem & item = data_[i]; ++ if (item.id_ == id && item.tstep_ == tstep) ++ break; ++ } ++ if (i == n) { ++ // Look for an empty slot: ++ for (i = 0; i < n; i++) ++ if (data_[i].id_ == "??") ++ break; ++ // No empty slot: create a new slot: ++ if (i == n) ++ data_.add(); ++ DataCacheItem & item = data_[i]; ++ item.id_ = id; ++ item.tstep_ = tstep; ++ item.lock_ = 0; ++ Journal(cache_info_level) << "LataFilterCache::get " << id << " (new cache entry " << i << ")." << endl; ++ } else { ++ Journal(cache_info_level) << "LataFilterCache::get " << id << " (existing cache entry " << i << ")." << endl; ++ } ++ // Mark item and lock it: ++ DataCacheItem & item = data_[i]; ++ item.last_access_time_ = cache_data_access_count_++; ++ item.lock_++; ++ return item.item_; ++} ++ ++ ++// Description: tells that if needed the item can be deleted from cache ++// (there is no reference to it anymore outside of the cache). ++// We update the memory size of this item here. ++void LataFilterCache::release_item(const Nom & id) ++{ ++ Journal(cache_info_level) << "LataFilterCache::release_item " << id << endl; ++ const entier n = data_.size(); ++ entier i; ++ for (i = 0; i < n; i++) { ++ const DataCacheItem & item = data_[i]; ++ if (item.id_ == id) ++ break; ++ } ++ if (i == n) { ++ Journal() << "LataFilterCache::release_item internal error: unknown item " << id << endl; ++ throw; ++ } ++ if (data_[i].lock_ <= 0) { ++ Journal() << "LataFilterCache::release_item internal error: item is already unlocked" << id << endl; ++ throw; ++ } ++ data_[i].last_access_time_ = cache_data_access_count_++; ++ data_[i].lock_--; ++ if (data_[i].item_.non_nul()) ++ data_[i].memory_size_ = data_[i].item_.valeur().compute_memory_size(); ++ else ++ data_[i].memory_size_ = 0; ++} ++ ++// Description: removes from the cache the oldest items until the total ++// memory used by the cache is below max_mem_size (in bytes), and ++// if tstep_to_keep > 0, also removes all timesteps except 0 and tstep_to_keep ++void LataFilterCache::cleanup_cache(entier tstep_to_keep) ++{ ++ if (clear_cache_on_tstep_change_ && tstep_to_keep > 0) { ++ Journal(cache_info_level) << "LataFilterCache::clear_cache_tsteps except 0 and " << tstep_to_keep << endl; ++ const entier n = data_.size(); ++ for (entier i = 0; i < n; i++) { ++ DataCacheItem & item = data_[i]; ++ if (item.id_ != "??") { ++ if (item.tstep_ == 0 || item.tstep_ == tstep_to_keep) { ++ Journal(cache_info_level+1) << " item " << item.id_ << " timestep " << item.tstep_ << " kept" << endl; ++ } else if (item.lock_) { ++ Journal(cache_info_level+1) << " item " << item.id_ << " locked" << endl; ++ } else { ++ Journal(cache_info_level) << " deleting item " << item.id_ << " " << item.tstep_ << endl; ++ item.item_.reset(); ++ item.id_ = "??"; ++ item.tstep_ = -1; ++ } ++ } ++ } ++ } ++ if (cache_memory_limit_ >= 0) { ++ Journal(cache_info_level) << "LataFilterCache::clear_cache_memory " << cache_memory_limit_ << endl; ++ do { ++ const entier n = data_.size(); ++ // Scan cached data, looking for the oldest item and summing up memory ++ BigEntier total_memsize = 0; ++ entier oldest = -1; ++ BigEntier oldest_time = cache_data_access_count_; ++ for (entier i = 0; i < n; i++) { ++ const DataCacheItem & item = data_[i]; ++ if (item.id_ != "??") { ++ total_memsize += item.memory_size_; ++ if (!item.lock_ && item.last_access_time_ < oldest_time) { ++ oldest_time = item.last_access_time_; ++ oldest = i; ++ } ++ } ++ } ++ if (oldest < 0 || total_memsize < cache_memory_limit_) ++ break; ++ ++ DataCacheItem & item = data_[oldest]; ++ Journal(cache_info_level) << " deleting item " << item.id_ << " " << item.tstep_ << endl; ++ item.item_.reset(); ++ item.id_ = "??"; ++ item.tstep_ = -1; ++ } while(1); ++ } ++} ++ ++// Description: Cleanup everything, associate the lata_db and fills metadata information. ++void LataFilter::initialize(const LataOptions & opt, const LataDB & lata_db) ++{ ++ opt_ = opt; ++ data_cache_.reset(); ++ lataDB__ = &lata_db; ++ if (opt_.user_fields_) { ++ user_fields_.instancie(UserFields); ++ user_fields_.valeur().set_options(opt_.user_fields_options_); ++ } ++ ++ get_all_metadata(geoms_metadata_, fields_metadata_); ++} ++ ++void LataFilter::set_cache_properties(BigEntier max_memory, const entier keep_all_timesteps) ++{ ++ data_cache_.set_cache_properties(!keep_all_timesteps, max_memory); ++} ++ ++// Description: Return the number of timesteps in the database ++// (=number of physical timesteps + one containing global definitions at timestep 0) ++entier LataFilter::get_nb_timesteps() const ++{ ++ return lataDB().nb_timesteps(); ++} ++ ++// Description: Return the physical time for this timestep. ++// returns -1.0 for timestep 0 (global definitions) ++double LataFilter::get_timestep(entier i) const ++{ ++ if (i == 0) ++ return -1.0; ++ else ++ return lataDB().get_time(i); ++} ++ ++static void add_fields_to_metadata_list(const LataDB & lataDB, ++ const Nom & lata_geom, ++ const Nom & dest_geom, ++ const Nom & options, ++ entier dim, ++ LataVector & fields_data, ++ const Motcle & source, ++ const Nom & source_domain) ++{ ++ if (lataDB.nb_timesteps()<2) return; ++ // Query for existing fields in the latadb : ++ Field_UNames lata_fields = lataDB.field_unames(1, lata_geom, "*", LataDB::FIRST_AND_CURRENT); ++ const entier nb_fields = lata_fields.size(); ++ for (entier i_field = 0; i_field < nb_fields; i_field++) { ++ const LataDBField & lata_field = lataDB.get_field(1, lata_fields[i_field], LataDB::FIRST_AND_CURRENT); ++ LataField_base::Elem_som loc = LataField_base::localisation_from_string(lata_field.localisation_); ++ ++ // Hidden special fields ++ if (Motcle(lata_field.name_) == "INVALID_CONNECTIONS") ++ continue; ++ if (Motcle(lata_field.name_) == "ELEMENTS") ++ continue; ++ if (Motcle(lata_field.name_) == "FACES") ++ continue; ++ if (Motcle(lata_field.name_) == "ELEM_FACES") ++ continue; ++ LataFieldMetaData data; ++ data.name_ = lata_field.name_; ++ data.geometry_name_ = dest_geom; ++ data.component_names_ = lata_field.component_names_; ++ data.nb_components_ = lata_field.nb_comp_; ++ data.source_localisation_ = lata_field.localisation_; ++ ++ if (options.find("to_vector")>=0) { ++ data.is_vector_ = 1; ++ data.nb_components_ = dim; ++ } else ++ data.is_vector_ = (lata_field.nature_ == LataDBField::VECTOR); ++ ++ if (options.find("to_elem")>=0) ++ data.localisation_ = LataField_base::ELEM; ++ else if (options.find("to_som")>=0) ++ data.localisation_ = LataField_base::SOM; ++ else if (options.find("to_faces")>=0) ++ data.localisation_ = LataField_base::FACES; ++ else ++ data.localisation_ = loc; ++ ++ data.source_ = source; ++ data.uname_ = Field_UName(data.geometry_name_, ++ data.name_, ++ LataField_base::localisation_to_string(data.localisation_)); ++ data.source_field_ = Field_UName(source_domain, ++ data.name_, ++ lata_fields[i_field].get_localisation()); ++ ++ if ((loc == LataField_base::ELEM && options.find("from_elem")>=0) ++ || (loc == LataField_base::SOM && options.find("from_som")>=0) ++ || (loc == LataField_base::FACES && options.find("from_faces")>=0)) { ++ Journal(filter_info_level) << " register field metadata: " << data.uname_ << endl; ++ fields_data.add(data); ++ } ++ } ++} ++ ++// Process the content of the source LataDB structure and builds the metadata for ++// all geometries and fields that the filter can export (depending on options, ++// for example, provide dual mesh geometry and fields only if dualmesh option is on). ++void LataFilter::get_all_metadata(LataVector & geoms_data, LataVector & fields_data) ++{ ++ geoms_data.reset(); ++ fields_data.reset(); ++ entier current_tstep = 1; ++ // If no real timestep, just check timestep 0 ++ if (lataDB().nb_timesteps() < 2) ++ current_tstep = 0; ++ Noms lata_geoms_names = lataDB().geometry_names(current_tstep, LataDB::FIRST_AND_CURRENT); ++ const entier nb_geoms = lata_geoms_names.size(); ++ for (entier i_geom = 0; i_geom < nb_geoms; i_geom++) { ++ // Name of the current geometry (from lataDB) ++ const Nom & lata_geom_name = lata_geoms_names[i_geom]; ++ const LataDBGeometry & lata_geom = lataDB().get_geometry(current_tstep, lata_geom_name, LataDB::FIRST_AND_CURRENT); ++ // Query properties from LataDB: ++ // Is it a dynamic mesh ? ++ const entier dynamic = lata_geom.timestep_ > 0; ++ // Element type ? ++ Domain::Element element_type = Domain::element_type_from_string(lata_geom.elem_type_); ++ // Query for dimension ++ const entier domain_already_ijk = lataDB().field_exists(current_tstep, lata_geom_name, "SOMMETS_IJK_I", LataDB::FIRST_AND_CURRENT); ++ ++ // Do we have faces ? ++ const entier have_faces = ++ domain_already_ijk || ++ (lataDB().field_exists(current_tstep, lata_geom_name, "FACES", LataDB::FIRST_AND_CURRENT) ++ && lataDB().field_exists(current_tstep, lata_geom_name, "ELEM_FACES", LataDB::FIRST_AND_CURRENT)); ++ ++ entier dim = 1; ++ // Query for number of blocks in the lata file: ++ entier nblocks = 1; ++ if (domain_already_ijk) { ++ if (lataDB().field_exists(current_tstep, lata_geom_name, "SOMMETS_IJK_K", LataDB::FIRST_AND_CURRENT)) ++ dim = 3; ++ else ++ dim = 2; ++ nblocks = opt_.ijk_mesh_nb_parts_; ++ Nom nom_sommets; ++ if (dim == 2) ++ nom_sommets = "SOMMETS_IJK_J"; ++ else ++ nom_sommets = "SOMMETS_IJK_K"; ++ const LataDBField & coord = lataDB().get_field(current_tstep, lata_geom_name, nom_sommets, "", LataDB::FIRST_AND_CURRENT); ++ // Nombre d'elements dans la direction du decoupage parallele: ++ const entier nelem = coord.size_ - 1; ++ // Si les tranches sont trop petites diminuer le nombre de blocs ++ if (nblocks > (nelem + 3) / 4) ++ nblocks = (nelem + 3) / 4; ++ } else { ++ dim = lataDB().get_field(current_tstep, lata_geom_name, "SOMMETS", "*", LataDB::FIRST_AND_CURRENT).nb_comp_; ++ if (lataDB().field_exists(current_tstep, lata_geom_name, "JOINTS_SOMMETS", LataDB::FIRST_AND_CURRENT)) ++ nblocks = lataDB().get_field(current_tstep, lata_geom_name, "JOINTS_SOMMETS", "*", LataDB::FIRST_AND_CURRENT).size_; ++ } ++ ++ // Initialize data common to all domains: ++ LataGeometryMetaData data; ++ data.dynamic_ = dynamic; ++ data.dimension_ = dim; ++ data.element_type_ = element_type; ++ data.is_ijk_=domain_already_ijk; ++ ++ // If we reconnect all subdomains, always load all of them: ++ if (!opt_.reconnect) ++ data.nblocks_ = nblocks; ++ else ++ data.nblocks_ = 1; ++ ++ data.internal_name_ = lata_geom_name; ++ data.displayed_name_ = lata_geom_name; ++ ++ Nom separ("boundaries_"); ++ int m=data.displayed_name_.find(separ); ++ if (m>0) ++ { ++ const Nom& name= data.displayed_name_; ++ // on remplace boundaries_ par boundaries/ ++ const char* jj =name; ++ Nom disp(name); ++ disp.prefix(jj+m-1); ++ // GF le nom du domaine existe t il siuoi on a peut etre postraite sur un bord ++ if (lata_geoms_names.rang(disp)>-1) ++ { ++ Nom bord(jj+m+separ.longueur()-1); ++ disp+=Nom("_boundaries/"); ++ disp+=bord; ++ data.displayed_name_=disp; ++ } ++ } ++ // cerr<< data.displayed_name_< do not regularize" << endl; ++ regularizable = 0; ++ } ++ } ++ if (regularizable) { ++ data.internal_name_ = lata_geom_name; ++ data.internal_name_ += "_IJK"; ++ data.is_ijk_=1; ++ data.displayed_name_ = lata_geom_name; ++ data.source_ = "operator_ijk"; ++ data.source_domain_ = lata_geom_name; ++ geoms_data.add(data); ++ Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl; ++ // Add fields at som and elem: ++ add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_, ++ "from_elem,from_som,from_faces", dim, fields_data, ++ "operator_ijk", ++ data.source_domain_); ++ } ++ ++ // Provide dual mesh ++ if (opt_.dual_mesh && have_faces) { ++ data.internal_name_ = lata_geom_name; ++ ++ // If it's quadri or hexa, we need the regular mesh ++ data.source_domain_ = data.internal_name_; ++ if (regularizable) { ++ data.internal_name_ += "_IJK"; ++ data.source_domain_ += "_IJK"; ++ data.is_ijk_=1; ++ } ++ data.internal_name_ += "_dual"; ++ data.displayed_name_ += "_dual"; ++ ++ data.source_ = "operator_dual"; ++ geoms_data.add(data); ++ Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl; ++ // Add fields at faces, localisation will be at elements, ++ // forced to vector type if vdf: ++ Nom options("from_faces,to_elem"); ++ if (regularizable) ++ options += ",to_vector"; ++ add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_, ++ options, dim, fields_data, ++ "operator_dual", ++ data.source_domain_); ++ } ++ ++ // Provide nc mesh if possible ++ if (opt_.nc_mesh && have_faces && !regularizable /* doesn't work for vdf */) { ++ data.internal_name_ = lata_geom_name; ++ data.internal_name_ += "_nc"; ++ data.displayed_name_ = data.internal_name_; ++ data.source_ = "operator_nc"; ++ data.source_domain_ = lata_geom_name; ++ geoms_data.add(data); ++ Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl; ++ // Add fields at faces, localisation will be at nodes ++ Nom options("from_faces,to_som"); ++ add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_, ++ options, dim, fields_data, ++ "operator_nc", ++ data.source_domain_); ++ } ++ // Provide faces mesh if possible ++ if (opt_.faces_mesh && have_faces && !regularizable /* doesn't work for vdf */ && !(domain_already_ijk) ) { ++ ++ data.internal_name_ = lata_geom_name; ++ data.internal_name_ += "_centerfaces"; ++ data.displayed_name_ = data.internal_name_; ++ data.source_ = "operator_faces"; ++ data.source_domain_ = lata_geom_name; ++ if (data.element_type_ == Domain::triangle) ++ data.element_type_=Domain::line; ++ else if ( data.element_type_ == Domain::tetra) ++ data.element_type_=Domain::triangle; ++ ++ geoms_data.add(data); ++ Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl; ++ // Add fields at faces, localisation will be at nodes ++ Nom options("from_faces,to_elem"); ++ add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_, ++ options, dim, fields_data, ++ "operator_faces", ++ data.source_domain_); ++ } ++ // Provide boundary mesh ++ if (opt_.boundary_mesh && (element_type == Domain::hexa || element_type == Domain::tetra)) { ++ data.internal_name_ = lata_geom_name; ++ data.internal_name_ += "_Boundary"; ++ data.displayed_name_ = data.internal_name_; ++ data.source_ = "operator_boundary"; ++ data.source_domain_ = lata_geom_name; ++ geoms_data.add(data); ++ Journal(filter_info_level) << " metadata: adding geometry " << data.internal_name_ << " displayed name=" << data.displayed_name_ << endl; ++ Nom options("from_elem,from_som"); ++ add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_, ++ options, dim, fields_data, ++ "operator_boundary", ++ data.source_domain_); ++ options = "from_faces,to_elem"; ++ add_fields_to_metadata_list(lataDB(), lata_geom_name, data.internal_name_, ++ options, dim, fields_data, ++ "operator_boundary", ++ data.source_domain_); ++ } ++ } ++ ++ if (user_fields_.non_nul()) ++ user_fields_.valeur().new_fields_metadata(*this, fields_data); ++} ++ ++// Description: Return a list of domain names available from get_geometry_metadata() ++// and that we want to show to the user. ++// This includes the domains loaded from the lata file plus new constructed domains ++// (nc_mesh, dual_mesh, boundary_mesh, etc) if requested in options and if available ++// (depending if requiered data (eg faces, ...) ++Noms LataFilter::get_exportable_geometry_names() const ++{ ++ Noms names; ++ entier i; ++ for (i = 0; i < geoms_metadata_.size(); i++) ++ names.add(geoms_metadata_[i].internal_name_); ++ ++ // If an IJK domain is here, don't show the original domain: ++ Noms names2; ++ for (i = 0; i < names.size(); i++) { ++ Nom n(names[i]); ++ n += "_IJK"; ++ if (names.rang(n) < 0) ++ names2.add(names[i]); ++ } ++ return names2; ++} ++ ++// Description: the same, with field names... ++// If geometry=="*", returns all fields ++// Currently, doesn't show fields located at faces... ++Field_UNames LataFilter::get_exportable_field_unames(const char * geometry) const ++{ ++ Field_UNames unames; ++ Motcle geom(geometry); ++ for (entier i = 0; i < fields_metadata_.size(); i++) ++ if (geom == fields_metadata_[i].geometry_name_ || geom == "*") ++ // Do not show faces located fields to the user... ++ if (fields_metadata_[i].localisation_ != LataField_base::FACES || opt_.export_fields_at_faces_) ++ unames.add(fields_metadata_[i].uname_); ++ ++ return unames; ++} ++ ++// Description: fill "data" for the requested "geometry". "geometry" must be a name ++// returned by get_exportable_geometry_names() ++const LataGeometryMetaData & LataFilter::get_geometry_metadata(const char * geometry) const ++{ ++ Motcle geom(geometry); ++ for (entier i = 0; i < geoms_metadata_.size(); i++) ++ if (geom == geoms_metadata_[i].internal_name_) ++ return geoms_metadata_[i]; ++ ++ Journal() << "Error in LataFilter::get_geometry_metadata: unknown geometry " << geometry << endl; ++ throw LataError(LataError::INVALID_DOMAIN,"unknown geometry"); ++ return geoms_metadata_[0]; ++} ++ ++// Description: fill "data" for the requested "geometry/field". "geometry" and "field" must be names ++// returned by get_exportable_geometry_names() and get_exportable_field_names() ++const LataFieldMetaData & LataFilter::get_field_metadata(const Field_UName & uname) const ++{ ++ for (entier i = 0; i < fields_metadata_.size(); i++) ++ if (fields_metadata_[i].uname_ == uname) ++ return fields_metadata_[i]; ++ ++ Journal() << "Error in LataFilter::get_field_metadata: unknown field " << uname << endl; ++ throw LataError(LataError::INVALID_COMPONENT,"unknown field"); ++ return fields_metadata_[0]; ++} ++ ++// Description: ++// Returns a reference to the requested geometry. ++// If the geometry is not found at the requested timestep, it ++// is seached in the first timestep. ++// If the geometry does not exist in the cache, all needed data is loaded ++// and the geometry is allocated and built in the internal cache. ++// The reference is valid until the user calls release_geometry() ++// The user MUST call release_geometry() to allow the data to be ++// removed from the data cache. ++const Domain & LataFilter::get_geometry(const Domain_Id & id) ++{ ++ Journal(filter_info_level) << "LataFilter::get_geometry " ++ << id.name_ << " time=" << id.timestep_ ++ << " bloc=" << id.block_ << endl; ++ data_cache_.cleanup_cache(id.timestep_); ++ ++ Domain_Id requested_id(id); ++ // Get the real timestep where this domain is stored: ++ const LataGeometryMetaData & geom_metadata = get_geometry_metadata(id.name_); ++ if (geom_metadata.dynamic_) ++ requested_id.timestep_ = id.timestep_; ++ else ++ requested_id.timestep_ = 0; ++ ++ LataDeriv & dom_ptr = get_cached_domain(requested_id); ++ if (!dom_ptr.non_nul()) { ++ if (geom_metadata.source_ == "latadb") { ++ // Request for a native domain : load it from lataDB ++ // If reconnect and loading all subdomains, go ! Don't store the operator in cache since it's ++ // not required to process fields. ++ ++ // Is it a structured or unstructured mesh ? ++ if (lataDB().field_exists(requested_id.timestep_, requested_id.name_, "SOMMETS")) ++ { ++ DomainUnstructured & dom = dom_ptr.instancie(DomainUnstructured); ++ ++ if (opt_.reconnect) { ++ // Bloc demande, peut etre le bloc 0 ou le bloc -1: ++ const entier req_block = requested_id.block_; ++ if (requested_id.block_ > 0) { ++ Cerr << "Error: requesting block " << requested_id.block_ << " with reconnect option" << endl; ++ throw; ++ } ++ requested_id.block_ = -1; // load all blocks ++ dom.fill_domain_from_lataDB(lataDB(), requested_id, 1 /* faces */, 0); ++ Reconnect::reconnect_geometry(dom, opt_.reconnect_tolerance); ++ dom.id_.block_ = req_block; ++ } else { ++ dom.fill_domain_from_lataDB(lataDB(), requested_id, 1 /* faces */, opt_.load_virtual_elements ? 1 : 0); ++ if (opt_.load_virtual_elements && dom.nb_virt_items(LataField_base::ELEM) > 0) { ++ Reconnect::reconnect_geometry(dom, opt_.reconnect_tolerance, ++ dom.nb_nodes() - dom.nb_virt_items(LataField_base::SOM)); ++ } ++ } ++ } ++ else ++ { ++ // Structured ijk: ++ DomainIJK & dom = dom_ptr.instancie(DomainIJK); ++ if (opt_.reconnect || requested_id.block_ < 0) { ++ dom.fill_domain_from_lataDB(lataDB(), requested_id, 1 /* parallel splitting */, ++ 0 /* no virtual elements */); ++ } else { ++ const entier nparts = opt_.ijk_mesh_nb_parts_; ++ const entier virtual_size = opt_.load_virtual_elements ? opt_.ijk_virt_layer : 0; ++ dom.fill_domain_from_lataDB(lataDB(), requested_id, nparts /* parallel splitting */, ++ virtual_size /* with virtual elements */); ++ } ++ } ++ } else if (geom_metadata.source_.debute_par("OPERATOR")) { ++ const Domain & src_domain = get_geometry(Domain_Id(geom_metadata.source_domain_, ++ requested_id.timestep_, ++ requested_id.block_)); ++ Operator & op = get_set_operator(requested_id); ++ op.build_geometry(src_domain, dom_ptr); ++ dom_ptr.valeur().id_ = requested_id; ++ release_cached_operator(requested_id); ++ release_geometry(src_domain); ++ } else { ++ Journal() << "Unknown source in geometry metadata " << geom_metadata.source_ << endl; ++ throw; ++ } ++ } ++ ++ return dom_ptr.valeur(); ++} ++ ++Operator & LataFilter::get_set_operator(const Domain_Id & id) ++{ ++ LataDeriv & op_ptr = get_cached_operator(id); ++ if (!op_ptr.non_nul()) { ++ // Operator not in the cache ? Build it: ++ if (id.name_.finit_par("_IJK")) { ++ OperatorRegularize & op = op_ptr.instancie(OperatorRegularize); ++ op.set_tolerance(opt_.regularize_tolerance); ++ op.set_extend_layer(opt_.extend_domain); ++ } else if (id.name_.finit_par("_dual")) { ++ op_ptr.instancie(OperatorDualMesh); ++ } else if (id.name_.finit_par("_Boundary")) { ++ op_ptr.instancie(OperatorBoundary); ++ } else if (id.name_.finit_par("_centerfaces")) { ++ op_ptr.instancie(OperatorFacesMesh); ++ } else { ++ Journal() << "Internal error in LataFilter::get_operator: forgot to implement operator choice for " << id.name_ << endl; ++ throw; ++ } ++ } ++ return op_ptr.valeur(); ++} ++ ++ ++// Description: returns the requested field, computing it if it is not ++// already in the cache. You MUST call release_field() on the returned field ++// when you don't need it any more... ++// See also class Field_Id ++const LataField_base & LataFilter::get_field(const Field_Id & id) ++{ ++ Journal(filter_info_level) << "LataFilter::get_field " ++ << id.uname_ << " time=" << id.timestep_ ++ << " bloc=" << id.block_ << endl; ++ ++ data_cache_.cleanup_cache(id.timestep_); ++ ++ const LataFieldMetaData & field_metadata = get_field_metadata(id.uname_); ++ ++ LataDeriv & field_ptr = get_cached_field(id); ++ if (!field_ptr.non_nul()) { ++ if (field_metadata.source_ == "latadb") { ++ // Request for a native field : load it from lataDB ++ const Domain & dom = get_geometry(id); ++ dom.fill_field_from_lataDB(lataDB(), id, field_ptr); ++ release_geometry(dom); ++ } else if (field_metadata.source_.debute_par("OPERATOR")) { ++ const Field_Id src_id(field_metadata.source_field_, ++ id.timestep_, ++ id.block_); ++ const Domain & src_domain = get_geometry(src_id); ++ const LataField_base & src_field = get_field(src_id); ++ const Domain & dest_domain = get_geometry(id); ++ Operator & op = get_set_operator(dest_domain.id_); ++ op.build_field(src_domain, src_field, dest_domain, field_ptr); ++ field_ptr.valeur().id_ = Field_Id(field_metadata.uname_, src_field.id_.timestep_, src_field.id_.block_); ++ release_field(src_field); ++ release_geometry(src_domain); ++ release_geometry(dest_domain); ++ release_cached_operator(dest_domain.id_); ++ } else if (field_metadata.source_ == "user_fields") { ++ Field & f = field_ptr.instancie(Field ); ++ f = user_fields_.valeur().get_field(id); ++ // Force field id to correct value: ++ f.id_ = id; ++ f.component_names_ = field_metadata.component_names_; ++ f.nature_ = field_metadata.is_vector_ ? LataDBField::VECTOR : LataDBField::SCALAR; ++ f.localisation_ = field_metadata.localisation_; ++ } ++ } ++ ++ return field_ptr.valeur(); ++} ++ ++// Description: returns the requested float field, computing it if it is not ++// already in the cache. You MUST call release_field() on the returned field ++// when you don't need it any more... ++// See also class Field_Id ++const FieldFloat & LataFilter::get_float_field(const Field_Id & id) ++{ ++ const LataField_base & field = get_field(id); ++ const FieldFloat * float_field_ptr = dynamic_cast(&field); ++ if (! float_field_ptr) { /*assert(! float_field_ptr);*/ throw LataError(LataError::INVALID_COMPONENT,"unknown field");} ++ const FieldFloat & fld = *float_field_ptr; ++ return fld; ++} ++void LataFilter::release_geometry(const Domain & dom) ++{ ++ Journal(filter_info_level) << "LataFilter::release_geometry " ++ << dom.id_.name_ << " time=" << dom.id_.timestep_ ++ << " bloc=" << dom.id_.block_ << endl; ++ release_cached_domain(dom.id_); ++} ++ ++void LataFilter::release_field(const LataField_base & field) ++{ ++ Journal(filter_info_level) << "LataFilter::release_field " ++ << field.id_.uname_ << " time=" << field.id_.timestep_ ++ << " bloc=" << field.id_.block_ << endl; ++ release_cached_field(field.id_); ++} ++ ++void build_mangeld_domain_name(const Domain_Id & id, Nom & name) ++{ ++ name = id.name_; ++ name += "_"; ++ name += Nom(id.timestep_); ++ name += "_"; ++ name += Nom(id.block_); ++ name.majuscule(); ++} ++ ++void build_mangeld_field_name(const Field_Id & id, Nom & name) ++{ ++ name = id.uname_.build_string(); ++ name += "_"; ++ name += Nom(id.timestep_); ++ name += "_"; ++ name += Nom(id.block_); ++ name.majuscule(); ++} ++ ++LataDeriv & LataFilter::get_cached_field(const Field_Id& id) ++{ ++ Nom n; ++ build_mangeld_field_name(id, n); ++ return data_cache_.get_item >(n, id.timestep_); ++} ++LataDeriv & LataFilter::get_cached_domain(const Domain_Id& id) ++{ ++ Nom n; ++ build_mangeld_domain_name(id, n); ++ return data_cache_.get_item >(n, id.timestep_); ++} ++LataDeriv & LataFilter::get_cached_operator(const Domain_Id& id) ++{ ++ Nom n; ++ build_mangeld_domain_name(id, n); ++ n += "_OP"; ++ return data_cache_.get_item >(n, id.timestep_); ++} ++void LataFilter::release_cached_domain(const Domain_Id& id) ++{ ++ Nom n; ++ build_mangeld_domain_name(id, n); ++ data_cache_.release_item(n); ++} ++void LataFilter::release_cached_field(const Field_Id& id) ++{ ++ Nom n; ++ build_mangeld_field_name(id, n); ++ data_cache_.release_item(n); ++} ++void LataFilter::release_cached_operator(const Domain_Id& id) ++{ ++ Nom n; ++ build_mangeld_domain_name(id, n); ++ n += "_OP"; ++ data_cache_.release_item(n); ++} ++ ++void LataOptions::extract_path_basename(const char * s, Nom & path_prefix, Nom & basename) ++{ ++ int i; ++ for (i=(int)strlen(s)-1;i>=0;i--) ++ if ((s[i]==PATH_SEPARATOR) ||(s[i]=='\\')) ++ break; ++ path_prefix = ""; ++ int j; ++ for (j = 0; j <= i; j++) ++ path_prefix += Nom(s[j]); ++ ++ // Parse basename : if extension given, remove it ++ int n = (int)strlen(s); ++ if (n > 5 && strcmp(s+n-5,".lata") == 0) ++ n -= 5; ++ basename = ""; ++ for (j = i+1; j < n; j++) ++ basename += Nom(s[j]); ++ // Journal(9)<<" prefix "< & dest) ++{ ++ Journal() << "Error in an operator: build_geometry not coded for this Operator/Domain" << endl; ++ throw; ++} ++ ++void build_field_(Operator & op, const Domain & src, const Domain & dest, ++ const LataField_base & srcf, LataField_base & destf) ++{ ++ Journal() << "Error in an operator: build_field not coded for this Operator/Domain/Field" << endl; ++ throw; ++} ++ ++void LataDB_apply_input_filter(const LataDB & lata_db, LataDB & filtered_db, ++ const ArrOfInt & input_timesteps_filter, ++ const Noms & input_domains_filter, ++ const Noms & input_components_filter) ++{ ++ ArrOfInt timesteps_filter(input_timesteps_filter); ++ Noms domains_filter(input_domains_filter); ++ Noms components_filter(input_components_filter); ++ ++ // Build a list of all available geometries and components ++ Noms list_all_domains = lata_db.geometry_names(lata_db.nb_timesteps()-1, LataDB::FIRST_AND_CURRENT); ++ Noms list_all_fields; ++ { ++ Field_UNames fields = lata_db.field_unames(lata_db.nb_timesteps()-1, "*", "*", LataDB::FIRST_AND_CURRENT); ++ for (entier i = 0; i < fields.size(); i++) { ++ const Nom & n = fields[i].get_field_name(); ++ if (list_all_fields.rang(n) < 0) ++ list_all_fields.add(n); ++ } ++ } ++ ++ if (timesteps_filter.size_array() == 0) { ++ // Add all timesteps, timestep 0 is implicitely added. ++ entier n = lata_db.nb_timesteps(); ++ timesteps_filter.resize_array(n-1); ++ for (entier i = 1; i < n; i++) ++ timesteps_filter[i-1] = i; ++ Journal(3) << " Exporting all " << n-1 << " timesteps" << endl; ++ } else if (timesteps_filter[0] < 0) { ++ timesteps_filter.resize_array(0); ++ Journal(3) << " Request timestep -1: Exporting only global time independent data" << endl; ++ } ++ if (domains_filter.size() == 0) { ++ // Add all geometries ++ domains_filter = list_all_domains; ++ Journal(3) << " Exporting all geometries" << endl; ++ } ++ if (components_filter.size() == 0) { ++ // Add all fields of the selected geometries ++ components_filter = list_all_fields; ++ Journal(3) << " Exporting all fields:" << endl; ++ } else { ++ // Add all known geometry data fields ++ components_filter.add("SOMMETS"); ++ components_filter.add("ELEMENTS"); ++ components_filter.add("FACES"); ++ components_filter.add("ELEM_FACES"); ++ components_filter.add("JOINTS_SOMMETS"); ++ components_filter.add("JOINTS_ELEMENTS"); ++ components_filter.add("JOINTS_FACES"); ++ components_filter.add("VIRTUAL_ELEMENTS"); ++ // these are for ijk meshs: ++ components_filter.add("SOMMETS_IJK_I"); ++ components_filter.add("SOMMETS_IJK_J"); ++ components_filter.add("SOMMETS_IJK_K"); ++ components_filter.add("INVALID_CONNECTIONS"); ++ } ++ filtered_db.filter_db(lata_db, ++ noms_to_motcles(domains_filter), ++ noms_to_motcles(components_filter), ++ timesteps_filter); ++} +diff --git a/databases/readers/Lata/LataFilter.h b/databases/readers/Lata/LataFilter.h +new file mode 100644 +index 0000000..77f24d9 +--- /dev/null ++++ b/databases/readers/Lata/LataFilter.h +@@ -0,0 +1,261 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef LATA_H_INCLUDE ++#define LATA_H_INCLUDE ++ ++#include ++#include ++#include ++ ++typedef Field FieldFloat; ++ ++// This file provides the LataFilter class: it is a dynamic mesh ++// and field generator which is able to load data from a lata file, ++// apply operators. Once computed, the data is kept in a data cache ++// to speed up further access to the same data. ++ ++// This class holds the LataFilter configuration (determines which ++// combination of operators should be applied to the data) ++class LataOptions ++{ ++public : ++ static void extract_path_basename(const char * s, Nom & path_prefix, Nom & basename); ++ static entier read_int_opt(const Nom & s); ++ static double read_float_opt(const Nom & s); ++ static Nom read_string_opt(const Nom & s); ++ ++ Nom basename; // Name of the case. ++ Nom path_prefix; // Path for the case. ++ ++ // Generate de the following meshes and associated data, if the flag is set. ++ bool dual_mesh; ++ bool nc_mesh; ++ bool faces_mesh; ++ bool boundary_mesh; ++ ++ bool reconnect; // Do we want to reconnect multiblock meshes ++ float reconnect_tolerance; ++ int regularize_polyedre ; // if 1 Treate polyedre as poyledre extruder ++ 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) ++ // special value 2 means "regularize if faces present and vdf" ++ int extend_domain; // Extend the regularized domaine by n layers of cells ++ float regularize_tolerance; ++ bool invalidate; // invalidate unused positions and connections; ++ bool load_virtual_elements; // Do we want to extend the loaded mesh subblocks with a layer of virtual elements ++ bool export_fields_at_faces_; // Should we show these fields in exportable fields ++ ++ // When loading ijk regular meshes, virtually create this number of blocks in the K direction: ++ int ijk_mesh_nb_parts_; ++ // When loading ijk regular meshes, merge N layers of virtual elements (default=1) ++ int ijk_virt_layer; ++ ++ bool user_fields_; //activate user fields ? ++ ++ ArrOfDouble clipbox_min; ++ ArrOfDouble clipbox_max; ++ ++ UserFields_options user_fields_options_; ++ ++ LataOptions(); ++ virtual entier parse_option(const Nom &); ++ virtual void describe(); ++ virtual ~LataOptions() {}; ++}; ++ ++class Operator : public LataObject ++{ ++public: ++ virtual void build_field(const Domain & src_domain, const LataField_base & src_field, ++ const Domain & dest_domain, LataDeriv & dest) = 0; ++ virtual void build_geometry(const Domain & src_domain, LataDeriv & dest) = 0; ++protected: ++}; ++ ++struct LataGeometryMetaData ++{ ++ Nom internal_name_; // Internal full name (eg DOM_IJK) ++ Nom displayed_name_; // Short name showed to the user (DOM for DOM_IJK, ?? if the geometry should not be exported) ++ entier dynamic_; // Is the geometry changing at each timestep ? ++ entier dimension_; // spatial dimension of coordinates ++ Domain::Element element_type_; ++ entier nblocks_; // Number of sub_blocks in the geometry (parallel computation) ++ Motcle source_; // How to build this domain ("latadb", "operator_ijk", "operator_dual", "operator_boundary", "user_fields") ++ Nom source_domain_; ++ entier is_ijk_; ++}; ++ ++struct LataFieldMetaData ++{ ++ Field_UName uname_; ++ Nom name_; ++ Nom geometry_name_; ++ Noms component_names_; ++ entier nb_components_; ++ entier is_vector_; // Yes => nb_components is equal to spatial dimension ++ LataField_base::Elem_som localisation_; ++ Nom source_localisation_; // Localisation of source field (for displayed name in visit) ++ Motcle source_; // How to build this field ("latadb", "operator_ijk", "operator_dual", "operator_boundary", "user_fields") ++ Field_UName source_field_; ++}; ++ ++class DataCacheItem ++{ ++public: ++ DataCacheItem() : tstep_(-1), last_access_time_(0), lock_(0), memory_size_(0) {} ++ LataDeriv item_; // The cached item ++ Nom id_; // The id for this item ++ entier tstep_; // The timestep of the cached data (for cache cleanup) ++ BigEntier last_access_time_; // Last time this item has been accessed (for cache cleanup) ++ // Is the item locked ? => cannot be deleted by clear_cache() ++ // This is a counter: get_item increases, release_item dereases. ++ // (this is when we simultaneously need several items, we must lock them to be sure) ++ entier lock_; ++ // The memory size is computed when the item is released ++ BigEntier memory_size_; ++}; ++ ++class LataFilterCache ++{ ++public: ++ LataFilterCache() : cache_data_access_count_(0), ++ clear_cache_on_tstep_change_(1), cache_memory_limit_(-1) {}; ++ void reset() { data_.reset(); cache_data_access_count_ = 0; } ++ void set_cache_properties(entier clear_on_tstep_change, BigEntier mem_limit); ++ template C & get_item(const Nom & id, entier tstep) ++ { ++ LataDeriv & obj = get_item_(id, tstep); ++ if (obj.non_nul()) ++ return obj.refcast(C); ++ else ++ return obj.instancie(C); ++ } ++ void release_item(const Nom & id); ++ void remove_item(const Nom & id); ++ void cleanup_cache(entier tstep_to_keep); ++protected: ++ LataDeriv & get_item_(const Nom & id, entier tstep); ++ // Stored data (depends on caching strategy) ++ // data_ grows when needed. ++ LataVector data_; ++ BigEntier cache_data_access_count_; ++ // If nonzero, whenever we ask a timestep, ++ // remove all cached data from other timesteps ++ entier clear_cache_on_tstep_change_; ++ // If before getting a new geometry or field, the data cache ++ // uses more than the limit, remove old data until we are below. ++ // -1 means "no limit" ++ BigEntier cache_memory_limit_; // Limit in bytes ++}; ++ ++// Description: This is the MAIN class for the lata filter tool: ++// It reads data from a lata database on disk (initialize), ++// and proposes several geometries and fields (get_exportable...) to the user. ++// The user can get them with get_geometry and get_field. ++// He must then call release_geometry and release_field to free the memory. ++// The user can also get metadata information (available without loading all ++// the data from disk) for geometries and fields and also timestep informations. ++// Timestep 0 contains global geometry and field definitions, timestep 1..n ++// are associated with each "TEMPS" entry in the lata file. ++// ++// LataFilter uses a data cache internally: it keeps fields and geometries after ++// the user calls release_xxx(). The cache is controlled by set_cache_properties() ++class LataFilter { ++public: ++ LataFilter() : lataDB__(0) {}; ++ void initialize(const LataOptions & opt, const LataDB & db); ++ void set_cache_properties(BigEntier max_memory, const entier keep_all_timesteps); ++ Noms get_exportable_geometry_names() const; ++ const LataGeometryMetaData & get_geometry_metadata(const char * geometry) const; ++ LataVector get_exportable_field_unames(const char * geometry) const; ++ const LataFieldMetaData & get_field_metadata(const Field_UName & uname) const; ++ entier get_nb_timesteps() const; ++ double get_timestep(entier i) const; ++ ++ const Domain & get_geometry(const Domain_Id &); ++ ++ void release_geometry(const Domain &); ++ const LataField_base & get_field(const Field_Id &); ++ const FieldFloat & get_float_field(const Field_Id &) ; ++ ++ void release_field(const LataField_base &); ++ ++ const LataDB & get_lataDB() const { return lataDB(); } ++ ++ const LataOptions & get_options() const { return opt_; } ++protected: ++ Operator & get_set_operator(const Domain_Id & id); ++ LataDeriv & get_cached_field(const Field_Id&); ++ LataDeriv & get_cached_domain(const Domain_Id&); ++ LataDeriv & get_cached_operator(const Domain_Id&); ++ void release_cached_domain(const Domain_Id&); ++ void release_cached_field(const Field_Id&); ++ void release_cached_operator(const Domain_Id&); ++ const Domain & get_geom_field_(const Field_Id & id, LataRef & field_result); ++ void get_all_metadata(LataVector & geoms_data, LataVector & fields_data); ++ // LataDB & lataDB() { return lataDB__; } ++ const LataDB & lataDB() const { assert(lataDB__); return *lataDB__; } ++ ++ // We store in the cache objects of type: ++ // LataDeriv ++ // derived types of Operator ++ // LataDeriv ++ LataFilterCache data_cache_; ++ ++ // LataV2 masterfile database ++ const LataDB *lataDB__; ++ LataOptions opt_; ++ // Metadata information for all fields and geometries (built in initialize) ++ LataVector geoms_metadata_; ++ LataVector fields_metadata_; ++ ++ LataDeriv user_fields_; ++}; ++ ++struct LataError ++{ ++ enum ErrorCode { NEED_REGULAR, NO_FACES, WRONG_ELT_TYPE, INVALID_TSTEP, INVALID_COMPONENT, ++ INVALID_DOMAIN, OTHER}; ++ LataError(ErrorCode code, const char * msg) : code_(code), msg_(msg) {}; ++ ErrorCode code_; ++ const char *msg_; ++}; ++ ++struct InternalError ++{ ++ InternalError(const char *msg) : msg_(msg) {}; ++ const char *msg_; ++}; ++ ++void LataDB_apply_input_filter(const LataDB & lata_db, LataDB & filtered_db, ++ const ArrOfInt & input_timesteps_filter, ++ const Noms & input_domains_filter, ++ const Noms & input_components_filter); ++#endif ++ +diff --git a/databases/readers/Lata/LataJournal.h b/databases/readers/Lata/LataJournal.h +new file mode 100644 +index 0000000..acc68e3 +--- /dev/null ++++ b/databases/readers/Lata/LataJournal.h +@@ -0,0 +1,36 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef LataJournal_H ++#define LataJournal_H ++#include ++#include ++std::ostream & Journal(entier level=0); ++void set_Journal_level(entier level); ++#endif +diff --git a/databases/readers/Lata/LataStructures.C b/databases/readers/Lata/LataStructures.C +new file mode 100644 +index 0000000..390d289 +--- /dev/null ++++ b/databases/readers/Lata/LataStructures.C +@@ -0,0 +1,743 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++#include ++static const entier info_level = 4; ++ ++// Description: returns the number of items of the given type ++entier Domain::nb_items(const LataField_base::Elem_som loc) const ++{ ++ entier n = -1; ++ switch (loc) { ++ case LataField_base::SOM: n = nb_nodes(); break; ++ case LataField_base::ELEM: n = nb_elements(); break; ++ case LataField_base::FACES: n = nb_faces(); break; ++ default: ++ Journal() << "Invalid localisation " << (int) loc << " in Domain::nb_items" << endl; ++ throw; ++ } ++ return n; ++} ++ ++// Description: returns the offset in the lata block on disk of the first ++// item for this Domain.id_.block_ (parallel computation). ++// (this value must be set with set_lata_block_offset) ++entier Domain::lata_block_offset(const LataField_base::Elem_som loc) const ++{ ++ entier n = -1; ++ switch (loc) { ++ case LataField_base::SOM: n = decal_nodes_lata_; break; ++ case LataField_base::ELEM: n = decal_elements_lata_; break; ++ case LataField_base::FACES: n = decal_faces_lata_; break; ++ default: ++ Journal() << "Invalid localisation " << (int) loc << " in Domain::lata_block_offset" << endl; ++ throw; ++ } ++ if (n < 0) { ++ Journal() << "Error: lata_block_offset not set for localisation " << (int) loc << endl; ++ throw; ++ } ++ return n; ++} ++ ++// Description: set the lata_block_offset (see lata_block_offset) ++void Domain::set_lata_block_offset(const LataField_base::Elem_som loc, entier n) ++{ ++ switch (loc) { ++ case LataField_base::SOM: decal_nodes_lata_ = n; break; ++ case LataField_base::ELEM: decal_elements_lata_ = n; break; ++ case LataField_base::FACES: decal_faces_lata_ = n; break; ++ default: ++ Journal() << "Invalid localisation " << (int) loc << " in Domain::set_lata_block_offset" << endl; ++ throw; ++ } ++} ++ ++template ++void DomainUnstructured::compute_cell_center_coordinates(TabType & coord, entier index_begin) const ++{ ++ const entier dim = nodes_.dimension(1); ++ const entier nb_elem = elements_.dimension(0); ++ const entier nb_som_elem = elements_.dimension(1); ++ const double facteur = 1. / (double) nb_som_elem; ++ double tmp[3]; ++ for (int i = 0; i < nb_elem; i++) { ++ int j, k; ++ tmp[0] = tmp[1] = tmp[2] = 0.; ++ for (j = 0; j < nb_som_elem; j++) { ++ int som = elements_(i, j); ++ for (k = 0; k < loop_max(dim, 3); k++) { ++ tmp[k] += nodes_(som, k); ++ break_loop(k, dim); ++ } ++ } ++ for (k = 0; k < loop_max(dim, 3); k++) { ++ coord(index_begin + i, k) = tmp[k] * facteur; ++ break_loop(k, dim); ++ } ++ } ++} ++ ++template ++void DomainUnstructured::compute_cell_center_coordinates(FloatTab & coord, entier index_begin) const; ++template ++void DomainUnstructured::compute_cell_center_coordinates(DoubleTab & coord, entier index_begin) const; ++ ++ ++LataField_base::Elem_som LataField_base::localisation_from_string(const Motcle & loc) ++{ ++ if (loc.debute_par("SOM")) ++ return SOM; ++ else if (loc.debute_par("ELEM")) ++ return ELEM; ++ else if (loc.debute_par("FACE")) ++ return FACES; ++ else ++ return UNKNOWN; ++} ++ ++Nom LataField_base::localisation_to_string(const Elem_som loc) ++{ ++ Nom n; ++ switch(loc) { ++ case SOM: n = "SOM"; break; ++ case ELEM: n = "ELEM"; break; ++ case FACES: n = "FACES"; break; ++ case UNKNOWN: n = ""; ++ } ++ return n; ++} ++ ++Motcle Domain::lata_element_name(Domain::Element type) ++{ ++ switch(type) { ++ case point: return "POINT"; break; ++ case line: return "SEGMENT"; break; ++ case triangle: return "TRIANGLE"; break; ++ case quadri: return "QUADRANGLE"; break; ++ case tetra: return "TETRAEDRE"; break; ++ case hexa: return "HEXAEDRE"; break; ++ case prism6: return "PRISM6"; break; ++ case polyedre: return "POLYEDRE"; break; ++ case polygone: return "POLYGONE"; break; ++ default: return "UNSPECIFIED"; ++ } ++ return "UNSPECIFIED"; ++} ++ ++Domain::Element Domain::element_type_from_string(const Motcle & type_elem) ++{ ++ Element type; ++ if (type_elem == "HEXAEDRE") ++ type=hexa; ++ else if (type_elem == "HEXAEDRE_AXI") ++ type=hexa; ++ else if (type_elem == "HEXAEDRE_VEF") ++ type=hexa; ++ else if (type_elem == "QUADRANGLE") ++ type=quadri; ++ else if (type_elem == "QUADRANGLE_3D") ++ type=quadri; ++ else if (type_elem == "RECTANGLE") ++ type=quadri; ++ else if (type_elem == "RECTANGLE_2D_AXI") ++ type=quadri; ++ else if (type_elem == "RECTANGLE_AXI") ++ type=quadri; ++ else if (type_elem == "SEGMENT") ++ type=line; ++ else if (type_elem == "SEGMENT_2D") ++ type=line; ++ else if (type_elem == "TETRAEDRE") ++ type=tetra; ++ else if (type_elem == "TRIANGLE") ++ type=triangle; ++ else if (type_elem == "TRIANGLE_3D") ++ type=triangle; ++ else if (type_elem == "POINT") ++ type=point; ++ else if ((type_elem == "PRISM6")||(type_elem == "PRISME")) ++ type=prism6; ++ else if (type_elem.debute_par("POLYEDRE")) ++ type=polyedre; ++ else if (type_elem.debute_par("POLYGONE")) ++ type=polygone; ++ else { ++ Journal() << "Error in elem_type_from_string: unknown element type " << type_elem << endl; ++ throw; ++ } ++ return type; ++} ++ ++Nom Domain::element_type_to_string(Element type) ++{ ++ Nom n; ++ switch(type) { ++ case point: n = "POINT"; break; ++ case line: n = "SEGMENT"; break; ++ case triangle: n = "TRIANGLE"; break; ++ case quadri: n = "QUADRANGLE"; break; ++ case tetra: n = "TETRAEDRE"; break; ++ case hexa: n = "HEXAEDRE"; break; ++ case prism6: n = "PRISM6"; break; ++ case polyedre: n = "POLYEDRE_0"; break; ++ case polygone: n = "POLYGONE"; break; ++ case unspecified: n = "UNKNOWN"; break; ++ } ++ return n; ++} ++ ++// Description: read the specified geometry from the lataDB_ structure and put it in "dom". ++// load_faces: flag, tells if we should read faces definitions in the lata file ++// merge_virtual_elements: flag, if a "VIRTUAL_ELEMENTS" array is present in the lata file, ++// merges these elements to the requested block. ++void DomainUnstructured::fill_domain_from_lataDB(const LataDB & lataDB, ++ const Domain_Id & id, ++ entier load_faces, ++ entier merge_virtual_elements) ++{ ++ operator=(DomainUnstructured()); // Reset all data. ++ ++ id_ = id; ++ const LataDBGeometry & geom = lataDB.get_geometry(id.timestep_, id.name_); ++ ++ // ******************************** ++ // 1) Look for the sub-block items to read (parallel computation) ++ entier decal_nodes = 0; ++ entier decal_elements = 0; ++ entier decal_faces = 0; ++ entier nb_sommets = -1; ++ entier nbelements = -1; ++ entier nbfaces = -1; ++ ++ entier domain_has_faces = load_faces && lataDB.field_exists(id.timestep_, id.name_, "FACES"); ++ ++ // Tableau de 3 joints (SOM, ELEM et FACES) ++ LataVector joints; ++ entier nproc = 1; ++ for (entier i_item = 0; i_item < 3; i_item++) { ++ // LataField_base::Elem_som loc = LataField_base::SOM; ++ Nom nom("JOINTS_SOMMETS"); ++ Nom nom2("SOMMETS"); ++ if (i_item == 1) { ++ //loc = LataField_base::ELEM; ++ nom = "JOINTS_ELEMENTS"; ++ nom2 = "ELEMENTS"; ++ } else if (i_item == 2) { ++ // loc = LataField_base::FACES; ++ nom = "JOINTS_FACES"; ++ nom2 = "FACES"; ++ } ++ ++ IntTab & joint = joints.add(); ++ if (lataDB.field_exists(id.timestep_, id.name_, nom)) { ++ entier nbitems = lataDB.get_field(id.timestep_, id.name_, nom2, "*").size_; ++ IntTab tmp; ++ lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, nom, "*"), tmp); ++ nproc = tmp.dimension(0); ++ // Recalcule la deuxieme colonne en fonction de la premiere ++ joint.resize(nproc, 2); ++ for (entier i = 0; i < nproc; i++) { ++ joint(i, 0) = tmp(i, 0); ++ if (i < nproc-1) ++ joint(i, 1) = tmp(i+1, 0) - tmp(i, 0); ++ else ++ joint(i, 1) = nbitems - tmp(i, 0); ++ } ++ } ++ } ++ ++ if (id_.block_ < 0 || nproc == 1) { ++ // read all blocks at once default values are ok ++ set_joints(LataField_base::SOM) = joints[0]; ++ set_joints(LataField_base::ELEM) = joints[1]; ++ set_joints(LataField_base::FACES) = joints[2]; ++ } else { ++ if (id_.block_ >= nproc) { ++ Journal() << "LataFilter::get_geometry : request non existant block " << id.block_ ++ << " in geometry " << id.name_ << endl; ++ throw; ++ } ++ const entier n = id_.block_; ++ decal_nodes = joints[0](n, 0); ++ nb_sommets = joints[0](n, 1); ++ decal_elements = joints[1](n, 0); ++ nbelements = joints[1](n, 1); ++ if (domain_has_faces) { ++ decal_faces = joints[2](n, 0); ++ nbfaces = joints[2](n, 1); ++ } ++ } ++ ++ // ****************************** ++ // 2) Read nodes, elements and faces data ++ elt_type_ = Domain::element_type_from_string(geom.elem_type_); ++ ++ lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "SOMMETS", "*"), nodes_, decal_nodes, nb_sommets); ++ lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "ELEMENTS", "*"), elements_, decal_elements, nbelements); ++ set_lata_block_offset(LataField_base::SOM, decal_nodes); ++ set_lata_block_offset(LataField_base::ELEM, decal_elements); ++ if (decal_nodes > 0) { ++ // Nodes are stored with global numbering in the lata file: transform to sub_block numbering : ++ elements_ -= decal_nodes; ++ } ++ if (domain_has_faces) { ++ set_lata_block_offset(LataField_base::FACES, decal_faces); ++ lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "FACES", "*"), faces_, decal_faces, nbfaces); ++ if (decal_nodes > 0) ++ faces_ -= decal_nodes; ++ lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "ELEM_FACES", "*"), elem_faces_, decal_elements, nbelements); ++ if (decal_faces > 0) ++ elem_faces_ -= decal_faces; ++ } ++ ++ // ************************* ++ // 3) Merge virtual elements if requested ++ if (merge_virtual_elements && lataDB.field_exists(id.timestep_, id.name_, "VIRTUAL_ELEMENTS") && id.block_ >= 0) ++ { ++ Journal(info_level) << " Merging virtual elements" << endl; ++ // joints_virt_elems(sub_block, 0) = index of first virtual element in the VIRTUAL_ELEMENTS array ++ IntTab joints_virt_elems; ++ // Load the virtual elements (nodes are in global numbering) ++ // First: find the index and number of virtual elements for block number id.block_: ++ lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "JOINTS_VIRTUAL_ELEMENTS", "*"), joints_virt_elems); ++ entier nb_virt_elems; ++ if (id.block_ < nproc-1) ++ nb_virt_elems = joints_virt_elems(id.block_+1, 0) - joints_virt_elems(id.block_, 0); ++ else ++ nb_virt_elems = lataDB.get_field(id.timestep_, id.name_, "VIRTUAL_ELEMENTS", "*").size_ - joints_virt_elems(id.block_, 0); ++ Journal(info_level+1) << " Number of virtual elements for block " << id.block_ << "=" << nb_virt_elems << endl; ++ // Second: load the indexes of the virtual elements to load: ++ IntTab virt_elems; ++ lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "VIRTUAL_ELEMENTS", "*"), virt_elems, joints_virt_elems(id.block_,0), nb_virt_elems); ++ set_virt_items(LataField_base::ELEM, virt_elems); ++ ++ { ++ // Third: load the virtual elements (virt_elems contains the global indexes of the elements to ++ // load and virt_elem_som will contain global nodes indexes of the virtual elements) ++ IntTab virt_elem_som; ++ lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "ELEMENTS", "*"), virt_elem_som, virt_elems); ++ // Find which virtual nodes are required and load them: virtual nodes to load are ++ // all nodes of the virtual elements (they have duplicates). ++ ArrOfInt index; ++ ArrOfInt & virt_elem_som_array = virt_elem_som; // Array seen as monodimensionnal ++ array_sort_indirect(virt_elem_som_array, index); ++ // Global nodes indexes of needed virtual nodes ++ ArrOfInt nodes_to_read; ++ nodes_to_read.set_smart_resize(1); ++ { ++ const entier n = index.size_array(); ++ // Global index of the last loaded node: ++ entier last_node = -1; ++ // Local index of the new loaded node: ++ entier new_node_index = nodes_.dimension(0)-1; ++ for (entier i = 0; i < n; i++) { ++ // Take nodes to load in ascending order of their global numbers: ++ const entier idx = index[i]; ++ const entier node = virt_elem_som_array[idx]; ++ if (node != last_node) { ++ // Node not yet encountered ++ nodes_to_read.append_array(node); ++ new_node_index++; ++ last_node = node; ++ } ++ virt_elem_som_array[idx] = new_node_index; ++ } ++ } ++ set_virt_items(LataField_base::SOM, nodes_to_read); ++ // Copy virtual elements to elements_ ++ entier debut = elements_.size_array(); ++ elements_.resize(elements_.dimension(0) + virt_elem_som.dimension(0), ++ elements_.dimension(1)); ++ elements_.inject_array(virt_elem_som, virt_elem_som.size_array(), debut); ++ // Load virtual nodes ++ FloatTab tmp_nodes; ++ lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "SOMMETS", "*"), tmp_nodes, nodes_to_read); ++ // Copy to nodes_ ++ debut = nodes_.size_array(); ++ nodes_.resize(nodes_.dimension(0) + tmp_nodes.dimension(0), ++ nodes_.dimension(1)); ++ nodes_.inject_array(tmp_nodes, tmp_nodes.size_array(), debut); ++ } ++ ++ if (domain_has_faces) { ++ // Find which virtual faces are required and load them ++ // For each virtual element, index of its faces (like virt_elem_som) ++ IntTab virt_elem_faces; ++ lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "ELEM_FACES", "*"), virt_elem_faces, virt_elems); ++ // Build the list of missing faces: ++ ArrOfInt index; ++ ArrOfInt & virt_elem_faces_array = virt_elem_faces; // Array seen as monodimensionnal ++ array_sort_indirect(virt_elem_faces_array, index); ++ ArrOfInt faces_to_read; ++ faces_to_read.set_smart_resize(1); ++ { ++ const entier n = index.size_array(); ++ // Global index of the last loaded face: ++ entier last_face = -1; ++ // Local index of the new loaded node: ++ entier new_face_index = faces_.dimension(0)-1; ++ for (entier i = 0; i < n; i++) { ++ // Take nodes to load in ascending order of their global numbers: ++ const entier idx = index[i]; ++ const entier face = virt_elem_faces_array[idx]; ++ if (face != last_face) { ++ // Node not yet encountered ++ faces_to_read.append_array(face); ++ new_face_index++; ++ last_face = face; ++ } ++ virt_elem_faces_array[idx] = new_face_index; ++ } ++ } ++ set_virt_items(LataField_base::FACES, faces_to_read); ++ // Copy virtual elem_faces to elem_faces ++ entier debut = elem_faces_.size_array(); ++ elem_faces_.resize(elem_faces_.dimension(0) + virt_elem_faces.dimension(0), ++ elem_faces_.dimension(1)); ++ elem_faces_.inject_array(virt_elem_faces, virt_elem_faces.size_array(), debut); ++ ++ // Load virtual faces ++ IntTab tmp_faces_nodes; ++ lataDB.read_data(lataDB.get_field(id.timestep_, id.name_, "FACES", "*"), tmp_faces_nodes, faces_to_read); ++ // Convert global nodes indexes to local loaded nodes indexes in tmp_faces_nodes ++ { ++ // sort tmp_faces in ascending order so that the search requires linear time ++ ArrOfInt & array_tmp_faces_nodes = tmp_faces_nodes; ++ index.reset(); ++ array_sort_indirect(array_tmp_faces_nodes, index); ++ const entier n = array_tmp_faces_nodes.size_array(); ++ // Take nodes in tmp_faces_nodes in ascending order and find the corresponding node in nodes_to_read ++ // (which is also in sorted) ++ entier i1; // index in array_tmp_faces_nodes (the current node to convert) ++ entier i2 = 0; // index in nodes_to_read ++ const entier index_of_first_virtual_node = nodes_.dimension(0) - nb_virt_items(LataField_base::SOM); ++ const ArrOfInt & nodes_to_read = get_virt_items(LataField_base::SOM); ++ const entier max_i2 = nodes_to_read.size_array(); ++ for (i1 = 0; i1 < n; i1++) { ++ const entier j = index[i1]; ++ const entier global_node_index_to_find = array_tmp_faces_nodes[j]; ++ // find the matching node in nodes_to_read (nodes_to_read is in ascending order) ++ while (nodes_to_read[i2] != global_node_index_to_find) { ++ i2++; ++ if (i2 >= max_i2) { ++ cerr << "Internal error in DomainUnstructured::fill_domain_from_lataDB:\n" ++ << " node " << global_node_index_to_find << " of a virtual face does not belong to a virtual element" << endl; ++ throw; ++ } ++ } ++ array_tmp_faces_nodes[j] = index_of_first_virtual_node + i2; // index of this node in the local nodes_ array ++ } ++ } ++ // Copy to faces_ array ++ debut = faces_.size_array(); ++ faces_.resize(faces_.dimension(0) + tmp_faces_nodes.dimension(0), ++ faces_.dimension(1)); ++ faces_.inject_array(tmp_faces_nodes, tmp_faces_nodes.size_array(), debut); ++ } ++ } ++} ++ ++void Domain::fill_field_from_lataDB(const LataDB & lataDB, ++ const Field_Id & id, ++ LataDeriv & field) const ++{ ++ Journal() << "Error : fill_field_from_lataDB not coded for this domain type" << endl; ++ throw; ++} ++ ++// Reads the requested field to "field" structure. ++// id.block_ is not used, the data block read is the same as the domain. ++void DomainUnstructured::fill_field_from_lataDB(const LataDB & lataDB, ++ const Field_Id & id, ++ LataDeriv & field) const ++{ ++ const LataDBField & lata_field = lataDB.get_field(id.timestep_, id.uname_); ++ LataField_base::Elem_som loc = LataField_base::localisation_from_string(lata_field.localisation_); ++ const entier decal = lata_block_offset(loc); ++ ++ const ArrOfInt & virt_items = get_virt_items(loc); ++ const entier virt_size = virt_items.size_array(); ++ const entier size = nb_items(loc) - virt_size; ++ ++ const LataDBDataType & type = lata_field.datatype_; ++ switch(type.type_) { ++ case LataDBDataType::REAL32: { ++ FloatTab & data = field.instancie(Field ).data_; ++ lataDB.read_data(lata_field, data, decal, size); ++ if (virt_size > 0) { ++ FloatTab tmp; ++ lataDB.read_data(lata_field, tmp, virt_items); ++ const entier debut = data.size_array(); ++ data.resize(data.dimension(0)+virt_size, data.dimension(1)); ++ data.inject_array(tmp, virt_size, debut); ++ } ++ break; ++ } ++ case LataDBDataType::REAL64: { ++ DoubleTab & data = field.instancie(Field ).data_; ++ lataDB.read_data(lata_field, data, decal, size); ++ if (virt_size > 0) { ++ DoubleTab tmp; ++ lataDB.read_data(lata_field, tmp, virt_items); ++ const entier debut = data.size_array(); ++ data.resize(data.dimension(0)+virt_size, data.dimension(1)); ++ data.inject_array(tmp, virt_size, debut); ++ } ++ break; ++ } ++ case LataDBDataType::INT32: ++ case LataDBDataType::INT64: { ++ IntTab & data = field.instancie(Field ).data_; ++ lataDB.read_data(lata_field, data, decal, size); ++ if (virt_size > 0) { ++ IntTab tmp; ++ lataDB.read_data(lata_field, tmp, virt_items); ++ const entier debut = data.size_array(); ++ data.resize(data.dimension(0)+virt_size, data.dimension(1)); ++ data.inject_array(tmp, virt_size, debut); ++ } ++ break; ++ } ++ default: ++ Journal() << "LataFilter::get_field_from_lataDB " << id.uname_ << ": data type not implemented" << endl; ++ throw; ++ } ++ field.valeur().id_ = id; ++ field.valeur().component_names_ = lata_field.component_names_; ++ field.valeur().localisation_ = loc; ++ field.valeur().nature_ = lata_field.nature_; ++} ++ ++DomainIJK::DomainIJK() ++{ ++ part_begin_ = 0; ++ part_end_ = 0; ++ virtual_layer_begin_ = 0; ++ virtual_layer_end_ = 0; ++} ++ ++void DomainIJK::fill_domain_from_lataDB(const LataDB & lataDB, ++ const Domain_Id & id, ++ entier split_in_N_parts, ++ const entier virt_layer_size) ++{ ++ if (virt_layer_size < 0) { ++ Journal() << "Error in DomainIJK::fill_domain_from_lataDB: virt_layer_size < 0" << endl; ++ throw; ++ } ++ id_ = id; ++ ++ Journal(info_level) << "Filling ijk domain " << id.name_ << " tstep " << id.timestep_ << " block " << id.block_ << endl; ++ coord_.reset(); ++ entier dim3 = lataDB.field_exists(id.timestep_, id.name_, "SOMMETS_IJK_K", LataDB::FIRST_AND_CURRENT /* timestep */); ++ { ++ const LataDBField & coord = lataDB.get_field(id.timestep_, ++ Field_UName(id.name_, "SOMMETS_IJK_I", ""), ++ LataDB::FIRST_AND_CURRENT /* timestep */); ++ FloatTab tmp; ++ lataDB.read_data(coord, tmp); ++ coord_.add(); ++ coord_[0] = tmp; ++ } ++ { ++ const LataDBField & coord = lataDB.get_field(id.timestep_, ++ Field_UName(id.name_, "SOMMETS_IJK_J", ""), ++ LataDB::FIRST_AND_CURRENT /* timestep */); ++ FloatTab tmp; ++ lataDB.read_data(coord, tmp); ++ coord_.add(); ++ coord_[1] = tmp; ++ } ++ if (dim3) { ++ const LataDBField & coord = lataDB.get_field(id.timestep_, ++ Field_UName(id.name_, "SOMMETS_IJK_K", ""), ++ LataDB::FIRST_AND_CURRENT /* timestep */); ++ FloatTab tmp; ++ lataDB.read_data(coord, tmp); ++ coord_.add(); ++ coord_[2] = tmp; ++ } ++ ++ elt_type_ = dim3 ? hexa : quadri; ++ ++ entier block = (id.block_) < 0 ? 0 : id.block_; ++ ++ if (id.block_ >= split_in_N_parts) { ++ Journal() << "Error in DomainIJK::fill_domain_from_lataDB: invalid block " << id.block_ << endl; ++ throw; ++ } ++ ++ // Load the N-th part ++ // The ijk domain is virtually split in the Z direction (or Y en 2D) ++ entier maxdim = coord_.size() - 1; ++ // Number of elements in the Z direction: ++ const entier nelem = coord_[maxdim].size_array() - 1; ++ entier part_size = nelem / split_in_N_parts; ++ if (part_size * split_in_N_parts < nelem) ++ part_size++; ++ ++ // Begin and end of the requested part: ++ part_begin_ = part_size * block - virt_layer_size; ++ if (part_begin_ < 0) ++ part_begin_ = 0; ++ part_end_ = part_size * block + part_size + virt_layer_size; ++ if (part_end_ > nelem) ++ part_end_ = nelem; ++ if (part_begin_ > part_end_) ++ // empty block ++ part_begin_ = part_end_ = 0; ++ ++ if (block > 0 && part_end_ > part_begin_) ++ // There is a virtual layer at the begin ++ virtual_layer_begin_ = virt_layer_size; ++ if (block < split_in_N_parts-1 && part_end_ > part_begin_) ++ virtual_layer_end_ = virt_layer_size; ++ ++ // Extract coordinates: ++ ArrOfFloat tmp(coord_[maxdim]); ++ const entier n = part_end_ - part_begin_ + 1; ++ coord_[maxdim].resize_array(n); ++ for (entier i = 0; i < n; i++) ++ coord_[maxdim][i] = tmp[i + part_begin_]; ++ ++ Journal(info_level) << "Domain " << id.name_ << " has number of nodes: [ "; ++ for (entier dim = 0; dim < coord_.size(); dim++) ++ Journal(info_level) << coord_[dim].size_array() << " "; ++ Journal(info_level) << "]" << endl; ++ ++ if (part_end_ > part_begin_ // part might be empty if too many processors ++ && lataDB.field_exists(id.timestep_, id.name_, "INVALID_CONNECTIONS", LataDB::FIRST_AND_CURRENT /* timestep */)) ++ { ++ Journal(info_level) << " loading invalid_connections" << endl; ++ IntTab Itmp; ++ entier ij = 0, offset = 0, sz = 0; ++ // Product of number of elements in directions I and J ++ ij = coord_[0].size_array() - 1; ++ if (coord_.size() > 2) ++ ij *= coord_[1].size_array() - 1; ++ // Select a range of elements in direction K ++ offset = ij * part_begin_; ++ sz = nb_elements(); ++ const LataDBField & lata_field = lataDB.get_field(id.timestep_, id.name_, "INVALID_CONNECTIONS", "ELEM", ++ LataDB::FIRST_AND_CURRENT); ++ ++ lataDB.read_data(lata_field, Itmp, offset, sz); ++ ++ invalid_connections_.resize_array(nb_elements()); ++ invalid_connections_ = 0; // everything valid by default ++ ++ for (entier i = 0; i < sz; i++) { ++ if (Itmp(i, 0) != 0) ++ invalid_connections_.setbit(i); ++ } ++ } ++} ++ ++void DomainIJK::fill_field_from_lataDB(const LataDB & lataDB, ++ const Field_Id & id, ++ LataDeriv & field) const ++{ ++ const LataDBField & lata_field = lataDB.get_field(id.timestep_, id.uname_); ++ LataField_base::Elem_som loc = LataField_base::localisation_from_string(lata_field.localisation_); ++ ++ entier ij = 0, offset = 0, sz = 0; ++ switch(loc) { ++ case LataField_base::ELEM: ++ // Product of number of elements in directions I and J ++ ij = coord_[0].size_array() - 1; ++ if (coord_.size() > 2) ++ ij *= coord_[1].size_array() - 1; ++ // Select a range of elements in direction K ++ offset = ij * part_begin_; ++ sz = ij * (part_end_ - part_begin_); ++ break; ++ case LataField_base::SOM: ++ case LataField_base::FACES: ++ // Product of number of nodes in directions I and J ++ ij = coord_[0].size_array(); ++ if (coord_.size() > 2) ++ ij *= coord_[1].size_array(); ++ offset = ij * part_begin_; ++ sz = ij * (part_end_ + 1 - part_begin_); ++ break; ++ default: ++ Journal() << "Error in DomainIJK::fill_field_from_lataDB: unknown localisation" << endl; ++ throw; ++ } ++ ++ const LataDBDataType & type = lata_field.datatype_; ++ switch(type.type_) { ++ case LataDBDataType::REAL32: { ++ FloatTab & data = field.instancie(Field ).data_; ++ lataDB.read_data(lata_field, data, offset, sz); ++ break; ++ } ++ case LataDBDataType::REAL64: { ++ DoubleTab & data = field.instancie(Field ).data_; ++ lataDB.read_data(lata_field, data, offset, sz); ++ break; ++ } ++ case LataDBDataType::INT32: ++ case LataDBDataType::INT64: { ++ IntTab & data = field.instancie(Field ).data_; ++ lataDB.read_data(lata_field, data, offset, sz); ++ break; ++ } ++ default: ++ Journal() << "LataFilter::get_field_from_lataDB " << id.uname_ << ": data type not implemented" << endl; ++ throw; ++ } ++ field.valeur().id_ = id; ++ field.valeur().component_names_ = lata_field.component_names_; ++ field.valeur().localisation_ = loc; ++ field.valeur().nature_ = lata_field.nature_; ++} ++ ++ ++Domain::DomainType Domain::get_domain_type() const ++{ ++ const DomainUnstructured* geom_ptr = dynamic_cast(this); ++ if (geom_ptr!=0) ++ return UNSTRUCTURED; ++ const DomainIJK* ijk_ptr = dynamic_cast(this); ++ if (ijk_ptr!=0) ++ return IJK; ++ throw ("Not implemeneted"); ++} ++const DomainUnstructured & Domain::cast_DomainUnstructured() const ++{ ++ return dynamic_cast(*this); ++} ++const DomainIJK & Domain::cast_DomainIJK() const ++{ ++ return dynamic_cast(*this); ++} +diff --git a/databases/readers/Lata/LataStructures.h b/databases/readers/Lata/LataStructures.h +new file mode 100644 +index 0000000..74fa765 +--- /dev/null ++++ b/databases/readers/Lata/LataStructures.h +@@ -0,0 +1,332 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef LataStructures_H ++#define LataStructures_H ++ ++#include ++#include ++#include ++ ++// This file contains definitions of data structures containind meshes and fields ++// used by LataFilter. ++ ++// Description: Domain_Id is what you need to identify the content ++// of a Domain object (at this time, the domain name, the timestep and the ++// parallel sub_block number) ++class Domain_Id ++{ ++public: ++ Domain_Id(const char * name = "??", int t = 0, int block = -1) : ++ name_(name), timestep_(t), block_(block) {}; ++ // Domain name ++ Nom name_; ++ // At which timestep (needed for dynamic domains) ++ int timestep_; ++ // Which block of the parallel computation ? -1 => all blocks ++ int block_; ++}; ++ ++// Description: Field_Id is what you need to identify the content of a ++// LataField_base structure (at this time, the field uname, ++// the timestep and the parallel sub_block number) ++class Field_Id ++{ ++public: ++ Field_Id() : timestep_(0) {}; ++ Field_Id(const Field_UName & uname, int timestep, int block) : ++ timestep_(timestep), block_(block), uname_(uname) {}; ++ ++ int timestep_; ++ int block_; ++ Field_UName uname_; ++ ++ operator Domain_Id() const { return Domain_Id(uname_.get_geometry(), timestep_, block_); } ++}; ++ ++// Description: This structure contains a discrete data array for a specific ++// field, at one timestep, for one sub_block of the geometry, with ++// one localisation (but many components) ++class LataField_base : public LataObject ++{ ++public: ++ LataField_base() { localisation_ = UNKNOWN; nature_ = LataDBField::UNKNOWN; } ++ Field_Id id_; ++ Noms component_names_; ++ enum Elem_som { ELEM, SOM, FACES, UNKNOWN }; ++ Elem_som localisation_; ++ LataDBField::Nature nature_; ++ ++ static Elem_som localisation_from_string(const Motcle &); ++ static Nom localisation_to_string(const Elem_som); ++}; ++class DomainUnstructured; ++class DomainIJK; ++ ++// This class stores the geometry of a domain ++class Domain : public LataObject ++{ ++public: ++ Domain_Id id_; ++ enum Element { point, line, triangle, quadri, tetra, hexa, prism6, polyedre, polygone, unspecified }; ++ enum DomainType { IJK, UNSTRUCTURED }; ++ static Element element_type_from_string(const Motcle & type_elem); ++ static Nom element_type_to_string(Element type); ++ Element elt_type_; ++ ++ Domain() : ++ elt_type_(unspecified), ++ decal_nodes_lata_(-1), // -1 indicates: value not set. see lata_block_offset ++ decal_elements_lata_(-1), ++ decal_faces_lata_(-1) {}; ++ DomainType get_domain_type() const; ++ const DomainUnstructured & cast_DomainUnstructured() const; ++ const DomainIJK & cast_DomainIJK() const; ++ virtual entier dimension() const = 0; ++ virtual entier nb_nodes() const = 0; ++ virtual entier nb_elements() const = 0; ++ virtual entier nb_faces() const = 0; ++ virtual entier nb_items(const LataField_base::Elem_som) const; ++ virtual entier lata_block_offset(const LataField_base::Elem_som) const; ++ virtual void set_lata_block_offset(const LataField_base::Elem_som, entier n); ++ ++ virtual void fill_field_from_lataDB(const LataDB & lataDB, ++ const Field_Id & id, ++ LataDeriv & field) const = 0; ++ ++ static Motcle lata_element_name(Domain::Element type); ++ ++protected: ++ // If the Domain has been loaded from a lata file and it's not the ++ // first block this is the offset in the lata file: ++ entier decal_nodes_lata_; ++ entier decal_elements_lata_; ++ entier decal_faces_lata_; ++}; ++ ++class DomainUnstructured : public Domain ++{ ++public: ++ DomainUnstructured() { nb_virt_nodes_ = 0; nb_virt_elements_ = 0; nb_virt_faces_ = 0; } ++ ++ FloatTab nodes_; ++ // For each element, indexes of the nodes (first node is at index 0) ++ // Nodes ordering in an element is the same as in TRUST ++ IntTab elements_; ++ // For each face, indexes of the nodes (if present in lata file) ++ IntTab faces_; ++ // For each elements, indexes of the faces (first face at index 0, if present in lata file) ++ // Faces ordering in an element is the same as in TRUST ++ IntTab elem_faces_; ++ ++ entier dimension() const { return nodes_.dimension(1); } ++ entier nb_nodes() const { return nodes_.dimension(0); } ++ entier nb_elements() const { return elements_.dimension(0); } ++ entier nb_faces() const { return faces_.dimension(0); } ++ // Tests if the geometry contains faces description ++ entier faces_ok() const { return elem_faces_.dimension(0) == elements_.dimension(0); } ++ template ++ void compute_cell_center_coordinates(TabType & coord, entier index_begin) const; ++ BigEntier compute_memory_size() const ++ { return ++ memory_size(nodes_) ++ + memory_size(elements_) ++ + memory_size(faces_) ++ + memory_size(elem_faces_); ++ } ++ const IntTab & get_joints(LataField_base::Elem_som loc) const { ++ const IntTab * ptr = 0; ++ switch(loc) { ++ case LataField_base::SOM: ptr = &joints_sommets_; break; ++ case LataField_base::ELEM: ptr = &joints_elements_; break; ++ case LataField_base::FACES: ptr = &joints_faces_; break; ++ default: throw; ++ } ++ if (ptr->dimension(1) == 0) throw; ++ return *ptr; ++ } ++ IntTab & set_joints(LataField_base::Elem_som loc) { ++ IntTab * ptr = 0; ++ switch(loc) { ++ case LataField_base::SOM: ptr = &joints_sommets_; break; ++ case LataField_base::ELEM: ptr = &joints_elements_; break; ++ case LataField_base::FACES: ptr = &joints_faces_; break; ++ default: throw; ++ } ++ return *ptr; ++ } ++ const ArrOfInt & get_virt_items(LataField_base::Elem_som loc) const { ++ switch(loc) { ++ case LataField_base::SOM: return virt_nodes_; break; ++ case LataField_base::ELEM: return virt_elements_; break; ++ case LataField_base::FACES: return virt_faces_; break; ++ default: throw; ++ } ++ return virt_nodes_; ++ } ++ void set_virt_items(LataField_base::Elem_som loc, const ArrOfInt & list) { ++ switch(loc) { ++ case LataField_base::SOM: virt_nodes_ = list; nb_virt_nodes_ = list.size_array(); break; ++ case LataField_base::ELEM: virt_elements_ = list; nb_virt_elements_ = list.size_array(); break; ++ case LataField_base::FACES: virt_faces_ = list; nb_virt_faces_ = list.size_array(); break; ++ default: throw; ++ } ++ }; ++ void set_nb_virt_items(LataField_base::Elem_som loc, entier n) { ++ switch(loc) { ++ case LataField_base::SOM: nb_virt_nodes_ = n; break; ++ case LataField_base::ELEM: nb_virt_elements_ = n; break; ++ case LataField_base::FACES: nb_virt_faces_ = n; break; ++ default: throw; ++ } ++ }; ++ entier nb_virt_items(LataField_base::Elem_som loc) const { ++ switch(loc) { ++ case LataField_base::SOM: return nb_virt_nodes_; break; ++ case LataField_base::ELEM: return nb_virt_elements_; break; ++ case LataField_base::FACES: return nb_virt_faces_; break; ++ default: throw; ++ } ++ return nb_virt_nodes_; ++ } ++ ++ virtual void fill_domain_from_lataDB(const LataDB & lataDB, ++ const Domain_Id & id, ++ entier load_faces = 1, ++ entier merge_virtual_elements = 0); ++ virtual void fill_field_from_lataDB(const LataDB & lataDB, ++ const Field_Id & id, ++ LataDeriv & field) const; ++ ++protected: ++ // data not always filled: ++ IntTab joints_sommets_; ++ IntTab joints_elements_; ++ IntTab joints_faces_; ++ ArrOfInt virt_nodes_; // Global indexes of virtual nodes to load ++ ArrOfInt virt_elements_; // Global indexes of virtual elements to load ++ ArrOfInt virt_faces_; // Global indexes of virtual faces to load ++ entier nb_virt_nodes_; ++ entier nb_virt_elements_; ++ entier nb_virt_faces_; ++}; ++ ++// This is a structured grid, grid axes aligned on X, Y and Z. ++// The grid can have "invalid_positions_" and "invalid_connections_". ++// Nodes are numbered like this: ++// node_index(i,j,k) = (k * nb_nodes_y + j) * nb_nodes_x + i ++// Elements are numbered like this: ++// element_index(i,j,k) = (k * nb_elements_y + j) * nb_elements_x + i ++// Faces are numbered like this: faces of each direction have a numbering starting at zero. ++// The number of a particular face is the smallest number of its nodes. ++// Hence some numbers are not used (le last face of each "row" depending on the ++// direction) ++class DomainIJK : public Domain ++{ ++public: ++ DomainIJK(); ++ // In each spatial direction, ordered list of coordinates of the IJK grid ++ LataVector coord_; ++ ++ // For each node and each element, flag indicates if it is valid or not ++ // (eg, has usable field values) ++ // If array is empty, all data is valid. ++ ArrOfBit invalid_positions_; ++ ArrOfBit invalid_connections_; ++ ++ entier dimension() const { return coord_.size(); } ++ entier nb_nodes() const { ++ entier n = 1, d = coord_.size(); ++ for (entier i=0; i= dimension()) ++ entier nb_som_dir(entier dir) const { ++ if (dir >= dimension()) ++ return 1; ++ else ++ return coord_[dir].size_array(); ++ } ++ // renvoie le nombre d'elements dans la direction dir ++ // (renvoie 1 si dir >= dimension()) ++ entier nb_elem_dir(entier dir) const { ++ if (dir >= dimension()) ++ return 1; ++ else ++ return coord_[dir].size_array() - 1; ++ } ++ ++ virtual void fill_domain_from_lataDB(const LataDB & lataDB, ++ const Domain_Id & id, ++ const entier split_in_nparts = 1, ++ const entier virt_layer_size = 1); ++ virtual void fill_field_from_lataDB(const LataDB & lataDB, ++ const Field_Id & id, ++ LataDeriv & field) const; ++ ++ // when loading fields, we will load elements (i,j,k) with ++ // part_begin_ <= k < part_end_ ++ // (or j in 2D), part_begin_ and part_end_ include the virtual layer ++ entier part_begin_; ++ entier part_end_; ++ // number of layers of virtual elements at each side: ++ entier virtual_layer_begin_; ++ entier virtual_layer_end_; ++}; ++ ++template ++class Field : public LataField_base ++{ ++public: ++ TabType data_; ++ BigEntier compute_memory_size() const { return memory_size(data_); } ++}; ++#endif +diff --git a/databases/readers/Lata/LataV1_field_definitions.C b/databases/readers/Lata/LataV1_field_definitions.C +new file mode 100644 +index 0000000..7bb0e2f +--- /dev/null ++++ b/databases/readers/Lata/LataV1_field_definitions.C +@@ -0,0 +1,84 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++ ++typedef struct { ++ const char * name; ++ int shape; // Vector size (-1 => dimension of the problem) ++} StdComponents; ++ ++// COMPOSANTES EN MAJUSCULES !!!!! ++// Components are checked in the same order than this array. ++// We assume that the component has been found if component ++// name begins with the string in this array. For example ++// if the lata file contains INDICATRICE_INTERF, we will ++// find that it is an "INDICATRICE" component. ++// Therefore, long names must be placed before short names: ++// If we have a component "K" and a component "K_EPS", then ++// "K_EPS" must be placed before "K", otherwise "K_EPS" will ++// never be found. ++const StdComponents std_components[] = ++ { ++ { "VITESSE", -1 }, ++ { "primal", -1 }, ++ { "VORTICITE", -2 }, ++ { "MOYENNE_VITESSE", -1 }, ++ { "ECART_TYPE_VITESSE", -1 }, ++ { "MOYENNE_VORTICITE", -2 }, ++ { "ECART_TYPE_VORTICITE", -2 }, ++ { "GRADIENT_PRESSION", -1 }, ++ { "DERIVEE_U_ETOILE", -1 }, ++ { "TERME_DIFFUSION_VITESSE", -1 }, ++ { "TERME_CONVECTION_VITESSE", -1 }, ++ { "TERME_SOURCE_VITESSE", -1 }, ++ { "GRAD", -1 }, ++ { "NORMALE_INTERFACE", -1 }, ++ { "K_EPS", 2 }, ++ { "ACCELERATION", -1 }, ++ { "CHAMP_VECTORIEL", -1}, ++ { "2_", 2}, ++ { "3_", 3}, ++ { "6_", 6}, ++ { "9_", 9}, ++ { "", 1 } ++ // Empty label means end of the table ++ }; ++ ++int latav1_component_shape(const Motcle & compo) ++{ ++ entier i = 0; ++ while (std_components[i].name[0] != 0) { ++ if (compo.debute_par(std_components[i].name)) ++ return std_components[i].shape; ++ i++; ++ } ++ return 1; ++} +diff --git a/databases/readers/Lata/LataV1_field_definitions.h b/databases/readers/Lata/LataV1_field_definitions.h +new file mode 100644 +index 0000000..8aaca6a +--- /dev/null ++++ b/databases/readers/Lata/LataV1_field_definitions.h +@@ -0,0 +1,35 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++// This file is included in LataDB.cpp (and only there) ++// It contains fields definitions for the old LataV1 format ++// (separated from LataDB.cpp so that changes in this file are ++// easily identified) ++class Motcle; ++int latav1_component_shape(const Motcle & compo); +diff --git a/databases/readers/Lata/LataVector.h b/databases/readers/Lata/LataVector.h +new file mode 100644 +index 0000000..18e46f6 +--- /dev/null ++++ b/databases/readers/Lata/LataVector.h +@@ -0,0 +1,64 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef LataVector_H ++#define LataVector_H ++#include ++#include ++// This vector class uses an array of pointers so that objects stored are never ++// moved in memory when the array is resized. ++template ++class LataVector ++{ ++public: ++ LataVector() : n_(0), data_(0) { } ++ LataVector(const LataVector & x) : n_(0), data_(0) { operator=(x); } ++ LataVector(entier n) : n_(0), data_(0) { for (entier i=0; i=0 && i=0 && i & operator=(const LataVector & x) { reset(); for (int i=0; i ++#include ++ ++// Path, if not empty, must include a trailing '/' ++// basename must not include the .lata extension ++void LataWriter::init_file(const Nom & path, const Nom & basename, ++ const LataDBDataType & default_int_format, ++ LataDBDataType::Type default_float_type) ++{ ++ db_.reset(); ++ db_.set_path_prefix(path); ++ basename_ = basename; ++ db_.default_type_int_ = default_int_format; ++ db_.default_float_type_ = default_float_type; ++ db_.header_ = "Lata V2"; ++ db_.case_ = "lata2dx"; ++ db_.software_id_ = "Trio_U"; ++ //split_ = split; ++ ++ // Global geometries and fields: ++ db_.add_timestep(0.); ++} ++ ++// Add a new timestep to the lata database (new TEMPS entry) ++// Geometries and fields are always written in the last added timestep ++// (the timestep stored within the domain or field is ignored) ++// Those written before the first call to write_time() go into global ++// fields and geometry definitions. ++void LataWriter::write_time(double t) ++{ ++ db_.add_timestep(t); ++} ++ ++void LataWriter::write_geometry(const Domain & dom) ++{ ++ // Index of the last timestep: ++ const entier tstep = db_.nb_timesteps() - 1; ++ ++ // Build a geometry database entry and add it to database ++ LataDBGeometry geom; ++ geom.name_ = dom.id_.name_; ++ geom.elem_type_ = dom.element_type_to_string(dom.elt_type_); ++ geom.timestep_ = tstep; ++ db_.add_geometry(geom); ++ ++ // Write geometry data ++ const DomainUnstructured * dom1_ptr = dynamic_cast(&dom); ++ const DomainIJK * dom2_ptr = dynamic_cast(&dom); ++ ++ if (dom1_ptr) ++ { ++ // For unstructured meshes, we write the following fields: ++ // SOMMETS ++ // ELEMENTS ++ // [ FACES ] ++ // [ ELEM_FACES ] ++ const DomainUnstructured & domain = *dom1_ptr; ++ LataDBField field; ++ // Write nodes ++ Nom fieldname = "SOMMETS"; ++ field.uname_ = Field_UName(geom.name_, fieldname, "" /* localisation */); ++ field.name_ = fieldname; ++ field.timestep_ = tstep; ++ ++ field.filename_ = basename_; ++ field.filename_ += ".lata."; ++ field.filename_ += fieldname; ++ field.filename_ += "."; ++ field.filename_ += geom.name_; ++ if (tstep > 0) { ++ field.filename_ += "."; ++ field.filename_ += Nom(tstep); ++ } ++ field.nb_comp_ = domain.dimension(); ++ field.geometry_ = geom.name_; ++ field.datatype_ = db_.default_type_float(); ++ field.localisation_ = ""; ++ field.reference_ = ""; ++ field.size_ = domain.nb_nodes(); ++ ++ db_.add_field(field); ++ db_.write_data(tstep, field.uname_, domain.nodes_); ++ ++ // Write elements ++ fieldname = "ELEMENTS"; ++ field.uname_ = Field_UName(geom.name_, fieldname, "" /* localisation */); ++ field.name_ = fieldname; ++ field.timestep_ = tstep; ++ ++ field.filename_ = basename_; ++ field.filename_ += ".lata."; ++ field.filename_ += fieldname; ++ field.filename_ += "."; ++ field.filename_ += geom.name_; ++ if (tstep > 0) { ++ field.filename_ += "."; ++ field.filename_ += Nom(tstep); ++ } ++ field.nb_comp_ = domain.elements_.dimension(1); ++ field.geometry_ = geom.name_; ++ field.datatype_ = db_.default_type_int_; ++ field.localisation_ = ""; ++ field.reference_ = "SOMMETS"; ++ field.size_ = domain.nb_elements(); ++ ++ db_.add_field(field); ++ db_.write_data(tstep, field.uname_, domain.elements_); ++ ++ // Write faces ++ if (domain.faces_ok()) { ++ fieldname = "FACES"; ++ field.uname_ = Field_UName(geom.name_, fieldname, "" /* localisation */); ++ field.name_ = fieldname; ++ field.timestep_ = tstep; ++ ++ field.filename_ = basename_; ++ field.filename_ += ".lata."; ++ field.filename_ += fieldname; ++ field.filename_ += "."; ++ field.filename_ += geom.name_; ++ if (tstep > 0) { ++ field.filename_ += "."; ++ field.filename_ += Nom(tstep); ++ } ++ field.nb_comp_ = domain.faces_.dimension(1); ++ field.geometry_ = geom.name_; ++ field.datatype_ = db_.default_type_int_; ++ field.localisation_ = ""; ++ field.reference_ = "SOMMETS"; ++ field.size_ = domain.nb_faces(); ++ ++ db_.add_field(field); ++ db_.write_data(tstep, field.uname_, domain.faces_); ++ ++ fieldname = "ELEM_FACES"; ++ field.uname_ = Field_UName(geom.name_, fieldname, "" /* localisation */); ++ field.name_ = fieldname; ++ field.timestep_ = tstep; ++ ++ field.filename_ = basename_; ++ field.filename_ += ".lata."; ++ field.filename_ += fieldname; ++ field.filename_ += "."; ++ field.filename_ += geom.name_; ++ if (tstep > 0) { ++ field.filename_ += "."; ++ field.filename_ += Nom(tstep); ++ } ++ field.nb_comp_ = domain.elem_faces_.dimension(1); ++ field.geometry_ = geom.name_; ++ field.datatype_ = db_.default_type_int_; ++ field.localisation_ = ""; ++ field.reference_ = "FACES"; ++ field.size_ = domain.nb_elements(); ++ ++ db_.add_field(field); ++ db_.write_data(tstep, field.uname_, domain.elem_faces_); ++ } ++ } ++ else if (dom2_ptr) ++ { ++ // For IJK we write 2 or 3 fields containing 1-dimensionnal arrays with ++ // the nodes coordinates in each direction: ++ // SOMMETS_IJK_I, SOMMETS_IJK_J, SOMMETS_IJK_K. ++ ++ const DomainIJK & domain = *dom2_ptr; ++ // Write coordinates ++ const entier dim = domain.coord_.size(); ++ if (dim > 3) { ++ Journal() << "Error in LataWriter::write_geometry: dimension > 3" << endl; ++ throw InternalError; ++ } ++ Noms dir_names(3); ++ dir_names[0] = "I"; ++ dir_names[1] = "J"; ++ dir_names[2] = "K"; ++ for (entier i_dim = 0; i_dim < dim; i_dim++) { ++ FloatTab coord; ++ { ++ const ArrOfFloat & x = domain.coord_[i_dim]; ++ const entier n = x.size_array(); ++ coord.resize(n, 1); ++ for (entier i = 0; i < n; i++) ++ coord(i, 0) = x[i]; ++ } ++ ++ Nom fieldname = "SOMMETS_IJK_"; ++ fieldname += dir_names[i_dim]; ++ LataDBField field; ++ field.uname_ = Field_UName(geom.name_, fieldname, "" /* localisation */); ++ field.name_ = fieldname; ++ field.timestep_ = tstep; ++ ++ field.filename_ = basename_; ++ field.filename_ += ".lata."; ++ field.filename_ += fieldname; ++ field.filename_ += "."; ++ field.filename_ += geom.name_; ++ if (tstep > 0) { ++ field.filename_ += "."; ++ field.filename_ += Nom(tstep); ++ } ++ field.nb_comp_ = 1; ++ field.geometry_ = geom.name_; ++ field.datatype_ = db_.default_type_float(); ++ field.localisation_ = ""; ++ field.reference_ = ""; ++ field.size_ = coord.dimension(0); ++ ++ db_.add_field(field); ++ db_.write_data(tstep, field.uname_, coord); ++ } ++ ++ if (domain.invalid_connections_.size_array() > 0) { ++ const entier n = domain.invalid_connections_.size_array(); ++ IntTab tmp(n, 1); ++ for (entier i = 0; i < n; i++) ++ tmp(i, 0) = domain.invalid_connections_[i]; ++ ++ Nom fieldname = "INVALID_CONNECTIONS"; ++ LataDBField field; ++ field.uname_ = Field_UName(geom.name_, fieldname, "ELEM" /* localisation */); ++ field.name_ = fieldname; ++ field.timestep_ = tstep; ++ ++ field.filename_ = basename_; ++ field.filename_ += ".lata."; ++ field.filename_ += fieldname; ++ field.filename_ += "."; ++ field.filename_ += geom.name_; ++ if (tstep > 0) { ++ field.filename_ += "."; ++ field.filename_ += Nom(tstep); ++ } ++ field.nb_comp_ = 1; ++ field.geometry_ = geom.name_; ++ field.datatype_ = db_.default_type_int_; ++ field.datatype_.array_index_ = LataDBDataType::NOT_AN_INDEX; ++ field.localisation_ = "ELEM"; ++ field.reference_ = ""; ++ field.size_ = n; ++ ++ db_.add_field(field); ++ db_.write_data(tstep, field.uname_, tmp); ++ } ++ } ++ else ++ { ++ Journal() << "Error LataWriter::write_geometry domain type not supported" << endl; ++ throw InternalError; ++ } ++} ++ ++void LataWriter::write_component(const LataField_base & field) ++{ ++ // Index of the last timestep: ++ const entier tstep = db_.nb_timesteps() - 1; ++ ++ LataDBField lata_field; ++ ++ lata_field.uname_ = field.id_.uname_; ++ lata_field.name_ = field.id_.uname_.get_field_name(); ++ lata_field.timestep_ = tstep; ++ lata_field.filename_ = basename_; ++ lata_field.filename_ += ".lata."; ++ lata_field.filename_ += lata_field.uname_.build_string(); ++ if (tstep > 0) { ++ lata_field.filename_ += "."; ++ lata_field.filename_ += Nom(tstep); ++ } ++ lata_field.geometry_ = field.id_.uname_.get_geometry(); ++ lata_field.component_names_ = field.component_names_; ++ // Unites a remplir ++ // Size = -1 => valeur par defaut cherchee dans la geometrie ++ lata_field.localisation_ = LataField_base::localisation_to_string(field.localisation_); ++ lata_field.nature_ = field.nature_; ++ ++ const Field * float_f = dynamic_cast*>(&field); ++ const Field* int_f = dynamic_cast*>(&field); ++ if (int_f) { ++ lata_field.nb_comp_ = int_f->data_.dimension(1); ++ lata_field.size_ = int_f->data_.dimension(0); ++ lata_field.datatype_ = db_.default_type_int_; ++ lata_field.datatype_.array_index_ = LataDBDataType::NOT_AN_INDEX; ++ db_.add_field(lata_field); ++ db_.write_data(tstep, lata_field.uname_, int_f->data_); ++ } else if (float_f) { ++ lata_field.nb_comp_ = float_f->data_.dimension(1); ++ lata_field.size_ = float_f->data_.dimension(0); ++ lata_field.datatype_ = db_.default_type_float(); ++ db_.add_field(lata_field); ++ db_.write_data(tstep, lata_field.uname_, float_f->data_); ++ } ++} ++ ++void LataWriter::finish() ++{ ++ Nom n(db_.path_prefix()); ++ n += basename_; ++ n += ".lata"; ++ db_.write_master_file(n); ++} +diff --git a/databases/readers/Lata/LataWriter.h b/databases/readers/Lata/LataWriter.h +new file mode 100644 +index 0000000..d17c413 +--- /dev/null ++++ b/databases/readers/Lata/LataWriter.h +@@ -0,0 +1,61 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef LataWriter_H ++#define LataWriter_H ++#include ++class Domain; ++class LataField_base; ++ ++// This class provides general services to write lata files ++// from the "high level" objects Domain and Field (the LataDB class provides ++// only low level services to write arrays) ++class LataWriter ++{ ++public: ++ enum FileSplittingOption { MULTIPLE_FILES, SINGLE_FILE }; ++ void init_file(const Nom & path, const Nom & basename, ++ const LataDBDataType & default_int_format, ++ LataDBDataType::Type default_float_type); ++ ++ void write_time(double t); ++ void write_geometry(const Domain & dom); ++ void write_component(const LataField_base & field); ++ ++ void finish(); ++ enum ERRORS { InternalError }; ++ ++protected: ++ // This is the database where we put all data... ++ LataDB db_; ++ // Basename for files and lata master file: ++ Nom basename_; ++ // FileSplittingOption split_; ++}; ++#endif +diff --git a/databases/readers/Lata/Lata_tools.C b/databases/readers/Lata/Lata_tools.C +new file mode 100644 +index 0000000..fb97479 +--- /dev/null ++++ b/databases/readers/Lata/Lata_tools.C +@@ -0,0 +1,128 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int journal_level = 0; ++ ++void set_Journal_level(entier level) ++{ ++ if (journal_level==level) return; ++ journal_level = level; ++ Journal() << "Changed lata journal level: " << journal_level << endl; ++} ++ ++static std::ostringstream junk_journal; ++ ++std::ostream & Journal(entier level) ++{ ++ if (level <= journal_level) { ++ cerr << "[" << level << "] "; ++ return cerr; ++ } else { ++ junk_journal.seekp(0); ++ return junk_journal; ++ } ++} ++ ++// Description: this method must return the total memory consumption ++// of the object (used to compute the size of the data cache) ++BigEntier LataObject::compute_memory_size() const ++{ ++ Journal() << "Error in LataObject::compute_memory_size(): function not implemented" << endl; ++ throw; ++} ++ ++BigEntier memory_size(const ArrOfInt & tab) ++{ ++ // On ne tient pas compte du caractere smart_resize ou ref du tableau ++ // c'est pas tres grave pour l'instant pour ce qu'on en fait... ++ return ((BigEntier)sizeof(tab)) + ((BigEntier)tab.size_array()) * sizeof(entier); ++} ++ ++BigEntier memory_size(const ArrOfDouble & tab) ++{ ++ // on ne tient pas compte du caractere smart_resize ou ref du tableau ++ // c'est pas tres grave pour l'instant pour ce qu'on en fait... ++ return ((BigEntier)sizeof(tab)) + ((BigEntier)tab.size_array()) * sizeof(double); ++} ++ ++BigEntier memory_size(const ArrOfFloat & tab) ++{ ++ // on ne tient pas compte du caractere smart_resize ou ref du tableau ++ // c'est pas tres grave pour l'instant pour ce qu'on en fait... ++ return ((BigEntier)sizeof(tab)) + ((BigEntier)tab.size_array()) * sizeof(float); ++} ++ ++BigEntier memory_size(const ArrOfBit & tab) ++{ ++ return ((BigEntier)sizeof(tab)) + ((BigEntier)tab.size_array()) * sizeof(int) / 32; ++} ++ ++void split_path_filename(const char *s, Nom & path, Nom & filename) ++{ ++ int i; ++ for (i=(int)strlen(s)-1;i>=0;i--) ++ if ((s[i]==PATH_SEPARATOR) || (s[i]=='\\')) ++ break; ++ path = ""; ++ int j; ++ for (j = 0; j <= i; j++) ++ path += Nom(s[j]); ++ ++ // Parse basename : if extension given, remove it ++ filename = s+i+1; ++} ++ ++static const ArrOfInt * array_to_sort_ptr = 0; ++int compare_indirect(const void *ptr1, const void *ptr2) ++{ ++ entier i1 = *(const entier*)ptr1; ++ entier i2 = *(const entier*)ptr2; ++ entier diff = (*array_to_sort_ptr)[i1] - (*array_to_sort_ptr)[i2]; ++ return (diff>0) ? 1 : ((diff==0) ? 0 : -1); ++} ++ ++void array_sort_indirect(const ArrOfInt & array_to_sort, ArrOfInt & index) ++{ ++ const entier n = array_to_sort.size_array(); ++ index.set_smart_resize(1); ++ index.resize_array(n); ++ for (entier i = 0; i < n; i++) ++ index[i] = i; ++ array_to_sort_ptr = &array_to_sort; ++ qsort(index.addr(), n, sizeof(entier), compare_indirect); ++} +diff --git a/databases/readers/Lata/Lata_tools.h b/databases/readers/Lata/Lata_tools.h +new file mode 100644 +index 0000000..940fc54 +--- /dev/null ++++ b/databases/readers/Lata/Lata_tools.h +@@ -0,0 +1,194 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef Lata_tools_include_ ++#define Lata_tools_include_ ++#include ++#include ++ ++ ++ ++ ++ ++#ifdef WIN32 ++#define __BIG_ENDIAN 111 ++#define __LITTLE_ENDIAN 121 ++#define __BYTE_ORDER __LITTLE_ENDIAN ++ ++#define strtoll _strtoi64 ++// This must be able to contain a total memory size ++// or a very big operation counter. ++typedef __int64 BigEntier; ++ ++#else ++#ifdef __APPLE__ ++// Assume we only have x86, x86_64 based Macs. ++#define __BIG_ENDIAN 111 ++#define __LITTLE_ENDIAN 121 ++#define __BYTE_ORDER __LITTLE_ENDIAN ++#endif ++ ++// This must be able to contain a total memory size ++// or a very big operation counter. ++typedef long long BigEntier; ++#endif ++ ++#ifndef __BYTE_ORDER ++#include ++#endif ++ ++#include ++ ++ ++#define PATH_SEPARATOR '/' ++ ++#ifndef __BYTE_ORDER ++#error "Byte order not defined." ++#endif ++#if (__BYTE_ORDER == __BIG_ENDIAN) ++const bool mymachine_msb = true; ++#elif (__BYTE_ORDER == __LITTLE_ENDIAN) ++const bool mymachine_msb = false; ++#else ++#error "Byte order is neither __BIG_ENDIAN nor __LITTLE_ENDIAN : " ++#endif ++ ++class ArrOfInt; ++class ArrOfDouble; ++class ArrOfFloat; ++class ArrOfBit; ++BigEntier memory_size(const ArrOfInt &); ++BigEntier memory_size(const ArrOfDouble &); ++BigEntier memory_size(const ArrOfFloat &); ++BigEntier memory_size(const ArrOfBit &); ++ ++class LataObject ++{ ++public: ++ virtual ~LataObject() {}; ++ virtual BigEntier compute_memory_size() const; ++}; ++ ++// A 'LataDeriv ptr' object can hold an object of class Y which is any derived type of X. ++// The contained object can be accessed via "valeur()" (you get an object of type X) ++// or "refcast()" (get an object of any derived type Z between X and Y) ++// (refcast() throws an exception if you try to cast with a wrong type) ++// It can also be null (hold no object). valeur() will then throw an exception. ++// Example: ++// LataDeriv deriv_x; ++// Y & y = deriv_x.instancie(Y); // Creates an instance of type Y within deriv_x ++// X & x = deriv_x.valeur(); // Get a reference to the contained object ++// Y & y2 = deriv_x.refcast(Y); // Same, but you get a reference of type Y ++// Z & z = deriv_x.refcast(Z); // Throw an exception if Z is not a derived class of X and a base class of Y ++// x.reset(); // Destroys the contained object (also destroyed when deriv_x is destroyed) ++#define instancie(x) instancie_(new x) ++#define refcast(x) refcast_((x*) 0) ++ ++template ++class LataDeriv : public LataObject ++{ ++public: ++ enum DERIV_ERROR { ERROR_TYPE, ERROR_NULL }; ++ LataDeriv() : ptr_(0) { }; ++ ~LataDeriv() { delete ptr_; ptr_ = 0; } ++ void reset() { delete ptr_; ptr_ = 0; } ++ entier non_nul() const { return ptr_ != 0; } ++ // operator C &() { return valeur(); } ++ // operator const C &() const { return valeur(); } ++ C & valeur() { if (!ptr_) throw ERROR_NULL; return *ptr_; } ++ const C & valeur() const { if (!ptr_) throw ERROR_NULL; return *ptr_; } ++ template DER_C & instancie_(DER_C *ptr) { ++ reset(); ++ ptr_ = ptr; ++ if (!dynamic_cast(ptr_)) { ++ delete ptr_; ++ throw ERROR_TYPE; // DER_C is not a derived type of C ++ } ++ return (DER_C &) (*ptr_); ++ } ++ template DER_C & refcast_(DER_C *cast_type) { ++ if (!ptr_) ++ throw ERROR_NULL; ++ DER_C * x = dynamic_cast(ptr_); ++ if (!x) ++ throw ERROR_TYPE; ++ return *x; ++ } ++ BigEntier compute_memory_size() const { if (ptr_) return ptr_->compute_memory_size(); else return 0; } ++protected: ++ LataDeriv(const LataDeriv & c) { ptr_ = 0; operator=(c); } ++ LataDeriv(const C & c) { ptr_ = 0; operator=(c); } ++ LataDeriv & operator=(const LataDeriv &); ++ LataDeriv & operator=(const C &); ++ C *ptr_; ++}; ++ ++// This is a reference to an object of type C, but thr reference can be null ++template ++class LataRef ++{ ++public: ++ enum REF_ERROR { ERROR_NULL }; ++ LataRef() : ptr_(0) { } ++ ~LataRef() { ptr_ = 0; } ++ LataRef(const LataRef & x) : ptr_(x.ptr_) { } ++ LataRef(C & x) : ptr_(&x) { } ++ LataRef & operator=(LataRef & x) { ptr_ = x.ptr_; return *this; } ++ LataRef & operator=(C & x) { ptr_ = &x; return *this; } ++ void reset() { ptr_ = 0; } ++ operator C&() { if (!ptr_) throw ERROR_NULL; return *ptr_; } ++ C& valeur() { if (!ptr_) throw ERROR_NULL; return *ptr_; } ++ entier non_nul() const { return ptr_ != 0; } ++protected: ++ C *ptr_; ++}; ++ ++void array_sort_indirect(const ArrOfInt & array_to_sort, ArrOfInt & index); ++ ++class Nom; ++void split_path_filename(const char *full_name, Nom & path, Nom & filename); ++ ++// To optimize small loops: replace for(i=0;i= nloops-1) break ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++Motcles noms_to_motcles(const Noms & noms); ++ ++#endif +diff --git a/databases/readers/Lata/LmlReader.C b/databases/readers/Lata/LmlReader.C +new file mode 100644 +index 0000000..1b1b7d2 +--- /dev/null ++++ b/databases/readers/Lata/LmlReader.C +@@ -0,0 +1,435 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#define BUFSZ 1000 ++#include ++#include ++#include ++#include ++#include ++#include ++// lml files contain double precision values that can overflow or underflow ++// if converted to float. Check for overflow, ignore underflow ++static inline float double_to_float(double x) ++{ ++ // Written like this, the code will also stop on NAN values: ++ if (!(x < 1.e38 && x > -1.e38)) { ++ Journal() << "lml reader: Error converting double value " << x << " to float" << endl; ++ throw LataDBError(LataDBError::READ_ERROR); ++ } ++ return (float) x; ++} ++ ++// Reads the lml file, fills the lata_db and writes the data (coordinates, elements and ++// fields data) to a unique file data_filename. ++// The default format used to write data in the data_filename is lata_db.default_type_* ++// data_filename must not contain the path but only a filename with extension. ++// The path to the data file must be set by lata_db.set_path_prefix() before. ++// If data_filename is a null pointer, data files are not written and file offsets in lata_db will ++// be wrong (useful for just getting metadata) ++void lml_reader(const char * lmlfilename, const char * data_filename, LataDB & lata_db) ++{ ++ Nom filename_in_master_file; ++ if (!data_filename) ++ filename_in_master_file = "DATA_NOT_WRITTEN"; ++ else ++ filename_in_master_file = data_filename; ++ ++ const entier lmllevel=4; ++ EFichier is; ++ Journal(lmllevel) << "lml_reader: " << endl; ++ is.ouvrir(lmlfilename); ++ if (!is.good()) { ++ Journal() << "Error: cannot open lml file " << lmlfilename << endl; ++ throw; ++ } ++ char s[BUFSZ+1]; ++ is.get_istream().getline(s, BUFSZ); ++ if (!is.good()) { ++ Journal() << "Lml file " << lmlfilename << " is empty" << endl; ++ // Just put an empty initial timestep: ++ lata_db.add_timestep(-1.); ++ return; ++ } ++ lata_db.header_ = s; ++ Journal(lmllevel) << "Header: " << s << endl; ++ is.get_istream().getline(s, BUFSZ); ++ lata_db.case_ = s; ++ Journal(lmllevel) << "Case: " << s << endl; ++ is.get_istream().getline(s, BUFSZ); ++ lata_db.software_id_ = s; ++ Journal(lmllevel) << "Software_id: " << s << endl; ++ ++ Noms liste_noms_geoms; ++ Noms liste_noms_topo; ++ // Create first timestep (global definitions) ++ lata_db.add_timestep(-1.); ++ // file_offset_blurb: ++ // the file offset will be computed by LataDB::write_data(), ++ // but we must tell write_data() if it must put the data at the beginning ++ // (file_offset==0) or append the data at the end of the file (file_offset!=0) ++ // file_offset is 0 for the first data block and it is incremented for each block. ++ entier file_offset = 0; ++ LataDBField sommets; ++ FloatTab nodes; ++ while(1) { ++ const entier tstep = lata_db.nb_timesteps() - 1; ++ Motcle motlu; ++ is >> motlu; ++ if (!is.good()) break; ++ if (motlu == "GRILLE") { ++ LataDBGeometry geom; ++ sommets.name_ = "SOMMETS"; ++ geom.timestep_ = sommets.timestep_ = tstep; ++ sommets.filename_ = filename_in_master_file; ++ Nom mottmp; ++ is >> mottmp; ++ geom.name_ = ((const char*)mottmp)+7; // retire GRILLE_ du nom ++ Journal(lmllevel) << "lml_reader: GRILLE " << geom.name_ << endl; ++ is >> sommets.nb_comp_; ++ { ++ int tmp; ++ is >> tmp; ++ sommets.size_ = tmp; // size_ est long long... ++ } ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ sommets.geometry_ = geom.name_; ++ sommets.uname_ = Field_UName(sommets.geometry_, sommets.name_, ""); ++ sommets.datatype_ = lata_db.default_type_float(); ++ sommets.datatype_.file_offset_ = file_offset++; // see file_offset_blurb ++ nodes.resize(sommets.size_, sommets.nb_comp_); ++ for (entier i = 0; i < sommets.size_; i++) ++ for (entier j = 0; j < sommets.nb_comp_; j++) { ++ double x; ++ is >> x; ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ nodes(i,j) = double_to_float(x); ++ } ++ Journal(lmllevel+1) << "Finished reading nodes" << endl; ++ ++ lata_db.add_geometry(geom); ++ // Write nodes to disk later: in 2D they will be cropped ++ } else if (motlu == "TOPOLOGIE") { ++ LataDBField elements; ++ elements.name_ = "ELEMENTS"; ++ elements.timestep_ = tstep; ++ elements.filename_ = filename_in_master_file; ++ elements.datatype_ = lata_db.default_type_int_; ++ elements.datatype_.file_offset_ = file_offset++; // see file_offset_blurb ++ Nom ident; ++ is >> ident; // Topologie_MAILLAGE_VOLUMIQUE_XXX ++ Nom mottmp; ++ is >> mottmp; ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ elements.geometry_ = ((const char*)mottmp)+7; // retire GRILLE_ du nom ++ elements.uname_ = Field_UName(elements.geometry_, elements.name_, ""); ++ liste_noms_geoms.add(elements.geometry_); ++ liste_noms_topo.add(ident); ++ is >> motlu; ++ if (motlu != "MAILLE") { ++ Journal() << "Error reading TOPOLOGIE: expected MAILLE" << endl; ++ throw; ++ } ++ { ++ int tmp; ++ is >> tmp; // size_ est long long... ++ elements.size_ = tmp; ++ } ++ is >> motlu; ++ int borne_index_min=0; ++ if (motlu == "TETRA4") { ++ lata_db.set_elemtype(tstep, elements.geometry_, "TETRAEDRE"); ++ elements.nb_comp_ = 4; ++ } else if (motlu == "TRIANGLE_3D") { ++ elements.nb_comp_ = 3; ++ lata_db.set_elemtype(tstep, elements.geometry_, "TRIANGLE_3D"); ++ } else if (motlu == "QUADRANGLE_3D") { ++ elements.nb_comp_ = 4; ++ lata_db.set_elemtype(tstep, elements.geometry_, "QUADRANGLE_3D"); ++ } else if (motlu == "VOXEL8") { ++ elements.nb_comp_ = 8; ++ lata_db.set_elemtype(tstep, elements.geometry_, "HEXAEDRE"); ++ } else if (motlu == "SEGMENT") { ++ elements.nb_comp_ = 2; ++ lata_db.set_elemtype(tstep, elements.geometry_, "SEGMENT"); ++ } else if (motlu == "POINT") { ++ elements.nb_comp_ = 1; ++ lata_db.set_elemtype(tstep, elements.geometry_, "POINT"); ++ } else if (motlu == "PRISM6") { ++ lata_db.set_elemtype(tstep, elements.geometry_, "PRISM6"); ++ elements.nb_comp_ = 6; ++ } else if (motlu.debute_par("POLYEDRE_")) { ++ lata_db.set_elemtype(tstep, elements.geometry_, motlu); ++ elements.nb_comp_ = atoi(((const char *)motlu) + strlen("polyedre_")); ++ borne_index_min=-1; ++ } else if (motlu.debute_par("POLYGONE_")) { ++ lata_db.set_elemtype(tstep, elements.geometry_, motlu); ++ elements.nb_comp_ = atoi(((const char *)motlu) + strlen("polygone_")); ++ borne_index_min=-1; ++ } else { ++ Journal() << "Error reading TOPOLOGIE: unknown element type" << endl; ++ throw; ++ } ++ ++ Journal(lmllevel+1) << " " << elements.size_ << " elements " << motlu << endl; ++ IntTab elems; ++ elems.resize(elements.size_, elements.nb_comp_); ++ for (entier i = 0; i < elements.size_; i++) { ++ if (i != 0) { ++ is >> motlu; // element type ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ } ++ entier j; ++ for (j = 0; j < elements.nb_comp_; j++) { ++ is >> elems(i,j); ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ elems(i,j)--; ++ if (elems(i,j) < borne_index_min || elems(i,j) >= sommets.size_ ) { ++ Journal() << "Error reading TOPOLOGIE: bad node number elem(" << i << "," << j << ")=" << elems(i,j) << endl; ++ throw; ++ } ++ } ++ } ++ Journal(lmllevel+1) << " finished reading elements" << endl; ++ lata_db.add_field(sommets); ++ if (data_filename) ++ lata_db.write_data(tstep, sommets.uname_, nodes); ++ lata_db.add_field(elements); ++ if (data_filename) ++ lata_db.write_data(tstep, elements.uname_, elems); ++ } else if (motlu == "FACE") { ++ int n; ++ is >> n; ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ Journal(lmllevel+1) << " faces " << n << endl; ++ } else if (motlu == "TEMPS") { ++ double t; ++ is >> t; ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ lata_db.add_timestep(t); ++ Journal(lmllevel+1) << " new time: " << t << endl; ++ } else if (motlu == "CHAMPMAILLE" || motlu == "CHAMPPOINT") { ++ LataDBField field; ++ is >> field.name_; ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ Journal(lmllevel+1) << " new field: " << field.name_ << endl; ++ field.timestep_ = tstep; ++ field.filename_ = filename_in_master_file; ++ if (motlu == "CHAMPMAILLE") ++ field.localisation_ = "ELEM"; ++ else ++ field.localisation_ ="SOM"; ++ Nom nom_topo; ++ is >> nom_topo; ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ ++ const entier rang_topo = liste_noms_topo.rang(nom_topo); ++ if (rang_topo < 0) { ++ Journal() << "Error reading lml file : unknown topology name " << nom_topo << endl; ++ throw; ++ } ++ field.geometry_ = liste_noms_geoms[rang_topo]; ++ Motcle mottmp(field.name_); ++ Motcle tmp2("_"); ++ tmp2 += field.localisation_; ++ tmp2 += "_"; ++ tmp2 += field.geometry_; ++ mottmp.prefix(tmp2); // Retire _SOM_dom du nom ++ field.name_ = mottmp; ++ field.uname_ = Field_UName(field.geometry_, field.name_, field.localisation_); ++ double t; ++ is >> t; // Unused time value ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ is >> motlu; // Repeat fieldname ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ is >> field.nb_comp_; ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ Nom unit; ++ is >> unit; ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ field.unites_.add(unit); ++ is >> motlu; // type0 ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ { ++ int tmp; ++ is >> tmp; ++ field.size_ = tmp; // long long convert ++ } ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ // By default, 3 components fields are vectors: ++ if (field.nb_comp_ == 3) { ++ Journal(lmllevel+1) << " 3 components=> say it's a vector" << endl; ++ field.nature_ = LataDBField::VECTOR; ++ } else { ++ field.nature_ = LataDBField::SCALAR; ++ } ++ field.datatype_ = lata_db.default_type_float(); ++ field.datatype_.file_offset_ = file_offset++; // see file_offset_blurb ++ FloatTab tab; ++ tab.resize(field.size_, field.nb_comp_); ++ for (entier i = 0; i < field.size_; i++) { ++ entier n; ++ is >> n; ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ for (entier j = 0; j < field.nb_comp_; j++) { ++ double x; ++ is >> x; ++ if (!is.good()) ++ throw LataDBError(LataDBError::READ_ERROR); ++ tab(i,j) = double_to_float(x); ++ } ++ } ++ Journal(lmllevel+1) << " finished reading field " << field.name_ << endl; ++ lata_db.add_field(field); ++ if (data_filename) ++ lata_db.write_data(tstep, field.uname_, tab); ++ } else if (motlu == "FIN") { ++ break; ++ } else { ++ Journal() << "Error reading lml file, unknown keyword " << motlu << endl; ++ throw; ++ } ++ } ++} ++ ++void lml_to_lata(const char *lmlname, const char *latafilename, ++ entier ascii, entier fortran_blocs, entier fortran_ordering, entier fortran_indexing) ++{ ++ const entier lmllevel=4; ++ Journal(lmllevel) << "lml_to_lata " << lmlname << " -> " << latafilename << endl; ++ LataDB lata_db; ++ Nom dest_prefix, dest_name; ++ LataOptions::extract_path_basename(latafilename, dest_prefix, dest_name); ++ // Nom du fichier .data a ecrire (sans le chemin) ++ Nom datafile(dest_name); ++ datafile += ".lata.data"; ++ lata_db.set_path_prefix(dest_prefix); ++ // Nom complet du fichier lml a lire ++ LataDBDataType type; ++ if (ascii) ++ type.msb_ = LataDBDataType::ASCII; ++ else ++ type.msb_ = LataDBDataType::machine_msb_; ++ type.type_ = LataDBDataType::INT32; ++ type.array_index_ = fortran_indexing ? LataDBDataType::F_INDEXING : LataDBDataType::C_INDEXING; ++ type.data_ordering_ = fortran_ordering ? LataDBDataType::F_ORDERING : LataDBDataType::C_ORDERING; ++ type.fortran_bloc_markers_ = fortran_blocs ? LataDBDataType::BLOC_MARKERS_SINGLE_WRITE : LataDBDataType::NO_BLOC_MARKER; ++ type.bloc_marker_type_ = LataDBDataType::INT32; ++ type.file_offset_ = 0; ++ lata_db.default_type_int_ = type; ++ lata_db.default_float_type_ = LataDBDataType::REAL32; ++ ++ lml_reader(lmlname, datafile, lata_db); ++ Journal(lmllevel) << "lml_to_lata writing lata master file" << endl; ++ lata_db.write_master_file(latafilename); ++} ++ ++// Reads lml or lata file into lata_db. lml data is loaded in an internal memory buffer ++// file: full name with path ++// path_prefix: the path (used to access lata data files) ++// If dest_file_if_lml is not null, puts lml data into this file... ++// In this case, you must set lata_db.default_type* to tell which format to use. ++void read_any_format(const char * file, const Nom & path_prefix, LataDB & lata_db) ++{ ++ // Is it an lml ? ++ Motcle motcle_nom_fic(file); ++ if (motcle_nom_fic.finit_par(".lml")) { ++ Journal(1) << "Detected lml file : " << file << endl; ++ // Nom complet du fichier lml a lire ++ Journal(1) << "Reading lml file to memory buffer" << endl; ++ // data will be put in an internal memory buffer. ++ // choose appropriate data format: ++ LataDBDataType type; ++ type.msb_ = LataDBDataType::machine_msb_; ++ type.type_ = LataDBDataType::INT32; ++ type.array_index_ = LataDBDataType::C_INDEXING; ++ type.data_ordering_ = LataDBDataType::C_ORDERING; ++ type.fortran_bloc_markers_ = LataDBDataType::NO_BLOC_MARKER; ++ type.bloc_marker_type_ = LataDBDataType::INT32; ++ type.file_offset_ = 0; ++ lata_db.default_type_int_ = type; ++ lata_db.default_float_type_ = LataDBDataType::REAL32; ++ lml_reader(file, LataDBField::memory_buffer_file(), lata_db); ++ } else { ++ Journal(1) << "Detected lata file : " << file << endl; ++ lata_db.read_master_file(path_prefix, file); ++ } ++} ++ ++// Description: if the file is a lata file, read the third line and interprets it as options ++// if lml format, do nothing ++// otherwise, error. ++void read_any_format_options(const char * file, LataOptions & opt) ++{ ++ Motcle nom_fic(file); ++ if (nom_fic.finit_par(".lml")) { ++ // do nothing ++ } else if (nom_fic.finit_par(".med")) { ++ // do nothing ++ } else if (nom_fic.finit_par(".lata")) { ++ Journal(1) << "Lata file: Interpreting LataFilter options on third line" << endl; ++ Nom ligne = LataDB::read_master_file_options(file); ++ const char *s = ligne; ++ while (*s) { ++ Nom toto(""); ++ while ((*s) != ' ' && (*s) != 0) { ++ toto += Nom(*s); ++ s++; ++ } ++ if ((toto != "Trio_U")&&(toto != "TRUST" )) { ++ if (!opt.parse_option(toto)) { ++ Journal(0) << "Interpreting option: " << toto <<" Failed." << endl; ++ throw LataDBError::BAD_HEADER; ++ } else ++ Journal(1) << "Interpreting option: " << toto <<" Success." << endl; ++ } ++ while ((*s) == ' ') ++ s++; ++ } ++ } else { ++ Journal(0) << "read_any_format_options: file " << nom_fic << " has unsupported extension" << endl; ++ throw LataDBError::BAD_HEADER; ++ } ++} +diff --git a/databases/readers/Lata/LmlReader.h b/databases/readers/Lata/LmlReader.h +new file mode 100644 +index 0000000..9a37ab5 +--- /dev/null ++++ b/databases/readers/Lata/LmlReader.h +@@ -0,0 +1,38 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef LMLREADER_H ++#define LMLREADER_H ++void lml_reader(const char * lmlfilename, const char * data_filename, LataDB & lata_db); ++void lml_to_lata(const char *lmlfilename, const char *latafilename, ++ entier ascii = 0, entier fortran_blocs = 1, entier fortran_ordering = 0, entier fortran_indexing = 1); ++void read_any_format(const char * file, const Nom & path_prefix, LataDB & lata_db); ++void read_any_format_options(const char * file, LataOptions & opt); ++#endif ++ +diff --git a/databases/readers/Lata/Motcle.C b/databases/readers/Lata/Motcle.C +new file mode 100644 +index 0000000..4227be6 +--- /dev/null ++++ b/databases/readers/Lata/Motcle.C +@@ -0,0 +1,142 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++Nom& Nom::majuscule() ++{ ++ const int n = longueur()-1; ++ for (int i = 0; i < n; i++) ++ { ++ char c = s_[i]; ++ if (c >= 'a' && c <= 'z') ++ s_[i] = c + 'A' - 'a'; ++ } ++ return *this; ++} ++ ++static inline char char_uppercase(char c) ++{ ++ if (c >= 'a' && c <= 'z') ++ c += 'A' - 'a'; ++ return c; ++} ++ ++ ++// opt=0 => comparaison des chaines completes ++// opt=1 => le debut de n1 doit etre egal a n2 ++int Motcle::strcmp_uppercase(const char *n1, const char *n2, int opt) ++{ ++ entier i = 0; ++ unsigned char c1, c2; ++ entier delta; ++ do ++ { ++ c1 = (unsigned char) char_uppercase(n1[i]); ++ c2 = (unsigned char) char_uppercase(n2[i]); ++ delta = c1 - c2; ++ i++; ++ if (c2 == 0 && opt == 1) ++ { ++ // Fin de la deuxieme chaine et opt=1 (fonction "debute_par"): ++ // Test ok ++ return 0; ++ } ++ } ++ while ((delta == 0) && (c1 != 0) && (c2 != 0)); ++ return delta; ++} ++ ++int Nom::debute_par(const char * s) const ++{ ++ const int l1 = longueur()-1; ++ const int l2 = (int)strlen(s); ++ return (l1>=l2) ? (strncmp(s_.c_str(), s, l2) == 0) : 0; ++} ++ ++int Nom::finit_par(const char * s) const ++{ ++ const int l1 = longueur()-1; ++ const int l2 = (int)strlen(s); ++ return (l1>=l2) ? (strncmp(s_.c_str()+(l1-l2), s, l2) == 0) : 0; ++} ++ ++entier Nom::find(const char * n) const ++{ ++ std::size_t x = s_.find(n); ++ return (x != std::string::npos) ? x : -1; ++} ++ ++Nom& Nom::prefix(const char *s) ++{ ++ if (finit_par(s)) ++ { ++ entier n = strlen(s_.c_str()); ++ entier n2 = strlen(s); ++ s_.erase(n-n2,n2); ++ } ++ return *this; ++} ++ ++int Motcle::debute_par(const char * s) const ++{ ++ return (strcmp_uppercase(s_.c_str(), s, 1) == 0); ++} ++ ++int Motcle::finit_par(const char * s) const ++{ ++ const int l1 = longueur()-1; ++ const int l2 = (int)strlen(s); ++ return (l1>=l2) ? (strcmp_uppercase(s_.c_str()+(l1-l2), s) == 0) : 0; ++} ++ ++Motcles noms_to_motcles(const Noms& a) ++{ ++ Motcles b; ++ entier n = a.size(); ++ for (entier i = 0; i < n; i++) ++ b.add() = a[i]; // ouais, ecriture bizarre mais la plus efficace... ++ return b; ++} ++ ++std::istream& operator>>(std::istream& is, Nom& nom) ++{ ++ nom.read(is); ++ return is; ++} ++ ++std::ostream& operator<<(std::ostream& os, const Nom& nom) ++{ ++ nom.write(os); ++ return os; ++} ++ +diff --git a/databases/readers/Lata/Motcle.h b/databases/readers/Lata/Motcle.h +new file mode 100644 +index 0000000..e1a992d +--- /dev/null ++++ b/databases/readers/Lata/Motcle.h +@@ -0,0 +1,150 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef LataMotcle_H ++#define LataMotcle_H ++#include ++#include ++#include ++#include ++// pour gcc 2.96: ++#include ++ ++class Motcle; ++ ++class Nom ++{ ++public: ++ Nom() ++ { ++ s_ = "??"; ++ }; ++ ++ ++ ++ Nom(std::string str) ++ { ++ s_ = str; ++ } ++ ++ inline const std::string& getString() const { return s_; } ++ ++ virtual ~Nom() { }; ++ Nom(const char * nom) : s_(nom) { }; ++ Nom(char c) ++ { ++ s_ = c; ++ }; ++ Nom(int i) ++ { ++ char s[30]; ++ sprintf(s, "%d", i); ++ s_ = s; ++ } ++ operator const char *() const ++ { ++ return s_.c_str(); ++ } ++ virtual Nom& operator=(const char * nom) ++ { ++ s_ = nom; ++ return *this; ++ } ++ virtual entier longueur() const ++ { ++ return static_cast(s_.length())+1; /*ATTENTION: +1 pour compatibilite avec TRUST*/ ++ } ++ virtual void read(std::istream& is) ++ { ++ is >> s_; ++ } ++ virtual void write(std::ostream& os) const ++ { ++ os << s_; ++ } ++ virtual int operator==(const char * s) const ++ { ++ return (s_ == s); ++ } ++ virtual int operator!=(const char * s) const ++ { ++ return !operator==(s); ++ } ++ virtual Nom& operator+=(const char * n) ++ { ++ s_ += n; ++ return *this; ++ } ++ virtual entier find(const char * n) const; ++ virtual int debute_par(const char * s) const; ++ virtual int finit_par(const char * s) const; ++ virtual Nom& prefix(const char * s); ++ Nom& majuscule(); ++protected: ++ friend class Motcle; ++ std::string s_; ++}; ++ ++class Motcle : public Nom ++{ ++public: ++ Motcle() {}; ++ Motcle(const char * s) : Nom(s) {}; ++ Motcle(const Nom& n) : Nom(n) {}; ++ ~Motcle() {}; ++ int operator==(const char * s) const ++ { ++ return (strcmp_uppercase(s_.c_str(), s) == 0); ++ } ++ int operator!=(const char * s) const ++ { ++ return !operator==(s); ++ } ++ Motcle& operator+=(const char * n) ++ { ++ s_ += n; ++ return *this; ++ } ++ int debute_par(const char * s) const; ++ int finit_par(const char * s) const; ++ ++ static int strcmp_uppercase(const char * s1, const char * s2, int opt = 0); ++ virtual entier find(const char * n) const ++ { ++ return Nom(*this).majuscule().find(Nom(n).majuscule()); ++ } ++}; ++ ++typedef LataVector Motcles; ++typedef LataVector Noms; ++ ++std::istream& operator>>(std::istream& is, Nom& nom); ++std::ostream& operator<<(std::ostream& os, const Nom& nom); ++ ++#endif +diff --git a/databases/readers/Lata/Noms.h b/databases/readers/Lata/Noms.h +new file mode 100644 +index 0000000..d9231d2 +--- /dev/null ++++ b/databases/readers/Lata/Noms.h +@@ -0,0 +1,29 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ +diff --git a/databases/readers/Lata/Objet_U.h b/databases/readers/Lata/Objet_U.h +new file mode 100644 +index 0000000..1f63425 +--- /dev/null ++++ b/databases/readers/Lata/Objet_U.h +@@ -0,0 +1,41 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++// Class declared for compatibility with TRUST ++#ifndef Objet_U_inclu ++#define Objet_U_inclu ++#include ++#include ++#include ++#include ++ ++#define Cerr Journal() ++#define finl std::endl ++ ++#endif +diff --git a/databases/readers/Lata/Octree_Double.C b/databases/readers/Lata/Octree_Double.C +new file mode 100644 +index 0000000..f7cb229 +--- /dev/null ++++ b/databases/readers/Lata/Octree_Double.C +@@ -0,0 +1,395 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++#include ++ ++Octree_Double::Octree_Double() ++{ ++ dim_ = 0; ++} ++ ++void Octree_Double::reset() ++{ ++ dim_ = 0; ++ octree_int_.reset(); ++ origin_.reset(); ++ factor_.reset(); ++} ++ ++// Description: Convertit une coordonnees reele en coordonnee entiere pour l'octree_int ++// Valeur de retour: 1 si ok, 0 si coordonnee hors de l'octree ++inline entier Octree_Double::integer_position(double x, entier direction, entier& ix) const ++{ ++ const double coord_max = (double) Octree_Int::coord_max_; ++ double rnd_x = (x - origin_[direction]) * factor_[direction]; ++ // 0.49 permet d'accepter une coordonnee x egale a xmin ou xmax de l'octree, ++ // sinon pour un octree cree a partir de sommets, il y a un risque ++ // de ne pas trouver les coordonnees des points qu'on avait mis au bord de l'octree. ++ if (rnd_x >= -0.49 && rnd_x <= coord_max + 0.49) ++ { ++ ix = (entier) floor(rnd_x + 0.5); ++ return 1; ++ } ++ return 0; ++} ++ ++// Valeur de retour: 1 s'il y a une intersection non vide avec l'octree, 0 sinon ++inline entier Octree_Double::integer_position_clip(double xmin, double xmax, ++ entier& x0, entier& x1, ++ entier direction) const ++{ ++ const double coord_max = (double) Octree_Int::coord_max_; ++ xmin = (xmin - origin_[direction]) * factor_[direction]; ++ xmax = (xmax - origin_[direction]) * factor_[direction]; ++ // pas de marge ici comme on cherche avec une boite, l'epsilon est deja ++ // dans la dimension de la boite. ++ if (xmin > coord_max || xmax < 0.) ++ return 0; ++ if (xmin < .0) ++ x0 = 0; ++ else ++ x0 = (entier) (floor(xmin+0.5)); ++ if (xmax > coord_max) ++ x1 = Octree_Int::coord_max_; ++ else ++ x1 = (entier) (floor(xmax+0.5)); ++ return 1; ++} ++ ++// Description: cherche les elements ou les points contenus dans l'octree_floor qui ++// contient le point (x,y,z). Renvoie le nombre n de ces elements. ++// Les indices des elements sont dans floor_elements()[index+i] pour 0 <= i < n ++entier Octree_Double::search_elements(double x, double y, double z, entier& index) const ++{ ++ if (dim_ == 0) ++ return 0; // octree vide ++ entier ix = 0, iy = 0, iz = 0; ++ entier ok = integer_position(x, 0, ix) ++ && integer_position(y, 1, iy) ++ && integer_position(z, 2, iz); ++ if (ok) ++ { ++ return octree_int_.search_elements(ix, iy, iz, index); ++ } ++ else ++ { ++ return 0; ++ } ++} ++ ++// Description: methode outil pour build_nodes et build_elements ++// (calcul des facteurs de conversion entre reels et entiers pour Octree_Int ++void Octree_Double::compute_origin_factors(const DoubleTab& coords, ++ const double epsilon, ++ const entier include_virtual) ++{ ++ // Recherche des coordonnees min et max du domaine ++ const entier nb_som = include_virtual ? coords.dimension_tot(0) : coords.dimension(0); ++ if (nb_som == 0) ++ return; // octree vide ++ ++ const entier dim = coords.dimension(1); ++ dim_ = dim; ++ origin_.resize_array(3); ++ factor_.resize_array(3); ++ ArrOfDouble xmin(dim, 1.e37); ++ ArrOfDouble xmax(dim, -1.e-37); ++ assert(dim >= 1 && dim <= 3); ++ entier i, j; ++ for (i = 0; i < nb_som; i++) ++ { ++ for (j = 0; j < dim; j++) ++ { ++ const double x = coords(i, j); ++ if (x < xmin[j]) ++ xmin[j] = x; ++ if (x > xmax[j]) ++ xmax[j] = x; ++ } ++ } ++ const double coord_max = (double) Octree_Int::coord_max_; ++ for (j = 0; j < dim; j++) ++ { ++ xmin[j] -= epsilon; ++ xmax[j] += epsilon; ++ origin_[j] = xmin[j]; ++ if (xmax[j] - xmin[j] > 0.) ++ { ++ factor_[j] = coord_max / (xmax[j] - xmin[j]); ++ } ++ else ++ factor_[j] = 0.; ++ } ++} ++void Octree_Double::compute_origin_factors(const FloatTab& coords, ++ const double epsilon, ++ const entier include_virtual) ++{ ++ // Recherche des coordonnees min et max du domaine ++ const entier nb_som = include_virtual ? coords.dimension_tot(0) : coords.dimension(0); ++ if (nb_som == 0) ++ return; // octree vide ++ ++ const entier dim = coords.dimension(1); ++ dim_ = dim; ++ origin_.resize_array(3); ++ factor_.resize_array(3); ++ ArrOfDouble xmin(dim, 1.e37); ++ ArrOfDouble xmax(dim, -1.e-37); ++ assert(dim >= 1 && dim <= 3); ++ entier i, j; ++ for (i = 0; i < nb_som; i++) ++ { ++ for (j = 0; j < dim; j++) ++ { ++ const double x = coords(i, j); ++ if (x < xmin[j]) ++ xmin[j] = x; ++ if (x > xmax[j]) ++ xmax[j] = x; ++ } ++ } ++ const double coord_max = (double) Octree_Int::coord_max_; ++ for (j = 0; j < dim; j++) ++ { ++ xmin[j] -= epsilon; ++ xmax[j] += epsilon; ++ origin_[j] = xmin[j]; ++ if (xmax[j] - xmin[j] > 0.) ++ { ++ factor_[j] = coord_max / (xmax[j] - xmin[j]); ++ } ++ else ++ factor_[j] = 0.; ++ } ++} ++ ++// Description: construit un octree contenant les points de coordonnees coords. ++// Si include_virtual=1, on stocke coords.dimension_tot(0) elements, sinon on en ++// stocke coords.dimension(0) ++void Octree_Double::build_nodes(const DoubleTab& coords, const entier include_virtual) ++{ ++ octree_int_.reset(); ++ compute_origin_factors(coords, 0. /* epsilon */, include_virtual); ++ const entier nb_som = include_virtual ? coords.dimension_tot(0) : coords.dimension(0); ++ if (nb_som == 0) ++ return; // octree vide ++ const entier dim = coords.dimension(1); ++ IntTab elements_boxes(nb_som, dim); ++ for (entier i = 0; i < nb_som; i++) ++ { ++ for (entier j = 0; j < dim; j++) ++ { ++ entier pos1 = 0; ++ const double x = coords(i, j); ++ if (!integer_position(x, j, pos1)) ++ { ++ Cerr << "Fatal error in octree : integer position outside octree" << finl; ++ throw; ++ } ++ elements_boxes(i, j) = pos1; ++ } ++ } ++ octree_int_.build(dim, elements_boxes); ++} ++ ++// Description: Construit un octree a partir d'elements volumiques decrits par des ++// ensembles de sommets. On stocke dans l'octree les parallelipipdes englobant chaque ++// element (contenant tous les sommets de l'element) plus une marge de epsilon. ++// Si include_virtual=1, on stocke elements.dimension_tot(0) elements, sinon on en ++// stocke elements.dimension(0) ++void Octree_Double::build_elements(const DoubleTab& coords, const IntTab& elements, ++ const double epsilon, const entier include_virtual) ++{ ++ octree_int_.reset(); ++ compute_origin_factors(coords, epsilon, include_virtual); ++ ++ const entier nb_elems = include_virtual ? elements.dimension_tot(0) : elements.dimension(0); ++ const entier nb_som_elem = elements.dimension(1); ++ const entier dim = coords.dimension(1); ++ IntTab elements_boxes(nb_elems, dim * 2); ++ for (entier i = 0; i < nb_elems; i++) ++ { ++ for (entier j = 0; j < dim; j++) ++ { ++ double xmin = 1.e37; ++ double xmax = -1.e37; ++ for (entier k = 0; k < nb_som_elem; k++) ++ { ++ const entier som = elements(i, k); ++ if (som>=0) { // polyedre som peut valoir -1 ++ const double x = coords(som, j); ++ xmin = (xxmax) ? x : xmax; ++ } ++ } ++ entier pos1 = 0, pos2 = 0; ++ if (!integer_position(xmin, j, pos1) || !integer_position(xmax, j, pos2)) ++ { ++ Cerr << "Fatal error in octree : integer position outside octree" << finl; ++ throw; ++ } ++ elements_boxes(i, j) = pos1; ++ elements_boxes(i, j+dim) = pos2; ++ } ++ } ++ octree_int_.build(dim, elements_boxes); ++} ++ ++void Octree_Double::build_elements(const FloatTab& coords, const IntTab& elements, ++ const double epsilon, const entier include_virtual) ++{ ++ octree_int_.reset(); ++ compute_origin_factors(coords, epsilon, include_virtual); ++ ++ const entier nb_elems = include_virtual ? elements.dimension_tot(0) : elements.dimension(0); ++ const entier nb_som_elem = elements.dimension(1); ++ const entier dim = coords.dimension(1); ++ IntTab elements_boxes(nb_elems, dim * 2); ++ for (entier i = 0; i < nb_elems; i++) ++ { ++ for (entier j = 0; j < dim; j++) ++ { ++ double xmin = 1.e37; ++ double xmax = -1.e37; ++ for (entier k = 0; k < nb_som_elem; k++) ++ { ++ const entier som = elements(i, k); ++ if (som>=0) { // polyedre som peut valoir -1 ++ const double x = coords(som, j); ++ xmin = (xxmax) ? x : xmax; ++ } ++ } ++ entier pos1 = 0, pos2 = 0; ++ if (!integer_position(xmin, j, pos1) || !integer_position(xmax, j, pos2)) ++ { ++ Cerr << "Fatal error in octree : integer position outside octree" << finl; ++ throw; ++ } ++ elements_boxes(i, j) = pos1; ++ elements_boxes(i, j+dim) = pos2; ++ } ++ } ++ octree_int_.build(dim, elements_boxes); ++} ++ ++// Description: cherche tous les elements ou points ayant potentiellement une intersection ++// non vide avec la boite donnee. ++entier Octree_Double::search_elements_box(double xmin, double ymin, double zmin, ++ double xmax, double ymax, double zmax, ++ ArrOfInt& elements) const ++{ ++ const entier dim = dim_; ++ if (dim == 0) ++ { ++ elements.resize_array(0); ++ return 0; ++ } ++ entier x0 = 0, x1 = 0, y0 = 0, y1 = 0, z0 = 0, z1 = 0; ++ entier ok = integer_position_clip(xmin, xmax, x0, x1, 0); ++ if (ok && dim >= 1) ++ { ++ ok = integer_position_clip(ymin, ymax, y0, y1, 1); ++ if (ok && dim >= 2) ++ ok = integer_position_clip(zmin, zmax, z0, z1, 2); ++ } ++ if (ok) ++ octree_int_.search_elements_box(x0, y0, z0, x1, y1, z1, elements); ++ else ++ elements.resize_array(0); ++ return elements.size_array(); ++} ++ ++// Description: cherche tous les elements ou points ayant potentiellement une intersection ++// non vide avec la boite donnee (centre + ou - radius dans chaque direction) ++entier Octree_Double::search_elements_box(const ArrOfDouble& center, const double radius, ++ ArrOfInt& elements) const ++{ ++ entier dim = center.size_array(); ++ double x = center[0]; ++ double y = (dim>=2) ? center[1] : 0.; ++ double z = (dim>2) ? center[2] : 0.; ++ entier i = search_elements_box(x-radius, y-radius, z-radius, ++ x+radius, y+radius, z+radius, ++ elements); ++ return i; ++} ++ ++// Description: Methode hors classe ++// Cherche parmi les sommets de la liste node_list ceux qui sont a une ++// distance inferieure a epsilon du point (x,y,z). node_list contient des indices de ++// sommets dans le tableau coords. La liste des noeuds verifiant le critere est mise ++// dans node_list. On renvoie l'indice dans le tableau coords du sommet le plus proche. ++entier Octree_Double::search_nodes_close_to(double x, double y, double z, ++ const DoubleTab& coords, ArrOfInt& node_list, ++ double epsilon) ++{ ++ const entier n = node_list.size_array(); ++ double eps2 = epsilon * epsilon; ++ entier count = 0; ++ const entier dim = coords.dimension(1); ++ double dmin = eps2; ++ entier nearest = -1; ++ for (entier i = 0; i < n; i++) ++ { ++ const entier som = node_list[i]; ++ double dx = x - coords(som, 0); ++ double dy = (dim >= 2) ? y - coords(som, 1) : 0.; ++ double dz = (dim >= 3) ? z - coords(som, 2) : 0.; ++ double d2 = dx * dx + dy * dy + dz * dz; ++ if (d2 < eps2) ++ { ++ node_list[count] = som; ++ if (d2 < dmin) ++ { ++ dmin = d2; ++ nearest = som; ++ } ++ count++; ++ } ++ } ++ node_list.resize_array(count); ++ return nearest; ++} ++ ++// Description: Idem que search_nodes_close_to(double x, double y, double z, ...) ++entier Octree_Double::search_nodes_close_to(const ArrOfDouble& point, ++ const DoubleTab& coords, ArrOfInt& node_list, ++ double epsilon) ++{ ++ entier dim = point.size_array(); ++ double x = point[0]; ++ double y = (dim>=2) ? point[1] : 0.; ++ double z = (dim>2) ? point[2] : 0.; ++ entier i = search_nodes_close_to(x, y, z, coords, node_list, epsilon); ++ return i; ++} +diff --git a/databases/readers/Lata/Octree_Double.h b/databases/readers/Lata/Octree_Double.h +new file mode 100644 +index 0000000..abf3258 +--- /dev/null ++++ b/databases/readers/Lata/Octree_Double.h +@@ -0,0 +1,89 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++ ++#ifndef Octree_Double_inclu ++#define Octree_Double_inclu ++#include ++#include ++class DoubleTab; ++class FloatTab; ++ ++// .DESCRIPTION : Un octree permettant de chercher dans l'espace des elements ou des points ++// decrits par des coordonnees reeles. Cet objet est base sur Octree_Int. ++class Octree_Double ++{ ++public: ++ Octree_Double(); ++ void reset(); ++ void build_elements(const FloatTab& coords, const IntTab& elements, ++ const double epsilon, const entier include_virtual); ++ void build_elements(const DoubleTab& coords, const IntTab& elements, ++ const double epsilon, const entier include_virtual); ++ void build_nodes(const DoubleTab& coords, const entier include_virtual); ++ entier search_elements(double x, double y, double z, entier& index) const; ++ entier search_elements_box(double xmin, double ymin, double zmin, ++ double xmax, double ymax, double zmax, ++ ArrOfInt& elements) const; ++ static entier search_nodes_close_to(double x, double y, double z, ++ const DoubleTab& coords, ArrOfInt& node_list, ++ double epsilon); ++ entier search_elements_box(const ArrOfDouble& center, const double radius, ++ ArrOfInt& elements) const; ++ static entier search_nodes_close_to(const ArrOfDouble& point, ++ const DoubleTab& coords, ArrOfInt& node_list, ++ double epsilon); ++ entier dimension() const ++ { ++ assert(dim_ > 0); ++ return dim_; ++ } ++ inline const ArrOfInt& floor_elements() const ++ { ++ return octree_int_.floor_elements(); ++ }; ++protected: ++ inline entier integer_position(double x, entier direction, entier& ix) const; ++ inline entier integer_position_clip(double xmin, double xmax, ++ entier& x0, entier& x1, ++ entier direction) const; ++ void compute_origin_factors(const DoubleTab& coords, ++ const double epsilon, ++ const entier include_virtual); ++ void compute_origin_factors(const FloatTab& coords, ++ const double epsilon, ++ const entier include_virtual); ++ ++ Octree_Int octree_int_; ++ // Ces deux tableaux sont toujours de taille 3 par commodite ++ ArrOfDouble origin_; ++ ArrOfDouble factor_; ++ entier dim_; ++}; ++#endif +diff --git a/databases/readers/Lata/Octree_Int.C b/databases/readers/Lata/Octree_Int.C +new file mode 100644 +index 0000000..4f96b7c +--- /dev/null ++++ b/databases/readers/Lata/Octree_Int.C +@@ -0,0 +1,485 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++ ++static const entier max_levels_ = 32; // 1 de plus que le nombre de bits=1 dans coords_max ++// La valeur suivante doit etre une puissance de deux ++const entier Octree_Int::root_octree_half_width_ = 1073741824; /* 2^30 = 0100 0000 0000 0000 0000 0000 0000 0000b */ ++// La valeur suivante doit etre egale a (root_octree_half_width_ * 2 - 1) ++const entier Octree_Int::coord_max_ = 2147483647; /* 2^31-1 = 0111 1111 1111 1111 1111 1111 1111 1111b */ ++ ++// Description: construction d'un octree_id (voir octree_structure_) ++// Si type==EMPTY, on l'octree_id est 0 ++// Si type==OCTREE, on suppose que index est un indice dans octree_structure_ ++// Si type==FLOOR, on suppose que index est un indice dans floor_elements_ ++inline entier Octree_Int::octree_id(entier index, Octree_Type type) ++{ ++ switch(type) ++ { ++ case EMPTY: ++ return 0; ++ case OCTREE: ++ return index + 1; ++ case FLOOR: ++ return - index - 1; ++ } ++ return -1; ++} ++ ++// Description: calcul de l'index de l'octree dans octree_structure ou floor_elements ++// en fonction du type de l'octree et de son octree_id. ++// En general on a deja determine le type avant, on le passe en parametre pour optimiser. ++inline entier Octree_Int::octree_index(entier octree_id, Octree_Type type) ++{ ++ assert(type==octree_type(octree_id)); ++ switch(type) ++ { ++ case EMPTY: ++ return -1; ++ case OCTREE: ++ return octree_id - 1; ++ case FLOOR: ++ return - octree_id - 1; ++ } ++ return -1; ++} ++ ++// Description: Renvoie le type d'un octree en fonction de son octree_id. ++inline Octree_Int::Octree_Type Octree_Int::octree_type(entier octree_id) ++{ ++ if (octree_id > 0) ++ return OCTREE; ++ else if (octree_id == 0) ++ return EMPTY; ++ else ++ return FLOOR; ++} ++ ++// Description: construction de l'octree. On donne la dimension (1, 2 ou 3) ++// et un tableau d'elements a stocker dans l'octree. Deux possibilites: ++// 1) les elements sont ponctuels si elements_boxes.dimension(1) == dimension. ++// Dans ce cas, chaque element se trouve dans un et un seul octree_floor ++// 2) les elements sont des parallelipipedes, si elements_boxes.dimension(1) == dimension*2 ++// Les "dimension" premieres colonnes sont les coordonnees inferieures, ++// les "dimension" suivantes sont les coordonnees superieures. ++// Un parallelipipede peut etre affecte a plusieurs octree_floor. ++// Les coordonnees stockees dans elements_boxes peuvent aller de 0 a coord_max_ inclus. ++// Il vaut mieux utiliser toute la plage des entiers en multipliant par un facteur adequat. ++void Octree_Int::build(const entier dimension, const IntTab& elements_boxes) ++{ ++ assert(dimension >= 1 && dimension <= 3); ++ assert(elements_boxes.dimension(1) == dimension ++ || elements_boxes.dimension(1) == dimension * 2 ); ++ ++ const entier nb_elems = elements_boxes.dimension(0); ++ nb_elements_ = nb_elems; ++ entier i; ++ octree_structure_.set_smart_resize(1); ++ floor_elements_.set_smart_resize(1); ++ floor_elements_.resize_array(0); ++ const entier nb_octrees = 1 << dimension; ++ octree_structure_.resize(0, nb_octrees); ++ ++ assert(elements_boxes.size_array() == 0 ++ || (min_array(elements_boxes) >= 0 && max_array(elements_boxes) <= coord_max_)); ++ ++ VECT(ArrOfInt) tmp_elem_flags(max_levels_); ++ VECT(ArrOfInt) tmp_elem_list(max_levels_); ++ for (i = 0; i < max_levels_; i++) ++ { ++ tmp_elem_flags[i].set_smart_resize(1); ++ tmp_elem_list[i].set_smart_resize(1); ++ } ++ ArrOfInt& elements_list = tmp_elem_list[0]; ++ elements_list.resize_array(nb_elems); ++ for (entier i = 0; i < nb_elems; i++) ++ elements_list[i] = i; ++ ++ root_octree_id_ = build_octree_recursively(root_octree_half_width_,root_octree_half_width_,root_octree_half_width_, ++ root_octree_half_width_, ++ elements_boxes, ++ tmp_elem_list, ++ 0, ++ tmp_elem_flags); ++} ++ ++// Description: renvoie la liste des elements contenant potentiellement le point (x,y,z) ++// On renvoie n=nombre d'elements de la liste et les elements sont dans ++// floor_elements()[index+i] pour 0 <= i < n. ++// En realite on renvoie tous les elements qui ont une intersection non vide avec l'octree_floor ++// contenant le point (x,y,z) ++entier Octree_Int::search_elements(entier x, entier y, entier z, entier& index) const ++{ ++ const entier nb_octrees = octree_structure_.dimension(1); ++ if (nb_octrees == 2) ++ y = 0; // important pour ne pas tomber sur des cubes inexistants ++ if (nb_octrees <= 4) ++ z = 0; // idem ++ assert(x >= 0 && x <= coord_max_); ++ assert(y >= 0 && y <= coord_max_); ++ assert(z >= 0 && z <= coord_max_); ++ ++ const entier octree_id = search_octree_floor(x, y, z); ++ ++ if (octree_type(octree_id) == EMPTY) ++ { ++ return 0; ++ } ++ const entier idx = octree_index(octree_id, FLOOR); ++ const entier n = floor_elements_[idx]; ++ index = idx + 1; ++ return n; ++} ++ ++struct IntBoxData ++{ ++ IntBoxData(entier xmin, entier ymin, entier zmin, ++ entier xmax, entier ymax, entier zmax, ++ ArrOfInt& elements, ++ ArrOfBit *markers) : ++ xmin_(xmin), ymin_(ymin), zmin_(zmin), ++ xmax_(xmax), ymax_(ymax), zmax_(zmax), ++ elements_(elements), ++ markers_(markers) { }; ++ entier xmin_, ymin_, zmin_; ++ entier xmax_, ymax_, zmax_; ++ ArrOfInt& elements_; ++ ArrOfBit *markers_; ++}; ++ ++// Description: cherche les elements ayant potentiellement une intersection non vide avec la ++// boite xmin..zmax. Le tableau elements doit etre de type smart_resize(1). ++// Les elements peuvent apparaitre plusieurs fois dans le tableau "elements" ++entier Octree_Int::search_elements_box(entier xmin, entier ymin, entier zmin, ++ entier xmax, entier ymax, entier zmax, ++ ArrOfInt& elements) const ++{ ++ const entier nb_octrees = octree_structure_.dimension(1); ++ if (nb_octrees == 2) ++ ymin = ymax = 0; // important pour ne pas tomber sur des cubes inexistants ++ if (nb_octrees <= 4) ++ zmin = zmax = 0; // idem ++ assert(xmin >= 0 && xmin <= coord_max_); ++ assert(ymin >= 0 && ymin <= coord_max_); ++ assert(zmin >= 0 && zmin <= coord_max_); ++ assert(xmax >= 0 && xmax <= coord_max_); ++ assert(ymax >= 0 && ymax <= coord_max_); ++ assert(zmax >= 0 && zmax <= coord_max_); ++ ++ elements.resize_array(0); ++ IntBoxData boxdata(xmin, ymin, zmin, xmax, ymax, zmax, elements, 0); ++ switch(octree_type(root_octree_id_)) ++ { ++ case FLOOR: ++ search_elements_box_floor(boxdata, root_octree_id_); ++ break; ++ case OCTREE: ++ search_elements_box_recursively(boxdata, root_octree_id_, ++ root_octree_half_width_,root_octree_half_width_,root_octree_half_width_, ++ root_octree_half_width_); ++ break; ++ case EMPTY: ++ break; ++ } ++ const entier n = elements.size_array(); ++ return n; ++} ++ ++// Description: ajoute des elements de l'octree_floor a boxdata.elements_ ++void Octree_Int::search_elements_box_floor(IntBoxData& boxdata, ++ entier octree_floor_id) const ++{ ++ const entier idx = octree_index(octree_floor_id, FLOOR); ++ const entier n = floor_elements_[idx]; ++ if (boxdata.markers_) ++ for (entier i = 0; i < n; i++) ++ { ++ const entier elem = floor_elements_[idx+1+i]; ++ if (!boxdata.markers_->testsetbit(elem)) ++ boxdata.elements_.append_array(elem); ++ } ++ else ++ for (entier i = 0; i < n; i++) ++ { ++ const entier elem = floor_elements_[idx+1+i]; ++ boxdata.elements_.append_array(elem); ++ } ++} ++ ++// Pour chaque direction, drapeaux des cubes de la rangee inferieure ++static entier sub_cube_flags_min[3] = { 1+4+16+64, /* drapeaux des cubes 0,2,4,6 */ ++ 1+2+16+32, /* drapeaux des cubes 0,1,4,5 */ ++ 1+2+4+8 /* drapeaux des cubes 0,1,2,3 */ ++ }; ++static entier sub_cube_flags_max[3] = { 2+8+32+128, /* drapeaux des cubes 1,3,5,7 */ ++ 4+8+64+128, /* drapeaux des cubes 2,3,7,8 */ ++ 16+32+64+128 /* drapeaux des cubes 4,5,6,7 */ ++ }; ++ ++// Description: cherche recursivement les elements inclus dans la boite ++// boxdata pour l'octree_id donne, de centre cx, cy, cz. ++ ++void Octree_Int::search_elements_box_recursively(IntBoxData& boxdata, ++ entier octree_id, ++ entier cx, entier cy, entier cz, ++ entier half_width) const ++{ ++ entier flags = 255; ++ if (cx > boxdata.xmax_) // les cubes superieurs en x ne sont pas dedans ++ flags &= sub_cube_flags_min[0]; ++ if (cx <= boxdata.xmin_) // les cubes inferieurs ne sont pas dedans ++ flags &= sub_cube_flags_max[0]; ++ if (cy > boxdata.ymax_) ++ flags &= sub_cube_flags_min[1]; ++ if (cy <= boxdata.ymin_) ++ flags &= sub_cube_flags_max[1]; ++ if (cz > boxdata.zmax_) ++ flags &= sub_cube_flags_min[2]; ++ if (cz <= boxdata.zmin_) ++ flags &= sub_cube_flags_max[2]; ++ entier test_flag = 1; ++ const entier idx = octree_index(octree_id, OCTREE); ++ const entier half_width_2 = half_width >> 1; ++ const entier mhalf_width = - half_width_2; ++ entier cx2, cy2, cz2; ++ for (entier i = 0; i < 8; i++, test_flag <<= 1) ++ { ++ if ((flags & test_flag) != 0) ++ { ++ const entier id = octree_structure_(idx, i); ++ switch(octree_type(id)) ++ { ++ case FLOOR: ++ search_elements_box_floor(boxdata, id); ++ break; ++ case OCTREE: ++ cx2 = cx + ((i & 1) ? half_width_2 : mhalf_width); ++ cy2 = cy + ((i & 2) ? half_width_2 : mhalf_width); ++ cz2 = cz + ((i & 4) ? half_width_2 : mhalf_width); ++ search_elements_box_recursively(boxdata, id, ++ cx2, cy2, cz2, ++ half_width_2); ++ break; ++ case EMPTY: ++ break; ++ } ++ } ++ } ++} ++ ++void Octree_Int::reset() ++{ ++ root_octree_id_ = octree_id(0, EMPTY); ++ nb_elements_ = 0; ++ octree_structure_.reset(); ++ floor_elements_.reset(); ++} ++ ++// Description: construit un octree_floor avec la liste d'elements donnee et ++// renvoie l'octree_id de cet octree_floor ++entier Octree_Int::build_octree_floor(const ArrOfInt& elements_list) ++{ ++ const entier nb_elems = elements_list.size_array(); ++ const entier index = floor_elements_.size_array(); ++ floor_elements_.resize_array(index + nb_elems + 1); ++ floor_elements_[index] = nb_elems; ++ for (entier i = 0; i < nb_elems; i++) ++ floor_elements_[index + 1 + i] = elements_list[i]; ++ return octree_id(index, FLOOR); ++} ++ ++// Description: ++// octree_center_i est le premier entier de la moitie superieure de l'octree dans la direction i. ++// octree_half_width est une puissance de 2 egale a octree_center_i-octree_min_i (octree_min_i ++// est le premier entier inclu dans cet octree dans la direction i) ++// Valeur de retour: octree_id de l'octree construit (void octree_structure_) ++entier Octree_Int::build_octree_recursively(const entier octree_center_x, ++ const entier octree_center_y, ++ const entier octree_center_z, ++ const entier octree_half_width, ++ const IntTab& elements_boxes, ++ VECT(ArrOfInt) & vect_elements_list, ++ const entier level, ++ VECT(ArrOfInt) & tmp_elem_flags) ++{ ++ // Criteres d'arret de la subdivision: ++ // Nombre maximal d'elements dans un sous-cube floor ++ static const entier octree_floor_max_elems = 8; ++ // S'il y a beaucoup d'elements dupliques, mais pas trop, et que le nombre d'elements ++ // dans l'octree est superieur a cette valeur, on subdivise quand-meme ++ static const entier octree_duplicate_elements_limit = 32; ++ const ArrOfInt& elements_list = vect_elements_list[level]; ++ // Si le nombre d'elements est inferieur a la limite, on cree un floor_element, ++ // sinon on subdivise ++ const entier nb_elems = elements_list.size_array(); ++ if (nb_elems == 0) ++ return octree_id(0, EMPTY); ++ ++ if (nb_elems < octree_floor_max_elems || octree_half_width == 1 /* dernier niveau */) ++ { ++ const entier octree_id = build_octree_floor(elements_list); ++ return octree_id; ++ } ++ ++ ArrOfInt& elem_flags = tmp_elem_flags[level]; ++ elem_flags.resize_array(0); // Ne pas conserver les anciennes valeurs ++ elem_flags.resize_array(nb_elems); ++ ++ const entier nb_octrees = octree_structure_.dimension(1); ++ assert(nb_octrees == 2 || nb_octrees == 4 || nb_octrees == 8); ++ const entier elem_box_dim = elements_boxes.dimension(1); ++ // Soit elements_boxes contient dimension colonnes, soit dimension*2 ++ const entier box_delta = (elem_box_dim > 3) ? (elem_box_dim >> 1) : 0; ++ // Nombre d'elements stockes en double dans l'octree (a cause des elements a cheval ++ // sur plusieurs sous-octrees) ++ entier nb_duplicate_elements = 0; ++ // On range les elements de la liste dans 8 sous-cubes (remplissage de elem_flags) ++ for (entier i_elem = 0; i_elem < nb_elems; i_elem++) ++ { ++ const entier elem = elements_list[i_elem]; ++ // dir_flag vaut 1 pour la direction x, 2 pour y et 4 pour z ++ entier dir_flag = 1; ++ // sub_cube_flags contient 2^dim drapeaux binaires (1 par sous-cube), ++ // et indique les sous-cubes coupes par l'element ++ entier octree_flags = 255; ++ // dans combien de sous-octree cet element est-il stocke ? ++ entier nb_duplicates = 1; ++ ++ for (entier direction = 0; direction < 3; direction++) ++ { ++ const entier elem_min = elements_boxes(elem, direction); ++ const entier elem_max = elements_boxes(elem, box_delta+direction); ++ assert(elem_max >= elem_min); ++ // coordonnee du centre du cube dans la direction j: ++ const entier center = (direction==0) ? octree_center_x : ((direction==1) ? octree_center_y : octree_center_z); ++ // L'element coupe-t-il la partie inferieure et la partie superieure du cube dans la "direction" ? ++ if (elem_min >= center) // non -> on retire les flags des cubes de la partie inferieure ++ octree_flags &= sub_cube_flags_max[direction]; ++ else if (elem_max < center) // non -> on retire les flags des cubes de la partie superieure ++ octree_flags &= sub_cube_flags_min[direction]; ++ else ++ nb_duplicates <<= 1; // l'element coupe les deux parties ! ++ dir_flag = dir_flag << 1; ++ if (dir_flag == nb_octrees) ++ break; ++ } ++ elem_flags[i_elem] = octree_flags; ++ nb_duplicate_elements += nb_duplicates - 1; ++ } ++ ++ // Critere un peu complique : s'il y a vraiment beaucoup d'elements ++ // dans cet octree, on autorise jusqu'a dupliquer tous les elements, ++ // ce qui permet de ranger des elements tres alonges qui sont forcement ++ // dupliques dans une direction (>octree_duplicate_elements_limit). ++ if ((nb_duplicate_elements * 2 >= nb_elems && nb_elems < octree_duplicate_elements_limit) ++ || nb_duplicate_elements > nb_elems) ++ { ++ const entier octree_id = build_octree_floor(elements_list); ++ // On renvoie un index d'octreefloor ++ return octree_id; ++ } ++ ++ // On reserve une case a la fin de octree_structure pour stocker cet octree: ++ const entier index_octree = octree_structure_.dimension(0); ++ octree_structure_.resize(index_octree + 1, nb_octrees); ++ ArrOfInt& new_liste_elems = vect_elements_list[level+1]; ++ new_liste_elems.resize_array(0); ++ const entier width = octree_half_width >> 1; ++ const entier m_width = - width; ++ // Traitement recursif des sous-cubes de l'octree: ++ entier i_cube; ++ for (i_cube = 0; i_cube < nb_octrees; i_cube++) ++ { ++ const entier octree_flag = 1 << i_cube; ++ new_liste_elems.resize_array(0); // ne pas conserver les anciennes valeurs ++ new_liste_elems.resize_array(nb_elems); ++ entier count = 0; ++ // Liste des elements inclus dans le sous-cube: ++ for (entier i_elem = 0; i_elem < nb_elems; i_elem++) ++ if ((elem_flags[i_elem] & octree_flag) != 0) ++ new_liste_elems[count++] = elements_list[i_elem]; ++ new_liste_elems.resize_array(count); ++ ++ entier sub_octree_id; ++ if (new_liste_elems.size_array() == 0) ++ { ++ sub_octree_id = octree_id(-1, EMPTY); ++ } ++ else ++ { ++ // Coordonnees du nouveau sous-cube ++ const entier cx = octree_center_x + ((i_cube&1) ? width : m_width); ++ const entier cy = octree_center_y + ((i_cube&2) ? width : m_width); ++ const entier cz = octree_center_z + ((i_cube&4) ? width : m_width); ++ sub_octree_id = build_octree_recursively(cx, cy, cz, width, ++ elements_boxes, ++ vect_elements_list, ++ level+1, ++ tmp_elem_flags); ++ } ++ octree_structure_(index_octree, i_cube) = sub_octree_id; ++ } ++ ++ return octree_id(index_octree, OCTREE); ++} ++ ++// Description: renvoie l'octree_id de l'octree_floor contenant le sommet (x,y,z) ++// (peut renvoyer l'octree EMPTY) ++entier Octree_Int::search_octree_floor(entier x, entier y, entier z) const ++{ ++ if (octree_type(root_octree_id_) != OCTREE) ++ return root_octree_id_; ++ // Le test pour savoir si on est dans la partie superieure ou ++ // inferieure d'un octree au niveau i consiste simplement a tester ++ // le i-ieme bit de la position. ++ entier flag = root_octree_half_width_; ++ ++ entier index = octree_index(root_octree_id_, OCTREE); ++ ++ // Descendre dans la hierarchie d'octree subdivises jusqu'au cube ++ // le plus petit ++ while (1) ++ { ++ // Numero du sous-cube dans lequel se trouve le sommet x,y,z ++ const entier ix = (x & flag) ? 1 : 0; ++ const entier iy = (y & flag) ? 2 : 0; ++ const entier iz = (z & flag) ? 4 : 0; ++ entier i_sous_cube = ix + iy + iz; ++ // On entre dans le sous-cube : ++ const entier octree_id = octree_structure_(index, i_sous_cube); ++ if (octree_type(octree_id) != OCTREE) ++ return octree_id; ++ ++ index = octree_index(octree_id, OCTREE); ++ flag >>= 1; ++ } ++ return -1; // On n'arrive jamais ici ! ++} +diff --git a/databases/readers/Lata/Octree_Int.h b/databases/readers/Lata/Octree_Int.h +new file mode 100644 +index 0000000..ace9c2d +--- /dev/null ++++ b/databases/readers/Lata/Octree_Int.h +@@ -0,0 +1,103 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef Octree_Int_inclus ++#define Octree_Int_inclus ++#include ++#include ++ ++struct IntBoxData; ++class ArrOfBit; ++ ++// .DESCRIPTION : Un octree permettant de retrouver des objets ponctuels ou ++// parallelipipediques dans un espace 1D, 2D ou 3D et des coordonnees entieres ++class Octree_Int ++{ ++public: ++ void build(const entier dimension, const IntTab& elements_boxes); ++ entier search_elements(entier x, entier y, entier z, entier& floor_elements_index) const; ++ entier search_elements_box(entier xmin, entier ymin, entier zmin, ++ entier xmax, entier ymax, entier zmax, ++ ArrOfInt& elements) const; ++ void reset(); ++ ++ inline const ArrOfInt& floor_elements() const ++ { ++ return floor_elements_; ++ }; ++ ++ // Le plus grand entier autorise pour les coordonnees (du type 2^n - 1) ++ static const entier coord_max_; ++ // Premier entier de la moitie superieure de l'octree root (si coord_max_=2^n-1, half_width_=2^(n-1)) ++ static const entier root_octree_half_width_; ++protected: ++ entier build_octree_recursively(const entier octree_center_x, const entier octree_center_y, const entier octree_center_z, ++ const entier octree_half_width, ++ const IntTab& elements_boxes, ++ VECT(ArrOfInt) & vect_elements_list, ++ const entier level, ++ VECT(ArrOfInt) & tmp_elem_flags); ++ entier build_octree_floor(const ArrOfInt& elements_list); ++ ++ entier search_octree_floor(entier x_pos, entier y_pos, entier z_pos) const; ++ void search_elements_box_floor(IntBoxData& boxdata, ++ entier octree_floor_id) const; ++ void search_elements_box_recursively(IntBoxData& boxdata, ++ entier octree_id, ++ entier cx, entier cy, entier cz, ++ entier half_width) const; ++ ++ // Un octree peut etre soit vide, soit subdivise en nb_octrees autres octrees, ++ // soit un octree_floor contenant une liste d'elements. ++ enum Octree_Type { EMPTY, OCTREE, FLOOR }; ++ ++ static inline entier octree_id(entier index, Octree_Type type); ++ static inline entier octree_index(entier octree_id, Octree_Type type); ++ static inline Octree_Type octree_type(entier octree_id); ++ ++ // Octree_id du cube principal : peut etre EMPTY, OCTREE ou FLOOR ++ entier root_octree_id_; ++ // Nombre d'elements stockes (dimension(0) du tableau elements_boxes) ++ entier nb_elements_; ++ // Tableau contenant tous les cubes qui sont divises en sous-cubes ++ // octree_structure_(i, j) decrit le contenu du sous-cube j du cube d'index i. ++ // pour 0 <= j < nombre de sous-cubes par cube. ++ // On appelle "octree_id" une valeur X=octree_structure_(i,j) (identifiant octree) ++ // L'octree id encode a la fois le type de l'octree et l'index ou ++ // il se trouve dans les tableaux (voir octree_id(entier, Octree_Type)) ++ IntTab octree_structure_; ++ ++ // Tableau contenant la liste des elements de chaque sous-cube final non subdivise. ++ // Si X < 0, on note i_debut = -X-1. ++ // floor_elements_(i_debut) = n = nombre d'elements dans ce sous-cube ++ // floor_elements_[i_debut+j] = numero d'un element qui coupe ce sous-cube pour 1 <= j <= n ++ ArrOfInt floor_elements_; ++}; ++ ++#endif +diff --git a/databases/readers/Lata/OpenDXWriter.C b/databases/readers/Lata/OpenDXWriter.C +new file mode 100644 +index 0000000..7add5ed +--- /dev/null ++++ b/databases/readers/Lata/OpenDXWriter.C +@@ -0,0 +1,335 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++ ++class DX_stream; ++ ++class DX_stream ++{ ++public: ++ DX_stream() : os_to_cout_(0), os_(0) {}; ++ void init_cout(int is_ascii) ++ { ++ reset(); ++ os_to_cout_ = 1; ++ ascii_ = is_ascii; ++ os_ = &std::cout; ++ } ++ void init_file(const char *fname, int is_ascii) ++ { ++ reset(); ++ os_to_cout_ = 0; ++ ascii_ = is_ascii; ++ os_ = new std::ofstream(fname); ++ } ++ ~DX_stream() { reset(); } ++ void reset() ++ { ++ if (!os_to_cout_) ++ delete os_; ++ os_ = 0; ++ os_to_cout_ = 0; ++ } ++ DX_stream & operator<<(const float f) { (*os_) << f; return *this; } ++ DX_stream & operator<<(const int i) { (*os_) << i; return *this; } ++ DX_stream & operator<<(const char * s) { (*os_) << s; return *this; } ++ DX_stream & operator<<(DX_stream & f(DX_stream &)) { return f(*this); } ++ ++ void write(char * ptr, int sz) { os_->write(ptr, sz); } ++ entier ok() { return os_ != 0; } ++ entier ascii() { return ascii_; } ++ std::ostream & stream() { return *os_; } ++protected: ++ int os_to_cout_; ++ int ascii_; ++ std::ostream *os_; ++}; ++ ++DX_stream & endl(DX_stream & os) ++{ ++ os.stream() << std::endl; ++ return os; ++} ++ ++void DX_write_vect(DX_stream & os, int dxobject, const ArrOfFloat & v) ++{ ++ const int places = v.size_array(); ++ os << "object " << dxobject << " class array" << endl; ++ os << "type float rank 1 shape 1 items " << places << " "; ++ ++ if (!os.ascii()) { ++ os << (mymachine_msb ? "msb ieee" : "lsb ieee") << " data follows" << endl; ++ os.write((char*)v.addr(), sizeof(float) * places); ++ } else { ++ os << "ascii data follows" << endl; ++ for (int i=0;iinit_cout(ascii); ++ dx_time_index_ = ++index_counter_; ++ FloatTab t; ++ t.resize(1,1); ++ t(0,0) = time; ++ DX_write_vect(*os_, dx_time_index_, t); ++} ++ ++void OpenDXWriter::init_file(double time, Nom & filename_, int ascii) ++{ ++ reset(); ++ os_->init_file(filename_, ascii); ++ dx_time_index_ = ++index_counter_; ++ FloatTab t; ++ t.resize(1,1); ++ t(0,0) = time; ++ DX_write_vect(*os_, dx_time_index_, t); ++} ++ ++const char * DX_element_name(Domain::Element elem) ++{ ++ switch(elem) { ++ case Domain::line: return "lines"; ++ case Domain::triangle: return "triangles"; ++ case Domain::quadri: return "quads"; ++ case Domain::tetra: return "tetrahedra"; ++ case Domain::hexa: return "cubes"; ++ default: ++ Journal() << "DX_element_name unknown element" << endl; ++ throw OpenDXWriter::DXInternalError; ++ } ++} ++ ++void OpenDXWriter::write_geometry(const Domain & dom) ++{ ++ // Write last geometry and begin a new one ++ finish_geometry(); ++ const DomainUnstructured * dom1 = dynamic_cast(&dom); ++ const DomainIJK * dom2 = dynamic_cast(&dom); ++ DX_stream & os = *os_; ++ if (dom1) { ++ nodes_index_ = ++index_counter_; ++ DX_write_vect(os, nodes_index_, dom1->nodes_); ++ elements_index_ = ++index_counter_; ++ DX_write_vect(os, elements_index_, dom1->elements_); ++ os << "attribute \"element type\" string \"" << DX_element_name(dom.elt_type_) << "\"" << endl; ++ os << "attribute \"ref\" string \"positions\"" << endl; ++ } else if (dom2) { ++ const entier dim = dom.dimension(); ++ ArrOfInt dx_coord_index(dim); ++ for (entier i = 0; i < dim; i++) { ++ dx_coord_index[i] = ++index_counter_; ++ const entier n = dom2->coord_[i].size_array(); ++ FloatTab tmp; ++ tmp.resize(n, 3); ++ for (entier j = 0; j < n; j++) ++ tmp(j, i) = dom2->coord_[i][j]; ++ DX_write_vect(os, dx_coord_index[i], tmp); ++ } ++ nodes_index_ = ++index_counter_; ++ os << "object " << nodes_index_ << " class productarray" << endl; ++ entier i; ++ for (i = dim-1; i >= 0; i--) ++ os << " term " << dx_coord_index[i] << endl; ++ elements_index_ = ++index_counter_; ++ os << "object " << elements_index_ << " class gridconnections counts"; ++ for (i = dim-1; i >= 0; i--) ++ os << " " << dom2->coord_[i].size_array(); ++ os << endl; ++ os << "attribute \"element type\" string \"" << ((dim==2)?"quads":"cubes") << "\"" << endl; ++ os << "attribute \"ref\" string \"positions\"" << endl; ++ const entier n1 = dom2->invalid_positions_.size_array(); ++ if (n1 > 0) { ++ invalid_positions_ = ++index_counter_; ++ IntTab tmp; ++ tmp.resize(n1, 1); ++ ArrOfInt & array = tmp; ++ for (entier ii = 0; ii < n1; ii++) array[ii] = dom2->invalid_positions_[ii]; ++ DX_write_vect(os, invalid_positions_, tmp); ++ os << "attribute \"ref\" string \"positions\"" << endl; ++ } ++#if 0 ++ if (n2 > 0) { ++ IntTab tmp; ++ tmp.resize(n2, 1); ++ ArrOfInt & array = tmp; ++ for (entier i = 0; i < n2; i++) array[i] = dom2->invalid_connections_[i]; ++ DX_write_vect(os, invalid_connections_, tmp); ++ os << "attribute \"ref\" string \"connections\"" << endl; ++ } ++#endif ++ } else { ++ Journal() << "Error OpenDXWriter::write_geometry domain type not supported" << endl; ++ throw DXInternalError; ++ } ++ fields_names_.add(dom.id_.name_); ++} ++ ++void OpenDXWriter::finish_geometry() ++{ ++ if (nodes_index_ >= 0) { ++ index_counter_++; ++ fields_indexes_.append_array(index_counter_); ++ DX_stream & os = *os_; ++ os << "object " << index_counter_ << " class field" << endl; ++ os << " component \"positions\" " << nodes_index_ << endl; ++ os << " component \"connections\" " << elements_index_ << endl; ++ if (invalid_positions_ >= 0) ++ os << " component \"invalid positions\" " << invalid_positions_ << endl; ++ if (invalid_connections_ >= 0) ++ os << " component \"invalid connections\" " << invalid_connections_ << endl; ++ os << " component \"TIME\" " << dx_time_index_ << endl; ++ ++ for (entier i=0; i < components_indexes_.size_array(); i++) ++ os << " component \"" << components_names_[i] << "\" " << components_indexes_[i] << endl; ++ } ++ nodes_index_ = -1; ++ elements_index_ = -1; ++ components_indexes_.resize_array(0); ++ components_indexes_.set_smart_resize(1); ++ components_names_ = Noms(); ++ invalid_positions_ = -1; ++ invalid_connections_ = -1; ++} ++ ++void OpenDXWriter::write_component(const LataField_base & field) ++{ ++ index_counter_++; ++ const Field * int_field = dynamic_cast*>(&field); ++ const Field * float_field = dynamic_cast*>(&field); ++ if (int_field) ++ DX_write_vect(*os_, index_counter_, int_field->data_); ++ else if (float_field) ++ DX_write_vect(*os_, index_counter_, float_field->data_); ++ else { ++ Journal() << "Error OpenDXWriter::write_component: unknown field type" << endl; ++ throw; ++ } ++ if (field.localisation_ == LataField_base::ELEM) ++ (*os_) << "attribute \"dep\" string \"connections\"" << endl; ++ else if (field.localisation_ == LataField_base::SOM) ++ (*os_) << "attribute \"dep\" string \"positions\"" << endl; ++ else ++ { ++ ; // no attribute ++ } ++ components_indexes_.append_array(index_counter_); ++ Nom n = field.id_.uname_.get_field_name(); ++ n += "_"; ++ n += field.id_.uname_.get_localisation(); ++ components_names_.add(n); ++} ++ ++entier OpenDXWriter::finish(int force_group) ++{ ++ DX_stream & os = *os_; ++ finish_geometry(); ++ if (force_group || fields_indexes_.size_array() > 1) { ++ //DX_stream & os = *os_; ++ os << "object " << ++index_counter_ << " class group" << endl; ++ for (entier i = 0; i < fields_indexes_.size_array(); i++) { ++ os << " member \"" << fields_names_[i] << "\" value " << fields_indexes_[i] << endl; ++ } ++ } ++ os << "END" << endl; ++ return index_counter_; ++} +diff --git a/databases/readers/Lata/OpenDXWriter.h b/databases/readers/Lata/OpenDXWriter.h +new file mode 100644 +index 0000000..e8f6358 +--- /dev/null ++++ b/databases/readers/Lata/OpenDXWriter.h +@@ -0,0 +1,83 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef OpenDXWriter_H_ ++#define OpenDXWriter_H_ ++#include ++#include ++ ++class Domain; ++class LataField_base; ++// Usage: ++// init_cout(...) or init_file(...) ++// for (i=0; i < nb_geometries; i++) { ++// write_geometry(...); ++// for (j=0; j < nb_fields; j++) ++// write_component(...); ++// } ++// finish(); ++class DX_stream; ++class OpenDXWriter ++{ ++public: ++ OpenDXWriter(); ++ ~OpenDXWriter(); ++ void init_cout(double time, int ascii = 0); ++ void init_file(double time, Nom & filename_, int ascii = 0); ++ ++ void write_geometry(const Domain & dom); ++ void write_component(const LataField_base & field); ++ ++ entier finish(int force_group = 0); ++ enum DXErrors { DXInternalError }; ++protected: ++ void reset(); ++ void finish_geometry(); ++ ++ int dx_time_index_; ++ int index_counter_; ++ // Indexes of all DXfield objects in the file (to build the final group) ++ ArrOfInt fields_indexes_; ++ // Names of the DXfields: ++ Noms fields_names_; ++ ++ // Index of the nodes array of the last geometry ++ int nodes_index_; ++ // Index of the elements array of the last geometry ++ int elements_index_; ++ // Index of these arrays: ++ int invalid_positions_; ++ int invalid_connections_; ++ // Indexes of the components associated with the last geometry ++ ArrOfInt components_indexes_; ++ Noms components_names_; ++ ++ DX_stream * os_; ++}; ++#endif +diff --git a/databases/readers/Lata/Operator.h b/databases/readers/Lata/Operator.h +new file mode 100644 +index 0000000..2ae94bf +--- /dev/null ++++ b/databases/readers/Lata/Operator.h +@@ -0,0 +1,224 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef OPERATORS_H ++#define OPERATORS_H ++#include ++ ++// A tool to "reconnect" several subdomains of a parallel computation: ++// reconnect_geometry() searches for duplicate node coordinates and ++// changes the elements_ and faces_ arrays to use the smallest node ++// index that has the same coordinate. Hence, we recover the connectivity ++// between blocks. ++class Reconnect ++{ ++public: ++ static void reconnect_geometry(DomainUnstructured & geom, double tolerance, entier nb_nodes_untouched = 0); ++ static void apply_renumbering(const ArrOfInt & nodes_renumber, ArrOfInt & data); ++ static void search_duplicate_nodes(const FloatTab & src_coord, ++ ArrOfInt & nodes_renumber, ++ double eps, ++ entier nb_nodes_untouched = 0); ++}; ++ ++class OperatorClipbox : public Operator ++{ ++public: ++ void build_geometry(const Domain & src_domain, LataDeriv & dest); ++ void build_field(const Domain & src_domain, const LataField_base & src_field, ++ const Domain & dest_domain, LataDeriv & dest); ++ // Renumerotation des sommets, elements et faces par rapport aux donnees brutes lues ++ // renum_truc_[new_index] = index in lata file; ++ // La renumerotation vient de clip_box et de regularize ++ ArrOfInt renum_nodes_; ++ ArrOfInt renum_elements_; ++ ArrOfInt renum_faces_; ++}; ++ ++class OperatorBoundary : public Operator ++{ ++public: ++ OperatorBoundary() { geom_init_ = 0; } ++ void build_geometry(const Domain & src_domain, LataDeriv & dest); ++ void build_field(const Domain & src_domain, const LataField_base & src_field, ++ const Domain & dest_domain, LataDeriv & dest); ++ BigEntier compute_memory_size() const { ++ return ++ memory_size(src_nodes_) ++ + memory_size(src_element_) ++ + memory_size(src_face_); ++ } ++ // Renumerotation des sommets, elements et faces par rapport aux donnees brutes lues ++ // renum_truc_[new_index] = index in lata file; ++ // La renumerotation vient de clip_box et de regularize ++ ArrOfInt src_nodes_; // for each boundary node, which node is it in source domain ? ++ ArrOfInt src_element_; // same for boundary face vs source domain element ++ ArrOfInt src_face_; // local face number on src_element_ ++ entier geom_init_; ++}; ++ ++class OperatorRegularize : public Operator ++{ ++public: ++ OperatorRegularize() { tolerance_ = -1.; geom_init_ = 0; extend_layer_ = 0; } ++ void set_tolerance(double epsilon) { tolerance_ = epsilon; } ++ void set_extend_layer(entier n) { if (n >= 0) extend_layer_ = n; else extend_layer_ = 0; } ++ void build_geometry(const Domain & src_domain, LataDeriv & dest); ++ void build_field(const Domain & src_domain, const LataField_base & src_field, ++ const Domain & dest_domain, LataDeriv & dest); ++ ++ BigEntier compute_memory_size() const { ++ return ++ memory_size(renum_nodes_) ++ + memory_size(renum_elements_) ++ + memory_size(renum_faces_); ++ } ++ // Renumerotation des sommets, elements et faces par rapport aux donnees brutes lues ++ // renum_truc_[old_index] = new_index; ++ ArrOfInt renum_nodes_; ++ ArrOfInt renum_elements_; ++ // Pour les faces: les faces de chaque direction du domaine ijk sont numerotees ++ // separement: faces de normales X entre 0 et N, faces de normales Y entre 0 et N, etc... ++ // Le numero d'une face est egal au plus petit des numeros de ses sommets du le maillage ijk. ++ // Renum faces contient le codage suivant: ++ // numero de la face = renum_faces_[i] >> 2; ++ // direction de la face = (renum_faces_ & 3) ++ ArrOfInt renum_faces_; ++ double tolerance_; ++ entier extend_layer_; ++ entier geom_init_; ++}; ++ ++class OperatorDualMesh : public Operator ++{ ++public: ++ void build_geometry(const Domain & src_domain, LataDeriv & dest); ++ void build_field(const Domain & src_domain, const LataField_base & src_field, ++ const Domain & dest_domain, LataDeriv & dest); ++ BigEntier compute_memory_size() const { return 0; } ++}; ++class OperatorFacesMesh : public Operator ++{ ++public: ++ void build_geometry(const Domain & src_domain, LataDeriv & dest); ++ void build_field(const Domain & src_domain, const LataField_base & src_field, ++ const Domain & dest_domain, LataDeriv & dest); ++ BigEntier compute_memory_size() const { return 0; } ++}; ++ ++class OperatorNCMesh : public Operator ++{ ++public: ++ void build_geometry(const Domain & src_domain, LataDeriv & dest); ++ void build_field(const Domain & src_domain, const LataField_base & src_field, ++ const Domain & dest_domain, LataDeriv & dest); ++ BigEntier compute_memory_size() const { return 0; } ++}; ++ ++// These generic methods just say that the particular function does not exist: ++void build_geometry_(Operator & op, const Domain & src, LataDeriv & dest); ++void build_field_(Operator & op, const Domain & src, const Domain & dest, ++ const LataField_base & srcf, LataField_base & destf); ++ ++template ++void apply_geometry(Op & op, const Domain & src_domain, LataDeriv & dest) ++{ ++ const DomainUnstructured *src1 = dynamic_cast(&src_domain); ++ const DomainIJK *src2 = dynamic_cast(&src_domain); ++ ++ if (src1) { ++ build_geometry_(op, *src1, dest); ++ } else if (src2) { ++ build_geometry_(op, *src2, dest); ++ } else { ++ Journal() << "Error in OperatorDualMesh::build_geometry: unsupported domain type" << endl; ++ throw; ++ } ++} ++ ++// See apply_field ++template ++void apply_field3(Op & op, const DomSrc & src_domain, const LataField_base & src_field, ++ const DomDest & dest_domain, LataDeriv & dest) ++{ ++ const Field *src1 = dynamic_cast*> (&src_field); ++ const Field *src2 = dynamic_cast*> (&src_field); ++ const Field *src3 = dynamic_cast*> (&src_field); ++ ++ if (src1) ++ build_field_(op, src_domain, dest_domain, *src1, dest.instancie(Field )); ++ else if (src2) ++ build_field_(op, src_domain, dest_domain, *src2, dest.instancie(Field )); ++ else if (src3) ++ build_field_(op, src_domain, dest_domain, *src3, dest.instancie(Field )); ++ else { ++ Journal() << "Error in apply_field3: unsupported field type" << endl; ++ throw; ++ } ++} ++ ++// See apply_field ++template ++void apply_field2(Op & op, const DomSrc & src_domain, const LataField_base & src_field, ++ const Domain & dest_domain, LataDeriv & dest) ++{ ++ const DomainUnstructured *d1 = dynamic_cast(&dest_domain); ++ const DomainIJK *d2 = dynamic_cast(&dest_domain); ++ if (d1) ++ apply_field3(op, src_domain, src_field, *d1, dest); ++ else if (d2) ++ apply_field3(op, src_domain, src_field, *d2, dest); ++ else { ++ Journal() << "Error in apply_field2: unsupported destination domain type" << endl; ++ throw; ++ } ++} ++ ++// This template calls the appropriate "build_field_()" method in the given operator. ++// The operator should implement non virtual methods for any usefull combination ++// of source domain type, destination domain type and source field type. This template ++// will call the correct method depending on the effective type of the parameters ++// (determined with dynamic_cast). ++template ++void apply_field(Op & op, const Domain & src_domain, const LataField_base & src_field, ++ const Domain & dest_domain, LataDeriv & dest) ++{ ++ const DomainUnstructured *d1 = dynamic_cast(&src_domain); ++ const DomainIJK *d2 = dynamic_cast(&src_domain); ++ if (d1) ++ apply_field2(op, *d1, src_field, dest_domain, dest); ++ else if (d2) ++ apply_field2(op, *d2, src_field, dest_domain, dest); ++ else { ++ Journal() << "Error in apply_field: unsupported source domain type" << endl; ++ throw; ++ } ++} ++ ++#endif +diff --git a/databases/readers/Lata/OperatorBoundary.C b/databases/readers/Lata/OperatorBoundary.C +new file mode 100644 +index 0000000..1e10d1a +--- /dev/null ++++ b/databases/readers/Lata/OperatorBoundary.C +@@ -0,0 +1,227 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++ ++// Journal level for messages ++#define verb_level 4 ++ ++void build_ref_elem_face(const Domain::Element elt_type, IntTab & ref_elem_face) ++{ ++ static entier faces_sommets_tetra[4][3] = ++ { { 1, 2, 3 }, ++ { 0, 3, 2 }, ++ { 3, 0, 1 }, ++ { 0, 2, 1 } }; ++ static entier faces_sommets_hexa[6][4] = ++ { { 0, 2, 4, 6 }, ++ { 0, 1, 4, 5 }, ++ { 0, 1, 2, 3 }, ++ { 1, 3, 5, 7 }, ++ { 2, 3, 6, 7 }, ++ { 4, 5, 6, 7 } }; ++ ++ int i, j; ++ switch(elt_type) { ++ case Domain::tetra: ++ ref_elem_face.resize(4,3); ++ for(i=0;i<4;i++) ++ for(j=0;j<3;j++) ++ ref_elem_face(i,j) = faces_sommets_tetra[i][j]; ++ break; ++ case Domain::hexa: ++ ref_elem_face.resize(6,4); ++ for(i=0;i<6;i++) ++ for(j=0;j<4;j++) ++ ref_elem_face(i,j) = faces_sommets_hexa[i][j]; ++ break; ++ default: ++ Journal() << "build_ref_elem_face : non code pour element " ++ << endl; ++ } ++} ++ ++void build_geometry_(OperatorBoundary & op, ++ const DomainUnstructured & src, LataDeriv & dest_domain) ++{ ++ Journal(verb_level) << "OperatorBoundary domain " << src.id_.name_ << endl; ++ DomainUnstructured & dest = dest_domain.instancie(DomainUnstructured); ++ switch(src.elt_type_) { ++ case Domain::tetra: dest.elt_type_ = Domain::triangle; break; ++ case Domain::hexa: dest.elt_type_ = Domain::quadri; break; ++ default: ++ Journal() << "Error in OperatorBoundary: element type not supported" << endl; ++ throw; ++ } ++ ++ Static_Int_Lists som_elem; ++ construire_connectivite_som_elem(src.nb_nodes(), src.elements_, som_elem, 0); ++ // For each element: ++ // for each face of this element ++ // how many neighbouring elements ? ++ // if only one neighbour, it's a boundary face ! ++ ++ IntTab element_faces; ++ build_ref_elem_face(src.elt_type_, element_faces); ++ op.src_element_.set_smart_resize(1); ++ op.src_face_.set_smart_resize(1); ++ op.src_nodes_.set_smart_resize(1); ++ const int nb_nodes_per_face = element_faces.dimension(1); ++ const int nb_faces_per_element = element_faces.dimension(0); ++ ++ ArrOfInt one_face(nb_nodes_per_face); ++ ArrOfInt adjacent_elements; ++ ++ // For each node in the source domain, node number on the boundary: ++ ArrOfInt nodes_renumber; ++ nodes_renumber.resize_array(src.nb_nodes()); ++ nodes_renumber = -1; ++ ++ entier element_index, local_face_index; ++ // Browse only real elements (so we don't see boundaries between processors) ++ const entier nelem = src.nb_elements() - src.nb_virt_items(LataField_base::ELEM); ++ entier i; ++ entier count = 0; ++ for (element_index = 0; element_index < nelem; element_index++) { ++ for (local_face_index = 0; local_face_index < nb_faces_per_element; local_face_index++) { ++ for (i = 0; i < nb_nodes_per_face; i++) { ++ int local_node = element_faces(local_face_index, i); ++ int node = src.elements_(element_index, local_node); ++ one_face[i] = node; ++ } ++ find_adjacent_elements(som_elem, one_face, adjacent_elements); ++ if (adjacent_elements.size_array() == 1) { ++ op.src_element_.append_array(element_index); ++ op.src_face_.append_array(local_face_index); ++ for (i = 0; i < nb_nodes_per_face; i++) { ++ const entier node = one_face[i]; ++ entier dest_node = nodes_renumber[node]; ++ if (dest_node < 0) { ++ dest_node = count++; ++ op.src_nodes_.append_array(node); ++ nodes_renumber[node] = dest_node; ++ } ++ } ++ } ++ } ++ } ++ ++ // Build nodes ++ const entier nb_nodes = op.src_nodes_.size_array(); ++ const entier dim = src.nodes_.dimension(1); ++ dest.nodes_.resize(nb_nodes, dim); ++ for (i = 0; i < nb_nodes; i++) { ++ const entier n = op.src_nodes_[i]; ++ for (entier j = 0; j < dim; j++) ++ dest.nodes_(i, j) = src.nodes_(n, j); ++ } ++ ++ // Build elements ++ const entier nb_elems = op.src_element_.size_array(); ++ dest.elements_.resize(nb_elems, nb_nodes_per_face); ++ for (i = 0; i < nb_elems; i++) { ++ const entier elem = op.src_element_[i]; ++ const entier face = op.src_face_[i]; ++ for (entier j = 0; j < nb_nodes_per_face; j++) { ++ const entier src_node = src.elements_(elem, element_faces(face, j)); ++ dest.elements_(i, j) = nodes_renumber[src_node]; ++ } ++ } ++ op.geom_init_ = 1; ++} ++ ++template ++void build_field_(OperatorBoundary & op, ++ const DomainUnstructured & src_domain, ++ const DomainUnstructured & dest_domain, ++ const Field & src, ++ Field & dest) ++{ ++ if (!op.geom_init_) { ++ // Must fill the renum_.... arrays first ! ++ LataDeriv destb; ++ op.build_geometry(src_domain, destb); ++ } ++ dest.component_names_ = src.component_names_; ++ dest.localisation_ = src.localisation_; ++ dest.nature_ = src.nature_; ++ if (dest.localisation_ == LataField_base::FACES) ++ dest.localisation_ = LataField_base::ELEM; ++ ++ const entier nb_compo = src.data_.dimension(1); ++ entier i, sz = 0; ++ switch(src.localisation_) { ++ case LataField_base::ELEM: ++ sz = dest_domain.nb_elements(); ++ dest.data_.resize(sz, nb_compo); ++ for (i = 0; i < sz; i++) { ++ const entier old_i = op.src_element_[i]; ++ for (entier j = 0; j < nb_compo; j++) ++ dest.data_(i, j) = src.data_(old_i, j); ++ } ++ break; ++ case LataField_base::SOM: ++ sz = dest_domain.nb_nodes(); ++ dest.data_.resize(sz, nb_compo); ++ for (i = 0; i < sz; i++) { ++ const entier old_i = op.src_nodes_[i]; ++ for (entier j = 0; j < nb_compo; j++) ++ dest.data_(i, j) = src.data_(old_i, j); ++ } ++ break; ++ case LataField_base::FACES: ++ sz = dest_domain.nb_elements(); ++ dest.data_.resize(sz, nb_compo); ++ for (i = 0; i < sz; i++) { ++ const entier old_i = src_domain.elem_faces_(op.src_element_[i], op.src_face_[i]); ++ for (entier j = 0; j < nb_compo; j++) ++ dest.data_(i, j) = src.data_(old_i, j); ++ } ++ break; ++ default: ++ Journal() << "Error in OperatorRegularize::build_field_: unknown localisation" << endl; ++ throw; ++ } ++} ++ ++void OperatorBoundary::build_geometry(const Domain & src_domain, LataDeriv & dest) ++{ ++ apply_geometry(*this, src_domain, dest); ++} ++ ++void OperatorBoundary::build_field(const Domain & src_domain, const LataField_base & src_field, ++ const Domain & dest_domain, LataDeriv & dest) ++{ ++ apply_field(*this, src_domain, src_field, dest_domain, dest); ++} ++ ++#undef verb_level +diff --git a/databases/readers/Lata/OperatorDualMesh.C b/databases/readers/Lata/OperatorDualMesh.C +new file mode 100644 +index 0000000..9ecd859 +--- /dev/null ++++ b/databases/readers/Lata/OperatorDualMesh.C +@@ -0,0 +1,222 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++ ++// Journal level ++#define verb_level 4 ++ ++void build_geometry_(OperatorDualMesh & op, ++ const DomainUnstructured & src, LataDeriv & dest_domain) ++{ ++ Journal(verb_level) << "OperatorDualMesh geometry(unstructured) " << src.id_.name_ << endl; ++ if (!src.faces_ok()) { ++ Journal() << "Error in OperatorDualMesh::build_geometry: source domain has no faces data" << endl; ++ throw; ++ } ++ const int max_nb_som_face = 3; // for tetrahedra ++ if (src.elt_type_ != Domain::triangle && src.elt_type_ != Domain::tetra) { ++ Journal() << "Error in OperatorDualMesh::build_geometry: cannot operate on unstructured mesh with this element type" << endl; ++ throw; ++ } ++ const entier nb_som = src.nodes_.dimension(0); ++ const entier nb_elem = src.elem_faces_.dimension(0); // Not elements_, in case elem_faces_ has no virtual data. ++ const entier dim = src.dimension(); ++ ++ DomainUnstructured & dest = dest_domain.instancie(DomainUnstructured); ++ dest.id_ = src.id_; ++ dest.id_.name_ += "_dual"; ++ dest.elt_type_ = src.elt_type_; ++ ++ dest.nodes_ = src.nodes_; ++ dest.nodes_.resize(nb_som + nb_elem, dim); ++ src.compute_cell_center_coordinates(dest.nodes_, nb_som); ++ ++ const entier nb_faces_elem = src.elem_faces_.dimension(1); ++ const entier nb_som_face = src.faces_.dimension(1); ++ const entier nb_som_elem = src.elements_.dimension(1); ++ dest.elements_.resize(nb_elem * nb_faces_elem, nb_som_elem); ++ int index = 0; ++ for (int i = 0; i < nb_elem; i++) { ++ const int central_node = nb_som + i; ++ for (int j = 0; j < nb_faces_elem; j++) { ++ const int face = src.elem_faces_(i, j); ++ dest.elements_(index, 0) = central_node; ++ for (int k = 0; k < loop_max(nb_som_face, max_nb_som_face); k++) { ++ dest.elements_(index, k+1) = src.faces_(face, k); ++ break_loop(k, nb_som_face); ++ } ++ index++; ++ } ++ } ++ const entier nb_elem_virt = src.nb_virt_items(LataField_base::ELEM); ++ dest.set_nb_virt_items(LataField_base::ELEM, nb_elem_virt * nb_faces_elem); ++} ++ ++// Builds a field on the dual domain from the field on the source domain. ++// Source field must be located at faces. ++// (destination field is located at the elements. the value for an element ++// is the value associated to the adjacent face of the source domain). ++template ++void build_field_(OperatorDualMesh & op, ++ const DomainUnstructured & src_domain, ++ const DomainUnstructured & dest_domain, ++ const Field & src, ++ Field & dest) ++{ ++ Journal(verb_level) << "OperatorDualMesh field(unstructured) " << src.id_.uname_ << endl; ++ dest.component_names_ = src.component_names_; ++ dest.localisation_ = LataField_base::ELEM; ++ dest.nature_ = src.nature_; ++ const entier nb_elem = src_domain.elements_.dimension(0); ++ const entier nb_face_elem = src_domain.elem_faces_.dimension(1); ++ const entier nb_comp = src.data_.dimension(1); ++ dest.data_.resize(nb_elem * nb_face_elem, nb_comp); ++ int index = 0; ++ for (int i = 0; i < nb_elem; i++) { ++ for (int j = 0; j < nb_face_elem; j++) { ++ const int face = src_domain.elem_faces_(i, j); ++ for (int k = 0; k < nb_comp; k++) ++ dest.data_(index, k) = src.data_(face, k); ++ index++; ++ } ++ } ++} ++ ++void build_geometry_(OperatorDualMesh & op, ++ const DomainIJK & src, LataDeriv & dest_domain) ++{ ++ Journal(verb_level) << "OperatorDualMesh geometry(ijk) " << src.id_.name_ << endl; ++ if (src.elt_type_ != Domain::quadri && src.elt_type_ != Domain::hexa) { ++ Journal() << "Error in OperatorDualMesh::build_geometry: cannot operate on unstructured mesh with this element type" << endl; ++ throw; ++ } ++ ++ DomainIJK & dest = dest_domain.instancie(DomainIJK); ++ dest.elt_type_ = src.elt_type_; ++ const entier dim = src.dimension(); ++ for (entier i_dim = 0; i_dim < dim; i_dim++) { ++ const ArrOfFloat & c1 = src.coord_[i_dim]; ++ ArrOfFloat & c2 = dest.coord_.add(ArrOfFloat()); ++ const int n = c1.size_array() - 1; ++ c2.resize_array(n*2+1); ++ for (int i = 0; i < n; i++) { ++ c2[i*2] = c1[i]; ++ c2[i*2+1] = (c1[i] + c1[i+1]) * 0.5; ++ } ++ c2[n*2] = c1[n]; ++ } ++ ++ if (src.invalid_connections_.size_array() > 0) { ++ dest.invalid_connections_.resize_array(dest.nb_elements()); ++ dest.invalid_connections_ = 0; ++ int index = 0; ++ ++ const entier ni = dest.coord_[0].size_array()-1; ++ const entier nj = dest.coord_[1].size_array()-1; ++ const entier nk = (dim==3) ? (dest.coord_[2].size_array()-1) : 1; ++ const entier ni_src = src.coord_[0].size_array() - 1; ++ const entier nj_src = src.coord_[1].size_array() - 1; ++ for (int k = 0; k < nk; k++) { ++ const int k_src = k / 2; ++ for (int j = 0; j < nj; j++) { ++ const int j_src = j / 2; ++ const int idx_source = (k_src * nj_src + j_src) * ni_src; ++ for (int i = 0; i < ni; i++) { ++ const int idx = idx_source + i / 2; ++ if (src.invalid_connections_[idx]) ++ dest.invalid_connections_.setbit(index); ++ index++; ++ } ++ } ++ } ++ } ++ dest.virtual_layer_begin_ = 2 * src.virtual_layer_begin_; ++ dest.virtual_layer_end_ = 2 * src.virtual_layer_end_; ++} ++#define IJK(i,j,k) (k*nj_ni_src + j*ni_src + i) ++ ++template ++void build_field_(OperatorDualMesh & op, ++ const DomainIJK & src_domain, ++ const DomainIJK & dest_domain, ++ const Field & src, ++ Field & dest) ++{ ++ Journal(verb_level) << "OperatorDualMesh field(ijk) " << src.id_.uname_ << endl; ++ dest.component_names_ = src.component_names_; ++ dest.localisation_ = LataField_base::ELEM; ++ dest.nature_ = LataDBField::VECTOR; ++ const entier dim = src_domain.dimension(); ++ int index = 0; ++ ++ // Loop on destination elements ++ const entier ni = dest_domain.coord_[0].size_array()-1; ++ const entier nj = dest_domain.coord_[1].size_array()-1; ++ const entier nk = (dim==3) ? (dest_domain.coord_[2].size_array()-1) : 1; ++ dest.data_.resize(ni*nj*nk, dim); ++ const entier ni_src = src_domain.coord_[0].size_array(); ++ const entier nj_ni_src = src_domain.coord_[1].size_array() * ni_src; ++ for (int k = 0; k < nk; k++) { ++ const int k2 = k/2; ++ const int k3 = (k+1)/2; ++ for (int j = 0; j < nj; j++) { ++ const int j2 = j/2; ++ const int j3 = (j+1)/2; ++ for (int i = 0; i < ni; i++) { ++ const int i2 = i/2; ++ const int i3 = (i+1)/2; ++ dest.data_(index, 0) = src.data_(IJK(i3,j2,k2), 0); ++ dest.data_(index, 1) = src.data_(IJK(i2,j3,k2), 1); ++ if (dim==3) ++ dest.data_(index, 2) = src.data_(IJK(i2,j2,k3), 2); ++ index++; ++ } ++ } ++ } ++} ++ ++#undef IJK ++ ++void OperatorDualMesh::build_geometry(const Domain & src_domain, LataDeriv & dest) ++{ ++ apply_geometry(*this, src_domain, dest); ++} ++ ++void OperatorDualMesh::build_field(const Domain & src_domain, const LataField_base & src_field, ++ const Domain & dest_domain, LataDeriv & dest) ++{ ++ if (src_field.localisation_ != LataField_base::FACES) { ++ Journal() << "Error in OperatorDualMesh::build_field: source field is not located at faces" << endl; ++ throw; ++ } ++ apply_field(*this, src_domain, src_field, dest_domain, dest); ++} ++#undef level +diff --git a/databases/readers/Lata/OperatorFacesMesh.C b/databases/readers/Lata/OperatorFacesMesh.C +new file mode 100644 +index 0000000..6aa85a5 +--- /dev/null ++++ b/databases/readers/Lata/OperatorFacesMesh.C +@@ -0,0 +1,130 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++ ++// Journal level ++#define verb_level 4 ++ ++void build_geometry_(OperatorFacesMesh & op, ++ const DomainUnstructured & src, LataDeriv & dest_domain) ++{ ++ Journal(verb_level) << "OperatorFacesMesh geometry(unstructured) " << src.id_.name_ << endl; ++ if (!src.faces_ok()) { ++ Journal() << "Error in OperatorFacesMesh::build_geometry: source domain has no faces data" << endl; ++ throw; ++ } ++ // const int max_nb_som_face = 3; // for tetrahedra ++ if (src.elt_type_ != Domain::triangle && src.elt_type_ != Domain::polygone && src.elt_type_ != Domain::tetra && src.elt_type_ != Domain::polyedre) { ++ Journal() << "Error in OperatorFacesMesh::build_geometry: cannot operate on unstructured mesh with this element type" << endl; ++ throw; ++ } ++ // const entier nb_som = src.nodes_.dimension(0); ++ // const entier nb_elem = src.elem_faces_.dimension(0); // Not elements_, in case elem_faces_ has no virtual data. ++ //const entier dim = src.dimension(); ++ ++ DomainUnstructured & dest = dest_domain.instancie(DomainUnstructured); ++ dest.id_ = src.id_; ++ dest.id_.name_ += "_centerfaces"; ++ if (src.elt_type_ == Domain::triangle || src.elt_type_ == Domain::polygone) ++ dest.elt_type_=Domain::line; ++ else if ( src.elt_type_ == Domain::tetra) ++ dest.elt_type_=Domain::triangle; ++ else if ( src.elt_type_ == Domain::polyedre) ++ dest.elt_type_=Domain::polygone; ++ ++ dest.nodes_ = src.nodes_; ++ dest.elements_ = src.faces_; ++ ++ ++ ++ ++ const entier nb_elem_virt = src.nb_virt_items(LataField_base::FACES); ++ dest.set_nb_virt_items(LataField_base::ELEM, nb_elem_virt ); ++} ++ ++// Builds a field on the dual domain from the field on the source domain. ++// Source field must be located at faces. ++// (destination field is located at the elements. the value for an element ++// is the value associated to the adjacent face of the source domain). ++template ++void build_field_(OperatorFacesMesh & op, ++ const DomainUnstructured & src_domain, ++ const DomainUnstructured & dest_domain, ++ const Field & src, ++ Field & dest) ++{ ++ Journal(verb_level) << "OperatorFacesMesh field(unstructured) " << src.id_.uname_ << endl; ++ dest.component_names_ = src.component_names_; ++ dest.localisation_ = LataField_base::ELEM; ++ dest.nature_ = src.nature_; ++ ++ dest.data_=src.data_; ++ ++ ++} ++ ++void build_geometry_(OperatorFacesMesh & op, ++ const DomainIJK & src, LataDeriv & dest_domain) ++{ ++ Journal(verb_level) << "OperatorFacesMesh geometry(ijk) " << src.id_.name_ << endl; ++ Journal() << "Error in OperatorFacesMesh::build_geometry: cannot operate on domainIJK" << endl; ++ throw; ++ ++} ++template ++void build_field_(OperatorFacesMesh & op, ++ const DomainIJK & src_domain, ++ const DomainIJK & dest_domain, ++ const Field & src, ++ Field & dest) ++{ ++ Journal(verb_level) << "OperatorFacesMesh field(ijk) " << src.id_.uname_ << endl; ++ Journal() << "Error in OperatorFacesMesh::build_geometry: cannot operate on domainIJK" << endl; ++ throw; ++} ++ ++ ++ ++void OperatorFacesMesh::build_geometry(const Domain & src_domain, LataDeriv & dest) ++{ ++ apply_geometry(*this, src_domain, dest); ++} ++ ++void OperatorFacesMesh::build_field(const Domain & src_domain, const LataField_base & src_field, ++ const Domain & dest_domain, LataDeriv & dest) ++{ ++ if (src_field.localisation_ != LataField_base::FACES) { ++ Journal() << "Error in OperatorFacesMesh::build_field: source field is not located at faces" << endl; ++ throw; ++ } ++ apply_field(*this, src_domain, src_field, dest_domain, dest); ++} ++#undef level +diff --git a/databases/readers/Lata/OperatorReconnect.C b/databases/readers/Lata/OperatorReconnect.C +new file mode 100644 +index 0000000..4cabccc +--- /dev/null ++++ b/databases/readers/Lata/OperatorReconnect.C +@@ -0,0 +1,125 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++ ++#define verb_level 4 ++ ++// Description: Find duplicate coordinates in the "coord" array. ++// nodes_renumber will have dimension src_coord.dimension(0) ++// nodes_renumber[i] = i if the node imust be conserved, ++// nodes_renumber[i] = j if the node i is identical to node j. We always have j1) ? coords(i, 1) : 0.; ++ const double z = (dim>2) ? coords(i, 2) : 0.; ++ octree.search_elements_box(x-eps, y-eps, z-eps, ++ x+eps, y+eps, z+eps, ++ node_list); ++ Octree_Double::search_nodes_close_to(x, y, z, ++ coords, node_list, ++ eps); ++ const entier n = node_list.size_array(); ++ if (n > 1) { ++ for (entier j = 0; j < n; j++) { ++ // Change only nodes with rank > i ++ const entier node = node_list[j]; ++ if (node > j) { ++ nodes_renumber[node] = i; ++ count++; ++ } ++ } ++ } ++ } ++ Journal(verb_level+1) << " " << count << " duplicate nodes will be removed" << endl; ++} ++ ++void Reconnect::apply_renumbering(const ArrOfInt & nodes_renumber, ArrOfInt & data) ++{ ++ entier ntot = data.size_array(); ++ entier i; ++ for (i = 0; i < ntot; i++) { ++ const entier node = data[i]; ++ const entier n = nodes_renumber[node]; ++ if (n != node) ++ data[i] = n; ++ } ++} ++ ++// Description: updates the elements_ and faces_ arrays of the domain so that ++// all nodes having the same coordinates are replaced by one unique node ++// in these arrays. See search_duplicate_nodes for nb_nodes_untouched description. ++void Reconnect::reconnect_geometry(DomainUnstructured & geom, double tolerance, entier nb_nodes_untouched) ++{ ++ Journal(verb_level) << "Reconnect domain " << geom.id_.name_ << endl; ++ ++ ArrOfInt nodes_renumber; ++ search_duplicate_nodes(geom.nodes_, nodes_renumber, tolerance, nb_nodes_untouched); ++ ++ apply_renumbering(nodes_renumber, geom.elements_); ++ ++ if (geom.faces_ok()) ++ apply_renumbering(nodes_renumber, geom.faces_); ++} ++ ++#undef verb_level +diff --git a/databases/readers/Lata/OperatorRegularize.C b/databases/readers/Lata/OperatorRegularize.C +new file mode 100644 +index 0000000..5bbde88 +--- /dev/null ++++ b/databases/readers/Lata/OperatorRegularize.C +@@ -0,0 +1,296 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++ ++#define verb_level 4 ++ ++template int search_in_ordered_vect(T x, const Tab & v, const T epsilon) { ++ if (!v.size_array()) ++ return -1; ++ int i1=0; ++ int i; ++ int i2 = (int)v.size_array()-1; ++ while (i1 != i2) { ++ i = (i1+i2)/2; ++ if (epsilon+ v[i] < x) ++ i1=i+1; ++ else ++ i2=i; ++ } ++ if (v[i1] == x) ++ return i1; ++ if (((v[i1] - x) * (v[i1] - x))<= (epsilon*epsilon) ) ++ return i1; ++ ++ return -1; ++} ++ ++template ++static void retirer_doublons(Tab & tab, const T epsilon) ++{ ++ int i = 0; ++ int j; ++ const int n = tab.size_array(); ++ T last_tab_i = -1e40; ++ for (j = 0; j < n; j++) { ++ const T x = tab[j]; ++ assert(x >= last_tab_i); // Array must be sorted ++ if (x - last_tab_i > epsilon) { ++ tab[i] = x; ++ last_tab_i = x; ++ i++; ++ } ++ } ++ tab.resize_array(i); ++} ++ ++void build_geometry_(OperatorRegularize & op, ++ const DomainUnstructured & src, LataDeriv & dest_domain) ++{ ++ Journal(verb_level) << "OperatorRegularize domain " << src.id_.name_ << endl; ++ if (src.elt_type_ != Domain::quadri && src.elt_type_ != Domain::hexa) { ++ Journal() << "Error in OperatorRegularize::build_geometry: cannot operate on unstructured mesh with this element type" << endl; ++ throw; ++ } ++ ++ DomainIJK & dest = dest_domain.instancie(DomainIJK); ++ dest.elt_type_ = src.elt_type_; ++ const entier nsom = src.nodes_.dimension(0); ++ const entier dim = src.nodes_.dimension(1); ++ ArrOfInt nb_som_dir(dim); ++ { ++ double product_n = 1.; ++ for (entier i_dim = 0; i_dim < dim; i_dim++) { ++ ArrOfFloat & coord = dest.coord_.add(ArrOfFloat()); ++ coord.resize_array(nsom); ++ entier i; ++ for (i = 0; i < nsom; i++) ++ coord[i] = src.nodes_(i, i_dim); ++ coord.ordonne_array(); ++ retirer_doublons(coord, op.tolerance_); ++ product_n *= coord.size_array(); ++ // Add extended domain layer: ++ if (coord.size_array() > 1) { ++ const entier n = coord.size_array(); ++ const entier l = op.extend_layer_; ++ coord.resize_array(n + l * 2); ++ double x0 = coord[n-1]; ++ double delta = coord[n-2] - x0; ++ for (i = 1; i <= l; i++) ++ coord[n + l + i] = x0 + delta * i; ++ for (i = l-1; i >= 0; i--) ++ coord[i + l] = coord[i]; ++ x0 = coord[l]; ++ delta = coord[l+1] - x0; ++ for (i = 1; i <= l; i++) ++ coord[l - i] = x0 - delta * i; ++ } ++ nb_som_dir[i_dim] = coord.size_array(); ++ } ++ // Verifying that unique has deleted many points... ++ // If well organised, nsom=nx*ny*nz ++ // If chaos, nsom=(nx+ny+nz)/3 ++ // We want to verify that we are nearer to organisation than to chaos ! ++ if (product_n > (double) nsom * (double) nsom - 1.) { ++ Journal() << "Positions do not seam regular !" << endl; ++ throw; ++ } ++ } ++ int i; ++ op.renum_nodes_.resize_array(nsom); ++ int nb_som_ijk = 1; ++ for (i = 0; i < dim; i++) ++ nb_som_ijk *= nb_som_dir[i]; ++ IntTab ijk_indexes; ++ ijk_indexes.resize(nsom, dim); ++ for (i = 0; i < nsom; i++) { ++ entier ijk_index = 0; ++ for (int j = dim-1; j >= 0; j--) { ++ const double x = src.nodes_(i,j); ++ int index = search_in_ordered_vect(x, dest.coord_[j],op.tolerance_); ++ if (index < 0) { ++ Journal() << "Error: coordinate (" << i << "," << j << ") = " << x << " not found in regularize" << endl ++ << "Try reducing regularize tolerance value (option regularize=epsilon)" << endl; ++ throw; ++ } ++ ijk_indexes(i, j) = index; ++ ijk_index += index; ++ if (j) ++ ijk_index *= nb_som_dir[j-1]; ++ } ++ op.renum_nodes_[i] = ijk_index; ++ } ++ const int max_index = max_array(nb_som_dir); ++ int nb_elems_ijk = 1; ++ for (i = 0; i < dim; i++) ++ nb_elems_ijk *= nb_som_dir[i] - 1; ++ dest.invalid_connections_.resize_array(nb_elems_ijk); ++ dest.invalid_connections_ = 1; // Everything invalid by default ++ const int nelem = src.elements_.dimension(0); ++ const int nb_som_elem = src.elements_.dimension(1); ++ op.renum_elements_.resize_array(nelem); ++ // Pour chaque element, indice dans le maillage ijk du plus sommet le plus proche de l'origine ++ // (pour les faces...) ++ ArrOfInt idx_elem_som; ++ idx_elem_som.resize_array(nelem); ++ int min_index[3]; ++ for (i = 0; i < nelem; i++) { ++ min_index[0] = min_index[1] = min_index[2] = max_index; ++ for (int j = 0; j < nb_som_elem; j++) { ++ int node = src.elements_(i,j); ++ for (int k = 0; k < loop_max(dim, 3); k++) { ++ int idx = ijk_indexes(node, k); ++ min_index[k] = (idx < min_index[k]) ? idx : min_index[k]; ++ break_loop(k,dim); ++ } ++ } ++ entier idx = 0; ++ entier idx_som = 0; ++ if (dim == 1) { ++ idx = min_index[0]; ++ idx_som = idx; ++ } else if (dim == 2) { ++ idx = min_index[1] * (nb_som_dir[0]-1) + min_index[0]; ++ idx_som = min_index[1] * nb_som_dir[0] + min_index[0]; ++ } else if (dim == 3) { ++ idx = (min_index[2] * (nb_som_dir[1]-1) + min_index[1]) * (nb_som_dir[0]-1) + min_index[0]; ++ idx_som = (min_index[2] * nb_som_dir[1] + min_index[1]) * nb_som_dir[0] + min_index[0]; ++ } else ++ throw; ++ op.renum_elements_[i] = idx; ++ dest.invalid_connections_.clearbit(idx); ++ idx_elem_som[i] = idx_som; ++ } ++ ++ if (src.faces_ok()) { ++ const int nfaces = src.faces_.dimension(0); ++ op.renum_faces_.resize_array(nfaces); ++ op.renum_faces_ = -1; ++ const int nb_elem_face = src.elem_faces_.dimension(1); ++ ArrOfInt delta_dir(dim); ++ delta_dir[0] = 1; ++ for (i = 1; i < dim; i++) ++ delta_dir[i] = delta_dir[i-1] * nb_som_dir[i-1]; ++ for (i = 0; i < nelem; i++) { ++ // Les faces haut, gauche et arriere du cube a l'origine portent le numero 0 ++ // Voir DomaineIJK pour la convention sur la numerotation des faces ++ for (entier j = 0; j < nb_elem_face; j++) { ++ const entier i_face = src.elem_faces_(i, j); ++ entier dir = j % dim; ++ entier index = idx_elem_som[i]; ++ if (j>=dim) ++ index += delta_dir[dir]; ++ // Encodage du numero de la face et de la direction ++ index = (index << 2) + dir; ++ if (op.renum_faces_[i_face] < 0) { ++ op.renum_faces_[i_face] = index; ++ } else if (op.renum_faces_[i_face] != index) { ++ Journal() << "Error in OperatorRegularize: faces renumbering failed" << endl; ++ throw; ++ } ++ } ++ } ++ } ++ op.geom_init_ = 1; ++} ++ ++template ++void build_field_(OperatorRegularize & op, ++ const DomainUnstructured & src_domain, ++ const DomainIJK & dest_domain, ++ const Field & src, ++ Field & dest) ++{ ++ Journal(verb_level) << "OperatorRegularize field " << src.id_.uname_ << endl; ++ if (!op.geom_init_) { ++ // Must fill the renum_.... arrays first ! ++ LataDeriv destr; ++ op.build_geometry(src_domain, destr); ++ } ++ dest.component_names_ = src.component_names_; ++ dest.localisation_ = src.localisation_; ++ dest.nature_ = src.nature_; ++ const entier sz = src.data_.dimension(0); ++ const entier nb_compo = src.data_.dimension(1); ++ entier i; ++ switch(src.localisation_) { ++ case LataField_base::ELEM: ++ dest.data_.resize(dest_domain.nb_elements(), nb_compo); ++ for (i = 0; i < sz; i++) { ++ const entier new_i = op.renum_elements_[i]; ++ for (entier j = 0; j < nb_compo; j++) ++ dest.data_(new_i, j) = src.data_(i, j); ++ } ++ break; ++ case LataField_base::SOM: ++ dest.data_.resize(dest_domain.nb_nodes(), nb_compo); ++ for (i = 0; i < sz; i++) { ++ const entier new_i = op.renum_nodes_[i]; ++ for (entier j = 0; j < nb_compo; j++) ++ dest.data_(new_i, j) = src.data_(i, j); ++ } ++ break; ++ case LataField_base::FACES: ++ { ++ if (nb_compo != 1) { ++ Journal() << "Error in OperatorRegularize: field at faces has nb_compo != 1" << endl; ++ throw; ++ } ++ dest.nature_ = LataDBField::VECTOR; ++ const entier nb_dim = dest_domain.dimension(); ++ dest.data_.resize(dest_domain.nb_faces(), nb_dim); ++ // Field is interpreted as normal component to the face ++ for (i = 0; i < sz; i++) { ++ const entier code = op.renum_faces_[i]; ++ // decodage numero et direction de la face: ++ const entier new_i = code >> 2; ++ const entier direction = (code & 3); ++ dest.data_(new_i, direction) = src.data_(i, 0); ++ } ++ } ++ break; ++ default: ++ Journal() << "Error in OperatorRegularize::build_field_: unknown localisation" << endl; ++ throw; ++ } ++} ++ ++void OperatorRegularize::build_geometry(const Domain & src_domain, LataDeriv & dest) ++{ ++ apply_geometry(*this, src_domain, dest); ++} ++ ++void OperatorRegularize::build_field(const Domain & src_domain, const LataField_base & src_field, ++ const Domain & dest_domain, LataDeriv & dest) ++{ ++ apply_field(*this, src_domain, src_field, dest_domain, dest); ++} ++#undef verb_level +diff --git a/databases/readers/Lata/Rebuild_virtual_layer.C b/databases/readers/Lata/Rebuild_virtual_layer.C +new file mode 100644 +index 0000000..ac29742 +--- /dev/null ++++ b/databases/readers/Lata/Rebuild_virtual_layer.C +@@ -0,0 +1,141 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++void find_virtual_layer(DomainUnstructured & domain, ++ IntTab & virtual_elements, ++ IntTab & joints_virtual_elements, ++ double tolerance) ++{ ++ Journal(4) << "Searching virtual elements for domain " << domain.id_.name_ << endl; ++ // Step 1 : find duplicate nodes ++ ArrOfInt nodes_renumber; ++ Reconnect::search_duplicate_nodes(domain.nodes_, ++ nodes_renumber, ++ tolerance, ++ 0); ++ ++ // Build reconnected elements ++ Reconnect::apply_renumbering(nodes_renumber, domain.elements_); ++ ++ Static_Int_Lists som_elem; ++ construire_connectivite_som_elem(domain.nb_nodes(), ++ domain.elements_, ++ som_elem, ++ 0 /* include virtual */); ++ ++ virtual_elements.resize(0, 1); ++ virtual_elements.set_smart_resize(1); ++ ++ // Step 2 : for each sub_zone, add to virtual_elements list all elements ++ // touching the zone and not included in the zone ++ const IntTab & joints_sommets = domain.get_joints(LataField_base::SOM); ++ const IntTab & joints_elements = domain.get_joints(LataField_base::ELEM); ++ const entier nprocs = joints_sommets.dimension(0); ++ joints_virtual_elements.resize(nprocs, 2); ++ ArrOfInt tmp; ++ tmp.set_smart_resize(1); ++ for (entier i_proc = 0; i_proc < nprocs; i_proc++) { ++ entier first_elem_zone = joints_elements(i_proc, 0); ++ entier end_elems_zone = first_elem_zone + joints_elements(i_proc, 1); ++ entier first_node_zone = joints_sommets(i_proc, 0); ++ entier end_nodes_zone = first_node_zone + joints_sommets(i_proc, 1); ++ const entier first_virtual_element = virtual_elements.dimension(0); ++ tmp.resize_array(0); ++ for (entier i_node = first_node_zone; i_node < end_nodes_zone; i_node++) { ++ const entier renum_node = nodes_renumber[i_node]; ++ const entier nb_elems_voisins = som_elem.get_list_size(renum_node); ++ for (entier i = 0; i < nb_elems_voisins; i++) { ++ const entier elem = som_elem(renum_node, i); ++ if (elem < first_elem_zone || elem >= end_elems_zone) ++ tmp.append_array(elem); ++ } ++ } ++ // Retirer les doublons ++ tmp.ordonne_array(); ++ const entier n = tmp.size_array(); ++ entier last = -1; ++ for (entier i = 0; i < n; i++) { ++ const entier elem = tmp[i]; ++ if (elem != last) { ++ const entier idx = virtual_elements.dimension(0); ++ virtual_elements.resize(idx+1, 1); ++ virtual_elements(idx, 0) = elem; ++ last = elem; ++ } ++ } ++ joints_virtual_elements(i_proc, 0) = first_virtual_element; ++ joints_virtual_elements(i_proc, 1) = virtual_elements.dimension(0) - first_virtual_element; ++ Journal(5) << "Zone " << i_proc << " has " << joints_virtual_elements(i_proc, 1) << " virtual elements" << endl; ++ } ++} ++ ++entier rebuild_virtual_layer(LataDB & lataDB, Domain_Id id, double reconnect_tolerance) ++{ ++ Journal(4) << "rebuilt_virtual_layer domain " << id.name_ << " " << id.timestep_ << endl; ++ if (lataDB.field_exists(id.timestep_, id.name_, "VIRTUAL_ELEMENTS")) { ++ Journal(4) << " Virtual elements data already exist. Skip" << endl; ++ return 1; ++ } ++ if (!lataDB.field_exists(id.timestep_, id.name_, "JOINTS_ELEMENTS")) { ++ Journal(4) << " Domain has no processor splitting information. Skip" << endl; ++ return 0; ++ } ++ // Load all domain, without faces: ++ id.block_ = -1; ++ DomainUnstructured dom; ++ dom.fill_domain_from_lataDB(lataDB, id, 0 /* no faces */); ++ // Compute virtual zones: ++ IntTab joints_virtual_elements; ++ IntTab virtual_elements; ++ find_virtual_layer(dom, virtual_elements, joints_virtual_elements, reconnect_tolerance); ++ // Write data to disk ++ const LataDBField & joints = lataDB.get_field(id.timestep_, id.name_, "JOINTS_ELEMENTS", "*"); ++ LataDBField fld(joints); ++ // Append virtual_elements data to JOINTS_ELEMENTS, same format, etc ++ fld.name_ = "JOINTS_VIRTUAL_ELEMENTS"; ++ fld.uname_ = Field_UName(fld.geometry_, fld.name_, ""); ++ fld.nb_comp_ = 2; ++ fld.datatype_.file_offset_ = 0; ++ fld.filename_ += ".ghostdata"; ++ lataDB.add_field(fld); ++ lataDB.write_data(id.timestep_, fld.uname_, joints_virtual_elements); ++ fld.name_ = "VIRTUAL_ELEMENTS"; ++ fld.uname_ = Field_UName(fld.geometry_, fld.name_, ""); ++ fld.nb_comp_ = 1; ++ fld.datatype_.file_offset_ = 1; // append ++ fld.size_ = virtual_elements.dimension(0); ++ lataDB.add_field(fld); ++ lataDB.write_data(id.timestep_, fld.uname_, virtual_elements); ++ return 1; ++} +diff --git a/databases/readers/Lata/Rebuild_virtual_layer.h b/databases/readers/Lata/Rebuild_virtual_layer.h +new file mode 100644 +index 0000000..f2666dd +--- /dev/null ++++ b/databases/readers/Lata/Rebuild_virtual_layer.h +@@ -0,0 +1,35 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++void find_virtual_layer(DomainUnstructured & domain, ++ IntTab & virtual_elements, ++ IntTab & joints_virtual_elements, ++ double tolerance); ++ ++entier rebuild_virtual_layer(LataDB & lataDB, Domain_Id id, double reconnect_tolerance); +diff --git a/databases/readers/Lata/Sortie.h b/databases/readers/Lata/Sortie.h +new file mode 100644 +index 0000000..69c967e +--- /dev/null ++++ b/databases/readers/Lata/Sortie.h +@@ -0,0 +1,44 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef Sortie_h_inclu ++#define Sortie_h_inclu ++#include ++//using namespace std; ++using std::cerr; ++using std::endl; ++#define Sortie std::ostream ++class ArrOfInt; ++// for Static_Int_Lists ++inline Sortie& operator<<(Sortie& is, const ArrOfInt& t) ++{ ++ throw; ++ return is; ++} ++#endif +diff --git a/databases/readers/Lata/Static_Int_Lists.C b/databases/readers/Lata/Static_Int_Lists.C +new file mode 100644 +index 0000000..4c3f065 +--- /dev/null ++++ b/databases/readers/Lata/Static_Int_Lists.C +@@ -0,0 +1,128 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++// Description: detruit toutes les listes ++void Static_Int_Lists::reset() ++{ ++ index_.resize_array(0); ++ valeurs_.resize_array(0); ++} ++ ++// Description: detruit les listes existantes et en cree de nouvelles. ++// On cree autant de listes que d'elements dans le tableau sizes. ++// La i-ieme liste a une taille sizes[i] ++// Les valeurs sizes doivent etre positives ou nulles. ++void Static_Int_Lists::set_list_sizes(const ArrOfInt& sizes) ++{ ++ reset(); ++ ++ const entier nb_listes = sizes.size_array(); ++ index_.resize_array(nb_listes + 1); ++ // Construction du tableau d'index ++ index_[0]; ++ entier i; ++ for (i = 0; i < nb_listes; i++) ++ { ++ assert(sizes[i] >= 0); ++ index_[i+1] = index_[i] + sizes[i]; ++ } ++ const entier somme_sizes = index_[nb_listes]; ++ valeurs_.resize_array(somme_sizes); ++} ++ ++// Description: tri par ordre croissant des valeurs de la i-ieme liste. ++// Si num_liste < 0, on trie toutes les listes. ++void Static_Int_Lists::trier_liste(entier num_liste) ++{ ++ const entier i_debut = (num_liste < 0) ? 0 : num_liste; ++ const entier i_fin = (num_liste < 0) ? index_.size_array() - 1 : num_liste + 1; ++ ++ entier i; ++ ArrOfInt valeurs_liste; ++ for (i = i_debut; i < i_fin; i++) ++ { ++ const entier index = index_[i]; ++ const entier size = index_[i+1] - index; ++ entier * data = valeurs_.addr() + index; ++ valeurs_liste.ref_data(data, size); ++ valeurs_liste.ordonne_array(); ++ } ++} ++ ++// Description: copie la i-ieme liste dans le tableau fourni ++// Le tableau array doit etre resizable. ++void Static_Int_Lists::copy_list_to_array(entier i, ArrOfInt& array) const ++{ ++ const entier n = get_list_size(i); ++ array.resize_array(0); // Ne pas copier les donnees d'origine ++ array.resize_array(n); ++ entier index = index_[i]; ++ entier j = 0; ++ for (j = 0; j < n; index++, j++) ++ array[j] = valeurs_[index]; ++} ++ ++Sortie& Static_Int_Lists::printOn(Sortie& os) const ++{ ++ os << index_ << " "; ++ os << valeurs_ << " "; ++ return os; ++} ++ ++Entree& Static_Int_Lists::readOn(Entree& is) ++{ ++ reset(); ++ is >> index_; ++ is >> valeurs_; ++ return is; ++} ++ ++Sortie& Static_Int_Lists::ecrire(Sortie& os) const ++{ ++ os << "nb lists : " << get_nb_lists() << finl; ++ os << "sizes of lists : "; ++ for (entier i=0; i ++ ++// .DESCRIPTION ++// Cette classe permet de stocker des listes d'entiers accessibles ++// en temps constant. La taille des listes ne peut pas changer sans ++// perdre le contenu (ce sont des listes statiques). ++// Exemple: ++// Static_Int_List l; ++// ArrOfInt tailles(3); ++// tailles[0] = 2; tailles[1] = 3; tailles[2] = 0; ++// // On reserve la memoire pour trois listes de taille 2, 3 et 0: ++// l.set_list_sizes(tailles); ++// // On affecte une valeur au deuxieme element de la premiere liste: ++// l.set_value(0,1,765); ++// // Affiche la valeur ++// cout << l(0,1); ++class Static_Int_Lists ++{ ++public: ++ void set_list_sizes(const ArrOfInt& sizes); ++ void reset(); ++ void copy_list_to_array(entier i_liste, ArrOfInt& array) const; ++ ++ inline void set_value(entier i_liste, entier i_element, entier valeur); ++ inline entier operator() (entier i_liste, entier i_element) const; ++ inline entier get_list_size(entier i_liste) const; ++ inline entier get_nb_lists() const; ++ ++ void trier_liste(entier i); ++ ++ Sortie& printOn(Sortie& os) const; ++ Entree& readOn(Entree& is); ++ ++ Sortie& ecrire(Sortie& os) const; ++ ++private: ++ // Les listes d'entiers sont stockees de facon contigue ++ // dans le tableau valeurs_. ++ // Le premier element de la liste i est valeurs_[index_[i]] ++ // et le dernier element est valeurs_[index_[i+1]-1] ++ // (c'est comme le stockage morse des matrices). ++ ArrOfInt index_; ++ ArrOfInt valeurs_; ++}; ++ ++// Description: affecte la "valeur" au j-ieme element de la i-ieme liste avec ++// 0 <= i < get_nb_lists() et 0 <= j < get_list_size(i) ++inline void Static_Int_Lists::set_value(entier i, entier j, entier valeur) ++{ ++ const entier index = index_[i] + j; ++ assert(index < index_[i+1]); ++ valeurs_[index] = valeur; ++} ++ ++// Description: renvoie le j-ieme element de la i-ieme liste avec ++// 0 <= i < get_nb_lists() et 0 <= j < get_list_size(i) ++inline entier Static_Int_Lists::operator() (entier i, entier j) const ++{ ++ const entier index = index_[i] + j; ++ assert(index < index_[i+1]); ++ const entier val = valeurs_[index]; ++ return val; ++} ++ ++// Description: renvoie le nombre d'elements de la liste i ++inline entier Static_Int_Lists::get_list_size(entier i) const ++{ ++ const entier size = index_[i+1] - index_[i]; ++ return size; ++} ++ ++// Description: renvoie le nombre de listes stockees ++inline entier Static_Int_Lists::get_nb_lists() const ++{ ++ return index_.size_array() - 1; ++} ++ ++#endif +diff --git a/databases/readers/Lata/UserFields.C b/databases/readers/Lata/UserFields.C +new file mode 100644 +index 0000000..575c231 +--- /dev/null ++++ b/databases/readers/Lata/UserFields.C +@@ -0,0 +1,1038 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#include ++#include ++#include ++// ******************************************************************************** ++// METHODES OUTILS DE GESTION ++// (normalement, on n'a pas besoin de les modifier mais on peut en ajouter...) ++// ******************************************************************************** ++ ++// Implementation de la classe Geometry_handle ++// (utiliser cette classe pour eviter d'avoir a faire des dynamic_cast ++// compliques et pour ne pas avoir a gerer get_geometry et release_geometry a la main) ++// Exemple d'utilisation: voir interpoler_elem_vers_som() ++Geometry_handle::Geometry_handle() ++{ ++} ++void Geometry_handle::set(LataFilter & lata_filter, const Domain_Id & id) ++{ ++ lata_filter_ = lata_filter; ++ geom_ = lata_filter.get_geometry(id); ++} ++Geometry_handle::Geometry_handle(Geometry_handle & handle) ++{ ++ operator=(handle); ++} ++Geometry_handle & Geometry_handle::operator=(Geometry_handle & handle) ++{ ++ reset(); ++ lata_filter_ = handle.lata_filter_; ++ // Get another reference from the lata filter (to increment ref counter in the cache) ++ geom_ = lata_filter_.valeur().get_geometry(handle.geom_.valeur().id_); ++ return *this; ++} ++Geometry_handle::~Geometry_handle() ++{ ++ reset(); ++} ++void Geometry_handle::reset() ++{ ++ if (geom_.non_nul()) ++ lata_filter_.valeur().release_geometry(geom_.valeur()); ++ geom_.reset(); ++ lata_filter_.reset(); ++} ++const DomainUnstructured & Geometry_handle::geom() ++{ ++ if (!geom_.non_nul()) { ++ Journal() << "Internal error in Geometry_handle::geom() : nul pointer" << endl; ++ throw; ++ } ++ const DomainUnstructured* ptr = dynamic_cast(&geom_.valeur()); ++ if (!ptr) { ++ Journal() << "Error in Geometry_handle::geom() : domain " ++ << geom_.valeur().id_.name_ << " is not unstructured" << endl; ++ throw; ++ } ++ return *ptr; ++} ++const DomainIJK & Geometry_handle::geom_ijk() ++{ ++ if (!geom_.non_nul()) { ++ Journal() << "Internal error in Geometry_handle::geom() : nul pointer" << endl; ++ throw; ++ } ++ const DomainIJK* ptr = dynamic_cast(&geom_.valeur()); ++ if (!ptr) { ++ Journal() << "Error in Geometry_handle::geom() : domain " ++ << geom_.valeur().id_.name_ << " is not IJK" << endl; ++ throw; ++ } ++ return *ptr; ++} ++entier Geometry_handle::test_ijk() ++{ ++ if (!geom_.non_nul()) { ++ Journal() << "Internal error in Geometry_handle::geom() : nul pointer" << endl; ++ throw; ++ } ++ const DomainIJK* ptr = dynamic_cast(&geom_.valeur()); ++ if (ptr) ++ return 1; ++ else ++ return 0; ++} ++ ++// Petite fonction outil qui construit l'objet LataFieldMetaData en changeant uniquement ++// le nom du champ (dimension, localisation, geometrie, nombre de composantes sont identiques) ++// Le champ "source" est rempli avec une reference a source, on pourra donc appeler ++// get_champ_source() (voir interpoler_elem_vers_som pour un exemple) ++// Voir new_fields_metadata() pour un exemple d'utilisation. ++static LataFieldMetaData declare_new_name(const LataFieldMetaData & source, ++ const char * name) ++{ ++ LataFieldMetaData dest = source; ++ // Lorsqu'on demandera ce champ, on saura que c'est UserFields qui devra le calculer ++ dest.source_ = "user_fields"; ++ // On change le nom du champ: ++ dest.name_ = name; ++ dest.uname_.set_field_name(name); ++ // On remplit le champ source ++ dest.source_field_ = source.uname_; ++ ++ return dest; ++} ++ ++// Fonction identique a declare_new_name, mais pour declarer un champ avec une localisation ++// differente. ++// Voir new_fields_metadata() pour un exemple d'utilisation. ++static LataFieldMetaData declare_new_name_localisation(const LataFieldMetaData & source, ++ const char * name, ++ LataField_base::Elem_som loc) ++{ ++ LataFieldMetaData dest = source; ++ // Lorsqu'on demandera ce champ, on saura que c'est UserFields qui devra le calculer ++ dest.source_ = "user_fields"; ++ // On change le nom du champ et la localisation: ++ dest.name_ = name; ++ dest.uname_ = Field_UName(source.uname_.get_geometry(), ++ name, ++ LataField_base::localisation_to_string(loc)); ++ // On remplit le champ source ++ dest.source_field_ = source.uname_; ++ ++ // En plus: je change la localisation: ++ dest.localisation_ = loc; ++ ++ return dest; ++} ++ ++// Fonction identique a declare_new_name, mais pour declarer un champ avec une localisation ++// differente de type vectoriel. ++// Voir new_fields_metadata() pour un exemple d'utilisation. ++static LataFieldMetaData declare_new_vector_field(const LataFieldMetaData & source, ++ const char * name, ++ LataField_base::Elem_som loc, ++ const entier dim) ++{ ++ LataFieldMetaData dest = source; ++ // Lorsqu'on demandera ce champ, on saura que c'est UserFields qui devra le calculer ++ dest.source_ = "user_fields"; ++ // On change le nom du champ et la localisation: ++ dest.name_ = name; ++ dest.uname_ = Field_UName(source.uname_.get_geometry(), ++ name, ++ LataField_base::localisation_to_string(loc)); ++ // On remplit le champ source ++ dest.source_field_ = source.uname_; ++ ++ // En plus: je change la localisation: ++ dest.localisation_ = loc; ++ ++ // et le type (vecteur) ++ dest.component_names_.reset(); ++ dest.nb_components_ = dim; ++ dest.is_vector_ = 1; ++ ++ return dest; ++} ++ ++// Description: demande a la classe LataFilter le champ source du champ "id" ++// qui a ete declare quand on a appele declare_new_name() au debut ++// Voir filtre_boite() pour un exemple d'utilisation. ++FieldType UserFields::get_champ_source(const Field_Id & id) ++{ ++ // Cherche la structure LataFieldMetaData du champ "id": ++ const LataFieldMetaData & data = lata_filter_.valeur().get_field_metadata(id.uname_); ++ Field_Id id2(data.source_field_, id.timestep_, id.block_); ++ FieldType tmp; ++ const LataField_base & field = lata_filter_.valeur().get_field(id2); ++ const FieldType* ptr = dynamic_cast(&field); ++ if (!ptr) { ++ Journal() << "Error in UserFields::get_champ_source : field " << id.uname_ ++ << " is not a floattab" << endl; ++ throw; ++ } ++ // Copie le contenu du champ dans un tableau temporaire: ++ tmp = *ptr; ++ // Libere le champ d'origine ++ lata_filter_.valeur().release_field(field); ++ return tmp; ++} ++ ++// Description: demande a la classe LataFilter le champ de nom "nom" et dont ++// la geometrie, le pas de temps et la localisation sont celles de "id". ++FieldType UserFields::get_champ(const Nom & nom, const Field_Id & id) ++{ ++ FieldType tmp; ++ // Construit un Field_Id identique, seul le nom du champ chamge: ++ Field_Id id2(id); ++ id2.uname_.set_field_name(nom); ++ const LataField_base & field = lata_filter_.valeur().get_field(id2); ++ const FieldType* ptr = dynamic_cast(&field); ++ if (!ptr) { ++ Journal() << "Error in UserFields::get_champ : field " << id.uname_ ++ << " is not a floattab" << endl; ++ throw; ++ } ++ // Copie le contenu du champ dans un tableau temporaire: ++ tmp = *ptr; ++ // Libere le champ d'origine ++ lata_filter_.valeur().release_field(field); ++ ++ return tmp; ++} ++ ++// Description: idem, mais cherche un champ avec une localisation differente de id ++FieldType UserFields::get_champ_loc(const Nom & nom, LataField_base::Elem_som loc, const Field_Id & id) ++{ ++ FieldType tmp; ++ // Construit un Field_Id identique, seul le nom du champ chamge: ++ Field_Id id2(id); ++ id2.uname_ = Field_UName(id.uname_.get_geometry(), nom, LataField_base::localisation_to_string(loc)); ++ ++ const LataField_base & field = lata_filter_.valeur().get_field(id2); ++ const FieldType* ptr = dynamic_cast(&field); ++ if (!ptr) { ++ Journal() << "Error in UserFields::get_champ : field " << id.uname_ ++ << " is not a floattab" << endl; ++ throw; ++ } ++ // Copie le contenu du champ dans un tableau temporaire: ++ tmp = *ptr; ++ // Libere le champ d'origine ++ lata_filter_.valeur().release_field(field); ++ ++ return tmp; ++} ++ ++// Description: renvoie un objet Geometry_handle qui pointe sur le domaine ++// support du champ "id". ++// Voir interpoler_elem_vers_som() pour un exemple d'utilisation ++void UserFields::get_geometry(const Domain_Id & id, Geometry_handle & h) ++{ ++ h.set(lata_filter_.valeur(), id); ++} ++ ++// ******************************************************************************** ++// METHODES OUTILS DE CALCUL ++// Ces methodes sont des fonctions qui calculent un champ en fonction d'un autre champ. ++// On peut les modifier comme on veut, en ajouter, etc... ++// Lachez-vous... ++// ******************************************************************************** ++ ++// Description: ++// Fonction d'interpolation qui transforme un champ aux "elements" ++// en un champ aux "sommets". ++// Dans cet exemple, on a deux algorithmes selon que le champ est sur ++// un maillage ijk ou non. ++// La valeur aux sommets est la moyenne des valeurs sur les elements adjacents. ++FieldType UserFields::interpoler_elem_vers_som(const Field_Id & id) ++{ ++ // Recupere le champ a filtrer (champ aux elements) ++ FieldType source = get_champ_source(id); ++ ++ FieldType resu; ++ // Remplissage des meta-data du champ: ++ resu.id_ = id; ++ resu.component_names_ = source.component_names_; ++ resu.localisation_ = LataField_base::SOM; ++ resu.nature_ = source.nature_; ++ ++ // Recupere la geometrie (domaine ijk ou non structure) sur laquelle est definie ++ // le champ source: ++ Geometry_handle geom; ++ get_geometry(id, geom); ++ ArrOfFloat poids; ++ ++ if (geom.test_ijk()) { ++ const DomainIJK & dom = geom.geom_ijk(); ++ // Le code suivant marche en 1D, 2D et 3D: ++ const entier nbsom = dom.nb_nodes(); ++ const entier nbcompo = source.data_.dimension(1); ++ resu.data_.resize(nbsom, nbcompo); ++ const entier nsom_x = dom.nb_som_dir(0); ++ const entier nsom_y = dom.nb_som_dir(1); ++ const entier nelem_x = dom.nb_elem_dir(0); ++ const entier nelem_y = dom.nb_elem_dir(1); ++ const entier nelem_z = dom.nb_elem_dir(2); ++ poids.resize_array(nbsom); ++ const entier ni = 2; ++ const entier nj = (dom.dimension() > 1) ? 2 : 1; ++ const entier nk = (dom.dimension() > 2) ? 2 : 1; ++ ++ // Avec les boucles imbriquees comme ceci, on parcourt tous les ++ // elements dans l'ordre croissant: ++ // (l'indice de l'element (i,j,k) est : ++ // elem = (k * nelem_y + j) * nelem_x + i ++ entier elem = 0; ++ for (entier k = 0; k < nelem_z; k++) { ++ for (entier j = 0; j < nelem_y; j++) { ++ for (entier i = 0; i < nelem_x; i++) { ++ if (dom.invalid_connections_.size_array() == 0 || dom.invalid_connections_[elem] == 0) { ++ // Element valide: ++ // Boucle sur les sommets de l'element ++ const entier som0 = (k * nsom_y + j) * nsom_x + i; ++ for (entier kk = 0; kk < nk; kk++) { ++ for (entier jj = 0; jj < nj; jj++) { ++ for (entier ii = 0; ii < ni; ii++) { ++ entier som = som0 + (kk * nsom_y + jj) * nsom_x + ii; ++ for (entier compo = 0; compo < nbcompo; compo++) ++ resu.data_(som, compo) += source.data_(elem, compo); ++ poids[som] += 1.; ++ } ++ } ++ } ++ } ++ elem++; ++ } ++ } ++ } ++ } else { ++ const DomainUnstructured & dom = geom.geom(); ++ ++ const entier nbsom = dom.nb_nodes(); ++ const entier nbcompo = source.data_.dimension(1); ++ resu.data_.resize(nbsom, nbcompo); ++ poids.resize_array(nbsom); ++ const IntTab & les_elem = dom.elements_; ++ const entier n = les_elem.dimension(0); ++ const entier m = les_elem.dimension(1); ++ int i, j, k; ++ for ( i = 0; i < n; i++) { ++ for (j = 0; j < m; j++) { ++ entier som = les_elem(i,j); ++ for (k = 0; k < nbcompo; k++) { ++ float x = source.data_(i, k); ++ resu.data_(som, k) += x; ++ } ++ poids[som] += 1.; ++ } ++ } ++ } ++ const entier nbsom = poids.size_array(); ++ const entier nbcompo = resu.data_.dimension(1); ++ for (entier i = 0; i < nbsom; i++) ++ for (entier k = 0; k < nbcompo; k++) ++ resu.data_(i, k) /= poids[i]; ++ ++ return resu; ++} ++ ++ ++ ++ ++ ++// Attention: le constructeur par defaut n'initialise pas le vecteur ! ++class Vecteur3 ++{ ++public: ++ Vecteur3() {}; ++ Vecteur3(const Vecteur3 & w) { ++ v[0] = w.v[0]; v[1] = w.v[1]; v[2] = w.v[2]; ++ } ++ Vecteur3(double x, double y, double z) { ++ v[0] = x; v[1] = y; v[2] = z; ++ } ++ void set(double x, double y, double z) { ++ v[0] = x; v[1] = y; v[2] = z; ++ } ++ double length() const { return sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); }; ++ Vecteur3(const DoubleTab & tab, entier i) { ++ //assert(tab.line_size() == 3); ++ assert(i >= 0 && i < tab.dimension_tot(0)); ++ const double *ptr = tab.addr() + i * 3; ++ v[0] = ptr[0]; ++ v[1] = ptr[1]; ++ v[2] = ptr[2]; ++ } ++ Vecteur3 & operator=(double x) { ++ v[0] = x; v[1] = x; v[2] = x; ++ return *this; ++ } ++ Vecteur3 & operator*=(double x) { ++ v[0] *= x; v[1] *= x; v[2] *= x; ++ return *this; ++ } ++ ++ Vecteur3 & operator=(const Vecteur3 & w) { ++ v[0] = w.v[0]; v[1] = w.v[1]; v[2] = w.v[2]; ++ return *this; ++ } ++ double operator[](entier i) const { assert(i>=0 && i<3); return v[i]; } ++ double & operator[](entier i) { assert(i>=0 && i<3); return v[i]; } ++ inline double norme_Linfini(); ++ static inline void produit_vectoriel(const Vecteur3 & x, const Vecteur3 & y, Vecteur3 & resu); ++ static inline double produit_scalaire(const Vecteur3 & x, const Vecteur3 & y); ++ friend Vecteur3 operator-(const Vecteur3 &, const Vecteur3 &); ++protected: ++ double v[3]; ++}; ++ ++ ++inline void Vecteur3::produit_vectoriel(const Vecteur3 & x, const Vecteur3 & y, Vecteur3 & z) ++{ ++ z.v[0] = x.v[1] * y.v[2] - x.v[2] * y.v[1]; ++ z.v[1] = x.v[2] * y.v[0] - x.v[0] * y.v[2]; ++ z.v[2] = x.v[0] * y.v[1] - x.v[1] * y.v[0]; ++} ++ ++inline double Vecteur3::produit_scalaire(const Vecteur3 & x, const Vecteur3 & y) ++{ ++ double r = x.v[0] * y.v[0] + x.v[1] * y.v[1] + x.v[2] * y.v[2]; ++ return r; ++} ++ ++// Description: norme L_infini, c'est le max des abs(v[i]) ++inline double Vecteur3::norme_Linfini() ++{ ++ double x = fabs(v[0]); ++ double y = fabs(v[1]); ++ double z = fabs(v[2]); ++ double resu = ((x > y) ? x : y); ++ resu = ((resu > z) ? resu : z); ++ return resu; ++} ++ ++inline Vecteur3 operator-(const Vecteur3 & x, const Vecteur3 & y) ++{ ++ Vecteur3 z; ++ z.v[0] = x.v[0] - y.v[0]; ++ z.v[1] = x.v[1] - y.v[1]; ++ z.v[2] = x.v[2] - y.v[2]; ++ return z; ++} ++ ++double largest_angle_2(const DoubleTab& coords) ++ ++{ ++ if (((coords.dimension(0)!=4)&&(coords.dimension(0)!=3))||(coords.dimension(1)!=3)) ++ { ++ Cerr<<" cas nn prevu"<max_pscal) ++ max_pscal=pscal; ++ } ++ double tet=acos(max_pscal)/acos(-1.)*180; // PL: acos(-1) ne compile pas sur de multiples plateformes ++ ++ tet=180-tet; ++ return tet; ++} ++ ++ ++ ++FieldType UserFields::calculer_angle(const Field_Id & id) ++{ ++ // Recupere le champ a filtrer (champ aux elements) ++ // FieldType source = get_champ_source(id); ++ ++ FieldType resu; ++ // Remplissage des meta-data du champ: ++ resu.id_ = id; ++ const LataFieldMetaData & data = lata_filter_.valeur().get_field_metadata(id.uname_); ++ resu.component_names_ = data.component_names_; ++ resu.localisation_ = data.localisation_; ++ resu.nature_ = LataDBField::SCALAR; ++ ++ // Recupere la geometrie (domaine ijk ou non structure) sur laquelle est definie ++ // le champ source: ++ Geometry_handle geom; ++ get_geometry(id, geom); ++ ++ if (geom.test_ijk()) { ++ Journal() << "non code" < & fields_data) ++{ ++ lata_filter_ = filter; ++ ++ const Noms geoms = filter.get_exportable_geometry_names(); ++ ++ const entier nb_geometries = geoms.size(); ++ ++ for (int i = 0; i < nb_geometries; i++) { ++ const LataGeometryMetaData data = filter.get_geometry_metadata(geoms[i]); ++ ++ // Si on a des faces, proposer la normale aux faces ++ int topo_dim=data.dimension_; ++ ++ switch(data.element_type_) { ++ case Domain::point: topo_dim = 0; break; ++ case Domain::line: topo_dim = 1; break; ++ case Domain::triangle: ++ case Domain::polygone: ++ case Domain::quadri: topo_dim = 2; break; ++ case Domain::tetra: ++ case Domain::prism6: ++ case Domain::polyedre: ++ case Domain::hexa: topo_dim = 3; break; ++ default: ++ cerr << "avtlataFileFormat::PopulateDatabaseMetaData error: unknown element type" << endl; ++ throw; ++ } ++ if ((data.dimension_>1)&&(topo_dim!=data.dimension_)) { ++ Journal(1)<<"Ajout de la normale"<= nx_) ++ i = nx_-1; ++ if (j < 0) ++ j = 0; ++ else if (j >= ny_) ++ j = ny_ - 1; ++ if (k < 0) ++ k = 0; ++ else if (k >= nz_) ++ k = nz_-1; ++ return k * ny_ * nx_ + j * nx_ + i; ++ } ++ ++ // Tableau: pour chaque element, 1 s'il est INVALIDE, 0 s'il est OK ++ ArrOfBit invalid_connections_; ++ ++ entier demi_pas_; ++ int pbDim_; // dimension ++ int nx_; ++ int ny_; ++ int nz_; ++ float dx_; ++ float dy_; ++ float dz_; ++}; ++ ++void FiltreSpatial::init(LataFilter & lata, const Domain_Id & id, entier demi_pas) ++{ ++ const Domain & dom = lata.get_geometry(id); ++ const DomainIJK * ptr = dynamic_cast(&dom); ++ if (!ptr) { ++ Journal() << "Error in FiltreSpatial::init : domain " << id.name_ << " is not IJK" << endl; ++ throw; ++ } ++ demi_pas_ = demi_pas; ++ pbDim_ = ptr->coord_.size(); ++ nx_ = ptr->coord_[0].size_array() - 1; ++ ny_ = ptr->coord_[1].size_array() - 1; ++ if (pbDim_ == 3) ++ nz_ = ptr->coord_[2].size_array() - 1; ++ else ++ nz_ = 1; ++ ++ dx_ = ptr->coord_[0][1] - ptr->coord_[0][0]; ++ dy_ = ptr->coord_[1][1] - ptr->coord_[1][0]; ++ if (pbDim_ == 3) ++ dz_ = ptr->coord_[2][1] - ptr->coord_[2][0]; ++ else ++ dz_ = 1.; ++ ++ invalid_connections_ = ptr->invalid_connections_; ++ ++ if (invalid_connections_.size_array() == 0) { ++ invalid_connections_.resize_array(ptr->nb_elements()); ++ invalid_connections_ = 0; ++ } ++ ++ lata.release_geometry(dom); ++} ++ ++FloatTab FiltreSpatial::calculer_somme_dir(const FloatTab & src, const int dir) const ++{ ++ const int n = src.dimension(0); ++ const int nb_compo = src.dimension(1); ++ FloatTab tmp; ++ tmp.resize(n, nb_compo); ++ ++ int index_resu = 0; ++ for (int k = 0; k < nz_; k++) { ++ for (int j = 0; j < ny_; j++) { ++ for (int i = 0; i < nx_; i++) { ++ for (int count = -demi_pas_; count <= demi_pas_; count++) { ++ int index; ++ switch(dir) { ++ case 0: index = ijk_index(i+count, j, k); break; ++ case 1: index = ijk_index(i, j+count, k); break; ++ case 2: index = ijk_index(i, j, k+count); break; ++ default: ++ throw; ++ } ++ ++ if (invalid_connections_[index] == 1 && dir == 0) { ++ // element invalide ! ++ } else { ++ // element ok ! ++ for (int compo = 0; compo < nb_compo; compo++) ++ tmp(index_resu, compo) += src(index, compo); ++ } ++ } ++ index_resu++; ++ } ++ } ++ } ++ return tmp; ++} ++ ++FieldType FiltreSpatial::filtrer(const FieldType & source, const Field_Id & id) const ++{ ++ // On copie tout pour avoir les noms des composantes, localisation etc... ++ FieldType resu = source; ++ resu.id_ = id; ++ ++ FloatTab somme_x = calculer_somme_dir(source.data_, 0); ++ FloatTab somme_y = calculer_somme_dir(somme_x, 1); ++ if (pbDim_ == 3) ++ resu.data_ = calculer_somme_dir(somme_y, 2); ++ else ++ resu.data_ = somme_y; ++ ++ entier pas = demi_pas_ * 2 + 1; ++ double fact = pas * pas; ++ if (pbDim_ == 3) ++ fact *= pas; ++ resu.data_ *= (1. / fact); ++ ++ return resu; ++} ++ ++FieldType UserFields::filtre_boite(const Field_Id & id) ++{ ++ FieldType source = get_champ_source(id); ++ ++ FiltreSpatial filtre(lata_filter_.valeur(), id, opt_.demie_largeur_filtre_boite_); ++ ++ FieldType resu = filtre.filtrer(source, id); ++ ++ return resu; ++} ++ +diff --git a/databases/readers/Lata/UserFields.h b/databases/readers/Lata/UserFields.h +new file mode 100644 +index 0000000..8e2052c +--- /dev/null ++++ b/databases/readers/Lata/UserFields.h +@@ -0,0 +1,108 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef UserFields_H ++#define UserFields_H ++#include ++#include ++ ++template class Field; ++class FloatTab; ++typedef Field FieldType; ++class Field_Id; ++class LataFilter; ++struct LataFieldMetaData; ++class DomainUnstructured; ++class DomainIJK; ++ ++// Description: classe outil pour acceder a une geometrie dans LataFilter. ++// La geometrie est chargee en memoire quand cet objet est cree, ++// elle est dechargee quand il est detruit. ++// Exemple d'utilisation dans UserFields::interpoler_elem_vers_som ++class Geometry_handle ++{ ++public: ++ Geometry_handle(); ++ Geometry_handle(Geometry_handle &); ++ Geometry_handle & operator=(Geometry_handle &); ++ ~Geometry_handle(); ++ void set(LataFilter & filter, const Domain_Id &); ++ const DomainUnstructured & geom(); ++ const DomainIJK & geom_ijk(); ++ entier test_ijk(); ++protected: ++ void reset(); ++ LataRef lata_filter_; ++ LataRef geom_; ++}; ++ ++class UserFields_options ++{ ++public: ++ UserFields_options(); ++ entier parse_option(const Nom &); ++ void print_help_option() const; ++ ++ // Exemple de parametre en option (commentaires bienvenus !) ++ ++ // demie-largeur du filtre_boite en mailles ++ entier demie_largeur_filtre_boite_; ++}; ++ ++class UserFields ++{ ++public: ++ void set_options(const UserFields_options & opt) { opt_ = opt; } ++ ++ void new_fields_metadata(LataFilter & filter, ++ LataVector & fields_data); ++ ++ FieldType get_field(const Field_Id & id); ++ ++ BigEntier compute_memory_size() { return 0; } ++ ++protected: ++ // Declaration de methodes outils ++ FieldType get_champ_source(const Field_Id & id); ++ FieldType get_champ(const Nom & nom, const Field_Id & id); ++ FieldType get_champ_loc(const Nom & nom, LataField_base::Elem_som loc, const Field_Id & id); ++ void get_geometry(const Domain_Id & id, Geometry_handle &); ++ ++ FieldType filtre_boite(const Field_Id & id); ++ FieldType calculer_normale(const Field_Id & id); ++ FieldType calculer_angle(const Field_Id & id); ++ FieldType interpoler_elem_vers_som(const Field_Id & id); ++ FieldType interpoler_faces_vdf_vers_elem(const Field_Id & id); ++ ++ // Reference a la classe LataFilter (pour recuperer les champs sources) ++ LataRef lata_filter_; ++ ++ UserFields_options opt_; ++}; ++#endif +diff --git a/databases/readers/Lata/Vect.h b/databases/readers/Lata/Vect.h +new file mode 100644 +index 0000000..a650806 +--- /dev/null ++++ b/databases/readers/Lata/Vect.h +@@ -0,0 +1,34 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef Vect_h_inclu ++#define Vect_h_inclu ++#include ++#define VECT(x) LataVector ++#endif +diff --git a/databases/readers/Lata/VectArrOfInt.h b/databases/readers/Lata/VectArrOfInt.h +new file mode 100644 +index 0000000..c666311 +--- /dev/null ++++ b/databases/readers/Lata/VectArrOfInt.h +@@ -0,0 +1,34 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef VectArrOfInt_h_inclu ++#define VectArrOfInt_h_inclu ++#include ++#include ++#endif +diff --git a/databases/readers/Lata/arch.h b/databases/readers/Lata/arch.h +new file mode 100644 +index 0000000..68c5800 +--- /dev/null ++++ b/databases/readers/Lata/arch.h +@@ -0,0 +1,34 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++ ++#ifndef arch_include_ ++#define arch_include_ ++typedef int entier; ++#endif ++ +diff --git a/databases/readers/Lata/avtlataFileFormat.C b/databases/readers/Lata/avtlataFileFormat.C +new file mode 100644 +index 0000000..2c4d27c +--- /dev/null ++++ b/databases/readers/Lata/avtlataFileFormat.C +@@ -0,0 +1,865 @@ ++/***************************************************************************** ++ * ++ * Copyright (c) 2000 - 2015, Lawrence Livermore National Security, LLC ++ * Produced at the Lawrence Livermore National Laboratory ++ * All rights reserved. ++ * ++ * This file is part of VisIt. For details, see http://www.llnl.gov/visit/. The ++ * full copyright notice is contained in the file COPYRIGHT located at the root ++ * of the VisIt distribution or at http://www.llnl.gov/visit/copyright.html. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * ++ * - Redistributions of source code must retain the above copyright notice, ++ * this list of conditions and the disclaimer below. ++ * - Redistributions in binary form must reproduce the above copyright notice, ++ * this list of conditions and the disclaimer (as noted below) in the ++ * documentation and/or materials provided with the distribution. ++ * - Neither the name of the UC/LLNL nor the names of its contributors may be ++ * used to endorse or promote products derived from this software without ++ * specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF ++ * CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR ++ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ++ *****************************************************************************/ ++ ++// ************************************************************************* // ++// avtlataFileFormat.C // ++// ************************************************************************* // ++ ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++// **************************************************************************** ++// Method: avtlata constructor ++// ++// Programmer: fauchet -- generated by xml2avt ++// ++// **************************************************************************** ++ ++avtlataFileFormat::avtlataFileFormat(const char *filename) ++ : avtMTMDFileFormat(filename) ++{ ++ debug1 << "avtlataFileFormat constructor " << filename << endl; ++ try { ++ set_Journal_level(0); ++ ++ LataOptions opt; ++ LataOptions::extract_path_basename(filename, opt.path_prefix, opt.basename); ++ opt.dual_mesh = true; ++ opt.faces_mesh = true; ++ opt.regularize = 2; ++ opt.regularize_tolerance = 1e-7; ++ opt.user_fields_=true; ++ read_any_format_options(filename, opt); ++ debug1 << "avtlataFileFormat: initializing filter" << endl; ++ // Read the source file to the lata database ++ read_any_format(filename, opt.path_prefix, lata_db_); ++ filter_.initialize(opt, lata_db_); ++ } ++ catch (LataDBError err) { ++ cerr << "Error in LataFilter::initialize " << filename << " " << err.describe() << endl; ++ throw; ++ } ++} ++ ++avtlataFileFormat::~avtlataFileFormat() ++{ ++} ++ ++// **************************************************************************** ++// Method: avtEMSTDFileFormat::GetNTimesteps ++// ++// Purpose: ++// Tells the rest of the code how many timesteps there are in this file. ++// ++// Programmer: fauchet -- generated by xml2avt ++// ++// **************************************************************************** ++ ++int ++avtlataFileFormat::GetNTimesteps(void) ++{ ++ int n; ++ try { ++ n = filter_.get_nb_timesteps(); ++ // Timestep 0 contains global definitions. ++ // If we have "real" timesteps, do not show timestep 0 ++ if (n > 1) ++ n--; ++ } ++ catch (LataDBError err) { ++ cerr << "Error in getntimesteps " << filename << " " << err.describe() << endl; ++ throw; ++ } ++ return n; ++} ++ ++void avtlataFileFormat::GetTimes(std::vector& times) ++{ ++ int n; ++ try { ++ n = filter_.get_nb_timesteps(); ++ if (n == 1) ++ times.push_back(0.); ++ else ++ for (int i = 1; i < n; i++) ++ times.push_back(filter_.get_timestep(i)); ++ } ++ catch (LataDBError err) { ++ cerr << "Error in gettimes " << filename << " " << err.describe() << endl; ++ throw; ++ } ++ return; ++} ++ ++// **************************************************************************** ++// Method: avtlataFileFormat::FreeUpResources ++// ++// Purpose: ++// When VisIt is done focusing on a particular timestep, it asks that ++// timestep to free up any resources (memory, file descriptors) that ++// it has associated with it. This method is the mechanism for doing ++// that. ++// ++// Programmer: fauchet -- generated by xml2avt ++// ++// **************************************************************************** ++ ++void ++avtlataFileFormat::FreeUpResources(void) ++{ ++} ++ ++ ++// **************************************************************************** ++// Method: avtlataFileFormat::PopulateDatabaseMetaData ++// ++// Purpose: ++// This database meta-data object is like a table of contents for the ++// file. By populating it, you are telling the rest of VisIt what ++// information it can request from you. ++// ++// Programmer: fauchet -- generated by xml2avt ++// ++// **************************************************************************** ++ ++void ++avtlataFileFormat::PopulateDatabaseMetaData(avtDatabaseMetaData *md, int timeState) ++{ ++ try { ++ debug1 << "avtlataFileFormat::PopulateDatabaseMetaData : " ++ << filename << " " << timeState << endl; ++ ++ const char *suffix_vector_names[] = { "_X", "_Y", "_Z" }; ++ const char *suffix_vector_expr[] = { "[0]", "[1]", "[2]" }; ++ ++ const Noms geoms = filter_.get_exportable_geometry_names(); ++ ++ for (int i_geom = 0; i_geom < geoms.size(); i_geom++) { ++ debug1 << " Domain : " << geoms[i_geom] << endl; ++ const LataGeometryMetaData data = filter_.get_geometry_metadata(geoms[i_geom]); ++ ++ avtMeshType mt = AVT_UNSTRUCTURED_MESH; ++ ++ if (data.is_ijk_==1) ++ { ++ mt = AVT_RECTILINEAR_MESH; ++ } ++ int block_origin = 0; ++ int topo_dim; ++ switch(data.element_type_) { ++ case Domain::point: topo_dim = 0; mt = AVT_POINT_MESH; break; ++ case Domain::line: topo_dim = 1; break; ++ case Domain::triangle: ++ case Domain::polygone: ++ case Domain::quadri: topo_dim = 2; break; ++ case Domain::tetra: ++ case Domain::prism6: ++ case Domain::polyedre: ++ case Domain::hexa: topo_dim = 3; break; ++ default: ++ cerr << "avtlataFileFormat::PopulateDatabaseMetaData error: unknown element type" << endl; ++ topo_dim = 3; ///TODO: this should be an error in default case! ++ EXCEPTION1(InvalidVariableException, ++ "avtlataFileFormat::PopulateDatabaseMetaData error: unknown element type"); ++ throw; ++ } ++ ++ int mesh_faces=0; ++ if (data.internal_name_.finit_par("_centerfaces")) ++ { ++ //cerr<<"la "<AddExpression(&v); ++ } ++ if (varname.find_first_of("/",0)==std::string::npos) ++ { ++ // On calcule la norme des vecteurs de premier niveau (pas de / dans le chemin) ++ Expression norme_v; ++ n = "norme_"; ++ n += varname; ++ norme_v.SetName(n); ++ n = "magnitude("; ++ n += varname; ++ n += ")"; ++ norme_v.SetDefinition(n); ++ norme_v.SetType(Expression::ScalarMeshVar); ++ md->AddExpression(&norme_v); ++ } ++ } ++ } else { ++ // Multiscalar field ++ // I chose to postfix the varname with the component name, perhaps not the best choice. ++ if (mesh_faces==0) ++ { ++ for (entier i_compo = 0; i_compo < data2.nb_components_; i_compo++) { ++ std::string varname2(data2.name_); ++ varname2 += "_"; ++ if (data2.component_names_.size() == data2.nb_components_) { ++ varname2 += data2.component_names_[i_compo]; ++ } else { ++ Nom n(i_compo); ++ varname2 += n; ++ } ++ varname2 += "_"; ++ varname2 += loc; ++ varname2 += "_"; ++ varname2 += geom_name; ++ register_fieldname(varname2.c_str(), fields[i_field], i_compo); ++ AddScalarVarToMetaData(md, varname2, geom_name, cent); ++ } ++ } ++ } ++ } ++ } ++ debug1 << "End avtlataFileFormat::PopulateDatabaseMetaData" << endl; ++ } ++ catch (LataDBError err) { ++ cerr << "Error in PopulateDatabaseMetaData " << err.describe() << endl; ++ throw; ++ } ++} ++ ++void ++avtlataFileFormat::register_fieldname(const char *visit_name, const Field_UName & uname, int component) ++{ ++ if (field_username_.rang(visit_name) >= 0) { ++ cerr << "Error in avtlataFileFormat::register_fieldname: duplicate field name " << visit_name << endl; ++ cerr << "Ignoring field" << endl; ++ return; ++ } ++ field_username_.add(visit_name); ++ field_uname_.add(uname); ++ field_component_.add(component); ++} ++ ++void ++avtlataFileFormat::register_meshname(const char *visit_name, const char *latafilter_name) ++{ ++ if (mesh_username_.rang(visit_name) >= 0) { ++ cerr << "Error in avtlataFileFormat::register_meshname: duplicate name " << visit_name << endl; ++ cerr << "Ignoring mesh" << endl; ++ return; ++ } ++ mesh_username_.add(visit_name); ++ mesh_latafilter_name_.add(latafilter_name); ++} ++ ++// **************************************************************************** ++// Method: avtlataFileFormat::GetMesh ++// ++// Purpose: ++// Gets the mesh associated with this file. The mesh is returned as a ++// derived type of vtkDataSet (ie vtkRectilinearGrid, vtkStructuredGrid, ++// vtkUnstructuredGrid, etc). ++// ++// Arguments: ++// timestate The index of the timestate. If GetNTimesteps returned ++// 'N' time steps, this is guaranteed to be between 0 and N-1. ++// domain The index of the domain. If there are NDomains, this ++// value is guaranteed to be between 0 and NDomains-1, ++// regardless of block origin. ++// meshname The name of the mesh of interest. This can be ignored if ++// there is only one mesh. ++// ++// Programmer: fauchet -- generated by xml2avt ++// ++// **************************************************************************** ++ ++vtkDataSet * ++avtlataFileFormat::GetMesh(int timestate, int block, const char *meshname) ++{ ++ vtkDataSet *return_value = 0; ++ try { ++ debug1 << " avtlataFileFormat::GetMesh ts=" << timestate ++ << " block=" << block ++ << " meshname=" << meshname << endl; ++ ++ // We have real timesteps in the database, add one to timestep index: ++ if (filter_.get_nb_timesteps() > 1) ++ timestate++; ++ ++ const entier index = mesh_username_.rang(meshname); ++ if (index < 0) { ++ cerr << "internal error in avtlataFileFormat::GetMesh: name " << meshname << " not found" << endl; ++ throw; ++ } ++ Domain_Id id(mesh_latafilter_name_[index], timestate, block); ++ const Domain & geometry = filter_.get_geometry(id); ++ ++ const DomainUnstructured * geom_ptr = dynamic_cast(&geometry); ++ const DomainIJK * ijk_ptr = dynamic_cast(&geometry); ++ ++ if (geom_ptr) { ++ const DomainUnstructured & geom = *geom_ptr; ++ ++ vtkUnstructuredGrid *ugrid = vtkUnstructuredGrid::New(); ++ vtkPoints *points = vtkPoints::New(); ++ const FloatTab & pos = geom.nodes_; ++ const int nnodes = pos.dimension(0); ++ const int dim3 = pos.dimension(1) == 3; ++ points->SetNumberOfPoints(nnodes); ++ float* pts = (float *) points->GetVoidPointer(0); ++ int jl=0; ++ int i; ++ for (i = 0; i < nnodes; i++) { ++ pts[jl] = pos(i,0); ++ pts[jl+1] = pos(i,1); ++ pts[jl+2] = dim3 ? pos(i,2) : 0.; ++ jl+=3; ++ } ++ ugrid->SetPoints(points); ++ points->Delete(); ++ ++ const IntTab & conn = geom.elements_; ++ const IntTab & elem_faces = geom.elem_faces_; ++ const IntTab & faces = geom.faces_; ++ const int ncells = conn.dimension(0); ++ int nverts = conn.dimension(1); ++ ++ int type_cell; ++ switch (geom.elt_type_) { ++ case Domain::point: ++ type_cell=VTK_VERTEX; ++ if (ncells == 0) ++ nverts = 1; ++ break; ++ case Domain::line: ++ type_cell=VTK_LINE; ++ break; ++ case Domain::triangle: ++ type_cell=VTK_TRIANGLE; ++ break; ++ case Domain::quadri: ++ type_cell=VTK_QUAD; ++ break; ++ case Domain::tetra: ++ type_cell=VTK_TETRA; ++ break; ++ case Domain::prism6: ++ type_cell=VTK_WEDGE; ++ break; ++ case Domain::hexa: ++ type_cell=VTK_HEXAHEDRON; ++ break; ++ case Domain::polygone: ++ type_cell=VTK_POLYGON; ++ break; ++ case Domain::polyedre: ++ type_cell= elem_faces.dimension(0) > 0 ? VTK_POLYHEDRON : VTK_CONVEX_POINT_SET; ++ break; ++ default: ++ type_cell=-1; ++ cerr<<"avtlataFileFormat::GetMesh unknown elt type "< poly_p, poly_f; ++ if (type_cell == VTK_VERTEX && ncells == 0) { ++ // Cells are implicit. Create them: ++ ugrid->Allocate(nnodes); ++ for (i = 0; i < nnodes; i++) { ++ verts[0] = i; ++ ugrid->InsertNextCell(type_cell, nverts, verts); ++ } ++ } else { ++ ugrid->Allocate(ncells); ++ for (i = 0; i < ncells; i++) { ++ if (type_cell==VTK_QUAD) { ++ // Nodes order is different in visit than in trio_u ++ verts[0]=conn(i,0); ++ verts[1]=conn(i,1); ++ verts[2]=conn(i,3); ++ verts[3]=conn(i,2); ++ } else if (type_cell==VTK_HEXAHEDRON) { ++ // Nodes order is different in visit than in trio_u ++ verts[0]=conn(i,0); ++ verts[1]=conn(i,1); ++ verts[2]=conn(i,3); ++ verts[3]=conn(i,2); ++ verts[4]=conn(i,4); ++ verts[5]=conn(i,5); ++ verts[6]=conn(i,7); ++ verts[7]=conn(i,6); ++ } else if (type_cell==VTK_POLYHEDRON) { ++ //polyhedra, face by face ++ int j, nfaces = 0, npts = 0, k, i_f, s, f; ++ poly_p.resize(0), poly_f.resize(0); ++ for (j = 0; j < conn.dimension(1); j++) if ((s = conn(i, j)) >= 0) poly_p.push_back(s), npts++; ++ for (j = 0; j < elem_faces.dimension(1); j++) if ((f = elem_faces(i, j)) >= 0) ++ 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) ++ poly_f.push_back(s), poly_f[i_f]++; ++ ugrid->InsertNextCell(type_cell, npts, &poly_p[0], nfaces, &poly_f[0]); ++ } else if ((type_cell==VTK_CONVEX_POINT_SET)||(type_cell==VTK_POLYGON)) { ++ int nverts_loc=nverts; ++ for (int j = 0; j < nverts; j++) ++ { ++ verts[j] = conn(i,j); ++ ++ if (verts[j]<=-1) ++ { ++ nverts_loc=j; ++ break; ++ } ++ /* else ++ { ++ if (verts[j]<-1) ++ { ++ std::cerr<=6) && (nverts_loc==6)) ++ ugrid->InsertNextCell(VTK_WEDGE, nverts_loc, verts); ++ else if ((nb_som_max_to_regularize>=12)&&(nverts_loc==12)) ++ ugrid->InsertNextCell(VTK_HEXAGONAL_PRISM, nverts_loc, verts); ++ else if ((nb_som_max_to_regularize>=8)&&(nverts_loc==8)) ++ { ++ // Nodes order is different in visit than in trio_u ++ verts[0]=conn(i,0); ++ verts[1]=conn(i,1); ++ verts[2]=conn(i,3); ++ verts[3]=conn(i,2); ++ verts[4]=conn(i,4); ++ verts[5]=conn(i,5); ++ verts[6]=conn(i,7); ++ verts[7]=conn(i,6); ++ ugrid->InsertNextCell(VTK_HEXAHEDRON, nverts_loc, verts); ++ ++ } ++ else ++ ugrid->InsertNextCell(type_cell, nverts_loc, verts); ++ } ++ else { ++ for (int j = 0; j < nverts; j++) ++ verts[j] = conn(i,j); ++ } ++ if ((type_cell!=VTK_POLYHEDRON) &&(type_cell!=VTK_CONVEX_POINT_SET) && (type_cell!=VTK_POLYGON)) ++ ++ ugrid->InsertNextCell(type_cell, nverts, verts); ++ } ++ } ++ delete [] verts; ++ verts = 0; ++ // Declare ghost elements: ++ const int n = geom.nb_virt_items(LataField_base::ELEM); ++ if (n > 0) { ++ unsigned char realVal = 0; ++ unsigned char ghost = 0; // Sera modifie par AddGhostZoneType ++ avtGhostData::AddGhostZoneType(ghost, DUPLICATED_ZONE_INTERNAL_TO_PROBLEM); ++ vtkUnsignedCharArray *ghostcells = vtkUnsignedCharArray::New(); ++ ghostcells->SetName("avtGhostZones"); ++ ghostcells->SetNumberOfTuples(ncells); ++ unsigned char *dat = (unsigned char *) ghostcells->GetVoidPointer(0); ++ for (i = 0; i < ncells - n; i++) ++ dat[i] = realVal; ++ for (i = ncells - n; i < ncells; i++) ++ dat[i] = ghost; ++ ugrid->GetCellData()->AddArray(ghostcells); ++ ugrid->GetInformation()->Set( ++ vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), 0); ++ ghostcells->Delete(); ++ } ++ return_value = ugrid; ++ ++ } else if (ijk_ptr) { ++ const DomainIJK & geom = *ijk_ptr; ++ ++ // Maillage regulier : on transmet la grille ijk ++ vtkRectilinearGrid *sgrid = vtkRectilinearGrid::New(); ++ ++ const int dim = geom.coord_.size(); ++ ArrOfInt ncoord(3, 1); ++ int i; ++ for (i = 0; i < dim; i++) ++ ncoord[i] = geom.coord_[i].size_array(); ++ sgrid->SetDimensions(ncoord[0], ncoord[1], ncoord[2]); ++ ++ for (i = 0; i < 3; i++) { ++ float *data; ++ vtkFloatArray *c; ++ c = vtkFloatArray::New(); ++ const int n = ncoord[i]; ++ c->SetNumberOfTuples(n); ++ data = (float *) c->GetVoidPointer(0); ++ if (i < dim) { ++ const ArrOfFloat & coord = geom.coord_[i]; ++ for (int j = 0; j < n; j++) ++ data[j] = coord[j]; ++ } else { ++ data[0] = 0.; ++ } ++ switch(i) { ++ case 0: sgrid->SetXCoordinates(c); break; ++ case 1: sgrid->SetYCoordinates(c); break; ++ case 2: sgrid->SetZCoordinates(c); break; ++ default: ; ++ } ++ c->Delete(); ++ } ++ // Create "invalid cells" data (GettingDataIntoVisit.pdf, page 136) ++ // and "ghost cells" ++ const int n = geom.invalid_connections_.size_array(); ++ if (n > 0 || geom.virtual_layer_begin_ || geom.virtual_layer_end_) { ++ const int ncells = geom.nb_elements(); ++ unsigned char realVal = 0; ++ unsigned char invalid = 0; // Sera modifie par AddGhostZoneType ++ unsigned char ghost = 0; ++ avtGhostData::AddGhostZoneType(invalid, ZONE_NOT_APPLICABLE_TO_PROBLEM); ++ avtGhostData::AddGhostZoneType(ghost, DUPLICATED_ZONE_INTERNAL_TO_PROBLEM); ++ vtkUnsignedCharArray *ghostcells = vtkUnsignedCharArray::New(); ++ ghostcells->SetName("avtGhostZones"); ++ ghostcells->SetNumberOfTuples(ncells); ++ unsigned char *dat = (unsigned char *) ghostcells->GetVoidPointer(0); ++ ++ for (i = 0; i < ncells; i++) ++ dat[i] = realVal; ++ ++ if (n > 0) { ++ // invalid cells ++ for (i = 0; i < ncells; i++) { ++ if (geom.invalid_connections_[i]) ++ dat[i] = invalid; ++ } ++ } ++ ++ // ghost cells ++ entier ij = 1; ++ for (i = 0; i < dim-1; i++) ++ ij *= ncoord[i]-1; ++ if (geom.virtual_layer_begin_) { ++ // first layer of cells is ghost ++ for (i = 0; i < ij * geom.virtual_layer_begin_; i++) ++ dat[i] += ghost; ++ } ++ if (geom.virtual_layer_end_) { ++ // last layer of cells is ghost ++ for (i = ncells - ij * geom.virtual_layer_end_; i < ncells; i++) ++ dat[i] += ghost; ++ } ++ ++ sgrid->GetCellData()->AddArray(ghostcells); ++ sgrid->GetInformation()->Set( ++ vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), 0); ++ ghostcells->Delete(); ++ } ++ ++ return_value = sgrid; ++ } else { ++ cerr << "Error in avtlataFileFormat::GetMesh: unknown geometry type" << endl; ++ throw; ++ } ++ ++ filter_.release_geometry(geometry); ++ } ++ catch (LataDBError err) { ++ cerr << "Error in getmesh " << timestate << " " << block << " " << meshname << " " << err.describe() << endl; ++ throw; ++ } ++ ++ return return_value; ++} ++ ++ ++// **************************************************************************** ++// Method: avtlataFileFormat::GetVar ++// ++// Purpose: ++// Gets a scalar variable associated with this file. Although VTK has ++// support for many different types, the best bet is vtkFloatArray, since ++// that is supported everywhere through VisIt. ++// ++// Arguments: ++// timestate The index of the timestate. If GetNTimesteps returned ++// 'N' time steps, this is guaranteed to be between 0 and N-1. ++// domain The index of the domain. If there are NDomains, this ++// value is guaranteed to be between 0 and NDomains-1, ++// regardless of block origin. ++// varname The name of the variable requested. ++// ++// Programmer: fauchet -- generated by xml2avt ++// ++// **************************************************************************** ++ ++vtkDataArray * ++avtlataFileFormat::GetVar(int timestate, int block, const char *varname) ++{ ++ vtkDataArray * return_value = 0; ++ try { ++ debug1 << "Getvar time:" << timestate ++ << " block:" << block ++ << " varname:" << varname << endl; ++ ++ if (filter_.get_nb_timesteps() > 1) ++ timestate++; ++ ++ Field_UName field_uname; ++ int component; ++ get_field_info_from_visitname(varname, field_uname, component); ++ ++ if (component < 0) { ++ cerr << "Error: avtlataFileFormat::GetVar called for vector field" << endl; ++ throw; ++ } ++ ++ Field_Id id(field_uname, timestate, block); ++ ++ const LataField_base & field = filter_.get_field(id); ++ ++ const Field * float_field_ptr = dynamic_cast*>(&field); ++ const Field * int_field_ptr = dynamic_cast*>(&field); ++ ++ if (float_field_ptr) { ++ vtkFloatArray *rv = vtkFloatArray::New(); ++ const Field & fld = *float_field_ptr; ++ const FloatTab & values = fld.data_; ++ int ntuples = values.dimension(0); ++ rv->SetNumberOfTuples(ntuples); ++ float * data = rv->GetPointer(0); ++ for (int i = 0; i < ntuples; i++) ++ data[i] = values(i, component); ++ return_value = rv; ++ } else if (int_field_ptr) { ++ vtkIntArray *rv = vtkIntArray::New(); ++ const Field & fld = *int_field_ptr; ++ const IntTab & values = fld.data_; ++ int ntuples = values.dimension(0); ++ rv->SetNumberOfTuples(ntuples); ++ int * data = rv->GetPointer(0); ++ for (int i = 0; i < ntuples; i++) ++ data[i] = values(i, component); ++ return_value = rv; ++ } else { ++ cerr << "Error in avtlataFileFormat::GetVar: unknown data type" << endl; ++ throw; ++ } ++ filter_.release_field(field); ++ } ++ catch (LataDBError err) { ++ cerr << "Error in getvar " << timestate << " " << block << " " << varname << " " << err.describe() << endl; ++ throw; ++ } ++ return return_value; ++} ++ ++ ++// **************************************************************************** ++// Method: avtlataFileFormat::GetVectorVar ++// ++// Purpose: ++// Gets a vector variable associated with this file. Although VTK has ++// support for many different types, the best bet is vtkFloatArray, since ++// that is supported everywhere through VisIt. ++// ++// Arguments: ++// timestate The index of the timestate. If GetNTimesteps returned ++// 'N' time steps, this is guaranteed to be between 0 and N-1. ++// domain The index of the domain. If there are NDomains, this ++// value is guaranteed to be between 0 and NDomains-1, ++// regardless of block origin. ++// varname The name of the variable requested. ++// ++// Programmer: fauchet -- generated by xml2avt ++// ++// **************************************************************************** ++ ++vtkDataArray * ++avtlataFileFormat::GetVectorVar(int timestate, int block, const char *varname) ++{ ++ vtkDataArray * return_value = 0; ++ try { ++ debug1 << "Getvectorvar time:" << timestate ++ << " block:" << block ++ << " varname:" << varname << endl; ++ ++ if (filter_.get_nb_timesteps() > 1) ++ timestate++; ++ ++ Field_UName field_uname; ++ int component; ++ get_field_info_from_visitname(varname, field_uname, component); ++ ++ if (component >= 0) { ++ cerr << "Error: avtlataFileFormat::GetVectorVar called for scalar field" << endl; ++ throw; ++ } ++ ++ Field_Id id(field_uname, timestate, block); ++ ++ const LataField_base & field = filter_.get_field(id); ++ ++ const Field * float_field_ptr = dynamic_cast*>(&field); ++ const Field * int_field_ptr = dynamic_cast*>(&field); ++ ++ if (float_field_ptr) { ++ vtkFloatArray *rv = vtkFloatArray::New(); ++ const Field & fld = *float_field_ptr; ++ const FloatTab & values = fld.data_; ++ int ntuples = values.dimension(0); ++ int dim = values.dimension(1); ++ rv->SetNumberOfComponents(3); ++ rv->SetNumberOfTuples(ntuples); ++ float* data= rv->WritePointer(0,3*ntuples); ++ for (int i = 0; i < ntuples; i++) ++ for (int j = 0; j < 3; j++) ++ data[i*3+j] = (j & fld = *int_field_ptr; ++ const IntTab & values = fld.data_; ++ int ntuples = values.dimension(0); ++ int dim = values.dimension(1); ++ rv->SetNumberOfComponents(3); ++ rv->SetNumberOfTuples(ntuples); ++ int* data= rv->WritePointer(0,3*ntuples); ++ for (int i = 0; i < ntuples; i++) ++ for (int j = 0; j < 3; j++) ++ data[i*3+j] = (j ++ ++#include ++#include "LataFilter.h" ++ ++// **************************************************************************** ++// Class: avtlataFileFormat ++// ++// Purpose: ++// Reads in lata files as a plugin to VisIt. ++// ++// Programmer: fauchet -- generated by xml2avt ++// ++// **************************************************************************** ++ ++class avtlataFileFormat : public avtMTMDFileFormat ++{ ++ public: ++ avtlataFileFormat(const char *); ++ virtual ~avtlataFileFormat(); ++ ++ // ++ // This is used to return unconvention data -- ranging from material ++ // information to information about block connectivity. ++ // ++ // virtual void *GetAuxiliaryData(const char *var, const char *type, ++ // int timestep, int domain,void *args, ++ // DestructorFunction &); ++ // ++ ++ // ++ // If you know the times and cycle numbers, overload this function. ++ // Otherwise, VisIt will make up some reasonable ones for you. ++ // ++ // virtual void GetCycles(std::vector &); ++ // virtual void GetTimes(std::vector &); ++ // ++ ++ virtual int GetNTimesteps(void); ++ ++ virtual const char *GetType(void) { return "lata"; }; ++ virtual void FreeUpResources(void); ++ ++ virtual vtkDataSet *GetMesh(int, int, const char *); ++ virtual vtkDataArray *GetVar(int, int, const char *); ++ virtual vtkDataArray *GetVectorVar(int, int, const char *); ++ virtual void GetTimes(std::vector& times); ++ protected: ++ // DATA MEMBERS ++ ++ virtual void PopulateDatabaseMetaData(avtDatabaseMetaData *, int); ++ ++ void register_fieldname(const char *visit_name, const Field_UName &, int component); ++ void register_meshname(const char *visit_name, const char *latafilter_name); ++ void get_field_info_from_visitname(const char *varname, Field_UName &, int & component) const; ++ ++ LataDB lata_db_; // Source database ++ LataFilter filter_; // Data processor and cache ++ Noms field_username_; ++ Field_UNames field_uname_; ++ ++ Noms mesh_username_; ++ Noms mesh_latafilter_name_; ++ ++ // For each name, which component is it in the source field: ++ LataVector field_component_; ++}; ++ ++ ++#endif +diff --git a/databases/readers/Lata/simd_interface.h b/databases/readers/Lata/simd_interface.h +new file mode 100644 +index 0000000..e14c409 +--- /dev/null ++++ b/databases/readers/Lata/simd_interface.h +@@ -0,0 +1,31 @@ ++/***************************************************************************** ++* ++* Copyright (c) 2011 - 2013, CEA ++* All rights reserved. ++* Redistribution and use in source and binary forms, with or without ++* modification, are permitted provided that the following conditions are met: ++* ++* * Redistributions of source code must retain the above copyright ++* notice, this list of conditions and the following disclaimer. ++* * Redistributions in binary form must reproduce the above copyright ++* notice, this list of conditions and the following disclaimer in the ++* documentation and/or other materials provided with the distribution. ++* * Neither the name of CEA, nor the ++* names of its contributors may be used to endorse or promote products ++* derived from this software without specific prior written permission. ++* ++* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY ++* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY ++* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++* ++*****************************************************************************/ ++#ifdef WITH_SIMD ++#include "simd_tools.h" ++#endif +diff --git a/databases/visit_readers.xml b/databases/visit_readers.xml +index 0b1405c..05aa776 100644 +--- a/databases/visit_readers.xml ++++ b/databases/visit_readers.xml +@@ -781,6 +781,19 @@ + + + ++ ++ ++ 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 ++ The default file extensions is .lata ++ ++ ++ ++ ++ ++ + + +Date: Fri, 13 Mar 2020 10:48:30 +0100 +Subject: [PATCH 2/3] vtkUnstructuredGridRelevantPointsFilter: fix for + polyhedra + +--- + .../vtkUnstructuredGridRelevantPointsFilter.C | 67 ++++++++----------- + 1 file changed, 27 insertions(+), 40 deletions(-) + +diff --git a/Library/VisItLib/visit_vtk/full/vtkUnstructuredGridRelevantPointsFilter.C b/Library/VisItLib/visit_vtk/full/vtkUnstructuredGridRelevantPointsFilter.C +index 5c73502..c4e772c 100644 +--- a/Library/VisItLib/visit_vtk/full/vtkUnstructuredGridRelevantPointsFilter.C ++++ b/Library/VisItLib/visit_vtk/full/vtkUnstructuredGridRelevantPointsFilter.C +@@ -116,29 +116,21 @@ vtkUnstructuredGridRelevantPointsFilter::RequestData( + { + pointMap[i] = -1; + } +- vtkCellArray *cells = input->GetCells(); +- auto cellIter = vtk::TakeSmartPointer(cells->NewIterator()); ++ + int numOutPts = 0; +- for (cellIter->GoToFirstCell(); +- !cellIter->IsDoneWithTraversal(); +- cellIter->GoToNextCell()) ++ vtkIdList *list = vtkIdList::New(); ++ for (i = 0; i < numCells; i++) + { +- vtkIdList *cell = cellIter->GetCurrentCell(); +- int npts = static_cast(cell->GetNumberOfIds()); +- for (j = 0 ; j < npts ; j++) +- { +- int oldPt = static_cast(cell->GetId(j)); +- if (pointMap[oldPt] == -1) +- pointMap[oldPt] = numOutPts++; +- } ++ input->GetCellPoints(i, list); ++ for (j = 0; j < list->GetNumberOfIds(); j++) if (pointMap[list->GetId(j)] < 0) pointMap[list->GetId(j)] = numOutPts++; + } + +- vtkPoints *newPts = vtkPoints::New(input->GetPoints()->GetDataType()); +- newPts->SetNumberOfPoints(numOutPts); + vtkPointData *inputPD = input->GetPointData(); + vtkPointData *outputPD = output->GetPointData(); + outputPD->CopyAllocate(inputPD, numOutPts); + ++ vtkPoints *newPts = vtkPoints::New(input->GetPoints()->GetDataType()); ++ newPts->SetNumberOfPoints(numOutPts); + for (j = 0 ; j < numInPts ; j++) + { + if (pointMap[j] != -1) +@@ -149,43 +141,38 @@ vtkUnstructuredGridRelevantPointsFilter::RequestData( + outputPD->CopyData(inputPD, j, pointMap[j]); + } + } ++ output->SetPoints(newPts); + + vtkCellData *inputCD = input->GetCellData(); + vtkCellData *outputCD = output->GetCellData(); + outputCD->PassData(inputCD); +- +- vtkIdList *cellIds = vtkIdList::New(); +- +- output->SetPoints(newPts); +- +- // now work through cells, changing associated point id to coincide +- // with the new ones as specified in the pointmap; + +- vtkIdList *oldIds = vtkIdList::New(); +- vtkIdList *newIds = vtkIdList::New(); +- int id, cellType; +- cellIter = vtk::TakeSmartPointer(cells->NewIterator()); +- for (cellIter->GoToFirstCell(); +- !cellIter->IsDoneWithTraversal(); +- cellIter->GoToNextCell()) ++ std::vector points, faces; ++ for (i = 0; i < numCells; i++) + { +- vtkIdList *cell = cellIter->GetCurrentCell(); +- cellType = input->GetCellType(cellIter->GetCurrentCellId()); +- int npts = static_cast(cell->GetNumberOfIds()); ++ int CellType = input->GetCellType(i); ++ points.resize(0), faces.resize(0); ++ input->GetCellPoints(i, list); ++ ++ for (j = 0; j < list->GetNumberOfIds(); j++) points.push_back(pointMap[list->GetId(j)]); + +- newIds->SetNumberOfIds(npts); +- for (j = 0; j < npts ; j++) ++ if (CellType == VTK_POLYHEDRON) //must deal with faces stream + { +- id = cell->GetId(j); +- newIds->SetId(j, pointMap[id]); ++ input->GetFaceStream(i, list); ++ int nfaces = list->GetId(0), idx = 1; ++ for (j = 0; j < nfaces; j++) ++ { ++ int npts = list->GetId(idx); ++ faces.push_back(npts), idx++; ++ for (int k = 0; k < npts; k++) faces.push_back(pointMap[list->GetId(idx)]), idx++; ++ } ++ output->InsertNextCell(CellType, points.size(), &points[0], nfaces, &faces[0]); + } +- output->InsertNextCell(cellType, newIds); ++ else output->InsertNextCell(CellType, points.size(), &points[0]); + } + + newPts->Delete(); +- oldIds->Delete(); +- newIds->Delete(); +- cellIds->Delete(); ++ list->Delete(); + delete [] pointMap; + + return 1; +-- +2.17.0 + diff --git a/config/patches/paraview.0003-ParaViewClient.patch b/config/patches/paraview.0003-ParaViewClient.patch new file mode 100644 index 0000000..5245133 --- /dev/null +++ b/config/patches/paraview.0003-ParaViewClient.patch @@ -0,0 +1,10 @@ +--- ParaView-5.8.0-RC2.orig/CMake/ParaViewClient.cmake 2020-03-02 15:38:53.791382799 +0300 ++++ ParaView-5.8.0-RC2.new/CMake/ParaViewClient.cmake 2020-03-02 18:31:04.304698442 +0300 +@@ -516,6 +516,7 @@ + NAMES xmlpatterns-qt5 xmlpatterns + HINTS "${Qt5_DIR}/../../../bin" + "${Qt5_DIR}/../../../libexec/qt5/bin" ++ NO_CMAKE_PATH + DOC "Path to xmlpatterns") + mark_as_advanced(qt_xmlpatterns_executable) + diff --git a/config/patches/paraview.0004-ParaView_hdf5.patch b/config/patches/paraview.0004-ParaView_hdf5.patch new file mode 100644 index 0000000..699226f --- /dev/null +++ b/config/patches/paraview.0004-ParaView_hdf5.patch @@ -0,0 +1,14 @@ +diff -Naur ParaView-5.8.0_SRC_orig/VTK/ThirdParty/hdf5/CMakeLists.txt ParaView-5.8.0_SRC_modif/VTK/ThirdParty/hdf5/CMakeLists.txt +--- ParaView-5.8.0_SRC_orig/VTK/ThirdParty/hdf5/CMakeLists.txt 2020-03-31 15:23:53.279485815 +0300 ++++ ParaView-5.8.0_SRC_modif/VTK/ThirdParty/hdf5/CMakeLists.txt 2020-03-31 13:59:17.768118278 +0300 +@@ -10,8 +10,8 @@ + EXTERNAL + PACKAGE HDF5 + COMPONENTS C HL +- TARGETS hdf5::hdf5 +- hdf5::hdf5_hl ++ TARGETS hdf5::hdf5-shared ++ hdf5::hdf5_hl-shared + USE_VARIABLES HDF5_IS_PARALLEL + STANDARD_INCLUDE_DIRS) + diff --git a/config/patches/paraview.0005-ParaView_find_cgns.patch b/config/patches/paraview.0005-ParaView_find_cgns.patch new file mode 100644 index 0000000..d636c32 --- /dev/null +++ b/config/patches/paraview.0005-ParaView_find_cgns.patch @@ -0,0 +1,15 @@ +diff -Naur ParaView-5.8.0_SRC_orig/CMake/FindCGNS.cmake ParaView-5.8.0_SRC_modif/CMake/FindCGNS.cmake +--- ParaView-5.8.0_SRC_orig/CMake/FindCGNS.cmake 2020-03-23 13:27:34.000000000 +0300 ++++ ParaView-5.8.0_SRC_modif/CMake/FindCGNS.cmake 2020-04-09 16:21:57.263362265 +0300 +@@ -5,6 +5,11 @@ + # CGNS_LIBRARIES - List of fully qualified libraries to link against when using CGNS. + # CGNS_FOUND - Do not attempt to use CGNS if "no" or undefined. + ++SET(CGNS_ROOT_DIR $ENV{CGNS_ROOT_DIR} CACHE PATH "Path to the CGNS.") ++IF(CGNS_ROOT_DIR) ++ LIST(APPEND CMAKE_PREFIX_PATH "${CGNS_ROOT_DIR}") ++ENDIF(CGNS_ROOT_DIR) ++ + find_path(CGNS_INCLUDE_DIR + NAMES + cgnslib.h diff --git a/config/patches/paraview.0006-ParaView_find_libxml2.patch b/config/patches/paraview.0006-ParaView_find_libxml2.patch new file mode 100644 index 0000000..a741d50 --- /dev/null +++ b/config/patches/paraview.0006-ParaView_find_libxml2.patch @@ -0,0 +1,14 @@ +--- ParaView-5.8.0_SRC_orig/VTK/CMake/FindLibXml2.cmake 2020-03-23 22:17:27.000000000 +0100 ++++ ParaView-5.8.0_SRC_modif/VTK/CMake/FindLibXml2.cmake 2020-04-10 09:56:00.627562062 +0200 +@@ -53,6 +53,11 @@ + PKG_CHECK_MODULES(PC_LIBXML QUIET libxml-2.0) + set(LIBXML2_DEFINITIONS ${PC_LIBXML_CFLAGS_OTHER}) + ++SET(LIBXML2_ROOT_DIR $ENV{LIBXML2_ROOT_DIR} CACHE PATH "Path to the LIBXML2.") ++IF(LIBXML2_ROOT_DIR) ++ LIST(APPEND CMAKE_PREFIX_PATH "${LIBXML2_ROOT_DIR}") ++ENDIF(LIBXML2_ROOT_DIR) ++ + find_path(LIBXML2_INCLUDE_DIR NAMES libxml/xpath.h + HINTS + ${PC_LIBXML_INCLUDEDIR} diff --git a/config/patches/paraview.0007-ParaView_find_freetype.patch b/config/patches/paraview.0007-ParaView_find_freetype.patch new file mode 100644 index 0000000..04e86fa --- /dev/null +++ b/config/patches/paraview.0007-ParaView_find_freetype.patch @@ -0,0 +1,15 @@ +diff -Naur ParaView-5.8.0_SRC_orig/VTK/CMake/FindFreetype.cmake ParaView-5.8.0_SRC_modif/VTK/CMake/FindFreetype.cmake +--- ParaView-5.8.0_SRC_orig/VTK/CMake/FindFreetype.cmake 2020-03-23 13:31:26.000000000 +0300 ++++ ParaView-5.8.0_SRC_modif/VTK/CMake/FindFreetype.cmake 2020-04-10 22:27:24.194525121 +0300 +@@ -63,6 +63,11 @@ + # I'm going to attempt to cut out the middleman and hope + # everything still works. + ++SET(FREETYPE_ROOT_DIR $ENV{FREETYPE_ROOT_DIR} CACHE PATH "Path to the FreeType.") ++IF(FREETYPE_ROOT_DIR) ++ LIST(APPEND CMAKE_PREFIX_PATH "${FREETYPE_ROOT_DIR}") ++ENDIF(FREETYPE_ROOT_DIR) ++ + set(FREETYPE_FIND_ARGS + HINTS + ENV FREETYPE_DIR diff --git a/config/patches/paraview.001_against_multiple_py_sv_thr.patch b/config/patches/paraview.001_against_multiple_py_sv_thr.patch deleted file mode 100644 index 33059a2..0000000 --- a/config/patches/paraview.001_against_multiple_py_sv_thr.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff -ruN ParaView/VTK/Utilities/PythonInterpreter/vtkPythonInterpreter.cxx ParaView_new/VTK/Utilities/PythonInterpreter/vtkPythonInterpreter.cxx ---- ParaView/VTK/Utilities/PythonInterpreter/vtkPythonInterpreter.cxx 2019-05-28 08:19:55.673481437 +0200 -+++ ParaView_new/VTK/Utilities/PythonInterpreter/vtkPythonInterpreter.cxx 2019-05-28 08:08:21.000000000 +0200 -@@ -260,8 +260,11 @@ - vtkPythonInterpreter::InitializedOnce = true; - - #ifdef VTK_PYTHON_FULL_THREADSAFE -- PyEval_InitThreads(); // safe to call this multiple time -- PyEval_SaveThread(); // release GIL -+ if(PyEval_ThreadsInitialized() == 0) -+ { -+ PyEval_InitThreads(); // safe to call this multiple time -+ PyEval_SaveThread(); // release GIL -+ } - #endif - - // HACK: Calling PyRun_SimpleString for the first time for some reason results in diff --git a/config/patches/paraview.002_statestorage_bug.patch b/config/patches/paraview.002_statestorage_bug.patch deleted file mode 100644 index 0115740..0000000 --- a/config/patches/paraview.002_statestorage_bug.patch +++ /dev/null @@ -1,34 +0,0 @@ -diff -Naur ParaView-5.6.0-bfaf7b82_SRC_orig/VTK/Rendering/OpenGL2/vtkStateStorage.h ParaView-5.6.0-bfaf7b82_SRC_modif/VTK/Rendering/OpenGL2/vtkStateStorage.h ---- ParaView-5.6.0-bfaf7b82_SRC_orig/VTK/Rendering/OpenGL2/vtkStateStorage.h 2019-06-25 16:00:38.000000000 +0300 -+++ ParaView-5.6.0-bfaf7b82_SRC_modif/VTK/Rendering/OpenGL2/vtkStateStorage.h 2019-07-12 11:32:00.000000000 +0300 -@@ -51,8 +51,11 @@ - - #include - #include -+#include - --#ifndef NDEBUG // a debug implementation -+// uncomment the folowing line to add in state debugging information -+//#define USE_STATE_DEBUGGING 1 -+#ifdef USE_STATE_DEBUGGING - - class VTKRENDERINGOPENGL2_EXPORT vtkStateStorage - { -@@ -120,7 +123,7 @@ - this->Storage.insert(this->Storage.end(), start, start + sizeof(T)); - } - --#else // release implementation -+#else // normal implementation - - class VTKRENDERINGOPENGL2_EXPORT vtkStateStorage - { -@@ -157,7 +160,7 @@ - this->Storage.insert(this->Storage.end(), start, start + sizeof(T)); - } - --#endif // Release implementation -+#endif // normal implementation - - #endif // vtkStateStorage_h - diff --git a/config/patches/paraview.004_forwarding.patch b/config/patches/paraview.004_forwarding.patch deleted file mode 100644 index 22f698a..0000000 --- a/config/patches/paraview.004_forwarding.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Naur ParaView-5.0.0_SRC_orig/CMake/pvForwardingExecutable.cmake ParaView-5.0.0_SRC_modif/CMake/pvForwardingExecutable.cmake ---- ParaView-5.0.0_SRC_orig/CMake/pvForwardingExecutable.cmake 2015-12-16 20:09:48.000000000 +0300 -+++ ParaView-5.0.0_SRC_modif/CMake/pvForwardingExecutable.cmake 2016-01-15 18:01:57.000000000 +0300 -@@ -81,7 +81,7 @@ - add_executable(${exe_name}${PV_EXE_SUFFIX} - ${CMAKE_CURRENT_BINARY_DIR}/${exe_name}-forward.c) - set_target_properties(${exe_name}${PV_EXE_SUFFIX} PROPERTIES -- RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/launcher) -+ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/launcher COMPILE_FLAGS -O2) - set_target_properties(${exe_name}${PV_EXE_SUFFIX} PROPERTIES - OUTPUT_NAME ${exe_name}) - add_dependencies(${exe_name}${PV_EXE_SUFFIX} ${exe_name}) -- 2.30.2