LCOV - code coverage report
Current view: top level - coupling - InstanceHandling.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.5 % 88 77
Test Date: 2026-08-21 15:14:06 Functions: 100.0 % 13 13

            Line data    Source code
       1              : // Copyright (C) 2016 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 _INSTANCE_HANDLING_H_
       6              : #define _INSTANCE_HANDLING_H_
       7              : 
       8              : #include "coupling/interface/MDSimulationFactory.h"
       9              : #include "coupling/services/MultiMDCellService.h"
      10              : #include "tarch/utils/MultiMDService.h"
      11              : 
      12              : namespace coupling {
      13              : template <class LinkedCell, unsigned int dim> class InstanceHandling;
      14              : }
      15              : class InstanceHandlingTest;
      16              : 
      17              : /** holds one vector of MDSimulation and one vector for MDSolverInterface.
      18              :  *Initialization, execution of MD time steps and shutdown are abstracted into
      19              :  *this class. In order to launch a new MF simulatio, a slot has to be chosen
      20              :  *first (either manualy or using coupling::MultiMDMediator). Then
      21              :  *MultiMDCellService initializes a new CouplingCellService via
      22              :  *MultiMDMediator. In the activated slot, a new MD simulation is launched. The
      23              :  *new MD instance has to be equilibrated first and then it can be coupled to the
      24              :  *simulation. In order to remove a MD simulation, the MD simulation and its
      25              :  *corresponding MDSolverInterface are shut down. Then, the respective instance
      26              :  *of the CouplingCellService is removed. Finally, the selected slot will be
      27              :  *set to inactive. This slot is now available again for the launch of a new MD
      28              :  *instance in the future.
      29              :  *      @brief Simulation slots are managed (i.e., added/removed) via this
      30              :  *class. Works and interacts with the class coupling::MultiMDMediator closely.
      31              :  *      @tparam LinkedCell type of the cell
      32              :  *      @tparam dim Number of dimensions; it can be 1, 2 or 3
      33              :  *      @sa see also coupling::MultiMDMediator
      34              :  *  @author Niklas Wittmer
      35              :  */
      36              : template <class LinkedCell, unsigned int dim> class coupling::InstanceHandling {
      37              : 
      38              : public:
      39              :   /** Constructor:
      40              :    *    @param mdConfig
      41              :    *    @param mamicoConfig
      42              :    *    @param multiMDService
      43              :    */
      44            4 :   InstanceHandling(simplemd::configurations::MolecularDynamicsConfiguration& mdConfig, coupling::configurations::MaMiCoConfiguration<dim>& mamicoConfig,
      45              :                    tarch::utils::MultiMDService<dim>& multiMDService)
      46            4 :       : _mdSimulations(), _mdSolverInterface(), _mdConfig(mdConfig), _mamicoConfig(mamicoConfig), _multiMDService(multiMDService) {
      47           12 :     for (unsigned int i = 0; i < multiMDService.getLocalNumberOfMDSimulations(); i++) {
      48            8 :       _mdSimulations.push_back(coupling::interface::SimulationAndInterfaceFactory::getInstance().getMDSimulation(_mdConfig, _mamicoConfig
      49              : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
      50              :                                                                                                                  ,
      51           16 :                                                                                                                  _multiMDService.getLocalCommunicator()
      52              : #endif
      53              :                                                                                                                      ));
      54              : 
      55            8 :       if (_mdSimulations[i] == nullptr) {
      56            0 :         std::cout << "ERROR InstanceHandling : _mdSimulations [" << i << "] == NULL!" << std::endl;
      57            0 :         std::exit(EXIT_FAILURE);
      58              :       }
      59              : 
      60            8 :       _mdSimulations[i]->init(_multiMDService, _multiMDService.getGlobalNumberOfLocalMDSimulation(i));
      61              :     }
      62            4 :   }
      63              : 
      64              :   /** Destructor:
      65              :    */
      66            4 :   ~InstanceHandling() { shutdown(); }
      67              : 
      68              :   /** switches off the coupling between the new MD simulations and Macroscopic
      69              :    *solver and lets the MD simulations run t time steps starting from the time
      70              :    *step T to equilibrate. It should be called before switchOnCoupling()
      71              :    *    @param T
      72              :    *    @param t
      73              :    */
      74            4 :   void equilibrate(const unsigned int& t, const unsigned int& T) {
      75           12 :     for (auto& md : _mdSimulations) {
      76            8 :       md->switchOffCoupling();
      77            8 :       md->simulateTimesteps(t, T);
      78              :     }
      79            4 :   }
      80              : 
      81              :   /** returns the vector of MD simulations
      82              :    *  @return  _mdSimulations
      83              :    */
      84              :   auto& getSimpleMD() const { return _mdSimulations; }
      85              : 
      86              :   /** Allocates Coupling interfaces
      87              :    *    This method has to be called after switchOnCoupling()
      88              :    */
      89            4 :   void setMDSolverInterface() {
      90              : 
      91           12 :     for (unsigned int i = 0; i < _mdSimulations.size(); ++i) {
      92           16 :       _mdSolverInterface.push_back(
      93            8 :           coupling::interface::SimulationAndInterfaceFactory::getInstance().getMDSolverInterface(_mdConfig, _mamicoConfig, _mdSimulations[i]));
      94            8 :       if (_mdSolverInterface[i] == NULL) {
      95            0 :         std::cout << "ERROR InstanceHandling: mdSolverInterface[" << i << "] == NULL!" << std::endl;
      96            0 :         exit(EXIT_FAILURE);
      97              :       }
      98              :     }
      99            4 :   }
     100              : 
     101              :   /** Returns the MD solver onterface
     102              :    *    @return _mdSolverInterface
     103              :    */
     104              :   auto& getMDSolverInterface() const { return _mdSolverInterface; }
     105              : 
     106              :   /** switches on the coupling between ALL new MD simulations and Macroscopic
     107              :    *solver after the new MD instances are equilibrated. It should be called
     108              :    *right after equilibrate() and before setMDSolverInterface()
     109              :    */
     110            4 :   void switchOnCoupling() {
     111           12 :     for (auto& simpleMD : _mdSimulations) {
     112            8 :       simpleMD->switchOnCoupling();
     113              :     }
     114            4 :   }
     115              : 
     116              :   /** switches on the coupling between a specific new MD simulation with the
     117              :    *index number i and Macroscopic solver. It should be called right after
     118              :    *equilibrate() and before setMDSolverInterface()
     119              :    *    @param i
     120              :    */
     121              :   void switchOnCoupling(const unsigned int& i) { _mdSimulations[i]->switchOnCoupling(); }
     122              : 
     123              :   /** switches off the coupling between All new MD simulations and Macroscopic
     124              :    * solver.
     125              :    */
     126            4 :   void switchOffCoupling() {
     127           12 :     for (auto& simpleMD : _mdSimulations) {
     128            8 :       simpleMD->switchOffCoupling();
     129              :     }
     130            4 :   }
     131              : 
     132              :   /** switches off the coupling between a new MD simulation with the index i and
     133              :    * Macroscopic solver.
     134              :    *    @param i index number of the MD simulation
     135              :    */
     136              :   void switchOffCoupling(const unsigned int& i) { _mdSimulations[i]->switchOffCoupling(); }
     137              : 
     138              :   /** Simulates t timesteps starting from current timestep T on all instances.
     139              :    *    @param T
     140              :    *    @param t
     141              :    */
     142            4 :   void simulateTimesteps(const unsigned int& t, unsigned int& T) {
     143           12 :     for (auto& simpleMD : _mdSimulations) {
     144            8 :       simpleMD->simulateTimesteps(t, T);
     145              :     }
     146            4 :   }
     147              : 
     148              :   /** Saves the simulation result of the first MD instance as check point in the
     149              :    * file filestem
     150              :    *    @param filestem
     151              :    *    @param T
     152              :    */
     153            4 :   void writeCheckpoint(const std::string& filestem, const unsigned int& T) const {
     154            4 :     if (_mdSimulations.size() > 0 && _mdSimulations[0] != nullptr) {
     155            4 :       _mdSimulations[0]->writeCheckpoint(filestem, T);
     156              :     }
     157            4 :   }
     158              : 
     159              :   /** Simulates t timesteps starting from current timestep T on all instances
     160              :    *    and additionally uses MamicoInterfaceProvider for interfacing MD to FD.
     161              :    *    @param t
     162              :    *    @param T
     163              :    *    @param multiMDCellService
     164              :    */
     165              :   void simulateTimesteps(const unsigned int& t, unsigned int& T, coupling::services::MultiMDCellService<LinkedCell, dim>& multiMDCellService) {
     166              :     for (unsigned int i = 0; i < _mdSimulations.size(); ++i) {
     167              :       coupling::interface::MamicoInterfaceProvider<LinkedCell, dim>::getInstance().setCouplingCellService(&multiMDCellService.getCouplingCellService(i));
     168              :       coupling::interface::MamicoInterfaceProvider<LinkedCell, dim>::getInstance().setMDSolverInterface(_mdSolverInterface[i]);
     169              : 
     170              :       if (_mdSimulations[i] != nullptr) {
     171              :         _mdSimulations[i]->simulateTimesteps(t, T);
     172              :       }
     173              :     }
     174              :   }
     175              : 
     176              :   /** Simulates t timesteps starting from current timestep T on all instances
     177              :    * but only performs simulation on one particular instance
     178              :    *    @param t
     179              :    *    @param T
     180              :    *    @param i
     181              :    */
     182            8 :   void simulateTimesteps(const unsigned int& t, unsigned int& T, const unsigned int& i) { _mdSimulations[i]->simulateTimesteps(t, T); }
     183              : 
     184              :   /** add a nullptr to the MD simulation vector and the vector of the MD solver
     185              :    * interface.
     186              :    */
     187            8 :   void addSimulationBlock() {
     188            8 :     _mdSimulations.push_back(nullptr);
     189            8 :     _mdSolverInterface.push_back(nullptr);
     190            8 :   }
     191              : 
     192              :   /** rempve the last element of the MD simulation vector and the last element
     193              :    * of the vector of the MD solver interface.
     194              :    */
     195            8 :   void rmSimulationBlock() {
     196            8 :     _mdSimulations.pop_back();
     197            8 :     _mdSolverInterface.pop_back();
     198              :   }
     199              : 
     200              :   /** adds one MS instance with the identifier localIndex to the slot "slot" and
     201              :    * return the corresponding MD solver interface. It initializes first an
     202              :    * instance of the slot "slot". Then set the _mdSimulations[localIndex] to this new
     203              :    * instance.
     204              :    *    @param slot
     205              :    *    @param localIndex
     206              :    *    @return _mdSolverInterface[localIndex]
     207              :    */
     208            4 :   coupling::interface::MDSolverInterface<LinkedCell, dim>* addMDSimulation(unsigned int slot, unsigned int localIndex) {
     209            4 :     auto* mdSim = coupling::interface::SimulationAndInterfaceFactory::getInstance().getMDSimulation(_mdConfig, _mamicoConfig
     210              : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
     211              :                                                                                                     ,
     212            4 :                                                                                                     _multiMDService.getLocalCommunicator()
     213              : #endif
     214              :     );
     215            4 :     if (mdSim == NULL) {
     216            0 :       std::cout << "ERROR! coupling::InstanceHandling::addMDSimulation(): "
     217              :                    "mdSim == NULL!"
     218            0 :                 << std::endl;
     219            0 :       std::exit(EXIT_FAILURE);
     220              :     }
     221              :     // NB: ls1 coupling will break if getMDSolverInterface does not happen immediately after init()
     222              :     // since the solver interface relies on the global simulation instance set by ls1 in init()
     223              : 
     224            4 :     mdSim->init(_multiMDService, slot);
     225              : 
     226            4 :     _mdSimulations[localIndex] = mdSim;
     227              : 
     228            4 :     _mdSolverInterface[localIndex] =
     229            4 :         coupling::interface::SimulationAndInterfaceFactory::getInstance().getMDSolverInterface(_mdConfig, _mamicoConfig, _mdSimulations[localIndex]);
     230              : 
     231            4 :     return _mdSolverInterface[localIndex];
     232              :   }
     233              : 
     234              :   /** removes one MS instance with the identifier index and delete the
     235              :    * corresponding MD solver interface.
     236              :    *    @param index
     237              :    */
     238            4 :   void rmMDSimulation(const unsigned int& index) {
     239            4 :     if (_mdSimulations[index] != nullptr) {
     240            4 :       _mdSimulations[index]->shutdown();
     241            4 :       delete _mdSimulations[index];
     242            4 :       _mdSimulations[index] = nullptr;
     243              :     } else {
     244            0 :       std::cout << "WARNING coupling::InstanceHandling::rmMDSimulation() : "
     245              :                    "_mdSimulations at index "
     246            0 :                 << index << " == null!" << std::endl;
     247              :     }
     248              :     //_mdSimulations.erase(_mdSimulations.begin()+index);
     249              : 
     250            4 :     if (_mdSolverInterface[index] != nullptr) {
     251            4 :       delete _mdSolverInterface[index];
     252            4 :       _mdSolverInterface[index] = nullptr;
     253              :     } else {
     254            0 :       std::cout << "WARNING coupling::InstanceHandling::rmMDSimulation() : "
     255              :                    "_mdSolverInterface at index "
     256            0 :                 << index << " == null!" << std::endl;
     257              :     }
     258              :     //_mdSolverInterface.erase(_mdSolverInterface.begin()+index);
     259            4 :   }
     260              : 
     261              :   /** sets single cell services in each MD simulation after initialising
     262              :    * coupling cell service for multi-MD case
     263              :    *    @param multiMDCellService
     264              :    */
     265              :   void setCouplingCellServices(coupling::services::MultiMDCellService<LinkedCell, dim>& multiMDCellService) {
     266              :     for (unsigned int i = 0; i < _mdSimulations.size(); ++i) {
     267              :       _mdSimulations[i]->setCouplingCellService(&(multiMDCellService.getCouplingCellService(i)));
     268              :     }
     269              :   }
     270              : 
     271              : private:
     272            4 :   void shutdown() {
     273           12 :     for (unsigned int i = 0; i < _mdSimulations.size(); ++i) {
     274            8 :       coupling::interface::MamicoInterfaceProvider<LinkedCell, dim>::getInstance().setMDSolverInterface(_mdSolverInterface[i]);
     275            8 :       if (_mdSimulations[i] != nullptr) {
     276            8 :         _mdSimulations[i]->shutdown();
     277            8 :         delete _mdSimulations[i];
     278            8 :         _mdSimulations[i] = nullptr;
     279              :       }
     280            8 :       _mdSolverInterface[i] = coupling::interface::MamicoInterfaceProvider<LinkedCell, dim>::getInstance().getMDSolverInterface();
     281              :     }
     282            4 :     _mdSimulations.clear();
     283           12 :     for (auto& solverInterface : _mdSolverInterface) {
     284            8 :       if (solverInterface != nullptr) {
     285            8 :         delete solverInterface;
     286            8 :         solverInterface = nullptr;
     287              :       }
     288              :     }
     289            4 :     _mdSolverInterface.clear();
     290            4 :   }
     291              : 
     292              :   std::vector<coupling::interface::MDSimulation*> _mdSimulations;
     293              :   std::vector<coupling::interface::MDSolverInterface<LinkedCell, dim>*> _mdSolverInterface;
     294              : 
     295              :   simplemd::configurations::MolecularDynamicsConfiguration& _mdConfig;
     296              :   coupling::configurations::MaMiCoConfiguration<dim>& _mamicoConfig;
     297              : 
     298              :   const tarch::utils::MultiMDService<dim>& _multiMDService;
     299              :   friend InstanceHandlingTest;
     300              : };
     301              : 
     302              : #endif //_INSTANCE_HANDLING_H_
        

Generated by: LCOV version 2.0-1