Back to index

salome-med  6.5.0
Functions
NonCoincidentDEC

Functions

 ParaMEDMEM::NonCoincidentDEC::NonCoincidentDEC (ProcessorGroup &, ProcessorGroup &)
 Constructor of a non coincident DEC with a source group on which lies a field lying on a mesh and a target group on which lies a mesh.
virtual ParaMEDMEM::NonCoincidentDEC::~NonCoincidentDEC ()
void ParaMEDMEM::NonCoincidentDEC::synchronize ()
 Synchronization process.
void ParaMEDMEM::NonCoincidentDEC::recvData ()
 This method is called on the target group in order to trigger the retrieveal of field data.
void ParaMEDMEM::NonCoincidentDEC::sendData ()
 This method is called on the source group in order to send field data.

Detailed Description

Overview

NonCoincidentDEC enables nonconservative 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 by a field evaluation at the point location. Thus, it is typically faster than the InterpKernelDEC which gives a conservativeremapping. It is particularly true for the initialisation phase (synchronize) which is very computationnaly intensive in InterpKernelDEC.

In the present version, only fields lying on elements 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.

NonCoincident_small.png
Example showing the transfer from a field based on a quadrangular mesh to a triangular mesh. The triangle barycenters are computed and located in the quadrangles. In a P0-P0 interpolation, the value on the quadrangle is then applied to the triangles whose barycenter lies within.
A typical use of NonCoincidentDEC encompasses two distinct phases :

The following code excerpt illutrates a typical use of the NonCoincidentDEC class.

    ...
    NonCoincidentDEC dec(groupA, groupB);
    dec.attachLocalField(field);
    dec.synchronize();
    if (groupA.containsMyRank())
    dec.recvData();
    else if (groupB.containsMyRank())
    dec.sendData();
    ...

Computing the field on the receiving side can be expressed in terms of a matrix-vector product : $ \phi_t=W.\phi_s$, with $ \phi_t $ the field on the target side and $ \phi_s $ the field on the source side. In the P0-P0 case, this matrix is a plain rectangular matrix with one non-zero element per row (with value 1). For instance, in the above figure, the matrix is :

\[ \begin{tabular}{|cccc|} 1 & 0 & 0 & 0\\ 0 & 0 & 1 & 0\\ 1 & 0 & 0 & 0\\ 0 & 0 & 1 & 0\\ \end{tabular} \]


Function Documentation

Constructor of a non coincident DEC with a source group on which lies a field lying on a mesh and a target group on which lies a mesh.

Parameters:
source_groupProcessorGroup on the source side
target_groupProcessorGroup on the target side

Definition at line 256 of file NonCoincidentDEC.cxx.

This method is called on the target group in order to trigger the retrieveal of field data.

It must be called synchronously with a sendData() call on the source group.

Definition at line 346 of file NonCoincidentDEC.cxx.

  {
    int nbelems = _local_field->getField()->getSupport()->getMesh()->getNumberOfElements(MED_EN::MED_CELL, MED_EN::MED_ALL_ELEMENTS);
    int nbcomp =  _local_field->getField()->getNumberOfComponents();
    double* values = new double [nbelems*nbcomp];
    fvm_locator_exchange_point_var(_locator,
                                   0,
                                   values,
                                   0,
                                   sizeof(double),
                                   nbcomp,
                                   0);
    _local_field->getField()->setValue(values);
    if (_forced_renormalization_flag)
      renormalizeTargetField();
    delete[]values;
  }

This method is called on the source group in order to send field data.

It must be called synchronously with a recvData() call on the target group.

Definition at line 369 of file NonCoincidentDEC.cxx.

  {
    const double* values=_local_field->getField()->getValue();
    int nbcomp = _local_field->getField()->getNumberOfComponents();
    double* distant_values = new double [_nb_distant_points*nbcomp];

    //cheap interpolation :  the value of the cell is transfered to the point
    for (int i=0; i<_nb_distant_points; i++)
      for (int j=0; j <nbcomp; j++)
        distant_values[i*nbcomp+j]=values[(_distant_locations[i]-1)*nbcomp+j];
  
    fvm_locator_exchange_point_var(_locator,
                                   distant_values,
                                   0,
                                   0,
                                   sizeof(double),
                                   nbcomp,
                                   0);

    delete [] distant_values;
    if (_forced_renormalization_flag)
      renormalizeTargetField();

  }

Synchronization process.

Calling this method synchronizes the topologies so that the target side gets the information which enable it to fetch the field value from the source side. A typical call is :

   NonCoincidentDEC dec(source_group,target_group);
   dec.attachLocalField(field);
   dec.synchronize();

Implements ParaMEDMEM::DEC.

Definition at line 276 of file NonCoincidentDEC.cxx.

  {
  
    //initializing FVM parallel environment
    const MPI_Comm* comm=dynamic_cast<const MPIProcessorGroup*> (_union_group)->getComm();
    fvm_parall_set_mpi_comm(*const_cast<MPI_Comm*> (comm));
  
  
    //setting up the communication DEC on both sides
  
    if (_source_group->containsMyRank())
      {
        MEDMEM::MESH* mesh = _local_field->getField()->getSupport()->getMesh();
        fvm_nodal_t* source_nodal = ParaMEDMEM::medmemMeshToFVMMesh(mesh);
      
        int target_size = _target_group->size()  ;
        int start_rank=  _source_group->size();
        const MPI_Comm* comm = (dynamic_cast<const MPIProcessorGroup*> (_union_group))->getComm();
      
        _locator =  fvm_locator_create(1e-6,
                                       *comm,
                                       target_size,
                                       start_rank);
      
        fvm_locator_set_nodal(_locator,
                              source_nodal,
                              mesh->getSpaceDimension(),
                              0,
                              NULL,
                              0);

      
        _nb_distant_points = fvm_locator_get_n_dist_points(_locator);
        _distant_coords = fvm_locator_get_dist_coords(_locator);
        _distant_locations = fvm_locator_get_dist_locations(_locator);
           
      }
    if (_target_group->containsMyRank())
      {
        MEDMEM::MESH* mesh = _local_field->getField()->getSupport()->getMesh();
      
        fvm_nodal_t* target_nodal = ParaMEDMEM::medmemMeshToFVMMesh(mesh);
        int source_size = _source_group->size();
        int start_rank=  0 ;
        const MPI_Comm* comm = (dynamic_cast<const MPIProcessorGroup*> (_union_group))->getComm();
      
        _locator = fvm_locator_create(1e-6,
                                      *comm,
                                      source_size,
                                      start_rank);
        int nbcells = mesh->getNumberOfElements(MED_EN::MED_CELL,MED_EN::MED_ALL_ELEMENTS);
        const MEDMEM::SUPPORT* support=_local_field->getField()->getSupport();
        MEDMEM::FIELD<double>* barycenter_coords = mesh->getBarycenter(support);
        const double* coords = barycenter_coords->getValue();
        fvm_locator_set_nodal(_locator,
                              target_nodal,
                              mesh->getSpaceDimension(),
                              nbcells,
                              NULL,
                              coords);  
        delete barycenter_coords;
      }
  }

Here is the call graph for this function:

Definition at line 261 of file NonCoincidentDEC.cxx.

  {
  }