X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FParaMEDMEM%2FInterpKernelDEC.cxx;h=f4494f489a64877a22e5e44bb242c497bf17d12b;hb=0bf52b9b294008eeb79b593572b035bff39bc7b7;hp=59dfbe9a92587999b7923bda8c617a749647a17e;hpb=22a4bd76f2e2c06917d391a07efa1aa293b35177;p=tools%2Fmedcoupling.git diff --git a/src/ParaMEDMEM/InterpKernelDEC.cxx b/src/ParaMEDMEM/InterpKernelDEC.cxx index 59dfbe9a9..f4494f489 100644 --- a/src/ParaMEDMEM/InterpKernelDEC.cxx +++ b/src/ParaMEDMEM/InterpKernelDEC.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D +// Copyright (C) 2007-2024 CEA, EDF // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -31,109 +31,10 @@ #include "ElementLocator.hxx" namespace MEDCoupling -{ - - /*! - \anchor InterpKernelDEC-det - \class InterpKernelDEC - - \section InterpKernelDEC-over Overview - - 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). - - 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 MEDCoupling::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 "Transfer of a field supported by a quadrangular mesh to a triangular mesh". - - \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 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 illustrates a typical use of the InterpKernelDEC class. - - \code - ... - InterpKernelDEC dec(groupA, groupB); - dec.attachLocalField(field); - dec.synchronize(); - if (groupA.containsMyRank()) - dec.recvData(); - else if (groupB.containsMyRank()) - dec.sendData(); - ... - \endcode - A \ref InterpKerRemapGlobal "remapping" of the field from the source mesh to the target mesh is performed by - the function synchronise(), which computes the interpolation matrix. - - Computing the field on the receiving side can be expressed in terms of a matrix-vector product : - \f$ \phi_t=W.\phi_s\f$, with \f$ \phi_t \f$ the field on the target side and \f$ \phi_s \f$ the field - on the source side. - When remapping a 3D surface to another 3D surface, a projection phase is necessary to match elements - from both sides. Care must be taken when defining this projection to obtain a - \ref InterpKerRemapGlobal "conservative remapping". - - In the P0-P0 case, this matrix is a plain rectangular matrix with coefficients equal to the - intersection areas between triangle and quadrangles. For instance, in the above figure, the matrix - is : - - \f[ - \begin{tabular}{|cccc|} - 0.72 & 0 & 0.2 & 0 \\ - 0.46 & 0 & 0.51 & 0.03\\ - 0.42 & 0.53 & 0 & 0.05\\ - 0 & 0 & 0.92 & 0.05 \\ - \end{tabular} - \f] - - \section InterpKernelDEC-options Options - On top of the usual \ref MEDCoupling::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 - be reviewed in \ref InterpKerIntersectors. - - For instance : - \verbatim - InterpKernelDEC dec(source_group, target_group); - dec.attachLocalField(field); - dec.setDoRotate(false); - dec.setPrecision(1e-12); - dec.synchronize(); - \endverbatim - - \warning{ Options must be set before calling the synchronize method. } - */ - +{ InterpKernelDEC::InterpKernelDEC(): DisjointDEC(), - _nb_distant_points(0), _distant_coords(0), - _distant_locations(0), _interpolation_matrix(0) + _interpolation_matrix(0) { } @@ -150,8 +51,7 @@ namespace MEDCoupling */ InterpKernelDEC::InterpKernelDEC(ProcessorGroup& source_group, ProcessorGroup& target_group): DisjointDEC(source_group, target_group), - _nb_distant_points(0), _distant_coords(0), - _distant_locations(0), _interpolation_matrix(0) + _interpolation_matrix(0) { } @@ -165,16 +65,60 @@ namespace MEDCoupling InterpKernelDEC::InterpKernelDEC(const std::set& src_ids, const std::set& trg_ids, 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) + _interpolation_matrix(0) + { + } + + /*! + * Creates an InterpKernelDEC from an string identifier for the source and target groups. + * The set of procs might not cover entirely MPI_COMM_WORLD + * (a sub-communicator holding the union of source and target procs is recreated internally). + */ + InterpKernelDEC::InterpKernelDEC(ProcessorGroup& generic_group, const std::string& source_group, const std::string& target_group): + DisjointDEC(generic_group.getProcIDsByName(source_group),generic_group.getProcIDsByName(target_group)), + _interpolation_matrix(0) + { + } + + /*! + * Split the interaction group based on the predefined token string "<->" + * The string at left of the token will be the source group and the string at right the target group + */ + static std::pair GetGroupsName( const std::string& interaction_group ) + { + const std::string delimiter = "<->"; + size_t delimiter_position = interaction_group.find(delimiter); + if ( delimiter_position == std::string::npos ) + throw ( "No delimiter <-> found in the interaction group."); + + std::string src = interaction_group.substr(0,delimiter_position); + std::string tgt = interaction_group.substr(delimiter_position+delimiter.size(),interaction_group.size()); + return std::make_pair(src,tgt); + } + + /*! + * Creates an InterpKernelDEC from an string defining an interaction. + * The source and target group are obtained by spliting the string based in the "<->" token. + * The constructor accepting a ProcessorGroup and two strings is reused. + */ + InterpKernelDEC::InterpKernelDEC(ProcessorGroup& generic_group, const std::string& interaction_group ): + InterpKernelDEC(generic_group,GetGroupsName(interaction_group).first,GetGroupsName(interaction_group).second) { } InterpKernelDEC::~InterpKernelDEC() { - if (_interpolation_matrix !=0) + release(); + } + + void InterpKernelDEC::release() + { + if (_interpolation_matrix != nullptr) delete _interpolation_matrix; - } + _interpolation_matrix = nullptr; + DisjointDEC::cleanInstance(); + } + /*! \brief Synchronization process for exchanging topologies. @@ -204,7 +148,7 @@ namespace MEDCoupling //transferring option from InterpKernelDEC to ElementLocator locator.copyOptions(*this); MEDCouplingPointSet* distant_mesh=0; - int* distant_ids=0; + mcIdType* distant_ids=0; std::string distantMeth; for (int i=0; i<_target_group->size(); i++) { @@ -235,7 +179,7 @@ namespace MEDCoupling //transferring option from InterpKernelDEC to ElementLocator locator.copyOptions(*this); MEDCouplingPointSet* distant_mesh=0; - int* distant_ids=0; + mcIdType* distant_ids=0; for (int i=0; i<_source_group->size(); i++) { // int idistant_proc = (i+_target_group->myRank())%_source_group->size(); @@ -258,6 +202,15 @@ namespace MEDCoupling _interpolation_matrix->prepare(); } + /*! + * Set a default value for non fetched entities + */ + void InterpKernelDEC::synchronizeWithDefaultValue(double val) + { + this->synchronize(); + if(_interpolation_matrix ) + _interpolation_matrix->setDefaultValue(val); + } /*! Receives the data whether the processor is on the working side or on the lazy side. It must match a \a sendData() call on the other side. @@ -274,6 +227,29 @@ namespace MEDCoupling } } + MCAuto InterpKernelDEC::retrieveNonFetchedIds() const + { + if( _source_group->containsMyRank() ) + { + return this->retrieveNonFetchedIdsSource(); + } + if( _target_group->containsMyRank() ) + { + return this->retrieveNonFetchedIdsTarget(); + } + THROW_IK_EXCEPTION("Not detected side of rank !"); + } + + MCAuto InterpKernelDEC::retrieveNonFetchedIdsSource() const + { + return _interpolation_matrix->retrieveNonFetchedIdsSource(); + } + + MCAuto InterpKernelDEC::retrieveNonFetchedIdsTarget() const + { + mcIdType nbTuples = _local_field->getField()->getNumberOfTuplesExpected(); + return _interpolation_matrix->retrieveNonFetchedIdsTarget(nbTuples); + } /*! Receives the data at time \a time in asynchronous mode. The value of the field