LCOV - code coverage report
Current view: top level - coupling - InstanceHandling.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 79 90 87.8 %
Date: 2026-02-16 14:39:39 Functions: 13 13 100.0 %

          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          28 :   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           8 :   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             : 
     222           4 :     mdSim->init(_multiMDService, slot);
     223             : 
     224           4 :     _mdSimulations[localIndex] = mdSim;
     225             : 
     226           4 :     _mdSolverInterface[localIndex] =
     227           4 :         coupling::interface::SimulationAndInterfaceFactory::getInstance().getMDSolverInterface(_mdConfig, _mamicoConfig, _mdSimulations[localIndex]);
     228             : 
     229           4 :     return _mdSolverInterface[localIndex];
     230             :   }
     231             : 
     232             :   /** removes one MS instance with the identifier index and delete the
     233             :    * corresponding MD solver interface.
     234             :    *    @param index
     235             :    */
     236           4 :   void rmMDSimulation(const unsigned int& index) {
     237           4 :     if (_mdSimulations[index] != nullptr) {
     238           4 :       _mdSimulations[index]->shutdown();
     239           4 :       delete _mdSimulations[index];
     240           4 :       _mdSimulations[index] = nullptr;
     241             :     } else {
     242           0 :       std::cout << "WARNING coupling::InstanceHandling::rmMDSimulation() : "
     243             :                    "_mdSimulations at index "
     244           0 :                 << index << " == null!" << std::endl;
     245             :     }
     246             :     //_mdSimulations.erase(_mdSimulations.begin()+index);
     247             : 
     248           4 :     if (_mdSolverInterface[index] != nullptr) {
     249           4 :       delete _mdSolverInterface[index];
     250           4 :       _mdSolverInterface[index] = nullptr;
     251             :     } else {
     252           0 :       std::cout << "WARNING coupling::InstanceHandling::rmMDSimulation() : "
     253             :                    "_mdSolverInterface at index "
     254           0 :                 << index << " == null!" << std::endl;
     255             :     }
     256             :     //_mdSolverInterface.erase(_mdSolverInterface.begin()+index);
     257           4 :   }
     258             : 
     259             :   /** sets single cell services in each MD simulation after initialising
     260             :    * coupling cell service for multi-MD case
     261             :    *    @param multiMDCellService
     262             :    */
     263             :   void setCouplingCellServices(coupling::services::MultiMDCellService<LinkedCell, dim>& multiMDCellService) {
     264             :     for (unsigned int i = 0; i < _mdSimulations.size(); ++i) {
     265             :       _mdSimulations[i]->setCouplingCellService(&(multiMDCellService.getCouplingCellService(i)));
     266             :     }
     267             :   }
     268             : 
     269             : private:
     270           4 :   void shutdown() {
     271          12 :     for (unsigned int i = 0; i < _mdSimulations.size(); ++i) {
     272           8 :       coupling::interface::MamicoInterfaceProvider<LinkedCell, dim>::getInstance().setMDSolverInterface(_mdSolverInterface[i]);
     273           8 :       if (_mdSimulations[i] != nullptr) {
     274           8 :         _mdSimulations[i]->shutdown();
     275           8 :         delete _mdSimulations[i];
     276           8 :         _mdSimulations[i] = nullptr;
     277             :       }
     278           8 :       _mdSolverInterface[i] = coupling::interface::MamicoInterfaceProvider<LinkedCell, dim>::getInstance().getMDSolverInterface();
     279             :     }
     280           4 :     _mdSimulations.clear();
     281          12 :     for (auto& solverInterface : _mdSolverInterface) {
     282           8 :       if (solverInterface != nullptr) {
     283           8 :         delete solverInterface;
     284           8 :         solverInterface = nullptr;
     285             :       }
     286             :     }
     287           4 :     _mdSolverInterface.clear();
     288           4 :   }
     289             : 
     290             :   std::vector<coupling::interface::MDSimulation*> _mdSimulations;
     291             :   std::vector<coupling::interface::MDSolverInterface<LinkedCell, dim>*> _mdSolverInterface;
     292             : 
     293             :   simplemd::configurations::MolecularDynamicsConfiguration& _mdConfig;
     294             :   coupling::configurations::MaMiCoConfiguration<dim>& _mamicoConfig;
     295             : 
     296             :   const tarch::utils::MultiMDService<dim>& _multiMDService;
     297             :   friend InstanceHandlingTest;
     298             : };
     299             : 
     300             : #endif //_INSTANCE_HANDLING_H_

Generated by: LCOV version 1.14