LCOV - code coverage report
Current view: top level - coupling/indexing - IndexingService.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 29.1 % 79 23
Test Date: 2026-08-21 15:14:06 Functions: 30.8 % 13 4

            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     14295560 :   static IndexingService& getInstance() {
      51     14295560 :     static IndexingService singleton{};
      52     14295560 :     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          748 :     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         1652 :   MPI_Comm getComm() const {
     163              : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     164         1652 :     if (!_isInitialized) {
     165            8 :       throw std::runtime_error(std::string("IndexingService: Called index system getComm() before initialization! "));
     166              :     }
     167              : #endif
     168              : 
     169         1648 :     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 2.0-1