From 60b56b221925a9a0449b47f24ef76432d8c68d36 Mon Sep 17 00:00:00 2001 From: abn Date: Mon, 2 Nov 2015 13:00:54 +0100 Subject: [PATCH] Enhance doc on parallelism. --- doc/user/doxygen/Doxyfile_med_user.in | 4 + .../doxfiles/reference/distrib/parallel.dox | 84 +++- .../reference/fields/discretization.dox | 53 ++- .../reference/interpolation/interpolation.dox | 4 +- .../reference/interpolation/intersectors.dox | 7 +- src/INTERP_KERNEL/InterpolationOptions.hxx | 4 +- src/MEDCoupling/MEDCouplingFieldTemplate.hxx | 9 +- src/MEDCoupling/MEDCouplingRefCountObject.hxx | 2 + src/ParaMEDMEM/BlockTopology.cxx | 173 +++---- src/ParaMEDMEM/BlockTopology.hxx | 12 +- src/ParaMEDMEM/CMakeLists.txt | 1 + src/ParaMEDMEM/CommInterface.cxx | 12 +- src/ParaMEDMEM/ComponentTopology.hxx | 8 + src/ParaMEDMEM/DEC.hxx | 9 + src/ParaMEDMEM/DECOptions.hxx | 57 ++- src/ParaMEDMEM/DisjointDEC.cxx | 50 +- src/ParaMEDMEM/DisjointDEC.hxx | 5 +- src/ParaMEDMEM/ElementLocator.cxx | 36 +- src/ParaMEDMEM/ElementLocator.hxx | 4 +- src/ParaMEDMEM/ExplicitCoincidentDEC.cxx | 68 ++- src/ParaMEDMEM/ExplicitMapping.cxx | 159 +++++++ src/ParaMEDMEM/ExplicitMapping.hxx | 143 +----- src/ParaMEDMEM/ExplicitTopology.cxx | 5 + src/ParaMEDMEM/ExplicitTopology.hxx | 9 +- src/ParaMEDMEM/InterpKernelDEC.cxx | 74 +-- src/ParaMEDMEM/InterpolationMatrix.hxx | 6 +- src/ParaMEDMEM/LinearTimeInterpolator.hxx | 5 + src/ParaMEDMEM/MPIAccessDEC.cxx | 2 +- src/ParaMEDMEM/MPIAccessDEC.hxx | 5 + src/ParaMEDMEM/MPIProcessorGroup.cxx | 29 +- src/ParaMEDMEM/MxN_Mapping.cxx | 8 +- src/ParaMEDMEM/MxN_Mapping.hxx | 7 +- src/ParaMEDMEM/NonCoincidentDEC.cxx | 17 +- src/ParaMEDMEM/OverlapDEC.cxx | 21 +- src/ParaMEDMEM/OverlapDEC.hxx | 2 +- src/ParaMEDMEM/OverlapElementLocator.hxx | 1 - src/ParaMEDMEM/OverlapInterpolationMatrix.hxx | 5 + src/ParaMEDMEM/OverlapMapping.hxx | 7 + src/ParaMEDMEM/ParaFIELD.cxx | 17 +- src/ParaMEDMEM/ParaFIELD.hxx | 6 +- src/ParaMEDMEM/ParaGRID.cxx | 4 +- src/ParaMEDMEM/ParaGRID.hxx | 4 + src/ParaMEDMEM/ParaMESH.cxx | 2 +- src/ParaMEDMEM/ParaMESH.hxx | 15 +- src/ParaMEDMEM/ProcessorGroup.hxx | 5 + src/ParaMEDMEM/README | 194 ++++++++ src/ParaMEDMEM/README_JR | 446 ------------------ src/ParaMEDMEM/StructuredCoincidentDEC.cxx | 47 +- src/ParaMEDMEM/StructuredCoincidentDEC.hxx | 1 + src/ParaMEDMEM/TimeInterpolator.hxx | 6 + src/ParaMEDMEM/Topology.hxx | 9 +- 51 files changed, 999 insertions(+), 864 deletions(-) create mode 100644 src/ParaMEDMEM/ExplicitMapping.cxx create mode 100644 src/ParaMEDMEM/README delete mode 100644 src/ParaMEDMEM/README_JR diff --git a/doc/user/doxygen/Doxyfile_med_user.in b/doc/user/doxygen/Doxyfile_med_user.in index 6c4cc970d..dbb6c5596 100644 --- a/doc/user/doxygen/Doxyfile_med_user.in +++ b/doc/user/doxygen/Doxyfile_med_user.in @@ -101,8 +101,11 @@ INPUT = @CMAKE_CURRENT_SOURCE_DIR@/doxfiles/index.dox \ FILE_PATTERNS = InterpKernelDEC.* \ OverlapDEC.* \ DEC.* \ + DECOptions.* \ DisjointDEC.* \ + *Topology.* \ MPIProcessorGroup.* \ + ProcessorGroup.* \ MPIAccess.* \ StructuredCoincidentDEC.* \ ExplicitCoincidentDEC.* \ @@ -128,6 +131,7 @@ FILE_PATTERNS = InterpKernelDEC.* \ InterpKernelGeo2DNode.* \ InterpKernelGeo2DQuadraticPolygon.* \ ParaFIELD.* \ + ParaMESH.* \ MEDCouplingMesh.* \ MEDCouplingUMesh.* \ MEDCoupling1GTUMesh.* \ diff --git a/doc/user/doxygen/doxfiles/reference/distrib/parallel.dox b/doc/user/doxygen/doxfiles/reference/distrib/parallel.dox index d53c9965f..0c197817a 100644 --- a/doc/user/doxygen/doxfiles/reference/distrib/parallel.dox +++ b/doc/user/doxygen/doxfiles/reference/distrib/parallel.dox @@ -1,33 +1,81 @@ /*! \page parallel Parallelism -\section para-over Base elements +\section para-over Building blocks Several classes and methods are available in the MED library to ease the exchange of information -in a parallel context. -For historical reasons, they are all in the same namespace as the non-parallel MEDCoupling functionalities, +in a parallel context. The DECs (\ref para-dec "detailed further down") then use those classes to enable +the parallel remapping (projection) of a field. +For historical reasons, all those items are in the same namespace as the non-parallel MEDCoupling functionalities, %ParaMEDMEM. The core elements of the API are: -- \ref ParaFIELD-det "ParaFIELD", the parallel instanciation of a MEDCoupling field -- \ref CommInterface-det "CommInterface", communication interface to the gateway to the MPI library -- \ref MPIProcessorGroup-det "MPIProcessorGroup", a group of processor in a parallel computation - -along with all the DEC explained below. +- \ref CommInterface-det "CommInterface", this is the wrapper around the MPI library, and an instance +of this object is required in many constructors of the following objects. +- \ref ParaMESH-det "ParaMESH", the parallel instanciation of a \ref meshes "MEDCoupling mesh" +- \ref ParaFIELD-det "ParaFIELD", the parallel instanciation of a \ref fields "MEDCoupling field" +- \ref MPIProcessorGroup-det "MPIProcessorGroup" (which inherits from the abstract +\ref ParaMEDMEM::ProcessorGroup "ProcessorGroup"), a group of processors (typically MPI nodes) +In an advanced usage, the topology of the nodes in the computation is accessed through the following elements: +- \ref BlockTopology-det "BlockTopology", specification of a topology based on the (structured) mesh. +The mesh is divided in block (typically a split along the first axis) which are allocated on the various +processors. +- %ExplicitTopology (not fully supported yet and only used internally), specification of user-defined +topology, still based on the mesh. +- \ref ComponentTopology-det "ComponentTopology", specification of a topology allowing the split of +several field *components* among different processors. The mesh is not the support of the topology anymore. + \section para-dec Data Exchange Channel - DEC -A Data Exchange Channel allows the transfer of information between two processor groups. -There are several variants of DEC depending on what you are aiming at: +A Data Exchange Channel (%DEC) allows the transfer and/or the interpolation (remapping) of field data between several +processors in a parallel (MPI) context. +Some DECs perform a simple renumbering and copy of the data, and some are capable of functionalities similar to the +\ref remapper "sequential remapper". -- \ref DisjointDEC-det "DisjointDEC" -- \ref InterpKernelDEC-det "InterpKernelDEC" -- \ref NonCoincidentDEC-det "NonCoincidentDEC" -- \ref OverlapDEC-det "OverlapDEC" -- \ref ExplicitCoincidentDEC-det "ExplicitCoincidentDEC" -- \ref StructuredCoincidentDEC-det "StructuredCoincidentDEC" - - TODO: more on DEC. +We list here the main characteristics of the DECs, the list being structured in the same +way as the class hierarchy: + +- \ref DisjointDEC-det "DisjointDEC", works with two disjoint groups of processors. This is an abstract class. + - \ref InterpKernelDEC-det "InterpKernelDEC", inherits the properties of the \c %DisjointDEC. The projection + methodology is based on the algorithms of %INTERP_KERNEL, that is to say, they work in a similar fashion than + what the \ref remapper "sequential remapper" does. The following \ref discretization "projection methods" + are supported: P0->P0 (the most common case), P1->P0, P0->P1. + - \ref StructuredCoincidentDEC-det "StructuredCoincidentDEC", also inherits the properties + of the \c %DisjointDEC, but this one is \b not based on the %INTERP_KERNEL algorithms. + This DEC does a simple data transfer between two fields having a common (coincident) structured support, + but different topologies (i.e. the structured domain is split differently among the processors for the + two fields). Only the cell identifiers are handled, and no kind of interpolation (in the sense of the + computation of a weight matrix) is performed. It is a "mere" reallocation of data from one domain + partitioning to another. + - \b ExplicitCoincidentDEC : as above, but based on an explicit topology. This DEC is used internally but + rarely directly in the public API. +- \ref OverlapDEC-det "OverlapDEC", works with a single processor group, but each processor detains +both (part of) the source and target fields. This %DEC can really be seen as the true parallelisation of the +\ref remapper "sequential remapper". Similarly to the \ref InterpKernelDEC-det "InterpKernelDEC" +the projection methodology is based on the algorithms of %INTERP_KERNEL, that is to say, +it works in a similar fashion than what the \ref remapper "sequential remapper" does. +- \b NonCoincidentDEC (deprecated for now) + +Besides, all the DECs inherit from the class \ref ParaMEDMEM::DECOptions "DECOptions" which provides +the necessary methods to adjust the parameters used in the transfer/remapping. + +The most commonly used %DEC is the \c %InterpKernelDEC, and here is a simple example to of its usage: + + \code +... +InterpKernelDEC dec(groupA, groupB); // groupA and groupB are two MPIProcessorGroup +dec.attachLocalField(field); // field is a ParaFIELD, a MEDCouplingField or an ICoCo::MEDField +dec.synchronize(); // compute the distributed interpolation matrix +if (groupA.containsMyRank()) +dec.recvData(); // effectively transfer the field (receiving side) +else if (groupB.containsMyRank()) +dec.sendData(); // effectively transfer the field (sending side) +... +\endcode +\n +\n +\n */ diff --git a/doc/user/doxygen/doxfiles/reference/fields/discretization.dox b/doc/user/doxygen/doxfiles/reference/fields/discretization.dox index 907890bae..dc466df78 100644 --- a/doc/user/doxygen/doxfiles/reference/fields/discretization.dox +++ b/doc/user/doxygen/doxfiles/reference/fields/discretization.dox @@ -1,21 +1,56 @@ /*! \page discretization Spatial and temporal discretizations -TODO: enhance this page +When defining a field in MEDCoupling, the notions of spatial and temporal discretizations play +a crucial role. + +The spatial discretization details the relationship between the field and its support mesh +and the temporal discretization gives an indication of the time coverage represented +by the field. \section field-space Spatial discretization A field can be supported by: -- the nodes (vertices) of the mesh: built with the -\ref ParaMEDMEM::MEDCouplingFieldDouble::New "ON_NODES" keyword. This is sometimes called a P1 field. +- the nodes (vertices) of the mesh: this is built with the +\ref ParaMEDMEM::TypeOfField "ON_NODES" keyword in the +\ref ParaMEDMEM::MEDCouplingFieldDouble::New(TypeOfField , TypeOfTimeDiscretization) "constructor of a field". + - the cells (or "elements") of the mesh: built with the -\ref ParaMEDMEM::MEDCouplingFieldDouble::New "ON_CELLS" keyword. This is sometimes called a P0 field. -- or more complex items (Gauss points, etc ...) +\ref ParaMEDMEM::TypeOfField "ON_CELLS" keyword in the +\ref ParaMEDMEM::MEDCouplingFieldDouble::New(TypeOfField , TypeOfTimeDiscretization) "constructor of a field". +- or more complex items: + - Gauss points: built with \ref ParaMEDMEM::TypeOfField "ON_GAUSS_PT" + - Gauss points on nodes per element: built with \ref ParaMEDMEM::TypeOfField "ON_GAUSS_NE" + - Kriging points: built with \ref ParaMEDMEM::TypeOfField "ON_NODES_KR" + +The spatial discretization is at the center of the \ref interpolation "interpolation" mechanisms, +since one of the main interpolation paramter is indeed specifying from which source discretization +to which target discretization one wants to go. For example: +- a P0->P0 interpolation means that a field on cells will be transfered to another cell-based field; +- a P1->P0 interpolation means that a field on nodes this time will be transfered to a cell-based field. +- etc ... + +Finally, in the code itself, the class \ref ParaMEDMEM::MEDCouplingFieldDiscretization "MEDCouplingFieldDiscretization" +is the concrete representation of this concept. \section field-time Temporal discretization -A field has a temporal discretization. It can be one of: -- \ref ParaMEDMEM::MEDCouplingFieldDouble::New "NO_TIME" -- \ref ParaMEDMEM::MEDCouplingFieldDouble::New "ONE_TIME" -- \ref ParaMEDMEM::MEDCouplingFieldDouble::New "CONST_ON_TIME_INTERVAL" +Similarly to the spatial discretization, a field object in MEDCoupling has a time discretization +representing the time range that is covered by the data. It is also specified in the +\ref ParaMEDMEM::MEDCouplingFieldDouble::New(TypeOfField , TypeOfTimeDiscretization) "constructor of a field". + +It can be one of: +- \ref ParaMEDMEM::TypeOfTimeDiscretization "NO_TIME", in this case no time is attached to the field, and no +time-related operation is permitted (for example unable to call +\ref ParaMEDMEM::MEDCouplingFieldDouble::getValueOnTime() "getValueOnTime()") +- \ref ParaMEDMEM::TypeOfTimeDiscretization "ONE_TIME", the field data represent a single time step. +- \ref ParaMEDMEM::TypeOfTimeDiscretization "LINEAR_TIME", the field data contains \b two arrays, stamped with two +different time points. A linear interpolation of the field values between those two time steps is then possible. +- \ref ParaMEDMEM::TypeOfTimeDiscretization "CONST_ON_TIME_INTERVAL", the field data contains a single array +of data, but a start- and end-time can be specified, thus declaring that the field represent a constant +set of data during this time interval. All time evaluation function then just check that the given time +fits in the interval. + +Finally, in the code itself, the class \ref ParaMEDMEM::MEDCouplingTimeDiscretization "MEDCouplingTimeDiscretization" +is the concrete representation of this concept. */ diff --git a/doc/user/doxygen/doxfiles/reference/interpolation/interpolation.dox b/doc/user/doxygen/doxfiles/reference/interpolation/interpolation.dox index ef9db963e..e8319c70d 100644 --- a/doc/user/doxygen/doxfiles/reference/interpolation/interpolation.dox +++ b/doc/user/doxygen/doxfiles/reference/interpolation/interpolation.dox @@ -2,12 +2,14 @@ \page interpolation Interpolation -Interpolation (or projection) methods is a key feature of the MEDCoupling library. +Interpolation (or projection) methods are a key feature of the MEDCoupling library. It allows to "transfer" the values of a field on a given source mesh to another, newly created field on a target mesh. The two meshes/fields need not to have the same \ref MEDCouplingMeshes "mesh/spatial dimension", nor do they need to have the same \ref discretization "discretization". + + - \subpage intro-interp - \subpage InterpKerRemapGlobal - \subpage NatureOfField diff --git a/doc/user/doxygen/doxfiles/reference/interpolation/intersectors.dox b/doc/user/doxygen/doxfiles/reference/interpolation/intersectors.dox index c38a87965..1729060bd 100644 --- a/doc/user/doxygen/doxfiles/reference/interpolation/intersectors.dox +++ b/doc/user/doxygen/doxfiles/reference/interpolation/intersectors.dox @@ -1,16 +1,17 @@ /*! -\page InterpKerIntersectors Intersectors +\page InterpKerIntersectors Intersectors and point locators The various interpolation methods often require the computation of the intersection between -a cell of the source mesh and a cell of the target mesh. The intersectors implemented in the +a cell of the source mesh and a cell of the target mesh, or the localization of a point +inside another mesh. The intersectors implemented in the library take care of this job. Before reading on, remember the definition of a \ref glossary "P0 and P1 field". - \subpage intersec-specifics - \subpage interpkernelGeo2D -- \subpage barycoords (used in some P1 intersectors) +- \subpage barycoords (used in some P1 intersectors/locators) Some implementation details of the C++ code can also be found here: \ref interpkernel diff --git a/src/INTERP_KERNEL/InterpolationOptions.hxx b/src/INTERP_KERNEL/InterpolationOptions.hxx index 61fc7141b..60bd70d96 100644 --- a/src/INTERP_KERNEL/InterpolationOptions.hxx +++ b/src/INTERP_KERNEL/InterpolationOptions.hxx @@ -31,8 +31,8 @@ namespace INTERP_KERNEL typedef enum { Triangulation, Convex, Geometric2D, PointLocator, Barycentric, BarycentricGeo2D } IntersectionType; /*! - * \class InterpolationOptions - * Class defining the options for all interpolation algorithms. + * Class defining the options for all interpolation algorithms used in the \ref MEDCouplingRemapper "remapper" and + * in some of the \ref para-dec "DECs". * * List of options, possible values and default values can be found on this page: * \ref InterpKerIntersectors diff --git a/src/MEDCoupling/MEDCouplingFieldTemplate.hxx b/src/MEDCoupling/MEDCouplingFieldTemplate.hxx index 8b3a3c8dd..6fa402cf6 100644 --- a/src/MEDCoupling/MEDCouplingFieldTemplate.hxx +++ b/src/MEDCoupling/MEDCouplingFieldTemplate.hxx @@ -27,11 +27,14 @@ namespace ParaMEDMEM { class MEDCouplingFieldDouble; /*! - * \brief A field template can be seen as a field without array of values. + * \brief A field template can be seen as a field without the array of values. * - * A field template instance aggregates a MEDCouplingMesh instance and a spatial discretization object (instance of MEDCouplingFieldDiscretization). + * A field template aggregates a MEDCouplingMesh and a spatial discretization object (instance of + * MEDCouplingFieldDiscretization). * - * Instances of type MEDCouplingFieldTemplate are the most appropriate for preparation of matrix using MEDCouplingRemapper::prepareEx. + * MEDCouplingFieldTemplate is the most appropriate type for the preparation of matrix using + * MEDCouplingRemapper::prepareEx, since it contains the minimal information requireds to prepare + * the interpolation matrix. */ class MEDCouplingFieldTemplate : public MEDCouplingField { diff --git a/src/MEDCoupling/MEDCouplingRefCountObject.hxx b/src/MEDCoupling/MEDCouplingRefCountObject.hxx index 4eea72a52..897cdc6f7 100644 --- a/src/MEDCoupling/MEDCouplingRefCountObject.hxx +++ b/src/MEDCoupling/MEDCouplingRefCountObject.hxx @@ -36,6 +36,7 @@ namespace ParaMEDMEM CPP_DEALLOC = 3 } DeallocType; + //! The various spatial discretization of a field typedef enum { ON_CELLS = 0, @@ -45,6 +46,7 @@ namespace ParaMEDMEM ON_NODES_KR = 4 } TypeOfField; + //! The various temporal discretization of a field typedef enum { NO_TIME = 4, diff --git a/src/ParaMEDMEM/BlockTopology.cxx b/src/ParaMEDMEM/BlockTopology.cxx index 8f6b4cea8..7297be21c 100644 --- a/src/ParaMEDMEM/BlockTopology.cxx +++ b/src/ParaMEDMEM/BlockTopology.cxx @@ -35,88 +35,15 @@ using namespace std; namespace ParaMEDMEM { - - //!converts a pair to a global number - std::pair BlockTopology::globalToLocal(const int global) const - { - int subdomain_id=0; - int position=global; - int size=_nb_elems; - int size_procs=_proc_group->size(); - int increment=size; - vectoraxis_position(_dimension); - vectoraxis_offset(_dimension); - for (int idim=0; idim<_dimension; idim++) - { - int axis_size=_local_array_indices[idim].size()-1; - int axis_nb_elem=_local_array_indices[idim][axis_size]; - increment=increment/axis_nb_elem; - int proc_increment = size_procs/(axis_size); - int axis_pos=position/increment; - position=position%increment; - int iaxis=1; - while (_local_array_indices[idim][iaxis]<=axis_pos) - { - subdomain_id+=proc_increment; - iaxis++; - } - axis_position[idim]=axis_pos-_local_array_indices[idim][iaxis-1]; - axis_offset[idim]=iaxis; - } - int local=0; - int local_increment=1; - for (int idim=_dimension-1; idim>=0; idim--) - { - local+=axis_position[idim]*local_increment; - local_increment*=_local_array_indices[idim][axis_offset[idim]]-_local_array_indices[idim][axis_offset[idim]-1]; - } - return make_pair(subdomain_id,local); - } - - //!converts local number to a global number - int BlockTopology::localToGlobal(const pair local) const - { - - int subdomain_id=local.first; - int global=0; - int loc=local.second; - int increment=_nb_elems; - int proc_increment=_proc_group->size(); - int local_increment=getNbLocalElements(); - for (int idim=0; idim < _dimension; idim++) - { - int axis_size=_local_array_indices[idim].size()-1; - int axis_nb_elem=_local_array_indices[idim][axis_size]; - increment=axis_nb_elem==0?0:increment/axis_nb_elem; - proc_increment = proc_increment/(axis_size); - int proc_axis=subdomain_id/proc_increment; - subdomain_id=subdomain_id%proc_increment; - int local_axis_nb_elem=_local_array_indices[idim][proc_axis+1]-_local_array_indices[idim][proc_axis]; - local_increment = (local_axis_nb_elem==0)?0:(local_increment/local_axis_nb_elem); - int iaxis=((local_increment==0)?0:(loc/local_increment))+_local_array_indices[idim][proc_axis]; - global+=increment*iaxis; - loc = (local_increment==0)?0:(loc%local_increment); - } - return global; - } - - //Retrieves the local number of elements - int BlockTopology::getNbLocalElements()const - { - int position=_proc_group->myRank(); - int nb_elem = 1; - int increment=1; - for (int i=_dimension-1; i>=0; i--) - { - increment *=_nb_procs_per_dim[i]; - int idim=position%increment; - position=position/increment; - int imin=_local_array_indices[i][idim]; - int imax=_local_array_indices[i][idim+1]; - nb_elem*=(imax-imin); - } - return nb_elem; - } + /*! + * Default ctor. + */ + BlockTopology::BlockTopology() : + _dimension(0), _nb_procs_per_dim(0), + _local_array_indices(0), _cycle_type(0), + _proc_group(NULL),_nb_elems(0), + _owns_processor_group(false) + {} /*! * Constructor of a block topology from a grid. @@ -246,6 +173,88 @@ namespace ParaMEDMEM delete _proc_group; } + //!converts a pair to a global number + std::pair BlockTopology::globalToLocal(const int global) const + { + int subdomain_id=0; + int position=global; + int size=_nb_elems; + int size_procs=_proc_group->size(); + int increment=size; + vectoraxis_position(_dimension); + vectoraxis_offset(_dimension); + for (int idim=0; idim<_dimension; idim++) + { + int axis_size=_local_array_indices[idim].size()-1; + int axis_nb_elem=_local_array_indices[idim][axis_size]; + increment=increment/axis_nb_elem; + int proc_increment = size_procs/(axis_size); + int axis_pos=position/increment; + position=position%increment; + int iaxis=1; + while (_local_array_indices[idim][iaxis]<=axis_pos) + { + subdomain_id+=proc_increment; + iaxis++; + } + axis_position[idim]=axis_pos-_local_array_indices[idim][iaxis-1]; + axis_offset[idim]=iaxis; + } + int local=0; + int local_increment=1; + for (int idim=_dimension-1; idim>=0; idim--) + { + local+=axis_position[idim]*local_increment; + local_increment*=_local_array_indices[idim][axis_offset[idim]]-_local_array_indices[idim][axis_offset[idim]-1]; + } + return make_pair(subdomain_id,local); + } + + //!converts local number to a global number + int BlockTopology::localToGlobal(const pair local) const + { + + int subdomain_id=local.first; + int global=0; + int loc=local.second; + int increment=_nb_elems; + int proc_increment=_proc_group->size(); + int local_increment=getNbLocalElements(); + for (int idim=0; idim < _dimension; idim++) + { + int axis_size=_local_array_indices[idim].size()-1; + int axis_nb_elem=_local_array_indices[idim][axis_size]; + increment=axis_nb_elem==0?0:increment/axis_nb_elem; + proc_increment = proc_increment/(axis_size); + int proc_axis=subdomain_id/proc_increment; + subdomain_id=subdomain_id%proc_increment; + int local_axis_nb_elem=_local_array_indices[idim][proc_axis+1]-_local_array_indices[idim][proc_axis]; + local_increment = (local_axis_nb_elem==0)?0:(local_increment/local_axis_nb_elem); + int iaxis=((local_increment==0)?0:(loc/local_increment))+_local_array_indices[idim][proc_axis]; + global+=increment*iaxis; + loc = (local_increment==0)?0:(loc%local_increment); + } + return global; + } + + //Retrieves the local number of elements + int BlockTopology::getNbLocalElements()const + { + int position=_proc_group->myRank(); + int nb_elem = 1; + int increment=1; + for (int i=_dimension-1; i>=0; i--) + { + increment *=_nb_procs_per_dim[i]; + int idim=position%increment; + position=position/increment; + int imin=_local_array_indices[i][idim]; + int imax=_local_array_indices[i][idim+1]; + nb_elem*=(imax-imin); + } + return nb_elem; + } + /*! Retrieves the min and max indices of the domain stored locally * for each dimension. The output vector has the topology dimension * as a size and each pair contains min and max. Indices diff --git a/src/ParaMEDMEM/BlockTopology.hxx b/src/ParaMEDMEM/BlockTopology.hxx index eabc2ec2d..37466731d 100644 --- a/src/ParaMEDMEM/BlockTopology.hxx +++ b/src/ParaMEDMEM/BlockTopology.hxx @@ -32,10 +32,20 @@ namespace ParaMEDMEM typedef enum{Block,Cycle} CYCLE_TYPE; + /*! + * \anchor BlockTopology-det + * + * A BlockTopology typically represents the split of a *structured* mesh among the processors of + * a common ProcessorGroup. Each processor gets a contiguous part of the cells in the mesh (a block). + * + * A BlockTopology can also be used to split a structured domain among the various components of a field. + * + * \sa ExplicitTopology + */ class BlockTopology : public Topology { public: - BlockTopology() { } + BlockTopology(); BlockTopology(const ProcessorGroup& group, MEDCouplingCMesh *grid); BlockTopology(const BlockTopology& geom_topo, const ComponentTopology& comp_topo); BlockTopology(const ProcessorGroup& group, int nb_elem); diff --git a/src/ParaMEDMEM/CMakeLists.txt b/src/ParaMEDMEM/CMakeLists.txt index 6a03e285a..d682e55b5 100644 --- a/src/ParaMEDMEM/CMakeLists.txt +++ b/src/ParaMEDMEM/CMakeLists.txt @@ -58,6 +58,7 @@ SET(paramedmem_SOURCES ParaFIELD.cxx ParaGRID.cxx BlockTopology.cxx + ExplicitMapping.cxx ) ADD_LIBRARY(paramedmem SHARED ${paramedmem_SOURCES}) diff --git a/src/ParaMEDMEM/CommInterface.cxx b/src/ParaMEDMEM/CommInterface.cxx index 948f099d8..54e06e6fc 100644 --- a/src/ParaMEDMEM/CommInterface.cxx +++ b/src/ParaMEDMEM/CommInterface.cxx @@ -25,13 +25,13 @@ namespace ParaMEDMEM \class CommInterface The class \a CommInterface is the gateway to the MPI library. + It is a wrapper around all MPI calls, thus trying to abstract the rest of the code from using the direct MPI API + (but this is not strictly respected overall in practice ...). It is used in all + the \ref parallel "DEC related classes". - It is a helper class that gathers the calls to the MPI - library that are made in the %ParaMEDMEM library. This gathering - allows easier gathering of information about the communication - in the library. - - It is typically called after the MPI_Init() call in a program. It is afterwards passed as a parameter to the constructors of %ParaMEDMEM objects so that they access the MPI library via the CommInterface. + It is typically instanciated after the MPI_Init() call in a program and is afterwards passed as a + parameter to the constructors of various \ref parallel "parallel objects" so that they access the + MPI library via this common interface. As an example, the following code excerpt initializes a processor group made of the zero processor. diff --git a/src/ParaMEDMEM/ComponentTopology.hxx b/src/ParaMEDMEM/ComponentTopology.hxx index de11e3efe..9b84607a3 100644 --- a/src/ParaMEDMEM/ComponentTopology.hxx +++ b/src/ParaMEDMEM/ComponentTopology.hxx @@ -28,6 +28,14 @@ namespace ParaMEDMEM { class ProcessorGroup; + /*! + * \anchor ComponentTopology-det + * + * The ComponentTopology can be used when building a ParaFIELD. It allows the splitting of the components + * of the field among different processors within a single processor group. + * + * \sa ParaFIELD::ParaFIELD(TypeOfField , TypeOfTimeDiscretization , ParaMESH* , const ComponentTopology& ) + */ class ComponentTopology { public: diff --git a/src/ParaMEDMEM/DEC.hxx b/src/ParaMEDMEM/DEC.hxx index 1b0a8675f..6df677bbc 100644 --- a/src/ParaMEDMEM/DEC.hxx +++ b/src/ParaMEDMEM/DEC.hxx @@ -27,6 +27,15 @@ namespace ParaMEDMEM { class CommInterface; + + /*! + * DEC stands for Data Exchange Channel. See the page \ref para-dec for more on this. + * + * This class is purely abstract. See the derivations: + * - \ref DisjointDEC-det "DisjointDEC" + * - \ref NonCoincidentDEC "NonCoincidentDEC" + * - \ref OverlapDEC "OverlapDEC" + */ class DEC : public DECOptions { public: diff --git a/src/ParaMEDMEM/DECOptions.hxx b/src/ParaMEDMEM/DECOptions.hxx index 5572ffdca..eb9271237 100644 --- a/src/ParaMEDMEM/DECOptions.hxx +++ b/src/ParaMEDMEM/DECOptions.hxx @@ -24,10 +24,29 @@ namespace ParaMEDMEM { - //Enum describing the allToAll method used in the communication pattern + //! Enum describing the allToAll method used in the communication pattern typedef enum { Native, PointToPoint } AllToAllMethod; + //! Enum describing the time interpolation method typedef enum { WithoutTimeInterp, LinearTimeInterp } TimeInterpolationMethod; + /*! + This class groups the various options accepted by all \ref para-dec "DECs" (which all inherit from %DECOptions). + + The following code excerpt shows how to set options on a %DEC : + + \code + InterpKernelDEC dec(source_group,target_group); + dec.setForcedRenormalization(true); + dec.attachLocalField(field); + dec.synchronize(); + if (source_group.containsMyRank()) + dec.sendData(); + else + dec.recvData(); + \endcode + * + * + */ class DECOptions { protected: @@ -54,19 +73,55 @@ namespace ParaMEDMEM _allToAllMethod=deco._allToAllMethod; } + + /*! + * \sa setMethod() + */ const std::string& getMethod() const { return _method; } + /*! + * Set interpolation method. Defaults to "P0". + */ void setMethod(const char *m) { _method=m; } + /*! + * \sa setTimeInterpolationMethod() + */ TimeInterpolationMethod getTimeInterpolationMethod() const { return DECOptions::_timeInterpolationMethod; } + /*! + * Set time interpolation method. Default to WithoutTimeInterp. + */ void setTimeInterpolationMethod(TimeInterpolationMethod it) { DECOptions::_timeInterpolationMethod=it; } + /*! + * \sa setForcedRenormalization() + */ bool getForcedRenormalization() const { return DECOptions::_forcedRenormalization; } + + /*! + * Force renormalization of the field after it has been received so that the total sum + * of the field values are the same on both the sending and the receiving side. Defaults to + * false. + */ void setForcedRenormalization( bool dr) { DECOptions::_forcedRenormalization = dr; } + + /*! + * \sa setAsynchronous() + */ bool getAsynchronous() const { return DECOptions::_asynchronous; } + + /*! + * Switch to asynchronous data transfer mode. Default is false. + */ void setAsynchronous( bool dr) { DECOptions::_asynchronous = dr; } + /*! + * \sa setAllToAllMethod() + */ AllToAllMethod getAllToAllMethod() const { return _allToAllMethod; } + /*! + * Set the broadcast method for synchronisation processes. Default to Native. + */ void setAllToAllMethod(AllToAllMethod sp) { _allToAllMethod=sp; } }; } diff --git a/src/ParaMEDMEM/DisjointDEC.cxx b/src/ParaMEDMEM/DisjointDEC.cxx index 57e67fd2c..b2ba8f795 100644 --- a/src/ParaMEDMEM/DisjointDEC.cxx +++ b/src/ParaMEDMEM/DisjointDEC.cxx @@ -39,39 +39,31 @@ namespace ParaMEDMEM * \anchor DisjointDEC-det * \class DisjointDEC * - * Interface class for creation of a link between two - * processor groups for exhanging mesh or field data. - * The \c DEC is defined by attaching a field on the receiving or on the + * \section DisjointDEC-over Overview + * + * Abstract interface class representing a link between two + * processor groups for exchanging mesh or field data. The two processor groups must + * have a void intersection (\ref ParaMEDMEM::OverlapDEC "OverlapDEC" is to be considered otherwise). + * The %DEC is initialized by attaching a field on the receiving or on the * sending side. - * On top of attaching a \c ParaMEDMEM::ParaFIELD, it is possible to - * attach a ICoCo::Field. This class is an abstract class that enables - * coupling of codes that respect the ICoCo interface \ref icoco. It has two implementations: - * one for codes that express their fields as \ref fields "MEDCoupling fields" (ICoCo::MEDField). * - * \section dec_options DEC Options - * Options supported by \c DEC objects are + * The data is sent or received through calls to the (abstract) methods recvData() and sendData(). + * + * One can attach either a \c ParaMEDMEM::ParaFIELD, or a + * \c ICoCo::Field, or directly a \c ParaMEDMEM::MEDCouplingFieldDouble instance. + * See the various signatures of the method DisjointDEC::attachLocalField() + * + * The derivations of this class should be considered for practical instanciation: + * - \ref InterpKernelDEC-det "InterpKernelDEC" + * - \ref ExplicitCoincidentDEC-det "ExplicitCoincidentDEC" + * - \ref StructuredCoincidentDEC-det "StructuredCoincidentDEC" + * + * \section DisjointDEC-options DisjointDEC options + * The options supported by %DisjointDEC objects are the same that the ones supported for all + * DECs in general and are all inherited from the class \ref ParaMEDMEM::DECOptions "DECOptions" * - * - * - * - *
OptionDescriptionDefault value
ForcedRenormalizationAfter receiving data, the target field is renormalized so that L2-norms of the source and target fields match. false
- - - The following code excerpt shows how to set options for an object that inherits from \c DEC : - - \code - InterpKernelDEC dec(source_group,target_group); - dec.setOptions("ForcedRenormalization",true); - dec.attachLocalField(field); - dec.synchronize(); - if (source_group.containsMyRank()) - dec.sendData(); - else - dec.recvData(); - \endcode */ - DisjointDEC::DisjointDEC(ProcessorGroup& source_group, ProcessorGroup& target_group): _local_field(0), _source_group(&source_group), @@ -138,7 +130,7 @@ namespace ParaMEDMEM union_ids.insert(source_ids.begin(),source_ids.end()); union_ids.insert(target_ids.begin(),target_ids.end()); if(union_ids.size()!=(source_ids.size()+target_ids.size())) - throw INTERP_KERNEL::Exception("DisjointDEC constructor : source_ids and target_ids overlap partially or fully. This type of DEC does not support it ! OverlapDEC class could be the solution !"); + throw INTERP_KERNEL::Exception("DisjointDEC constructor : source_ids and target_ids overlap partially or fully. This type of DEC does not support it! OverlapDEC class could be the solution!"); int* union_ranks_world=new int[union_ids.size()]; // ranks of sources and targets in world_comm std::copy(union_ids.begin(), union_ids.end(), union_ranks_world); diff --git a/src/ParaMEDMEM/DisjointDEC.hxx b/src/ParaMEDMEM/DisjointDEC.hxx index aec6bb901..a4073a292 100644 --- a/src/ParaMEDMEM/DisjointDEC.hxx +++ b/src/ParaMEDMEM/DisjointDEC.hxx @@ -41,8 +41,9 @@ namespace ParaMEDMEM { public: DisjointDEC():_local_field(0),_union_group(0),_source_group(0),_target_group(0), - _owns_field(false),_owns_groups(false), - _comm_interface(0), _union_comm(MPI_COMM_NULL) + _comm_interface(0), + _owns_field(false),_owns_groups(false), + _union_comm(MPI_COMM_NULL) { } DisjointDEC(ProcessorGroup& source_group, ProcessorGroup& target_group); DisjointDEC(const DisjointDEC&); diff --git a/src/ParaMEDMEM/ElementLocator.cxx b/src/ParaMEDMEM/ElementLocator.cxx index a7fcfc28e..74e27545a 100644 --- a/src/ParaMEDMEM/ElementLocator.cxx +++ b/src/ParaMEDMEM/ElementLocator.cxx @@ -71,14 +71,14 @@ namespace ParaMEDMEM return _local_para_field.getField()->getNature(); } - // ========================================================================== - // Procedure for exchanging mesh between a distant proc and a local processor - // param idistantrank proc id on distant group - // param distant_mesh on return , points to a local reconstruction of - // the distant mesh - // param distant_ids on return, contains a vector defining a correspondence - // between the distant ids and the ids of the local reconstruction - // ========================================================================== + + /*! Procedure for exchanging a mesh between a distant proc and a local processor + \param idistantrank proc id on distant group + \param distant_mesh on return , points to a local reconstruction of + the distant mesh + \param distant_ids on return, contains a vector defining a correspondence + between the distant ids and the ids of the local reconstruction + */ void ElementLocator::exchangeMesh(int idistantrank, MEDCouplingPointSet*& distant_mesh, int*& distant_ids) @@ -127,10 +127,10 @@ namespace ParaMEDMEM } - // ====================== - // Compute bounding boxes - // ====================== + /*! + Compute bounding boxes + */ void ElementLocator::_computeBoundingBoxes() { CommInterface comm_interface =_union_group->getCommInterface(); @@ -194,9 +194,10 @@ namespace ParaMEDMEM } - // ============================================= - // Intersect Bounding Box (with a given "irank") - // ============================================= + + /*! + * Intersect local bounding box with a given distant bounding box on "irank" + */ bool ElementLocator::_intersectsBoundingBox(int irank) { #ifdef USE_DIRECTED_BB @@ -219,9 +220,10 @@ namespace ParaMEDMEM #endif } - // ====================== - // Exchanging meshes data - // ====================== + + /*! + * Exchange mesh data + */ void ElementLocator::_exchangeMesh( MEDCouplingPointSet* local_mesh, MEDCouplingPointSet*& distant_mesh, int iproc_distant, diff --git a/src/ParaMEDMEM/ElementLocator.hxx b/src/ParaMEDMEM/ElementLocator.hxx index 4853c9766..4edd27de6 100644 --- a/src/ParaMEDMEM/ElementLocator.hxx +++ b/src/ParaMEDMEM/ElementLocator.hxx @@ -31,11 +31,13 @@ namespace ParaMEDMEM { class ParaFIELD; class ProcessorGroup; - class ParaSUPPORT; class InterpolationMatrix; class MEDCouplingPointSet; class DataArrayInt; + /*! Internal class, not part of the public API. Used in InterpolationMatrix. + * + */ class ElementLocator : public INTERP_KERNEL::InterpolationOptions { public: diff --git a/src/ParaMEDMEM/ExplicitCoincidentDEC.cxx b/src/ParaMEDMEM/ExplicitCoincidentDEC.cxx index 5d30c60d4..7cab3095d 100644 --- a/src/ParaMEDMEM/ExplicitCoincidentDEC.cxx +++ b/src/ParaMEDMEM/ExplicitCoincidentDEC.cxx @@ -32,16 +32,69 @@ using namespace std; namespace ParaMEDMEM { + /*! - * \anchor ExplicitCoincidentDEC-det - * \class ExplicitCoincidentDEC - * - * TODO: doc - */ + \anchor ExplicitCoincidentDEC-det + \class ExplicitCoincidentDEC + + + This class aims at \ref interp "remapping fields" that have identical + supports (=the same underlying mesh) but different parallel topologies + (=different sub-domains in the mesh). It can be used to couple + together multi-physics codes that operate on the same domain + with different partitioning. + + It is very similar to what the \ref StructuredCoincidentDEC-det "StructuredCoincidentDEC" + does, except that it works with an arbitrary user-defined topology. + + The remapping between the two supports is based on identity of global + ids, instead of geometrical considerations (as it is the case for + \ref InterpKernelDEC-det "InterpKernelDEC"). + Therefore, beware that this \ref para-dec "DEC" can not be used + for coincident meshes if they do *not* have the exact same numbering. + + With this \ref para-dec "DEC" no projection, and no interpolation of the field data is done, contrary + to what happens in \ref InterpKernelDEC-det "InterpKernelDEC". It is just + a matter of allocating the values from one side to the other, using directly the cell + identifiers. + + As all the other DECs, its usage requires two phases : + - a setup phase during which the topologies are exchanged so that + the target side knows from which processors it should expect + the data. + - a send/recv phase during which the field data is actually transferred. + + This example illustrates the sending of a field with + the \c ExplicitCoincidentDEC : + \code + ... + ExplicitCoincidentDEC dec(groupA, groupB); + dec.attachLocalField(field); + dec.synchronize(); + if (groupA.containsMyRank()) + dec.recvData(); + else if (groupB.containsMyRank()) + dec.sendData(); + ... + \endcode + + Creating a ParaFIELD to be attached to the %DEC is done in exactly the same way as for + the other DECs, if only the partitioning of the support mesh differs. + In the case where the + fields have also different *component* topologies, creating the ParaFIELD + requires some more effort. See the \ref para-over "parallelism" section for more details. + */ + /*! Constructor */ - ExplicitCoincidentDEC::ExplicitCoincidentDEC():_toposource(0),_topotarget(0) + ExplicitCoincidentDEC::ExplicitCoincidentDEC(): + _toposource(0),_topotarget(0), + _targetgroup(0), _sourcegroup(0), + _sendcounts(0), _recvcounts(0), + _senddispls(0), _recvdispls(0), + _recvbuffer(0), _sendbuffer(0), + _distant_elems(), _explicit_mapping() { } @@ -186,8 +239,7 @@ namespace ParaMEDMEM /*! - * Synchronizing a topology so that all the - * group possesses it. + * Synchronizing a topology so that all the groups get it. * * \param toposend Topology that is transmitted. It is read on processes where it already exists, and it is created and filled on others. * \param toporecv Topology which is received. diff --git a/src/ParaMEDMEM/ExplicitMapping.cxx b/src/ParaMEDMEM/ExplicitMapping.cxx new file mode 100644 index 000000000..f4e754571 --- /dev/null +++ b/src/ParaMEDMEM/ExplicitMapping.cxx @@ -0,0 +1,159 @@ +// Copyright (C) 2007-2015 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, 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 +// + +#include "ExplicitMapping.hxx" + +namespace ParaMEDMEM +{ + + ExplicitMapping::ExplicitMapping(): + _mapping(), _distant_domains(), + _numbers(0), _domains(0), _comm_buffer(0), + _buffer_index(0), _send_counts(0) + { } + + ExplicitMapping::~ExplicitMapping() + { + if (_domains!=0) delete[] _domains; + if (_numbers!=0) delete[] _numbers; + if (_comm_buffer!=0) delete[] _comm_buffer; + } + + void ExplicitMapping::pushBackElem(std::pair idistant) + { + _mapping.push_back(idistant); + } + + void ExplicitMapping::setDistantElem(int ilocal, std::pair idistant) + { + _mapping[ilocal]=idistant; + } + + int ExplicitMapping::nbDistantDomains() + { + if (_distant_domains.empty()) + { + for (std::vector >::const_iterator iter= _mapping.begin(); + iter!=_mapping.end(); + iter++) + _distant_domains.insert(iter->first); + } + return _distant_domains.size(); + } + + std::pair ExplicitMapping::getDistantNumbering(int ielem)const + { + return _mapping[ielem]; + } + + int ExplicitMapping::getDistantDomain(int i) + { + if (_domains==0) + computeNumbers(); + + return _domains[i]; + } + + int ExplicitMapping::getNbDistantElems(int i) + { + if (_numbers==0) + computeNumbers(); + return _numbers[i]; + } + + int* ExplicitMapping::serialize(int idproc) + { + _comm_buffer=new int[_mapping.size()*2]; + std::vector offsets(_distant_domains.size()); + offsets[0]=0; + for (int i=1; i<(int)_distant_domains.size();i++) + offsets[i]=offsets[i-1]+_numbers[i-1]; + + for (int i=0; i<(int)_mapping.size(); i++) + { + int offset= offsets[_mapping[i].first]; + _comm_buffer[offset*2]=idproc; + _comm_buffer[offset*2+1]=_mapping[i].second; + offsets[_mapping[i].first]++; + } + return _comm_buffer; + } + + void ExplicitMapping::unserialize(int nbprocs, int* sizes,int nbtarget, int* targetrank, int* commbuffer) + { + int total_size=0; + for (int i=0; i< nbprocs; i++) + total_size+=sizes[i]; + + _mapping.resize(total_size); + _buffer_index=new int[total_size]; + int indmap=0; + for (int i=0; i0) + { + _numbers[index]=sizes[targetrank[i]]; + _domains[index]=i; + index++; + } + } + _send_counts=new int[nbprocs]; + for (int i=0; i counts; + if (_numbers==0) + { + _numbers=new int[nbDistantDomains()]; + _domains=new int[nbDistantDomains()]; + for (int i=0; i<(int)_mapping.size(); i++) + { + if ( counts.find(_mapping[i].first) == counts.end()) + counts.insert(std::make_pair(_mapping[i].first,1)); + else + (counts[_mapping[i].first])++; + } + int counter=0; + for (std::map::const_iterator iter=counts.begin(); + iter!=counts.end(); + iter++) + { + _numbers[counter]=iter->second; + _domains[counter]=iter->first; + counter++; + } + } + } + +} diff --git a/src/ParaMEDMEM/ExplicitMapping.hxx b/src/ParaMEDMEM/ExplicitMapping.hxx index e83d0dc97..3098b706f 100644 --- a/src/ParaMEDMEM/ExplicitMapping.hxx +++ b/src/ParaMEDMEM/ExplicitMapping.hxx @@ -26,114 +26,27 @@ namespace ParaMEDMEM { + /*! + * Internal class, not part of the public API. + * + * Used by the ExplicitCoincidentDEC. + */ class ExplicitMapping { public: - - ExplicitMapping():_numbers(0), _domains(0), _comm_buffer(0) { } - - ~ExplicitMapping() - { - if (_domains!=0) delete[] _domains; - if (_numbers!=0) delete[] _numbers; - if (_comm_buffer!=0) delete[] _comm_buffer; - } + ExplicitMapping(); + ~ExplicitMapping(); - void pushBackElem(std::pair idistant) - { - _mapping.push_back(idistant); - } - - void setDistantElem(int ilocal, std::pair idistant) - { - _mapping[ilocal]=idistant; - } - - int nbDistantDomains() - { - if (_distant_domains.empty()) - { - for (std::vector >::const_iterator iter= _mapping.begin(); - iter!=_mapping.end(); - iter++) - _distant_domains.insert(iter->first); - } - return _distant_domains.size(); - } + void pushBackElem(std::pair idistant); + void setDistantElem(int ilocal, std::pair idistant); + int nbDistantDomains(); + std::pair getDistantNumbering(int ielem) const; - std::pair getDistantNumbering(int ielem)const - { - return _mapping[ielem]; - } + int getDistantDomain(int i); + int getNbDistantElems(int i); + int* serialize(int idproc); + void unserialize(int nbprocs, int* sizes,int nbtarget, int* targetrank, int* commbuffer); - int getDistantDomain(int i) - { - if (_domains==0) - computeNumbers(); - - return _domains[i]; - } - - int getNbDistantElems(int i) - { - if (_numbers==0) - computeNumbers(); - return _numbers[i]; - } - - int* serialize(int idproc) - { - _comm_buffer=new int[_mapping.size()*2]; - std::vector offsets(_distant_domains.size()); - offsets[0]=0; - for (int i=1; i<(int)_distant_domains.size();i++) - offsets[i]=offsets[i-1]+_numbers[i-1]; - - for (int i=0; i<(int)_mapping.size(); i++) - { - int offset= offsets[_mapping[i].first]; - _comm_buffer[offset*2]=idproc; - _comm_buffer[offset*2+1]=_mapping[i].second; - offsets[_mapping[i].first]++; - } - return _comm_buffer; - } - - void unserialize(int nbprocs, int* sizes,int nbtarget, int* targetrank, int* commbuffer) - { - int total_size=0; - for (int i=0; i< nbprocs; i++) - total_size+=sizes[i]; - - _mapping.resize(total_size); - _buffer_index=new int[total_size]; - int indmap=0; - for (int i=0; i0) - { - _numbers[index]=sizes[targetrank[i]]; - _domains[index]=i; - index++; - } - } - _send_counts=new int[nbprocs]; - for (int i=0; i counts; - if (_numbers==0) - { - _numbers=new int[nbDistantDomains()]; - _domains=new int[nbDistantDomains()]; - for (int i=0; i<(int)_mapping.size(); i++) - { - if ( counts.find(_mapping[i].first) == counts.end()) - counts.insert(std::make_pair(_mapping[i].first,1)); - else - (counts[_mapping[i].first])++; - } - int counter=0; - for (std::map::const_iterator iter=counts.begin(); - iter!=counts.end(); - iter++) - { - _numbers[counter]=iter->second; - _domains[counter]=iter->first; - counter++; - } - } - } + void computeNumbers(); }; } diff --git a/src/ParaMEDMEM/ExplicitTopology.cxx b/src/ParaMEDMEM/ExplicitTopology.cxx index a624623a9..4facf53e0 100644 --- a/src/ParaMEDMEM/ExplicitTopology.cxx +++ b/src/ParaMEDMEM/ExplicitTopology.cxx @@ -33,6 +33,11 @@ using namespace std; namespace ParaMEDMEM { +ExplicitTopology::ExplicitTopology(): + _proc_group(NULL), _nb_elems(0), _nb_components(0), + _loc2glob(NULL), _glob2loc() + {} + ExplicitTopology::ExplicitTopology(const ParaMESH& paramesh ): _proc_group(paramesh.getBlockTopology()->getProcGroup()), _nb_components(1) diff --git a/src/ParaMEDMEM/ExplicitTopology.hxx b/src/ParaMEDMEM/ExplicitTopology.hxx index a1f4cceec..d7d73f9be 100644 --- a/src/ParaMEDMEM/ExplicitTopology.hxx +++ b/src/ParaMEDMEM/ExplicitTopology.hxx @@ -33,10 +33,17 @@ namespace ParaMEDMEM class Topology; class ComponentTopology; + /*! + * \anchor ExplicitTopology-det + * + * An ExplicitTopology typically represents the split of a mesh among the processors of + * a common ProcessorGroup. Each processor gets a user-defined part of the cells in the mesh. + * \sa BlockTopology + */ class ExplicitTopology : public Topology { public: - ExplicitTopology() { } + ExplicitTopology(); ExplicitTopology( const ExplicitTopology& topo, int nbcomponents); ExplicitTopology(const ParaMESH &mesh); virtual ~ExplicitTopology(); diff --git a/src/ParaMEDMEM/InterpKernelDEC.cxx b/src/ParaMEDMEM/InterpKernelDEC.cxx index a7557e509..7f1be4b36 100644 --- a/src/ParaMEDMEM/InterpKernelDEC.cxx +++ b/src/ParaMEDMEM/InterpKernelDEC.cxx @@ -37,33 +37,45 @@ namespace ParaMEDMEM \anchor InterpKernelDEC-det \class InterpKernelDEC - \section dec-over Overview + \section InterpKernelDEC-over Overview - The InterpKernelDEC enables the \ref InterpKerRemapGlobal "remapping" of fields between two parallel codes. - This remapping is based on the computation of intersection volumes between elements from code A - and elements from code B. The computation is possible for 3D meshes, 2D meshes, and 3D-surface - meshes. Dimensions must be similar for code A and code B (for instance, though it could be + The InterpKernelDEC enables the \ref InterpKerRemapGlobal "remapping" (or interpolation) of fields between + two parallel codes. + + The projection + methodology is based on the algorithms of %INTERP_KERNEL, that is to say, they work in a similar fashion than + what the \ref remapper "sequential remapper" does. The following \ref discretization "projection methods" + are supported: P0->P0 (the most common case), P1->P0, P0->P1. + + The computation is possible for 3D meshes, 2D meshes, and 3D-surface + meshes. Dimensions must be identical for code A and code B (for instance, though it could be desirable, it is not yet possible to couple 3D surfaces with 2D surfaces). - In the present version, only fields lying on elements are considered. + The name "InterpKernelDEC" comes from the fact that this class uses exactly the same algorithms + as the sequential remapper. Both this class and the sequential + \ref ParaMEDMEM::MEDCouplingRemapper "MEDCouplingRemapper" are built on top of the %INTERP_KERNEL + algorithms (notably the computation of the intersection volumes). + + Among the important properties inherited from the parent abstract class \ref DisjointDEC-det "DisjointDEC", + the two \ref MPIProcessorGroup-det "processor groups" (source and target) must have a void intersection. - \image html NonCoincident_small.png "Example showing the transfer from a field based on a - quadrangular mesh to a triangular mesh. In a P0-P0 interpolation, to obtain the value on a triangle, - the values on quadrangles are weighted by their intersection area and summed." + \image html NonCoincident_small.png "Transfer of a field supported by a quadrangular mesh to a triangular mesh". - \image latex NonCoincident_small.eps "Example showing the transfer from a field based on a quadrangular - mesh to a triangular mesh. In a P0-P0 interpolation, to obtain the value on a triangle, the values - on quadrangles are weighted by their intersection area and summed." + \image latex NonCoincident_small.eps "Transfer of a field supported by a quadrangular mesh to a triangular mesh" + + In the figure above we see the transfer of a field based on a quadrangular mesh to a new field supported by + a triangular mesh. In a P0-P0 interpolation, to obtain the value on a triangle, the values on the + quadrangles are weighted by their intersection area and summed. A typical use of InterpKernelDEC encompasses two distinct phases : - A setup phase during which the intersection volumes are computed and the communication structures are setup. This corresponds to calling the InterpKernelDEC::synchronize() method. - - A use phase during which the remappings are actually performed. This corresponds to the calls to + - A running phase during which the projections are actually performed. This corresponds to the calls to sendData() and recvData() which actually trigger the data exchange. The data exchange are synchronous in the current version of the library so that recvData() and sendData() calls must be synchronized on code A and code B processor groups. - The following code excerpt illutrates a typical use of the InterpKernelDEC class. + The following code excerpt illustrates a typical use of the InterpKernelDEC class. \code ... @@ -99,28 +111,29 @@ namespace ParaMEDMEM \end{tabular} \f] - - - \section interpkerneldec_options Options - On top of \ref dec_options, options supported by %InterpKernelDEC objects are - related to the underlying Intersector class. + \section InterpKernelDEC-options Options + On top of the usual \ref ParaMEDMEM::DECOptions "DEC options", the options supported by %InterpKernelDEC objects are + related to the underlying \ref InterpKerIntersectors "intersector class". All the options available in the intersector objects are - available for the %InterpKernelDEC object. The various options available for * intersectors can + available for the %InterpKernelDEC object. The various options available for intersectors can be reviewed in \ref InterpKerIntersectors. For instance : \verbatim InterpKernelDEC dec(source_group, target_group); dec.attachLocalField(field); - dec.setOptions("DoRotate",false); - dec.setOptions("Precision",1e-12); + dec.setDoRotate(false); + dec.setPrecision(1e-12); dec.synchronize(); \endverbatim \warning{ Options must be set before calling the synchronize method. } */ - InterpKernelDEC::InterpKernelDEC():_interpolation_matrix(0) + InterpKernelDEC::InterpKernelDEC(): + DisjointDEC(), + _nb_distant_points(0), _distant_coords(0), + _distant_locations(0), _interpolation_matrix(0) { } @@ -134,14 +147,18 @@ namespace ParaMEDMEM */ InterpKernelDEC::InterpKernelDEC(ProcessorGroup& source_group, ProcessorGroup& target_group): - DisjointDEC(source_group, target_group),_interpolation_matrix(0) + DisjointDEC(source_group, target_group), + _nb_distant_points(0), _distant_coords(0), + _distant_locations(0), _interpolation_matrix(0) { } InterpKernelDEC::InterpKernelDEC(const std::set& src_ids, const std::set& trg_ids, - const MPI_Comm& world_comm):DisjointDEC(src_ids,trg_ids,world_comm), - _interpolation_matrix(0) + const MPI_Comm& world_comm): + DisjointDEC(src_ids,trg_ids,world_comm), + _nb_distant_points(0), _distant_coords(0), + _distant_locations(0), _interpolation_matrix(0) { } @@ -154,9 +171,10 @@ namespace ParaMEDMEM /*! \brief Synchronization process for exchanging topologies. - This method prepares all the structures necessary for sending data from a processor group to the other. It uses the mesh underlying the fields that have been set with attachLocalField method. + This method prepares all the structures necessary for sending data from a processor group to the other. It uses the mesh + underlying the fields that have been set with attachLocalField method. It works in four steps : - -# Bounding boxes are computed for each subdomain, + -# Bounding boxes are computed for each sub-domain, -# The lazy side mesh parts that are likely to intersect the working side local processor are sent to the working side, -# The working side calls the interpolation kernel to compute the intersection between local and imported mesh. -# The lazy side is updated so that it knows the structure of the data that will be sent by diff --git a/src/ParaMEDMEM/InterpolationMatrix.hxx b/src/ParaMEDMEM/InterpolationMatrix.hxx index 97fc2a300..b60c9ee54 100644 --- a/src/ParaMEDMEM/InterpolationMatrix.hxx +++ b/src/ParaMEDMEM/InterpolationMatrix.hxx @@ -29,9 +29,11 @@ namespace ParaMEDMEM { class ElementLocator; - /**! class InterpolationMatrix + /*! + Internal class, not part of the public API. + This class enables the storage of an interpolation matrix Wij mapping - source field Sj to target field Ti via Ti=Vi^(-1).Wij.Sj. + a source field Sj to a target field Ti via Ti=Vi^(-1).Wij.Sj. The matrix is built and stored on the processors belonging to the source group. */ diff --git a/src/ParaMEDMEM/LinearTimeInterpolator.hxx b/src/ParaMEDMEM/LinearTimeInterpolator.hxx index 0128e42b2..76eca3fc7 100644 --- a/src/ParaMEDMEM/LinearTimeInterpolator.hxx +++ b/src/ParaMEDMEM/LinearTimeInterpolator.hxx @@ -29,6 +29,11 @@ namespace ParaMEDMEM { class DEC; + /*! + * Internal class, not part of the public API. + * + * Linear interpolation of a block of data between two given times. + */ class LinearTimeInterpolator : public TimeInterpolator { public: diff --git a/src/ParaMEDMEM/MPIAccessDEC.cxx b/src/ParaMEDMEM/MPIAccessDEC.cxx index f8a0e1002..18184dc27 100644 --- a/src/ParaMEDMEM/MPIAccessDEC.cxx +++ b/src/ParaMEDMEM/MPIAccessDEC.cxx @@ -568,7 +568,7 @@ namespace ParaMEDMEM int recvsize = recvcount*_MPI_access->extent( recvtype ) ; checkTime( recvcount , recvtype , target , false ) ; //=========================================================================== - //TODO : it is assumed actually that we have only 1 timestep before nad after + //TODO : it is assumed actually that we have only 1 timestep before and after //=========================================================================== if ( _time_interpolator && (*_time_messages)[target][0].time != -1 ) { diff --git a/src/ParaMEDMEM/MPIAccessDEC.hxx b/src/ParaMEDMEM/MPIAccessDEC.hxx index e381ff61a..aba86958f 100644 --- a/src/ParaMEDMEM/MPIAccessDEC.hxx +++ b/src/ParaMEDMEM/MPIAccessDEC.hxx @@ -29,6 +29,11 @@ namespace ParaMEDMEM { + /* + * Internal class, not part of the public API. + * + * Another gateway to the MPI library? + */ class MPIAccessDEC { public: diff --git a/src/ParaMEDMEM/MPIProcessorGroup.cxx b/src/ParaMEDMEM/MPIProcessorGroup.cxx index 922f20920..3bf01b69d 100644 --- a/src/ParaMEDMEM/MPIProcessorGroup.cxx +++ b/src/ParaMEDMEM/MPIProcessorGroup.cxx @@ -33,16 +33,17 @@ using namespace std; namespace ParaMEDMEM { /*! - * \anchor MPIProcessorGroup-det - * \class MPIProcessorGroup - * - * \section processor_group_overview Overview - * The MPIProcessorGroup class is used to set up processor groups that help to define - * the MPI topology of the couplings. They can be set up in various ways, the most common being - * the use of the \c MPIProcessorGroup(Comminterface, int pfirst, int plast) - * constructor. - * - * The following code excerpt creates two processor groups on respectively 3 and 2 processors. + \anchor MPIProcessorGroup-det + \class MPIProcessorGroup + + The MPIProcessorGroup class represents a set of distinct "processors" (computation nodes) + in a MPI code. It is used to define the MPI topology of code couplings. + + Groups can be set up in various ways, the most common being + the use of the \c MPIProcessorGroup(Comminterface, int pfirst, int plast) + constructor. + + The following code excerpt creates two processor groups on respectively 3 and 2 processors. \verbatim int main() { @@ -59,7 +60,7 @@ namespace ParaMEDMEM /*! * Creates a processor group that is based on all the - MPI_COMM_WORLD processor.This routine must be called by all processors in MPI_COMM_WORLD. + processors of MPI_COMM_WORLD .This routine must be called by all processors in MPI_COMM_WORLD. \param interface CommInterface object giving access to the MPI communication layer */ @@ -164,14 +165,16 @@ namespace ParaMEDMEM } MPIProcessorGroup::MPIProcessorGroup (const ProcessorGroup& proc_group, set proc_ids) : - ProcessorGroup(proc_group.getCommInterface()),_world_comm(MPI_COMM_WORLD) + ProcessorGroup(proc_group.getCommInterface()), + _world_comm(MPI_COMM_WORLD), _group(MPI_GROUP_NULL), _comm(MPI_COMM_NULL) { cout << "MPIProcessorGroup (const ProcessorGroup& proc_group, set proc_ids)" <setTimeInterpolator(getTimeInterpolationMethod()); diff --git a/src/ParaMEDMEM/MxN_Mapping.hxx b/src/ParaMEDMEM/MxN_Mapping.hxx index 5aa3ce7ff..cd613a8eb 100644 --- a/src/ParaMEDMEM/MxN_Mapping.hxx +++ b/src/ParaMEDMEM/MxN_Mapping.hxx @@ -31,10 +31,15 @@ namespace ParaMEDMEM class ProcessorGroup; + /*! + * Internal class, not part of the public API. + * + * Used by InterpolationMatrix. This class manages the mapping between a given processor and part + * of the mesh (cell ids). + */ class MxN_Mapping : public DECOptions { public: - MxN_Mapping(); MxN_Mapping(const ProcessorGroup& source_group, const ProcessorGroup& target_group, const DECOptions& dec_options); virtual ~MxN_Mapping(); void addElementFromSource(int distant_proc, int distant_elem); diff --git a/src/ParaMEDMEM/NonCoincidentDEC.cxx b/src/ParaMEDMEM/NonCoincidentDEC.cxx index 4f44a7f54..95b9d6acd 100644 --- a/src/ParaMEDMEM/NonCoincidentDEC.cxx +++ b/src/ParaMEDMEM/NonCoincidentDEC.cxx @@ -41,17 +41,20 @@ namespace ParaMEDMEM \anchor NonCoincidentDEC-det \class NonCoincidentDEC - \c NonCoincidentDEC enables nonconservative remapping of fields + \c NonCoincidentDEC enables non-conservative remapping of fields between two parallel codes. The computation is possible for 3D meshes and 2D meshes. - It is not available for 3D surfaces. The computation enables fast parallel localization, and is based on a point in element search, followed + It is not available for 3D surfaces. + + The computation enables fast parallel localization, and is based on a point in element search, followed by a field evaluation at the point location. Thus, it is typically - faster than the \ref InterpKernelDEC-det "InterpKernelDEC" which gives a - \ref InterpKerRemapGlobal "conservative remapping". - It is particularly true for the initialisation phase (synchronize) - which is very computationnaly intensive in \ref InterpKernelDEC-det. + faster than the \ref InterpKernelDEC-det "InterpKernelDEC" which uses a + \ref InterpKerRemapGlobal "conservative remapping" (i.e. the same algorithms of volume + intersection as in the \ref remapper "sequential remapper") + It is particularly true for the initialisation phase (synchronize() method) + which has a significant computation cost in \ref InterpKernelDEC-det. - In the present version, only fields lying on elements are considered. + In the present version, only fields lying on elements ("P0") are considered. The value is estimated by locating the barycenter of the target side cell in a source cell and sending the value of this source cell as the value of the target cell. diff --git a/src/ParaMEDMEM/OverlapDEC.cxx b/src/ParaMEDMEM/OverlapDEC.cxx index 0c02028d7..09253d350 100644 --- a/src/ParaMEDMEM/OverlapDEC.cxx +++ b/src/ParaMEDMEM/OverlapDEC.cxx @@ -31,22 +31,27 @@ namespace ParaMEDMEM \anchor OverlapDEC-det \class OverlapDEC + \section OverlapDEC-over Overview + The \c OverlapDEC enables the \ref InterpKerRemapGlobal "conservative remapping" of fields between two parallel codes. This remapping is based on the computation of intersection volumes on - a \b same \b processor \b group. On this processor group are defined two field-templates called A + a \b single \b processor \b group. On this processor group are defined two field-templates called A and B. The computation is possible for 3D meshes, 2D meshes, 3D-surface meshes, 1D meshes and 2D-curve meshes. Dimensions must be similar for the distribution templates A and B. - The main difference with \ref InterpKernelDEC-det is that this \ref para-dec "DEC" manages 2 field templates - on each processor of the processor group (A and B) called source and target. - Furthermore all processors in processor group cooperates in global interpolation matrix - computation. In this respect \ref InterpKernelDEC is a specialization of \c OverlapDEC. - \section ParaMEDMEMOverlapDECAlgorithmDescription Algorithm Description + The main difference with \ref InterpKernelDEC-det "InterpKernelDEC" is that this + \ref para-dec "DEC" works with a *single* processor group, in which processors will share the work. + Consequently each processor manages two \ref MEDCouplingFieldTemplatesPage "field templates" (A and B) + called source and target. + Furthermore all processors in the processor group cooperate in the global interpolation matrix + computation. In this respect \c InterpKernelDEC is a specialization of \c OverlapDEC. + + \section ParaMEDMEMOverlapDECAlgorithmDescription Algorithm description Let's consider the following use case that is ran in ParaMEDMEMTest_OverlapDEC.cxx to describes the different steps of the computation. The processor group contains 3 processors. \anchor ParaMEDMEMOverlapDECImgTest1 - \image html OverlapDEC1.png "Example showing the use case in order to explain the different steps." + \image html OverlapDEC1.png "Example split of the source and target mesh among the 3 procs" \subsection ParaMEDMEMOverlapDECAlgoStep1 Step 1 : Bounding box exchange and global interaction between procs computation. @@ -161,7 +166,7 @@ namespace ParaMEDMEM the \b local TODO list per proc is expected to be as well balanced as possible. - The interpolation is performed as \ref ParaMEDMEM::MEDCouplingRemapper "Remapper" does. + The interpolation is performed as the \ref ParaMEDMEM::MEDCouplingRemapper "remapper" does. This operation is performed by OverlapInterpolationMatrix::addContribution method. diff --git a/src/ParaMEDMEM/OverlapDEC.hxx b/src/ParaMEDMEM/OverlapDEC.hxx index 48b853ca0..b7b9b8c2f 100644 --- a/src/ParaMEDMEM/OverlapDEC.hxx +++ b/src/ParaMEDMEM/OverlapDEC.hxx @@ -49,7 +49,7 @@ namespace ParaMEDMEM bool _own_group; OverlapInterpolationMatrix* _interpolation_matrix; ProcessorGroup *_group; - private: + ParaFIELD *_source_field; bool _own_source_field; ParaFIELD *_target_field; diff --git a/src/ParaMEDMEM/OverlapElementLocator.hxx b/src/ParaMEDMEM/OverlapElementLocator.hxx index 13a94c821..6ce2677f2 100644 --- a/src/ParaMEDMEM/OverlapElementLocator.hxx +++ b/src/ParaMEDMEM/OverlapElementLocator.hxx @@ -36,7 +36,6 @@ namespace ParaMEDMEM { class ParaFIELD; class ProcessorGroup; - class ParaSUPPORT; class OverlapInterpolationMatrix; class OverlapElementLocator : public INTERP_KERNEL::InterpolationOptions diff --git a/src/ParaMEDMEM/OverlapInterpolationMatrix.hxx b/src/ParaMEDMEM/OverlapInterpolationMatrix.hxx index 514deb8de..2190e9add 100644 --- a/src/ParaMEDMEM/OverlapInterpolationMatrix.hxx +++ b/src/ParaMEDMEM/OverlapInterpolationMatrix.hxx @@ -31,6 +31,11 @@ namespace ParaMEDMEM class ParaFIELD; class MEDCouplingPointSet; + /*! + * Internal class, not part of the public API. + * + * Similar to InterpolationMatrix, but for the OverlapDEC instead of the InterpKernelDEC. + */ class OverlapInterpolationMatrix : public INTERP_KERNEL::InterpolationOptions, public DECOptions { diff --git a/src/ParaMEDMEM/OverlapMapping.hxx b/src/ParaMEDMEM/OverlapMapping.hxx index 952524715..cfb06b1bb 100644 --- a/src/ParaMEDMEM/OverlapMapping.hxx +++ b/src/ParaMEDMEM/OverlapMapping.hxx @@ -32,6 +32,13 @@ namespace ParaMEDMEM class DataArrayInt; class MEDCouplingFieldDouble; + /* + * Internal class, not part of the public API. + * + * Used by the impl of OverlapInterpolationMatrix, plays an equivalent role than what the NxM_Mapping + * does for the InterpolationMatrix. + * + */ class OverlapMapping { public: diff --git a/src/ParaMEDMEM/ParaFIELD.cxx b/src/ParaMEDMEM/ParaFIELD.cxx index 9995ccae1..e8e31e4ee 100644 --- a/src/ParaMEDMEM/ParaFIELD.cxx +++ b/src/ParaMEDMEM/ParaFIELD.cxx @@ -40,23 +40,22 @@ namespace ParaMEDMEM This class encapsulates parallel fields. - It basically encapsulates - a MEDCouplingField with extra information related to parallel + It gathers a \ref fields "MEDCouplingField" with some extra information related to the parallel topology. - It is most conveniently created by giving a pointer to a MEDCouplingField - object and a \c ProcessorGroup. + It is most conveniently created by giving a pointer to a MEDCouplingFieldDouble + object and a ProcessorGroup. By default, a ParaFIELD object will be constructed with all field components - located on the same processors. In some specific cases, it might be necessary to scatter components over several processors. In this case, the constructor - using a ComponentTopology is required. + located on the same processors. In some specific cases, it might be necessary to scatter components over + several processors. In this case, the constructor using a ComponentTopology is required. */ /*! - \brief Constructing a \c ParaFIELD from a \c ParaSUPPORT and a \c ComponentTopology. + \brief Constructing a \c ParaFIELD from a \c ParaMESH and a \c ComponentTopology. - This constructor creates an empty field based on the ParaSUPPORT description + This constructor creates an empty field based on the ParaMESH description and the partitioning of components described in \a component_topology. It takes ownership over the \c _field object that it creates. @@ -108,7 +107,7 @@ namespace ParaMEDMEM /*! \brief Constructor creating the ParaFIELD from a given FIELD and a processor group. - This constructor supposes that support underlying \a subdomain_field has no ParaSUPPORT + This constructor supposes that support underlying \a subdomain_field has no ParaMESH attached and it therefore recreates one. It therefore takes ownership over _support. The component topology associated with the field is a basic one (all components on the same processor). */ ParaFIELD::ParaFIELD(MEDCouplingFieldDouble* subdomain_field, ParaMESH *sup, const ProcessorGroup& proc_group): diff --git a/src/ParaMEDMEM/ParaFIELD.hxx b/src/ParaMEDMEM/ParaFIELD.hxx index 2f5f89367..fe0a6f9d7 100644 --- a/src/ParaMEDMEM/ParaFIELD.hxx +++ b/src/ParaMEDMEM/ParaFIELD.hxx @@ -35,13 +35,10 @@ namespace ParaMEDMEM class ParaFIELD { public: - ParaFIELD(TypeOfField type, TypeOfTimeDiscretization td, ParaMESH* mesh, const ComponentTopology& component_topology); - - ParaFIELD(MEDCouplingFieldDouble* field, ParaMESH *sup, const ProcessorGroup& group); - virtual ~ParaFIELD(); + void synchronizeTarget( ParaMEDMEM::ParaFIELD* source_field); void synchronizeSource( ParaMEDMEM::ParaFIELD* target_field); MEDCouplingFieldDouble* getField() const { return _field; } @@ -53,6 +50,7 @@ namespace ParaMEDMEM int nbComponents() const; double getVolumeIntegral(int icomp, bool isWAbs) const; double getL2Norm()const { return -1; } + private: MEDCouplingFieldDouble* _field; ParaMEDMEM::ComponentTopology _component_topology; diff --git a/src/ParaMEDMEM/ParaGRID.cxx b/src/ParaMEDMEM/ParaGRID.cxx index f45c1e7ac..8b26bd5f9 100644 --- a/src/ParaMEDMEM/ParaGRID.cxx +++ b/src/ParaMEDMEM/ParaGRID.cxx @@ -31,9 +31,9 @@ using namespace std; namespace ParaMEDMEM { - ParaGRID::ParaGRID(MEDCouplingCMesh* global_grid, Topology* topology) throw(INTERP_KERNEL::Exception) + ParaGRID::ParaGRID(MEDCouplingCMesh* global_grid, Topology* topology) throw(INTERP_KERNEL::Exception) : + _global_axis(), _my_domain_id(0) { - _block_topology = dynamic_cast(topology); if(_block_topology==0) throw INTERP_KERNEL::Exception(LOCALIZED("ParaGRID::ParaGRID topology must be block topology")); diff --git a/src/ParaMEDMEM/ParaGRID.hxx b/src/ParaMEDMEM/ParaGRID.hxx index 2335b9d6c..72a0109ec 100644 --- a/src/ParaMEDMEM/ParaGRID.hxx +++ b/src/ParaMEDMEM/ParaGRID.hxx @@ -30,6 +30,10 @@ namespace ParaMEDMEM class BlockTopology; class MEDCouplingCMesh; + /*! + * This class + * Equivalent of a ParaMESH for a structured mesh + */ class ParaGRID { public: diff --git a/src/ParaMEDMEM/ParaMESH.cxx b/src/ParaMEDMEM/ParaMESH.cxx index a6482a554..70b1ffff7 100644 --- a/src/ParaMEDMEM/ParaMESH.cxx +++ b/src/ParaMEDMEM/ParaMESH.cxx @@ -1,5 +1,5 @@ -// Copyright (C) 2007-2015 CEA/DEN, EDF R&D // +// Copyright (C) 2007-2015 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 diff --git a/src/ParaMEDMEM/ParaMESH.hxx b/src/ParaMEDMEM/ParaMESH.hxx index 391bff5dd..06c6d754a 100644 --- a/src/ParaMEDMEM/ParaMESH.hxx +++ b/src/ParaMEDMEM/ParaMESH.hxx @@ -33,17 +33,28 @@ namespace ParaMEDMEM class BlockTopology; class DataArrayInt; + /*! + * \anchor ParaMESH-det + * + * Parallel representation of an unstructured mesh. + * + * This class is very specific to the requirement of parallel code computations. + * Two main constructors are available: + * - the most simple one, taking directly a \ref meshes "MEDCoupling mesh" object + * - the second one (for an advanced usage), which can be used to specify an explicit topology + * in a parallel computation. + */ class ParaMESH { public: + ParaMESH( MEDCouplingPointSet *mesh, + const ProcessorGroup& proc_group, const std::string& name); ParaMESH( MEDCouplingPointSet *subdomain_mesh, MEDCouplingPointSet *subdomain_face, DataArrayInt *CorrespElt_local2global, DataArrayInt *CorrespFace_local2global, DataArrayInt *CorrespNod_local2global, const ProcessorGroup& proc_group ) ; - ParaMESH( MEDCouplingPointSet *mesh, - const ProcessorGroup& proc_group, const std::string& name); virtual ~ParaMESH(); void setNodeGlobal(DataArrayInt *nodeGlobal); diff --git a/src/ParaMEDMEM/ProcessorGroup.hxx b/src/ParaMEDMEM/ProcessorGroup.hxx index 344704a9f..972219b9e 100644 --- a/src/ParaMEDMEM/ProcessorGroup.hxx +++ b/src/ParaMEDMEM/ProcessorGroup.hxx @@ -26,6 +26,11 @@ namespace ParaMEDMEM { + /*! + * Abstract class defining a group of processors (computation nodes) in a parallel run of a code. + * + * See the non-abstract child \ref MPIProcessorGroup-det "MPIProcessorGroup" + */ class ProcessorGroup { public: diff --git a/src/ParaMEDMEM/README b/src/ParaMEDMEM/README new file mode 100644 index 000000000..8a72f3971 --- /dev/null +++ b/src/ParaMEDMEM/README @@ -0,0 +1,194 @@ +Tests avec CPPUNIT +================== + +L'appel a MPI_Init n'est fait qu'une seule fois pour chaque suite de test +(voir TestMPIAccessDEC.cxx, TestMPIAccess.cxx, TestParaMEDMEM.cxx qui inclut +tous MPIMainTest.hxx) +Il est suivi par l'execution de toute la suite des tests regroupes +dans les trois headers MPIAccess.hxx, MPIAccessDEC.hxx, ParaMEDMEMTest.hxx +On a enfin un seul appel a MPI_Finalize. + +Si un des tests d'une suite de tests comporte une anomalie cela +peut avoir des implications sur l'execution des tests suivants. + +[ABN-2015] Lancement des tests avec valgrind +============================================ + +Exemple avec MPICH : + +rm tmp_log* ; mpirun -np 3 valgrind --leak-check=full --show-reachable=yes --log-file=tmp_log%p src/ParaMEDMEMTest/TestParaMEDMEM && cat tmp_log* + +[ABN-2015] Lancement des tests avec gdb +======================================= + +Exemple avec MPICH : + +mpirun -np 2 xterm -e gdb src/ParaMEDMEMTest/TestMPIAccess + + + + + +************************************************************************************************************* +*********************** ce qui suit est obsolète ?? ************************************** +************************************************************************************************************* + +Lancement des tests de TestParaMEDMEM avec CPPUNIT et TotalView (option -tv) : +============================================================================== + +mpirun -np 5 -ssi rpi tcp C -tv -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} TestParaMEDMEM + +Il arrive qu'on ne puisse pas utiliser totalview par manque de +license. + + + +Lancement des tests de TestParaMEDMEM avec CPPUNIT et Valgrind avec "memory leaks" : +==================================================================================== + +mpirun -np 5 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full TestParaMEDMEM + + +Lancement des tests fonctionnels de MPI_AccessDEC avec CPPUNIT : +================================================================ + +mpirun -np 11 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full TestMPIAccessDEC + + +Lancement des tests unitaires de MPI_Access avec CPPUNIT : +========================================================== + +mpirun -np 3 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full TestMPIAccess + + +TestMPIAccess/TestMPIAccessDEC/TestParaMEDMEM et gcov : +======================================================= + +Les resultats sont dans les repertoires suivants de $MED_BUILD_DIR/src/ParaMEDMEM/Test : +------------- + + TestParaMEDMEM-gcov/ + TestMPIAccessDEC-gcov/ + TestMPIAccess-gcov/ + +Je n'y ai pas trouve d'anomalies. + +compilation : -fprofile-arcs -ftest-coverage +------------- + +$MED_BUILD_DIR/src/ParaMEDMEM/makefile.in : LIB=libparamedar.a \ +------------------------------------------- libparamed.la + +$MED_BUILD_DIR/src/ParaMEDMEM/Test/makefile.in : LIB = libParaMEDMEMTestar.a \ +------------------------------------------------ libParaMEDMEMTest.la + +execution et gcov : +------------------- + +Pour pouvoir traiter les .cxx de ${MED_BUILD_DIR}/src/ParaMEDMEM et de +${MED_BUILD_DIR}/src/ParaMEDMEM/Test, on execute deux fois gcov. + +cd ${MED_BUILD_DIR}/src/ParaMEDMEM/Test + +mpirun -np 3 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} TestMPIAccess + +gcov TestMPIAccess.cxx test_MPI_Access_Send_Recv.cxx \ + test_MPI_Access_Cyclic_Send_Recv.cxx \ + test_MPI_Access_SendRecv.cxx \ + test_MPI_Access_ISend_IRecv.cxx \ + test_MPI_Access_Cyclic_ISend_IRecv.cxx \ + test_MPI_Access_ISendRecv.cxx \ + test_MPI_Access_Probe.cxx \ + test_MPI_Access_IProbe.cxx \ + test_MPI_Access_Cancel.cxx \ + test_MPI_Access_Send_Recv_Length.cxx \ + test_MPI_Access_ISend_IRecv_Length.cxx \ + test_MPI_Access_ISend_IRecv_Length_1.cxx \ + test_MPI_Access_Time.cxx \ + test_MPI_Access_Time_0.cxx \ + test_MPI_Access_ISend_IRecv_BottleNeck.cxx \ + ../MPI_Access.cxx +gcov -o ../ TestMPIAccess.cxx test_MPI_Access_Send_Recv.cxx \ + test_MPI_Access_Cyclic_Send_Recv.cxx \ + test_MPI_Access_SendRecv.cxx \ + test_MPI_Access_ISend_IRecv.cxx \ + test_MPI_Access_Cyclic_ISend_IRecv.cxx \ + test_MPI_Access_ISendRecv.cxx \ + test_MPI_Access_Probe.cxx \ + test_MPI_Access_IProbe.cxx \ + test_MPI_Access_Cancel.cxx \ + test_MPI_Access_Send_Recv_Length.cxx \ + test_MPI_Access_ISend_IRecv_Length.cxx \ + test_MPI_Access_ISend_IRecv_Length_1.cxx \ + test_MPI_Access_Time.cxx \ + test_MPI_Access_Time_0.cxx \ + test_MPI_Access_ISend_IRecv_BottleNeck.cxx \ + ../MPI_Access.cxx + + +cd ${MED_BUILD_DIR}/src/ParaMEDMEM/Test +mpirun -np 11 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} TestMPIAccessDEC + +gcov TestMPIAccessDEC.cxx test_AllToAllDEC.cxx \ + test_AllToAllvDEC.cxx \ + test_AllToAllTimeDEC.cxx \ + test_AllToAllvTimeDEC.cxx \ + test_AllToAllvTimeDoubleDEC.cxx \ + ../TimeInterpolator.cxx \ + ../LinearTimeInterpolator.cxx \ + ../MPI_Access.cxx \ + ../MPI_AccessDEC.cxx +gcov -o ../ TestMPIAccessDEC.cxx test_AllToAllDEC.cxx \ + test_AllToAllvDEC.cxx \ + test_AllToAllTimeDEC.cxx \ + test_AllToAllvTimeDEC.cxx \ + test_AllToAllvTimeDoubleDEC.cxx \ + ../TimeInterpolator.cxx \ + ../LinearTimeInterpolator.cxx \ + ../MPI_Access.cxx \ + ../MPI_AccessDEC.cxx + +cd ${MED_BUILD_DIR}/src/ParaMEDMEM/Test +mpirun -np 5 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} TestParaMEDMEM + +gcov TestParaMEDMEM.cxx ParaMEDMEMTest.cxx \ + ParaMEDMEMTest_MPIProcessorGroup.cxx \ + ParaMEDMEMTest_BlockTopology.cxx \ + ParaMEDMEMTest_InterpKernelDEC.cxx \ + ../BlockTopology.cxx \ + ../ComponentTopology.cxx \ + ../DEC.cxx \ + ../ElementLocator.cxx \ + ../InterpolationMatrix.cxx \ + ../InterpKernelDEC.cxx \ + ../MPIProcessorGroup.cxx \ + ../MxN_Mapping.cxx \ + ../ParaFIELD.cxx \ + ../ParaMESH.cxx \ + ../ParaSUPPORT.cxx \ + ../ProcessorGroup.cxx \ + ../TimeInterpolator.cxx \ + ../LinearTimeInterpolator.cxx \ + ../MPI_Access.cxx \ + ../MPI_AccessDEC.cxx + +gcov -o ../ TestParaMEDMEM.cxx ParaMEDMEMTest.cxx \ + ParaMEDMEMTest_MPIProcessorGroup.cxx \ + ParaMEDMEMTest_BlockTopology.cxx \ + ParaMEDMEMTest_InterpKernelDEC.cxx \ + ../BlockTopology.cxx \ + ../ComponentTopology.cxx \ + ../DEC.cxx \ + ../ElementLocator.cxx \ + ../InterpolationMatrix.cxx \ + ../InterpKernelDEC.cxx \ + ../MPIProcessorGroup.cxx \ + ../MxN_Mapping.cxx \ + ../ParaFIELD.cxx \ + ../ParaMESH.cxx \ + ../ParaSUPPORT.cxx \ + ../ProcessorGroup.cxx \ + ../TimeInterpolator.cxx \ + ../LinearTimeInterpolator.cxx \ + ../MPI_Access.cxx \ + ../MPI_AccessDEC.cxx diff --git a/src/ParaMEDMEM/README_JR b/src/ParaMEDMEM/README_JR deleted file mode 100644 index 762dc9e47..000000000 --- a/src/ParaMEDMEM/README_JR +++ /dev/null @@ -1,446 +0,0 @@ - -CVS : -===== - -Branche : BR_MEDPARA : MED_SRC -setenv CVSROOT :pserver:rahuel@cvs.opencascade.com:/home/server/cvs/MED -cvs login -... - -Repertoires : -============= - -Sources : /home/rahuel/MEDPARAsynch -Construction sur awa : /data/tmpawa/rahuel/MEDPARAsynch/MED_Build -Intallation sur awa : /data/tmpawa/rahuel/MEDPARAsynch/MED_Install - - -Environnement : -=============== - -source /home/rahuel/MEDPARAsynch/env_products.csh - -On utilise : -/data/tmpawa/vb144235/valgrind-3.2.1/valgrind_install/bin -/data/tmpawa/adam/Salome3/V3_2_7_AWA_OCC/Python-2.4.1 -/data/tmpawa/vb144235/med_231_install -/data/tmpawa2/adam/omniORB/omniORB-4.0.7 -/data/tmpawa/vb144235/lam_install -/data/tmpawa/vb144235/cppunit_install -/data/tmpawa/vb144235/fvm_install_lam -/data/tmpawa/vb144235/bft_install -/home/rahuel/MEDPARAsynch/ICoCo -/data/tmpawa2/adam/Salome3/V3_2_0_maintainance/KERNEL/KERNEL_INSTALL - - -Build_Configure et Configure : -============================== - -MEDMEM est en "stand-alone" sans KERNEL ni IHM. - -cd $MED_BUILD_DIR -${MED_SRC_DIR}/build_configure --without-kernel --without-ihm -rm ${MED_SRC_DIR}/adm_local_without_kernel/adm_local_without_kernel -rm -fR $MED_BUILD_DIR/adm_local_without_kernel/adm_local_without_kernel - -cd $MED_BUILD_DIR -${MED_SRC_DIR}/configure --without-kernel --without-ihm --with-lam=/data/tmpawa/vb144235/lam_install --prefix=${MED_ROOT_DIR} --with-med2=/data/tmpawa/vb144235/med_231_install --with-python=/data/tmpawa/adam/Salome3/V3_2_7_AWA_OCC/Python-2.4.1 --with-cppunit=/data/tmpawa/vb144235/cppunit_install --with-cppunit_inc=/data/tmpawa/vb144235/cppunit_install/include --with-fvm=/data/tmpawa/vb144235/fvm_install_lam -rm ${MED_SRC_DIR}/adm_local_without_kernel/adm_local_without_kernel -rm -fR $MED_BUILD_DIR/adm_local_without_kernel/adm_local_without_kernel - - -Construction : -============== - -cd $MED_BUILD_DIR -make -make install - -Problemes de construction : -=========================== - -Liste des fichiers modifies et differents de la base CVS pour pouvoir -effectuer la construction et l'installation : - -M MED_SRC/configure.in.base : ------------------------------ -CHECK_MPICH -CHECK_LAM -CHECK_OPENMPI mis en commentaire (redefinit le resultat de CHECK_LAM) -CHECK_CPPUNIT a ete ajoute - -M MED_SRC/adm_local_without_kernel/unix/config_files/check_lam.m4 : -------------------------------------------------------------------- -Debugs pour trouver la bonne configuration de LAM - -M MED_SRC/src/INTERP_KERNEL/Makefile.in : ------------------------------------------ -Problemes de construction des tests - -M MED_SRC/src/ParaMEDMEM/Makefile.in : --------------------------------------- -. Construction de libParaMEDMEM.a pour gcov (link statique) -. Ajout d'options de compilations : -fprofile-arcs -ftest-coverage -pg (gcov) ==> - instrumentation du code - -C MED_SRC/src/ParaMEDMEM/Test/Makefile.in : -------------------------------------------- -. Construction de libParaMEDMEMTest.a pour gcov (link statique) -. Ajout d'options de compilations : -fprofile-arcs -ftest-coverage -pg (gcov) ==> - instrumentation du code -. Prise en compte de $(MED_WITH_KERNEL) avec : - ifeq ($(MED_WITH_KERNEL),yes) - LDFLAGSFORBIN += $(LDFLAGS) -lm $(MED3_LIBS) $(HDF5_LIBS) $(MPI_LIBS) \ - -L$(CMAKE_BINARY_DIR)/lib@LIB_LOCATION_SUFFIX@/salome -lmed_V2_1 -lparamed -lmedmem \ - ${KERNEL_LDFLAGS} -lSALOMELocalTrace -lSALOMEBasics \ - $(CPPUNIT_LIBS) \ - -lParaMEDMEMTest - endif - ifeq ($(MED_WITH_KERNEL),no) - LDFLAGSFORBIN += $(LDFLAGS) -lm $(MED3_LIBS) $(HDF5_LIBS) $(MPI_LIBS) \ - -L$(CMAKE_BINARY_DIR)/lib@LIB_LOCATION_SUFFIX@/salome -lmed_V2_1 -lparamed -linterpkernel -lmedmem \ - ${KERNEL_LDFLAGS} ${FVM_LIBS} ${CPPUNIT_LIBS} -L/data/tmpawa/vb144235/bft_install/lib -lbft\ - -lParaMEDMEMTest - endif - -M MED_SRC/src/ParaMEDMEM/Test/ParaMEDMEMTest.hxx : --------------------------------------------------- -Mise en commentaire du test manquant : -CPPUNIT_TEST(testNonCoincidentDEC_3D); - -U MED_SRC/src/ParaMEDMEM/Test/ParaMEDMEMTest_NonCoincidentDEC.cxx : -------------------------------------------------------------------- -Manque dans CVS - -Pour forcer la reconstruction des tests : -========================================= - -cd $MED_BUILD_DIR -rm src/ParaMEDMEM/*o -rm src/ParaMEDMEM/*.la -rm src/ParaMEDMEM/test_* -rm src/ParaMEDMEM/.libs/* -rm src/ParaMEDMEM/Test/*o -rm src/ParaMEDMEM/Test/*.la -rm src/ParaMEDMEM/Test/.libs/* -rm core.* -rm vgcore.* -cd $MED_BUILD_DIR/src/ParaMEDMEM/Test -make -make install -cd $MED_BUILD_DIR - - -Probleme avec lam : -=================== - -jr[1175]> mpirun -np 5 -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} TestParaMEDMEM -21508 TestParaMEDMEM running on n0 (o) -21509 TestParaMEDMEM running on n0 (o) -21510 TestParaMEDMEM running on n0 (o) -21511 TestParaMEDMEM running on n0 (o) -21512 TestParaMEDMEM running on n0 (o) -- Trace /home/rahuel/MEDPARAsynch/MED_SRC/src/MEDMEM/MEDMEM_Init.cxx [54] : Med Memory Initialization with $SALOME_trace = local -- Trace /home/rahuel/MEDPARAsynch/MED_SRC/src/MEDMEM/MEDMEM_Init.cxx [54] : Med Memory Initialization with $SALOME_trace = local -- Trace /home/rahuel/MEDPARAsynch/MED_SRC/src/MEDMEM/MEDMEM_Init.cxx [54] : Med Memory Initialization with $SALOME_trace = local -- Trace /home/rahuel/MEDPARAsynch/MED_SRC/src/MEDMEM/MEDMEM_Init.cxx [54] : Med Memory Initialization with $SALOME_trace = local -- Trace /home/rahuel/MEDPARAsynch/MED_SRC/src/MEDMEM/MEDMEM_Init.cxx [54] : Med Memory Initialization with $SALOME_trace = local ------------------------------------------------------------------------------ -The selected RPI failed to initialize during MPI_INIT. This is a -fatal error; I must abort. - -This occurred on host awa (n0). -The PID of failed process was 21508 (MPI_COMM_WORLD rank: 0) ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -One of the processes started by mpirun has exited with a nonzero exit -code. This typically indicates that the process finished in error. -If your process did not finish in error, be sure to include a "return -0" or "exit(0)" in your C code before exiting the application. - -PID 21510 failed on node n0 (127.0.0.1) with exit status 1. ------------------------------------------------------------------------------ -jr[1176]> - - -Contournement du probleme lam : -=============================== - -mpirun -np 5 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} TestParaMEDMEM - - -Valgrind : -========== -. Les tests avec valgrind indiquent des erreurs dans MPI_Init et - MPI_Finalize ainsi que dans des programmes appeles "below main". -. De plus on obtient un "Segmentation Violation" accompagne d'un - fichier "vgcore.*" (plantage de valgrind) -. Mais on a " All heap blocks were freed -- no leaks are possible." - et on n'a aucune erreur de malloc/free new/delete dans ParaMEDMEM et - dans les tests. - -. Cependant si on execute les tests sans valgrind, il n'y a pas - d'erreur ni de fichier "core.*". - - -Tests avec CPPUNIT de $MED_BUILD_DIR/src/ParaMEDMEM/Test : -========================================================== - -L'appel a MPI_Init n'est fait qu'une seule fois. -Il est suivi par l'execution de toute la suite des tests regroupes -dans les trois executables TestParaMEDMEM, TestMPIAccessDEC et -TestMPIAccess -On a enfin un seul appel a MPI_Finalize. - -Si un des tests d'une suite de tests comporte une anomalie cela -peut avoir des implications sur l'execution des tests suivants. - -Lors de la mise au point de la suite de tests de TestMPIAccessDEC -cela etait le cas : il restait des messages postes dans lam mais -non lus. Le test suivant s'executait de plus en plus lentement -sans donner d'erreur (probleme difficile a identifier). - - -Lancement des tests de TestParaMEDMEM avec CPPUNIT et TotalView (option -tv) : -============================================================================== - -mpirun -np 5 -ssi rpi tcp C -tv -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} TestParaMEDMEM - -Il arrive qu'on ne puisse pas utiliser totalview par manque de -license. - - - -Lancement des tests de TestParaMEDMEM avec CPPUNIT et Valgrind avec "memory leaks" : -==================================================================================== - -mpirun -np 5 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full TestParaMEDMEM - - -Lancement des tests fonctionnels de MPI_AccessDEC avec CPPUNIT : -================================================================ - -mpirun -np 11 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full TestMPIAccessDEC - - -Lancement des tests unitaires de MPI_Access avec CPPUNIT : -========================================================== - -mpirun -np 3 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full TestMPIAccess - - -TestMPIAccess/TestMPIAccessDEC/TestParaMEDMEM et gcov : -======================================================= - -Les resultats sont dans les repertoires suivants de $MED_BUILD_DIR/src/ParaMEDMEM/Test : -------------- - - TestParaMEDMEM-gcov/ - TestMPIAccessDEC-gcov/ - TestMPIAccess-gcov/ - -Je n'y ai pas trouve d'anomalies. - -compilation : -fprofile-arcs -ftest-coverage -------------- - -$MED_BUILD_DIR/src/ParaMEDMEM/makefile.in : LIB=libparamedar.a \ -------------------------------------------- libparamed.la - -$MED_BUILD_DIR/src/ParaMEDMEM/Test/makefile.in : LIB = libParaMEDMEMTestar.a \ ------------------------------------------------- libParaMEDMEMTest.la - -links statiques manuels : -------------------------- - -g++ -g -D_DEBUG_ -Wno-deprecated -Wparentheses -Wreturn-type -Wunused -DPCLINUX -I/data/tmpawa/vb144235/cppunit_install/include -I/data/tmpawa/vb144235/lam_install/include -ftemplate-depth-42 -I/home/rahuel/MEDPARAsynch/MED_SRC/src/ParaMEDMEM -fprofile-arcs -ftest-coverage -o TestMPIAccess TestMPIAccess.lo -L../../../lib64/salome -lstdc++ -L../../../lib64/salome -lstdc++ -lm -L/data/tmpawa/vb144235/med_231_install/lib -lmed -lhdf5 -lhdf5 -L/data/tmpawa/vb144235/lam_install/lib -llam -lmpi -L../../../lib64/salome -lmed_V2_1 --whole-archive -linterpkernel -lmedmem -L/data/tmpawa/vb144235/fvm_install_lam/lib -lfvm -L/data/tmpawa/vb144235/cppunit_install/lib -lcppunit -L/data/tmpawa/vb144235/bft_install/lib -lbft -lutil -lm -lrt -ldl -Bstatic -L./ -lParaMEDMEMTestar -L../ -lparamedar -L./ -lParaMEDMEMTestar - -g++ -g -D_DEBUG_ -Wno-deprecated -Wparentheses -Wreturn-type -Wunused -DPCLINUX -I/data/tmpawa/vb144235/cppunit_install/include -I/data/tmpawa/vb144235/lam_install/include -ftemplate-depth-42 -I/home/rahuel/MEDPARAsynch/MED_SRC/src/ParaMEDMEM -fprofile-arcs -ftest-coverage -o TestMPIAccessDEC TestMPIAccessDEC.lo -L../../../lib64/salome -lstdc++ -L../../../lib64/salome -lstdc++ -lm -L/data/tmpawa/vb144235/med_231_install/lib -lmed -lhdf5 -lhdf5 -L/data/tmpawa/vb144235/lam_install/lib -llam -lmpi -L../../../lib64/salome -lmed_V2_1 --whole-archive -linterpkernel -lmedmem -L/data/tmpawa/vb144235/fvm_install_lam/lib -lfvm -L/data/tmpawa/vb144235/cppunit_install/lib -lcppunit -L/data/tmpawa/vb144235/bft_install/lib -lbft -lutil -lm -lrt -ldl -Bstatic -L./ -lParaMEDMEMTestar -L../ -lparamedar -L./ -lParaMEDMEMTestar - -g++ -g -D_DEBUG_ -Wno-deprecated -Wparentheses -Wreturn-type -Wunused -DPCLINUX -I/data/tmpawa/vb144235/cppunit_install/include -I/data/tmpawa/vb144235/lam_install/include -ftemplate-depth-42 -I/home/rahuel/MEDPARAsynch/MED_SRC/src/ParaMEDMEM -fprofile-arcs -ftest-coverage -o TestParaMEDMEM TestParaMEDMEM.lo -L../../../lib64/salome -lstdc++ -L../../../lib64/salome -lstdc++ -lm -L/data/tmpawa/vb144235/med_231_install/lib -lmed -lhdf5 -lhdf5 -L/data/tmpawa/vb144235/lam_install/lib -llam -lmpi -L../../../lib64/salome -lmed_V2_1 --whole-archive -linterpkernel -lmedmem -L/data/tmpawa/vb144235/fvm_install_lam/lib -lfvm -L/data/tmpawa/vb144235/cppunit_install/lib -lcppunit -L/data/tmpawa/vb144235/bft_install/lib -lbft -lutil -lm -lrt -ldl -Bstatic -L./ -lParaMEDMEMTestar -L../ -lparamedar -L./ -lParaMEDMEMTestar - -Ne pas oublier le make install apres ... - -execution et gcov : -------------------- - -Pour pouvoir traiter les .cxx de ${MED_BUILD_DIR}/src/ParaMEDMEM et de -${MED_BUILD_DIR}/src/ParaMEDMEM/Test, on execute deux fois gcov. - -cd ${MED_BUILD_DIR}/src/ParaMEDMEM/Test - -mpirun -np 3 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} TestMPIAccess - -gcov TestMPIAccess.cxx test_MPI_Access_Send_Recv.cxx \ - test_MPI_Access_Cyclic_Send_Recv.cxx \ - test_MPI_Access_SendRecv.cxx \ - test_MPI_Access_ISend_IRecv.cxx \ - test_MPI_Access_Cyclic_ISend_IRecv.cxx \ - test_MPI_Access_ISendRecv.cxx \ - test_MPI_Access_Probe.cxx \ - test_MPI_Access_IProbe.cxx \ - test_MPI_Access_Cancel.cxx \ - test_MPI_Access_Send_Recv_Length.cxx \ - test_MPI_Access_ISend_IRecv_Length.cxx \ - test_MPI_Access_ISend_IRecv_Length_1.cxx \ - test_MPI_Access_Time.cxx \ - test_MPI_Access_Time_0.cxx \ - test_MPI_Access_ISend_IRecv_BottleNeck.cxx \ - ../MPI_Access.cxx -gcov -o ../ TestMPIAccess.cxx test_MPI_Access_Send_Recv.cxx \ - test_MPI_Access_Cyclic_Send_Recv.cxx \ - test_MPI_Access_SendRecv.cxx \ - test_MPI_Access_ISend_IRecv.cxx \ - test_MPI_Access_Cyclic_ISend_IRecv.cxx \ - test_MPI_Access_ISendRecv.cxx \ - test_MPI_Access_Probe.cxx \ - test_MPI_Access_IProbe.cxx \ - test_MPI_Access_Cancel.cxx \ - test_MPI_Access_Send_Recv_Length.cxx \ - test_MPI_Access_ISend_IRecv_Length.cxx \ - test_MPI_Access_ISend_IRecv_Length_1.cxx \ - test_MPI_Access_Time.cxx \ - test_MPI_Access_Time_0.cxx \ - test_MPI_Access_ISend_IRecv_BottleNeck.cxx \ - ../MPI_Access.cxx - - -cd ${MED_BUILD_DIR}/src/ParaMEDMEM/Test -mpirun -np 11 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} TestMPIAccessDEC - -gcov TestMPIAccessDEC.cxx test_AllToAllDEC.cxx \ - test_AllToAllvDEC.cxx \ - test_AllToAllTimeDEC.cxx \ - test_AllToAllvTimeDEC.cxx \ - test_AllToAllvTimeDoubleDEC.cxx \ - ../TimeInterpolator.cxx \ - ../LinearTimeInterpolator.cxx \ - ../MPI_Access.cxx \ - ../MPI_AccessDEC.cxx -gcov -o ../ TestMPIAccessDEC.cxx test_AllToAllDEC.cxx \ - test_AllToAllvDEC.cxx \ - test_AllToAllTimeDEC.cxx \ - test_AllToAllvTimeDEC.cxx \ - test_AllToAllvTimeDoubleDEC.cxx \ - ../TimeInterpolator.cxx \ - ../LinearTimeInterpolator.cxx \ - ../MPI_Access.cxx \ - ../MPI_AccessDEC.cxx - -cd ${MED_BUILD_DIR}/src/ParaMEDMEM/Test -mpirun -np 5 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} TestParaMEDMEM - -gcov TestParaMEDMEM.cxx ParaMEDMEMTest.cxx \ - ParaMEDMEMTest_MPIProcessorGroup.cxx \ - ParaMEDMEMTest_BlockTopology.cxx \ - ParaMEDMEMTest_InterpKernelDEC.cxx \ - ../BlockTopology.cxx \ - ../ComponentTopology.cxx \ - ../DEC.cxx \ - ../ElementLocator.cxx \ - ../InterpolationMatrix.cxx \ - ../InterpKernelDEC.cxx \ - ../MPIProcessorGroup.cxx \ - ../MxN_Mapping.cxx \ - ../ParaFIELD.cxx \ - ../ParaMESH.cxx \ - ../ParaSUPPORT.cxx \ - ../ProcessorGroup.cxx \ - ../TimeInterpolator.cxx \ - ../LinearTimeInterpolator.cxx \ - ../MPI_Access.cxx \ - ../MPI_AccessDEC.cxx - -gcov -o ../ TestParaMEDMEM.cxx ParaMEDMEMTest.cxx \ - ParaMEDMEMTest_MPIProcessorGroup.cxx \ - ParaMEDMEMTest_BlockTopology.cxx \ - ParaMEDMEMTest_InterpKernelDEC.cxx \ - ../BlockTopology.cxx \ - ../ComponentTopology.cxx \ - ../DEC.cxx \ - ../ElementLocator.cxx \ - ../InterpolationMatrix.cxx \ - ../InterpKernelDEC.cxx \ - ../MPIProcessorGroup.cxx \ - ../MxN_Mapping.cxx \ - ../ParaFIELD.cxx \ - ../ParaMESH.cxx \ - ../ParaSUPPORT.cxx \ - ../ProcessorGroup.cxx \ - ../TimeInterpolator.cxx \ - ../LinearTimeInterpolator.cxx \ - ../MPI_Access.cxx \ - ../MPI_AccessDEC.cxx - - - - - -Lancement des tests unitaires sans CPPUNIT : -============================================ - -mpirun -np 2 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_Send_Recv - -mpirun -np 3 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_Cyclic_Send_Recv - -mpirun -np 2 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_SendRecv - -mpirun -np 2 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_ISend_IRecv - -mpirun -np 3 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_Cyclic_ISend_IRecv - -mpirun -np 2 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_ISendRecv - -mpirun -np 2 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_Probe - -mpirun -np 2 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_IProbe - -mpirun -np 2 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_Cancel - -mpirun -np 2 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_Send_Recv_Length - -mpirun -np 2 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_ISend_IRecv_Length - -mpirun -np 2 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_ISend_IRecv_Length_1 - -mpirun -np 2 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_Time - -mpirun -np 2 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_Time_0 2 1 - - -#AllToAllDEC -mpirun -np 4 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_AllToAllDEC 0 - -mpirun -np 4 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_AllToAllDEC 1 - - -#AllToAllvDEC -mpirun -np 4 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_AllToAllvDEC 0 - -mpirun -np 4 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_AllToAllvDEC 1 - - -#AllToAllTimeDEC -mpirun -np 4 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_AllToAllTimeDEC 0 - -mpirun -np 4 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_AllToAllTimeDEC 1 - - -#AllToAllvTimeDEC -mpirun -np 11 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_AllToAllvTimeDEC 0 1 - -mpirun -np 11 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_AllToAllvTimeDEC 0 - -mpirun -np 11 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_AllToAllvTimeDEC 1 - - - -#AllToAllvTimeDoubleDEC -mpirun -np 11 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_AllToAllvTimeDoubleDEC 0 - -mpirun -np 11 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_AllToAllvTimeDoubleDEC 1 - - - -mpirun -np 2 -ssi rpi tcp C -v -x PATH=${PATH},LD_LIBRARY_PATH=${LD_LIBRARY_PATH} valgrind --leak-check=full test_MPI_Access_ISend_IRecv_BottleNeck - diff --git a/src/ParaMEDMEM/StructuredCoincidentDEC.cxx b/src/ParaMEDMEM/StructuredCoincidentDEC.cxx index 1e88a9581..7cdc16a44 100644 --- a/src/ParaMEDMEM/StructuredCoincidentDEC.cxx +++ b/src/ParaMEDMEM/StructuredCoincidentDEC.cxx @@ -38,23 +38,29 @@ namespace ParaMEDMEM \anchor StructuredCoincidentDEC-det \class StructuredCoincidentDEC - This class is meant for remapping fields that have identical - supports with different parallel topologies. It can be used to couple - together multiphysics codes that operate on the same domain - with different partitionings, which can be useful if one of + This class aims at \ref interp "remapping fields" that have identical + structured supports (=the same underlying mesh) but different parallel topologies + (=different sub-domains in the structured mesh). It can be used to couple + together multi-physics codes that operate on the same domain + with different partitioning. This can be useful for example if one of the computation is much faster than the other. It can also be used to couple together codes that share an interface that was generated in the same manner (with identical global ids). - Also, this \ref para-dec can be used for fields that have component topologies, + Also, this \ref para-dec "DEC" can be used for fields that have component topologies, i.e., components that are scattered over several processors. The remapping between the two supports is based on identity of global - ids, instead of geometrical considerations as it is the case for - \ref NonCoincidentDEC-det "NonCoincidentDEC" and \ref InterpKernelDEC-det "InterpKernelDEC". - Therefore, this \ref para-dec "DEC" must not be used - for coincident meshes that do not have the same numbering. + ids, instead of geometrical considerations (as it is the case for + \ref InterpKernelDEC-det "InterpKernelDEC"). + Therefore, beware that this \ref para-dec "DEC" can not be used + for coincident meshes if they do *not* have the exact same numbering. - As all the other DECs, its use is made of two phases : + With this %DEC no projection, and no interpolation of the field data is done, contrary + to what happens in \ref InterpKernelDEC-det "InterpKernelDEC". It is just + a matter of allocating the values from one side to the other, using directly the cell + identifiers. + + As all the other DECs, its usage requires two phases : - a setup phase during which the topologies are exchanged so that the target side knows from which processors it should expect the data. @@ -74,11 +80,11 @@ namespace ParaMEDMEM ... \endcode - Creating a ParaFIELD to be attached to the DEC is exactly the same as for - other DECs in the case when the remapping concerns similar meshes - that only have different partitionings. In the case when the - fields have also different component topologies, creating the ParaFIELD - requires some more effort. See the \ref para-over section for more details. + Creating a ParaFIELD to be attached to the %DEC is done in exactly the same way as for + the other DECs, if only the partitioning of the support mesh differs. + In the case where the + fields have also different *component* topologies, creating the ParaFIELD + requires some more effort. See the \ref para-over "parallelism" section for more details. */ @@ -104,11 +110,12 @@ namespace ParaMEDMEM delete _topo_target; } - StructuredCoincidentDEC::StructuredCoincidentDEC(ProcessorGroup& local_group, ProcessorGroup& distant_group):DisjointDEC(local_group,distant_group), - _topo_source(0),_topo_target(0), - _send_counts(0),_recv_counts(0), - _send_displs(0),_recv_displs(0), - _recv_buffer(0),_send_buffer(0) + StructuredCoincidentDEC::StructuredCoincidentDEC(ProcessorGroup& local_group, ProcessorGroup& distant_group): + DisjointDEC(local_group,distant_group), + _topo_source(0),_topo_target(0), + _send_counts(0),_recv_counts(0), + _send_displs(0),_recv_displs(0), + _recv_buffer(0),_send_buffer(0) { } diff --git a/src/ParaMEDMEM/StructuredCoincidentDEC.hxx b/src/ParaMEDMEM/StructuredCoincidentDEC.hxx index 75f63b4f0..1653467b1 100644 --- a/src/ParaMEDMEM/StructuredCoincidentDEC.hxx +++ b/src/ParaMEDMEM/StructuredCoincidentDEC.hxx @@ -28,6 +28,7 @@ namespace ParaMEDMEM { class DEC; class BlockTopology; + class StructuredCoincidentDEC : public DisjointDEC { public: diff --git a/src/ParaMEDMEM/TimeInterpolator.hxx b/src/ParaMEDMEM/TimeInterpolator.hxx index 30df1c5e6..e284acc8e 100644 --- a/src/ParaMEDMEM/TimeInterpolator.hxx +++ b/src/ParaMEDMEM/TimeInterpolator.hxx @@ -27,6 +27,12 @@ namespace ParaMEDMEM { + + /*! + * Internal class, not part of the public API. + * + * Abstract class for all time-related interpolation in a parallel context. + */ class TimeInterpolator { public: diff --git a/src/ParaMEDMEM/Topology.hxx b/src/ParaMEDMEM/Topology.hxx index 4b10f8b43..19ce03458 100644 --- a/src/ParaMEDMEM/Topology.hxx +++ b/src/ParaMEDMEM/Topology.hxx @@ -20,12 +20,17 @@ #ifndef __TOPOLOGY_HXX__ #define __TOPOLOGY_HXX__ -#include - namespace ParaMEDMEM { class ProcessorGroup; + /*! + * Topology of a group of processors within a processor group. Abstract class, see derivations. + * + * \sa BlockTopology + * \sa ExplicitTopology + * \sa MPIProcessorGroup + */ class Topology { public: -- 2.39.2