From 124a0e417b1854493fce1efe088c73cfcb4d50b9 Mon Sep 17 00:00:00 2001 From: Ovidiu Mircescu Date: Fri, 8 Jan 2016 17:55:11 +0100 Subject: [PATCH] Add an example for using MPIComponent and minor fixes. --- Examples/build.sh | 2 +- Examples/clean.sh | 2 +- Examples/mpi1/Makefile | 22 +++++++++ Examples/mpi1/README.txt | 15 ++++++ Examples/mpi1/build.sh | 6 +++ Examples/mpi1/components.py | 62 +++++++++++++++++++++++++ Examples/mpi1/coupling.xml | 52 +++++++++++++++++++++ Examples/mpi1/mpilib/Makefile | 11 +++++ Examples/mpi1/mpilib/include/mylibmpi.h | 12 +++++ Examples/mpi1/mpilib/src/myexempi.cxx | 26 +++++++++++ Examples/mpi1/mpilib/src/mylibmpi.cxx | 28 +++++++++++ Examples/parahxx1/Makefile | 21 +++++++++ Examples/parahxx1/build.sh | 5 ++ Examples/parahxx1/components.py | 61 ++++++++++++++++++++++++ Examples/parahxx1/coupling.xml | 52 +++++++++++++++++++++ module_generator/gener.py | 41 +++++++++------- module_generator/hxx_para_tmpl.py | 7 +-- module_generator/hxxcompo.py | 4 +- module_generator/hxxparacompo.py | 14 +++++- module_generator/mpicompo.py | 11 ++--- 20 files changed, 418 insertions(+), 36 deletions(-) create mode 100644 Examples/mpi1/Makefile create mode 100644 Examples/mpi1/README.txt create mode 100755 Examples/mpi1/build.sh create mode 100644 Examples/mpi1/components.py create mode 100644 Examples/mpi1/coupling.xml create mode 100644 Examples/mpi1/mpilib/Makefile create mode 100644 Examples/mpi1/mpilib/include/mylibmpi.h create mode 100644 Examples/mpi1/mpilib/src/myexempi.cxx create mode 100644 Examples/mpi1/mpilib/src/mylibmpi.cxx create mode 100644 Examples/parahxx1/Makefile create mode 100755 Examples/parahxx1/build.sh create mode 100644 Examples/parahxx1/components.py create mode 100644 Examples/parahxx1/coupling.xml diff --git a/Examples/build.sh b/Examples/build.sh index cc1c2f7..23787cb 100755 --- a/Examples/build.sh +++ b/Examples/build.sh @@ -10,7 +10,7 @@ script_dir=`dirname $0` cd $script_dir -list_dirs="calcium1 calcium2 cpp1 cpp2 cppgui1 fort1 fort2 pydoc1 pygui1 pyth1 pyth2 types1 hxx1" +list_dirs="calcium1 calcium2 cpp1 cpp2 cppgui1 fort1 fort2 pydoc1 pygui1 pyth1 pyth2 types1 mpi1 parahxx1 hxx1" for dir in $list_dirs ; do cd $dir echo Building $dir ... diff --git a/Examples/clean.sh b/Examples/clean.sh index 4908e47..475c693 100755 --- a/Examples/clean.sh +++ b/Examples/clean.sh @@ -4,7 +4,7 @@ script_dir=`dirname $0` cd $script_dir -list_dirs="calcium1 calcium2 cpp1 cpp2 cppgui1 fort1 fort2 pydoc1 pygui1 pyth1 pyth2 types1 hxx1" +list_dirs="calcium1 calcium2 cpp1 cpp2 cppgui1 fort1 fort2 pydoc1 pygui1 pyth1 pyth2 types1 mpi1 parahxx1 hxx1" for dir in $list_dirs ; do cd $dir diff --git a/Examples/mpi1/Makefile b/Examples/mpi1/Makefile new file mode 100644 index 0000000..53efb89 --- /dev/null +++ b/Examples/mpi1/Makefile @@ -0,0 +1,22 @@ +# Copyright (C) 2009-2015 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, or (at your option) any later version. +# +# 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 +# + +clean: + rm -rf *.o *.so appli install *.bak traceExec_* mymodule_* *.err *.log + cd mpilib; make clean diff --git a/Examples/mpi1/README.txt b/Examples/mpi1/README.txt new file mode 100644 index 0000000..bcffc2f --- /dev/null +++ b/Examples/mpi1/README.txt @@ -0,0 +1,15 @@ +A example of a MPI component +========================================= + +To build this example, modify the ../exec.sh file to take into account your configuration. +Run build.sh to build and test the component. + +You should get a SALOME module in source form (mymodule_SRC), its installation (install) and +a SALOME application (appli) composed of modules KERNEL, GUI, YACS and the new module cppcompos. + +To run a coupling: + + 1. start SALOME in background : ./appli/salome -t + 2. run the example schema in a SALOME session : ./appli/salome shell -- driver coupling.xml + 3. examine output files in /tmp + 4. shutdown SALOME : ./appli/salome killall diff --git a/Examples/mpi1/build.sh b/Examples/mpi1/build.sh new file mode 100755 index 0000000..34ef8e0 --- /dev/null +++ b/Examples/mpi1/build.sh @@ -0,0 +1,6 @@ +(cd mpilib; make) +../exec.sh python components.py + +# test +appli/salome shell ../test_compo.py + diff --git a/Examples/mpi1/components.py b/Examples/mpi1/components.py new file mode 100644 index 0000000..89185e4 --- /dev/null +++ b/Examples/mpi1/components.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +import os +from module_generator import Generator,Module,Service +from module_generator import MPIComponent +from module_generator import Library + +SALOME_ROOT=os.getenv("SALOME_DIR") +prerequis_file=os.path.join(SALOME_ROOT, "salome_prerequisites.sh") + +kernel_root_dir=os.getenv("KERNEL_ROOT_DIR") +gui_root_dir=os.getenv("GUI_ROOT_DIR") +yacs_root_dir=os.getenv("YACS_ROOT_DIR") + +context={'update':1, + "makeflags":"-j2", + "prerequisites":prerequis_file, + "kernel":kernel_root_dir + } + +cwd=os.getcwd() + +# PUT HERE DEFINITIONS OF THE COMPONENTS AND THE SERVICES +body_a=""" +Mylibmpi myinstance; +res_val = myinstance.mympi_funct(in_val); +""" + +defs_service=""" +""" + +service_s = Service("mpifunc", + inport=[("in_val", "long")], + outport=[("res_val", "long")], + body=body_a, + defs=defs_service + ) + +mpilib_root_path = os.path.join(cwd, "mpilib") +mpilib_include_path = os.path.join(mpilib_root_path, "include") +mpilib_lib_path = os.path.join(mpilib_root_path, "lib") + +compodefs = """ +#include "mylibmpi.h" +""" + +compo=MPIComponent("mycompoMpi", + services=[service_s], + compodefs=compodefs, + libs=[Library(name="mylibmpi", path=mpilib_lib_path)], + rlibs=mpilib_lib_path, + includes=mpilib_include_path, + ) + +g=Generator(Module("mymodule",components=[compo],prefix="./install"),context) +g.generate() +g.configure() +g.make() +g.install() +g.make_appli("appli", + restrict=["KERNEL","GUI","YACS","JOBMANAGER"]) + + diff --git a/Examples/mpi1/coupling.xml b/Examples/mpi1/coupling.xml new file mode 100644 index 0000000..a46afa6 --- /dev/null +++ b/Examples/mpi1/coupling.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mycompoMpi + + mpifunc + + + + + mpifunc1in_val + 1 + + + + diff --git a/Examples/mpi1/mpilib/Makefile b/Examples/mpi1/mpilib/Makefile new file mode 100644 index 0000000..fa89940 --- /dev/null +++ b/Examples/mpi1/mpilib/Makefile @@ -0,0 +1,11 @@ + +all : myexe + +myexe : lib/libmylibmpi.so src/myexempi.cxx include/mylibmpi.h + mpic++ -o myexe -Iinclude src/myexempi.cxx -Llib -lmylibmpi + +lib/libmylibmpi.so : src/mylibmpi.cxx include/mylibmpi.h + mkdir -p lib; mpic++ -shared -fPIC -o lib/libmylibmpi.so -Iinclude src/mylibmpi.cxx + +clean : + rm -f myexe lib/libmylibmpi.so *~ diff --git a/Examples/mpi1/mpilib/include/mylibmpi.h b/Examples/mpi1/mpilib/include/mylibmpi.h new file mode 100644 index 0000000..53d5317 --- /dev/null +++ b/Examples/mpi1/mpilib/include/mylibmpi.h @@ -0,0 +1,12 @@ +#ifndef _mylibmpi_h_ +#define _mylibmpi_h_ + +#define MASTER 0 + +class Mylibmpi +{ + public: + int mympi_funct(int v); +}; + +#endif \ No newline at end of file diff --git a/Examples/mpi1/mpilib/src/myexempi.cxx b/Examples/mpi1/mpilib/src/myexempi.cxx new file mode 100644 index 0000000..2bd2afa --- /dev/null +++ b/Examples/mpi1/mpilib/src/myexempi.cxx @@ -0,0 +1,26 @@ +#include "mylibmpi.h" +#include +#include + +int main(int argc, char* argv[]) +{ + int namelen, numprocs, myid ; + int result; + Mylibmpi myinstance; + + /** initialisation de mpi **/ + MPI_Init(&argc,&argv); + /** combien y-a-t-il de processeurs ? **/ + MPI_Comm_size(MPI_COMM_WORLD,&numprocs); + /** numero du processus courant **/ + MPI_Comm_rank(MPI_COMM_WORLD,&myid); + + result = myinstance.mympi_funct(3); + if(MASTER == myid) + std::cout << "Resultat:" << result << std::endl; + + /** fin du pg **/ + MPI_Finalize(); + + return 0; +} \ No newline at end of file diff --git a/Examples/mpi1/mpilib/src/mylibmpi.cxx b/Examples/mpi1/mpilib/src/mylibmpi.cxx new file mode 100644 index 0000000..9fd3b89 --- /dev/null +++ b/Examples/mpi1/mpilib/src/mylibmpi.cxx @@ -0,0 +1,28 @@ +#include "mylibmpi.h" +#include "mpi.h" + +int Mylibmpi::mympi_funct(int v) +{ + int namelen, numprocs, myid ; + char processor_name[MPI_MAX_PROCESSOR_NAME] ; + int local_result; + int result, err_code; + + /** combien y-a-t-il de processeurs ? **/ + MPI_Comm_size(MPI_COMM_WORLD,&numprocs); + /** numero du processus courant **/ + MPI_Comm_rank(MPI_COMM_WORLD,&myid); + /** num du processeur courant **/ + MPI_Get_processor_name(processor_name,&namelen); + + local_result = myid + v; + err_code = MPI_Reduce(&local_result, &result, 1, MPI_INT, MPI_SUM, + MASTER, MPI_COMM_WORLD); + if(MPI_SUCCESS != err_code) + printf("%d: failure on mpc_reduce\n", myid); + + return result; +// if(MASTER == myid) +//printf("id %d: result=%d\n", myid, result); + +} \ No newline at end of file diff --git a/Examples/parahxx1/Makefile b/Examples/parahxx1/Makefile new file mode 100644 index 0000000..a10053c --- /dev/null +++ b/Examples/parahxx1/Makefile @@ -0,0 +1,21 @@ +# Copyright (C) 2009-2015 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, or (at your option) any later version. +# +# 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 +# + +clean: + rm -rf *.o *.so appli install *.bak traceExec_* hxxcompos_* *.err *.log par* diff --git a/Examples/parahxx1/build.sh b/Examples/parahxx1/build.sh new file mode 100755 index 0000000..5578fe9 --- /dev/null +++ b/Examples/parahxx1/build.sh @@ -0,0 +1,5 @@ +../exec.sh python components.py + +# test +LD_LIBRARY_PATH=`pwd`/../mpi1/mpilib/lib/ appli/salome shell ../test_compo.py + diff --git a/Examples/parahxx1/components.py b/Examples/parahxx1/components.py new file mode 100644 index 0000000..b907cae --- /dev/null +++ b/Examples/parahxx1/components.py @@ -0,0 +1,61 @@ +# Copyright (C) 2009-2015 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, or (at your option) any later version. +# +# 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 +# + +import os +from module_generator import Generator,Module,Service +from module_generator import CPPComponent,PYComponent,HXX2SALOMEParaComponent +class Invalid(Exception): + pass + +kernel_root_dir=os.environ["KERNEL_ROOT_DIR"] +gui_root_dir=os.environ["GUI_ROOT_DIR"] +yacs_root_dir=os.environ["YACS_ROOT_DIR"] +med_root_dir=os.environ["MED_ROOT_DIR"] +SALOME_ROOT=os.getenv("SALOME_DIR") +prereq_file=os.path.join(SALOME_ROOT, "salome_prerequisites.sh") + +if not os.path.exists(prereq_file): + prereq_file=os.path.join(kernel_root_dir,"..","..","env_products.sh") +if not os.path.exists(prereq_file): + raise Invalid("prerequisite file env_products.sh not found. please replace it manually in component.py") + +context={'update':1, + "makeflags":"", + "prerequisites":prereq_file, + "kernel":kernel_root_dir, + "gui":gui_root_dir, + "med":med_root_dir, + "yacs":yacs_root_dir, + } + +cwd=os.getcwd() +cpppath=os.path.join(cwd,"..","mpi1","mpilib") + +# PUT HERE DEFINITIONS OF THE COMPONENTS AND THE SERVICES + +c1=HXX2SALOMEParaComponent("mylibmpi.h","libmylibmpi.so" , cpppath ) + +g=Generator(Module("hxxcompos",components=[c1],prefix="./install"),context) +g.generate() +g.configure() +g.make() +g.install() +g.make_appli("appli", + restrict=["KERNEL","GUI","YACS","MED"], + ) diff --git a/Examples/parahxx1/coupling.xml b/Examples/parahxx1/coupling.xml new file mode 100644 index 0000000..03d6ed3 --- /dev/null +++ b/Examples/parahxx1/coupling.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Mylibmpi + + mympi_funct + + + + + mympi_funct1v + 1 + + + + diff --git a/module_generator/gener.py b/module_generator/gener.py index 4487248..2464b2b 100644 --- a/module_generator/gener.py +++ b/module_generator/gener.py @@ -170,7 +170,7 @@ class Component(object): cmake_vars = cmake_vars + "${" + lib.cmakeVarName() + "}\n " var_template = Template("$${${name}_SalomeIDL${name}}") - for mod in self.depend_modules: + for mod in self.getDependentModules(): if salome_modules[mod]["linklibs"]: cmake_vars = cmake_vars + salome_modules[mod]["linklibs"] else: @@ -247,6 +247,24 @@ class Component(object): idldefs = idldefs + self.interfacedefs return idldefs + def getDependentModules(self): + """get the list of SALOME modules used by the component + """ + def get_dependent_modules(mod,modules): + modules.add(mod) + if salome_modules[mod].has_key("depends"): + for m in salome_modules[mod]["depends"]: + if m not in modules: + get_dependent_modules(m,modules) + + depend_modules = set() + for serv in self.services: + for name, typ in serv.inport + serv.outport + [ ("return",serv.ret) ] : + mod = moduleTypes[typ] + if mod: + get_dependent_modules(mod,depend_modules) + return depend_modules + class Service(object): """ A :class:`Service` instance represents a component service with dataflow and datastream ports. @@ -425,24 +443,11 @@ class Generator(object): srcs = {} #get the list of SALOME modules used and put it in used_modules attribute - def get_dependent_modules(mod,modules): - modules[mod]=1 - if not salome_modules[mod].has_key("depends"):return - for m in salome_modules[mod]["depends"]: - if modules.has_key(m):continue - get_dependent_modules(m,modules) - - modules = {} + modules = set() for compo in module.components: - compo.depend_modules = set() - for serv in compo.services: - for name, typ in serv.inport + serv.outport + [ ("return",serv.ret) ] : - mod = moduleTypes[typ] - if mod: - get_dependent_modules(mod,modules) - compo.depend_modules.add(mod) - - self.used_modules = modules.keys() + modules |= compo.getDependentModules() + + self.used_modules = modules for compo in module.components: #for components files diff --git a/module_generator/hxx_para_tmpl.py b/module_generator/hxx_para_tmpl.py index c826faa..8f9448d 100644 --- a/module_generator/hxx_para_tmpl.py +++ b/module_generator/hxx_para_tmpl.py @@ -221,6 +221,7 @@ INCLUDE_DIRECTORIES( $${OMNIORB_INCLUDE_DIR} $${PROJECT_BINARY_DIR} $${PROJECT_BINARY_DIR}/idl + $${MEDCOUPLING_INCLUDE_DIRS} ${includes} ) @@ -238,13 +239,9 @@ SET(_link_LIBRARIES $${KERNEL_SalomeIDLKernel} $${KERNEL_OpUtil} $${KERNEL_SalomeContainer} - $${KERNEL_SalomeDSCContainer} - $${KERNEL_SalomeDSCSuperv} - $${KERNEL_SalomeDatastream} - $${KERNEL_SalomeDSCSupervBasic} - $${KERNEL_CalciumC} $${KERNEL_SalomeMPIContainer} $${MED_paramedmemcompo} + $${MED_paramedcouplingcorba} SalomeIDL${module} ${libs} ) diff --git a/module_generator/hxxcompo.py b/module_generator/hxxcompo.py index 41aae04..ff39cb4 100644 --- a/module_generator/hxxcompo.py +++ b/module_generator/hxxcompo.py @@ -531,9 +531,9 @@ class HXX2SALOMEComponent(Component): services = self.getIdlServices() from hxx_tmpl import interfaceidlhxx Inherited="" - if compo.use_medmem==True: + if self.use_medmem==True: Inherited="Engines::EngineComponent,SALOME::MultiCommClass,SALOME_MED::MED_Gen_Driver" else: Inherited="Engines::EngineComponent" - return interfaceidlhxx.substitute(component=compo.name,inherited=Inherited, services="\n".join(services)) + return interfaceidlhxx.substitute(component=self.name,inherited=Inherited, services="\n".join(services)) diff --git a/module_generator/hxxparacompo.py b/module_generator/hxxparacompo.py index b27d003..b2eeece 100644 --- a/module_generator/hxxparacompo.py +++ b/module_generator/hxxparacompo.py @@ -476,5 +476,17 @@ void *th_%(serv_name)s(void *s) from hxx_tmpl import interfaceidlhxx Inherited="" Inherited="SALOME_MED::ParaMEDMEMComponent" + return interfaceidlhxx.substitute(component=self.name,inherited=Inherited, services="\n".join(services)) + + def getIdlDefs(self): idldefs="""#include "ParaMEDMEMComponent.idl"\n""" - return interfaceidlhxx.substitute(component=compo.name,inherited=Inherited, services="\n".join(services)) + if self.interfacedefs: + idldefs = idldefs + self.interfacedefs + return idldefs + + def getDependentModules(self): + """ This component depends on "MED" because it inherits from ParaMEDMEMComponent + """ + depend_modules = Component.getDependentModules(self) + depend_modules.add("MED") + return depend_modules diff --git a/module_generator/mpicompo.py b/module_generator/mpicompo.py index 21b20ad..2ea388d 100644 --- a/module_generator/mpicompo.py +++ b/module_generator/mpicompo.py @@ -42,8 +42,7 @@ class MPIComponent(CPPComponent): :param name: gives the name of the component. :type name: str :param services: the list of services (:class:`Service`) of the component. - :param kind: If it is given and has the value "exe", the component will be built as a standalone - component (executable or shell script). The default is to build the component as a dynamic library. + :param kind: For this type of component, "lib" is the unique valid option. The component is built as a dynamic library. :param libs: list of the additional libraries. see *Library* class. If you want to add "libmylib.so", installed in "/path/to/lib" you should use: libs=[Library(name="mylib", path="/path/to/lib")] @@ -106,11 +105,7 @@ class MPIComponent(CPPComponent): cmake_vars = "${KERNEL_SalomeMPIContainer}\n " + cmake_vars cxxfile = "%s.cxx" % self.name hxxfile = "%s.hxx" % self.name - if self.kind == "exe": - exe_opt = 1 - else: - exe_opt = 0 - ret = { cxxfile:self.makecxx(gen, exe_opt), + ret = { cxxfile:self.makecxx(gen), hxxfile:self.makehxx(gen) } sources = " ".join(map(os.path.basename,self.sources)) @@ -159,7 +154,7 @@ class MPIComponent(CPPComponent): servicesdef=servicesdef, inheritedclass=inheritedclass, compodefs=compodefs) - def makecxx(self, gen, exe=0): + def makecxx(self, gen): """return a string that is the content of .cxx file """ services = [] -- 2.39.2