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

Generated by: LCOV version 1.14