LCOV - code coverage report
Current view: top level - simplemd/services - ParallelAndLocalBufferService.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 1 1
Test Date: 2026-08-21 15:14:06 Functions: 100.0 % 1 1

            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
        

Generated by: LCOV version 2.0-1