]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
adding the possibility to send data from the target (idle) side and receiving it...
authorvbd <vbd>
Wed, 1 Aug 2007 06:36:59 +0000 (06:36 +0000)
committervbd <vbd>
Wed, 1 Aug 2007 06:36:59 +0000 (06:36 +0000)
src/ParaMEDMEM/InterpolationMatrix.cxx
src/ParaMEDMEM/InterpolationMatrix.hxx
src/ParaMEDMEM/IntersectionDEC.cxx
src/ParaMEDMEM/IntersectionDEC.hxx
src/ParaMEDMEM/MxN_Mapping.cxx
src/ParaMEDMEM/MxN_Mapping.hxx

index 1452d9aeeec871207eb239022cb9eef9467dcb0e..58f9b406c0c40593d48a7f7d703ba555238f6e6d 100644 (file)
@@ -6,10 +6,12 @@
 #include "Interpolation3DSurf.hxx"
 
 /*! \class InterpolationMatrix
+
 This class enables the storage of an interpolation matrix Wij mapping 
-source field Sj to target field Ti via Ti=Wij.Sj.
+source field Sj to target field Ti via Ti=Vi^(-1).Wij.Sj.
 The matrix is built and stored on the processors belonging to the source
 group. 
+
 */
 
 namespace ParaMEDMEM
@@ -22,22 +24,26 @@ namespace ParaMEDMEM
     \param local_group processor group containing the local processors
     \param distant_group processor group containing the distant processors
     \param method interpolation method
-   */
+       */
 InterpolationMatrix::InterpolationMatrix(
 const ParaMEDMEM::ParaMESH& source_support, 
-const ProcessorGroup& local_group,
-const ProcessorGroup& distant_group, 
+const ProcessorGroup& source_group,
+const ProcessorGroup& target_group, 
 const string& method):
-_source_support(*source_support.getMesh()),
-_local_group(local_group),
-_distant_group(distant_group),
-_mapping(local_group, distant_group),
-_method(method)
+       _source_support(*source_support.getMesh()),
+       _mapping(source_group, target_group),
+       _method(method),
+       _source_group(source_group),
+       _target_group(target_group),
+       _source_volume(0)
+       
 {
   int nbelems=  _source_support.getNumberOfElements(MED_EN::MED_CELL,MED_EN::MED_ALL_ELEMENTS);
-  _row_offsets.resize(nbelems+1,0);
-  
+  _row_offsets.resize(nbelems+1);
+       for (int i=0; i<nbelems+1; i++)
+               _row_offsets[i]=0;
   
+       _coeffs.resize(nbelems);
 }
 
 InterpolationMatrix::~InterpolationMatrix()
@@ -45,115 +51,98 @@ InterpolationMatrix::~InterpolationMatrix()
 }
 
 /*!
-adds the contribution of a distant subdomain to the interpolation matrix
+\brief Adds the contribution of a distant subdomain to the interpolation matrix.
+
+The method adds contribution to the interpolation matrix.
+For each row of the matrix, elements are addded as
+a (column, coeff) pair in the _coeffs array. This column number refers
+to an element on the target side via the _col_offsets array. It is made of a series 
+of (iproc, ielem) pairs. 
+The number of elements per row is stored in the row_offsets array.
+
 \param distant_support local representation of the distant subdomain
 \param iproc_distant id of the distant subdomain (in the distant group)
 \param distant_elems mapping between the local representation of the subdomain and the actual elem ids on the distant subdomain
  */
 void InterpolationMatrix::addContribution(MEDMEM::MESH& distant_support, int iproc_distant, int* distant_elems)
 {
-
-       // computing the intersections between distant and local elements
+       //creating the interpolator structure
   MEDMEM::Interpolation* interpolator;
-       if (distant_support.getMeshDimension()==2 && distant_support.getSpaceDimension()==3)
-               interpolator=new MEDMEM::Interpolation3DSurf();
-       else if (distant_support.getMeshDimension()==2 && distant_support.getSpaceDimension()==2)
-               interpolator=new MEDMEM::Interpolation2D();
-
-  int nbelems=  _source_support.getNumberOfElements(MED_EN::MED_CELL,MED_EN::MED_ALL_ELEMENTS);  
+  if (distant_support.getMeshDimension()==2 && distant_support.getSpaceDimension()==3)
+    interpolator=new MEDMEM::Interpolation3DSurf();
+  else if (distant_support.getMeshDimension()==2 && distant_support.getSpaceDimension()==2)
+    interpolator=new MEDMEM::Interpolation2D();
+  
+       //computation of the intersection volumes between source and target elements
+  int source_size=  _source_support.getNumberOfElements(MED_EN::MED_CELL,MED_EN::MED_ALL_ELEMENTS);  
   vector<map<int,double> > surfaces = interpolator->interpol_maillages(distant_support,_source_support);
-       delete interpolator;
+  delete interpolator;  
+  if (surfaces.size() != source_size)
+    throw MEDEXCEPTION("uncoherent number of rows in interpolation matrix");
+  
+       //computing the vectors containing the source and target element volumes
+  MEDMEM::SUPPORT target_support(&distant_support,"all cells", MED_EN::MED_CELL);
+  MEDMEM::FIELD<double>* target_triangle_surf = distant_support.getArea(&target_support);
+       MEDMEM::SUPPORT source_support (const_cast<MEDMEM::MESH*>(&_source_support),"all cells", MED_EN::MED_CELL);
+       MEDMEM::FIELD<double>* source_triangle_surf = _source_support.getArea(&source_support);
+
+       //storing the source volumes
+       _source_volume.resize(source_size);
+       for (int i=0; i<source_size;i++)
+               _source_volume[i]=source_triangle_surf->getValueIJ(i+1,1);
+       
+       //loop over the elements to build the interpolation
+       //matrix structures
+  for (int ielem=0; ielem < surfaces.size(); ielem++) 
+    {
+      _row_offsets[ielem+1]+=surfaces[ielem].size();
+      //    _source_indices.push_back(make_pair(iproc_distant, ielem));
+      for (map<int,double>::const_iterator iter=surfaces[ielem].begin();
+                                        iter!=surfaces[ielem].end();
+                                        iter++)
+                               {
+                                       //surface of the target triangle
+                                       double surf = target_triangle_surf->getValueIJ(iter->first,1);
 
+                                       //locating the (iproc, itriangle) pair in the list of columns
+                                       vector<pair<int,int> >::iterator iter2 = find (_col_offsets.begin(), _col_offsets.end(),make_pair(iproc_distant,iter->first));
+                                       int col_id;
+                                       
+                                       
+                                       if (iter2==_col_offsets.end())
+                                               {
+                                                       //(iproc, itriangle) is not registered in the list
+                                                       //of distant elements
 
-  if (surfaces.size() != nbelems)
-    throw MEDEXCEPTION("uncoherent number of rows in interpolation matrix");
+                                                       _col_offsets.push_back(make_pair(iproc_distant,iter->first));
+                                                       col_id =_col_offsets.size();
+                                                       _mapping.addElementFromSource(iproc_distant,distant_elems[iter->first-1]);
+                                                       _target_volume.push_back(surf);
+                                               } 
+                                       else 
+                                               {
+                                                       col_id=iter2-_col_offsets.begin()+1;
+                                               }
 
-  MEDMEM::SUPPORT support(&distant_support,"all cells", MED_EN::MED_CELL);
-  MEDMEM::FIELD<double>* triangle_surf = distant_support.getArea(&support);
+                                       //the non zero coefficient is stored 
+                                       //ielem is the row,
+                                       //col_id is the number of the column
+                                       //iter->second is the value of the coefficient
 
-  for (int ielem=0; ielem < surfaces.size(); ielem++) 
-  {
-    _row_offsets[ielem+1]+=surfaces[ielem].size();
-    //    _source_indices.push_back(make_pair(iproc_distant, ielem));
-    for (map<int,double>::const_iterator iter=surfaces[ielem].begin();
-         iter!=surfaces[ielem].end();
-         iter++)
-         {
-          //surface of the source triangle
-          double surf = triangle_surf->getValueIJ(iter->first,1);
-          //oriented surfaces are not considered
-          surf = (surf>0)?surf:-surf;
-          //locating the (iproc, itriangle) pair in the list of columns
-           vector<pair<int,int> >::iterator iter2 = find (_col_offsets.begin(), _col_offsets.end(),make_pair(iproc_distant,iter->first));
-           int col_id;
-          
-          //(iproc, itriangle) is not registered in the list
-          //of distant elements
-           if (iter2==_col_offsets.end())
-           {
-             _col_offsets.push_back(make_pair(iproc_distant,iter->first));
-             col_id =_col_offsets.size();
-            _mapping.addElementFromSource(iproc_distant,distant_elems[iter->first-1]);
-           } 
-           else 
-           {
-            col_id=iter2-_col_offsets.begin()+1;
-           }
-          //the column indirection number is registered
-          //with the interpolation coefficient
-          //actual column number is obtained with _col_offsets[col_id]
-           _col_numbers.push_back(col_id);
-           _coeffs.push_back(iter->second/surf);
-         }
-  }
-  delete triangle_surf;
+                                       _coeffs[ielem].push_back(make_pair(col_id,iter->second));
+
+                               }
+    }
+  delete source_triangle_surf;
+       delete target_triangle_surf;
 }
-    
-//  intersect (_local_support,_distant_support);
-//  const int* conn_source_index = _local_support->getConnectivityIndex(MED_EN::MED_NODAL,MED_EN::MED_ALL_ELEMENTS);
-//  const int* conn_source = distant_support->getConnectivity(MED_EN::MED_NODAL,MED_EN::MED_ALL_ELEMENTS);
-//  const double* coords_source = _local_support->getCoords(MED_EN::MED_FULL_INTERLACE);
-//  for (int ielem=0; ielem< _local_support->getNumberOfElements(MED_EN::MED_CELL); ielem++)
-//    {
-//      MED_EN::medGeometryElementType type = distant_support->getElementType(ielem);
-//      switch (type)
-//      {
-//
-//        case MED_EN::TRIA3 :
-//          double* coords=new int[3*dim];
-//          for (ielem_distant=0; ielem_distant<distant_support->getNumberOfElements(MED_EN::MED_CELL);ielem_distant++)
-//          {
-//            int ielem_target=*iter;
-//                    
-//            for (int i=0; i<3; i++)
-//              {
-//                int node = conn[conn_source_index[ielem]+i];
-//                for  (int idim=0; i<dim; idim++)
-//                   coords[idim+dim*i]=coords_source[node*dim+idim];
-//              }
-//            double* moments = new double[dim+1];
-//            intersection (target_support, ielem_target, dim, coords,intersection_moments); 
-//          }
-//          
-//          //intersection_moments :
-//          // 0 -> int(1.dV)
-//          // 1 -> int(x.dV)
-//          // 2 -> int(y.dV)
-//          // 3 -> int(z.dV)
-//          if (intersection_moments[0]>0)
-//          {
-//           _source_indices.push_back(make_pair(iproc_distant, ielem);
-//           _col_numbers.push_back(ielem_target);
-//           _row_offsets[irow]++;
-//           _coeffs.push_back(intersection_moments[0]);
-//           for (int i=0; i<dim; i++)
-//              _coeffs.push_back(intersection_moments[i+1]);
-//           _mapping.addElementFromSource(ielem,iproc_distant,ielem_target);
-//           }        
-//      }
-//      irow++;
-//    }  
-//}
+
+/*! The call to this method updates the arrays on the target side
+so that they know which amount of data from which processor they 
+should expect. 
+That call makes actual interpolations via multiply method 
+available.
+*/
 
 void InterpolationMatrix::prepare()
 {
@@ -165,30 +154,107 @@ void InterpolationMatrix::prepare()
   _mapping.prepareSendRecv();
 }
 
+/*!
+  \brief performs t=Ws, where t is the target field, s is the source field
+
+       The call to this method must be called both on the working side 
+and on the idle side. On the working side, the vector  T=VT^(-1).(W.S)
+is computed and sent. On the idle side, no computation is done, but the 
+result from the working side is received and the field is updated.
+
+  \param field source field on processors involved on the source side, target field on processors on the target side
+ */
 void InterpolationMatrix::multiply(MEDMEM::FIELD<double>& field) const
 {
-  double* target_value = new double[_col_offsets.size()* field.getNumberOfComponents()];
-  for (int i=0; i< _col_offsets.size()* field.getNumberOfComponents();i++)
-    {
-      target_value[i]=0.0;
-    }
-  int nbrows=  _source_support.getNumberOfElements(MED_EN::MED_CELL,MED_EN::MED_ALL_ELEMENTS);
-  for (int irow=0; irow<nbrows; irow++)
-  {
-    for (int icol=_row_offsets[irow]; icol< _row_offsets[irow+1];icol++)
-    {
-      for (int icomp=0; icomp<field.getNumberOfComponents(); icomp++)
-       {
-         double coeff_row = field.getValueIJ(irow+1,icomp+1);
-         target_value[_col_numbers[icol]-1]+=_coeffs[icol]*coeff_row;
-       }
-    } 
-  }
-  _mapping.sendRecv(target_value,field);
+  vector<double> target_value(_col_offsets.size()* field.getNumberOfComponents(),0.0);
+
+       //computing the matrix multiply on source side
+       if (_source_group.containsMyRank())
+               {
+                       int nbcomp = field.getNumberOfComponents();
+                       int nbrows=  _source_support.getNumberOfElements(MED_EN::MED_CELL,MED_EN::MED_ALL_ELEMENTS);
+                       
+                       // performing W.S
+                       // W is the intersection matrix
+                       // S is the source vector
+
+                       for (int irow=0; irow<nbrows; irow++)
+                               for (int icomp=0; icomp< nbcomp; icomp++)
+                                       {
+                                               double coeff_row = field.getValueIJ(irow+1,icomp+1);
+                                               for (int icol=_row_offsets[irow]; icol< _row_offsets[irow+1];icol++)
+                                                       {
+                                                               int colid= _coeffs[irow][icol-_row_offsets[irow]].first;
+                                                               double value = _coeffs[irow][icol-_row_offsets[irow]].second;
+                                                               target_value[(colid-1)*nbcomp+icomp]+=value*coeff_row;
+                                                       }
+                                       }
+
+                       // performing VT^(-1).(W.S)
+                       // where VT^(-1) is the inverse of the diagonal matrix  containing 
+                       // the volumes of target cells
+
+                       for (int i=0; i<_col_offsets.size();i++)
+                               for (int icomp=0; icomp<nbcomp; icomp++)
+                                       target_value[i*nbcomp+icomp] /= _target_volume[i];
+               }
+
+       //on source side : sending  T=VT^(-1).(W.S)
+       //on target side :: receiving T and storing it in field
+  _mapping.sendRecv(&target_value[0],field);
   
-  if (_col_offsets.size()>0)
-       delete[] target_value;
 }
-  
+/*!
+  \brief performs s=WTt, where t is the target field, s is the source field, WT is the transpose matrix from W
+
+       The call to this method must be called both on the working side 
+and on the idle side. On the working side, the target vector T is received and the
+ vector  S=VS^(-1).(WT.T) is computed to update the field. 
+On the idle side, no computation is done, but the field is sent.
+
+  \param field source field on processors involved on the source side, target field on processors on the target side
+ */ 
+void InterpolationMatrix::transposeMultiply(MEDMEM::FIELD<double>& field) const
+{
+  vector<double> source_value(_col_offsets.size()* field.getNumberOfComponents(),0.0);
+  _mapping.reverseSendRecv(&source_value[0],field);
+
+       //treatment of the transpose matrix multiply on the source side
+       if (_source_group.containsMyRank())
+               {
+                       int nbcomp = field.getNumberOfComponents();
+                       int nbrows = _source_support.getNumberOfElements(MED_EN::MED_CELL,MED_EN::MED_ALL_ELEMENTS);
+                       
+                       vector<double> target_value(nbrows,0.0);
+
+                       //performing WT.T
+                       //WT is W transpose
+                       //T is the target vector
+                       for (int irow=0; irow<nbrows; irow++)
+                               for (int icol=_row_offsets[irow]; icol< _row_offsets[irow+1];icol++)
+                                       for (int icomp=0; icomp<nbcomp; icomp++)
+                                               {
+                                                       int colid= _coeffs[irow][icol-_row_offsets[irow]].first;
+                                                       double value = _coeffs[irow][icol-_row_offsets[irow]].second;
+
+                                                       double coeff_row = source_value[colid-1];
+                                                       target_value[irow*nbcomp+icomp]+=value*coeff_row;
+                                               }
+                               
+                       //performing VS^(-1).(WT.T)
+                       //VS^(-1) is the inverse of the diagonal matrix storing
+                       //volumes of the source cells
+                       for (int i=0; i<nbrows; i++)
+                               for (int icomp;  icomp<nbcomp; icomp++)
+                                       target_value[i*nbcomp+icomp]/=_source_volume[i];
+                               
+                       //storing S= VS^(-1).(WT.T)
+                       for (int irow=0; irow<nbrows; irow++)
+                               for (int icomp=0; icomp<nbcomp; icomp++)
+                                       field.setValueIJ(irow+1,icomp+1,target_value[irow*nbcomp+icomp]);
+               }
+
+}
+
 
 }
index ac686308cb331b67a3925ab1bfefc701e280f628..599f00be9849fdb76c9006036aa036694af603ae 100644 (file)
@@ -9,7 +9,7 @@ namespace ParaMEDMEM
   class InterpolationMatrix
   {
   public:
-    //InterpolationMatrix();
+    
     InterpolationMatrix(const ParaMEDMEM::ParaMESH& source_support, 
                        const ProcessorGroup& local_group,
                        const ProcessorGroup& distant_group, 
@@ -20,22 +20,24 @@ namespace ParaMEDMEM
     virtual ~InterpolationMatrix();
     void addContribution(MEDMEM::MESH& distant_support, int iproc_distant, int* distant_elems);
     void multiply(MEDMEM::FIELD<double>&) const;
+               void transposeMultiply(MEDMEM::FIELD<double>&)const;
     void prepare();
     int getNbRows() const {return _row_offsets.size();}
     
   private:
     //  vector<pair <int,int> > _source_indices;
     vector<int> _row_offsets;
-    vector<int> _col_numbers;
+    //vector<int> _col_numbers;
     vector<pair<int,int> > _col_offsets;
-    vector<double> _coeffs;
+               //    vector<double> _coeffs;
     const MEDMEM::MESH& _source_support; 
     MxN_Mapping _mapping;
     string _method;
-    const ProcessorGroup& _local_group;
-    const ProcessorGroup& _distant_group;
-    
-    
+    const ProcessorGroup& _source_group;
+    const ProcessorGroup& _target_group;
+    vector<double> _target_volume;
+               vector<double> _source_volume;
+    vector<vector<pair<int,double> > > _coeffs;
   };
   
 }
index 78a15ab71273c1315b8cf55621b7f15730a3e3b6..142ea8d40b7199d4e6a2f6f8c8cadddb8d702400 100644 (file)
@@ -29,85 +29,93 @@ IntersectionDEC::~IntersectionDEC()
 {
   if (_interpolation_matrix !=0)
     delete _interpolation_matrix;
 }
 
 /*! Synchronization process for exchanging topologies
  */
 void IntersectionDEC::synchronize()
 {
-
+       const ParaMEDMEM::ParaMESH* para_mesh = _local_field->getSupport()->getMesh();
+       cout <<"size of Interpolation Matrix"<<sizeof(InterpolationMatrix)<<endl;
+       _interpolation_matrix = new InterpolationMatrix (*para_mesh, *_source_group,*_target_group,"P0"); 
+       
   //setting up the communication DEC on both sides  
-  if (_source_field!=0)
+  if (_source_group->containsMyRank())
     {
-      const ParaMEDMEM::ParaMESH* para_mesh = _source_field->getSupport()->getMesh();
-      _interpolation_matrix = new InterpolationMatrix (*para_mesh, *_source_group,*_target_group,"P0"); 
-     
       //locate the distant meshes
       ElementLocator locator(*para_mesh, *_target_group);
-
+                       
       MESH* distant_mesh=0; 
       int* distant_ids=0;
       for (int i=0; i<_target_group->size(); i++)
-      {
-       //      int idistant_proc = (i+_source_group->myRank())%_target_group->size();
-       int     idistant_proc=i;
-
-        //gathers pieces of the target meshes that can intersect the local mesh
-        locator.exchangeMesh(idistant_proc,distant_mesh,distant_ids);
-
-        if (distant_mesh !=0)
-         {
-           //adds the contribution of the distant mesh on the local one
-           int idistant_proc_in_union=_union_group->translateRank(_target_group,idistant_proc);
-           cout <<"add contribution from proc "<<idistant_proc_in_union<<" to proc "<<_union_group->myRank()<<endl;
-           _interpolation_matrix->addContribution(*distant_mesh,idistant_proc_in_union,distant_ids);
-           
-           delete distant_mesh;
-           delete[] distant_ids;
-           distant_mesh=0;
-           distant_ids=0;
-         }
-      }  
-           
-  }
-
-  if (_target_field!=0)
+                               {
+                                       //      int idistant_proc = (i+_source_group->myRank())%_target_group->size();
+                                       int     idistant_proc=i;
+                                       
+                                       //gathers pieces of the target meshes that can intersect the local mesh
+                                       locator.exchangeMesh(idistant_proc,distant_mesh,distant_ids);
+                                       
+                                       if (distant_mesh !=0)
+                                               {
+                                                       //adds the contribution of the distant mesh on the local one
+                                                       int idistant_proc_in_union=_union_group->translateRank(_target_group,idistant_proc);
+                                                       cout <<"add contribution from proc "<<idistant_proc_in_union<<" to proc "<<_union_group->myRank()<<endl;
+                                                       _interpolation_matrix->addContribution(*distant_mesh,idistant_proc_in_union,distant_ids);
+                                                       
+                                                       delete distant_mesh;
+                                                       delete[] distant_ids;
+                                                       distant_mesh=0;
+                                                       distant_ids=0;
+                                               }
+                               }  
+                       
+               }
+       
+  if (_target_group->containsMyRank())
     {
-      const ParaMEDMEM::ParaMESH* para_mesh = _target_field->getSupport()->getMesh();
-       _interpolation_matrix = new InterpolationMatrix (*para_mesh, *_source_group,*_target_group,"P0"); 
-     
       ElementLocator locator(*para_mesh, *_source_group);
       MESH* distant_mesh=0;
       int* distant_ids=0;
       for (int i=0; i<_source_group->size(); i++)
-      {
-       //      int idistant_proc = (i+_target_group->myRank())%_source_group->size();
-       int  idistant_proc=i;
-        //gathers pieces of the target meshes that can intersect the local mesh
-        locator.exchangeMesh(idistant_proc,distant_mesh,distant_ids);
-       cout << " Data sent from "<<_union_group->myRank()<<" to source proc "<< idistant_proc<<endl;
-        if (distant_mesh!=0)
-         {
-           delete distant_mesh;
-           delete[] distant_ids;
-           distant_mesh=0;
-           distant_ids=0;
-         }
-      }      
-   }
+                               {
+                                       //      int idistant_proc = (i+_target_group->myRank())%_source_group->size();
+                                       int  idistant_proc=i;
+                                       //gathers pieces of the target meshes that can intersect the local mesh
+                                       locator.exchangeMesh(idistant_proc,distant_mesh,distant_ids);
+                                       cout << " Data sent from "<<_union_group->myRank()<<" to source proc "<< idistant_proc<<endl;
+                                       if (distant_mesh!=0)
+                                               {
+                                                       delete distant_mesh;
+                                                       delete[] distant_ids;
+                                                       distant_mesh=0;
+                                                       distant_ids=0;
+                                               }
+                               }      
+               }
   _interpolation_matrix->prepare();
+       //      _volume_vector=para_mesh->getVolume();
+       
 }
 
 
 void IntersectionDEC::recvData()
 {
-  _interpolation_matrix->multiply(*_target_field->getField());
+       if (_source_group->containsMyRank())
+               _interpolation_matrix->transposeMultiply(*_local_field->getField());
+       else if (_target_group->containsMyRank())
+               _interpolation_matrix->multiply(*_local_field->getField());
 }
 
 void IntersectionDEC::sendData()
 {
-    _interpolation_matrix->multiply(*_source_field->getField());
+       if (_source_group->containsMyRank())
+    _interpolation_matrix->multiply(*_local_field->getField());
+       else if (_target_group->containsMyRank())
+               _interpolation_matrix->transposeMultiply(*_local_field->getField());
 }
+
+
        
 }
 
index ae9f6bc3758c82963192f9e5b0f291a990be532d..d4ddf3acd8eb66fa9c34349a1bfb1ac34ca2d333 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef INTERSECTIONDEC_HXX_
 #define INTERSECTIONDEC_HXX_
 
-
 namespace ParaMEDMEM
 {
   class DEC;
@@ -39,6 +38,7 @@ namespace ParaMEDMEM
    string _method;
    
    InterpolationMatrix* _interpolation_matrix;
+
   };
 }
 
index 8dc6fa749e99c220b9f68a5278bb7c3e6d07269d..729f1bd8c860418ceca0dc767a8351caa5680565 100644 (file)
@@ -203,6 +203,7 @@ void MxN_Mapping::sendRecv(double* sendfield, MEDMEM::FIELD<double>& field) cons
   }
   //building the buffer of the elements to be sent
   vector<int> offsets = _send_proc_offsets;
+
   for (int i=0; i<_sending_ids.size();i++)
   { 
     int iproc = _sending_ids[i].first;
@@ -244,5 +245,91 @@ void MxN_Mapping::sendRecv(double* sendfield, MEDMEM::FIELD<double>& field) cons
   
 }
 
+/*! Exchanging field data between two groups of processes
+ * 
+ * \param field MEDMEM field containing the values to be sent
+ * 
+ * The ids that were defined by addElementFromSource method
+ * are sent.
+ */ 
+void MxN_Mapping::reverseSendRecv(double* recvfield, MEDMEM::FIELD<double>& field) const 
+{
+  CommInterface comm_interface=_union_group->getCommInterface();
+  const MPIProcessorGroup* group = static_cast<const MPIProcessorGroup*>(_union_group);
+  int nbcomp=field.getNumberOfComponents();
+  double* sendbuf=0;
+  double* recvbuf=0;
+  if (_recv_ids.size() >0)
+    sendbuf = new double[_recv_ids.size()*nbcomp];
+  if (_sending_ids.size()>0)
+    recvbuf = new double[_sending_ids.size()*nbcomp];
+    
+  int* sendcounts = new int[_union_group->size()];
+  int* senddispls=new int[_union_group->size()];
+  int* recvcounts=new int[_union_group->size()];
+  int* recvdispls=new int[_union_group->size()];
+  
+  for (int i=0; i< _union_group->size(); i++)
+  {
+    sendcounts[i]=nbcomp*(_recv_proc_offsets[i+1]-_recv_proc_offsets[i]);
+    senddispls[i]=nbcomp*(_recv_proc_offsets[i]);
+    recvcounts[i]=nbcomp*(_send_proc_offsets[i+1]-_send_proc_offsets[i]);
+    recvdispls[i]=nbcomp*(_send_proc_offsets[i]);
+  }
+  //building the buffer of the elements to be sent
+  vector<int> offsets = _recv_proc_offsets;
+       
+       for (int iproc=0; iproc<_union_group->size();iproc++)
+               for (int i=_recv_proc_offsets[iproc]; i<_recv_proc_offsets[iproc+1]; i++)
+                       {
+                                       for (int icomp=0; icomp<nbcomp; icomp++)
+                                               sendbuf[i*nbcomp+icomp]=field.getValueIJ(_recv_ids[i],icomp+1);
+                                       //                                      offsets[iproc]++;
+                       }
+  // for (int i=0; i<_recv_ids.size();i++)
+//             { 
+//                     //    int iproc = _recv_ids[i].first;
+//                     int iproc=_recv_ids[i];
+//                     for (int icomp=0; icomp<nbcomp; icomp++)
+//                             //      sendbuf[offsets[iproc]*nbcomp+icomp]=recvfield[i+1*nbcomp+icomp];
+//                             sendbuf[offsets[iproc]*nbcomp+icomp]=field.getValueIJ(i+1,icomp+1);
+//                     offsets[iproc]++;
+//             }
+  
+  //communication phase
+  const MPI_Comm* comm = group->getComm();
+  comm_interface.allToAllV(sendbuf, sendcounts, senddispls, MPI_DOUBLE,
+                           recvbuf, recvcounts, recvdispls, MPI_DOUBLE,
+                           *comm);
+       
+  
+  //setting zero values in the field
+       //   for (int i=0; i< field.getSupport()->getNumberOfElements(MED_EN::MED_ALL_ELEMENTS);i++)
+       //     for (int j=0; j<field.getNumberOfComponents(); j++)
+       //       field.setValueIJ(i+1,j+1,0.0);
+  
+  //setting the received values in the field
+  double* recvptr=recvbuf;                         
+  for (int i=0; i< _send_proc_offsets[_union_group->size()]; i++)
+               {
+                       for (int icomp=0; icomp<nbcomp; icomp++)
+                               {
+                                       //                                      recvfield[(_sending_ids[i].second-1)*nbcomp+icomp]+=*recvptr;
+                                       recvfield[i*nbcomp+icomp]=*recvptr;
+                                       recvptr++;
+                               }  
+               }       
+       
+  
+  if (sendbuf!=0) delete[] sendbuf;
+  if (recvbuf!=0) delete[] recvbuf;
+  delete[] sendcounts;
+  delete[] recvcounts;
+  delete[] senddispls; 
+  delete[] recvdispls;
+  
+}
+
 
 }
index e38360bf3f08c30197cba3f1045b2bd56d1a1031..51136c0ad759520a9883a9220e8674beb3717eda 100644 (file)
@@ -20,6 +20,7 @@ public:
   void prepareSendRecv();
   void sendRecv(MEDMEM::FIELD<double>& field);
   void sendRecv(double* field, MEDMEM::FIELD<double>& field) const ;
+       void reverseSendRecv(double* field, MEDMEM::FIELD<double>& field) const ;
   
 private :
 //  ProcessorGroup& _local_group;