MaMiCo 1.2
Loading...
Searching...
No Matches
MultiMDCellService.h
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 _MOLECULARDYNAMICS_COUPLING_SERVICES_MULTIMDCELLSERVICE_H_
6#define _MOLECULARDYNAMICS_COUPLING_SERVICES_MULTIMDCELLSERVICE_H_
7
8namespace coupling {
9template <class LinkedCell, unsigned int dim> class InstanceHandling;
10namespace services {
11template <class LinkedCell, unsigned int dim> class MultiMDCellService;
12}
13} // namespace coupling
14
15#include "coupling/InstanceHandling.h"
16#include "coupling/configurations/MaMiCoConfiguration.h"
17#include "coupling/indexing/IndexingService.h"
18#include "coupling/interface/MDSimulationFactory.h"
19#include "coupling/services/CouplingCellService.h"
20#include "coupling/services/CouplingCellServiceDummy.h"
21
29template <class LinkedCell, unsigned int dim> class coupling::services::MultiMDCellService {
30public:
31 MultiMDCellService(std::vector<coupling::interface::MDSolverInterface<LinkedCell, dim>*> mdSolverInterfaces, // MD solver interfaces for each MD simulation
32 // (which uses this rank)
34 simplemd::configurations::MolecularDynamicsConfiguration& mdConfiguration,
35 coupling::configurations::MaMiCoConfiguration<dim>& mamicoConfiguration, const char* filterPipelineConfiguration,
36 tarch::utils::MultiMDService<dim>& multiMDService, int tws = 0)
37 : _multiMDService(multiMDService), _tws(tws), _intNumberProcesses(computeScalarNumberProcesses()), _mdConfiguration(mdConfiguration),
38 _mamicoConfiguration(mamicoConfiguration), _filterPipelineConfiguration(filterPipelineConfiguration),
39 _macroscopicSolverInterface(macroscopicSolverInterface), _postMultiInstanceFilterPipeline(nullptr) {
40 _topologyOffset = computeTopologyOffset();
41 _localNumberMDSimulations = multiMDService.getLocalNumberOfMDSimulations();
42 _totalNumberMDSimulations = multiMDService.getTotalNumberOfMDSimulations();
43
44 _blockOffset = _localNumberMDSimulations * _topologyOffset / _intNumberProcesses;
45
46 _listActiveMDSimulations = std::vector<bool>(_totalNumberMDSimulations, true);
47 _nextFreeBlock = _multiMDService.getNumberLocalComms() - 1;
48 _warmupPhase = std::vector<int>(_totalNumberMDSimulations, 0);
49
50 // If we allow for zero MD instances on ranks, this initializion process
51 // would segfault...
52 if (mdSolverInterfaces.size() == 0) {
53 std::cout << "ERROR: Zero MD instances on rank " << _multiMDService.getGlobalRank() << ". Maybe you forgot to adjust number-md-simulations?" << std::endl;
54 exit(EXIT_FAILURE);
55 }
56
57 // determine globally unique IDs for each coupling cell service.
58 // Assumptions:
59 // - the global parallel topology is subdivided into equally sized blocks of
60 // ranks
61 // - on each block of ranks, the SAME number of MD simulations is executed.
62 // This yields that the variable _topologyOffset together with the local ID
63 // of an MD simulation yields a unique global ID
64 // - an MD simulation executes on one full block of ranks
66 if (_couplingCellServices == NULL) {
67 std::cout << "ERROR "
68 "coupling::services::MultiMDCellService::MultiMDCellService("
69 "...): _couplingCellServices==NULL!"
70 << std::endl;
71 exit(EXIT_FAILURE);
72 }
73
74 // allocate all coupling cell services for macro-only-solver BEFORE
75 // topology offset
76 // -> we have localNumberMDSimulations that run per block of ranks on
77 // intNumberProcesses
78 // -> this yields
79 // localNumberMDSimulations*topologyOffset/intNumberProcesses MD simulations
80 // before the actual block of ranks
81 for (unsigned int i = 0; i < _blockOffset; i++) {
82 _couplingCellServices[i] = createCouplingCellServiceDummy(i, macroscopicSolverInterface, mdConfiguration, _multiMDService, mamicoConfiguration,
83 (i / _localNumberMDSimulations) * _intNumberProcesses);
84 if (_couplingCellServices[i] == NULL) {
85 std::cout << "ERROR "
86 "coupling::services::MultiMDCellService::MultiMDCellServic"
87 "e(...): _couplingCellServices["
88 << i << "]==NULL!" << std::endl;
89 exit(EXIT_FAILURE);
90 }
91 }
92 // allocate all coupling cell services for macro- and micro-interactions
93 for (unsigned int i = _blockOffset; i < _localNumberMDSimulations + _blockOffset; i++) {
95 i, mdSolverInterfaces[i - _blockOffset], macroscopicSolverInterface, mdConfiguration.getMPIConfiguration().getNumberOfProcesses(),
96 _multiMDService.getGlobalRank(), mamicoConfiguration.getParticleInsertionConfiguration(), mamicoConfiguration.getMomentumInsertionConfiguration(),
97 mamicoConfiguration.getBoundaryForceConfiguration(), mamicoConfiguration.getTransferStrategyConfiguration(),
98 mamicoConfiguration.getParallelTopologyConfiguration(), mamicoConfiguration.getThermostatConfiguration(),
99 mdConfiguration.getSimulationConfiguration().getNumberOfTimesteps(), mamicoConfiguration.getCouplingCellConfiguration(),
100 _filterPipelineConfiguration.c_str(), multiMDService, _topologyOffset, _tws);
101 if (_couplingCellServices[i] == NULL) {
102 std::cout << "ERROR "
103 "coupling::services::MultiMDCellService::MultiMDCellServic"
104 "e(...): _couplingCellServices["
105 << i << "]==NULL!" << std::endl;
106 exit(EXIT_FAILURE);
107 }
108 }
109 // allocate all coupling cell services for macro-only-solver AFTER
110 // topology offset
111 for (unsigned int i = _blockOffset + _localNumberMDSimulations; i < _totalNumberMDSimulations; i++) {
112 _couplingCellServices[i] = createCouplingCellServiceDummy(i, macroscopicSolverInterface, mdConfiguration, _multiMDService, mamicoConfiguration,
113 (i / _localNumberMDSimulations) * _intNumberProcesses);
114 if (_couplingCellServices[i] == NULL) {
115 std::cout << "ERROR "
116 "coupling::services::MultiMDCellService::MultiMDCellServic"
117 "e(...): _couplingCellServices["
118 << i << "]==NULL!" << std::endl;
119 exit(EXIT_FAILURE);
120 }
121 }
122
123 _mdConfiguration.getDomainConfigurationNonConst().setInitFromCheckpoint(true);
124 std::stringstream filestem;
125 filestem << "restart_checkpoint_" << (_multiMDService.getGlobalRank()) / computeScalarNumberProcesses() << "_0";
126 _mdConfiguration.getDomainConfigurationNonConst().setCheckpointFilestem(filestem.str());
127 _mdConfiguration.getDomainConfigurationNonConst().setInitFromSequentialCheckpoint(false);
128 }
129
130 ~MultiMDCellService() {
131 for (unsigned int i = 0; i < _totalNumberMDSimulations; i++) {
132 if (_couplingCellServices[i] != nullptr) {
133 delete _couplingCellServices[i];
134 _couplingCellServices[i] = nullptr;
135 }
136 }
137 if (_couplingCellServices != NULL) {
138 delete[] _couplingCellServices;
140 }
141
142 // TODO: fix free bug/possible memory leak here
143 I01 idx;
145 for (auto pair : _couplingCells) {
146 std::tie(cell, idx) = pair;
147 if (cell != nullptr)
148 delete cell;
149 }
152 }
153
158 if (localIndex < _localNumberMDSimulations) {
159 return *(_couplingCellServices[_topologyOffset * _localNumberMDSimulations / _intNumberProcesses + localIndex]);
160 } else {
161 std::cout << "ERROR MultiMDCellService::getCouplingCellService(localIndex): "
162 "localIndex >_localNumberMDSimulations-1!"
163 << std::endl;
164 exit(EXIT_FAILURE);
165 }
166 }
167
169 void plotEveryMacroscopicTimestepforCouplingCellService(unsigned int localIndex, int cycle) {
170 if (_couplingCellServices[_topologyOffset * _localNumberMDSimulations / _intNumberProcesses + localIndex] == nullptr)
171 return;
172 _couplingCellServices[_topologyOffset * _localNumberMDSimulations / _intNumberProcesses + localIndex]->plotEveryMacroscopicTimestep(cycle);
173 }
174
175 void plotEveryMacroscopicTimestep(int cycle) {
176 for (unsigned int i = _blockOffset; i < _blockOffset + _localNumberMDSimulations; ++i) {
177 if (_couplingCellServices[i] == nullptr)
178 continue;
179 _couplingCellServices[i]->plotEveryMacroscopicTimestep(cycle);
180 }
181 }
182
183 void setInnerMomentumImposition(bool enable) {
184 for (unsigned int i = _blockOffset; i < _blockOffset + _localNumberMDSimulations; ++i) {
185 if (_couplingCellServices[i] == nullptr)
186 continue;
187 _couplingCellServices[i]->setInnerMomentumImposition(enable);
188 }
189 }
190
191 void computeAndStoreTemperature(double temp) {
192 for (unsigned int i = _blockOffset; i < _blockOffset + _localNumberMDSimulations; ++i) {
193 if (_couplingCellServices[i] == nullptr)
194 continue;
195 _couplingCellServices[i]->computeAndStoreTemperature(temp);
196 }
197 }
198
201 // just send information to all MD instances. This is currently
202 // sequentialized inside CouplingCellService/SendRecvBuffer
203 for (unsigned int i = 0; i < _totalNumberMDSimulations; i++) {
204 if (_couplingCellServices[i] != nullptr) {
205 _couplingCellServices[i]->sendFromMacro2MD(macro2mdCouplingCellContainer);
206 }
207 }
208 }
209
211 void bcastFromMacro2MD(const std::vector<coupling::datastructures::CouplingCell<dim>*>& couplingCellsFromMacroscopicSolver, const I00* const indices) {
212#if (COUPLING_MD_PARALLEL == COUPLING_MD_NO)
213 // Fall back on sequential operation when MPI is not available (avoids redundant implementation)
214 sendFromMacro2MD(couplingCellsFromMacroscopicSolver, indices);
215 return;
216#else
217
218 std::vector<coupling::sendrecv::DataExchangeFromMacro2MD<dim>*> allDEs(_totalNumberMDSimulations);
219 std::vector<std::vector<coupling::datastructures::CouplingCell<dim>*>> allCouplingCellsFromMamico(_totalNumberMDSimulations);
220 for (unsigned int i = 0; i < _totalNumberMDSimulations; ++i) {
221 if (nullptr == _couplingCellServices[i])
222 continue;
223 allDEs[i] = new coupling::sendrecv::DataExchangeFromMacro2MD<dim>(_macroscopicSolverInterface, _couplingCellServices[i]->getID());
224 if (auto* v = dynamic_cast<CouplingCellServiceImpl<LinkedCell, dim>*>(_couplingCellServices[i])) {
225 allCouplingCellsFromMamico[i] = v->getCouplingCells().getCouplingCells();
226 }
227 }
228
229 for (unsigned int i = 0; i < _totalNumberMDSimulations; ++i) {
230 if (nullptr == _couplingCellServices[i])
231 continue;
232 _couplingCellServices[i]->sendFromMacro2MDPreProcess();
233 }
234
236 fromMacro2MD.bcastFromMacro2MD(allDEs, couplingCellsFromMacroscopicSolver, indices, allCouplingCellsFromMamico);
237
238 for (unsigned int i = 0; i < _totalNumberMDSimulations; ++i) {
239 if (nullptr == _couplingCellServices[i])
240 continue;
241 _couplingCellServices[i]->sendFromMacro2MDPostProcess();
242 }
244 delete de;
245 de = nullptr;
246 }
247#endif
248 }
249
253 /*
254 * On the first coupling step, initialize the reduced couplingCell vector according to `size`
255 */
256 if (!_sumCouplingCells.empty()) {
257 for (unsigned int i = 0; i < _sumCouplingCells.size(); ++i) {
258 _sumCouplingCells[i]->setMacroscopicMass(0);
259 _sumCouplingCells[i]->setMacroscopicMomentum(tarch::la::Vector<dim, double>(0.0));
260 }
261 }
262 for (unsigned int n = 0; n < _totalNumberMDSimulations; ++n) {
263 if (0 != _warmupPhase[n])
264 continue;
265 if (auto* v = dynamic_cast<CouplingCellServiceImpl<LinkedCell, dim>*>(_couplingCellServices[n])) {
266 for (unsigned int i = 0; i < v->getCouplingCells().getCouplingCells().size(); ++i) {
267 if (_sumCouplingCells.size() <= i) {
269 }
270 _sumCouplingCells[i]->addMacroscopicMass(v->getCouplingCells().getCouplingCells()[i]->getMacroscopicMass());
271 _sumCouplingCells[i]->addMacroscopicMomentum(v->getCouplingCells().getCouplingCells()[i]->getMacroscopicMomentum());
272 }
273 }
274 }
275 }
276
283 double reduceFromMD2Macro(const std::vector<coupling::datastructures::CouplingCell<dim>*>& couplingCellsFromMacroscopicSolver, const I00* const indices) {
284#if (COUPLING_MD_PARALLEL == COUPLING_MD_NO)
285 // Fall back on sequential operation when MPI is not available (avoids redundant implementation)
286 return sendFromMD2Macro(couplingCellsFromMacroscopicSolver, indices);
287#else
288 double res = 0;
289 const unsigned int size = (unsigned int)couplingCellsFromMacroscopicSolver.size();
290
291 preprocessingForMD2Macro(couplingCellsFromMacroscopicSolver);
292
293 for (unsigned int i = 0; i < _totalNumberMDSimulations; ++i) {
294 if (nullptr == _couplingCellServices[i] || 0 != _warmupPhase[i])
295 continue;
296 _couplingCellServices[i]->sendFromMD2MacroPreProcess();
297 res += _couplingCellServices[i]->applyFilterPipeline();
298 }
299
304
305 // reset macroscopic data (only those should be used by macroscopic solver anyway) in cells
306 for (coupling::datastructures::CouplingCell<dim>*& couplingCell : _couplingCells) {
307 couplingCell->setMacroscopicMass(0.0);
308 couplingCell->setMacroscopicMomentum(tarch::la::Vector<dim, double>(0.0));
309 }
310
311 std::vector<coupling::sendrecv::DataExchangeFromMD2Macro<dim>*> allDEs(_totalNumberMDSimulations);
312 std::vector<std::vector<coupling::datastructures::CouplingCell<dim>*>> allCouplingCellsFromMamico(_totalNumberMDSimulations);
313 coupling::interface::MacroscopicSolverInterface<dim>* _macroscopicSolverInterface =
315 unsigned int totalNumberEquilibratedMDSimulations = 0;
316 for (unsigned int i = 0; i < _totalNumberMDSimulations; ++i) {
317 if (nullptr == _couplingCellServices[i] || 0 != _warmupPhase[i])
318 continue; // Only reduce using equilibrated MD simulation instances
319 allDEs[i] = new coupling::sendrecv::DataExchangeFromMD2Macro<dim>(_macroscopicSolverInterface, _couplingCellServices[i]->getID());
320 totalNumberEquilibratedMDSimulations += 1;
321 }
322 _fromMD2Macro.reduceFromMD2Macro(allDEs, couplingCellsFromMacroscopicSolver, indices, _sumCouplingCells);
323
324 // average data
325 for (unsigned int i = 0; i < size; i++) {
326 _couplingCells[i]->setMacroscopicMass(couplingCellsFromMacroscopicSolver[i]->getMacroscopicMass() / (double)totalNumberEquilibratedMDSimulations);
327 _couplingCells[i]->setMacroscopicMomentum(1.0 / (double)totalNumberEquilibratedMDSimulations *
328 couplingCellsFromMacroscopicSolver[i]->getMacroscopicMomentum());
329 }
330
331 for (unsigned int i = 0; i < _totalNumberMDSimulations; i++) {
332 if (nullptr == _couplingCellServices[i] || 0 != _warmupPhase[i])
333 continue; // Only equilibrated MD simulation instances
334 _couplingCellServices[i]->sendFromMD2MacroPostProcess();
335 }
336
337 // apply post multi instance FilterPipeline on cell data
338
339#ifdef DEBUG_FILTER_PIPELINE
340 std::cout << "FP: Now applying post-multi-instance filter pipeline" << std::endl;
341#endif
342
343 // FIXME apply filtering to correct region res += (*_postMultiInstanceFilterPipeline)();
344
345 // store data in couplingCellsFromMacroscopicSolver
346 for (unsigned int i = 0; i < size; i++) {
347 couplingCellsFromMacroscopicSolver[i]->setMacroscopicMass(_couplingCells[i]->getMacroscopicMass());
348 couplingCellsFromMacroscopicSolver[i]->setMacroscopicMomentum(_couplingCells[i]->getMacroscopicMomentum());
349 }
350 return res;
351#endif
352 }
353
358 double res = 0;
359
360 preprocessingForMD2Macro(md2macroCouplingCells);
361
362#if (COUPLING_MD_ERROR == COUPLING_MD_YES)
363 if (_couplingCells.size() != md2macroCouplingCells.size())
364 throw std::runtime_error(std::string("Buffers must have the same size!"));
365#endif
366
367 // reset macroscopic data (only those should be used by macroscopic solver
368 // anyway) in duplicate
369 I01 idx;
372 for (auto pair : _couplingCells) {
373 std::tie(cellA, idx) = pair;
374 cellA->setMacroscopicMass(0.0);
376 }
377
378 // receive data from each MD simulation and accumulate information in
379 // duplicate
380 unsigned int totalNumberEquilibratedMDSimulations = 0;
381 for (unsigned int l = 0; l < _totalNumberMDSimulations; l++) {
382 // std::cout << "Rank " <<
383 //_couplingCellServices[l]->getIndexConversion().getThisRank() << ":
384 // Send from MD to Macro for Simulation no. " << l << std::endl;
385 if (_couplingCellServices[l] != nullptr && _warmupPhase[l] == 0) {
386 res += _couplingCellServices[l]->sendFromMD2Macro(md2macroCouplingCells);
387 auto itCouplingCells = _couplingCells.begin();
388 auto itMd2macroCouplingCells = md2macroCouplingCells.begin();
389 while (itCouplingCells != _couplingCells.end()) {
390 std::tie(cellA, idx) = *itCouplingCells;
391 std::tie(cellB, idx) = *itMd2macroCouplingCells;
392 cellA->addMacroscopicMass(cellB->getMacroscopicMass());
394 itCouplingCells++;
395 itMd2macroCouplingCells++;
396 }
397 totalNumberEquilibratedMDSimulations += 1;
398 }
399 }
400
401 // average data
402 for (auto pair : _couplingCells) {
403 std::tie(cellA, idx) = pair;
404 cellA->setMacroscopicMass(cellA->getMacroscopicMass() / (double)totalNumberEquilibratedMDSimulations);
405 cellA->setMacroscopicMomentum(1.0 / (double)totalNumberEquilibratedMDSimulations * cellA->getMacroscopicMomentum());
406 }
407
408 // apply post multi instance FilterPipeline on cell data
409
410#ifdef DEBUG_FILTER_PIPELINE
411 std::cout << "FP: Now applying post-multi-instance filter pipeline" << std::endl;
412#endif
413
414 // FIXME apply filtering to correct region res += (*_postMultiInstanceFilterPipeline)();
415
416 // store data in md2macroCouplingCells
417 auto itCouplingCells = _couplingCells.begin();
418 auto itMd2macroCouplingCells = md2macroCouplingCells.begin();
419 while (itCouplingCells != _couplingCells.end()) {
420 std::tie(cellA, idx) = *itCouplingCells;
421 std::tie(cellB, idx) = *itMd2macroCouplingCells;
422 cellB->setMacroscopicMass(cellA->getMacroscopicMass());
424 itCouplingCells++;
425 itMd2macroCouplingCells++;
426 }
427
428 return res;
429 }
430
435
436 /*
437 * If this is first coupling step, we must allocate space for the
438 * coupling cells we filter and determine averages with.
439 */
440 if (_couplingCells.size() == 0) {
441 // Allocate & init _couplingCells
442 I01 idx;
444 for (auto pair : cells) {
445 std::tie(cell, idx) = pair;
447 _couplingCells << std::make_pair(newCell, idx);
448 }
449 }
450
451 if (_postMultiInstanceFilterPipeline == nullptr) {
452 // Init filter pipeline
453 // FIXME Invalid cell container
454 // _postMultiInstanceFilterPipeline = new coupling::filtering::FilterPipeline<I14, dim>(_couplingCells, coupling::filtering::Scope::postMultiInstance,
455 // _multiMDService, _filterPipelineConfiguration.c_str());
456 }
457 }
458
462 unsigned int rmMDSimulation(coupling::InstanceHandling<LinkedCell, dim>& instanceHandling, const unsigned int& index) {
463#if (COUPLING_MD_DEBUG == COUPLING_MD_YES)
464 if (_couplingCellServices[index] == nullptr) {
465 std::cout << "Rank " << _multiMDService.getGlobalRank() << ": _couplingCellService at " << index << " == NULL" << std::endl;
466 }
467#endif
468
469 delete _couplingCellServices[index];
470 _couplingCellServices[index] = nullptr;
471
472 if (index >= _blockOffset && index < _blockOffset + _localNumberMDSimulations) {
473 unsigned int iSim = index - _blockOffset;
474#if (COUPLING_MD_DEBUG == COUPLING_MD_YES)
475 if (_multiMDService.getGlobalRank() == 0)
476 std::cout << "MultiMDCellService: removing instance " << iSim << "..." << std::endl;
477#endif
478 instanceHandling.rmMDSimulation(iSim);
479 }
480
481 _warmupPhase[index] = -1;
482
483 return index;
484 }
485
490
491 unsigned int newLocalNumberMDSimulations = _localNumberMDSimulations - 1;
492 unsigned int newTotalNumberMDSimulations = _totalNumberMDSimulations - _multiMDService.getNumberLocalComms();
493 unsigned int newBlockOffset = newLocalNumberMDSimulations * _topologyOffset / _intNumberProcesses;
494
495 auto** newCouplingCellServices = new CouplingCellService<dim>*[newTotalNumberMDSimulations];
496
497 for (unsigned int i = 0; i < _multiMDService.getNumberLocalComms(); ++i) {
498 for (unsigned int j = 0; j < newLocalNumberMDSimulations; ++j) {
499 unsigned int index = i * _localNumberMDSimulations + j;
500 unsigned int newIndex = i * newLocalNumberMDSimulations + j;
501
502 newCouplingCellServices[newIndex] = _couplingCellServices[index];
503 }
504
505 auto pos = _warmupPhase.begin() + newLocalNumberMDSimulations * i - i;
506 _warmupPhase.erase(pos);
507 }
508
509 // Update local variables
510 _localNumberMDSimulations = newLocalNumberMDSimulations;
511 _totalNumberMDSimulations = newTotalNumberMDSimulations;
512 _blockOffset = newBlockOffset;
513
514 delete[] _couplingCellServices;
515 _couplingCellServices = newCouplingCellServices;
516
517 //_multiMDService.removeMDSimulationBlock();
518
519 //_listActiveMDSimulations.pop_back();
520 }
521
530
531 unsigned int newLocalNumberMDSimulations = _localNumberMDSimulations + 1;
532 unsigned int newTotalNumberMDSimulations = _totalNumberMDSimulations + _multiMDService.getNumberLocalComms();
533 unsigned int newBlockOffset = newLocalNumberMDSimulations * _topologyOffset / _intNumberProcesses;
534
535 auto** newCouplingCellServices = new CouplingCellService<dim>*[newTotalNumberMDSimulations];
536 for (unsigned int i = 0; i < _multiMDService.getNumberLocalComms(); ++i) {
537 for (unsigned int j = 0; j < _localNumberMDSimulations; ++j) {
538 unsigned int index = i * _localNumberMDSimulations + j;
539 unsigned int newIndex = i * newLocalNumberMDSimulations + j;
540 newCouplingCellServices[newIndex] = _couplingCellServices[index];
541 }
542 newCouplingCellServices[(i + 1) * newLocalNumberMDSimulations - 1] = nullptr;
543
544 auto pos = _warmupPhase.begin() + ((i + 1) * newLocalNumberMDSimulations - 1);
545 _warmupPhase.insert(pos, 0);
546 }
547
548 // Update local variables
549 _localNumberMDSimulations = newLocalNumberMDSimulations;
550 _totalNumberMDSimulations = newTotalNumberMDSimulations;
551 _blockOffset = newBlockOffset;
552 delete[] _couplingCellServices;
553 _couplingCellServices = newCouplingCellServices;
554 }
555
561 coupling::interface::MacroscopicSolverInterface<dim>* macroscopicSolverInterface, const unsigned int& slot) {
562
563 if (slot >= _totalNumberMDSimulations) {
564 std::cout << "ERROR coupling::services::MultiMDCellService::addMDSimulation(): "
565 "Invalid slot "
566 << slot << "!" << std::endl;
567 std::exit(EXIT_FAILURE);
568 }
569 if (_couplingCellServices[slot] != nullptr) {
570 std::cout << "ERROR! "
571 "coupling::services::MultiMDCellService::addMDSimulation(): "
572 "Simulation at "
573 << slot << " already exists!" << std::endl;
574 std::exit(EXIT_FAILURE);
575 }
576
577 std::stringstream filestem;
578 filestem << "restart_checkpoint_" << _multiMDService.getGlobalRank() / computeScalarNumberProcesses();
579 instanceHandling.writeCheckpoint(filestem.str().c_str(), 0);
580
581 if (slot < _blockOffset || slot >= _blockOffset + _localNumberMDSimulations) {
582
584 slot, macroscopicSolverInterface, _mdConfiguration.getMPIConfiguration().getNumberOfProcesses(), _multiMDService.getGlobalRank(),
585 _mdConfiguration.getDomainConfiguration().getGlobalDomainSize(), _mdConfiguration.getDomainConfiguration().getGlobalDomainOffset(),
586 _mamicoConfiguration.getParallelTopologyConfiguration(), _mamicoConfiguration.getCouplingCellConfiguration(),
587 (slot / _localNumberMDSimulations) * _intNumberProcesses);
588 } else {
589
590 unsigned localIndex = slot - _blockOffset;
591 auto* mdSolverInterface = instanceHandling.addMDSimulation(slot, localIndex);
592
594 slot, mdSolverInterface, macroscopicSolverInterface, _mdConfiguration.getMPIConfiguration().getNumberOfProcesses(), _multiMDService.getGlobalRank(),
595 _mamicoConfiguration.getParticleInsertionConfiguration(), _mamicoConfiguration.getMomentumInsertionConfiguration(),
596 _mamicoConfiguration.getBoundaryForceConfiguration(), _mamicoConfiguration.getTransferStrategyConfiguration(),
597 _mamicoConfiguration.getParallelTopologyConfiguration(), _mamicoConfiguration.getThermostatConfiguration(),
598 _mdConfiguration.getSimulationConfiguration().getNumberOfTimesteps(), _mamicoConfiguration.getCouplingCellConfiguration(),
599 _filterPipelineConfiguration.c_str(), _multiMDService, _topologyOffset, _tws);
600 instanceHandling.getSimpleMD()[localIndex]->setCouplingCellService((_couplingCellServices[slot]));
601 _couplingCellServices[slot]->perturbateVelocity();
602 if (_couplingCellServices[slot]->getFilterPipeline() == nullptr) {
603 _couplingCellServices[slot]->initFiltering();
604 }
605 }
606
607 _warmupPhase[slot] = 10;
608
609 return slot;
610 }
611
612 unsigned int getLocalNumberOfMDSimulations() const { return _localNumberMDSimulations; }
613
614 void finishCycle(const unsigned int& cycle, coupling::InstanceHandling<LinkedCell, dim>& instanceHandling) {
615 // TODO this should be move to somewhere else (MDMediator?)
616 for (unsigned int i = 0; i < _totalNumberMDSimulations; ++i) {
617 if (_warmupPhase[i] > 0) {
618 _warmupPhase[i] -= 1;
619 if (_warmupPhase[i] == 0 && i >= _blockOffset && i < _blockOffset + _localNumberMDSimulations) {
620 instanceHandling.switchOnCoupling(i - _blockOffset);
621 }
622 }
623 }
624 // writeCheckpoint(cycle, instanceHandling);
625 // TODO call directly instanceHandling.writeCheckpoint();
626 }
627
628 void writeCheckpoint(const unsigned int& cycle, const coupling::InstanceHandling<LinkedCell, dim>& instanceHandling) const {
629 if (cycle % 10 != 0)
630 return;
631 std::stringstream filestem;
632 filestem << "restart_checkpoint_" << _multiMDService.getGlobalRank() / computeScalarNumberProcesses();
633 instanceHandling.writeCheckpoint(filestem.str().c_str(), 0);
634 }
635
636 // Must be called after construction of MultiMDCellService, but before the
637 // first coupling step.
638 void constructFilterPipelines() {
639 for (unsigned int md = 0; md < _totalNumberMDSimulations; md++) {
640 // get coupling cell service of instance
641 auto& mcs = _couplingCellServices[md];
642
643 // only Impl instances of MCS contain filtering
644 if (dynamic_cast<coupling::services::CouplingCellServiceImpl<LinkedCell, dim>*>(mcs) == nullptr)
645 continue;
646
647 if (mcs->getFilterPipeline() == nullptr) {
648 mcs->initFiltering();
649 }
650 }
651 }
652
653private:
654 unsigned int computeTopologyOffset() const {
655 // determine topology offset of this rank
656 const unsigned int intNumberProcesses = computeScalarNumberProcesses();
657 const unsigned int topologyOffset = (_multiMDService.getGlobalRank() / intNumberProcesses) * intNumberProcesses;
658 return topologyOffset;
659 }
660
661 unsigned int computeScalarNumberProcesses() const {
662 unsigned int np = _multiMDService.getNumberProcessesPerMDSimulation()[0];
663 for (unsigned int d = 1; d < dim; d++) {
664 np = np * _multiMDService.getNumberProcessesPerMDSimulation()[d];
665 }
666 return np;
667 }
668
669 coupling::services::CouplingCellService<dim>*
670 createCouplingCellServiceDummy(unsigned int ID, coupling::interface::MacroscopicSolverInterface<dim>* macroscopicSolverInterface,
671 simplemd::configurations::MolecularDynamicsConfiguration& mdConfiguration, tarch::utils::MultiMDService<dim>& multiMDService,
672 coupling::configurations::MaMiCoConfiguration<dim>& mamicoConfiguration, unsigned int topologyOffset) const {
673 return new coupling::services::CouplingCellServiceDummy<dim>(
674 ID, macroscopicSolverInterface, mdConfiguration.getMPIConfiguration().getNumberOfProcesses(), multiMDService.getGlobalRank(),
675 mdConfiguration.getDomainConfiguration().getGlobalDomainSize(), mdConfiguration.getDomainConfiguration().getGlobalDomainOffset(),
676 mamicoConfiguration.getParallelTopologyConfiguration(), mamicoConfiguration.getCouplingCellConfiguration(), topologyOffset);
677 }
678
679 unsigned int _localNumberMDSimulations;
686 unsigned int _topologyOffset;
687
688 const int _tws;
689 const unsigned int _intNumberProcesses;
690
691 // conversions during filtering TODO after merge with dynamic-md*/
694
695 simplemd::configurations::MolecularDynamicsConfiguration& _mdConfiguration;
697 const std::string _filterPipelineConfiguration;
698 coupling::interface::MacroscopicSolverInterface<dim>* _macroscopicSolverInterface;
699
700 unsigned int _blockOffset;
701 std::vector<bool> _listActiveMDSimulations;
703 unsigned int _nextFreeBlock;
705 std::vector<int> _warmupPhase;
711 /*
712 * Analogon to CouplingCellService's FilterPipeline.
713 * Is applied during this->sendFromMD2Macro.
714 */
716 /* Buffer for copying data from MD to macro */
718};
719#endif // _MOLECULARDYNAMICS_COUPLING_SERVICES_MULTIMDCELLSERVICE_H_
Simulation slots are managed (i.e., added/removed) via this class. Works and interacts with the class...
Definition InstanceHandling.h:35
auto & getSimpleMD() const
Definition InstanceHandling.h:101
void writeCheckpoint(const std::string &filestem, const unsigned int &T) const
Definition InstanceHandling.h:170
void rmMDSimulation(const unsigned int &index)
Definition InstanceHandling.h:253
void switchOnCoupling()
Definition InstanceHandling.h:127
coupling::interface::MDSolverInterface< LinkedCell, dim > * addMDSimulation(unsigned int slot, unsigned int localIndex)
Definition InstanceHandling.h:225
parses all sub-tags for MaMiCo configuration.
Definition MaMiCoConfiguration.h:31
const coupling::configurations::MomentumInsertionConfiguration & getMomentumInsertionConfiguration() const
Definition MaMiCoConfiguration.h:86
const coupling::configurations::ThermostatConfiguration & getThermostatConfiguration() const
Definition MaMiCoConfiguration.h:146
const coupling::configurations::BoundaryForceConfiguration< dim > & getBoundaryForceConfiguration() const
Definition MaMiCoConfiguration.h:99
const coupling::configurations::ParticleInsertionConfiguration & getParticleInsertionConfiguration() const
Definition MaMiCoConfiguration.h:73
const coupling::configurations::ParallelTopologyConfiguration & getParallelTopologyConfiguration() const
Definition MaMiCoConfiguration.h:125
const coupling::configurations::TransferStrategyConfiguration< dim > & getTransferStrategyConfiguration() const
Definition MaMiCoConfiguration.h:112
const coupling::configurations::CouplingCellConfiguration< dim > & getCouplingCellConfiguration() const
Definition MaMiCoConfiguration.h:68
defines the cell type with cell-averaged quantities only (no linked cells).
Definition CouplingCell.h:29
void addMacroscopicMomentum(const tarch::la::Vector< dim, double > &momentum)
Definition CouplingCell.h:85
const tarch::la::Vector< dim, double > & getMacroscopicMomentum() const
Definition CouplingCell.h:64
void addMacroscopicMass(const double &mass)
Definition CouplingCell.h:82
void setMacroscopicMomentum(const tarch::la::Vector< dim, double > &momentum)
Definition CouplingCell.h:61
const double & getMacroscopicMass() const
Definition CouplingCell.h:58
void setMacroscopicMass(const double &mass)
Definition CouplingCell.h:55
provides access to coupling cells, which may belong to different indexing domains
Definition FlexibleCellContainer.h:30
Iterator begin() const
Definition FlexibleCellContainer.h:121
unsigned int size() const
Definition FlexibleCellContainer.h:78
Definition FilterPipeline.h:44
interface to the MD simulation
Definition MDSolverInterface.h:25
interface for the macroscopic, i.e. continuum solver
Definition MacroscopicSolverInterface.h:23
static MamicoInterfaceProvider & getInstance()
Definition MamicoInterfaceProvider.h:28
coupling::interface::MacroscopicSolverInterface< dim > * getMacroscopicSolverInterface()
Definition MamicoInterfaceProvider.h:43
data exchange from the MD solver to the macroscopic solver. Derived from the class coupling::sendrecv...
Definition DataExchangeFromMD2Macro.h:36
data exchange from the macroscopic solver to the MD solver. Derived from the class coupling::sendrecv...
Definition DataExchangeFromMacro2MD.h:36
sends coupling cell information from MaMiCo to the macroscopic solver. Derived from the class couplin...
Definition FromMD2Macro.h:29
SendReceiveBuffer for transfer of quantities from a macroscopic solver to the coupling cells....
Definition FromMacro2MD.h:28
Definition CouplingCellServiceDummy.h:28
Definition CouplingCellService.h:100
Definition CouplingCellService.h:50
Definition MultiMDCellService.h:29
const int _tws
Definition MultiMDCellService.h:688
coupling::filtering::FilterPipeline< I14, dim > * _postMultiInstanceFilterPipeline
Definition MultiMDCellService.h:715
void sendFromMacro2MD(const coupling::datastructures::FlexibleCellContainer< dim > &macro2mdCouplingCellContainer)
Definition MultiMDCellService.h:200
void removeSimulationBlock()
Definition MultiMDCellService.h:489
void bcastFromMacro2MD(const std::vector< coupling::datastructures::CouplingCell< dim > * > &couplingCellsFromMacroscopicSolver, const I00 *const indices)
Definition MultiMDCellService.h:211
void sumUpCouplingCellsFromMamico()
Definition MultiMDCellService.h:252
double reduceFromMD2Macro(const std::vector< coupling::datastructures::CouplingCell< dim > * > &couplingCellsFromMacroscopicSolver, const I00 *const indices)
Definition MultiMDCellService.h:283
std::vector< int > _warmupPhase
Definition MultiMDCellService.h:705
double sendFromMD2Macro(const coupling::datastructures::FlexibleCellContainer< dim > &md2macroCouplingCells)
Definition MultiMDCellService.h:357
simplemd::configurations::MolecularDynamicsConfiguration & _mdConfiguration
Definition MultiMDCellService.h:695
coupling::services::CouplingCellService< dim > & getCouplingCellService(unsigned int localIndex)
Definition MultiMDCellService.h:157
coupling::services::CouplingCellService< dim > ** _couplingCellServices
Definition MultiMDCellService.h:683
unsigned int rmMDSimulation(coupling::InstanceHandling< LinkedCell, dim > &instanceHandling, const unsigned int &index)
Definition MultiMDCellService.h:462
unsigned int addMDSimulation(coupling::InstanceHandling< LinkedCell, dim > &instanceHandling, coupling::interface::MacroscopicSolverInterface< dim > *macroscopicSolverInterface, const unsigned int &slot)
Definition MultiMDCellService.h:560
unsigned int _totalNumberMDSimulations
Definition MultiMDCellService.h:682
void addSimulationBlock()
Definition MultiMDCellService.h:529
void plotEveryMacroscopicTimestepforCouplingCellService(unsigned int localIndex, int cycle)
Definition MultiMDCellService.h:169
unsigned int _nextFreeBlock
Definition MultiMDCellService.h:703
void preprocessingForMD2Macro(const coupling::datastructures::FlexibleCellContainer< dim > &cells)
Definition MultiMDCellService.h:434
tarch::utils::MultiMDService< dim > & _multiMDService
Definition MultiMDCellService.h:685
coupling::datastructures::FlexibleCellContainer< dim > _sumCouplingCells
Definition MultiMDCellService.h:693
Definition Vector.h:24
Definition MultiMDService.h:30
everything necessary for coupling operations, is defined in here
Definition AdditiveMomentumInsertion.h:15