LCOV - code coverage report
Current view: top level - coupling/interface/impl/SimpleMD - SimpleMDSimulation.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 29 64 45.3 %
Date: 2026-02-16 14:39:39 Functions: 11 15 73.3 %

          Line data    Source code
       1             : #pragma once
       2             : #include "coupling/interface/MDSimulation.h"
       3             : #include "coupling/interface/MamicoInterfaceProvider.h"
       4             : #include "simplemd/MolecularDynamicsSimulation.h"
       5             : #include "simplemd/molecule-mappings/ConvertForcesFloatToFixedMapping.h"
       6             : #include "simplemd/molecule-mappings/ConvertForcesFixedToFloatMapping.h"
       7             : #include "simplemd/molecule-mappings/WriteCheckPointMapping.h"
       8             : 
       9             : namespace coupling {
      10             : namespace interface {
      11             : /** defines a MDsimulation based on simplemd::MolecularDynamicsSimulation but for coupled MD simulations.
      12             :  * Thus, the implementation of one timestep slightly differs from the one of the base class.
      13             :  *      @brief defines MD simulation from default simple MD code.
      14             :  *  @author Philipp Neumann
      15             :  */
      16             : class SimpleMDSimulation : public coupling::interface::MDSimulation, public simplemd::MolecularDynamicsSimulation {
      17             : public:
      18          12 :   SimpleMDSimulation(const simplemd::configurations::MolecularDynamicsConfiguration& configuration)
      19          12 :       : coupling::interface::MDSimulation(), simplemd::MolecularDynamicsSimulation(configuration), _couplingCellService(NULL), _couplingSwitchedOn(true) {}
      20             : 
      21          12 :   virtual ~SimpleMDSimulation() {}
      22             : 
      23          16 :   virtual void switchOffCoupling() { _couplingSwitchedOn = false; }
      24             : 
      25           8 :   virtual void switchOnCoupling() { _couplingSwitchedOn = true; }
      26             : 
      27          24 :   virtual void simulateTimesteps(const unsigned int& numberTimesteps, const unsigned int& firstTimestep) {
      28         144 :     for (unsigned int t = firstTimestep; t < firstTimestep + numberTimesteps; t++) {
      29         120 :       simulateOneCouplingTimestep(t);
      30             :     }
      31          24 :   }
      32             : 
      33         120 :   void simulateOneCouplingTimestep(const unsigned int& t) {
      34             :     // if coupling is switched off, perform "normal" MD timestep
      35         120 :     if (!_couplingSwitchedOn) {
      36         120 :       simulateOneTimestep(t);
      37         120 :       return;
      38             :     }
      39           0 :     if (_parallelTopologyService->isIdle()) {
      40             :       return;
      41             :     }
      42             : 
      43           0 :     _boundaryTreatment->putBoundaryParticlesToInnerCellsAndFillBoundaryCells(_localBoundary, *_parallelTopologyService);
      44             : 
      45             :     // call to synchronise data in cells; needs to be at this point of the
      46             :     // coupling algorithm as the particles need to be placed inside the correct
      47             :     // sampling volumes (hence: after communication with neighbours and molecule
      48             :     // updates); do it BEFORE quantities are manipulated as we can then also do
      49             :     // some pre-processing here.
      50           0 :     _couplingCellService->processInnerCouplingCellAfterMDTimestep();
      51             :     // ------------ coupling step: distribute mass ---------------------
      52           0 :     _couplingCellService->distributeMass(t);
      53             :     // for isothermal simulations: apply thermostat
      54           0 :     _couplingCellService->applyTemperatureToMolecules(t);
      55             : 
      56             :     // ---------- from here: go on with usual MD algorithm
      57             :     // ------------------------------
      58             : 
      59             :     // compute forces. After this step, each molecule has received all force
      60             :     // contributions from its neighbors.
      61             : #if (TARCH_DEBUG == TARCH_YES)
      62           0 :     _moleculeService->getContainer().iterateMolecules(_convertForcesFloatToFixedMapping);
      63             : #endif
      64           0 :     _moleculeService->getContainer().iterateCellPairs(*_lennardJonesForce);
      65             : #if (TARCH_DEBUG == TARCH_YES)
      66           0 :     _moleculeService->getContainer().iterateMolecules(_convertForcesFixedToFloatMapping);
      67             : #endif
      68             : 
      69             :     // distribute momentum -> some methods require modification of force terms,
      70             :     // therefore we call it AFTER the force computation and before everything else
      71           0 :     _couplingCellService->distributeMomentum(t);
      72             :     // apply boundary forces
      73           0 :     _couplingCellService->applyBoundaryForce(t);
      74             :     // evaluate statistics
      75           0 :     evaluateStatistics(t);
      76             : 
      77           0 :     _boundaryTreatment->emptyGhostBoundaryCells();
      78             : 
      79             :     // plot VTK output
      80           0 :     if ((_configuration.getVTKConfiguration().getWriteEveryTimestep() != 0) && (t % _configuration.getVTKConfiguration().getWriteEveryTimestep() == 0)) {
      81           0 :       _vtkMoleculeWriter->setTimestep(t);
      82           0 :       _moleculeService->getContainer().iterateMolecules(*_vtkMoleculeWriter);
      83             :     }
      84             : 
      85             : // plot ADIOS2 output
      86             : #if BUILD_WITH_ADIOS2
      87             :     if ((_configuration.getAdios2Configuration().getWriteEveryTimestep() != 0) && (t % _configuration.getAdios2Configuration().getWriteEveryTimestep() == 0)) {
      88             :       _Adios2Writer->setTimestep(t);
      89             :       _moleculeService->getContainer().iterateMolecules(*_Adios2Writer);
      90             :     }
      91             : #endif
      92             : 
      93             :     // write checkpoint
      94           0 :     if ((_configuration.getCheckpointConfiguration().getWriteEveryTimestep() != 0) &&
      95           0 :         (t % _configuration.getCheckpointConfiguration().getWriteEveryTimestep() == 0)) {
      96           0 :       simplemd::moleculemappings::WriteCheckPointMapping writeCheckPointMapping(*_parallelTopologyService,
      97           0 :                                                                                 _configuration.getCheckpointConfiguration().getFilename(), t);
      98           0 :       _moleculeService->getContainer().iterateMolecules(writeCheckPointMapping);
      99           0 :     }
     100             :     // plot also coupling cell information
     101           0 :     _couplingCellService->plotEveryMicroscopicTimestep(t);
     102             : 
     103             :     // time integration. After this step, the velocities and the positions of the
     104             :     // molecules have been updated.
     105           0 :     _moleculeService->getContainer().iterateMolecules(*_timeIntegrator);
     106             : 
     107             :     // sort molecules into linked cells
     108           0 :     _moleculeService->getContainer().sort();
     109             :   }
     110             : 
     111           0 :   virtual void sortMoleculesIntoCells() {
     112             :     // nop required, since the linked cells are very tightly linked to mamico
     113           0 :   }
     114             : 
     115           0 :   virtual void setCouplingCellService(coupling::services::CouplingCellService<MDSIMULATIONFACTORY_DIMENSION>* couplingCellService) {
     116           0 :     _couplingCellService = couplingCellService;
     117             :     // set the cell service also in singleton of mamico interface provider ->
     118             :     // typically not required in coupling, but makes the simulation state more
     119             :     // consistent compared to using LAMMPS
     120           0 :     coupling::interface::MamicoInterfaceProvider<simplemd::LinkedCell, MDSIMULATIONFACTORY_DIMENSION>::getInstance().setCouplingCellService(
     121             :         couplingCellService);
     122           0 :   }
     123             : 
     124           0 :   virtual void init() { initServices(); }
     125             : 
     126          12 :   virtual void init(const tarch::utils::MultiMDService<MDSIMULATIONFACTORY_DIMENSION>& multiMDService, unsigned int localMDSimulation) {
     127          12 :     initServices(multiMDService, localMDSimulation);
     128          12 :   }
     129             : 
     130          12 :   virtual void shutdown() { shutdownServices(); }
     131             : 
     132           4 :   virtual void writeCheckpoint(const std::string& filestem, const unsigned int& t) {
     133           4 :     simplemd::moleculemappings::WriteCheckPointMapping writeCheckPointMapping(getParallelTopologyService(), filestem, t);
     134           4 :     _moleculeService->getContainer().iterateMolecules(writeCheckPointMapping);
     135           4 :   }
     136             : 
     137             :   // function particularly needed to init MD solver interface -> should only be
     138             :   // called from factory
     139          12 :   simplemd::BoundaryTreatment& getBoundaryTreatment() { return *_boundaryTreatment; }
     140          28 :   simplemd::services::ParallelTopologyService& getParallelTopologyService() { return *_parallelTopologyService; }
     141          12 :   simplemd::services::MoleculeService& getMoleculeService() {
     142             : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     143          12 :     if (_moleculeService == NULL) {
     144           0 :       std::cout << "ERROR coupling::interface::MDSimulation::getMoleculeService(): _moleculeService == NULL " << std::endl;
     145           0 :       exit(1);
     146             :     }
     147             : #endif
     148          12 :     return *_moleculeService;
     149             :   }
     150          12 :   const simplemd::services::MolecularPropertiesService& getMolecularPropertiesService() {
     151             : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
     152          12 :     if (_molecularPropertiesService == NULL) {
     153           0 :       std::cout << "ERROR coupling::interface::MDSimulation::getMolecularPropertiesService(): _molecularPropertiesService == NULL " << std::endl;
     154           0 :       exit(1);
     155             :     }
     156             : #endif
     157          12 :     return *_molecularPropertiesService;
     158             :   }
     159             : 
     160             : private:
     161             :   /** @brief the coupling cell service for the coupled md simulation  */
     162             :   coupling::services::CouplingCellService<MD_DIM>* _couplingCellService;
     163             :   /** @brief bool holding the current state of the coupling: true - coupled
     164             :    * simulation and false - independent md simulation */
     165             :   bool _couplingSwitchedOn;
     166             : #if (TARCH_DEBUG == TARCH_YES)
     167             :   simplemd::moleculemappings::ConvertForcesFloatToFixedMapping _convertForcesFloatToFixedMapping;
     168             :   simplemd::moleculemappings::ConvertForcesFixedToFloatMapping _convertForcesFixedToFloatMapping;
     169             : #endif
     170             : };
     171             : } // namespace interface
     172             : } // namespace coupling

Generated by: LCOV version 1.14