-// 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 "OverlapDEC.hxx"
#include "CommInterface.hxx"
+#include "ParaMESH.hxx"
#include "ParaFIELD.hxx"
#include "MPIProcessorGroup.hxx"
#include "OverlapElementLocator.hxx"
#include "OverlapInterpolationMatrix.hxx"
+#include "ICoCoMEDField.hxx"
-namespace ParaMEDMEM
+namespace MEDCoupling
{
/*!
\anchor OverlapDEC-det
\class OverlapDEC
+ \section OverlapDEC-over Overview
+
The \c OverlapDEC enables the \ref InterpKerRemapGlobal "conservative remapping" of fields between
two parallel codes. This remapping is based on the computation of intersection volumes on
- a \b same \b processor \b group. On this processor group are defined two field-templates called A
+ a \b single \b processor \b group. On this processor group are defined two field-templates called A
and B. The computation is possible for 3D meshes, 2D meshes, 3D-surface meshes, 1D meshes and
2D-curve meshes. Dimensions must be similar for the distribution templates A and B.
- The main difference with \ref InterpKernelDEC-det is that this \ref para-dec "DEC" manages 2 field templates
- on each processor of the processor group (A and B) called source and target.
- Furthermore all processors in processor group cooperates in global interpolation matrix
- computation. In this respect \ref InterpKernelDEC is a specialization of \c OverlapDEC.
- \section ParaMEDMEMOverlapDECAlgorithmDescription Algorithm Description
+ The main difference with \ref InterpKernelDEC-det "InterpKernelDEC" is that this
+ \ref para-dec "DEC" works with a *single* processor group, in which processors will share the work.
+ Consequently each processor manages two \ref MEDCouplingFieldTemplatesPage "field templates" (A and B)
+ called source and target.
+ Furthermore all processors in the processor group cooperate in the global interpolation matrix
+ computation. In this respect \c InterpKernelDEC is a specialization of \c OverlapDEC.
+
+ \section ParaMEDMEMOverlapDECAlgorithmDescription Algorithm description
Let's consider the following use case that is ran in ParaMEDMEMTest_OverlapDEC.cxx to describes
the different steps of the computation. The processor group contains 3 processors.
\anchor ParaMEDMEMOverlapDECImgTest1
- \image html OverlapDEC1.png "Example showing the use case in order to explain the different steps."
+ \image html OverlapDEC1.png "Example split of the source and target mesh among the 3 procs"
- \subsection ParaMEDMEMOverlapDECAlgoStep1 Step 1 : Bounding box exchange and global interaction
- between procs computation.
+ \subsection ParaMEDMEMOverlapDECAlgoStep1 Step 1 : Bounding box exchange and global interaction between procs computation.
In order to reduce as much as possible the amount of communications between distant processors,
every processor computes a bounding box for A and B. Then a AllToAll communication is performed
Here the pair (0,2) does not appear because the bounding box of fieldtemplateA of proc#2 does
not intersect that of fieldtemplate B on proc#0.
- Stage performed by ParaMEDMEM::OverlapElementLocator::computeBoundingBoxes.
+ Stage performed by MEDCoupling::OverlapElementLocator::computeBoundingBoxes.
\subsection ParaMEDMEMOverlapDECAlgoStep2 Step 2 : Computation of local TODO list
keep track of the ids sent to proc \#m for te matrix-vector computation.
This is incarnated by OverlapMapping::keepTracksOfSourceIds in proc k.
- This step is performed in ParaMEDMEM::OverlapElementLocator::exchangeMeshes method.
+ This step is performed in MEDCoupling::OverlapElementLocator::exchangeMeshes method.
\subsection ParaMEDMEMOverlapDECAlgoStep4 Step 4 : Computation of the interpolation matrix
the \b local TODO list per proc is expected to
be as well balanced as possible.
- The interpolation is performed as \ref ParaMEDMEM::MEDCouplingRemapper "Remapper" does.
+ The interpolation is performed as the \ref MEDCoupling::MEDCouplingRemapper "remapper" does.
This operation is performed by OverlapInterpolationMatrix::addContribution method.
is equal to k.
After this step, the matrix repartition is the following after a call to
- ParaMEDMEM::OverlapMapping::prepare :
+ MEDCoupling::OverlapMapping::prepare :
- proc\#0 : (0,0),(1,0),(2,0)
- proc\#1 : (0,1),(2,1)
"prepare". This is an example of item 0 in \ref ParaMEDMEMOverlapDECAlgoStep2 "Step2".
Tuple (0,1) computed on proc 1 is stored in proc 1 too. This is an example of item 1 in \ref ParaMEDMEMOverlapDECAlgoStep2 "Step2".
- In the end ParaMEDMEM::OverlapMapping::_proc_ids_to_send_vector_st will contain :
+ In the end MEDCoupling::OverlapMapping::_proc_ids_to_send_vector_st will contain :
- Proc\#0 : 0,1
- Proc\#1 : 0,2
- Proc\#2 : 0,1,2
- In the end ParaMEDMEM::OverlapMapping::_proc_ids_to_recv_vector_st will contain :
+ In the end MEDCoupling::OverlapMapping::_proc_ids_to_recv_vector_st will contain :
- Proc\#0 : 0,1,2
- Proc\#1 : 0,2
- Proc\#2 : 1,2
- The method in charge to perform this is : ParaMEDMEM::OverlapMapping::prepare.
+ The method in charge to perform this is : MEDCoupling::OverlapMapping::prepare.
*/
OverlapDEC::OverlapDEC(const std::set<int>& procIds, const MPI_Comm& world_comm):
- _own_group(true),_interpolation_matrix(0),
+ _load_balancing_algo(1),
+ _own_group(true),_interpolation_matrix(0), _locator(0),
_source_field(0),_own_source_field(false),
_target_field(0),_own_target_field(false),
+ _default_field_value(0.0),
_comm(MPI_COMM_NULL)
{
- ParaMEDMEM::CommInterface comm;
+ MEDCoupling::CommInterface comm;
int *ranks_world=new int[procIds.size()]; // ranks of sources and targets in world_comm
std::copy(procIds.begin(),procIds.end(),ranks_world);
MPI_Group group,world_group;
if(_own_target_field)
delete _target_field;
delete _interpolation_matrix;
+ delete _locator;
if (_comm != MPI_COMM_NULL)
{
- ParaMEDMEM::CommInterface comm;
+ MEDCoupling::CommInterface comm;
comm.commFree(&_comm);
}
}
void OverlapDEC::sendData()
{
- _interpolation_matrix->multiply();
+ _interpolation_matrix->multiply(_default_field_value);
}
void OverlapDEC::recvData()
{
if(!isInGroup())
return ;
+ // Check number of components of field on both side (for now allowing void field/mesh on one proc is not allowed)
+ if (!_source_field || !_source_field->getField())
+ throw INTERP_KERNEL::Exception("OverlapDEC::synchronize(): currently, having a void source field on a proc is not allowed!");
+ if (!_target_field || !_target_field->getField())
+ throw INTERP_KERNEL::Exception("OverlapDEC::synchronize(): currently, having a void target field on a proc is not allowed!");
+ if (_target_field->getField()->getNumberOfComponents() != _source_field->getField()->getNumberOfComponents())
+ throw INTERP_KERNEL::Exception("OverlapDEC::synchronize(): source and target field have different number of components!");
delete _interpolation_matrix;
- _interpolation_matrix=new OverlapInterpolationMatrix(_source_field,_target_field,*_group,*this,*this);
- OverlapElementLocator locator(_source_field,_target_field,*_group);
- locator.copyOptions(*this);
- locator.exchangeMeshes(*_interpolation_matrix);
- std::vector< std::pair<int,int> > jobs=locator.getToDoList();
- std::string srcMeth=locator.getSourceMethod();
- std::string trgMeth=locator.getTargetMethod();
+ _locator = new OverlapElementLocator(_source_field,_target_field,*_group, getBoundingBoxAdjustmentAbs(), _load_balancing_algo);
+ _interpolation_matrix=new OverlapInterpolationMatrix(_source_field,_target_field,*_group,*this,*this, *_locator);
+ _locator->copyOptions(*this);
+ _locator->exchangeMeshes(*_interpolation_matrix);
+ std::vector< std::pair<int,int> > jobs=_locator->getToDoList();
+ std::string srcMeth=_locator->getSourceMethod();
+ std::string trgMeth=_locator->getTargetMethod();
for(std::vector< std::pair<int,int> >::const_iterator it=jobs.begin();it!=jobs.end();it++)
{
- const MEDCouplingPointSet *src=locator.getSourceMesh((*it).first);
- const DataArrayInt *srcIds=locator.getSourceIds((*it).first);
- const MEDCouplingPointSet *trg=locator.getTargetMesh((*it).second);
- const DataArrayInt *trgIds=locator.getTargetIds((*it).second);
- _interpolation_matrix->addContribution(src,srcIds,srcMeth,(*it).first,trg,trgIds,trgMeth,(*it).second);
+ const MEDCouplingPointSet *src=_locator->getSourceMesh((*it).first);
+ const DataArrayInt *srcIds=_locator->getSourceIds((*it).first);
+ const MEDCouplingPointSet *trg=_locator->getTargetMesh((*it).second);
+ const DataArrayInt *trgIds=_locator->getTargetIds((*it).second);
+ _interpolation_matrix->computeLocalIntersection(src,srcIds,srcMeth,(*it).first,trg,trgIds,trgMeth,(*it).second);
}
- _interpolation_matrix->prepare(locator.getProcsInInteraction());
- _interpolation_matrix->computeDeno();
+ _interpolation_matrix->prepare(_locator->getProcsToSendFieldData());
+ _interpolation_matrix->computeSurfacesAndDeno();
}
void OverlapDEC::attachSourceLocalField(ParaFIELD *field, bool ownPt)
_own_target_field=ownPt;
}
+ void OverlapDEC::attachSourceLocalField(MEDCouplingFieldDouble *field)
+ {
+ if(!isInGroup())
+ return ;
+
+ ParaMESH *paramesh = new ParaMESH(static_cast<MEDCouplingPointSet *>(const_cast<MEDCouplingMesh *>(field->getMesh())),
+ *_group,field->getMesh()->getName());
+ ParaFIELD *tmpField=new ParaFIELD(field, paramesh, *_group);
+ tmpField->setOwnSupport(true);
+ attachSourceLocalField(tmpField,true);
+ }
+
+ void OverlapDEC::attachTargetLocalField(MEDCouplingFieldDouble *field)
+ {
+ if(!isInGroup())
+ return ;
+
+ ParaMESH *paramesh = new ParaMESH(static_cast<MEDCouplingPointSet *>(const_cast<MEDCouplingMesh *>(field->getMesh())),
+ *_group,field->getMesh()->getName());
+ ParaFIELD *tmpField=new ParaFIELD(field, paramesh, *_group);
+ tmpField->setOwnSupport(true);
+ attachTargetLocalField(tmpField,true);
+ }
+
+ void OverlapDEC::attachSourceLocalField(ICoCo::MEDField *field)
+ {
+ attachSourceLocalField(field->getField());
+ }
+
+ void OverlapDEC::attachTargetLocalField(ICoCo::MEDField *field)
+ {
+ attachTargetLocalField(field->getField());
+ }
+
bool OverlapDEC::isInGroup() const
{
if(!_group)
return false;
return _group->containsMyRank();
}
+
+ void OverlapDEC::debugPrintWorkSharing(std::ostream & ostr) const
+ {
+ _locator->debugPrintWorkSharing(ostr);
+ }
}