Salome HOME
Various fixes for test runs - introducing MEDCOUPLING_RESOURCE_DIR env variable
[tools/medcoupling.git] / src / ParaMEDMEM / OverlapDEC.cxx
1 // Copyright (C) 2007-2020  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "OverlapDEC.hxx"
22 #include "CommInterface.hxx"
23 #include "ParaMESH.hxx"
24 #include "ParaFIELD.hxx"
25 #include "MPIProcessorGroup.hxx"
26 #include "OverlapElementLocator.hxx"
27 #include "OverlapInterpolationMatrix.hxx"
28 #include "ICoCoMEDField.hxx"
29
30 namespace MEDCoupling
31 {
32   OverlapDEC::OverlapDEC(const std::set<int>& procIds, const MPI_Comm& world_comm):
33       _load_balancing_algo(1),
34       _own_group(true),_interpolation_matrix(0), _locator(0),
35       _default_field_value(0.0),
36       _source_field(0),_own_source_field(false),
37       _target_field(0),_own_target_field(false),
38       _comm(MPI_COMM_NULL)
39   {
40     MEDCoupling::CommInterface comm;
41     int *ranks_world=new int[procIds.size()]; // ranks of sources and targets in world_comm
42     std::copy(procIds.begin(),procIds.end(),ranks_world);
43     MPI_Group group,world_group;
44     comm.commGroup(world_comm,&world_group);
45     comm.groupIncl(world_group,(int)procIds.size(),ranks_world,&group);
46     delete [] ranks_world;
47     comm.commCreate(world_comm,group,&_comm);
48     comm.groupFree(&group);
49     comm.groupFree(&world_group);
50     if(_comm==MPI_COMM_NULL)
51       {
52         _group=0;
53         return ;
54       }
55     std::set<int> idsUnion;
56     for(unsigned int i=0;i<procIds.size();i++)
57       idsUnion.insert(i);
58     _group=new MPIProcessorGroup(comm,idsUnion,_comm);
59   }
60
61   OverlapDEC::~OverlapDEC()
62   {
63     if(_own_group)
64       delete _group;
65     if(_own_source_field)
66       delete _source_field;
67     if(_own_target_field)
68       delete _target_field;
69     delete _interpolation_matrix;
70     delete _locator;
71     if (_comm != MPI_COMM_NULL)
72       {
73         MEDCoupling::CommInterface comm;
74         comm.commFree(&_comm);
75       }
76   }
77
78   void OverlapDEC::sendRecvData(bool way)
79   {
80     if(way)
81       sendData();
82     else
83       recvData();
84   }
85
86   void OverlapDEC::sendData()
87   {
88     _interpolation_matrix->multiply(_default_field_value);
89   }
90
91   void OverlapDEC::recvData()
92   {
93     throw INTERP_KERNEL::Exception("Not implemented yet !!!!");
94     //_interpolation_matrix->transposeMultiply();
95   }
96   
97   void OverlapDEC::synchronize()
98   {
99     if(!isInGroup())
100       return ;
101     // Check number of components of field on both side (for now allowing void field/mesh on one proc is not allowed)
102     if (!_source_field || !_source_field->getField())
103       throw INTERP_KERNEL::Exception("OverlapDEC::synchronize(): currently, having a void source field on a proc is not allowed!");
104     if (!_target_field || !_target_field->getField())
105       throw INTERP_KERNEL::Exception("OverlapDEC::synchronize(): currently, having a void target field on a proc is not allowed!");
106     if (_target_field->getField()->getNumberOfComponents() != _source_field->getField()->getNumberOfComponents())
107       throw INTERP_KERNEL::Exception("OverlapDEC::synchronize(): source and target field have different number of components!");
108     delete _interpolation_matrix;
109     _locator = new OverlapElementLocator(_source_field,_target_field,*_group, getBoundingBoxAdjustmentAbs(), _load_balancing_algo);
110     _interpolation_matrix=new OverlapInterpolationMatrix(_source_field,_target_field,*_group,*this,*this, *_locator);
111     _locator->copyOptions(*this);
112     _locator->exchangeMeshes(*_interpolation_matrix);
113     std::vector< std::pair<int,int> > jobs=_locator->getToDoList();
114     std::string srcMeth=_locator->getSourceMethod();
115     std::string trgMeth=_locator->getTargetMethod();
116     for(std::vector< std::pair<int,int> >::const_iterator it=jobs.begin();it!=jobs.end();it++)
117       {
118         const MEDCouplingPointSet *src=_locator->getSourceMesh((*it).first);
119         const DataArrayIdType *srcIds=_locator->getSourceIds((*it).first);
120         const MEDCouplingPointSet *trg=_locator->getTargetMesh((*it).second);
121         const DataArrayIdType *trgIds=_locator->getTargetIds((*it).second);
122         _interpolation_matrix->computeLocalIntersection(src,srcIds,srcMeth,(*it).first,trg,trgIds,trgMeth,(*it).second);
123       }
124     _interpolation_matrix->prepare(_locator->getProcsToSendFieldData());
125     _interpolation_matrix->computeSurfacesAndDeno();
126   }
127
128   void OverlapDEC::attachSourceLocalField(ParaFIELD *field, bool ownPt)
129   {
130     if(!isInGroup())
131       return ;
132     if(_own_source_field)
133       delete _source_field;
134     _source_field=field;
135     _own_source_field=ownPt;
136   }
137
138   void OverlapDEC::attachTargetLocalField(ParaFIELD *field, bool ownPt)
139   {
140     if(!isInGroup())
141       return ;
142     if(_own_target_field)
143       delete _target_field;
144     _target_field=field;
145     _own_target_field=ownPt;
146   }
147
148   void OverlapDEC::attachSourceLocalField(MEDCouplingFieldDouble *field)
149   {
150     if(!isInGroup())
151       return ;
152
153     ParaMESH *paramesh = new ParaMESH(static_cast<MEDCouplingPointSet *>(const_cast<MEDCouplingMesh *>(field->getMesh())),
154                                       *_group,field->getMesh()->getName());
155     ParaFIELD *tmpField=new ParaFIELD(field, paramesh, *_group);
156     tmpField->setOwnSupport(true);
157     attachSourceLocalField(tmpField,true);
158   }
159
160   void OverlapDEC::attachTargetLocalField(MEDCouplingFieldDouble *field)
161   {
162     if(!isInGroup())
163       return ;
164
165     ParaMESH *paramesh = new ParaMESH(static_cast<MEDCouplingPointSet *>(const_cast<MEDCouplingMesh *>(field->getMesh())),
166                                       *_group,field->getMesh()->getName());
167     ParaFIELD *tmpField=new ParaFIELD(field, paramesh, *_group);
168     tmpField->setOwnSupport(true);
169     attachTargetLocalField(tmpField,true);
170   }
171
172   void OverlapDEC::attachSourceLocalField(ICoCo::MEDField *field)
173   {
174     attachSourceLocalField(field->getField());
175   }
176
177   void OverlapDEC::attachTargetLocalField(ICoCo::MEDField *field)
178   {
179     attachTargetLocalField(field->getField());
180   }
181
182   bool OverlapDEC::isInGroup() const
183   {
184     if(!_group)
185       return false;
186     return _group->containsMyRank();
187   }
188
189   void OverlapDEC::debugPrintWorkSharing(std::ostream & ostr) const
190   {
191     _locator->debugPrintWorkSharing(ostr);
192   }
193 }