-// Copyright (C) 2007-2015 CEA/DEN, EDF R&D
+// Copyright (C) 2007-2016 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
#include <iostream>
-namespace ParaMEDMEM
+namespace MEDCoupling
{
/*!
* \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 MEDCoupling::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 MEDCoupling::ParaFIELD, or a
+ * \c ICoCo::Field, or directly a \c MEDCoupling::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 MEDCoupling::DECOptions "DECOptions"
*
- * <TABLE BORDER=1 >
- * <TR><TD>Option</TD><TD>Description</TD><TD>Default value</TD></TR>
- * <TR><TD>ForcedRenormalization</TD><TD>After receiving data, the target field is renormalized so that L2-norms of the source and target fields match.</TD><TD> false </TD></TR>
- *</TABLE>
-
-
- 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),
- _target_group(&target_group),
- _owns_field(false),
- _owns_groups(false)
+ DisjointDEC::DisjointDEC(ProcessorGroup& source_group, ProcessorGroup& target_group):
+ _local_field(0),
+ _source_group(&source_group),
+ _target_group(&target_group),
+ _comm_interface(0),
+ _owns_field(false),
+ _owns_groups(false),
+ _union_comm(MPI_COMM_NULL)
{
+ checkPartitionGroup();
_union_group = source_group.fuse(target_group);
}
- DisjointDEC::DisjointDEC(const DisjointDEC& s):DEC(s),_local_field(0),_union_group(0),_source_group(0),_target_group(0),_owns_field(false),_owns_groups(false)
+ DisjointDEC::DisjointDEC(const DisjointDEC& s):
+ DEC(s),
+ _local_field(0),
+ _union_group(0),
+ _source_group(0),
+ _target_group(0),
+ _comm_interface(0),
+ _owns_field(false),
+ _owns_groups(false),
+ _union_comm(MPI_COMM_NULL)
{
copyInstance(s);
}
void DisjointDEC::copyInstance(const DisjointDEC& other)
{
DEC::copyFrom(other);
- if(other._target_group)
+ if (other._union_comm != MPI_COMM_NULL)
{
- _target_group=other._target_group->deepCpy();
- _owns_groups=true;
- }
- if(other._source_group)
- {
- _source_group=other._source_group->deepCpy();
- _owns_groups=true;
+ // Tricky: the DEC is responsible for the management of _union_comm. And this comm is referenced by
+ // the MPIProcGroups (source/targets). In the case where _union_comm is not NULL we must take care of rebuilding the
+ // MPIProcGroups with a communicator that will survive the destruction of 'other'.
+ _owns_groups = true;
+ MPI_Comm_dup(other._union_comm, &_union_comm);
+// std::cout << "DUP union comm - new is "<< _union_comm << "\n";
+ _target_group = new MPIProcessorGroup(*_comm_interface, other._target_group->getProcIDs(), _union_comm);
+ _source_group = new MPIProcessorGroup(*_comm_interface, other._source_group->getProcIDs(), _union_comm);
}
+ else{
+ if(other._target_group)
+ {
+ _target_group=other._target_group->deepCopy();
+ _owns_groups=true;
+ }
+ if(other._source_group)
+ {
+ _source_group=other._source_group->deepCopy();
+ _owns_groups=true;
+ }
+ }
if (_source_group && _target_group)
_union_group = _source_group->fuse(*_target_group);
}
- DisjointDEC::DisjointDEC(const std::set<int>& source_ids, const std::set<int>& target_ids, const MPI_Comm& world_comm):_local_field(0),
- _owns_field(false),
- _owns_groups(true)
+ DisjointDEC::DisjointDEC(const std::set<int>& source_ids,
+ const std::set<int>& target_ids,
+ const MPI_Comm& world_comm):
+ _local_field(0),
+ _owns_field(false),
+ _owns_groups(true),
+ _comm_interface(0),
+ _union_comm(MPI_COMM_NULL)
{
- ParaMEDMEM::CommInterface comm;
+ MEDCoupling::CommInterface comm;
// Create the list of procs including source and target
std::set<int> union_ids; // source and target ids in world_comm
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);
MPI_Group union_group,world_group;
comm.commGroup(world_comm,&world_group);
comm.groupIncl(world_group,union_ids.size(),union_ranks_world,&union_group);
- MPI_Comm union_comm;
- comm.commCreate(world_comm,union_group,&union_comm);
+ comm.commCreate(world_comm,union_group,&_union_comm);
delete[] union_ranks_world;
-
- if (union_comm==MPI_COMM_NULL)
+ if (_union_comm==MPI_COMM_NULL)
{ // This process is not in union
_source_group=0;
_target_group=0;
_union_group=0;
+ comm.groupFree(&union_group);
+ comm.groupFree(&world_group);
return;
}
delete [] target_ranks_union;
// Create the MPIProcessorGroups
- _source_group = new MPIProcessorGroup(comm,source_ids_union,union_comm);
- _target_group = new MPIProcessorGroup(comm,target_ids_union,union_comm);
+ _source_group = new MPIProcessorGroup(comm,source_ids_union,_union_comm);
+ _target_group = new MPIProcessorGroup(comm,target_ids_union,_union_comm);
_union_group = _source_group->fuse(*_target_group);
-
+ comm.groupFree(&union_group);
+ comm.groupFree(&world_group);
}
DisjointDEC::~DisjointDEC()
_target_group=0;
delete _union_group;
_union_group=0;
+ if (_union_comm != MPI_COMM_NULL)
+ _comm_interface->commFree(&_union_comm);
+ }
+
+ /**
+ * Check that the sources and targets procs form a partition of the world communicator referenced in the groups.
+ * This world communicator is not necessarily MPI_WORLD_COMM, but it has to be covered completly for the DECs to work.
+ */
+ void DisjointDEC::checkPartitionGroup() const
+ {
+ int size = -1;
+ MPIProcessorGroup * tgt = static_cast<MPIProcessorGroup *>(_target_group);
+ MPIProcessorGroup * src = static_cast<MPIProcessorGroup *>(_source_group);
+ MPI_Comm comm_t = tgt->getWorldComm();
+ MPI_Comm comm_s = src->getWorldComm();
+ if (comm_t != comm_s)
+ throw INTERP_KERNEL::Exception("DisjointDEC constructor: Inconsistent world communicator when building DisjointDEC");
+ MPI_Comm_size(comm_t, &size);
+
+ std::set<int> union_ids; // source and target ids in world_comm
+ union_ids.insert(src->getProcIDs().begin(),src->getProcIDs().end());
+ union_ids.insert(tgt->getProcIDs().begin(),tgt->getProcIDs().end());
+ if(union_ids.size()!=size)
+ throw INTERP_KERNEL::Exception("DisjointDEC constructor: source_ids and target_ids do not form a partition of the communicator! Restrain the world communicator passed to MPIProcessorGroup ctor.");
}
void DisjointDEC::setNature(NatureOfField nature)