From: cs Date: Fri, 9 Mar 2007 14:29:06 +0000 (+0000) Subject: Module MULTIPR X-Git-Tag: MULTIPR_1 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=1cabb28ebdb266aa36cdac8ac7af7491ed53c8b8;p=modules%2Fmultipr.git Module MULTIPR --- 1cabb28ebdb266aa36cdac8ac7af7491ed53c8b8 diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..adabbd3 --- /dev/null +++ b/INSTALL @@ -0,0 +1 @@ +SALOME2 : MULTIPR module diff --git a/MULTIPR_version.h.in b/MULTIPR_version.h.in new file mode 100644 index 0000000..69335a1 --- /dev/null +++ b/MULTIPR_version.h.in @@ -0,0 +1,34 @@ +// Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ +// +// File : MULTIPR_version.h +// Author : Vadim SANDLER +// Module : SALOME + +#if !defined(__MULTIPR_VERSION_H__) +#define __MULTIPR_VERSION_H__ + +/* + MULTIPR_VERSION is (major << 16) + (minor << 8) + patch. +*/ + +#define MULTIPR_VERSION_STR "@VERSION@" +#define MULTIPR_VERSION @XVERSION@ + +#endif // __MULTIPR_VERSION_H__ diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..1eeeb2f --- /dev/null +++ b/Makefile.in @@ -0,0 +1,121 @@ +# Copyright (C) 2005 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +# -* Makefile *- +# +# Author : C. Caremoli +# Date : 10/10/2003 +# $Header$ +# + +# source path +top_srcdir=@top_srcdir@ +top_builddir=. +srcdir=@srcdir@ +VPATH=.:@srcdir@:@top_srcdir@/bin:./bin/salome:./resources:@top_srcdir@/resources:./bin:@top_srcdir@/idl + + +@COMMENCE@ + +SUBDIRS = idl src adm_local + +RESOURCES_FILES = MULTIPRCatalog.xml MULTIPR.png ExecMULTIPR.png MULTIPR_import_med.png MULTIPR_save_med.png SalomeApp.xml + +BIN_SCRIPT= VERSION runAppli myrunSalome.py + +# copy header files in common directory + +include_list = include/salome/SALOMEconfig.h \ + include/salome/MULTIPR_version.h + +ifneq ($(HAVE_SSTREAM),yes) + include_list += include/salome/sstream +endif + +inc: idl $(include_list) + +bin: bin/salome/VERSION + +bin/salome/VERSION : bin/VERSION + -$(RM) $@ + $(LN_S) ../../$< $@ + +include/salome/SALOMEconfig.h: salome_adm/unix/SALOMEconfig.ref + -$(RM) $@ + $(LN_S) ../../$< $@ + +# test if SALOMEconfig.h has changed (contents) +salome_adm/unix/SALOMEconfig.ref: salome_adm/unix/SALOMEconfig.h + @if ! [ -a $@ ]; then \ + cp -p $< $@; \ + fi; \ + if ! cmp $< $@; then \ + cp -p $< $@; \ + fi; \ + +include/salome/sstream: salome_adm/unix/sstream + -$(RM) $@ + $(LN_S) ../../$< $@ + +include/salome/MULTIPR_version.h: MULTIPR_version.h + -$(RM) $@ + $(LN_S) ../../$< $@ + +depend: depend_idl + +depend_idl: + (cd idl ; $(MAKE) $@) || exit 1 + +# doc is already build : if you want to had documents, go manually to doc and run 'make doc' +#doc: +# (cd doc && $(MAKE) $@) || exit 1 + +install-end: +# finish libtool install +# @$(LT) --mode=finish $(libdir) + +install-include: $(include_list) + $(INSTALL) -d $(includedir) + @for f in X $(include_list); do \ + if test $$f != X; then \ + ($(INSTALL_DATA) $$f $(includedir)/. || exit 1); \ + fi; \ + done + +# install script in $(bindir) : +install-bin: $(BIN_SCRIPT) + $(INSTALL) -d $(bindir) + $(INSTALL_PROGRAM) $^ $(bindir) + +uninstall: uninstall-idl + +uninstall-idl: + $(RM) $(idldir)/*.idl + +distclean: distclean-other + +distclean-other: + -$(RM) salome_adm/unix/*~ salome_adm/unix/*% salome_adm/unix/*.bak salome_adm/unix/*.new salome_adm/unix/*.old + -$(RM) salome_adm/unix/make_* + -$(RM) salome_adm/unix/depend salome_adm/unix/SALOMEconfig.h + -$(RM) config.cache config.log config.status + +@MODULE@ + +install: install-bin install-include install-end + diff --git a/README b/README new file mode 100755 index 0000000..2e4ce3c --- /dev/null +++ b/README @@ -0,0 +1,228 @@ +MODULE SALOME MULTIPR +===================== +Par EDF/CS, 02/2007 + + +Description +----------- +MULTIPR est un module pour la plateforme SALOME (v3.2). +Le module sert au partitionnement et a la decimation de maillages tetraedriques (TETRA10), +dans le but de pouvoir visualiser d'importants volumes de donnees. + + +Contenu de ce fichier +--------------------- +I. INSTALLATION/COMPILATION +II. L'APPLICATION AUTONOME EN LIGNE DE COMMANDE multipr +III LE MODULE SALOME MULTIPR + + +******************************************************************************* +* +* I. INSTALLATION/COMPILATION +* +******************************************************************************* + +A. Information generales +------------------------ +MULTIPR a besoin des prerequis suivants: + 1. Salome V3.2 + 2. MESPLITTER (branche CVS WP1_2_3_17-01-2007_Data_format_at_entry_of_visualization_pipeline) + 3. MED fichier v2.3 + 4. METIS v4.0.1 (version NON modifiee par EDF) + 5. SCOTCH v4 + +A propos de MEDSPLITTER : +MEDSPLITTER est un partitionneur de fichiers MED qui repose sur le format MED v2.3 +et les outils METIS et SCOTCH. L'outil a ete developpe par Vincent Bergeaud du CEA. +Dans le cadre du module MULTIPR, MEDSPLITTER est utilise pour partitionner des grains +(scenario a 2 echelles). + + + +B. Installation/compilation +--------------------------- + + + B.1. Se procurer le module MED/MEDSPLITTER compatible avec MULTIPR + ------------------------------------------------------------------ + +1. Charger la branche CVS WP1_2_3_17-01-2007_Data_format_at_entry_of_visualization_pipeline dans le repertoire MED sur le server d'OpenCascade + > cvs -d ":pserver:salome2anonymous@www.opencascade.com:/home/server/cvs/MED" login + rntlrntl (<--- mot de passe) + > cvs -d ":pserver:salome2anonymous@www.opencascade.com:/home/server/cvs/MED" checkout -kk -RP -r WP1_2_3_17-01-2007_Data_format_at_entry_of_visualization_pipeline MED_SRC + > cvs -d ":pserver:salome2anonymous@www.opencascade.com:/home/server/cvs/MED" logout + (note : MEDPLITTER peut également être compilé à partir de la branche CVS BR_SPLITTER_improved) + +2. Modifier le code pour utiliser MED fichier v2.3 : + A. Supprimer les 6 fichiers suivants : + MED_SRC/src/medmem/MEDMEM_MEDMEMchampLire.hxx/cxx + MED_SRC/src/medmem/MEDMEM_MEDMEMgaussEcr.hxx/cxx + MED_SRC/src/medmem/MEDMEM_MEDMEMprofilEcr.hxx/cxx + B. Mettre a jour le fichier medmem/Makefile.in en supprimant les 6 lignes correspondantes + C. Mettre a jour le fichier MEDMEM_MedFieldDriver22.hxx + 1. Dans la section "includes, supprimer les 3 lignes #include "MEDMEM_MEDMEMchampLire.hxx" ... + 2. Remplacer ces lignes par l'inclusion de l'API MED : + namespace med_2_2 + { + extern "C" + { + #include + #include + } + } + 3. Effectuer les changements suivants (utiliser l'API MED fichier v2.3) : + MEDMEMchampLire -> MEDchampLire + MEDMEMgaussEcr -> MEDgaussEcr + MEDMEMprofilEcr -> MEDprofilEcr + => En tout, il y a 4 lignes a changer + + + B.2. Prerequis a la compilation du module MED/MEDSPLITTER + --------------------------------------------------------- + +3. Verifier que la variable d'environnement LD_LIBRARY_PATH ne pointe pas vers un repertoire MED +4. Verifier que la variable d'environnement MED_ROOT_DIR n'est pas definie +5. Installer METIS v4.0.1 (soit le repertoire d'installation) + A. Charger le source sur http://glaros.dtc.umn.edu/gkhome/metis/metis/download + B. Decompresser l'archive : tar -zxvz metis-4.0.tar.gz + C. Puis make dans le repertoire + D. Verifier que tout est OK : depuis \Graph, lancer ./mtest 4elt.graph +6. Verifier que la bibliotheque boost v1.32 ou + est installee + A. Bien verifier que le paquet libboost_program_option est inclu (ce paquet est utilise par MEDSPLITTER) + B. Ajouter la variable d'environnement export BOOSTDIR=/usr, si nécessaire + C. Si necessaire, dans /usr/lib, ajouter le lien + ln -s libboost_program_options.so libboost_program_options-gcc-mt.so + (droits administrateur necessaires) + + + B.3. Compilation du module MED/MEDSPLITTER + ------------------------------------------ + +7. Pour compiler la branche MED WP1_2_3_17-01-2007_Data_format_at_entry_of_visualization_pipeline avec SALOME V3.2.2 (Debian Sarge) + Dans le repertoire SALOME v3.2.2 : + A. Sourcer prerequis-Sarge-slash-usr.sh et envSalome-V3_2_2.sh + B. Verifier que la variable d'environnement MED2HOME pointe bien vers + MED fichier v2.3 +8. Pour compiler avec METIS v4.0.1 precedemment charge : + Renommer la fonction log2 en log2_ dans metis\lib\proto.h + (sinon, un conflit se produit) + +Depuis le repertoire contenant WP1_2_3_17-01-2007_Data_format_at_entry_of_visualization_pipeline : +9. Creer un repertoire Build et un repertoire MED au cote de MED_SRC +10. Dans le repertoire MED_SRC, faire ./build_configure +11. Depuis le repertoire Build, faire (en remplacant les <...> par les bons répertoires) + ../MED_SRC/configure --prefix=/MED --enable-splitter=yes --with-metis= --with-scotch= + --enable-production=yes --disable-debug +12. Puis : make +13. Puis : make install + + + B.4. Tester l'installation du module MED/MEDSPLITTER + ---------------------------------------------------- + +14. Definir la variable d'environnement MED_ROOT_DIR (=/MED) +15. Eventuellement, mettre a jour les variables d'environnement LD_LIBRARY_PATH et PYTHONPATH +16. Pour verifier que MEDMEM est bien installe : + Depuis le repertoire /MED : python bin/salome/testMedMemGeneral.py +17. Pour verifier que MEDSPLITTER est bien installe : + A. Dans /MED/bin/salome, creer le repertoire tests : mkdir tests + B. Puis : + ./test_SPLITTER_indivisible + ./test_SPLITTER_square + ./medsplitter --input-file=/MED/share/salome/resources/med/pointe_import22.med --output-file=toto --ndomains=2 --meshname=maa1 + + + B.5. Compiler le module MULTIPR + ------------------------------- + +18. Creer un repertoire Build et un repertoire MULTIPR au cote de MULTIPR_SRC +19. Dans le repertoire MULTIPR_SRC, faire ./build_configure +20. Depuis le repertoire Build, faire (en remplacant les <...> par les bons répertoires) + ../MULTIPR_SRC/configure --prefix=/MULTIPR --enable-production=yes --disable-debug +21. Puis : make +22. Puis : make install + + +******************************************************************************* +* +* II. L'APPLICATION AUTONOME EN LIGNE DE COMMANDE multipr +* +******************************************************************************* + +Tests de l'application autonome en ligne de commande multipr +------------------------------------------------------------ +L'application "multipr" se trouve dans .../bin/salome + +1. Affichage de la page d'aide + + $ ./multipr + +2. Autotest complet de l'application + + $ ./multipr --auto /data + (ou /data designe le repertoire dans lequel se trouve le fichier agregat100grains_12pas.med) + +3. Affichage de la liste des maillages et des champs d'un fichier MED sequentiel : + + $ ./multipr --info agregat100grains_12pas.med + +4. Affichage de toutes les informations concernant un maillage : + + $ ./multipr --info agregat100grains_12pas.med MAIL + +5. Partitionnement (1 echelle) : + Extraction des grains du maillage MAIL dans le fichier agregat100grains_12pas.med + + $ ./multipr --part1 agregat100grains_12pas.med MAIL + +6. Partitionnement (2 echelles) : + Decoupage du grain numero 98 en 3 parties : + + $ ./multipr --part2 agregat100grains_12pas_grains_maitre.med MAIL_98 3 + +7. Decimation : + Creation de 3 resolutions du grain numero 99 en prenant : + comme reference le 12e pas de temps du champ SIG_____SIEF_ELGA_______________ + comme seuil pour la resolution MEDIUM : 10 + comme seuil pour la resolution BASSE : 25 + comme rayon pour le calcul du voisinage : 0.3 + + $ ./multipr --decim agregat100grains_12pas_grains_maitre.med MAIL_99 SIG_____SIEF_ELGA_______________ 12 Filtre_GradientMoyen 10 25 0.3 + +8. Messages d'erreur : + Les exemples suivants sont des commandes erronees : + + $ ./multipr --part1 agregat100grains_12pas.m MAIL + ... MULTIPR: FileNotFoundException (MULTIPR_Mesh.cxx, line 663): MED file not found + + $ ./multipr --part1 agregat100grains_12pas.med MAILLAGE + ... MULTIPR: IllegalStateException (MULTIPR_Mesh.cxx, line 747): mesh not found in the given MED file + + $ ./multipr --part2 agregat100grains_12pas.med MAIL 2 + ... MULTIPR: IOException (MULTIPR_API.cxx, line 106): waiting for a distributed MED file (not a sequential one) + + $ ./multipr --part2 agregat100grains_12pas_grains_maitre.med MAIL_95 0 + ... MULTIPR: IllegalArgumentException (MULTIPR_API.cxx, line 97): pNbParts should be >= 2 + + $ ./multipr --decim agregat100grains_12pas_grains_maitre.med MAIL_99 SIG_____SIEF_ELGA_______________ 14 Filtre_GradientMoyen 10 25 0.3 + ... MULTIPR: IllegalArgumentException (MULTIPR_DecimationFilter.cxx, line 100): invalid field iteration (14) + + $ ./multipr --decim agregat100grains_12pas_grains_maitre.med MAIL_99 SIG_____SIEF_ELGA___________TEST 12 Filtre_GradientMoyen 10 25 0.3 + MULTIPR: IllegalArgumentException (MULTIPR_DecimationFilter.cxx, line 99): field not found + + etc. + + +******************************************************************************* +* +* III. LE MODULE SALOME MULTIPR +* +******************************************************************************* + +Lancer le module salome seul : ./bin/salome/runAppli depuis le repertoire MULTIPR + + + + + diff --git a/adm_local/Makefile.in b/adm_local/Makefile.in new file mode 100644 index 0000000..cfbe6f4 --- /dev/null +++ b/adm_local/Makefile.in @@ -0,0 +1,59 @@ +# Copyright (C) 2005 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +# source path +top_srcdir=@top_srcdir@ +top_builddir=.. +srcdir=@srcdir@ +VPATH=.:$(srcdir)/adm_local + + +all: resources + +install: + cp -rf @top_srcdir@/adm_local @prefix@ + +bin: + +resources : + cp -rf @top_srcdir@/adm_local $(top_builddir) + +inc: + +lib: + +depend: + +depend_idl: + +install-end: + +install-include: + +install-bin: + +uninstall: + +uninstall-idl: + +distclean: + +clean: + +distclean-other: + diff --git a/adm_local/unix/config_files/check_MULTIPR.m4 b/adm_local/unix/config_files/check_MULTIPR.m4 new file mode 100755 index 0000000..91816f8 --- /dev/null +++ b/adm_local/unix/config_files/check_MULTIPR.m4 @@ -0,0 +1,53 @@ +# Check availability of MULTIPR module binary distribution +# +# Author : Olivier LE ROUX (CS, 2006) +#------------------------------------------------------------ + +AC_DEFUN([CHECK_MULTIPR],[ + +AC_CHECKING(for Multipr) + +Multipr_ok=no + +AC_ARG_WITH(multipr, + --with-multipr=DIR root directory path of MULTIPR installation, + MULTIPR_DIR="$withval",MULTIPR_DIR="") + +if test "x$MULTIPR_DIR" = "x" ; then + +# no --with-gui-dir option used + + if test "x$MULTIPR_ROOT_DIR" != "x" ; then + + # MULTIPR_ROOT_DIR environment variable defined + MULTIPR_DIR=$MULTIPR_ROOT_DIR + + else + + # search multipr binaries in PATH variable + AC_PATH_PROG(TEMP, libMULTIPR.so) + if test "x$TEMP" != "x" ; then + MULTIPR_BIN_DIR=`dirname $TEMP` + MULTIPR_DIR=`dirname $MULTIPR_BIN_DIR` + fi + + fi +# +fi + +if test -f ${MULTIPR_DIR}/lib/salome/libMULTIPR.so ; then + Multipr_ok=yes + AC_MSG_RESULT(Using MULTIPR distribution in ${MULTIPR_DIR}) + + if test "x$MULTIPR_ROOT_DIR" == "x" ; then + MULTIPR_ROOT_DIR=${MULTIPR_DIR} + fi + AC_SUBST(MULTIPR_ROOT_DIR) +else + AC_MSG_WARN("Cannot find compiled MULTIPR distribution") +fi + +AC_MSG_RESULT(for MULTIPR: $Multipr_ok) + +])dnl + diff --git a/adm_local/unix/make_commence.in b/adm_local/unix/make_commence.in new file mode 100644 index 0000000..4d769e4 --- /dev/null +++ b/adm_local/unix/make_commence.in @@ -0,0 +1,278 @@ +# common directories to put headerfiles +inc_builddir=$(top_builddir)/include/salome + +MODULE_NAME=@MODULE_NAME@ + +@SET_MAKE@ +SHELL=/bin/sh + +# header missing + +HAVE_SSTREAM=@HAVE_SSTREAM@ + + +LIBS=@LIBS@ +LDFLAGS=@LDFLAGS@ -L$(top_builddir)/lib@LIB_LOCATION_SUFFIX@/salome -Xlinker -rpath-link -Xlinker $(top_builddir)/lib@LIB_LOCATION_SUFFIX@/salome +# add libstdc++ to link c++ library with libtool ! +LDFLAGS+= -lstdc++ + +CP=@CP@ + +# CPP + +CPP=@CPP@ +CXXCPP=@CXXCPP@ +CPPFLAGS=@CPPFLAGS@ -I$(inc_builddir) -I$(srcdir) -I. + +# C + +CC = @CC@ +CFLAGS = @CFLAGS@ +C_DEPEND_FLAG = @C_DEPEND_FLAG@ + +# C++ + +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CXX_DEPEND_FLAG = @CXX_DEPEND_FLAG@ + +# BOOST Library + +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ + +# JAVA + +JAVA_INCLUDES = @JAVA_INCLUDES@ +JAVA_LIBS = @JAVA_LIBS@ +JAVA_LDPATH = @JAVA_LDPATH@ + +# PYTHON + +PYTHON = @PYTHON@ +PYTHONHOME = @PYTHONHOME@ +PYTHON_INCLUDES = @PYTHON_INCLUDES@ +PYTHON_LIBS = @PYTHON_LIBS@ +PYTHON_VERSION = @PYTHON_VERSION@ +PYTHON_SITE = $(prefix)/lib@LIB_LOCATION_SUFFIX@/python$(PYTHON_VERSION)/site-packages +PYTHON_SITE_INSTALL = $(prefix)/lib@LIB_LOCATION_SUFFIX@/python$(PYTHON_VERSION)/site-packages/salome + +# QT + +QT_ROOT = @QT_ROOT@ +QT_INCLUDES = @QT_INCLUDES@ +QT_MT_INCLUDES = @QT_INCLUDES@ -DQT_THREAD_SUPPORT +QT_LIBS = @QT_LIBS@ +QT_MT_LIBS = @QT_MT_LIBS@ + +MOC = @MOC@ +UIC = @UIC@ + +# msg2qm + +MSG2QM = @MSG2QM@ + +#QWT + +QWT_INCLUDES=@QWT_INCLUDES@ +QWT_LIBS=@QWT_LIBS@ + +# SIP +SIP = @SIP@ +SIP_INCLUDES = @SIP_INCLUDES@ +SIP_LIBS = @SIP_LIBS@ + +# PYQT +PYQT_SIPS = @PYQT_SIPS@ +PYQT_LIBS = @PYQT_LIBS@ + +# openGL +OGL_INCLUDES=@OGL_INCLUDES@ +OGL_LIBS=@OGL_LIBS@ + +# VTK +VTK_INCLUDES=@VTK_INCLUDES@ +VTK_LIBS=@VTK_LIBS@ + +# HDF5 + +HDF5_INCLUDES=@HDF5_INCLUDES@ +HDF5_LIBS=@HDF5_LIBS@ +HDF5_MT_LIBS=@HDF5_MT_LIBS@ + +# MED2 + +MED2_INCLUDES=@MED2_INCLUDES@ +MED2_LIBS=@MED2_LIBS@ +MED2_MT_LIBS=@MED2_MT_LIBS@ + +# OpenCasCade + +OCC_INCLUDES=@CAS_CPPFLAGS@ +OCC_CXXFLAGS=@CAS_CXXFLAGS@ + +OCC_KERNEL_LIBS=@CAS_KERNEL@ +OCC_OCAF_LIBS=@CAS_OCAF@ +OCC_VIEWER_LIBS=@CAS_VIEWER@ +OCC_MODELER_LIBS=@CAS_MODELER@ +OCC_DATAEXCHANGE_LIBS=@CAS_DATAEXCHANGE@ +OCC_LIBS=@CAS_LDFLAGS@ + +# MPICH + +MPICH_INCLUDES=@MPICH_INCLUDES@ +MPICH_LIBS=@MPICH_LIBS@ + +# Swig C++ Python + +SWIG = @SWIG@ +SWIG_FLAGS = @SWIG_FLAGS@ -I$(inc_builddir) -I$(srcdir) -I. + +# OMNIORB + +OMNIORB_ROOT = @OMNIORB_ROOT@ +OMNIORB_INCLUDES = @OMNIORB_INCLUDES@ +OMNIORB_LIBS = @OMNIORB_LIBS@ +OMNIORB_CXXFLAGS = @OMNIORB_CXXFLAGS@ + +OMNIORB_IDL = @OMNIORB_IDL@ +OMNIORB_IDLCXXFLAGS = @OMNIORB_IDLCXXFLAGS@ +OMNIORB_IDLPYFLAGS = @OMNIORB_IDLPYFLAGS@ -I$(top_srcdir)/idl -I$(top_builddir)/idl -I$(KERNEL_ROOT_DIR)/idl/salome + +OMNIORB_IDL_CLN_H = @OMNIORB_IDL_CLN_H@ +OMNIORB_IDL_CLN_CXX = @OMNIORB_IDL_CLN_CXX@ +OMNIORB_IDL_CLN_OBJ = @OMNIORB_IDL_CLN_OBJ@ + +OMNIORB_IDL_SRV_H = @OMNIORB_IDL_SRV_H@ +OMNIORB_IDL_SRV_CXX = @OMNIORB_IDL_SRV_CXX@ +OMNIORB_IDL_SRV_OBJ = @OMNIORB_IDL_SRV_OBJ@ + +# Default ORB + +CORBA_ROOT = @CORBA_ROOT@ +CORBA_INCLUDES = @CORBA_INCLUDES@ +CORBA_LIBS = @CORBA_LIBS@ +CORBA_CXXFLAGS = @CORBA_CXXFLAGS@ + +IDLCXXFLAGS = -bcxx @IDLCXXFLAGS@ -I$(top_srcdir)/idl -I$(top_builddir)/idl -I$(KERNEL_ROOT_DIR)/idl/salome +IDLPYFLAGS = @IDLPYFLAGS@ + +IDL = @IDL@ + +IDL_CLN_H = @IDL_CLN_H@ +IDL_CLN_CXX = @IDL_CLN_CXX@ +IDL_CLN_OBJ = @IDL_CLN_OBJ@ + +IDL_SRV_H = @IDL_SRV_H@ +IDL_SRV_CXX = @IDL_SRV_CXX@ +IDL_SRV_OBJ = @IDL_SRV_OBJ@ + +CPPFLAGS+= $(CORBA_INCLUDES) +CXXFLAGS+= $(CORBA_CXXFLAGS) + +# add corba libs when link salome application ! +#LDFLAGS+= $(CORBA_LIBS) +LIBS+=$(CORBA_LIBS) + +## Shared libraries +LT_STATIC_EXEC=@LT_STATIC_EXEC@ +DYNAMIC_DIRS=@DYNAMIC_DIRS@ +LT_LIB=libtool +LT=$(top_builddir)/libtool +LT_COMPILE=$(LT) --mode=compile $(CC) +LT_LINK_LIB=$(LT_LIB) --mode=link $(CC) -rpath $(libdir) +LT_LINK_EXE=$(LT) --mode=link $(CC) $(LT_STATIC_EXEC) -dlopen self -rpath $(bindir) $(DYNAMIC_DIRS) +LT_RUN=$(LT) --mode=execute +LT_INSTALL_PROG=$(LT) --mode=install $(INSTALL_PROGRAM) +LT_INSTALL_LIB=$(LT) --mode=install $(INSTALL_DATA) +LT_UNINSTALL=$(LT) --mode=uninstall $(RM) + +INSTALL=@INSTALL@ +INSTALL_PROGRAM=@INSTALL_PROGRAM@ +INSTALL_DATA=@INSTALL_DATA@ + +# create a symbolic link (or a copie ?) +LN_S=@LN_S@ + +KERNEL_ROOT_DIR=@KERNEL_ROOT_DIR@ +KERNEL_SITE_DIR=@KERNEL_SITE_DIR@ +KERNEL_LDFLAGS=@KERNEL_LDFLAGS@ +KERNEL_CXXFLAGS=@KERNEL_CXXFLAGS@ + +GUI_ROOT_DIR=@GUI_ROOT_DIR@ +GUI_LDFLAGS=@GUI_LDFLAGS@ +GUI_CXXFLAGS=@GUI_CXXFLAGS@ + +## Installation points +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@/salome +libdir=@exec_prefix@/lib@LIB_LOCATION_SUFFIX@/salome +# warning : if user give this path in configure we could have salome/salome :-( +includedir=@includedir@/salome +datadir=@datadir@/salome +idldir=$(prefix)/idl/salome +sharedpydir=@exec_prefix@/lib@LIB_LOCATION_SUFFIX@/python$(PYTHON_VERSION)/site-packages/salome/shared_modules + +docdir=$(datadir)/doc + +# +# begin of package rules +# + +.PHONY: all lib bin inc resources tests install uninstall dep depend depend_idl cleandep mostlyclean clean distclean + +.SUFFIXES: .cxx .cc .c .f .o .lo .idl .py .i .ui .po .qm + +all: + $(MAKE) inc + $(MAKE) depend_idl + $(MAKE) depend + $(MAKE) lib + $(MAKE) bin + $(MAKE) resources + +# +# add target to build administrative files +# + +Makefile: $(top_builddir)/config.status $(srcdir)/Makefile.in + cd $(top_builddir) ; ./config.status + +LOCAL_MAKE = make_commence make_omniorb + +KERNEL_MAKE = make_module make_conclude depend SALOMEconfig.h F77config.h sstream envScript + +$(top_builddir)/config.status: $(top_srcdir)/configure \ + $(LOCAL_MAKE:%=$(top_srcdir)/adm_local/unix/%.in) \ + $(KERNEL_MAKE:%=$(KERNEL_ROOT_DIR)/salome_adm/unix/%.in) + cd $(top_builddir) ; ./config.status --recheck + +# VPATH contain $(srcdir), so make configure is good in top_srcdir and we must add target configure otherwise :-) +ifneq ($(top_srcdir),$(srcdir)) +configure: $(top_srcdir)/configure +endif + +$(top_srcdir)/configure: $(top_srcdir)/configure.in $(top_srcdir)/aclocal.m4 + cd $(top_srcdir) ; autoconf + +$(top_srcdir)/configure.in: $(top_srcdir)/configure.in.base + cd $(top_srcdir) && ./build_configure + + +ACLOCAL_KERNEL = \ +ac_cxx_bool.m4 check_corba.m4 \ +ac_cxx_depend_flag.m4 check_hdf5.m4 enable_pthreads.m4 \ +ac_cxx_mutable.m4 check_mico.m4 libtool.m4 \ +ac_cxx_namespaces.m4 check_omniorb.m4 pyembed.m4 \ +ac_cxx_partial_specialization.m4 python.m4 \ +ac_cxx_typename.m4 check_pthreads.m4 check_cas.m4 \ +ac_cc_warnings.m4 check_swig.m4 + +ACLOCAL_GUI = \ +check_vtk.m4 check_opengl.m4 check_qt.m4 \ +check_GUI.m4 check_corba_in_GUI.m4 + +$(top_srcdir)/aclocal.m4: $(ACLOCAL_KERNEL:%=@KERNEL_ROOT_DIR@/salome_adm/unix/config_files/%) \ + $(ACLOCAL_GUI:%=@GUI_ROOT_DIR@/adm_local/unix/config_files/%) + cd $(top_srcdir) ; aclocal -I adm_local/unix/config_files -I @KERNEL_ROOT_DIR@/salome_adm/unix/config_files \ + -I @GUI_ROOT_DIR@/adm_local/unix/config_files diff --git a/adm_local/unix/make_omniorb.in b/adm_local/unix/make_omniorb.in new file mode 100644 index 0000000..c91ccbf --- /dev/null +++ b/adm_local/unix/make_omniorb.in @@ -0,0 +1,52 @@ +#======================================================================= +# Begin specific part to omniorb +# (include from file adm/unix/make_omniorb generated by +# adm/unix/make_omniorb.in) +#======================================================================= +# -* Makefile *- +# +# Author : Patrick GOLDBRONN (CEA) +# Date : 29/06/2001 +# + +# Client and server object are the same with omniorb +# There are one header file and one source file generate + +#IDLOBJ=$(IDLSRC:%.idl=%$(IDL_CLN_OBJ)) + +# dependancies between idl and it's generated files +%$(OMNIORB_IDL_CLN_CXX) %$(OMNIORB_IDL_CLN_H): ${KERNEL_ROOT_DIR}/idl/salome/%.idl + $(OMNIORB_IDL) $(IDLCXXFLAGS) $(OMNIORB_IDLCXXFLAGS) $< + +%$(OMNIORB_IDL_CLN_CXX) %$(OMNIORB_IDL_CLN_H): ${top_srcdir}/idl/%.idl + $(OMNIORB_IDL) $(IDLCXXFLAGS) $(OMNIORB_IDLCXXFLAGS) $< + +# dependncies between idl files +depend_idl: .depidl + +# we use cpp to generate dependencies between idl files. +# we change cpp output to keep only idl file and transform it to get a suitable rule +.depidl: $(IDL_FILES) + @touch $@ + @for dep in $? dummy; do \ + if [ $$dep != "dummy" ]; then \ + echo Building dependencies for $$dep; \ + basedep=`basename $$dep .idl`; \ + header="$$basedep"$(IDL_CLN_H); \ + sed '\%^'"$$header"':%,\%[^\\]$$%d' <$@ >$@- && mv $@- $@; \ + $(CPP) $(C_DEPEND_FLAG) -I$(srcdir) $$dep 2>/dev/null | \ + sed `echo "s%$$basedep\\.idl%$$header:%g"` | \ + sed 's% $(srcdir)/% %g' | \ + sed 's% $(top_srcdir)/% %g' | \ + sed 's% $(top_builddir)/% %g' | \ + sed 's%^.*:\.o: *%%' | sed 's%^ *\\ *%%'| sed 's%^ *\(.*\):%\1:%' | \ + sed 's/\.idl/$(IDL_CLN_H)/' >>$@; \ + echo '' >>$@; \ + fi; \ + done ; + +-include .depidl + +#======================================================================= +# End specific part to omniorb +#======================================================================= diff --git a/bin/VERSION.in b/bin/VERSION.in new file mode 100755 index 0000000..8395447 --- /dev/null +++ b/bin/VERSION.in @@ -0,0 +1 @@ +SALOME 2 MODULE C++ : MULTIPR : @VERSION@ diff --git a/bin/myrunSalome.py b/bin/myrunSalome.py new file mode 100755 index 0000000..e9d52c4 --- /dev/null +++ b/bin/myrunSalome.py @@ -0,0 +1,162 @@ +# Copyright (C) 2005 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +#!/usr/bin/env python + +def test(clt): + """ + Test function that creates an instance of MULTIPR component + usage : multipr=test(clt) + """ + # create an LifeCycleCORBA instance + import LifeCycleCORBA + lcc = LifeCycleCORBA.LifeCycleCORBA(clt.orb) + import MULTIPR_ORB + multipr = lcc.FindOrLoadComponent("FactoryServer", "MULTIPR") + return multipr + + +def multipr_test1(clt,path): + import LifeCycleCORBA + lcc = LifeCycleCORBA.LifeCycleCORBA(clt.orb) + import MULTIPR_ORB + engine = lcc.FindOrLoadComponent("FactoryServer", "MULTIPR") + m = engine.getObject(path+'/agregat100grains_12pas.med') + liste_champs = m.getFields() + for i in liste_champs: + m.getTimeStamps(i) + liste_maillages = m.getMeshes() + m.setMesh(liste_maillages[0]) + m.partitionneDomaine() + m.getParts() + m.save() + m.decimePartition('MAIL_99', 'SIG_____SIEF_ELGA_______________', 12, 'Filtre_GradientMoyen', 10, 25, 0.3) + liste_grains = m.getParts() + m.save() + m.partitionneGrain('MAIL_98', 3, 0) + m.save() + m.getParts() + m.getMeshes() + m.getFields() + + +def multipr_test2(clt,path): + import LifeCycleCORBA + lcc = LifeCycleCORBA.LifeCycleCORBA(clt.orb) + import MULTIPR_ORB + engine = lcc.FindOrLoadComponent("FactoryServer", "MULTIPR") + m = engine.getObject(path+'/agregat100grains_12pas.med') + m.getMeshes() + m.setMesh('MAIL') + m.partitionneDomaine() + m.getParts() + liste_champs = m.getFields() + m.getTimeStamps(liste_champs[3]) + m.decimePartition('MAIL_99', 'SIG_____SIEF_ELGA_______________', 12, 'Filtre_GradientMoyen', 10, 25, 0.3) + m.save() + m.getMeshes() + m.getParts() + m.getFields() + + +def multipr_test3(clt,path): + import LifeCycleCORBA + lcc = LifeCycleCORBA.LifeCycleCORBA(clt.orb) + import MULTIPR_ORB + engine = lcc.FindOrLoadComponent("FactoryServer", "MULTIPR") + m = engine.getObject(path+'/agregat100grains_12pas.med') + m.setMesh('MAIL') + m.partitionneDomaine() + m.getParts() + liste_champs = m.getFields() + m.getTimeStamps(liste_champs[3]) + m.decimePartition('MAIL_99', 'SIG_____SIEF_ELGA_______________', 12, 'Filtre_GradientMoyen', 10, 25, 0.3) + m.partitionneGrain('MAIL_1', 3, 0) + m.getParts() + #m.partitionneGrain('MAIL_2', 4, 1) + m.getMeshes() + m.getParts() + m.getFields() + m.save() + + +def multipr_test4(clt,path): + import LifeCycleCORBA + lcc = LifeCycleCORBA.LifeCycleCORBA(clt.orb) + import MULTIPR_ORB + engine = lcc.FindOrLoadComponent("FactoryServer", "MULTIPR") + m = engine.getObject(path+'/agregat100grains_12pas_grains_maitre.med') + m.getFields() + m.getParts() + for i in m.getParts(): + m.partitionneGrain(i, 3, 0); + + +def multipr_test5(clt,path): + import LifeCycleCORBA + lcc = LifeCycleCORBA.LifeCycleCORBA(clt.orb) + import MULTIPR_ORB + engine = lcc.FindOrLoadComponent("FactoryServer", "MULTIPR") + m = engine.getObject(path+'/agregat100grains_12pas.med') + liste_champs = m.getFields() + liste_maillages = m.getMeshes() + m.setMesh(liste_maillages[0]) + liste_grains = m.partitionneDomaine() + for grain in liste_grains[0:4]: + m.decimePartition(grain, liste_champs[1], 12, 'Filtre_GradientMoyen', 10, 25, 0.3) + m.getParts() + m.save() + + +def multipr_test6(clt,path): + import LifeCycleCORBA + lcc = LifeCycleCORBA.LifeCycleCORBA(clt.orb) + import MULTIPR_ORB + engine = lcc.FindOrLoadComponent("FactoryServer", "MULTIPR") + m = engine.getObject(path+'/agregat100grains_12pas.med') + liste_champs = m.getFields() + liste_maillages = m.getMeshes() + m.setMesh(liste_maillages[0]) + liste_grains = m.partitionneDomaine() + liste_pgrain = m.partitionneGrain(liste_grains[4], 16, 0) + m.setBoxing(10) + for grain in liste_pgrain[0:11]: + m.decimePartition(grain, liste_champs[1], 12, 'Filtre_GradientMoyen', 10, 25, 0.5) + m.getParts() + m.save() + n = engine.getObject(path+'/agregat100grains_12pas_grains_maitre.med') + n.getParts() + + +if __name__ == "__main__": + import user + from runSalome import * + clt,args = main() + + # + # Impression arborescence Naming Service + # + + if clt != None: + print + print " --- registered objects tree in Naming Service ---" + clt.showNS() + session=clt.waitNS("/Kernel/Session") + catalog=clt.waitNS("/Kernel/ModulCatalog") + import socket + container = clt.waitNS("/Containers/" + socket.gethostname().split('.')[0] + "/FactoryServer") diff --git a/bin/runAppli.in b/bin/runAppli.in new file mode 100755 index 0000000..99af375 --- /dev/null +++ b/bin/runAppli.in @@ -0,0 +1,44 @@ +#!/bin/sh + +if [ -z "${KERNEL_ROOT_DIR}" ] ; then +export KERNEL_ROOT_DIR=@KERNEL_ROOT_DIR@ +fi +if [ -z "${MULTIPR_ROOT_DIR}" ] ; then +export MULTIPR_ROOT_DIR=@prefix@ +fi + +searchFreePort() { + echo -n "Searching for a free port for naming service: " + export NSPORT=2810 + local limit=$NSPORT + let limit=limit+100 + while [ 1 ] + do + aRes=`netstat -ltn | grep -E :${NSPORT}` + if [ -z "$aRes" ]; then + echo ${NSPORT} - Ok + local myhost=`hostname` + export OMNIORB_CONFIG=${HOME}/.omniORB_${myhost}_${NSPORT}.cfg + local initref="NameService=corbaname::"`hostname`":$NSPORT" + if [[ `python -c "import CORBA; print CORBA.ORB_ID"` = "omniORB4" ]]; then + echo "InitRef = $initref" > $OMNIORB_CONFIG + else + echo "ORBInitRef $initref" > $OMNIORB_CONFIG + fi + break + fi + echo -n "${NSPORT} " + if [[ $NSPORT -eq $limit ]] ; then + echo + echo "Can't find a free port to launch omniNames" + echo "Try to kill the running servers and then launch SALOME again." + exit + fi + let NSPORT=NSPORT+1 + done +} + +searchFreePort + + +${KERNEL_ROOT_DIR}/bin/salome/envSalome.py python -i $MULTIPR_ROOT_DIR/bin/salome/myrunSalome.py --modules=MULTIPR --containers=cpp,python --killall diff --git a/build_configure b/build_configure new file mode 100755 index 0000000..9aa3637 --- /dev/null +++ b/build_configure @@ -0,0 +1,242 @@ +#!/bin/bash + +# +# Tool for updating list of .in file for the SALOME project +# and regenerating configure script +# +# Author : Marc Tajchman - CEA +# Date : 10/10/2002 +# $Header $ +# + +ORIG_DIR=`pwd` +CONF_DIR=`echo $0 | sed -e "s,[^/]*$,,;s,/$,,;s,^$,.,"` + +######################################################################## +# Test if the KERNEL_ROOT_DIR is set correctly + +if test ! -d "${KERNEL_ROOT_DIR}"; then + echo "failed : KERNEL_ROOT_DIR variable is not correct !" + exit +fi + +######################################################################## +# Test if the GUI_ROOT_DIR is set correctly + +if test ! -d "${GUI_ROOT_DIR}"; then + echo "failed : GUI_ROOT_DIR variable is not correct !" + exit +fi + +######################################################################## +# Test if the MED_ROOT_DIR is set correctly + +if test ! -d "${MED_ROOT_DIR}"; then + echo "failed : MED_ROOT_DIR variable is not correct !" + exit +fi + +######################################################################## +# Test if the MED2HOME is set correctly + +if test ! -d "${MED2HOME}"; then + echo "failed : MED2HOME variable is not correct !" + exit +fi + +######################################################################## +# Test if the HDF5HOME is set correctly + +if test ! -d "${HDF5HOME}"; then + echo "failed : HDF5HOME variable is not correct !" + exit +fi + +######################################################################## +# find_in - utility function +# +# usage : +# find_in directory filename +# +# Finds files following the *.in pattern, recursively in the +# directory (first argument). +# Results are appended into the file (second argument) +# +# Difference from the standard unix find is that files are tested +# before directories +# + +find_in() +{ + local i + local f=$2 + +# if the first argument is not a directory, returns + + if [ ! -d "$1" ] ; then + return + fi + +# dont look in the CVS directories + + case $1 in + */CVS) return ;; + */adm_local/*) return ;; + *) ;; + esac + +# for each regular file contained in the directory +# test if it's a .in file + + for i in "$1"/* + do + if [ -f "$i" ] ; then + case $i in + *.in) echo $i" \\" >> $f;; + *) ;; + esac + fi + done + +# for each subdirectory of the first argument, proceeds recursively + + for i in "$1"/* + do + if [ -d "$i" ] ; then + find_in "$i" "$f" + fi + done +} + + +####################################################################### +# Generate list of .in files (Makefile.in, config.h.in, etc) +# appending it in file configure.in + +cd ${CONF_DIR} +ABS_CONF_DIR=`pwd` + +# +# Common part of the configure.in file +# +chmod u+w configure.in.base +if ! \cp -f configure.in.base configure.in_tmp1 +then + echo + echo "error : can't create files in" ${CONF_DIR} + echo "aborting ..." + chmod u-w configure.in.base + exit +fi +chmod u-w configure.in.base + +if [ -e "${CONF_DIR}/salome_adm" ] ; then + \rm -f ${CONF_DIR}/salome_adm +fi + +# make a link allowing AC_OUTPUT to find the salome_adm/.../*.in files +echo "" >> configure.in_tmp1 +echo 'ln -fs ${KERNEL_ROOT_DIR}/salome_adm ${ROOT_SRCDIR}' >> configure.in_tmp1 + +echo "" >> configure.in_tmp1 +echo "AC_OUTPUT([ \\" >> configure.in_tmp1 + +# +# List of .in files in the adm/unix directory +# These files MUST be on top of AC_OUTPUT list so we +# put them "manually" +# + +echo "./salome_adm/unix/SALOMEconfig.h \\" >> configure.in_tmp1 +echo "./salome_adm/unix/F77config.h \\" >> configure.in_tmp1 +echo "./salome_adm/unix/sstream \\" >> configure.in_tmp1 +echo "./salome_adm/unix/depend \\" >> configure.in_tmp1 +echo "./adm_local/unix/make_omniorb:${ABS_CONF_DIR}/adm_local/unix/make_omniorb.in \\" >> configure.in_tmp1 +echo "./salome_adm/unix/envScript \\" >> configure.in_tmp1 +echo "./adm_local/unix/make_commence:${ABS_CONF_DIR}/adm_local/unix/make_commence.in \\" >> configure.in_tmp1 +echo "./salome_adm/unix/make_conclude \\" >> configure.in_tmp1 +echo "./salome_adm/unix/make_module \\" >> configure.in_tmp1 + +\rm -f configure.in_tmp2 +touch configure.in_tmp2 +find_in . configure.in_tmp2 + +sed -e '/^...salome_adm/d' \ + -e '/configure.in/d' \ + -e '/^...adm_local/d' \ + -e 's/.in / /' \ + configure.in_tmp2 >> configure.in_tmp1 + +echo "])" >> configure.in_tmp1 + +# delete the link created for AC_OUTPUT +echo "" >> configure.in_tmp1 +\mv configure.in_tmp1 configure.in_new +\rm -f configure.in_tmp2 + + +######################################################################## +# Create new (or replace old) configure.in file +# Print a message if the file is write protected +# + +echo +if test ! -f configure.in +then + echo -n "Creating new file 'configure.in' ... " + if \mv configure.in_new configure.in >& /dev/null + then + echo "done" + else + echo "error, check your file permissions" + fi +else + echo -n "Updating 'configure.in' file ... " + if ! \cp configure.in configure.in_old >& /dev/null + then + echo + echo + echo "Can't backup previous configure.in" + echo -n "Continue (you will not be able to revert) - (Y/N) ? " + read R + case "x$R" in + xn*) exit;; + xN*) exit;; + esac + echo + echo -n " " + fi + if \cp configure.in_new configure.in >& /dev/null + then + \rm -f configure.in_new + echo "done" + else + echo + echo "error, can't update previous configure.in" + fi +fi + +######################################################################## +# Use autoconf to rebuild the configure script +# + +if test -f configure +then + echo -n "Updating 'configure' script ... " +else + echo -n "Creating 'configure' script ... " +fi + +aclocal -I adm_local/unix/config_files -I ${KERNEL_ROOT_DIR}/salome_adm/unix/config_files \ + -I ${GUI_ROOT_DIR}/adm_local/unix/config_files \ + -I ${MED_ROOT_DIR}/adm_local/unix/config_files +if autoconf +then + echo "done" +else + echo "failed (check file permissions and/or user quotas ...)" +fi + +cd ${ORIG_DIR} + +echo diff --git a/configure.in.base b/configure.in.base new file mode 100644 index 0000000..bfad732 --- /dev/null +++ b/configure.in.base @@ -0,0 +1,337 @@ +# +# PLEASE DO NOT MODIFY configure.in FILE +# +# ALL CHANGES WILL BE DISCARDED BY THE NEXT +# build_configure COMMAND +# +# CHANGES MUST BE MADE IN configure.in.base FILE +# +# +# Author : Marc Tajchman (CEA) +# Date : 28/06/2001 +# Modified by : Patrick GOLDBRONN (CEA) +# Modified by : Marc Tajchman (CEA) +# +# Created from configure.in.base +# + +AC_INIT(src) +AC_CONFIG_AUX_DIR(${KERNEL_ROOT_DIR}/salome_adm/unix/config_files) +AC_CANONICAL_HOST + +PACKAGE=salome +AC_SUBST(PACKAGE) + +VERSION=3.2.2 +XVERSION=0x030202 +AC_SUBST(VERSION) +AC_SUBST(XVERSION) + +# set up MODULE_NAME variable for dynamic construction of directories (resources, etc.) +MODULE_NAME=multipr +AC_SUBST(MODULE_NAME) + +dnl +dnl Initialize source and build root directories +dnl + +ROOT_BUILDDIR=`pwd` +ROOT_SRCDIR=`echo $0 | sed -e "s,[[^/]]*$,,;s,/$,,;s,^$,.,"` +cd $ROOT_SRCDIR +ROOT_SRCDIR=`pwd` +cd $ROOT_BUILDDIR + +AC_SUBST(ROOT_SRCDIR) +AC_SUBST(ROOT_BUILDDIR) + +echo +echo Source root directory : $ROOT_SRCDIR +echo Build root directory : $ROOT_BUILDDIR +echo +echo + +if test -z "$AR"; then + AC_CHECK_PROGS(AR,ar xar,:,$PATH) +fi +AC_SUBST(AR) + +dnl Export the AR macro so that it will be placed in the libtool file +dnl correctly. +export AR + +echo +echo --------------------------------------------- +echo testing make +echo --------------------------------------------- +echo + +AC_PROG_MAKE_SET +AC_PROG_INSTALL +dnl +dnl libtool macro check for CC, LD, NM, LN_S, RANLIB, STRIP + for shared libraries + +AC_ENABLE_DEBUG(yes) +AC_DISABLE_PRODUCTION + +echo --------------------------------------------- +echo testing libtool +echo --------------------------------------------- + +dnl first, we set static to no! +dnl if we want it, use --enable-static +AC_ENABLE_STATIC(no) + +AC_LIBTOOL_DLOPEN +AC_PROG_LIBTOOL + +dnl Fix up the INSTALL macro if it s a relative path. We want the +dnl full-path to the binary instead. +case "$INSTALL" in + *install-sh*) + INSTALL='\${KERNEL_ROOT_DIR}'/salome_adm/unix/config_files/install-sh + ;; +esac + +echo +echo --------------------------------------------- +echo testing C/C++ +echo --------------------------------------------- +echo + +cc_ok=no +dnl inutil car libtool +dnl AC_PROG_CC +AC_PROG_CXX +AC_CXX_WARNINGS +AC_CXX_TEMPLATE_OPTIONS +AC_DEPEND_FLAG +# AC_CC_WARNINGS([ansi]) +cc_ok=yes + +dnl Library libdl : +AC_CHECK_LIB(dl,dlopen) + +dnl Library librt : for alpha/osf +AC_CHECK_LIB(rt,nanosleep) + +dnl add library libm : +AC_CHECK_LIB(m,ceil) + +AC_CXX_USE_STD_IOSTREAM +AC_CXX_HAVE_SSTREAM + +dnl +dnl --------------------------------------------- +dnl testing linker +dnl --------------------------------------------- +dnl + +AC_LINKER_OPTIONS + +echo +echo --------------------------------------------- +echo testing threads +echo --------------------------------------------- +echo + +ENABLE_PTHREADS + +echo +echo --------------------------------------------- +echo testing python +echo --------------------------------------------- +echo + +CHECK_PYTHON + +echo +echo --------------------------------------------- +echo testing QT +echo --------------------------------------------- +echo + +CHECK_QT + +echo +echo --------------------------------------------- +echo testing msg2qm +echo --------------------------------------------- +echo + +CHECK_MSG2QM + +echo +echo --------------------------------------------- +echo BOOST Library +echo --------------------------------------------- +echo + +CHECK_BOOST + +echo +echo --------------------------------------------- +echo Testing OpenCascade +echo --------------------------------------------- +echo + +CHECK_CAS + +echo +echo --------------------------------------------- +echo testing omniORB +echo --------------------------------------------- +echo + +CHECK_OMNIORB + +echo +echo --------------------------------------------- +echo default ORB : omniORB +echo --------------------------------------------- +echo + +DEFAULT_ORB=omniORB +CHECK_CORBA + +AC_SUBST_FILE(CORBA) +corba=make_$ORB +CORBA=adm_local/unix/$corba + +echo +echo --------------------------------------------- +echo Testing GUI +echo --------------------------------------------- +echo + +CHECK_SALOME_GUI + +echo +echo --------------------------------------------- +echo Testing full GUI +echo --------------------------------------------- +echo + +CHECK_CORBA_IN_GUI +if test "x${CORBA_IN_GUI}" != "xyes"; then + echo "failed : For configure MULTIPR module necessary full GUI !" + exit +fi + +echo +echo --------------------------------------------- +echo Testing Kernel +echo --------------------------------------------- +echo + +CHECK_KERNEL + +echo +echo --------------------------------------------- +echo Testing Med +echo --------------------------------------------- +echo + +CHECK_MED + +echo +echo --------------------------------------------- +echo testing HDF5 +echo --------------------------------------------- +echo + +CHECK_HDF5 + +echo +echo --------------------------------------------- +echo testing MED2 +echo --------------------------------------------- +echo + +CHECK_MED2 + +echo +echo --------------------------------------------- +echo Testing GUI +echo --------------------------------------------- +echo + +CHECK_SALOME_GUI + +echo +echo --------------------------------------------- +echo Summary +echo --------------------------------------------- +echo + +echo Configure +variables="cc_ok threads_ok boost_ok python_ok omniORB_ok qt_ok msg2qm_ok Kernel_ok Med_ok hdf5_ok med2_ok SalomeGUI_ok" + +for var in $variables +do + printf " %10s : " `echo \$var | sed -e "s,_ok,,"` + eval echo \$$var +done + +echo +echo "Default ORB : $DEFAULT_ORB" +echo + +dnl generals files which could be included in every makefile + +AC_SUBST_FILE(COMMENCE) COMMENCE=adm_local/unix/make_commence +AC_SUBST_FILE(CONCLUDE) CONCLUDE=salome_adm/unix/make_conclude +AC_SUBST_FILE(MODULE) MODULE=salome_adm/unix/make_module + +dnl les dependences +AC_SUBST_FILE(DEPEND) DEPEND=salome_adm/unix/depend + +dnl We don t need to say when we re entering directories if we re using +dnl GNU make becuase make does it for us. +if test "X$GMAKE" = "Xyes"; then + AC_SUBST(SETX) SETX=":" +else + AC_SUBST(SETX) SETX="set -x" +fi + +# make other build directories +for rep in salome_adm adm_local doc bin/salome include/salome lib${LIB_LOCATION_SUFFIX}/salome share/salome/resources/${MODULE_NAME} share/salome/doc idl +do + $INSTALL -d $rep +done + +echo +echo --------------------------------------------- +echo copying resource files, shell scripts, and +echo xml files +echo --------------------------------------------- +echo + +dnl copy shells and utilities contained in the bin directory +dnl excluding .in files (treated in AC-OUTPUT below) and CVS +dnl directory + +cd bin +for i in $ROOT_SRCDIR/bin/* +do + local_bin=`echo $i | sed -e "s,$ROOT_SRCDIR,.,"` + case "$local_bin" in + *.in | *~) ;; + ./bin/CVS) ;; + *) ln -fs $i; echo $local_bin ;; + esac +done +cd $ROOT_BUILDDIR + +AC_SUBST_FILE(ENVSCRIPT) ENVSCRIPT=salome_adm/unix/envScript + +echo +echo --------------------------------------------- +echo generating Makefiles and configure files +echo --------------------------------------------- +echo + +AC_OUTPUT_COMMANDS([ \ + chmod +x ./bin/* \ +]) + +## do not delete this line diff --git a/doc/CSSI_DRV_EDF-IOLS-MULTIPR_spec-conception_1_1.odt b/doc/CSSI_DRV_EDF-IOLS-MULTIPR_spec-conception_1_1.odt new file mode 100755 index 0000000..80f8063 Binary files /dev/null and b/doc/CSSI_DRV_EDF-IOLS-MULTIPR_spec-conception_1_1.odt differ diff --git a/doc/CSSI_DRV_EDF-IOLS-MULTIPR_spec-conception_1_1.pdf b/doc/CSSI_DRV_EDF-IOLS-MULTIPR_spec-conception_1_1.pdf new file mode 100755 index 0000000..1584def Binary files /dev/null and b/doc/CSSI_DRV_EDF-IOLS-MULTIPR_spec-conception_1_1.pdf differ diff --git a/idl/MULTIPR.idl b/idl/MULTIPR.idl new file mode 100644 index 0000000..19510b7 --- /dev/null +++ b/idl/MULTIPR.idl @@ -0,0 +1,230 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +// +// MULTIPR.idl +// +// Interface CORBA for the MULTIPR module +// +// Author: Olivier LE ROUX - CS, Virtual Reality Dpt +// +// Date: 01/2007 +// + +#ifndef __MULTIPR_INTERFACE_CORBA__ +#define __MULTIPR_INTERFACE_CORBA__ + +#include "SALOME_Exception.idl" +#include "SALOME_Component.idl" +#include "SALOME_GenericObj.idl" +#include "SALOMEDS.idl" // to access study + + +/*! \ingroup MULTIPR + * + * This package contains the interface MULTIPR_ORB used for %MULTIPR component. + */ +module MULTIPR_ORB +{ + + +typedef sequence string_array; + + +//************************************************************************* +// Interface of the %MULTIPR component used to manage partition/decimation +//************************************************************************* + +interface MULTIPR_Obj +{ + + //--------------------------------------------------------------------- + // Basic accessors/mutators + //-------------------------------------------------------------------- + + /*! + * Return true iff this obj represents a valid sequential MED file. + */ + boolean isValidSequentialMEDFile(); + + /*! + * Return true iff this obj represents a valid distributed MED file. + */ + boolean isValidDistributedMEDFile(); + + /*! + * Set the mesh to be partitionned/decimated. + * Assume sequential MED file. + */ + void setMesh(in string meshName) + raises (SALOME::SALOME_Exception); + + /*! + * Set the boxing parameter used for decimation (100 by default). + */ + void setBoxing(in long boxing) + raises (SALOME::SALOME_Exception); + + /*! + * Return the list of meshes contained in the associated MED file. + */ + string_array getMeshes() + raises (SALOME::SALOME_Exception); + + /*! + * Return the list of fields contained in the current mesh of the associated MED file. + */ + string_array getFields() + raises (SALOME::SALOME_Exception); + + /*! + * Return the number of iterations for a given field. + */ + long getTimeStamps(in string fieldName) + raises (SALOME::SALOME_Exception); + + /*! + * Return the name of all partitions. + * Assume this object encapsulates a distributed MED file. + */ + string_array getParts() + raises (SALOME::SALOME_Exception); + + /*! + * Return all information abour a part. + * Assume this object encapsulates a distributed MED file. + */ + string getPartInfo(in string partName) + raises (SALOME::SALOME_Exception); + + //--------------------------------------------------------------------- + // Algorithms + //-------------------------------------------------------------------- + + /*! + * Create a distributed MED file (v2.3) by extracting all the groups from the current mesh of the current MED sequential MED file. + * Assume: + * - the file is in MED format and can be read using MED file v2.3. + * - the file is sequential (not a distributed MED). + * - the file only contains TETRA10 elements (dimension of space and mesh is 3). + * - the file have no profil. + * \return the name of each part. + */ + string_array partitionneDomaine() + raises (SALOME::SALOME_Exception); + + /*! + * Create a distributed MED file (V2.3) by splitting a group of a MED file previously created by partitionneDomaine. + * Assume: + * - the file is a distributed MED file, previously created by partitionneDomaine() + * (=> each part only contain 1 mesh, TETRA10 elements only) + * - nbPart > 1 + * - partitionner METIS=0 or SCOTCH=1 + * \return the name of each part. + */ + string_array partitionneGrain( + in string partName, + in long nbParts, + in long partitionner) + raises (SALOME::SALOME_Exception); + + /*! + * Create 3 resolutions of the given part of a distributed MED file (V2.3). + * Assume: + * - the file is a distributed MED file, previously created by partitionneDomaine() or partitionneGrain() + * (=> each part only contain 1 mesh, TETRA10 elements only) + */ + string_array decimePartition( + in string partName, + in string fieldName, + in long fieldIt, + in string filterName, + in double tmed, + in double tlow, + in double radius) + raises (SALOME::SALOME_Exception); + + //--------------------------------------------------------------------- + // i/o + //-------------------------------------------------------------------- + + /*! + * Save the current distributed MED file to disk. + */ + void save() + raises (SALOME::SALOME_Exception); + +}; // interface MULTIPR_Obj + + +//************************************************************************* +// Interface of the %MULTIPR component; used to create MULTIPR_Obj object +// and to define high level API. +//************************************************************************* +interface MULTIPR_Gen : Engines::Component +{ + /*! + * Return the version of the MULTIPR library. + */ + string getVersion() + raises (SALOME::SALOME_Exception); + + //------------------------------------------------------------------------ + // High level API + // Directly apply one of the 3 main operations of the MULTIPR module on a MED file + //------------------------------------------------------------------------ + + /*! + * Create a distributed MED file (v2.3) by extracting all the groups from the mesh of a sequential MED file. + * High level function. + */ + void partitionneDomaine( + in string medFilename, + in string meshName) + raises (SALOME::SALOME_Exception); + + /*! + * Create a distributed MED file (V2.3) by splitting a group of a MED file previously created by partitionneDomaine(). + * High level function. + */ + void partitionneGrain( + in string medFilename, + in string partName, + in long nbParts, + in long partitionner) // 0=METIS 1=SCOTCH + raises (SALOME::SALOME_Exception); + + /*! + * Creates 3 resolutions of the given part of a distributed MED file (V2.3). + * High level function. + */ + void decimePartition( + in string medFilename, + in string partName, + in string fieldName, + in long fieldIt, + in string filterName, + in double tmed, + in double tlow, + in double radius, + in long boxing) + raises (SALOME::SALOME_Exception); + + //------------------------------------------------------------------------ + // Low level API + // Create an object to encapsulate a MED file. + //------------------------------------------------------------------------ + + /*! + * Create a MULTIPR_Obj object which encapsulate a MED file. + */ + MULTIPR_Obj getObject(in string medFilename) + raises (SALOME::SALOME_Exception); + +}; // interface MULTIPR_Gen + + +}; // module MULTIPR_ORB + +#endif // __MULTIPR_INTERFACE_CORBA__ + diff --git a/idl/Makefile.in b/idl/Makefile.in new file mode 100644 index 0000000..57b0c2f --- /dev/null +++ b/idl/Makefile.in @@ -0,0 +1,86 @@ +# Copyright (C) 2005 OPEN CASCADE, CEA, EDF R&D, LEG +# PRINCIPIA R&D, EADS CCR, Lip6, BV, CEDRAT +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +# +# generate dependencies for idl file : +# + +# source path +top_srcdir=@top_srcdir@ +top_builddir=.. +srcdir=@srcdir@ +VPATH=.:${KERNEL_ROOT_DIR}/idl/salome + +@COMMENCE@ + +IDL_FILES = \ + MULTIPR.idl + +PY_CLIENT_IDL = $(IDL_FILES) + +# we copy all idl file in $(top_builddir)/idl +inc: $(top_builddir)/idl/salome $(IDL_FILES:%=$(top_builddir)/idl/salome/%) + +$(top_builddir)/idl/salome: + mkdir $@ + +$(IDL_FILES:%=$(top_builddir)/idl/salome/%):$(IDL_FILES:%=$(top_srcdir)/idl/%) +# $(CP) $< $@ + cp -f $^ $(top_builddir)/idl/salome + + +lib: pyidl + +PYTHON_BUILD_SITE=$(top_builddir)/lib@LIB_LOCATION_SUFFIX@/python$(PYTHON_VERSION)/site-packages/@PACKAGE@ + +pyidl: $(PYTHON_BUILD_SITE) $(IDL_FILES:%.idl=$(PYTHON_BUILD_SITE)/%_idl.py) + +$(PYTHON_BUILD_SITE): + $(INSTALL) -d $@ + +$(PYTHON_BUILD_SITE)/%_idl.py: $(top_builddir)/idl/salome/%.idl + $(OMNIORB_IDL) $(OMNIORB_IDLPYFLAGS) -C$(PYTHON_BUILD_SITE) $< + + +# install python client (generated from idl file +install: install-pyidl install-idl + +# create directory $(idldir) and copy idl files into it +install-idl: $(IDL_FILES:%=$(top_builddir)/idl/salome/%) + $(INSTALL) -d $(idldir) + $(INSTALL_DATA) $^ $(idldir) + + +install-pyidl: $(IDL_FILES:%=$(top_builddir)/idl/salome/%) + $(INSTALL) -d $(PYTHON_SITE_INSTALL) + @for file in $^ dummy; do \ + if [ $$file != "dummy" ]; then \ + $(OMNIORB_IDL) $(OMNIORB_IDLPYFLAGS) -C$(PYTHON_SITE_INSTALL) $$file ; \ + fi ; \ + done ; + +#@ CONCLUDE @ + +cleandep: + -$(RM) .dep* + +distclean: + -$(RM) *.py + -$(RM) $(IDL_FILES:%=$(top_builddir)/idl/salome/%) + -$(RM) Makefile + diff --git a/resources/ExecMULTIPR.png b/resources/ExecMULTIPR.png new file mode 100644 index 0000000..436af1d Binary files /dev/null and b/resources/ExecMULTIPR.png differ diff --git a/resources/MULTIPR.png b/resources/MULTIPR.png new file mode 100644 index 0000000..436af1d Binary files /dev/null and b/resources/MULTIPR.png differ diff --git a/resources/MULTIPRCatalog.xml.in b/resources/MULTIPRCatalog.xml.in new file mode 100644 index 0000000..5ee10c9 --- /dev/null +++ b/resources/MULTIPRCatalog.xml.in @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + MULTIPR + MULTIPR GUI + Data + O. Le Roux + @VERSION@ + CS/EDF-RD + 1 + MULTIPR.png + 'linux' ~ OS + + + + + MULTIPR + No comment + + + + + getObject + O. Le Roux + 1.0.0 + + + + MEDfilename + string + Name of the MED file to be processed + + + + + return + MULTIPR_Obj + + + + + + + + + + + diff --git a/resources/MULTIPR_import_med.png b/resources/MULTIPR_import_med.png new file mode 100644 index 0000000..d9953b6 Binary files /dev/null and b/resources/MULTIPR_import_med.png differ diff --git a/resources/MULTIPR_save_med.png b/resources/MULTIPR_save_med.png new file mode 100644 index 0000000..330493f Binary files /dev/null and b/resources/MULTIPR_save_med.png differ diff --git a/resources/SalomeApp.xml b/resources/SalomeApp.xml new file mode 100644 index 0000000..3e52145 --- /dev/null +++ b/resources/SalomeApp.xml @@ -0,0 +1,11 @@ + +
+ + + +
+
+ + +
+
diff --git a/src/MULTIPR/MULTIPR_API.cxx b/src/MULTIPR/MULTIPR_API.cxx new file mode 100644 index 0000000..5c5fda5 --- /dev/null +++ b/src/MULTIPR/MULTIPR_API.cxx @@ -0,0 +1,193 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_API.cxx + * + * \brief see MULTIPR_API.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_API.hxx" +#include "MULTIPR_Globals.hxx" +#include "MULTIPR_Mesh.hxx" +#include "MULTIPR_MeshDis.hxx" +#include "MULTIPR_Utils.hxx" +#include "MULTIPR_Exceptions.hxx" + +extern "C" +{ + #include "med.h" +} + +#include "MEDSPLITTER_API.hxx" + +#include +#include +#include + +using namespace std; + + +//***************************************************************************** +// Implementation +//***************************************************************************** + +const char* multipr::getVersion() +{ + return "1.0"; +} + + +void multipr::partitionneDomaine(const char* pMEDfilename, const char* pMeshName) +{ + if (pMEDfilename == NULL) throw NullArgumentException("pMEDfilename should not be NULL", __FILE__, __LINE__); + if (pMeshName == NULL) throw NullArgumentException("pMeshName should not be NULL", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Read the sequential mesh + //--------------------------------------------------------------------- + cout << "Read sequential MED file: " << pMEDfilename << ": please wait... " << endl; + + multipr::Mesh mesh; + mesh.readSequentialMED(pMEDfilename, pMeshName); + cout << mesh << endl; + + //--------------------------------------------------------------------- + // Build distributed mesh from groups + //--------------------------------------------------------------------- + cout << "Build distributed mesh: please wait... " << endl; + multipr::MeshDis* meshDis = NULL; + try + { + meshDis = mesh.splitGroupsOfElements(); + + //------------------------------------------------------------- + // Write distributed mesh + //------------------------------------------------------------- + cout << "Write distributed mesh: please wait... " << endl; + string strPrefix = removeExtension(pMEDfilename, ".med"); + meshDis->writeDistributedMED(strPrefix.c_str()); + + delete meshDis; + } + catch (RuntimeException& e) + { + delete meshDis; + throw e; + } +} + + +void multipr::partitionneGrain( + const char* pMEDfilename, + const char* pGroupName, + int pNbParts, + int pPartitionner) +{ + if (pMEDfilename == NULL) throw NullArgumentException("pMEDfilename should not be NULL", __FILE__, __LINE__); + if (pGroupName == NULL) throw NullArgumentException("pGroupName should not be NULL", __FILE__, __LINE__); + if (pNbParts < 2) throw IllegalArgumentException("pNbParts should be >= 2", __FILE__, __LINE__); + if ((pPartitionner != MULTIPR_METIS) && (pPartitionner != MULTIPR_SCOTCH)) throw NullArgumentException("pPartitionner should be METIS (0) or SCOTCH (1)", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Read the distributed mesh + //--------------------------------------------------------------------- + MULTIPR_LOG("Read distributed MED file: " << pMEDfilename << ": please wait... " << endl); + + int ret = MEDformatConforme(pMEDfilename); + if (ret == 0) throw IOException("waiting for a distributed MED file (not a sequential one)", __FILE__, __LINE__); + + multipr::MeshDis meshDis; + meshDis.readDistributedMED(pMEDfilename); + cout << meshDis << endl; + + //--------------------------------------------------------------------- + // Split the given part (pGroupName) + //--------------------------------------------------------------------- + if (pPartitionner == MULTIPR_METIS) + { + cout << "Use METIS" << endl; + } + else if (pPartitionner == MULTIPR_SCOTCH) + { + cout << "Use SCOTCH" << endl; + } + + meshDis.splitPart(pGroupName, pNbParts, pPartitionner); + cout << meshDis << endl; + + //--------------------------------------------------------------------- + // Write new distributed mesh + //--------------------------------------------------------------------- + string strPrefix = multipr::removeExtension(pMEDfilename, ".med"); + meshDis.writeDistributedMED(strPrefix.c_str()); +} + + +void multipr::decimePartition( + const char* pMEDfilename, + const char* pPartName, + const char* pFieldName, + int pFieldIt, + const char* pFilterName, + double pTMed, + double pTLow, + double pRadius, + int pBoxing) +{ + //--------------------------------------------------------------------- + // Check arguments + //--------------------------------------------------------------------- + if (pMEDfilename == NULL) throw NullArgumentException("pMEDfilename should not be NULL", __FILE__, __LINE__); + if (pPartName == NULL) throw NullArgumentException("pPartName should not be NULL", __FILE__, __LINE__); + if (pFieldName == NULL) throw NullArgumentException("pFieldName should not be NULL", __FILE__, __LINE__); + if (pFieldIt < 1) throw IllegalArgumentException("pFieldIt: invalid field iteration; should be >= 1", __FILE__, __LINE__); + if (pTMed < 0.0) throw IllegalArgumentException("med res.: threshold must be > 0", __FILE__, __LINE__); + if (pTMed >= pTLow) throw IllegalArgumentException("threshold for med res. must be < threshold for low res.", __FILE__, __LINE__); + if (pRadius <= 0.0) throw IllegalArgumentException("radius should be > 0", __FILE__, __LINE__); + if ((pBoxing < 1) || (pBoxing > 200)) throw IllegalArgumentException("boxing should be in [1..200]", __FILE__, __LINE__); + + cout << "--decim file=" << pMEDfilename << " part=" << pPartName << " filter=" << pFilterName << " tmed=" << pTMed << " tlow=" << pTLow << " radius=" << pRadius << endl; + + //--------------------------------------------------------------------- + // Read the distributed mesh + //--------------------------------------------------------------------- + MULTIPR_LOG("Read distributed MED file: " << pMEDfilename << ": please wait... " << endl); + + int ret = MEDformatConforme(pMEDfilename); + if (ret == 0) throw IOException("waiting for a distributed MED file (not a sequential one)", __FILE__, __LINE__); + + multipr::MeshDis meshDis; + meshDis.readDistributedMED(pMEDfilename); + cout << meshDis << endl; + + //--------------------------------------------------------------------- + // Create 3 resolutions of the given part + //--------------------------------------------------------------------- + meshDis.decimatePart( + pPartName, + pFieldName, + pFieldIt, + pFilterName, + pTMed, + pTLow, + pRadius, + pBoxing); + cout << meshDis << endl; + + //--------------------------------------------------------------------- + // Write new distributed mesh + //--------------------------------------------------------------------- + string strPrefix = removeExtension(pMEDfilename, ".med"); // get prefix from the original MED filename + meshDis.writeDistributedMED(strPrefix.c_str()); +} + +// EOF diff --git a/src/MULTIPR/MULTIPR_API.hxx b/src/MULTIPR/MULTIPR_API.hxx new file mode 100644 index 0000000..8c42885 --- /dev/null +++ b/src/MULTIPR/MULTIPR_API.hxx @@ -0,0 +1,108 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_API.hxx + * + * \brief Main header of the high level MULTIPR API. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_API_HXX +#define MULTIPR_API_HXX + + +namespace multipr +{ + + +enum Partitionner +{ + MULTIPR_METIS = 0, + MULTIPR_SCOTCH = 1 + +}; // enum Partitionner + + +/** + * \fn const char* getVersion() + * \brief returns the current version of the MULTIPR API. + * \return the current version of the MULTIPR API. + */ +const char* getVersion(); + + +/** + * \fn int partitionneDomaine(const char* medFilename, const char* meshName) + * \brief creates a distributed MED file (v2.3) by extracting all the groups from the mesh of a sequential MED file. + * Assumes: + * - the file is in MED format and can be read using MED file v2.3. + * - the file is sequential (not a distributed MED). + * - the file only contains TETRA10 elements (dimension of space and mesh is 3). + * - the file have no profil. + * \param medFilename filename of any valid sequential MED file with TETRA10 elements only. + * \param meshName name of the mesh to be distributed. + * \throw RuntimeException if any error occurs. + */ +void partitionneDomaine( + const char* medFilename, + const char* meshName); + + +/** + * \fn int partitionneGrain(const char* medFilename, const char* groupName, int nbParts, int partitionner) + * \brief creates a distributed MED file (V2.3) by splitting a group of a MED file previously created by partitionneDomaine. + * Assumes: + * - the file is a distributed MED file, previously created by partitionneDomaine() + * (=> each part only contain 1 mesh, TETRA10 elements only) + * - nbPart > 1 + * \param medFilename filename of any valid distributed MED file previously created by partitionneDomaine(). + * \param partName name of the part to be splitted. + * \param nbParts number of parts; must be > 1. + * \param partitionner use value MULTIPR_METIS for Metis or MULTIPR_SCOTCH for Scotch. + * \throw RuntimeException if any error occurs. + */ + void partitionneGrain( + const char* medFilename, + const char* partName, + int nbParts, + int partitionner=MULTIPR_METIS); + + +/** + * \fn int decimePartition(const char* medFilename, const char* partName, const char* fieldName, int fieldIt, const char* filterName, double tmed, double tlow, double radius); + * \brief creates 3 resolutions of the given part of a distributed MED file (V2.3). + * Assumes: + * - the file is a distributed MED file, previously created by partitionneDomaine() or partitionneGrain() + * (=> each part only contain 1 mesh, TETRA10 elements only) + * \param medFilename filename of any valid distributed MED file previously created by partitionneDomaine or partitionneGrain. + * \param partName name of the part to be decimated. + * \param fieldName name of the field used for decimation. + * \param fieldIt iteration (time step) of the field. + * \param filterName name of the filter to be used. + * \param tmed threshold used for medium resolution. + * \param tlow threshold used for low resolution; tmed must be less than tlow + * \param radius radius used to determine the neighbourhood. + * \param boxing number of cells along each axis; must be >= 1; e.g. if 100 then acceleration grid will have 100*100*100 = 10**6 cells. + * \throw RuntimeException if any error occurs. + */ +void decimePartition( + const char* medFilename, + const char* partName, + const char* fieldName, + int fieldIt, + const char* filterName, + double tmed, + double tlow, + double radius, + int boxing); + +} // namespace MULTIPR + + +#endif // MULTIPR_API_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_DecimationAccel.cxx b/src/MULTIPR/MULTIPR_DecimationAccel.cxx new file mode 100644 index 0000000..080613a --- /dev/null +++ b/src/MULTIPR/MULTIPR_DecimationAccel.cxx @@ -0,0 +1,325 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_DecimationAccel.cxx + * + * \brief see MULTIPR_DecimationAccel.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_DecimationAccel.hxx" +#include "MULTIPR_PointOfField.hxx" +#include "MULTIPR_Exceptions.hxx" + +#include + +using namespace std; + + +namespace multipr +{ + + +//***************************************************************************** +// Class DecimationAccel implementation +//***************************************************************************** + + +ostream& operator<<(ostream& pOs, DecimationAccel& pA) +{ + pOs << "DecimationAccel:" << endl; + return pOs; +} + + +//***************************************************************************** +// Class DecimationAccelGrid +//***************************************************************************** + +DecimationAccelGrid::DecimationAccelGrid() +{ + mGrid = NULL; + + reset(); +} + + +DecimationAccelGrid::~DecimationAccelGrid() +{ + reset(); +} + + +void DecimationAccelGrid::reset() +{ + mNum = 0; + + mMin[0] = numeric_limits::quiet_NaN(); + mMin[1] = numeric_limits::quiet_NaN(); + mMin[2] = numeric_limits::quiet_NaN(); + + mMax[0] = numeric_limits::quiet_NaN(); + mMax[1] = numeric_limits::quiet_NaN(); + mMax[2] = numeric_limits::quiet_NaN(); + + mInvLen[0] = numeric_limits::quiet_NaN(); + mInvLen[1] = numeric_limits::quiet_NaN(); + mInvLen[2] = numeric_limits::quiet_NaN(); + + mSize[0] = 0; + mSize[1] = 0; + mSize[2] = 0; + + if (mGrid != NULL) + { + delete[] mGrid; + mGrid = NULL; + } + + mFlagPrintAll = false; +} + + +void DecimationAccelGrid::create(const std::vector& pPts) +{ + // check if grid have been initialized + if (mSize[0] == 0) throw IllegalStateException("call setSize() before", __FILE__, __LINE__); + + // compute bbox of the grid + computeBBox(pPts); + + // allocate the grid + int size = mSize[0] * mSize[1] * mSize[2]; + mGrid = new vector[size]; + + // fill the grid + mNum = pPts.size(); + for (int i = 0 ; i < mNum ; i++) + { + vector& cell = getCell(pPts[i]); + cell.push_back(pPts[i]); + } +} + + +void DecimationAccelGrid::configure(const char* pArgv) +{ + // check arguments + if (pArgv == NULL) throw NullArgumentException("", __FILE__, __LINE__); + + int sizeX = 0; + int sizeY = 0; + int sizeZ = 0; + + int ret = sscanf(pArgv, "%d %d %d", &sizeX, &sizeY, &sizeZ); + + if (ret != 3) throw IllegalArgumentException("expected 3 parameters", __FILE__, __LINE__); + if (sizeX <= 0) throw IllegalArgumentException("number of cells along X-axis must be > 0", __FILE__, __LINE__); + if (sizeY <= 0) throw IllegalArgumentException("number of cells along Y-axis must be > 0", __FILE__, __LINE__); + if (sizeZ <= 0) throw IllegalArgumentException("number of cells along Z-axis must be > 0", __FILE__, __LINE__); + + reset(); + + mSize[0] = sizeX; + mSize[1] = sizeY; + mSize[2] = sizeZ; +} + + +void DecimationAccelGrid::getCellCoord( + med_float pX, med_float pY, med_float pZ, + int* pIx, int* pIy, int* pIz) const +{ + med_float cx = (pX - mMin[0]) * mInvLen[0]; + med_float cy = (pY - mMin[1]) * mInvLen[1]; + med_float cz = (pZ - mMin[2]) * mInvLen[2]; + + *pIx = med_int(cx); + if (*pIx >= mSize[0]) *pIx = mSize[0] - 1; + else if (*pIx < 0) *pIx = 0; + + *pIy = med_int(cy); + if (*pIy >= mSize[1]) *pIy = mSize[1] - 1; + else if (*pIy < 0) *pIy = 0; + + *pIz = med_int(cz); + if (*pIz >= mSize[2]) *pIz = mSize[2] - 1; + else if (*pIz < 0) *pIz = 0; +} + + +int DecimationAccelGrid::getCellIndex(int pI, int pJ, int pK) const +{ + int index = pK * (mSize[0] * mSize[1]) + pJ * mSize[0] + pI; + + return index; +} + + +vector& DecimationAccelGrid::getCell(const PointOfField& pPt) +{ + int ix, iy, iz; + + getCellCoord( + pPt.mXYZ[0], pPt.mXYZ[1], pPt.mXYZ[2], + &ix, &iy, &iz); + + int index = getCellIndex(ix, iy, iz); + + return mGrid[index]; +} + + +vector DecimationAccelGrid::findNeighbours( + med_float pCenterX, + med_float pCenterY, + med_float pCenterZ, + med_float pRadius) const +{ + //--------------------------------------------------------------------- + // Determine the axis aligned bounding box of the sphere ((x, y, z), r) + //--------------------------------------------------------------------- + med_float sphereBBoxMin[3]; + med_float sphereBBoxMax[3]; + + sphereBBoxMin[0] = pCenterX - pRadius; + sphereBBoxMin[1] = pCenterY - pRadius; + sphereBBoxMin[2] = pCenterZ - pRadius; + + sphereBBoxMax[0] = pCenterX + pRadius; + sphereBBoxMax[1] = pCenterY + pRadius; + sphereBBoxMax[2] = pCenterZ + pRadius; + + //--------------------------------------------------------------------- + // Determine the cells of the grid intersected by the sphere ((x, y, z), r) + // => range of cells are [iMinCell[0], iMaxCell[0]] x [iMinCell[1], iMaxCell[1]] x [iMinCell[2], iMaxCell[2]] + //--------------------------------------------------------------------- + int iMinCell[3]; + int iMaxCell[3]; + + getCellCoord(sphereBBoxMin[0], sphereBBoxMin[1], sphereBBoxMin[2], + &iMinCell[0], &iMinCell[1], &iMinCell[2]); + + getCellCoord(sphereBBoxMax[0], sphereBBoxMax[1], sphereBBoxMax[2], + &iMaxCell[0], &iMaxCell[1], &iMaxCell[2]); + + //--------------------------------------------------------------------- + // Collect points of the field which are in the sphere + //--------------------------------------------------------------------- + vector res; + +/* +// debug +cout << "Center = " << pCenterX << " " << pCenterY << " " << pCenterZ << endl; +cout << "Radius = " << pRadius << endl; +cout << "Visited cells : [" << iMinCell[0] << " ; " << iMaxCell[0] << "] x ["<< iMinCell[1] << " ; " << iMaxCell[1] << "] x [" << iMinCell[2] << " ; " << iMaxCell[2] << "]" << endl; +*/ + + // for all the cells in the grid intersected by the sphere ((x, y, z), r) + for (int i = iMinCell[0] ; i <= iMaxCell[0] ; i++) + { + for (int j = iMinCell[1] ; j <= iMaxCell[1] ; j++) + { + for (int k = iMinCell[2] ; k <= iMaxCell[2] ; k++) + { + int idCell = getCellIndex(i, j, k); + +//printf("DEBUG: visited cell(%d %d %d) -> %d\n", i, j, k, idCell); + + vector& cell = mGrid[idCell]; + + // for all the points in the current cell + for (vector::const_iterator itPoint = cell.begin() ; itPoint != cell.end() ; itPoint++) + { + const PointOfField& currentPt = *itPoint; + + // test if currentPt is in the sphere ((x, y, z), r) + med_float vecX = currentPt.mXYZ[0] - pCenterX; + med_float vecY = currentPt.mXYZ[1] - pCenterY; + med_float vecZ = currentPt.mXYZ[2] - pCenterZ; + + med_float norm = med_float( sqrt( vecX*vecX + vecY*vecY + vecZ*vecZ ) ); + if (norm < pRadius) + { + // only add the point if it is different from (x, y, z) + if ((currentPt.mXYZ[0] != pCenterX) || + (currentPt.mXYZ[1] != pCenterY) || + (currentPt.mXYZ[2] != pCenterZ)) + { + res.push_back(currentPt); + } + } + } + } + } + } + + return res; +} + + +void DecimationAccelGrid::computeBBox(const std::vector& pPts) +{ + for (int itDim = 0 ; itDim < 3 ; itDim++) + { + mMin[itDim] = numeric_limits::max(); + mMax[itDim] = -mMin[itDim]; + } + + for (unsigned i = 0 ; i < pPts.size() ; i++) + { + for (int itDim = 0 ; itDim < 3 ; itDim++) + { + med_float coord = pPts[i].mXYZ[itDim]; + if (coord < mMin[itDim]) mMin[itDim] = coord; + if (coord > mMax[itDim]) mMax[itDim] = coord; + } + } + + mInvLen[0] = med_float(mSize[0]) / (mMax[0] - mMin[0]); + mInvLen[1] = med_float(mSize[1]) / (mMax[1] - mMin[1]); + mInvLen[2] = med_float(mSize[2]) / (mMax[2] - mMin[2]); +} + + +ostream& operator<<(ostream& pOs, DecimationAccelGrid& pG) +{ + pOs << "DecimationAccelGrid:" << endl; + pOs << " Num=" << pG.mNum << endl; + pOs << " Size=" << pG.mSize[0] << " x " << pG.mSize[1] << " x " << pG.mSize[2] << endl; + pOs << " BBox=[" << pG.mMin[0] << " ; " << pG.mMax[0] << "] x [" << pG.mMin[1] << " ; " << pG.mMax[1] << "] x [" << pG.mMin[2] << " ; " << pG.mMax[2] << "]" << endl; + pOs << " Inv len.=" << pG.mInvLen[0] << " ; " << pG.mInvLen[1] << " ; " << pG.mInvLen[2] << endl; + + if (pG.mFlagPrintAll) + { + int checkNumCells = 0; + int numCells = pG.mSize[0] * pG.mSize[1] * pG.mSize[2]; + for (int i = 0 ; i < numCells ; i++) + { + vector& cell = pG.mGrid[i]; + cout << " Cell " << i << ": #=" << cell.size() << ": " << endl; + for (unsigned j = 0 ; j < cell.size() ; j++) + { + cout << " " << cell[j] << endl; + } + checkNumCells += cell.size(); + } + + if (pG.mNum != checkNumCells) throw IllegalStateException("", __FILE__, __LINE__); + } + + return pOs; +} + + +} // namespace multipr + +// EOF diff --git a/src/MULTIPR/MULTIPR_DecimationAccel.hxx b/src/MULTIPR/MULTIPR_DecimationAccel.hxx new file mode 100644 index 0000000..f85f846 --- /dev/null +++ b/src/MULTIPR/MULTIPR_DecimationAccel.hxx @@ -0,0 +1,258 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_DecimationAccel.hxx + * + * \brief Interface DecimationAccel: acceleration structure used for decimation. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_DECIMATION_ACCEL_HXX +#define MULTIPR_DECIMATION_ACCEL_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + +extern "C" +{ + #include "med.h" +} + +#include +#include + + +namespace multipr +{ + +//***************************************************************************** +// Predeclaration +//***************************************************************************** + +class PointOfField; + + +//***************************************************************************** +// Interface DecimationAccel +//***************************************************************************** + +class DecimationAccel +{ +public: + + /** + * Builds an empty DecimationAccel (default constructor). + */ + DecimationAccel() { /* do nothing */ } + + /** + * Destructor. Removes everything. + */ + virtual ~DecimationAccel() { /* do nothing */ } + + //--------------------------------------------------------------------- + // Algorithms + //--------------------------------------------------------------------- + + /** + * Interface. Configures this acceleration structure. String is used for genericity. + * \param pArgv all the configuration parameters in a string. + */ + virtual void configure(const char* pArgv) = 0; + + /** + * Interface. Creates a new acceleration structure and fills it with the given list of points. + * \param pPts list of points to be inserted in the acceleration structure. + */ + virtual void create(const std::vector& pPts) = 0; + + /** + * Interface. Finds all the points in a sphere defined by its center (x,y,z) and its radius. + * \param pCenterX x-coordinates of the center of the sphere. + * \param pCenterY y-coordinates of the center of the sphere. + * \param pCenterZ z-coordinates of the center of the sphere. + * \param pRadius radius of the sphere. + * \return all the points in a sphere defined by its center (x,y,z) and its radius. + */ + virtual std::vector findNeighbours( + med_float pCenterX, + med_float pCenterY, + med_float pCenterZ, + med_float pRadius) const = 0; + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Sets the flag which control the stream operator <<. + * \param pFlag new flag value. + */ + void setPrintAll(bool pFlag) { mFlagPrintAll = pFlag; } + + /** + * Dumps any GaussLoc to the given output stream. + * \param pOs any output stream. + * \param pA any DecimationAccel. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, DecimationAccel& pA); + +protected: + + bool mFlagPrintAll; /** Flag to control the behaviour of the stream operator <<. */ + +private: + + // do not allow copy constructor + DecimationAccel(const DecimationAccel&); + + // do not allow copy + DecimationAccel& operator=(const DecimationAccel&); + + // do not allow operator == + bool operator==(const DecimationAccel&); + +}; // class DecimationAccel + + +//***************************************************************************** +// Interface DecimationFilter and factory to build filters. +//***************************************************************************** + +class DecimationAccelGrid : public DecimationAccel +{ +public: + + /** + * Builds an empty DecimationAccelGrid (default constructor). + */ + DecimationAccelGrid(); + + /** + * Destructor. Removes everything. + */ + virtual ~DecimationAccelGrid(); + + /** + * Resets this object in its state by default (empty). Cleans memory. + */ + void reset(); + + //--------------------------------------------------------------------- + // Algorithms + //--------------------------------------------------------------------- + + /** + * Configures this acceleration structure. String is used for genericity. + * \param pArgv assumes "size_x size_y size_z": number of cells along each axis. + */ + virtual void configure(const char* pArgv); + + /** + * Creates a new acceleration structure and fills it with the given list of points. + * setSize() must have been called before. + * \param pPts list of points to be inserted in the acceleration structure. + * \throw IllegalStateException if setSize() has not been called before. + */ + virtual void create(const std::vector& pPts); + + /** + * Finds all the points in a sphere defined by its center (x,y,z) and its radius. + * \param pCenterX x-coordinates of the center of the sphere. + * \param pCenterY y-coordinates of the center of the sphere. + * \param pCenterZ z-coordinates of the center of the sphere. + * \param pRadius radius of the sphere. + * \return all the points in a sphere defined by its center (x,y,z) and its radius. + */ + virtual std::vector findNeighbours( + med_float pCenterX, + med_float pCenterY, + med_float pCenterZ, + med_float pRadius) const; + + /** + * Returns the coordinates of the cell which contain the point (x,y,z). + * Clamping is performed on (pIx, pIy, pIz) to avoid out of bounds. + * \param pX (in) X-coordinates of the point. + * \param pY (in) Y-coordinates of the point. + * \param pZ (in) Z-coordinates of the point. + * \param pIx (out) X-index of the cell which contain the point (x,y,z). + * \param pIy (out) Y-index. + * \param pIz (out) Z-index. + */ + void getCellCoord( + med_float pX, med_float pY, med_float pZ, + int* pIx, int* pIy, int* pIz) const; + + /** + * Returns the index of the cell whose coordinates are (i, j, k). + * \param pI + * \param pJ + * \param pK + * \return the index of the cell (i, j, k). + */ + int getCellIndex(int pI, int pJ, int pK) const; + + /** + * Returns the list of points contained in the cell of pPt. + * \param pPt any point which coordinates are in the bbox of this acceleration structure. + * \return the list of points contained in the cell of pPt. + */ + std::vector& getCell(const PointOfField& pPt); + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Dumps any GaussLoc to the given output stream. + * \param pOs any output stream. + * \param pG any DecimationAccelGrid. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, DecimationAccelGrid& pG); + +private: + + /** + * Computes the axis-aligned bounding box of a set of points. + * Sets the fields mMin/mMax. + * \param pPts list of points. + */ + void computeBBox(const std::vector& pPts); + +private: + + int mNum; /**< Number of points in the grid. */ + med_float mMin[3]; /**< Bounding box, min corner. */ + med_float mMax[3]; /**< Bounding box, max corner. */ + med_float mInvLen[3]; /**< 1/length of cells, along each dimension. */ + med_int mSize[3]; /**< Number of cells along each dimension. */ + std::vector* mGrid; /**< Flatten grid structure; each cell is a vector of PointOfField. */ + +private: + + // do not allow copy constructor + DecimationAccelGrid(const DecimationAccelGrid&); + + // do not allow copy + DecimationAccelGrid& operator=(const DecimationAccelGrid&); + + // do not allow operator == + bool operator==(const DecimationAccelGrid&); + +}; // class DecimationAccelGrid + + +} // namespace MULTIPR + + +#endif // MULTIPR_DECIMATION_ACCEL_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_DecimationFilter.cxx b/src/MULTIPR/MULTIPR_DecimationFilter.cxx new file mode 100644 index 0000000..ef9e335 --- /dev/null +++ b/src/MULTIPR/MULTIPR_DecimationFilter.cxx @@ -0,0 +1,306 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_DecimationFilter.cxx + * + * \brief see MULTIPR_DecimationFilter.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_DecimationFilter.hxx" +#include "MULTIPR_Field.hxx" +#include "MULTIPR_Mesh.hxx" +#include "MULTIPR_PointOfField.hxx" +#include "MULTIPR_DecimationAccel.hxx" +#include "MULTIPR_Exceptions.hxx" + +#include + +using namespace std; + + +namespace multipr +{ + + +//***************************************************************************** +// Class DecimationFilter implementation +//***************************************************************************** + +// factory +DecimationFilter* DecimationFilter::create(const char* pFilterName) +{ + if (pFilterName == NULL) throw NullArgumentException("filter name should not be NULL", __FILE__, __LINE__); + + if (strcmp(pFilterName, "Filtre_GradientMoyen") == 0) + { + return new DecimationFilterGradAvg(); + } + else + { + throw IllegalArgumentException("unknown filter", __FILE__, __LINE__); + } +} + + +//***************************************************************************** +// Class DecimationFilterGradAvg +//***************************************************************************** + +DecimationFilterGradAvg::DecimationFilterGradAvg() +{ + // do nothing +} + + +DecimationFilterGradAvg::~DecimationFilterGradAvg() +{ + // do nothing +} + + +Mesh* DecimationFilterGradAvg::apply(Mesh* pMesh, const char* pArgv, const char* pNameNewMesh) +{ + //--------------------------------------------------------------------- + // Retrieve and check parameters + //--------------------------------------------------------------------- + if (pMesh == NULL) throw NullArgumentException("pMesh should not be NULL", __FILE__, __LINE__); + if (pArgv == NULL) throw NullArgumentException("pArgv should not be NULL", __FILE__, __LINE__); + if (pNameNewMesh == NULL) throw NullArgumentException("pNameNewMesh should not be NULL", __FILE__, __LINE__); + + char fieldName[MED_TAILLE_NOM + 1]; + int fieldIt; + double threshold; + double radius; + int boxing; // number of cells along axis (if 100 then grid will have 100*100*100 = 10**6 cells) + + int ret = sscanf(pArgv, "%s %d %lf %lf %d", + fieldName, + &fieldIt, + &threshold, + &radius, + &boxing); + + if (ret != 5) throw IllegalArgumentException("wrong number of arguments for filter GradAvg; expected 5 parameters", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Retrieve field = for each point: get its coordinate and the value of the field + //--------------------------------------------------------------------- + Field* field = pMesh->getFieldByName(fieldName); + + if (field == NULL) throw IllegalArgumentException("field not found", __FILE__, __LINE__); + if ((fieldIt < 1) || (fieldIt > field->getNumberOfTimeSteps())) throw IllegalArgumentException("invalid field iteration", __FILE__, __LINE__); + + vector points; + pMesh->getAllPointsOfField(field, fieldIt, points); + + //--------------------------------------------------------------------- + // Creates acceleration structure used to compute gradient + //--------------------------------------------------------------------- + DecimationAccel* accel = new DecimationAccelGrid(); + char strCfg[256]; // a string is used for genericity + sprintf(strCfg, "%d %d %d", boxing, boxing, boxing); + accel->configure(strCfg); + accel->create(points); + + //--------------------------------------------------------------------- + // Collects elements of the mesh to be kept + //--------------------------------------------------------------------- + set elementsToKeep; + + int numElements = pMesh->getNumberOfElements(); + int numGaussPointsByElt = points.size() / numElements; // for a TETRA10, should be 5 for a field of elements and 10 for a field of nodes + + // for each element + for (int itElt = 0 ; itElt < numElements ; itElt++) + { + bool keepElement = false; + + // for each Gauss point of the current element + for (int itPtGauss = 0 ; itPtGauss < numGaussPointsByElt ; itPtGauss++) + { + const PointOfField& currentPt = points[itElt * numGaussPointsByElt + itPtGauss]; + + vector neighbours = accel->findNeighbours( + currentPt.mXYZ[0], + currentPt.mXYZ[1], + currentPt.mXYZ[2], + radius); + + // if no neighbours => keep element + if (neighbours.size() == 0) + { + keepElement = true; + break; + } + + // otherwise compute gradient... + med_float normGrad = computeNormGrad(currentPt, neighbours); + + // debug + //cout << (itElt * numGaussPointsByElt + j) << ": " << normGrad << endl; + + if ((normGrad >= threshold) || isnan(normGrad)) + { + keepElement = true; + break; + } + } + + if (keepElement) + { + // add index of the element to keep (index must start at 1) + elementsToKeep.insert(itElt + 1); + } + } + + //--------------------------------------------------------------------- + // Cleans + //--------------------------------------------------------------------- + delete accel; + + //--------------------------------------------------------------------- + // Create the final mesh by extracting elements to keep from the current mesh + //--------------------------------------------------------------------- + Mesh* newMesh = pMesh->createFromSetOfElements(elementsToKeep, pNameNewMesh); + + return newMesh; +} + + +void DecimationFilterGradAvg::getGradientInfo( + Mesh* pMesh, + const char* pFieldName, + int pFieldIt, + double pRadius, + int pBoxing, + double* pOutGradMin, + double* pOutGradAvg, + double* pOutGradMax) +{ + if (pMesh == NULL) throw NullArgumentException("pMesh should not be NULL", __FILE__, __LINE__); + if (pFieldName == NULL) throw NullArgumentException("pFieldName should not be NULL", __FILE__, __LINE__); + + Field* field = pMesh->getFieldByName(pFieldName); + + if (field == NULL) throw IllegalArgumentException("field not found", __FILE__, __LINE__); + if ((pFieldIt < 1) || (pFieldIt > field->getNumberOfTimeSteps())) throw IllegalArgumentException("invalid field iteration", __FILE__, __LINE__); + + vector points; + pMesh->getAllPointsOfField(field, pFieldIt, points); + + //--------------------------------------------------------------------- + // Creates acceleration structure used to compute gradient + //--------------------------------------------------------------------- + DecimationAccel* accel = new DecimationAccelGrid(); + char strCfg[256]; // a string is used for genericity + sprintf(strCfg, "%d %d %d", pBoxing, pBoxing, pBoxing); + accel->configure(strCfg); + accel->create(points); + + //--------------------------------------------------------------------- + // Collects elements of the mesh to be kept + //--------------------------------------------------------------------- + + int numElements = pMesh->getNumberOfElements(); + int numGaussPointsByElt = points.size() / numElements; // for a TETRA10, should be 5 for a field of elements and 10 for a field of nodes + + *pOutGradMax = -1e300; + *pOutGradMin = 1e300; + *pOutGradAvg = 0.0; + int count = 0; + + // for each element + for (int itElt = 0 ; itElt < numElements ; itElt++) + { + // for each Gauss point of the current element + for (int itPtGauss = 0 ; itPtGauss < numGaussPointsByElt ; itPtGauss++) + { + const PointOfField& currentPt = points[itElt * numGaussPointsByElt + itPtGauss]; + + vector neighbours = accel->findNeighbours( + currentPt.mXYZ[0], + currentPt.mXYZ[1], + currentPt.mXYZ[2], + pRadius); + + // if no neighbours => keep element + if (neighbours.size() == 0) + { + continue; + } + + // otherwise compute gradient... + med_float normGrad = computeNormGrad(currentPt, neighbours); + + // debug + //cout << (itElt * numGaussPointsByElt + j) << ": " << normGrad << endl; + + if (!isnan(normGrad)) + { + if (normGrad > *pOutGradMax) *pOutGradMax = normGrad; + if (normGrad < *pOutGradMin) *pOutGradMin = normGrad; + *pOutGradAvg += normGrad; + count++; + } + } + } + + if (count != 0) *pOutGradAvg /= double(count); + + //--------------------------------------------------------------------- + // Cleans + //--------------------------------------------------------------------- + delete accel; +} + + +med_float DecimationFilterGradAvg::computeNormGrad(const PointOfField& pPt, const std::vector& pNeighbours) const +{ + med_float gradX = 0.0; + med_float gradY = 0.0; + med_float gradZ = 0.0; + + // for each neighbour + for (unsigned i = 0 ; i < pNeighbours.size() ; i++) + { + const PointOfField& neighbourPt = pNeighbours[i]; + + med_float vecX = neighbourPt.mXYZ[0] - pPt.mXYZ[0]; + med_float vecY = neighbourPt.mXYZ[1] - pPt.mXYZ[1]; + med_float vecZ = neighbourPt.mXYZ[2] - pPt.mXYZ[2]; + + med_float norm = med_float( sqrt( vecX*vecX + vecY*vecY + vecZ*vecZ ) ); + med_float val = neighbourPt.mVal - pPt.mVal; + + val /= norm; + + gradX += vecX * val; + gradY += vecY * val; + gradZ += vecZ * val; + } + + med_float invSize = 1.0 / med_float(pNeighbours.size()); + + gradX *= invSize; + gradY *= invSize; + gradZ *= invSize; + + med_float norm = med_float( sqrt( gradX*gradX + gradY*gradY + gradZ*gradZ ) ); + + return norm; + +} + + +} // namespace multipr + +// EOF diff --git a/src/MULTIPR/MULTIPR_DecimationFilter.hxx b/src/MULTIPR/MULTIPR_DecimationFilter.hxx new file mode 100644 index 0000000..828da59 --- /dev/null +++ b/src/MULTIPR/MULTIPR_DecimationFilter.hxx @@ -0,0 +1,167 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_DecimationFilter.hxx + * + * \brief Interface DecimationFilter: filter used for decimation. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_DECIMATION_FILTER_HXX +#define MULTIPR_DECIMATION_FILTER_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + +extern "C" +{ + #include "med.h" +} + +#include +#include + + +namespace multipr +{ + +//***************************************************************************** +// Predeclaration +//***************************************************************************** + +class Mesh; +class PointOfField; + + +//***************************************************************************** +// Interface DecimationFilter and factory to build filters. +//***************************************************************************** + +class DecimationFilter +{ +public: + /** + * Decimation filter factory. + * \param pFilterName name of the filter to be instanciated. + * \return a new instance of the given filter. + */ + static DecimationFilter* create(const char* pFilterName); + +public: + + /** + * Builds an empty DecimationFilter (default constructor). + */ + DecimationFilter() { } + + /** + * Destructor. Removes everything. + */ + virtual ~DecimationFilter() { } + + /** + * Interface. Creates a new Mesh by decimating the given Mesh with this DecimationFilter. + * \param pMesh any mesh to be decimated; must not be NULL. + * \param pArgv all the arguments of the filter as a string; must not be NULL. + * \param pNameNewMesh name of the decimated mesh; must not be NULL. + * \return the decimated mesh. + */ + virtual Mesh* apply(Mesh* pMesh, const char* pArgv, const char* pNameNewMesh) = 0; + +private: + + // do not allow copy constructor + DecimationFilter(const DecimationFilter&); + + // do not allow copy + DecimationFilter& operator=(const DecimationFilter&); + + // do not allow operator == + bool operator==(const DecimationFilter&); + +}; // class DecimationFilter + + +//***************************************************************************** +// Filter : Average Gradient +//***************************************************************************** + +class DecimationFilterGradAvg : public DecimationFilter +{ +public: + + /** + * Builds an empty DecimationFilterGradAvg (default constructor). + */ + DecimationFilterGradAvg(); + + /** + * Destructor. Removes everything. + */ + virtual ~DecimationFilterGradAvg(); + + /** + * Creates a new Mesh by decimating the given Mesh with this DecimationFilter. + * + * For each element + * Keep this element if all its points (related to a field) have a |gradient| > threshold. + * + * For each point, gradient is computed by considering all the neighbours in a sphere of radius r. + * + * \param pMesh any mesh to be decimated; must not be NULL. + * \param pArgv all the arguments of the filter as a string; must not be NULL. + * for GradAvg, expected "fieldName fieldIt threshold radius boxing" (5 parameters). + * \param pNameNewMesh name of the decimated mesh; must not be NULL. + * \return the decimated mesh. + */ + virtual Mesh* apply(Mesh* pMesh, const char* pArgv, const char* pNameNewMesh); + + /** + * Returns information about gradient. + */ + void getGradientInfo( + Mesh* pMesh, + const char* pFieldName, + int pFieldIt, + double pRadius, + int pBoxing, + double* pOutGradMin, + double* pOutGradAvg, + double* pOutGradMax); + +private: + + /** + * Returns the norm of the gradient of the field at the given point. + * Sub-method used by apply(). + * \param pPt any point in the field. + * \param pNeigbours neighbourhood of pPt. + * \return the norm of the gradient of the field in pPt. + */ + med_float computeNormGrad(const PointOfField& pPt, const std::vector& pNeighbours) const; + +private: + + // do not allow copy constructor + DecimationFilterGradAvg(const DecimationFilterGradAvg&); + + // do not allow copy + DecimationFilterGradAvg& operator=(const DecimationFilterGradAvg&); + + // do not allow operator == + bool operator==(const DecimationFilterGradAvg&); + +}; // class DecimationFilterGradAvg + + +} // namespace MULTIPR + + +#endif // MULTIPR_DECIMATION_FILTER_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_Elements.cxx b/src/MULTIPR/MULTIPR_Elements.cxx new file mode 100644 index 0000000..226267e --- /dev/null +++ b/src/MULTIPR/MULTIPR_Elements.cxx @@ -0,0 +1,459 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Elements.cxx + * + * \brief see MULTIPR_Elements.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_Elements.hxx" +#include "MULTIPR_Nodes.hxx" +#include "MULTIPR_Exceptions.hxx" + +#include +#include +#include + +using namespace std; + + +namespace multipr +{ + + +//***************************************************************************** +// Class Elements implementation +//***************************************************************************** + +Elements::Elements() +{ + mId = NULL; + mFamIdent = NULL; + mNames = NULL; + mCon = NULL; + + reset(); +} + + +Elements::~Elements() +{ + reset(); +} + + +void Elements::reset() +{ + mNum = 0; + mEntity = MED_MAILLE; + mGeom = MED_NONE; + mNumNodesByElt = 0; + mDim = 0; + + if (mId != NULL) { delete[] mId; mId = NULL; } + if (mFamIdent != NULL) { delete[] mFamIdent; mFamIdent = NULL; } + if (mNames != NULL) { delete[] mNames; mNames = NULL; } + if (mCon != NULL) { delete[] mCon; mCon = NULL; } + + mSetOfNodes.clear(); + + mFlagPrintAll = false; +} + + +med_int Elements::getFamilyIdentifier(med_int pIndex) const +{ + if ((pIndex < 0) || (pIndex >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__); + + return mFamIdent[pIndex]; +} + + +const med_int* Elements::getConnectivity(int pIndex) const +{ + if ((pIndex < 0) || (pIndex >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__); + + return mCon + mNumNodesByElt * pIndex; +} + + +void Elements::getCoordinates(med_int pIndexElt, const Nodes* pNodes, med_float* pCoo, int pFirst) const +{ + if ((pIndexElt < 0) || (pIndexElt >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__); + if (pNodes == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (pCoo == NULL) throw NullArgumentException("", __FILE__, __LINE__); + + // get the list of nodes of the element + const med_int* con = getConnectivity(pIndexElt); + + med_float* destCoo = pCoo; + int size = sizeof(med_float) * mDim; + + // for each node of the element + int n = (mNumNodesByElt < pFirst) ? mNumNodesByElt : pFirst; + for (int i = 0 ; i < n ; i++) + { + // get index of node (MED index start at 1) + med_int indexNode = con[i] - 1; + + // get coordinates of this node + const med_float* srcCoo = pNodes->getCoordinates(indexNode); + + // copy coordinates to destCoo + memcpy(destCoo, srcCoo, size); + + // prepare next point + destCoo += mDim; + } +} + + +Elements* Elements::extractSubSet(const set& pSetIndices) const +{ + Elements* subset = new Elements(); + + //--------------------------------------------------------------------- + // Copy parameters + //--------------------------------------------------------------------- + subset->mNum = pSetIndices.size(); + subset->mEntity = mEntity; + subset->mGeom = mGeom; // e.g. 310 for a TETRA10 + subset->mNumNodesByElt = mNumNodesByElt; // e.g. 10 for a TETRA10 + subset->mDim = mDim; // e.g. 3 for a TETRA10 + + //--------------------------------------------------------------------- + // Allocate arrays + //--------------------------------------------------------------------- + subset->mFamIdent = new med_int[subset->mNum]; + subset->mCon = new med_int[mNumNodesByElt * subset->mNum]; + + //--------------------------------------------------------------------- + // Copy subset of familys id and connectivity. + //--------------------------------------------------------------------- + med_int* destCon = subset->mCon; + set::iterator itSet = pSetIndices.begin(); + for (int itElt = 0 ; itElt < subset->mNum; itElt++) + { + med_int srcIndex = (*itSet) - 1; // MED index start at 1 + subset->mFamIdent[itElt] = mFamIdent[srcIndex]; + + med_int* srcCon = mCon + srcIndex * mNumNodesByElt; + memcpy(destCon, srcCon, sizeof(med_int) * mNumNodesByElt); + + destCon += mNumNodesByElt; + itSet++; + } + + //--------------------------------------------------------------------- + // Copy subset of identifiers if necessary + //--------------------------------------------------------------------- + if (isIdentifiers()) + { + itSet = pSetIndices.begin(); + subset->mId = new med_int[subset->mNum]; + for (int itElt = 0 ; itElt < subset->mNum; itElt++) + { + med_int srcIndex = (*itSet) - 1; // MED index start at 1 + subset->mId[itElt] = mId[srcIndex]; + + itSet++; + } + } + + //--------------------------------------------------------------------- + // Copy subset of names if necessary + //--------------------------------------------------------------------- + if (isNames()) + { + itSet = pSetIndices.begin(); + subset->mNames = new char[MED_TAILLE_PNOM * subset->mNum + 1]; + char* destPtr = subset->mNames; + for (int itElt = 0 ; itElt < subset->mNum; itElt++) + { + med_int srcIndex = (*itSet) - 1; // MED index start at 1 + char* srcPtr = mNames + srcIndex * MED_TAILLE_PNOM; + memcpy(destPtr, srcPtr, MED_TAILLE_PNOM); + + destPtr += MED_TAILLE_PNOM; + itSet++; + } + subset->mNames[MED_TAILLE_PNOM * subset->mNum] = '\0'; + } + + return subset; +} + + +const set& Elements::getSetOfNodes() +{ + // lazy get: test if mSetOfNodes has already been built + if (mSetOfNodes.size() == 0) + { + buildSetOfNodes(); + } + + return mSetOfNodes; +} + + +set Elements::getSetOfFamilies() const +{ + // set of families is empty at the beginning + set setOfFamilies; + + // for each element, add its family to the set + for (int itElt = 0 ; itElt < mNum ; itElt++) + { + setOfFamilies.insert(mFamIdent[itElt]); + } + + return setOfFamilies; +} + + +void Elements::remap() +{ + // build set of nodes if necessary + if (mSetOfNodes.size() == 0) + { + buildSetOfNodes(); + } + + // build the map for indices convertion + map mapOldIndexToNewIndex; + med_int newIndex = 1; // MED index start at 1 + for (set::iterator itSet = mSetOfNodes.begin(); itSet != mSetOfNodes.end() ; itSet++) + { + med_int oldIndex = (*itSet); + mapOldIndexToNewIndex.insert(make_pair(oldIndex, newIndex)); + newIndex++; + } + + // for each node referenced by this set of elements + for (int itNode = 0, size = mNum * mNumNodesByElt ; itNode < size ; itNode++) + { + // convert old index to new index (remap) + mCon[itNode] = mapOldIndexToNewIndex[mCon[itNode]]; + } + + buildSetOfNodes(); +} + + +void Elements::buildSetOfNodes() +{ + if (mSetOfNodes.size() != 0) + { + mSetOfNodes.clear(); + } + + // for each node referenced by this set of elements + for (int itNode = 0, size = mNum * mNumNodesByElt ; itNode < size ; itNode++) + { + // add the node to the set + mSetOfNodes.insert(mCon[itNode]); + } +} + + +void Elements::readMED( + med_idt pMEDfile, + char* pMeshName, + med_int pMeshDim, + med_entite_maillage pEntity, + med_geometrie_element pGeom) +{ + if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__); + if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if ((pMeshDim < 1) || (pMeshDim > 3)) throw IllegalArgumentException("", __FILE__, __LINE__); + + reset(); + + mEntity = pEntity; + mGeom = pGeom; + mNumNodesByElt = mGeom % 100; + mDim = mGeom / 100; + + mNum = MEDnEntMaa( + pMEDfile, + pMeshName, + MED_CONN, // type of information requested = CONNECTIVITY + pEntity, + pGeom, + MED_NOD); // nodal connectivity + + if (mNum < 0) throw IOException("i/o error while reading information about elements in MED file", __FILE__, __LINE__); + + mCon = new med_int[mNumNodesByElt * mNum]; + mNames = new char[MED_TAILLE_PNOM * mNum + 1]; + mId = new med_int[mNum]; + mFamIdent = new med_int[mNum]; + med_booleen isNames; + med_booleen isIdentifiers; + + med_err ret = MEDelementsLire( + pMEDfile, + pMeshName, + pMeshDim, + mCon, + MED_FULL_INTERLACE, + mNames, + &isNames, + mId, + &isIdentifiers, + mFamIdent, + mNum, + mEntity, + mGeom, + MED_NOD); // NODAL CONNECTIVITY + + if (ret != 0) throw IOException("i/o error while reading elements in MED file", __FILE__, __LINE__); + + if (!isNames) + { + delete[] mNames; + mNames = NULL; + } + + if (!isIdentifiers) + { + delete[] mId; + mId = NULL; + } +} + + +void Elements::writeMED(med_idt pMEDfile, char* pMeshName, med_int pMeshDim) +{ + if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__); + if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (strlen(pMeshName) > MED_TAILLE_NOM) throw IllegalArgumentException("", __FILE__, __LINE__); + if ((pMeshDim < 1) || (pMeshDim > 3)) throw IllegalArgumentException("", __FILE__, __LINE__); + + // special case: if no elements => do nothing + if (mNum == 0) return; + + med_err ret = MEDelementsEcr( + pMEDfile, + pMeshName, + pMeshDim, + mCon, + MED_FULL_INTERLACE, + mNames, + isNames()?MED_VRAI:MED_FAUX, + mId, + isIdentifiers()?MED_VRAI:MED_FAUX, + mFamIdent, + mNum, + mEntity, + mGeom, + MED_NOD); // NODAL CONNECTIVITY + + if (ret != 0) throw IOException("i/o error while writing elements in MED file", __FILE__, __LINE__); +} + + +ostream& operator<<(ostream& pOs, Elements& pE) +{ + char strEntity[16]; + switch (pE.mEntity) + { + case MED_MAILLE: strcpy(strEntity, "MED_MAILLE"); break; + case MED_FACE: strcpy(strEntity, "MED_FACE"); break; + case MED_ARETE: strcpy(strEntity, "MED_ARETE"); break; + case MED_NOEUD: strcpy(strEntity, "MED_NOEUD"); break; + default: strcpy(strEntity, "UNKNOWN"); break; + } + + pOs << "Elements: " << endl; + pOs << " #number =" << pE.mNum << endl; + pOs << " Entity =" << strEntity << endl; + pOs << " Geom =" << pE.mGeom << endl; + pOs << " Has names?" << (pE.isNames()?"yes":"no") << endl; + pOs << " Has id ?" << (pE.isIdentifiers()?"yes":"no") << endl; + + { + set setOfFam = pE.getSetOfFamilies(); + if (setOfFam.size() == 0) + { + pOs << " Families: #fam=0" << endl; + } + else + { + set::iterator itFam = setOfFam.end(); + itFam--; + pOs << " Families: #fam=" << setOfFam.size() << " id_min=" << (*(setOfFam.begin())) << " id_max=" << (*itFam) << endl; + + if (pE.mFlagPrintAll) + { + for (int i = 0 ; i < pE.mNum; i++) + { + pOs << " Elt " << (i + 1) << ": " << pE.mFamIdent[i] << endl; + } + } + } + } + + { + set setOfNodes = pE.getSetOfNodes(); + if (setOfNodes.size() == 0) + { + pOs << " Connectivity: #nodes=0" << endl; + } + else + { + set::iterator itNode = setOfNodes.end(); + itNode--; + pOs << " Connectivity: #nodes=" << setOfNodes.size() << " id_min=" << (*(setOfNodes.begin())) << " id_max=" << (*itNode) << endl; + + if (pE.mFlagPrintAll) + { + for (int i = 0 ; i < pE.mNum ; i++) + { + pOs << " Elt " << (i + 1) << ": "; + for (int j = 0 ; j < pE.mNumNodesByElt ; j++) + { + pOs << pE.mCon[i * pE.mNumNodesByElt + j] << " "; + } + pOs << endl; + } + } + } + } + + if (pE.mFlagPrintAll) + { + + if (pE.isIdentifiers()) + { + pOs << " Num (identifier): " << endl; + for (int i = 0 ; i < pE.mNum; i++) + { + pOs << " Elt " << (i + 1) << ": " << pE.mId[i] << " " << endl; + } + } + + if (pE.isNames()) + { + pE.mNames[MED_TAILLE_PNOM * pE.mNum] = '\0'; + pOs << " Names: |" << pE.mNames << "|" << endl; + } + + } + + return pOs; +} + + +} // namespace multipr + +// EOF diff --git a/src/MULTIPR/MULTIPR_Elements.hxx b/src/MULTIPR/MULTIPR_Elements.hxx new file mode 100644 index 0000000..178aa4c --- /dev/null +++ b/src/MULTIPR/MULTIPR_Elements.hxx @@ -0,0 +1,248 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Elements.hxx + * + * \brief Class Elements = table of elements in a mesh. + * All elements share the same type (e.g. MED_MAILLE) and the same geometric description (e.g. TETRA10). + * Each element has a family and a table of connectivity. + * Optional: each element has a name and an id. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_ELEMENTS_HXX +#define MULTIPR_ELEMENTS_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + +extern "C" +{ + #include "med.h" +} + +#include + + +namespace multipr +{ + +//***************************************************************************** +// Predeclaration +//***************************************************************************** + +class Nodes; + + +//***************************************************************************** +// Class Elements +//***************************************************************************** + +class Elements +{ +public: + + /** + * Builds an empty set of elements (default constructor). + */ + Elements(); + + /** + * Destructor. Removes everything. + */ + ~Elements(); + + /** + * Resets this object in its state by default (empty). Cleans memory. + */ + void reset(); + + //--------------------------------------------------------------------- + // Basic accessors/mutators + //--------------------------------------------------------------------- + + /** + * Returns true iff this object contains no elements (table of elements is empty). + * \return true iff this object contains no elements. + */ + bool isEmpty() const { return (mNum == 0); } + + /** + * Returns true iff elements have a name. + * \return true iff elements have a name. + */ + bool isNames() const { return (mNames != NULL); } + + /** + * Returns true iff elements have an identifier (= a number). + * \return true iff elements have an identifier (= a number). + */ + bool isIdentifiers() const { return (mId != NULL); } + + /** + * Returns the number of elements. + * \return the number of elements. + */ + int getNumberOfElements() const { return mNum; } + + /** + * Returns the type of primitives (e.g. MED_TETRA10). + * \return the type of primitives + */ + med_geometrie_element getTypeOfPrimitives() const { return mGeom; } + + /** + * Returns the number of nodes that composed an element. + * \return the number of nodes that composed an element. + */ + int getNumberOfNodesByElement() const { return mNumNodesByElt; } + + /** + * Returns the family associated with an element. + * \param pIndex index of any element in [0..NUMBER_OF_ELEMENTS-1]. + * \return the family associated with an element. + * \throw IndexOutOfBoundsException if pIndex is invalid. + */ + med_int getFamilyIdentifier(med_int pIndex) const; + + /** + * Returns the connectivity of one element. + * \param pIndex must be in [0..NUMBER_OF_ELEMENTS-1]. + * \return a pointer towards the table of connectivity of the element. + * \throw IndexOutOfBoundsException if pIndex is invalid. + */ + const med_int* getConnectivity(int pIndex) const; + + /** + * Returns the coordinates of all the nodes of one element. + * \param pIndexElt must be in [0..NUMBER_OF_ELEMENTS-1]. + * \param pNodes table of nodes, used to retrieve coordinates. + * \param pCoo (out) table of coordinates of nodes (e.g. 30 = 3 * 10 med_float for a TETRA10). + * \param pFirst only get the pFirst coordinates. + * \throw IndexOutOfBoundsException if pIndex is invalid. + */ + void getCoordinates(med_int pIndexElt, const Nodes* pNodes, med_float* pCoo, int pFirst = 100) const; + + //--------------------------------------------------------------------- + // Algorithms + //--------------------------------------------------------------------- + + /** + * Constructor. Creates a subset of this set of elements from a set of indices. + * \param pSetIndices set of indices (start at 1). + * \return a restriction of this set of elements. + */ + Elements* extractSubSet(const std::set& pSetIndices) const; + + /** + * Returns the set of indices (starting at 1) of all nodes used by this set of elements. + * \return the set of indices of all nodes used by this set of elements. + */ + const std::set& getSetOfNodes(); + + /** + * Returns the set of families referenced by this set of elements. + * Each family is described by its identifier. + * \return Returns the set of families referenced by this set of elements. + */ + std::set getSetOfFamilies() const; + + /** + * Remaps this set of elements such that indices of nodes are continous 1 2 3 4 5 ... * + * This method is intended to be used after extractSubSet(). + */ + void remap(); + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Reads a set of elements from a MED file. + * You must give: name of mesh, dimension of the mesh, type of entity and type of elements. + * \param pMEDfile any valid MED file opened for reading. + * \param pMeshName name of the mesh. + * \param pMeshDim dimension of the mesh. + * \param pEntity entity to be read (e.g. MED_MAILLE). + * \param pGeom type of primitves to be read (e.g. MED_TETRA10). + * \throw IOException if any i/o error occurs. + */ + void readMED( + med_idt pMEDfile, + char* pMeshName, + med_int pMeshDim, + med_entite_maillage pEntity, + med_geometrie_element pGeom); + + /** + * Writes this set of elements to a MED file. + * WARNING: mesh must have been created and added to the MED file before. + * \param pMEDfile any valid MED file opened for writing. + * \param pMeshName name of the mesh. + * \param pMeshDim dimension of the mesh. + * \throw IOException if any i/o error occurs. + */ + void writeMED(med_idt pMEDfile, char* pMeshName, med_int pMeshDim); + + /** + * Sets the flag which control the stream operator <<. + * \param pFlag new flag value. + */ + void setPrintAll(bool pFlag) { mFlagPrintAll = pFlag; } + + /** + * Dumps any Elements to the given output stream. + * \param pOs any output stream. + * \param pE any Elements. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, Elements& pE); + +private: + + /** + * Builds the set of nodes used by this set of elements. + * If the set already exist, then it is cleared and a new set is computed. + */ + void buildSetOfNodes(); + +private: + + med_int mNum; /**< Number of elements. */ + med_entite_maillage mEntity; /**< Type of entity, e.g. MED_MAILLE. */ + med_geometrie_element mGeom; /**< Type of primitive, e.g. MED_TETRA10. */ + int mDim; /**< Dimension of elements = mGeom / 100. */ + int mNumNodesByElt; /**< Number of nodes by element = mGeom % 100. */ + med_int* mId; /**< Optional; for each element, its identifier; NULL if undefined. */ + med_int* mFamIdent; /**< For each element, its family (identifier). */ + char* mNames; /**< Optional; for each element, its name; NULL if undefined. */ + med_int* mCon; /**< For each element, list of nodes (index in 1..*) = table of connectivity. */ + std::set mSetOfNodes; /**< Set of all nodes used by this set of elements. */ + + bool mFlagPrintAll; /** Flag to control the behaviour of the stream operator <<. */ + +private: + + // do not allow copy constructor + Elements(const Elements&); + + // do not allow copy + Elements& operator=(const Elements&); + + // do not allow operator == + bool operator==(const Elements&); + +}; // class Elements + + +} // namespace MULTIPR + + +#endif // MULTIPR_NODES_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_Exceptions.hxx b/src/MULTIPR/MULTIPR_Exceptions.hxx new file mode 100644 index 0000000..2b25de1 --- /dev/null +++ b/src/MULTIPR/MULTIPR_Exceptions.hxx @@ -0,0 +1,203 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Exceptions.hxx + * + * \brief All the exceptions used by MULTIPR. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_EXCEPTIONS_HXX +#define MULTIPR_EXCEPTIONS_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include +#include + + +namespace multipr +{ + +//***************************************************************************** +// Class RuntimeException +// Super class for all exceptions used by the module MULTIPR +//***************************************************************************** + +class RuntimeException +{ +public: + + /** + * Constructor. Build a new RuntimeException. + * \param pMsg message to be associated with this exception. + * \param pFile name of the file where the probem occur (you can use the macro __FILE__); "unknown" by default. + * \param pLine number of the line where the probem occur (you can use the macro __LINE__); 0 by default. + */ + RuntimeException( + const std::string& pMsg, + const std::string& pFile = "unknown", + int pLine = 0) + { + mMsg = pMsg; + mFile = pFile; + mLine = pLine; + mType = "RuntimeException"; + } + + /** + * Dumps info about this exception to the given output stream. + */ + void dump(std::ostream& pOs) const + { + pOs << "MULTIPR: " << mType << " (" << mFile << ", line " << mLine << "): " << mMsg << std::endl; + } + +protected: + + std::string mMsg; /**< Message associated with this exception. */ + std::string mFile; /**< Name of the source file where the problem occurs. */ + int mLine; /**< Number of the line where the problem occurs. */ + std::string mType; /**< Type of this exception. */ +}; + + +//***************************************************************************** +// Class NullArgumentException +// Should be used for a NULL pointer +//***************************************************************************** + +class NullArgumentException : public RuntimeException +{ +public: + NullArgumentException( + const std::string& pMsg, + const std::string& pFile="unknown", + int pLine=0) : RuntimeException(pMsg, pFile, pLine) + { + mType = "NullArgumentException"; + } +}; + + +//***************************************************************************** +// Class IllegalArgumentException +// Should be used when a parameter is invalid (check precondition) +//***************************************************************************** + +class IllegalArgumentException : public RuntimeException +{ +public: + IllegalArgumentException( + const std::string& pMsg, + const std::string& pFile="unknown", + int pLine=0) : RuntimeException(pMsg, pFile, pLine) + { + mType = "IllegalArgumentException"; + } +}; + + +//***************************************************************************** +// Class IllegalStateException +// Should be used when the internal state of an object is invalid +//***************************************************************************** + +class IllegalStateException : public RuntimeException +{ +public: + IllegalStateException( + const std::string& pMsg, + const std::string& pFile="unknown", + int pLine=0) : RuntimeException(pMsg, pFile, pLine) + { + mType = "IllegalStateException"; + } +}; + + +//***************************************************************************** +// Class IndexOutOfBoundsException +// Should be used when an index is out of bounds +//***************************************************************************** + +class IndexOutOfBoundsException : public RuntimeException +{ +public: + IndexOutOfBoundsException( + const std::string& pMsg, + const std::string& pFile="unknown", + int pLine=0) : RuntimeException(pMsg, pFile, pLine) + { + mType = "IndexOutOfBoundsException"; + } +}; + + +//***************************************************************************** +// Class IOException +// Should be used when any i/o error occurs +//***************************************************************************** + +class IOException : public RuntimeException +{ +public: + IOException( + const std::string& pMsg, + const std::string& pFile="unknown", + int pLine=0) : RuntimeException(pMsg, pFile, pLine) + { + mType = "IOException"; + } +}; + + +//***************************************************************************** +// Class FileNotFoundException +// Should be used to indicate that a file has not been found +//***************************************************************************** + +class FileNotFoundException : public IOException +{ +public: + FileNotFoundException( + const std::string& pMsg, + const std::string& pFile="unknown", + int pLine=0) : IOException(pMsg, pFile, pLine) + { + mType = "FileNotFoundException"; + } +}; + + +//***************************************************************************** +// Class UnsupportedOperationException +// Should be used when a function/method is not yet implemented or +// if an operation is not supported in a given context +//***************************************************************************** + +class UnsupportedOperationException : public RuntimeException +{ +public: + UnsupportedOperationException( + const std::string& pMsg, + const std::string& pFile="unknown", + int pLine=0) : RuntimeException(pMsg, pFile, pLine) + { + mType = "UnsupportedOperationException"; + } +}; + + +} // namespace MULTIPR + + +#endif // MULTIPR_EXCEPTIONS_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_Family.cxx b/src/MULTIPR/MULTIPR_Family.cxx new file mode 100644 index 0000000..e6ab2fc --- /dev/null +++ b/src/MULTIPR/MULTIPR_Family.cxx @@ -0,0 +1,463 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Family.cxx + * + * \brief see MULTIPR_Family.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_Family.hxx" +#include "MULTIPR_Exceptions.hxx" + +#include + +using namespace std; + + +namespace multipr +{ + + +//***************************************************************************** +// Class Attributs implementation +//***************************************************************************** + +Attributs::Attributs() +{ + mId = NULL; + mVal = NULL; + mDesc = NULL; + + reset(); +} + + +Attributs::~Attributs() +{ + reset(); +} + + +Attributs& Attributs::operator=(const Attributs& pAttr) +{ + if (this != &pAttr) // check for self-assignement + { + reset(); + + mNum = pAttr.mNum; + + if (mNum < 0) throw IllegalStateException("", __FILE__, __LINE__); + + if (pAttr.mId != NULL) + { + mId = new med_int[mNum]; + memcpy(mId, pAttr.mId, sizeof(med_int) * mNum); + } + + if (pAttr.mVal != NULL) + { + mVal = new med_int[mNum]; + memcpy(mVal, pAttr.mVal, sizeof(med_int) * mNum); + } + + if (pAttr.mDesc != NULL) + { + mDesc = new char[MED_TAILLE_DESC * mNum + 1]; + memcpy(mDesc, pAttr.mDesc, MED_TAILLE_DESC * mNum + 1); + } + } + + return *this; +} + + +void Attributs::reset() +{ + mNum = 0; + + if (mId != NULL) { delete[] mId; mId = NULL; } + if (mVal != NULL) { delete[] mVal; mVal = NULL; } + if (mDesc != NULL) { delete[] mDesc; mDesc = NULL; } +} + + +ostream& operator<<(ostream& pOs, Attributs& pA) +{ + if (pA.mNum == 0) + { + pOs << "NONE" << endl; + } + else + { + pOs << endl << " #attr=" << pA.mNum << endl; + + if (pA.mId != NULL) + { + pOs << " Id =["; + for (int i = 0 ; i < pA.mNum ; i++) + { + pOs << pA.mId[i] << " "; + } + pOs << "]" << endl; + } + else + { + pOs << " Id =NULL" << endl; + } + + if (pA.mVal != NULL) + { + pOs << " Val =["; + for (int i = 0 ; i < pA.mNum ; i++) + { + pOs << pA.mVal[i] << " "; + } + pOs << "]" << endl; + } + else + { + pOs << " Val =NULL"; + } + + if (pA.mDesc != NULL) + { + pOs << " Desc=|" << pA.mDesc << "|" << endl; + } + else + { + pOs << " Desc=NULL" << endl; + } + } + + return pOs; +} + + +//***************************************************************************** +// Class Family implementation +//***************************************************************************** + +Family::Family() +{ + reset(); +} + + +Family::~Family() +{ + reset(); +} + + +void Family::reset() +{ + mName[0] = '\0'; + mId = 0; + mStrNameGroups = ""; + + mElt.clear(); + mNameGroups.clear(); + mAttributs.reset(); + + mIsFamilyOfNodes = true; + + mFlagPrintAll = false; +} + + +void Family::insertElt(med_int pIndexElt) +{ + if (pIndexElt < 1) throw new IllegalArgumentException("", __FILE__, __LINE__); + + mElt.insert(pIndexElt); +} + + +void Family::buildGroups(vector& pGroups, map& pGroupNameToGroup) const +{ + // pGroups / pGroupNameToGroup can be empty or not + + // for each group in this family + for (unsigned itGroup = 0 ; itGroup < mNameGroups.size() ; itGroup++) + { + const string& keyName = mNameGroups[itGroup]; + + // check if the group already exist + map::iterator it = pGroupNameToGroup.find(keyName); + + Group* group = NULL; + if (it != pGroupNameToGroup.end()) + { + // the group already exists + group = (*it).second; + } + else + { + // a new group have been identified: create a new entry + group = new Group(); + group->setName(keyName); + group->setIsGroupOfNodes(isFamilyOfNodes()); + + pGroups.push_back(group); + pGroupNameToGroup.insert(make_pair(keyName, group)); + } + + // add all elements of the this family to the group + for (set::iterator itElt = mElt.begin() ; itElt != mElt.end() ; itElt++) + { + group->insertElt(*itElt); + } + + } +} + + +Family* Family::extractGroup(const char* pGroupName) +{ + Family* family = new Family(); + + strcpy(family->mName, mName); + family->mId = mId; + family->mAttributs = mAttributs; + + if (pGroupName == NULL) + { + family->mStrNameGroups = mStrNameGroups; + family->mNameGroups = mNameGroups; + } + else + { + if (strlen(pGroupName) > MED_TAILLE_LNOM) throw IllegalArgumentException("", __FILE__, __LINE__); + if (strlen(pGroupName) == 0) throw IllegalArgumentException("", __FILE__, __LINE__); + + if (strstr(mStrNameGroups.c_str(), pGroupName) == 0) + { + // pGroupName found in the list of groups => just keep pGroupName + family->mStrNameGroups = mStrNameGroups; + family->mNameGroups = mNameGroups; + } + else + { + // pGroupName not found in the current list of groups + // probably not a group of the same nature => keep all the groups + family->mStrNameGroups = pGroupName; + family->mNameGroups.push_back(pGroupName); + } + } + + return family; +} + + +void Family::readMED(med_idt pMEDfile, char* pMeshName, med_int pIndex) +{ + if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__); + if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (strlen(pMeshName) > MED_TAILLE_NOM) throw IllegalArgumentException("", __FILE__, __LINE__); + if (pIndex < 1) throw IllegalArgumentException("", __FILE__, __LINE__); + + reset(); + + med_int numGroups = MEDnGroupe(pMEDfile, pMeshName, pIndex); + + if (numGroups < 0) throw IOException("i/o error while reading number of groups in MED file", __FILE__, __LINE__); + + med_int numAttr = MEDnAttribut(pMEDfile, pMeshName, pIndex); + + med_int* attrId = new med_int[numAttr]; + med_int* attrVal = new med_int[numAttr]; + char* attrDesc = new char[MED_TAILLE_DESC * numAttr + 1]; + attrDesc[0] = '\0'; + + char* nameGroups = new char[MED_TAILLE_LNOM * numGroups + 1]; + nameGroups[0] = '\0'; + + med_err ret = MEDfamInfo( + pMEDfile, + pMeshName, + pIndex, + mName, + &mId, + attrId, + attrVal, + attrDesc, + &numAttr, + nameGroups, + &numGroups); + + if (ret != 0) throw IOException("i/o error while reading family information in MED file", __FILE__, __LINE__); + + attrDesc[MED_TAILLE_DESC * numAttr] = '\0'; + + mAttributs.mNum = numAttr; + mAttributs.mId = attrId; + mAttributs.mVal = attrVal; + mAttributs.mDesc = attrDesc; + + mStrNameGroups = nameGroups; + + // split nameGroups + for (int itGroup = 0 ; itGroup < numGroups ; itGroup++) + { + char str[MED_TAILLE_LNOM + 1]; + strncpy(str, nameGroups + itGroup * MED_TAILLE_LNOM, MED_TAILLE_LNOM); + str[MED_TAILLE_LNOM] = '\0'; + mNameGroups.push_back(str); + } + + delete[] nameGroups; + + // MEDfamLire is not necessary as we used MEDnoeudsLire/MEDelementsLire instead +} + + +void Family::writeMED(med_idt pMEDfile, char* pMeshName) +{ + if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__); + if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (strlen(pMeshName) > MED_TAILLE_NOM) throw IllegalArgumentException("", __FILE__, __LINE__); + if (strlen(mName) > MED_TAILLE_NOM) throw IllegalArgumentException("", __FILE__, __LINE__); + if (mAttributs.mVal == NULL) throw IllegalStateException("", __FILE__, __LINE__); + if (mAttributs.mDesc == NULL) throw IllegalStateException("", __FILE__, __LINE__); + if (mAttributs.mId == NULL) throw IllegalStateException("", __FILE__, __LINE__); + + med_err ret = MEDfamCr( + pMEDfile, + pMeshName, + mName, + mId, + mAttributs.mId, + mAttributs.mVal, + mAttributs.mDesc, + mAttributs.mNum, + const_cast(mStrNameGroups.c_str()), + mNameGroups.size()); + + if (ret != 0) throw IOException("i/o error while creating family in MED file", __FILE__, __LINE__); + + // MEDfamEcr is not necessary as we used MEDnoeudsEcr/MEDelementsEcr instead + +} + + +ostream& operator<<(ostream& pOs, Family& pF) +{ + pOs << "Family: " << endl; + pOs << " Name =|" << pF.mName << "| size=" << strlen(pF.mName) << endl; + pOs << " Id =" << pF.mId << endl; + pOs << " Family of =" << (pF.isFamilyOfNodes()?"NODES":"ELEMENTS") << endl; + + pOs << " Groups: #groups=" << pF.mNameGroups.size() << endl; + for (unsigned itGroup = 0 ; itGroup < pF.mNameGroups.size() ; itGroup++) + { + pOs << " Group " << (itGroup + 1) << ": |" << pF.mNameGroups[itGroup] << "| size=" << pF.mNameGroups[itGroup].length() << endl; + } + pOs << " Attributs: " << pF.mAttributs; + + if (pF.mElt.size() != 0) + { + set::iterator itSet = pF.mElt.end(); + itSet--; + pOs << " Elements: #elt=" << pF.mElt.size() << " min_id=" << (*(pF.mElt.begin())) << " max_id=" << (*itSet) << endl; + if (pF.mFlagPrintAll) + { + pOs << " "; + for (set::iterator itSet = pF.mElt.begin() ; itSet != pF.mElt.end() ; itSet++) + { + pOs << (*itSet) << " "; + } + pOs << endl; + } + } + else + { + pOs << " Elements: #elt=0" << endl; + } + + return pOs; +} + + +//***************************************************************************** +// Class Group implementation +//***************************************************************************** + +Group::Group() +{ + reset(); +} + + +Group::~Group() +{ + reset(); +} + + +void Group::reset() +{ + mName = ""; + mElt.clear(); + mIsGroupOfNodes = true; + + mFlagPrintAll = false; +} + + +void Group::setName(const string& pName) +{ + if (pName.length() > MED_TAILLE_LNOM) throw IllegalArgumentException("", __FILE__, __LINE__); + + mName = pName; +} + + +void Group::insertElt(med_int pIndexElt) +{ + if (pIndexElt < 1) throw IllegalArgumentException("", __FILE__, __LINE__); + + mElt.insert(pIndexElt); +} + +ostream& operator<<(ostream& pOs, Group& pG) +{ + pOs << "Group: " << endl; + pOs << " Name =|" << pG.mName << "| size=" << pG.mName.length() << endl; + pOs << " Group of =" << (pG.isGroupOfNodes()?"NODES":"ELEMENTS") << endl; + + if (pG.mElt.size() != 0) + { + set::iterator itSet = pG.mElt.end(); + itSet--; + pOs << " Elements: #elt=" << pG.mElt.size() << " min_id=" << (*(pG.mElt.begin())) << " max_id=" << (*itSet) << endl; + if (pG.mFlagPrintAll) + { + pOs << " "; + for (set::iterator itSet = pG.mElt.begin() ; itSet != pG.mElt.end() ; itSet++) + { + pOs << (*itSet) << " "; + } + pOs << endl; + } + } + else + { + pOs << " Elements: #elt=0" << endl; + } + + return pOs; +} + + +} // namespace multipr + +// EOF diff --git a/src/MULTIPR/MULTIPR_Family.hxx b/src/MULTIPR/MULTIPR_Family.hxx new file mode 100644 index 0000000..15d1833 --- /dev/null +++ b/src/MULTIPR/MULTIPR_Family.hxx @@ -0,0 +1,367 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Family.hxx + * + * \brief Class Family, Group and Attributs used to wrap MED file structures. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_FAMILY_HXX +#define MULTIPR_FAMILY_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + +extern "C" +{ + #include "med.h" +} + + +#include +#include +#include +#include + + +namespace multipr +{ + +//***************************************************************************** +// Predeclaration +//***************************************************************************** + +class Group; + + +//***************************************************************************** +// Class Attributs +//***************************************************************************** + +class Attributs +{ +public: + + /** + * Builds an empty Attributs (default constructor). + */ + Attributs(); + + /** + * Destructor. Removes everything. + */ + ~Attributs(); + + /** + * Assignment operator (deep copy). + * \param pAttr any Atttibuts to be copied. + * \return a reference towards the copy. + */ + Attributs& operator=(const Attributs& pAttr); + + /** + * Resets this object in its state by default (empty). Cleans memory. + */ + void reset(); + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Dumps any Attributs to the given output stream. + * \param pOs any output stream. + * \param pA any Attributs. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, Attributs& pA); + +public: + + med_int mNum; /**< Number of attributes. */ + med_int* mId; /**< Table of identifiers: for each attribute, its identifier. */ + med_int* mVal; /**< Table of values; for each attribute, its value. */ + char* mDesc; /**< Table of description; for each attribute, its description. */ + +private: + + // do not allow copy constructor + Attributs(const Attributs&); + + // do not allow operator == + bool operator==(const Attributs&); + +}; // class Attribut + + +//***************************************************************************** +// Class Family +//***************************************************************************** + +class Family +{ +public: + + /** + * Builds an empty Family (default constructor). + */ + Family(); + + /** + * Destructor. Removes everything. + */ + ~Family(); + + /** + * Resets this object in its state by default (empty). Cleans memory. + */ + void reset(); + + //--------------------------------------------------------------------- + // Basic accessors/mutators + //--------------------------------------------------------------------- + + /** + * Returns the identifier (= number) of this Family. + * \return the identifier of this Family. + */ + med_int getId() const { return mId; } + + /** + * Returns the name of this Family. + * \return the name of this Family. + */ + const char* getName() const { return mName; } + + /** + * Returns true if this Family if a family of nodes, false if is a family of elements (=cells)). + * \return true iff this Family if a family of nodes. + */ + bool isFamilyOfNodes() const { return mIsFamilyOfNodes; } + + /** + * Sets whether this Family is a family of nodes or family of elements (= cells). + * \param pIsFamilyOfNodes flag. + */ + void setIsFamilyOfNodes(bool pIsFamilyOfNodes) { mIsFamilyOfNodes = pIsFamilyOfNodes; } + + /** + * Inserts a new element (by its index) into this Family. + * \param pIndexElt index of the element to be added; must be >= 1. + * \throw IllegalArgumentException if pIndexElt <= 0. + */ + void insertElt(med_int pIndexElt); + + /** + * Returns the number of elements in this Family. + * \return the number of elements in this Family. + */ + int getSize() const { return mElt.size(); } + + //--------------------------------------------------------------------- + // Algorithms + //--------------------------------------------------------------------- + + /** + * Adds all the groups of this Family into the set of groups described by (pGroups, pGroupNameToGroup). + * \param pGroups current list of groups. + * \param pGroupNameToGroup table (map) to retrieve a Group* from its name. + */ + void buildGroups( + std::vector& pGroups, + std::map& pGroupNameToGroup) const; + + /** + * Constructor. Returns a copy of this family restricted to the given group if pGroupName != NULL. + * Examples: + * 1. If current family have 3 groups "A", "B" and "C" and pGroupName="B", then the new family will only reference the group "B" + * 2. If current family have 3 groups "A", "B" and "C" and pGroupName="D", then the new family will reference groups "A", "B" and "C". + * WARNING: elements are not copied + * \param pGroupName name of the group to keep. + * \return a copy of this family. + */ + Family* extractGroup(const char* pGroupName); + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Reads a Family from a MED file. + * \param pMEDfile any valid MED file opened for reading. + * \param pMeshName name of the mesh. + * \param pIndex index of the family to be read (must be >= 1). + * \throw IOException if any i/o error occurs. + */ + void readMED(med_idt pMEDfile, char* pMeshName, med_int pIndex); + + /** + * Writes this Family to a MED file. + * WARNING: mesh must have been created and added to the MED file before. + * \param pMEDfile any valid MED file opened for writing. + * \param pPeshName name of the mesh. + * \throw IOException if any i/o error occurs. + */ + void writeMED(med_idt pMEDfile, char* pMeshName); + + /** + * Sets the flag which control the stream operator <<. + * \param pFlag new flag value. + */ + void setPrintAll(bool pFlag) { mFlagPrintAll = pFlag; } + + /** + * Dumps any Family to the given output stream. + * \param pOs any output stream. + * \param pF any Family. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, Family& pF); + +private: + + char mName[MED_TAILLE_NOM + 1]; /** Name of the Family */ + med_int mId; /**< Id: > 0 if family of nodes; < 0 if family of elements. */ + std::set mElt; /**< Set of all the elements (by their index in 1..*). */ + std::string mStrNameGroups; /**< A string with name of all groups which contain the Family. */ + std::vector mNameGroups; /**< List of groups (by name) which contain the Family. */ + Attributs mAttributs; /**< All the attributed related to the Family. */ + bool mIsFamilyOfNodes; /**< Is it a family of nodes or a family of elements? */ + + bool mFlagPrintAll; /** Flag to control the behaviour of the stream operator <<. */ + +private: + + // do not allow copy constructor + Family(const Family&); + + // do not allow copy + Family& operator=(const Family&); + + // do not allow operator == + bool operator==(const Family&); + +}; // class Family + + +//***************************************************************************** +// Class Group +//***************************************************************************** + +class Group +{ +public: + + /** + * Builds an empty group (default constructor). + */ + Group(); + + /** + * Destructor. Removes everything. + */ + ~Group(); + + /** + * Resets this object in its state by default (empty). Cleans memory. + */ + void reset(); + + //--------------------------------------------------------------------- + // Basic accessors/mutators + //--------------------------------------------------------------------- + + /** + * Returns true if it is a group of nodes, false if it is a group of elements. + * \return true if it is a group of nodes, false if it is a group of elements. + */ + bool isGroupOfNodes() const { return mIsGroupOfNodes; } + + /** + * Sets whether it is a group of nodes or a group of elements. + * \param pIsGroupOfNodes true for a group of nodes, false for a group of elements. + */ + void setIsGroupOfNodes(bool pIsGroupOfNodes) { mIsGroupOfNodes = pIsGroupOfNodes; } + + /** + * Returns the name of this Group. + * \return the name of this Group. + */ + const std::string& getName() const { return mName; } + + /** + * Sets the name of this Group. + * \param pName new name of this Group (length of name must not exceed MED_TAILLE_LNOM). + */ + void setName(const std::string& pName); + + /** + * Adds the index of a new element to this Group. + * \param pIndexElt must be >= 1. + */ + void insertElt(med_int pIndexElt); + + /** + * Returns the set of all the elements referenced in this Group. + * \return the set of all the elements referenced in this Group. + */ + const std::set& getSetOfElt() const { return mElt; } + + /** + * Returns the number of elements referenced in this Group. + * \return the number of elements referenced in this Group. + */ + int getSize() const { return mElt.size(); } + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Sets the flag which control the stream operator <<. + * \param pFlag new flag value. + */ + void setPrintAll(bool pFlag) { mFlagPrintAll = pFlag; } + + /** + * Dumps any Group to the given output stream. + * \param pOs any output stream. + * \param pG any Group. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, Group& pG); + +private: + + std::string mName; /**< Name of the group. */ + std::set mElt; /**< All elements of this group; each element is referenced by its index >= 1; each element is unique. */ + bool mIsGroupOfNodes; /**< Is it a group of nodes or a group of elements? */ + + bool mFlagPrintAll; /** Flag to control the behaviour of the stream operator <<. */ + +private: + + // do not allow copy constructor + Group(const Group&); + + // do not allow copy + Group& operator=(const Group&); + + // do not allow operator == + bool operator==(const Group&); + +}; // class Group + + +} // namespace MULTIPR + + +#endif // MULTIPR_FAMILY_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_Field.cxx b/src/MULTIPR/MULTIPR_Field.cxx new file mode 100644 index 0000000..6d1854a --- /dev/null +++ b/src/MULTIPR/MULTIPR_Field.cxx @@ -0,0 +1,524 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Field.cxx + * + * \brief see MULTIPR_Field.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_Field.hxx" +#include "MULTIPR_Exceptions.hxx" + +#include + +using namespace std; + + +namespace multipr +{ + + +//***************************************************************************** +// Class Field implementation +//***************************************************************************** + +Field::Field() +{ + reset(); +} + + +Field::~Field() +{ + reset(); +} + + +void Field::reset() +{ + mName[0] = '\0'; + mEntity = MED_NOEUD; + mGeom = MED_NONE; + mType = MED_FLOAT64; + mSizeOfType = 8; + mNumComponents = 0; + mStrComponent = ""; + mStrUnit = ""; + + mNGauss.clear(); + mDT.clear(); + mNumDT.clear(); + mDTUnit.clear(); + mNumO.clear(); + mGaussLoc.clear(); + mProfil.clear(); + mSizeOfData.clear(); + mNVal.clear(); + + for (unsigned it = 0 ; it < mVal.size() ; it++) + { + delete[] mVal[it]; + } + mVal.clear(); + + mFlagPrintAll = false; +} + + +bool Field::isEmpty() const +{ + return (mNGauss.size() == 0); +} + + +int Field::getNumberOfGaussPointsByElement(int pTimeStepIt) const +{ + if ((pTimeStepIt < 1) || (pTimeStepIt > int(mNGauss.size()))) throw IndexOutOfBoundsException("", __FILE__, __LINE__); + + return mNGauss[pTimeStepIt - 1]; +} + + +const string& Field::getNameGaussLoc(int pTimeStepIt) const +{ + if ((pTimeStepIt < 1) || (pTimeStepIt > int(mNGauss.size()))) throw IndexOutOfBoundsException("", __FILE__, __LINE__); + + return mGaussLoc[pTimeStepIt - 1]; +} + + +const unsigned char* Field::getValue(int pTimeStepIt, int pIndex) const +{ + if ((pTimeStepIt < 1) || (pTimeStepIt > int(mNGauss.size()))) throw IndexOutOfBoundsException("", __FILE__, __LINE__); + if ((pIndex < 1) || (pIndex > mNVal[pTimeStepIt - 1] / mNGauss[pTimeStepIt - 1])) throw IndexOutOfBoundsException("", __FILE__, __LINE__); + + // size of one data = size of type * number of components * number of Gauss points + int sizeOfOneData = mSizeOfType * mNumComponents * mNGauss[pTimeStepIt - 1]; + + unsigned char* ret = mVal[pTimeStepIt - 1] + (pIndex - 1) * sizeOfOneData; + + return ret; +} + + +Field* Field::extractSubSet(const set& pSetIndices) const +{ + Field* subset = new Field(); + + memcpy(subset->mName, mName, MED_TAILLE_NOM + 1); + subset->mEntity = mEntity; + subset->mGeom = mGeom; + subset->mType = mType; + subset->mSizeOfType = mSizeOfType; + subset->mNumComponents = mNumComponents; + subset->mStrComponent = mStrComponent; + subset->mStrUnit = mStrUnit; + + subset->mNGauss = mNGauss; + subset->mDT = mDT; + subset->mNumDT = mNumDT; + subset->mDTUnit = mDTUnit; + subset->mNumO = mNumO; + subset->mGaussLoc = mGaussLoc; + subset->mProfil = mProfil; + + // for each time step + for (unsigned itTimeStep = 0 ; itTimeStep < mNGauss.size() ; itTimeStep++) + { + if (mProfil[itTimeStep].size() != 0) throw UnsupportedOperationException("", __FILE__, __LINE__); + // TODO ??? + // WARNING : do not manage profil for the moment + // if there is a profil, + // 1. we should set mProfil to NO_PROFIL for this time_step + // 2. we should extract data according to the profil + + int nval = pSetIndices.size() * subset->mNGauss[itTimeStep]; + subset->mNVal.push_back(nval); + + int sizeOfData = nval * mSizeOfType * mNumComponents; + subset->mSizeOfData.push_back(sizeOfData); + + unsigned char* data = new unsigned char[sizeOfData]; + unsigned char* dest = data; + int sizeOfOneData = mSizeOfType * mNumComponents * subset->mNGauss[itTimeStep]; + + //cout << "Size of 1 data = " << sizeOfOneData << endl; // debug + + // for each element to extract + for (set::iterator itSet = pSetIndices.begin() ; itSet != pSetIndices.end() ; itSet++) + { + int indexElt = (*itSet); + + // MED index start at 1. + if (indexElt < 1) throw new IllegalArgumentException("", __FILE__, __LINE__); + + unsigned char* src = mVal[itTimeStep] + (indexElt - 1) * sizeOfOneData; + memcpy(dest, src, sizeOfOneData); + + dest += sizeOfOneData; + } + subset->mVal.push_back(data); + } + + return subset; +} + + +void Field::getSetOfGaussLoc(set& pSetOfGaussLoc) const +{ + for (unsigned itGaussLoc = 0 ; itGaussLoc < mGaussLoc.size() ; itGaussLoc++) + { + const string& gaussLocName = mGaussLoc[itGaussLoc]; + + if (gaussLocName.length() != 0) + { + pSetOfGaussLoc.insert(gaussLocName); + } + } +} + + +void Field::readMED(med_idt pMEDfile, med_int pIndex, char* pMeshName) +{ + if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__); + if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (strlen(pMeshName) > MED_TAILLE_NOM) throw IllegalArgumentException("", __FILE__, __LINE__); + if (pIndex < 1) throw IllegalArgumentException("", __FILE__, __LINE__); + + reset(); + + mNumComponents = MEDnChamp(pMEDfile, pIndex); + + if (mNumComponents < 0) throw IOException("", __FILE__, __LINE__); + + char* strComponent = new char[mNumComponents * MED_TAILLE_PNOM + 1]; + char* strUnit = new char[mNumComponents * MED_TAILLE_PNOM + 1]; + + strComponent[0] = '\0'; + strUnit[0] = '\0'; + + med_err ret = MEDchampInfo( + pMEDfile, + pIndex, + mName, + &(mType), + strComponent, + strUnit, + mNumComponents); + + if (ret != 0) throw IOException("", __FILE__, __LINE__); + + mStrComponent = strComponent; + mStrUnit = strUnit; + + delete[] strUnit; + delete[] strComponent; + + switch (mType) + { + case MED_FLOAT64: mSizeOfType = 8; break; + case MED_INT64: mSizeOfType = 8; break; + case MED_INT32: mSizeOfType = 4; break; + case MED_INT: mSizeOfType = 4; break; + default: throw IllegalStateException("should not be there", __FILE__, __LINE__); + } + + //--------------------------------------------------------------------- + // Read fields over nodes + //--------------------------------------------------------------------- + bool fieldOnNodes = false; + { + med_int numTimeStepNodes = MEDnPasdetemps( + pMEDfile, + mName, + MED_NOEUD, + (med_geometrie_element) 0); + + if (numTimeStepNodes < 0) throw IOException("", __FILE__, __LINE__); + + if (numTimeStepNodes != 0) + { + fieldOnNodes = true; + mEntity = MED_NOEUD; + mGeom = (med_geometrie_element) 0; + readMEDtimeSteps(pMEDfile, numTimeStepNodes, pMeshName); + } + } + + //--------------------------------------------------------------------- + // Read fields over elements + //--------------------------------------------------------------------- + { + med_int numTimeStepElt = MEDnPasdetemps( + pMEDfile, + mName, + MED_MAILLE, + MED_TETRA10); + + if (numTimeStepElt < 0) throw IOException("", __FILE__, __LINE__); + + if (numTimeStepElt != 0) + { + if (fieldOnNodes) throw IllegalStateException("", __FILE__, __LINE__); + + mEntity = MED_MAILLE; + mGeom = MED_TETRA10; + readMEDtimeSteps(pMEDfile, numTimeStepElt, pMeshName); + } + } +} + + +void Field::readMEDtimeSteps(med_idt pMEDfile, med_int pNumberOfTimeSteps, char* pMeshName) +{ + if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__); + if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (strlen(pMeshName) > MED_TAILLE_NOM) throw IllegalArgumentException("", __FILE__, __LINE__); + if (pNumberOfTimeSteps < 0) throw IllegalArgumentException("", __FILE__, __LINE__); + + char strEntity[8]; + switch (mEntity) + { + case MED_ARETE: + case MED_FACE: + case MED_MAILLE: strcpy(strEntity, "CELLS"); break; + case MED_NOEUD: strcpy(strEntity, "NODES"); break; + default: strcpy(strEntity, "UNKNOWN"); break; + } + + // iterates over time step + for (int itTimeStep = 1 ; itTimeStep <= pNumberOfTimeSteps ; itTimeStep++) + { + med_int ngauss; + med_int numdt; + med_int numo; + char dtunit[MED_TAILLE_PNOM + 1]; + med_float dt; + char maa[MED_TAILLE_NOM + 1]; + med_booleen local; + med_int nmaa; + + med_err ret = MEDpasdetempsInfo( + pMEDfile, + mName, + mEntity, + mGeom, + itTimeStep, + &ngauss, + &numdt, + &numo, + dtunit, + &dt, + maa, + &local, + &nmaa); + + if (ret != 0) throw IOException("i/o error while reading #timesteps in MED file", __FILE__, __LINE__); + + // mesh must be local + if (local != MED_VRAI) throw IllegalStateException("only local fields are currently supported", __FILE__, __LINE__); + + // #mesh must be 1 + if (nmaa != 1) throw IllegalStateException("field shoud be associated with 1 mesh only", __FILE__, __LINE__); + + // mesh must be pMeshName + //MULTIPR_CHECK((strcmp(maa, pMeshName) == 0), MED_ILLEGAL_FILE, pMEDfile); + // if field does not apply on the current mesh, skip + if (strcmp(maa, pMeshName) != 0) + { + continue; + } + + mNGauss.push_back(ngauss); + mDT.push_back(dt); + mNumDT.push_back(numdt); + mDTUnit.push_back(dtunit); + mNumO.push_back(numo); + + //MULTIPR_LOG("Time step #" << itTimeStep << ": #gauss=" << ngauss << " dt=" << dt << " maa=" << maa << " has_dt?" << ((numdt==MED_NOPDT)?"no":"yes") << " numdt=" << numdt << " unit=" << dtunit << " has_order?" << ((numo==MED_NONOR)?"no":"yes") << " numo:" << numo << endl); + + med_int nval = MEDnVal( + pMEDfile, + mName, + mEntity, + mGeom, + numdt, + numo, + pMeshName, + MED_GLOBAL); + + if (nval < 0) throw IOException("i/o error while reading field in MED file", __FILE__, __LINE__); + + mNVal.push_back(nval); + + char gaussLocName[MED_TAILLE_NOM + 1]; + char profilName[MED_TAILLE_NOM + 1]; + int sizeOfData = mSizeOfType * mNumComponents * nval; + mSizeOfData.push_back(sizeOfData); + unsigned char* fieldData = new unsigned char[sizeOfData]; + + ret = MEDchampLire( + pMEDfile, + pMeshName, + mName, + fieldData, + MED_FULL_INTERLACE, + MED_ALL, + gaussLocName, + profilName, + MED_COMPACT, //MED_GLOBAL, MED_NO_PFLMOD, MED_COMPACT + mEntity, + mGeom, + numdt, + numo); + + if (ret != 0) throw IOException("i/o error while reading field in MED file", __FILE__, __LINE__); + + mGaussLoc.push_back(gaussLocName); + mProfil.push_back(profilName); + mVal.push_back(fieldData); + } +} + + +void Field::writeMED(med_idt pMEDfile, char* pMeshName) +{ + if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__); + if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (strlen(pMeshName) > MED_TAILLE_NOM) throw IllegalArgumentException("", __FILE__, __LINE__); + if (mNumComponents < 1) throw IllegalStateException("", __FILE__, __LINE__); + + med_err ret = MEDchampCr( + pMEDfile, + mName, // name of the field + mType, // type of data (MED_FLOAT64, MED_INT32, etc.) + const_cast(mStrComponent.c_str()), // name of components + const_cast(mStrUnit.c_str()), // name of units + mNumComponents); // number of components + + if (ret != 0) throw IOException("i/o error while creating field in MED file", __FILE__, __LINE__); + + // for each time step + for (unsigned i = 0 ; i < mNGauss.size() ; i++) + { + // skip if no values + if (mNVal[i] == 0) continue; + + ret = MEDchampEcr( + pMEDfile, + pMeshName, // name of the mesh (first call to MEDchampEcr => name of reference) + mName, // name of the field + mVal[i], // data (= values) + MED_FULL_INTERLACE, // data organization + mNVal[i], // number of values + const_cast(mGaussLoc[i].c_str()), // name of Gauss reference + MED_ALL, // components to be selected + const_cast(mProfil[i].c_str()), // name of profil + MED_GLOBAL, // how to read data: MED_NO_PFLMOD,MED_COMPACT,MED_GLOBAL + mEntity, // type of entity (MED_NOEUD, MED_MAILLE, etc.) + mGeom, // type of geometry (TETRA10, etc.) + mNumDT[i], // time step iteration + const_cast(mDTUnit[i].c_str()), // unit of time step + mDT[i], // time key + mNumO[i]); // order number + + if (ret != 0) throw IOException("i/o error while writing field in MED file", __FILE__, __LINE__); + } +} + + +ostream& operator<<(ostream& pOs, Field& pF) +{ + char strEntity[16]; + switch (pF.mEntity) + { + case MED_MAILLE: strcpy(strEntity, "MED_MAILLE"); break; + case MED_FACE: strcpy(strEntity, "MED_FACE"); break; + case MED_ARETE: strcpy(strEntity, "MED_ARETE"); break; + case MED_NOEUD: strcpy(strEntity, "MED_NOEUD"); break; + default: strcpy(strEntity, "UNKNOWN"); break; + } + + char strType[16]; + switch (pF.mType) + { + case MED_FLOAT64: strcpy(strType, "MED_FLOAT64"); break; + case MED_INT32: strcpy(strType, "MED_INT32"); break; + case MED_INT64: strcpy(strType, "MED_INT64"); break; + case MED_INT: strcpy(strType, "MED_INT"); break; + default: strcpy(strType, "UNKNOWN"); break; + } + + pOs << "Field: " << endl; + pOs << " Name =|" << pF.mName << "|" << endl; + pOs << " Entity =" << strEntity << endl; + pOs << " Geom =" << pF.mGeom << endl; + pOs << " Type =" << strType << " (size=" << pF.mSizeOfType << ")" << endl; + pOs << " #Components=" << pF.mNumComponents << endl; + pOs << " Name component=|" << pF.mStrComponent << "|" << endl; + pOs << " Unit component=|" << pF.mStrUnit << "|" << endl; + pOs << " #Time steps=" << pF.mNGauss.size() << endl; + + for (unsigned itTimeStep = 0 ; itTimeStep < pF.mNGauss.size() ; itTimeStep++) + { + pOs << " Time=" << pF.mDT[itTimeStep]; + pOs << " it=" << pF.mNumDT[itTimeStep]; + pOs << " order=" << pF.mNumO[itTimeStep]; + pOs << " #gauss=" << pF.mNGauss[itTimeStep]; + pOs << " #val=" << pF.mNVal[itTimeStep]; + pOs << " sizeof_val=" << pF.mSizeOfData[itTimeStep]; + pOs << " gauss_loc=|" << ((pF.mGaussLoc[itTimeStep].size() == 0)?"NONE":pF.mGaussLoc[itTimeStep]) << "| size=" << pF.mGaussLoc[itTimeStep].size(); + pOs << " profil=|" << ((pF.mProfil[itTimeStep].size() == 0)?"NONE":pF.mProfil[itTimeStep]) << "| size=" << pF.mProfil[itTimeStep].size() << endl; + + if (pF.mFlagPrintAll) + { + cout << " Values: "; + switch (pF.mType) + { + case MED_FLOAT64: + { + med_float* src = reinterpret_cast(pF.mVal[itTimeStep]); + for (int itVal = 0 ; itVal < pF.mNVal[itTimeStep] * pF.mNumComponents ; itVal++) + { + cout << src[itVal] << " "; + } + } + break; + case MED_INT: + case MED_INT32: + { + med_int* src = reinterpret_cast(pF.mVal[itTimeStep]); + for (int itVal = 0 ; itVal < pF.mNVal[itTimeStep] * pF.mNumComponents ; itVal++) + { + cout << src[itVal] << " "; + } + } + break; + case MED_INT64: + // not yet implemented + throw UnsupportedOperationException("not yet implemented", __FILE__, __LINE__); + default: + // should not be there + throw IllegalStateException("should not be there", __FILE__, __LINE__); + } + cout << endl; + } + + } + + return pOs; +} + + +} // namespace multipr + +// EOF diff --git a/src/MULTIPR/MULTIPR_Field.hxx b/src/MULTIPR/MULTIPR_Field.hxx new file mode 100644 index 0000000..2e82140 --- /dev/null +++ b/src/MULTIPR/MULTIPR_Field.hxx @@ -0,0 +1,236 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Field.hxx + * + * \brief Class Field used to wrap MED file fields. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_FIELD_HXX +#define MULTIPR_FIELD_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + +extern "C" +{ + #include "med.h" +} + +#include +#include +#include + + +namespace multipr +{ + + +//***************************************************************************** +// Class Field +//***************************************************************************** + +class Field +{ +public: + + /** + * Builds an empty field (default constructor). + */ + Field(); + + /** + * Destructor. Removes everything. + */ + ~Field(); + + /** + * Resets this object in its state by default (empty). Cleans memory. + */ + void reset(); + + //--------------------------------------------------------------------- + // Basic accessors/mutators + //--------------------------------------------------------------------- + + /** + * Returns true iff this field is empty (no data). + * \return true if this field is empty, false otherwise. + */ + bool isEmpty() const; + + /** + * Returns true iff this field apply on nodes (otherwise, information are related to elements). + * \return true iff this field apply on nodes. + */ + bool isFieldOnNodes() const { return (mEntity == MED_NOEUD); } + + /** + * Returns the name of this Field. + * \return the name of this Field. + */ + const char* getName() const { return mName; } + + /** + * Returns the number of time steps in this Field. + * \return the number of time steps in this Field. + */ + int getNumberOfTimeSteps() const { return mNGauss.size(); } + + /** + * Returns the numeric type of information contained in this Field (e.g. MED_FLOAT64). + * \return the numeric type of this Field. + */ + med_type_champ getType() const { return mType; } + + /** + * Returns the number of components of this Field. + * \return the number of components of this Field. + */ + int getNumberOfComponents() const { return mNumComponents; } + + /** + * Returns the number of Gauss points for each element at the given time step. + * \param pTimeStepIt iteration of the field; must be in [1..MAX_ITERATION]. + * \return number of Gauss points in the elements of this Field at the given iteration. + * \throw IndexOutOfBoundsException if pTimeStepIt not in [1..MAX_ITERATION]. + */ + int getNumberOfGaussPointsByElement(int pTimeStepIt) const; + + /** + * Returns the name of the Gauss localization related to the given iteration. + * \param pTimeStepIt iteration of the field; must be in [1..MAX_ITERATION]. + * \return the name of the Gauss localization related to the given iteration. + * \throw IndexOutOfBoundsException if pTimeStepIt not in [1..MAX_ITERATION]. + */ + const std::string& getNameGaussLoc(int pTimeStepIt) const; + + /** + * Returns a pointer towards the first value of this Field for the given element at the given time step. + * \param pTimeStepIt iteration of the field; must be in [1..MAX_ITERATION]. + * \param pIndex index of the element; must be >= 1. + * \return the value of this Field for the given element at the given time step. + * \throw IndexOutOfBoundsException if pTimeStepIt or pIndex are invalid. + */ + const unsigned char* getValue(int pTimeStepIt, int pIndex) const; + + //--------------------------------------------------------------------- + // Algorithms + //--------------------------------------------------------------------- + + /** + * Creates a subset of this Field restricted to a set of elements (NODES or CELLS). + * This method performs a projection of this Field on the given set of elements. + * \param pSetIndices WARNING: indices start at 1. + * \return a new Field restricted to the given set of elements. + */ + Field* extractSubSet(const std::set& pSetIndices) const; + + /** + * Adds the set of GaussLoc used by this Field into the given set. + * \param pSetOfGauss any set of Gauss localisation. + */ + void getSetOfGaussLoc(std::set& pSetOfGaussLoc) const; + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Reads a field from a MED file. + * If the field is not related to the given mesh, the result is an empty field. + * \param pMEDfile any valid MED file opened for reading. + * \param pIndex index of the field to be read; must be >= 1. + * \param pMeshName name of the mesh (a field is always related to a mesh). + * \throw IOException if any i/o error occurs. + */ + void readMED(med_idt pMEDfile, med_int pIndex, char* pMeshName); + + /** + * Writes this field to a MED file. The field is linked to the given mesh. + * WARNING: all related Gauss info must have been added to the MED file before. + * \param pMEDfile any valid MED file opened for writing. + * \param pMeshName name of the mesh. + * \throw IOException if any i/o error occurs. + */ + void writeMED(med_idt pMEDfile, char* pMeshName); + + /** + * Sets the flag which control the stream operator <<. + * \param pFlag new flag value. + */ + void setPrintAll(bool pFlag) { mFlagPrintAll = pFlag; } + + /** + * Dumps any Field to the given output stream. + * \param pOs any output stream. + * \param pF any Field. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, Field& pF); + +private: + + /** + * Reads all the information related to its field and a given time step (by its index). + * \param pMEDfile MED file handle. + * \param pNumberOfTimeSteps number of timesteps (iteration) to be read. + * \param pMeshName name of the mesh. + * \throw IOException if any i/o error occurs. + */ + void readMEDtimeSteps(med_idt pMEDfile, med_int pNumberOfTimeSteps, char* pMeshName); + +private: + + char mName[MED_TAILLE_NOM + 1]; + med_entite_maillage mEntity; // type of entity, e.g. MED_MAILLE + med_geometrie_element mGeom; // type of primitives, e.g. MED_TETRA10 (MED_NONE for a field on nodes) + med_type_champ mType; // type of field, e.g. MED_FLOAT64, MED_INT32 + int mSizeOfType; // 8 for MED_FLOAT64, 4 for MED_INT32, etc. + med_int mNumComponents; + std::string mStrComponent; + std::string mStrUnit; + + // Information related to time steps. + // Each vector should contain the same number of elements. + // Number of time step = mNGauss.size() = mDT.size() = ... + + std::vector mNGauss; /**< For each time step, number of Gauss points in the field. */ + std::vector mDT; /**< For each time step, value of time step. */ + std::vector mNumDT; /**< For each time step, iteration number. */ + std::vector mDTUnit; /**< For each time step, units. */ + std::vector mNumO; /**< For each time step, order number. */ + std::vector mGaussLoc; /**< For each time step, name of Gauss localization to be used (empty if none). */ + std::vector mProfil; /**< For each time step, name of the profil to be used (empty if none). */ + std::vector mSizeOfData; /**< For each time step, sizeof data (mVal) in bytes. */ + std::vector mNVal; /**< For each time step, number of values. */ + std::vector mVal; /**< For each time step, raw data; can be MED_FLOAT64, MED_INT32, etc. see mType. */ + + bool mFlagPrintAll; /**< Flag to control the behaviour of the stream operator <<. */ + +private: + + // do not allow copy constructor + Field(const Field&); + + // do not allow copy + Field& operator=(const Field&); + + // do not allow operator == + bool operator==(const Field&); + +}; // class Field + + +} // namespace MULTIPR + + +#endif // MULTIPR_FIELD_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_GaussLoc.cxx b/src/MULTIPR/MULTIPR_GaussLoc.cxx new file mode 100644 index 0000000..7fd8566 --- /dev/null +++ b/src/MULTIPR/MULTIPR_GaussLoc.cxx @@ -0,0 +1,235 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_GaussLoc.cxx + * + * \brief see MULTIPR_GaussLoc.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_GaussLoc.hxx" +#include "MULTIPR_Utils.hxx" +#include "MULTIPR_Exceptions.hxx" + +#include + +using namespace std; + + +namespace multipr +{ + + +//***************************************************************************** +// Class GaussLoc implementation +//***************************************************************************** + +GaussLoc::GaussLoc() +{ + mRefCoo = NULL; + mGaussCoo = NULL; + mWeight = NULL; + + reset(); +} + + +GaussLoc::GaussLoc(const GaussLoc& pGaussLoc) +{ + mRefCoo = NULL; + mGaussCoo = NULL; + mWeight = NULL; + + strcpy(mName, pGaussLoc.mName); + + mGeom = pGaussLoc.mGeom; + mDim = pGaussLoc.mDim; + mNumNodes = pGaussLoc.mNumNodes; + mNumGauss = pGaussLoc.mNumGauss; + + if (mDim != (mGeom / 100)) throw IllegalStateException("", __FILE__, __LINE__); + if (mNumNodes != (mGeom % 100)) throw IllegalStateException("", __FILE__, __LINE__); + + if (pGaussLoc.mRefCoo != NULL) + { + mRefCoo = new med_float[mDim * mNumNodes]; + memcpy(mRefCoo, pGaussLoc.mRefCoo, sizeof(med_float) * mDim * mNumNodes); + } + + if (pGaussLoc.mGaussCoo != NULL) + { + mGaussCoo = new med_float[mDim * mNumGauss]; + memcpy(mGaussCoo, pGaussLoc.mGaussCoo, sizeof(med_float) * mDim * mNumGauss); + } + + if (pGaussLoc.mWeight != NULL) + { + mWeight = new med_float[mNumGauss]; + memcpy(mWeight, pGaussLoc.mWeight, sizeof(med_float) * mNumGauss); + } +} + + +GaussLoc::~GaussLoc() +{ + reset(); +} + + +void GaussLoc::reset() +{ + mName[0] = '\0'; + mGeom = MED_NONE; + mDim = 0; + mNumNodes = 0; + mNumGauss = 0; + + if (mRefCoo != NULL) { delete[] mRefCoo; mRefCoo = NULL; } + if (mGaussCoo != NULL) { delete[] mGaussCoo; mGaussCoo = NULL; } + if (mWeight != NULL) { delete[] mWeight; mWeight = NULL; } +} + + +void GaussLoc::getCoordGaussPoints( + const med_float* pCooElt, + med_float* pCooGaussPoints) const +{ + // debug + //printArray2D(pCooElt, mNumNodes, mDim, "Node"); + + // WARNING: assumes TETRA10 !!! + // This method is not completely generic and should be extended to support all cases. + if (mGeom != MED_TETRA10) throw UnsupportedOperationException("only support TETRA10 for the moment", __FILE__, __LINE__); + + const med_float* pt1 = pCooElt; + const med_float* pt2 = pt1 + mDim; + const med_float* pt3 = pt2 + mDim; + const med_float* pt4 = pt3 + mDim; + + const med_float* coeff = mGaussCoo; + med_float* dest = pCooGaussPoints; + + // for each Gauss point + for (int i = 0 ; i < mNumGauss ; i++) + { + dest[0] = pt2[0] + (pt4[0] - pt2[0]) * coeff[0] + (pt1[0] - pt2[0]) * coeff[1] + (pt3[0] - pt2[0]) * coeff[2]; + dest[1] = pt2[1] + (pt4[1] - pt2[1]) * coeff[0] + (pt1[1] - pt2[1]) * coeff[1] + (pt3[1] - pt2[1]) * coeff[2]; + dest[2] = pt2[2] + (pt4[2] - pt2[2]) * coeff[0] + (pt1[2] - pt2[2]) * coeff[1] + (pt3[2] - pt2[2]) * coeff[2]; + + // prepare next point + coeff += mDim; + dest += mDim; + } +} + + +void GaussLoc::readMED(med_idt pMEDfile, med_int pIndex) +{ + if (pMEDfile == 0) throw IOException("pMEDfile should not be NULL", __FILE__, __LINE__); + if (pIndex < 1) throw IllegalArgumentException("pIndex should be >= 1", __FILE__, __LINE__); + + reset(); + + med_err ret = MEDgaussInfo( + pMEDfile, + pIndex, + mName, + &mGeom, + &mNumGauss); + + if (ret != 0) throw IOException("i/o error while reading Gauss localization information in MED file", __FILE__, __LINE__); + + mDim = mGeom / 100; + mNumNodes = mGeom % 100; + + mRefCoo = new med_float[mDim * mNumNodes]; + mGaussCoo = new med_float[mDim * mNumGauss]; + mWeight = new med_float[mNumGauss]; + + ret = MEDgaussLire( + pMEDfile, + mRefCoo, + mGaussCoo, + mWeight, + MED_FULL_INTERLACE, + mName); + + if (ret != 0) throw IOException("i/o error while reading Gauss localization in MED file", __FILE__, __LINE__); +} + + +void GaussLoc::writeMED(med_idt pMEDfile) +{ + if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__); + if (mNumGauss < 0) throw IllegalStateException("", __FILE__, __LINE__); + if (mRefCoo == NULL) throw IllegalStateException("", __FILE__, __LINE__); + if (mGaussCoo == NULL) throw IllegalStateException("", __FILE__, __LINE__); + if (mWeight == NULL) throw IllegalStateException("", __FILE__, __LINE__); + if (strlen(mName) > MED_TAILLE_NOM) throw IllegalStateException("", __FILE__, __LINE__); + + med_err ret = MEDgaussEcr( + pMEDfile, + mGeom, + mRefCoo, + MED_FULL_INTERLACE, + mNumGauss, + mGaussCoo, + mWeight, + mName); + + if (ret != 0) throw IOException("i/o error while writing Gauss localization", __FILE__, __LINE__); +} + + +ostream& operator<<(ostream& pOs, GaussLoc& pG) +{ + pOs << "Gauss ref:" << endl; + pOs << " Name =|" << pG.mName << "|" << endl; + pOs << " Geom =" << pG.mGeom << endl; + pOs << " #Pt Gauss=" << pG.mNumGauss << endl; + + pOs << " Ref nodes coords.: (#nodes=" << pG.mNumNodes << " dim=" << pG.mDim << ")" << endl; + for (int itNode = 0 ; itNode < pG.mNumNodes ; itNode++) + { + pOs << " Node " << (itNode + 1) << ": "; + for (int itDim = 0; itDim < pG.mDim ; itDim++) + { + pOs << pG.mRefCoo[itNode * pG.mDim + itDim] << " "; + } + pOs << endl; + } + + pOs << " Gauss coords. and weight:" << endl; + for (int itGauss = 0 ; itGauss < pG.mNumGauss ; itGauss++) + { + pOs << " Pt " << (itGauss+1) << ": "; + for (int itDim = 0; itDim < pG.mDim ; itDim++) + { + pOs << pG.mGaussCoo[itGauss * pG.mDim + itDim] << " "; + } + pOs << "weight=" << pG.mWeight[itGauss]; + pOs << endl; + } + + /* + // debug + med_float res[15]; + pG.getCoordGaussPoints(pG.mRefCoo, res); + printArray2D(res, pG.mNumGauss, pG.mDim, "Gauss pt"); + */ + + return pOs; +} + + +} // namespace multipr + +// EOF diff --git a/src/MULTIPR/MULTIPR_GaussLoc.hxx b/src/MULTIPR/MULTIPR_GaussLoc.hxx new file mode 100644 index 0000000..d55deb7 --- /dev/null +++ b/src/MULTIPR/MULTIPR_GaussLoc.hxx @@ -0,0 +1,150 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_GaussLoc.hxx + * + * \brief Class GaussLoc. Allow to locate all the Gauss points in an element of reference (e.g. a TETRA10). + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_GAUSSLOC_HXX +#define MULTIPR_GAUSSLOC_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + +extern "C" +{ + #include "med.h" +} + +#include + + +namespace multipr +{ + + +//***************************************************************************** +// Class GaussLoc +//***************************************************************************** + +class GaussLoc +{ +public: + + /** + * Builds an empty Gauss reference (default constructor). + */ + GaussLoc(); + + /** + * Copy constructor (deep copy). + * \param pGaussLoc the GaussLoc to copy. + */ + GaussLoc(const GaussLoc& pGaussLoc); + + /** + * Destructor. Removes everything. + */ + ~GaussLoc(); + + /** + * Resets this object in its state by default (empty). Cleans memory. + */ + void reset(); + + //--------------------------------------------------------------------- + // Basic accessors/mutators + //-------------------------------------------------------------------- + + /** + * Returns the name of this GaussLoc. + * \return the name of this GaussLoc. + */ + std::string getName() const { return mName; } + + /** + * Returns dimension of Gauss points which is also the dimension of reference nodes. + * \return dimension of Gauss points. + */ + int getDim() const { return mDim; } + + /** + * Returns number of Gauss points. + * \return number of Gauss points. + */ + int getNumGaussPoints() const { return mNumGauss; } + + //--------------------------------------------------------------------- + // Algorithms + //-------------------------------------------------------------------- + + /** + * Returns the coordinates of all the Gauss points for a given element. + * \param pCooElt (in) coordinates of nodes of an element. + * \param pCoo (out) coordinates of all the Gauss points (interlaced); memory must have been allocated. + */ + void getCoordGaussPoints(const med_float* pCooElt, med_float* pCooGaussPoints) const; + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Reads a GaussLoc object from a MED file. + * \param pMEDfile any valid MED file opened for reading. + * \param pIndex index of the gauss localization to be read; must be >= 1. + * \throw IOException if any i/o error occurs. + */ + void readMED(med_idt pMEDfile, med_int pIndex); + + /** + * Writes this GaussLoc object to the given MED file. + * \param pMEDfile any valid MED file opened for writing. + * \throw IOException if any i/o error occurs. + */ + void writeMED(med_idt pMEDfile); + + /** + * Dumps any GaussLoc to the given output stream. + * \param pOs any output stream. + * \param pF any Field. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, GaussLoc& pG); + +private: + + char mName[MED_TAILLE_NOM + 1]; /**< Name of the Gauss info. */ + med_geometrie_element mGeom; /**< Type of elements, e.g. TETRA10 (code is 310). */ + int mDim; /**< Dimension of nodes, e.g. 3 for a TETRA10. */ + int mNumNodes; /**< Number of nodes in the reference element, e.g. 10 for a TETRA10. */ + med_int mNumGauss; /**< Number of Gauss points. */ + med_float* mRefCoo; /**< Table of coordinates of nodes. + Example: for a TETRA10: 10 nodes, 3 components => 30 med_float. */ + med_float* mGaussCoo; /**< Table of coordinates of Gauss points. */ + med_float* mWeight; /**< Table of weights of Gauss points. */ + +private: + + // do not allow copy + GaussLoc& operator=(const GaussLoc&); + + // do not allow operator == + bool operator==(const GaussLoc&); + +}; // class GaussLoc + + +} // namespace MULTIPR + + +#endif // MULTIPR_GAUSSLOC_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_Globals.hxx b/src/MULTIPR/MULTIPR_Globals.hxx new file mode 100644 index 0000000..ff51f67 --- /dev/null +++ b/src/MULTIPR/MULTIPR_Globals.hxx @@ -0,0 +1,29 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Globals.hxx + * + * \brief Some useful macros. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + + +#ifndef MULTIPR_GLOBALS_HXX +#define MULTIPR_GLOBALS_HXX + +//***************************************************************************** +// Some useful macros +//***************************************************************************** + +#define ENABLE_LOG 0 +#define MULTIPR_LOG(STR) if (ENABLE_LOG) cout << STR; + + +#endif // MULTIPR_GLOBALS_HXX + + +// EOF diff --git a/src/MULTIPR/MULTIPR_Mesh.cxx b/src/MULTIPR/MULTIPR_Mesh.cxx new file mode 100644 index 0000000..fc16c30 --- /dev/null +++ b/src/MULTIPR/MULTIPR_Mesh.cxx @@ -0,0 +1,1188 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Mesh.cxx + * + * \brief see MULTIPR_Mesh.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_Mesh.hxx" +#include "MULTIPR_Nodes.hxx" +#include "MULTIPR_Elements.hxx" +#include "MULTIPR_Family.hxx" +#include "MULTIPR_Profil.hxx" +#include "MULTIPR_GaussLoc.hxx" +#include "MULTIPR_Field.hxx" +#include "MULTIPR_MeshDis.hxx" +#include "MULTIPR_PointOfField.hxx" +#include "MULTIPR_DecimationFilter.hxx" +#include "MULTIPR_Utils.hxx" +#include "MULTIPR_Exceptions.hxx" +#include "MULTIPR_Globals.hxx" +#include "MULTIPR_API.hxx" + +using namespace std; + + +namespace multipr +{ + + +//***************************************************************************** +// Class Mesh implementation +//***************************************************************************** + +Mesh::Mesh() +{ + mNodes = NULL; + mElements = NULL; + + reset(); +} + + +Mesh::~Mesh() +{ + reset(); +} + + +void Mesh::reset() +{ + mMEDfilename[0] = '\0'; + mMEDfile = 0; + + mMeshName[0] = '\0'; + mMeshUName[0] = '\0'; + mMeshDesc[0] = '\0'; + mMeshDim = -1; + mMeshType = MED_NON_STRUCTURE; + + for (int itDim = 0 ; itDim < 3 ; itDim++) + { + mMeshBBoxMin[itDim] = numeric_limits::quiet_NaN(); + mMeshBBoxMax[itDim] = numeric_limits::quiet_NaN(); + } + + if (mNodes != NULL) { delete mNodes; mNodes = NULL; } + if (mElements != NULL) { delete mElements; mElements = NULL; } + + for (unsigned itFam = 0 ; itFam < mFamilies.size() ; itFam++) + { + delete mFamilies[itFam]; + } + mFamilies.clear(); + mFamIdToFam.clear(); + + for (unsigned itGroup = 0 ; itGroup < mGroups.size() ; itGroup++) + { + delete mGroups[itGroup]; + } + mGroups.clear(); + mGroupNameToGroup.clear(); + + for (unsigned itGaussLoc = 0 ; itGaussLoc < mGaussLoc.size() ; itGaussLoc++) + { + delete mGaussLoc[itGaussLoc]; + } + mGaussLoc.clear(); + mGaussLocNameToGaussLoc.clear(); + + for (unsigned itField = 0 ; itField < mFields.size() ; itField++) + { + delete mFields[itField]; + } + mFields.clear(); + + for (unsigned itProfil = 0 ; itProfil < mProfils.size() ; itProfil++) + { + delete mProfils[itProfil]; + } + mProfils.clear(); + + mFlagPrintAll = false; +} + + +vector Mesh::getNameFields() const +{ + vector res; + + for (int itField = 0 ; itField < mFields.size() ; itField++) + { + Field* currentField = mFields[itField]; + res.push_back(currentField->getName()); + } + + return res; +} + + +int Mesh::getTimeStamps(const char* pFieldName) const +{ + for (int itField = 0 ; itField < mFields.size() ; itField++) + { + Field* currentField = mFields[itField]; + if (strcmp(currentField->getName(), pFieldName) == 0) + { + return currentField->getNumberOfTimeSteps(); + } + } + + return 0; +} + + +Field* Mesh::getFieldByName(const char* pFieldName) const +{ + if (pFieldName == NULL) throw NullArgumentException("pFieldName should not be NULL", __FILE__, __LINE__); + + Field* retField = NULL; + + // for each field + for (unsigned itField = 0 ; itField < mFields.size() ; itField++) + { + Field* currentField = mFields[itField]; + if (strcmp(pFieldName, currentField->getName()) == 0) + { + // field found! + retField = currentField; + break; + } + } + + return retField; +} + + +GaussLoc* Mesh::getGaussLocByName(const char* pGaussLocName) const +{ + if (pGaussLocName == NULL) throw NullArgumentException("pGaussLocName should not be NULL", __FILE__, __LINE__); + + map::const_iterator itGaussLoc = mGaussLocNameToGaussLoc.find(pGaussLocName); + GaussLoc* retGaussLoc = NULL; + + if (itGaussLoc != mGaussLocNameToGaussLoc.end()) + { + retGaussLoc = (*itGaussLoc).second; + } + + return retGaussLoc; +} + + +int Mesh::getNumberOfElements() const +{ + if (mElements == NULL) throw IllegalStateException("", __FILE__, __LINE__); + + return mElements->getNumberOfElements(); +} + + +Mesh* Mesh::createFromSetOfElements(const std::set& pSetOfElements, const char* pNewMeshName) +{ + if (pNewMeshName == NULL) throw NullArgumentException("pNewMeshName", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Create a new mesh + //--------------------------------------------------------------------- + Mesh* mesh = new Mesh(); + + //--------------------------------------------------------------------- + // Build name of the new mesh + //--------------------------------------------------------------------- + strcpy(mesh->mMeshName, pNewMeshName); + + MULTIPR_LOG("Mesh name=|" << mesh->mMeshName << "|" << endl); + + //--------------------------------------------------------------------- + // Fill general infos + //--------------------------------------------------------------------- + strcpy(mesh->mMeshUName, mMeshUName); + strcpy(mesh->mMeshDesc, mMeshDesc); + + mesh->mMeshDim = mMeshDim; + mesh->mMeshType = mMeshType; + + MULTIPR_LOG("Mesh u. name=|" << mesh->mMeshUName << "|" << endl); + MULTIPR_LOG("Mesh desc=|" << mesh->mMeshDesc << "|" << endl); + MULTIPR_LOG("Mesh dim=" << mesh->mMeshDim << endl); + MULTIPR_LOG("Mesh Type=" << mesh->mMeshType << endl); + + //--------------------------------------------------------------------- + // Build nodes and elements + //--------------------------------------------------------------------- + // get all elements involved + mesh->mElements = mElements->extractSubSet(pSetOfElements); + MULTIPR_LOG((*(mesh->mElements)) << endl); + + // get all nodes involved + const set setOfNodes = mesh->mElements->getSetOfNodes(); + mesh->mNodes = mNodes->extractSubSet(setOfNodes); + MULTIPR_LOG((*(mesh->mNodes)) << endl); + + //--------------------------------------------------------------------- + // Remap nodes + //--------------------------------------------------------------------- + mesh->mElements->remap(); + MULTIPR_LOG((*(mesh->mElements)) << endl); + + //--------------------------------------------------------------------- + // Build families + //--------------------------------------------------------------------- + MULTIPR_LOG("Build fam.:" << endl); + // get families of nodes + { + set famOfNodes = mesh->mNodes->getSetOfFamilies(); + for (set::iterator itFam = famOfNodes.begin() ; itFam != famOfNodes.end() ; itFam++) + { + Family* famSrc = mFamIdToFam[*itFam]; + cout << (*famSrc) << endl; + Family* famDest = famSrc->extractGroup(NULL); + mesh->mFamilies.push_back(famDest); + } + } + + // get families of elements + { + set famOfElt = mesh->mElements->getSetOfFamilies(); + for (set::iterator itFam = famOfElt.begin() ; itFam != famOfElt.end() ; itFam++) + { + Family* famSrc = mFamIdToFam[*itFam]; + Family* famDest = famSrc->extractGroup(NULL); + mesh->mFamilies.push_back(famDest); + } + } + + MULTIPR_LOG("Finalize:"); + + // fill families with elements and build groups + mesh->finalizeFamiliesAndGroups(); + + MULTIPR_LOG("OK\n"); + + //--------------------------------------------------------------------- + // Create new fields and collect Gauss + //--------------------------------------------------------------------- + // for each field + set newSetOfGauss; + for (unsigned itField = 0 ; itField < mFields.size() ; itField++) + { + Field* currentField = mFields[itField]; + + Field* newField; + if (currentField->isFieldOnNodes()) + { + newField = currentField->extractSubSet(setOfNodes); + } + else + { + newField = currentField->extractSubSet(pSetOfElements); + } + + if (!newField->isEmpty()) + { + mesh->mFields.push_back(newField); + newField->getSetOfGaussLoc(newSetOfGauss); + } + } + MULTIPR_LOG("Collect fields: ok: #gauss=" << newSetOfGauss.size() << endl); + + //--------------------------------------------------------------------- + // Build Gauss infos + //--------------------------------------------------------------------- + for (set::iterator itSet = newSetOfGauss.begin() ; itSet != newSetOfGauss.end(); itSet++) + { + const string& keyName = (*itSet); + + GaussLoc* gaussLoc = getGaussLocByName(keyName.c_str()); + if (gaussLoc != NULL) + { + GaussLoc* copyGaussLoc = new GaussLoc(*gaussLoc); + mesh->mGaussLoc.push_back(copyGaussLoc); + mesh->mGaussLocNameToGaussLoc.insert(make_pair(copyGaussLoc->getName(), copyGaussLoc)); + } + } + + //--------------------------------------------------------------------- + // Compute bbox + //--------------------------------------------------------------------- + mesh->mNodes->getBBox(mesh->mMeshBBoxMin, mesh->mMeshBBoxMax); + + return mesh; +} + + +Mesh* Mesh::createFromGroup(const Group* pGroup, const char* pNewMeshName) +{ + if (pGroup == NULL) throw NullArgumentException("pGroup should not be NULL", __FILE__, __LINE__); + if (pNewMeshName == NULL) throw NullArgumentException("pNewMeshName should not be NULL", __FILE__, __LINE__); + if (strlen(pNewMeshName) > MED_TAILLE_NOM) throw IllegalArgumentException("pNewMeshName length too long", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Create a new mesh + //--------------------------------------------------------------------- + Mesh* mesh = new Mesh(); + + //--------------------------------------------------------------------- + // Build name of the new mesh + //--------------------------------------------------------------------- + strcpy(mesh->mMeshName, pNewMeshName); + + MULTIPR_LOG("Mesh name=|" << mesh->mMeshName << "|" << endl); + + //--------------------------------------------------------------------- + // Fill general infos + //--------------------------------------------------------------------- + strcpy(mesh->mMeshUName, mMeshUName); + strcpy(mesh->mMeshDesc, mMeshDesc); + + mesh->mMeshDim = mMeshDim; + mesh->mMeshType = mMeshType; + + MULTIPR_LOG("Mesh u. name=|" << mesh->mMeshUName << "|" << endl); + MULTIPR_LOG("Mesh desc=|" << mesh->mMeshDesc << "|" << endl); + MULTIPR_LOG("Mesh dim=" << mesh->mMeshDim << endl); + MULTIPR_LOG("Mesh Type=" << mesh->mMeshType << endl); + + //--------------------------------------------------------------------- + // Build nodes and elements + //--------------------------------------------------------------------- + // get all elements involved + const set setOfElt = pGroup->getSetOfElt(); + mesh->mElements = mElements->extractSubSet(setOfElt); + MULTIPR_LOG((*(mesh->mElements)) << endl); + + // get all nodes involved + const set setOfNodes = mesh->mElements->getSetOfNodes(); + mesh->mNodes = mNodes->extractSubSet(setOfNodes); + MULTIPR_LOG((*(mesh->mNodes)) << endl); + + //--------------------------------------------------------------------- + // Remap nodes + //--------------------------------------------------------------------- + mesh->mElements->remap(); + MULTIPR_LOG((*(mesh->mElements)) << endl); + + //--------------------------------------------------------------------- + // Build families + //--------------------------------------------------------------------- + MULTIPR_LOG("Build fam.:" << endl); + // get families of nodes + { + set famOfNodes = mesh->mNodes->getSetOfFamilies(); + for (set::iterator itFam = famOfNodes.begin() ; itFam != famOfNodes.end() ; itFam++) + { + Family* famSrc = mFamIdToFam[*itFam]; + Family* famDest = famSrc->extractGroup(pGroup->getName().c_str()); + mesh->mFamilies.push_back(famDest); + } + } + + // get families of elements + { + set famOfElt = mesh->mElements->getSetOfFamilies(); + for (set::iterator itFam = famOfElt.begin() ; itFam != famOfElt.end() ; itFam++) + { + Family* famSrc = mFamIdToFam[*itFam]; + Family* famDest = famSrc->extractGroup(pGroup->getName().c_str()); + mesh->mFamilies.push_back(famDest); + } + } + + MULTIPR_LOG("Finalize:"); + + // fill families with elements and build groups + mesh->finalizeFamiliesAndGroups(); + + MULTIPR_LOG("OK\n"); + + //--------------------------------------------------------------------- + // Create new fields and collect Gauss + //--------------------------------------------------------------------- + // for each field + set newSetOfGauss; + for (unsigned itField = 0 ; itField < mFields.size() ; itField++) + { + Field* currentField = mFields[itField]; + + Field* newField; + if (currentField->isFieldOnNodes()) + { + newField = currentField->extractSubSet(setOfNodes); + } + else + { + newField = currentField->extractSubSet(setOfElt); + } + + if (!newField->isEmpty()) + { + mesh->mFields.push_back(newField); + newField->getSetOfGaussLoc(newSetOfGauss); + } + } + MULTIPR_LOG("Collect fields: ok: #gauss=" << newSetOfGauss.size() << endl); + + //--------------------------------------------------------------------- + // Build Gauss infos + //--------------------------------------------------------------------- + for (set::iterator itSet = newSetOfGauss.begin() ; itSet != newSetOfGauss.end(); itSet++) + { + const string& keyName = (*itSet); + + GaussLoc* gaussLoc = getGaussLocByName(keyName.c_str()); + if (gaussLoc != NULL) + { + GaussLoc* copyGaussLoc = new GaussLoc(*gaussLoc); + mesh->mGaussLoc.push_back(copyGaussLoc); + mesh->mGaussLocNameToGaussLoc.insert(make_pair(copyGaussLoc->getName(), copyGaussLoc)); + } + } + + //--------------------------------------------------------------------- + // Compute bbox + //--------------------------------------------------------------------- + mesh->mNodes->getBBox(mesh->mMeshBBoxMin, mesh->mMeshBBoxMax); + + return mesh; +} + + +MeshDis* Mesh::splitGroupsOfElements() +{ + MeshDis* meshDis = new MeshDis(); + + // get prefix from the original MED filename + string strPrefix = removeExtension(mMEDfilename, ".med"); + + int numGroup = 1; + + // for each group + for (unsigned itGroup = 0 ; itGroup < mGroups.size() ; itGroup++) + { + Group* currentGroup = mGroups[itGroup]; + + // skip this group if it is a group of nodes + if (currentGroup->isGroupOfNodes()) + { + continue; + } + + char strPartName[256]; + sprintf(strPartName, "%s_%d", mMeshName, numGroup); + + char strMEDfilename[256]; + sprintf(strMEDfilename, "%s_grain%d.med", strPrefix.c_str(), numGroup); + + Mesh* mesh = createFromGroup(currentGroup, mMeshName); + + // skip the group which contain all the others groups, even it contains only 1 group + if ((mesh->mElements->getNumberOfElements() == mElements->getNumberOfElements()) && (mGroups.size() > 1)) + { + delete mesh; + continue; + } + + meshDis->addMesh( + MeshDisPart::MULTIPR_WRITE_MESH, + mMeshName, + numGroup, + strPartName, + "localhost", + strMEDfilename, + mesh); + + numGroup++; + } + + return meshDis; +} + + +Mesh* Mesh::decimate( + const char* pFilterName, + const char* pArgv, + const char* pNameNewMesh) +{ + //--------------------------------------------------------------------- + // Check parameters + //--------------------------------------------------------------------- + if (pFilterName == NULL) throw NullArgumentException("pFilterName should not be NULL", __FILE__, __LINE__); + if (pArgv == NULL) throw NullArgumentException("pArgv should not be NULL", __FILE__, __LINE__); + if (pNameNewMesh == NULL) throw NullArgumentException("pNameNewMesh should not be NULL", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Instanciate filter used for decimation + //--------------------------------------------------------------------- + DecimationFilter* filter = DecimationFilter::create(pFilterName); + + //--------------------------------------------------------------------- + // Create new mesh by decimating current one + //--------------------------------------------------------------------- + Mesh* decimatedMesh = filter->apply(this, pArgv, pNameNewMesh); + + //--------------------------------------------------------------------- + // Cleans + //--------------------------------------------------------------------- + delete filter; + + return decimatedMesh; +} + + + +void Mesh::getAllPointsOfField(Field* pField, int pTimeStepIt, std::vector& pPoints) +{ + //--------------------------------------------------------------------- + // Check arguments + //--------------------------------------------------------------------- + + if (pField == NULL) throw NullArgumentException("field should not be NULL", __FILE__, __LINE__); + if (pTimeStepIt < 1) throw IllegalArgumentException("invalid field iteration; should be >= 1", __FILE__, __LINE__); + + if (mMeshDim != 3) throw UnsupportedOperationException("not yet implemented", __FILE__, __LINE__); + if (pField->getType() != MED_FLOAT64) throw UnsupportedOperationException("not yet implemented", __FILE__, __LINE__); + if (pField->getNumberOfComponents() != 1) throw UnsupportedOperationException("field have more than 1 component (vectorial field, expected scalar field)", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Collect points + //--------------------------------------------------------------------- + + if (pField->isFieldOnNodes()) + { + //------------------------------------------------------------- + // Case 1: field of nodes + //------------------------------------------------------------- + if (mNodes == NULL) throw IllegalStateException("no nodes in the current mesh", __FILE__, __LINE__); + + // for each node + for (int itNode = 0, size = mNodes->getNumberOfNodes() ; itNode < size ; itNode++) + { + // collect coordinates and value of the point + const med_float* coo = mNodes->getCoordinates(itNode); + + const med_float* val = + reinterpret_cast(pField->getValue(pTimeStepIt, itNode + 1)); + + // add new point + pPoints.push_back(PointOfField(coo[0], coo[1], coo[2], val[0])); + } + } + else + { + //------------------------------------------------------------- + // Case 2: field of elements + //------------------------------------------------------------- + + if (mElements == NULL) throw IllegalStateException("no elements in the current mesh", __FILE__, __LINE__); + if (mElements->getTypeOfPrimitives() != MED_TETRA10) throw UnsupportedOperationException("only support TETRA10 mesh", __FILE__, __LINE__); + + const string& nameGaussLoc = pField->getNameGaussLoc(pTimeStepIt); + GaussLoc* gaussLoc = getGaussLocByName(nameGaussLoc.c_str()); + if (gaussLoc == NULL) throw IllegalStateException("no Gauss localization for these elements", __FILE__, __LINE__); + + int numGauss = pField->getNumberOfGaussPointsByElement(pTimeStepIt); + + int size = gaussLoc->getDim() * gaussLoc->getNumGaussPoints(); + med_float* cooGaussPts = new med_float[size]; + + int dim = mElements->getTypeOfPrimitives() / 100; + int numNodes = mElements->getTypeOfPrimitives() % 100; + size = dim * numNodes; + med_float* cooNodes = new med_float[size]; + + // for each elements + for (int itElt = 0, size = mElements->getNumberOfElements() ; itElt < size ; itElt++) + { + // get coordinates of nodes of the current elements + // OPTIMIZATION: ASSUME TETRA10: ONLY GETS THE 4 FIRST NODES OF EACH ELEMENT + mElements->getCoordinates(itElt, mNodes, cooNodes, 4); + + // compute coordinates of gauss points + gaussLoc->getCoordGaussPoints(cooNodes, cooGaussPts); + + //printArray2D(cooGaussPts, 5, 3, "Gauss pt"); + + const med_float* val = + reinterpret_cast(pField->getValue(pTimeStepIt, itElt + 1)); + + // for each point of Gauss of the element + med_float* srcCoo = cooGaussPts; + for (int itPtGauss = 0 ; itPtGauss < numGauss ; itPtGauss++) + { + pPoints.push_back(PointOfField(srcCoo[0], srcCoo[1], srcCoo[2], val[itPtGauss])); + srcCoo += 3; + } + } + + delete[] cooNodes; + delete[] cooGaussPts; + } +} + + +float Mesh::evalDefaultRadius(int pN) const +{ + if (mFields.size() == 0) return 1.0f; + + //--------------------------------------------------------------------- + // Compute default radius + //--------------------------------------------------------------------- + + med_float volumeBBox = + (mMeshBBoxMax[0] - mMeshBBoxMin[0]) * + (mMeshBBoxMax[1] - mMeshBBoxMin[1]) * + (mMeshBBoxMax[2] - mMeshBBoxMin[2]); + + if (isnan(volumeBBox)) + { + return 1.0f; + } + + const med_float k = 0.8; // considered 80% of the volume + + // get nunmber of gauss points in the field + try + { + Field* anyField = mFields[mFields.size()-1]; + int numTimeSteps = anyField->getNumberOfTimeSteps(); + + int numGaussPoints = getNumberOfElements() * anyField->getNumberOfGaussPointsByElement(numTimeSteps-1); + + med_float radius = med_float(pow( (3.0/4.0) * pN * k * volumeBBox / (3.1415 * numGaussPoints), 1.0/3.0)); + + return float(radius); + } + catch (...) + { + return 1.0f; + } +} + + +med_geometrie_element CELL_TYPES[MED_NBR_GEOMETRIE_MAILLE] = +{ + MED_POINT1, + MED_SEG2, + MED_SEG3, + MED_TRIA3, + MED_TRIA6, + MED_QUAD4, + MED_QUAD8, + MED_TETRA4, + MED_TETRA10, + MED_HEXA8, + MED_HEXA20, + MED_PENTA6, + MED_PENTA15 +}; + + +char CELL_NAMES[MED_NBR_GEOMETRIE_MAILLE][MED_TAILLE_NOM + 1] = +{ + "MED_POINT1", + "MED_SEG2", + "MED_SEG3", + "MED_TRIA3", + "MED_TRIA6", + "MED_QUAD4", + "MED_QUAD8", + "MED_TETRA4", + "MED_TETRA10", + "MED_HEXA8", + "MED_HEXA20", + "MED_PENTA6", + "MED_PENTA15", + "MED_PYRA5", + "MED_PYRA13" +}; + + +void Mesh::readSequentialMED(const char* pMEDfilename, const char* pMeshName) +{ + reset(); + + //--------------------------------------------------------------------- + // Check arguments + //--------------------------------------------------------------------- + MULTIPR_LOG("Check arguments: "); + if (pMEDfilename == NULL) throw NullArgumentException("pMEDfilename should not be NULL", __FILE__, __LINE__); + if (pMeshName == NULL) throw NullArgumentException("pMeshName should not be NULL", __FILE__, __LINE__); + MULTIPR_LOG("OK\n"); + + strncpy(mMEDfilename, pMEDfilename, 256); + strncpy(mMeshName, pMeshName, MED_TAILLE_NOM); + + //--------------------------------------------------------------------- + // Open MED file (READ_ONLY) + //--------------------------------------------------------------------- + MULTIPR_LOG("Open MED file: "); + mMEDfile = MEDouvrir(mMEDfilename, MED_LECTURE); // open MED file for reading + if (mMEDfile <= 0) throw FileNotFoundException("MED file not found", __FILE__, __LINE__); + MULTIPR_LOG("OK\n"); + + //--------------------------------------------------------------------- + // Check valid HDF format + //--------------------------------------------------------------------- + MULTIPR_LOG("Format HDF: "); + if (MEDformatConforme(mMEDfilename) != 0) throw IOException("invalid file", __FILE__, __LINE__); + MULTIPR_LOG("OK\n"); + + //--------------------------------------------------------------------- + // Get MED version + //--------------------------------------------------------------------- + MULTIPR_LOG("MED version: "); + med_int verMajor, verMinor, verRelease; + med_err ret = MEDversionLire(mMEDfile, &verMajor, &verMinor, &verRelease); + if (ret != 0) throw IOException("error while reading MED version", __FILE__, __LINE__); + MULTIPR_LOG(verMajor << "." << verMinor << "." << verRelease << ": OK\n"); + + //--------------------------------------------------------------------- + // Check that there is no profil + //--------------------------------------------------------------------- + MULTIPR_LOG("#profils must be 0: "); + med_int nbProfils = MEDnProfil(mMEDfile); + if (nbProfils != 0) throw UnsupportedOperationException("not yet implemented", __FILE__, __LINE__); + MULTIPR_LOG("OK\n"); + + //--------------------------------------------------------------------- + // Read all Gauss localizations + //--------------------------------------------------------------------- + readGaussLoc(); + + //--------------------------------------------------------------------- + // Read scalars (should be 0) + //--------------------------------------------------------------------- + MULTIPR_LOG("Scalars: "); + med_int nbScalars = MEDnScalaire(mMEDfile); + if (nbScalars != 0) throw UnsupportedOperationException("not yet implemented", __FILE__, __LINE__); + MULTIPR_LOG(nbScalars << ": OK\n"); + + //--------------------------------------------------------------------- + // Find the mesh + //--------------------------------------------------------------------- + // read number of meshes + MULTIPR_LOG("Num meshes: "); + med_int nbMeshes = MEDnMaa(mMEDfile); + if (nbMeshes <= 0) throw IOException("i/o error while reading number of meshes in MED file", __FILE__, __LINE__); + MULTIPR_LOG(nbMeshes << ": OK\n"); + + med_int meshIndex = -1; + // iteration over mesh to find the mesh we want + // for each mesh in the file (warning: first mesh is number 1) + for (int itMesh = 1 ; itMesh <= nbMeshes ; itMesh++) + { + char meshName[MED_TAILLE_NOM + 1]; + + ret = MEDmaaInfo( + mMEDfile, + itMesh, + meshName, + &mMeshDim, + &mMeshType, + mMeshDesc); + + if (ret != 0) throw IOException("i/o error while reading mesh information in MED file", __FILE__, __LINE__); + MULTIPR_LOG("Mesh: |" << meshName << "|"); + + // test if the current mesh is the mesh we want + if (strcmp(pMeshName, meshName) == 0) + { + // *** mesh found *** + MULTIPR_LOG(" OK (found)\n"); + meshIndex = itMesh; + break; + } + else + { + // not the mesh we want: skip this mesh + MULTIPR_LOG(" skipped\n"); + } + } + + if (meshIndex == -1) + { + throw IllegalStateException("mesh not found in the given MED file", __FILE__, __LINE__); + } + + //--------------------------------------------------------------------- + // Check mesh validity + //--------------------------------------------------------------------- + // dimension of the mesh must be 3 (= 3D mesh) + MULTIPR_LOG("Mesh is 3D: "); + if (mMeshDim != 3) throw UnsupportedOperationException("dimension of the mesh should be 3; other dimension not yet implemented", __FILE__, __LINE__); + MULTIPR_LOG("OK\n"); + + // mesh must not be a grid + MULTIPR_LOG("Mesh is not a grid: "); + if (mMeshType != MED_NON_STRUCTURE) + throw UnsupportedOperationException("grid not supported", __FILE__, __LINE__); + MULTIPR_LOG("OK\n"); + + // mesh must only contain TETRA10 elements + MULTIPR_LOG("Only TETRA10: "); + med_connectivite connectivite = MED_NOD; // NODAL CONNECTIVITY ONLY + bool onlyTETRA10 = true; + int numTetra10 = -1; + for (int itCell = 0 ; itCell < MED_NBR_GEOMETRIE_MAILLE ; itCell++) + { + med_int meshNumCells = MEDnEntMaa( + mMEDfile, + mMeshName, + MED_CONN, + MED_MAILLE, + CELL_TYPES[itCell], + connectivite); + + if ((meshNumCells > 0) && (strcmp(CELL_NAMES[itCell], "MED_TETRA10") != 0)) + { + onlyTETRA10 = false; + break; + } + if (strcmp(CELL_NAMES[itCell], "MED_TETRA10") == 0) + { + numTetra10 = meshNumCells; + } + } + + if (!onlyTETRA10) throw UnsupportedOperationException("mesh should only contain TETRA10 elements", __FILE__, __LINE__); + MULTIPR_LOG(numTetra10 << ": OK\n"); + + // everything is OK... + + //--------------------------------------------------------------------- + // Check num joint = 0 + //--------------------------------------------------------------------- + MULTIPR_LOG("Num joints: "); + med_int numJoints = MEDnJoint(mMEDfile, mMeshName); + MULTIPR_LOG(numJoints << ": OK\n"); + + //--------------------------------------------------------------------- + // Check num equivalence = 0 + //--------------------------------------------------------------------- + MULTIPR_LOG("Num equivalences: "); + med_int numEquiv = MEDnEquiv(mMEDfile, mMeshName); + MULTIPR_LOG(numEquiv << ": OK\n"); + + //--------------------------------------------------------------------- + // Read nodes + //--------------------------------------------------------------------- + mNodes = new Nodes(); + mNodes->readMED(mMEDfile, mMeshName, mMeshDim); + mNodes->getBBox(mMeshBBoxMin, mMeshBBoxMax); + + //--------------------------------------------------------------------- + // Read elements + //--------------------------------------------------------------------- + mElements = new Elements(); + mElements->readMED(mMEDfile, mMeshName, mMeshDim, MED_MAILLE, MED_TETRA10); + + //--------------------------------------------------------------------- + // Read families + //--------------------------------------------------------------------- + readFamilies(); + finalizeFamiliesAndGroups(); + + //--------------------------------------------------------------------- + // Read fields + //--------------------------------------------------------------------- + readFields(); + + //--------------------------------------------------------------------- + // Close the MED file + //--------------------------------------------------------------------- + MULTIPR_LOG("Close MED file: "); + ret = MEDfermer(mMEDfile); + if (ret != 0) throw IOException("i/o error while closing MED file", __FILE__, __LINE__); + MULTIPR_LOG("OK\n"); +} + + +void Mesh::writeMED(const char* pMEDfilename) +{ + MULTIPR_LOG("Write MED: " << pMEDfilename << endl); + + if (pMEDfilename == NULL) throw NullArgumentException("pMEDfilename should not be NULL", __FILE__, __LINE__); + if (strlen(pMEDfilename) == 0) throw IllegalArgumentException("pMEDfilename size is 0", __FILE__, __LINE__); + + remove(pMEDfilename); + + //--------------------------------------------------------------------- + // Create the new MED file (WRITE_ONLY) + //--------------------------------------------------------------------- + med_idt newMEDfile = MEDouvrir(const_cast(pMEDfilename), MED_CREATION); + if (newMEDfile == -1) throw IOException("", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Write scalars + //--------------------------------------------------------------------- + // no scalars to write + + //--------------------------------------------------------------------- + // Create mesh: must be created first + //--------------------------------------------------------------------- + med_err ret = MEDmaaCr( + newMEDfile, + mMeshName, + mMeshDim, + MED_NON_STRUCTURE, + mMeshDesc); + + if (ret != 0) throw IOException("", __FILE__, __LINE__); + MULTIPR_LOG(" Create mesh: |" << mMeshName << "|: OK" << endl); + + //--------------------------------------------------------------------- + // Write nodes and elements (mesh must exist) + //--------------------------------------------------------------------- + mNodes->writeMED(newMEDfile, mMeshName); + MULTIPR_LOG(" Write nodes: ok" << endl); + mElements->writeMED(newMEDfile, mMeshName, mMeshDim); + MULTIPR_LOG(" write elt: ok" << endl); + + //--------------------------------------------------------------------- + // Write families (mesh must exist) + //--------------------------------------------------------------------- + for (unsigned itFam = 0 ; itFam < mFamilies.size() ; itFam++) + { + Family* fam = mFamilies[itFam]; + fam->writeMED(newMEDfile, mMeshName); + } + MULTIPR_LOG(" Write families: ok" << endl); + + //--------------------------------------------------------------------- + // Write profil + //--------------------------------------------------------------------- + // no profil + + //--------------------------------------------------------------------- + // Write Gauss localization (must be written before fields) + //--------------------------------------------------------------------- + for (unsigned itGaussLoc = 0 ; itGaussLoc < mGaussLoc.size() ; itGaussLoc++) + { + + GaussLoc* gaussLoc = mGaussLoc[itGaussLoc]; + gaussLoc->writeMED(newMEDfile); + } + MULTIPR_LOG(" Write Gauss: ok" << endl); + + //--------------------------------------------------------------------- + // Write fields + //--------------------------------------------------------------------- + for (unsigned itField = 0 ; itField < mFields.size() ; itField++) + { + Field* field = mFields[itField]; + field->writeMED(newMEDfile, mMeshName); + } + MULTIPR_LOG(" Write fields: ok" << endl); + + //--------------------------------------------------------------------- + // Close the new MED file + //--------------------------------------------------------------------- + ret = MEDfermer(newMEDfile); + if (ret != 0) throw IOException("", __FILE__, __LINE__); +} + + +void Mesh::readGaussLoc() +{ + MULTIPR_LOG("Gauss ref: "); + med_int numGauss = MEDnGauss(mMEDfile); + if (numGauss < 0) throw IOException("", __FILE__, __LINE__); + MULTIPR_LOG(numGauss << ": OK\n"); + + for (int itGauss = 1 ; itGauss <= numGauss ; itGauss++) + { + GaussLoc* gaussLoc = new GaussLoc(); + gaussLoc->readMED(mMEDfile, itGauss); + + MULTIPR_LOG((*gaussLoc) << endl); + + mGaussLoc.push_back(gaussLoc); + mGaussLocNameToGaussLoc.insert(make_pair(gaussLoc->getName(), gaussLoc)); + } +} + + +void Mesh::readFamilies() +{ + med_int numFamilies = MEDnFam(mMEDfile, mMeshName); + if (numFamilies <= 0) throw IOException("", __FILE__, __LINE__); + + for (int itFam = 1 ; itFam <= numFamilies ; itFam++) + { + Family* fam = new Family(); + fam->readMED(mMEDfile, mMeshName, itFam); + mFamilies.push_back(fam); + } +} + + +void Mesh::finalizeFamiliesAndGroups() +{ + //--------------------------------------------------------------------- + // Build mapping between family id and pointers towards families + //--------------------------------------------------------------------- + for (unsigned itFam = 0 ; itFam < mFamilies.size() ; itFam++) + { + Family* fam = mFamilies[itFam]; + mFamIdToFam.insert(make_pair(fam->getId(), fam)); + } + + //--------------------------------------------------------------------- + // Fill families of nodes + //--------------------------------------------------------------------- + for (int itNode = 1 ; itNode <= mNodes->getNumberOfNodes() ; itNode++) + { + // get family of the ith nodes + int famIdent = mNodes->getFamIdent(itNode - 1); // MED nodes start at 1 + map::iterator itFam = mFamIdToFam.find(famIdent); + + if (itFam == mFamIdToFam.end()) throw IllegalStateException("", __FILE__, __LINE__); + + Family* fam = (*itFam).second; + + // insert the current node to its family + fam->insertElt(itNode); + fam->setIsFamilyOfNodes(true); + } + + //--------------------------------------------------------------------- + // Fill families of elements + //--------------------------------------------------------------------- + for (int itElt = 1 ; itElt <= mElements->getNumberOfElements() ; itElt++) + { + // get family of the ith element (MED index start at 1) + int famIdent = mElements->getFamilyIdentifier(itElt - 1); + map::iterator itFam = mFamIdToFam.find(famIdent); + + if (itFam == mFamIdToFam.end()) throw IllegalStateException("", __FILE__, __LINE__); + + Family* fam = (*itFam).second; + + // insert the current node its family + fam->insertElt(itElt); + fam->setIsFamilyOfNodes(false); + } + + //--------------------------------------------------------------------- + // Build groups + //--------------------------------------------------------------------- + // for each family + for (unsigned itFam = 0 ; itFam < mFamilies.size() ; itFam++) + { + mFamilies[itFam]->buildGroups(mGroups, mGroupNameToGroup); + } +} + + +void Mesh::readFields() +{ + //--------------------------------------------------------------------- + // Read number of fields + //--------------------------------------------------------------------- + MULTIPR_LOG("Read fields: "); + med_int numFields = MEDnChamp(mMEDfile, 0); + if (numFields <= 0) throw IOException("", __FILE__, __LINE__); + MULTIPR_LOG(numFields << ": OK\n"); + + //--------------------------------------------------------------------- + // Iterate over fields + //--------------------------------------------------------------------- + // for each field, read number of components and others infos + for (int itField = 1 ; itField <= numFields ; itField++) + { + Field* field = new Field(); + field->readMED(mMEDfile, itField, mMeshName); + + // if the nth field does not apply on our mesh => slip it + if (field->isEmpty()) + { + delete field; + } + else + { + mFields.push_back(field); + } + } +} + + +ostream& operator<<(ostream& pOs, Mesh& pM) +{ + pOs << "Mesh: " << endl; + pOs << " MED file =|" << pM.mMEDfilename << "|" << endl; + pOs << " Name =|" << pM.mMeshName << "|" << endl; + pOs << " Unv name =|" << pM.mMeshUName << "|" << endl; + pOs << " Desc =|" << pM.mMeshDesc << "|" << endl; + pOs << " Dim =" << pM.mMeshDim << endl; + pOs << " Type =" << ((pM.mMeshType == MED_STRUCTURE)?"STRUCTURE":"NON_STRUCTURE") << endl; + pOs << " BBox =[" << pM.mMeshBBoxMin[0] << " ; " << pM.mMeshBBoxMax[0] << "] x [" << pM.mMeshBBoxMin[1] << " ; " << pM.mMeshBBoxMax[1] << "] x [" << pM.mMeshBBoxMin[2] << " ; " << pM.mMeshBBoxMax[2] << "]" << endl; + + if (pM.mFlagPrintAll) + { + cout << (*(pM.mNodes)) << endl; + cout << (*(pM.mElements)) << endl; + + pOs << " Families : #=" << pM.mFamilies.size() << endl; + for (unsigned i = 0 ; i < pM.mFamilies.size() ; i++) + { + cout << (*(pM.mFamilies[i])) << endl; + } + + pOs << " Groups : #=" << pM.mGroups.size() << endl; + for (unsigned i = 0 ; i < pM.mGroups.size() ; i++) + { + cout << (*(pM.mGroups[i])) << endl; + } + + pOs << " Gauss loc: #=" << pM.mGaussLoc.size() << endl; + for (unsigned i = 0 ; i < pM.mGaussLoc.size() ; i++) + { + cout << (*(pM.mGaussLoc[i])) << endl; + } + + pOs << " Fields : #=" << pM.mFields.size() << endl; + for (unsigned i = 0 ; i < pM.mFields.size() ; i++) + { + cout << (*(pM.mFields[i])) << endl; + } + } + else + { + pOs << " Nodes : #=" << pM.mNodes->getNumberOfNodes() << endl; + + const set& setOfNodes = pM.mElements->getSetOfNodes(); + if (setOfNodes.size() == 0) + { + pOs << " Elt : #=" << pM.mElements->getNumberOfElements() << endl; + } + else + { + set::iterator itNode = setOfNodes.end(); + itNode--; + pOs << " Elt : #=" << pM.mElements->getNumberOfElements() << " node_id_min=" << (*(setOfNodes.begin())) << " node_id_max=" << (*itNode) << endl; + } + + pOs << " Families : #=" << pM.mFamilies.size() << endl; + pOs << " Groups : #=" << pM.mGroups.size() << endl; + pOs << " Gauss loc: #=" << pM.mGaussLoc.size() << endl; + pOs << " Fields : #=" << pM.mFields.size() << endl; + } + + return pOs; +} + + +} // namespace multipr + +// EOF diff --git a/src/MULTIPR/MULTIPR_Mesh.hxx b/src/MULTIPR/MULTIPR_Mesh.hxx new file mode 100644 index 0000000..d72bd8b --- /dev/null +++ b/src/MULTIPR/MULTIPR_Mesh.hxx @@ -0,0 +1,378 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Mesh.hxx + * + * \brief Class Mesh used by the MULTIPR API; used to wrap MED file meshes. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_MESH_HXX +#define MULTIPR_MESH_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + +extern "C" +{ + #include "med.h" +} + +#include +#include +#include +#include +#include +#include + + +namespace multipr +{ + +//***************************************************************************** +// Pre-declaration +//***************************************************************************** + +class GaussLoc; +class Profil; +class Nodes; +class Elements; +class Family; +class Field; +class Group; +class MeshDis; +class PointOfField; + + +//***************************************************************************** +// Class Mesh +//***************************************************************************** + +/** + * Assumes: + * - 3D mesh in a 3D space + * - Unstructured mesh (not a grid) + * - Nodal connectivity + * - Cartesian coordinates system + * Always use FULL_INTERLACE arrays + */ +class Mesh +{ +public: + + /** + * Builds an empty Mesh (default constructor). + */ + Mesh(); + + /** + * Destructor. Removes everything. + */ + ~Mesh(); + + /** + * Resets this object in its state by default (empty). Cleans memory. + */ + void reset(); + + //--------------------------------------------------------------------- + // Basic accessors/mutators + //--------------------------------------------------------------------- + + /** + * Returns the name of this Mesh. + * \return the name of this Mesh. + */ + const char* getName() const { return mMeshName; } + + /** + * Returns the name of all the fields. + * \return the name of all the fields. + */ + std::vector getNameFields() const; + + /** + * Returns the number of iteration for a given field. + * \return the number of iteration for a given field. + */ + int getTimeStamps(const char* pFieldName) const; + + /** + * Returns a Field from its name; NULL if it does not exist. + * \param pFieldName name of the field to be retrieved. + * \return the Field pFieldName of it exists, NULL otherwise. + * \throw NullArgumentException if pFieldName is NULL. + */ + Field* getFieldByName(const char* pFieldName) const; + + /** + * Returns a GaussLoc from its name; NULL if it does not exist. + * \param pGaussLocName name of the GaussLoc to be retrieved. + * \return the GaussLoc pGaussLocName if it exists, NULL otherwise. + * \throw NullArgumentException if pGaussLocName is NULL. + */ + GaussLoc* getGaussLocByName(const char* pGaussLocName) const; + + /** + * Returns true iff the given 3D-point is in the bounding box of this Mesh. + * \param pX + * \param pY + * \param pZ + * \return true iff the given 3D-point is in the bounding box of this Mesh. + */ + bool isInBBox(med_float pX, med_float pY, med_float pZ) const + { + return ((pX >= mMeshBBoxMin[0]) && (pX <= mMeshBBoxMax[0]) && + (pY >= mMeshBBoxMin[1]) && (pY <= mMeshBBoxMax[1]) && + (pZ >= mMeshBBoxMin[2]) && (pZ <= mMeshBBoxMax[2])); + } + + /** + * Returns the number of elements. + * \return the number of elements. + */ + int getNumberOfElements() const; + + //--------------------------------------------------------------------- + // Algorithms + //--------------------------------------------------------------------- + + /** + * Creates a Mesh from a subset of its elements (cells). + * \param pSetOfElements subset of elements to keep. + * \param pNewMeshName name of the new Mesh. + * \return a new Mesh which is a restriction of this Mesh to the given set of elements. + * \throw NullArgumentException if pNewMeshName is NULL. + */ + Mesh* createFromSetOfElements(const std::set& pSetOfElements, const char* pNewMeshName); + + /** + * Creates a Mesh from one of its group. + * \param pGroup any group of this Mesh. + * \param pNewMeshName name of the new Mesh. + * \return a new Mesh which is a restriction of this Mesh to pGroup. + * \throw NullArgumentException if pGroup or pNewMeshName is NULL. + */ + Mesh* createFromGroup(const Group* pGroup, const char* pNewMeshName); + + /** + * Creates a distributed mesh (MeshDis) by creating a new mesh for each group of elements in this Mesh. + * \return a distributed mesh from groups of this Mesh. + */ + MeshDis* splitGroupsOfElements(); + + /** + * Creates a new mesh by decimating this one. + * \param pFilterName name of the filter to be used for decimation (e.g. Filtre_GradientMoyen); should not be NULL. + * \param pArgv all the arguments for filtering as a single string. + * \param pNameNewMesh name of the new mesh. + * \return the decimated mesh. + * \throw NullArgumentException if one of the arguments is NULL. + * \throw RuntimeException if any error occurs while decimating data. + */ + Mesh* decimate( + const char* pFilterName, + const char* pArgv, + const char* pNameNewMesh); + + /** + * Gets all the points in a field. Each point has coordinates and a value. + * \param pField any field of this Mesh. + * \param pTimeStepIt time step iteration. + * \param pPoints (out) list of points. + * \throw NullArgumentException if pField is NULL. + * \throw IllegalArgumentException if pTimeStepIt is invalid. + */ + void getAllPointsOfField(Field* pField, int pTimeStepIt, std::vector& pPoints); + + /** + * Returns a default value for neighborhood radius. + * Return value is such that, for any point in the field, average number of neighbours is pN. + * \param pN average number of neighbours. + * \return a default value for neighborhood radius; 1.0 if some error occurs. + */ + float evalDefaultRadius(int pN) const; + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Reads a Mesh from a sequential MED file. Resets the object before. + * \param pMEDfilename + * \param pMeshName + * \throw IOException if any i/o error occurs. + */ + void readSequentialMED(const char* pMEDfilename, const char* pMeshName); + + /** + * Writes this Mesh and all related things into a MED file. + * \param pMEDfilename + * \throw IOException if any i/o error occurs. + */ + void writeMED(const char* pMEDfilename); + + /** + * Sets the flag which control the stream operator <<. + * \param pFlag new flag value. + */ + void setPrintAll(bool pFlag) { mFlagPrintAll = pFlag; } + + /** + * Dumps any Mesh to the given output stream. + * \param pOs any output stream. + * \param pM any Mesh. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, Mesh& pM); + +private: + + /** + * Reads all Gauss localizations in the current MED file. + * \throw IOException if an i/o error occurs. + */ + void readGaussLoc(); + + /** + * Reads families in the currentMED file and build groups. + * \throw IOException if an i/o error occurs. + */ + void readFamilies(); + + /** + * Finalizes the constructions of families and groups. + * Fill structures with elements. + */ + void finalizeFamiliesAndGroups(); + + /** + * Reads fields related to this mesh in the current MED file. + * \throw IOException if an i/o error occurs. + */ + void readFields(); + +private: + + /** + * Name of the associated MED file. + */ + char mMEDfilename[256]; + + /** + * MED file handle. + */ + med_idt mMEDfile; + + /** + * Name of this mesh. + */ + char mMeshName[MED_TAILLE_NOM + 1]; + + /** + * Universal name of this mesh. + */ + char mMeshUName[MED_TAILLE_DESC + 1]; + + /** + * Description. + */ + char mMeshDesc[MED_TAILLE_DESC + 1]; + + /** + * Dimension. + */ + med_int mMeshDim; + + /** + * Type of mesh (MED_NON_STRUCTURE or MED_STRUCTURE (=grid)) + */ + med_maillage mMeshType; + + /** + * Axis aligned bounding box of this mesh. + */ + med_float mMeshBBoxMin[3]; + med_float mMeshBBoxMax[3]; + + /** + * All the nodes used by this mesh. + */ + Nodes* mNodes; + + /** + * All the TETRA10 elements used by this mesh. + */ + Elements* mElements; + + /** + * Table of families used by this mesh. + */ + std::vector mFamilies; + + /** + * Map to retrieve a Family from its name. + */ + std::map mFamIdToFam; + + /** + * Table of groups used by this mesh. + */ + std::vector mGroups; + + /** + * Map to retrieve a Group from its name. + */ + std::map mGroupNameToGroup; + + /** + * Table of GaussLoc. + */ + std::vector mGaussLoc; + + /** + * Map to retrieve a Gauss info from its name. + */ + std::map mGaussLocNameToGaussLoc; + + /** + * Table of fields related to this mesh. + * Number of fiels = mFields.size(). + */ + std::vector mFields; + + /** + * Table of profils. + */ + std::vector mProfils; + + /** + * Flag to control the behaviour of the stream operator <<. + */ + bool mFlagPrintAll; + +private: + + // do not allow copy constructor + Mesh(const Mesh&); + + // do not allow copy + Mesh& operator=(const Mesh&); + + // do not allow operator == + bool operator==(const Mesh&); + +}; // class Mesh + + +} // namespace MULTIPR + + +#endif // MULTIPR_MESH_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_MeshDis.cxx b/src/MULTIPR/MULTIPR_MeshDis.cxx new file mode 100644 index 0000000..3a856f3 --- /dev/null +++ b/src/MULTIPR/MULTIPR_MeshDis.cxx @@ -0,0 +1,893 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_MeshDis.cxx + * + * \brief see MULTIPR_MeshDis.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_MeshDis.hxx" +#include "MULTIPR_Mesh.hxx" +#include "MULTIPR_Utils.hxx" +#include "MULTIPR_Globals.hxx" +#include "MULTIPR_API.hxx" +#include "MULTIPR_Exceptions.hxx" +#include "MULTIPR_ProgressCallback.hxx" + +#include "MEDSPLITTER_API.hxx" + +#include +#include + +using namespace std; + + +namespace multipr +{ + + +//***************************************************************************** +// Global variables (exported) +//***************************************************************************** + +MULTIPR_ProgressCallback* gProgressCallback = NULL; + + +//***************************************************************************** +// Class MeshDisEntry implementation +//***************************************************************************** + +MeshDisPart::MeshDisPart() +{ + mMesh = NULL; + mCollection = NULL; + mOldCollection = NULL; + + reset(); +} + + +MeshDisPart::~MeshDisPart() +{ + reset(); +} + + +void MeshDisPart::reset() +{ + mToDoOnNextWrite = MULTIPR_UNDEFINED; + + mMeshName[0] = '\0'; + mId = 0; + mPartName[0] = '\0'; + mPath[0] = '\0'; + mMEDFileName[0] = '\0'; + + if (mMesh != NULL) + { + delete mMesh; + mMesh = NULL; + } + + mSplit = 0; + + if (mCollection != NULL) + { + delete mCollection; + mCollection = NULL; + } + + if (mOldCollection != NULL) + { + delete mOldCollection; + mOldCollection = NULL; + } +} + + +const char* MeshDisPart::getMEDFileNameSuffix() const +{ + // "agregat100grains_12pas_grain97.med" -> "grain97" + // "agregat100grains_12pas_grain100_part2.med" -> "grain100_part2" + // "aagregat100grains_12pas_grain98_gradmoy-low-25.0-0.3.med" -> "grain98_gradmoy-low-25-0.3" + + string prefix = removeExtension(mMEDFileName, ".med"); + prefix.erase(0, prefix.rfind("grain")); + return prefix.c_str(); +} + + +void MeshDisPart::create( + OnNextWrite pToDoOnNextWrite, + const char* pMeshName, + int pId, + const char* pPartName, + const char* pPath, + const char* pMEDFileName, + Mesh* pMesh) +{ + if (pToDoOnNextWrite == MULTIPR_UNDEFINED) throw IllegalArgumentException("", __FILE__, __LINE__); + if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (pId < 1) throw IllegalArgumentException("", __FILE__, __LINE__); + if (pPartName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (pPath == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (pMEDFileName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + + reset(); + + mToDoOnNextWrite = pToDoOnNextWrite; + strcpy(mMeshName, pMeshName); + mId = pId; + strcpy(mPartName, pPartName); + strcpy(mPath, pPath); + strcpy(mMEDFileName, pMEDFileName); + mMesh = pMesh; + +} + + +void MeshDisPart::readMED() +{ + if (mMesh != NULL) throw IllegalStateException("", __FILE__, __LINE__); + if (mCollection != NULL) throw IllegalStateException("", __FILE__, __LINE__); + if (mOldCollection != NULL) throw IllegalStateException("", __FILE__, __LINE__); + + //cout << "read MED : mesh=" << mMEDfilename << endl; + + mMesh = new Mesh(); + mMesh->readSequentialMED(mMEDFileName, mMeshName); +} + + +ostream& operator<<(ostream& pOs, MeshDisPart& pM) +{ + switch (pM.mToDoOnNextWrite) + { + case MeshDisPart::MULTIPR_UNDEFINED: + pOs << "undefined"; + break; + + case MeshDisPart::MULTIPR_KEEP_AS_IT: + pOs << pM.mMeshName << " " << pM.mId << " " << pM.mPartName << " " << pM.mPath << " " << pM.mMEDFileName; + break; + + case MeshDisPart::MULTIPR_WRITE_MESH: + pOs << pM.mMeshName << " " << pM.mId << " " << pM.mPartName << " " << pM.mPath << " " << pM.mMEDFileName; + break; + + case MeshDisPart::MULTIPR_WRITE_PARTS: + pOs << pM.mMeshName << " " << pM.mId << " " << pM.mPartName << " " << pM.mPath << " " << pM.mMEDFileName << " SPLIT " << pM.mSplit; + break; + + default: throw IllegalStateException("", __FILE__, __LINE__); + } + + return pOs; +} + + +//***************************************************************************** +// Class MeshDis implementation +//***************************************************************************** + +MeshDis::MeshDis() +{ + reset(); +} + + +MeshDis::~MeshDis() +{ + reset(); +} + + +void MeshDis::reset() +{ + mMEDfilename[0] = '\0'; + + for (unsigned itPart = 0 ; itPart != mParts.size() ; itPart++) + { + MeshDisPart* part = mParts[itPart]; + delete part; + } + mParts.clear(); + + //mProgressCallback = NULL; +} + + +void MeshDis::addMesh( + MeshDisPart::OnNextWrite pToDoOnNextWrite, + const char* pMeshName, + int pId, + const char* pPartName, + const char* pPath, + const char* pMEDFileName, + Mesh* pMesh) +{ + MeshDisPart* part = new MeshDisPart(); + + part->create( + pToDoOnNextWrite, + pMeshName, + pId, + pPartName, + pPath, + pMEDFileName, + pMesh); + + mParts.push_back(part); +} + + +void MeshDis::insertMesh( + MeshDisPart::OnNextWrite pToDoOnNextWrite, + const char* pMeshName, + int pId, + const char* pPartName, + const char* pPath, + const char* pMEDFileName, + Mesh* pMesh, + int pPosition) +{ + MeshDisPart* part = new MeshDisPart(); + + part->create( + pToDoOnNextWrite, + pMeshName, + pId, + pPartName, + pPath, + pMEDFileName, + pMesh); + + mParts.insert(mParts.begin() + pPosition, part); + + // rename id of following parts + for (unsigned i = pPosition + 1 ; i < mParts.size() ; i++) + { + mParts[i]->mId = i + 1; + } +} + + +MeshDisPart* MeshDis::findPart(const char* pPartName) +{ + if (pPartName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + + MeshDisPart* part = NULL; + + for (unsigned itPart = 0 ; itPart < mParts.size() ; itPart++) + { + MeshDisPart* currentPart = mParts[itPart]; + + if (strcmp(currentPart->getPartName(), pPartName) == 0) + { + part = currentPart; + break; + } + } + + return part; + +} + + +vector MeshDis::getMeshes() const +{ + vector res; + + if (mParts.size() > 0) + { + MeshDisPart* part = mParts[0]; + const char* meshName = part->getMeshName(); + res.push_back(meshName); + } + + return res; +} + + +vector MeshDis::getFields() const +{ + vector res; + + if (mParts.size() == 0) + { + return res; + } + + // all the parts of the distributed MED file should have the same fields + // => just return the name of fields of the first part + switch (mParts[0]->mToDoOnNextWrite) + { + case MeshDisPart::MULTIPR_KEEP_AS_IT: + case MeshDisPart::MULTIPR_WRITE_PARTS: + { + vector > tmp = multipr::getListFields(mParts[0]->getMEDFileName()); + + for (int i = 0 ; i < tmp.size() ; i++) + { + res.push_back(tmp[i].first); + } + return res; + } + + case MeshDisPart::MULTIPR_WRITE_MESH: + return mParts[0]->mMesh->getNameFields(); + + default: + throw IllegalStateException("", __FILE__, __LINE__); + } +} + + +int MeshDis::getTimeStamps(const char* pFieldName) const +{ + if (mParts.size() == 0) + { + // no parts in this distributed MED file => no fields => #iteration = 0 + return 0; + } + + // all the parts of the distributed MED file should have the same fields + // => just return the number of iteration found in the field of the first part + switch (mParts[0]->mToDoOnNextWrite) + { + case MeshDisPart::MULTIPR_KEEP_AS_IT: + case MeshDisPart::MULTIPR_WRITE_PARTS: + { + vector > tmp = multipr::getListFields(mParts[0]->getMEDFileName()); + + for (int i = 0 ; i < tmp.size() ; i++) + { + if (strcmp(tmp[i].first.c_str(), pFieldName) == 0) + { + return tmp[i].second; + } + } + + // pFieldName not found in the list of fields + return 0; + } + + case MeshDisPart::MULTIPR_WRITE_MESH: + return mParts[0]->mMesh->getTimeStamps(pFieldName); + + default: + throw IllegalStateException("", __FILE__, __LINE__); + } +} + + +string MeshDis::getPartInfo(const char* pPartName) +{ + MeshDisPart* part = findPart(pPartName); + + if (part != NULL) + { + char num[16]; + sprintf(num, "%d", part->mId); + + string res = + string(part->mMeshName) + + string(" ") + + string(num) + + string(" ") + + string(part->mPartName) + + string(" ") + + string(part->mPath) + + string(" ") + + string(part->mMEDFileName); + + return res; + } + else + { + // part not found => return empty string + return ""; + } +} + + +void MeshDis::splitPart(const char* pPartName, int pNbParts, int pPartitionner) +{ + if (pPartName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (pNbParts < 2) throw IllegalArgumentException("", __FILE__, __LINE__); + if ((pPartitionner != MULTIPR_METIS) && (pPartitionner != MULTIPR_SCOTCH)) throw IllegalArgumentException("should be 0=METIS or 1=SCOTCH", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Find the MED file corresponding to the given part + //--------------------------------------------------------------------- + MeshDisPart* part = findPart(pPartName); + + if (part == NULL) + { + throw IllegalArgumentException("part not found in this distributed MED file", __FILE__, __LINE__); + } + + //--------------------------------------------------------------------- + // Load the sequential MED file + //--------------------------------------------------------------------- + MEDSPLITTER::MESHCollection* collection; + collection = new MEDSPLITTER::MESHCollection(part->getMEDFileName(), part->getMeshName()); + + //--------------------------------------------------------------------- + // Partition the group + //--------------------------------------------------------------------- + MEDSPLITTER::Topology* topology; + if (pPartitionner == MULTIPR_METIS) + { + try + { + topology = collection->createPartition(pNbParts, MEDSPLITTER::Graph::METIS); + } + catch (...) + { + throw RuntimeException("MEDSPLITTER error: createPartition(), using METIS", __FILE__, __LINE__); + } + } + else if (pPartitionner == MULTIPR_SCOTCH) + { + try + { + topology = collection->createPartition(pNbParts, MEDSPLITTER::Graph::SCOTCH); + } + catch (...) + { + throw RuntimeException("MEDSPLITTER error: createPartition(), using SCOTCH", __FILE__, __LINE__); + } + } + else + { + throw IllegalStateException("unknown partitionner", __FILE__, __LINE__); + } + + try + { + MEDSPLITTER::MESHCollection* newCollection = new MEDSPLITTER::MESHCollection(*collection, topology); + + part->mToDoOnNextWrite = MeshDisPart::MULTIPR_WRITE_PARTS; + part->mSplit = pNbParts; + part->mOldCollection = collection; + part->mCollection = newCollection; + } + catch (...) + { + throw RuntimeException("MEDSPLITTER error: new MESHCollection()", __FILE__, __LINE__); + } +} + + +void MeshDis::decimatePart( + const char* pPartName, + const char* pFieldName, + med_int pFieldIt, + const char* pFilterName, + med_float pTMed, + med_float pTLow, + med_float pRadius, + int pBoxing) +{ + //--------------------------------------------------------------------- + // Check arguments + //--------------------------------------------------------------------- + if (pPartName == NULL) throw NullArgumentException("partname should not be NULL", __FILE__, __LINE__); + if (pFieldName == NULL) throw NullArgumentException("fieldname should not be NULL", __FILE__, __LINE__); + if (pFieldIt < med_int(1)) throw IllegalArgumentException("invalid field iteration; should be >= 1", __FILE__, __LINE__); + if (pTMed < 0.0) throw IllegalArgumentException("med res.: threshold must be > 0", __FILE__, __LINE__); + if (pTMed >= pTLow) throw IllegalArgumentException("threshold for med res. must be < threshold for low res.", __FILE__, __LINE__); + if (pRadius <= med_float(0.0)) throw IllegalArgumentException("radius should be > 0", __FILE__, __LINE__); + if ((pBoxing < 1) || (pBoxing > 200)) throw IllegalArgumentException("boxing should be in [1..200]", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Find the MED file corresponding to the given part + //--------------------------------------------------------------------- + MeshDisPart* part = findPart(pPartName); + if (part == NULL) + { + throw IllegalArgumentException("part not found in the given distributed MED file", __FILE__, __LINE__); + } + + //--------------------------------------------------------------------- + // Load the associated sequential MED file + //--------------------------------------------------------------------- + if (part->mMesh == NULL) + { + part->readMED(); + } + + Mesh* meshFull = part->mMesh; + cout << (*meshFull) << endl; + + const char* originalFilename = part->getMEDFileName(); + string strPrefix = removeExtension(originalFilename, ".med"); + + //--------------------------------------------------------------------- + // Decimates the given mesh + //--------------------------------------------------------------------- + // arguments for decimation are passed as a string for genericity + char argv[256]; + char newPartName[MED_TAILLE_NOM + 1]; + char newMEDFileName[256]; + + // *** create a new mesh = MEDIUM resolution *** + sprintf(argv, "%s %d %lf %lf %d", pFieldName, pFieldIt, pTMed, pRadius, pBoxing); + sprintf(newPartName, "%s_MED", pPartName); + sprintf(newMEDFileName, "%s_gradmoy-med-%s-%s.med", + strPrefix.c_str(), + realToString(pTMed).c_str(), + realToString(pRadius).c_str()); + + { + Mesh* meshMedium = meshFull->decimate(pFilterName, argv, part->getMeshName()); + cout << (*meshMedium) << endl; + + insertMesh( + MeshDisPart::MULTIPR_WRITE_MESH, + part->getMeshName(), + part->mId + 1, + newPartName, + "localhost", + newMEDFileName, + meshMedium, + part->mId + 0); + } + + // *** create a new mesh = LOW resolution *** + sprintf(argv, "%s %d %lf %lf %d", pFieldName, pFieldIt, pTLow, pRadius, pBoxing); + sprintf(newPartName, "%s_LOW", pPartName); + sprintf(newMEDFileName, "%s_gradmoy-low-%s-%s.med", + strPrefix.c_str(), + realToString(pTLow).c_str(), + realToString(pRadius).c_str()); + + { + Mesh* meshLow = meshFull->decimate(pFilterName, argv, part->getMeshName()); + cout << (*meshLow) << endl; + + insertMesh( + MeshDisPart::MULTIPR_WRITE_MESH, + part->getMeshName(), + part->mId + 2, + newPartName, + "localhost", + newMEDFileName, + meshLow, + part->mId + 1); + } +} + + +int MeshDis::computeNumParts() +{ + int numParts = 0; + + for (unsigned itPart = 0 ; itPart < mParts.size() ; itPart++) + { + switch (mParts[itPart]->mToDoOnNextWrite) + { + case MeshDisPart::MULTIPR_KEEP_AS_IT: + case MeshDisPart::MULTIPR_WRITE_MESH: + numParts++; + break; + + case MeshDisPart::MULTIPR_WRITE_PARTS: + numParts += mParts[itPart]->mSplit; + break; + + default: throw IllegalStateException("", __FILE__, __LINE__); + } + } + + return numParts; +} + + +void MeshDis::readDistributedMED(const char* pMEDfilename) +{ + //cout << "DBG: readDistributedMED" << endl; + if (pMEDfilename == NULL) throw NullArgumentException("filename should not be NULL", __FILE__, __LINE__); + + const int MAX_SIZEOF_LINE = 1024; + + reset(); + strcpy(mMEDfilename, pMEDfilename); + + //--------------------------------------------------------------------- + // Open master file (ASCII file) + //--------------------------------------------------------------------- + ifstream fileMaster(mMEDfilename); + if (fileMaster.fail()) throw IOException("i/o error while opening MED master file", __FILE__, __LINE__); + + //cout << "DBG: readDistributedMED: open" << endl; + + //--------------------------------------------------------------------- + // Read header + //--------------------------------------------------------------------- + char charbuffer[MAX_SIZEOF_LINE]; + fileMaster.getline(charbuffer, MAX_SIZEOF_LINE); + if (fileMaster.fail()) throw IOException("i/o error while reading MED master file", __FILE__, __LINE__); + + // check format + if ((charbuffer[0] != '#') || + (charbuffer[1] != ' ') || + (charbuffer[2] != 'M') || + (charbuffer[3] != 'E') || + (charbuffer[4] != 'D')) + throw IOException("not a valid distributed MED file", __FILE__, __LINE__); + + while ((charbuffer[0] == '#') || (strlen(charbuffer) == 0)) + { + fileMaster.getline(charbuffer, MAX_SIZEOF_LINE); + if (fileMaster.fail()) throw IOException("i/o error while reading MED master file", __FILE__, __LINE__); + } + + // read number of parts + int nbParts = atoi(charbuffer); + //cout << "DBG: readDistributedMED: #parts=" << nbParts << endl; + + //--------------------------------------------------------------------- + // Read infos about sub-parts + //--------------------------------------------------------------------- + char lMeshName[MED_TAILLE_NOM + 1]; + int lId; + char lPartName[MED_TAILLE_NOM + 1]; + char lPath[256]; + char lMEDFileName[256]; + + for (int i = 0 ; i < nbParts ; i++) + { + fileMaster.getline(charbuffer, MAX_SIZEOF_LINE); + if (fileMaster.fail()) throw IOException("i/o error while reading MED master file", __FILE__, __LINE__); + + while ((charbuffer[0] == '#') || (strlen(charbuffer) == 0)) + { + fileMaster.getline(charbuffer, MAX_SIZEOF_LINE); + if (fileMaster.fail()) throw IOException("i/o error while reading MED master file", __FILE__, __LINE__); + } + + lMeshName[0] = '\0'; + lId = 0; + lPartName[0] = '\0'; + lPath[0] = '\0'; + lMEDFileName[0] = '\0'; + + int ret = sscanf(charbuffer, "%s %d %s %s %s", + lMeshName, + &lId, + lPartName, + lPath, + lMEDFileName); + + if (ret != 5) throw IOException("i/o error while reading MED master file; bad format", __FILE__, __LINE__); + + //cout << "DBG: read: " << lMeshName << " " << lId << " " << lPartName << endl; + addMesh( + MeshDisPart::MULTIPR_KEEP_AS_IT, + lMeshName, + lId, + lPartName, + lPath, + lMEDFileName, + NULL); + } + + //--------------------------------------------------------------------- + // Close master file + //--------------------------------------------------------------------- + fileMaster.close(); + if (fileMaster.fail()) throw IOException("i/o error while closing MED master file", __FILE__, __LINE__); + //cout << "DBG: readDistributedMED: close" << endl; +} + + +/** + * Retrieves the output of MEDSPLITTER and convert it for MULTIPR. + */ +int convertMedsplitterToMultipr(ofstream& pFileMaster, const char* pTmpFilename, int pId, MeshDisPart* pPart) +{ + MULTIPR_LOG("convert" << endl); + + const int MAX_SIZEOF_LINE = 1024; + char charbuffer[MAX_SIZEOF_LINE]; + + // Open medsplitter master file (ASCII file) + ifstream fileMasterMedsplitter(pTmpFilename); + if (fileMasterMedsplitter.fail()) throw IOException("i/o error while opening MEDSPLITTER master file", __FILE__, __LINE__); + + fileMasterMedsplitter.getline(charbuffer, MAX_SIZEOF_LINE); + if (fileMasterMedsplitter.fail()) throw IOException("i/o error while reading MEDSPLITTER master file", __FILE__, __LINE__); + + while ((charbuffer[0] == '#') || (strlen(charbuffer) == 0)) + { + fileMasterMedsplitter.getline(charbuffer, MAX_SIZEOF_LINE); + if (fileMasterMedsplitter.fail()) throw IOException("i/o error while reading MEDSPLITTER master file", __FILE__, __LINE__); + } + + // read number of parts + int nbParts = atoi(charbuffer); + cout << "nb parts=" << nbParts << endl; + + char lMeshName[MED_TAILLE_NOM + 1]; + int lId; + char lPartName[MED_TAILLE_NOM + 1]; + char lPath[256]; + char lMEDFileName[256]; + + for (int i = 0 ; i < nbParts ; i++) + { + fileMasterMedsplitter.getline(charbuffer, MAX_SIZEOF_LINE); + if (fileMasterMedsplitter.fail()) throw IOException("", __FILE__, __LINE__); + + // parses the current line + lMeshName[0] = '\0'; + lId = 0; + lPartName[0] = '\0'; + lPath[0] = '\0'; + lMEDFileName[0] = '\0'; + + int ret = sscanf(charbuffer, "%s %d %s %s %s", + lMeshName, + &lId, + lPartName, + lPath, + lMEDFileName); + + if (ret != 5) throw IOException("i/o error while reading MEDSPLITTER master file; bad format", __FILE__, __LINE__); + + //cout << lMeshName << " " << (pId + i) << " " << pPart->getPartName() << "_" << (i + 1) << " " << lPath << " " << lMEDFileName << endl; + + pFileMaster << lMeshName << " " << (pId + i) << " " << pPart->getPartName() << "_" << (i + 1) << " " << lPath << " " << lMEDFileName << endl; + } + + fileMasterMedsplitter.close(); + if (fileMasterMedsplitter.fail()) throw IOException("i/o error while closing MEDSPLITTER master file", __FILE__, __LINE__); + + // remove master file generated by MEDSPLITTER + remove(pTmpFilename); + + return nbParts; +} + + +void MeshDis::writeDistributedMED(const char* pMEDfilenamePrefix) +{ + if (pMEDfilenamePrefix == NULL) throw NullArgumentException("", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Build master filename + //--------------------------------------------------------------------- + string strPrefix = string(pMEDfilenamePrefix); + const char* strExtension = ".med"; + string strMasterFilename; + + // add suffix "_grains_maitre" iff it is not yet in the filename + if (strstr(pMEDfilenamePrefix, "_grains_maitre") == 0) + { + strMasterFilename= strPrefix + "_grains_maitre" + strExtension; + } + else + { + strMasterFilename = strPrefix + strExtension; + } + + MULTIPR_LOG("Create master: " << strMasterFilename << endl); + strcpy(mMEDfilename, strMasterFilename.c_str()); + + //--------------------------------------------------------------------- + // Create an ASCII master file for the resulting distributed mesh and write header + //--------------------------------------------------------------------- + remove(strMasterFilename.c_str()); + ofstream fileMaster(strMasterFilename.c_str()); + + if (fileMaster == 0) throw IOException("i/o error while creating MED master file", __FILE__, __LINE__); + + fileMaster << "# MED file v2.3 - Master file created by MULTIPR v" << getVersion() << endl; + fileMaster << "#" << " " << endl; + + fileMaster << computeNumParts() << endl; + if (fileMaster.fail()) throw IOException("i/o error while writing MED master file", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Create a new MED file (v2.3) + //--------------------------------------------------------------------- + int id = 1; + + if (gProgressCallback != NULL) gProgressCallback->start("Save mesh", mParts.size()); + + try + { + + // for each sub-meshes + for (unsigned itPart = 0 ; itPart < mParts.size() ; itPart++) + { + switch (mParts[itPart]->mToDoOnNextWrite) + { + case MeshDisPart::MULTIPR_KEEP_AS_IT: + { + mParts[itPart]->mId = id; + id++; + fileMaster << (*mParts[itPart]) << endl; + cout << (*mParts[itPart]) << endl; + break; + } + + case MeshDisPart::MULTIPR_WRITE_MESH: + { + if (strlen(mParts[itPart]->getMEDFileName()) == 0) throw IOException("MED filename is empty", __FILE__, __LINE__); + if (mParts[itPart]->mMesh == NULL) throw IllegalStateException("invalid mesh (shoult not be NULL)", __FILE__, __LINE__); + mParts[itPart]->mMesh->writeMED(mParts[itPart]->getMEDFileName()); + mParts[itPart]->mId = id; + id++; + fileMaster << (*mParts[itPart]) << endl; + cout << (*mParts[itPart]) << endl; + break; + } + + case MeshDisPart::MULTIPR_WRITE_PARTS: + { + // split this part using medsplitter + if (mParts[itPart]->mOldCollection == NULL) throw IllegalStateException("", __FILE__, __LINE__); + string strPrefix = removeExtension(mParts[itPart]->getMEDFileName(), ".med"); + char tmpFilename[256]; + sprintf(tmpFilename, "%s_part", strPrefix.c_str()); + mParts[itPart]->mCollection->write(tmpFilename); + mParts[itPart]->mCollection->castAllFields(*(mParts[itPart]->mOldCollection)); + int ret = convertMedsplitterToMultipr(fileMaster, tmpFilename, id, mParts[itPart]); + id += ret; + remove(mParts[itPart]->getMEDFileName()); + break; + } + + default: throw IllegalStateException("should not be there", __FILE__, __LINE__); + } + + if (gProgressCallback != NULL) gProgressCallback->moveOn(); + } + + } + catch (RuntimeException& e) + { + if (gProgressCallback != NULL) gProgressCallback->done(); + throw e; + } + + if (gProgressCallback != NULL) gProgressCallback->done(); + + //--------------------------------------------------------------------- + // Close master file + //--------------------------------------------------------------------- + fileMaster.close(); + if (fileMaster.fail()) throw IOException("i/o error while closing MED master file", __FILE__, __LINE__); +} + + +ostream& operator<<(ostream& pOs, MeshDis& pM) +{ + pOs << "Mesh Dis.:" << endl; + pOs << " Filename =|" << pM.mMEDfilename << "|" << endl; + pOs << " #Sub-meshes=" << pM.mParts.size() << endl; + + for (unsigned itPart = 0 ; itPart < pM.mParts.size() ; itPart++) + { + cout << " " << (itPart + 1) << ": " << (*(pM.mParts[itPart])) << endl; + } + + return pOs; +} + + +} // namespace multipr + +// EOF diff --git a/src/MULTIPR/MULTIPR_MeshDis.hxx b/src/MULTIPR/MULTIPR_MeshDis.hxx new file mode 100644 index 0000000..bcfeebc --- /dev/null +++ b/src/MULTIPR/MULTIPR_MeshDis.hxx @@ -0,0 +1,436 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_MeshDis.hxx + * + * \brief Class MeshDis: distributed mesh. + * = MASTER file (ASCII) -> list of sequential MED file. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_MESHDIS_HXX +#define MULTIPR_MESHDIS_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + +extern "C" +{ + #include "med.h" +} + +#include +#include + +// include MEDSPLITTER used to split mesh using METIS or SCOTCH +#include "MEDMEM_define.hxx" +#include "MEDMEM_Mesh.hxx" +#include "MEDMEM_Family.hxx" +#include "MEDSPLITTER_Graph.hxx" +#include "MEDSPLITTER_MESHCollection.hxx" +#include "MEDSPLITTER_Topology.hxx" + + +namespace multipr +{ + +//***************************************************************************** +// Pre-declaration +//***************************************************************************** + +class Mesh; + + +//***************************************************************************** +// Class MeshDisPart = a sub-part of a distributed mesh. +// +// It can be : +// - a sequential MED file representing a Group (scenario 1) +// - a sequential MED file representing a part of a Group (scenario 2 -> MEDSPLITTER) +// - a lower resolution of a part (decimation) +//***************************************************************************** + +class MeshDisPart +{ + +public: + + /** + * Action to be done for this part on next writing on disk. + */ + enum OnNextWrite + { + MULTIPR_UNDEFINED, + MULTIPR_KEEP_AS_IT, + MULTIPR_WRITE_MESH, + MULTIPR_WRITE_PARTS + }; + +public: + + /** + * Builds an empty part of a distributed mesh (default constructor). + */ + MeshDisPart(); + + /** + * Destructor. Removes everything. + */ + ~MeshDisPart(); + + /** + * Resets this object in its state by default (empty). Cleans memory. + */ + void reset(); + + /** + * Creates a MeshDisPart. + * \param pToDoOnNextWrite + * \param pMeshName + * \param pId + * \param pPartName + * \param pPath + * \param pMEDFileName + * \param pMesh can be NULL. + */ + void create( + OnNextWrite pToDoOnNextWrite, + const char* pMeshName, + int pId, + const char* pPartName, + const char* pPath, + const char* pMEDFileName, + Mesh* pMesh); + + //--------------------------------------------------------------------- + // Basic accessors/mutators + //--------------------------------------------------------------------- + + /** + * Returns the name of this part. + * \return the name of this part. + */ + const char* getPartName() const { return mPartName; } + + /** + * Returns the name of the mesh of this part. + * \return the name of the mesh of this part. + */ + const char* getMeshName() const { return mMeshName; } + + /** + * Returns the MED filename which contain this part. + * \return the MED filename which contain this part. + */ + const char* getMEDFileName() const { return mMEDFileName; } + + /** + * Returns the suffix of the related MED filename (without .med extension). + * For examples: + * 1. "agregat100grains_12pas_grain97.med" -> "grain97" + * 2. "agregat100grains_12pas_grain100_part2.med" -> "grain100_part2" + * 3. "aagregat100grains_12pas_grain98_gradmoy-low-25.0-0.3.med" -> "grain98_gradmoy-low-25-0.3" + */ + const char* getMEDFileNameSuffix() const; + + /** + * Returns the action to be performed on this part on next write. + * \return the action to be performed on this part on next write. + */ + OnNextWrite getOnNextWrite() const { return mToDoOnNextWrite; } + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Reads the sequentiel MED file corresponding to this part. + * \throw IOException if an i/o error occurs. + */ + void readMED(); + + /** + * Dumps any MeshDisPart to the given output stream. + * \param pOs any output stream. + * \param pM any MeshDisPart. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, MeshDisPart& pM); + +private: + + // MeshDisPart can be used: + // 1 (KEEP_AS_IT) : To store data read from one line of an ASCII master file (distributed MED file) + // 2 (WRITE_MESH) : As a temporary structure to store all infos about a mesh corresponding to a group (before writing on disk). + // 3 (WRITE_PARTS) : As a temporary structure to store all infos about splitting using MEDSPLITTER. + + OnNextWrite mToDoOnNextWrite; /**< See enum OnNextWrite. */ + + //--------------------------------------------------------------------- + // Case 1, 2, and 3 + //--------------------------------------------------------------------- + char mMeshName[MED_TAILLE_NOM + 1]; /**< Name of the mesh. */ + int mId; /**< Id of this part in [1..n]. */ + char mPartName[MED_TAILLE_NOM + 1]; /**< Name of this part. */ + char mPath[256]; /**< Path of the MED file. */ + char mMEDFileName[256]; /**< Name of the MED file which contain this part. */ + + //--------------------------------------------------------------------- + // Case 2: mesh of the related sequential MED file (can be NULL if not loaded) + //--------------------------------------------------------------------- + Mesh* mMesh; /**< Mesh associated with this part; can be NULL. */ + + //--------------------------------------------------------------------- + // Case 3 only: temporary result of MEDSPLITTER + //--------------------------------------------------------------------- + int mSplit; /**< For MEDSPLITTER: number of parts. Temporary. */ + MEDSPLITTER::MESHCollection* mCollection; /**< New data after splitting. */ + MEDSPLITTER::MESHCollection* mOldCollection; /**< Data before splitting (we need them when we want to write new data on disk. */ + +private: + + // do not allow copy constructor + MeshDisPart(const MeshDisPart&); + + // do not allow copy + MeshDisPart& operator=(const MeshDisPart&); + + // do not allow operator == + bool operator==(const MeshDisPart&); + + //--------------------------------------------------------------------- + // Friends + //--------------------------------------------------------------------- + friend class MeshDis; + +}; // class MeshDisPart + + +//***************************************************************************** +// Class MeshDis +//***************************************************************************** + +class MeshDis +{ +public: + + /** + * Builds an empty mesh (default constructor). + */ + MeshDis(); + + /** + * Destructor. Removes everything. + */ + ~MeshDis(); + + /** + * Resets this object in its state by default (empty). Clean memory. + */ + void reset(); + + //--------------------------------------------------------------------- + // Basic accessors/mutators + //--------------------------------------------------------------------- + + /** + * Returns the name of this distributed MED file (=name of the master file). + * \return the name of this distributed MED file (=name of the master file). + */ + const char* getFilename() const { return mMEDfilename; } + + /** + * Adds a new part to this distributed mesh. + * Used by the split process (extract groups). + * \param pToDoOnNextWrite + * \param pMeshName + * \param pId + * \param pPartName + * \param pPath + * \param pMEDFileName + * \param pMesh can be NULL. + */ + void addMesh( + MeshDisPart::OnNextWrite pToDoOnNextWrite, + const char* pMeshName, + int pId, + const char* pPartName, + const char* pPath, + const char* pMEDFileName, + Mesh* pMesh); + + /** + * Inserts a new part to this distributed mesh. + * Used by the decimation process. + * \param pToDoOnNextWrite + * \param pMeshName + * \param pId + * \param pPartName + * \param pPath + * \param pMEDFileName + * \param pMesh can be NULL. + * \param pPosition insert after this position. Start at 1. + */ + void insertMesh( + MeshDisPart::OnNextWrite pToDoOnNextWrite, + const char* pMeshName, + int pId, + const char* pPartName, + const char* pPath, + const char* pMEDFileName, + Mesh* pMesh, + int pPosition); + + /** + * Returns the current number of parts in this distributed mesh. + * \return the current number of parts in this distributed mesh. + */ + int getNumParts() const { return mParts.size(); } + + /** + * Returns the nth part of this distributed mesh. + * \param pIndex index of the part (in 0..getNumParts()-1). + * \return the nth part of this distributed mesh. + */ + MeshDisPart* getPart(int pIndex) const { return mParts[pIndex]; } + + /** + * Returns the list of meshes contained in this distributed MED file. + * \return the list of meshes contained in this distributed MED file. + */ + std::vector getMeshes() const; + + /** + * Returns the list of fields contained in this distributed MED file. + * \return the list of fields contained in this distributed MED file. + */ + std::vector getFields() const; + + /** + * Returns the number of iteration for a given field. + * \param pFieldName field name. + * \return the number of iteration for a given field. + */ + int getTimeStamps(const char* pFieldName) const; + + /** + * Returns all information about a part. + * \param pPartName name of the part. + * \return all information about a part. + */ + std::string getPartInfo(const char* pPartName); + + //--------------------------------------------------------------------- + // Algorithms + //--------------------------------------------------------------------- + + /** + * Finds a part of this distributed mesh by its name. + * Returns NULL if the part does not exist. + * \param pPartName part to be found; must not be NULL. + * \return a pointer towards the part if it exists, NULL otherwise. + * \throw NullArgumentException if pPartName is NULL. + */ + MeshDisPart* findPart(const char* pPartName); + + /** + * Updates this distributed mesh by splitting one of its part. + * This splitting method leans on medsplitter, by V. Bergeaud (CEA). + * \param pPartName name of the part to be splitted. + * \param pNbParts number of sub-parts. + * \param pPartitionner MULTIPR_METIS or MULTIPR_SCOTCH. + * \throw RuntimeException if any error occurs. + */ + void splitPart(const char* pPartName, int pNbParts, int pPartitionner); + + /** + * Creates 3 resolution (CURRENT = FULL, MEDIUM and LOW) of a part of this distributed mesh. + * Names of new meshes are _MED and _LOW. + * \param pPartName + * \param pFielName + * \param pFieldIt + * \param pFilterName + * \param pTMed threshold used to generate MEDIUM resolution. + * \param pTLow threshold used to generate LOW resolution (must be >= pTMed). + * \param pRadius + * \param pBoxing number of cells along each axis; e.g. if 100 then grid will have 100*100*100 = 10**6 cells; 100 by default. + * \throw RuntimeException if any error occurs. + */ + void decimatePart( + const char* pPartName, + const char* pFieldName, + med_int pFieldIt, + const char* pFilterName, + med_float pTMed, + med_float pTLow, + med_float pRadius, + int pBoxing = 100); + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Reads the master file of a distributed MED file. + * \param pMEDfilename + * \throw NullArgumentException if pMEDfilename is NULL. + * \throw IOException if any i/o error occurs. + */ + void readDistributedMED(const char* pMEDfilename); + + /** + * Writes this distributed MED file (including master file and sub MED files if necessary). + * \param pMEDfilenamePrefix + * \throw NullArgumentException if pMEDfilename is NULL. + * \throw IOException if any i/o error occurs. + */ + void writeDistributedMED(const char* pMEDfilenamePrefix); + + /** + * Dumps any MeshDis to the given output stream. + * \param pOs any output stream. + * \param pM any MeshDis. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, MeshDis& pM); + +private: + + /** + * Recomputes the number of parts in this distributed mesh. + * This method is used by writeDistributedMED(). + * \return the number of parts in this distributed mesh. + */ + int computeNumParts(); + +private: + + char mMEDfilename[256]; /** Name of this distributed MED file (= name of the master file). */ + std::vector mParts; /**< Table of sub-parts; a distributed mesh is composed of N sub-part, where N = mParts.size(). */ + //MULTIPR_ProgressCallback* mProgressCallback; + +private: + + // do not allow copy constructor + MeshDis(const MeshDis&); + + // do not allow copy + MeshDis& operator=(const MeshDis&); + + // do not allow operator == + bool operator==(const MeshDis&); + +}; // class MeshDis + + +} // namespace MULTIPR + + +#endif // MULTIPR_MESHDIS_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_Nodes.cxx b/src/MULTIPR/MULTIPR_Nodes.cxx new file mode 100644 index 0000000..a499c95 --- /dev/null +++ b/src/MULTIPR/MULTIPR_Nodes.cxx @@ -0,0 +1,400 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Nodes.cxx + * + * \brief see MULTIPR_Nodes.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_Nodes.hxx" +#include "MULTIPR_Exceptions.hxx" + +#include + +using namespace std; + + +namespace multipr +{ + + +//***************************************************************************** +// Class Nodes implementation +//***************************************************************************** + +Nodes::Nodes() +{ + mId = NULL; + mFamIdent = NULL; + mNames = NULL; + mCoo = NULL; + mNamesCoo = NULL; + mNamesUnitCoo = NULL; + + reset(); +} + + +Nodes::~Nodes() +{ + reset(); +} + + +void Nodes::reset() +{ + mNum = 0; + mDim = 0; + mCoordSystem = MED_CART; + + if (mId != NULL) { delete[] mId; mId = NULL; } + if (mFamIdent != NULL) { delete[] mFamIdent; mFamIdent = NULL; } + if (mNames != NULL) { delete[] mNames; mNames = NULL; } + if (mCoo != NULL) { delete[] mCoo; mCoo = NULL; } + if (mNamesCoo != NULL) { delete[] mNamesCoo; mNamesCoo = NULL; } + if (mNamesUnitCoo != NULL) { delete[] mNamesUnitCoo; mNamesUnitCoo = NULL; } + + mFlagPrintAll = false; +} + + +const med_float* Nodes::getCoordinates(med_int pIndexNode) const +{ + if ((pIndexNode < 0) || (pIndexNode >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__); + + return mCoo + pIndexNode * mDim; +} + + +med_int Nodes::getFamIdent(med_int pIndexNode) const +{ + if ((pIndexNode < 0) || (pIndexNode >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__); + + return mFamIdent[pIndexNode]; +} + + +void Nodes::getBBox(med_float pMin[3], med_float pMax[3]) const +{ + //--------------------------------------------------------------------- + // Special case: no nodes => bbox = [0 ; 0] x [0 ; 0] x [0 ; 0] + //--------------------------------------------------------------------- + if (mNum == 0) + { + for (int itDim = 0 ; itDim < mDim ; itDim++) + { + pMin[itDim] = med_float(0.0); + pMax[itDim] = med_float(0.0); + } + + return; + } + + //--------------------------------------------------------------------- + // Compute axis-aligned bounding box + //--------------------------------------------------------------------- + for (int itDim = 0 ; itDim < mDim ; itDim++) + { + pMin[itDim] = numeric_limits::max(); + pMax[itDim] = -pMin[itDim]; + } + for (int itNode = 0 ; itNode < mNum ; itNode++) + { + for (int itDim = 0 ; itDim < mDim ; itDim++) + { + med_float coord = mCoo[itNode * mDim + itDim]; + if (coord < pMin[itDim]) pMin[itDim] = coord; + if (coord > pMax[itDim]) pMax[itDim] = coord; + } + } +} + + +set Nodes::getSetOfFamilies() const +{ + set setOfFamilies; + + // for each node, ad its family to the set + for (int itNode = 0 ; itNode < mNum ; itNode++) + { + setOfFamilies.insert(mFamIdent[itNode]); + } + + return setOfFamilies; +} + + +Nodes* Nodes::extractSubSet(const set& pSetIndices) const +{ + Nodes* subset = new Nodes(); + + subset->mNum = pSetIndices.size(); + subset->mDim = mDim; + subset->mCoordSystem = mCoordSystem; + + //--------------------------------------------------------------------- + // Allocate arrays + //--------------------------------------------------------------------- + subset->mFamIdent = new med_int[subset->mNum]; + subset->mCoo = new med_float[subset->mDim * subset->mNum]; + subset->mNamesCoo = new char[subset->mDim * MED_TAILLE_PNOM + 1]; + subset->mNamesUnitCoo = new char[subset->mDim * MED_TAILLE_PNOM + 1]; + + memcpy(subset->mNamesCoo, mNamesCoo, subset->mDim * MED_TAILLE_PNOM + 1); + memcpy(subset->mNamesUnitCoo, mNamesUnitCoo, subset->mDim * MED_TAILLE_PNOM + 1); + + //--------------------------------------------------------------------- + // Copy subset of familys id and coords. + //--------------------------------------------------------------------- + set::iterator itSet = pSetIndices.begin(); + for (int i = 0 ; i < subset->mNum; i++) + { + + med_int srcIndex = (*itSet) - 1; // MED index start at 1 + subset->mFamIdent[i] = mFamIdent[srcIndex]; + + med_float* srcCoo = mCoo + srcIndex * mDim; + med_float* destCoo = subset->mCoo + i * subset->mDim; + for (int itDim = 0 ; itDim < mDim ; itDim++) + { + destCoo[itDim] = srcCoo[itDim]; + } + + itSet++; + } + + //--------------------------------------------------------------------- + // Copy subset of identifiers if necessary + //--------------------------------------------------------------------- + if (isIdentifiers()) + { + itSet = pSetIndices.begin(); + subset->mId = new med_int[subset->mNum]; + for (int i = 0 ; i < subset->mNum; i++) + { + med_int srcIndex = (*itSet) - 1; // MED index start at 1 + subset->mId[i] = mId[srcIndex]; + + itSet++; + } + } + + //--------------------------------------------------------------------- + // Copy subset of names if necessary + //--------------------------------------------------------------------- + if (isNames()) + { + subset->mNames = new char[MED_TAILLE_PNOM * subset->mNum + 1]; + char* destPtr = subset->mNames; + itSet = pSetIndices.begin(); + for (int i = 0 ; i < subset->mNum; i++) + { + med_int srcIndex = (*itSet) - 1; // MED index start at 1 + char* srcPtr = mNames + srcIndex * MED_TAILLE_PNOM; + memcpy(destPtr, srcPtr, MED_TAILLE_PNOM); + destPtr += MED_TAILLE_PNOM; + + itSet++; + } + subset->mNames[MED_TAILLE_PNOM * subset->mNum] = '\0'; + } + + return subset; +} + + +void Nodes::readMED(med_idt pMEDfile, char* pMeshName, med_int pDim) +{ + if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__); + if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (pDim != 3) throw IllegalArgumentException("", __FILE__, __LINE__); + + reset(); + + mDim = pDim; + mNum = MEDnEntMaa( + pMEDfile, + pMeshName, + MED_COOR, + MED_NOEUD, + med_geometrie_element(0), + med_connectivite(0)); + + if (mNum <= 0) throw IOException("", __FILE__, __LINE__); + + mId = new med_int[mNum]; + mFamIdent = new med_int[mNum]; + mNames = new char[MED_TAILLE_PNOM * mNum + 1]; + mCoo = new med_float[mDim * mNum]; + mNamesCoo = new char[mDim * MED_TAILLE_PNOM + 1]; + mNamesUnitCoo = new char[mDim * MED_TAILLE_PNOM + 1]; + + mNames[0] = '\0'; + mNamesCoo[0] = '\0'; + mNamesUnitCoo[0] = '\0'; + + med_booleen isIdentifiers; + med_booleen isNames; + + med_err ret = MEDnoeudsLire( + pMEDfile, + pMeshName, + mDim, + mCoo, + MED_FULL_INTERLACE, + &mCoordSystem, + mNamesCoo, + mNamesUnitCoo, + mNames, + &isNames, + mId, + &isIdentifiers, + mFamIdent, + mNum); + + if (ret != 0) throw IOException("", __FILE__, __LINE__); + + // check if coordinates system is CARTESIAN + if (mCoordSystem != MED_CART) throw IllegalStateException("", __FILE__, __LINE__); + + if (!isNames) + { + delete[] mNames; + mNames = NULL; + } + + if (!isIdentifiers) + { + delete[] mId; + mId = NULL; + } +} + + +void Nodes::writeMED(med_idt pMEDfile, char* pMeshName) const +{ + if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__); + if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (strlen(pMeshName) > MED_TAILLE_NOM) throw IllegalArgumentException("", __FILE__, __LINE__); + if ((mDim < 1) || (mDim > 3)) throw IllegalStateException("", __FILE__, __LINE__); + if (mFamIdent == NULL) throw IllegalStateException("", __FILE__, __LINE__); + if (mCoo == NULL) throw IllegalStateException("", __FILE__, __LINE__); + if (mNamesCoo == NULL) throw IllegalStateException("", __FILE__, __LINE__); + if (mNamesUnitCoo == NULL) throw IllegalStateException("", __FILE__, __LINE__); + + // special case: if no nodes => do nothing + if (mNum == 0) return; + + med_err ret = MEDnoeudsEcr( + pMEDfile, + pMeshName, + mDim, + mCoo, + MED_FULL_INTERLACE, + mCoordSystem, + mNamesCoo, + mNamesUnitCoo, + mNames, + isNames()?MED_VRAI:MED_FAUX, + mId, + isIdentifiers()?MED_VRAI:MED_FAUX, + mFamIdent, + mNum); + + if (ret != 0) throw IOException("i/o error while writing nodes", __FILE__, __LINE__); + +} + + +ostream& operator<<(ostream& pOs, Nodes& pN) +{ + char strCoordSystem[16]; + switch (pN.mCoordSystem) + { + case MED_CART: strcpy(strCoordSystem, "CARTESIAN"); break; + case MED_CYL: strcpy(strCoordSystem, "CYLINDRIC"); break; + case MED_SPHER: strcpy(strCoordSystem, "SPHERIC"); break; + default: strcpy(strCoordSystem, "UNKNOWN"); break; + } + + pOs << "Nodes: " << endl; + pOs << " #number =" << pN.mNum << endl; + pOs << " Dimension =" << pN.mDim << endl; + pOs << " Coord. system=" << strCoordSystem << endl; + pOs << " Has names ?" << (pN.isNames()?"yes":"no") << endl; + pOs << " Has id ?" << (pN.isIdentifiers()?"yes":"no") << endl; + pOs << " Axis names =" << "|" << pN.mNamesCoo << "|" << endl; + pOs << " Unit axis =" << "|" << pN.mNamesUnitCoo << "|" << endl; + + { + set setOfFam = pN.getSetOfFamilies(); + if (setOfFam.size() == 0) + { + pOs << " Families: #fam=0" << endl; + } + else + { + set::iterator itFam = setOfFam.end(); + itFam--; + pOs << " Families: #fam=" << setOfFam.size() << " id_min=" << (*(setOfFam.begin())) << " id_max=" << (*itFam) << endl; + } + + if (pN.mFlagPrintAll) + { + for (int itNode = 0 ; itNode < pN.mNum; itNode++) + { + pOs << " Node " << (itNode+1) << ": " << pN.mFamIdent[itNode] << endl; + } + } + } + + med_float bboxMin[3], bboxMax[3]; + pN.getBBox(bboxMin, bboxMax); + pOs << " BBox: [" << bboxMin[0] << " ; " << bboxMax[0] << "] x [" << bboxMin[1] << " ; " << bboxMax[1] << "] x [" << bboxMin[2] << " ; " << bboxMax[2] << "]" << endl; + + if (pN.mFlagPrintAll) + { + pOs << " Coordinates: " << endl; + for (int itNode = 0 ; itNode < pN.mNum ; itNode++) + { + pOs << " Node " << (itNode+1) << ": "; + for (int itDim = 0 ; itDim < pN.mDim ; itDim++) + { + pOs << pN.mCoo[itNode * pN.mDim + itDim] << " "; + } + pOs << endl; + } + + if (pN.isIdentifiers()) + { + pOs << " Num: " << endl; + for (int itNode = 0 ; itNode < pN.mNum; itNode++) + { + pOs << " Node " << (itNode+1) << ": " << pN.mId[itNode] << endl; + } + } + + if (pN.isNames()) + { + pN.mNames[MED_TAILLE_PNOM * pN.mNum] = '\0'; + pOs << " Names: |" << pN.mNames << "|" << endl; + } + + } + + return pOs; +} + + +} // namespace multipr + +// EOF diff --git a/src/MULTIPR/MULTIPR_Nodes.hxx b/src/MULTIPR/MULTIPR_Nodes.hxx new file mode 100644 index 0000000..ed39c9d --- /dev/null +++ b/src/MULTIPR/MULTIPR_Nodes.hxx @@ -0,0 +1,190 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Nodes.hxx + * + * \brief Class Nodes = table of nodes. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_NODES_HXX +#define MULTIPR_NODES_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + +extern "C" +{ + #include "med.h" +} + +#include +#include + + +namespace multipr +{ + + +//***************************************************************************** +// Class Nodes +//***************************************************************************** + +class Nodes +{ +public: + + /** + * Builds an empty set of nodes (default constructor). + */ + Nodes(); + + /** + * Destructor. Removes everything. + */ + ~Nodes(); + + /** + * Resets this object in its state by default (empty). Cleans memory. + */ + void reset(); + + //--------------------------------------------------------------------- + // Basic accessors/mutators + //--------------------------------------------------------------------- + + /** + * Returns true if nodes have a name. + * \return true if nodes have a name. + */ + bool isNames() const { return (mNames != NULL); } + + /** + * Returns true if elements have an identifier (= a number). + * \return true if elements have an identifier (= a number). + */ + bool isIdentifiers() const { return (mId != NULL); } + + /** + * Returns the coordinates of one node according to its index. + * \param pIndexNode index of node in [0..NUMBER_OF_NODES-1]. + * \return the coordinates of one node. + * \throw IndexOutOfBoundsException if pIndexNode is invalid. + */ + const med_float* getCoordinates(med_int pIndexNode) const; + + /** + * Returns the family of one node. + * \param pIndexNode index of node in [0..NUMBER_OF_NODES-1]. + * \return the family of the given node. + * \throw IndexOutOfBoundsException if pIndexNode is invalid. + */ + med_int getFamIdent(med_int pIndexNode) const; + + /** + * Returns the number of nodes. + * \return the number of nodes. + */ + int getNumberOfNodes() const { return mNum; } + + //--------------------------------------------------------------------- + // Algorithms + //--------------------------------------------------------------------- + + /** + * Returns the axis-aligned bounding box (CARTESIAN coordinates system) of this set of nodes. + * \param pMin (out) coordinates of the min-corner of the bbox. + * \param pMin (out) coordinates of the max-corner of the bbox. + */ + void getBBox(med_float pMin[3], med_float pMax[3]) const; + + /** + * Returns the set of families referenced by this set of nodes. + * Each family is described by its identifier. + * \return the set of families referenced by this set of nodes. + */ + std::set getSetOfFamilies() const; + + /** + * Constructor. Creates a subset of this set of nodes from a set of indices. + * \param pSetOfIndices set of indices; each index must be >= 1. + * \return a subset of this set of nodes from a set of indices. + */ + Nodes* extractSubSet(const std::set& pSetIndices) const; + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Reads all nodes of a mesh from a MED file. + * \param pMEDfile any valid MED file opened for reading. + * \param pMeshName name of the mesh to be read. + * \param pDim dimension of the mesh. + * \throw IOException if any i/o error occurs. + */ + void readMED(med_idt pMEDfile, char* pMeshName, med_int pDim); + + /** + * Writes this set of nodes to a MED file. Nodes are associated with the given mesh. + * WARNING: mesh must have been created and added to the MED file before. + * \param pMEDfile any valid MED file opened for writing. + * \param pMeshName any mesh of the MED file. + * \throw IOException if any i/o error occurs. + */ + void writeMED(med_idt pMEDfile, char* pMeshName) const; + + /** + * Sets the flag which control the stream operator <<. + * \param pFlag new flag value. + */ + void setPrintAll(bool pFlag) { mFlagPrintAll = pFlag; } + + /** + * Dumps any Nodes to the given output stream. + * \param pOs any output stream. + * \param pN any Nodes. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, Nodes& pN); + +private: + + med_int mNum; /**< Number of nodes in this set. */ + med_int mDim; /**< Dimension of nodes. */ + med_repere mCoordSystem; /**< Type of coordinates system; should be MED_CART for cartesian. */ + + med_int* mId; /**< Optional; for each node, its identifier; NULL if undefined. */ + med_int* mFamIdent; /**< For each node, its identifier of its family. */ + char* mNames; /**< Optional; for each node, its name; NULL if undefined. */ + med_float* mCoo; /**< For each node, coordinates of node; array is interlaced: x1 y1 z1 x2 y2 z2 ...*/ + char* mNamesCoo; /**< Names of axis of the coordinates system. */ + char* mNamesUnitCoo; /**< Unit of axis of the coordinates system. */ + + bool mFlagPrintAll; /** Flag to control the behaviour of the stream operator <<. */ + +private: + + // do not allow copy constructor + Nodes(const Nodes&); + + // do not allow copy + Nodes& operator=(const Nodes&); + + // do not allow operator == + bool operator==(const Nodes&); + +}; // class Nodes + + +} // namespace MULTIPR + + +#endif // MULTIPR_NODES_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_Obj.cxx b/src/MULTIPR/MULTIPR_Obj.cxx new file mode 100644 index 0000000..99e69f8 --- /dev/null +++ b/src/MULTIPR/MULTIPR_Obj.cxx @@ -0,0 +1,427 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Obj.cxx + * + * \brief see MULTIPR_Obj.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_Obj.hxx" +#include "MULTIPR_Exceptions.hxx" +#include "MULTIPR_Mesh.hxx" +#include "MULTIPR_MeshDis.hxx" +#include "MULTIPR_Utils.hxx" + +#include +#include + +using namespace std; + + +namespace multipr +{ + + +//***************************************************************************** +// Class Obj implementation +//***************************************************************************** + +Obj::Obj() +{ + mMeshDis = NULL; + + reset(); +} + + +Obj::~Obj() +{ + reset(); +} + + +void Obj::reset() +{ + mMEDfilename = ""; + mMeshName = ""; + mState = MULTIPR_OBJ_STATE_RESET; + + if (mMeshDis != NULL) { delete mMeshDis; mMeshDis = NULL; } +} + + +void Obj::create(const char* pMEDfilename) +{ + if (pMEDfilename == NULL) throw multipr::NullArgumentException("file name must not be NULL", __FILE__, __LINE__); + + // reset everything before associating a new MED file to this object + reset(); + + mMEDfilename = pMEDfilename; + + // check if file exists + FILE* f = fopen(pMEDfilename, "rb"); + if (f == 0) + { + // file does not exist + mState = MULTIPR_OBJ_STATE_ERROR; + throw FileNotFoundException("file not found", __FILE__, __LINE__); + } + fclose(f); + + // test whether it is a sequential MED file or a distributed MED file + med_idt file = MEDouvrir(const_cast(pMEDfilename), MED_LECTURE); // open sequential MED file for reading + if (file > 0) + { + // sequential MED file has been sucessfuly openened + + // CASE 1: sequential MED file + med_int ret = MEDfermer(file); + + if (ret != 0) + { + // error while closing sequential MED file + mState = MULTIPR_OBJ_STATE_ERROR; + throw multipr::IOException("i/o error while closing MED file", __FILE__, __LINE__); + } + + mState = MULTIPR_OBJ_STATE_SEQ_INIT; + cout << "Sequential MED file " << pMEDfilename << " has been successfuly opened" << endl; + } + else + { + // CASE 2: distributed MED file? + try + { + mMeshDis = new multipr::MeshDis(); + mMeshDis->readDistributedMED(pMEDfilename); + + mState = MULTIPR_OBJ_STATE_DIS; + cout << "Distributed MED file " << pMEDfilename << " has been successfuly opened" << endl; + } + catch (...) + { + // neither a sequential MED file, nor a distributed MED file => error + mState = MULTIPR_OBJ_STATE_ERROR; + throw IOException("file is nor a sequential MED file, neither a distributed MED file", __FILE__, __LINE__); + } + } +} + + +void Obj::setMesh(const char* pMeshName) +{ + // setMesh() is only available for sequential MED file (not distributed MED file) + if ((mState != MULTIPR_OBJ_STATE_SEQ_INIT) && + (mState != MULTIPR_OBJ_STATE_SEQ)) throw IllegalStateException("expected a sequential MED file", __FILE__, __LINE__); + + mMeshName = pMeshName; + + // change state to MULTIPR_OBJ_STATE_SEQ (in case of state=MULTIPR_OBJ_STATE_SEQ_INIT) + mState = MULTIPR_OBJ_STATE_SEQ; +} + + +vector Obj::getMeshes() const +{ + // test whether it is a sequential MED file or a distributed MED file + if ((mState == MULTIPR_OBJ_STATE_SEQ_INIT) || + (mState == MULTIPR_OBJ_STATE_SEQ)) + { + // CASE 1: sequential MED file + return multipr::getListMeshes(mMEDfilename.c_str()); + } + else + { + // CASE 2: distributed MED file + if (mMeshDis == NULL) + { + throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__); + } + + return mMeshDis->getMeshes(); + } +} + + +vector Obj::getFields() const +{ + // test whether it is a sequential MED file or a distributed MED file + if ((mState == MULTIPR_OBJ_STATE_SEQ_INIT) || + (mState == MULTIPR_OBJ_STATE_SEQ)) + { + // CASE 1: sequential MED file + vector > tmp = multipr::getListFields(mMEDfilename.c_str()); + + vector res; + for (int i = 0 ; i < tmp.size() ; i++) + { + res.push_back(tmp[i].first); + } + + return res; + } + else + { + // CASE 2: distributed MED file + if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__); + + return mMeshDis->getFields(); + } +} + + +int Obj::getTimeStamps(const char* pFieldName) const +{ + // test whether it is a sequential MED file or a distributed MED file + if ((mState == MULTIPR_OBJ_STATE_SEQ_INIT) || + (mState == MULTIPR_OBJ_STATE_SEQ)) + { + // CASE 1: sequential MED file + vector > tmp = multipr::getListFields(mMEDfilename.c_str()); + + for (int i = 0 ; i < tmp.size() ; i++) + { + if (strcmp(tmp[i].first.c_str(), pFieldName) == 0) + { + return tmp[i].second; + } + } + + // pFieldName not found in the list of fields + return 0; + } + else + { + // CASE 2: distributed MED file + if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__); + + return mMeshDis->getTimeStamps(pFieldName); + } +} + + +vector Obj::getParts() const +{ + // getParts() is only available for distributed MED file (not sequential MED file) + if ((mState != MULTIPR_OBJ_STATE_DIS) && + (mState != MULTIPR_OBJ_STATE_DIS_MEM)) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__); + + return getListParts(); +} + + +string Obj::getPartInfo(const char* pPartName) const +{ + // getParts() is only available for distributed MED file (not sequential MED file) + if ((mState != MULTIPR_OBJ_STATE_DIS) && + (mState != MULTIPR_OBJ_STATE_DIS_MEM)) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__); + + if (mMeshDis == NULL) throw IllegalStateException("distributed MED file should not be NULL", __FILE__, __LINE__); + + return mMeshDis->getPartInfo(pPartName); + +} + + +vector Obj::partitionneDomaine() +{ + if (mState == MULTIPR_OBJ_STATE_SEQ_INIT) throw IllegalStateException("use setMesh() before", __FILE__, __LINE__); + + // partitionneDomaine() is only available for sequential MED file (not distributed MED file) + if (mState != MULTIPR_OBJ_STATE_SEQ) throw IllegalStateException("unexpected operation", __FILE__, __LINE__); + + //------------------------------------------------------------- + // Read the sequential mesh + //------------------------------------------------------------- + cout << "Read sequential MED file: " << mMEDfilename << ": please wait... " << endl; + + Mesh mesh; + mesh.readSequentialMED(mMEDfilename.c_str(), mMeshName.c_str()); + cout << mesh << endl; + + //------------------------------------------------------------- + // Build distributed mesh from groups + //------------------------------------------------------------- + cout << "Build distributed mesh: please wait... " << endl; + try + { + mMeshDis = mesh.splitGroupsOfElements(); + } + catch (RuntimeException& e) + { + delete mMeshDis; + mMeshDis = NULL; + throw e; + } + + mState = MULTIPR_OBJ_STATE_DIS_MEM; + + return getListParts(); +} + + +vector Obj::partitionneGrain( + const char* pPartName, + int pNbParts, + int pPartitionner) +{ + if (mMeshDis == NULL) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__); + if (pPartName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + if (pNbParts < 2) throw IllegalArgumentException("", __FILE__, __LINE__); + if ((pPartitionner != 0) && (pPartitionner != 1)) throw IllegalArgumentException("partitionner should be 0=METIS or 1=SCOTCH", __FILE__, __LINE__); + + // partitionneGrain() is only available for distributed MED file (not sequential MED file) + if ((mState != MULTIPR_OBJ_STATE_DIS_MEM) && + (mState != MULTIPR_OBJ_STATE_DIS)) throw IllegalStateException("unexpected operation", __FILE__, __LINE__); + + // if distributed MED file is currently in memory, then write to disk before performing partitionneGrain() + // (because MEDSPLIITER starts from a file) + if (mState == MULTIPR_OBJ_STATE_DIS_MEM) + { + //----------------------------------------------------- + // Write distributed mesh + //----------------------------------------------------- + cout << "Write distributed mesh: please wait... " << endl; + string strPrefix = removeExtension(mMEDfilename.c_str(), ".med"); + mMeshDis->writeDistributedMED(strPrefix.c_str()); + + mMEDfilename = mMeshDis->getFilename(); + + delete mMeshDis; + + //--------------------------------------------------------------------- + // Read the distributed mesh + //--------------------------------------------------------------------- + int ret = MEDformatConforme(mMEDfilename.c_str()); + if (ret == 0) throw IOException("waiting for a distributed MED file (not a sequential one)", __FILE__, __LINE__); + + mMeshDis = new MeshDis(); + mMeshDis->readDistributedMED(mMEDfilename.c_str()); + + mState = MULTIPR_OBJ_STATE_DIS; + } + + //--------------------------------------------------------------------- + // Split the given part (pGroupName) + //--------------------------------------------------------------------- + mMeshDis->splitPart(pPartName, pNbParts, pPartitionner); + cout << mMeshDis << endl; + + //--------------------------------------------------------------------- + // Write new distributed mesh + //--------------------------------------------------------------------- + string strPrefix = multipr::removeExtension(mMEDfilename.c_str(), ".med"); + mMeshDis->writeDistributedMED(strPrefix.c_str()); + + //--------------------------------------------------------------------- + // Read the distributed mesh + //--------------------------------------------------------------------- + delete mMeshDis; + mMeshDis = new MeshDis(); + //cout << "read dis MED file: filename=" << mMEDfilename << endl; + mMeshDis->readDistributedMED(mMEDfilename.c_str()); + + return getListParts(); +} + + +vector Obj::decimePartition( + const char* pPartName, + const char* pFieldName, + int pFieldIt, + const char* pFilterName, + double pTmed, + double pTlow, + double pRadius, + int pBoxing) +{ + + // decimePartition() is only available for distributed MED file (not sequential MED file) + if ((mState != MULTIPR_OBJ_STATE_DIS_MEM) && + (mState != MULTIPR_OBJ_STATE_DIS)) throw IllegalStateException("unexpected operation", __FILE__, __LINE__); + + if (mMeshDis == NULL) throw IllegalStateException("expected a distributed MED file", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Decimate + //--------------------------------------------------------------------- + mMeshDis->decimatePart( + pPartName, + pFieldName, + pFieldIt, + pFilterName, + pTmed, + pTlow, + pRadius, + pBoxing); + + mState = MULTIPR_OBJ_STATE_DIS_MEM; + + return getListParts(); +} + + +vector Obj::getListParts() const +{ + if (mMeshDis == NULL) throw IllegalStateException("not a distributed mesh", __FILE__, __LINE__); + + vector names; + + int numParts = mMeshDis->getNumParts(); + for (int i = 0 ; i < numParts ; i++) + { + names.push_back( mMeshDis->getPart(i)->getPartName() ); + } + + return names; +} + + +void Obj::save() +{ + // only save file if it is a distributed MED file currently in memory + if (mState == MULTIPR_OBJ_STATE_DIS_MEM) + { + //------------------------------------------------------------- + // Write new distributed mesh + //------------------------------------------------------------- + string strPrefix = multipr::removeExtension(mMEDfilename.c_str(), ".med"); + mMeshDis->writeDistributedMED(strPrefix.c_str()); + mMEDfilename = mMeshDis->getFilename(); + + cout << "Write MED master file: " << mMEDfilename << ": OK" << endl; + + //------------------------------------------------------------- + // Read the distributed mesh + //------------------------------------------------------------- + delete mMeshDis; + mMeshDis = new MeshDis(); + mMeshDis->readDistributedMED(mMEDfilename.c_str()); + + mState = MULTIPR_OBJ_STATE_DIS; + } +} + + +ostream& operator<<(ostream& pOs, Obj& pO) +{ + pOs << "Obj:" << endl; + pOs << " Name:" << pO.mMEDfilename << endl; + + return pOs; +} + + +} // namespace multipr + +// EOF diff --git a/src/MULTIPR/MULTIPR_Obj.hxx b/src/MULTIPR/MULTIPR_Obj.hxx new file mode 100644 index 0000000..ea1ab55 --- /dev/null +++ b/src/MULTIPR/MULTIPR_Obj.hxx @@ -0,0 +1,249 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_GaussLoc.hxx + * + * \brief Class MULTIPR_Obj. + * This class is used as an interface to implement MULTIPR services in the salome MODULE + * as described in the spec/design doc. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_OBJ_HXX +#define MULTIPR_OBJ_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include +#include +#include + + +namespace multipr +{ + +class MeshDis; + + +//***************************************************************************** +// Class Obj +//***************************************************************************** + +enum ObjState +{ + MULTIPR_OBJ_STATE_ERROR, + MULTIPR_OBJ_STATE_RESET, + MULTIPR_OBJ_STATE_SEQ_INIT, + MULTIPR_OBJ_STATE_SEQ, + MULTIPR_OBJ_STATE_DIS, + MULTIPR_OBJ_STATE_DIS_MEM +}; // enum ObjState + + +class Obj +{ +public: + + /** + * Builds an empty Gauss reference (default constructor). + */ + Obj(); + + /** + * Destructor. Removes everything. + */ + ~Obj(); + + /** + * Resets this object in its state by default (empty). Cleans memory. + */ + void reset(); + + /** + * Associate a MED file (sequential or distributed) with this object. + * This method also: + * - reset everything before starting + * - determine if the given file is a sequential (SEQ) or a distributed (DIS) MED file + * - read the ASCII master file if it is a distributed MED file + * - set state + */ + void create(const char* pMEDfilename); + + //--------------------------------------------------------------------- + // Basic accessors/mutators + //-------------------------------------------------------------------- + + /** + * Returns true iff this obj represents a valid sequential MED file. + * \return true iff this obj represents a valid sequential MED file. + */ + bool isValidSequentialMEDFile() const { return (mState == MULTIPR_OBJ_STATE_SEQ) || (mState == MULTIPR_OBJ_STATE_SEQ_INIT); } + + /** + * Returns true iff this obj represents a valid distributed MED file. + * \return true iff this obj represents a valid distributed MED file. + */ + bool isValidDistributedMEDFile() const { return (mState == MULTIPR_OBJ_STATE_DIS) || (mState == MULTIPR_OBJ_STATE_DIS_MEM); } + + /** + * Defines the mesh to be processed. + * \param pMeshName name of the mesh to be partitionned. + */ + void setMesh(const char* pMeshName); + + /** + * Returns the list of meshes contained in the sequential MED file. + * Assumes this object encapsulates a sequential MED file. + * \return the list of meshes contained in the sequential MED file. + */ + std::vector getMeshes() const; + + /** + * Returns the list of fields contained in the sequential MED file. + * Assumes this object encapsulates a sequential MED file. + * \return the list of fields contained in the sequential MED file. + */ + std::vector getFields() const; + + /** + * Returns the number of timestamps for a given field. + * Assumes this object encapsulates a sequential MED file. + * \param pFieldName name of any field. + * \return the number of timestamps for a given field; 0 if field not found. + */ + int getTimeStamps(const char* pFieldName) const; + + /** + * Returns the name of all partitions. + * Assumes this object encapsulates a distributed MED file. + * \return the name of all partitions. + */ + std::vector getParts() const; + + /** + * Returns all information about a part. + * \param pPartName name of the part. + * \return all information about a part. + */ + std::string getPartInfo(const char* pPartName) const; + + //--------------------------------------------------------------------- + // Algorithms + //-------------------------------------------------------------------- + + /** + * Creates a distributed MED file (v2.3) by extracting all the groups from the current mesh of the current MED sequential MED file. + * Assumes: + * - the file is in MED format and can be read using MED file v2.3. + * - the file is sequential (not a distributed MED). + * - the file only contains TETRA10 elements (dimension of space and mesh is 3). + * - the file have no profil. + * \return the name of each part. + * \throw RuntimeException if any error occurs. + */ + std::vector partitionneDomaine(); + + /** + * Creates a distributed MED file (V2.3) by splitting a group of a MED file previously created by partitionneDomaine. + * Assumes: + * - the file is a distributed MED file, previously created by partitionneDomaine() + * (=> each part only contain 1 mesh, TETRA10 elements only) + * - nbPart > 1 + * \param pPartName name of the part to be splitted. + * \param pNbParts number of parts; must be > 1. + * \param pPartitionner use value 0=MULTIPR_METIS for Metis or 1=MULTIPR_SCOTCH for Scotch. + * \return the name of each part. + * \throw RuntimeException if any error occurs. + */ + std::vector partitionneGrain( + const char* pPartName, + int pNbParts, + int pPartitionner=0); + + /** + * Creates 3 resolutions of the given part of a distributed MED file (V2.3). + * Assumes: + * - the file is a distributed MED file, previously created by partitionneDomaine() or partitionneGrain() + * (=> each part only contain 1 mesh, TETRA10 elements only) + * \param pPartName name of the part to be decimated. + * \param pFieldName name of the field used for decimation. + * \param pFieldIt iteration (time step) of the field. + * \param pFilterName name of the filter to be used. + * \param pTmed threshold used for medium resolution. + * \param pTlow threshold used for low resolution; tmed must be less than tlow + * \param pTadius radius used to determine the neighbourhood. + * \param pBoxing number of cells along each axis; must be >= 1; e.g. if 100 then acceleration grid will have 100*100*100 = 10**6 cells. + * \return the name of each part. + * \throw RuntimeException if any error occurs. + */ + std::vector decimePartition( + const char* pPartName, + const char* pFieldName, + int pFieldIt, + const char* pFilterName, + double pTmed, + double pTlow, + double pRadius, + int pBoxing); + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Saves the associated MED file if necessary. + * \throw IOException if any i/o error occurs. + */ + void save(); + + /** + * Dumps any Obj to the given output stream. + * \param pOs any output stream. + * \param pO any Obj. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, Obj& pO); + +private: + + /** + * Returns the list of parts contained in the current distributed mesh. + * \return the list of parts contained in the current distributed mesh. + * \throw IllegalStateException if the distributed mesh does not still exist. + */ + std::vector getListParts() const; + +private: + + std::string mMEDfilename; /**< Name of the MED file: sequential or distributed. */ + std::string mMeshName; /**< Mesh to be partitionned. */ + ObjState mState; /**< State of this object. */ + MeshDis* mMeshDis; /**< Distributed mesh. */ + + +private: + + // do not allow copy constructor + Obj(const Obj&); + + // do not allow copy + Obj& operator=(const Obj&); + + // do not allow operator == + bool operator==(const Obj&); + +}; // class Obj + + +} // namespace MULTIPR + + +#endif // MULTIPR_OBJ_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_PointOfField.hxx b/src/MULTIPR/MULTIPR_PointOfField.hxx new file mode 100644 index 0000000..907aab4 --- /dev/null +++ b/src/MULTIPR/MULTIPR_PointOfField.hxx @@ -0,0 +1,100 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_PointOfField.hxx + * + * \brief Class PointOfField used for decimation. PointOfField = a point in a field = coordinates + value. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_POINTOFFIELD_HXX +#define MULTIPR_POINTOFFIELD_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + +extern "C" +{ + #include "med.h" +} + + +namespace multipr +{ + + +//***************************************************************************** +// Class PointOfField +//***************************************************************************** + +class PointOfField +{ +public: + + /** + * Builds an empty set of elements (default constructor). + */ + PointOfField() { reset(); } + + /** + * Constructor. + * \param pX x-coordinate of the point. + * \param pY y-coordinate of the point. + * \param pZ z-coordinate of the point. + * \param pVal value of the field at the given point. + */ + PointOfField(med_float pX, med_float pY, med_float pZ, med_float pVal) + { + mXYZ[0] = pX; + mXYZ[1] = pY; + mXYZ[2] = pZ; + mVal = pVal; + } + + /** + * Destructor. Removes everything. + */ + ~PointOfField() { reset(); } + + /** + * Resets this object in its state by default (empty). + */ + void reset() + { + mXYZ[0] = std::numeric_limits::quiet_NaN(); + mXYZ[1] = std::numeric_limits::quiet_NaN(); + mXYZ[2] = std::numeric_limits::quiet_NaN(); + mVal = std::numeric_limits::quiet_NaN(); + } + + /** + * Dumps any PointOfField to the given output stream. + * \param pOs any output stream. + * \param pP any PointOfField. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, PointOfField& pP) + { + pOs << "[ " << pP.mXYZ[0] << " ; " << pP.mXYZ[1] << " ; " << pP.mXYZ[2] << "]: " << pP.mVal; + return pOs; + } + +public: + + med_float mXYZ[3]; /**< 3D-position. */ + med_float mVal; /**< Value of the field on this point. */ + +}; // class PointOfField + + +} // namespace multipr + + +#endif // MULTIPR_FIELDPOINT_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_Profil.cxx b/src/MULTIPR/MULTIPR_Profil.cxx new file mode 100644 index 0000000..89dfea4 --- /dev/null +++ b/src/MULTIPR/MULTIPR_Profil.cxx @@ -0,0 +1,160 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Profil.cxx + * + * \brief see MULTIPR_Profil.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_Profil.hxx" +#include "MULTIPR_Exceptions.hxx" + +#include + +using namespace std; + + +namespace multipr +{ + + +//***************************************************************************** +// Class Profil implementation +//***************************************************************************** + +Profil::Profil() +{ + reset(); +} + + +Profil::~Profil() +{ + reset(); +} + + +void Profil::reset() +{ + mName[0] = '\0'; + mTable.clear(); +} + + +void Profil::create(const char* pName) +{ + if (pName == NULL) throw NullArgumentException("", __FILE__, __LINE__); + + reset(); + strcpy(mName, pName); +} + + + +const char* Profil::getName() const +{ + return mName; +} + + +med_int Profil::get(med_int pIndex) const +{ + if ((pIndex < 0) || (pIndex >= med_int(mTable.size()))) throw IndexOutOfBoundsException("", __FILE__, __LINE__); + + return mTable[pIndex]; +} + + +void Profil::add(med_int pElt) +{ + mTable.push_back(pElt); +} + + +void Profil::readMED(med_idt pMEDfile, med_int pIndexProfil) +{ + if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__); + if (pIndexProfil < 1) throw IllegalArgumentException("", __FILE__, __LINE__); + + reset(); + + med_int numData; + med_err ret = MEDprofilInfo( + pMEDfile, + pIndexProfil, + mName, + &numData); + + if (ret != 0) throw IOException("", __FILE__, __LINE__); + + med_int* dataTmp = new med_int[numData]; + + ret = MEDprofilLire( + pMEDfile, + dataTmp, + mName); + + if (ret != 0) throw IOException("", __FILE__, __LINE__); + + for (int itData = 0 ; itData < numData ; itData++) + { + mTable.push_back(dataTmp[itData]); + } + + delete[] dataTmp; +} + + +void Profil::writeMED(med_idt pMEDfile) +{ + if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__); + if (strlen(mName) > MED_TAILLE_NOM) throw IllegalStateException("", __FILE__, __LINE__); + if (mTable.size() == 0) throw IllegalStateException("", __FILE__, __LINE__); + + med_int* dataTmp = new med_int[mTable.size()]; + for (unsigned itData = 0 ; itData < mTable.size() ; itData++) + { + dataTmp[itData] = mTable[itData]; + } + + med_err ret = MEDprofilEcr( + pMEDfile, + dataTmp, + mTable.size(), + mName); + + if (ret != 0) throw IOException("", __FILE__, __LINE__); + + delete[] dataTmp; +} + + +ostream& operator<<(ostream& pOs, Profil& pP) +{ + pOs << "Profil:" << endl; + pOs << " Name=|" << pP.mName << "|" << endl; + pOs << " Size=" << pP.mTable.size() << endl; + + pOs << " Entities=["; + for (unsigned itElt = 0; itElt < pP.mTable.size() ; itElt++) + { + pOs << pP.mTable[itElt] << " "; + } + pOs << "]"; + + return pOs; +} + + +} // namespace multipr + +// EOF diff --git a/src/MULTIPR/MULTIPR_Profil.hxx b/src/MULTIPR/MULTIPR_Profil.hxx new file mode 100644 index 0000000..6a12b25 --- /dev/null +++ b/src/MULTIPR/MULTIPR_Profil.hxx @@ -0,0 +1,140 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Profil.hxx + * + * \brief Class Profil used to managed MED profil. + * Profil is just a list of indices related to elements (NODES, CELLS). + * !!! currently not used !!! + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_PROFIL_HXX +#define MULTIPR_PROFIL_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + +extern "C" +{ + #include "med.h" +} + +#include + + +namespace multipr +{ + + +//***************************************************************************** +// Class Profil +//***************************************************************************** + +class Profil +{ +public: + + /** + * Builds an empty profil (default constructor). + */ + Profil(); + + /** + * Destructor. Removes everything. + */ + ~Profil(); + + /** + * Resets this object in its state by default (empty). Cleans memory. + */ + void reset(); + + /** + * Creates a profil from its name (reset before). + * \param pName name of the profil to be created. + * \throw NullArgumentException if pName is NULL. + */ + void create(const char* pName); + + //--------------------------------------------------------------------- + // Basic accessors/mutators + //--------------------------------------------------------------------- + + /** + * Returns the name of this profil. + * \return the name of this profil. + */ + const char* getName() const; + + /** + * Returns the nth elements of this profil. + * \param pIndex index of the element to get; must be in [0..NUMBER_OF_ELEMENTS-1]. + * \return the nth elements of this profil. + * \throw IndexOutOfBoundsException if index is invalid. + */ + med_int get(med_int pIndex) const; + + /** + * Adds a new element to this profil. + * \param pElt element to be added; must be >= 1. + */ + void add(med_int pElt); + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Reads a Profil from a MED file. + * \param pMEDfile any valid MED file opened for reading. + * \param pIndexProfil index of the profil to be read; must be >= 1. + * \throw IOException if any i/o error occurs. + */ + void readMED(med_idt pMEDfile, med_int pIndexProfil); + + /** + * Writes this profil to a MED file. + * \param pMEDfile any valid MED file opened for writing. + * \throw IOException if any i/o error occurs. + */ + void writeMED(med_idt pMEDfile); + + /** + * Dumps any Profil to the given output stream. + * \param pOs any output stream. + * \param pP any Profil. + * \return the output stream pOs. + */ + friend std::ostream& operator<<(std::ostream& pOs, Profil& pP); + +private: + + char mName[MED_TAILLE_NOM + 1]; /**< Name of the profil. */ + std::vector mTable; /**< Table of elements. */ + +private: + + // do not allow copy constructor + Profil(const Profil&); + + // do not allow copy + Profil& operator=(const Profil&); + + // do not allow operator == + bool operator==(const Profil&); + +}; // class Profil + + +} // namespace MULTIPR + + +#endif // MULTIPR_PROFIL_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_ProgressCallback.hxx b/src/MULTIPR/MULTIPR_ProgressCallback.hxx new file mode 100644 index 0000000..f8e0ff6 --- /dev/null +++ b/src/MULTIPR/MULTIPR_ProgressCallback.hxx @@ -0,0 +1,82 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_ProgressCallback.hxx + * + * \brief Class MULTIPR_ProgressCallback + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_PROGRESS_CALLBACK_HXX +#define MULTIPR_PROGRESS_CALLBACK_HXX + +//***************************************************************************** +// Includes section +//***************************************************************************** + + +//***************************************************************************** +// Class MULTIPR_ProgressCallback +// Used to provide feedback on the progress of a slow operation. +//***************************************************************************** + +class MULTIPR_ProgressCallback +{ +public: + + /** + * Builds a new MULTIPR_ProgressCallback (default constructor). + */ + MULTIPR_ProgressCallback() { init(100); } + + /** + * Destructor. Removes everything. + */ + ~MULTIPR_ProgressCallback() { /* do nothing */ } + + /** + * Starts to provide feedback on the progress of a slow operation. + * \param pTaskTitle name of the task to be monitored. + * \param pNumSteps number of steps in the task. + */ + virtual void start(const char* pTaskTitle, int pNumSteps) = 0; + + /** + * Moves on the current amount of progress made. + */ + void moveOn() { mCurrentStep++; float percent = float(mCurrentStep)/float(mTotalSteps)*100.0f; progress(percent); } + + /** + * Termines to provide feedback. + */ + virtual void done() = 0; + +protected: + + /** + * Resets this progress callback. + * \param pNumSteps number of steps in the task to be monitored. + */ + void init(int pNumSteps) { mCurrentStep = 0; mTotalSteps = pNumSteps; } + + /** + * Callback. Called on each progress. + * \param pPercent percent accomplished. + */ + virtual void progress(float pPercent) = 0; + +private: + + int mCurrentStep; + int mTotalSteps; + +}; // class MULTIPR_ProgressCallback + + +#endif // MULTIPR_PROGRESS_CALLBACK_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_Utils.cxx b/src/MULTIPR/MULTIPR_Utils.cxx new file mode 100644 index 0000000..ad6b01f --- /dev/null +++ b/src/MULTIPR/MULTIPR_Utils.cxx @@ -0,0 +1,226 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Utils.cxx + * + * \brief see MULTIPR_Utils.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_Utils.hxx" +#include "MULTIPR_Exceptions.hxx" + +#include + +using namespace std; + + +//***************************************************************************** +// Implementation +//***************************************************************************** + +void multipr::trim(char* pStr, char pChar) +{ + int len = strlen(pStr) - 1; + int p = len; + while (pStr[p] == pChar) + { + p--; + } + if (p != len) + { + pStr[p + 1] = '\0'; + } +} + + +string multipr::removeExtension(const char* pFilename, const char* pExtension) +{ + string strPrefix(pFilename); + strPrefix.erase(strPrefix.rfind(pExtension), strlen(pExtension)); + + return strPrefix; +} + + +void multipr::printArray2D( + const med_float* pData, + const int pNumElt, + const int pDimElt, + const char* pPrefix) +{ + for (int itElt = 0 ; itElt < pNumElt ; itElt++) + { + cout << pPrefix << " " << (itElt + 1) << ": "; + for (int itDim = 0 ; itDim < pDimElt ; itDim++) + { + cout << pData[itElt * pDimElt + itDim] << " "; + } + cout << endl; + } +} + + +string multipr::realToString(med_float mV) +{ + char str[32]; + sprintf(str, "%lf", mV); + trim(str, '0'); + int len = strlen(str); + if (str[len - 1] == '.') + { + str[len] = '0'; + str[len + 1] = '\0'; + } + return string(str); +} + + +vector multipr::getListMeshes(const char* pMEDfilename) +{ + if (pMEDfilename == NULL) throw multipr::NullArgumentException("", __FILE__, __LINE__); + + vector res; + med_err ret; + + //--------------------------------------------------------------------- + // Open MED file (READ_ONLY) + //--------------------------------------------------------------------- + med_idt file = MEDouvrir(const_cast(pMEDfilename), MED_LECTURE); // open MED file for reading + if (file <= 0) throw multipr::IOException("MED file not found or not a sequential MED file", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Read name of meshes + //--------------------------------------------------------------------- + med_int nbMeshes = MEDnMaa(file); + if (nbMeshes <= 0) throw multipr::IOException("i/o error while reading number of meshes in MED file", __FILE__, __LINE__); + + // for each mesh in the file (warning: first mesh is number 1) + for (int itMesh = 1 ; itMesh <= nbMeshes ; itMesh++) + { + char meshName[MED_TAILLE_NOM + 1]; + + int meshDim; + med_maillage meshType; + char meshDesc[MED_TAILLE_DESC + 1]; + + ret = MEDmaaInfo( + file, + itMesh, + meshName, + &meshDim, + &meshType, + meshDesc); + + if (ret != 0) throw multipr::IOException("i/o error while reading mesh information in MED file", __FILE__, __LINE__); + + res.push_back(meshName); + } + + //--------------------------------------------------------------------- + // Close the MED file + //--------------------------------------------------------------------- + ret = MEDfermer(file); + if (ret != 0) throw multipr::IOException("i/o error while closing MED file", __FILE__, __LINE__); + + return res; +} + + +vector > multipr::getListFields(const char* pMEDfilename) +{ + if (pMEDfilename == NULL) throw multipr::NullArgumentException("", __FILE__, __LINE__); + + vector > res; + med_err ret; + + //--------------------------------------------------------------------- + // Open MED file (READ_ONLY) + //--------------------------------------------------------------------- + med_idt file = MEDouvrir(const_cast(pMEDfilename), MED_LECTURE); // open MED file for reading + if (file <= 0) throw multipr::IOException("MED file not found or not a sequential MED file", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // Read number of fields + //--------------------------------------------------------------------- + med_int numFields = MEDnChamp(file, 0); + if (numFields <= 0) throw IOException("", __FILE__, __LINE__); + + //--------------------------------------------------------------------- + // For each field, read its name + //--------------------------------------------------------------------- + for (int itField = 1 ; itField <= numFields ; itField++) + { + char name[MED_TAILLE_NOM + 1]; + med_type_champ type; + + med_int numComponents = MEDnChamp(file, itField); + + if (numComponents < 0) throw IOException("", __FILE__, __LINE__); + + // collect scalar field only (not vectorial fields) + if (numComponents != 1) + continue; + + char* strComponent = new char[numComponents * MED_TAILLE_PNOM + 1]; + char* strUnit = new char[numComponents * MED_TAILLE_PNOM + 1]; + + strComponent[0] = '\0'; + strUnit[0] = '\0'; + + med_err ret = MEDchampInfo( + file, + itField, + name, + &(type), + strComponent, + strUnit, + numComponents); + + if (ret != 0) throw IOException("", __FILE__, __LINE__); + + delete[] strUnit; + delete[] strComponent; + + med_int numTimeStep = MEDnPasdetemps( + file, + name, + MED_NOEUD, + (med_geometrie_element) 0); + + if (numTimeStep < 0) throw IOException("", __FILE__, __LINE__); + + if (numTimeStep == 0) + { + numTimeStep = MEDnPasdetemps( + file, + name, + MED_MAILLE, + MED_TETRA10); + + if (numTimeStep < 0) throw IOException("", __FILE__, __LINE__); + + } + + res.push_back(make_pair(name, numTimeStep)); + } + + //--------------------------------------------------------------------- + // Close the MED file + //--------------------------------------------------------------------- + ret = MEDfermer(file); + if (ret != 0) throw multipr::IOException("i/o error while closing MED file", __FILE__, __LINE__); + + return res; +} + + +// EOF diff --git a/src/MULTIPR/MULTIPR_Utils.hxx b/src/MULTIPR/MULTIPR_Utils.hxx new file mode 100644 index 0000000..01b5a73 --- /dev/null +++ b/src/MULTIPR/MULTIPR_Utils.hxx @@ -0,0 +1,94 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_Utils.hxx + * + * \brief Some useful miscellaneous tools. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef MULTIPR_UTILS_HXX +#define MULTIPR_UTILS_HXX + +extern "C" +{ + #include "med.h" +} + +#include +#include + + +namespace multipr +{ + + +/** + * Removes all the pChar at the end of the string. + * \param pStr any valid C string ending with the char '\0'. + * \param pChar any char; SPACE by default. + * \return the same string where the ending spaces have been removed. + */ +void trim(char* pStr, char pChar=' '); + + +/** + * Removes the extension (suffix) of a filename. + * Example: removeExtension("agregat100grains_12pas.med", ".med") -> "agregat100grains_12pas" + * \param pPilename any valid C string ending with the char '\0'. + * \param pExtension any valid C string ending with the char '\0'. + * \return the filename without extension. + */ +std::string removeExtension(const char* pFilename, const char* pExtension); + + +/** + * Prints all the elements of a 2D array. + * \param pData all the data (should contain pNumberOfElements * pDimOfElements values) + * \param pNumElt number of elements to display. + * \param pDimElt Dimension of elements. + * \param pPrefix string to display before each element. + */ +void printArray2D( + const med_float* pData, + const int pNumElt, + const int pDimElt, + const char* pPrefix); + + +/** + * Converts any float value to a string (remove unecessary 0). + * \param mV any float value. + */ +std::string realToString(med_float mV); + + +/** + * Returns the name of all meshes contained in a sequential MED file. + * \param pMEDfilename name of any valid sequential MED file; must not be NULL. + * \return a list of mesh names. + * \throw NullArgumentException if pMEDfilename is NULL. + * \throw IOException if any other error occurs while reading MED file. + */ + std::vector getListMeshes(const char* pMEDfilename); + + + /** + * For each field in a sequential MED file, returns its name and the related number of iterations. + * \param pMEDfilename name of any valid sequential MED file; must not be NULL. + * \return a list of (name, #iterations). + * \throw NullArgumentException if pMEDfilename is NULL. + * \throw IOException if any other error occurs while reading MED file. + */ + std::vector > getListFields(const char* pMEDfilename); + +} // namespace MULTIPR + + +#endif // MULTIPR_UTILS_HXX + +// EOF diff --git a/src/MULTIPR/MULTIPR_i.cxx b/src/MULTIPR/MULTIPR_i.cxx new file mode 100644 index 0000000..e9dd3a2 --- /dev/null +++ b/src/MULTIPR/MULTIPR_i.cxx @@ -0,0 +1,485 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_i.cxx + * + * \brief see MULTIPR_i.hxx + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + + +//***************************************************************************** +// Includes section +//***************************************************************************** + +using namespace std; + +#include "MULTIPR_i.hxx" +#include "utilities.h" + +#include + +#include "MULTIPR_API.hxx" +#include "MULTIPR_Exceptions.hxx" + + +//***************************************************************************** +// Class MULTIPR_Gen_i implementation +//***************************************************************************** + +MULTIPR_Gen_i::MULTIPR_Gen_i( + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + PortableServer::ObjectId* contId, + const char* instanceName, + const char* interfaceName) : + Engines_Component_i(orb, poa, contId, instanceName, interfaceName) +{ + MESSAGE("activate object"); + _thisObj = this ; + _id = _poa->activate_object(_thisObj); +} + + +MULTIPR_Gen_i::~MULTIPR_Gen_i() +{ +} + + +//----------------------------------------------------------------------------- +// High level API +//----------------------------------------------------------------------------- + +char* MULTIPR_Gen_i::getVersion() + throw (SALOME::SALOME_Exception) +{ + return CORBA::string_dup(multipr::getVersion()); +} + + +void MULTIPR_Gen_i::partitionneDomaine( + const char* medFilename, + const char* meshName) + throw (SALOME::SALOME_Exception) +{ + try + { + multipr::partitionneDomaine(medFilename, meshName); + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + THROW_SALOME_CORBA_EXCEPTION("partitionneDomaine() failed", SALOME::INTERNAL_ERROR); + } +} + + +void MULTIPR_Gen_i::partitionneGrain( + const char* medFilename, + const char* partName, + CORBA::Long nbParts, + CORBA::Long partitionner) + throw (SALOME::SALOME_Exception) +{ + try + { + multipr::partitionneGrain( + medFilename, + partName, + nbParts, + partitionner); + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + THROW_SALOME_CORBA_EXCEPTION("partitionneGrain() failed", SALOME::INTERNAL_ERROR); + } +} + + +void MULTIPR_Gen_i::decimePartition( + const char* medFilename, + const char* partName, + const char* fieldName, + CORBA::Long fieldIt, + const char* filterName, + CORBA::Double tmed, + CORBA::Double tlow, + CORBA::Double radius, + CORBA::Long boxing) + throw (SALOME::SALOME_Exception) +{ + /* + // debug + cout << "File : " << medFilename << endl; + cout << "Part : " << partName << endl; + cout << "Field : " << fieldName << endl; + cout << "It : " << fieldIt << endl; + cout << "Filter: " << filterName << endl; + cout << "Med : " << tmed << endl; + cout << "Low : " << tlow << endl; + cout << "Rad : " << radius << endl; + cout << "Box : " << boxing << endl; + cout << endl; + */ + + try + { + multipr::decimePartition( + medFilename, + partName, + fieldName, + fieldIt, + filterName, + tmed, + tlow, + radius, + boxing); + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + THROW_SALOME_CORBA_EXCEPTION("decimePartition() failed", SALOME::INTERNAL_ERROR); + } +} + + +//----------------------------------------------------------------------------- +// Low level API +//----------------------------------------------------------------------------- + +MULTIPR_ORB::MULTIPR_Obj_ptr MULTIPR_Gen_i::getObject(const char* medFilename) + throw (SALOME::SALOME_Exception) +{ + MULTIPR_Obj_i* obj = new MULTIPR_Obj_i(medFilename); + return obj->POA_MULTIPR_ORB::MULTIPR_Obj::_this(); +} + + +MULTIPR_Obj_i::MULTIPR_Obj_i(const char* medFilename) + throw (SALOME::SALOME_Exception) +{ + mObj = new multipr::Obj(); + mBoxing = 100; + + try + { + cout << "Load " << medFilename << endl; + mObj->create(medFilename); + cout << endl; + } + catch (multipr::RuntimeException& e) + { + delete mObj; + mObj = NULL; + e.dump(cout); + THROW_SALOME_CORBA_EXCEPTION("Unable to create object", SALOME::INTERNAL_ERROR); + } +} + + +MULTIPR_Obj_i::~MULTIPR_Obj_i() +{ + if (mObj != NULL) + { + delete mObj; + mObj = NULL; + } +} + + +CORBA::Boolean MULTIPR_Obj_i::isValidSequentialMEDFile() + throw (SALOME::SALOME_Exception) +{ + if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR); + + return mObj->isValidSequentialMEDFile(); +} + + +CORBA::Boolean MULTIPR_Obj_i::isValidDistributedMEDFile() + throw (SALOME::SALOME_Exception) +{ + if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR); + + return mObj->isValidDistributedMEDFile(); +} + + +void MULTIPR_Obj_i::setMesh(const char* meshName) + throw (SALOME::SALOME_Exception) +{ + if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR); + + try + { + mObj->setMesh(meshName); + + cout << "Set mesh OK" << endl << endl; + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + THROW_SALOME_CORBA_EXCEPTION("Unable to set mesh", SALOME::INTERNAL_ERROR); + } +} + + +void MULTIPR_Obj_i::setBoxing(CORBA::Long pBoxing) + throw (SALOME::SALOME_Exception) +{ + if (mBoxing < 0) THROW_SALOME_CORBA_EXCEPTION("Invalid boxing parameter; should be >= 1", SALOME::INTERNAL_ERROR); + if (mBoxing > 200) THROW_SALOME_CORBA_EXCEPTION("Invalid boxing parameter; should be <= 200", SALOME::INTERNAL_ERROR); + + mBoxing = pBoxing; +} + + +MULTIPR_ORB::string_array* MULTIPR_Obj_i::getMeshes() + throw (SALOME::SALOME_Exception) +{ + if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR); + + MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array(); + + try + { + std::vector listMeshes = mObj->getMeshes(); + mySeq->length(listMeshes.size()); + + for (int i = 0 ; i < listMeshes.size() ; i++) + { + mySeq[i] = CORBA::string_dup(listMeshes[i].c_str()); + } + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + THROW_SALOME_CORBA_EXCEPTION("Unable to get meshes", SALOME::INTERNAL_ERROR); + } + + return mySeq._retn(); +} + + +MULTIPR_ORB::string_array* MULTIPR_Obj_i::getFields() + throw (SALOME::SALOME_Exception) +{ + if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR); + + MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array(); + + try + { + std::vector listFields = mObj->getFields(); + mySeq->length(listFields.size()); + + for (int i = 0 ; i < listFields.size() ; i++) + { + mySeq[i] = CORBA::string_dup(listFields[i].c_str()); + } + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + THROW_SALOME_CORBA_EXCEPTION("Unable to get fields", SALOME::INTERNAL_ERROR); + } + + return mySeq._retn(); +} + + +CORBA::Long MULTIPR_Obj_i::getTimeStamps(const char* fieldName) + throw (SALOME::SALOME_Exception) +{ + if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR); + + try + { + return mObj->getTimeStamps(fieldName); + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + THROW_SALOME_CORBA_EXCEPTION("Unable to get time stamps", SALOME::INTERNAL_ERROR); + } +} + + +MULTIPR_ORB::string_array* MULTIPR_Obj_i::getParts() + throw (SALOME::SALOME_Exception) +{ + if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR); + + MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array(); + + try + { + std::vector listParts = mObj->getParts(); + mySeq->length(listParts.size()); + + for (int i = 0 ; i < listParts.size() ; i++) + { + mySeq[i] = CORBA::string_dup(listParts[i].c_str()); + } + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + THROW_SALOME_CORBA_EXCEPTION("Unable to get parts", SALOME::INTERNAL_ERROR); + } + + return mySeq._retn(); +} + + +char* MULTIPR_Obj_i::getPartInfo(const char* pPartName) + throw (SALOME::SALOME_Exception) +{ + if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR); + + return CORBA::string_dup(mObj->getPartInfo(pPartName).c_str()); +} + + +MULTIPR_ORB::string_array* MULTIPR_Obj_i::partitionneDomaine() + throw (SALOME::SALOME_Exception) +{ + if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR); + + MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array(); + + try + { + std::vector listParts = mObj->partitionneDomaine(); + mySeq->length(listParts.size()); + + for (int i = 0 ; i < listParts.size() ; i++) + { + mySeq[i] = CORBA::string_dup(listParts[i].c_str()); + } + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + THROW_SALOME_CORBA_EXCEPTION("Unable to partition mesh", SALOME::INTERNAL_ERROR); + } + + return mySeq._retn(); +} + + +MULTIPR_ORB::string_array* MULTIPR_Obj_i::partitionneGrain( + const char* pPartName, + CORBA::Long pNbParts, + CORBA::Long pPartitionner) + throw (SALOME::SALOME_Exception) +{ + if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR); + + MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array(); + + try + { + std::vector listParts = mObj->partitionneGrain( + pPartName, + pNbParts, + pPartitionner); + + mySeq->length(listParts.size()); + + for (int i = 0 ; i < listParts.size() ; i++) + { + mySeq[i] = CORBA::string_dup(listParts[i].c_str()); + } + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + THROW_SALOME_CORBA_EXCEPTION("Unable to partition group", SALOME::INTERNAL_ERROR); + } + + return mySeq._retn(); +} + + +MULTIPR_ORB::string_array* MULTIPR_Obj_i::decimePartition( + const char* pPartName, + const char* pFieldName, + CORBA::Long pFieldIt, + const char* pFilterName, + CORBA::Double pTmed, + CORBA::Double pTlow, + CORBA::Double pRadius) + throw (SALOME::SALOME_Exception) +{ + if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR); + + MULTIPR_ORB::string_array_var mySeq = new MULTIPR_ORB::string_array(); + + try + { + std::vector listParts = mObj->decimePartition( + pPartName, + pFieldName, + pFieldIt, + pFilterName, + pTmed, + pTlow, + pRadius, + mBoxing); + + mySeq->length(listParts.size()); + + for (int i = 0 ; i < listParts.size() ; i++) + { + mySeq[i] = CORBA::string_dup(listParts[i].c_str()); + } + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + THROW_SALOME_CORBA_EXCEPTION("Unable to decimate", SALOME::INTERNAL_ERROR); + } + + return mySeq._retn(); +} + + +void MULTIPR_Obj_i::save() + throw (SALOME::SALOME_Exception) +{ + if (mObj == NULL) THROW_SALOME_CORBA_EXCEPTION("No associated MED file", SALOME::INTERNAL_ERROR); + + try + { + mObj->save(); + + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + THROW_SALOME_CORBA_EXCEPTION("Unable to save MED file", SALOME::INTERNAL_ERROR); + } +} + + +extern "C" +{ + PortableServer::ObjectId* MULTIPREngine_factory( + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + PortableServer::ObjectId * contId, + const char* instanceName, + const char* interfaceName) + { + MESSAGE("PortableServer::ObjectId* MULTIPREngine_factory()"); + SCRUTE(interfaceName); + MULTIPR_Gen_i* myMULTIPR = new MULTIPR_Gen_i(orb, poa, contId, instanceName, interfaceName); + return myMULTIPR->getId(); + } +} diff --git a/src/MULTIPR/MULTIPR_i.hxx b/src/MULTIPR/MULTIPR_i.hxx new file mode 100644 index 0000000..73bd6cf --- /dev/null +++ b/src/MULTIPR/MULTIPR_i.hxx @@ -0,0 +1,273 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_i.hxx + * + * \brief C++ implementation of the CORBA interface of the MULTIPR module. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#ifndef __MULTIPR_IMPLEMENTATION_CORBA__ +#define __MULTIPR_IMPLEMENTATION_CORBA__ + +#include +#include CORBA_SERVER_HEADER(MULTIPR) +#include "SALOME_Component_i.hxx" +#include "Utils_CorbaException.hxx" + +#include "MULTIPR_Obj.hxx" + + +//***************************************************************************** +// Class MULTIPR_Obj_i +// C++ implementation of the MULTIPR_Obj CORBA interface +// This class is a wrapper to encapsulate MULTIPR_Obj +//***************************************************************************** + +class MULTIPR_Obj_i : + public POA_MULTIPR_ORB::MULTIPR_Obj +{ + +public: + + /** + * Constructor. + * Associate a MED file (sequential or distributed) with this object. + * \param pMEDFilename MED file to be associated with this object. + */ + MULTIPR_Obj_i(const char* pMEDFilename) + throw (SALOME::SALOME_Exception); + + /** + * Destructor. + */ + virtual ~MULTIPR_Obj_i(); + + //--------------------------------------------------------------------- + // Basic accessors/mutators + //-------------------------------------------------------------------- + + /** + * Returns true iff this obj represents a valid sequential MED file. + * \return true iff this obj represents a valid sequential MED file. + */ + CORBA::Boolean isValidSequentialMEDFile() + throw (SALOME::SALOME_Exception); + + /** + * Returns true iff this obj represents a valid distributed MED file. + * \return true iff this obj represents a valid distributed MED file. + */ + CORBA::Boolean isValidDistributedMEDFile() + throw (SALOME::SALOME_Exception); + + /** + * Defines the mesh to be processed. + * \param pMeshName name of the mesh to be partitionned. + */ + void setMesh(const char* pMeshName) + throw (SALOME::SALOME_Exception); + + /** + * Sets boxing parameters for decimation (100 by default). + * \param pBoxing number of cells along each axis of the grid (= acceleration structure) ; should be in [1..200]. + */ + void setBoxing(CORBA::Long pBoxing) + throw (SALOME::SALOME_Exception); + + /** + * Returns the list of meshes contained in the sequential MED file. + * Assumes this object encapsulates a sequential MED file. + * \return the list of meshes contained in the sequential MED file. + */ + MULTIPR_ORB::string_array* getMeshes() + throw (SALOME::SALOME_Exception); + + /** + * Returns the list of fields contained in the sequential MED file. + * Assumes this object encapsulates a sequential MED file. + * \return the list of fields contained in the sequential MED file. + */ + MULTIPR_ORB::string_array* getFields() + throw (SALOME::SALOME_Exception); + + /** + * Returns the number of timestamps for a given field. + * Assumes this object encapsulates a sequential MED file. + * \param pFieldName name of any field. + * \return the number of timestamps for a given field; 0 if field not found. + */ + CORBA::Long getTimeStamps(const char* pFieldName) + throw (SALOME::SALOME_Exception); + + /** + * Returns the name of all partitions. + * Assumes this object encapsulates a distributed MED file. + * \return the name of all partitions. + */ + MULTIPR_ORB::string_array* getParts() + throw (SALOME::SALOME_Exception); + + /** + * Returns all information abour a part. + * Assumes this object encapsulates a distributed MED file. + * \param pPartName name of the part. + * \return information about a part. + */ + char* getPartInfo(const char* pPartName) + throw (SALOME::SALOME_Exception); + + //--------------------------------------------------------------------- + // Algorithms + //--------------------------------------------------------------------- + + /** + * Creates a distributed MED file (v2.3) by extracting all the groups from the current mesh of the current MED sequential MED file. + * Assumes: + * - the file is in MED format and can be read using MED file v2.3. + * - the file is sequential (not a distributed MED). + * - the file only contains TETRA10 elements (dimension of space and mesh is 3). + * - the file have no profil. + * \return the name of each part. + */ + MULTIPR_ORB::string_array* partitionneDomaine() + throw (SALOME::SALOME_Exception); + + /** + * Creates a distributed MED file (V2.3) by splitting a group of a MED file previously created by partitionneDomaine. + * Assumes: + * - the file is a distributed MED file, previously created by partitionneDomaine() + * (=> each part only contain 1 mesh, TETRA10 elements only) + * - nbPart > 1 + * \param pPartName name of the part to be splitted. + * \param pNbParts number of parts; must be > 1. + * \param pPartitionner use value 0=MULTIPR_METIS for Metis or 1=MULTIPR_SCOTCH for Scotch. + * \return the name of each part. + */ + MULTIPR_ORB::string_array* partitionneGrain( + const char* pPartName, + CORBA::Long pNbParts, + CORBA::Long pPartitionner) + throw (SALOME::SALOME_Exception); + + /** + * Creates 3 resolutions of the given part of a distributed MED file (V2.3). + * Assumes: + * - the file is a distributed MED file, previously created by partitionneDomaine() or partitionneGrain() + * (=> each part only contain 1 mesh, TETRA10 elements only) + * \param pPartName name of the part to be decimated. + * \param pFieldName name of the field used for decimation. + * \param pFieldIt iteration (time step) of the field. + * \param pFilterName name of the filter to be used. + * \param pTmed threshold used for medium resolution. + * \param pTlow threshold used for low resolution; tmed must be less than tlow + * \param pTadius radius used to determine the neighbourhood. + * \return the name of each part. + */ + MULTIPR_ORB::string_array* decimePartition( + const char* pPartName, + const char* pFieldName, + CORBA::Long pFieldIt, + const char* pFilterName, + CORBA::Double pTmed, + CORBA::Double pTlow, + CORBA::Double pRadius) + throw (SALOME::SALOME_Exception); + + //--------------------------------------------------------------------- + // I/O + //--------------------------------------------------------------------- + + /** + * Saves the associated MED file if necessary. + */ + void save() + throw (SALOME::SALOME_Exception); + +private: + + /** + * The associated MULTIPR object. + */ + multipr::Obj* mObj; + + /** + * Boxing paremeter: number of cells along each axis. + * E.g. if mBoxing=10 then total number of cells = 10*10*10 = 1000. + * By default, mBoxing=100. + */ + int mBoxing; + +}; + + +//***************************************************************************** +// Class MULTIPR_Gen_i +// C++ implementation of the MULTIPR_Gen CORBA interface +//***************************************************************************** + +class MULTIPR_Gen_i : + public POA_MULTIPR_ORB::MULTIPR_Gen, + public Engines_Component_i +{ + +public: + + MULTIPR_Gen_i( + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + PortableServer::ObjectId* contId, + const char* instanceName, + const char* interfaceName); + + virtual ~MULTIPR_Gen_i(); + + char* getVersion() + throw (SALOME::SALOME_Exception); + + void partitionneDomaine( + const char* medFilename, + const char* meshName) + throw (SALOME::SALOME_Exception); + + void partitionneGrain( + const char* medFilename, + const char* partName, + CORBA::Long nbParts, + CORBA::Long partitionner) + throw (SALOME::SALOME_Exception); + + void decimePartition( + const char* medFilename, + const char* partName, + const char* fieldName, + CORBA::Long fieldIt, + const char* filterName, + CORBA::Double tmed, + CORBA::Double tlow, + CORBA::Double radius, + CORBA::Long boxing) + throw (SALOME::SALOME_Exception); + + MULTIPR_ORB::MULTIPR_Obj_ptr getObject(const char* medFilename) + throw (SALOME::SALOME_Exception); +}; + + +extern "C" PortableServer::ObjectId* MULTIPREngine_factory( + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + PortableServer::ObjectId * contId, + const char* instanceName, + const char* interfaceName); + +#endif // __MULTIPR_IMPLEMENTATION_CORBA__ diff --git a/src/MULTIPR/Makefile.in b/src/MULTIPR/Makefile.in new file mode 100644 index 0000000..5599f79 --- /dev/null +++ b/src/MULTIPR/Makefile.in @@ -0,0 +1,56 @@ +# Copyright (C) 2005 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +# Source path + +top_srcdir=@top_srcdir@ +top_builddir=../.. +srcdir=@srcdir@ +VPATH=.:@srcdir@:@top_srcdir@/idl + +MACHINE=PCLINUX + +@COMMENCE@ + +# Libraries targets + +LIB = libMULTIPREngine.la +LIB_SRC = MULTIPR_i.cxx MULTIPR_API.cxx MULTIPR_Mesh.cxx MULTIPR_Profil.cxx MULTIPR_GaussLoc.cxx MULTIPR_Field.cxx MULTIPR_Nodes.cxx MULTIPR_Elements.cxx MULTIPR_Family.cxx MULTIPR_MeshDis.cxx MULTIPR_DecimationFilter.cxx MULTIPR_DecimationAccel.cxx MULTIPR_Utils.cxx MULTIPR_Obj.cxx +LIB_SERVER_IDL = MULTIPR.idl +LIB_CLIENT_IDL = SALOME_Component.idl SALOME_Exception.idl SALOMEDS.idl SALOME_GenericObj.idl Logger.idl + +EXPORT_HEADERS = MULTIPR_API.hxx MULTIPR_DecimationAccel.hxx MULTIPR_DecimationFilter.hxx MULTIPR_Elements.hxx MULTIPR_Exceptions.hxx MULTIPR_Family.hxx MULTIPR_Field.hxx MULTIPR_GaussLoc.hxx MULTIPR_Globals.hxx MULTIPR_MeshDis.hxx MULTIPR_Mesh.hxx MULTIPR_Nodes.hxx MULTIPR_PointOfField.hxx MULTIPR_Profil.hxx MULTIPR_Utils.hxx MULTIPR_Obj.hxx MULTIPR_ProgressCallback.hxx + +BIN = multipr +BIN_SRC = + +# additionnal information to compile and link file + +CPPFLAGS += $(KERNEL_CXXFLAGS) -Wno-deprecated -Wparentheses -Wreturn-type -pthread $(MED2_INCLUDES) $(HDF5_INCLUDES) -I$(MED_ROOT_DIR)/include/salome + +CPPFLAGSFORBIN=$(CPPFLAGS) + +LDFLAGS += $(KERNEL_LDFLAGS) -lSalomeContainer -lOpUtil -lm -lmed -lmedsplitter -lmedmem -lhdf5 -lmed_V2_1 -lSALOMELocalTrace $(MED2_LIBS) $(HDF5_LIBS) -L$(MED_ROOT_DIR)/lib/salome + +LDFLAGSFORBIN=$(LDFLAGS) + +# Executables targets + +@CONCLUDE@ + diff --git a/src/MULTIPR/multipr.cxx b/src/MULTIPR/multipr.cxx new file mode 100644 index 0000000..ccdedb7 --- /dev/null +++ b/src/MULTIPR/multipr.cxx @@ -0,0 +1,703 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file multipr.cxx + * + * \brief Standalone command line application of the MULTIPR component. + * The application aims to reduce large data set to allow interactive visualization. + * Its two main function are the following: + * 1. Splits any TETRA10 mesh contained in a MED file. + * a. Builds a distributed MED file by extracting all the groups from a sequential MED file. + * b. Splits a part of distributed MED file. + * 2. Decimates fields to produce multi-resolution data set. + * + * Return 0 if application succeed, 1 otherwise (failure). + * + * See http://www.salome-platform.org to learn more about Salome or MED. + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#include "MULTIPR_API.hxx" +#include "MULTIPR_Obj.hxx" +#include "MULTIPR_Mesh.hxx" +#include "MULTIPR_Exceptions.hxx" +#include "MULTIPR_Utils.hxx" + +#include +#include +#include + +using namespace std; + + +// This command line application can use 2 differents API to do the same work. +// If MULTIPR_USE_OBJ_API is defined then this command line application used the MULTIPR_Obj API; +// otherwise, it uses the MULTIPR_API +//#define MULTIPR_USE_OBJ_API + + +const int MULTIPR_APP_OK = 0; +const int MULTIPR_APP_FAILED = 1; + + +/** + * Enumerates all the usages of this application. + */ +enum Usage +{ + MULTIPR_USAGE_UNKNOWN, + MULTIPR_USAGE_DISPLAY_HELP, + MULTIPR_USAGE_AUTOTEST, + MULTIPR_USAGE_PARTITION1, + MULTIPR_USAGE_PARTITION2, + MULTIPR_USAGE_DECIMATION, + MULTIPR_USAGE_INFO +}; + + +/** + * Enumerates all the possible errors. + */ +enum Error +{ + MULTIPR_APP_NO_ERROR, + MULTIPR_APP_UNKNOWN_USAGE, + MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS, + MULTIPR_APP_ILLEGAL_ARGUMENT, + MULTIPR_APP_FILE_NOT_FOUND, + MULTIPR_APP_IO_ERROR, + MULTIPR_APP_UNDEFINED_ERROR +}; + + +// global variables used to configure the application +int g_usage = 0; +int g_errorCode = MULTIPR_APP_NO_ERROR; +char* g_medFilename = NULL; +char* g_meshName = NULL; +char* g_partName = NULL; +int g_nbParts = 0; +char* g_filterName = NULL; +char* g_fieldName = NULL; +int g_fieldTimeStepIt = 0; +float g_decimThresholdMed = 0.0f; +float g_decimThresholdLow = 0.0f; +float g_decimRadius = 0.0f; +int g_boxing = 100; + + +/** + * \fn const char* getUsage(int usage) + * \brief returns a string describing the usage of this application. + */ +const char* getUsage(int usage) +{ + switch(usage) + { + case MULTIPR_USAGE_DISPLAY_HELP: + return "--help: display help"; + + case MULTIPR_USAGE_AUTOTEST: + return "--auto: unit tests"; + + case MULTIPR_USAGE_PARTITION1: + return "--part1: extract all groups of a sequential MED file"; + + case MULTIPR_USAGE_PARTITION2: + return "--part2: split a part of a distributed MED file"; + + case MULTIPR_USAGE_DECIMATION: + return "--decim: generated level of details of a part of a distributed MED file"; + + case MULTIPR_USAGE_INFO: + return "--info: prints all infos about a mesh in a sequential MED file"; + + default: + return "unknown"; + } +} + + +/** + * \fn void printDescription() + * \brief prints a short description of this application. + */ +void printDescription() +{ + cout << "Keywords:" << endl; + cout << " Post-processing numerical simulation, Salome platform, " << endl; + cout << " Large data set visualization, 3D meshes and fields" << endl; + cout << "Description:" << endl; + cout << " multipr is a partitionning/decimation tool of MED files." << endl; + cout << " See http://www.salome-platform.org for information about MED or Salome." << endl; + cout << " Note: current version only accept TETRA10 meshes." << endl; +} + + +/** + * \fn void printUsage() + * \brief prints "how to use" manual of this tools.2NbPart + */ +void printUsage() +{ + cout << "Usages:" << endl; + cout << " --auto Autotest: performs some unit tests on the MULTIPR API" << endl; + cout << " * Usage: --auto path (path where to find test file \"agregat100grains_12pas.med\")" << endl; + cout << " --part1 Extracts all groups from a sequential MED file (V2.2 or higher)" << endl; + cout << " * Usage: --part1 file.med meshName" << endl; + cout << " --part2 Split a group of a distributed MED file (V2.3) produced with --part1" << endl; + cout << " * Usage: --part2 file.med partName nbParts" << endl; + cout << " --decim Generates 3 level of details (full, medium and low) of a part" << endl; + cout << " of a distributed MED file (V2.3)" << endl; + cout << " * Usage: --decim file.med partName fieldName fieldIt filterName [...]" << endl; + cout << " * Only one filter is currently available: Filtre_GradientMoyen" << endl; + cout << " * Usage: --decim file.med partName fieldName fieldIt Filtre_GradientMoyen m l radius" << endl; + cout << " where m=threshold for medium res. and l=threshold for low res.; assume m < l" << endl; + cout << " --info Dumps all infos related to a mesh in a sequential MED file" << endl; + cout << " * Usage: --info file.med [meshName]" << endl; + cout << " --help Displays this help page" << endl; + cout << endl; +} + + +/** + * \fn void printGlobals() + * \brief print current state of all global variables. + */ +void printGlobals() +{ + cout << endl; + cout << "********************************************************************************" << endl; + cout << "CONFIGURATION" << endl; + cout << "--------------------------------------------------------------------------------" << endl; + cout << "Mode : " << getUsage(g_usage) << endl; + cout << "Med filename : " << ((g_medFilename != NULL) ? g_medFilename : "UNDEFINED") << endl; + cout << "Mesh name : " << ((g_meshName != NULL) ? g_meshName : "UNDEFINED") << endl; + cout << "Part name : " << ((g_partName != NULL) ? g_partName : "UNDEFINED") << endl; + cout << "Nb parts : " << g_nbParts << endl; + cout << "Decimation:" << endl; + cout << " Field name : " << ((g_fieldName != NULL) ? g_fieldName : "UNDEFINED") << endl; + cout << " Time step iteration : " << g_fieldTimeStepIt << endl; + cout << " Filter name : " << ((g_filterName != NULL) ? g_filterName : "UNDEFINED") << endl; + cout << " Threshold for med. res. : " << g_decimThresholdMed << endl; + cout << " Threshold for low res. : " << g_decimThresholdLow << endl; + cout << " Radius : " << g_decimRadius << endl; + cout << " Boxing : " << g_boxing << endl; + cout << "********************************************************************************" << endl; + cout << endl; +} + + +/** + * \fn const char* getErrorMsg() + * \brief returns the error message corresponding to current error code. + * \return the current error message. + */ +const char* getErrorMsg() +{ + switch (g_errorCode) + { + case MULTIPR_APP_NO_ERROR: + return "no error"; + + case MULTIPR_APP_UNKNOWN_USAGE: + return "unknown usage"; + + case MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS: + return "wrong number of arguments"; + + case MULTIPR_APP_ILLEGAL_ARGUMENT: + return "illegal argument"; + + case MULTIPR_APP_FILE_NOT_FOUND: + return "file not found"; + + case MULTIPR_APP_IO_ERROR: + return "i/o error"; + + default: + return "error (undefined)"; + } +} + + +/** + * \fn void parseCommandLine(int argc, char** argv) + * \brief parses the command line and configure this application. + * \param argc number of arguments. + * \param argv array of arguments. + */ +void parseCommandLine(int argc, char** argv) +{ + if (argc == 1) + { + g_usage = MULTIPR_USAGE_UNKNOWN; + return; + } + + if (strcmp(argv[1],"--help") == 0) + { + g_usage = MULTIPR_USAGE_DISPLAY_HELP; + } + else if (strcmp(argv[1],"--auto") == 0) + { + if (argc != 3) + { + g_usage = MULTIPR_USAGE_UNKNOWN; + g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS; + } + else + { + g_usage = MULTIPR_USAGE_AUTOTEST; + g_medFilename = argv[2]; + } + } + else if (strcmp(argv[1],"--part1") == 0) + { + if (argc != 4) + { + g_usage = MULTIPR_USAGE_UNKNOWN; + g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS; + } + else + { + g_usage = MULTIPR_USAGE_PARTITION1; + g_medFilename = argv[2]; + g_meshName = argv[3]; + } + } + else if (strcmp(argv[1],"--part2") == 0) + { + if (argc != 5) + { + g_usage = MULTIPR_USAGE_UNKNOWN; + g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS; + } + else + { + g_usage = MULTIPR_USAGE_PARTITION2; + g_medFilename = argv[2]; + g_partName = argv[3]; + g_nbParts = atoi(argv[4]); + } + } + else if (strcmp(argv[1],"--decim") == 0) + { + if ((argc != 10) && (argc != 11)) + { + g_usage = MULTIPR_USAGE_UNKNOWN; + g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS; + } + else + { + g_usage = MULTIPR_USAGE_DECIMATION; + g_medFilename = argv[2]; + g_partName = argv[3]; + g_fieldName = argv[4]; + g_fieldTimeStepIt = atoi(argv[5]); + g_filterName = argv[6]; + g_decimThresholdMed = atof(argv[7]); + g_decimThresholdLow = atof(argv[8]); + g_decimRadius = atof(argv[9]); + + if (argc == 11) + { + g_boxing = atoi(argv[10]); + } + } + } + else if (strcmp(argv[1],"--info") == 0) + { + if ((argc != 3) && (argc != 4)) + { + g_usage = MULTIPR_USAGE_UNKNOWN; + g_errorCode = MULTIPR_APP_WRONG_NUMBER_OF_ARGUMENTS; + } + else + { + g_usage = MULTIPR_USAGE_INFO; + g_medFilename = argv[2]; + + if (argc == 4) + { + g_meshName = argv[3]; + } + } + } + else + { + g_usage = MULTIPR_USAGE_UNKNOWN; + g_errorCode = MULTIPR_APP_UNKNOWN_USAGE; + } +} + + +/** + * \fn int runAutotest() + * \brief performs some unit tests on the MULTIPR API. + * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure. + */ +int runAutotest() +{ + cout << "Start autotest..." << endl; + + int ret = MULTIPR_APP_OK; + try + { + string strMEDfilename = g_medFilename; + strMEDfilename += "/agregat100grains_12pas.med"; + + cout << "Test file: " << strMEDfilename << endl << endl; + + //--------------------------------------------------------------------- + // Test partionneDomaine() = extract groups from a sequential MED file + //--------------------------------------------------------------------- + multipr::partitionneDomaine(strMEDfilename.c_str(), "MAIL"); + + //--------------------------------------------------------------------- + // Test partitionneGrain() = split a group from a distributed MED file + // using MEDSPLITTER (METIS) + //--------------------------------------------------------------------- + string strDistributedMEDfilename = g_medFilename; + strDistributedMEDfilename += "/agregat100grains_12pas_grains_maitre.med"; + + multipr::partitionneGrain( + strDistributedMEDfilename.c_str(), + "MAIL_1", + 4, + multipr::MULTIPR_SCOTCH); + + multipr::partitionneGrain( + strDistributedMEDfilename.c_str(), + "MAIL_97", + 3, + multipr::MULTIPR_METIS); + + //--------------------------------------------------------------------- + // Test decimePartition() = generate 2 lower resolution of a mesh + // using decimation based on gradient + //--------------------------------------------------------------------- + multipr::decimePartition( + strDistributedMEDfilename.c_str(), + "MAIL_98", + "SIG_____SIEF_ELGA_______________", + 12, + "Filtre_GradientMoyen", + 10.0, + 25.0, + 0.3, + 100); + + multipr::decimePartition( + strDistributedMEDfilename.c_str(), + "MAIL_92", + "SIG_____SIEF_ELGA_______________", + 11, + "Filtre_GradientMoyen", + 10.0, + 25.0, + 0.5, + 10); + + multipr::decimePartition( + strDistributedMEDfilename.c_str(), + "MAIL_97_2", + "SIG_____SIEF_ELGA_______________", + 10, + "Filtre_GradientMoyen", + 10.0, + 25.0, + 0.4, + 20); + + //--------------------------------------------------------------------- + // Test passed: OK! + //--------------------------------------------------------------------- + cout << endl; + cout << "Test passed: everything seems to be OK" << endl; + cout << "OK" << endl << endl; + + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + cout << endl; + cout << "Test failed" << endl; + cout << "Failure" << endl << endl; + ret = MULTIPR_APP_FAILED; + } + + return ret; +} + + +/** + * \fn void runPartition1() + * \brief builds a distributed MED file (v2.3) by extracting groups from a sequential MED file. + * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure. + */ +int runPartition1() +{ + int ret = MULTIPR_APP_OK; + try + { + multipr::partitionneDomaine(g_medFilename, g_meshName); + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + ret = MULTIPR_APP_FAILED; + } + + return ret; +} + + +/** + * \fn void runPartition2() + * \brief builds a distributed MED file (v2.3) by splitting a part of a distributed MED file generated by runPartition1(). + * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure. + */ +int runPartition2() +{ + int ret = MULTIPR_APP_OK; + try + { + multipr::partitionneGrain( + g_medFilename, + g_partName, + g_nbParts, + multipr::MULTIPR_METIS); + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + ret = MULTIPR_APP_FAILED; + } + + return ret; +} + + +/** + * \fn int runDecimation() + * \brief creates 3 resolutions of a part of a distributed MED file. + * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure. + */ +int runDecimation() +{ + int ret = MULTIPR_APP_OK; + try + { + multipr::decimePartition( + g_medFilename, + g_partName, + g_fieldName, + g_fieldTimeStepIt, + g_filterName, + g_decimThresholdMed, + g_decimThresholdLow, + g_decimRadius, + g_boxing); + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + ret = MULTIPR_APP_FAILED; + } + + return ret; +} + + +/** + * \fn int runDumpMED() + * \brief dumps info about a sequential MED file. + * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure. + */ +int runDumpMED() +{ +#ifdef MULTIPR_USE_OBJ_API + int ret = MULTIPR_APP_OK; + try + { + // if mesh is unknown, then list all the meshes in the given MED file + if (g_meshName == NULL) + { + multipr::Obj obj; + obj.create(g_medFilename); + + { + // display list of meshes contained in the MED file + vector res = obj.getMeshes(); + cout << "List of meshes in this MED file:" << endl; + for (unsigned i = 0 ; i < res.size() ; i++) + { + cout << "Mesh " << (i + 1) << ": " << res[i] << endl; + } + } + + cout << endl; + + { + // display list of fields contained in the MED file + vector names = obj.getFields(); + cout << "List of fields in this MED file:" << endl; + for (unsigned i = 0 ; i < names.size() ; i++) + { + cout << "Field " << (i + 1) << ": " << names[i] << " #it=" << obj.getTimeStamps(names[i].c_str()) << endl; + } + } + } + else + { + // display all infos about one mesh in a MED file + multipr::Mesh mesh; + mesh.readSequentialMED(g_medFilename, g_meshName); + mesh.setPrintAll(true); + cout << mesh << endl; + } + cout << "OK" << endl; + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + ret = MULTIPR_APP_FAILED; + } + + return ret; +#else + int ret = MULTIPR_APP_OK; + try + { + // if mesh is unknown, then list all the meshes in the given MED file + if (g_meshName == NULL) + { + { + // display list of meshes contained in the MED file + vector res = multipr::getListMeshes(g_medFilename); + cout << "List of meshes in this MED file:" << endl; + for (unsigned i = 0 ; i < res.size() ; i++) + { + cout << "Mesh " << (i + 1) << ": " << res[i] << endl; + } + } + + cout << endl; + + { + // display list of fields contained in the MED file + vector > res = multipr::getListFields(g_medFilename); + cout << "List of fields in this MED file:" << endl; + for (unsigned i = 0 ; i < res.size() ; i++) + { + cout << "Field " << (i + 1) << ": " << res[i].first << " #it=" << res[i].second << endl; + } + } + } + else + { + // display all infos about one mesh in a MED file + multipr::Mesh mesh; + mesh.readSequentialMED(g_medFilename, g_meshName); + mesh.setPrintAll(true); + cout << mesh << endl; + } + cout << "OK" << endl; + } + catch (multipr::RuntimeException& e) + { + e.dump(cout); + ret = MULTIPR_APP_FAILED; + } + + return ret; +#endif +} + + +/** + * \fn int run() + * \brief applies partitioning/decimation according to global parameters. + * \return MULTIPR_APP_OK if successful, MULTIPR_APP_FAILED if failure. + */ +int run() +{ + printGlobals(); + + int ret = MULTIPR_APP_OK; + switch (g_usage) + { + case MULTIPR_USAGE_AUTOTEST: ret = runAutotest(); break; + case MULTIPR_USAGE_PARTITION1: ret = runPartition1(); break; + case MULTIPR_USAGE_PARTITION2: ret = runPartition2(); break; + case MULTIPR_USAGE_DECIMATION: ret = runDecimation(); break; + case MULTIPR_USAGE_INFO: ret = runDumpMED(); break; + default: + cout << "ERROR: unknown usage" << endl; + ret = MULTIPR_APP_FAILED; + break; + } + + return ret; +} + + +/** + * \fn int main(int argc, char** argv) + * \brief entry point of the application. + * \param argc number of arguments. + * \param argv list of arguments. + * \return 0 if OK, 1 if failed. + */ +int main(int argc, char** argv) +{ + cout << "multipr v" << multipr::getVersion() << " - by EDF/CS - 01/2007" << endl; + cout << "==================================" << endl; + + #ifdef MULTIPR_USE_OBJ_API + cout << "Version MULTIPR_Obj" << endl; + #else + cout << "Version MULTIPR_API" << endl; + #endif + + parseCommandLine(argc, argv); + + int ret = MULTIPR_APP_OK; // assume no error at the beginning + + if (g_usage == MULTIPR_USAGE_UNKNOWN) + { + if (argc != 1) + { + // if usage is unknown and there are some arguments, print an error message + cout << "ERROR: " << getErrorMsg() << endl; + cout << endl; + ret = MULTIPR_APP_FAILED; + } + else + { + // if no argument, print a description of this application + printDescription(); + } + + printUsage(); + } + else if (g_usage == MULTIPR_USAGE_DISPLAY_HELP) + { + printDescription(); + printUsage(); + } + else + { + // the application seems to be configured properly: it can be executed + ret = run(); + } + + return ret; +} + +// EOF diff --git a/src/MULTIPRGUI/MULTIPR_GUI.cxx b/src/MULTIPRGUI/MULTIPR_GUI.cxx new file mode 100644 index 0000000..650b930 --- /dev/null +++ b/src/MULTIPRGUI/MULTIPR_GUI.cxx @@ -0,0 +1,747 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_GUI.cxx + * + * \brief see MULTIPR_GUI.h + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +// MULTIPR Includes +#include "MULTIPR_GUI.h" +#include "MULTIPR_GUI_Dlg.h" + +// Salome Includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +// QT Includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace std; + + +//***************************************************************************** +// Global variable +//***************************************************************************** + +namespace multipr +{ + // progress callback used by the MULTIPR library + extern MULTIPR_ProgressCallback* gProgressCallback; +} + + +//***************************************************************************** +// Class MULTIPR_GUI implementation +//***************************************************************************** + +MULTIPR_GUI::MULTIPR_GUI() : SalomeApp_Module("MULTIPR") +{ + mMEDFileName = ""; + mMULTIPRObj = NULL; +} + + +MULTIPR_ORB::MULTIPR_Obj_ptr MULTIPR_GUI::getMULTIPRObj() +{ + return mMULTIPRObj; +} + + +SalomeApp_Application* MULTIPR_GUI::getAppli() const +{ + return getApp(); +} + + +MULTIPR_ORB::MULTIPR_Gen_ptr MULTIPR_GUI::InitMULTIPRGen(SalomeApp_Application* app) +{ + Engines::Component_var comp = app->lcc()->FindOrLoad_Component("FactoryServer", "MULTIPR"); + MULTIPR_ORB::MULTIPR_Gen_ptr clr = MULTIPR_ORB::MULTIPR_Gen::_narrow(comp); + ASSERT(!CORBA::is_nil(clr)); + return clr; +} + + +void MULTIPR_GUI::initialize(CAM_Application* app) +{ + SalomeApp_Module::initialize(app); + + InitMULTIPRGen(dynamic_cast(app)); + + QWidget* aParent = app->desktop(); + SUIT_ResourceMgr* aResourceMgr = app->resourceMgr(); + + //------------------------------------------------------------------------- + // create actions + //------------------------------------------------------------------------- + QPixmap aPixmapImportFromMEDFile = aResourceMgr->loadPixmap("MULTIPR", tr("ICON_IMPORT_MED")); + + createAction( + ACTION_IMPORT_MED, + tr("TLT_IMPORT_FROM_MED_FILE"), + QIconSet(aPixmapImportFromMEDFile), + tr("MEN_IMPORT_FROM_MED_FILE"), + tr("STS_IMPORT_FROM_MED_FILE"), + (CTRL + Key_I), + aParent, + false, + this, + SLOT(OnImportFromMEDFile())); + + createAction( + ACTION_SPLIT, + tr("TLT_SPLIT"), + QIconSet(), + tr("MEN_SPLIT"), + tr("STS_SPLIT"), + 0, + aParent, + false, + this, + SLOT(OnPartition2())); + + createAction( + ACTION_DECIMATE, + tr("TLT_DECIMATE"), + QIconSet(), + tr("MEN_DECIMATE"), + tr("STS_DECIMATE"), + 0, + aParent, + false, + this, + SLOT(OnDecimate())); + + QPixmap aPixmapSaveMEDFile = aResourceMgr->loadPixmap("MULTIPR", tr("ICON_SAVE_MED")); + + createAction( + ACTION_SAVE, + tr("TLT_SAVE"), + QIconSet(aPixmapSaveMEDFile), + tr("MEN_SAVE"), + tr("STS_SAVE"), + 0, + aParent, + false, + this, + SLOT(OnSave())); + + //------------------------------------------------------------------------- + // create menus + //------------------------------------------------------------------------- + int aMenuId; + aMenuId = createMenu(tr("MEN_FILE"), -1, -1); + createMenu(separator(), aMenuId, -1, 10); + aMenuId = createMenu(tr("MEN_FILE_MULTIPR"), aMenuId, -1, 10); + createMenu(ACTION_IMPORT_MED, aMenuId); + + aMenuId = createMenu(tr("MEN_MULTIPR"), -1, -1, 30); + createMenu(ACTION_IMPORT_MED, aMenuId, 10); + createMenu(ACTION_SAVE, aMenuId, 10); + createMenu(ACTION_SPLIT, aMenuId, 10); + createMenu(ACTION_DECIMATE, aMenuId, 10); + + //------------------------------------------------------------------------- + // create toolbars + //------------------------------------------------------------------------- + int aToolId = createTool(tr("TOOL_MULTIPR")); + createTool(ACTION_IMPORT_MED, aToolId); + createTool(ACTION_SAVE, aToolId); + + //------------------------------------------------------------------------- + // create popup menus + //------------------------------------------------------------------------- + QtxPopupMgr* mgr = popupMgr(); + mgr->insert( action(ACTION_SPLIT), -1, -1, -1 ); + mgr->insert( action(ACTION_DECIMATE), -1, -1, -1 ); + mgr->insert( action(ACTION_SAVE), -1, -1, -1 ); + + QString aRule = "client='ObjectBrowser' and selcount>=1"; // $type in {'VISU::TMESH'}"; + mgr->setRule(action(ACTION_SPLIT), aRule, true); + mgr->setRule(action(ACTION_DECIMATE), aRule, true); + mgr->setRule(action(ACTION_SAVE), aRule, true); + + //------------------------------------------------------------------------- + // set progress dialog + //------------------------------------------------------------------------- + MULTIPR_GUI_ProgressCallbackDlg* progressDlg = new MULTIPR_GUI_ProgressCallbackDlg(application()->desktop()); + multipr::gProgressCallback = progressDlg; +} + + +CAM_DataModel* MULTIPR_GUI::createDataModel() +{ + return new MULTIPR_GUI_DataModel(this); +} + + +QString MULTIPR_GUI::engineIOR() const +{ + CORBA::String_var anIOR = getApp()->orb()->object_to_string(InitMULTIPRGen(getApp())); + return QString(anIOR.in()); +} + + +bool MULTIPR_GUI::activateModule(SUIT_Study* theStudy) +{ + bool bOk = SalomeApp_Module::activateModule(theStudy); + + setMenuShown(true); + setToolShown(true); + + return bOk; +} + + +bool MULTIPR_GUI::deactivateModule(SUIT_Study* theStudy) +{ + setMenuShown(false); + setToolShown(false); + + return SalomeApp_Module::deactivateModule(theStudy); +} + + +void MULTIPR_GUI::windows(QMap& theMap) const +{ + theMap.clear(); + theMap.insert(SalomeApp_Application::WT_ObjectBrowser, Qt::DockLeft); + theMap.insert(SalomeApp_Application::WT_PyConsole, Qt::DockBottom); +} + + +void MULTIPR_GUI::selected(QStringList& entries, const bool multiple) +{ + LightApp_SelectionMgr* mgr = getApp()->selectionMgr(); + + if(!mgr) return; + + SUIT_DataOwnerPtrList anOwnersList; + mgr->selected(anOwnersList); + + for (int i = 0 ; i < anOwnersList.size() ; i++) + { + const LightApp_DataOwner* owner = dynamic_cast(anOwnersList[i].get()); + + if (!entries.contains(owner->entry())) + { + entries.append(owner->entry()); + } + + if (!multiple) + break; + } +} + + +void MULTIPR_GUI::OnImportFromMEDFile() +{ + // Get file name + QStringList aFilter; + aFilter.append(tr("FLT_MED_FILES")); + aFilter.append(tr("FLT_ALL_FILES")); + + SalomeApp_CheckFileDlg* fd = new SalomeApp_CheckFileDlg( + this->application()->desktop(), + true, + tr("USE_BUILD_PROGRESS") ); + fd->setCaption(tr("MEN_IMPORT_FROM_MED_FILE")); + fd->setFilters(aFilter); + fd->exec(); + QFileInfo aFileInfo(fd->selectedFile()); + delete fd; + + // Check the file name + if (!aFileInfo.exists()) + return; + + mMEDFileName = aFileInfo.filePath(); + + QApplication::setOverrideCursor(Qt::waitCursor); + + try + { + MULTIPR_ORB::MULTIPR_Gen_ptr multiprgen = MULTIPR_GUI::InitMULTIPRGen(getApp()); + mMULTIPRObj = multiprgen->getObject(mMEDFileName.latin1()); + } + catch(...) + { + SUIT_MessageBox::error1( + getApp()->desktop(), + "Import MED file error", + "Invalid MED file (not recognized by MULTIPR)", + tr("OK") ); + } + QApplication::restoreOverrideCursor(); + + try + { + if (mMULTIPRObj->isValidSequentialMEDFile()) + { + OnPartition1(); + } + } + catch (...) + { + } +} + + +void MULTIPR_GUI::OnPartition1() +{ + MULTIPR_GUI_Partition1Dlg* dialog = new MULTIPR_GUI_Partition1Dlg(this); + dialog->exec(); + delete dialog; +} + + +void MULTIPR_GUI::OnPartition2() +{ + retrieveSelectedParts(); + + if (mSelectedParts.count() == 0) + { + SUIT_MessageBox::warn1( + getApp()->desktop(), + "Split warning", + "No parts selected", + tr("OK") ); + return; + } + + MULTIPR_GUI_Partition2Dlg* dialog = new MULTIPR_GUI_Partition2Dlg(this); + dialog->exec(); + delete dialog; + getApp()->updateObjectBrowser(); +} + + +void MULTIPR_GUI::OnDecimate() +{ + retrieveSelectedParts(); + + if (mSelectedParts.count() == 0) + { + SUIT_MessageBox::warn1( + getApp()->desktop(), + "Decimation warning", + "No parts selected", + tr("OK") ); + return; + } + + MULTIPR_GUI_DecimateDlg* dialog = new MULTIPR_GUI_DecimateDlg(this); + dialog->exec(); + delete dialog; + getApp()->updateObjectBrowser(); +} + + +void MULTIPR_GUI::OnSave() +{ + QApplication::setOverrideCursor(Qt::waitCursor); + + try + { + mMULTIPRObj->save(); + getApp()->updateObjectBrowser(); + } + catch(...) + { + SUIT_MessageBox::error1( + getApp()->desktop(), + "Save distributed MED file error", + "Error while writing distributed MED file", + tr("OK") ); + } + + QApplication::restoreOverrideCursor(); +} + + + +void MULTIPR_GUI::retrieveSelectedParts() +{ + mSelectedParts.clear(); + + QStringList userSelection; + selected(userSelection, true); + for (QStringList::const_iterator it = userSelection.begin(), last = userSelection.end(); it != last; it++) + { + const QString& str = (*it); + QStringList words = QStringList::split(":", str); + if (words.count() == 2) + { + if (words[0] == "MULTIPR_PART") + { + mSelectedParts.push_back(words[1]); + } + } + } +} + + +//***************************************************************************** +// Super class Data Object implementation +//***************************************************************************** + +MULTIPR_GUI_DataObject::MULTIPR_GUI_DataObject(SUIT_DataObject* parent, const char* name) : + LightApp_DataObject(parent), + CAM_DataObject(parent) +{ + mName = name; +} + + +MULTIPR_GUI_DataObject::~MULTIPR_GUI_DataObject() +{ + // do nothing! +} + + +QString MULTIPR_GUI_DataObject::entry() const +{ + return QString("MULTIPR_OBJECT"); +} + + +QString MULTIPR_GUI_DataObject::name() const +{ + return mName; +} + + +QPixmap MULTIPR_GUI_DataObject::icon() const +{ + //static QPixmap icon = SUIT_Session::session()->resourceMgr()->loadPixmap("MULTIPR", QObject::tr("ICON_IMPORT_MED"), false); + return QPixmap(); + +} + + +QString MULTIPR_GUI_DataObject::toolTip() const +{ + // default behaviour: return an empty string + return ""; +} + + +//***************************************************************************** +// Class Data Object Module implementation +//***************************************************************************** + +MULTIPR_GUI_DataObject_Module::MULTIPR_GUI_DataObject_Module(CAM_DataModel* dm, SUIT_DataObject* parent, const char* name) : + MULTIPR_GUI_DataObject(parent, name), + LightApp_ModuleObject(dm, parent), + CAM_DataObject(parent) +{ + // do nothing! +} + + +MULTIPR_GUI_DataObject_Module::~MULTIPR_GUI_DataObject_Module() +{ + // do nothing! +} + + +QString MULTIPR_GUI_DataObject_Module::entry() const +{ + return QString("MULTIPR_MODULE:" + mName); +} + + +QString MULTIPR_GUI_DataObject_Module::name() const +{ + return CAM_RootObject::name(); +} + + +QPixmap MULTIPR_GUI_DataObject_Module::icon() const +{ + return QPixmap(); +} + + +QString MULTIPR_GUI_DataObject_Module::toolTip() const +{ + return QString("Module MULTIPR"); +} + + +//***************************************************************************** +// Class Data Object Mesh implementation +//***************************************************************************** + +MULTIPR_GUI_DataObject_Mesh::MULTIPR_GUI_DataObject_Mesh(SUIT_DataObject* parent, const char* name) : + MULTIPR_GUI_DataObject(parent, name), + CAM_DataObject(parent) +{ + // do nothing! +} + + +MULTIPR_GUI_DataObject_Mesh::~MULTIPR_GUI_DataObject_Mesh() +{ + // do nothing! +} + + +QString MULTIPR_GUI_DataObject_Mesh::entry() const +{ + return QString("MULTIPR_MESH:") + mName; +} + + +QPixmap MULTIPR_GUI_DataObject_Mesh::icon() const +{ + return QPixmap(); +} + + +QString MULTIPR_GUI_DataObject_Mesh::toolTip() const +{ + return QString("Original mesh"); +} + + +//***************************************************************************** +// Class Data Object Part implementation +//***************************************************************************** + +MULTIPR_GUI_DataObject_Part::MULTIPR_GUI_DataObject_Part(SUIT_DataObject* parent, const char* name, const char* info) : + MULTIPR_GUI_DataObject(parent, name), + CAM_DataObject(parent) +{ + mMeshName = ""; + mId = 0; + mPath = ""; + mMEDFileName = ""; + + mTooltip = info; + + // parse info to retrieve all the fields + char lMeshName[256]; + int lId; + char lPartName[256]; + char lPath[256]; + char lMEDFileName[256]; + + int ret = sscanf(info, "%s %d %s %s %s", + lMeshName, + &lId, + lPartName, + lPath, + lMEDFileName); + + // number of read parameters should be 5 + if (ret != 5) return; + + mMeshName = lMeshName; + mId = lId; + mPath = lPath; + mMEDFileName = lMEDFileName; +} + + +MULTIPR_GUI_DataObject_Part::~MULTIPR_GUI_DataObject_Part() +{ + // do nothing! +} + + +QString MULTIPR_GUI_DataObject_Part::entry() const +{ + return QString("MULTIPR_PART:") + mName; +} + + +QPixmap MULTIPR_GUI_DataObject_Part::icon() const +{ + return QPixmap(); +} + + +QString MULTIPR_GUI_DataObject_Part::toolTip() const +{ + return mTooltip; +} + + +//***************************************************************************** +// Class Data Object Resolution implementation +//***************************************************************************** + +MULTIPR_GUI_DataObject_Resolution::MULTIPR_GUI_DataObject_Resolution(SUIT_DataObject* parent, const char* name, const char* info) : + MULTIPR_GUI_DataObject_Part(parent, name, info), + CAM_DataObject(parent) +{ + // do nothing! +} + + +MULTIPR_GUI_DataObject_Resolution::~MULTIPR_GUI_DataObject_Resolution() +{ + // do nothing! +} + + +QString MULTIPR_GUI_DataObject_Resolution::entry() const +{ + return QString("MULTIPR_RESOLUTION:") + mName; +} + + +QPixmap MULTIPR_GUI_DataObject_Resolution::icon() const +{ + return QPixmap(); +} + + +QString MULTIPR_GUI_DataObject_Resolution::toolTip() const +{ + return mTooltip; +} + + +//***************************************************************************** +// Data Model +//***************************************************************************** + +MULTIPR_GUI_DataModel::MULTIPR_GUI_DataModel(CAM_Module* module) : + LightApp_DataModel(module) +{ + mMULTIPR_GUI = dynamic_cast(module); +} + + +MULTIPR_GUI_DataModel::~MULTIPR_GUI_DataModel() +{ + // do nothing! +} + + +void MULTIPR_GUI_DataModel::build() +{ + MULTIPR_GUI_DataObject_Module* modelRoot = dynamic_cast(root()); + + if (!modelRoot) + { + // root is not set yet + modelRoot = new MULTIPR_GUI_DataObject_Module(this, NULL, "MULTIPR"); + setRoot(modelRoot); + } + + MULTIPR_ORB::MULTIPR_Obj_ptr obj = mMULTIPR_GUI->getMULTIPRObj(); + + if (obj != NULL) + { + MULTIPR_ORB::string_array* listParts = obj->getParts(); + + if (listParts->length() >= 1) + { + const char* strPartName0 = (*listParts)[0]; + char* strPartInfo0 = obj->getPartInfo(strPartName0); + + char lMeshName[256]; + int lId; + char lPartName[256]; + char lPath[256]; + char lMEDFileName[256]; + + // parse infos + int ret = sscanf(strPartInfo0, "%s %d %s %s %s", + lMeshName, + &lId, + lPartName, + lPath, + lMEDFileName); + + if (ret != 5) return; + + MULTIPR_GUI_DataObject_Mesh* dataObjectMesh = new MULTIPR_GUI_DataObject_Mesh(modelRoot, lMeshName); + + MULTIPR_GUI_DataObject_Part* dataObjectPart_prev = NULL; + + for (int i = 0 ; i < listParts->length() ; i++) + { + const char* strItem = (*listParts)[i]; + char* strPartInfo = obj->getPartInfo(strItem); + + // parse infos + int ret = sscanf(strPartInfo, "%s %d %s %s %s", + lMeshName, + &lId, + lPartName, + lPath, + lMEDFileName); + + if (ret != 5) return; + + //cout << "Part : " << lPartName << endl; + if ((strstr(lPartName,"_MED") != NULL) || (strstr(lPartName,"_LOW") != NULL)) + { + //cout << "Found MED/LOW" << endl; + new MULTIPR_GUI_DataObject_Resolution(dataObjectPart_prev, strItem, strPartInfo); + } + else + { + dataObjectPart_prev = new MULTIPR_GUI_DataObject_Part(dataObjectMesh, strItem, strPartInfo); + } + } + } + } +} + + +extern "C" +{ + CAM_Module* createModule() + { + return new MULTIPR_GUI(); + } +} + + +// EOF diff --git a/src/MULTIPRGUI/MULTIPR_GUI.h b/src/MULTIPRGUI/MULTIPR_GUI.h new file mode 100644 index 0000000..aa929e2 --- /dev/null +++ b/src/MULTIPRGUI/MULTIPR_GUI.h @@ -0,0 +1,235 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_GUI.h + * + * \brief MULTIPR GUI (QT) + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef __MULTIPR_GUI__ +#define __MULTIPR_GUI__ + + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include +#include +#include +#include + +#include +#include CORBA_CLIENT_HEADER(MULTIPR) + +#include +#include +#include +#include + +#include "MULTIPR_ProgressCallback.hxx" + + +//***************************************************************************** +// Pre-declaration +//***************************************************************************** + +class SalomeApp_Application; +class CAM_Module; + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QSpacerItem; +class QButtonGroup; +class QLabel; +class QComboBox; +class QLineEdit; +class QSpinBox; +class QPushButton; + + +//***************************************************************************** +// Class MULTIPR_GUI +// Salome Application +//***************************************************************************** + +class MULTIPR_GUI: public SalomeApp_Module +{ + Q_OBJECT + +public: + MULTIPR_GUI(); + + void initialize(CAM_Application*); + QString engineIOR() const; + void windows(QMap&) const; + + MULTIPR_ORB::MULTIPR_Obj_ptr getMULTIPRObj(); + SalomeApp_Application* getAppli() const; + void selected(QStringList&, const bool); + + static MULTIPR_ORB::MULTIPR_Gen_ptr InitMULTIPRGen(SalomeApp_Application*); + + const QStringList& getSelectedParts() const { return mSelectedParts; } + +public slots: + bool deactivateModule(SUIT_Study*); + bool activateModule(SUIT_Study*); + +protected slots: + void OnImportFromMEDFile(); + void OnPartition1(); + void OnPartition2(); + void OnDecimate(); + void OnSave(); + + void retrieveSelectedParts(); + +protected: + virtual CAM_DataModel* createDataModel(); + +protected: + + enum + { + ACTION_IMPORT_MED = 190, + ACTION_SAVE, + ACTION_SPLIT, + ACTION_DECIMATE + }; + +private: + QString mMEDFileName; + QStringList mSelectedParts; + MULTIPR_ORB::MULTIPR_Obj_ptr mMULTIPRObj; + +}; // class MULTIPR_GUI + + +//***************************************************************************** +// Class MULTIPR_GUI_DataObject +//***************************************************************************** + +class MULTIPR_GUI_DataObject : public LightApp_DataObject +{ +public: + MULTIPR_GUI_DataObject(SUIT_DataObject* parent, const char* name); + virtual ~MULTIPR_GUI_DataObject(); + + virtual QString entry() const; + virtual QString name() const; + virtual QPixmap icon() const; + virtual QString toolTip() const; + +protected: + QString mName; +}; + + +//***************************************************************************** +// Class MULTIPR_GUI_DataObject_Module +//***************************************************************************** + +class MULTIPR_GUI_DataObject_Module : public MULTIPR_GUI_DataObject, public LightApp_ModuleObject +{ +public: + MULTIPR_GUI_DataObject_Module(CAM_DataModel* dm, SUIT_DataObject* parent, const char* name); + virtual ~MULTIPR_GUI_DataObject_Module(); + + virtual QString entry() const; + virtual QString name() const; + virtual QPixmap icon() const; + virtual QString toolTip() const; + +private: +}; + + +//***************************************************************************** +// Class MULTIPR_GUI_DataObject_Mesh +//***************************************************************************** + +class MULTIPR_GUI_DataObject_Mesh : public MULTIPR_GUI_DataObject +{ +public: + MULTIPR_GUI_DataObject_Mesh(SUIT_DataObject* parent, const char* name); + virtual ~MULTIPR_GUI_DataObject_Mesh(); + + virtual QString entry() const; + virtual QPixmap icon() const; + virtual QString toolTip() const; + +private: +}; + + +//***************************************************************************** +// Class MULTIPR_GUI_DataObject_Part +//***************************************************************************** + +class MULTIPR_GUI_DataObject_Part : public MULTIPR_GUI_DataObject +{ +public: + MULTIPR_GUI_DataObject_Part(SUIT_DataObject* parent, const char* name, const char* info); + virtual ~MULTIPR_GUI_DataObject_Part(); + + virtual QString entry() const; + virtual QPixmap icon() const; + virtual QString toolTip() const; + +protected: + QString mMeshName; + int mId; + QString mPath; + QString mMEDFileName; + QString mTooltip; +}; + + +//***************************************************************************** +// Class MULTIPR_GUI_DataObject_Resolution +//***************************************************************************** + +class MULTIPR_GUI_DataObject_Resolution : public MULTIPR_GUI_DataObject_Part +{ +public: + MULTIPR_GUI_DataObject_Resolution(SUIT_DataObject* parent, const char* name, const char* info); + virtual ~MULTIPR_GUI_DataObject_Resolution(); + + virtual QString entry() const; + virtual QPixmap icon() const; + virtual QString toolTip() const; + +private: +}; + + +//***************************************************************************** +// Class MULTIPR_GUI_DataModel +//***************************************************************************** + +class MULTIPR_GUI_DataModel : public LightApp_DataModel +{ +public: + MULTIPR_GUI_DataModel(CAM_Module*); + virtual ~MULTIPR_GUI_DataModel(); + +protected: + virtual void build(); + +private: + MULTIPR_GUI* mMULTIPR_GUI; +}; + + +#endif // __MULTIPR_GUI__ + + +// EOF + diff --git a/src/MULTIPRGUI/MULTIPR_GUI_Dlg.cxx b/src/MULTIPRGUI/MULTIPR_GUI_Dlg.cxx new file mode 100644 index 0000000..be2a2fd --- /dev/null +++ b/src/MULTIPRGUI/MULTIPR_GUI_Dlg.cxx @@ -0,0 +1,651 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_GUI_Dlg.cxx + * + * \brief see MULTIPR_GUI_Dlg.h + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include "MULTIPR_GUI_Dlg.h" +#include "MULTIPR_GUI.h" +#include "MULTIPR_Mesh.hxx" +#include "MULTIPR_DecimationFilter.hxx" + +// Salome Includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +// QT Includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace std; + + +MULTIPR_GUI_Partition1Dlg::MULTIPR_GUI_Partition1Dlg(MULTIPR_GUI* theModule) : + QDialog( theModule->application()->desktop(), 0, false, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu) +{ + mModule = theModule; + + buttonGroupProcess = new QButtonGroup( this, "buttonGroupProcess" ); + buttonGroupProcess->setGeometry( QRect( 10, 110, 450, 60 ) ); + + pushButtonCancel = new QPushButton( buttonGroupProcess, "pushButtonCancel" ); + pushButtonCancel->setGeometry( QRect( 321, 10, 110, 41 ) ); + + pushButtonOK = new QPushButton( buttonGroupProcess, "pushButtonOK" ); + pushButtonOK->setGeometry( QRect( 10, 10, 110, 41 ) ); + + buttonGroupSelectMesh = new QButtonGroup( this, "buttonGroupSelectMesh" ); + buttonGroupSelectMesh->setGeometry( QRect( 10, 10, 450, 91 ) ); + + comboBoxSelectMesh = new QComboBox( FALSE, buttonGroupSelectMesh, "comboBoxSelectMesh" ); + comboBoxSelectMesh->setGeometry( QRect( 160, 30, 280, 40 ) ); + MULTIPR_ORB::string_array* listMeshes = theModule->getMULTIPRObj()->getMeshes(); + for (int i=0; ilength() ; i++) + { + const char* strItem = (*listMeshes)[i]; + comboBoxSelectMesh->insertItem(strItem); + } + comboBoxSelectMesh->setEditable(false); + + textLabelSelectMesh = new QLabel( buttonGroupSelectMesh, "textLabelSelectMesh" ); + textLabelSelectMesh->setGeometry( QRect( 20, 30, 110, 40 ) ); + + setCaption( tr( "Extract groups from sequential MED file" ) ); + buttonGroupProcess->setTitle( QString::null ); + pushButtonCancel->setText( tr( "Cancel" ) ); + pushButtonOK->setText( tr("OK") ); + buttonGroupSelectMesh->setTitle( tr( "Select mesh" ) ); + textLabelSelectMesh->setText( tr( "Mesh name" ) ); + + resize( QSize(471, 185).expandedTo(minimumSizeHint()) ); + clearWState( WState_Polished ); + + connect(pushButtonOK, SIGNAL(clicked()), this, SLOT(accept())); + connect(pushButtonCancel, SIGNAL(clicked()), this, SLOT(reject())); +} + + +/* + * Destroys the object and frees any allocated resources + */ +MULTIPR_GUI_Partition1Dlg::~MULTIPR_GUI_Partition1Dlg() +{ + // no need to delete child widgets, Qt does it all for us +} + + +void MULTIPR_GUI_Partition1Dlg::accept() +{ + const char* meshName = comboBoxSelectMesh->currentText().latin1(); + + try + { + mModule->getMULTIPRObj()->setMesh(meshName); + + QApplication::setOverrideCursor(Qt::waitCursor); + mModule->getMULTIPRObj()->partitionneDomaine(); + QApplication::restoreOverrideCursor(); + + } + catch(...) + { + SUIT_MessageBox::error1( + mModule->getAppli()->desktop(), + "Import MED file error", + "Unable to set mesh", + tr("OK") ); + } + + QDialog::accept(); + mModule->getAppli()->updateObjectBrowser(); +} + + +void MULTIPR_GUI_Partition1Dlg::reject() +{ + QDialog::reject(); +} + + +MULTIPR_GUI_Partition2Dlg::MULTIPR_GUI_Partition2Dlg(MULTIPR_GUI* theModule) : + QDialog( theModule->application()->desktop(), 0, false, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu) +{ + mModule = theModule; + + buttonGroupSplitParameters = new QButtonGroup( this, "buttonGroupSplitParameters" ); + buttonGroupSplitParameters->setGeometry( QRect( 10, 10, 380, 140 ) ); + + textLabelSelectNbParts = new QLabel( buttonGroupSplitParameters, "textLabelSelectNbParts" ); + textLabelSelectNbParts->setGeometry( QRect( 30, 30, 160, 31 ) ); + + textLabelSelectSplitter = new QLabel( buttonGroupSplitParameters, "textLabelSelectSplitter" ); + textLabelSelectSplitter->setGeometry( QRect( 30, 80, 111, 31 ) ); + + comboBoxSelectSplitter = new QComboBox( FALSE, buttonGroupSplitParameters, "comboBoxSelectSplitter" ); + comboBoxSelectSplitter->setGeometry( QRect( 210, 80, 150, 40 ) ); + comboBoxSelectSplitter->insertItem("METIS"); + comboBoxSelectSplitter->insertItem("SCOTCH"); + comboBoxSelectSplitter->setEditable(false); + + spinBoxNbParts = new QSpinBox( buttonGroupSplitParameters, "spinBoxNbParts" ); + spinBoxNbParts->setGeometry( QRect( 210, 30, 150, 30 ) ); + spinBoxNbParts->setMaxValue( 1000 ); + spinBoxNbParts->setMinValue( 2 ); + spinBoxNbParts->setValue( 2 ); + + buttonGroupProcess = new QButtonGroup( this, "buttonGroupProcess" ); + buttonGroupProcess->setGeometry( QRect( 10, 160, 380, 60 ) ); + + pushButtonOK = new QPushButton( buttonGroupProcess, "pushButtonOK" ); + pushButtonOK->setGeometry( QRect( 10, 10, 110, 41 ) ); + + pushButtonCancel = new QPushButton( buttonGroupProcess, "pushButtonCancel" ); + pushButtonCancel->setGeometry( QRect( 250, 10, 110, 41 ) ); + + setCaption( tr( "Split selected part" ) ); + buttonGroupSplitParameters->setTitle( tr( "Split parameters" ) ); + textLabelSelectNbParts->setText( tr( "Number of sub-parts" ) ); + textLabelSelectSplitter->setText( tr( "Splitter" ) ); + buttonGroupProcess->setTitle( QString::null ); + pushButtonOK->setText( tr("OK") ); + pushButtonCancel->setText( tr( "Cancel" ) ); + + resize( QSize(403, 234).expandedTo(minimumSizeHint()) ); + clearWState( WState_Polished ); + + connect(pushButtonOK, SIGNAL(clicked()), this, SLOT(accept())); + connect(pushButtonCancel, SIGNAL(clicked()), this, SLOT(reject())); +} + +/* + * Destroys the object and frees any allocated resources + */ +MULTIPR_GUI_Partition2Dlg::~MULTIPR_GUI_Partition2Dlg() +{ + // no need to delete child widgets, Qt does it all for us +} + + +void MULTIPR_GUI_Partition2Dlg::accept() +{ + const char* strSplitter = comboBoxSelectSplitter->currentText().latin1(); + int nbParts = spinBoxNbParts->value(); + int partitionner = -1; + if (strcmp(strSplitter, "METIS") == 0) + { + partitionner = 0; + } + else if (strcmp(strSplitter, "SCOTCH") == 0) + { + partitionner = 1; + } + + QApplication::setOverrideCursor(Qt::waitCursor); + + try + { + const QStringList& partsList = mModule->getSelectedParts(); + for (QStringList::const_iterator it = partsList.begin(), last = partsList.end(); it != last; it++) + { + const QString& partName = (*it); + cout << "Split " << partName.latin1() << " #parts=" << nbParts << " splitter=" << strSplitter; + mModule->getMULTIPRObj()->partitionneGrain(partName.latin1(), nbParts, partitionner); + } + + } + catch(...) + { + SUIT_MessageBox::error1( + mModule->getAppli()->desktop(), + "Split error", + "Error while splitting selected part(s)", + tr("OK") ); + } + + QApplication::restoreOverrideCursor(); + QDialog::accept(); +} + + +void MULTIPR_GUI_Partition2Dlg::reject() +{ + QDialog::reject(); +} + + +MULTIPR_GUI_DecimateDlg::MULTIPR_GUI_DecimateDlg(MULTIPR_GUI* theModule) : + QDialog( theModule->application()->desktop(), 0, false, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu) +{ + mModule = theModule; + + buttonGroupSelectField = new QButtonGroup( this, "buttonGroupSelectField" ); + buttonGroupSelectField->setGeometry( QRect( 10, 10, 450, 140 ) ); + + textLabelSelectFieldName = new QLabel( buttonGroupSelectField, "textLabelSelectFieldName" ); + textLabelSelectFieldName->setGeometry( QRect( 30, 30, 141, 31 ) ); + + textLabelSelectFieldIteration = new QLabel( buttonGroupSelectField, "textLabelSelectFieldIteration" ); + textLabelSelectFieldIteration->setGeometry( QRect( 30, 80, 111, 31 ) ); + + MULTIPR_ORB::string_array* listFields = theModule->getMULTIPRObj()->getFields(); + int maxIteration = 0; + for (int i=0 ; ilength() ; i++) + { + const char* strItem = (*listFields)[i]; + CORBA::Long nbIteration = theModule->getMULTIPRObj()->getTimeStamps(strItem); + if (nbIteration > maxIteration) + { + maxIteration = nbIteration; + } + } + + comboBoxSelectFieldIteration = new QComboBox( FALSE, buttonGroupSelectField, "comboBoxSelectFieldIteration" ); + comboBoxSelectFieldIteration->setGeometry( QRect( 150, 80, 280, 40 ) ); + for (int i=1 ; i<=maxIteration ; i++) + { + comboBoxSelectFieldIteration->insertItem(QString::number(i)); + } + + comboBoxSelectFieldName = new QComboBox( FALSE, buttonGroupSelectField, "comboBoxSelectFieldName" ); + comboBoxSelectFieldName->setGeometry( QRect( 150, 30, 280, 40 ) ); + for (int i=0 ; ilength() ; i++) + { + const char* strItem = (*listFields)[i]; + comboBoxSelectFieldName->insertItem(strItem); + } + comboBoxSelectFieldName->setEditable(false); + QToolTip::add( comboBoxSelectFieldName, tr( "only scalar fields are listed (multi-component fields are not displayed)" ) ); + + buttonGroupSelectFilter = new QButtonGroup( this, "buttonGroupSelectFilter" ); + buttonGroupSelectFilter->setGeometry( QRect( 10, 160, 450, 90 ) ); + + textLabelSelectFilter = new QLabel( buttonGroupSelectFilter, "textLabelSelectFilter" ); + textLabelSelectFilter->setGeometry( QRect( 30, 30, 101, 31 ) ); + + comboBoxSelectFilter = new QComboBox( FALSE, buttonGroupSelectFilter, "comboBoxSelectFilter" ); + comboBoxSelectFilter->setGeometry( QRect( 150, 30, 280, 40 ) ); + comboBoxSelectFilter->insertItem("Filtre_GradientMoyen"); + + buttonGroupParameters = new QButtonGroup( this, "buttonGroupParameters" ); + buttonGroupParameters->setGeometry( QRect( 10, 260, 450, 210 ) ); + + textLabelTMed = new QLabel( buttonGroupParameters, "textLabelTMed" ); + textLabelTMed->setGeometry( QRect( 20, 40, 242, 30 ) ); + + textLabelTLow = new QLabel( buttonGroupParameters, "textLabelTLow" ); + textLabelTLow->setGeometry( QRect( 20, 80, 208, 30 ) ); + + textLabelRadius = new QLabel( buttonGroupParameters, "textLabelRadius" ); + textLabelRadius->setGeometry( QRect( 20, 120, 211, 30 ) ); + + textLabelBoxing = new QLabel( buttonGroupParameters, "textLabelBoxing" ); + textLabelBoxing->setGeometry( QRect( 20, 160, 241, 30 ) ); + + lineEditTMed = new QLineEdit( buttonGroupParameters, "lineEditTMed" ); + lineEditTMed->setGeometry( QRect( 320, 40, 111, 30 ) ); + + lineEditTLow = new QLineEdit( buttonGroupParameters, "lineEditTLow" ); + lineEditTLow->setGeometry( QRect( 320, 80, 111, 30 ) ); + + lineEditRadius = new QLineEdit( buttonGroupParameters, "lineEditRadius" ); + lineEditRadius->setGeometry( QRect( 320, 120, 111, 30 ) ); + + spinBoxBoxing = new QSpinBox( buttonGroupParameters, "spinBoxBoxing" ); + spinBoxBoxing->setGeometry( QRect( 320, 160, 111, 30 ) ); + spinBoxBoxing->setMaxValue( 200 ); + spinBoxBoxing->setMinValue( 2 ); + spinBoxBoxing->setValue( 100 ); + + buttonGroupProcess = new QButtonGroup( this, "buttonGroupProcess" ); + buttonGroupProcess->setGeometry( QRect( 10, 480, 450, 60 ) ); + + pushButtonCancel = new QPushButton( buttonGroupProcess, "pushButtonCancel" ); + pushButtonCancel->setGeometry( QRect( 321, 10, 110, 41 ) ); + + pushButtonOK = new QPushButton( buttonGroupProcess, "pushButtonOK" ); + pushButtonOK->setGeometry( QRect( 10, 10, 110, 41 ) ); + + setCaption( tr( "Decimation" ) ); + buttonGroupSelectField->setTitle( tr( "Select field" ) ); + textLabelSelectFieldName->setText( tr( "Field name" ) ); + textLabelSelectFieldIteration->setText( tr( "Iteration" ) ); + buttonGroupSelectFilter->setTitle( tr( "Select filter" ) ); + textLabelSelectFilter->setText( tr( "Filter name" ) ); + buttonGroupParameters->setTitle( tr( "Set parameters" ) ); + textLabelTMed->setText( tr( "Threshold for medium resolution" ) ); + textLabelTLow->setText( tr( "Threshold for low resolution" ) ); + textLabelRadius->setText( tr( "Radius (neighborhood)" ) ); + textLabelBoxing->setText( tr( "Boxing parameter" ) ); + lineEditTMed->setText( tr( "0.1" ) ); + lineEditTLow->setText( tr( "0.2" ) ); + + float defaultRadius = 0.5f; + lineEditRadius->setText( QString::number(defaultRadius) ); + buttonGroupProcess->setTitle( QString::null ); + pushButtonCancel->setText( tr( "Cancel" ) ); + pushButtonOK->setText( tr("OK") ); + + pushButtonThresholdAuto = new QPushButton( buttonGroupParameters, "pushButtonThresholdAuto" ); + pushButtonThresholdAuto->setGeometry( QRect( 260, 80, 50, 30 ) ); + QFont pushButtonThresholdAuto_font( pushButtonThresholdAuto->font() ); + pushButtonThresholdAuto_font.setPointSize( 11 ); + pushButtonThresholdAuto->setFont( pushButtonThresholdAuto_font ); + pushButtonThresholdAuto->setText( tr( "auto" ) ); + QToolTip::add( pushButtonThresholdAuto, tr( "compute extremum for gradient (set medium=MIN and low=MAX)" ) ); + + pushButtonRadiusAuto = new QPushButton( buttonGroupParameters, "pushButtonRadiusAuto" ); + pushButtonRadiusAuto->setGeometry( QRect( 260, 120, 50, 30 ) ); + QFont pushButtonRadiusAuto_font( pushButtonRadiusAuto->font() ); + pushButtonRadiusAuto_font.setPointSize( 11 ); + pushButtonRadiusAuto->setFont( pushButtonRadiusAuto_font ); + pushButtonRadiusAuto->setText( tr( "auto" ) ); + QToolTip::add( pushButtonRadiusAuto, tr( "set radius automatically (average #neighbours equal to 8)" ) ); + + resize( QSize(470, 554).expandedTo(minimumSizeHint()) ); + clearWState( WState_Polished ); + + connect(pushButtonOK, SIGNAL(clicked()), this, SLOT(accept())); + connect(pushButtonCancel, SIGNAL(clicked()), this, SLOT(reject())); + connect(pushButtonRadiusAuto, SIGNAL(clicked()), this, SLOT(OnRadiusAuto())); + connect(pushButtonThresholdAuto, SIGNAL(clicked()), this, SLOT(OnThresholdAuto())); +} + + +/* + * Destroys the object and frees any allocated resources + */ +MULTIPR_GUI_DecimateDlg::~MULTIPR_GUI_DecimateDlg() +{ + // no need to delete child widgets, Qt does it all for us +} + + +void MULTIPR_GUI_DecimateDlg::accept() +{ + const char* strFieldName = comboBoxSelectFieldName->currentText().latin1(); + const char* strFieldIt = comboBoxSelectFieldIteration->currentText().latin1(); + int fieldIteration = atoi(strFieldIt); + + double thresholdMed; + int ret = sscanf(lineEditTMed->text().latin1(), "%lf", &thresholdMed); + if ((ret != 1) || (thresholdMed <= 0.0f)) + { + SUIT_MessageBox::error1( + mModule->getAppli()->desktop(), + "Decimation parameters error", + "Invalid medium threshold (should be > 0.0)", + tr("OK") ); + + return; + } + + double thresholdLow; + ret = sscanf(lineEditTLow->text().latin1(), "%lf", &thresholdLow); + if ((ret != 1) || (thresholdLow <= 0.0f)) + { + SUIT_MessageBox::error1( + mModule->getAppli()->desktop(), + "Decimation parameters error", + "Invalid low threshold (should be > 0.0)", + tr("OK") ); + + return; + } + + if (thresholdMed >= thresholdLow) + { + SUIT_MessageBox::error1( + mModule->getAppli()->desktop(), + "Decimation parameters error", + "Medium threshold must be < low threshold", + tr("OK") ); + + return; + } + + double radius; + ret = sscanf(lineEditRadius->text().latin1(), "%lf", &radius); + if ((ret != 1) || (radius <= 0.0f)) + { + SUIT_MessageBox::error1( + mModule->getAppli()->desktop(), + "Decimation parameters error", + "Invalid radius (should be > 0.0)", + tr("OK") ); + + return; + } + + QApplication::setOverrideCursor(Qt::waitCursor); + + try + { + const QStringList& partsList = mModule->getSelectedParts(); + for (QStringList::const_iterator it = partsList.begin(), last = partsList.end(); it != last; it++) + { + const QString& partName = (*it); + + mModule->getMULTIPRObj()->setBoxing(spinBoxBoxing->value()); + + mModule->getMULTIPRObj()->decimePartition( + partName.latin1(), + strFieldName, + fieldIteration, + comboBoxSelectFilter->currentText().latin1(), + thresholdMed, + thresholdLow, + radius); + } + } + catch(...) + { + SUIT_MessageBox::error1( + mModule->getAppli()->desktop(), + "Decimation error", + "Error while decimating selected part(s)", + tr("OK") ); + } + + QApplication::restoreOverrideCursor(); + QDialog::accept(); +} + + +void MULTIPR_GUI_DecimateDlg::reject() +{ + QDialog::reject(); +} + + +void MULTIPR_GUI_DecimateDlg::OnRadiusAuto() +{ + // evaluates default radius for the first selected part + const QStringList& partsList = mModule->getSelectedParts(); + char* strPartInfo0 = mModule->getMULTIPRObj()->getPartInfo(partsList[0].latin1()); + + char lMeshName[256]; + int lId; + char lPartName[256]; + char lPath[256]; + char lMEDFileName[256]; + + // parse infos + int ret = sscanf(strPartInfo0, "%s %d %s %s %s", + lMeshName, + &lId, + lPartName, + lPath, + lMEDFileName); + + QApplication::setOverrideCursor(Qt::waitCursor); + float defaultRadius = 0.5f; + try + { + multipr::Mesh* mesh = new multipr::Mesh(); + mesh->readSequentialMED(lMEDFileName, lMeshName); + const int averageNumberOfNeighbours = 8; + defaultRadius = mesh->evalDefaultRadius(averageNumberOfNeighbours); + delete mesh; + } + catch (...) + { + } + QApplication::restoreOverrideCursor(); + + lineEditRadius->setText( QString::number(defaultRadius) ); +} + + +void MULTIPR_GUI_DecimateDlg::OnThresholdAuto() +{ + // evaluates default radius for the first selected part + const QStringList& partsList = mModule->getSelectedParts(); + char* strPartInfo0 = mModule->getMULTIPRObj()->getPartInfo(partsList[0].latin1()); + + char lMeshName[256]; + int lId; + char lPartName[256]; + char lPath[256]; + char lMEDFileName[256]; + + // parse infos + int ret = sscanf(strPartInfo0, "%s %d %s %s %s", + lMeshName, + &lId, + lPartName, + lPath, + lMEDFileName); + + QApplication::setOverrideCursor(Qt::waitCursor); + float defaultRadius = 0.5f; + try + { + multipr::Mesh* mesh = new multipr::Mesh(); + mesh->readSequentialMED(lMEDFileName, lMeshName); + + multipr::DecimationFilter* filter = + multipr::DecimationFilter::create(comboBoxSelectFilter->currentText().latin1()); + + double gradMin = 0.1, gradAvg = 0.15, gradMax = 0.2; + + multipr::DecimationFilterGradAvg* filterGrad = dynamic_cast(filter); + if (filterGrad) + { + const char* strFieldIt = comboBoxSelectFieldIteration->currentText().latin1(); + int fieldIteration = atoi(strFieldIt); + + double radius; + ret = sscanf(lineEditRadius->text().latin1(), "%lf", &radius); + if ((ret != 1) || (radius <= 0.0f)) + { + SUIT_MessageBox::error1( + mModule->getAppli()->desktop(), + "Decimation parameters error", + "Invalid radius (should be > 0.0)", + tr("OK") ); + + return; + } + + filterGrad->getGradientInfo( + mesh, + comboBoxSelectFieldName->currentText().latin1(), + fieldIteration, + radius, + spinBoxBoxing->value(), + &gradMin, + &gradAvg, + &gradMax); + } + + delete filter; + delete mesh; + + lineEditTMed->setText( QString::number(gradMin) ); + lineEditTLow->setText( QString::number(gradMax) ); + } + catch (...) + { + } + QApplication::restoreOverrideCursor(); +} + + +//***************************************************************************** +// MULTIPR_GUI_ProgressCallbackDlg +//***************************************************************************** + +MULTIPR_GUI_ProgressCallbackDlg::MULTIPR_GUI_ProgressCallbackDlg(QWidget* parent) : + QProgressDialog(parent, 0, false, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu) +{ + setLabel(new QLabel(this, "Please wait")); + setLabelText("Please wait"); + setTotalSteps(100); +} + + +MULTIPR_GUI_ProgressCallbackDlg::~MULTIPR_GUI_ProgressCallbackDlg() +{ +} + + +void MULTIPR_GUI_ProgressCallbackDlg::start(const char* pTaskTitle, int pNumStep) +{ + setCaption(pTaskTitle); + MULTIPR_ProgressCallback::init(pNumStep); +} + + +void MULTIPR_GUI_ProgressCallbackDlg::done() +{ + setProgress(100); +} + + +void MULTIPR_GUI_ProgressCallbackDlg::progress(float pPercent) +{ + setProgress(int(pPercent)); +} + +// EOF diff --git a/src/MULTIPRGUI/MULTIPR_GUI_Dlg.h b/src/MULTIPRGUI/MULTIPR_GUI_Dlg.h new file mode 100644 index 0000000..c43df01 --- /dev/null +++ b/src/MULTIPRGUI/MULTIPR_GUI_Dlg.h @@ -0,0 +1,202 @@ +// Project MULTIPR, IOLS WP1.2.1 - EDF/CS +// Partitioning/decimation module for the SALOME v3.2 platform + +/** + * \file MULTIPR_GUI_Dlg.h + * + * \brief MULTIPR GUI Dialog (QT) + * + * \author Olivier LE ROUX - CS, Virtual Reality Dpt + * + * \date 01/2007 + */ + +#ifndef __MULTIPR_GUI_DLG__ +#define __MULTIPR_GUI_DLG__ + + +//***************************************************************************** +// Includes section +//***************************************************************************** + +#include +#include +#include +#include + +#include +#include CORBA_CLIENT_HEADER(MULTIPR) + +#include +#include +#include +#include + +#include "MULTIPR_ProgressCallback.hxx" + + +//***************************************************************************** +// Pre-declaration +//***************************************************************************** + +class SalomeApp_Application; +class CAM_Module; + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QSpacerItem; +class QButtonGroup; +class QLabel; +class QComboBox; +class QLineEdit; +class QSpinBox; +class QPushButton; + +class MULTIPR_GUI; + + + +//***************************************************************************** +// Class MULTIPR_GUI_Partition1Dlg +// Dialog box used for extracting groups from sequential MED file +//***************************************************************************** + +class MULTIPR_GUI_Partition1Dlg : public QDialog +{ + Q_OBJECT + +public: + MULTIPR_GUI_Partition1Dlg(MULTIPR_GUI* theModule); + ~MULTIPR_GUI_Partition1Dlg(); + + QButtonGroup* buttonGroupProcess; + QPushButton* pushButtonCancel; + QPushButton* pushButtonOK; + QButtonGroup* buttonGroupSelectMesh; + QComboBox* comboBoxSelectMesh; + QLabel* textLabelSelectMesh; + +protected slots: + void accept(); + void reject(); + +private: + MULTIPR_GUI* mModule; + +}; + + +//***************************************************************************** +// Class MULTIPR_GUI_Partition2Dlg +// Dialog box used for splitting a group (use MEDSPLITTER) +//***************************************************************************** + +class MULTIPR_GUI_Partition2Dlg : public QDialog +{ + Q_OBJECT + +public: + MULTIPR_GUI_Partition2Dlg(MULTIPR_GUI* theModule); + ~MULTIPR_GUI_Partition2Dlg(); + + QButtonGroup* buttonGroupSplitParameters; + QLabel* textLabelSelectNbParts; + QLabel* textLabelSelectSplitter; + QComboBox* comboBoxSelectSplitter; + QSpinBox* spinBoxNbParts; + QButtonGroup* buttonGroupProcess; + QPushButton* pushButtonOK; + QPushButton* pushButtonCancel; + +protected slots: + void accept(); + void reject(); + +private: + MULTIPR_GUI* mModule; +}; + + +//***************************************************************************** +// Class MULTIPR_GUI_DecimateDlg +// Dialog box used for decimating mesh (compute 2 lower resolution: medium and low) +//***************************************************************************** + +class MULTIPR_GUI_DecimateDlg : public QDialog +{ + Q_OBJECT + +public: + MULTIPR_GUI_DecimateDlg(MULTIPR_GUI* theModule); + ~MULTIPR_GUI_DecimateDlg(); + + QButtonGroup* buttonGroupSelectField; + QLabel* textLabelSelectFieldName; + QLabel* textLabelSelectFieldIteration; + QComboBox* comboBoxSelectFieldIteration; + QComboBox* comboBoxSelectFieldName; + QButtonGroup* buttonGroupSelectFilter; + QLabel* textLabelSelectFilter; + QComboBox* comboBoxSelectFilter; + QButtonGroup* buttonGroupParameters; + QLabel* textLabelTMed; + QLabel* textLabelTLow; + QLabel* textLabelRadius; + QLabel* textLabelBoxing; + QLineEdit* lineEditTMed; + QLineEdit* lineEditTLow; + QLineEdit* lineEditRadius; + QSpinBox* spinBoxBoxing; + QButtonGroup* buttonGroupProcess; + QPushButton* pushButtonCancel; + QPushButton* pushButtonOK; + QPushButton* pushButtonThresholdAuto; + QPushButton* pushButtonRadiusAuto; + +protected: + +protected slots: + void accept(); + void reject(); + void OnRadiusAuto(); + void OnThresholdAuto(); + +private: + MULTIPR_GUI* mModule; + +}; + + +//***************************************************************************** +// Class MULTIPR_GUI_ProgressCallbackDlg +//***************************************************************************** + +class MULTIPR_GUI_ProgressCallbackDlg : + public QProgressDialog, + public MULTIPR_ProgressCallback + +{ + Q_OBJECT + +public: + + MULTIPR_GUI_ProgressCallbackDlg(QWidget* parent); + + ~MULTIPR_GUI_ProgressCallbackDlg(); + + virtual void start(const char* pTaskTitle, int pNumStep); + + virtual void done(); + +protected: + + virtual void progress(float pPercent); +}; + + +#endif // __MULTIPR_GUI_DLG__ + + +// EOF + diff --git a/src/MULTIPRGUI/MULTIPR_icons.po b/src/MULTIPRGUI/MULTIPR_icons.po new file mode 100644 index 0000000..e7a6c52 --- /dev/null +++ b/src/MULTIPRGUI/MULTIPR_icons.po @@ -0,0 +1,37 @@ +# Copyright (C) 2005 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +# This is a Qt message file in .po format. Each msgid starts with +# a scope. This scope should *NOT* be translated - eg. "Foo::Bar" +# would be translated to "Pub", not "Foo::Pub". +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2002-05-28 10:57:43 AM CEST\n" +"PO-Revision-Date: YYYY-MM-DD\n" +"Last-Translator: FULLNAME \n" +"Content-Type: text/plain; charset=iso-8859-1\n" + +msgid "ICON_GET_BANNER" +msgstr "ExecMULTIPR.png" + +msgid "ICON_IMPORT_MED" +msgstr "MULTIPR_import_med.png" + +msgid "ICON_SAVE_MED" +msgstr "MULTIPR_save_med.png" diff --git a/src/MULTIPRGUI/MULTIPR_msg_en.po b/src/MULTIPRGUI/MULTIPR_msg_en.po new file mode 100644 index 0000000..e85b5fc --- /dev/null +++ b/src/MULTIPRGUI/MULTIPR_msg_en.po @@ -0,0 +1,92 @@ +# Copyright (C) 2005 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but MULTIPR_GUI ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +# This is a Qt message file in .po format. Each msgid starts with +# a scope. This scope should *NOT* be translated - eg. translating +# from French to English, "Foo::Bar" would be translated to "Pub", +# not "Foo::Pub". +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2003-11-19 03:10:19 PM CET\n" +"PO-Revision-Date: YYYY-MM-DD\n" +"Last-Translator: FULLNAME \n" +"Content-Type: text/plain; charset=iso-8859-1\n" + +msgid "MULTIPR_GUI::BUT_OK" +msgstr "OKO" + +msgid "MULTIPR_GUI::BUT_CANCEL" +msgstr "Cancel" + +msgid "TLT_IMPORT_FROM_MED_FILE" +msgstr "Import from MED file" + +msgid "MEN_IMPORT_FROM_MED_FILE" +msgstr "Import from MED file" + +msgid "STS_IMPORT_FROM_MED_FILE" +msgstr "Call import from sequential or distributed MED file" + +msgid "TLT_SPLIT" +msgstr "Split part" + +msgid "MEN_SPLIT" +msgstr "Split part" + +msgid "STS_SPLIT" +msgstr "Split selected parts of the current distributed mesh" + +msgid "TLT_DECIMATE" +msgstr "Decimate" + +msgid "MEN_DECIMATE" +msgstr "Decimate" + +msgid "STS_DECIMATE" +msgstr "Decimate selected parts (build two new meshes at lower resolution)" + +msgid "TLT_SAVE" +msgstr "Save distributed mesh" + +msgid "MEN_SAVE" +msgstr "Save distributed mesh" + +msgid "STS_SAVE" +msgstr "Save the current distributed MED file" + +msgid "MEN_FILE" +msgstr "&File" + +msgid "MEN_FILE_MULTIPR" +msgstr "Multipr" + +msgid "MEN_MULTIPR" +msgstr "Multipr" + +msgid "TOOL_MULTIPR" +msgstr "MULTIPR" + +msgid "FLT_ALL_FILES" +msgstr "All Files (*.*)" + +msgid "FLT_MED_FILES" +msgstr "MED Files (*.med)" + +msgid "USE_BUILD_PROGRESS" +msgstr "Use build progress" diff --git a/src/MULTIPRGUI/MULTIPR_msg_fr.po b/src/MULTIPRGUI/MULTIPR_msg_fr.po new file mode 100644 index 0000000..3722623 --- /dev/null +++ b/src/MULTIPRGUI/MULTIPR_msg_fr.po @@ -0,0 +1,80 @@ +# Copyright (C) 2005 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +# This is a Qt message file in .po format. Each msgid starts with +# a scope. This scope should *NOT* be translated - eg. translating +# from French to English, "Foo::Bar" would be translated to "Pub", +# not "Foo::Pub". +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2003-11-19 03:10:25 PM CET\n" +"PO-Revision-Date: YYYY-MM-DD\n" +"Last-Translator: FULLNAME \n" +"Content-Type: text/plain; charset=iso-8859-1\n" + +#: MULTIPR_GUI.cxx:76 +msgid "MULTIPR_GUI::BUT_OK" +msgstr "OK" + +#: MULTIPR_GUI.cxx:76 +msgid "MULTIPR_GUI::INF_MULTIPR_BANNER" +msgstr "Information MULTIPR" + +#: MULTIPR_GUI.cxx:76 +msgid "MULTIPR_GUI::INF_MULTIPR_MENU" +msgstr "Ceci est un simple test" + +#: MULTIPR_GUI.cxx:57 +msgid "MULTIPR_GUI::QUE_MULTIPR_LABEL" +msgstr "Import Prénom" + +#: MULTIPR_GUI.cxx:57 +msgid "MULTIPR_GUI::QUE_MULTIPR_NAME" +msgstr "Entrez votre prénom, s'il vous plait" + +msgid "TLT_MY_NEW_ITEM" +msgstr "My menu item" + +msgid "MEN_MY_NEW_ITEM" +msgstr "My menu item" + +msgid "STS_MY_NEW_ITEM" +msgstr "Call my menu item" + +msgid "TLT_GET_BANNER" +msgstr "Get MULTIPR banner" + +msgid "MEN_GET_BANNER" +msgstr "Get banner" + +msgid "STS_GET_BANNER" +msgstr "Get MULTIPR banner" + +msgid "MEN_FILE" +msgstr "&File" + +msgid "MEN_FILE_MULTIPR" +msgstr "Multipr" + +msgid "MEN_MULTIPR" +msgstr "MULTIPR" + +msgid "TOOL_MULTIPR" +msgstr "MULTIPR" + diff --git a/src/MULTIPRGUI/Makefile.in b/src/MULTIPRGUI/Makefile.in new file mode 100644 index 0000000..212cb33 --- /dev/null +++ b/src/MULTIPRGUI/Makefile.in @@ -0,0 +1,51 @@ +# Copyright (C) 2005 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +# source path +top_srcdir=@top_srcdir@ +top_builddir=../.. +srcdir=@srcdir@ +VPATH=.:@srcdir@:@top_srcdir@/idl:$(top_builddir)/idl:${KERNEL_ROOT_DIR}/idl/salome + +@COMMENCE@ + +# header files +EXPORT_HEADERS= + +# .po files to transform in .qm +PO_FILES = MULTIPR_msg_en.po MULTIPR_msg_fr.po MULTIPR_icons.po + +# Libraries targets +LIB = libMULTIPR.la +LIB_SRC = MULTIPR_GUI.cxx MULTIPR_GUI_Dlg.cxx +LIB_MOC = MULTIPR_GUI.h MULTIPR_GUI_Dlg.h + + +LIB_CLIENT_IDL = SALOMEDS.idl SALOME_Exception.idl SALOME_ModuleCatalog.idl SALOMEDS_Attributes.idl SALOME_Component.idl SALOME_GenericObj.idl MULTIPR.idl Logger.idl + +LIB_SERVER_IDL = + +# additionnal information to compil and link file + +CPPFLAGS += $(QT_INCLUDES) $(OCC_INCLUDES) $(PYTHON_INCLUDES) $(BOOST_CPPFLAGS) $(KERNEL_CXXFLAGS) $(GUI_CXXFLAGS) $(MED2_INCLUDES) $(HDF5_INCLUDES) -I$(MED_ROOT_DIR)/include/salome +CXXFLAGS += $(KERNEL_CXXFLAGS) $(GUI_CXXFLAGS) +LDFLAGS += -lSalomeApp -lMULTIPREngine $(KERNEL_LDFLAGS) $(GUI_LDFLAGS) -lmed -lmedsplitter -lmedmem -lhdf5 -lmed_V2_1 -lSALOMELocalTrace $(MED2_LIBS) $(HDF5_LIBS) -L$(MED_ROOT_DIR)/lib/salome + + + +@CONCLUDE@ diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..c8862d4 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,35 @@ +# Copyright (C) 2005 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +#============================================================================== +# File : Makefile.in +# Author : O. LE ROUX, CS +# Project : SALOME +#============================================================================== + +# source path +top_srcdir=@top_srcdir@ +top_builddir=.. +srcdir=@srcdir@ +VPATH=.:@srcdir@ + +@COMMENCE@ + +SUBDIRS = MULTIPR MULTIPRGUI + +@MODULE@