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_