LCOV - code coverage report
Current view: top level - coupling/indexing - IndexingService.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 23 79 29.1 %
Date: 2025-06-25 11:26:37 Functions: 4 13 30.8 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : // parallel topologies
       4             : #include "coupling/CouplingMDDefinitions.h"
       5             : #include "coupling/paralleltopology/ParallelTopology.h"
       6             : #include "coupling/paralleltopology/ParallelTopologyFactory.h"
       7             : 
       8             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
       9             : #include <mpi.h>
      10             : #endif
      11             : 
      12             : namespace coupling {
      13             : namespace indexing {
      14             : 
      15             : template <unsigned int dim> class IndexingService;
      16             : 
      17             : }
      18             : } // namespace coupling
      19             : 
      20             : // Include CellIndex template class definition
      21             : #include "coupling/indexing/IndexTypes.h"
      22             : 
      23             : namespace coupling {
      24             : namespace indexing {
      25             : 
      26             : template <unsigned int dim> std::vector<unsigned int> getRanksForGlobalIndex(const BaseIndex<dim>& globalCellIndex, unsigned int topologyOffset);
      27             : 
      28             : } // namespace indexing
      29             : } // namespace coupling
      30             : 
      31             : // Include non-member functions operating on indexes
      32             : #include "Operations.h"
      33             : 
      34             : class IndexingServiceTest;
      35             : 
      36             : /**
      37             :  * Singleton service class initialising lower and upper boundaries of all
      38             :  * possible CellIndex specialisations.
      39             :  *
      40             :  * @tparam dim number of dimensions of the coupled simulation
      41             :  * @param simpleMDConfig config object of SimpleMD instance used in coupling
      42             :  * @param mamicoConfig config object containg general information of coupling
      43             :  * process
      44             :  * @param outer region
      45             :  *
      46             :  * @author Felix Maurer
      47             :  */
      48         184 : template <unsigned int dim> class coupling::indexing::IndexingService {
      49             : public:
      50    14295443 :   static IndexingService& getInstance() {
      51    14295627 :     static IndexingService singleton{};
      52    14295443 :     return singleton;
      53             :   }
      54             : 
      55         748 :   void initWithCells(tarch::la::Vector<dim, unsigned int> globalNumberCouplingCells, tarch::la::Vector<dim, unsigned int> numberProcesses,
      56             :                      coupling::paralleltopology::ParallelTopologyType parallelTopologyType, unsigned int outerRegion, const unsigned int rank
      57             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
      58             :                      ,
      59             :                      MPI_Comm comm = MPI_COMM_WORLD
      60             : #endif
      61             :   ) {
      62             :     // regular grid
      63        2992 :     tarch::la::Vector<dim, std::vector<unsigned int>> subdomainWeights;
      64        2992 :     for (unsigned int i = 0; i < dim; i++) {
      65        2244 :       subdomainWeights[i].reserve(numberProcesses[i]);
      66        6156 :       for (unsigned int j = 0; j < numberProcesses[i]; j++) {
      67        3912 :         subdomainWeights[i].push_back(1);
      68             :       }
      69             :     }
      70        1496 :     initWithCells(subdomainWeights, globalNumberCouplingCells, numberProcesses, parallelTopologyType, outerRegion, rank
      71             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
      72             :                   ,
      73             :                   comm
      74             : #endif
      75             :     );
      76         744 :   }
      77             : 
      78             :   void initWithCells(const tarch::la::Vector<dim, std::vector<unsigned int>>& subdomainWeights, tarch::la::Vector<dim, unsigned int> globalNumberCouplingCells,
      79             :                      tarch::la::Vector<dim, unsigned int> numberProcesses, coupling::paralleltopology::ParallelTopologyType parallelTopologyType,
      80             :                      unsigned int outerRegion, const unsigned int rank
      81             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
      82             :                      ,
      83             :                      MPI_Comm comm = MPI_COMM_WORLD
      84             : #endif
      85             :   );
      86             : 
      87           0 :   void initWithMDSize(const tarch::la::Vector<3, double>& globalMDDomainSize, const tarch::la::Vector<3, double>& globalMDDomainOffset,
      88             :                       const tarch::la::Vector<3, unsigned int>& mdNumberProcesses, const tarch::la::Vector<3, double>& couplingCellSize,
      89             :                       coupling::paralleltopology::ParallelTopologyType parallelTopologyType, unsigned int outerRegion, unsigned int rank
      90             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
      91             :                       ,
      92             :                       MPI_Comm comm = MPI_COMM_WORLD
      93             : #endif
      94             :   ) {
      95             :     // regular grid
      96           0 :     tarch::la::Vector<dim, std::vector<unsigned int>> subdomainWeights;
      97           0 :     for (unsigned int i = 0; i < dim; i++) {
      98           0 :       subdomainWeights[i].reserve(mdNumberProcesses[i]);
      99           0 :       for (unsigned int j = 0; j < mdNumberProcesses[i]; j++) {
     100           0 :         subdomainWeights[i].push_back(1);
     101             :       }
     102             :     }
     103             : 
     104           0 :     initWithMDSize(subdomainWeights, globalMDDomainSize, globalMDDomainOffset, mdNumberProcesses, couplingCellSize, parallelTopologyType, outerRegion, rank
     105             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
     106             :                    ,
     107             :                    comm
     108             : #endif
     109             :     );
     110           0 :   }
     111           0 :   void initWithMDSize(const tarch::la::Vector<dim, std::vector<unsigned int>>& subdomainWeights, const tarch::la::Vector<3, double>& globalMDDomainSize,
     112             :                       const tarch::la::Vector<3, double>& globalMDDomainOffset, const tarch::la::Vector<3, unsigned int>& mdNumberProcesses,
     113             :                       const tarch::la::Vector<3, double>& couplingCellSize, coupling::paralleltopology::ParallelTopologyType parallelTopologyType,
     114             :                       unsigned int outerRegion, unsigned int rank
     115             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
     116             :                       ,
     117             :                       MPI_Comm comm = MPI_COMM_WORLD
     118             : #endif
     119             :   ) {
     120           0 :     _globalMDDomainSize = globalMDDomainSize;
     121           0 :     _globalMDDomainOffset = globalMDDomainOffset;
     122           0 :     _couplingCellSize = couplingCellSize;
     123           0 :     _initedWithMDSize = true;
     124             : 
     125             :     // calculate total number of coupling cells on all ranks in Base Domain
     126           0 :     tarch::la::Vector<dim, unsigned int> globalNumberCouplingCells(0);
     127           0 :     for (unsigned int d = 0; d < dim; d++) {
     128           0 :       globalNumberCouplingCells[d] = (unsigned int)floor(globalMDDomainSize[d] / couplingCellSize[d] + 0.5);
     129             : 
     130           0 :       if (fabs((globalNumberCouplingCells[d]) * couplingCellSize[d] - globalMDDomainSize[d]) > 1e-13)
     131           0 :         std::cout << "IndexingService: Deviation of domain size > 1e-13!" << std::endl;
     132             :     }
     133             : 
     134           0 :     initWithCells(subdomainWeights, globalNumberCouplingCells, mdNumberProcesses, parallelTopologyType, outerRegion, rank
     135             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
     136             :                   ,
     137             :                   comm
     138             : #endif
     139             :     );
     140           0 :   }
     141             : 
     142         732 :   void finalize() {
     143             : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     144         732 :     _isInitialized = false;
     145             : #endif
     146           0 :   }
     147             : 
     148             :   /**
     149             :    * Determines all ranks that contain a certain global BaseIndex.
     150             :    * Ripped from deprecated IndexConversion.
     151             :    *
     152             :    * @param globalCellIndex index to be looked up
     153             :    * @param globalNumberCouplingCells global number of cells in BaseIndex
     154             :    * domain EXCLUDING global ghost layer cells.
     155             :    * @returns vector of all cells which contain the index
     156             :    */
     157             :   std::vector<unsigned int> getRanksForGlobalIndex(const BaseIndex<dim>& globalCellIndex, unsigned int topologyOffset) const;
     158             : 
     159             :   unsigned int getUniqueRankForCouplingCell(const BaseIndex<dim>& globalCellIndex, unsigned int topologyOffset) const;
     160             : 
     161             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES) // parallel scenario
     162        1535 :   MPI_Comm getComm() const {
     163             : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     164        1535 :     if (!_isInitialized) {
     165           8 :       throw std::runtime_error(std::string("IndexingService: Called index system getComm() before initialization! "));
     166             :     }
     167             : #endif
     168             : 
     169        1531 :     return _comm;
     170             :   }
     171             : #endif
     172             : 
     173         188 :   unsigned int getRank() const {
     174             : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     175         188 :     if (!_isInitialized) {
     176           8 :       throw std::runtime_error(std::string("IndexingService: Called index system getRank() before initialization! "));
     177             :     }
     178             : #endif
     179             : 
     180         184 :     return _rank;
     181             :   }
     182             : 
     183             : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     184    14292236 :   bool isInitialized() const { return _isInitialized; }
     185             : #endif
     186             : 
     187             :   /** returns the global domain size of the MD domain (excl. ghost layer which
     188             :    * naturally is not part of MD).
     189             :    *  @returns the total size of the md simulation domain (dimensional) */
     190           0 :   tarch::la::Vector<dim, double> getGlobalMDDomainSize() const {
     191             : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     192           0 :     if (!_isInitialized) {
     193           0 :       throw std::runtime_error(std::string("IndexingService: Called getGlobalMDDomainSize() before initalization! "));
     194             :     }
     195           0 :     if (!_initedWithMDSize) {
     196           0 :       throw std::runtime_error(std::string("IndexingService: Called getGlobalMDDomainSize() without calling initWithMDSize()! "));
     197             :     }
     198             : #endif
     199           0 :     return _globalMDDomainSize;
     200             :   }
     201             : 
     202             :   /** @brief returns the offset, i.e. the lower,left... corner coordinate, of
     203             :    * the MD domain.
     204             :    *  @returns the offset of the MD domain */
     205           0 :   tarch::la::Vector<dim, double> getGlobalMDDomainOffset() const {
     206             : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     207           0 :     if (!_isInitialized) {
     208           0 :       throw std::runtime_error(std::string("IndexingService: Called getGlobalMDDomainOffset() before initalization! "));
     209             :     }
     210           0 :     if (!_initedWithMDSize) {
     211           0 :       throw std::runtime_error(std::string("IndexingService: Called getGlobalMDDomainOffset() without calling initWithMDSize()! "));
     212             :     }
     213             : #endif
     214           0 :     return _globalMDDomainOffset;
     215             :   }
     216             : 
     217             :   /** @brief returns the vector size of each coupling cell.
     218             :    *  @returns the size of the coupling cells (dimensional) */
     219           0 :   tarch::la::Vector<dim, double> getCouplingCellSize() const {
     220             : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     221           0 :     if (!_isInitialized) {
     222           0 :       throw std::runtime_error(std::string("IndexingService: Called getCouplingCellSize() before initalization! "));
     223             :     }
     224           0 :     if (!_initedWithMDSize) {
     225           0 :       throw std::runtime_error(std::string("IndexingService: Called getCouplingCellSize() without calling initWithMDSize()! "));
     226             :     }
     227             : #endif
     228           0 :     return _couplingCellSize;
     229             :   }
     230             : 
     231           0 :   unsigned int getScalarNumberProcesses() const {
     232             : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     233           0 :     if (!_isInitialized) {
     234           0 :       throw std::runtime_error(std::string("IndexingService: Called getScalarNumberProcesses() before initalization! "));
     235             :     }
     236             : #endif
     237           0 :     return _scalarNumberProcesses;
     238             :   }
     239             : 
     240           0 :   BaseIndex<dim> getCellIndex(tarch::la::Vector<dim, double> position) const {
     241             : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     242           0 :     if (!_isInitialized) {
     243           0 :       throw std::runtime_error(std::string("IndexingService: Called getCellIndex() before initalization! "));
     244             :     }
     245           0 :     if (!_initedWithMDSize) {
     246           0 :       throw std::runtime_error(std::string("IndexingService: Called getCellIndex() without calling initWithMDSize()! "));
     247             :     }
     248             : #endif
     249             : 
     250           0 :     tarch::la::Vector<dim, int> res_raw;
     251           0 :     for (unsigned int d = 0; d < dim; d++) {
     252           0 :       const double buf = position[d] - (_globalMDDomainOffset[d] - _couplingCellSize[d]);
     253           0 :       res_raw[d] = buf / _couplingCellSize[d];
     254             :     }
     255             : 
     256           0 :     BaseIndex<dim> res{res_raw};
     257             : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     258           0 :     if (!BaseIndex<dim>::contains(res)) {
     259           0 :       throw std::runtime_error(std::string("IndexingService::getCellIndex(): Invalid conversion!"));
     260             :     }
     261             : #endif
     262           0 :     return res;
     263             :   }
     264             : 
     265             : private:
     266             :   unsigned int getUniqueRankForCouplingCell(tarch::la::Vector<dim, unsigned int> globalCellIndex,
     267             :                                             const tarch::la::Vector<dim, unsigned int>& globalNumberCouplingCells, unsigned int topologyOffset) const;
     268             : 
     269             :   /*const*/ tarch::la::Vector<dim, unsigned int> _numberProcesses; // TODO: make const
     270             :   unsigned int _scalarNumberProcesses;
     271             :   const coupling::paralleltopology::ParallelTopology<dim>* _parallelTopology;
     272             : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES) // parallel scenario
     273             :   MPI_Comm _comm;
     274             : #endif
     275             :   unsigned int _rank;
     276             : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     277             :   bool _isInitialized = false;
     278             : #endif
     279             :   bool _initedWithMDSize = false;
     280             :   tarch::la::Vector<dim, std::vector<unsigned int>> _subdomainOwnership;
     281             :   tarch::la::Vector<dim, double> _globalMDDomainSize;
     282             :   tarch::la::Vector<dim, double> _globalMDDomainOffset;
     283             :   tarch::la::Vector<dim, double> _couplingCellSize;
     284             :   coupling::paralleltopology::ParallelTopologyType _parallelTopologyType;
     285             :   friend IndexingServiceTest;
     286             : };

Generated by: LCOV version 1.14