1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "Topology.hxx"
21 #include "BlockTopology.hxx"
22 #include "ComponentTopology.hxx"
23 #include "ExplicitCoincidentDEC.hxx"
24 #include "StructuredCoincidentDEC.hxx"
25 #include "CommInterface.hxx"
26 #include "ProcessorGroup.hxx"
27 #include "MPIProcessorGroup.hxx"
28 #include "ParaFIELD.hxx"
29 #include "ParaMESH.hxx"
30 #include "InterpKernelUtilities.hxx"
31 #include "InterpolationMatrix.hxx"
38 \defgroup parafield ParaFIELD
39 This class encapsulates parallel fields. It basically encapsulates
40 a MEDCouplingField with extra information related to parallel
42 It is most conveniently created by giving a pointer to a MEDCouplingField
43 object and a \c ProcessorGroup.
44 By default, a ParaFIELD object will be constructed with all field components
45 located on the same processors. In some specific cases, it might be necessary to scatter components over several processors. In this case, the constructor
46 using a ComponentTopology is required.
52 \brief Constructing a \c ParaFIELD from a \c ParaSUPPORT and a \c ComponentTopology.
54 This constructor creates an empty field based on the ParaSUPPORT description
55 and the partitioning of components described in \a component_topology.
56 It takes ownership over the \c _field object that it creates.
58 Here come the three ComponentTopology constructors :
60 ComponentTopology c; // one component in the field
61 ComponentTopology c(6); //six components, all of them on the same processor
62 ComponentTopology c(6, proc_group); // six components, evenly distributed over the processors of procgroup
66 ParaFIELD::ParaFIELD(TypeOfField type, TypeOfTimeDiscretization td, ParaMESH* para_support, const ComponentTopology& component_topology)
68 _component_topology(component_topology),_topology(0),_own_support(false),
69 _support(para_support)
71 if (para_support->isStructured() || (para_support->getTopology()->getProcGroup()->size()==1 && component_topology.nbBlocks()!=1))
73 const BlockTopology* source_topo = dynamic_cast<const BlockTopology*>(para_support->getTopology());
74 _topology=new BlockTopology(*source_topo,component_topology);
78 if (component_topology.nbBlocks()!=1 && para_support->getTopology()->getProcGroup()->size()!=1)
79 throw INTERP_KERNEL::Exception(LOCALIZED("ParaFIELD constructor : Unstructured Support not taken into account with component topology yet"));
82 const BlockTopology* source_topo=dynamic_cast<const BlockTopology*> (para_support->getTopology());
83 int nb_local_comp=component_topology.nbLocalComponents();
84 _topology=new BlockTopology(*source_topo,nb_local_comp);
87 int nb_components = component_topology.nbLocalComponents();
90 _field=MEDCouplingFieldDouble::New(type,td);
91 _field->setMesh(_support->getCellMesh());
92 DataArrayDouble *array=DataArrayDouble::New();
93 array->alloc(_field->getNumberOfTuples(),nb_components);
94 _field->setArray(array);
99 _field->setName("Default ParaFIELD name");
100 _field->setDescription("Default ParaFIELD description");
103 /*! \brief Constructor creating the ParaFIELD
104 from a given FIELD and a processor group.
106 This constructor supposes that support underlying \a subdomain_field has no ParaSUPPORT
107 attached and it therefore recreates one. It therefore takes ownership over _support. The component topology associated with the field is a basic one (all components on the same processor).
109 ParaFIELD::ParaFIELD(MEDCouplingFieldDouble* subdomain_field, ParaMESH *sup, const ProcessorGroup& proc_group):
110 _field(subdomain_field),
111 _component_topology(ComponentTopology(_field->getNumberOfComponents())),_topology(0),_own_support(false),
116 const BlockTopology* source_topo=dynamic_cast<const BlockTopology*> (_support->getTopology());
117 _topology=new BlockTopology(*source_topo,_component_topology.nbLocalComponents());
120 ParaFIELD::~ParaFIELD()
129 void ParaFIELD::synchronizeTarget(ParaFIELD* source_field)
131 DisjointDEC* data_channel;
132 if (dynamic_cast<BlockTopology*>(_topology)!=0)
134 data_channel=new StructuredCoincidentDEC;
138 data_channel=new ExplicitCoincidentDEC;
140 data_channel->attachLocalField(this);
141 data_channel->synchronize();
142 data_channel->prepareTargetDE();
143 data_channel->recvData();
148 void ParaFIELD::synchronizeSource(ParaFIELD* target_field)
150 DisjointDEC* data_channel;
151 if (dynamic_cast<BlockTopology*>(_topology)!=0)
153 data_channel=new StructuredCoincidentDEC;
157 data_channel=new ExplicitCoincidentDEC;
159 data_channel->attachLocalField(this);
160 data_channel->synchronize();
161 data_channel->prepareSourceDE();
162 data_channel->sendData();
168 * This method returns, if it exists, an array with only one component and as many as tuples as _field has.
169 * This array gives for every element on which this->_field lies, its global number, if this->_field is nodal.
170 * For example if _field is a nodal field : returned array will be the nodal global numbers.
171 * The content of this method is used to inform Working side to accumulate data recieved by lazy side.
173 DataArrayInt* ParaFIELD::returnCumulativeGlobalNumbering() const
177 TypeOfField type=_field->getTypeOfField();
183 return _support->getGlobalNumberingNodeDA();
189 DataArrayInt* ParaFIELD::returnGlobalNumbering() const
193 TypeOfField type=_field->getTypeOfField();
197 return _support->getGlobalNumberingCellDA();
199 return _support->getGlobalNumberingNodeDA();
205 int ParaFIELD::nbComponents() const
207 return _component_topology.nbComponents();
211 /*! This method retrieves the integral of component \a icomp
212 over the all domain. */
213 double ParaFIELD::getVolumeIntegral(int icomp, bool isWAbs) const
215 CommInterface comm_interface = _topology->getProcGroup()->getCommInterface();
216 double integral=_field->integral(icomp,isWAbs);
218 const MPI_Comm* comm = (dynamic_cast<const MPIProcessorGroup*>(_topology->getProcGroup()))->getComm();
219 comm_interface.allReduce(&integral, &total, 1, MPI_DOUBLE, MPI_SUM, *comm);