MercuryDPM  Trunk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MpiContainer.cc
Go to the documentation of this file.
1 //Copyright (c) 2013-2020, The MercuryDPM Developers Team. All rights reserved.
2 //For the list of developers, see <http://www.MercuryDPM.org/Team>.
3 //
4 //Redistribution and use in source and binary forms, with or without
5 //modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name MercuryDPM nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 //ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 //WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 //DISCLAIMED. IN NO EVENT SHALL THE MERCURYDPM DEVELOPERS TEAM BE LIABLE FOR ANY
19 //DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 //(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 //ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 //(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 #include "MpiContainer.h"
27 #include "Logger.h"
28 
29 #ifdef MERCURY_USE_MPI
30 #include <mpi.h>
33 #include "Particles/BaseParticle.h"
34 #include "MpiDataClass.h"
35 #endif
36 
37 #include "SpeciesHandler.h"
38 #include "GeneralDefine.h"
39 
44 {
45 #ifdef MERCURY_USE_MPI
46  if(!MPI::Is_initialized())
47  {
48  logger(FATAL,"MPI should be initialised before calling the MPIContainer constructor");
49  }
50  //A personal communicator will be created to ensure we don't meddle with communicators of other libraries
51  MPI::Group groupID = MPI::COMM_WORLD.Get_group();
52  communicator_ = MPI::COMM_WORLD.Create( groupID );
53  processorID_ = communicator_.Get_rank();
54  numberOfProcessors_ = communicator_.Get_size();
55 #else
57  processorID_ = 0;
58 #endif
59 }
60 
61 /*
62  * \brief Initialises MercuryMPIType MPITypes
63  * \details This function intialises five different Mercury data types that have to
64  * be send over the MPI interface. Most of the data types are just structs containing the raw
65  * required data. The interaction data type however is a very complex datatype
66  * as it can vary over every simulation what type of interaction is set.
67  * Currently it is only possible to have one type of interaction in the MPI (and that should be sufficient)
68  * \param[in] speciesHandler Handles all the species, required to create a prototype interaction
69  */
71 {
72 #ifdef MERCURY_USE_MPI
73  //Note: Important that the MPI type creation is done in the order given by the enum
74  MPIParticle dummyParticle;
75  MPIParticlePosition dummyPosition;
76  MPIParticleVelocity dummyVelocity;
77  MPIParticleForce dummyForce;
82 
83  //Obtain the correct history force class
84  //NOTE: only works for one type of interaction
85  if (dataTypes_.size() == 4)
86  {
87  //Create a dummy interaction to get a grip on the size of the MPI interaction class
88  const BaseSpecies* species = speciesHandler.getObject(0);
89  BaseInteraction* emptyInteraction = species->getEmptyInteraction();
90  emptyInteraction->createMPIType();
91  species->deleteEmptyInteraction(emptyInteraction);
92  }
93 #endif
94 }
95 
101 {
102  return numberOfProcessors_;
103 }
104 
110 {
111  return processorID_;
112 }
113 
114 
115 #ifdef MERCURY_USE_MPI
116 
123 MPI::Intracomm& MPIContainer::getComm()
124 {
125  return communicator_;
126 }
127 
128 #endif
129 
134 {
135 #ifdef MERCURY_USE_MPI
136  //Check if MPI is already initialised
137  if (!MPI::Is_initialized())
138  {
139  MPI::Init();
140  MPIContainer& communicator = MPIContainer::Instance();
141  if (PROCESSOR_ID == 0)
142  {
143  std::cout << "MPI has been initialised" << std::endl;
144  }
145 
146  //MPI should be finalised at the end of any program.
147  std::atexit([]()
148  {
149  MPIContainer& communicator = MPIContainer::Instance();
150  communicator.deleteMercuryMPITypes();
151  MPI::Finalize();
152  if (PROCESSOR_ID == 0)
153  {
154  std::cout << "MPI has been finalised" << std::endl;
155  }
156  });
157  }
158 #endif
159 }
160 
Container to store all ParticleSpecies.
This class contains all information and functions required for communication between processors...
Definition: MpiContainer.h:125
virtual void deleteEmptyInteraction(BaseInteraction *interaction) const =0
static MPIContainer & Instance()
fetch the instance to be used for communication
Definition: MpiContainer.h:130
void initialiseMercuryMPITypes(const SpeciesHandler &speciesHandler)
Creates the MPI types required for communication of Mercury data through the MPI interface.
Definition: MpiContainer.cc:70
BaseSpecies is the class from which all other species are derived.
Definition: BaseSpecies.h:49
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
Data class to send a particle velocity over MPI.
Definition: MpiDataClass.h:102
std::size_t processorID_
The ID of the processor this class is running on.
Definition: MpiContainer.h:590
std::size_t getNumberOfProcessors() const
Get the total number of processors participating in this simulation.
virtual void createMPIType()
void initialiseMPI()
Inialises the MPI library.
Stores information about interactions between two interactable objects; often particles but could be ...
MPIContainer()
Constructor.
Definition: MpiContainer.cc:43
std::size_t getProcessorID()
Reduces a scalar on all processors to one scalar on a target processor.
T * getObject(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:613
Data class to send a particle over MPI.
Definition: MpiDataClass.h:81
virtual BaseInteraction * getEmptyInteraction() const =0
#define PROCESSOR_ID
Definition: GeneralDefine.h:63
void deleteMercuryMPITypes()
Deletes the MercuryMPITypes.
Definition: MpiContainer.h:565
Data class to send a particle position over MPI.
Definition: MpiDataClass.h:89
void createMercuryMPIType(T t, MercuryMPIType type)
Get the communicator used for MPI commands.
Definition: MpiContainer.h:551
Data class to send a particle force over MPI.
Definition: MpiDataClass.h:113
std::size_t numberOfProcessors_
The total number of processors in the communicator.
Definition: MpiContainer.h:595