Line data Source code
1 : // Copyright (C) 2015 Technische Universitaet Muenchen
2 : // This file is part of the Mamico project. For conditions of distribution
3 : // and use, please see the copyright notice in Mamico's main folder, or at
4 : // www5.in.tum.de/mamico
5 : #ifndef _MOLECULARDYNAMICS_SERVICES_PARALLELANDLOCALBUFFERSERVICE_H_
6 : #define _MOLECULARDYNAMICS_SERVICES_PARALLELANDLOCALBUFFERSERVICE_H_
7 :
8 : #include "simplemd/MolecularDynamicsDefinitions.h"
9 : #include "simplemd/Molecule.h"
10 : #include <cmath>
11 : #include <cstdlib>
12 : #include <iostream>
13 :
14 : /** Class for managing buffers for sending messages between processors and
15 : * "local" buffer for managing periodic boundary conditions, which need
16 : * to be handled locally
17 : *
18 : * @author Nikola Tchipev
19 : */
20 : namespace simplemd {
21 : namespace services {
22 : class ParallelAndLocalBufferService {
23 : public:
24 : // We want a class for managing buffers, but we don't want
25 : // that class to exist out of the ParallelAndLocalBufferService
26 : // so we use a nested class
27 :
28 : // ========================= //
29 : // nested class SimpleBuffer //
30 : // ========================= //
31 :
32 : /** Class that mimics an stl vector, but is guaranteed to be
33 : * contiguous in memory, a requirement for MPI calls.
34 : *
35 : * @author Nikola Tchipev
36 : */
37 : class SimpleBuffer {
38 : public:
39 : SimpleBuffer();
40 : ~SimpleBuffer();
41 :
42 : /** allocate storage */
43 : bool initialise(const unsigned int doublesPerMolecule, const unsigned int upperBoundOnNumberOfMolecules);
44 :
45 : void shutdown();
46 :
47 : /** push data (molecule) into local or send buffer
48 : * if _capacity was not exceeded by pushing
49 : * or if reallocation was permitted (for local buffers),
50 : * function returns true
51 : * otherwise - false
52 : */
53 : bool pushData(const tarch::la::Vector<MD_DIM, double> position, const tarch::la::Vector<MD_DIM, double> velocity,
54 : const tarch::la::Vector<MD_DIM, double> force, const double isFixed, const bool permitReallocation);
55 :
56 : /** clear buffer values for use at next iteration
57 : * capacity is preserved
58 : */
59 : void clearBuffer() { _length = 0; };
60 :
61 : void setLength(const unsigned int len) { _length = len; }
62 :
63 : unsigned int getLength() const { return _length; }
64 : unsigned int getCapacity() const { return _capacity; }
65 : double* getValues() const { return _values; }
66 :
67 : private:
68 : /* METHODS */
69 :
70 : /** double the capacity */
71 : bool reallocate();
72 :
73 : /* FIELDS */
74 :
75 : /** the values */
76 : double* _values;
77 :
78 : /** the number of values currently stored */
79 : unsigned int _length;
80 :
81 : /** allocated capacity */
82 : unsigned int _capacity;
83 : };
84 :
85 : // ========================= //
86 : // end of class SimpleBuffer //
87 : // ========================= //
88 :
89 : public:
90 : ParallelAndLocalBufferService() {}
91 9540 : ~ParallelAndLocalBufferService() {}
92 :
93 : /** allocate all necessary buffers
94 : * return false if allocation of a buffer fails
95 : */
96 : bool initialise(const unsigned int numUniqueNeighbours, const unsigned int numCellsPerBuffer[], const double avMoleculesPerCell);
97 :
98 : void shutdown();
99 :
100 : bool pushMoleculeToLocalBuffer(const tarch::la::Vector<MD_DIM, double>& position, const Molecule* mol);
101 :
102 : unsigned int getLocalBufferLength(unsigned int i_buf) const { return _localBuffer.getLength(); }
103 :
104 : SimpleBuffer* getLocalBuffer() { return &_localBuffer; }
105 :
106 : #if (MD_PARALLEL == MD_YES)
107 : bool pushMoleculeToSendBuffer(const tarch::la::Vector<MD_DIM, double>& position, const Molecule* mol, const unsigned int i_buffer);
108 :
109 : unsigned int getBufferCapacity(unsigned int i_buf) const { return _sendBuffers[i_buf].getCapacity(); }
110 : unsigned int getSendBufferLength(unsigned int i_buf) const { return _sendBuffers[i_buf].getLength(); }
111 : SimpleBuffer* getSendBuffer(const unsigned int& i_buf) { return &(_sendBuffers[i_buf]); }
112 : SimpleBuffer* getReceiveBuffer(const unsigned int& i_buf) { return &(_receiveBuffers[i_buf]); }
113 :
114 : void setReceiveBufferLength(const unsigned int i_buf, const unsigned int count) { _receiveBuffers[i_buf].setLength(count); };
115 : #endif
116 :
117 : private:
118 : /* Methods */
119 :
120 : /** method that calculates upper bound on number of molecules to be stored in the respective buffer.
121 : * Determined from average number of molecules per linked cell, number of cells to be transferred
122 : * via respective buffer and a special function A:
123 : * upperBound[bufferIndex] = ceil(numCells[bufferIndex] * avMolPerCell * A(numCells[bufferIndex]))
124 : *
125 : * The purpose of this function A is to deal with the following:
126 : * when we send only one linked cell to a process, the probability that the average number of molecules is exceeded is
127 : * high, whereas, when we send thousands of cells, the probability that the average number of molecules is exceeded in all
128 : * of them is much lower. We also need to keep buffer size low, so we choose the function A to satisfy the following:
129 : * 1. A: N -> R
130 : * 2. A(1) is "high", in our choice, A(1) = 5.5
131 : * 3. lim_{k to Inf} A(k) is "low", in our choice lim_{k to Inf} A(k) = 1.5
132 : * 4. A - monotonically decreasing
133 : *
134 : */
135 : unsigned int computeBufferUpperBound(const unsigned int numCells, const double avMoleculesPerCell) const;
136 :
137 : /* Fields */
138 :
139 : /**
140 : * buffer needed for handling local periodic boundaries in
141 : * broadcast-broadcast methods. Reallocation is permitted.
142 : */
143 : SimpleBuffer _localBuffer;
144 :
145 : #if (MD_PARALLEL == MD_YES)
146 : unsigned int _numberActiveParallelBuffers;
147 :
148 : /** buffers for sending (only _numberActiveParallelBuffers will be used)
149 : * Reallocation is not permitted. It means the upper bound on number
150 : * of molecules was exceeded, causing termination.
151 : */
152 : SimpleBuffer _sendBuffers[MD_LINKED_CELL_NEIGHBOURS];
153 :
154 : /** buffers for receiving (only _numberActiveParallelBuffers will be used)
155 : * Reallocation is not permitted. It means the upper bound on number
156 : * of molecules was exceeded, causing termination.
157 : */
158 : SimpleBuffer _receiveBuffers[MD_LINKED_CELL_NEIGHBOURS];
159 : #endif
160 : };
161 : } // namespace services
162 : } // namespace simplemd
163 :
164 : #endif
|