From 03e8943fe476623aee299e538093b059aeeb3b86 Mon Sep 17 00:00:00 2001 From: vbd Date: Fri, 4 Jan 2008 15:48:05 +0000 Subject: [PATCH] fixing StructuredCoincidentDEC improving comments --- src/ParaMEDMEM/ComponentTopology.cxx | 12 ++++ src/ParaMEDMEM/ComponentTopology.hxx | 2 + src/ParaMEDMEM/ExplicitCoincidentDEC.cxx | 5 +- src/ParaMEDMEM/IntersectionDEC.cxx | 2 +- src/ParaMEDMEM/NonCoincidentDEC.cxx | 3 - src/ParaMEDMEM/ParaFIELD.cxx | 46 ++++++++++-- src/ParaMEDMEM/ParaFIELD.hxx | 2 +- src/ParaMEDMEM/ParaSUPPORT.cxx | 7 ++ src/ParaMEDMEM/ParaSUPPORT.hxx | 2 + src/ParaMEDMEM/StructuredCoincidentDEC.cxx | 83 +++++++++++++++++++--- src/ParaMEDMEM/StructuredCoincidentDEC.hxx | 11 +-- src/ParaMEDMEM/UnstructuredParaSUPPORT.hxx | 1 + 12 files changed, 149 insertions(+), 27 deletions(-) diff --git a/src/ParaMEDMEM/ComponentTopology.cxx b/src/ParaMEDMEM/ComponentTopology.cxx index d3d8e920b..c95b6e9e4 100644 --- a/src/ParaMEDMEM/ComponentTopology.cxx +++ b/src/ParaMEDMEM/ComponentTopology.cxx @@ -79,4 +79,16 @@ int ComponentTopology::nbLocalComponents() const{ nbcomp=0; return nbcomp; } + +int ComponentTopology::firstLocalComponent() const{ + if (_proc_group==0) return 0; + + int icomp; + int myrank = _proc_group->myRank(); + if (myrank!=-1) + icomp = component_array[myrank]; + else + icomp=-1; + return icomp; +} } diff --git a/src/ParaMEDMEM/ComponentTopology.hxx b/src/ParaMEDMEM/ComponentTopology.hxx index e2c2463c2..f509c8d2d 100644 --- a/src/ParaMEDMEM/ComponentTopology.hxx +++ b/src/ParaMEDMEM/ComponentTopology.hxx @@ -20,6 +20,8 @@ public: int nbComponents() const {return component_array[component_array.size()-1];} //!returns the number of MED components on local processor int nbLocalComponents() const ; + //!returns the number of the first MED component on local processor + int firstLocalComponent() const ; //!returns the number of blocks in the topology int nbBlocks()const {return component_array.size()-1;} //!returns the block structure diff --git a/src/ParaMEDMEM/ExplicitCoincidentDEC.cxx b/src/ParaMEDMEM/ExplicitCoincidentDEC.cxx index 61a3f930e..d0aeb9976 100644 --- a/src/ParaMEDMEM/ExplicitCoincidentDEC.cxx +++ b/src/ParaMEDMEM/ExplicitCoincidentDEC.cxx @@ -61,8 +61,6 @@ void ExplicitCoincidentDEC::prepareSourceDE() return; MPIProcessorGroup* group=new MPIProcessorGroup(_sourcegroup->getCommInterface()); - int myranksource = _sourcegroup->myRank(); - // Warning : the size of the target side is implicitly deduced //from the size of MPI_COMM_WORLD int target_size = _toposource->getProcGroup()->getCommInterface().worldSize()- _toposource->getProcGroup()->size() ; @@ -203,7 +201,6 @@ void ExplicitCoincidentDEC::broadcastTopology(const ExplicitTopology* toposend, else { vector size (group->size()); - int myrank=toporecv->getProcGroup()->myRank(); int myworldrank=group->myRank(); for (int iproc=0; iprocsize();iproc++) { @@ -342,7 +339,7 @@ void ExplicitCoincidentDEC::recvData() cout<<"end AllToAll"<getNbLocalElements(); double* value=new double[nb_local*_topotarget->getNbComponents()]; - int myranktarget=_topotarget->getProcGroup()->myRank(); + vector counters(_sourcegroup->size()); counters[0]=0; for (int i=0; i<_sourcegroup->size()-1; i++) diff --git a/src/ParaMEDMEM/IntersectionDEC.cxx b/src/ParaMEDMEM/IntersectionDEC.cxx index abcfe6848..2eed43952 100644 --- a/src/ParaMEDMEM/IntersectionDEC.cxx +++ b/src/ParaMEDMEM/IntersectionDEC.cxx @@ -58,7 +58,7 @@ In the P0-P0 case, this matrix is a plain rectangular matrix with coefficients e 0 & 0 & 0.92 & 0.05 \\ \end{tabular} \f] -*/ + * \section intersectiondec_options Options diff --git a/src/ParaMEDMEM/NonCoincidentDEC.cxx b/src/ParaMEDMEM/NonCoincidentDEC.cxx index f71b04988..abc455fbc 100644 --- a/src/ParaMEDMEM/NonCoincidentDEC.cxx +++ b/src/ParaMEDMEM/NonCoincidentDEC.cxx @@ -264,7 +264,6 @@ void NonCoincidentDEC::synchronize() MEDMEM::MESH* mesh = _local_field->getField()->getSupport()->getMesh(); fvm_nodal_t* source_nodal = ParaMEDMEM::medmemMeshToFVMMesh(mesh); - const ProcessorGroup* proc_group = _local_field->getTopology()->getProcGroup(); int target_size = _target_group->size() ; int start_rank= _source_group->size(); //const MPI_Comm* comm = (dynamic_cast (_source_group))->getComm(); @@ -311,8 +310,6 @@ void NonCoincidentDEC::synchronize() nbcells, NULL, coords); - int nb_internal_points= fvm_locator_get_n_interior(_locator); - int nb_exterior_points= fvm_locator_get_n_exterior(_locator); } } diff --git a/src/ParaMEDMEM/ParaFIELD.cxx b/src/ParaMEDMEM/ParaFIELD.cxx index a088303b6..cd81617a1 100644 --- a/src/ParaMEDMEM/ParaFIELD.cxx +++ b/src/ParaMEDMEM/ParaFIELD.cxx @@ -15,17 +15,41 @@ using namespace MEDMEM; + namespace ParaMEDMEM { - /*! Constructing a \c ParaFIELD from a \c ParaSUPPORT and a \c ComponentTopology. - This constructor creates an empty field based on the ParaSUPPORT description + +/*! +\defgroup parafield ParaFIELD +This class encapsulates parallel fields. It basically encapsulates +a MEDMEM::FIELD with extra information related to parallel +topology. +It is most conveniently created by giving a pointer to a MEDMEM::FIELD +object and a \c ProcessorGroup. +By default, a ParaFIELD object will be constructed with all field components +located on the same processors. In some specific cases, it might be necessary to scatter components over several processors. In this case, the constructor +using a ComponentTopology is required. + +@{ */ + +/*! + +\brief Constructing a \c ParaFIELD from a \c ParaSUPPORT and a \c ComponentTopology. + +This constructor creates an empty field based on the ParaSUPPORT description and the partitioning of components described in \a component_topology. It takes ownership over the \c _field object that it creates. - - */ +Here come the three ComponentTopology constructors : +\verbatim +ComponentTopology c; // one component in the field +ComponentTopology c(6); //six components, all of them on the same processor +ComponentTopology c(6, proc_group); // six components, evenly distributed over the processors of procgroup +\endverbatim + +*/ ParaFIELD::ParaFIELD(const ParaSUPPORT* para_support, const ComponentTopology& component_topology) :_support(para_support), _component_topology(component_topology), @@ -89,12 +113,13 @@ ParaFIELD::ParaFIELD(const ParaSUPPORT* para_support, const ComponentTopology& c delete[] compunit; } -/*! Constructor creating the ParaFIELD +/*! \brief Constructor creating the ParaFIELD from a given FIELD and a processor group. This constructor supposes that support underlying \a subdomain_field has no ParaSUPPORT -attached and it therefore recreates one. It therefore takes ownership over _support. +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). */ + ParaFIELD::ParaFIELD(MEDMEM::FIELD* subdomain_field, const ProcessorGroup& proc_group): _field(subdomain_field), _support(new UnstructuredParaSUPPORT(subdomain_field->getSupport(), proc_group)), @@ -120,6 +145,10 @@ ParaFIELD::~ParaFIELD() } + /*! writes the contents of the field in MED v2.3 file \a filename : +- \c filename is the name of the master file +- files containing the subdomains are named \c filename1.med, \c filename2.med, etc... + */ void ParaFIELD::write(MEDMEM::driverTypes driverType, const string& fileName, const string& meshName){ // Topology* topo = dynamic_cast (_topology); int myrank = _topology->getProcGroup()->myRank(); @@ -166,6 +195,8 @@ void ParaFIELD::synchronizeSource(ParaFIELD* target_field){ delete data_channel; } + /*! This method retrieves the integral of component \a icomp + over the all domain. */ double ParaFIELD::getVolumeIntegral(int icomp) const { CommInterface comm_interface = _topology->getProcGroup()->getCommInterface(); @@ -206,4 +237,7 @@ For 3D geometries, the returned field contains the volumes. throw MEDMEM::MEDEXCEPTION("interpolation is not available for this dimension"); } } + +/*! @} */ } + diff --git a/src/ParaMEDMEM/ParaFIELD.hxx b/src/ParaMEDMEM/ParaFIELD.hxx index f9a69404e..2fcd5356b 100644 --- a/src/ParaMEDMEM/ParaFIELD.hxx +++ b/src/ParaMEDMEM/ParaFIELD.hxx @@ -22,7 +22,7 @@ class ParaFIELD { public: - ParaFIELD(const ParaMEDMEM::ParaSUPPORT* support, const ParaMEDMEM::ComponentTopology& component_topology); + ParaFIELD(const ParaSUPPORT* support, const ComponentTopology& component_topology); ParaFIELD(MEDMEM::driverTypes driver_type, const string& file_name, const string& driver_name, const ComponentTopology& component_topology) diff --git a/src/ParaMEDMEM/ParaSUPPORT.cxx b/src/ParaMEDMEM/ParaSUPPORT.cxx index fb6570a78..d7b4b0c7b 100644 --- a/src/ParaMEDMEM/ParaSUPPORT.cxx +++ b/src/ParaMEDMEM/ParaSUPPORT.cxx @@ -25,5 +25,12 @@ namespace ParaMEDMEM delete _mesh; } + const int* ParaSUPPORT::getGlobalNumbering() const + { + if (! _support->isOnAllElements()) + throw MEDMEM::MEDEXCEPTION("GlobalNumbering can only be retrieved on supports on all elements"); + return _mesh->getGlobalNumbering(_support->getEntity()); + } + } diff --git a/src/ParaMEDMEM/ParaSUPPORT.hxx b/src/ParaMEDMEM/ParaSUPPORT.hxx index 404305de9..87c8d4264 100644 --- a/src/ParaMEDMEM/ParaSUPPORT.hxx +++ b/src/ParaMEDMEM/ParaSUPPORT.hxx @@ -23,6 +23,8 @@ namespace ParaMEDMEM virtual const Topology* getTopology() const =0; virtual const MEDMEM::SUPPORT* getSupport() const {return _support;} virtual const ParaMESH* getMesh() const {return _mesh;} + virtual const int* getGlobalNumbering() const; + protected : const MEDMEM::SUPPORT* _support; diff --git a/src/ParaMEDMEM/StructuredCoincidentDEC.cxx b/src/ParaMEDMEM/StructuredCoincidentDEC.cxx index a175854d4..77f2c6aa2 100644 --- a/src/ParaMEDMEM/StructuredCoincidentDEC.cxx +++ b/src/ParaMEDMEM/StructuredCoincidentDEC.cxx @@ -7,6 +7,50 @@ #include "MPIProcessorGroup.hxx" #include "StructuredCoincidentDEC.hxx" + +/*! \defgroup structuredcoincidentdec StructuredCoincidentDEC + +This class is meant for remapping fields that have identical +supports with different parallel topologies. It can be used to couple + together multiphysics codes that operate on the same domain + with different partitionings, which can be useful if one of + the computation is much faster than the other. It can also be used +to couple together codes that share an interface that was generated + in the same manner (with identical global ids). +Also, this DEC can be used for fields that have component topologies, +i.e., components that are scattered over several processors. + +The remapping between the two supports is based on identity of global + ids, instead of geometrical considerations as it is the case for + NonCoincidentDEC and IntersectionDEC. Therefore, this DEC must not be used +for coincident meshes that do not have the same numbering. + +As all the other DECs, its use is made of two phases : +- a setup phase during whih the topologies are exchanged so that + the target side knows from which processors it should expect + the data. +- a send/recv phase during which the field data is actually transferred. + +This example illustrates the sending of a field with +the DEC : +\code +... +StructuredCoincidentDEC dec(groupA, groupB); +dec.attachLocalField(field); +dec.synchronize(); +if (groupA.containsMyRank()) + dec.recvData(); +else if (groupB.containsMyRank()) + dec.sendData(); +... +\endcode + +Creating a ParaFIELD to be attached to the DEC is exactly the same as for +other DECs in the case when the remapping concerns similar meshes +that only have different partitionings. In the case when the + fields have also different component topologies, creating the ParaFIELD +requires some more effort. See \ref parafield section for more details. +*/ namespace ParaMEDMEM { @@ -19,10 +63,13 @@ StructuredCoincidentDEC::~StructuredCoincidentDEC() { } +StructuredCoincidentDEC::StructuredCoincidentDEC(ProcessorGroup& local_group, ProcessorGroup& distant_group):DEC(local_group,distant_group),_toposource(0),_topotarget(0) +{ +} /*! Synchronization process for exchanging topologies */ -void StructuredCoincidentDEC::synchronize() +void StructuredCoincidentDEC::synchronizeTopology() { if (_source_group->containsMyRank()) _toposource = dynamic_cast(_local_field->getTopology()); @@ -33,7 +80,9 @@ void StructuredCoincidentDEC::synchronize() broadcastTopology(_toposource,1000); // Transmitting target topology to source code broadcastTopology(_topotarget,2000); - //checkCompatibility(_toposource,_topotarget); + if (_toposource->getNbElements() != _topotarget->getNbElements()) + throw MEDEXCEPTION("Incompatible dimensions for target and source topologies"); + } /*! Creates the arrays necessary for the data transfer @@ -244,8 +293,9 @@ void StructuredCoincidentDEC::recvData() cout <(_union_group)->getComm()); _comm_interface->allToAllV(_sendbuffer, _sendcounts, _senddispls, MPI_DOUBLE, - _recvbuffer, _recvcounts, _recvdispls, MPI_DOUBLE,MPI_COMM_WORLD); + _recvbuffer, _recvcounts, _recvdispls, MPI_DOUBLE,comm); cout<<"end AllToAll"<getNbLocalElements(); @@ -280,15 +330,32 @@ void StructuredCoincidentDEC::sendData() for (int i=0; i< 4; i++) cout << _senddispls[i]<<" "; cout <(_union_group)->getComm()); _comm_interface->allToAllV(_sendbuffer, _sendcounts, _senddispls, MPI_DOUBLE, - _recvbuffer, _recvcounts, _recvdispls, MPI_DOUBLE,MPI_COMM_WORLD); + _recvbuffer, _recvcounts, _recvdispls, MPI_DOUBLE,comm); cout<<"end AllToAll"<containsMyRank()) + { + synchronizeTopology(); + prepareSourceDE(); + } + else if (_target_group->containsMyRank()) + { + synchronizeTopology(); + prepareTargetDE(); + } +} } diff --git a/src/ParaMEDMEM/StructuredCoincidentDEC.hxx b/src/ParaMEDMEM/StructuredCoincidentDEC.hxx index 4231124e0..736b36442 100644 --- a/src/ParaMEDMEM/StructuredCoincidentDEC.hxx +++ b/src/ParaMEDMEM/StructuredCoincidentDEC.hxx @@ -13,15 +13,18 @@ class StructuredCoincidentDEC: public DEC { public: StructuredCoincidentDEC(); + StructuredCoincidentDEC( ProcessorGroup& source, ProcessorGroup& target); virtual ~StructuredCoincidentDEC(); void synchronize(); - void broadcastTopology(BlockTopology*&, int tag); - void prepareSourceDE(); - void prepareTargetDE(); void recvData(); void sendData(); + void prepareSourceDE(); + void prepareTargetDE(); + private : - + void synchronizeTopology(); + void broadcastTopology(BlockTopology*&, int tag); + BlockTopology* _toposource; BlockTopology* _topotarget; int* _sendcounts; diff --git a/src/ParaMEDMEM/UnstructuredParaSUPPORT.hxx b/src/ParaMEDMEM/UnstructuredParaSUPPORT.hxx index e5b1d232d..f9d93b9ce 100644 --- a/src/ParaMEDMEM/UnstructuredParaSUPPORT.hxx +++ b/src/ParaMEDMEM/UnstructuredParaSUPPORT.hxx @@ -30,6 +30,7 @@ namespace ParaMEDMEM virtual ~UnstructuredParaSUPPORT(); const Topology* UnstructuredParaSUPPORT::getTopology() const {return _explicit_topology;} + private: const Topology* _explicit_topology; const MED_EN::medEntityMesh _entity; -- 2.39.2