Back to index

salome-med  6.5.0
Functions
DEC

Functions

 ParaMEDMEM::DisjointDEC::DisjointDEC (ProcessorGroup &source_group, ProcessorGroup &target_group)
 ParaMEDMEM::DisjointDEC::DisjointDEC (const DisjointDEC &)
DisjointDEC & ParaMEDMEM::DisjointDEC::operator= (const DisjointDEC &s)
void ParaMEDMEM::DisjointDEC::copyInstance (const DisjointDEC &other)
 ParaMEDMEM::DisjointDEC::DisjointDEC (const std::set< int > &src_ids, const std::set< int > &trg_ids, const MPI_Comm &world_comm=MPI_COMM_WORLD)
virtual ParaMEDMEM::DisjointDEC::~DisjointDEC ()
void ParaMEDMEM::DisjointDEC::cleanInstance ()
void ParaMEDMEM::DisjointDEC::setNature (NatureOfField nature)
void ParaMEDMEM::DisjointDEC::attachLocalField (const ParaFIELD *field, bool ownPt=false)
 Attaches a local field to a DEC.
void ParaMEDMEM::DisjointDEC::attachLocalField (MEDCouplingFieldDouble *field)
 Attaches a local field to a DEC.
void ParaMEDMEM::DisjointDEC::attachLocalField (const ICoCo::Field *field)
 Attaches a local field to a DEC.
void ParaMEDMEM::DisjointDEC::renormalizeTargetField (bool isWAbs)
 Computes the field norm over its support on the source side and renormalizes the field on the target side so that the norms match.

Detailed Description

Introduction

Interface class for creation of a link between two processor groups for exhanging mesh or field data. The DEC is defined by attaching a field on the receiving or on the sending side. On top of attaching a ParaMEDMEM::FIELD, it is possible to attach a ICoCo::Field. This class is an abstract class that enables coupling of codes that respect the ICoCo interface icoco. It has two implementations: one for codes that express their fields as medoupling fields (ICoCo::MEDField) and one for codes that express their fields as Trio/U fields.

DEC Options

Options supported by DEC objects are

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 DEC :

 InterpKernelDEC dec(source_group,target_group);
 dec.setOptions("ForcedRenormalization",true);
 dec.attachLocalField(field);
 dec.synchronize();
 if (source_group.containsMyRank())
 dec.sendData();
 else
 dec.recvData();

Function Documentation

Attaches a local field to a DEC.

The method will test whether the processor is on the source or the target side and will associate the mesh underlying the field to the local side.

If the processor is on the receiving end of the DEC, the field will be updated by a recvData() call. Reversely, if the processor is on the sending end, the field will be read, possibly transformed, and sent appropriately to the other side.

Definition at line 237 of file DisjointDEC.cxx.

  {
    if(!isInUnion())
      return ;
    ProcessorGroup* local_group;
    if (_source_group->containsMyRank())
      local_group=_source_group;
    else if (_target_group->containsMyRank())
      local_group=_target_group;
    else
      throw INTERP_KERNEL::Exception("Invalid procgroup for field attachment to DEC");
    ParaMESH *paramesh=new ParaMESH((MEDCouplingPointSet *)field->getMesh(),*local_group,field->getMesh()->getName());
    ParaFIELD *tmp=new ParaFIELD(field, paramesh, *local_group);
    tmp->setOwnSupport(true);
    attachLocalField(tmp,true);
    //_comm_interface=&(local_group->getCommInterface());
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void ParaMEDMEM::DisjointDEC::attachLocalField ( const ParaFIELD field,
bool  ownPt = false 
)

Attaches a local field to a DEC.

If the processor is on the receiving end of the DEC, the field will be updated by a recvData() call. Reversely, if the processor is on the sending end, the field will be read, possibly transformed, and sent appropriately to the other side.

Definition at line 215 of file DisjointDEC.cxx.

  {
    if(!isInUnion())
      return ;
    if(_owns_field)
      delete _local_field;
    _local_field=field;
    _owns_field=ownPt;
    _comm_interface=&(field->getTopology()->getProcGroup()->getCommInterface());
    compareFieldAndMethod();
  }

Here is the call graph for this function:

Attaches a local field to a DEC.

If the processor is on the receiving end of the DEC, the field will be updated by a recvData() call. Reversely, if the processor is on the sending end, the field will be read, possibly transformed, and sent appropriately to the other side. The field type is a generic ICoCo Field, so that the DEC can couple a number of different fields :

  • a ICoCo::MEDField, that is created from a MEDCoupling structure
  • a ICOCo::TrioField, that is created from tables extracted from a TRIO-U structure.

Definition at line 265 of file DisjointDEC.cxx.

  {
    if(!isInUnion())
      return ;
    const ICoCo::MEDField* medfield=dynamic_cast<const ICoCo::MEDField*> (field);
    if(medfield !=0)
      {
        attachLocalField(medfield->getField());
        return;
      }
    const ICoCo::TrioField* triofield=dynamic_cast<const ICoCo::TrioField*> (field);
    if (triofield !=0)
      {
        ProcessorGroup* localgroup;
        if (_source_group->containsMyRank())
          localgroup=_source_group;
        else
          localgroup=_target_group;
        delete _icoco_field;
        
        _icoco_field=new ICoCo::MEDField(*const_cast<ICoCo::TrioField* >(triofield));
        attachLocalField(_icoco_field);
        return;
      }
    throw INTERP_KERNEL::Exception("incompatible field type");
  }

Here is the call graph for this function:

Definition at line 182 of file DisjointDEC.cxx.

Here is the caller graph for this function:

void ParaMEDMEM::DisjointDEC::copyInstance ( const DisjointDEC other) [protected]

Definition at line 102 of file DisjointDEC.cxx.

  {
    DEC::copyFrom(other);
    if(other._target_group)
      {
        _target_group=other._target_group->deepCpy();
        _owns_groups=true;
      }
    if(other._source_group)
      {
        _source_group=other._source_group->deepCpy();
        _owns_groups=true;
      }
    if (_source_group && _target_group)
      _union_group = _source_group->fuse(*_target_group);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

ParaMEDMEM::DisjointDEC::DisjointDEC ( ProcessorGroup source_group,
ProcessorGroup target_group 
)

Definition at line 79 of file DisjointDEC.cxx.

Here is the call graph for this function:

Definition at line 89 of file DisjointDEC.cxx.

Here is the call graph for this function:

ParaMEDMEM::DisjointDEC::DisjointDEC ( const std::set< int > &  src_ids,
const std::set< int > &  trg_ids,
const MPI_Comm &  world_comm = MPI_COMM_WORLD 
)

Definition at line 119 of file DisjointDEC.cxx.

                                                                                                                  :_local_field(0), 
                                                                                                                         _owns_field(false),
                                                                                                                         _owns_groups(true),
                                                                                                                         _icoco_field(0)
  {
    ParaMEDMEM::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 !");
    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);

    // Create a communicator on these procs
    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);
    delete[] union_ranks_world;

    if (union_comm==MPI_COMM_NULL)
      { // This process is not in union
        _source_group=0;
        _target_group=0;
        _union_group=0;
        return;
      }

    // Translate source_ids and target_ids from world_comm to union_comm
    int* source_ranks_world=new int[source_ids.size()]; // ranks of sources in world_comm
    std::copy(source_ids.begin(), source_ids.end(),source_ranks_world);
    int* source_ranks_union=new int[source_ids.size()]; // ranks of sources in union_comm
    int* target_ranks_world=new int[target_ids.size()]; // ranks of targets in world_comm
    std::copy(target_ids.begin(), target_ids.end(),target_ranks_world);
    int* target_ranks_union=new int[target_ids.size()]; // ranks of targets in union_comm
    MPI_Group_translate_ranks(world_group,source_ids.size(),source_ranks_world,union_group,source_ranks_union);
    MPI_Group_translate_ranks(world_group,target_ids.size(),target_ranks_world,union_group,target_ranks_union);
    std::set<int> source_ids_union;
    for (int i=0;i<(int)source_ids.size();i++)
      source_ids_union.insert(source_ranks_union[i]);
    std::set<int> target_ids_union;
    for (int i=0;i<(int)target_ids.size();i++)
      target_ids_union.insert(target_ranks_union[i]);
    delete [] source_ranks_world;
    delete [] source_ranks_union;
    delete [] target_ranks_world;
    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);
    _union_group = _source_group->fuse(*_target_group);

  }

Here is the call graph for this function:

DisjointDEC & ParaMEDMEM::DisjointDEC::operator= ( const DisjointDEC s)

Definition at line 94 of file DisjointDEC.cxx.

  {
    cleanInstance();
    copyInstance(s);
    return *this;
     
  }

Here is the call graph for this function:

Computes the field norm over its support on the source side and renormalizes the field on the target side so that the norms match.

\[ I_{source}=\sum_{i=1}^{n_{source}}V_{i}.|\Phi^{source}_{i}|^2, \]

\[ I_{target}=\sum_{i=1}^{n_{target}}V_{i}.|\Phi^{target}_{i}|^2, \]

\[ \Phi^{target}:=\Phi^{target}.\sqrt{I_{source}/I_{target}}. \]

Definition at line 310 of file DisjointDEC.cxx.

  {
    if (_source_group->containsMyRank())
      for (int icomp=0; icomp<_local_field->getField()->getArray()->getNumberOfComponents(); icomp++)
        {
          double total_norm = _local_field->getVolumeIntegral(icomp+1,isWAbs);
          double source_norm = total_norm;
          _comm_interface->broadcast(&source_norm, 1, MPI_DOUBLE, 0,* dynamic_cast<MPIProcessorGroup*>(_union_group)->getComm());

        }
    if (_target_group->containsMyRank())
      {
        for (int icomp=0; icomp<_local_field->getField()->getArray()->getNumberOfComponents(); icomp++)
          {
            double total_norm = _local_field->getVolumeIntegral(icomp+1,isWAbs);
            double source_norm=total_norm;
            _comm_interface->broadcast(&source_norm, 1, MPI_DOUBLE, 0,* dynamic_cast<MPIProcessorGroup*>(_union_group)->getComm());

            if (fabs(total_norm)>1e-100)
              _local_field->getField()->applyLin(source_norm/total_norm,0.0,icomp+1);
          }
      }
  }

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 204 of file DisjointDEC.cxx.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 177 of file DisjointDEC.cxx.

  {
    cleanInstance();
  }

Here is the call graph for this function: