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_